]>
Commit | Line | Data |
---|---|---|
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 | } |