Home | History | Annotate | Download | only in toolutil
      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) 2005-2012, International Business Machines
      7 *   Corporation and others.  All Rights Reserved.
      8 *
      9 *******************************************************************************
     10 *   file name:  writesrc.c
     11 *   encoding:   UTF-8
     12 *   tab size:   8 (not used)
     13 *   indentation:4
     14 *
     15 *   created on: 2005apr23
     16 *   created by: Markus W. Scherer
     17 *
     18 *   Helper functions for writing source code for data.
     19 */
     20 
     21 #include <stdio.h>
     22 #include <time.h>
     23 #include "unicode/utypes.h"
     24 #include "unicode/putil.h"
     25 #include "utrie2.h"
     26 #include "cstring.h"
     27 #include "writesrc.h"
     28 
     29 static FILE *
     30 usrc_createWithHeader(const char *path, const char *filename,
     31                       const char *generator, const char *header) {
     32     char buffer[1024];
     33     const char *p;
     34     char *q;
     35     FILE *f;
     36     char c;
     37 
     38     if(path==NULL) {
     39         p=filename;
     40     } else {
     41         /* concatenate path and filename, with U_FILE_SEP_CHAR in between if necessary */
     42         uprv_strcpy(buffer, path);
     43         q=buffer+uprv_strlen(buffer);
     44         if(q>buffer && (c=*(q-1))!=U_FILE_SEP_CHAR && c!=U_FILE_ALT_SEP_CHAR) {
     45             *q++=U_FILE_SEP_CHAR;
     46         }
     47         uprv_strcpy(q, filename);
     48         p=buffer;
     49     }
     50 
     51     f=fopen(p, "w");
     52     if(f!=NULL) {
     53         const struct tm *lt;
     54         time_t t;
     55 
     56         time(&t);
     57         lt=localtime(&t);
     58         if(generator==NULL) {
     59             strftime(buffer, sizeof(buffer), "%Y-%m-%d", lt);
     60             fprintf(f, header, filename, buffer);
     61         } else {
     62             fprintf(f, header, filename, generator);
     63         }
     64     } else {
     65         fprintf(
     66             stderr,
     67             "usrc_create(%s, %s): unable to create file\n",
     68             path!=NULL ? path : "", filename);
     69     }
     70     return f;
     71 }
     72 
     73 U_CAPI FILE * U_EXPORT2
     74 usrc_create(const char *path, const char *filename, const char *generator) {
     75     // TODO: Add parameter for the first year this file was generated, not before 2016.
     76     static const char *header=
     77         "//  2016 and later: Unicode, Inc. and others.\n"
     78         "// License & terms of use: http://www.unicode.org/copyright.html\n"
     79         "//\n"
     80         "// Copyright (C) 1999-2016, International Business Machines\n"
     81         "// Corporation and others.  All Rights Reserved.\n"
     82         "//\n"
     83         "// file name: %s\n"
     84         "//\n"
     85         "// machine-generated by: %s\n"
     86         "\n\n";
     87     return usrc_createWithHeader(path, filename, generator, header);
     88 }
     89 
     90 U_CAPI FILE * U_EXPORT2
     91 usrc_createTextData(const char *path, const char *filename, const char *generator) {
     92     // TODO: Add parameter for the first year this file was generated, not before 2016.
     93     static const char *header=
     94         "# Copyright (C) 2016 and later: Unicode, Inc. and others.\n"
     95         "# License & terms of use: http://www.unicode.org/copyright.html\n"
     96         "# Copyright (C) 1999-2016, International Business Machines\n"
     97         "# Corporation and others.  All Rights Reserved.\n"
     98         "#\n"
     99         "# file name: %s\n"
    100         "#\n"
    101         "# machine-generated by: %s\n"
    102         "\n\n";
    103     return usrc_createWithHeader(path, filename, generator, header);
    104 }
    105 
    106 U_CAPI void U_EXPORT2
    107 usrc_writeArray(FILE *f,
    108                 const char *prefix,
    109                 const void *p, int32_t width, int32_t length,
    110                 const char *postfix) {
    111     const uint8_t *p8;
    112     const uint16_t *p16;
    113     const uint32_t *p32;
    114     uint32_t value;
    115     int32_t i, col;
    116 
    117     p8=NULL;
    118     p16=NULL;
    119     p32=NULL;
    120     switch(width) {
    121     case 8:
    122         p8=(const uint8_t *)p;
    123         break;
    124     case 16:
    125         p16=(const uint16_t *)p;
    126         break;
    127     case 32:
    128         p32=(const uint32_t *)p;
    129         break;
    130     default:
    131         fprintf(stderr, "usrc_writeArray(width=%ld) unrecognized width\n", (long)width);
    132         return;
    133     }
    134     if(prefix!=NULL) {
    135         fprintf(f, prefix, (long)length);
    136     }
    137     for(i=col=0; i<length; ++i, ++col) {
    138         if(i>0) {
    139             if(col<16) {
    140                 fputc(',', f);
    141             } else {
    142                 fputs(",\n", f);
    143                 col=0;
    144             }
    145         }
    146         switch(width) {
    147         case 8:
    148             value=p8[i];
    149             break;
    150         case 16:
    151             value=p16[i];
    152             break;
    153         case 32:
    154             value=p32[i];
    155             break;
    156         default:
    157             value=0; /* unreachable */
    158             break;
    159         }
    160         fprintf(f, value<=9 ? "%lu" : "0x%lx", (unsigned long)value);
    161     }
    162     if(postfix!=NULL) {
    163         fputs(postfix, f);
    164     }
    165 }
    166 
    167 U_CAPI void U_EXPORT2
    168 usrc_writeUTrie2Arrays(FILE *f,
    169                        const char *indexPrefix, const char *data32Prefix,
    170                        const UTrie2 *pTrie,
    171                        const char *postfix) {
    172     if(pTrie->data32==NULL) {
    173         /* 16-bit trie */
    174         usrc_writeArray(f, indexPrefix, pTrie->index, 16, pTrie->indexLength+pTrie->dataLength, postfix);
    175     } else {
    176         /* 32-bit trie */
    177         usrc_writeArray(f, indexPrefix, pTrie->index, 16, pTrie->indexLength, postfix);
    178         usrc_writeArray(f, data32Prefix, pTrie->data32, 32, pTrie->dataLength, postfix);
    179     }
    180 }
    181 
    182 U_CAPI void U_EXPORT2
    183 usrc_writeUTrie2Struct(FILE *f,
    184                        const char *prefix,
    185                        const UTrie2 *pTrie,
    186                        const char *indexName, const char *data32Name,
    187                        const char *postfix) {
    188     if(prefix!=NULL) {
    189         fputs(prefix, f);
    190     }
    191     if(pTrie->data32==NULL) {
    192         /* 16-bit trie */
    193         fprintf(
    194             f,
    195             "    %s,\n"         /* index */
    196             "    %s+%ld,\n"     /* data16 */
    197             "    NULL,\n",      /* data32 */
    198             indexName,
    199             indexName,
    200             (long)pTrie->indexLength);
    201     } else {
    202         /* 32-bit trie */
    203         fprintf(
    204             f,
    205             "    %s,\n"         /* index */
    206             "    NULL,\n"       /* data16 */
    207             "    %s,\n",        /* data32 */
    208             indexName,
    209             data32Name);
    210     }
    211     fprintf(
    212         f,
    213         "    %ld,\n"            /* indexLength */
    214         "    %ld,\n"            /* dataLength */
    215         "    0x%hx,\n"          /* index2NullOffset */
    216         "    0x%hx,\n"          /* dataNullOffset */
    217         "    0x%lx,\n"          /* initialValue */
    218         "    0x%lx,\n"          /* errorValue */
    219         "    0x%lx,\n"          /* highStart */
    220         "    0x%lx,\n"          /* highValueIndex */
    221         "    NULL, 0, FALSE, FALSE, 0, NULL\n",
    222         (long)pTrie->indexLength, (long)pTrie->dataLength,
    223         (short)pTrie->index2NullOffset, (short)pTrie->dataNullOffset,
    224         (long)pTrie->initialValue, (long)pTrie->errorValue,
    225         (long)pTrie->highStart, (long)pTrie->highValueIndex);
    226     if(postfix!=NULL) {
    227         fputs(postfix, f);
    228     }
    229 }
    230 
    231 U_CAPI void U_EXPORT2
    232 usrc_writeArrayOfMostlyInvChars(FILE *f,
    233                                 const char *prefix,
    234                                 const char *p, int32_t length,
    235                                 const char *postfix) {
    236     int32_t i, col;
    237     int prev2, prev, c;
    238 
    239     if(prefix!=NULL) {
    240         fprintf(f, prefix, (long)length);
    241     }
    242     prev2=prev=-1;
    243     for(i=col=0; i<length; ++i, ++col) {
    244         c=(uint8_t)p[i];
    245         if(i>0) {
    246             /* Break long lines. Try to break at interesting places, to minimize revision diffs. */
    247             if(
    248                 /* Very long line. */
    249                 col>=32 ||
    250                 /* Long line, break after terminating NUL. */
    251                 (col>=24 && prev2>=0x20 && prev==0) ||
    252                 /* Medium-long line, break before non-NUL, non-character byte. */
    253                 (col>=16 && (prev==0 || prev>=0x20) && 0<c && c<0x20)
    254             ) {
    255                 fputs(",\n", f);
    256                 col=0;
    257             } else {
    258                 fputc(',', f);
    259             }
    260         }
    261         fprintf(f, c<0x20 ? "%u" : "'%c'", c);
    262         prev2=prev;
    263         prev=c;
    264     }
    265     if(postfix!=NULL) {
    266         fputs(postfix, f);
    267     }
    268 }
    269