Annotation of parser3/src/main/pa_charset.C, revision 1.1

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

E-mail: