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