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 const char *savedSrc=src;
00193 int lastWasBlank;
00194 int lastBlankPos;
00195 int insideQuotes;
00196 int lastWasEscape;
00197
00198
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
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
00257
00258
00259 GWEN_Buffer_AppendByte(buf, *src);
00260 }
00261
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 }
00272 }
00273
00274 src++;
00275 }
00276
00277 if (insideQuotes) {
00278 DBG_ERROR(GWEN_LOGDOMAIN, "Missing \" after word (at %d: [%s])", (int)(src-savedSrc), savedSrc);
00279 return -1;
00280 }
00281
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
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 }
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 }
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
00449 src++;
00450 if (!(*src) || !isxdigit((int)*src)) {
00451 DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete escape sequence (no digits)");
00452 return 0;
00453 }
00454
00455 d1=(unsigned char)(toupper(*src));
00456
00457
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
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
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 }
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
00550 src++;
00551 if (!(*src) || !isxdigit((int)*src)) {
00552 DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete escape sequence (no digits)");
00553 return 0;
00554 }
00555
00556 d1=(unsigned char)(toupper(*src));
00557
00558
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
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
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 }
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
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
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
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
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 }
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
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
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
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
00891 GWEN_Buffer_AppendByte(buf, (char)c);
00892 }
00893 }
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
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
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
00932 d1-='0';
00933 c=(d1<<4)&0xf0;
00934 d2-='0';
00935 c+=(d2&0xf);
00936
00937 GWEN_Buffer_AppendByte(buf, (char)c);
00938 }
00939
00940 return 0;
00941 }
00942
00943
00944
00945 int GWEN_Text_ToBcdBuffer(const char *src, unsigned l,
00946 GWEN_BUFFER *buf,
00947 unsigned int groupsize,
00948 char delimiter,
00949 int skipLeadingZeroes){
00950 unsigned int pos;
00951 unsigned int size;
00952 unsigned int j;
00953
00954 j=0;
00955
00956 pos=0;
00957 size=0;
00958 j=0;
00959 while(pos<l) {
00960 unsigned char c;
00961 int skipThis;
00962
00963 skipThis=0;
00964 c=(((unsigned char)(src[pos]))>>4)&0xf;
00965 if (skipLeadingZeroes) {
00966 if (c==0)
00967 skipThis=1;
00968 else
00969 skipLeadingZeroes=0;
00970 }
00971 c+='0';
00972 if (!skipThis) {
00973 if (GWEN_Buffer_AppendByte(buf, c)) {
00974 DBG_INFO(GWEN_LOGDOMAIN, "here");
00975 return -1;
00976 }
00977 j++;
00978 if (groupsize && j==groupsize) {
00979 if (GWEN_Buffer_AppendByte(buf, delimiter)) {
00980 DBG_INFO(GWEN_LOGDOMAIN, "here");
00981 return -1;
00982 }
00983 j=0;
00984 }
00985 }
00986
00987 skipThis=0;
00988 c=((unsigned char)(src[pos]))&0xf;
00989 if (skipLeadingZeroes) {
00990 if (c==0 && pos+1<l)
00991 skipThis=1;
00992 else
00993 skipLeadingZeroes=0;
00994 }
00995 c+='0';
00996 if (!skipThis) {
00997 if (GWEN_Buffer_AppendByte(buf, c)) {
00998 DBG_INFO(GWEN_LOGDOMAIN, "here");
00999 return -1;
01000 }
01001 j++;
01002 if (groupsize && j==groupsize) {
01003 if (pos+1<l) {
01004 if (GWEN_Buffer_AppendByte(buf, delimiter)) {
01005 DBG_INFO(GWEN_LOGDOMAIN, "here");
01006 return -1;
01007 }
01008 }
01009 j=0;
01010 }
01011 }
01012 pos++;
01013 }
01014 return 0;
01015 }
01016
01017
01018
01019 int GWEN_Text_Compare(const char *s1, const char *s2, int ign) {
01020 if (s1)
01021 if (*s1==0)
01022 s1=0;
01023 if (s2)
01024 if (*s2==0)
01025 s2=0;
01026 if (!s1 && !s2)
01027 return 0;
01028 if (!s1 && s2)
01029 return 1;
01030 if (s1 && !s2)
01031 return -1;
01032 if (ign)
01033 return strcasecmp(s1, s2);
01034 else
01035 return strcmp(s1, s2);
01036 }
01037
01038
01039
01040
01041 int GWEN_Text__cmpSegment(const char *w, unsigned int *wpos,
01042 const char *p, unsigned int *ppos,
01043 int sensecase,
01044 unsigned int *matches) {
01045 char a;
01046 char b;
01047 unsigned wlength;
01048 unsigned plength;
01049
01050 unsigned int _wpos = *wpos, _ppos = *ppos, _matches = *matches;
01051
01052 a=0;
01053 b=0;
01054 wlength=strlen(w);
01055 plength=strlen(p);
01056
01057 while (_wpos<wlength && _ppos<plength) {
01058 a=w[_wpos];
01059 b=p[_ppos];
01060 if (b=='*') {
01061 *wpos = _wpos;
01062 *ppos = _ppos;
01063 *matches = _matches;
01064 return 1;
01065 }
01066 if (!sensecase) {
01067 a=toupper(a);
01068 b=toupper(b);
01069 }
01070
01071 if (a==b)
01072 ++_matches;
01073 if (a!=b && b!='?') {
01074 *wpos = _wpos;
01075 *ppos = _ppos;
01076 *matches = _matches;
01077 return 0;
01078 }
01079 ++_wpos;
01080 ++_ppos;
01081 }
01082
01083 if (_wpos==wlength && _ppos==plength) {
01084 *wpos = _wpos;
01085 *ppos = _ppos;
01086 *matches = _matches;
01087 return 1;
01088 }
01089
01090 if (_wpos>=wlength && _ppos<plength)
01091 if (p[_ppos]=='*') {
01092 *wpos = _wpos;
01093 *ppos = _ppos;
01094 *matches = _matches;
01095 return 1;
01096 }
01097
01098 *wpos = _wpos;
01099 *ppos = _ppos;
01100 *matches = _matches;
01101 return 0;
01102 }
01103
01104
01105
01106 int GWEN_Text__findSegment(const char *w, unsigned int *wpos,
01107 const char *p, unsigned int *ppos,
01108 int sensecase,
01109 unsigned int *matches) {
01110 unsigned int lwpos, lppos, lmatches;
01111 unsigned wlength;
01112
01113 wlength=strlen(w);
01114 lwpos=*wpos;
01115 lppos=*ppos;
01116 lmatches=*matches;
01117 while(lwpos<wlength) {
01118 *ppos=lppos;
01119 *wpos=lwpos;
01120 *matches=lmatches;
01121 if (GWEN_Text__cmpSegment(w,wpos,p,ppos,sensecase,matches))
01122 return 1;
01123 lwpos++;
01124 }
01125 return 0;
01126 }
01127
01128
01129 int GWEN_Text_ComparePattern(const char *w, const char *p, int sensecase) {
01130 unsigned int ppos;
01131 unsigned int wpos;
01132 unsigned int matches;
01133 unsigned int plength;
01134
01135 ppos=wpos=matches=0;
01136 plength=strlen(p);
01137
01138
01139 if (!GWEN_Text__cmpSegment(w,&wpos,p,&ppos,sensecase,&matches)) {
01140 return -1;
01141 }
01142
01143 while(1) {
01144
01145 if (ppos>=plength)
01146 return matches;
01147
01148 ppos++;
01149
01150 if (ppos>=plength)
01151 return matches;
01152
01153 if (!GWEN_Text__findSegment(w,&wpos,p,&ppos,sensecase,&matches)) {
01154 return -1;
01155 }
01156 }
01157
01158 return -1;
01159 }
01160
01161
01162
01163 int GWEN_Text_NumToString(int num, char *buffer, unsigned int bufsize,
01164 int fillchar){
01165 char lbuffer[128];
01166 unsigned int i;
01167
01168 sprintf(lbuffer,"%d", num);
01169 i=strlen(lbuffer);
01170 if (i>=bufsize) {
01171 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small (%d>=%d)", i, bufsize);
01172 return -1;
01173 }
01174 if (fillchar>0) {
01175
01176 strcpy(buffer, lbuffer);
01177 while(i<bufsize-1)
01178 buffer[i++]=fillchar;
01179 buffer[i]=0;
01180 return bufsize;
01181 }
01182 else if (fillchar<0) {
01183 int j, k;
01184
01185 fillchar=-fillchar;
01186 j=bufsize-1-i;
01187 for (k=0; k<j; k++)
01188 buffer[k]=fillchar;
01189 buffer[k]=0;
01190 strcat(buffer, lbuffer);
01191 return bufsize;
01192 }
01193 else {
01194
01195 strcpy(buffer, lbuffer);
01196 return i;
01197 }
01198 }
01199
01200
01201
01202 void GWEN_Text_DumpString(const char *s, unsigned int l,
01203 FILE *f, unsigned int insert) {
01204 unsigned int i;
01205 unsigned int j;
01206 unsigned int pos;
01207 unsigned k;
01208
01209 pos=0;
01210 for (k=0; k<insert; k++)
01211 fprintf(f, " ");
01212 fprintf(f,"String size is %d:\n",l);
01213 while(pos<l) {
01214 for (k=0; k<insert; k++)
01215 fprintf(f, " ");
01216 fprintf(f,"%04x: ",pos);
01217 j=pos+16;
01218 if (j>=l)
01219 j=l;
01220
01221
01222 for (i=pos; i<j; i++) {
01223 fprintf(f,"%02x ",(unsigned char)s[i]);
01224 }
01225 if (j-pos<16)
01226 for (i=0; i<16-(j-pos); i++)
01227 fprintf(f," ");
01228
01229 for (i=pos; i<j; i++) {
01230 if (s[i]<32)
01231 fprintf(f,".");
01232 else
01233 fprintf(f,"%c",s[i]);
01234 }
01235 fprintf(f,"\n");
01236 pos+=16;
01237 }
01238 }
01239
01240
01241
01242 void GWEN_Text_DumpString2Buffer(const char *s, unsigned int l,
01243 GWEN_BUFFER *mbuf,
01244 unsigned int insert) {
01245 unsigned int i;
01246 unsigned int j;
01247 unsigned int pos;
01248 unsigned k;
01249 char numbuf[32];
01250
01251 pos=0;
01252 for (k=0; k<insert; k++)
01253 GWEN_Buffer_AppendByte(mbuf, ' ');
01254 GWEN_Buffer_AppendString(mbuf,"String size is ");
01255 snprintf(numbuf, sizeof(numbuf), "%d", l);
01256 GWEN_Buffer_AppendString(mbuf, numbuf);
01257 GWEN_Buffer_AppendByte(mbuf, '\n');
01258 while(pos<l) {
01259 for (k=0; k<insert; k++)
01260 GWEN_Buffer_AppendByte(mbuf, ' ');
01261 snprintf(numbuf, sizeof(numbuf),"%04x: ",pos);
01262 GWEN_Buffer_AppendString(mbuf, numbuf);
01263 j=pos+16;
01264 if (j>=l)
01265 j=l;
01266
01267
01268 for (i=pos; i<j; i++) {
01269 snprintf(numbuf, sizeof(numbuf),"%02x ", (unsigned char)s[i]);
01270 GWEN_Buffer_AppendString(mbuf, numbuf);
01271 }
01272 if (j-pos<16)
01273 for (i=0; i<16-(j-pos); i++)
01274 GWEN_Buffer_AppendString(mbuf, " ");
01275
01276 for (i=pos; i<j; i++) {
01277 if (s[i]<32)
01278 GWEN_Buffer_AppendByte(mbuf, '.');
01279 else
01280 GWEN_Buffer_AppendByte(mbuf, s[i]);
01281 }
01282 GWEN_Buffer_AppendByte(mbuf, '\n');
01283 pos+=16;
01284 }
01285 }
01286
01287
01288
01289
01290
01291
01292
01293 int GWEN_Text_EscapeToBuffer(const char *src, GWEN_BUFFER *buf) {
01294 while(*src) {
01295 unsigned char x;
01296
01297 x=(unsigned char)*src;
01298 if (!(
01299 (x>='A' && x<='Z') ||
01300 (x>='a' && x<='z') ||
01301 (x>='0' && x<='9'))) {
01302 unsigned char c;
01303
01304 GWEN_Buffer_AppendByte(buf, '%');
01305 c=(((unsigned char)(*src))>>4)&0xf;
01306 if (c>9)
01307 c+=7;
01308 c+='0';
01309 GWEN_Buffer_AppendByte(buf, c);
01310 c=((unsigned char)(*src))&0xf;
01311 if (c>9)
01312 c+=7;
01313 c+='0';
01314 GWEN_Buffer_AppendByte(buf, c);
01315 }
01316 else
01317 GWEN_Buffer_AppendByte(buf, *src);
01318
01319 src++;
01320 }
01321
01322 return 0;
01323 }
01324
01325
01326
01327 int GWEN_Text_UnescapeToBuffer(const char *src, GWEN_BUFFER *buf) {
01328 while(*src) {
01329 unsigned char x;
01330
01331 x=(unsigned char)*src;
01332 if (
01333 (x>='A' && x<='Z') ||
01334 (x>='a' && x<='z') ||
01335 (x>='0' && x<='9')) {
01336 GWEN_Buffer_AppendByte(buf, *src);
01337 }
01338 else {
01339 if (*src=='%') {
01340 unsigned char d1, d2;
01341 unsigned char c;
01342
01343
01344 src++;
01345 if (!(*src) || !isxdigit((int)*src)) {
01346 DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete escape sequence (no digits)");
01347 return 0;
01348 }
01349
01350 d1=(unsigned char)(toupper(*src));
01351
01352
01353 src++;
01354 if (!(*src) || !isxdigit((int)*src)) {
01355 DBG_ERROR(GWEN_LOGDOMAIN, "Incomplete escape sequence (only 1 digit)");
01356 return 0;
01357 }
01358 d2=(unsigned char)(toupper(*src));
01359
01360 d1-='0';
01361 if (d1>9)
01362 d1-=7;
01363 c=(d1<<4)&0xf0;
01364 d2-='0';
01365 if (d2>9)
01366 d2-=7;
01367 c+=(d2&0xf);
01368
01369 GWEN_Buffer_AppendByte(buf, (char)c);
01370 }
01371 else {
01372 DBG_ERROR(GWEN_LOGDOMAIN, "Found non-alphanum "
01373 "characters in escaped string (\"%s\")",
01374 src);
01375 return -1;
01376 }
01377 }
01378 src++;
01379 }
01380
01381 return 0;
01382 }
01383
01384
01385
01386 int GWEN_Text_EscapeToBufferTolerant(const char *src, GWEN_BUFFER *buf) {
01387 while(*src) {
01388 unsigned char x;
01389
01390 x=(unsigned char)*src;
01391 if (!(
01392 (x>='A' && x<='Z') ||
01393 (x>='a' && x<='z') ||
01394 (x>='0' && x<='9') ||
01395 x==' ' ||
01396 x=='.' ||
01397 x==',' ||
01398 x=='.' ||
01399 x=='_' ||
01400 x=='-' ||
01401 x=='*' ||
01402 x=='?'
01403 )) {
01404 unsigned char c;
01405
01406 GWEN_Buffer_AppendByte(buf, '%');
01407 c=(((unsigned char)(*src))>>4)&0xf;
01408 if (c>9)
01409 c+=7;
01410 c+='0';
01411 GWEN_Buffer_AppendByte(buf, c);
01412 c=((unsigned char)(*src))&0xf;
01413 if (c>9)
01414 c+=7;
01415 c+='0';
01416 GWEN_Buffer_AppendByte(buf, c);
01417 }
01418 else
01419 GWEN_Buffer_AppendByte(buf, *src);
01420
01421 src++;
01422 }
01423
01424 return 0;
01425 }
01426
01427
01428
01429 int GWEN_Text_UnescapeToBufferTolerant(const char *src, GWEN_BUFFER *buf) {
01430 while(*src) {
01431 const char *srcBak;
01432 int charHandled;
01433
01434 srcBak=src;
01435 charHandled=0;
01436 if (*src=='%') {
01437 if (strlen(src)>2) {
01438 unsigned char d1, d2;
01439 unsigned char c;
01440
01441 if (isxdigit((int)src[1]) && isxdigit((int)src[2])) {
01442
01443 src++;
01444
01445 d1=(unsigned char)(toupper(*src));
01446
01447
01448 src++;
01449 d2=(unsigned char)(toupper(*src));
01450
01451 d1-='0';
01452 if (d1>9)
01453 d1-=7;
01454 c=(d1<<4)&0xf0;
01455 d2-='0';
01456 if (d2>9)
01457 d2-=7;
01458 c+=(d2&0xf);
01459
01460 GWEN_Buffer_AppendByte(buf, (char)c);
01461 charHandled=1;
01462 }
01463 }
01464 }
01465 if (!charHandled)
01466 GWEN_Buffer_AppendByte(buf, *src);
01467 src++;
01468 }
01469
01470 return 0;
01471 }
01472
01473
01474
01475 int GWEN_Text_EscapeToBufferTolerant2(GWEN_BUFFER *src, GWEN_BUFFER *buf) {
01476 while(GWEN_Buffer_GetBytesLeft(src)) {
01477 int z;
01478 unsigned char x;
01479
01480 z=GWEN_Buffer_ReadByte(src);
01481 if (z==-1) {
01482 DBG_INFO(GWEN_LOGDOMAIN, "here");
01483 return -1;
01484 }
01485 x=(unsigned char)z;
01486 if (!(
01487 (x>='A' && x<='Z') ||
01488 (x>='a' && x<='z') ||
01489 (x>='0' && x<='9') ||
01490 x==' ' ||
01491 x=='.' ||
01492 x==',' ||
01493 x=='.' ||
01494 x=='*' ||
01495 x=='?'
01496 )) {
01497 unsigned char c;
01498
01499 GWEN_Buffer_AppendByte(buf, '%');
01500 c=(((unsigned char)x)>>4)&0xf;
01501 if (c>9)
01502 c+=7;
01503 c+='0';
01504 GWEN_Buffer_AppendByte(buf, c);
01505 c=((unsigned char)x)&0xf;
01506 if (c>9)
01507 c+=7;
01508 c+='0';
01509 GWEN_Buffer_AppendByte(buf, c);
01510 }
01511 else
01512 GWEN_Buffer_AppendByte(buf, x);
01513 }
01514
01515 return 0;
01516 }
01517
01518
01519
01520 void GWEN_Text_LogString(const char *s, unsigned int l,
01521 const char *logDomain,
01522 GWEN_LOGGER_LEVEL lv){
01523 GWEN_BUFFER *mbuf;
01524
01525 mbuf=GWEN_Buffer_new(0, ((l*16)<1024)?1024:l*16, 0, 1);
01526 GWEN_Text_DumpString2Buffer(s, l, mbuf, 0);
01527 GWEN_Logger_Log(logDomain, lv, GWEN_Buffer_GetStart(mbuf));
01528 GWEN_Buffer_free(mbuf);
01529 }
01530
01531
01532
01533 void GWEN_Text_CondenseBuffer(GWEN_BUFFER *buf){
01534 const char *p;
01535 char *dst;
01536 unsigned int size;
01537 unsigned int i;
01538 int lastWasBlank;
01539 char *lastBlankPos;
01540
01541 dst=GWEN_Buffer_GetStart(buf);
01542 p=dst;
01543 size=GWEN_Buffer_GetUsedBytes(buf);
01544 lastWasBlank=0;
01545 lastBlankPos=0;
01546
01547 for (i=0; i<size; i++) {
01548
01549 if (isspace((int)*p)) {
01550 if (!lastWasBlank) {
01551
01552 lastWasBlank=1;
01553 lastBlankPos=dst;
01554 *(dst++)=*p;
01555 }
01556 }
01557 else {
01558 lastWasBlank=0;
01559 lastBlankPos=0;
01560 *(dst++)=*p;
01561 }
01562 p++;
01563 }
01564
01565
01566 if (lastBlankPos!=0)
01567 dst=lastBlankPos;
01568
01569 size=dst-GWEN_Buffer_GetStart(buf);
01570 GWEN_Buffer_Crop(buf, 0, size);
01571 }
01572
01573
01574
01575 int GWEN_Text_DoubleToBuffer(double num, GWEN_BUFFER *buf){
01576 char numbuf[128];
01577 int rv;
01578 #ifdef HAVE_SETLOCALE
01579 const char *orig_locale = setlocale(LC_NUMERIC, NULL);
01580 char *currentLocale = strdup(orig_locale ? orig_locale : "C");
01581 setlocale(LC_NUMERIC,"C");
01582 #endif
01583
01584 rv=snprintf(numbuf, sizeof(numbuf), "%f", num);
01585
01586 #ifdef HAVE_SETLOCALE
01587 setlocale(LC_NUMERIC, currentLocale);
01588 free(currentLocale);
01589 #endif
01590
01591 if (rv<1 || rv>=sizeof(numbuf))
01592 return -1;
01593 GWEN_Buffer_AppendString(buf, numbuf);
01594 return 0;
01595 }
01596
01597
01598
01599 int GWEN_Text_StringToDouble(const char *s, double *num){
01600 int rv;
01601 #ifdef HAVE_SETLOCALE
01602 const char *orig_locale = setlocale(LC_NUMERIC, NULL);
01603 char *currentLocale = strdup(orig_locale ? orig_locale : "C");
01604 setlocale(LC_NUMERIC,"C");
01605 #endif
01606
01607 rv=sscanf(s, "%lf", num);
01608
01609 #ifdef HAVE_SETLOCALE
01610 setlocale(LC_NUMERIC, currentLocale);
01611 free(currentLocale);
01612 #endif
01613
01614 if (rv!=1)
01615 return -1;
01616 return 0;
01617 }
01618
01619
01620
01621 double GWEN_Text__CheckSimilarity(const char *s1, const char *s2, int ign){
01622 int nboth;
01623 int nmatch;
01624 double pc;
01625
01626 nboth=strlen(s1)+strlen(s2);
01627 nmatch=0;
01628 if (ign) {
01629 while(*s1 && *s2) {
01630 const char *t;
01631 int lmatch;
01632
01633
01634 t=s2;
01635 lmatch=0;
01636 while(*t) {
01637 if (toupper(*s1)==toupper(*t)) {
01638 lmatch=2;
01639 break;
01640 }
01641 if (isalnum((int)*s1) && isalnum((int)*t)) {
01642 lmatch=1;
01643 break;
01644 }
01645 t++;
01646 }
01647
01648 if (lmatch) {
01649 nmatch+=lmatch;
01650 s2=t+1;
01651 }
01652
01653 s1++;
01654 }
01655 }
01656 else {
01657 while(*s1 && *s2) {
01658 const char *t;
01659 int lmatch;
01660
01661
01662 t=s2;
01663 lmatch=0;
01664 while(*t) {
01665 if (*s1==*t) {
01666 lmatch=2;
01667 break;
01668 }
01669 if (toupper(*s1)==toupper(*t)) {
01670 lmatch=1;
01671 break;
01672 }
01673 if (isalnum((int)*s1) && isalnum((int)*t)) {
01674 lmatch=1;
01675 break;
01676 }
01677 t++;
01678 }
01679
01680 if (lmatch) {
01681 nmatch+=lmatch;
01682 s2=t+1;
01683 }
01684
01685 s1++;
01686 }
01687 }
01688
01689 pc=(nmatch*100)/nboth;
01690 return pc;
01691 }
01692
01693
01694
01695 double GWEN_Text_CheckSimilarity(const char *s1, const char *s2, int ign){
01696 double pc1, pc2;
01697
01698 pc1=GWEN_Text__CheckSimilarity(s1, s2, ign);
01699 pc2=GWEN_Text__CheckSimilarity(s2, s1, ign);
01700 if (pc2>pc1)
01701 return pc2;
01702 return pc1;
01703 }
01704
01705
01706
01707 int GWEN_Text_CountUtf8Chars(const char *s, int len) {
01708 int count;
01709 int handled;
01710
01711 if (len==0)
01712 len=strlen(s);
01713 count=0;
01714 handled=0;
01715 while(handled<len) {
01716 unsigned char c;
01717 int i;
01718
01719 c=(unsigned char)*s;
01720 if ((c & 0xfe)==0xfc)
01721 i=5;
01722 else if ((c & 0xfc)==0xf8)
01723 i=4;
01724 else if ((c & 0xf8)==0xf0)
01725 i=3;
01726 else if ((c & 0xf0)==0xe0)
01727 i=2;
01728 else if ((c & 0xe0)==0xc0)
01729 i=1;
01730 else if (c & 0x80) {
01731 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid UTF8 character at pos %d", handled);
01732 return -1;
01733 }
01734 else
01735 i=0;
01736 if (handled+i+1>len) {
01737 DBG_ERROR(GWEN_LOGDOMAIN,
01738 "Incomplete UTF8 sequence at pos %d", handled);
01739 return -1;
01740 }
01741 s++;
01742 if (i) {
01743 int j;
01744
01745 for (j=0; j<j; j++) {
01746 if ((((unsigned char)*s) & 0xc0)!=0xc0) {
01747 DBG_ERROR(GWEN_LOGDOMAIN,
01748 "Invalid UTF8 sequence at pos %d (rel %d of %d)",
01749 handled, j, i);
01750 }
01751 s++;
01752 }
01753 }
01754 handled+=i+1;
01755 count++;
01756 }
01757
01758 return count;
01759 }
01760
01761
01762
01763 int GWEN_Text_UnescapeXmlToBuffer(const char *src, GWEN_BUFFER *buf) {
01764 char *pdst;
01765 uint32_t roomLeft;
01766 uint32_t bytesAdded;
01767
01768 #define GWEN_TEXT__APPENDCHAR(chr) \
01769 if (roomLeft<2) { \
01770 if (bytesAdded) { \
01771 GWEN_Buffer_IncrementPos(buf, bytesAdded); \
01772 GWEN_Buffer_AdjustUsedBytes(buf); \
01773 } \
01774 GWEN_Buffer_AllocRoom(buf, 2); \
01775 pdst=GWEN_Buffer_GetPosPointer(buf); \
01776 roomLeft=GWEN_Buffer_GetMaxUnsegmentedWrite(buf); \
01777 bytesAdded=0; \
01778 } \
01779 *(pdst++)=(unsigned char)chr; \
01780 *pdst=0; \
01781 bytesAdded++; \
01782 roomLeft--
01783
01784 pdst=GWEN_Buffer_GetPosPointer(buf);
01785 roomLeft=GWEN_Buffer_GetMaxUnsegmentedWrite(buf);
01786 bytesAdded=0;
01787
01788 while(*src) {
01789 unsigned char x;
01790 int match;
01791
01792 match=0;
01793 x=(unsigned char)*src;
01794 if (x=='&') {
01795 if (0 && src[1]=='#') {
01796 unsigned char num=0;
01797
01798 src++;
01799 while(isdigit((int)*src)) {
01800 num*=10;
01801 num+=(*src)-'0';
01802 src++;
01803 }
01804 src++;
01805 GWEN_TEXT__APPENDCHAR(num);
01806 }
01807 else {
01808 const GWEN_TEXT_ESCAPE_ENTRY *e;
01809 e=gwen_text__xml_escape_chars;
01810 while(e->replace) {
01811 int l;
01812
01813 l=strlen(e->replace);
01814 if (strncasecmp(src, e->replace, l)==0) {
01815 GWEN_TEXT__APPENDCHAR(e->character);
01816
01817 src+=l;
01818 match=1;
01819 break;
01820 }
01821 e++;
01822 }
01823 }
01824 }
01825 if (!match) {
01826 GWEN_TEXT__APPENDCHAR(*(src++));
01827 }
01828 }
01829
01830 if (bytesAdded) {
01831 GWEN_Buffer_IncrementPos(buf, bytesAdded);
01832 GWEN_Buffer_AdjustUsedBytes(buf);
01833 }
01834
01835 return 0;
01836 #undef GWEN_TEXT__APPENDCHAR
01837 }
01838
01839
01840
01841 int GWEN_Text_EscapeXmlToBuffer(const char *src, GWEN_BUFFER *buf) {
01842 while(*src) {
01843 unsigned char x;
01844 const GWEN_TEXT_ESCAPE_ENTRY *e;
01845 int match;
01846
01847 match=0;
01848 x=(unsigned char)*src;
01849 e=gwen_text__xml_escape_chars;
01850 while(e->replace) {
01851 if (x==e->character) {
01852 GWEN_Buffer_AppendString(buf, e->replace);
01853 match=1;
01854 break;
01855 }
01856 e++;
01857 }
01858
01859 if (!match) {
01860 if (0 && x>127) {
01861 char numbuf[32];
01862
01863 snprintf(numbuf, sizeof(numbuf), "&#%d;", x);
01864 GWEN_Buffer_AppendString(buf, numbuf);
01865 }
01866 else
01867 GWEN_Buffer_AppendByte(buf, *src);
01868 }
01869 src++;
01870 }
01871
01872 return 0;
01873 }
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885