tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

wrtxml.cpp (37676B)


      1 // © 2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 /*
      4 *******************************************************************************
      5 *
      6 *   Copyright (C) 2002-2015, International Business Machines
      7 *   Corporation and others.  All Rights Reserved.
      8 *
      9 *******************************************************************************
     10 *
     11 * File wrtxml.cpp
     12 *
     13 * Modification History:
     14 *
     15 *   Date        Name        Description
     16 *   10/01/02    Ram         Creation.
     17 *   02/07/08    Spieth      Correct XLIFF generation on EBCDIC platform
     18 *
     19 *******************************************************************************
     20 */
     21 
     22 // Safer use of UnicodeString.
     23 #ifndef UNISTR_FROM_CHAR_EXPLICIT
     24 #   define UNISTR_FROM_CHAR_EXPLICIT explicit
     25 #endif
     26 
     27 // Less important, but still a good idea.
     28 #ifndef UNISTR_FROM_STRING_EXPLICIT
     29 #   define UNISTR_FROM_STRING_EXPLICIT explicit
     30 #endif
     31 
     32 #include "reslist.h"
     33 #include "unewdata.h"
     34 #include "unicode/ures.h"
     35 #include "errmsg.h"
     36 #include "filestrm.h"
     37 #include "cstring.h"
     38 #include "unicode/ucnv.h"
     39 #include "genrb.h"
     40 #include "rle.h"
     41 #include "uhash.h"
     42 #include "uresimp.h"
     43 #include "unicode/ustring.h"
     44 #include "unicode/uchar.h"
     45 #include "ustr.h"
     46 #include "prscmnts.h"
     47 #include "unicode/unistr.h"
     48 #include "unicode/utf8.h"
     49 #include "unicode/utf16.h"
     50 #include <time.h>
     51 
     52 U_NAMESPACE_USE
     53 
     54 static int tabCount = 0;
     55 
     56 static FileStream* out=nullptr;
     57 static struct SRBRoot* srBundle ;
     58 static const char* outDir = nullptr;
     59 static const char* enc ="";
     60 static UConverter* conv = nullptr;
     61 
     62 const char* const* ISOLanguages;
     63 const char* const* ISOCountries;
     64 const char* textExt = ".txt";
     65 const char* xliffExt = ".xlf";
     66 
     67 static int32_t write_utf8_file(FileStream* fileStream, UnicodeString outString)
     68 {
     69    UErrorCode status = U_ZERO_ERROR;
     70    int32_t len = 0;
     71 
     72    // preflight to get the destination buffer size
     73    u_strToUTF8(nullptr,
     74                0,
     75                &len,
     76                toUCharPtr(outString.getBuffer()),
     77                outString.length(),
     78                &status);
     79 
     80    // allocate the buffer
     81    char* dest = static_cast<char*>(uprv_malloc(len));
     82    status = U_ZERO_ERROR;
     83 
     84    // convert the data
     85    u_strToUTF8(dest,
     86                len,
     87                &len,
     88                toUCharPtr(outString.getBuffer()),
     89                outString.length(),
     90                &status);
     91 
     92    // write data to out file
     93    int32_t ret = T_FileStream_write(fileStream, dest, len);
     94    uprv_free(dest);
     95    return (ret);
     96 }
     97 
     98 /*write indentation for formatting*/
     99 static void write_tabs(FileStream* os){
    100    int i=0;
    101    for(;i<=tabCount;i++){
    102        write_utf8_file(os,UnicodeString("    "));
    103    }
    104 }
    105 
    106 /*get ID for each element. ID is globally unique.*/
    107 static char* getID(const char* id, const char* curKey, char* result) {
    108    if(curKey == nullptr) {
    109        result = static_cast<char*>(uprv_malloc(sizeof(char) * uprv_strlen(id) + 1));
    110        uprv_memset(result, 0, sizeof(char)*uprv_strlen(id) + 1);
    111        uprv_strcpy(result, id);
    112    } else {
    113        result = static_cast<char*>(uprv_malloc(sizeof(char) * (uprv_strlen(id) + 1 + uprv_strlen(curKey)) + 1));
    114        uprv_memset(result, 0, sizeof(char)*(uprv_strlen(id) + 1 + uprv_strlen(curKey)) + 1);
    115        if(id[0]!='\0'){
    116            uprv_strcpy(result, id);
    117            uprv_strcat(result, "_");
    118        }
    119        uprv_strcat(result, curKey);
    120    }
    121    return result;
    122 }
    123 
    124 /*compute CRC for binary code*/
    125 /* The code is from  http://www.theorem.com/java/CRC32.java
    126 * Calculates the CRC32 - 32 bit Cyclical Redundancy Check
    127 * <P> This check is used in numerous systems to verify the integrity
    128 * of information.  It's also used as a hashing function.  Unlike a regular
    129 * checksum, it's sensitive to the order of the characters.
    130 * It produces a 32 bit
    131 *
    132 * @author Michael Lecuyer (mjl@theorem.com)
    133 * @version 1.1 August 11, 1998
    134 */
    135 
    136 /* ICU is not endian portable, because ICU data generated on big endian machines can be
    137 * ported to big endian machines but not to little endian machines and vice versa. The
    138 * conversion is not portable across platforms with different endianness.
    139 */
    140 
    141 uint32_t computeCRC(const char *ptr, uint32_t len, uint32_t lastcrc){
    142    int32_t crc;
    143    uint32_t temp1;
    144    uint32_t temp2;
    145 
    146    int32_t crc_ta[256];
    147    int i = 0;
    148    int j = 0;
    149    uint32_t crc2 = 0;
    150 
    151 #define CRC32_POLYNOMIAL 0xEDB88320
    152 
    153    /*build crc table*/
    154    for (i = 0; i <= 255; i++) {
    155        crc2 = i;
    156        for (j = 8; j > 0; j--) {
    157            if ((crc2 & 1) == 1) {
    158                crc2 = (crc2 >> 1) ^ CRC32_POLYNOMIAL;
    159            } else {
    160                crc2 >>= 1;
    161            }
    162        }
    163        crc_ta[i] = crc2;
    164    }
    165 
    166    crc = lastcrc;
    167    while(len--!=0) {
    168        temp1 = static_cast<uint32_t>(crc) >> 8;
    169        temp2 = crc_ta[(crc^*ptr) & 0xFF];
    170        crc = temp1^temp2;
    171        ptr++;
    172    }
    173    return(crc);
    174 }
    175 
    176 static void strnrepchr(char* src, int32_t srcLen, char s, char r){
    177    int32_t i = 0;
    178    for(i=0;i<srcLen;i++){
    179        if(src[i]==s){
    180            src[i]=r;
    181        }
    182    }
    183 }
    184 /* Parse the filename, and get its language information.
    185 * If it fails to get the language information from the filename,
    186 * use "en" as the default value for language
    187 */
    188 static char* parseFilename(const char* id, char* /*lang*/) {
    189    int idLen = static_cast<int>(uprv_strlen(id));
    190    char* localeID = static_cast<char*>(uprv_malloc(idLen+1));
    191    int pos = 0;
    192    int canonCapacity = 0;
    193    char* canon = nullptr;
    194    int canonLen = 0;
    195    /*int i;*/
    196    UErrorCode status = U_ZERO_ERROR;
    197    const char *ext = uprv_strchr(id, '.');
    198 
    199    if(ext != nullptr){
    200        pos = static_cast<int>(ext - id);
    201    } else {
    202        pos = idLen;
    203    }
    204    uprv_memcpy(localeID, id, pos);
    205    localeID[pos]=0; /* NUL terminate the string */
    206 
    207    canonCapacity =pos*3;
    208    canon = static_cast<char*>(uprv_malloc(canonCapacity));
    209    canonLen = uloc_canonicalize(localeID, canon, canonCapacity, &status);
    210 
    211    if(U_FAILURE(status)){
    212        fprintf(stderr, "Could not canonicalize the locale ID: %s. Error: %s\n", localeID, u_errorName(status));
    213        exit(status);
    214    }
    215    strnrepchr(canon, canonLen, '_', '-');
    216    return canon;
    217 }
    218 
    219 static const char* xmlHeader = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
    220 #if 0
    221 static const char* bundleStart = "<xliff version = \"1.2\" "
    222                                        "xmlns='urn:oasis:names:tc:xliff:document:1.2' "
    223                                        "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' "
    224                                        "xsi:schemaLocation='urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd'>\n";
    225 #else
    226 static const char* bundleStart = "<xliff version = \"1.1\" "
    227                                        "xmlns='urn:oasis:names:tc:xliff:document:1.1' "
    228                                        "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' "
    229                                        "xsi:schemaLocation='urn:oasis:names:tc:xliff:document:1.1 http://www.oasis-open.org/committees/xliff/documents/xliff-core-1.1.xsd'>\n";
    230 #endif
    231 static const char* bundleEnd   = "</xliff>\n";
    232 
    233 void res_write_xml(struct SResource *res, const char* id, const char* language, UBool isTopLevel, UErrorCode *status);
    234 
    235 static char* convertAndEscape(char** pDest, int32_t destCap, int32_t* destLength,
    236                              const char16_t* src, int32_t srcLen, UErrorCode* status){
    237    int32_t srcIndex=0;
    238    char* dest=nullptr;
    239    char* temp=nullptr;
    240    int32_t destLen=0;
    241    UChar32 c = 0;
    242 
    243    if(status==nullptr || U_FAILURE(*status) || pDest==nullptr  || srcLen==0 || src == nullptr){
    244        return nullptr;
    245    }
    246    dest =*pDest;
    247    if(dest==nullptr || destCap <=0){
    248        destCap = srcLen * 8;
    249        dest = static_cast<char*>(uprv_malloc(sizeof(char) * destCap));
    250        if(dest==nullptr){
    251            *status=U_MEMORY_ALLOCATION_ERROR;
    252            return nullptr;
    253        }
    254    }
    255 
    256    dest[0]=0;
    257 
    258    while(srcIndex<srcLen){
    259        U16_NEXT(src, srcIndex, srcLen, c);
    260 
    261        if (U16_IS_LEAD(c) || U16_IS_TRAIL(c)) {
    262            *status = U_ILLEGAL_CHAR_FOUND;
    263            fprintf(stderr, "Illegal Surrogate! \n");
    264            uprv_free(dest);
    265            return nullptr;
    266        }
    267 
    268        if((destLen+U8_LENGTH(c)) < destCap){
    269 
    270            /* ASCII Range */
    271            if(c <=0x007F){
    272                switch(c) {
    273                case '\x26':
    274                    uprv_strcpy(dest+( destLen),"\x26\x61\x6d\x70\x3b"); /* &amp;*/
    275                    destLen += static_cast<int32_t>(uprv_strlen("\x26\x61\x6d\x70\x3b"));
    276                    break;
    277                case '\x3c':
    278                    uprv_strcpy(dest+(destLen),"\x26\x6c\x74\x3b"); /* &lt;*/
    279                    destLen += static_cast<int32_t>(uprv_strlen("\x26\x6c\x74\x3b"));
    280                    break;
    281                case '\x3e':
    282                    uprv_strcpy(dest+(destLen),"\x26\x67\x74\x3b"); /* &gt;*/
    283                    destLen += static_cast<int32_t>(uprv_strlen("\x26\x67\x74\x3b"));
    284                    break;
    285                case '\x22':
    286                    uprv_strcpy(dest+(destLen),"\x26\x71\x75\x6f\x74\x3b"); /* &quot;*/
    287                    destLen += static_cast<int32_t>(uprv_strlen("\x26\x71\x75\x6f\x74\x3b"));
    288                    break;
    289                case '\x27':
    290                    uprv_strcpy(dest+(destLen),"\x26\x61\x70\x6f\x73\x3b"); /* &apos; */
    291                    destLen += static_cast<int32_t>(uprv_strlen("\x26\x61\x70\x6f\x73\x3b"));
    292                    break;
    293 
    294                 /* Disallow C0 controls except TAB, CR, LF*/
    295                case 0x00:
    296                case 0x01:
    297                case 0x02:
    298                case 0x03:
    299                case 0x04:
    300                case 0x05:
    301                case 0x06:
    302                case 0x07:
    303                case 0x08:
    304                /*case 0x09:*/
    305                /*case 0x0A: */
    306                case 0x0B:
    307                case 0x0C:
    308                /*case 0x0D:*/
    309                case 0x0E:
    310                case 0x0F:
    311                case 0x10:
    312                case 0x11:
    313                case 0x12:
    314                case 0x13:
    315                case 0x14:
    316                case 0x15:
    317                case 0x16:
    318                case 0x17:
    319                case 0x18:
    320                case 0x19:
    321                case 0x1A:
    322                case 0x1B:
    323                case 0x1C:
    324                case 0x1D:
    325                case 0x1E:
    326                case 0x1F:
    327                    *status = U_ILLEGAL_CHAR_FOUND;
    328                    fprintf(stderr, "Illegal Character \\u%04X!\n", static_cast<int>(c));
    329                    uprv_free(dest);
    330                    return nullptr;
    331                default:
    332                    dest[destLen++] = static_cast<char>(c);
    333                }
    334            }else{
    335                UBool isError = false;
    336                U8_APPEND((unsigned char*)dest,destLen,destCap,c,isError);
    337                if(isError){
    338                    *status = U_ILLEGAL_CHAR_FOUND;
    339                    fprintf(stderr, "Illegal Character \\U%08X!\n", static_cast<int>(c));
    340                    uprv_free(dest);
    341                    return nullptr;
    342                }
    343            }
    344        }else{
    345            destCap += destLen;
    346 
    347            temp = static_cast<char*>(uprv_malloc(sizeof(char) * destCap));
    348            if(temp==nullptr){
    349                *status=U_MEMORY_ALLOCATION_ERROR;
    350                uprv_free(dest);
    351                return nullptr;
    352            }
    353            uprv_memmove(temp,dest,destLen);
    354            destLen=0;
    355            uprv_free(dest);
    356            dest=temp;
    357            temp=nullptr;
    358        }
    359 
    360    }
    361    *destLength = destLen;
    362    return dest;
    363 }
    364 
    365 #define ASTERISK 0x002A
    366 #define SPACE    0x0020
    367 #define CR       0x000A
    368 #define LF       0x000D
    369 #define AT_SIGN  0x0040
    370 
    371 #if UCONFIG_NO_REGULAR_EXPRESSIONS==0
    372 static void
    373 trim(char **src, int32_t *len){
    374 
    375    char *s = nullptr;
    376    int32_t i = 0;
    377    if(src == nullptr || *src == nullptr){
    378        return;
    379    }
    380    s = *src;
    381    /* trim from the end */
    382    for( i=(*len-1); i>= 0; i--){
    383        switch(s[i]){
    384        case ASTERISK:
    385        case SPACE:
    386        case CR:
    387        case LF:
    388            s[i] = 0;
    389            continue;
    390        default:
    391            break;
    392        }
    393        break;
    394 
    395    }
    396    *len = i+1;
    397 }
    398 
    399 static void
    400 print(char16_t* src, int32_t srcLen,const char *tagStart,const char *tagEnd,  UErrorCode *status){
    401    int32_t bufCapacity   = srcLen*4;
    402    char *buf       = nullptr;
    403    int32_t bufLen = 0;
    404 
    405    if(U_FAILURE(*status)){
    406        return;
    407    }
    408 
    409    buf = static_cast<char*>(uprv_malloc(bufCapacity));
    410    if (buf == nullptr) {
    411        fprintf(stderr, "Could not allocate memory!!");
    412        exit(U_MEMORY_ALLOCATION_ERROR);
    413    }
    414    buf = convertAndEscape(&buf, bufCapacity, &bufLen, src, srcLen,status);
    415    if(U_SUCCESS(*status)){
    416        trim(&buf,&bufLen);
    417        write_utf8_file(out,UnicodeString(tagStart));
    418        write_utf8_file(out,UnicodeString(buf, bufLen, "UTF-8"));
    419        write_utf8_file(out,UnicodeString(tagEnd));
    420        write_utf8_file(out,UnicodeString("\n"));
    421 
    422    }
    423 }
    424 #endif
    425 
    426 static void
    427 printNoteElements(const UString *src, UErrorCode *status){
    428 
    429 #if UCONFIG_NO_REGULAR_EXPRESSIONS==0 /* donot compile when no RegularExpressions are available */
    430 
    431    int32_t capacity = 0;
    432    char16_t* note = nullptr;
    433    int32_t noteLen = 0;
    434    int32_t count = 0,i;
    435 
    436    if(src == nullptr){
    437        return;
    438    }
    439 
    440    capacity = src->fLength;
    441    note = static_cast<char16_t*>(uprv_malloc(U_SIZEOF_UCHAR * capacity));
    442 
    443    count = getCount(src->fChars,src->fLength, UPC_NOTE, status);
    444    if(U_FAILURE(*status)){
    445        uprv_free(note);
    446        return;
    447    }
    448    for(i=0; i < count; i++){
    449        noteLen =  getAt(src->fChars,src->fLength, &note, capacity, i, UPC_NOTE, status);
    450        if(U_FAILURE(*status)){
    451            uprv_free(note);
    452            return;
    453        }
    454        if(noteLen > 0){
    455            write_tabs(out);
    456            print(note, noteLen,"<note>", "</note>", status);
    457        }
    458    }
    459    uprv_free(note);
    460 #else
    461 
    462    fprintf(stderr, "Warning: Could not output comments to XLIFF file. ICU has been built without RegularExpression support.\n");
    463 
    464 #endif /* UCONFIG_NO_REGULAR_EXPRESSIONS */
    465 
    466 }
    467 
    468 static void printAttribute(const char *name, const char *value, int32_t /*len*/)
    469 {
    470    write_utf8_file(out, UnicodeString(" "));
    471    write_utf8_file(out, UnicodeString(name));
    472    write_utf8_file(out, UnicodeString(" = \""));
    473    write_utf8_file(out, UnicodeString(value));
    474    write_utf8_file(out, UnicodeString("\""));
    475 }
    476 
    477 #if UCONFIG_NO_REGULAR_EXPRESSIONS==0 /* donot compile when no RegularExpressions are available */
    478 static void printAttribute(const char *name, const UnicodeString value, int32_t /*len*/)
    479 {
    480    write_utf8_file(out, UnicodeString(" "));
    481    write_utf8_file(out, UnicodeString(name));
    482    write_utf8_file(out, UnicodeString(" = \""));
    483    write_utf8_file(out, value);
    484    write_utf8_file(out, UnicodeString("\""));
    485 }
    486 #endif
    487 
    488 static void
    489 printComments(struct UString *src, const char *resName, UBool printTranslate, UErrorCode *status){
    490 
    491 #if UCONFIG_NO_REGULAR_EXPRESSIONS==0 /* donot compile when no RegularExpressions are available */
    492 
    493    if(status==nullptr || U_FAILURE(*status)){
    494        return;
    495    }
    496 
    497    int32_t capacity = src->fLength + 1;
    498    char* buf = nullptr;
    499    int32_t bufLen = 0;
    500    char16_t* desc = static_cast<char16_t*>(uprv_malloc(U_SIZEOF_UCHAR * capacity));
    501    char16_t* trans = static_cast<char16_t*>(uprv_malloc(U_SIZEOF_UCHAR * capacity));
    502 
    503    int32_t descLen = 0, transLen=0;
    504    if(desc==nullptr || trans==nullptr){
    505        *status = U_MEMORY_ALLOCATION_ERROR;
    506        uprv_free(desc);
    507        uprv_free(trans);
    508        return;
    509    }
    510    // TODO: make src const, stop modifying it in-place, make printContainer() take const resource, etc.
    511    src->fLength = removeCmtText(src->fChars, src->fLength, status);
    512    descLen  = getDescription(src->fChars,src->fLength, &desc, capacity, status);
    513    transLen = getTranslate(src->fChars,src->fLength, &trans, capacity, status);
    514 
    515    /* first print translate attribute */
    516    if(transLen > 0){
    517        if(printTranslate){
    518            /* print translate attribute */
    519            buf = convertAndEscape(&buf, 0, &bufLen, trans, transLen, status);
    520            if(U_SUCCESS(*status)){
    521                printAttribute("translate", UnicodeString(buf, bufLen, "UTF-8"), bufLen);
    522                write_utf8_file(out,UnicodeString(">\n"));
    523            }
    524        }else if(getShowWarning()){
    525            fprintf(stderr, "Warning: Translate attribute for resource %s cannot be set. XLIFF prohibits it.\n", resName);
    526            /* no translate attribute .. just close the tag */
    527            write_utf8_file(out,UnicodeString(">\n"));
    528        }
    529    }else{
    530        /* no translate attribute .. just close the tag */
    531        write_utf8_file(out,UnicodeString(">\n"));
    532    }
    533 
    534    if(descLen > 0){
    535        write_tabs(out);
    536        print(desc, descLen, "<!--", "-->", status);
    537    }
    538 
    539    uprv_free(desc);
    540    uprv_free(trans);
    541 #else
    542 
    543    fprintf(stderr, "Warning: Could not output comments to XLIFF file. ICU has been built without RegularExpression support.\n");
    544 
    545 #endif /* UCONFIG_NO_REGULAR_EXPRESSIONS */
    546 
    547 }
    548 
    549 /*
    550 * Print out a containing element, like:
    551 * <trans-unit id = "blah" resname = "blah" restype = "x-id-alias" translate = "no">
    552 * <group id "calendar_gregorian" resname = "gregorian" restype = "x-icu-array">
    553 */
    554 static char *printContainer(SResource *res, const char *container, const char *restype, const char *mimetype, const char *id, UErrorCode *status)
    555 {
    556    const char *resname = nullptr;
    557    char *sid = nullptr;
    558 
    559    write_tabs(out);
    560 
    561    resname = res->getKeyString(srBundle);
    562    if (resname != nullptr && *resname != 0) {
    563        sid = getID(id, resname, sid);
    564    } else {
    565        sid = getID(id, nullptr, sid);
    566    }
    567 
    568    write_utf8_file(out, UnicodeString("<"));
    569    write_utf8_file(out, UnicodeString(container));
    570    printAttribute("id", sid, static_cast<int32_t>(uprv_strlen(sid)));
    571 
    572    if (resname != nullptr) {
    573        printAttribute("resname", resname, static_cast<int32_t>(uprv_strlen(resname)));
    574    }
    575 
    576    if (mimetype != nullptr) {
    577        printAttribute("mime-type", mimetype, static_cast<int32_t>(uprv_strlen(mimetype)));
    578    }
    579 
    580    if (restype != nullptr) {
    581        printAttribute("restype", restype, static_cast<int32_t>(uprv_strlen(restype)));
    582    }
    583 
    584    tabCount += 1;
    585    if (res->fComment.fLength > 0) {
    586        /* printComments will print the closing ">\n" */
    587        printComments(&res->fComment, resname, true, status);
    588    } else {
    589        write_utf8_file(out, UnicodeString(">\n"));
    590    }
    591 
    592    return sid;
    593 }
    594 
    595 /* Writing Functions */
    596 
    597 static const char *trans_unit = "trans-unit";
    598 static const char *close_trans_unit = "</trans-unit>\n";
    599 static const char *source = "<source>";
    600 static const char *close_source = "</source>\n";
    601 static const char *group = "group";
    602 static const char *close_group = "</group>\n";
    603 
    604 static const char *bin_unit = "bin-unit";
    605 static const char *close_bin_unit = "</bin-unit>\n";
    606 static const char *bin_source = "<bin-source>\n";
    607 static const char *close_bin_source = "</bin-source>\n";
    608 static const char *external_file = "<external-file";
    609 /*static const char *close_external_file = "</external-file>\n";*/
    610 static const char *internal_file = "<internal-file";
    611 static const char *close_internal_file = "</internal-file>\n";
    612 
    613 static const char *application_mimetype = "application"; /* add "/octet-stream"? */
    614 
    615 static const char *alias_restype     = "x-icu-alias";
    616 static const char *array_restype     = "x-icu-array";
    617 static const char *binary_restype    = "x-icu-binary";
    618 static const char *integer_restype   = "x-icu-integer";
    619 static const char *intvector_restype = "x-icu-intvector";
    620 static const char *table_restype     = "x-icu-table";
    621 
    622 static void
    623 string_write_xml(StringResource *res, const char* id, const char* /*language*/, UErrorCode *status) {
    624 
    625    char *sid = nullptr;
    626    char* buf = nullptr;
    627    int32_t bufLen = 0;
    628 
    629    if(status==nullptr || U_FAILURE(*status)){
    630        return;
    631    }
    632 
    633    sid = printContainer(res, trans_unit, nullptr, nullptr, id, status);
    634 
    635    write_tabs(out);
    636 
    637    write_utf8_file(out, UnicodeString(source));
    638 
    639    buf = convertAndEscape(&buf, 0, &bufLen, res->getBuffer(), res->length(), status);
    640 
    641    if (U_FAILURE(*status)) {
    642        uprv_free(buf);
    643        uprv_free(sid);
    644        return;
    645    }
    646 
    647    write_utf8_file(out, UnicodeString(buf, bufLen, "UTF-8"));
    648    write_utf8_file(out, UnicodeString(close_source));
    649 
    650    printNoteElements(&res->fComment, status);
    651 
    652    tabCount -= 1;
    653    write_tabs(out);
    654 
    655    write_utf8_file(out, UnicodeString(close_trans_unit));
    656 
    657    uprv_free(buf);
    658    uprv_free(sid);
    659 }
    660 
    661 static void
    662 alias_write_xml(AliasResource *res, const char* id, const char* /*language*/, UErrorCode *status) {
    663    char *sid = nullptr;
    664    char* buf = nullptr;
    665    int32_t bufLen=0;
    666 
    667    sid = printContainer(res, trans_unit, alias_restype, nullptr, id, status);
    668 
    669    write_tabs(out);
    670 
    671    write_utf8_file(out, UnicodeString(source));
    672 
    673    buf = convertAndEscape(&buf, 0, &bufLen, res->getBuffer(), res->length(), status);
    674 
    675    if(U_FAILURE(*status)){
    676        uprv_free(buf);
    677        uprv_free(sid);
    678        return;
    679    }
    680    write_utf8_file(out, UnicodeString(buf, bufLen, "UTF-8"));
    681    write_utf8_file(out, UnicodeString(close_source));
    682 
    683    printNoteElements(&res->fComment, status);
    684 
    685    tabCount -= 1;
    686    write_tabs(out);
    687 
    688    write_utf8_file(out, UnicodeString(close_trans_unit));
    689 
    690    uprv_free(buf);
    691    uprv_free(sid);
    692 }
    693 
    694 static void
    695 array_write_xml(ArrayResource *res, const char* id, const char* language, UErrorCode *status) {
    696    char* sid = nullptr;
    697    int index = 0;
    698 
    699    struct SResource *current = nullptr;
    700 
    701    sid = printContainer(res, group, array_restype, nullptr, id, status);
    702 
    703    current = res->fFirst;
    704 
    705    while (current != nullptr) {
    706        char c[256] = {0};
    707        char* subId = nullptr;
    708 
    709        itostr(c, index, 10, 0);
    710        index += 1;
    711        subId = getID(sid, c, subId);
    712 
    713        res_write_xml(current, subId, language, false, status);
    714        uprv_free(subId);
    715        subId = nullptr;
    716 
    717        if(U_FAILURE(*status)){
    718            uprv_free(sid);
    719            return;
    720        }
    721 
    722        current = current->fNext;
    723    }
    724 
    725    tabCount -= 1;
    726    write_tabs(out);
    727    write_utf8_file(out, UnicodeString(close_group));
    728 
    729    uprv_free(sid);
    730 }
    731 
    732 static void
    733 intvector_write_xml(IntVectorResource *res, const char* id, const char* /*language*/, UErrorCode *status) {
    734    char* sid = nullptr;
    735    char* ivd = nullptr;
    736    uint32_t i=0;
    737    uint32_t len=0;
    738    char buf[256] = {'0'};
    739 
    740    sid = printContainer(res, group, intvector_restype, nullptr, id, status);
    741 
    742    for(i = 0; i < res->fCount; i += 1) {
    743        char c[256] = {0};
    744 
    745        itostr(c, i, 10, 0);
    746        ivd = getID(sid, c, ivd);
    747        len = itostr(buf, res->fArray[i], 10, 0);
    748 
    749        write_tabs(out);
    750        write_utf8_file(out, UnicodeString("<"));
    751        write_utf8_file(out, UnicodeString(trans_unit));
    752 
    753        printAttribute("id", ivd, static_cast<int32_t>(uprv_strlen(ivd)));
    754        printAttribute("restype", integer_restype, static_cast<int32_t>(strlen(integer_restype)));
    755 
    756        write_utf8_file(out, UnicodeString(">\n"));
    757 
    758        tabCount += 1;
    759        write_tabs(out);
    760        write_utf8_file(out, UnicodeString(source));
    761 
    762        write_utf8_file(out, UnicodeString(buf, len));
    763 
    764        write_utf8_file(out, UnicodeString(close_source));
    765        tabCount -= 1;
    766        write_tabs(out);
    767        write_utf8_file(out, UnicodeString(close_trans_unit));
    768 
    769        uprv_free(ivd);
    770        ivd = nullptr;
    771    }
    772 
    773    tabCount -= 1;
    774    write_tabs(out);
    775 
    776    write_utf8_file(out, UnicodeString(close_group));
    777    uprv_free(sid);
    778    sid = nullptr;
    779 }
    780 
    781 static void
    782 int_write_xml(IntResource *res, const char* id, const char* /*language*/, UErrorCode *status) {
    783    char* sid = nullptr;
    784    char buf[256] = {0};
    785    uint32_t len = 0;
    786 
    787    sid = printContainer(res, trans_unit, integer_restype, nullptr, id, status);
    788 
    789    write_tabs(out);
    790 
    791    write_utf8_file(out, UnicodeString(source));
    792 
    793    len = itostr(buf, res->fValue, 10, 0);
    794    write_utf8_file(out, UnicodeString(buf, len));
    795 
    796    write_utf8_file(out, UnicodeString(close_source));
    797 
    798    printNoteElements(&res->fComment, status);
    799 
    800    tabCount -= 1;
    801    write_tabs(out);
    802 
    803    write_utf8_file(out, UnicodeString(close_trans_unit));
    804 
    805    uprv_free(sid);
    806    sid = nullptr;
    807 }
    808 
    809 static void
    810 bin_write_xml(BinaryResource *res, const char* id, const char* /*language*/, UErrorCode *status) {
    811    const char* m_type = application_mimetype;
    812    char* sid = nullptr;
    813    uint32_t crc = 0xFFFFFFFF;
    814 
    815    char fileName[1024] ={0};
    816    int32_t tLen = outDir == nullptr ? 0 : static_cast<int32_t>(uprv_strlen(outDir));
    817    char* fn = static_cast<char*>(uprv_malloc(sizeof(char) * (tLen + 1024 +
    818                                                    (res->fFileName !=nullptr ?
    819                                                    uprv_strlen(res->fFileName) :0))));
    820    const char* ext = nullptr;
    821 
    822    char* f = nullptr;
    823 
    824    fn[0]=0;
    825 
    826    if(res->fFileName != nullptr){
    827        uprv_strcpy(fileName, res->fFileName);
    828        f = uprv_strrchr(fileName, '\\');
    829 
    830        if (f != nullptr) {
    831            f++;
    832        } else {
    833            f = fileName;
    834        }
    835 
    836        ext = uprv_strrchr(fileName, '.');
    837 
    838        if (ext == nullptr) {
    839            fprintf(stderr, "Error: %s is an unknown binary filename type.\n", fileName);
    840            exit(U_ILLEGAL_ARGUMENT_ERROR);
    841        }
    842 
    843        if(uprv_strcmp(ext, ".jpg")==0 || uprv_strcmp(ext, ".jpeg")==0 || uprv_strcmp(ext, ".gif")==0 ){
    844            m_type = "image";
    845        } else if(uprv_strcmp(ext, ".wav")==0 || uprv_strcmp(ext, ".au")==0 ){
    846            m_type = "audio";
    847        } else if(uprv_strcmp(ext, ".avi")==0 || uprv_strcmp(ext, ".mpg")==0 || uprv_strcmp(ext, ".mpeg")==0){
    848            m_type = "video";
    849        } else if(uprv_strcmp(ext, ".txt")==0 || uprv_strcmp(ext, ".text")==0){
    850            m_type = "text";
    851        }
    852 
    853        sid = printContainer(res, bin_unit, binary_restype, m_type, id, status);
    854 
    855        write_tabs(out);
    856 
    857        write_utf8_file(out, UnicodeString(bin_source));
    858 
    859        tabCount+= 1;
    860        write_tabs(out);
    861 
    862        write_utf8_file(out, UnicodeString(external_file));
    863        printAttribute("href", f, static_cast<int32_t>(uprv_strlen(f)));
    864        write_utf8_file(out, UnicodeString("/>\n"));
    865        tabCount -= 1;
    866        write_tabs(out);
    867 
    868        write_utf8_file(out, UnicodeString(close_bin_source));
    869 
    870        printNoteElements(&res->fComment, status);
    871        tabCount -= 1;
    872        write_tabs(out);
    873        write_utf8_file(out, UnicodeString(close_bin_unit));
    874    } else {
    875        char temp[256] = {0};
    876        uint32_t i = 0;
    877        int32_t len=0;
    878 
    879        sid = printContainer(res, bin_unit, binary_restype, m_type, id, status);
    880 
    881        write_tabs(out);
    882        write_utf8_file(out, UnicodeString(bin_source));
    883 
    884        tabCount += 1;
    885        write_tabs(out);
    886 
    887        write_utf8_file(out, UnicodeString(internal_file));
    888        printAttribute("form", application_mimetype, static_cast<int32_t>(uprv_strlen(application_mimetype)));
    889 
    890        while(i <res->fLength){
    891            len = itostr(temp, res->fData[i], 16, 2);
    892            crc = computeCRC(temp, len, crc);
    893            i++;
    894        }
    895 
    896        len = itostr(temp, crc, 10, 0);
    897        printAttribute("crc", temp, len);
    898 
    899        write_utf8_file(out, UnicodeString(">"));
    900 
    901        i = 0;
    902        while(i <res->fLength){
    903            len = itostr(temp, res->fData[i], 16, 2);
    904            write_utf8_file(out, UnicodeString(temp));
    905            i += 1;
    906        }
    907 
    908        write_utf8_file(out, UnicodeString(close_internal_file));
    909 
    910        tabCount -= 2;
    911        write_tabs(out);
    912 
    913        write_utf8_file(out, UnicodeString(close_bin_source));
    914        printNoteElements(&res->fComment, status);
    915 
    916        tabCount -= 1;
    917        write_tabs(out);
    918        write_utf8_file(out, UnicodeString(close_bin_unit));
    919 
    920        uprv_free(sid);
    921        sid = nullptr;
    922    }
    923 
    924    uprv_free(fn);
    925 }
    926 
    927 
    928 
    929 static void
    930 table_write_xml(TableResource *res, const char* id, const char* language, UBool isTopLevel, UErrorCode *status) {
    931 
    932    struct SResource *current = nullptr;
    933    char* sid = nullptr;
    934 
    935    if (U_FAILURE(*status)) {
    936        return ;
    937    }
    938 
    939    sid = printContainer(res, group, table_restype, nullptr, id, status);
    940 
    941    if(isTopLevel) {
    942        sid[0] = '\0';
    943    }
    944 
    945    current = res->fFirst;
    946 
    947    while (current != nullptr) {
    948        res_write_xml(current, sid, language, false, status);
    949 
    950        if(U_FAILURE(*status)){
    951            uprv_free(sid);
    952            return;
    953        }
    954 
    955        current = current->fNext;
    956    }
    957 
    958    tabCount -= 1;
    959    write_tabs(out);
    960 
    961    write_utf8_file(out, UnicodeString(close_group));
    962 
    963    uprv_free(sid);
    964    sid = nullptr;
    965 }
    966 
    967 void
    968 res_write_xml(struct SResource *res, const char* id,  const char* language, UBool isTopLevel, UErrorCode *status) {
    969 
    970    if (U_FAILURE(*status)) {
    971        return ;
    972    }
    973 
    974    if (res != nullptr) {
    975        switch (res->fType) {
    976        case URES_STRING:
    977             string_write_xml    (static_cast<StringResource *>(res), id, language, status);
    978             return;
    979 
    980        case URES_ALIAS:
    981             alias_write_xml     (static_cast<AliasResource *>(res), id, language, status);
    982             return;
    983 
    984        case URES_INT_VECTOR:
    985             intvector_write_xml (static_cast<IntVectorResource *>(res), id, language, status);
    986             return;
    987 
    988        case URES_BINARY:
    989             bin_write_xml       (static_cast<BinaryResource *>(res), id, language, status);
    990             return;
    991 
    992        case URES_INT:
    993             int_write_xml       (static_cast<IntResource *>(res), id, language, status);
    994             return;
    995 
    996        case URES_ARRAY:
    997             array_write_xml     (static_cast<ArrayResource *>(res), id, language, status);
    998             return;
    999 
   1000        case URES_TABLE:
   1001             table_write_xml     (static_cast<TableResource *>(res), id, language, isTopLevel, status);
   1002             return;
   1003 
   1004        default:
   1005            break;
   1006        }
   1007    }
   1008 
   1009    *status = U_INTERNAL_PROGRAM_ERROR;
   1010 }
   1011 
   1012 void
   1013 bundle_write_xml(struct SRBRoot *bundle, const char *outputDir,const char* outputEnc, const char* filename,
   1014                  char *writtenFilename, int writtenFilenameLen,
   1015                  const char* language, const char* outFileName, UErrorCode *status) {
   1016 
   1017    char* xmlfileName = nullptr;
   1018    char* outputFileName = nullptr;
   1019    char* originalFileName = nullptr;
   1020    const char* fileStart = "<file xml:space = \"preserve\" source-language = \"";
   1021    const char* file1 = "\" datatype = \"x-icu-resource-bundle\" ";
   1022    const char* file2 = "original = \"";
   1023    const char* file4 = "\" date = \"";
   1024    const char* fileEnd = "</file>\n";
   1025    const char* headerStart = "<header>\n";
   1026    const char* headerEnd = "</header>\n";
   1027    const char* bodyStart = "<body>\n";
   1028    const char* bodyEnd = "</body>\n";
   1029 
   1030    const char *tool_start = "<tool";
   1031    const char *tool_id = "genrb-" GENRB_VERSION "-icu-" U_ICU_VERSION;
   1032    const char *tool_name = "genrb";
   1033 
   1034    char* temp = nullptr;
   1035    char* lang = nullptr;
   1036    const char* pos = nullptr;
   1037    int32_t first, index;
   1038    time_t currTime;
   1039    char timeBuf[128];
   1040 
   1041    outDir = outputDir;
   1042 
   1043    srBundle = bundle;
   1044 
   1045    pos = uprv_strrchr(filename, '\\');
   1046    if(pos != nullptr) {
   1047        first = static_cast<int32_t>(pos - filename + 1);
   1048    } else {
   1049        first = 0;
   1050    }
   1051    index = static_cast<int32_t>(uprv_strlen(filename) - uprv_strlen(textExt) - first);
   1052    originalFileName = static_cast<char*>(uprv_malloc(sizeof(char) * index + 1));
   1053    uprv_memset(originalFileName, 0, sizeof(char)*index+1);
   1054    uprv_strncpy(originalFileName, filename + first, index);
   1055 
   1056    if(uprv_strcmp(originalFileName, srBundle->fLocale) != 0) {
   1057        fprintf(stdout, "Warning: The file name is not same as the resource name!\n");
   1058    }
   1059 
   1060    temp = originalFileName;
   1061    originalFileName = static_cast<char*>(uprv_malloc(sizeof(char) * (uprv_strlen(temp) + uprv_strlen(textExt)) + 1));
   1062    uprv_memset(originalFileName, 0, sizeof(char)* (uprv_strlen(temp)+uprv_strlen(textExt)) + 1);
   1063    uprv_strcat(originalFileName, temp);
   1064    uprv_strcat(originalFileName, textExt);
   1065    uprv_free(temp);
   1066    temp = nullptr;
   1067 
   1068 
   1069    if (language == nullptr) {
   1070 /*        lang = parseFilename(filename, lang);
   1071        if (lang == nullptr) {*/
   1072            /* now check if locale name is valid or not
   1073             * this is to cater for situation where
   1074             * pegasusServer.txt contains
   1075             *
   1076             * en{
   1077             *      ..
   1078             * }
   1079             */
   1080             lang = parseFilename(srBundle->fLocale, lang);
   1081             /*
   1082              * Neither  the file name nor the table name inside the
   1083              * txt file contain a valid country and language codes
   1084              * throw an error.
   1085              * pegasusServer.txt contains
   1086              *
   1087              * testelements{
   1088              *     ....
   1089              * }
   1090              */
   1091             if(lang==nullptr){
   1092                 fprintf(stderr, "Error: The file name and table name do not contain a valid language code. Please use -l option to specify it.\n");
   1093                 exit(U_ILLEGAL_ARGUMENT_ERROR);
   1094             }
   1095       /* }*/
   1096    } else {
   1097        lang = static_cast<char*>(uprv_malloc(sizeof(char) * uprv_strlen(language) + 1));
   1098        uprv_memset(lang, 0, sizeof(char)*uprv_strlen(language) +1);
   1099        uprv_strcpy(lang, language);
   1100    }
   1101 
   1102    if(outFileName) {
   1103        outputFileName = static_cast<char*>(uprv_malloc(sizeof(char) * uprv_strlen(outFileName) + 1));
   1104        uprv_memset(outputFileName, 0, sizeof(char)*uprv_strlen(outFileName) + 1);
   1105        uprv_strcpy(outputFileName,outFileName);
   1106    } else {
   1107        outputFileName = static_cast<char*>(uprv_malloc(sizeof(char) * uprv_strlen(srBundle->fLocale) + 1));
   1108        uprv_memset(outputFileName, 0, sizeof(char)*uprv_strlen(srBundle->fLocale) + 1);
   1109        uprv_strcpy(outputFileName,srBundle->fLocale);
   1110    }
   1111 
   1112    if(outputDir) {
   1113        xmlfileName = static_cast<char*>(uprv_malloc(sizeof(char) * (uprv_strlen(outputDir) + uprv_strlen(outputFileName) + uprv_strlen(xliffExt) + 1) + 1));
   1114        uprv_memset(xmlfileName, 0, sizeof(char)*(uprv_strlen(outputDir)+ uprv_strlen(outputFileName) + uprv_strlen(xliffExt) + 1) +1);
   1115    } else {
   1116        xmlfileName = static_cast<char*>(uprv_malloc(sizeof(char) * (uprv_strlen(outputFileName) + uprv_strlen(xliffExt)) + 1));
   1117        uprv_memset(xmlfileName, 0, sizeof(char)*(uprv_strlen(outputFileName) + uprv_strlen(xliffExt)) +1);
   1118    }
   1119 
   1120    if(outputDir){
   1121        uprv_strcpy(xmlfileName, outputDir);
   1122        if(outputDir[uprv_strlen(outputDir)-1] !=U_FILE_SEP_CHAR){
   1123            uprv_strcat(xmlfileName,U_FILE_SEP_STRING);
   1124        }
   1125    }
   1126    uprv_strcat(xmlfileName,outputFileName);
   1127    uprv_strcat(xmlfileName,xliffExt);
   1128 
   1129    if (writtenFilename) {
   1130        uprv_strncpy(writtenFilename, xmlfileName, writtenFilenameLen);
   1131    }
   1132 
   1133    if (U_FAILURE(*status)) {
   1134        goto cleanup_bundle_write_xml;
   1135    }
   1136 
   1137    out= T_FileStream_open(xmlfileName,"w");
   1138 
   1139    if(out==nullptr){
   1140        *status = U_FILE_ACCESS_ERROR;
   1141        goto cleanup_bundle_write_xml;
   1142    }
   1143    write_utf8_file(out, UnicodeString(xmlHeader));
   1144 
   1145    if(outputEnc && *outputEnc!='\0'){
   1146        /* store the output encoding */
   1147        enc = outputEnc;
   1148        conv=ucnv_open(enc,status);
   1149        if(U_FAILURE(*status)){
   1150            goto cleanup_bundle_write_xml;
   1151        }
   1152    }
   1153    write_utf8_file(out, UnicodeString(bundleStart));
   1154    write_tabs(out);
   1155    write_utf8_file(out, UnicodeString(fileStart));
   1156    /* check if lang and language are the same */
   1157    if(language != nullptr && uprv_strcmp(lang, srBundle->fLocale)!=0){
   1158        fprintf(stderr,"Warning: The top level tag in the resource and language specified are not the same. Please check the input.\n");
   1159    }
   1160    write_utf8_file(out, UnicodeString(lang));
   1161    write_utf8_file(out, UnicodeString(file1));
   1162    write_utf8_file(out, UnicodeString(file2));
   1163    write_utf8_file(out, UnicodeString(originalFileName));
   1164    write_utf8_file(out, UnicodeString(file4));
   1165 
   1166    time(&currTime);
   1167    strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%dT%H:%M:%SZ", gmtime(&currTime));
   1168    write_utf8_file(out, UnicodeString(timeBuf));
   1169    write_utf8_file(out, UnicodeString("\">\n"));
   1170 
   1171    tabCount += 1;
   1172    write_tabs(out);
   1173    write_utf8_file(out, UnicodeString(headerStart));
   1174 
   1175    tabCount += 1;
   1176    write_tabs(out);
   1177 
   1178    write_utf8_file(out, UnicodeString(tool_start));
   1179    printAttribute("tool-id", tool_id, static_cast<int32_t>(uprv_strlen(tool_id)));
   1180    printAttribute("tool-name", tool_name, static_cast<int32_t>(uprv_strlen(tool_name)));
   1181    write_utf8_file(out, UnicodeString("/>\n"));
   1182 
   1183    tabCount -= 1;
   1184    write_tabs(out);
   1185 
   1186    write_utf8_file(out, UnicodeString(headerEnd));
   1187 
   1188    write_tabs(out);
   1189    tabCount += 1;
   1190 
   1191    write_utf8_file(out, UnicodeString(bodyStart));
   1192 
   1193 
   1194    res_write_xml(bundle->fRoot, bundle->fLocale, lang, true, status);
   1195 
   1196    tabCount -= 1;
   1197    write_tabs(out);
   1198 
   1199    write_utf8_file(out, UnicodeString(bodyEnd));
   1200    tabCount--;
   1201    write_tabs(out);
   1202    write_utf8_file(out, UnicodeString(fileEnd));
   1203    tabCount--;
   1204    write_tabs(out);
   1205    write_utf8_file(out, UnicodeString(bundleEnd));
   1206    T_FileStream_close(out);
   1207 
   1208    ucnv_close(conv);
   1209 
   1210 cleanup_bundle_write_xml:
   1211    uprv_free(originalFileName);
   1212    uprv_free(lang);
   1213    if(xmlfileName != nullptr) {
   1214        uprv_free(xmlfileName);
   1215    }
   1216    if(outputFileName != nullptr){
   1217        uprv_free(outputFileName);
   1218    }
   1219 }