]> git.saurik.com Git - apple/icu.git/blame - icuSources/tools/genrb/reslist.c
ICU-6.2.13.tar.gz
[apple/icu.git] / icuSources / tools / genrb / reslist.c
CommitLineData
b75a7d8f
A
1/*
2*******************************************************************************
3*
374ca955 4* Copyright (C) 2000-2004, International Business Machines
b75a7d8f
A
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>
374ca955 19#include <stdio.h>
b75a7d8f
A
20#include "reslist.h"
21#include "unewdata.h"
22#include "unicode/ures.h"
374ca955 23#include "unicode/putil.h"
b75a7d8f
A
24#include "errmsg.h"
25
26#define BIN_ALIGNMENT 16
27
28static UBool gIncludeCopyright = FALSE;
29
30uint32_t res_write(UNewDataMemory *mem, struct SResource *res,
31 uint32_t usedOffset, UErrorCode *status);
32
33static 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" */
374ca955 43 {1, 1, 0, 0}, /* formatVersion */
b75a7d8f
A
44 {1, 4, 0, 0} /* dataVersion take a look at version inside parsed resb*/
45};
46
47static 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
53void setIncludeCopyright(UBool val){
54 gIncludeCopyright=val;
55}
56
57UBool getIncludeCopyright(void){
58 return gIncludeCopyright;
59}
60
61/* Writing Functions */
62static 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 */
72static 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
81static 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
135static 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
146static 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
167static uint32_t int_write(UNewDataMemory *mem, struct SResource *res,
168 uint32_t usedOffset, UErrorCode *status) {
169 return usedOffset;
170}
171
172static 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;
374ca955
A
176 uint16_t *keys16 = NULL;
177 int32_t *keys32 = NULL;
b75a7d8f
A
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) {
374ca955
A
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 }
b75a7d8f
A
201 }
202
203 resources = (uint32_t *) uprv_malloc(sizeof(uint32_t) * res->u.fTable.fCount);
204
205 if (resources == NULL) {
374ca955
A
206 uprv_free(keys16);
207 uprv_free(keys32);
b75a7d8f
A
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
374ca955
A
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 }
b75a7d8f
A
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
374ca955
A
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 }
b75a7d8f 253
b75a7d8f
A
254 udata_writeBlock(mem, resources, sizeof(uint32_t) * res->u.fTable.fCount);
255
374ca955
A
256 uprv_free(keys16);
257 uprv_free(keys32);
b75a7d8f
A
258 uprv_free(resources);
259 } else {
260 /* table is empty */
374ca955
A
261 if(res->fType == URES_TABLE) {
262 udata_write16(mem, 0);
263 udata_writePadding(mem, pad);
264 } else {
265 udata_write32(mem, 0);
266 }
b75a7d8f
A
267 }
268
269 return usedOffset;
270}
271
272uint32_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:
374ca955 293 case URES_TABLE32:
b75a7d8f
A
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
305void 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;
374ca955 310 uint32_t top, size;
b75a7d8f 311 char dataName[1024];
374ca955 312 int32_t indexes[URES_INDEX_TOP];
b75a7d8f
A
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);
374ca955 339 off += (int32_t)uprv_strlen(outputPkg);
b75a7d8f
A
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
374ca955 378 usedOffset = bundle->fKeyPoint + pad ; /* top of the strings */
b75a7d8f 379
374ca955
A
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);
b75a7d8f 383
374ca955 384 /* write the root item */
b75a7d8f
A
385 udata_write32(mem, root);
386
374ca955
A
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 indexes[URES_INDEX_LENGTH]= URES_INDEX_TOP;
397 indexes[URES_INDEX_STRINGS_TOP]= (int32_t)(usedOffset>>2);
398 indexes[URES_INDEX_RESOURCES_TOP]= (int32_t)(top>>2);
399 indexes[URES_INDEX_BUNDLE_TOP]= indexes[URES_INDEX_RESOURCES_TOP];
400 indexes[URES_INDEX_MAX_TABLE_LENGTH]= bundle->fMaxTableLength;
401
402 /* write the indexes[] */
403 udata_writeBlock(mem, indexes, sizeof(indexes));
404
405 /* write the table key strings */
406 udata_writeBlock(mem, bundle->fKeys+URES_STRINGS_BOTTOM,
407 bundle->fKeyPoint-URES_STRINGS_BOTTOM);
408
409 /* write the padding bytes after the table key strings */
b75a7d8f
A
410 udata_writePadding(mem, pad);
411
374ca955 412 /* write all of the bundle contents: the root item and its children */
b75a7d8f
A
413 usedOffset = res_write(mem, bundle->fRoot, usedOffset, status);
414
374ca955
A
415 size = udata_finish(mem, status);
416 if(top != size) {
417 fprintf(stderr, "genrb error: wrote %u bytes but counted %u\n",
418 (int)size, (int)top);
419 *status = U_INTERNAL_PROGRAM_ERROR;
420 }
b75a7d8f
A
421}
422
423/* Opening Functions */
374ca955 424struct SResource* res_open(const struct UString* comment, UErrorCode* status){
b75a7d8f
A
425 struct SResource *res;
426
427 if (U_FAILURE(*status)) {
428 return NULL;
429 }
430
431 res = (struct SResource *) uprv_malloc(sizeof(struct SResource));
432
433 if (res == NULL) {
434 *status = U_MEMORY_ALLOCATION_ERROR;
435 return NULL;
436 }
374ca955
A
437 uprv_memset(res, 0, sizeof(struct SResource));
438
439 res->fComment = NULL;
440 if(comment != NULL){
441 res->fComment = (struct UString *) uprv_malloc(sizeof(struct UString));
442 if(res->fComment == NULL){
443 *status = U_MEMORY_ALLOCATION_ERROR;
444 return NULL;
445 }
446 ustr_init(res->fComment);
447 ustr_cpy(res->fComment, comment, status);
448 }
449 return res;
450
451}
452struct SResource* table_open(struct SRBRoot *bundle, char *tag, const struct UString* comment, UErrorCode *status) {
453
454 struct SResource *res = res_open(comment, status);
b75a7d8f 455
b75a7d8f
A
456 res->fKey = bundle_addtag(bundle, tag, status);
457
458 if (U_FAILURE(*status)) {
374ca955 459 uprv_free(res->fComment);
b75a7d8f
A
460 uprv_free(res);
461 return NULL;
462 }
463
464 res->fNext = NULL;
374ca955
A
465
466 /*
467 * always open a table not a table32 in case it remains empty -
468 * try to use table32 only when necessary
469 */
470 res->fType = URES_TABLE;
b75a7d8f
A
471 res->fSize = sizeof(uint16_t);
472
473 res->u.fTable.fCount = 0;
474 res->u.fTable.fChildrenSize = 0;
475 res->u.fTable.fFirst = NULL;
476 res->u.fTable.fRoot = bundle;
477
478 return res;
479}
480
374ca955 481struct SResource* array_open(struct SRBRoot *bundle, char *tag, const struct UString* comment, UErrorCode *status) {
b75a7d8f 482
374ca955 483 struct SResource *res = res_open(comment, status);
b75a7d8f 484
374ca955 485 if (U_FAILURE(*status)) {
b75a7d8f
A
486 return NULL;
487 }
488
489 res->fType = URES_ARRAY;
490 res->fKey = bundle_addtag(bundle, tag, status);
491
492 if (U_FAILURE(*status)) {
374ca955 493 uprv_free(res->fComment);
b75a7d8f
A
494 uprv_free(res);
495 return NULL;
496 }
497
498 res->fNext = NULL;
499 res->fSize = sizeof(int32_t);
500
501 res->u.fArray.fCount = 0;
502 res->u.fArray.fChildrenSize = 0;
503 res->u.fArray.fFirst = NULL;
504 res->u.fArray.fLast = NULL;
505
506 return res;
507}
508
374ca955
A
509struct SResource *string_open(struct SRBRoot *bundle, char *tag, const UChar *value, int32_t len, const struct UString* comment, UErrorCode *status) {
510 struct SResource *res = res_open(comment, status);
b75a7d8f
A
511
512 if (U_FAILURE(*status)) {
513 return NULL;
514 }
515
b75a7d8f
A
516 res->fType = URES_STRING;
517 res->fKey = bundle_addtag(bundle, tag, status);
518
519 if (U_FAILURE(*status)) {
374ca955 520 uprv_free(res->fComment);
b75a7d8f
A
521 uprv_free(res);
522 return NULL;
523 }
524
525 res->fNext = NULL;
526
527 res->u.fString.fLength = len;
528 res->u.fString.fChars = (UChar *) uprv_malloc(sizeof(UChar) * (len + 1));
529
530 if (res->u.fString.fChars == NULL) {
531 *status = U_MEMORY_ALLOCATION_ERROR;
532 uprv_free(res);
533 return NULL;
534 }
535
536 uprv_memcpy(res->u.fString.fChars, value, sizeof(UChar) * (len + 1));
537 res->fSize = sizeof(int32_t) + sizeof(UChar) * (len+1);
538
539 return res;
540}
541
542/* TODO: make alias_open and string_open use the same code */
374ca955
A
543struct SResource *alias_open(struct SRBRoot *bundle, char *tag, UChar *value, int32_t len, const struct UString* comment, UErrorCode *status) {
544 struct SResource *res = res_open(comment, status);
b75a7d8f
A
545
546 if (U_FAILURE(*status)) {
547 return NULL;
548 }
549
b75a7d8f
A
550 res->fType = URES_ALIAS;
551 res->fKey = bundle_addtag(bundle, tag, status);
552
553 if (U_FAILURE(*status)) {
374ca955 554 uprv_free(res->fComment);
b75a7d8f
A
555 uprv_free(res);
556 return NULL;
557 }
558
559 res->fNext = NULL;
560
561 res->u.fString.fLength = len;
562 res->u.fString.fChars = (UChar *) uprv_malloc(sizeof(UChar) * (len + 1));
563
564 if (res->u.fString.fChars == NULL) {
565 *status = U_MEMORY_ALLOCATION_ERROR;
566 uprv_free(res);
567 return NULL;
568 }
569
570 uprv_memcpy(res->u.fString.fChars, value, sizeof(UChar) * (len + 1));
571 res->fSize = sizeof(int32_t) + sizeof(UChar) * (len + 1);
572
573 return res;
574}
575
576
374ca955
A
577struct SResource* intvector_open(struct SRBRoot *bundle, char *tag, const struct UString* comment, UErrorCode *status) {
578 struct SResource *res = res_open(comment, status);
b75a7d8f
A
579
580 if (U_FAILURE(*status)) {
581 return NULL;
582 }
583
b75a7d8f
A
584 res->fType = URES_INT_VECTOR;
585 res->fKey = bundle_addtag(bundle, tag, status);
586
587 if (U_FAILURE(*status)) {
374ca955 588 uprv_free(res->fComment);
b75a7d8f
A
589 uprv_free(res);
590 return NULL;
591 }
592
593 res->fNext = NULL;
594 res->fSize = sizeof(int32_t);
595
596 res->u.fIntVector.fCount = 0;
597 res->u.fIntVector.fArray = (uint32_t *) uprv_malloc(sizeof(uint32_t) * RESLIST_MAX_INT_VECTOR);
598
599 if (res->u.fIntVector.fArray == NULL) {
600 *status = U_MEMORY_ALLOCATION_ERROR;
601 uprv_free(res);
602 return NULL;
603 }
604
605 return res;
606}
607
374ca955
A
608struct SResource *int_open(struct SRBRoot *bundle, char *tag, int32_t value, const struct UString* comment, UErrorCode *status) {
609 struct SResource *res = res_open(comment, status);
b75a7d8f
A
610
611 if (U_FAILURE(*status)) {
612 return NULL;
613 }
614
b75a7d8f
A
615 res->fType = URES_INT;
616 res->fKey = bundle_addtag(bundle, tag, status);
617
618 if (U_FAILURE(*status)) {
374ca955 619 uprv_free(res->fComment);
b75a7d8f
A
620 uprv_free(res);
621 return NULL;
622 }
623
624 res->fSize = 0;
625 res->fNext = NULL;
626 res->u.fIntValue.fValue = value;
627
628 return res;
629}
630
374ca955
A
631struct SResource *bin_open(struct SRBRoot *bundle, const char *tag, uint32_t length, uint8_t *data, const char* fileName, const struct UString* comment, UErrorCode *status) {
632 struct SResource *res = res_open(comment, status);
b75a7d8f
A
633
634 if (U_FAILURE(*status)) {
635 return NULL;
636 }
637
b75a7d8f
A
638 res->fType = URES_BINARY;
639 res->fKey = bundle_addtag(bundle, tag, status);
640
641 if (U_FAILURE(*status)) {
374ca955 642 uprv_free(res->fComment);
b75a7d8f
A
643 uprv_free(res);
644 return NULL;
645 }
374ca955 646
b75a7d8f
A
647 res->fNext = NULL;
648
649 res->u.fBinaryValue.fLength = length;
650 res->u.fBinaryValue.fFileName = NULL;
651 if(fileName!=NULL && uprv_strcmp(fileName, "") !=0){
652 res->u.fBinaryValue.fFileName = (char*) uprv_malloc(sizeof(char) * (uprv_strlen(fileName)+1));
653 uprv_strcpy(res->u.fBinaryValue.fFileName,fileName);
654 }
655 if (length > 0) {
656 res->u.fBinaryValue.fData = (uint8_t *) uprv_malloc(sizeof(uint8_t) * length);
657
658 if (res->u.fBinaryValue.fData == NULL) {
659 *status = U_MEMORY_ALLOCATION_ERROR;
660 uprv_free(res);
661 return NULL;
662 }
663
664 uprv_memcpy(res->u.fBinaryValue.fData, data, length);
665 }
666 else {
667 res->u.fBinaryValue.fData = NULL;
668 }
669
670 res->fSize = sizeof(int32_t) + sizeof(uint8_t) * length + BIN_ALIGNMENT;
671
672 return res;
673}
674
374ca955 675struct SRBRoot *bundle_open(const struct UString* comment, UErrorCode *status) {
b75a7d8f
A
676 struct SRBRoot *bundle = NULL;
677
678 if (U_FAILURE(*status)) {
679 return NULL;
680 }
681
682 bundle = (struct SRBRoot *) uprv_malloc(sizeof(struct SRBRoot));
683
684 if (bundle == NULL) {
685 *status = U_MEMORY_ALLOCATION_ERROR;
686 return 0;
687 }
374ca955 688 uprv_memset(bundle, 0, sizeof(struct SRBRoot));
b75a7d8f
A
689
690 bundle->fLocale = NULL;
374ca955 691
b75a7d8f 692 bundle->fKeys = (char *) uprv_malloc(sizeof(char) * KEY_SPACE_SIZE);
374ca955
A
693 bundle->fKeysCapacity = KEY_SPACE_SIZE;
694
695 if(comment != NULL){
696
697 }
b75a7d8f
A
698
699 if (bundle->fKeys == NULL) {
700 *status = U_MEMORY_ALLOCATION_ERROR;
701 uprv_free(bundle);
702 return NULL;
703 }
704
374ca955
A
705 /* formatVersion 1.1: start fKeyPoint after the root item and indexes[] */
706 bundle->fKeyPoint = URES_STRINGS_BOTTOM;
707 uprv_memset(bundle->fKeys, 0, URES_STRINGS_BOTTOM);
708
b75a7d8f 709 bundle->fCount = 0;
374ca955 710 bundle->fRoot = table_open(bundle, NULL, comment, status);
b75a7d8f
A
711
712 if (bundle->fRoot == NULL || U_FAILURE(*status)) {
374ca955
A
713 if (U_SUCCESS(*status)) {
714 *status = U_MEMORY_ALLOCATION_ERROR;
715 }
b75a7d8f
A
716
717 uprv_free(bundle->fKeys);
718 uprv_free(bundle);
719
720 return NULL;
721 }
722
723 return bundle;
724}
725
726/* Closing Functions */
727void table_close(struct SResource *table, UErrorCode *status) {
728 struct SResource *current = NULL;
729 struct SResource *prev = NULL;
730
731 current = table->u.fTable.fFirst;
732
733 while (current != NULL) {
734 prev = current;
735 current = current->fNext;
736
737 res_close(prev, status);
738 }
739
740 table->u.fTable.fFirst = NULL;
741}
742
743void array_close(struct SResource *array, UErrorCode *status) {
744 struct SResource *current = NULL;
745 struct SResource *prev = NULL;
746
747 current = array->u.fArray.fFirst;
748
749 while (current != NULL) {
750 prev = current;
751 current = current->fNext;
752
753 res_close(prev, status);
754 }
755 array->u.fArray.fFirst = NULL;
756}
757
758void string_close(struct SResource *string, UErrorCode *status) {
759 if (string->u.fString.fChars != NULL) {
760 uprv_free(string->u.fString.fChars);
761 string->u.fString.fChars =NULL;
762 }
763}
764
765void alias_close(struct SResource *alias, UErrorCode *status) {
766 if (alias->u.fString.fChars != NULL) {
767 uprv_free(alias->u.fString.fChars);
768 alias->u.fString.fChars =NULL;
769 }
770}
771
772void intvector_close(struct SResource *intvector, UErrorCode *status) {
773 if (intvector->u.fIntVector.fArray != NULL) {
774 uprv_free(intvector->u.fIntVector.fArray);
775 intvector->u.fIntVector.fArray =NULL;
776 }
777}
778
779void int_close(struct SResource *intres, UErrorCode *status) {
780 /* Intentionally left blank */
781}
782
783void bin_close(struct SResource *binres, UErrorCode *status) {
784 if (binres->u.fBinaryValue.fData != NULL) {
785 uprv_free(binres->u.fBinaryValue.fData);
786 binres->u.fBinaryValue.fData = NULL;
787 }
788}
789
790void res_close(struct SResource *res, UErrorCode *status) {
791 if (res != NULL) {
792 switch(res->fType) {
793 case URES_STRING:
794 string_close(res, status);
795 break;
796 case URES_ALIAS:
797 alias_close(res, status);
798 break;
799 case URES_INT_VECTOR:
800 intvector_close(res, status);
801 break;
802 case URES_BINARY:
803 bin_close(res, status);
804 break;
805 case URES_INT:
806 int_close(res, status);
807 break;
808 case URES_ARRAY:
809 array_close(res, status);
810 break;
374ca955
A
811 case URES_TABLE:
812 case URES_TABLE32:
b75a7d8f
A
813 table_close(res, status);
814 break;
815 default:
816 /* Shouldn't happen */
817 break;
818 }
819
820 uprv_free(res);
821 }
822}
823
824void bundle_close(struct SRBRoot *bundle, UErrorCode *status) {
825 struct SResource *current = NULL;
826 struct SResource *prev = NULL;
827
828 if (bundle->fRoot != NULL) {
829 current = bundle->fRoot->u.fTable.fFirst;
830
831 while (current != NULL) {
832 prev = current;
833 current = current->fNext;
834
835 res_close(prev, status);
836 }
837
838 uprv_free(bundle->fRoot);
839 }
840
841 if (bundle->fLocale != NULL) {
842 uprv_free(bundle->fLocale);
843 }
844
845 if (bundle->fKeys != NULL) {
846 uprv_free(bundle->fKeys);
847 }
848
849 uprv_free(bundle);
850}
851
852/* Adding Functions */
853void table_add(struct SResource *table, struct SResource *res, int linenumber, UErrorCode *status) {
854 struct SResource *current = NULL;
855 struct SResource *prev = NULL;
856 struct SResTable *list;
857
858 if (U_FAILURE(*status)) {
859 return;
860 }
861
862 /* remember this linenumber to report to the user if there is a duplicate key */
863 res->line = linenumber;
864
865 /* here we need to traverse the list */
866 list = &(table->u.fTable);
867
374ca955
A
868 if(table->fType == URES_TABLE && res->fKey > 0xffff) {
869 /* this table straddles the 64k strings boundary, update to a table32 */
870 table->fType = URES_TABLE32;
871
872 /*
873 * increase the size because count and each string offset
874 * increase from uint16_t to int32_t
875 */
876 table->fSize += (1 + list->fCount) * 2;
877 }
878
b75a7d8f 879 ++(list->fCount);
374ca955
A
880 if(list->fCount > (uint32_t)list->fRoot->fMaxTableLength) {
881 list->fRoot->fMaxTableLength = list->fCount;
882 }
883
884 /*
885 * URES_TABLE: 6 bytes = 1 uint16_t key string offset + 1 uint32_t Resource
886 * URES_TABLE32: 8 bytes = 1 int32_t key string offset + 1 uint32_t Resource
887 */
888 table->fSize += table->fType == URES_TABLE ? 6 : 8;
b75a7d8f
A
889
890 table->u.fTable.fChildrenSize += res->fSize + calcPadding(res->fSize);
891
374ca955 892 if (res->fType == URES_TABLE || res->fType == URES_TABLE32) {
b75a7d8f
A
893 table->u.fTable.fChildrenSize += res->u.fTable.fChildrenSize;
894 } else if (res->fType == URES_ARRAY) {
895 table->u.fTable.fChildrenSize += res->u.fArray.fChildrenSize;
896 }
897
898 /* is list still empty? */
899 if (list->fFirst == NULL) {
900 list->fFirst = res;
901 res->fNext = NULL;
902 return;
903 }
904
905 current = list->fFirst;
906
907 while (current != NULL) {
908 if (uprv_strcmp(((list->fRoot->fKeys) + (current->fKey)), ((list->fRoot->fKeys) + (res->fKey))) < 0) {
909 prev = current;
910 current = current->fNext;
911 } else if (uprv_strcmp(((list->fRoot->fKeys) + (current->fKey)), ((list->fRoot->fKeys) + (res->fKey))) > 0) {
912 /* we're either in front of list, or in middle */
913 if (prev == NULL) {
914 /* front of the list */
915 list->fFirst = res;
916 } else {
917 /* middle of the list */
918 prev->fNext = res;
919 }
920
921 res->fNext = current;
922 return;
923 } else {
924 /* Key already exists! ERROR! */
925 error(linenumber, "duplicate key '%s' in table, first appeared at line %d", list->fRoot->fKeys + current->fKey, current->line);
926 *status = U_UNSUPPORTED_ERROR;
927 return;
928 }
929 }
930
931 /* end of list */
932 prev->fNext = res;
933 res->fNext = NULL;
934}
935
936void array_add(struct SResource *array, struct SResource *res, UErrorCode *status) {
937 if (U_FAILURE(*status)) {
938 return;
939 }
940
941 if (array->u.fArray.fFirst == NULL) {
942 array->u.fArray.fFirst = res;
943 array->u.fArray.fLast = res;
944 } else {
945 array->u.fArray.fLast->fNext = res;
946 array->u.fArray.fLast = res;
947 }
948
949 (array->u.fArray.fCount)++;
950
951 array->fSize += sizeof(uint32_t);
952 array->u.fArray.fChildrenSize += res->fSize + calcPadding(res->fSize);
953
374ca955 954 if (res->fType == URES_TABLE || res->fType == URES_TABLE32) {
b75a7d8f
A
955 array->u.fArray.fChildrenSize += res->u.fTable.fChildrenSize;
956 } else if (res->fType == URES_ARRAY) {
957 array->u.fArray.fChildrenSize += res->u.fArray.fChildrenSize;
958 }
959}
960
961void intvector_add(struct SResource *intvector, int32_t value, UErrorCode *status) {
962 if (U_FAILURE(*status)) {
963 return;
964 }
965
966 *(intvector->u.fIntVector.fArray + intvector->u.fIntVector.fCount) = value;
967 intvector->u.fIntVector.fCount++;
968
969 intvector->fSize += sizeof(uint32_t);
970}
971
972/* Misc Functions */
973
974void bundle_setlocale(struct SRBRoot *bundle, UChar *locale, UErrorCode *status) {
975
976 if(U_FAILURE(*status)) {
977 return;
978 }
979
980 if (bundle->fLocale!=NULL) {
981 uprv_free(bundle->fLocale);
982 }
983
984 bundle->fLocale= (char*) uprv_malloc(sizeof(char) * (u_strlen(locale)+1));
985
986 if(bundle->fLocale == NULL) {
987 *status = U_MEMORY_ALLOCATION_ERROR;
988 return;
989 }
990
991 /*u_strcpy(bundle->fLocale, locale);*/
992 u_UCharsToChars(locale, bundle->fLocale, u_strlen(locale)+1);
993
994}
995
374ca955
A
996
997int32_t
998bundle_addtag(struct SRBRoot *bundle, const char *tag, UErrorCode *status) {
999 int32_t keypos, length;
b75a7d8f
A
1000
1001 if (U_FAILURE(*status)) {
374ca955 1002 return -1;
b75a7d8f
A
1003 }
1004
1005 if (tag == NULL) {
374ca955
A
1006 /* do not set an error: the root table has a NULL tag */
1007 return -1;
b75a7d8f
A
1008 }
1009
374ca955 1010 keypos = bundle->fKeyPoint;
b75a7d8f 1011
374ca955 1012 bundle->fKeyPoint += length = (int32_t) (uprv_strlen(tag) + 1);
b75a7d8f 1013
374ca955
A
1014 if (bundle->fKeyPoint >= bundle->fKeysCapacity) {
1015 /* overflow - resize the keys buffer */
1016 bundle->fKeysCapacity += KEY_SPACE_SIZE;
1017 bundle->fKeys = uprv_realloc(bundle->fKeys, bundle->fKeysCapacity);
1018 if(bundle->fKeys == NULL) {
1019 *status = U_MEMORY_ALLOCATION_ERROR;
1020 return -1;
1021 }
b75a7d8f
A
1022 }
1023
374ca955 1024 uprv_memcpy(bundle->fKeys + keypos, tag, length);
b75a7d8f
A
1025
1026 return keypos;
1027}