00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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 {'&', "&"},
00053 {'<', "<"},
00054 {'>', ">"},
00055 {'\'', "'"},
00056 {'\"', """},
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
00077 if (flags & GWEN_TEXT_FLAGS_DEL_LEADING_BLANKS) {
00078 while(*src && (unsigned char)(*src)<33)
00079 src++;
00080 }
00081
00082
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
00132
00133
00134 buffer[size]=*src;
00135 size++;
00136 }
00137
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 }
00147 }
00148
00149 src++;
00150 }
00151
00152
00153 buffer[size]=0;
00154
00155 if (insideQuotes) {
00156 DBG_DEBUG(GWEN_LOGDOMAIN, "Missing \" after word");
00157 return 0;
00158 }
00159
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
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
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
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
00256
00257
00258 GWEN_Buffer_AppendByte(buf, *src);
00259 }
00260
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 }
00270 }
00271
00272 src++;
00273 }
00274
00275 if (insideQuotes) {
00276 DBG_ERROR(GWEN_LOGDOMAIN, "Missing \" after word");
00277 return -1;
00278 }
00279
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
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 }
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 }
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
00447 src++;
00448 if (!(*src) || !isxdigit((int)*src)) {
00449 DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete escape sequence (no digits)");
00450 return 0;
00451 }
00452
00453 d1=(unsigned char)(toupper(*src));
00454
00455
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
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
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 }
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
00548 src++;
00549 if (!(*src) || !isxdigit((int)*src)) {
00550 DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete escape sequence (no digits)");
00551 return 0;
00552 }
00553
00554 d1=(unsigned char)(toupper(*src));
00555
00556
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
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
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 }
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
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
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
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
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 }
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
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
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
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
00889 GWEN_Buffer_AppendByte(buf, (char)c);
00890 }
00891 }
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
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
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
00930 d1-='0';
00931 c=(d1<<4)&0xf0;
00932 d2-='0';
00933 c+=(d2&0xf);
00934
00935 GWEN_Buffer_AppendByte(buf, (char)c);
00936 }
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
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
01081 if (_wpos==wlength && _ppos==plength) {
01082 *wpos = _wpos;
01083 *ppos = _ppos;
01084 *matches = _matches;
01085 return 1;
01086 }
01087
01088 if (_wpos>=wlength && _ppos<plength)
01089 if (p[_ppos]=='*') {
01090 *wpos = _wpos;
01091 *ppos = _ppos;
01092 *matches = _matches;
01093 return 1;
01094 }
01095
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
01137 if (!GWEN_Text__cmpSegment(w,&wpos,p,&ppos,sensecase,&matches)) {
01138 return -1;
01139 }
01140
01141 while(1) {
01142
01143 if (ppos>=plength)
01144 return matches;
01145
01146 ppos++;
01147
01148 if (ppos>=plength)
01149 return matches;
01150
01151 if (!GWEN_Text__findSegment(w,&wpos,p,&ppos,sensecase,&matches)) {
01152 return -1;
01153 }
01154 }
01155
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
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
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
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
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
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
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 }
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
01342 src++;
01343 if (!(*src) || !isxdigit((int)*src)) {
01344 DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete escape sequence (no digits)");
01345 return 0;
01346 }
01347
01348 d1=(unsigned char)(toupper(*src));
01349
01350
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
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
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 }
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 }
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
01439 src++;
01440
01441 d1=(unsigned char)(toupper(*src));
01442
01443
01444 src++;
01445 d2=(unsigned char)(toupper(*src));
01446
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
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 }
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 }
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
01545 if (isspace((int)*p)) {
01546 if (!lastWasBlank) {
01547
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
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
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 }
01642
01643 if (lmatch) {
01644 nmatch+=lmatch;
01645 s2=t+1;
01646 }
01647
01648 s1++;
01649 }
01650 }
01651 else {
01652 while(*s1 && *s2) {
01653 const char *t;
01654 int lmatch;
01655
01656
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 }
01673
01674 if (lmatch) {
01675 nmatch+=lmatch;
01676 s2=t+1;
01677 }
01678
01679 s1++;
01680 }
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 }
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]=='#') {
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
01811 src+=l;
01812 match=1;
01813 break;
01814 }
01815 e++;
01816 }
01817 }
01818 }
01819 if (!match) {
01820 GWEN_TEXT__APPENDCHAR(*(src++));
01821 }
01822 }
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 }
01852
01853 if (!match) {
01854 if (0 && x>127) {
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 }
01865
01866 return 0;
01867 }
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879