/* * * kkstrtext string related and text processing routines * $Id: kkstrtext.cc,v 1.45 2005/02/01 00:13:24 konst Exp $ * * Copyright (C) 1999-2004 by Konstantin Klyagin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * */ #include "kkstrtext.h" #include char *strcut(char *strin, int frompos, int count) { if(count > 0) { if(count > strlen(strin)-frompos) count = strlen(strin)-frompos; char *buf = (char *) malloc(strlen(strin) - frompos - count + 1); memcpy(buf, strin + frompos + count, strlen(strin) - frompos - count); memcpy(strin + frompos, buf, strlen(strin) - frompos - count); strin[strlen(strin) - count] = 0; free(buf); } return strin; } char *strimlead(char *str) { return trimlead(str, " \t"); } char *strimtrail(char *str) { return trimtrail(str, " \t"); } char *strim(char *str) { return trim(str, " \t"); } char *trimlead(char *str, char *chr) { while(strchr(chr, str[0]) && strlen(str)) strcpy(str, str + 1); return str; } char *trimtrail(char *str, char *chr) { while(strchr(chr, str[strlen(str)-1]) && strlen(str)) str[strlen(str)-1] = 0; return str; } char *trim(char *str, char *chr) { return trimlead(trimtrail(str, chr), chr); } char *time2str(const time_t *t, char *mask, char *sout) { struct tm *s; char ch, b[10], b1[20]; int len, i, j; sout[0] = 0; s = localtime(t); for(i = 0; i < strlen(mask); i++) { len = 0; if(strchr("DMYhms", ch = mask[i])) { j = i; len = 1; while(mask[++j] == ch) len++; sprintf(b, "%%0%dd", len); i += len-1; switch(ch) { case 'D': sprintf(b1, b, s->tm_mday); break; case 'M': sprintf(b1, b, s->tm_mon+1); break; case 'Y': j = s->tm_year + 1900; sprintf(b1, b, j); if(len <= 3) strcut(b1, 0, 2); break; case 'h': sprintf(b1, b, s->tm_hour); break; case 'm': sprintf(b1, b, s->tm_min); break; case 's': sprintf(b1, b, s->tm_sec); break; } strcat(sout, b1); } else { len = strlen(sout); sout[len+1] = 0; sout[len] = mask[i]; } } return sout; } time_t str2time(char *sdate, char *mask, time_t *t) { struct tm *s; int i, len, j, k; char ch, b[10]; s = (struct tm*) malloc(sizeof(struct tm)); for(i = 0; i < strlen(mask); i++) { len = 0; if(strchr("DMYhms", ch = mask[i])) { j = i; len = 1; while(mask[++j] == ch) len++; i += len-1; b[0] = 0; for(j = i-len+1; j < i+1; j++) { k = strlen(b); b[k+1] = 0; b[k] = sdate[j]; } switch(ch) { case 'D': s->tm_mday=atoi(b); break; case 'M': s->tm_mon=atoi(b); s->tm_mon--; break; case 'Y': s->tm_year=atoi(b); s->tm_year-=1900; break; case 'h': s->tm_hour=atoi(b); s->tm_hour--; break; case 'm': s->tm_min=atoi(b); break; case 's': s->tm_sec=atoi(b); break; } } } s->tm_isdst = -1; *t = mktime(s); free(s); return *t; } string unmime(const string &text) { string r; char *buf = new char[text.size()+1]; strcpy(buf, text.c_str()); r = unmime(buf); delete[] buf; return r; } string mime(const string &text) { string r; char *buf = new char[text.size()*3+1]; r = mime(buf, text.c_str()); delete[] buf; return r; } string fromutf8(const string &text) { string r; char *buf = (char *) utf8_to_str(text.c_str()); r = buf; delete buf; return r; } string toutf8(const string &text) { string r; char *buf = str_to_utf8(text.c_str()); r = buf; delete buf; return r; } char *unmime(char *text) { register int s, d; int htm; for(s = 0, d = 0; text[s] != 0; s++) { if(text[s] == '+') text[d++] = ' '; else if(text[s] == '%') { sscanf(text + s + 1, "%2x", &htm); text[d++] = htm; s += 2; } else text[d++] = text[s]; } text[d] = 0; return(text); } char *mime(char *dst, const char *src) { register int s, d; char c; for(s = 0, d = 0; src[s]; s++) { if((src[s] >= 'a' && src[s] <= 'z') || (src[s] >= 'A' && src[s] <= 'Z') || (src[s] >= '0' && src[s] <= '9')) dst[d++] = src[s]; else { if(src[s] != ' ') { dst[d++] = '%'; c = (src[s] >> 4 & 0x0F); dst[d++] = (c > 9) ? 'A'+c-10 : '0'+c; c = (src[s] & 0x0F); dst[d++] = (c > 9) ? 'A'+c-10 : '0'+c; } else dst[d++] = '+'; } } dst[d] = '\0'; return(dst); } char *strccat(char *dest, char c) { int k = strlen(dest); dest[k] = c; dest[k+1] = 0; return dest; } vector getquotelayout(const string &haystack, const string &qs, const string &aescs) { vector r; string needle, escs; int pos, prevpos, curpos; char cchar, qchar, prevchar; qchar = 0; curpos = prevpos = 0; escs = (qs == aescs) ? "" : aescs; needle = qs + escs; while((pos = haystack.substr(curpos).find_first_of(needle)) != -1) { curpos += pos; cchar = *(haystack.begin()+curpos); if(escs.find(cchar) != -1) { if(qchar) if(prevpos == curpos-1) if(escs.find(prevchar) != -1) { /* Neutralize previous esc char */ cchar = 0; } } else if(qs.find(cchar) != -1) { if(!((escs.find(prevchar) != -1) && (prevpos == curpos-1))) { /* Wasn't an escape (right before this quote char) */ if(!qchar || (qchar == cchar)) { qchar = qchar ? 0 : cchar; r.push_back(curpos); } } } prevpos = curpos++; prevchar = cchar; } return r; } vector getsymbolpositions(const string &haystack, const string &needles, const string &qoutes, const string &esc) { vector r, qp, nr; vector::iterator iq, ir; int pos, st, ed, cpos; for(cpos = 0; (pos = haystack.substr(cpos).find_first_of(needles)) != -1; ) { r.push_back(cpos+pos); cpos += pos+1; } qp = getquotelayout(haystack, qoutes, esc); for(iq = qp.begin(); iq != qp.end(); iq++) { if(!((iq-qp.begin()) % 2)) { st = *iq; ed = iq+1 != qp.end() ? *(iq+1) : haystack.size(); nr.clear(); for(ir = r.begin(); ir != r.end(); ir++) { if(!(*ir > st && *ir < ed)) { nr.push_back(*ir); } } r = nr; } } return r; } #define CHECKESC(curpos, startpos, esc) \ if(curpos > startpos+1) \ if(strchr(esc, *(curpos-1))) \ if(!strchr(esc, *(curpos-2))) { \ curpos++; \ continue; \ } const char *strqpbrk(const char *s, int offset, const char *accept, const char *q, const char *esc) { if(!s) return 0; if(!s[0]) return 0; char qchar = 0; const char *ret = 0, *p = s; char *cset = (char *) malloc(strlen(accept)+strlen(q)+1); strcpy(cset, accept); strcat(cset, q); while(p = strpbrk(p, cset)) { if(strchr(q, *p)) { if(strcmp(esc, q)) CHECKESC(p, s, esc); if(!qchar) { qchar = *p; } else { if(*p == qchar) qchar = 0; } } else if((p-s >= offset) && !qchar) { ret = p; break; } p++; } free(cset); return ret; } const char *strqcasestr(const char *s, const char *str, const char *q, const char *esc) { char quote = 0; int i; for(i = 0; i < strlen(s); i++) { if(strchr(q, s[i])) { if(strcmp(esc, q)) CHECKESC(s+i, s, esc); quote = !quote; } if(!quote) if(!strncasecmp(s + i, str, strlen(str))) return s + i; } return 0; } const char *strqstr(const char *s, const char *str, const char *q, const char *esc) { char quote; const char *ret = 0, *p, *ss, *r; p = ss = s; while(p = strstr(ss, str)) { quote = 0; r = s; while(r = strpbrk(r, q)) { if(r > p) break; if(strcmp(esc, q)) CHECKESC(r, s, esc); quote = !quote; r++; } if(!quote) { ret = p; break; } else { ss = p+strlen(str); } } return ret; } char *strinsert(char *buf, int pos, char *ins) { char *p = strdup(buf+pos); memcpy(buf+pos+strlen(ins), p, strlen(p)+1); memcpy(buf+pos, ins, strlen(ins)); free(p); return buf; } char *strcinsert(char *buf, int pos, char ins) { char *p = strdup(buf+pos); memcpy(buf+pos+1, p, strlen(p)+1); buf[pos] = ins; free(p); return buf; } int strchcount(char *s, char *accept) { char *p = s-1; int ret = 0; while(p = strpbrk(p+1, accept)) ret++; return ret; } int stralone(char *buf, char *startword, int wordlen, char *delim) { int leftdelim = 0, rightdelim = 0; leftdelim = (buf != startword && strchr(delim, *(startword-1))) || buf == startword; rightdelim = !*(startword+wordlen) || strchr(delim, *(startword+wordlen)); return leftdelim && rightdelim; } string justfname(const string &fname) { return fname.substr(fname.rfind("/")+1); } string justpathname(const string &fname) { int pos; if((pos = fname.rfind("/")) != -1) { return fname.substr(0, pos); } else { return ""; } } void charpointerfree(void *p) { char *cp = (char *) p; if(cp) delete cp; } void nothingfree(void *p) { } int stringcompare(void *s1, void *s2) { if(!s1 || !s2) { return s1 != s2; } else { return strcmp((char *) s1, (char *) s2); } } int intcompare(void *s1, void *s2) { return s1 != s2; } string i2str(int i) { char buf[64]; sprintf(buf, "%d", i); return (string) buf; } string ui2str(int i) { char buf[64]; sprintf(buf, "%du", i); return (string) buf; } string textscreen(const string &text) { string r = text; for(int i = 0; i < r.size(); i++) { if(!isalnum(r[i])) r.insert(i++, "\\"); } return r; } string leadcut(const string &base, const string &delim) { int pos = base.find_first_not_of(delim); return (pos != -1) ? base.substr(pos) : ""; } string trailcut(const string &base, const string &delim) { int pos = base.find_last_not_of(delim); return (pos != -1) ? base.substr(0, pos+1) : ""; } string getword(string &base, const string &delim) { string sub; int i; bool found = false; base = leadcut(base, delim); for(i = 0, sub = base; i < sub.size(); i++) if(strchr(delim.c_str(), sub[i])) { sub.resize(i); base.replace(0, i, ""); base = leadcut(base, delim); found = true; break; } if(!found) base = ""; return sub; } const string getwordquote(string &base, string quote, string delim) { string sub; bool inquote = false; int i; base = leadcut(base, delim); for(i = 0, sub = base; i < sub.size(); i++) { if(strchr(quote.c_str(), sub[i])) { inquote = !inquote; } else if(!inquote && strchr(delim.c_str(), sub[i])) { sub.resize(i); base.replace(0, i, ""); base = leadcut(base, delim); break; } } if(sub == base) base = ""; return sub; } string getrword(string &base, const string &delim) { string sub; int i; base = trailcut(base, delim); for(i = base.size()-1, sub = base; i >= 0; i--) if(strchr(delim.c_str(), base[i])) { sub = base.substr(i+1); base.resize(i); base = trailcut(base, delim); break; } if(sub == base) base = ""; return sub; } string getrwordquote(string &base, const string "e, const string &delim) { string sub; bool inquote = false; int i; base = trailcut(base, delim); for(i = base.size()-1, sub = base; i >= 0; i--) if(strchr(quote.c_str(), base[i])) { inquote = !inquote; } else if(!inquote && strchr(delim.c_str(), base[i])) { sub = base.substr(i+1); base.resize(i); base = trailcut(base, delim); break; } if(sub == base) base = ""; return sub; } int rtabmargin(bool fake, int curpos, const char *p) { int ret = -1, n, near; if(p && (curpos != strlen(p))) { n = strspn(p+curpos, " "); if(fake) { near = ((curpos/(TAB_SIZE/2))+1)*(TAB_SIZE/2); if(n >= near-curpos) ret = near; } near = ((curpos/TAB_SIZE)+1)*TAB_SIZE; if(n >= near-curpos) ret = near; } else { if(p && fake) fake = (strspn(p, " ") == strlen(p)); if(fake) ret = ((curpos/(TAB_SIZE/2))+1)*(TAB_SIZE/2); else ret = ((curpos/TAB_SIZE)+1)*TAB_SIZE; } return ret; } int ltabmargin(bool fake, int curpos, const char *p) { int ret = -1, near, n = 0; const char *cp; if(p) { cp = p+curpos; if(curpos) { if(*(--cp) == ' ') n++; for(; (*cp == ' ') && (cp != p); cp--) n++; } if(fake) { near = (curpos/(TAB_SIZE/2))*(TAB_SIZE/2); if(near <= curpos-n) if((ret = curpos-n) != 0) ret++; } near = (curpos/TAB_SIZE)*TAB_SIZE; if(near <= curpos-n) { if((ret = curpos-n) != 0) ret++; } else ret = near; } else { if(fake) ret = (curpos/(TAB_SIZE/2))*(TAB_SIZE/2); else ret = (curpos/TAB_SIZE)*TAB_SIZE; } return ret; } void breakintolines(string text, vector &lst, int linelen) { int dpos, nlen; string sub; vector::iterator i; breakintolines(text, lst); if(linelen > 0) { for(i = lst.begin(); i != lst.end(); i++) { if(i->size() > linelen) { sub = i->substr(0, nlen = linelen); if((dpos = sub.rfind(" ")) != -1) { if(dpos) nlen = dpos; else nlen = 1; } if(dpos != -1) nlen++; sub = i->substr(nlen); i->erase(nlen); lst.insert(i+1, sub); i = lst.begin(); } } } } void breakintolines(const string &text, vector &lst) { int npos, dpos, tpos; string sub; tpos = 0; lst.clear(); while(tpos < text.size()) { if((npos = text.find("\n", tpos)) != -1) { sub = text.substr(tpos, npos-tpos); } else { sub = text.substr(tpos); npos = text.size(); } tpos += npos-tpos+1; for(dpos = 0; (dpos = sub.find("\r", dpos)) != -1; ) { sub.erase(dpos, 1); } for(dpos = 0; (dpos = sub.find("\t", dpos)) != -1; ) { sub.erase(dpos, 1); sub.insert(dpos, string(rtabmargin(false, dpos)-dpos, ' ')); } lst.push_back(sub); } } void find_gather_quoted(vector &lst, const string &str, const string "e, const string &escape) { bool inquote = false; int npos = 0, qch; quotedblock qb; while((npos = str.find_first_of(quote, npos)) != -1) { if(npos) if(escape.find(str[npos-1]) == -1) { inquote = !inquote; if(inquote) { qb.begin = npos; qch = str[npos]; } else { if(str[npos] == qch) { qb.end = npos; lst.push_back(qb); } else { inquote = true; } } } npos++; } } int find_quoted(const string &str, const string &needle, int offs, const string "e, const string &escape) { vector positions; vector::iterator qi; int npos = offs; bool found; find_gather_quoted(positions, str, quote, escape); while((npos = str.find(needle, npos)) != -1) { for(found = false, qi = positions.begin(); qi != positions.end() && !found; qi++) if((npos > qi->begin) && (npos < qi->end)) found = true; if(!found) break; npos++; } return !found ? npos : -1; } int find_quoted_first_of(const string &str, const string &needle, int offs, const string "e, const string &escape) { vector positions; vector::iterator qi; int npos = offs; bool found; find_gather_quoted(positions, str, quote, escape); while((npos = str.find_first_of(needle, npos)) != -1) { for(found = false, qi = positions.begin(); qi != positions.end() && !found; qi++) if((npos > qi->begin) && (npos < qi->end)) found = true; if(!found) break; npos++; } return !found ? npos : -1; } void splitlongtext(string text, vector &lst, int size, const string cont) { string sub; int npos; lst.clear(); while(!text.empty()) { if(text.size() <= size-cont.size()) { npos = text.size(); } else if((npos = text.substr(0, size-cont.size()).find_last_of(" \t")) == -1) { npos = size-cont.size(); } sub = text.substr(0, npos); text.erase(0, npos); if(text.size() > cont.size()) sub += cont; else { sub += text; text = ""; } if((npos = text.find_first_not_of(" \t")) != -1) text.erase(0, npos); lst.push_back(sub); } } string strdateandtime(time_t stamp, const string &fmt) { return strdateandtime(localtime(&stamp), fmt); } string strdateandtime(struct tm *tms, const string &fmt) { char buf[512]; time_t current_time = time(0); time_t when = mktime(tms); string afmt = fmt; if(afmt.empty()) { afmt = "%b %e %Y %H:%M"; /* if(current_time > when + 6L * 30L * 24L * 60L * 60L // Old. || current_time < when - 60L * 60L) { // Future. afmt = "%b %e %Y"; } else { afmt = "%b %e %H:%M"; } */ } strftime(buf, 512, afmt.c_str(), tms); return buf; } bool iswholeword(const string &s, int so, int eo) { bool rm, lm; const string wdelims = "[](),.; <>-+{}=|&%~*/:?@"; lm = !so || (wdelims.find(s.substr(so-1, 1)) != -1); rm = (eo == s.size()-1) || (wdelims.find(s.substr(eo, 1)) != -1); return rm && lm; } int hex2int(const string &ahex) { int r, i; r = 0; if(ahex.size() <= 2) { for(i = 0; i < ahex.size(); i++) { r += isdigit(ahex[i]) ? ahex[i]-48 : toupper(ahex[i])-55; if(!i) r *= 16; } } return r; } bool getconf(string &st, string &buf, ifstream &f, bool passemptylines) { bool ret = false; static string sect; while(!f.eof() && !ret) { getstring(f, buf); if(buf.size()) { switch(buf[0]) { case '%': sect = buf.substr(1); break; case '#': if(buf[1] != '!') break; default: ret = buf.size(); break; } } else if(passemptylines) { ret = 1; } } st = sect; return ret; } bool getstring(istream &f, string &sbuf) { static char buf[2048]; bool r; if(r = !f.eof()) { sbuf = ""; do { f.clear(); f.getline(buf, 2048); sbuf += buf; } while(!f.good() && !f.eof()); } return r; } string ruscase(const string &s, const string &mode) { static const string lower = "ÁÂ×ÇÄÅÖÚÉÊËÌÍÎÏÐÒÓÔÕÆÈÃÞÛÝØßÙÜÀÑ"; static const string upper = "áâ÷çäåöúéêëìíîïðòóôõæèãþûýøÿùüàñ"; string r, tfrom, tto; int pos, tpos; if(mode == "tolower") { tfrom = upper; tto = lower; } else if(mode == "toupper") { tfrom = lower; tto = upper; } else { return s; } for(r = s; (pos = r.find_first_of(tfrom)) != -1; ) { char c = r[pos]; tpos = tfrom.find(c); r[pos] = tto[tpos]; } pos = 0; while((pos = r.find_first_not_of(tfrom, pos)) != -1) { if(mode == "tolower") r[pos] = tolower(r[pos]); else if(mode == "toupper") r[pos] = toupper(r[pos]); pos++; } return r; } string siconv(const string &atext, const string &fromcs, const string &tocs) { #ifdef HAVE_ICONV iconv_t cd = iconv_open(tocs.c_str(), fromcs.c_str()); if(((int) cd) != -1) { string r, text(atext); size_t inleft, outleft, soutleft; char *inbuf, *outbuf, *sinbuf, *soutbuf; //from iconv.c (libiconv) iconv(cd,NULL,NULL,NULL,NULL); while(!text.empty()) { sinbuf = inbuf = strdup(text.c_str()); inleft = strlen(inbuf); soutleft = outleft = inleft*4; soutbuf = outbuf = new char[outleft]; size_t res = iconv(cd, (ICONV_CONST char **) &inbuf, &inleft, &outbuf, &outleft); soutbuf[soutleft-outleft] = 0; r += soutbuf; text.erase(0, text.size()-inleft); delete soutbuf; delete sinbuf; if(res == -1 && errno != EILSEQ) break; if(!text.empty()) { text.erase(0, 1); r += " "; } } iconv_close(cd); return r; } #endif return atext; } string cuthtml(const string &html, int flags) { string r, tag, buf, token; int npos, pos, tpos; for(pos = 0; (npos = html.find("<", pos)) != -1; pos = npos) { tpos = npos; r += html.substr(pos, npos-pos); if((npos = html.find(">", ++npos)) != -1) { npos++; tag = html.substr(tpos+1, npos-tpos-2); if(tag.substr(0, 1) == "/") tag.erase(0, 1); tag = leadcut(trailcut(tag, "/ \n\r"), "/ \n\r"); buf = ruscase(tag, "toupper"); token = getword(buf); if(token == "BR") r += (flags & chCutBR) ? "\n" : "
"; else if((flags & chCutBR) && token == "P") r += "\n\n"; if(flags & chLeaveLinks) { getword(tag); if(token == "A") { if((tpos = buf.find("HREF")) != -1) if((tpos = buf.substr(tpos).find("\"")) != -1) { tag.erase(0, tpos+1); r += "[ href: " + getword(tag, "\"") + " ] "; } } else if(token == "IMG") { if((tpos = buf.find("SRC")) != -1) if((tpos = buf.substr(tpos).find("\"")) != -1) { tag.erase(0, tpos+1); r += " [ img: " + getword(tag, "\"") + " ]"; } } } } else { r += html.substr(tpos); npos = html.size(); } } if(pos < html.size()) r += html.substr(pos); return r; } char *utf8_to_str(const char *pin) { int n = 0, i = 0, inlen; unsigned char *result; const unsigned char *in = (unsigned char *) pin; if(!in) return NULL; inlen = strlen(pin); result = new unsigned char[inlen + 1]; while (n <= inlen - 1) { long c = (long)in[n]; if(c < 0x80) result[i++] = (char)c; else { if((c & 0xC0) == 0xC0) result[i++] = (char)(((c & 0x03) << 6) | (((unsigned char)in[++n]) & 0x3F)); else if ((c & 0xE0) == 0xE0) { if (n + 2 <= inlen) { result[i] = (char)(((c & 0xF) << 4) | (((unsigned char)in[++n]) & 0x3F)); result[i] = (char)(((unsigned char)result[i]) | (((unsigned char)in[++n]) & 0x3F)); i++; } else n += 2; } else if ((c & 0xF0) == 0xF0) n += 3; else if ((c & 0xF8) == 0xF8) n += 4; else if ((c & 0xFC) == 0xFC) n += 5; } n++; } result[i] = '\0'; return (char *) result; } char *str_to_utf8(const char *pin) { int n = 0, i = 0; int inlen; char *result = NULL; const unsigned char *in = (unsigned char *) pin; if(!in) return NULL; inlen = strlen(pin); result = new char[inlen * 2 + 1]; while (n < inlen) { long c = (long)in[n]; if (c == 27) { n += 2; if (in[n] == 'x') n++; if (in[n] == '3') n++; n += 2; continue; } if (c < 128) result[i++] = (char)c; else { result[i++] = (char)((c >> 6) | 192); result[i++] = (char)((c & 63) | 128); } n++; } result[i] = '\0'; return result; } string striprtf(const string &s, const string &charset) { string r, spec, unichar, tmp; char pre = 0; bool bprint, bspec, bunicode; int bparen = -1; bprint = true; bspec = bunicode = false; for(string::const_iterator i = s.begin(); i != s.end(); ++i) { if(!isalpha(*i) && !isdigit(*i)) bprint = true; if(bspec) { spec += *i; if(spec.size() == 2) { r += (char) hex2int(spec); bspec = false; bprint = true; } } else switch(*i) { case '{': if(pre != '\\') { bparen++; bprint = false; } else { bprint = true; r += *i; } break; case '}': if(pre != '\\') { bprint = false; bparen--; } else { bprint = true; r += *i; } break; case '\\': if(pre != '\\') { bprint = false; } else { bprint = true; r += *i; pre = 0; continue; } break; case '\'': if(!bparen && bprint && pre == '\\') { spec = ""; bspec = true; } else { r += *i; } break; case 'u': if(!bparen) { if(pre == '\\' && isdigit(*(i+1))) { unichar = ""; bunicode = true; } else if(bprint) { r += *i; } } break; default: if(!bparen) { if(bunicode) { unichar += *i; if(unichar.size() == 5) { bunicode = false; if(unichar.substr(0, 4).find_first_not_of("0123456789") == -1) { long l = strtol(unichar.substr(0, 4).c_str(), 0, 0); char ubuf[sizeof(long)+4]; #ifdef HAVE_ICONV memcpy(ubuf, "\xff\xfe", 2); memcpy(ubuf+2, &l, sizeof(long)); memcpy(ubuf+sizeof(long)*2, "\x0a\x00", 2); #else strcpy(ubuf, unichar.substr(4).c_str()); #endif r += siconv(ubuf , "utf-16", charset); } } } else if(bprint) { r += *i; } } } pre = *i; } return leadcut(trailcut(r)); }