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"
27 #include <stdint.h> /* for intptr_t */
29 char *strcut(char *strin
, int frompos
, int count
) {
31 if(count
> strlen(strin
)-frompos
)
32 count
= strlen(strin
)-frompos
;
33 char *buf
= (char *) malloc(strlen(strin
) - frompos
- count
+ 1);
34 memcpy(buf
, strin
+ frompos
+ count
, strlen(strin
) - frompos
- count
);
35 memcpy(strin
+ frompos
, buf
, strlen(strin
) - frompos
- count
);
36 strin
[strlen(strin
) - count
] = 0;
42 char *strimlead(char *str
) { return trimlead(str
, " \t"); }
43 char *strimtrail(char *str
) { return trimtrail(str
, " \t"); }
44 char *strim(char *str
) { return trim(str
, " \t"); }
46 char *trimlead(char *str
, char *chr
) {
47 while(strchr(chr
, str
[0]) && strlen(str
)) strcpy(str
, str
+ 1);
51 char *trimtrail(char *str
, char *chr
) {
52 while(strlen(str
) && strchr(chr
, str
[strlen(str
)-1]))
53 str
[strlen(str
)-1] = 0;
57 char *trim(char *str
, char *chr
) {
58 return trimlead(trimtrail(str
, chr
), chr
);
61 char *time2str(const time_t *t
, char *mask
, char *sout
) {
63 char ch
, b
[10], b1
[20];
69 for(i
= 0; i
< strlen(mask
); i
++) {
72 if(strchr("DMYhms", ch
= mask
[i
])) {
74 while(mask
[++j
] == ch
) len
++;
75 sprintf(b
, "%%0%dd", len
);
79 case 'D': sprintf(b1
, b
, s
->tm_mday
); break;
80 case 'M': sprintf(b1
, b
, s
->tm_mon
+1); break;
82 j
= s
->tm_year
+ 1900;
84 if(len
<= 3) strcut(b1
, 0, 2);
86 case 'h': sprintf(b1
, b
, s
->tm_hour
); break;
87 case 'm': sprintf(b1
, b
, s
->tm_min
); break;
88 case 's': sprintf(b1
, b
, s
->tm_sec
); break;
100 time_t str2time(char *sdate
, char *mask
, time_t *t
) {
105 s
= (struct tm
*) malloc(sizeof(struct tm
));
107 for(i
= 0; i
< strlen(mask
); i
++) {
110 if(strchr("DMYhms", ch
= mask
[i
])) {
112 while(mask
[++j
] == ch
) len
++;
116 for(j
= i
-len
+1; j
< i
+1; j
++) {
123 case 'D': s
->tm_mday
=atoi(b
); break;
124 case 'M': s
->tm_mon
=atoi(b
); s
->tm_mon
--; break;
125 case 'Y': s
->tm_year
=atoi(b
); s
->tm_year
-=1900; break;
126 case 'h': s
->tm_hour
=atoi(b
); s
->tm_hour
--; break;
127 case 'm': s
->tm_min
=atoi(b
); break;
128 case 's': s
->tm_sec
=atoi(b
); break;
139 string
unmime(const string
&text
) {
141 char *buf
= new char[text
.size()+1];
142 strcpy(buf
, text
.c_str());
148 string
mime(const string
&text
) {
150 char *buf
= new char[text
.size()*3+1];
151 r
= mime(buf
, text
.c_str());
156 string
fromutf8(const string
&text
) {
158 char *buf
= (char *) utf8_to_str(text
.c_str());
164 string
toutf8(const string
&text
) {
166 char *buf
= str_to_utf8(text
.c_str());
172 char *unmime(char *text
) {
176 for(s
= 0, d
= 0; text
[s
] != 0; s
++) {
177 if(text
[s
] == '+') text
[d
++] = ' '; else
179 sscanf(text
+ s
+ 1, "%2x", &htm
);
190 char *mime(char *dst
, const char *src
) {
194 for(s
= 0, d
= 0; src
[s
]; s
++) {
195 if((src
[s
] >= 'a' && src
[s
] <= 'z') ||
196 (src
[s
] >= 'A' && src
[s
] <= 'Z') ||
197 (src
[s
] >= '0' && src
[s
] <= '9')) dst
[d
++] = src
[s
]; else {
200 c
= (src
[s
] >> 4 & 0x0F);
201 dst
[d
++] = (c
> 9) ? 'A'+c
-10 : '0'+c
;
203 dst
[d
++] = (c
> 9) ? 'A'+c
-10 : '0'+c
;
213 char *strccat(char *dest
, char c
) {
214 int k
= strlen(dest
);
220 vector
<int> getquotelayout(const string
&haystack
, const string
&qs
, const string
&aescs
) {
223 int pos
, prevpos
, curpos
;
224 char cchar
, qchar
, prevchar
;
227 curpos
= prevpos
= 0;
228 escs
= (qs
== aescs
) ? "" : aescs
;
231 while((pos
= haystack
.substr(curpos
).find_first_of(needle
)) != -1) {
233 cchar
= *(haystack
.begin()+curpos
);
235 if(escs
.find(cchar
) != -1) {
237 if(prevpos
== curpos
-1)
238 if(escs
.find(prevchar
) != -1) {
239 /* Neutralize previous esc char */
242 } else if(qs
.find(cchar
) != -1) {
243 if(!((escs
.find(prevchar
) != -1) && (prevpos
== curpos
-1))) {
244 /* Wasn't an escape (right before this quote char) */
246 if(!qchar
|| (qchar
== cchar
)) {
247 qchar
= qchar
? 0 : cchar
;
260 vector
<int> getsymbolpositions(const string
&haystack
, const string
&needles
, const string
&qoutes
, const string
&esc
) {
261 vector
<int> r
, qp
, nr
;
262 vector
<int>::iterator iq
, ir
;
263 int pos
, st
, ed
, cpos
;
265 for(cpos
= 0; (pos
= haystack
.substr(cpos
).find_first_of(needles
)) != -1; ) {
266 r
.push_back(cpos
+pos
);
270 qp
= getquotelayout(haystack
, qoutes
, esc
);
271 for(iq
= qp
.begin(); iq
!= qp
.end(); iq
++) {
272 if(!((iq
-qp
.begin()) % 2)) {
274 ed
= iq
+1 != qp
.end() ? *(iq
+1) : haystack
.size();
277 for(ir
= r
.begin(); ir
!= r
.end(); ir
++) {
278 if(!(*ir
> st
&& *ir
< ed
)) {
290 #define CHECKESC(curpos, startpos, esc) \
291 if(curpos > startpos+1) \
292 if(strchr(esc, *(curpos-1))) \
293 if(!strchr(esc, *(curpos-2))) { \
298 const char *strqpbrk(const char *s
, int offset
, const char *accept
, const char *q
, const char *esc
) {
303 const char *ret
= 0, *p
= s
;
304 char *cset
= (char *) malloc(strlen(accept
)+strlen(q
)+1);
306 strcpy(cset
, accept
);
309 while(p
= strpbrk(p
, cset
)) {
317 if(*p
== qchar
) qchar
= 0;
319 } else if((p
-s
>= offset
) && !qchar
) {
330 const char *strqcasestr(const char *s
, const char *str
, const char *q
, const char *esc
) {
334 for(i
= 0; i
< strlen(s
); i
++) {
335 if(strchr(q
, s
[i
])) {
337 CHECKESC(s
+i
, s
, esc
);
342 if(!strncasecmp(s
+ i
, str
, strlen(str
))) return s
+ i
;
348 const char *strqstr(const char *s
, const char *str
, const char *q
, const char *esc
) {
350 const char *ret
= 0, *p
, *ss
, *r
;
353 while(p
= strstr(ss
, str
)) {
357 while(r
= strpbrk(r
, q
)) {
376 char *strinsert(char *buf
, int pos
, char *ins
) {
377 char *p
= strdup(buf
+pos
);
378 memcpy(buf
+pos
+strlen(ins
), p
, strlen(p
)+1);
379 memcpy(buf
+pos
, ins
, strlen(ins
));
384 char *strcinsert(char *buf
, int pos
, char ins
) {
385 char *p
= strdup(buf
+pos
);
386 memcpy(buf
+pos
+1, p
, strlen(p
)+1);
392 int strchcount(char *s
, char *accept
) {
395 while(p
= strpbrk(p
+1, accept
)) ret
++;
399 int stralone(char *buf
, char *startword
, int wordlen
, char *delim
) {
400 int leftdelim
= 0, rightdelim
= 0;
401 leftdelim
= (buf
!= startword
&& strchr(delim
, *(startword
-1))) || buf
== startword
;
402 rightdelim
= !*(startword
+wordlen
) || strchr(delim
, *(startword
+wordlen
));
403 return leftdelim
&& rightdelim
;
406 string
justfname(const string
&fname
) {
407 return fname
.substr(fname
.rfind("/")+1);
410 string
justpathname(const string
&fname
) {
413 if((pos
= fname
.rfind("/")) != -1) {
414 return fname
.substr(0, pos
);
420 void charpointerfree(void *p
) {
421 char *cp
= (char *) p
;
426 void nothingfree(void *p
) {
429 int stringcompare(void *s1
, void *s2
) {
433 return strcmp((char *) s1
, (char *) s2
);
437 int intcompare(void *s1
, void *s2
) {
438 return (intptr_t) s1
!= (intptr_t) s2
;
441 string
i2str(int i
) {
443 sprintf(buf
, "%d", i
);
447 string
ui2str(int i
) {
449 sprintf(buf
, "%du", i
);
453 string
textscreen(const string
&text
) {
456 for(int i
= 0; i
< r
.size(); i
++) {
457 if(!isalnum(r
[i
])) r
.insert(i
++, "\\");
463 string
leadcut(const string
&base
, const string
&delim
) {
464 int pos
= base
.find_first_not_of(delim
);
465 return (pos
!= -1) ? base
.substr(pos
) : "";
468 string
trailcut(const string
&base
, const string
&delim
) {
469 int pos
= base
.find_last_not_of(delim
);
470 return (pos
!= -1) ? base
.substr(0, pos
+1) : "";
473 string
getword(string
&base
, const string
&delim
) {
478 base
= leadcut(base
, delim
);
480 for(i
= 0, sub
= base
; i
< sub
.size(); i
++)
481 if(strchr(delim
.c_str(), sub
[i
])) {
483 base
.replace(0, i
, "");
484 base
= leadcut(base
, delim
);
489 if(!found
) base
= "";
493 const string
getwordquote(string
&base
, string quote
, string delim
) {
495 bool inquote
= false;
498 base
= leadcut(base
, delim
);
500 for(i
= 0, sub
= base
; i
< sub
.size(); i
++) {
501 if(strchr(quote
.c_str(), sub
[i
])) {
503 } else if(!inquote
&& strchr(delim
.c_str(), sub
[i
])) {
505 base
.replace(0, i
, "");
506 base
= leadcut(base
, delim
);
511 if(sub
== base
) base
= "";
515 string
getrword(string
&base
, const string
&delim
) {
519 base
= trailcut(base
, delim
);
521 for(i
= base
.size()-1, sub
= base
; i
>= 0; i
--)
522 if(strchr(delim
.c_str(), base
[i
])) {
523 sub
= base
.substr(i
+1);
525 base
= trailcut(base
, delim
);
529 if(sub
== base
) base
= "";
533 string
getrwordquote(string
&base
, const string
"e
, const string
&delim
) {
535 bool inquote
= false;
538 base
= trailcut(base
, delim
);
540 for(i
= base
.size()-1, sub
= base
; i
>= 0; i
--)
541 if(strchr(quote
.c_str(), base
[i
])) {
543 } else if(!inquote
&& strchr(delim
.c_str(), base
[i
])) {
544 sub
= base
.substr(i
+1);
546 base
= trailcut(base
, delim
);
550 if(sub
== base
) base
= "";
554 int rtabmargin(bool fake
, int curpos
, const char *p
) {
555 int ret
= -1, n
, near
;
557 if(p
&& (curpos
!= strlen(p
))) {
558 n
= strspn(p
+curpos
, " ");
561 near
= ((curpos
/(TAB_SIZE
/2))+1)*(TAB_SIZE
/2);
562 if(n
>= near
-curpos
) ret
= near
;
565 near
= ((curpos
/TAB_SIZE
)+1)*TAB_SIZE
;
566 if(n
>= near
-curpos
) ret
= near
;
568 if(p
&& fake
) fake
= (strspn(p
, " ") == strlen(p
));
569 if(fake
) ret
= ((curpos
/(TAB_SIZE
/2))+1)*(TAB_SIZE
/2);
570 else ret
= ((curpos
/TAB_SIZE
)+1)*TAB_SIZE
;
576 int ltabmargin(bool fake
, int curpos
, const char *p
) {
577 int ret
= -1, near
, n
= 0;
584 if(*(--cp
) == ' ') n
++;
585 for(; (*cp
== ' ') && (cp
!= p
); cp
--) n
++;
589 near
= (curpos
/(TAB_SIZE
/2))*(TAB_SIZE
/2);
591 if((ret
= curpos
-n
) != 0) ret
++;
594 near
= (curpos
/TAB_SIZE
)*TAB_SIZE
;
595 if(near
<= curpos
-n
) {
596 if((ret
= curpos
-n
) != 0) ret
++;
600 if(fake
) ret
= (curpos
/(TAB_SIZE
/2))*(TAB_SIZE
/2);
601 else ret
= (curpos
/TAB_SIZE
)*TAB_SIZE
;
607 void breakintolines(string text
, vector
<string
> &lst
, int linelen
) {
610 vector
<string
>::iterator i
;
612 breakintolines(text
, lst
);
615 for(i
= lst
.begin(); i
!= lst
.end(); i
++) {
616 if(i
->size() > linelen
) {
617 sub
= i
->substr(0, nlen
= linelen
);
619 if((dpos
= sub
.rfind(" ")) != -1) {
620 if(dpos
) nlen
= dpos
; else nlen
= 1;
626 sub
= i
->substr(nlen
);
628 lst
.insert(i
+1, sub
);
635 void breakintolines(const string
&text
, vector
<string
> &lst
) {
636 int npos
, dpos
, tpos
;
642 while(tpos
< text
.size()) {
643 if((npos
= text
.find("\n", tpos
)) != -1) {
644 sub
= text
.substr(tpos
, npos
-tpos
);
646 sub
= text
.substr(tpos
);
652 for(dpos
= 0; (dpos
= sub
.find("\r", dpos
)) != -1; ) {
656 for(dpos
= 0; (dpos
= sub
.find("\t", dpos
)) != -1; ) {
658 sub
.insert(dpos
, string(rtabmargin(false, dpos
)-dpos
, ' '));
665 void find_gather_quoted(vector
<quotedblock
> &lst
, const string
&str
,
666 const string
"e
, const string
&escape
) {
667 bool inquote
= false;
671 while((npos
= str
.find_first_of(quote
, npos
)) != -1) {
673 if(escape
.find(str
[npos
-1]) == -1) {
680 if(str
[npos
] == qch
) {
692 int find_quoted(const string
&str
, const string
&needle
, int offs
,
693 const string
"e
, const string
&escape
) {
694 vector
<quotedblock
> positions
;
695 vector
<quotedblock
>::iterator qi
;
699 find_gather_quoted(positions
, str
, quote
, escape
);
701 while((npos
= str
.find(needle
, npos
)) != -1) {
702 for(found
= false, qi
= positions
.begin(); qi
!= positions
.end() && !found
; qi
++)
703 if((npos
> qi
->begin
) && (npos
< qi
->end
)) found
= true;
709 return !found
? npos
: -1;
712 int find_quoted_first_of(const string
&str
, const string
&needle
, int offs
,
713 const string
"e
, const string
&escape
) {
714 vector
<quotedblock
> positions
;
715 vector
<quotedblock
>::iterator qi
;
719 find_gather_quoted(positions
, str
, quote
, escape
);
721 while((npos
= str
.find_first_of(needle
, npos
)) != -1) {
722 for(found
= false, qi
= positions
.begin(); qi
!= positions
.end() && !found
; qi
++)
723 if((npos
> qi
->begin
) && (npos
< qi
->end
)) found
= true;
729 return !found
? npos
: -1;
732 void splitlongtext(string text
, vector
<string
> &lst
, int size
, const string cont
) {
738 while(!text
.empty()) {
739 if(text
.size() <= size
-cont
.size()) {
741 } else if((npos
= text
.substr(0, size
-cont
.size()).find_last_of(" \t")) == -1) {
742 npos
= size
-cont
.size();
745 sub
= text
.substr(0, npos
);
748 if(text
.size() > cont
.size()) sub
+= cont
; else {
753 if((npos
= text
.find_first_not_of(" \t")) != -1)
760 string
strdateandtime(time_t stamp
, const string
&fmt
) {
761 return strdateandtime(localtime(&stamp
), fmt
);
764 string
strdateandtime(struct tm
*tms
, const string
&fmt
) {
766 /*time_t current_time = time(0);*/
767 /*time_t when = mktime(tms);*/
771 afmt
= "%b %e %Y %H:%M";
773 if(current_time > when + 6L * 30L * 24L * 60L * 60L // Old.
774 || current_time < when - 60L * 60L) { // Future.
777 afmt = "%b %e %H:%M";
782 strftime(buf
, 512, afmt
.c_str(), tms
);
786 bool iswholeword(const string
&s
, int so
, int eo
) {
788 const string wdelims
= "[](),.; <>-+{}=|&%~*/:?@";
790 lm
= !so
|| (wdelims
.find(s
.substr(so
-1, 1)) != -1);
791 rm
= (eo
== s
.size()-1) || (wdelims
.find(s
.substr(eo
, 1)) != -1);
796 int hex2int(const string
&ahex
) {
801 if(ahex
.size() <= 2) {
802 for(i
= 0; i
< ahex
.size(); i
++) {
803 r
+= isdigit(ahex
[i
]) ? ahex
[i
]-48 : toupper(ahex
[i
])-55;
811 bool getconf(string
&st
, string
&buf
, ifstream
&f
, bool passemptylines
) {
815 while(!f
.eof() && !ret
) {
821 sect
= buf
.substr(1);
824 if(buf
[1] != '!') break;
829 } else if(passemptylines
) {
838 bool getstring(istream
&f
, string
&sbuf
) {
839 static char buf
[2048];
847 f
.getline(buf
, 2048);
849 } while(!f
.good() && !f
.eof());
855 string
ruscase(const string
&s
, const string
&mode
) {
856 static const string lower
= "ÁÂ×ÇÄÅÖÚÉÊËÌÍÎÏÐÒÓÔÕÆÈÃÞÛÝØßÙÜÀÑ";
857 static const string upper
= "áâ÷çäåöúéêëìíîïðòóôõæèãþûýøÿùüàñ";
858 string r
, tfrom
, tto
;
861 if(mode
== "tolower") {
864 } else if(mode
== "toupper") {
871 for(r
= s
; (pos
= r
.find_first_of(tfrom
)) != -1; ) {
873 tpos
= tfrom
.find(c
);
879 while((pos
= r
.find_first_not_of(tfrom
, pos
)) != -1) {
880 if(mode
== "tolower") r
[pos
] = tolower(r
[pos
]); else
881 if(mode
== "toupper") r
[pos
] = toupper(r
[pos
]);
888 string
siconv(const string
&atext
, const string
&fromcs
, const string
&tocs
) {
890 iconv_t cd
= iconv_open(tocs
.c_str(), fromcs
.c_str());
892 if(cd
!= ((iconv_t
) -1)) {
893 string r
, text(atext
);
894 size_t inleft
, outleft
, soutleft
;
895 char *inbuf
, *outbuf
, *sinbuf
, *soutbuf
;
897 //from iconv.c (libiconv)
898 iconv(cd
,NULL
,NULL
,NULL
,NULL
);
900 while(!text
.empty()) {
901 sinbuf
= inbuf
= strdup(text
.c_str());
902 inleft
= strlen(inbuf
);
904 soutleft
= outleft
= inleft
*4;
905 soutbuf
= outbuf
= new char[outleft
];
907 size_t res
= iconv(cd
, (ICONV_CONST
char **) &inbuf
, &inleft
,
910 soutbuf
[soutleft
-outleft
] = 0;
912 text
.erase(0, text
.size()-inleft
);
917 if(res
== -1 && errno
!= EILSEQ
)
934 string
cuthtml(const string
&html
, int flags
) {
935 string r
, tag
, buf
, token
;
938 for(pos
= 0; (npos
= html
.find("<", pos
)) != -1; pos
= npos
) {
940 r
+= html
.substr(pos
, npos
-pos
);
942 if((npos
= html
.find(">", ++npos
)) != -1) {
945 tag
= html
.substr(tpos
+1, npos
-tpos
-2);
946 if(tag
.substr(0, 1) == "/") tag
.erase(0, 1);
947 tag
= leadcut(trailcut(tag
, "/ \n\r"), "/ \n\r");
949 buf
= ruscase(tag
, "toupper");
950 token
= getword(buf
);
952 if(token
== "BR") r
+= (flags
& chCutBR
) ? "\n" : "<br>";
953 else if((flags
& chCutBR
) && token
== "P") r
+= "\n\n";
955 if(flags
& chLeaveLinks
) {
959 if((tpos
= buf
.find("HREF")) != -1)
960 if((tpos
= buf
.substr(tpos
).find("\"")) != -1) {
961 tag
.erase(0, tpos
+1);
962 r
+= "[ href: " + getword(tag
, "\"") + " ] ";
965 } else if(token
== "IMG") {
966 if((tpos
= buf
.find("SRC")) != -1)
967 if((tpos
= buf
.substr(tpos
).find("\"")) != -1) {
968 tag
.erase(0, tpos
+1);
969 r
+= " [ img: " + getword(tag
, "\"") + " ]";
976 r
+= html
.substr(tpos
);
981 if(pos
< html
.size())
982 r
+= html
.substr(pos
);
987 char *utf8_to_str(const char *pin
) {
988 int n
= 0, i
= 0, inlen
;
989 unsigned char *result
;
990 const unsigned char *in
= (unsigned char *) pin
;
995 result
= new unsigned char[inlen
+ 1];
997 while (n
<= inlen
- 1) {
998 long c
= (long)in
[n
];
999 if(c
< 0x80) result
[i
++] = (char)c
; else {
1000 if((c
& 0xC0) == 0xC0) result
[i
++] = (char)(((c
& 0x03) << 6) | (((unsigned char)in
[++n
]) & 0x3F));
1001 else if ((c
& 0xE0) == 0xE0) {
1002 if (n
+ 2 <= inlen
) {
1003 result
[i
] = (char)(((c
& 0xF) << 4) | (((unsigned char)in
[++n
]) & 0x3F));
1004 result
[i
] = (char)(((unsigned char)result
[i
]) | (((unsigned char)in
[++n
]) & 0x3F));
1007 } else if ((c
& 0xF0) == 0xF0) n
+= 3;
1008 else if ((c
& 0xF8) == 0xF8)
1010 else if ((c
& 0xFC) == 0xFC)
1017 return (char *) result
;
1020 char *str_to_utf8(const char *pin
) {
1023 char *result
= NULL
;
1024 const unsigned char *in
= (unsigned char *) pin
;
1029 inlen
= strlen(pin
);
1030 result
= new char[inlen
* 2 + 1];
1033 long c
= (long)in
[n
];
1045 result
[i
++] = (char)c
;
1047 result
[i
++] = (char)((c
>> 6) | 192);
1048 result
[i
++] = (char)((c
& 63) | 128);
1057 string
striprtf(const string
&s
, const string
&charset
) {
1058 string r
, spec
, unichar
, tmp
;
1060 bool bprint
, bspec
, bunicode
;
1064 bspec
= bunicode
= false;
1066 for(string::const_iterator i
= s
.begin(); i
!= s
.end(); ++i
) {
1067 if(!isalpha(*i
) && !isdigit(*i
)) bprint
= true;
1072 if(spec
.size() == 2) {
1073 r
+= (char) hex2int(spec
);
1112 if(!bparen
&& bprint
&& pre
== '\\') {
1122 if(pre
== '\\' && isdigit(*(i
+1))) {
1135 if(unichar
.size() == 5) {
1137 if(unichar
.substr(0, 4).find_first_not_of("0123456789") == -1) {
1138 long l
= strtol(unichar
.substr(0, 4).c_str(), 0, 0);
1139 char ubuf
[sizeof(long)+4];
1141 memcpy(ubuf
, "\xff\xfe", 2);
1142 memcpy(ubuf
+2, &l
, sizeof(long));
1143 memcpy(ubuf
+sizeof(long)*2, "\x0a\x00", 2);
1145 strcpy(ubuf
, unichar
.substr(4).c_str());
1147 r
+= siconv(ubuf
, "utf-16", charset
);
1160 return leadcut(trailcut(r
));