Annotation of parser3/src/main/pa_charset.C, revision 1.7
1.1 paf 1: /** @file
2: Parser: Charset connection implementation.
3:
1.4 paf 4: Copyright(c) 2001 ArtLebedev Group(http://www.artlebedev.com)
5: Author: Alexander Petrosyan<paf@design.ru>(http://paf.design.ru)
1.1 paf 6:
1.7 ! paf 7: $Id: pa_charset.C,v 1.6 2001/12/19 16:41:02 paf Exp $
1.1 paf 8: */
9:
10: #include "pa_charset.h"
11: //#include "pa_exception.h"
12: //#include "pa_common.h"
13: //#include "pa_threads.h"
14:
15: #ifdef XML
1.4 paf 16: # include<util/TransENameMap.hpp>
17: # include<util/XML256TableTranscoder.hpp>
18: # include<util/PlatformUtils.hpp>
19: # include<PlatformSupport/XalanTranscodingServices.hpp>
1.1 paf 20: #endif
21:
22: // globals
23:
24:
25: // consts
26:
27: #define MAX_CHARSET_UNI_CODES 500
28:
29: // helpers
30:
31: inline void prepare_case_tables(unsigned char *tables) {
32: unsigned char *lcc_table=tables+lcc_offset;
33: unsigned char *fcc_table=tables+fcc_offset;
34: for(int i=0; i<0x100; i++)
35: lcc_table[i]=fcc_table[i]=i;
36: }
37: inline void cstr2ctypes(unsigned char *tables, const unsigned char *cstr,
38: unsigned char bit) {
39: unsigned char *ctypes_table=tables+ctypes_offset;
40: ctypes_table[0]=bit;
41: for(; *cstr; cstr++) {
42: unsigned char c=*cstr;
43: ctypes_table[c]|=bit;
44: }
45: }
46: inline unsigned int to_wchar_code(const char *cstr) {
47: if(!cstr || !*cstr)
48: return 0;
49: if(cstr[1]==0)
1.4 paf 50: return(unsigned int)(unsigned char)cstr[0];
1.1 paf 51:
52: char *error_pos;
1.4 paf 53: return(unsigned int)strtol(cstr, &error_pos, 0);
1.1 paf 54: }
55: inline bool to_bool(const char *cstr) {
56: return cstr && *cstr!=0;
57: }
58: static void element2ctypes(unsigned char c, bool belongs,
59: unsigned char *tables, unsigned char bit, int group_offset=-1) {
60: if(!belongs)
61: return;
62:
63: unsigned char *ctypes_table=tables+ctypes_offset;
64:
65: ctypes_table[c]|=bit;
66: if(group_offset>=0)
1.4 paf 67: tables[cbits_offset+group_offset+c/8] |= 1<<(c%8);
1.1 paf 68: }
69: static void element2case(unsigned char from, unsigned char to,
70: unsigned char *tables) {
71: if(!to)
72: return;
73:
74: unsigned char *lcc_table=tables+lcc_offset;
75: unsigned char *fcc_table=tables+fcc_offset;
76: lcc_table[from]=to;
77: fcc_table[from]=to; fcc_table[to]=from;
78: }
79:
80: #ifdef XML
81: template <class TType> class ENameMapFor2 : public ENameMap {
1.4 paf 82: public:
1.1 paf 83: // -----------------------------------------------------------------------
84: // Constructors and Destructor
85: // -----------------------------------------------------------------------
86: ENameMapFor2(
87: const XMLCh* const encodingName
88: , const XMLCh* const fromTable
89: , const XMLTransService::TransRec* const toTable
90: , const unsigned int toTableSize
1.4 paf 91: ): ENameMap(encodingName),
1.1 paf 92: ffromTable(fromTable),
93: ftoTable(toTable),
94: ftoTableSize(toTableSize) {}
95:
96: // -----------------------------------------------------------------------
97: // Implementation of virtual factory method
98: // -----------------------------------------------------------------------
99: virtual XMLTranscoder* makeNew(const unsigned int blockSize) const {
100: return new TType(
101: getKey(),
102: blockSize,
103: ffromTable,
104: ftoTable, ftoTableSize);
105: }
106: private:
107: const XMLCh* const ffromTable;
108: const XMLTransService::TransRec* const ftoTable;
109: const unsigned int ftoTableSize;
110:
1.4 paf 111: private:
1.1 paf 112: // -----------------------------------------------------------------------
113: // Unimplemented constructors and operators
114: // -----------------------------------------------------------------------
115: ENameMapFor2();
116: ENameMapFor2(const ENameMapFor2<TType>&);
117: void operator=(const ENameMapFor2<TType>&);
118: };
119:
120: class XML256TableTranscoder2 : public XML256TableTranscoder {
121: public :
122: XML256TableTranscoder2(
123: const XMLCh* const encodingName
124: , const unsigned int blockSize
125: , const XMLCh* const fromTable
126: , const XMLTransService::TransRec* const toTable
127: , const unsigned int toTableSize
128: ) : XML256TableTranscoder(encodingName, blockSize, fromTable, toTable, toTableSize) {}
129:
1.4 paf 130: private:
1.1 paf 131: XML256TableTranscoder2();
132: XML256TableTranscoder2(const XML256TableTranscoder2&);
133: void operator=(const XML256TableTranscoder2&);
134: };
135: #endif
136:
137: // methods
138:
139: extern "C" unsigned char pcre_default_tables[]; // pcre/chartables.c
1.7 ! paf 140: Charset::Charset(Pool& apool, const String& aname, const String *request_file_spec): Pooled(apool),
! 141: fname(aname) {
1.1 paf 142:
1.7 ! paf 143: const char *name_cstr=fname.cstr();
! 144:
! 145: if(request_file_spec) {
1.1 paf 146: fisUTF8=false;
1.7 ! paf 147: loadDefinition(*request_file_spec);
1.1 paf 148: #ifdef XML
149: addEncoding(name_cstr);
150: #endif
151: } else {
152: fisUTF8=true;
1.4 paf 153: // grab default onces [for UTF-8 so to be able to make a-z =>A-Z
1.1 paf 154: memcpy(pcre_tables, pcre_default_tables, sizeof(pcre_tables));
155: }
156:
157: #ifdef XML
158: initTranscoder(&aname, name_cstr);
159: #endif
160: }
161:
162: Charset::~Charset() {
163: #ifdef XML
164: delete transcoder;
165: #endif
166: }
167:
1.7 ! paf 168: void Charset::loadDefinition(const String& request_file_spec) {
1.1 paf 169: // pcre_tables
170: // lowcase, flipcase, bits digit+word+whitespace, masks
171:
172: // must not move this inside of prepare_case_tables
173: // don't know the size there
174: memset(pcre_tables, 0, sizeof(pcre_tables));
175: prepare_case_tables(pcre_tables);
1.4 paf 176: cstr2ctypes(pcre_tables,(const unsigned char *)"*+?{^.$|()[", ctype_meta);
1.1 paf 177:
178: // charset
179: memset(fromTable, 0, sizeof(fromTable));
1.5 paf 180: toTable=(Charset_TransRec *)calloc(sizeof(Charset_TransRec)*MAX_CHARSET_UNI_CODES);
1.1 paf 181: toTableSize=0;
182: // strangly vital
183: toTable[toTableSize].intCh=0;
184: toTable[toTableSize].extCh=(XMLByte)0;
185: toTableSize++;
186:
187: // loading text
1.7 ! paf 188: char *data=file_read_text(pool(), request_file_spec);
1.1 paf 189:
190: // ignore header
191: getrow(&data);
192:
193: // parse cells
194: char *row;
195: while(row=getrow(&data)) {
196: // remove empty&comment lines
197: if(!*row || *row=='#')
198: continue;
199:
200: // char white-space digit hex-digit letter word lowercase unicode1 unicode2
201: unsigned int c=0;
202: char *cell;
203: for(int column=0; cell=lsplit(&row, '\t'); column++) {
204: switch(column) {
205: case 0: c=to_wchar_code(cell); break;
206: // pcre_tables
207: case 1: element2ctypes(c, to_bool(cell), pcre_tables, ctype_space, cbit_space); break;
208: case 2: element2ctypes(c, to_bool(cell), pcre_tables, ctype_digit, cbit_digit); break;
209: case 3: element2ctypes(c, to_bool(cell), pcre_tables, ctype_xdigit); break;
210: case 4: element2ctypes(c, to_bool(cell), pcre_tables, ctype_letter); break;
211: case 5: element2ctypes(c, to_bool(cell), pcre_tables, ctype_word, cbit_word); break;
212: case 6: element2case(c, to_wchar_code(cell), pcre_tables); break;
213: case 7:
214: case 8:
215: // charset
216: if(toTableSize>MAX_CHARSET_UNI_CODES)
217: throw Exception(0, 0,
1.7 ! paf 218: &request_file_spec,
1.1 paf 219: "charset must contain not more then %d unicode values", MAX_CHARSET_UNI_CODES);
220:
221: XMLCh unicode=(XMLCh)to_wchar_code(cell);
222: if(!unicode && column==7/*unicode1 column*/)
223: unicode=(XMLCh)c;
224: if(unicode) {
225: if(!fromTable[c])
226: fromTable[c]=unicode;
227: toTable[toTableSize].intCh=unicode;
228: toTable[toTableSize].extCh=(XMLByte)c;
229: toTableSize++;
230: }
231: break;
232: }
233: }
234: };
235:
236: // sort by the Unicode code point
237: sort_ToTable();
238: }
239:
240: #ifdef XML
241: void Charset::addEncoding(const char *name_cstr) {
242: // addEncoding
243: XalanDOMString sencoding(name_cstr);
244: const XMLCh* const auto_encoding_cstr=sencoding.c_str();
245: int size=sizeof(XMLCh)*(sencoding.size()+1);
246: XMLCh* pool_encoding_cstr=(XMLCh*)malloc(size);
247: memcpy(pool_encoding_cstr, auto_encoding_cstr, size);
248: XMLString::upperCase(pool_encoding_cstr);
249:
250: XMLPlatformUtils::fgTransService->addEncoding(
251: pool_encoding_cstr,
252: new ENameMapFor2<XML256TableTranscoder2>(
253: pool_encoding_cstr
254: , fromTable
255: , toTable
256: , toTableSize
257: ));
258: }
259:
260: void Charset::initTranscoder(const String *source, const char *name_cstr) {
261: XMLTransService::Codes resValue;
262: transcoder=XMLPlatformUtils::fgTransService->makeNewTranscoderFor(name_cstr, resValue, 60);
263: if(!transcoder)
264: throw Exception(0, 0,
265: source,
266: "unsupported encoding");
267: }
268: #endif
269:
270: static int sort_cmp_Trans_rec_intCh(const void *a, const void *b) {
271: return
272: static_cast<const Charset_TransRec *>(a)->intCh-
273: static_cast<const Charset_TransRec *>(b)->intCh;
274: }
275:
276: void Charset::sort_ToTable() {
277: _qsort(toTable, toTableSize, sizeof(*toTable),
278: sort_cmp_Trans_rec_intCh);
279: //FILE *f=fopen("c:\\temp\\a", "wb");
280: //fwrite(toTable, toTableSize, sizeof(*toTable), f);
281: //fclose(f);
282: }
283:
284: XMLByte Charset::xlatOneTo(const XMLCh toXlat) const {
285: unsigned int lowOfs = 0;
286: unsigned int hiOfs = toTableSize - 1;
287: XMLByte curByte = 0;
288: do {
289: // Calc the mid point of the low and high offset.
1.4 paf 290: const unsigned int midOfs =((hiOfs - lowOfs) / 2)+lowOfs;
1.1 paf 291:
292: // If our test char is greater than the mid point char, then
293: // we move up to the upper half. Else we move to the lower
294: // half. If its equal, then its our guy.
1.4 paf 295: if(toXlat>toTable[midOfs].intCh)
1.1 paf 296: lowOfs = midOfs;
1.4 paf 297: else if(toXlat<toTable[midOfs].intCh)
1.1 paf 298: hiOfs = midOfs;
299: else
300: return toTable[midOfs].extCh;
1.4 paf 301: } while(lowOfs+1<hiOfs);
1.1 paf 302:
303: return '?';
304: }
305:
306: void Charset::transcode(Pool& pool,
307: const Charset& source_charset, const void *source_body, size_t source_content_length,
308: const Charset& dest_charset, const void *& dest_body, size_t& dest_content_length
309: ) {
1.4 paf 310: if(!source_content_length) {
311: dest_body=0;
312: dest_content_length=0;
313: return;
314: }
315:
1.1 paf 316: switch((source_charset.isUTF8()?0x10:0x00)|(dest_charset.isUTF8()?0x01:0x00)) {
317: default: // 0x00
318: source_charset.transcodeToCharset(pool, dest_charset,
319: source_body, source_content_length,
320: dest_body, dest_content_length);
321: break;
322: case 0x01:
323: source_charset.transcodeToUTF8(pool,
324: source_body, source_content_length,
325: dest_body, dest_content_length);
326: break;
327: case 0x10:
328: dest_charset.transcodeFromUTF8(pool,
329: source_body, source_content_length,
330: dest_body, dest_content_length);
331: break;
332: case 0x11:
333: dest_body=source_body;
334: dest_content_length=source_content_length;
335: break;
336: }
337: }
338:
339: // ---------------------------------------------------------------------------
340: // Local static data
341: //
342: // gUTFBytes
343: // A list of counts of trailing bytes for each initial byte in the input.
344: //
345: // gUTFOffsets
346: // A list of values to offset each result char type, according to how
347: // many source bytes when into making it.
348: //
349: // gFirstByteMark
350: // A list of values to mask onto the first byte of an encoded sequence,
351: // indexed by the number of bytes used to create the sequence.
352: // ---------------------------------------------------------------------------
353: static const XMLByte gUTFBytes[0x100] = {
354: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
355: , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
356: , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
357: , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
358: , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
359: , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
360: , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
361: , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
362: , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
363: , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
364: , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
365: , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
366: , 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
367: , 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
368: , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
369: , 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5
370: };
371:
372: static const uint gUTFOffsets[6] = {
373: 0, 0x3080, 0xE2080, 0x3C82080, 0xFA082080, 0x82082080
374: };
375:
376: static const XMLByte gFirstByteMark[7] = {
377: 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC
378: };
379:
380: /// @todo not so memory-hungry with prescan
381: void Charset::transcodeToUTF8(Pool& pool,
382: const void *source_body, size_t source_content_length,
383: const void *& adest_body, size_t& adest_content_length) const {
384:
385: size_t dest_content_length=0;
386: XMLByte *dest_body=(XMLByte*)pool.malloc(source_content_length*6/*so that surly enough*/);
387:
388: const XMLByte* srcPtr=(const XMLByte*)source_body;
389: const XMLByte* srcEnd=(const XMLByte*)source_body+source_content_length;
390: XMLByte* outPtr=dest_body;
391:
1.4 paf 392: while(srcPtr<srcEnd) {
1.1 paf 393: uint curVal = fromTable[*srcPtr];
394: if(!curVal) {
395: // use the replacement character
1.4 paf 396: *outPtr++= '?';
397: srcPtr++;
1.1 paf 398: continue;
399: }
400:
401: // Figure out how many bytes we need
402: unsigned int encodedBytes;
1.4 paf 403: if(curVal<0x80)
1.1 paf 404: encodedBytes = 1;
1.4 paf 405: else if(curVal<0x800)
1.1 paf 406: encodedBytes = 2;
1.4 paf 407: else if(curVal<0x10000)
1.1 paf 408: encodedBytes = 3;
1.4 paf 409: else if(curVal<0x200000)
1.1 paf 410: encodedBytes = 4;
1.4 paf 411: else if(curVal<0x4000000)
1.1 paf 412: encodedBytes = 5;
1.4 paf 413: else if(curVal<= 0x7FFFFFFF)
1.1 paf 414: encodedBytes = 6;
415: else {
416: // use the replacement character
1.4 paf 417: *outPtr++= '?';
418: srcPtr++;
1.1 paf 419: continue;
420: }
421:
422: // If we cannot fully get this char into the output buffer,
423: // never
424:
425: // We can do it, so update the source index
426: srcPtr++;
427:
428: // And spit out the bytes. We spit them out in reverse order
429: // here, so bump up the output pointer and work down as we go.
1.4 paf 430: outPtr+= encodedBytes;
1.1 paf 431: switch(encodedBytes) {
1.4 paf 432: case 6: *--outPtr = XMLByte((curVal | 0x80UL) & 0xBFUL);
433: curVal>>= 6;
434: case 5: *--outPtr = XMLByte((curVal | 0x80UL) & 0xBFUL);
435: curVal>>= 6;
436: case 4: *--outPtr = XMLByte((curVal | 0x80UL) & 0xBFUL);
437: curVal>>= 6;
438: case 3: *--outPtr = XMLByte((curVal | 0x80UL) & 0xBFUL);
439: curVal>>= 6;
440: case 2: *--outPtr = XMLByte((curVal | 0x80UL) & 0xBFUL);
441: curVal>>= 6;
442: case 1: *--outPtr = XMLByte(curVal | gFirstByteMark[encodedBytes]);
1.1 paf 443: }
444:
445: // Add the encoded bytes back in again to indicate we've eaten them
1.4 paf 446: outPtr+= encodedBytes;
1.1 paf 447: }
448:
449: // return
450: adest_body=dest_body;
451: adest_content_length=outPtr-dest_body;
452: }
453: void Charset::transcodeFromUTF8(Pool& pool,
454: const void *source_body, size_t source_content_length,
455: const void *& adest_body, size_t& adest_content_length) const {
456: size_t dest_content_length=0;
457: XMLByte *dest_body=(XMLByte*)pool.malloc(source_content_length/*surly enough*/);
458:
459: const XMLByte* srcPtr=(const XMLByte*)source_body;
460: const XMLByte* srcEnd=(const XMLByte*)source_body+source_content_length;
461: XMLByte* outPtr=dest_body;
462:
463: // We now loop until we either run out of input data
1.4 paf 464: while(srcPtr<srcEnd) {
1.1 paf 465: // Get the next leading byte out
466: const XMLByte firstByte = *srcPtr;
467:
1.4 paf 468: // Special-case ASCII, which is a leading byte value of<= 127
469: if(firstByte<= 127) {
470: *outPtr++= firstByte;
1.1 paf 471: srcPtr++;
472: continue;
473: }
474:
475: // See how many trailing src bytes this sequence is going to require
476: const unsigned int trailingBytes = gUTFBytes[firstByte];
477:
478: // If there are not enough source bytes to do this one, then we
1.4 paf 479: // are done. Note that we done>= here because we are implicitly
1.1 paf 480: // counting the 1 byte we get no matter what.
1.4 paf 481: if(srcPtr+trailingBytes>= srcEnd)
1.1 paf 482: break;
483:
484: // Looks ok, so lets build up the value
485: uint tmpVal=0;
486: switch(trailingBytes) {
487: case 5: tmpVal+=*srcPtr++; tmpVal<<=6;
488: case 4: tmpVal+=*srcPtr++; tmpVal<<=6;
489: case 3: tmpVal+=*srcPtr++; tmpVal<<=6;
490: case 2: tmpVal+=*srcPtr++; tmpVal<<=6;
491: case 1: tmpVal+=*srcPtr++; tmpVal<<=6;
492: case 0: tmpVal+=*srcPtr++;
493: break;
494:
495: default:
496: throw Exception(0, 0,
497: 0,
1.4 paf 498: "transcodeFromUTF8 error: wrong trailingBytes value(%d)", trailingBytes);
1.1 paf 499: }
500: tmpVal-=gUTFOffsets[trailingBytes];
501:
502: // If it will fit into a single char, then put it in. Otherwise
503: // fail [*encode it as a surrogate pair. If its not valid, use the
504: // replacement char.*]
1.4 paf 505: if(!(tmpVal & 0xFFFF0000))
506: *outPtr++= xlatOneTo(tmpVal);
1.1 paf 507: else
508: throw Exception(0, 0,
509: 0,
1.4 paf 510: "transcodeFromUTF8 error: too big tmpVal(0x%08X)", tmpVal);
1.1 paf 511: }
512:
513: // return
514: adest_body=dest_body;
515: adest_content_length=outPtr-dest_body;
516: }
517:
518: /// transcode using both charsets
519: void Charset::transcodeToCharset(Pool& pool,
520: const Charset& dest_charset,
521: const void *source_body, size_t source_content_length,
1.6 paf 522: const void *& adest_body, size_t& adest_content_length) const {
1.3 paf 523: if(&dest_charset==this) {
1.6 paf 524: adest_body=source_body;
525: adest_content_length=source_content_length;
526: } else {
527: size_t dest_content_length=source_content_length;
528: unsigned char *dest_body=(unsigned char *)pool.malloc(dest_content_length);
529:
530: const XMLByte* srcPtr=(const XMLByte*)source_body;
531: const XMLByte* srcEnd=(const XMLByte*)source_body+source_content_length;
532:
533: for(XMLByte* outPtr=dest_body; srcPtr<srcEnd; srcPtr++) {
534: XMLCh curVal = fromTable[*srcPtr];
535: if(curVal)
536: *outPtr++=dest_charset.xlatOneTo(curVal);
537: else {
538: // use the replacement character
539: *outPtr++= '?';
540: }
541: }
1.1 paf 542:
1.6 paf 543: adest_body=dest_body;
544: adest_content_length=dest_content_length;
545: }
1.1 paf 546: }
547:
548: #ifdef XML
549: const char *Charset::transcode_cstr(const XalanDOMString& s) {
550: const unsigned int len=s.size()*2;
551: XMLByte* dest=(XMLByte *)malloc((len+1)*sizeof(XMLByte));
552: bool error=true;
553: try {
554: if(transcoder) {
555: unsigned int charsEaten;
556: unsigned int size=transcoder->transcodeTo(
557: s.c_str(), s.length(),
558: dest, len,
559: charsEaten,
560: XMLTranscoder::UnRep_RepChar //UnRep_Throw
561: );
562: dest[size]=0;
563: error=false;
564: }
565: } catch(XMLException& e) {
566: Exception::provide_source(pool(), 0, e);
567: }
1.4 paf 568: return(const char *)dest;
1.1 paf 569: }
570: String& Charset::transcode(const XalanDOMString& s) {
571: return *NEW String(pool(), transcode_cstr(s));
572: }
573:
1.4 paf 574: std::auto_ptr<XalanDOMString>Charset::transcode_buf(const char *buf, size_t buf_size) {
1.1 paf 575: unsigned int dest_size=0;
576: XMLCh* dest=(XMLCh *)malloc((buf_size+1)*sizeof(XMLCh));
577: unsigned char *charSizes=(unsigned char *)malloc(buf_size*sizeof(unsigned char));
578: XalanDOMString *result;
579: try {
580: if(transcoder) {
581: unsigned int bytesEaten;
582: unsigned int dest_size=transcoder->transcodeFrom(
583: (unsigned char *)buf,
584: (const unsigned int)buf_size,
1.4 paf 585: dest,(const unsigned int)buf_size,
1.1 paf 586: bytesEaten,
587: charSizes
588: );
589: result=new XalanDOMString(dest, dest_size);
590: }
591: } catch(XMLException& e) {
592: Exception::provide_source(pool(), 0, e);
593: result=0; //calm, compiler
594: }
595:
596: return std::auto_ptr<XalanDOMString>(result);
597: }
1.4 paf 598: std::auto_ptr<XalanDOMString>Charset::transcode(const String& s) {
1.1 paf 599: const char *cstr=s.cstr(String::UL_UNSPECIFIED);
600:
601: return transcode_buf(cstr, strlen(cstr));
602: }
603: #endif
E-mail: