text.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  $RCSfile$
00003  -------------------
00004  cvs         : $Id$
00005  begin       : Sat Jun 28 2003
00006  copyright   : (C) 2003 by Martin Preuss
00007  email       : martin@libchipcard.de
00008 
00009  ***************************************************************************
00010  *                                                                         *
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU Lesser General Public            *
00013  *   License as published by the Free Software Foundation; either          *
00014  *   version 2.1 of the License, or (at your option) any later version.    *
00015  *                                                                         *
00016  *   This library is distributed in the hope that it will be useful,       *
00017  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00018  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00019  *   Lesser General Public License for more details.                       *
00020  *                                                                         *
00021  *   You should have received a copy of the GNU Lesser General Public      *
00022  *   License along with this library; if not, write to the Free Software   *
00023  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
00024  *   MA  02111-1307  USA                                                   *
00025  *                                                                         *
00026  ***************************************************************************/
00027 
00028 #ifdef HAVE_CONFIG_H
00029 # include <config.h>
00030 #endif
00031 
00032 #include "text.h"
00033 #include <stdlib.h>
00034 #include <assert.h>
00035 #include <string.h>
00036 #include <ctype.h>
00037 #ifdef HAVE_LOCALE_H
00038 # include <locale.h>
00039 #endif
00040 #include <gwenhywfar/gwenhywfarapi.h>
00041 #include <gwenhywfar/debug.h>
00042 #include <gwenhywfar/stringlist.h>
00043 
00044 
00045 
00046 typedef struct {
00047   int character;
00048   const char *replace;
00049 } GWEN_TEXT_ESCAPE_ENTRY;
00050 
00051 static const GWEN_TEXT_ESCAPE_ENTRY gwen_text__xml_escape_chars[]= {
00052 {'&', "&amp;"},
00053 {'<', "&lt;"},
00054 {'>', "&gt;"},
00055 {'\'', "&apos;"},
00056 {'\"', "&quot;"},
00057 {0, 0}
00058 };
00059 
00060 
00061 
00062 char *GWEN_Text_GetWord(const char *src,
00063                         const char *delims,
00064                         char *buffer,
00065                         unsigned int maxsize,
00066                         uint32_t flags,
00067                         const char **next){
00068   unsigned int size;
00069   int lastWasBlank;
00070   int lastBlankPos;
00071   int insideQuotes;
00072   int lastWasEscape;
00073 
00074   assert(maxsize);
00075 
00076   /* skip leading blanks, if wanted */
00077   if (flags & GWEN_TEXT_FLAGS_DEL_LEADING_BLANKS) {
00078     while(*src && (unsigned char)(*src)<33)
00079       src++;
00080   }
00081 
00082   /* get word */
00083   size=0;
00084   lastWasBlank=0;
00085   lastBlankPos=-1;
00086   lastWasEscape=0;
00087   insideQuotes=0;
00088 
00089   if (*src=='"') {
00090     insideQuotes=1;
00091     if (flags & GWEN_TEXT_FLAGS_DEL_QUOTES)
00092       src++;
00093   }
00094 
00095   while(*src && size<(maxsize-1)) {
00096     if (lastWasEscape) {
00097       buffer[size]=*src;
00098       size++;
00099       lastWasEscape=0;
00100       lastWasBlank=0;
00101       lastBlankPos=-1;
00102     }
00103     else {
00104       if (*src=='\\' && (flags & GWEN_TEXT_FLAGS_CHECK_BACKSLASH)) {
00105         lastWasEscape=1;
00106         lastWasBlank=0;
00107         lastBlankPos=-1;
00108       }
00109       else {
00110         if (!insideQuotes && strchr(delims, *src)!=0)
00111           break;
00112         if (*src=='"') {
00113           if (insideQuotes) {
00114             insideQuotes=0;
00115             src++;
00116             break;
00117           }
00118           else {
00119             DBG_DEBUG(GWEN_LOGDOMAIN,
00120                       "Found a closing \" without an opening one "
00121                       "(consider using a backslash to escape)");
00122             return 0;
00123           }
00124         }
00125 
00126 
00127         if (insideQuotes ||
00128             !lastWasBlank ||
00129             (lastWasBlank &&
00130              !(flags & GWEN_TEXT_FLAGS_DEL_MULTIPLE_BLANKS))) {
00131           /* only copy if last char was NOT blank or
00132            * last was blank but the caller does not want to have multiple
00133            * blanks removed */
00134           buffer[size]=*src;
00135           size++;
00136         }
00137         /* remember next loop whether this char was a blank */
00138         if (isspace((int)((unsigned char)*src)) && !lastWasEscape) {
00139           lastWasBlank=1;
00140           lastBlankPos=size;
00141         }
00142         else {
00143           lastWasBlank=0;
00144           lastBlankPos=-1;
00145         }
00146       } /* if this is not a backslash */
00147     } /* !lastWasEscape */
00148       /* advance source pointer */
00149       src++;
00150     } /* while */
00151 
00152   /* add trailing null to correctly terminate the buffer */
00153   buffer[size]=0;
00154 
00155   if (insideQuotes) {
00156     DBG_DEBUG(GWEN_LOGDOMAIN, "Missing \" after word");
00157     return 0;
00158   }
00159   /* check whether the source string was correctly terminated */
00160   if (flags & GWEN_TEXT_FLAGS_NEED_DELIMITER) {
00161     if (*src) {
00162       if (strchr(delims, *src)==0) {
00163         DBG_ERROR(GWEN_LOGDOMAIN, "No delimiter found within specified length");
00164         return 0;
00165       }
00166     }
00167     else {
00168       if (!(flags & GWEN_TEXT_FLAGS_NULL_IS_DELIMITER)) {
00169         DBG_ERROR(GWEN_LOGDOMAIN, "String ends without delimiter");
00170         return 0;
00171       }
00172     }
00173   }
00174 
00175   /* remove trailing blanks, if wanted */
00176   if (flags & GWEN_TEXT_FLAGS_DEL_TRAILING_BLANKS) {
00177     if (lastBlankPos!=-1)
00178       buffer[lastBlankPos]=0;
00179   }
00180 
00181   *next=src;
00182   return buffer;
00183 }
00184 
00185 
00186 
00187 int GWEN_Text_GetWordToBuffer(const char *src,
00188                               const char *delims,
00189                               GWEN_BUFFER *buf,
00190                               uint32_t flags,
00191                               const char **next){
00192   const char *savedSrc=src;
00193   int lastWasBlank;
00194   int lastBlankPos;
00195   int insideQuotes;
00196   int lastWasEscape;
00197 
00198   /* skip leading blanks, if wanted */
00199   if (flags & GWEN_TEXT_FLAGS_DEL_LEADING_BLANKS) {
00200     while(*src && (unsigned char)(*src)<33) {
00201       if (strchr(delims, *src)) {
00202         *next=src;
00203         return 0;
00204       }
00205       src++;
00206     }
00207   }
00208 
00209   /* get word */
00210   lastWasBlank=0;
00211   lastBlankPos=-1;
00212   lastWasEscape=0;
00213   insideQuotes=0;
00214 
00215   if (*src=='"') {
00216     insideQuotes=1;
00217     if (flags & GWEN_TEXT_FLAGS_DEL_QUOTES)
00218       src++;
00219   }
00220 
00221   while(*src) {
00222     if (lastWasEscape) {
00223       GWEN_Buffer_AppendByte(buf, *src);
00224       lastWasEscape=0;
00225       lastWasBlank=0;
00226       lastBlankPos=-1;
00227     }
00228     else {
00229       if (*src=='\\' && (flags & GWEN_TEXT_FLAGS_CHECK_BACKSLASH)) {
00230         lastWasEscape=1;
00231         lastWasBlank=0;
00232         lastBlankPos=-1;
00233       }
00234       else {
00235         if (!insideQuotes && strchr(delims, *src)!=0)
00236           break;
00237         if (*src=='"') {
00238           if (insideQuotes) {
00239             insideQuotes=0;
00240             src++;
00241             break;
00242           }
00243           else {
00244             DBG_ERROR(GWEN_LOGDOMAIN,
00245                       "Found a closing \" without an opening one "
00246                       "(consider using a backslash to escape)");
00247             return -1;
00248           }
00249         }
00250 
00251 
00252         if (insideQuotes ||
00253             !lastWasBlank ||
00254             (lastWasBlank &&
00255              !(flags & GWEN_TEXT_FLAGS_DEL_MULTIPLE_BLANKS))) {
00256           /* only copy if last char was NOT blank or
00257            * last was blank but the caller does not want to have multiple
00258            * blanks removed */
00259           GWEN_Buffer_AppendByte(buf, *src);
00260         }
00261         /* remember next loop whether this char was a blank */
00262 
00263         if (!lastWasEscape && *((unsigned char*)src)<33) {
00264           lastWasBlank=1;
00265           lastBlankPos=GWEN_Buffer_GetPos(buf);
00266         }
00267         else {
00268           lastWasBlank=0;
00269           lastBlankPos=-1;
00270         }
00271       } /* if this is not a backslash */
00272     } /* !lastWasEscape */
00273     /* advance source pointer */
00274     src++;
00275   } /* while */
00276 
00277   if (insideQuotes) {
00278     DBG_ERROR(GWEN_LOGDOMAIN, "Missing \" after word (at %d: [%s])", (int)(src-savedSrc), savedSrc);
00279     return -1;
00280   }
00281   /* check whether the source string was correctly terminated */
00282   if (flags & GWEN_TEXT_FLAGS_NEED_DELIMITER) {
00283     if (*src) {
00284       if (strchr(delims, *src)==0) {
00285         DBG_ERROR(GWEN_LOGDOMAIN, "No delimiter found within specified length");
00286         return -1;
00287       }
00288     }
00289     else {
00290       if (!(flags & GWEN_TEXT_FLAGS_NULL_IS_DELIMITER)) {
00291         DBG_ERROR(GWEN_LOGDOMAIN, "String ends without delimiter");
00292         return -1;
00293       }
00294     }
00295   }
00296 
00297   /* remove trailing blanks, if wanted */
00298   if (flags & GWEN_TEXT_FLAGS_DEL_TRAILING_BLANKS) {
00299     if (lastBlankPos!=-1)
00300       GWEN_Buffer_Crop(buf, 0, lastBlankPos);
00301   }
00302 
00303   *next=src;
00304   return 0;
00305 }
00306 
00307 
00308 
00309 char *GWEN_Text_Escape(const char *src,
00310                        char *buffer,
00311                        unsigned int maxsize) {
00312   unsigned int size;
00313 
00314   size=0;
00315   while(*src) {
00316     unsigned char x;
00317 
00318     x=(unsigned char)*src;
00319     if (!(
00320           (x>='A' && x<='Z') ||
00321           (x>='a' && x<='z') ||
00322           (x>='0' && x<='9'))) {
00323       unsigned char c;
00324 
00325       if ((maxsize-1)<size+3) {
00326         DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
00327         return 0;
00328       }
00329       buffer[size++]='%';
00330       c=(((unsigned char)(*src))>>4)&0xf;
00331       if (c>9)
00332         c+=7;
00333       c+='0';
00334       buffer[size++]=c;
00335       c=((unsigned char)(*src))&0xf;
00336       if (c>9)
00337         c+=7;
00338       c+='0';
00339       buffer[size++]=c;
00340     }
00341     else {
00342       if (size<(maxsize-1))
00343         buffer[size++]=*src;
00344       else {
00345         DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
00346         return 0;
00347       }
00348     }
00349 
00350     src++;
00351   } /* while */
00352 
00353   buffer[size]=0;
00354   return buffer;
00355 }
00356 
00357 
00358 
00359 char *GWEN_Text_EscapeTolerant(const char *src,
00360                                char *buffer,
00361                                unsigned int maxsize) {
00362   unsigned int size;
00363 
00364   size=0;
00365   while(*src) {
00366     unsigned char x;
00367 
00368     x=(unsigned char)*src;
00369     if (!(
00370           (x>='A' && x<='Z') ||
00371           (x>='a' && x<='z') ||
00372           (x>='0' && x<='9') ||
00373           x==' ' ||
00374           x=='.' ||
00375           x==',' ||
00376           x=='.' ||
00377           x=='*' ||
00378           x=='?'
00379          )) {
00380       unsigned char c;
00381 
00382       if ((maxsize-1)<size+3) {
00383         DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
00384         return 0;
00385       }
00386       buffer[size++]='%';
00387       c=(((unsigned char)(*src))>>4)&0xf;
00388       if (c>9)
00389         c+=7;
00390       c+='0';
00391       buffer[size++]=c;
00392       c=((unsigned char)(*src))&0xf;
00393       if (c>9)
00394         c+=7;
00395       c+='0';
00396       buffer[size++]=c;
00397     }
00398     else {
00399       if (size<(maxsize-1))
00400         buffer[size++]=*src;
00401       else {
00402         DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
00403         return 0;
00404       }
00405     }
00406 
00407     src++;
00408   } /* while */
00409 
00410   buffer[size]=0;
00411   return buffer;
00412 }
00413 
00414 
00415 
00416 char *GWEN_Text_UnescapeN(const char *src,
00417                           unsigned int srclen,
00418                           char *buffer,
00419                           unsigned int maxsize){
00420   unsigned int size;
00421 
00422   size=0;
00423 
00424   while(*src && srclen>0) {
00425     unsigned char x;
00426 
00427     x=(unsigned char)*src;
00428     if (
00429         (x>='A' && x<='Z') ||
00430         (x>='a' && x<='z') ||
00431         (x>='0' && x<='9')) {
00432       if (size<(maxsize-1))
00433         buffer[size++]=*src;
00434       else {
00435         DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
00436         return 0;
00437       }
00438     }
00439     else {
00440       if (*src=='%') {
00441         unsigned char d1, d2;
00442         unsigned char c;
00443 
00444         if (srclen<3) {
00445           DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete escape sequence (EOLN met)");
00446           return 0;
00447         }
00448         /* skip '%' */
00449         src++;
00450         if (!(*src) || !isxdigit((int)*src)) {
00451           DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete escape sequence (no digits)");
00452           return 0;
00453         }
00454         /* read first digit */
00455         d1=(unsigned char)(toupper(*src));
00456 
00457         /* get second digit */
00458         src++;
00459         if (!(*src) || !isxdigit((int)*src)) {
00460           DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete escape sequence (only 1 digit)");
00461           return 0;
00462         }
00463         d2=(unsigned char)(toupper(*src));
00464         /* compute character */
00465         d1-='0';
00466         if (d1>9)
00467           d1-=7;
00468         c=(d1<<4)&0xf0;
00469         d2-='0';
00470         if (d2>9)
00471           d2-=7;
00472         c+=(d2&0xf);
00473         /* store character */
00474         if (size<(maxsize-1))
00475           buffer[size++]=(char)c;
00476         else {
00477           DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
00478           return 0;
00479         }
00480         srclen-=2;
00481       }
00482       else {
00483         DBG_ERROR(GWEN_LOGDOMAIN, "Found non-alphanum "
00484                   "characters in escaped string (\"%s\")",
00485                   src);
00486         return 0;
00487       }
00488     }
00489     srclen--;
00490     src++;
00491   } /* while */
00492 
00493   buffer[size]=0;
00494   return buffer;
00495 }
00496 
00497 
00498 
00499 char *GWEN_Text_Unescape(const char *src,
00500                          char *buffer,
00501                          unsigned int maxsize){
00502   unsigned int srclen;
00503 
00504   srclen=strlen(src);
00505   return GWEN_Text_UnescapeN(src, srclen, buffer, maxsize);
00506 }
00507 
00508 
00509 
00510 char *GWEN_Text_UnescapeTolerantN(const char *src,
00511                                   unsigned int srclen,
00512                                   char *buffer,
00513                                   unsigned int maxsize){
00514   unsigned int size;
00515 
00516   size=0;
00517 
00518   while(*src && srclen>0) {
00519     unsigned char x;
00520 
00521     x=(unsigned char)*src;
00522     if (
00523         (x>='A' && x<='Z') ||
00524         (x>='a' && x<='z') ||
00525         (x>='0' && x<='9') ||
00526         x==' ' ||
00527         x=='.' ||
00528         x==',' ||
00529         x=='.' ||
00530         x=='*' ||
00531         x=='?'
00532        ) {
00533       if (size<(maxsize-1))
00534         buffer[size++]=*src;
00535       else {
00536         DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
00537         return 0;
00538       }
00539     }
00540     else {
00541       if (*src=='%') {
00542         unsigned char d1, d2;
00543         unsigned char c;
00544 
00545         if (srclen<3) {
00546           DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete escape sequence (EOLN met)");
00547           return 0;
00548         }
00549         /* skip '%' */
00550         src++;
00551         if (!(*src) || !isxdigit((int)*src)) {
00552           DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete escape sequence (no digits)");
00553           return 0;
00554         }
00555         /* read first digit */
00556         d1=(unsigned char)(toupper(*src));
00557 
00558         /* get second digit */
00559         src++;
00560         if (!(*src) || !isxdigit((int)*src)) {
00561           DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete escape sequence (only 1 digit)");
00562           return 0;
00563         }
00564         d2=(unsigned char)(toupper(*src));
00565         /* compute character */
00566         d1-='0';
00567         if (d1>9)
00568           d1-=7;
00569         c=(d1<<4)&0xf0;
00570         d2-='0';
00571         if (d2>9)
00572           d2-=7;
00573         c+=(d2&0xf);
00574         /* store character */
00575         if (size<(maxsize-1))
00576           buffer[size++]=(char)c;
00577         else {
00578           DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
00579           return 0;
00580         }
00581         srclen-=2;
00582       }
00583       else {
00584         DBG_ERROR(GWEN_LOGDOMAIN, "Found non-alphanum "
00585                   "characters in escaped string (\"%s\")",
00586                   src);
00587         return 0;
00588       }
00589     }
00590     srclen--;
00591     src++;
00592   } /* while */
00593 
00594   buffer[size]=0;
00595   return buffer;
00596 }
00597 
00598 
00599 
00600 char *GWEN_Text_UnescapeTolerant(const char *src,
00601                                  char *buffer,
00602                                  unsigned int maxsize){
00603   unsigned int srclen;
00604 
00605   srclen=strlen(src);
00606   return GWEN_Text_UnescapeTolerantN(src, srclen, buffer, maxsize);
00607 }
00608 
00609 
00610 
00611 char *GWEN_Text_ToHex(const char *src, unsigned l,
00612                       char *buffer, unsigned int maxsize) {
00613   unsigned int pos;
00614   unsigned int size;
00615 
00616   if ((l*2)+1 > maxsize) {
00617     DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
00618     return 0;
00619   }
00620 
00621   pos=0;
00622   size=0;
00623   while(pos<l) {
00624     unsigned char c;
00625 
00626     c=(((unsigned char)(src[pos]))>>4)&0xf;
00627     if (c>9)
00628       c+=7;
00629     c+='0';
00630     buffer[size++]=c;
00631     c=((unsigned char)(src[pos]))&0xf;
00632     if (c>9)
00633       c+=7;
00634     c+='0';
00635     buffer[size++]=c;
00636     pos++;
00637   }
00638   buffer[size]=0;
00639   return buffer;
00640 }
00641 
00642 
00643 
00644 char *GWEN_Text_ToHexGrouped(const char *src,
00645                              unsigned l,
00646                              char *buffer,
00647                              unsigned maxsize,
00648                              unsigned int groupsize,
00649                              char delimiter,
00650                              int skipLeadingZeroes) {
00651   unsigned int pos;
00652   unsigned int size;
00653   unsigned int j;
00654 
00655   j=0;
00656 
00657   pos=0;
00658   size=0;
00659   j=0;
00660   while(pos<l) {
00661     unsigned char c;
00662     int skipThis;
00663 
00664     skipThis=0;
00665     c=(((unsigned char)(src[pos]))>>4)&0xf;
00666     if (skipLeadingZeroes) {
00667       if (c==0)
00668         skipThis=1;
00669       else
00670         skipLeadingZeroes=0;
00671     }
00672     if (c>9)
00673       c+=7;
00674     c+='0';
00675     if (!skipThis) {
00676       if (size+1>=maxsize) {
00677         DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
00678         return 0;
00679       }
00680       buffer[size++]=c;
00681       j++;
00682       if (j==groupsize) {
00683         if (size+1>=maxsize) {
00684           DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
00685           return 0;
00686         }
00687         buffer[size++]=delimiter;
00688         j=0;
00689       }
00690     }
00691 
00692     skipThis=0;
00693     c=((unsigned char)(src[pos]))&0xf;
00694     if (skipLeadingZeroes) {
00695       if (c==0 && pos+1<l)
00696         skipThis=1;
00697       else
00698         skipLeadingZeroes=0;
00699     }
00700     if (c>9)
00701       c+=7;
00702     c+='0';
00703     if (size+1>=maxsize) {
00704       DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
00705       return 0;
00706     }
00707     if (!skipThis) {
00708       buffer[size++]=c;
00709       j++;
00710       if (j==groupsize) {
00711         if (pos+1<l) {
00712           if (size+1>=maxsize) {
00713             DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
00714             return 0;
00715           }
00716           buffer[size++]=delimiter;
00717         }
00718         j=0;
00719       }
00720     }
00721     pos++;
00722   }
00723   buffer[size]=0;
00724   return buffer;
00725 }
00726 
00727 
00728 
00729 int GWEN_Text_ToHexBuffer(const char *src, unsigned l,
00730                           GWEN_BUFFER *buf,
00731                           unsigned int groupsize,
00732                           char delimiter,
00733                           int skipLeadingZeroes){
00734   unsigned int pos;
00735   unsigned int size;
00736   unsigned int j;
00737 
00738   j=0;
00739 
00740   pos=0;
00741   size=0;
00742   j=0;
00743   while(pos<l) {
00744     unsigned char c;
00745     int skipThis;
00746 
00747     skipThis=0;
00748     c=(((unsigned char)(src[pos]))>>4)&0xf;
00749     if (skipLeadingZeroes) {
00750       if (c==0)
00751         skipThis=1;
00752       else
00753         skipLeadingZeroes=0;
00754     }
00755     if (c>9)
00756       c+=7;
00757     c+='0';
00758     if (!skipThis) {
00759       if (GWEN_Buffer_AppendByte(buf, c)) {
00760         DBG_INFO(GWEN_LOGDOMAIN, "here");
00761         return -1;
00762       }
00763       j++;
00764       if (groupsize && j==groupsize) {
00765         if (GWEN_Buffer_AppendByte(buf, delimiter)) {
00766           DBG_INFO(GWEN_LOGDOMAIN, "here");
00767           return -1;
00768         }
00769         j=0;
00770       }
00771     }
00772 
00773     skipThis=0;
00774     c=((unsigned char)(src[pos]))&0xf;
00775     if (skipLeadingZeroes) {
00776       if (c==0 && pos+1<l)
00777         skipThis=1;
00778       else
00779         skipLeadingZeroes=0;
00780     }
00781     if (c>9)
00782       c+=7;
00783     c+='0';
00784     if (!skipThis) {
00785       if (GWEN_Buffer_AppendByte(buf, c)) {
00786         DBG_INFO(GWEN_LOGDOMAIN, "here");
00787         return -1;
00788       }
00789       j++;
00790       if (groupsize && j==groupsize) {
00791         if (pos+1<l) {
00792           if (GWEN_Buffer_AppendByte(buf, delimiter)) {
00793             DBG_INFO(GWEN_LOGDOMAIN, "here");
00794             return -1;
00795           }
00796         }
00797         j=0;
00798       }
00799     }
00800     pos++;
00801   }
00802   return 0;
00803 }
00804 
00805 
00806 
00807 int GWEN_Text_FromHex(const char *src, char *buffer, unsigned maxsize){
00808   unsigned int pos;
00809   unsigned int size;
00810 
00811   pos=0;
00812   size=0;
00813   while(*src) {
00814     unsigned char d1, d2;
00815     unsigned char c;
00816 
00817     /* read first digit */
00818     if (!isxdigit((int)*src)) {
00819       DBG_ERROR(GWEN_LOGDOMAIN, "Bad char in hex string");
00820       return -1;
00821     }
00822     d1=(unsigned char)(toupper(*src));
00823 
00824     /* get second digit */
00825     src++;
00826     if (!(*src) || !isxdigit((int)*src)) {
00827       DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete hex byte (only 1 digit)");
00828       return -1;
00829     }
00830     d2=(unsigned char)(toupper(*src));
00831     src++;
00832 
00833     /* compute character */
00834     d1-='0';
00835     if (d1>9)
00836       d1-=7;
00837     c=(d1<<4)&0xf0;
00838     d2-='0';
00839     if (d2>9)
00840       d2-=7;
00841     c+=(d2&0xf);
00842     /* store character */
00843     if (size<(maxsize))
00844       buffer[size++]=(char)c;
00845     else {
00846         DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small (maxsize=%d)", maxsize);
00847       return -1;
00848     }
00849   } /* while */
00850 
00851   return size;
00852 }
00853 
00854 
00855 
00856 int GWEN_Text_FromHexBuffer(const char *src, GWEN_BUFFER *buf) {
00857   while(*src) {
00858     unsigned char d1, d2;
00859     unsigned char c;
00860 
00861     /* read first digit */
00862     if (isspace((int)*src)) {
00863       src++;
00864     }
00865     else {
00866       if (!isxdigit((int)*src)) {
00867         DBG_ERROR(GWEN_LOGDOMAIN, "Bad char in hex string");
00868         return -1;
00869       }
00870       d1=(unsigned char)(toupper(*src));
00871   
00872       /* get second digit */
00873       src++;
00874       if (!(*src) || !isxdigit((int)*src)) {
00875         DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete hex byte (only 1 digit)");
00876         return -1;
00877       }
00878       d2=(unsigned char)(toupper(*src));
00879       src++;
00880   
00881       /* compute character */
00882       d1-='0';
00883       if (d1>9)
00884         d1-=7;
00885       c=(d1<<4)&0xf0;
00886       d2-='0';
00887       if (d2>9)
00888         d2-=7;
00889       c+=(d2&0xf);
00890       /* store character */
00891       GWEN_Buffer_AppendByte(buf, (char)c);
00892     }
00893   } /* while */
00894 
00895   return 0;
00896 }
00897 
00898 
00899 
00900 int GWEN_Text_FromBcdBuffer(const char *src, GWEN_BUFFER *buf) {
00901   unsigned int l;
00902   int fakeByte;
00903 
00904   l=strlen(src);
00905   fakeByte=(l%2);
00906   while(*src) {
00907     unsigned char d1, d2;
00908     unsigned char c;
00909 
00910     if (fakeByte) {
00911       d1=0;
00912       fakeByte=0;
00913     }
00914     else {
00915       /* read first digit */
00916       if (!isdigit((int)*src)) {
00917         DBG_ERROR(GWEN_LOGDOMAIN, "Bad char in bcd string");
00918         return -1;
00919       }
00920       d1=(unsigned char)(*src);
00921       src++;
00922     }
00923     /* get second digit */
00924     if (!(*src) || !isxdigit((int)*src)) {
00925       DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete BCD byte (only 1 digit)");
00926       return -1;
00927     }
00928     d2=(unsigned char)(*src);
00929     src++;
00930 
00931     /* compute character */
00932     d1-='0';
00933     c=(d1<<4)&0xf0;
00934     d2-='0';
00935     c+=(d2&0xf);
00936     /* store character */
00937     GWEN_Buffer_AppendByte(buf, (char)c);
00938   } /* while */
00939 
00940   return 0;
00941 }
00942 
00943 
00944 
00945 int GWEN_Text_ToBcdBuffer(const char *src, unsigned l,
00946                           GWEN_BUFFER *buf,
00947                           unsigned int groupsize,
00948                           char delimiter,
00949                           int skipLeadingZeroes){
00950   unsigned int pos;
00951   unsigned int size;
00952   unsigned int j;
00953 
00954   j=0;
00955 
00956   pos=0;
00957   size=0;
00958   j=0;
00959   while(pos<l) {
00960     unsigned char c;
00961     int skipThis;
00962 
00963     skipThis=0;
00964     c=(((unsigned char)(src[pos]))>>4)&0xf;
00965     if (skipLeadingZeroes) {
00966       if (c==0)
00967         skipThis=1;
00968       else
00969         skipLeadingZeroes=0;
00970     }
00971     c+='0';
00972     if (!skipThis) {
00973       if (GWEN_Buffer_AppendByte(buf, c)) {
00974         DBG_INFO(GWEN_LOGDOMAIN, "here");
00975         return -1;
00976       }
00977       j++;
00978       if (groupsize && j==groupsize) {
00979         if (GWEN_Buffer_AppendByte(buf, delimiter)) {
00980           DBG_INFO(GWEN_LOGDOMAIN, "here");
00981           return -1;
00982         }
00983         j=0;
00984       }
00985     }
00986 
00987     skipThis=0;
00988     c=((unsigned char)(src[pos]))&0xf;
00989     if (skipLeadingZeroes) {
00990       if (c==0 && pos+1<l)
00991         skipThis=1;
00992       else
00993         skipLeadingZeroes=0;
00994     }
00995     c+='0';
00996     if (!skipThis) {
00997       if (GWEN_Buffer_AppendByte(buf, c)) {
00998         DBG_INFO(GWEN_LOGDOMAIN, "here");
00999         return -1;
01000       }
01001       j++;
01002       if (groupsize && j==groupsize) {
01003         if (pos+1<l) {
01004           if (GWEN_Buffer_AppendByte(buf, delimiter)) {
01005             DBG_INFO(GWEN_LOGDOMAIN, "here");
01006             return -1;
01007           }
01008         }
01009         j=0;
01010       }
01011     }
01012     pos++;
01013   }
01014   return 0;
01015 }
01016 
01017 
01018 
01019 int GWEN_Text_Compare(const char *s1, const char *s2, int ign) {
01020   if (s1)
01021     if (*s1==0)
01022       s1=0;
01023   if (s2)
01024     if (*s2==0)
01025       s2=0;
01026   if (!s1 && !s2)
01027     return 0;
01028   if (!s1 && s2)
01029     return 1;
01030   if (s1 && !s2)
01031     return -1;
01032   if (ign)
01033     return strcasecmp(s1, s2);
01034   else
01035     return strcmp(s1, s2);
01036 }
01037 
01038 
01039 
01040 
01041 int GWEN_Text__cmpSegment(const char *w, unsigned int *wpos,
01042                           const char *p, unsigned int *ppos,
01043                           int sensecase,
01044                           unsigned int *matches) {
01045   char a;
01046   char b;
01047   unsigned wlength;
01048   unsigned plength;
01049 
01050   unsigned int _wpos = *wpos, _ppos = *ppos, _matches = *matches;
01051 
01052   a=0;
01053   b=0;
01054   wlength=strlen(w);
01055   plength=strlen(p);
01056 
01057   while (_wpos<wlength && _ppos<plength) {
01058     a=w[_wpos];
01059     b=p[_ppos];
01060     if (b=='*') {
01061       *wpos = _wpos;
01062       *ppos = _ppos;
01063       *matches = _matches;
01064       return 1;
01065     }
01066     if (!sensecase) {
01067       a=toupper(a);
01068       b=toupper(b);
01069     }
01070     /* count matches */
01071     if (a==b)
01072       ++_matches;
01073     if (a!=b && b!='?') {
01074       *wpos = _wpos;
01075       *ppos = _ppos;
01076       *matches = _matches;
01077       return 0;
01078     }
01079     ++_wpos;
01080     ++_ppos;
01081   }
01082   /* both at end, would be ok */
01083   if (_wpos==wlength && _ppos==plength) {
01084     *wpos = _wpos;
01085     *ppos = _ppos;
01086     *matches = _matches;
01087     return 1;
01088   }
01089   /* word ends, pattern doesnt, would be ok if pattern is '*' here */
01090   if (_wpos>=wlength && _ppos<plength)
01091     if (p[_ppos]=='*') {
01092       *wpos = _wpos;
01093       *ppos = _ppos;
01094       *matches = _matches;
01095       return 1;
01096     }
01097   /* otherwise no match ;-/ */
01098   *wpos = _wpos;
01099   *ppos = _ppos;
01100   *matches = _matches;
01101   return 0;
01102 }
01103 
01104 
01105 
01106 int GWEN_Text__findSegment(const char *w, unsigned int *wpos,
01107                            const char *p, unsigned int *ppos,
01108                            int sensecase,
01109                            unsigned int *matches) {
01110   unsigned int lwpos, lppos, lmatches;
01111   unsigned wlength;
01112 
01113   wlength=strlen(w);
01114   lwpos=*wpos;
01115   lppos=*ppos;
01116   lmatches=*matches;
01117   while(lwpos<wlength) {
01118     *ppos=lppos;
01119     *wpos=lwpos;
01120     *matches=lmatches;
01121     if (GWEN_Text__cmpSegment(w,wpos,p,ppos,sensecase,matches))
01122       return 1;
01123     lwpos++;
01124   }
01125   return 0;
01126 }
01127 
01128 
01129 int GWEN_Text_ComparePattern(const char *w, const char *p, int sensecase) {
01130   unsigned int ppos;
01131   unsigned int wpos;
01132   unsigned int matches;
01133   unsigned int plength;
01134 
01135   ppos=wpos=matches=0;
01136   plength=strlen(p);
01137 
01138   /* compare until first occurrence of '*' */
01139   if (!GWEN_Text__cmpSegment(w,&wpos,p,&ppos,sensecase,&matches)) {
01140     return -1;
01141   }
01142 
01143   while(1) {
01144     /* if pattern ends we have done it */
01145     if (ppos>=plength)
01146       return matches;
01147     /* skip '*' in pattern */
01148     ppos++;
01149     /* if pattern ends behind '*' the word matches */
01150     if (ppos>=plength)
01151       return matches;
01152     /* find next matching segment */
01153     if (!GWEN_Text__findSegment(w,&wpos,p,&ppos,sensecase,&matches)) {
01154       return -1;
01155     }
01156   } /* while */
01157   /* I know, we'll never get to here ;-) */
01158   return -1;
01159 }
01160 
01161 
01162 
01163 int GWEN_Text_NumToString(int num, char *buffer, unsigned int bufsize,
01164                           int fillchar){
01165   char lbuffer[128];
01166   unsigned int i;
01167 
01168   sprintf(lbuffer,"%d", num);
01169   i=strlen(lbuffer);
01170   if (i>=bufsize) {
01171     DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small (%d>=%d)", i, bufsize);
01172     return -1;
01173   }
01174   if (fillchar>0) {
01175     /* fill right, but first copy chars */
01176     strcpy(buffer, lbuffer);
01177     while(i<bufsize-1)
01178       buffer[i++]=fillchar;
01179     buffer[i]=0;
01180     return bufsize;
01181   }
01182   else if (fillchar<0) {
01183     int j, k;
01184 
01185     fillchar=-fillchar;
01186     j=bufsize-1-i;
01187     for (k=0; k<j; k++)
01188       buffer[k]=fillchar;
01189     buffer[k]=0;
01190     strcat(buffer, lbuffer);
01191     return bufsize;
01192   }
01193   else {
01194     /* dont fill, just copy */
01195     strcpy(buffer, lbuffer);
01196     return i;
01197   }
01198 }
01199 
01200 
01201 
01202 void GWEN_Text_DumpString(const char *s, unsigned int l,
01203                           FILE *f, unsigned int insert) {
01204   unsigned int i;
01205   unsigned int j;
01206   unsigned int pos;
01207   unsigned k;
01208 
01209   pos=0;
01210   for (k=0; k<insert; k++)
01211     fprintf(f, " ");
01212   fprintf(f,"String size is %d:\n",l);
01213   while(pos<l) {
01214     for (k=0; k<insert; k++)
01215       fprintf(f, " ");
01216     fprintf(f,"%04x: ",pos);
01217     j=pos+16;
01218     if (j>=l)
01219       j=l;
01220 
01221     /* show hex dump */
01222     for (i=pos; i<j; i++) {
01223       fprintf(f,"%02x ",(unsigned char)s[i]);
01224     }
01225     if (j-pos<16)
01226       for (i=0; i<16-(j-pos); i++)
01227         fprintf(f,"   ");
01228     /* show text */
01229     for (i=pos; i<j; i++) {
01230       if (s[i]<32)
01231         fprintf(f,".");
01232       else
01233         fprintf(f,"%c",s[i]);
01234     }
01235     fprintf(f,"\n");
01236     pos+=16;
01237   }
01238 }
01239 
01240 
01241 
01242 void GWEN_Text_DumpString2Buffer(const char *s, unsigned int l,
01243                                  GWEN_BUFFER *mbuf,
01244                                  unsigned int insert) {
01245   unsigned int i;
01246   unsigned int j;
01247   unsigned int pos;
01248   unsigned k;
01249   char numbuf[32];
01250 
01251   pos=0;
01252   for (k=0; k<insert; k++)
01253     GWEN_Buffer_AppendByte(mbuf, ' ');
01254   GWEN_Buffer_AppendString(mbuf,"String size is ");
01255   snprintf(numbuf, sizeof(numbuf), "%d", l);
01256   GWEN_Buffer_AppendString(mbuf, numbuf);
01257   GWEN_Buffer_AppendByte(mbuf, '\n');
01258   while(pos<l) {
01259     for (k=0; k<insert; k++)
01260       GWEN_Buffer_AppendByte(mbuf, ' ');
01261     snprintf(numbuf, sizeof(numbuf),"%04x: ",pos);
01262     GWEN_Buffer_AppendString(mbuf, numbuf);
01263     j=pos+16;
01264     if (j>=l)
01265       j=l;
01266 
01267     /* show hex dump */
01268     for (i=pos; i<j; i++) {
01269       snprintf(numbuf, sizeof(numbuf),"%02x ", (unsigned char)s[i]);
01270       GWEN_Buffer_AppendString(mbuf, numbuf);
01271     }
01272     if (j-pos<16)
01273       for (i=0; i<16-(j-pos); i++)
01274         GWEN_Buffer_AppendString(mbuf, "   ");
01275     /* show text */
01276     for (i=pos; i<j; i++) {
01277       if (s[i]<32)
01278         GWEN_Buffer_AppendByte(mbuf, '.');
01279       else
01280         GWEN_Buffer_AppendByte(mbuf, s[i]);
01281     }
01282     GWEN_Buffer_AppendByte(mbuf, '\n');
01283     pos+=16;
01284   }
01285 }
01286 
01287 
01288 
01289 
01290 
01291 
01292 
01293 int GWEN_Text_EscapeToBuffer(const char *src, GWEN_BUFFER *buf) {
01294   while(*src) {
01295     unsigned char x;
01296 
01297     x=(unsigned char)*src;
01298     if (!(
01299           (x>='A' && x<='Z') ||
01300           (x>='a' && x<='z') ||
01301           (x>='0' && x<='9'))) {
01302       unsigned char c;
01303 
01304       GWEN_Buffer_AppendByte(buf, '%');
01305       c=(((unsigned char)(*src))>>4)&0xf;
01306       if (c>9)
01307         c+=7;
01308       c+='0';
01309       GWEN_Buffer_AppendByte(buf, c);
01310       c=((unsigned char)(*src))&0xf;
01311       if (c>9)
01312         c+=7;
01313       c+='0';
01314       GWEN_Buffer_AppendByte(buf, c);
01315     }
01316     else
01317       GWEN_Buffer_AppendByte(buf, *src);
01318 
01319     src++;
01320   } /* while */
01321 
01322   return 0;
01323 }
01324 
01325 
01326 
01327 int GWEN_Text_UnescapeToBuffer(const char *src, GWEN_BUFFER *buf) {
01328   while(*src) {
01329     unsigned char x;
01330 
01331     x=(unsigned char)*src;
01332     if (
01333         (x>='A' && x<='Z') ||
01334         (x>='a' && x<='z') ||
01335         (x>='0' && x<='9')) {
01336       GWEN_Buffer_AppendByte(buf, *src);
01337     }
01338     else {
01339       if (*src=='%') {
01340         unsigned char d1, d2;
01341         unsigned char c;
01342 
01343         /* skip '%' */
01344         src++;
01345         if (!(*src) || !isxdigit((int)*src)) {
01346           DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete escape sequence (no digits)");
01347           return 0;
01348         }
01349         /* read first digit */
01350         d1=(unsigned char)(toupper(*src));
01351 
01352         /* get second digit */
01353         src++;
01354         if (!(*src) || !isxdigit((int)*src)) {
01355           DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete escape sequence (only 1 digit)");
01356           return 0;
01357         }
01358         d2=(unsigned char)(toupper(*src));
01359         /* compute character */
01360         d1-='0';
01361         if (d1>9)
01362           d1-=7;
01363         c=(d1<<4)&0xf0;
01364         d2-='0';
01365         if (d2>9)
01366           d2-=7;
01367         c+=(d2&0xf);
01368         /* store character */
01369         GWEN_Buffer_AppendByte(buf, (char)c);
01370       }
01371       else {
01372         DBG_ERROR(GWEN_LOGDOMAIN, "Found non-alphanum "
01373                   "characters in escaped string (\"%s\")",
01374                   src);
01375         return -1;
01376       }
01377     }
01378     src++;
01379   } /* while */
01380 
01381   return 0;
01382 }
01383 
01384 
01385 
01386 int GWEN_Text_EscapeToBufferTolerant(const char *src, GWEN_BUFFER *buf) {
01387   while(*src) {
01388     unsigned char x;
01389 
01390     x=(unsigned char)*src;
01391     if (!(
01392           (x>='A' && x<='Z') ||
01393           (x>='a' && x<='z') ||
01394           (x>='0' && x<='9') ||
01395           x==' ' ||
01396           x=='.' ||
01397           x==',' ||
01398           x=='.' ||
01399           x=='_' ||
01400           x=='-' ||
01401           x=='*' ||
01402           x=='?'
01403          )) {
01404       unsigned char c;
01405 
01406       GWEN_Buffer_AppendByte(buf, '%');
01407       c=(((unsigned char)(*src))>>4)&0xf;
01408       if (c>9)
01409         c+=7;
01410       c+='0';
01411       GWEN_Buffer_AppendByte(buf, c);
01412       c=((unsigned char)(*src))&0xf;
01413       if (c>9)
01414         c+=7;
01415       c+='0';
01416       GWEN_Buffer_AppendByte(buf, c);
01417     }
01418     else
01419       GWEN_Buffer_AppendByte(buf, *src);
01420 
01421     src++;
01422   } /* while */
01423 
01424   return 0;
01425 }
01426 
01427 
01428 
01429 int GWEN_Text_UnescapeToBufferTolerant(const char *src, GWEN_BUFFER *buf) {
01430   while(*src) {
01431     const char *srcBak;
01432     int charHandled;
01433 
01434     srcBak=src;
01435     charHandled=0;
01436     if (*src=='%') {
01437       if (strlen(src)>2) {
01438         unsigned char d1, d2;
01439         unsigned char c;
01440 
01441         if (isxdigit((int)src[1]) && isxdigit((int)src[2])) {
01442           /* skip '%' */
01443           src++;
01444           /* read first digit */
01445           d1=(unsigned char)(toupper(*src));
01446 
01447           /* get second digit */
01448           src++;
01449           d2=(unsigned char)(toupper(*src));
01450           /* compute character */
01451           d1-='0';
01452           if (d1>9)
01453             d1-=7;
01454           c=(d1<<4)&0xf0;
01455           d2-='0';
01456           if (d2>9)
01457             d2-=7;
01458           c+=(d2&0xf);
01459           /* store character */
01460           GWEN_Buffer_AppendByte(buf, (char)c);
01461           charHandled=1;
01462         }
01463       }
01464     }
01465     if (!charHandled)
01466       GWEN_Buffer_AppendByte(buf, *src);
01467     src++;
01468   } /* while */
01469 
01470   return 0;
01471 }
01472 
01473 
01474 
01475 int GWEN_Text_EscapeToBufferTolerant2(GWEN_BUFFER *src, GWEN_BUFFER *buf) {
01476   while(GWEN_Buffer_GetBytesLeft(src)) {
01477     int z;
01478     unsigned char x;
01479 
01480     z=GWEN_Buffer_ReadByte(src);
01481     if (z==-1) {
01482       DBG_INFO(GWEN_LOGDOMAIN, "here");
01483       return -1;
01484     }
01485     x=(unsigned char)z;
01486     if (!(
01487           (x>='A' && x<='Z') ||
01488           (x>='a' && x<='z') ||
01489           (x>='0' && x<='9') ||
01490           x==' ' ||
01491           x=='.' ||
01492           x==',' ||
01493           x=='.' ||
01494           x=='*' ||
01495           x=='?'
01496          )) {
01497       unsigned char c;
01498 
01499       GWEN_Buffer_AppendByte(buf, '%');
01500       c=(((unsigned char)x)>>4)&0xf;
01501       if (c>9)
01502         c+=7;
01503       c+='0';
01504       GWEN_Buffer_AppendByte(buf, c);
01505       c=((unsigned char)x)&0xf;
01506       if (c>9)
01507         c+=7;
01508       c+='0';
01509       GWEN_Buffer_AppendByte(buf, c);
01510     }
01511     else
01512       GWEN_Buffer_AppendByte(buf, x);
01513   } /* while */
01514 
01515   return 0;
01516 }
01517 
01518 
01519 
01520 void GWEN_Text_LogString(const char *s, unsigned int l,
01521                          const char *logDomain,
01522                          GWEN_LOGGER_LEVEL lv){
01523   GWEN_BUFFER *mbuf;
01524 
01525   mbuf=GWEN_Buffer_new(0, ((l*16)<1024)?1024:l*16, 0, 1);
01526   GWEN_Text_DumpString2Buffer(s, l, mbuf, 0);
01527   GWEN_Logger_Log(logDomain, lv, GWEN_Buffer_GetStart(mbuf));
01528   GWEN_Buffer_free(mbuf);
01529 }
01530 
01531 
01532 
01533 void GWEN_Text_CondenseBuffer(GWEN_BUFFER *buf){
01534   const char *p;
01535   char *dst;
01536   unsigned int size;
01537   unsigned int i;
01538   int lastWasBlank;
01539   char *lastBlankPos;
01540 
01541   dst=GWEN_Buffer_GetStart(buf);
01542   p=dst;
01543   size=GWEN_Buffer_GetUsedBytes(buf);
01544   lastWasBlank=0;
01545   lastBlankPos=0;
01546 
01547   for (i=0; i<size; i++) {
01548     /* remember next loop whether this char was a blank */
01549     if (isspace((int)*p)) {
01550       if (!lastWasBlank) {
01551         /* store only one blank */
01552         lastWasBlank=1;
01553         lastBlankPos=dst;
01554         *(dst++)=*p;
01555       }
01556     }
01557     else {
01558       lastWasBlank=0;
01559       lastBlankPos=0;
01560       *(dst++)=*p;
01561     }
01562     p++;
01563   }
01564 
01565   /* remove trailing blanks */
01566   if (lastBlankPos!=0)
01567     dst=lastBlankPos;
01568 
01569   size=dst-GWEN_Buffer_GetStart(buf);
01570   GWEN_Buffer_Crop(buf, 0, size);
01571 }
01572 
01573 
01574 
01575 int GWEN_Text_DoubleToBuffer(double num, GWEN_BUFFER *buf){
01576   char numbuf[128];
01577   int rv;
01578 #ifdef HAVE_SETLOCALE
01579   const char *orig_locale = setlocale(LC_NUMERIC, NULL);
01580   char *currentLocale = strdup(orig_locale ? orig_locale : "C");
01581   setlocale(LC_NUMERIC,"C");
01582 #endif
01583 
01584   rv=snprintf(numbuf, sizeof(numbuf), "%f", num);
01585 
01586 #ifdef HAVE_SETLOCALE
01587   setlocale(LC_NUMERIC, currentLocale);
01588   free(currentLocale);
01589 #endif
01590 
01591   if (rv<1 || rv>=sizeof(numbuf))
01592     return -1;
01593   GWEN_Buffer_AppendString(buf, numbuf);
01594   return 0;
01595 }
01596 
01597 
01598 
01599 int GWEN_Text_StringToDouble(const char *s, double *num){
01600   int rv;
01601 #ifdef HAVE_SETLOCALE
01602   const char *orig_locale = setlocale(LC_NUMERIC, NULL);
01603   char *currentLocale = strdup(orig_locale ? orig_locale : "C");
01604   setlocale(LC_NUMERIC,"C");
01605 #endif
01606 
01607   rv=sscanf(s, "%lf", num);
01608 
01609 #ifdef HAVE_SETLOCALE
01610   setlocale(LC_NUMERIC, currentLocale);
01611   free(currentLocale);
01612 #endif
01613 
01614   if (rv!=1)
01615     return -1;
01616   return 0;
01617 }
01618 
01619 
01620 
01621 double GWEN_Text__CheckSimilarity(const char *s1, const char *s2, int ign){
01622   int nboth;
01623   int nmatch;
01624   double pc;
01625 
01626   nboth=strlen(s1)+strlen(s2);
01627   nmatch=0;
01628   if (ign) {
01629     while(*s1 && *s2) {
01630       const char *t;
01631       int lmatch;
01632 
01633       /* find next equal in s2 */
01634       t=s2;
01635       lmatch=0;
01636       while(*t) {
01637         if (toupper(*s1)==toupper(*t)) {
01638           lmatch=2;
01639           break;
01640         }
01641         if (isalnum((int)*s1) && isalnum((int)*t)) {
01642           lmatch=1;
01643           break;
01644         }
01645         t++;
01646       } /* while */
01647 
01648       if (lmatch) {
01649         nmatch+=lmatch;
01650         s2=t+1;
01651       }
01652 
01653       s1++;
01654     } /* while */
01655   }
01656   else {
01657     while(*s1 && *s2) {
01658       const char *t;
01659       int lmatch;
01660 
01661       /* find next equal in s2 */
01662       t=s2;
01663       lmatch=0;
01664       while(*t) {
01665         if (*s1==*t) {
01666           lmatch=2;
01667           break;
01668         }
01669         if (toupper(*s1)==toupper(*t)) {
01670           lmatch=1;
01671           break;
01672         }
01673         if (isalnum((int)*s1) && isalnum((int)*t)) {
01674           lmatch=1;
01675           break;
01676         }
01677         t++;
01678       } /* while */
01679 
01680       if (lmatch) {
01681         nmatch+=lmatch;
01682         s2=t+1;
01683       }
01684 
01685       s1++;
01686     } /* while */
01687   }
01688 
01689   pc=(nmatch*100)/nboth;
01690   return pc;
01691 }
01692 
01693 
01694 
01695 double GWEN_Text_CheckSimilarity(const char *s1, const char *s2, int ign){
01696   double pc1, pc2;
01697 
01698   pc1=GWEN_Text__CheckSimilarity(s1, s2, ign);
01699   pc2=GWEN_Text__CheckSimilarity(s2, s1, ign);
01700   if (pc2>pc1)
01701     return pc2;
01702   return pc1;
01703 }
01704 
01705 
01706 
01707 int GWEN_Text_CountUtf8Chars(const char *s, int len) {
01708   int count;
01709   int handled;
01710 
01711   if (len==0)
01712     len=strlen(s);
01713   count=0;
01714   handled=0;
01715   while(handled<len) {
01716     unsigned char c;
01717     int i;
01718 
01719     c=(unsigned char)*s;
01720     if ((c & 0xfe)==0xfc)
01721       i=5;
01722     else if ((c & 0xfc)==0xf8)
01723       i=4;
01724     else if ((c & 0xf8)==0xf0)
01725       i=3;
01726     else if ((c & 0xf0)==0xe0)
01727       i=2;
01728     else if ((c & 0xe0)==0xc0)
01729       i=1;
01730     else if (c & 0x80) {
01731       DBG_ERROR(GWEN_LOGDOMAIN, "Invalid UTF8 character at pos %d", handled);
01732       return -1;
01733     }
01734     else
01735       i=0;
01736     if (handled+i+1>len) {
01737       DBG_ERROR(GWEN_LOGDOMAIN,
01738                 "Incomplete UTF8 sequence at pos %d", handled);
01739       return -1;
01740     }
01741     s++;
01742     if (i) {
01743       int j;
01744 
01745       for (j=0; j<j; j++) {
01746         if ((((unsigned char)*s) & 0xc0)!=0xc0) {
01747           DBG_ERROR(GWEN_LOGDOMAIN,
01748                     "Invalid UTF8 sequence at pos %d (rel %d of %d)",
01749                     handled, j, i);
01750         }
01751         s++;
01752       }
01753     }
01754     handled+=i+1;
01755     count++;
01756   } /* while */
01757 
01758   return count;
01759 }
01760 
01761 
01762 
01763 int GWEN_Text_UnescapeXmlToBuffer(const char *src, GWEN_BUFFER *buf) {
01764   char *pdst;
01765   uint32_t roomLeft;
01766   uint32_t bytesAdded;
01767 
01768 #define GWEN_TEXT__APPENDCHAR(chr)                     \
01769   if (roomLeft<2) {                                   \
01770     if (bytesAdded) {                                 \
01771       GWEN_Buffer_IncrementPos(buf, bytesAdded);      \
01772       GWEN_Buffer_AdjustUsedBytes(buf);               \
01773     }                                                 \
01774     GWEN_Buffer_AllocRoom(buf, 2);                    \
01775     pdst=GWEN_Buffer_GetPosPointer(buf);              \
01776     roomLeft=GWEN_Buffer_GetMaxUnsegmentedWrite(buf); \
01777     bytesAdded=0;                                     \
01778    }                                                  \
01779    *(pdst++)=(unsigned char)chr;                      \
01780    *pdst=0;                                           \
01781    bytesAdded++;                                      \
01782   roomLeft--
01783 
01784   pdst=GWEN_Buffer_GetPosPointer(buf);
01785   roomLeft=GWEN_Buffer_GetMaxUnsegmentedWrite(buf);
01786   bytesAdded=0;
01787 
01788   while(*src) {
01789     unsigned char x;
01790     int match;
01791 
01792     match=0;
01793     x=(unsigned char)*src;
01794     if (x=='&') {
01795       if (0 && src[1]=='#') { /* disabled */
01796         unsigned char num=0;
01797 
01798         src++;
01799         while(isdigit((int)*src)) {
01800           num*=10;
01801           num+=(*src)-'0';
01802           src++;
01803         }
01804         src++;
01805         GWEN_TEXT__APPENDCHAR(num);
01806       }
01807       else {
01808         const GWEN_TEXT_ESCAPE_ENTRY *e;
01809         e=gwen_text__xml_escape_chars;
01810         while(e->replace) {
01811           int l;
01812 
01813           l=strlen(e->replace);
01814           if (strncasecmp(src, e->replace, l)==0) {
01815             GWEN_TEXT__APPENDCHAR(e->character);
01816             //GWEN_Buffer_AppendByte(buf, e->character);
01817             src+=l;
01818             match=1;
01819             break;
01820           }
01821           e++;
01822         } /* while */
01823       }
01824     }
01825     if (!match) {
01826       GWEN_TEXT__APPENDCHAR(*(src++));
01827     }
01828   } /* while */
01829 
01830   if (bytesAdded) {
01831     GWEN_Buffer_IncrementPos(buf, bytesAdded);
01832     GWEN_Buffer_AdjustUsedBytes(buf);
01833   }
01834 
01835   return 0;
01836 #undef GWEN_TEXT__APPENDCHAR
01837 }
01838 
01839 
01840 
01841 int GWEN_Text_EscapeXmlToBuffer(const char *src, GWEN_BUFFER *buf) {
01842   while(*src) {
01843     unsigned char x;
01844     const GWEN_TEXT_ESCAPE_ENTRY *e;
01845     int match;
01846 
01847     match=0;
01848     x=(unsigned char)*src;
01849     e=gwen_text__xml_escape_chars;
01850     while(e->replace) {
01851       if (x==e->character) {
01852         GWEN_Buffer_AppendString(buf, e->replace);
01853         match=1;
01854         break;
01855       }
01856       e++;
01857     } /* while */
01858 
01859     if (!match) {
01860       if (0 && x>127) { /* disabled */
01861         char numbuf[32];
01862 
01863         snprintf(numbuf, sizeof(numbuf), "&#%d;", x);
01864         GWEN_Buffer_AppendString(buf, numbuf);
01865       }
01866       else
01867         GWEN_Buffer_AppendByte(buf, *src);
01868     }
01869     src++;
01870   } /* while */
01871 
01872   return 0;
01873 }
01874 
01875 
01876 
01877 
01878 
01879 
01880 
01881 
01882 
01883 
01884 
01885 
Generated on Mon Jul 5 22:51:15 2010 for gwenhywfar by  doxygen 1.6.3