1 // © 2017 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 *******************************************************************************
5 *
6 * Copyright (C) 2004-2016, International Business Machines
7 * Corporation and others. All Rights Reserved.
8 *
9 *******************************************************************************
10 * file name: bidipropsbuilder.cpp (was genbidi/store.c)
11 * encoding: US-ASCII
12 * tab size: 8 (not used)
13 * indentation:4
14 *
15 * created on: 2004dec30
16 * created by: Markus W. Scherer
17 *
18 * Store Unicode bidi/shaping properties efficiently for
19 * random access.
20 */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include "unicode/utypes.h"
25 #include "unicode/uchar.h"
26 #include "unicode/uniset.h"
27 #include "cmemory.h"
28 #include "cstring.h"
29 #include "ppucd.h"
30 #include "uarrsort.h"
31 #include "unicode/udata.h"
32 #include "unewdata.h"
33 #include "utrie2.h"
34 #include "writesrc.h"
35 #include "ubidi_props.h"
36 #include "genprops.h"
37
38 /* Unicode bidi/shaping properties file format ---------------------------------
39
40 The file format prepared and written here contains several data
41 structures that store indexes or data.
42
43 Before the data contents described below, there are the headers required by
44 the udata API for loading ICU data. Especially, a UDataInfo structure
45 precedes the actual data. It contains platform properties values and the
46 file format version.
47
48 The following is a description of format version 2.2 .
49
50 The file contains the following structures:
51
52 const int32_t indexes[i0] with values i0, i1, ...:
53 (see UBIDI_IX_... constants for names of indexes)
54
55 i0 indexLength; -- length of indexes[] (UBIDI_IX_TOP)
56 i1 dataLength; -- length in bytes of the post-header data (incl. indexes[])
57 i2 trieSize; -- size in bytes of the bidi/shaping properties trie
58 i3 mirrorLength; -- length in uint32_t of the bidi mirroring array
59
60 i4 jgStart; -- first code point with Joining_Group data
61 i5 jgLimit; -- limit code point for Joining_Group data
62
63 -- i6, i7 new in format version 2.2:
64 i6 jgStart2; -- first code point with Joining_Group data, second range
65 i7 jgLimit2; -- limit code point for Joining_Group data, second range
66
67 i8..i14 reservedIndexes; -- reserved values; 0 for now
68
69 i15 maxValues; -- maximum code values for enumerated properties
70 bits 23..16 contain the max value for Joining_Group,
71 otherwise the bits are used like enum fields in the trie word
72
73 Serialized trie, see utrie2.h;
74
75 const uint32_t mirrors[mirrorLength];
76
77 const uint8_t jgArray[i5-i4]; -- (i5-i4)+(i7-i6) is always a multiple of 4
78 const uint8_t jgArray2[i7-i6]; -- new in format version 2.2
79
80 Trie data word:
81 Bits
82 15..13 signed delta to bidi mirroring code point
83 (add delta to input code point)
84 0 no such code point (source maps to itself)
85 -3..-1, 1..3 delta
86 -4 look in mirrors table
87 12 is mirrored
88 11 Bidi_Control
89 10 Join_Control
90 9.. 8 Bidi_Paired_Bracket_Type(bpt) -- new in format version 2.1
91 7.. 5 Joining_Type
92 4.. 0 BiDi category
93
94
95 Mirrors:
96 Stores some of the bidi mirroring data, where each code point maps to
97 at most one other.
98 Most code points do not have a mirroring code point; most that do have a signed
99 delta stored in the trie data value. Only those where the delta does not fit
100 into the trie data are stored in this table.
101
102 Logically, this is a two-column table with source and mirror code points.
103
104 Physically, the table is compressed by taking advantage of the fact that each
105 mirror code point is also a source code point
106 (each of them is a mirror of the other).
107 Therefore, both logical columns contain the same set of code points, which needs
108 to be stored only once.
109
110 The table stores source code points, and also for each the index of its mirror
111 code point in the same table, in a simple array of uint32_t.
112 Bits
113 31..21 index to mirror code point (unsigned)
114 20.. 0 source code point
115
116 The table is sorted by source code points.
117
118
119 Joining_Group array:
120 The Joining_Group values do not fit into the 16-bit trie, but the data is also
121 limited to a small range of code points (Arabic and Syriac) and not
122 well compressible.
123
124 The start and limit code points for the range are stored in the indexes[]
125 array, and the jgArray[] stores a byte for each of these code points,
126 containing the Joining_Group value.
127
128 All code points outside of this range have No_Joining_Group (0).
129
130 ICU 54 adds jgArray2[] for a second range.
131
132 --- Changes in format version 2.2 ---
133
134 Addition of second range for Joining_Group values (i6, i7),
135 for 10800..10FFF, including Unicode 7.0 10AC0..10AFF Manichaean.
136
137 --- Changes in format version 2.1 ---
138
139 Addition of Bidi_Paired_Bracket_Type(bpt) values.
140 (Trie data bits 9..8 were reserved.)
141
142 --- Changes in format version 2 ---
143
144 Change from UTrie to UTrie2.
145
146 ----------------------------------------------------------------------------- */
147
148 U_NAMESPACE_USE
149
150 /* UDataInfo cf. udata.h */
151 static UDataInfo dataInfo={
152 sizeof(UDataInfo),
153 0,
154
155 U_IS_BIG_ENDIAN,
156 U_CHARSET_FAMILY,
157 U_SIZEOF_UCHAR,
158 0,
159
160 /* dataFormat="BiDi" */
161 { UBIDI_FMT_0, UBIDI_FMT_1, UBIDI_FMT_2, UBIDI_FMT_3 },
162 { 2, 2, 0, 0 }, /* formatVersion */
163 { 6, 0, 0, 0 } /* dataVersion */
164 };
165
166 /* -------------------------------------------------------------------------- */
167
168 class BiDiPropsBuilder : public PropsBuilder {
169 public:
170 BiDiPropsBuilder(UErrorCode &errorCode);
171 virtual ~BiDiPropsBuilder();
172
173 virtual void setUnicodeVersion(const UVersionInfo version);
174 virtual void setProps(const UniProps &, const UnicodeSet &newValues, UErrorCode &errorCode);
175 virtual void build(UErrorCode &errorCode);
176 virtual void writeCSourceFile(const char *path, UErrorCode &errorCode);
177 virtual void writeBinaryData(const char *path, UBool withCopyright, UErrorCode &errorCode);
178
179 private:
180 int32_t encodeBidiMirroringGlyph(UChar32 src, UChar32 end, UChar32 mirror, UErrorCode &errorCode);
181 void makeMirror(UErrorCode &errorCode);
182
183 static const UChar32 MIN_JG_START=0x600;
184 static const UChar32 MAX_JG_LIMIT=0x8ff+1;
185 static const UChar32 MIN_JG_START2=0x10800;
186 static const UChar32 MAX_JG_LIMIT2=0x10fff+1;
187
188 UnicodeSet relevantProps;
189 UTrie2 *pTrie;
190 uint8_t jgArray[MAX_JG_LIMIT-MIN_JG_START];
191 uint8_t jgArray2[MAX_JG_LIMIT2-MIN_JG_START2];
192 uint32_t mirrors[UBIDI_MAX_MIRROR_INDEX+1][2];
193 int32_t mirrorTop;
194 };
195
BiDiPropsBuilder(UErrorCode & errorCode)196 BiDiPropsBuilder::BiDiPropsBuilder(UErrorCode &errorCode)
197 : pTrie(NULL),
198 mirrorTop(0) {
199 // This builder encodes the following properties.
200 relevantProps.
201 add(UCHAR_BIDI_CONTROL).
202 add(UCHAR_BIDI_MIRRORED).
203 add(UCHAR_BIDI_CLASS).
204 add(UCHAR_BIDI_MIRRORING_GLYPH).
205 add(UCHAR_JOIN_CONTROL).
206 add(UCHAR_JOINING_GROUP).
207 add(UCHAR_JOINING_TYPE);
208 pTrie=utrie2_open(0, 0, &errorCode);
209 if(U_FAILURE(errorCode)) {
210 fprintf(stderr, "genprops error: bidipropsbuilder utrie2_open() failed - %s\n",
211 u_errorName(errorCode));
212 }
213 uprv_memset(jgArray, U_JG_NO_JOINING_GROUP, sizeof(jgArray));
214 uprv_memset(jgArray2, U_JG_NO_JOINING_GROUP, sizeof(jgArray2));
215 }
216
~BiDiPropsBuilder()217 BiDiPropsBuilder::~BiDiPropsBuilder() {
218 utrie2_close(pTrie);
219 }
220
221 void
setUnicodeVersion(const UVersionInfo version)222 BiDiPropsBuilder::setUnicodeVersion(const UVersionInfo version) {
223 uprv_memcpy(dataInfo.dataVersion, version, 4);
224 }
225
226 /* bidi mirroring table ----------------------------------------------------- */
227
228 int32_t
encodeBidiMirroringGlyph(UChar32 src,UChar32 end,UChar32 mirror,UErrorCode & errorCode)229 BiDiPropsBuilder::encodeBidiMirroringGlyph(UChar32 src, UChar32 end, UChar32 mirror,
230 UErrorCode &errorCode) {
231 if(U_FAILURE(errorCode) || mirror<0) {
232 return 0;
233 }
234 if(src!=end) {
235 fprintf(stderr,
236 "genprops error: range U+%04lX..U+%04lX all with the same "
237 "Bidi_Mirroring_Glyph U+%04lX\n",
238 (long)src, (long)end, (long)mirror);
239 errorCode=U_ILLEGAL_ARGUMENT_ERROR;
240 return 0;
241 }
242 int32_t delta=mirror-src;
243 if(delta==0) {
244 return 0; /* mapping to self=no mapping */
245 }
246
247 if(delta<UBIDI_MIN_MIRROR_DELTA || UBIDI_MAX_MIRROR_DELTA<delta) {
248 /* delta does not fit into the trie properties value, store in the mirrors[] table */
249 if(mirrorTop==LENGTHOF(mirrors)) {
250 fprintf(stderr,
251 "genprops error: too many long-distance Bidi_Mirroring_Glyph mappings; "
252 "UBIDI_MAX_MIRROR_INDEX can only be increased by "
253 "redesigning the ubidi.icu data bit fields\n");
254 errorCode=U_BUFFER_OVERFLOW_ERROR;
255 return 0;
256 }
257
258 /* possible: search the table so far and see if src is already listed */
259
260 mirrors[mirrorTop][0]=(uint32_t)src;
261 mirrors[mirrorTop][1]=(uint32_t)mirror;
262 ++mirrorTop;
263
264 /* set an escape marker in src's properties */
265 delta=UBIDI_ESC_MIRROR_DELTA;
266 }
267 return delta;
268 }
269
270 void
setProps(const UniProps & props,const UnicodeSet & newValues,UErrorCode & errorCode)271 BiDiPropsBuilder::setProps(const UniProps &props, const UnicodeSet &newValues,
272 UErrorCode &errorCode) {
273 if(U_FAILURE(errorCode) || newValues.containsNone(relevantProps)) { return; }
274
275 UChar32 start=props.start;
276 UChar32 end=props.end;
277
278 // The runtime code relies on this invariant for returning both bmg and bpb
279 // from the same data.
280 int32_t bpt=props.getIntProp(UCHAR_BIDI_PAIRED_BRACKET_TYPE);
281 if(!(bpt==0 ? props.bpb==U_SENTINEL : props.bpb==props.bmg)) {
282 fprintf(stderr,
283 "genprops error: invariant not true: "
284 "if(bpt==None) then bpb=<none> else bpb=bmg\n");
285 return;
286 }
287 int32_t delta=encodeBidiMirroringGlyph(start, end, props.bmg, errorCode);
288 uint32_t value=(uint32_t)delta<<UBIDI_MIRROR_DELTA_SHIFT;
289 if(props.binProps[UCHAR_BIDI_MIRRORED]) {
290 value|=U_MASK(UBIDI_IS_MIRRORED_SHIFT);
291 }
292 if(props.binProps[UCHAR_BIDI_CONTROL]) {
293 value|=U_MASK(UBIDI_BIDI_CONTROL_SHIFT);
294 }
295 if(props.binProps[UCHAR_JOIN_CONTROL]) {
296 value|=U_MASK(UBIDI_JOIN_CONTROL_SHIFT);
297 }
298 value|=(uint32_t)bpt<<UBIDI_BPT_SHIFT;
299 value|=(uint32_t)props.getIntProp(UCHAR_JOINING_TYPE)<<UBIDI_JT_SHIFT;
300 value|=(uint32_t)props.getIntProp(UCHAR_BIDI_CLASS);
301 utrie2_setRange32(pTrie, start, end, value, TRUE, &errorCode);
302 if(U_FAILURE(errorCode)) {
303 fprintf(stderr, "genprops error: BiDiPropsBuilder utrie2_setRange32() failed - %s\n",
304 u_errorName(errorCode));
305 return;
306 }
307
308 // Store Joining_Group values from vector column 1 in simple byte arrays.
309 int32_t jg=props.getIntProp(UCHAR_JOINING_GROUP);
310 for(UChar32 c=start; c<=end; ++c) {
311 int32_t jgStart;
312 if(MIN_JG_START<=c && c<MAX_JG_LIMIT) {
313 jgArray[c-MIN_JG_START]=(uint8_t)jg;
314 } else if(MIN_JG_START2<=c && c<MAX_JG_LIMIT2) {
315 jgArray2[c-MIN_JG_START2]=(uint8_t)jg;
316 } else if(jg!=U_JG_NO_JOINING_GROUP) {
317 fprintf(stderr, "genprops error: Joining_Group for out-of-range code points U+%04lx..U+%04lx\n",
318 (long)start, (long)end);
319 errorCode=U_ILLEGAL_ARGUMENT_ERROR;
320 return;
321 }
322 }
323 }
324
325 /* generate output data ----------------------------------------------------- */
326
327 static int32_t U_CALLCONV
compareMirror(const void * context,const void * left,const void * right)328 compareMirror(const void *context, const void *left, const void *right) {
329 UChar32 l, r;
330
331 l=UBIDI_GET_MIRROR_CODE_POINT(((const uint32_t *)left)[0]);
332 r=UBIDI_GET_MIRROR_CODE_POINT(((const uint32_t *)right)[0]);
333 return l-r;
334 }
335
336 void
makeMirror(UErrorCode & errorCode)337 BiDiPropsBuilder::makeMirror(UErrorCode &errorCode) {
338 /* sort the mirroring table by source code points */
339 uprv_sortArray(mirrors, mirrorTop, 8,
340 compareMirror, NULL, FALSE, &errorCode);
341 if(U_FAILURE(errorCode)) { return; }
342
343 /*
344 * reduce the 2-column table to a single column
345 * by putting the index to the mirror entry into the source entry
346 *
347 * first:
348 * find each mirror code point in the source column and set each other's indexes
349 *
350 * second:
351 * reduce the table, combine the source code points with their indexes
352 * and store as a simple array of uint32_t
353 */
354 for(int32_t i=0; i<mirrorTop; ++i) {
355 uint32_t c=mirrors[i][1]; /* mirror code point */
356 if(c>0x1fffff) {
357 continue; /* this entry already has an index */
358 }
359
360 /* search for the mirror code point in the source column */
361 int32_t start, limit, step;
362 if(c<mirrors[i][0]) {
363 /* search before i */
364 start=i-1;
365 limit=-1;
366 step=-1;
367 } else {
368 start=i+1;
369 limit=mirrorTop;
370 step=1;
371 }
372
373 for(int32_t j=start;; j+=step) {
374 if(j==limit) {
375 fprintf(stderr,
376 "genprops error: bidi mirror does not roundtrip - %04lx->%04lx->?\n",
377 (long)mirrors[i][0], (long)mirrors[i][1]);
378 errorCode=U_ILLEGAL_ARGUMENT_ERROR;
379 }
380 if(c==mirrors[j][0]) {
381 /*
382 * found the mirror code point c in the source column,
383 * set both entries' indexes to each other
384 */
385 if(UBIDI_GET_MIRROR_CODE_POINT(mirrors[i][0])!=UBIDI_GET_MIRROR_CODE_POINT(mirrors[j][1])) {
386 /* roundtrip check fails */
387 fprintf(stderr,
388 "genprops error: bidi mirrors do not roundtrip - %04lx->%04lx->%04lx\n",
389 (long)mirrors[i][0], (long)mirrors[i][1], (long)mirrors[j][1]);
390 errorCode=U_ILLEGAL_ARGUMENT_ERROR;
391 } else {
392 mirrors[i][1]|=(uint32_t)j<<UBIDI_MIRROR_INDEX_SHIFT;
393 mirrors[j][1]|=(uint32_t)i<<UBIDI_MIRROR_INDEX_SHIFT;
394 }
395 break;
396 }
397 }
398 }
399
400 /* now the second step, the actual reduction of the table */
401 uint32_t *reducedMirror=mirrors[0];
402 for(int32_t i=0; i<mirrorTop; ++i) {
403 reducedMirror[i]=mirrors[i][0]|(mirrors[i][1]&~0x1fffff);
404 }
405 }
406
407 static int32_t indexes[UBIDI_IX_TOP]={
408 UBIDI_IX_TOP, 0, 0, 0,
409 0, 0, 0, 0,
410 0, 0, 0, 0,
411 0, 0, 0, 0
412 };
413
414 static uint8_t trieBlock[40000];
415 static int32_t trieSize;
416
417 void
build(UErrorCode & errorCode)418 BiDiPropsBuilder::build(UErrorCode &errorCode) {
419 makeMirror(errorCode);
420 if(U_FAILURE(errorCode)) { return; }
421
422 utrie2_freeze(pTrie, UTRIE2_16_VALUE_BITS, &errorCode);
423 trieSize=utrie2_serialize(pTrie, trieBlock, sizeof(trieBlock), &errorCode);
424 if(U_FAILURE(errorCode)) {
425 fprintf(stderr, "genprops error: utrie2_freeze()+utrie2_serialize() failed: %s (length %ld)\n",
426 u_errorName(errorCode), (long)trieSize);
427 return;
428 }
429
430 // Finish jgArray & jgArray2.
431 UChar32 jgStart; // First code point with a Joining_Group, first range.
432 UChar32 jgLimit; // One past the last one.
433 // Find the end of the range first, so that if it's empty we
434 // get jgStart=jgLimit=MIN_JG_START.
435 for(jgLimit=MAX_JG_LIMIT;
436 MIN_JG_START<jgLimit && jgArray[jgLimit-MIN_JG_START-1]==U_JG_NO_JOINING_GROUP;
437 --jgLimit) {}
438 for(jgStart=MIN_JG_START;
439 jgStart<jgLimit && jgArray[jgStart-MIN_JG_START]==U_JG_NO_JOINING_GROUP;
440 ++jgStart) {}
441
442 UChar32 jgStart2; // First code point with a Joining_Group, second range.
443 UChar32 jgLimit2; // One past the last one.
444 for(jgLimit2=MAX_JG_LIMIT2;
445 MIN_JG_START2<jgLimit2 && jgArray2[jgLimit2-MIN_JG_START2-1]==U_JG_NO_JOINING_GROUP;
446 --jgLimit2) {}
447 for(jgStart2=MIN_JG_START2;
448 jgStart2<jgLimit2 && jgArray2[jgStart2-MIN_JG_START2]==U_JG_NO_JOINING_GROUP;
449 ++jgStart2) {}
450
451 // Pad the total Joining_Group arrays length to a multiple of 4.
452 // Prefer rounding down starts before rounding up limits
453 // so that we are guaranteed not to increase the limits beyond
454 // the end of the arrays' code point ranges.
455 int32_t jgLength=jgLimit-jgStart+jgLimit2-jgStart2;
456 while(jgLength&3) {
457 if((jgStart<jgLimit) && (jgStart&3)) {
458 --jgStart;
459 } else if((jgStart2<jgLimit2) && (jgStart2&3)) {
460 --jgStart2;
461 } else if(jgStart<jgLimit) {
462 ++jgLimit;
463 } else {
464 ++jgLimit2;
465 }
466 ++jgLength;
467 }
468 indexes[UBIDI_IX_JG_START]=jgStart;
469 indexes[UBIDI_IX_JG_LIMIT]=jgLimit;
470 indexes[UBIDI_IX_JG_START2]=jgStart2;
471 indexes[UBIDI_IX_JG_LIMIT2]=jgLimit2;
472
473 indexes[UBIDI_IX_TRIE_SIZE]=trieSize;
474 indexes[UBIDI_IX_MIRROR_LENGTH]=mirrorTop;
475 indexes[UBIDI_IX_LENGTH]=
476 (int32_t)sizeof(indexes)+
477 trieSize+
478 4*mirrorTop+
479 jgLength;
480
481 if(!beQuiet) {
482 puts("* ubidi.icu stats *");
483 printf("trie size in bytes: %5d\n", (int)trieSize);
484 printf("size in bytes of mirroring table: %5d\n", (int)(4*mirrorTop));
485 printf("length of Joining_Group array: %5d (U+%04x..U+%04x)\n",
486 (int)(jgLimit-jgStart), (int)jgStart, (int)(jgLimit-1));
487 printf("length of Joining_Group array 2: %5d (U+%04x..U+%04x)\n",
488 (int)(jgLimit2-jgStart2), (int)jgStart2, (int)(jgLimit2-1));
489 printf("data size: %5d\n", (int)indexes[UBIDI_IX_LENGTH]);
490 }
491
492 indexes[UBIDI_MAX_VALUES_INDEX]=
493 ((int32_t)U_CHAR_DIRECTION_COUNT-1)|
494 (((int32_t)U_JT_COUNT-1)<<UBIDI_JT_SHIFT)|
495 (((int32_t)U_BPT_COUNT-1)<<UBIDI_BPT_SHIFT)|
496 (((int32_t)U_JG_COUNT-1)<<UBIDI_MAX_JG_SHIFT);
497 }
498
499 void
writeCSourceFile(const char * path,UErrorCode & errorCode)500 BiDiPropsBuilder::writeCSourceFile(const char *path, UErrorCode &errorCode) {
501 if(U_FAILURE(errorCode)) { return; }
502
503 FILE *f=usrc_create(path, "ubidi_props_data.h", 2016,
504 "icu/tools/unicode/c/genprops/bidipropsbuilder.cpp");
505 if(f==NULL) {
506 errorCode=U_FILE_ACCESS_ERROR;
507 return;
508 }
509 fputs("#ifdef INCLUDED_FROM_UBIDI_PROPS_C\n\n", f);
510 usrc_writeArray(f,
511 "static const UVersionInfo ubidi_props_dataVersion={",
512 dataInfo.dataVersion, 8, 4,
513 "};\n\n");
514 usrc_writeArray(f,
515 "static const int32_t ubidi_props_indexes[UBIDI_IX_TOP]={",
516 indexes, 32, UBIDI_IX_TOP,
517 "};\n\n");
518 usrc_writeUTrie2Arrays(f,
519 "static const uint16_t ubidi_props_trieIndex[%ld]={\n", NULL,
520 pTrie,
521 "\n};\n\n");
522 usrc_writeArray(f,
523 "static const uint32_t ubidi_props_mirrors[%ld]={\n",
524 mirrors, 32, mirrorTop,
525 "\n};\n\n");
526 UChar32 jgStart=indexes[UBIDI_IX_JG_START];
527 UChar32 jgLimit=indexes[UBIDI_IX_JG_LIMIT];
528 usrc_writeArray(f,
529 "static const uint8_t ubidi_props_jgArray[%ld]={\n",
530 jgArray+(jgStart-MIN_JG_START), 8, jgLimit-jgStart,
531 "\n};\n\n");
532 UChar32 jgStart2=indexes[UBIDI_IX_JG_START2];
533 UChar32 jgLimit2=indexes[UBIDI_IX_JG_LIMIT2];
534 usrc_writeArray(f,
535 "static const uint8_t ubidi_props_jgArray2[%ld]={\n",
536 jgArray2+(jgStart2-MIN_JG_START2), 8, jgLimit2-jgStart2,
537 "\n};\n\n");
538 fputs(
539 "static const UBiDiProps ubidi_props_singleton={\n"
540 " NULL,\n"
541 " ubidi_props_indexes,\n"
542 " ubidi_props_mirrors,\n"
543 " ubidi_props_jgArray,\n"
544 " ubidi_props_jgArray2,\n",
545 f);
546 usrc_writeUTrie2Struct(f,
547 " {\n",
548 pTrie, "ubidi_props_trieIndex", NULL,
549 " },\n");
550 usrc_writeArray(f, " { ", dataInfo.formatVersion, 8, 4, " }\n");
551 fputs("};\n\n"
552 "#endif // INCLUDED_FROM_UBIDI_PROPS_C\n", f);
553 fclose(f);
554 }
555
556 void
writeBinaryData(const char * path,UBool withCopyright,UErrorCode & errorCode)557 BiDiPropsBuilder::writeBinaryData(const char *path, UBool withCopyright, UErrorCode &errorCode) {
558 if(U_FAILURE(errorCode)) { return; }
559
560 UNewDataMemory *pData=udata_create(path, UBIDI_DATA_TYPE, UBIDI_DATA_NAME, &dataInfo,
561 withCopyright ? U_COPYRIGHT_STRING : NULL, &errorCode);
562 if(U_FAILURE(errorCode)) {
563 fprintf(stderr, "genprops: udata_create(%s, ubidi.icu) failed - %s\n",
564 path, u_errorName(errorCode));
565 return;
566 }
567
568 udata_writeBlock(pData, indexes, sizeof(indexes));
569 udata_writeBlock(pData, trieBlock, trieSize);
570 udata_writeBlock(pData, mirrors, 4*mirrorTop);
571 UChar32 jgStart=indexes[UBIDI_IX_JG_START];
572 UChar32 jgLimit=indexes[UBIDI_IX_JG_LIMIT];
573 udata_writeBlock(pData, jgArray+(jgStart-MIN_JG_START), jgLimit-jgStart);
574 UChar32 jgStart2=indexes[UBIDI_IX_JG_START2];
575 UChar32 jgLimit2=indexes[UBIDI_IX_JG_LIMIT2];
576 udata_writeBlock(pData, jgArray2+(jgStart2-MIN_JG_START2), jgLimit2-jgStart2);
577
578 long dataLength=udata_finish(pData, &errorCode);
579 if(U_FAILURE(errorCode)) {
580 fprintf(stderr, "genprops error: bidipropsbuilder %d writing the output file\n", errorCode);
581 return;
582 }
583
584 if(dataLength!=indexes[UBIDI_IX_LENGTH]) {
585 fprintf(stderr,
586 "udata_finish(ubidi.icu) reports %ld bytes written but should be %ld\n",
587 dataLength, (long)indexes[UBIDI_IX_LENGTH]);
588 errorCode=U_INTERNAL_PROGRAM_ERROR;
589 }
590 }
591
592 PropsBuilder *
createBiDiPropsBuilder(UErrorCode & errorCode)593 createBiDiPropsBuilder(UErrorCode &errorCode) {
594 if(U_FAILURE(errorCode)) { return NULL; }
595 PropsBuilder *pb=new BiDiPropsBuilder(errorCode);
596 if(pb==NULL) {
597 errorCode=U_MEMORY_ALLOCATION_ERROR;
598 }
599 return pb;
600 }
601
602 /*
603 * Hey, Emacs, please set the following:
604 *
605 * Local Variables:
606 * indent-tabs-mode: nil
607 * End:
608 *
609 */
610