3 * kkstrtext string related and text processing routines
4 * $Id: kkstrtext.cc,v 1.45 2005/02/01 00:13:24 konst Exp $
6 * Copyright (C) 1999-2004 by Konstantin Klyagin <k@thekonst.net>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or (at
11 * your option) any later version.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
25 #include "kkstrtext.h"
29 #include <stdint.h> /* for intptr_t */
32 char *strcut(char *strin
, int frompos
, int count
) {
34 if(count
> strlen(strin
)-frompos
)
35 count
= strlen(strin
)-frompos
;
36 char *buf
= (char *) malloc(strlen(strin
) - frompos
- count
+ 1);
37 memcpy(buf
, strin
+ frompos
+ count
, strlen(strin
) - frompos
- count
);
38 memcpy(strin
+ frompos
, buf
, strlen(strin
) - frompos
- count
);
39 strin
[strlen(strin
) - count
] = 0;
45 char *strimlead(char *str
) { return trimlead(str
, " \t"); }
46 char *strimtrail(char *str
) { return trimtrail(str
, " \t"); }
47 char *strim(char *str
) { return trim(str
, " \t"); }
49 char *trimlead(char *str
, char *chr
) {
50 while(strchr(chr
, str
[0]) && strlen(str
)) strcpy(str
, str
+ 1);
54 char *trimtrail(char *str
, char *chr
) {
55 while(strlen(str
) && strchr(chr
, str
[strlen(str
)-1]))
56 str
[strlen(str
)-1] = 0;
60 char *trim(char *str
, char *chr
) {
61 return trimlead(trimtrail(str
, chr
), chr
);
64 char *time2str(const time_t *t
, char *mask
, char *sout
) {
66 char ch
, b
[10], b1
[20];
72 for(i
= 0; i
< strlen(mask
); i
++) {
75 if(strchr("DMYhms", ch
= mask
[i
])) {
77 while(mask
[++j
] == ch
) len
++;
78 sprintf(b
, "%%0%dd", len
);
82 case 'D': sprintf(b1
, b
, s
->tm_mday
); break;
83 case 'M': sprintf(b1
, b
, s
->tm_mon
+1); break;
85 j
= s
->tm_year
+ 1900;
87 if(len
<= 3) strcut(b1
, 0, 2);
89 case 'h': sprintf(b1
, b
, s
->tm_hour
); break;
90 case 'm': sprintf(b1
, b
, s
->tm_min
); break;
91 case 's': sprintf(b1
, b
, s
->tm_sec
); break;
103 time_t str2time(char *sdate
, char *mask
, time_t *t
) {
108 s
= (struct tm
*) malloc(sizeof(struct tm
));
110 for(i
= 0; i
< strlen(mask
); i
++) {
113 if(strchr("DMYhms", ch
= mask
[i
])) {
115 while(mask
[++j
] == ch
) len
++;
119 for(j
= i
-len
+1; j
< i
+1; j
++) {
126 case 'D': s
->tm_mday
=atoi(b
); break;
127 case 'M': s
->tm_mon
=atoi(b
); s
->tm_mon
--; break;
128 case 'Y': s
->tm_year
=atoi(b
); s
->tm_year
-=1900; break;
129 case 'h': s
->tm_hour
=atoi(b
); s
->tm_hour
--; break;
130 case 'm': s
->tm_min
=atoi(b
); break;
131 case 's': s
->tm_sec
=atoi(b
); break;
142 string
unmime(const string
&text
) {
144 char *buf
= new char[text
.size()+1];
145 strcpy(buf
, text
.c_str());
151 string
mime(const string
&text
) {
153 char *buf
= new char[text
.size()*3+1];
154 r
= mime(buf
, text
.c_str());
159 string
fromutf8(const string
&text
) {
161 char *buf
= (char *) utf8_to_str(text
.c_str());
167 string
toutf8(const string
&text
) {
169 char *buf
= str_to_utf8(text
.c_str());
175 char *unmime(char *text
) {
179 for(s
= 0, d
= 0; text
[s
] != 0; s
++) {
180 if(text
[s
] == '+') text
[d
++] = ' '; else
182 sscanf(text
+ s
+ 1, "%2x", &htm
);
193 char *mime(char *dst
, const char *src
) {
197 for(s
= 0, d
= 0; src
[s
]; s
++) {
198 if((src
[s
] >= 'a' && src
[s
] <= 'z') ||
199 (src
[s
] >= 'A' && src
[s
] <= 'Z') ||
200 (src
[s
] >= '0' && src
[s
] <= '9')) dst
[d
++] = src
[s
]; else {
203 c
= (src
[s
] >> 4 & 0x0F);
204 dst
[d
++] = (c
> 9) ? 'A'+c
-10 : '0'+c
;
206 dst
[d
++] = (c
> 9) ? 'A'+c
-10 : '0'+c
;
216 char *strccat(char *dest
, char c
) {
217 int k
= strlen(dest
);
223 vector
<int> getquotelayout(const string
&haystack
, const string
&qs
, const string
&aescs
) {
226 int pos
, prevpos
, curpos
;
227 char cchar
, qchar
, prevchar
;
230 curpos
= prevpos
= 0;
231 escs
= (qs
== aescs
) ? "" : aescs
;
234 while((pos
= haystack
.substr(curpos
).find_first_of(needle
)) != -1) {
236 cchar
= *(haystack
.begin()+curpos
);
238 if(escs
.find(cchar
) != -1) {
240 if(prevpos
== curpos
-1)
241 if(escs
.find(prevchar
) != -1) {
242 /* Neutralize previous esc char */
245 } else if(qs
.find(cchar
) != -1) {
246 if(!((escs
.find(prevchar
) != -1) && (prevpos
== curpos
-1))) {
247 /* Wasn't an escape (right before this quote char) */
249 if(!qchar
|| (qchar
== cchar
)) {
250 qchar
= qchar
? 0 : cchar
;
263 vector
<int> getsymbolpositions(const string
&haystack
, const string
&needles
, const string
&qoutes
, const string
&esc
) {
264 vector
<int> r
, qp
, nr
;
265 vector
<int>::iterator iq
, ir
;
266 int pos
, st
, ed
, cpos
;
268 for(cpos
= 0; (pos
= haystack
.substr(cpos
).find_first_of(needles
)) != -1; ) {
269 r
.push_back(cpos
+pos
);
273 qp
= getquotelayout(haystack
, qoutes
, esc
);
274 for(iq
= qp
.begin(); iq
!= qp
.end(); iq
++) {
275 if(!((iq
-qp
.begin()) % 2)) {
277 ed
= iq
+1 != qp
.end() ? *(iq
+1) : haystack
.size();
280 for(ir
= r
.begin(); ir
!= r
.end(); ir
++) {
281 if(!(*ir
> st
&& *ir
< ed
)) {
293 #define CHECKESC(curpos, startpos, esc) \
294 if(curpos > startpos+1) \
295 if(strchr(esc, *(curpos-1))) \
296 if(!strchr(esc, *(curpos-2))) { \
301 const char *strqpbrk(const char *s
, int offset
, const char *accept
, const char *q
, const char *esc
) {
306 const char *ret
= 0, *p
= s
;
307 char *cset
= (char *) malloc(strlen(accept
)+strlen(q
)+1);
309 strcpy(cset
, accept
);
312 while(p
= strpbrk(p
, cset
)) {
320 if(*p
== qchar
) qchar
= 0;
322 } else if((p
-s
>= offset
) && !qchar
) {
333 const char *strqcasestr(const char *s
, const char *str
, const char *q
, const char *esc
) {
337 for(i
= 0; i
< strlen(s
); i
++) {
338 if(strchr(q
, s
[i
])) {
340 CHECKESC(s
+i
, s
, esc
);
345 if(!strncasecmp(s
+ i
, str
, strlen(str
))) return s
+ i
;
351 const char *strqstr(const char *s
, const char *str
, const char *q
, const char *esc
) {
353 const char *ret
= 0, *p
, *ss
, *r
;
356 while(p
= strstr(ss
, str
)) {
360 while(r
= strpbrk(r
, q
)) {
379 char *strinsert(char *buf
, int pos
, char *ins
) {
380 char *p
= strdup(buf
+pos
);
381 memcpy(buf
+pos
+strlen(ins
), p
, strlen(p
)+1);
382 memcpy(buf
+pos
, ins
, strlen(ins
));
387 char *strcinsert(char *buf
, int pos
, char ins
) {
388 char *p
= strdup(buf
+pos
);
389 memcpy(buf
+pos
+1, p
, strlen(p
)+1);
395 int strchcount(char *s
, char *accept
) {
398 while(p
= strpbrk(p
+1, accept
)) ret
++;
402 int stralone(char *buf
, char *startword
, int wordlen
, char *delim
) {
403 int leftdelim
= 0, rightdelim
= 0;
404 leftdelim
= (buf
!= startword
&& strchr(delim
, *(startword
-1))) || buf
== startword
;
405 rightdelim
= !*(startword
+wordlen
) || strchr(delim
, *(startword
+wordlen
));
406 return leftdelim
&& rightdelim
;
409 string
justfname(const string
&fname
) {
410 return fname
.substr(fname
.rfind("/")+1);
413 string
justpathname(const string
&fname
) {
416 if((pos
= fname
.rfind("/")) != -1) {
417 return fname
.substr(0, pos
);
423 void charpointerfree(void *p
) {
424 char *cp
= (char *) p
;
429 void nothingfree(void *p
) {
432 int stringcompare(void *s1
, void *s2
) {
436 return strcmp((char *) s1
, (char *) s2
);
440 int intcompare(void *s1
, void *s2
) {
441 return (intptr_t) s1
!= (intptr_t) s2
;
444 string
i2str(int i
) {
446 sprintf(buf
, "%d", i
);
450 string
ui2str(int i
) {
452 sprintf(buf
, "%du", i
);
456 string
textscreen(const string
&text
) {
459 for(int i
= 0; i
< r
.size(); i
++) {
460 if(!isalnum(r
[i
])) r
.insert(i
++, "\\");
466 string
leadcut(const string
&base
, const string
&delim
) {
467 int pos
= base
.find_first_not_of(delim
);
468 return (pos
!= -1) ? base
.substr(pos
) : "";
471 string
trailcut(const string
&base
, const string
&delim
) {
472 int pos
= base
.find_last_not_of(delim
);
473 return (pos
!= -1) ? base
.substr(0, pos
+1) : "";
476 string
getword(string
&base
, const string
&delim
) {
481 base
= leadcut(base
, delim
);
483 for(i
= 0, sub
= base
; i
< sub
.size(); i
++)
484 if(strchr(delim
.c_str(), sub
[i
])) {
486 base
.replace(0, i
, "");
487 base
= leadcut(base
, delim
);
492 if(!found
) base
= "";
496 const string
getwordquote(string
&base
, string quote
, string delim
) {
498 bool inquote
= false;
501 base
= leadcut(base
, delim
);
503 for(i
= 0, sub
= base
; i
< sub
.size(); i
++) {
504 if(strchr(quote
.c_str(), sub
[i
])) {
506 } else if(!inquote
&& strchr(delim
.c_str(), sub
[i
])) {
508 base
.replace(0, i
, "");
509 base
= leadcut(base
, delim
);
514 if(sub
== base
) base
= "";
518 string
getrword(string
&base
, const string
&delim
) {
522 base
= trailcut(base
, delim
);
524 for(i
= base
.size()-1, sub
= base
; i
>= 0; i
--)
525 if(strchr(delim
.c_str(), base
[i
])) {
526 sub
= base
.substr(i
+1);
528 base
= trailcut(base
, delim
);
532 if(sub
== base
) base
= "";
536 string
getrwordquote(string
&base
, const string
"e
, const string
&delim
) {
538 bool inquote
= false;
541 base
= trailcut(base
, delim
);
543 for(i
= base
.size()-1, sub
= base
; i
>= 0; i
--)
544 if(strchr(quote
.c_str(), base
[i
])) {
546 } else if(!inquote
&& strchr(delim
.c_str(), base
[i
])) {
547 sub
= base
.substr(i
+1);
549 base
= trailcut(base
, delim
);
553 if(sub
== base
) base
= "";
557 int rtabmargin(bool fake
, int curpos
, const char *p
) {
558 int ret
= -1, n
, near
;
560 if(p
&& (curpos
!= strlen(p
))) {
561 n
= strspn(p
+curpos
, " ");
564 near
= ((curpos
/(TAB_SIZE
/2))+1)*(TAB_SIZE
/2);
565 if(n
>= near
-curpos
) ret
= near
;
568 near
= ((curpos
/TAB_SIZE
)+1)*TAB_SIZE
;
569 if(n
>= near
-curpos
) ret
= near
;
571 if(p
&& fake
) fake
= (strspn(p
, " ") == strlen(p
));
572 if(fake
) ret
= ((curpos
/(TAB_SIZE
/2))+1)*(TAB_SIZE
/2);
573 else ret
= ((curpos
/TAB_SIZE
)+1)*TAB_SIZE
;
579 int ltabmargin(bool fake
, int curpos
, const char *p
) {
580 int ret
= -1, near
, n
= 0;
587 if(*(--cp
) == ' ') n
++;
588 for(; (*cp
== ' ') && (cp
!= p
); cp
--) n
++;
592 near
= (curpos
/(TAB_SIZE
/2))*(TAB_SIZE
/2);
594 if((ret
= curpos
-n
) != 0) ret
++;
597 near
= (curpos
/TAB_SIZE
)*TAB_SIZE
;
598 if(near
<= curpos
-n
) {
599 if((ret
= curpos
-n
) != 0) ret
++;
603 if(fake
) ret
= (curpos
/(TAB_SIZE
/2))*(TAB_SIZE
/2);
604 else ret
= (curpos
/TAB_SIZE
)*TAB_SIZE
;
610 void breakintolines(string text
, vector
<string
> &lst
, int linelen
) {
613 vector
<string
>::iterator i
;
615 breakintolines(text
, lst
);
618 for(i
= lst
.begin(); i
!= lst
.end(); i
++) {
619 if(i
->size() > linelen
) {
620 sub
= i
->substr(0, nlen
= linelen
);
622 if((dpos
= sub
.rfind(" ")) != -1) {
623 if(dpos
) nlen
= dpos
; else nlen
= 1;
629 sub
= i
->substr(nlen
);
631 lst
.insert(i
+1, sub
);
638 void breakintolines(const string
&text
, vector
<string
> &lst
) {
639 int npos
, dpos
, tpos
;
645 while(tpos
< text
.size()) {
646 if((npos
= text
.find("\n", tpos
)) != -1) {
647 sub
= text
.substr(tpos
, npos
-tpos
);
649 sub
= text
.substr(tpos
);
655 for(dpos
= 0; (dpos
= sub
.find("\r", dpos
)) != -1; ) {
659 for(dpos
= 0; (dpos
= sub
.find("\t", dpos
)) != -1; ) {
661 sub
.insert(dpos
, string(rtabmargin(false, dpos
)-dpos
, ' '));
668 void find_gather_quoted(vector
<quotedblock
> &lst
, const string
&str
,
669 const string
"e
, const string
&escape
) {
670 bool inquote
= false;
674 while((npos
= str
.find_first_of(quote
, npos
)) != -1) {
676 if(escape
.find(str
[npos
-1]) == -1) {
683 if(str
[npos
] == qch
) {
695 int find_quoted(const string
&str
, const string
&needle
, int offs
,
696 const string
"e
, const string
&escape
) {
697 vector
<quotedblock
> positions
;
698 vector
<quotedblock
>::iterator qi
;
702 find_gather_quoted(positions
, str
, quote
, escape
);
704 while((npos
= str
.find(needle
, npos
)) != -1) {
705 for(found
= false, qi
= positions
.begin(); qi
!= positions
.end() && !found
; qi
++)
706 if((npos
> qi
->begin
) && (npos
< qi
->end
)) found
= true;
712 return !found
? npos
: -1;
715 int find_quoted_first_of(const string
&str
, const string
&needle
, int offs
,
716 const string
"e
, const string
&escape
) {
717 vector
<quotedblock
> positions
;
718 vector
<quotedblock
>::iterator qi
;
722 find_gather_quoted(positions
, str
, quote
, escape
);
724 while((npos
= str
.find_first_of(needle
, npos
)) != -1) {
725 for(found
= false, qi
= positions
.begin(); qi
!= positions
.end() && !found
; qi
++)
726 if((npos
> qi
->begin
) && (npos
< qi
->end
)) found
= true;
732 return !found
? npos
: -1;
735 void splitlongtext(string text
, vector
<string
> &lst
, int size
, const string cont
) {
741 while(!text
.empty()) {
742 if(text
.size() <= size
-cont
.size()) {
744 } else if((npos
= text
.substr(0, size
-cont
.size()).find_last_of(" \t")) == -1) {
745 npos
= size
-cont
.size();
748 sub
= text
.substr(0, npos
);
751 if(text
.size() > cont
.size()) sub
+= cont
; else {
756 if((npos
= text
.find_first_not_of(" \t")) != -1)
763 string
strdateandtime(time_t stamp
, const string
&fmt
) {
764 return strdateandtime(localtime(&stamp
), fmt
);
767 string
strdateandtime(struct tm
*tms
, const string
&fmt
) {
769 /*time_t current_time = time(0);*/
770 /*time_t when = mktime(tms);*/
774 afmt
= "%b %e %Y %H:%M";
776 if(current_time > when + 6L * 30L * 24L * 60L * 60L // Old.
777 || current_time < when - 60L * 60L) { // Future.
780 afmt = "%b %e %H:%M";
785 strftime(buf
, 512, afmt
.c_str(), tms
);
789 bool iswholeword(const string
&s
, int so
, int eo
) {
791 const string wdelims
= "[](),.; <>-+{}=|&%~*/:?@";
793 lm
= !so
|| (wdelims
.find(s
.substr(so
-1, 1)) != -1);
794 rm
= (eo
== s
.size()-1) || (wdelims
.find(s
.substr(eo
, 1)) != -1);
799 int hex2int(const string
&ahex
) {
804 if(ahex
.size() <= 2) {
805 for(i
= 0; i
< ahex
.size(); i
++) {
806 r
+= isdigit(ahex
[i
]) ? ahex
[i
]-48 : toupper(ahex
[i
])-55;
814 bool getconf(string
&st
, string
&buf
, ifstream
&f
, bool passemptylines
) {
818 while(!f
.eof() && !ret
) {
824 sect
= buf
.substr(1);
827 if(buf
[1] != '!') break;
832 } else if(passemptylines
) {
841 bool getstring(istream
&f
, string
&sbuf
) {
842 static char buf
[2048];
850 f
.getline(buf
, 2048);
852 } while(!f
.good() && !f
.eof());
858 string
ruscase(const string
&s
, const string
&mode
) {
859 static const string lower
= "ÁÂ×ÇÄÅÖÚÉÊËÌÍÎÏÐÒÓÔÕÆÈÃÞÛÝØßÙÜÀÑ";
860 static const string upper
= "áâ÷çäåöúéêëìíîïðòóôõæèãþûýøÿùüàñ";
861 string r
, tfrom
, tto
;
864 if(mode
== "tolower") {
867 } else if(mode
== "toupper") {
876 for(r
= s
; (pos
= r
.find_first_of(tfrom
, pos
)) != -1; ) {
878 tpos
= tfrom
.find(c
);
885 while((pos
= r
.find_first_not_of(tfrom
, pos
)) != -1) {
886 if(mode
== "tolower") r
[pos
] = tolower(r
[pos
]); else
887 if(mode
== "toupper") r
[pos
] = toupper(r
[pos
]);
894 string
siconv(const string
&atext
, const string
&fromcs
, const string
&tocs
) {
896 iconv_t cd
= iconv_open(tocs
.c_str(), fromcs
.c_str());
898 if(cd
!= ((iconv_t
) -1)) {
899 string r
, text(atext
);
900 size_t inleft
, outleft
, soutleft
;
901 char *inbuf
, *outbuf
, *sinbuf
, *soutbuf
;
903 //from iconv.c (libiconv)
904 iconv(cd
,NULL
,NULL
,NULL
,NULL
);
906 size_t len
= text
.size();
907 sinbuf
= inbuf
= (char *)malloc(len
+1);
908 memcpy(sinbuf
, text
.c_str(), len
+1);
912 soutleft
= outleft
= inleft
*4;
913 soutbuf
= outbuf
= new char[outleft
];
915 size_t res
= iconv(cd
, (ICONV_CONST
char **) &inbuf
, &inleft
,
918 soutbuf
[soutleft
-outleft
] = 0;
923 if ((res
== (size_t)(-1)) && (errno
!= EILSEQ
)) {
943 string
cuthtml(const string
&html
, int flags
) {
944 string r
, tag
, buf
, token
;
947 for(pos
= 0; (npos
= html
.find("<", pos
)) != -1; pos
= npos
) {
949 r
+= html
.substr(pos
, npos
-pos
);
951 if((npos
= html
.find(">", ++npos
)) != -1) {
954 tag
= html
.substr(tpos
+1, npos
-tpos
-2);
955 if(tag
.substr(0, 1) == "/") tag
.erase(0, 1);
956 tag
= leadcut(trailcut(tag
, "/ \n\r"), "/ \n\r");
958 buf
= ruscase(tag
, "toupper");
959 token
= getword(buf
);
961 if(token
== "BR") r
+= (flags
& chCutBR
) ? "\n" : "<br>";
962 else if((flags
& chCutBR
) && token
== "P") r
+= "\n\n";
964 if(flags
& chLeaveLinks
) {
968 if((tpos
= buf
.find("HREF")) != -1)
969 if((tpos
= buf
.substr(tpos
).find("\"")) != -1) {
970 tag
.erase(0, tpos
+1);
971 r
+= "[ href: " + getword(tag
, "\"") + " ] ";
974 } else if(token
== "IMG") {
975 if((tpos
= buf
.find("SRC")) != -1)
976 if((tpos
= buf
.substr(tpos
).find("\"")) != -1) {
977 tag
.erase(0, tpos
+1);
978 r
+= " [ img: " + getword(tag
, "\"") + " ]";
985 r
+= html
.substr(tpos
);
990 if(pos
< html
.size())
991 r
+= html
.substr(pos
);
996 char *utf8_to_str(const char *pin
) {
997 int n
= 0, i
= 0, inlen
;
998 unsigned char *result
;
999 const unsigned char *in
= (unsigned char *) pin
;
1001 if(!in
) return NULL
;
1003 inlen
= strlen(pin
);
1004 result
= new unsigned char[inlen
+ 1];
1006 while (n
<= inlen
- 1) {
1007 long c
= (long)in
[n
];
1008 if(c
< 0x80) result
[i
++] = (char)c
; else {
1009 if((c
& 0xC0) == 0xC0) result
[i
++] = (char)(((c
& 0x03) << 6) | (((unsigned char)in
[++n
]) & 0x3F));
1010 else if ((c
& 0xE0) == 0xE0) {
1011 if (n
+ 2 <= inlen
) {
1012 result
[i
] = (char)(((c
& 0xF) << 4) | (((unsigned char)in
[++n
]) & 0x3F));
1013 result
[i
] = (char)(((unsigned char)result
[i
]) | (((unsigned char)in
[++n
]) & 0x3F));
1016 } else if ((c
& 0xF0) == 0xF0) n
+= 3;
1017 else if ((c
& 0xF8) == 0xF8)
1019 else if ((c
& 0xFC) == 0xFC)
1026 return (char *) result
;
1029 char *str_to_utf8(const char *pin
) {
1032 char *result
= NULL
;
1033 const unsigned char *in
= (unsigned char *) pin
;
1038 inlen
= strlen(pin
);
1039 result
= new char[inlen
* 2 + 1];
1042 long c
= (long)in
[n
];
1054 result
[i
++] = (char)c
;
1056 result
[i
++] = (char)((c
>> 6) | 192);
1057 result
[i
++] = (char)((c
& 63) | 128);
1066 string
striprtf(const string
&s
, const string
&charset
) {
1067 string r
, spec
, unichar
, tmp
;
1069 bool bprint
, bspec
, bunicode
;
1073 bspec
= bunicode
= false;
1075 for(string::const_iterator i
= s
.begin(); i
!= s
.end(); ++i
) {
1076 if(!isalpha(*i
) && !isdigit(*i
)) bprint
= true;
1081 if(spec
.size() == 2) {
1082 r
+= (char) hex2int(spec
);
1121 if(!bparen
&& bprint
&& pre
== '\\') {
1131 if(pre
== '\\' && isdigit(*(i
+1))) {
1144 if(unichar
.size() == 5) {
1146 if(unichar
.substr(0, 4).find_first_not_of("0123456789") == -1) {
1147 long l
= strtol(unichar
.substr(0, 4).c_str(), 0, 0);
1148 char ubuf
[sizeof(long)+4];
1150 memcpy(ubuf
, "\xff\xfe", 2);
1151 memcpy(ubuf
+2, &l
, sizeof(long));
1152 memcpy(ubuf
+sizeof(long)+2, "\x0a\x00", 2);
1154 strcpy(ubuf
, unichar
.substr(4).c_str());
1156 r
+= siconv(ubuf
, "utf-16", charset
);
1169 return leadcut(trailcut(r
));