gwenhywfar 4.0.3

text.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  begin       : Sat Jun 28 2003
00003  copyright   : (C) 2003 by Martin Preuss
00004  email       : martin@libchipcard.de
00005 
00006  ***************************************************************************
00007  *                                                                         *
00008  *   This library is free software; you can redistribute it and/or         *
00009  *   modify it under the terms of the GNU Lesser General Public            *
00010  *   License as published by the Free Software Foundation; either          *
00011  *   version 2.1 of the License, or (at your option) any later version.    *
00012  *                                                                         *
00013  *   This library is distributed in the hope that it will be useful,       *
00014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00016  *   Lesser General Public License for more details.                       *
00017  *                                                                         *
00018  *   You should have received a copy of the GNU Lesser General Public      *
00019  *   License along with this library; if not, write to the Free Software   *
00020  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
00021  *   MA  02111-1307  USA                                                   *
00022  *                                                                         *
00023  ***************************************************************************/
00024 
00025 #ifdef HAVE_CONFIG_H
00026 # include <config.h>
00027 #endif
00028 
00029 #define DISABLE_DEBUGLOG
00030 
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 const char *GWEN_Text_StrCaseStr(const char *haystack, const char *needle) {
01041   while(*haystack) {
01042     while(*haystack && tolower(*haystack)!=tolower(*needle))
01043       haystack++;
01044     if (*haystack) {
01045       const char *t;
01046       const char *s;
01047 
01048       /* now haystack points to an area which begins with *needle */
01049       t=haystack;
01050       s=needle;
01051       t++;
01052       s++;
01053       while(*t && *s && (tolower(*t)==tolower(*s))) {
01054         t++;
01055         s++;
01056       }
01057       if (*s==0)
01058         return haystack;
01059     }
01060     else
01061       /* not found */
01062       break;
01063     /* no match here, advance haystack */
01064     haystack++;
01065   }
01066 
01067   /* not found */
01068   return NULL;
01069 }
01070 
01071 
01072 
01073 
01074 int GWEN_Text__cmpSegment(const char *w, unsigned int *wpos,
01075                           const char *p, unsigned int *ppos,
01076                           int sensecase,
01077                           unsigned int *matches) {
01078   char a;
01079   char b;
01080   unsigned wlength;
01081   unsigned plength;
01082 
01083   unsigned int _wpos = *wpos, _ppos = *ppos, _matches = *matches;
01084 
01085   a=0;
01086   b=0;
01087   wlength=strlen(w);
01088   plength=strlen(p);
01089 
01090   while (_wpos<wlength && _ppos<plength) {
01091     a=w[_wpos];
01092     b=p[_ppos];
01093     if (b=='*') {
01094       *wpos = _wpos;
01095       *ppos = _ppos;
01096       *matches = _matches;
01097       return 1;
01098     }
01099     if (!sensecase) {
01100       a=toupper(a);
01101       b=toupper(b);
01102     }
01103     /* count matches */
01104     if (a==b)
01105       ++_matches;
01106     if (a!=b && b!='?') {
01107       *wpos = _wpos;
01108       *ppos = _ppos;
01109       *matches = _matches;
01110       return 0;
01111     }
01112     ++_wpos;
01113     ++_ppos;
01114   }
01115   /* both at end, would be ok */
01116   if (_wpos==wlength && _ppos==plength) {
01117     *wpos = _wpos;
01118     *ppos = _ppos;
01119     *matches = _matches;
01120     return 1;
01121   }
01122   /* word ends, pattern doesnt, would be ok if pattern is '*' here */
01123   if (_wpos>=wlength && _ppos<plength)
01124     if (p[_ppos]=='*') {
01125       *wpos = _wpos;
01126       *ppos = _ppos;
01127       *matches = _matches;
01128       return 1;
01129     }
01130   /* otherwise no match ;-/ */
01131   *wpos = _wpos;
01132   *ppos = _ppos;
01133   *matches = _matches;
01134   return 0;
01135 }
01136 
01137 
01138 
01139 int GWEN_Text__findSegment(const char *w, unsigned int *wpos,
01140                            const char *p, unsigned int *ppos,
01141                            int sensecase,
01142                            unsigned int *matches) {
01143   unsigned int lwpos, lppos, lmatches;
01144   unsigned wlength;
01145 
01146   wlength=strlen(w);
01147   lwpos=*wpos;
01148   lppos=*ppos;
01149   lmatches=*matches;
01150   while(lwpos<wlength) {
01151     *ppos=lppos;
01152     *wpos=lwpos;
01153     *matches=lmatches;
01154     if (GWEN_Text__cmpSegment(w,wpos,p,ppos,sensecase,matches))
01155       return 1;
01156     lwpos++;
01157   }
01158   return 0;
01159 }
01160 
01161 
01162 int GWEN_Text_ComparePattern(const char *w, const char *p, int sensecase) {
01163   unsigned int ppos;
01164   unsigned int wpos;
01165   unsigned int matches;
01166   unsigned int plength;
01167 
01168   ppos=wpos=matches=0;
01169   plength=strlen(p);
01170 
01171   /* compare until first occurrence of '*' */
01172   if (!GWEN_Text__cmpSegment(w,&wpos,p,&ppos,sensecase,&matches)) {
01173     return -1;
01174   }
01175 
01176   while(1) {
01177     /* if pattern ends we have done it */
01178     if (ppos>=plength)
01179       return matches;
01180     /* skip '*' in pattern */
01181     ppos++;
01182     /* if pattern ends behind '*' the word matches */
01183     if (ppos>=plength)
01184       return matches;
01185     /* find next matching segment */
01186     if (!GWEN_Text__findSegment(w,&wpos,p,&ppos,sensecase,&matches)) {
01187       return -1;
01188     }
01189   } /* while */
01190   /* I know, we'll never get to here ;-) */
01191   return -1;
01192 }
01193 
01194 
01195 
01196 int GWEN_Text_NumToString(int num, char *buffer, unsigned int bufsize,
01197                           int fillchar){
01198   char lbuffer[128];
01199   unsigned int i;
01200 
01201   sprintf(lbuffer,"%d", num);
01202   i=strlen(lbuffer);
01203   if (i>=bufsize) {
01204     DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small (%d>=%d)", i, bufsize);
01205     return -1;
01206   }
01207   if (fillchar>0) {
01208     /* fill right, but first copy chars */
01209     strcpy(buffer, lbuffer);
01210     while(i<bufsize-1)
01211       buffer[i++]=fillchar;
01212     buffer[i]=0;
01213     return bufsize;
01214   }
01215   else if (fillchar<0) {
01216     int j, k;
01217 
01218     fillchar=-fillchar;
01219     j=bufsize-1-i;
01220     for (k=0; k<j; k++)
01221       buffer[k]=fillchar;
01222     buffer[k]=0;
01223     strcat(buffer, lbuffer);
01224     return bufsize;
01225   }
01226   else {
01227     /* dont fill, just copy */
01228     strcpy(buffer, lbuffer);
01229     return i;
01230   }
01231 }
01232 
01233 
01234 
01235 void GWEN_Text_DumpString(const char *s, unsigned int l,
01236                           unsigned int insert) {
01237   unsigned int i;
01238   unsigned int j;
01239   unsigned int pos;
01240   unsigned k;
01241 
01242   pos=0;
01243   for (k=0; k<insert; k++)
01244     fprintf(stderr, " ");
01245   fprintf(stderr,"String size is %d:\n",l);
01246   while(pos<l) {
01247     for (k=0; k<insert; k++)
01248       fprintf(stderr, " ");
01249     fprintf(stderr,"%04x: ",pos);
01250     j=pos+16;
01251     if (j>=l)
01252       j=l;
01253 
01254     /* show hex dump */
01255     for (i=pos; i<j; i++) {
01256       fprintf(stderr,"%02x ",(unsigned char)s[i]);
01257     }
01258     if (j-pos<16)
01259       for (i=0; i<16-(j-pos); i++)
01260         fprintf(stderr,"   ");
01261     /* show text */
01262     for (i=pos; i<j; i++) {
01263       if (s[i]<32)
01264         fprintf(stderr,".");
01265       else
01266         fprintf(stderr,"%c",s[i]);
01267     }
01268     fprintf(stderr,"\n");
01269     pos+=16;
01270   }
01271 }
01272 
01273 
01274 
01275 void GWEN_Text_DumpString2Buffer(const char *s, unsigned int l,
01276                                  GWEN_BUFFER *mbuf,
01277                                  unsigned int insert) {
01278   unsigned int i;
01279   unsigned int j;
01280   unsigned int pos;
01281   unsigned k;
01282   char numbuf[32];
01283 
01284   pos=0;
01285   for (k=0; k<insert; k++)
01286     GWEN_Buffer_AppendByte(mbuf, ' ');
01287   GWEN_Buffer_AppendString(mbuf,"String size is ");
01288   snprintf(numbuf, sizeof(numbuf), "%d", l);
01289   GWEN_Buffer_AppendString(mbuf, numbuf);
01290   GWEN_Buffer_AppendByte(mbuf, '\n');
01291   while(pos<l) {
01292     for (k=0; k<insert; k++)
01293       GWEN_Buffer_AppendByte(mbuf, ' ');
01294     snprintf(numbuf, sizeof(numbuf),"%04x: ",pos);
01295     GWEN_Buffer_AppendString(mbuf, numbuf);
01296     j=pos+16;
01297     if (j>=l)
01298       j=l;
01299 
01300     /* show hex dump */
01301     for (i=pos; i<j; i++) {
01302       snprintf(numbuf, sizeof(numbuf),"%02x ", (unsigned char)s[i]);
01303       GWEN_Buffer_AppendString(mbuf, numbuf);
01304     }
01305     if (j-pos<16)
01306       for (i=0; i<16-(j-pos); i++)
01307         GWEN_Buffer_AppendString(mbuf, "   ");
01308     /* show text */
01309     for (i=pos; i<j; i++) {
01310       if (s[i]<32)
01311         GWEN_Buffer_AppendByte(mbuf, '.');
01312       else
01313         GWEN_Buffer_AppendByte(mbuf, s[i]);
01314     }
01315     GWEN_Buffer_AppendByte(mbuf, '\n');
01316     pos+=16;
01317   }
01318 }
01319 
01320 
01321 
01322 
01323 
01324 
01325 
01326 int GWEN_Text_EscapeToBuffer(const char *src, GWEN_BUFFER *buf) {
01327   while(*src) {
01328     unsigned char x;
01329 
01330     x=(unsigned char)*src;
01331     if (!(
01332           (x>='A' && x<='Z') ||
01333           (x>='a' && x<='z') ||
01334           (x>='0' && x<='9'))) {
01335       unsigned char c;
01336 
01337       GWEN_Buffer_AppendByte(buf, '%');
01338       c=(((unsigned char)(*src))>>4)&0xf;
01339       if (c>9)
01340         c+=7;
01341       c+='0';
01342       GWEN_Buffer_AppendByte(buf, c);
01343       c=((unsigned char)(*src))&0xf;
01344       if (c>9)
01345         c+=7;
01346       c+='0';
01347       GWEN_Buffer_AppendByte(buf, c);
01348     }
01349     else
01350       GWEN_Buffer_AppendByte(buf, *src);
01351 
01352     src++;
01353   } /* while */
01354 
01355   return 0;
01356 }
01357 
01358 
01359 
01360 int GWEN_Text_UnescapeToBuffer(const char *src, GWEN_BUFFER *buf) {
01361   while(*src) {
01362     unsigned char x;
01363 
01364     x=(unsigned char)*src;
01365     if (
01366         (x>='A' && x<='Z') ||
01367         (x>='a' && x<='z') ||
01368         (x>='0' && x<='9')) {
01369       GWEN_Buffer_AppendByte(buf, *src);
01370     }
01371     else {
01372       if (*src=='%') {
01373         unsigned char d1, d2;
01374         unsigned char c;
01375 
01376         /* skip '%' */
01377         src++;
01378         if (!(*src) || !isxdigit((int)*src)) {
01379           DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete escape sequence (no digits)");
01380           return 0;
01381         }
01382         /* read first digit */
01383         d1=(unsigned char)(toupper(*src));
01384 
01385         /* get second digit */
01386         src++;
01387         if (!(*src) || !isxdigit((int)*src)) {
01388           DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete escape sequence (only 1 digit)");
01389           return 0;
01390         }
01391         d2=(unsigned char)(toupper(*src));
01392         /* compute character */
01393         d1-='0';
01394         if (d1>9)
01395           d1-=7;
01396         c=(d1<<4)&0xf0;
01397         d2-='0';
01398         if (d2>9)
01399           d2-=7;
01400         c+=(d2&0xf);
01401         /* store character */
01402         GWEN_Buffer_AppendByte(buf, (char)c);
01403       }
01404       else {
01405         DBG_ERROR(GWEN_LOGDOMAIN, "Found non-alphanum "
01406                   "characters in escaped string (\"%s\")",
01407                   src);
01408         return -1;
01409       }
01410     }
01411     src++;
01412   } /* while */
01413 
01414   return 0;
01415 }
01416 
01417 
01418 
01419 int GWEN_Text_EscapeToBufferTolerant(const char *src, GWEN_BUFFER *buf) {
01420   while(*src) {
01421     unsigned char x;
01422 
01423     x=(unsigned char)*src;
01424     if (!(
01425           (x>='A' && x<='Z') ||
01426           (x>='a' && x<='z') ||
01427           (x>='0' && x<='9') ||
01428           x==' ' ||
01429           x=='.' ||
01430           x==',' ||
01431           x=='.' ||
01432           x=='_' ||
01433           x=='-' ||
01434           x=='*' ||
01435           x=='?'
01436          )) {
01437       unsigned char c;
01438 
01439       GWEN_Buffer_AppendByte(buf, '%');
01440       c=(((unsigned char)(*src))>>4)&0xf;
01441       if (c>9)
01442         c+=7;
01443       c+='0';
01444       GWEN_Buffer_AppendByte(buf, c);
01445       c=((unsigned char)(*src))&0xf;
01446       if (c>9)
01447         c+=7;
01448       c+='0';
01449       GWEN_Buffer_AppendByte(buf, c);
01450     }
01451     else
01452       GWEN_Buffer_AppendByte(buf, *src);
01453 
01454     src++;
01455   } /* while */
01456 
01457   return 0;
01458 }
01459 
01460 
01461 
01462 int GWEN_Text_UnescapeToBufferTolerant(const char *src, GWEN_BUFFER *buf) {
01463   while(*src) {
01464     const char *srcBak;
01465     int charHandled;
01466 
01467     srcBak=src;
01468     charHandled=0;
01469     if (*src=='%') {
01470       if (strlen(src)>2) {
01471         unsigned char d1, d2;
01472         unsigned char c;
01473 
01474         if (isxdigit((int)src[1]) && isxdigit((int)src[2])) {
01475           /* skip '%' */
01476           src++;
01477           /* read first digit */
01478           d1=(unsigned char)(toupper(*src));
01479 
01480           /* get second digit */
01481           src++;
01482           d2=(unsigned char)(toupper(*src));
01483           /* compute character */
01484           d1-='0';
01485           if (d1>9)
01486             d1-=7;
01487           c=(d1<<4)&0xf0;
01488           d2-='0';
01489           if (d2>9)
01490             d2-=7;
01491           c+=(d2&0xf);
01492           /* store character */
01493           GWEN_Buffer_AppendByte(buf, (char)c);
01494           charHandled=1;
01495         }
01496       }
01497     }
01498     if (!charHandled)
01499       GWEN_Buffer_AppendByte(buf, *src);
01500     src++;
01501   } /* while */
01502 
01503   return 0;
01504 }
01505 
01506 
01507 
01508 int GWEN_Text_EscapeToBufferTolerant2(GWEN_BUFFER *src, GWEN_BUFFER *buf) {
01509   while(GWEN_Buffer_GetBytesLeft(src)) {
01510     int z;
01511     unsigned char x;
01512 
01513     z=GWEN_Buffer_ReadByte(src);
01514     if (z==-1) {
01515       DBG_INFO(GWEN_LOGDOMAIN, "here");
01516       return -1;
01517     }
01518     x=(unsigned char)z;
01519     if (!(
01520           (x>='A' && x<='Z') ||
01521           (x>='a' && x<='z') ||
01522           (x>='0' && x<='9') ||
01523           x==' ' ||
01524           x=='.' ||
01525           x==',' ||
01526           x=='.' ||
01527           x=='*' ||
01528           x=='?'
01529          )) {
01530       unsigned char c;
01531 
01532       GWEN_Buffer_AppendByte(buf, '%');
01533       c=(((unsigned char)x)>>4)&0xf;
01534       if (c>9)
01535         c+=7;
01536       c+='0';
01537       GWEN_Buffer_AppendByte(buf, c);
01538       c=((unsigned char)x)&0xf;
01539       if (c>9)
01540         c+=7;
01541       c+='0';
01542       GWEN_Buffer_AppendByte(buf, c);
01543     }
01544     else
01545       GWEN_Buffer_AppendByte(buf, x);
01546   } /* while */
01547 
01548   return 0;
01549 }
01550 
01551 
01552 
01553 void GWEN_Text_LogString(const char *s, unsigned int l,
01554                          const char *logDomain,
01555                          GWEN_LOGGER_LEVEL lv){
01556   GWEN_BUFFER *mbuf;
01557 
01558   mbuf=GWEN_Buffer_new(0, ((l*16)<1024)?1024:l*16, 0, 1);
01559   GWEN_Text_DumpString2Buffer(s, l, mbuf, 0);
01560   GWEN_Logger_Log(logDomain, lv, GWEN_Buffer_GetStart(mbuf));
01561   GWEN_Buffer_free(mbuf);
01562 }
01563 
01564 
01565 
01566 void GWEN_Text_CondenseBuffer(GWEN_BUFFER *buf){
01567   const char *p;
01568   char *dst;
01569   unsigned int size;
01570   unsigned int i;
01571   int lastWasBlank;
01572   char *lastBlankPos;
01573 
01574   dst=GWEN_Buffer_GetStart(buf);
01575   p=dst;
01576   size=GWEN_Buffer_GetUsedBytes(buf);
01577   lastWasBlank=0;
01578   lastBlankPos=0;
01579 
01580   for (i=0; i<size; i++) {
01581     /* remember next loop whether this char was a blank */
01582     if (isspace((int)*p)) {
01583       if (!lastWasBlank) {
01584         /* store only one blank */
01585         lastWasBlank=1;
01586         lastBlankPos=dst;
01587         *(dst++)=*p;
01588       }
01589     }
01590     else {
01591       lastWasBlank=0;
01592       lastBlankPos=0;
01593       *(dst++)=*p;
01594     }
01595     p++;
01596   }
01597 
01598   /* remove trailing blanks */
01599   if (lastBlankPos!=0)
01600     dst=lastBlankPos;
01601 
01602   size=dst-GWEN_Buffer_GetStart(buf);
01603   GWEN_Buffer_Crop(buf, 0, size);
01604 }
01605 
01606 
01607 
01608 int GWEN_Text_DoubleToBuffer(double num, GWEN_BUFFER *buf){
01609   char numbuf[128];
01610   int rv;
01611 #ifdef HAVE_SETLOCALE
01612   const char *orig_locale = setlocale(LC_NUMERIC, NULL);
01613   char *currentLocale = strdup(orig_locale ? orig_locale : "C");
01614   setlocale(LC_NUMERIC,"C");
01615 #endif
01616 
01617   rv=snprintf(numbuf, sizeof(numbuf), "%f", num);
01618 
01619 #ifdef HAVE_SETLOCALE
01620   setlocale(LC_NUMERIC, currentLocale);
01621   free(currentLocale);
01622 #endif
01623 
01624   if (rv<1 || rv>=sizeof(numbuf))
01625     return -1;
01626   GWEN_Buffer_AppendString(buf, numbuf);
01627   return 0;
01628 }
01629 
01630 
01631 
01632 int GWEN_Text_StringToDouble(const char *s, double *num){
01633   int rv;
01634 #ifdef HAVE_SETLOCALE
01635   const char *orig_locale = setlocale(LC_NUMERIC, NULL);
01636   char *currentLocale = strdup(orig_locale ? orig_locale : "C");
01637   setlocale(LC_NUMERIC,"C");
01638 #endif
01639 
01640   rv=sscanf(s, "%lf", num);
01641 
01642 #ifdef HAVE_SETLOCALE
01643   setlocale(LC_NUMERIC, currentLocale);
01644   free(currentLocale);
01645 #endif
01646 
01647   if (rv!=1)
01648     return -1;
01649   return 0;
01650 }
01651 
01652 
01653 
01654 double GWEN_Text__CheckSimilarity(const char *s1, const char *s2, int ign){
01655   int nboth;
01656   int nmatch;
01657   double pc;
01658 
01659   nboth=strlen(s1)+strlen(s2);
01660   nmatch=0;
01661   if (ign) {
01662     while(*s1 && *s2) {
01663       const char *t;
01664       int lmatch;
01665 
01666       /* find next equal in s2 */
01667       t=s2;
01668       lmatch=0;
01669       while(*t) {
01670         if (toupper(*s1)==toupper(*t)) {
01671           lmatch=2;
01672           break;
01673         }
01674         if (isalnum((int)*s1) && isalnum((int)*t)) {
01675           lmatch=1;
01676           break;
01677         }
01678         t++;
01679       } /* while */
01680 
01681       if (lmatch) {
01682         nmatch+=lmatch;
01683         s2=t+1;
01684       }
01685 
01686       s1++;
01687     } /* while */
01688   }
01689   else {
01690     while(*s1 && *s2) {
01691       const char *t;
01692       int lmatch;
01693 
01694       /* find next equal in s2 */
01695       t=s2;
01696       lmatch=0;
01697       while(*t) {
01698         if (*s1==*t) {
01699           lmatch=2;
01700           break;
01701         }
01702         if (toupper(*s1)==toupper(*t)) {
01703           lmatch=1;
01704           break;
01705         }
01706         if (isalnum((int)*s1) && isalnum((int)*t)) {
01707           lmatch=1;
01708           break;
01709         }
01710         t++;
01711       } /* while */
01712 
01713       if (lmatch) {
01714         nmatch+=lmatch;
01715         s2=t+1;
01716       }
01717 
01718       s1++;
01719     } /* while */
01720   }
01721 
01722   pc=(nmatch*100)/nboth;
01723   return pc;
01724 }
01725 
01726 
01727 
01728 double GWEN_Text_CheckSimilarity(const char *s1, const char *s2, int ign){
01729   double pc1, pc2;
01730 
01731   pc1=GWEN_Text__CheckSimilarity(s1, s2, ign);
01732   pc2=GWEN_Text__CheckSimilarity(s2, s1, ign);
01733   if (pc2>pc1)
01734     return pc2;
01735   return pc1;
01736 }
01737 
01738 
01739 
01740 int GWEN_Text_CountUtf8Chars(const char *s, int len) {
01741   int count;
01742   int handled;
01743 
01744   if (len==0)
01745     len=strlen(s);
01746   count=0;
01747   handled=0;
01748   while(handled<len) {
01749     unsigned char c;
01750     int i;
01751 
01752     c=(unsigned char)*s;
01753     if ((c & 0xfe)==0xfc)
01754       i=5;
01755     else if ((c & 0xfc)==0xf8)
01756       i=4;
01757     else if ((c & 0xf8)==0xf0)
01758       i=3;
01759     else if ((c & 0xf0)==0xe0)
01760       i=2;
01761     else if ((c & 0xe0)==0xc0)
01762       i=1;
01763     else if (c & 0x80) {
01764       DBG_ERROR(GWEN_LOGDOMAIN, "Invalid UTF8 character at pos %d", handled);
01765       return -1;
01766     }
01767     else
01768       i=0;
01769     if (handled+i+1>len) {
01770       DBG_ERROR(GWEN_LOGDOMAIN,
01771                 "Incomplete UTF8 sequence at pos %d", handled);
01772       return -1;
01773     }
01774     s++;
01775     if (i) {
01776       int j;
01777 
01778       for (j=0; j<i; j++) {
01779         if ((((unsigned char)*s) & 0xc0)!=0xc0) {
01780           DBG_ERROR(GWEN_LOGDOMAIN,
01781                     "Invalid UTF8 sequence at pos %d (rel %d of %d)",
01782                     handled, j, i);
01783         }
01784         s++;
01785       }
01786     }
01787     handled+=i+1;
01788     count++;
01789   } /* while */
01790 
01791   return count;
01792 }
01793 
01794 
01795 
01796 int GWEN_Text_UnescapeXmlToBuffer(const char *src, GWEN_BUFFER *buf) {
01797   char *pdst;
01798   uint32_t roomLeft;
01799   uint32_t bytesAdded;
01800 
01801 #define GWEN_TEXT__APPENDCHAR(chr)                     \
01802   if (roomLeft<2) {                                   \
01803     if (bytesAdded) {                                 \
01804       GWEN_Buffer_IncrementPos(buf, bytesAdded);      \
01805       GWEN_Buffer_AdjustUsedBytes(buf);               \
01806     }                                                 \
01807     GWEN_Buffer_AllocRoom(buf, 2);                    \
01808     pdst=GWEN_Buffer_GetPosPointer(buf);              \
01809     roomLeft=GWEN_Buffer_GetMaxUnsegmentedWrite(buf); \
01810     bytesAdded=0;                                     \
01811    }                                                  \
01812    *(pdst++)=(unsigned char)chr;                      \
01813    *pdst=0;                                           \
01814    bytesAdded++;                                      \
01815   roomLeft--
01816 
01817   pdst=GWEN_Buffer_GetPosPointer(buf);
01818   roomLeft=GWEN_Buffer_GetMaxUnsegmentedWrite(buf);
01819   bytesAdded=0;
01820 
01821   while(*src) {
01822     unsigned char x;
01823     int match;
01824 
01825     match=0;
01826     x=(unsigned char)*src;
01827     if (x=='&') {
01828       if (src[1]=='#') {
01829         unsigned char num=0;
01830 
01831         src++;
01832         src++;
01833         while(*src && isdigit((int)*src)) {
01834           num*=10;
01835           num+=(*src)-'0';
01836           src++;
01837         }
01838         src++;
01839         GWEN_TEXT__APPENDCHAR(num);
01840       }
01841       else if (strncmp(src+1, "szlig;", 6)==0) {
01842         GWEN_TEXT__APPENDCHAR(0xc3);
01843         GWEN_TEXT__APPENDCHAR(0x9f);
01844         src+=7;
01845         match=1;
01846       }
01847       else if (strncmp(src+1, "Auml;", 5)==0) {
01848         GWEN_TEXT__APPENDCHAR(0xc3);
01849         GWEN_TEXT__APPENDCHAR(0x84);
01850         src+=6;
01851         match=1;
01852       }
01853       else if (strncmp(src+1, "Ouml;", 5)==0) {
01854         GWEN_TEXT__APPENDCHAR(0xc3);
01855         GWEN_TEXT__APPENDCHAR(0x96);
01856         src+=6;
01857         match=1;
01858       }
01859       else if (strncmp(src+1, "Uuml;", 5)==0) {
01860         GWEN_TEXT__APPENDCHAR(0xc3);
01861         GWEN_TEXT__APPENDCHAR(0x9c);
01862         src+=6;
01863         match=1;
01864       }
01865       else if (strncmp(src+1, "auml;", 5)==0) {
01866         GWEN_TEXT__APPENDCHAR(0xc3);
01867         GWEN_TEXT__APPENDCHAR(0xa4);
01868         src+=6;
01869         match=1;
01870       }
01871       else if (strncmp(src+1, "ouml;", 5)==0) {
01872         GWEN_TEXT__APPENDCHAR(0xc3);
01873         GWEN_TEXT__APPENDCHAR(0xb6);
01874         src+=6;
01875         match=1;
01876       }
01877       else if (strncmp(src+1, "uuml;", 5)==0) {
01878         GWEN_TEXT__APPENDCHAR(0xc3);
01879         GWEN_TEXT__APPENDCHAR(0xbc);
01880         src+=6;
01881         match=1;
01882       }
01883       else {
01884         const GWEN_TEXT_ESCAPE_ENTRY *e;
01885         e=gwen_text__xml_escape_chars;
01886         while(e->replace) {
01887           int l;
01888 
01889           l=strlen(e->replace);
01890           if (strncasecmp(src, e->replace, l)==0) {
01891             GWEN_TEXT__APPENDCHAR(e->character);
01892             //GWEN_Buffer_AppendByte(buf, e->character);
01893             src+=l;
01894             match=1;
01895             break;
01896           }
01897           e++;
01898         } /* while */
01899       }
01900     }
01901     if (!match) {
01902       GWEN_TEXT__APPENDCHAR(*(src++));
01903     }
01904   } /* while */
01905 
01906   if (bytesAdded) {
01907     GWEN_Buffer_IncrementPos(buf, bytesAdded);
01908     GWEN_Buffer_AdjustUsedBytes(buf);
01909   }
01910 
01911   return 0;
01912 #undef GWEN_TEXT__APPENDCHAR
01913 }
01914 
01915 
01916 
01917 int GWEN_Text_EscapeXmlToBuffer(const char *src, GWEN_BUFFER *buf) {
01918   while(*src) {
01919     unsigned char x;
01920     const GWEN_TEXT_ESCAPE_ENTRY *e;
01921     int match;
01922 
01923     match=0;
01924     x=(unsigned char)*src;
01925     e=gwen_text__xml_escape_chars;
01926     while(e->replace) {
01927       if (x==e->character) {
01928         GWEN_Buffer_AppendString(buf, e->replace);
01929         match=1;
01930         break;
01931       }
01932       e++;
01933     } /* while */
01934 
01935     if (!match) {
01936       if (0 && x>127) { /* disabled */
01937         char numbuf[32];
01938 
01939         snprintf(numbuf, sizeof(numbuf), "&#%d;", x);
01940         GWEN_Buffer_AppendString(buf, numbuf);
01941       }
01942       else
01943         GWEN_Buffer_AppendByte(buf, *src);
01944     }
01945     src++;
01946   } /* while */
01947 
01948   return 0;
01949 }
01950 
01951 
01952 
01953