]> git.saurik.com Git - apple/icu.git/blob - icuSources/tools/genrb/reslist.c
ICU-8.11.1.tar.gz
[apple/icu.git] / icuSources / tools / genrb / reslist.c
1 /*
2 *******************************************************************************
3 *
4 * Copyright (C) 2000-2006, International Business Machines
5 * Corporation and others. All Rights Reserved.
6 *
7 *******************************************************************************
8 *
9 * File reslist.c
10 *
11 * Modification History:
12 *
13 * Date Name Description
14 * 02/21/00 weiv Creation.
15 *******************************************************************************
16 */
17
18 #include <assert.h>
19 #include <stdio.h>
20 #include "reslist.h"
21 #include "unewdata.h"
22 #include "unicode/ures.h"
23 #include "unicode/putil.h"
24 #include "errmsg.h"
25
26 #define BIN_ALIGNMENT 16
27
28 static UBool gIncludeCopyright = FALSE;
29
30 uint32_t res_write(UNewDataMemory *mem, struct SResource *res,
31 uint32_t usedOffset, UErrorCode *status);
32
33 static const UDataInfo dataInfo= {
34 sizeof(UDataInfo),
35 0,
36
37 U_IS_BIG_ENDIAN,
38 U_CHARSET_FAMILY,
39 sizeof(UChar),
40 0,
41
42 {0x52, 0x65, 0x73, 0x42}, /* dataFormat="resb" */
43 {1, 2, 0, 0}, /* formatVersion */
44 {1, 4, 0, 0} /* dataVersion take a look at version inside parsed resb*/
45 };
46
47 static uint8_t calcPadding(uint32_t size) {
48 /* returns space we need to pad */
49 return (uint8_t) ((size % sizeof(uint32_t)) ? (sizeof(uint32_t) - (size % sizeof(uint32_t))) : 0);
50
51 }
52
53 void setIncludeCopyright(UBool val){
54 gIncludeCopyright=val;
55 }
56
57 UBool getIncludeCopyright(void){
58 return gIncludeCopyright;
59 }
60
61 /* Writing Functions */
62 static uint32_t string_write(UNewDataMemory *mem, struct SResource *res,
63 uint32_t usedOffset, UErrorCode *status) {
64 udata_write32(mem, res->u.fString.fLength);
65 udata_writeUString(mem, res->u.fString.fChars, res->u.fString.fLength + 1);
66 udata_writePadding(mem, calcPadding(res->fSize));
67
68 return usedOffset;
69 }
70
71 /* Writing Functions */
72 static uint32_t alias_write(UNewDataMemory *mem, struct SResource *res,
73 uint32_t usedOffset, UErrorCode *status) {
74 udata_write32(mem, res->u.fString.fLength);
75 udata_writeUString(mem, res->u.fString.fChars, res->u.fString.fLength + 1);
76 udata_writePadding(mem, calcPadding(res->fSize));
77
78 return usedOffset;
79 }
80
81 static uint32_t array_write(UNewDataMemory *mem, struct SResource *res,
82 uint32_t usedOffset, UErrorCode *status) {
83 uint32_t *resources = NULL;
84 uint32_t i = 0;
85
86 struct SResource *current = NULL;
87
88 if (U_FAILURE(*status)) {
89 return 0;
90 }
91
92 if (res->u.fArray.fCount > 0) {
93 resources = (uint32_t *) uprv_malloc(sizeof(uint32_t) * res->u.fArray.fCount);
94
95 if (resources == NULL) {
96 *status = U_MEMORY_ALLOCATION_ERROR;
97 return 0;
98 }
99
100 current = res->u.fArray.fFirst;
101 i = 0;
102
103 while (current != NULL) {
104 if (current->fType == URES_INT) {
105 resources[i] = (current->fType << 28) | (current->u.fIntValue.fValue & 0xFFFFFFF);
106 } else if (current->fType == URES_BINARY) {
107 uint32_t uo = usedOffset;
108
109 usedOffset = res_write(mem, current, usedOffset, status);
110 resources[i] = (current->fType << 28) | (usedOffset >> 2);
111 usedOffset += current->fSize + calcPadding(current->fSize) - (usedOffset - uo);
112 } else {
113 usedOffset = res_write(mem, current, usedOffset, status);
114 resources[i] = (current->fType << 28) | (usedOffset >> 2);
115 usedOffset += current->fSize + calcPadding(current->fSize);
116 }
117
118 i++;
119 current = current->fNext;
120 }
121
122 /* usedOffset += res->fSize + pad; */
123
124 udata_write32(mem, res->u.fArray.fCount);
125 udata_writeBlock(mem, resources, sizeof(uint32_t) * res->u.fArray.fCount);
126 uprv_free(resources);
127 } else {
128 /* array is empty */
129 udata_write32(mem, 0);
130 }
131
132 return usedOffset;
133 }
134
135 static uint32_t intvector_write(UNewDataMemory *mem, struct SResource *res,
136 uint32_t usedOffset, UErrorCode *status) {
137 uint32_t i = 0;
138 udata_write32(mem, res->u.fIntVector.fCount);
139 for(i = 0; i<res->u.fIntVector.fCount; i++) {
140 udata_write32(mem, res->u.fIntVector.fArray[i]);
141 }
142
143 return usedOffset;
144 }
145
146 static uint32_t bin_write(UNewDataMemory *mem, struct SResource *res,
147 uint32_t usedOffset, UErrorCode *status) {
148 uint32_t pad = 0;
149 uint32_t extrapad = calcPadding(res->fSize);
150 uint32_t dataStart = usedOffset + sizeof(res->u.fBinaryValue.fLength);
151
152 if (dataStart % BIN_ALIGNMENT) {
153 pad = (BIN_ALIGNMENT - dataStart % BIN_ALIGNMENT);
154 udata_writePadding(mem, pad);
155 usedOffset += pad;
156 }
157
158 udata_write32(mem, res->u.fBinaryValue.fLength);
159 if (res->u.fBinaryValue.fLength > 0) {
160 udata_writeBlock(mem, res->u.fBinaryValue.fData, res->u.fBinaryValue.fLength);
161 }
162 udata_writePadding(mem, (BIN_ALIGNMENT - pad + extrapad));
163
164 return usedOffset;
165 }
166
167 static uint32_t int_write(UNewDataMemory *mem, struct SResource *res,
168 uint32_t usedOffset, UErrorCode *status) {
169 return usedOffset;
170 }
171
172 static uint32_t table_write(UNewDataMemory *mem, struct SResource *res,
173 uint32_t usedOffset, UErrorCode *status) {
174 uint8_t pad = 0;
175 uint32_t i = 0;
176 uint16_t *keys16 = NULL;
177 int32_t *keys32 = NULL;
178 uint32_t *resources = NULL;
179
180 struct SResource *current = NULL;
181
182 if (U_FAILURE(*status)) {
183 return 0;
184 }
185
186 pad = calcPadding(res->fSize);
187
188 if (res->u.fTable.fCount > 0) {
189 if(res->fType == URES_TABLE) {
190 keys16 = (uint16_t *) uprv_malloc(sizeof(uint16_t) * res->u.fTable.fCount);
191 if (keys16 == NULL) {
192 *status = U_MEMORY_ALLOCATION_ERROR;
193 return 0;
194 }
195 } else {
196 keys32 = (int32_t *) uprv_malloc(sizeof(int32_t) * res->u.fTable.fCount);
197 if (keys32 == NULL) {
198 *status = U_MEMORY_ALLOCATION_ERROR;
199 return 0;
200 }
201 }
202
203 resources = (uint32_t *) uprv_malloc(sizeof(uint32_t) * res->u.fTable.fCount);
204
205 if (resources == NULL) {
206 uprv_free(keys16);
207 uprv_free(keys32);
208 *status = U_MEMORY_ALLOCATION_ERROR;
209 return 0;
210 }
211
212 current = res->u.fTable.fFirst;
213 i = 0;
214
215 while (current != NULL) {
216 assert(i < res->u.fTable.fCount);
217
218 /* where the key is */
219 if(res->fType == URES_TABLE) {
220 keys16[i] = (uint16_t) current->fKey;
221 } else {
222 keys32[i] = current->fKey;
223 }
224
225 if (current->fType == URES_INT) {
226 resources[i] = (current->fType << 28) | (current->u.fIntValue.fValue & 0xFFFFFFF);
227 } else if (current->fType == URES_BINARY) {
228 uint32_t uo = usedOffset;
229
230 usedOffset = res_write(mem, current, usedOffset, status);
231 resources[i] = (current->fType << 28) | (usedOffset >> 2);
232 usedOffset += current->fSize + calcPadding(current->fSize) - (usedOffset - uo);
233 } else {
234 usedOffset = res_write(mem, current, usedOffset, status);
235 resources[i] = (current->fType << 28) | (usedOffset >> 2);
236 usedOffset += current->fSize + calcPadding(current->fSize);
237 }
238
239 i++;
240 current = current->fNext;
241 }
242
243 if(res->fType == URES_TABLE) {
244 udata_write16(mem, (uint16_t)res->u.fTable.fCount);
245
246 udata_writeBlock(mem, keys16, sizeof(uint16_t) * res->u.fTable.fCount);
247 udata_writePadding(mem, pad);
248 } else {
249 udata_write32(mem, res->u.fTable.fCount);
250
251 udata_writeBlock(mem, keys32, sizeof(int32_t) * res->u.fTable.fCount);
252 }
253
254 udata_writeBlock(mem, resources, sizeof(uint32_t) * res->u.fTable.fCount);
255
256 uprv_free(keys16);
257 uprv_free(keys32);
258 uprv_free(resources);
259 } else {
260 /* table is empty */
261 if(res->fType == URES_TABLE) {
262 udata_write16(mem, 0);
263 udata_writePadding(mem, pad);
264 } else {
265 udata_write32(mem, 0);
266 }
267 }
268
269 return usedOffset;
270 }
271
272 uint32_t res_write(UNewDataMemory *mem, struct SResource *res,
273 uint32_t usedOffset, UErrorCode *status) {
274 if (U_FAILURE(*status)) {
275 return 0;
276 }
277
278 if (res != NULL) {
279 switch (res->fType) {
280 case URES_STRING:
281 return string_write (mem, res, usedOffset, status);
282 case URES_ALIAS:
283 return alias_write (mem, res, usedOffset, status);
284 case URES_INT_VECTOR:
285 return intvector_write (mem, res, usedOffset, status);
286 case URES_BINARY:
287 return bin_write (mem, res, usedOffset, status);
288 case URES_INT:
289 return int_write (mem, res, usedOffset, status);
290 case URES_ARRAY:
291 return array_write (mem, res, usedOffset, status);
292 case URES_TABLE:
293 case URES_TABLE32:
294 return table_write (mem, res, usedOffset, status);
295
296 default:
297 break;
298 }
299 }
300
301 *status = U_INTERNAL_PROGRAM_ERROR;
302 return 0;
303 }
304
305 void bundle_write(struct SRBRoot *bundle, const char *outputDir, const char *outputPkg, char *writtenFilename, int writtenFilenameLen, UErrorCode *status) {
306 UNewDataMemory *mem = NULL;
307 uint8_t pad = 0;
308 uint32_t root = 0;
309 uint32_t usedOffset = 0;
310 uint32_t top, size;
311 char dataName[1024];
312 int32_t indexes[URES_INDEX_TOP];
313
314 if (writtenFilename && writtenFilenameLen) {
315 *writtenFilename = 0;
316 }
317
318 if (U_FAILURE(*status)) {
319 return;
320 }
321
322 if (writtenFilename) {
323 int32_t off = 0, len = 0;
324 if (outputDir) {
325 len = (int32_t)uprv_strlen(outputDir);
326 if (len > writtenFilenameLen) {
327 len = writtenFilenameLen;
328 }
329 uprv_strncpy(writtenFilename, outputDir, len);
330 }
331 if (writtenFilenameLen -= len) {
332 off += len;
333 writtenFilename[off] = U_FILE_SEP_CHAR;
334 if (--writtenFilenameLen) {
335 ++off;
336 if(outputPkg != NULL)
337 {
338 uprv_strcpy(writtenFilename+off, outputPkg);
339 off += (int32_t)uprv_strlen(outputPkg);
340 writtenFilename[off] = '_';
341 ++off;
342 }
343
344 len = (int32_t)uprv_strlen(bundle->fLocale);
345 if (len > writtenFilenameLen) {
346 len = writtenFilenameLen;
347 }
348 uprv_strncpy(writtenFilename + off, bundle->fLocale, len);
349 if (writtenFilenameLen -= len) {
350 off += len;
351 len = 5;
352 if (len > writtenFilenameLen) {
353 len = writtenFilenameLen;
354 }
355 uprv_strncpy(writtenFilename + off, ".res", len);
356 }
357 }
358 }
359 }
360
361 if(outputPkg)
362 {
363 uprv_strcpy(dataName, outputPkg);
364 uprv_strcat(dataName, "_");
365 uprv_strcat(dataName, bundle->fLocale);
366 }
367 else
368 {
369 uprv_strcpy(dataName, bundle->fLocale);
370 }
371
372 mem = udata_create(outputDir, "res", dataName, &dataInfo, (gIncludeCopyright==TRUE)? U_COPYRIGHT_STRING:NULL, status);
373 if(U_FAILURE(*status)){
374 return;
375 }
376 pad = calcPadding(bundle->fKeyPoint);
377
378 usedOffset = bundle->fKeyPoint + pad ; /* top of the strings */
379
380 /* we're gonna put the main table at the end */
381 top = usedOffset + bundle->fRoot->u.fTable.fChildrenSize;
382 root = (top) >> 2 | (bundle->fRoot->fType << 28);
383
384 /* write the root item */
385 udata_write32(mem, root);
386
387 /* add to top the size of the root item */
388 top += bundle->fRoot->fSize;
389 top += calcPadding(top);
390
391 /*
392 * formatVersion 1.1 (ICU 2.8):
393 * write int32_t indexes[] after root and before the strings
394 * to make it easier to parse resource bundles in icuswap or from Java etc.
395 */
396 uprv_memset(indexes, 0, sizeof(indexes));
397 indexes[URES_INDEX_LENGTH]= URES_INDEX_TOP;
398 indexes[URES_INDEX_STRINGS_TOP]= (int32_t)(usedOffset>>2);
399 indexes[URES_INDEX_RESOURCES_TOP]= (int32_t)(top>>2);
400 indexes[URES_INDEX_BUNDLE_TOP]= indexes[URES_INDEX_RESOURCES_TOP];
401 indexes[URES_INDEX_MAX_TABLE_LENGTH]= bundle->fMaxTableLength;
402
403 /*
404 * formatVersion 1.2 (ICU 3.6):
405 * write indexes[URES_INDEX_ATTRIBUTES] with URES_ATT_NO_FALLBACK set or not set
406 * the memset() above initialized all indexes[] to 0
407 */
408 if(bundle->noFallback) {
409 indexes[URES_INDEX_ATTRIBUTES]=URES_ATT_NO_FALLBACK;
410 }
411
412 /* write the indexes[] */
413 udata_writeBlock(mem, indexes, sizeof(indexes));
414
415 /* write the table key strings */
416 udata_writeBlock(mem, bundle->fKeys+URES_STRINGS_BOTTOM,
417 bundle->fKeyPoint-URES_STRINGS_BOTTOM);
418
419 /* write the padding bytes after the table key strings */
420 udata_writePadding(mem, pad);
421
422 /* write all of the bundle contents: the root item and its children */
423 usedOffset = res_write(mem, bundle->fRoot, usedOffset, status);
424
425 size = udata_finish(mem, status);
426 if(top != size) {
427 fprintf(stderr, "genrb error: wrote %u bytes but counted %u\n",
428 (int)size, (int)top);
429 *status = U_INTERNAL_PROGRAM_ERROR;
430 }
431 }
432
433 /* Opening Functions */
434 struct SResource* res_open(const struct UString* comment, UErrorCode* status){
435 struct SResource *res;
436
437 if (U_FAILURE(*status)) {
438 return NULL;
439 }
440
441 res = (struct SResource *) uprv_malloc(sizeof(struct SResource));
442
443 if (res == NULL) {
444 *status = U_MEMORY_ALLOCATION_ERROR;
445 return NULL;
446 }
447 uprv_memset(res, 0, sizeof(struct SResource));
448
449 res->fComment = NULL;
450 if(comment != NULL){
451 res->fComment = (struct UString *) uprv_malloc(sizeof(struct UString));
452 if(res->fComment == NULL){
453 *status = U_MEMORY_ALLOCATION_ERROR;
454 uprv_free(res);
455 return NULL;
456 }
457 ustr_init(res->fComment);
458 ustr_cpy(res->fComment, comment, status);
459 }
460 return res;
461
462 }
463 struct SResource* table_open(struct SRBRoot *bundle, char *tag, const struct UString* comment, UErrorCode *status) {
464
465 struct SResource *res = res_open(comment, status);
466
467 res->fKey = bundle_addtag(bundle, tag, status);
468
469 if (U_FAILURE(*status)) {
470 uprv_free(res->fComment);
471 uprv_free(res);
472 return NULL;
473 }
474
475 res->fNext = NULL;
476
477 /*
478 * always open a table not a table32 in case it remains empty -
479 * try to use table32 only when necessary
480 */
481 res->fType = URES_TABLE;
482 res->fSize = sizeof(uint16_t);
483
484 res->u.fTable.fCount = 0;
485 res->u.fTable.fChildrenSize = 0;
486 res->u.fTable.fFirst = NULL;
487 res->u.fTable.fRoot = bundle;
488
489 return res;
490 }
491
492 struct SResource* array_open(struct SRBRoot *bundle, const char *tag, const struct UString* comment, UErrorCode *status) {
493
494 struct SResource *res = res_open(comment, status);
495
496 if (U_FAILURE(*status)) {
497 return NULL;
498 }
499
500 res->fType = URES_ARRAY;
501 res->fKey = bundle_addtag(bundle, tag, status);
502
503 if (U_FAILURE(*status)) {
504 uprv_free(res->fComment);
505 uprv_free(res);
506 return NULL;
507 }
508
509 res->fNext = NULL;
510 res->fSize = sizeof(int32_t);
511
512 res->u.fArray.fCount = 0;
513 res->u.fArray.fChildrenSize = 0;
514 res->u.fArray.fFirst = NULL;
515 res->u.fArray.fLast = NULL;
516
517 return res;
518 }
519
520 struct SResource *string_open(struct SRBRoot *bundle, char *tag, const UChar *value, int32_t len, const struct UString* comment, UErrorCode *status) {
521 struct SResource *res = res_open(comment, status);
522
523 if (U_FAILURE(*status)) {
524 return NULL;
525 }
526
527 res->fType = URES_STRING;
528 res->fKey = bundle_addtag(bundle, tag, status);
529
530 if (U_FAILURE(*status)) {
531 uprv_free(res->fComment);
532 uprv_free(res);
533 return NULL;
534 }
535
536 res->fNext = NULL;
537
538 res->u.fString.fLength = len;
539 res->u.fString.fChars = (UChar *) uprv_malloc(sizeof(UChar) * (len + 1));
540
541 if (res->u.fString.fChars == NULL) {
542 *status = U_MEMORY_ALLOCATION_ERROR;
543 uprv_free(res);
544 return NULL;
545 }
546
547 uprv_memcpy(res->u.fString.fChars, value, sizeof(UChar) * (len + 1));
548 res->fSize = sizeof(int32_t) + sizeof(UChar) * (len+1);
549
550 return res;
551 }
552
553 /* TODO: make alias_open and string_open use the same code */
554 struct SResource *alias_open(struct SRBRoot *bundle, char *tag, UChar *value, int32_t len, const struct UString* comment, UErrorCode *status) {
555 struct SResource *res = res_open(comment, status);
556
557 if (U_FAILURE(*status)) {
558 return NULL;
559 }
560
561 res->fType = URES_ALIAS;
562 res->fKey = bundle_addtag(bundle, tag, status);
563
564 if (U_FAILURE(*status)) {
565 uprv_free(res->fComment);
566 uprv_free(res);
567 return NULL;
568 }
569
570 res->fNext = NULL;
571
572 res->u.fString.fLength = len;
573 res->u.fString.fChars = (UChar *) uprv_malloc(sizeof(UChar) * (len + 1));
574
575 if (res->u.fString.fChars == NULL) {
576 *status = U_MEMORY_ALLOCATION_ERROR;
577 uprv_free(res);
578 return NULL;
579 }
580
581 uprv_memcpy(res->u.fString.fChars, value, sizeof(UChar) * (len + 1));
582 res->fSize = sizeof(int32_t) + sizeof(UChar) * (len + 1);
583
584 return res;
585 }
586
587
588 struct SResource* intvector_open(struct SRBRoot *bundle, char *tag, const struct UString* comment, UErrorCode *status) {
589 struct SResource *res = res_open(comment, status);
590
591 if (U_FAILURE(*status)) {
592 return NULL;
593 }
594
595 res->fType = URES_INT_VECTOR;
596 res->fKey = bundle_addtag(bundle, tag, status);
597
598 if (U_FAILURE(*status)) {
599 uprv_free(res->fComment);
600 uprv_free(res);
601 return NULL;
602 }
603
604 res->fNext = NULL;
605 res->fSize = sizeof(int32_t);
606
607 res->u.fIntVector.fCount = 0;
608 res->u.fIntVector.fArray = (uint32_t *) uprv_malloc(sizeof(uint32_t) * RESLIST_MAX_INT_VECTOR);
609
610 if (res->u.fIntVector.fArray == NULL) {
611 *status = U_MEMORY_ALLOCATION_ERROR;
612 uprv_free(res);
613 return NULL;
614 }
615
616 return res;
617 }
618
619 struct SResource *int_open(struct SRBRoot *bundle, char *tag, int32_t value, const struct UString* comment, UErrorCode *status) {
620 struct SResource *res = res_open(comment, status);
621
622 if (U_FAILURE(*status)) {
623 return NULL;
624 }
625
626 res->fType = URES_INT;
627 res->fKey = bundle_addtag(bundle, tag, status);
628
629 if (U_FAILURE(*status)) {
630 uprv_free(res->fComment);
631 uprv_free(res);
632 return NULL;
633 }
634
635 res->fSize = 0;
636 res->fNext = NULL;
637 res->u.fIntValue.fValue = value;
638
639 return res;
640 }
641
642 struct SResource *bin_open(struct SRBRoot *bundle, const char *tag, uint32_t length, uint8_t *data, const char* fileName, const struct UString* comment, UErrorCode *status) {
643 struct SResource *res = res_open(comment, status);
644
645 if (U_FAILURE(*status)) {
646 return NULL;
647 }
648
649 res->fType = URES_BINARY;
650 res->fKey = bundle_addtag(bundle, tag, status);
651
652 if (U_FAILURE(*status)) {
653 uprv_free(res->fComment);
654 uprv_free(res);
655 return NULL;
656 }
657
658 res->fNext = NULL;
659
660 res->u.fBinaryValue.fLength = length;
661 res->u.fBinaryValue.fFileName = NULL;
662 if(fileName!=NULL && uprv_strcmp(fileName, "") !=0){
663 res->u.fBinaryValue.fFileName = (char*) uprv_malloc(sizeof(char) * (uprv_strlen(fileName)+1));
664 uprv_strcpy(res->u.fBinaryValue.fFileName,fileName);
665 }
666 if (length > 0) {
667 res->u.fBinaryValue.fData = (uint8_t *) uprv_malloc(sizeof(uint8_t) * length);
668
669 if (res->u.fBinaryValue.fData == NULL) {
670 *status = U_MEMORY_ALLOCATION_ERROR;
671 uprv_free(res);
672 return NULL;
673 }
674
675 uprv_memcpy(res->u.fBinaryValue.fData, data, length);
676 }
677 else {
678 res->u.fBinaryValue.fData = NULL;
679 }
680
681 res->fSize = sizeof(int32_t) + sizeof(uint8_t) * length + BIN_ALIGNMENT;
682
683 return res;
684 }
685
686 struct SRBRoot *bundle_open(const struct UString* comment, UErrorCode *status) {
687 struct SRBRoot *bundle = NULL;
688
689 if (U_FAILURE(*status)) {
690 return NULL;
691 }
692
693 bundle = (struct SRBRoot *) uprv_malloc(sizeof(struct SRBRoot));
694
695 if (bundle == NULL) {
696 *status = U_MEMORY_ALLOCATION_ERROR;
697 return 0;
698 }
699 uprv_memset(bundle, 0, sizeof(struct SRBRoot));
700
701 bundle->fLocale = NULL;
702
703 bundle->fKeys = (char *) uprv_malloc(sizeof(char) * KEY_SPACE_SIZE);
704 bundle->fKeysCapacity = KEY_SPACE_SIZE;
705
706 if(comment != NULL){
707
708 }
709
710 if (bundle->fKeys == NULL) {
711 *status = U_MEMORY_ALLOCATION_ERROR;
712 uprv_free(bundle);
713 return NULL;
714 }
715
716 /* formatVersion 1.1: start fKeyPoint after the root item and indexes[] */
717 bundle->fKeyPoint = URES_STRINGS_BOTTOM;
718 uprv_memset(bundle->fKeys, 0, URES_STRINGS_BOTTOM);
719
720 bundle->fCount = 0;
721 bundle->fRoot = table_open(bundle, NULL, comment, status);
722
723 if (bundle->fRoot == NULL || U_FAILURE(*status)) {
724 if (U_SUCCESS(*status)) {
725 *status = U_MEMORY_ALLOCATION_ERROR;
726 }
727
728 uprv_free(bundle->fKeys);
729 uprv_free(bundle);
730
731 return NULL;
732 }
733
734 return bundle;
735 }
736
737 /* Closing Functions */
738 void table_close(struct SResource *table, UErrorCode *status) {
739 struct SResource *current = NULL;
740 struct SResource *prev = NULL;
741
742 current = table->u.fTable.fFirst;
743
744 while (current != NULL) {
745 prev = current;
746 current = current->fNext;
747
748 res_close(prev, status);
749 }
750
751 table->u.fTable.fFirst = NULL;
752 }
753
754 void array_close(struct SResource *array, UErrorCode *status) {
755 struct SResource *current = NULL;
756 struct SResource *prev = NULL;
757
758 if(array==NULL){
759 return;
760 }
761 current = array->u.fArray.fFirst;
762
763 while (current != NULL) {
764 prev = current;
765 current = current->fNext;
766
767 res_close(prev, status);
768 }
769 array->u.fArray.fFirst = NULL;
770 }
771
772 void string_close(struct SResource *string, UErrorCode *status) {
773 if (string->u.fString.fChars != NULL) {
774 uprv_free(string->u.fString.fChars);
775 string->u.fString.fChars =NULL;
776 }
777 }
778
779 void alias_close(struct SResource *alias, UErrorCode *status) {
780 if (alias->u.fString.fChars != NULL) {
781 uprv_free(alias->u.fString.fChars);
782 alias->u.fString.fChars =NULL;
783 }
784 }
785
786 void intvector_close(struct SResource *intvector, UErrorCode *status) {
787 if (intvector->u.fIntVector.fArray != NULL) {
788 uprv_free(intvector->u.fIntVector.fArray);
789 intvector->u.fIntVector.fArray =NULL;
790 }
791 }
792
793 void int_close(struct SResource *intres, UErrorCode *status) {
794 /* Intentionally left blank */
795 }
796
797 void bin_close(struct SResource *binres, UErrorCode *status) {
798 if (binres->u.fBinaryValue.fData != NULL) {
799 uprv_free(binres->u.fBinaryValue.fData);
800 binres->u.fBinaryValue.fData = NULL;
801 }
802 }
803
804 void res_close(struct SResource *res, UErrorCode *status) {
805 if (res != NULL) {
806 switch(res->fType) {
807 case URES_STRING:
808 string_close(res, status);
809 break;
810 case URES_ALIAS:
811 alias_close(res, status);
812 break;
813 case URES_INT_VECTOR:
814 intvector_close(res, status);
815 break;
816 case URES_BINARY:
817 bin_close(res, status);
818 break;
819 case URES_INT:
820 int_close(res, status);
821 break;
822 case URES_ARRAY:
823 array_close(res, status);
824 break;
825 case URES_TABLE:
826 case URES_TABLE32:
827 table_close(res, status);
828 break;
829 default:
830 /* Shouldn't happen */
831 break;
832 }
833
834 uprv_free(res);
835 }
836 }
837
838 void bundle_close(struct SRBRoot *bundle, UErrorCode *status) {
839 struct SResource *current = NULL;
840 struct SResource *prev = NULL;
841
842 if (bundle->fRoot != NULL) {
843 current = bundle->fRoot->u.fTable.fFirst;
844
845 while (current != NULL) {
846 prev = current;
847 current = current->fNext;
848
849 res_close(prev, status);
850 }
851
852 uprv_free(bundle->fRoot);
853 }
854
855 if (bundle->fLocale != NULL) {
856 uprv_free(bundle->fLocale);
857 }
858
859 if (bundle->fKeys != NULL) {
860 uprv_free(bundle->fKeys);
861 }
862
863 uprv_free(bundle);
864 }
865
866 /* Adding Functions */
867 void table_add(struct SResource *table, struct SResource *res, int linenumber, UErrorCode *status) {
868 struct SResource *current = NULL;
869 struct SResource *prev = NULL;
870 struct SResTable *list;
871
872 if (U_FAILURE(*status)) {
873 return;
874 }
875
876 /* remember this linenumber to report to the user if there is a duplicate key */
877 res->line = linenumber;
878
879 /* here we need to traverse the list */
880 list = &(table->u.fTable);
881
882 if(table->fType == URES_TABLE && res->fKey > 0xffff) {
883 /* this table straddles the 64k strings boundary, update to a table32 */
884 table->fType = URES_TABLE32;
885
886 /*
887 * increase the size because count and each string offset
888 * increase from uint16_t to int32_t
889 */
890 table->fSize += (1 + list->fCount) * 2;
891 }
892
893 ++(list->fCount);
894 if(list->fCount > (uint32_t)list->fRoot->fMaxTableLength) {
895 list->fRoot->fMaxTableLength = list->fCount;
896 }
897
898 /*
899 * URES_TABLE: 6 bytes = 1 uint16_t key string offset + 1 uint32_t Resource
900 * URES_TABLE32: 8 bytes = 1 int32_t key string offset + 1 uint32_t Resource
901 */
902 table->fSize += table->fType == URES_TABLE ? 6 : 8;
903
904 table->u.fTable.fChildrenSize += res->fSize + calcPadding(res->fSize);
905
906 if (res->fType == URES_TABLE || res->fType == URES_TABLE32) {
907 table->u.fTable.fChildrenSize += res->u.fTable.fChildrenSize;
908 } else if (res->fType == URES_ARRAY) {
909 table->u.fTable.fChildrenSize += res->u.fArray.fChildrenSize;
910 }
911
912 /* is list still empty? */
913 if (list->fFirst == NULL) {
914 list->fFirst = res;
915 res->fNext = NULL;
916 return;
917 }
918
919 current = list->fFirst;
920
921 while (current != NULL) {
922 if (uprv_strcmp(((list->fRoot->fKeys) + (current->fKey)), ((list->fRoot->fKeys) + (res->fKey))) < 0) {
923 prev = current;
924 current = current->fNext;
925 } else if (uprv_strcmp(((list->fRoot->fKeys) + (current->fKey)), ((list->fRoot->fKeys) + (res->fKey))) > 0) {
926 /* we're either in front of list, or in middle */
927 if (prev == NULL) {
928 /* front of the list */
929 list->fFirst = res;
930 } else {
931 /* middle of the list */
932 prev->fNext = res;
933 }
934
935 res->fNext = current;
936 return;
937 } else {
938 /* Key already exists! ERROR! */
939 error(linenumber, "duplicate key '%s' in table, first appeared at line %d", list->fRoot->fKeys + current->fKey, current->line);
940 *status = U_UNSUPPORTED_ERROR;
941 return;
942 }
943 }
944
945 /* end of list */
946 prev->fNext = res;
947 res->fNext = NULL;
948 }
949
950 void array_add(struct SResource *array, struct SResource *res, UErrorCode *status) {
951 if (U_FAILURE(*status)) {
952 return;
953 }
954
955 if (array->u.fArray.fFirst == NULL) {
956 array->u.fArray.fFirst = res;
957 array->u.fArray.fLast = res;
958 } else {
959 array->u.fArray.fLast->fNext = res;
960 array->u.fArray.fLast = res;
961 }
962
963 (array->u.fArray.fCount)++;
964
965 array->fSize += sizeof(uint32_t);
966 array->u.fArray.fChildrenSize += res->fSize + calcPadding(res->fSize);
967
968 if (res->fType == URES_TABLE || res->fType == URES_TABLE32) {
969 array->u.fArray.fChildrenSize += res->u.fTable.fChildrenSize;
970 } else if (res->fType == URES_ARRAY) {
971 array->u.fArray.fChildrenSize += res->u.fArray.fChildrenSize;
972 }
973 }
974
975 void intvector_add(struct SResource *intvector, int32_t value, UErrorCode *status) {
976 if (U_FAILURE(*status)) {
977 return;
978 }
979
980 *(intvector->u.fIntVector.fArray + intvector->u.fIntVector.fCount) = value;
981 intvector->u.fIntVector.fCount++;
982
983 intvector->fSize += sizeof(uint32_t);
984 }
985
986 /* Misc Functions */
987
988 void bundle_setlocale(struct SRBRoot *bundle, UChar *locale, UErrorCode *status) {
989
990 if(U_FAILURE(*status)) {
991 return;
992 }
993
994 if (bundle->fLocale!=NULL) {
995 uprv_free(bundle->fLocale);
996 }
997
998 bundle->fLocale= (char*) uprv_malloc(sizeof(char) * (u_strlen(locale)+1));
999
1000 if(bundle->fLocale == NULL) {
1001 *status = U_MEMORY_ALLOCATION_ERROR;
1002 return;
1003 }
1004
1005 /*u_strcpy(bundle->fLocale, locale);*/
1006 u_UCharsToChars(locale, bundle->fLocale, u_strlen(locale)+1);
1007
1008 }
1009
1010
1011 int32_t
1012 bundle_addtag(struct SRBRoot *bundle, const char *tag, UErrorCode *status) {
1013 int32_t keypos, length;
1014
1015 if (U_FAILURE(*status)) {
1016 return -1;
1017 }
1018
1019 if (tag == NULL) {
1020 /* do not set an error: the root table has a NULL tag */
1021 return -1;
1022 }
1023
1024 keypos = bundle->fKeyPoint;
1025
1026 bundle->fKeyPoint += length = (int32_t) (uprv_strlen(tag) + 1);
1027
1028 if (bundle->fKeyPoint >= bundle->fKeysCapacity) {
1029 /* overflow - resize the keys buffer */
1030 bundle->fKeysCapacity += KEY_SPACE_SIZE;
1031 bundle->fKeys = uprv_realloc(bundle->fKeys, bundle->fKeysCapacity);
1032 if(bundle->fKeys == NULL) {
1033 *status = U_MEMORY_ALLOCATION_ERROR;
1034 return -1;
1035 }
1036 }
1037
1038 uprv_memcpy(bundle->fKeys + keypos, tag, length);
1039
1040 return keypos;
1041 }