Imported Upstream version 58.1
[platform/upstream/icu.git] / source / tools / toolutil / writesrc.c
1 // Copyright (C) 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:   US-ASCII
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         "// Copyright (C) 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 }