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

Generated on Wed Jul 9 13:12:28 2008 for gwenhywfar by  doxygen 1.5.6