2 *******************************************************************************
4 * Copyright (C) 2000-2008, International Business Machines
5 * Corporation and others. All Rights Reserved.
7 *******************************************************************************
11 * Modification History:
13 * Date Name Description
14 * 02/21/00 weiv Creation.
15 *******************************************************************************
22 #include "unicode/ures.h"
23 #include "unicode/putil.h"
26 #define BIN_ALIGNMENT 16
28 static UBool gIncludeCopyright
= FALSE
;
31 * res_none() returns the address of kNoResource,
32 * for use in non-error cases when no resource is to be added to the bundle.
33 * (NULL is used in error cases.)
35 static struct SResource kNoResource
= { RES_NONE
};
37 uint32_t res_write(UNewDataMemory
*mem
, struct SResource
*res
,
38 uint32_t usedOffset
, UErrorCode
*status
);
40 static const UDataInfo dataInfo
= {
49 {0x52, 0x65, 0x73, 0x42}, /* dataFormat="resb" */
50 {1, 2, 0, 0}, /* formatVersion */
51 {1, 4, 0, 0} /* dataVersion take a look at version inside parsed resb*/
54 static uint8_t calcPadding(uint32_t size
) {
55 /* returns space we need to pad */
56 return (uint8_t) ((size
% sizeof(uint32_t)) ? (sizeof(uint32_t) - (size
% sizeof(uint32_t))) : 0);
60 void setIncludeCopyright(UBool val
){
61 gIncludeCopyright
=val
;
64 UBool
getIncludeCopyright(void){
65 return gIncludeCopyright
;
68 /* Writing Functions */
69 static uint32_t string_write(UNewDataMemory
*mem
, struct SResource
*res
,
70 uint32_t usedOffset
, UErrorCode
*status
) {
71 udata_write32(mem
, res
->u
.fString
.fLength
);
72 udata_writeUString(mem
, res
->u
.fString
.fChars
, res
->u
.fString
.fLength
+ 1);
73 udata_writePadding(mem
, calcPadding(res
->fSize
));
78 /* Writing Functions */
79 static uint32_t alias_write(UNewDataMemory
*mem
, struct SResource
*res
,
80 uint32_t usedOffset
, UErrorCode
*status
) {
81 udata_write32(mem
, res
->u
.fString
.fLength
);
82 udata_writeUString(mem
, res
->u
.fString
.fChars
, res
->u
.fString
.fLength
+ 1);
83 udata_writePadding(mem
, calcPadding(res
->fSize
));
88 static uint32_t array_write(UNewDataMemory
*mem
, struct SResource
*res
,
89 uint32_t usedOffset
, UErrorCode
*status
) {
90 uint32_t *resources
= NULL
;
93 struct SResource
*current
= NULL
;
95 if (U_FAILURE(*status
)) {
99 if (res
->u
.fArray
.fCount
> 0) {
100 resources
= (uint32_t *) uprv_malloc(sizeof(uint32_t) * res
->u
.fArray
.fCount
);
102 if (resources
== NULL
) {
103 *status
= U_MEMORY_ALLOCATION_ERROR
;
107 current
= res
->u
.fArray
.fFirst
;
110 while (current
!= NULL
) {
111 if (current
->fType
== URES_INT
) {
112 resources
[i
] = (current
->fType
<< 28) | (current
->u
.fIntValue
.fValue
& 0xFFFFFFF);
113 } else if (current
->fType
== URES_BINARY
) {
114 uint32_t uo
= usedOffset
;
116 usedOffset
= res_write(mem
, current
, usedOffset
, status
);
117 resources
[i
] = (current
->fType
<< 28) | (usedOffset
>> 2);
118 usedOffset
+= current
->fSize
+ calcPadding(current
->fSize
) - (usedOffset
- uo
);
120 usedOffset
= res_write(mem
, current
, usedOffset
, status
);
121 resources
[i
] = (current
->fType
<< 28) | (usedOffset
>> 2);
122 usedOffset
+= current
->fSize
+ calcPadding(current
->fSize
);
126 current
= current
->fNext
;
129 /* usedOffset += res->fSize + pad; */
131 udata_write32(mem
, res
->u
.fArray
.fCount
);
132 udata_writeBlock(mem
, resources
, sizeof(uint32_t) * res
->u
.fArray
.fCount
);
133 uprv_free(resources
);
136 udata_write32(mem
, 0);
142 static uint32_t intvector_write(UNewDataMemory
*mem
, struct SResource
*res
,
143 uint32_t usedOffset
, UErrorCode
*status
) {
145 udata_write32(mem
, res
->u
.fIntVector
.fCount
);
146 for(i
= 0; i
<res
->u
.fIntVector
.fCount
; i
++) {
147 udata_write32(mem
, res
->u
.fIntVector
.fArray
[i
]);
153 static uint32_t bin_write(UNewDataMemory
*mem
, struct SResource
*res
,
154 uint32_t usedOffset
, UErrorCode
*status
) {
156 uint32_t extrapad
= calcPadding(res
->fSize
);
157 uint32_t dataStart
= usedOffset
+ sizeof(res
->u
.fBinaryValue
.fLength
);
159 if (dataStart
% BIN_ALIGNMENT
) {
160 pad
= (BIN_ALIGNMENT
- dataStart
% BIN_ALIGNMENT
);
161 udata_writePadding(mem
, pad
);
165 udata_write32(mem
, res
->u
.fBinaryValue
.fLength
);
166 if (res
->u
.fBinaryValue
.fLength
> 0) {
167 udata_writeBlock(mem
, res
->u
.fBinaryValue
.fData
, res
->u
.fBinaryValue
.fLength
);
169 udata_writePadding(mem
, (BIN_ALIGNMENT
- pad
+ extrapad
));
174 static uint32_t int_write(UNewDataMemory
*mem
, struct SResource
*res
,
175 uint32_t usedOffset
, UErrorCode
*status
) {
179 static uint32_t table_write(UNewDataMemory
*mem
, struct SResource
*res
,
180 uint32_t usedOffset
, UErrorCode
*status
) {
183 uint16_t *keys16
= NULL
;
184 int32_t *keys32
= NULL
;
185 uint32_t *resources
= NULL
;
187 struct SResource
*current
= NULL
;
189 if (U_FAILURE(*status
)) {
193 pad
= calcPadding(res
->fSize
);
195 if (res
->u
.fTable
.fCount
> 0) {
196 if(res
->fType
== URES_TABLE
) {
197 keys16
= (uint16_t *) uprv_malloc(sizeof(uint16_t) * res
->u
.fTable
.fCount
);
198 if (keys16
== NULL
) {
199 *status
= U_MEMORY_ALLOCATION_ERROR
;
203 keys32
= (int32_t *) uprv_malloc(sizeof(int32_t) * res
->u
.fTable
.fCount
);
204 if (keys32
== NULL
) {
205 *status
= U_MEMORY_ALLOCATION_ERROR
;
210 resources
= (uint32_t *) uprv_malloc(sizeof(uint32_t) * res
->u
.fTable
.fCount
);
212 if (resources
== NULL
) {
215 *status
= U_MEMORY_ALLOCATION_ERROR
;
219 current
= res
->u
.fTable
.fFirst
;
222 while (current
!= NULL
) {
223 assert(i
< res
->u
.fTable
.fCount
);
225 /* where the key is */
226 if(res
->fType
== URES_TABLE
) {
227 keys16
[i
] = (uint16_t) current
->fKey
;
229 keys32
[i
] = current
->fKey
;
232 if (current
->fType
== URES_INT
) {
233 resources
[i
] = (current
->fType
<< 28) | (current
->u
.fIntValue
.fValue
& 0xFFFFFFF);
234 } else if (current
->fType
== URES_BINARY
) {
235 uint32_t uo
= usedOffset
;
237 usedOffset
= res_write(mem
, current
, usedOffset
, status
);
238 resources
[i
] = (current
->fType
<< 28) | (usedOffset
>> 2);
239 usedOffset
+= current
->fSize
+ calcPadding(current
->fSize
) - (usedOffset
- uo
);
241 usedOffset
= res_write(mem
, current
, usedOffset
, status
);
242 resources
[i
] = (current
->fType
<< 28) | (usedOffset
>> 2);
243 usedOffset
+= current
->fSize
+ calcPadding(current
->fSize
);
247 current
= current
->fNext
;
250 if(res
->fType
== URES_TABLE
) {
251 udata_write16(mem
, (uint16_t)res
->u
.fTable
.fCount
);
253 udata_writeBlock(mem
, keys16
, sizeof(uint16_t) * res
->u
.fTable
.fCount
);
254 udata_writePadding(mem
, pad
);
256 udata_write32(mem
, res
->u
.fTable
.fCount
);
258 udata_writeBlock(mem
, keys32
, sizeof(int32_t) * res
->u
.fTable
.fCount
);
261 udata_writeBlock(mem
, resources
, sizeof(uint32_t) * res
->u
.fTable
.fCount
);
265 uprv_free(resources
);
268 if(res
->fType
== URES_TABLE
) {
269 udata_write16(mem
, 0);
270 udata_writePadding(mem
, pad
);
272 udata_write32(mem
, 0);
279 uint32_t res_write(UNewDataMemory
*mem
, struct SResource
*res
,
280 uint32_t usedOffset
, UErrorCode
*status
) {
281 if (U_FAILURE(*status
)) {
286 switch (res
->fType
) {
288 return string_write (mem
, res
, usedOffset
, status
);
290 return alias_write (mem
, res
, usedOffset
, status
);
291 case URES_INT_VECTOR
:
292 return intvector_write (mem
, res
, usedOffset
, status
);
294 return bin_write (mem
, res
, usedOffset
, status
);
296 return int_write (mem
, res
, usedOffset
, status
);
298 return array_write (mem
, res
, usedOffset
, status
);
301 return table_write (mem
, res
, usedOffset
, status
);
308 *status
= U_INTERNAL_PROGRAM_ERROR
;
312 void bundle_write(struct SRBRoot
*bundle
, const char *outputDir
, const char *outputPkg
, char *writtenFilename
, int writtenFilenameLen
, UErrorCode
*status
) {
313 UNewDataMemory
*mem
= NULL
;
316 uint32_t usedOffset
= 0;
319 int32_t indexes
[URES_INDEX_TOP
];
321 if (writtenFilename
&& writtenFilenameLen
) {
322 *writtenFilename
= 0;
325 if (U_FAILURE(*status
)) {
329 if (writtenFilename
) {
330 int32_t off
= 0, len
= 0;
332 len
= (int32_t)uprv_strlen(outputDir
);
333 if (len
> writtenFilenameLen
) {
334 len
= writtenFilenameLen
;
336 uprv_strncpy(writtenFilename
, outputDir
, len
);
338 if (writtenFilenameLen
-= len
) {
340 writtenFilename
[off
] = U_FILE_SEP_CHAR
;
341 if (--writtenFilenameLen
) {
343 if(outputPkg
!= NULL
)
345 uprv_strcpy(writtenFilename
+off
, outputPkg
);
346 off
+= (int32_t)uprv_strlen(outputPkg
);
347 writtenFilename
[off
] = '_';
351 len
= (int32_t)uprv_strlen(bundle
->fLocale
);
352 if (len
> writtenFilenameLen
) {
353 len
= writtenFilenameLen
;
355 uprv_strncpy(writtenFilename
+ off
, bundle
->fLocale
, len
);
356 if (writtenFilenameLen
-= len
) {
359 if (len
> writtenFilenameLen
) {
360 len
= writtenFilenameLen
;
362 uprv_strncpy(writtenFilename
+ off
, ".res", len
);
370 uprv_strcpy(dataName
, outputPkg
);
371 uprv_strcat(dataName
, "_");
372 uprv_strcat(dataName
, bundle
->fLocale
);
376 uprv_strcpy(dataName
, bundle
->fLocale
);
379 mem
= udata_create(outputDir
, "res", dataName
, &dataInfo
, (gIncludeCopyright
==TRUE
)? U_COPYRIGHT_STRING
:NULL
, status
);
380 if(U_FAILURE(*status
)){
383 pad
= calcPadding(bundle
->fKeyPoint
);
385 usedOffset
= bundle
->fKeyPoint
+ pad
; /* top of the strings */
387 /* we're gonna put the main table at the end */
388 top
= usedOffset
+ bundle
->fRoot
->u
.fTable
.fChildrenSize
;
389 root
= (top
) >> 2 | (bundle
->fRoot
->fType
<< 28);
391 /* write the root item */
392 udata_write32(mem
, root
);
394 /* add to top the size of the root item */
395 top
+= bundle
->fRoot
->fSize
;
396 top
+= calcPadding(top
);
399 * formatVersion 1.1 (ICU 2.8):
400 * write int32_t indexes[] after root and before the strings
401 * to make it easier to parse resource bundles in icuswap or from Java etc.
403 uprv_memset(indexes
, 0, sizeof(indexes
));
404 indexes
[URES_INDEX_LENGTH
]= URES_INDEX_TOP
;
405 indexes
[URES_INDEX_STRINGS_TOP
]= (int32_t)(usedOffset
>>2);
406 indexes
[URES_INDEX_RESOURCES_TOP
]= (int32_t)(top
>>2);
407 indexes
[URES_INDEX_BUNDLE_TOP
]= indexes
[URES_INDEX_RESOURCES_TOP
];
408 indexes
[URES_INDEX_MAX_TABLE_LENGTH
]= bundle
->fMaxTableLength
;
411 * formatVersion 1.2 (ICU 3.6):
412 * write indexes[URES_INDEX_ATTRIBUTES] with URES_ATT_NO_FALLBACK set or not set
413 * the memset() above initialized all indexes[] to 0
415 if(bundle
->noFallback
) {
416 indexes
[URES_INDEX_ATTRIBUTES
]=URES_ATT_NO_FALLBACK
;
419 /* write the indexes[] */
420 udata_writeBlock(mem
, indexes
, sizeof(indexes
));
422 /* write the table key strings */
423 udata_writeBlock(mem
, bundle
->fKeys
+URES_STRINGS_BOTTOM
,
424 bundle
->fKeyPoint
-URES_STRINGS_BOTTOM
);
426 /* write the padding bytes after the table key strings */
427 udata_writePadding(mem
, pad
);
429 /* write all of the bundle contents: the root item and its children */
430 usedOffset
= res_write(mem
, bundle
->fRoot
, usedOffset
, status
);
432 size
= udata_finish(mem
, status
);
434 fprintf(stderr
, "genrb error: wrote %u bytes but counted %u\n",
435 (int)size
, (int)top
);
436 *status
= U_INTERNAL_PROGRAM_ERROR
;
440 /* Opening Functions */
441 struct SResource
* res_open(const struct UString
* comment
, UErrorCode
* status
){
442 struct SResource
*res
;
444 if (U_FAILURE(*status
)) {
448 res
= (struct SResource
*) uprv_malloc(sizeof(struct SResource
));
451 *status
= U_MEMORY_ALLOCATION_ERROR
;
454 uprv_memset(res
, 0, sizeof(struct SResource
));
456 ustr_init(&res
->fComment
);
458 ustr_cpy(&res
->fComment
, comment
, status
);
464 struct SResource
* res_none() {
468 struct SResource
* table_open(struct SRBRoot
*bundle
, char *tag
, const struct UString
* comment
, UErrorCode
*status
) {
470 struct SResource
*res
= res_open(comment
, status
);
472 res
->fKey
= bundle_addtag(bundle
, tag
, status
);
474 if (U_FAILURE(*status
)) {
482 * always open a table not a table32 in case it remains empty -
483 * try to use table32 only when necessary
485 res
->fType
= URES_TABLE
;
486 res
->fSize
= sizeof(uint16_t);
488 res
->u
.fTable
.fCount
= 0;
489 res
->u
.fTable
.fChildrenSize
= 0;
490 res
->u
.fTable
.fFirst
= NULL
;
491 res
->u
.fTable
.fRoot
= bundle
;
496 struct SResource
* array_open(struct SRBRoot
*bundle
, const char *tag
, const struct UString
* comment
, UErrorCode
*status
) {
498 struct SResource
*res
= res_open(comment
, status
);
500 if (U_FAILURE(*status
)) {
504 res
->fType
= URES_ARRAY
;
505 res
->fKey
= bundle_addtag(bundle
, tag
, status
);
507 if (U_FAILURE(*status
)) {
513 res
->fSize
= sizeof(int32_t);
515 res
->u
.fArray
.fCount
= 0;
516 res
->u
.fArray
.fChildrenSize
= 0;
517 res
->u
.fArray
.fFirst
= NULL
;
518 res
->u
.fArray
.fLast
= NULL
;
523 struct SResource
*string_open(struct SRBRoot
*bundle
, char *tag
, const UChar
*value
, int32_t len
, const struct UString
* comment
, UErrorCode
*status
) {
524 struct SResource
*res
= res_open(comment
, status
);
526 if (U_FAILURE(*status
)) {
530 res
->fType
= URES_STRING
;
531 res
->fKey
= bundle_addtag(bundle
, tag
, status
);
533 if (U_FAILURE(*status
)) {
540 res
->u
.fString
.fLength
= len
;
541 res
->u
.fString
.fChars
= (UChar
*) uprv_malloc(sizeof(UChar
) * (len
+ 1));
543 if (res
->u
.fString
.fChars
== NULL
) {
544 *status
= U_MEMORY_ALLOCATION_ERROR
;
549 uprv_memcpy(res
->u
.fString
.fChars
, value
, sizeof(UChar
) * (len
+ 1));
550 res
->fSize
= sizeof(int32_t) + sizeof(UChar
) * (len
+1);
555 /* TODO: make alias_open and string_open use the same code */
556 struct SResource
*alias_open(struct SRBRoot
*bundle
, char *tag
, UChar
*value
, int32_t len
, const struct UString
* comment
, UErrorCode
*status
) {
557 struct SResource
*res
= res_open(comment
, status
);
559 if (U_FAILURE(*status
)) {
563 res
->fType
= URES_ALIAS
;
564 res
->fKey
= bundle_addtag(bundle
, tag
, status
);
566 if (U_FAILURE(*status
)) {
573 res
->u
.fString
.fLength
= len
;
574 res
->u
.fString
.fChars
= (UChar
*) uprv_malloc(sizeof(UChar
) * (len
+ 1));
576 if (res
->u
.fString
.fChars
== NULL
) {
577 *status
= U_MEMORY_ALLOCATION_ERROR
;
582 uprv_memcpy(res
->u
.fString
.fChars
, value
, sizeof(UChar
) * (len
+ 1));
583 res
->fSize
= sizeof(int32_t) + sizeof(UChar
) * (len
+ 1);
589 struct SResource
* intvector_open(struct SRBRoot
*bundle
, char *tag
, const struct UString
* comment
, UErrorCode
*status
) {
590 struct SResource
*res
= res_open(comment
, status
);
592 if (U_FAILURE(*status
)) {
596 res
->fType
= URES_INT_VECTOR
;
597 res
->fKey
= bundle_addtag(bundle
, tag
, status
);
599 if (U_FAILURE(*status
)) {
605 res
->fSize
= sizeof(int32_t);
607 res
->u
.fIntVector
.fCount
= 0;
608 res
->u
.fIntVector
.fArray
= (uint32_t *) uprv_malloc(sizeof(uint32_t) * RESLIST_MAX_INT_VECTOR
);
610 if (res
->u
.fIntVector
.fArray
== NULL
) {
611 *status
= U_MEMORY_ALLOCATION_ERROR
;
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
);
622 if (U_FAILURE(*status
)) {
626 res
->fType
= URES_INT
;
627 res
->fKey
= bundle_addtag(bundle
, tag
, status
);
629 if (U_FAILURE(*status
)) {
636 res
->u
.fIntValue
.fValue
= value
;
641 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
) {
642 struct SResource
*res
= res_open(comment
, status
);
644 if (U_FAILURE(*status
)) {
648 res
->fType
= URES_BINARY
;
649 res
->fKey
= bundle_addtag(bundle
, tag
, status
);
651 if (U_FAILURE(*status
)) {
658 res
->u
.fBinaryValue
.fLength
= length
;
659 res
->u
.fBinaryValue
.fFileName
= NULL
;
660 if(fileName
!=NULL
&& uprv_strcmp(fileName
, "") !=0){
661 res
->u
.fBinaryValue
.fFileName
= (char*) uprv_malloc(sizeof(char) * (uprv_strlen(fileName
)+1));
662 uprv_strcpy(res
->u
.fBinaryValue
.fFileName
,fileName
);
665 res
->u
.fBinaryValue
.fData
= (uint8_t *) uprv_malloc(sizeof(uint8_t) * length
);
667 if (res
->u
.fBinaryValue
.fData
== NULL
) {
668 *status
= U_MEMORY_ALLOCATION_ERROR
;
673 uprv_memcpy(res
->u
.fBinaryValue
.fData
, data
, length
);
676 res
->u
.fBinaryValue
.fData
= NULL
;
679 res
->fSize
= sizeof(int32_t) + sizeof(uint8_t) * length
+ BIN_ALIGNMENT
;
684 struct SRBRoot
*bundle_open(const struct UString
* comment
, UErrorCode
*status
) {
685 struct SRBRoot
*bundle
= NULL
;
687 if (U_FAILURE(*status
)) {
691 bundle
= (struct SRBRoot
*) uprv_malloc(sizeof(struct SRBRoot
));
693 if (bundle
== NULL
) {
694 *status
= U_MEMORY_ALLOCATION_ERROR
;
697 uprv_memset(bundle
, 0, sizeof(struct SRBRoot
));
699 bundle
->fLocale
= NULL
;
701 bundle
->fKeys
= (char *) uprv_malloc(sizeof(char) * KEY_SPACE_SIZE
);
702 bundle
->fKeysCapacity
= KEY_SPACE_SIZE
;
708 if (bundle
->fKeys
== NULL
) {
709 *status
= U_MEMORY_ALLOCATION_ERROR
;
714 /* formatVersion 1.1: start fKeyPoint after the root item and indexes[] */
715 bundle
->fKeyPoint
= URES_STRINGS_BOTTOM
;
716 uprv_memset(bundle
->fKeys
, 0, URES_STRINGS_BOTTOM
);
719 bundle
->fRoot
= table_open(bundle
, NULL
, comment
, status
);
721 if (bundle
->fRoot
== NULL
|| U_FAILURE(*status
)) {
722 if (U_SUCCESS(*status
)) {
723 *status
= U_MEMORY_ALLOCATION_ERROR
;
726 uprv_free(bundle
->fKeys
);
735 /* Closing Functions */
736 static void table_close(struct SResource
*table
) {
737 struct SResource
*current
= NULL
;
738 struct SResource
*prev
= NULL
;
740 current
= table
->u
.fTable
.fFirst
;
742 while (current
!= NULL
) {
744 current
= current
->fNext
;
749 table
->u
.fTable
.fFirst
= NULL
;
752 static void array_close(struct SResource
*array
) {
753 struct SResource
*current
= NULL
;
754 struct SResource
*prev
= NULL
;
759 current
= array
->u
.fArray
.fFirst
;
761 while (current
!= NULL
) {
763 current
= current
->fNext
;
767 array
->u
.fArray
.fFirst
= NULL
;
770 static void string_close(struct SResource
*string
) {
771 if (string
->u
.fString
.fChars
!= NULL
) {
772 uprv_free(string
->u
.fString
.fChars
);
773 string
->u
.fString
.fChars
=NULL
;
777 static void alias_close(struct SResource
*alias
) {
778 if (alias
->u
.fString
.fChars
!= NULL
) {
779 uprv_free(alias
->u
.fString
.fChars
);
780 alias
->u
.fString
.fChars
=NULL
;
784 static void intvector_close(struct SResource
*intvector
) {
785 if (intvector
->u
.fIntVector
.fArray
!= NULL
) {
786 uprv_free(intvector
->u
.fIntVector
.fArray
);
787 intvector
->u
.fIntVector
.fArray
=NULL
;
791 static void int_close(struct SResource
*intres
) {
792 /* Intentionally left blank */
795 static void bin_close(struct SResource
*binres
) {
796 if (binres
->u
.fBinaryValue
.fData
!= NULL
) {
797 uprv_free(binres
->u
.fBinaryValue
.fData
);
798 binres
->u
.fBinaryValue
.fData
= NULL
;
802 void res_close(struct SResource
*res
) {
811 case URES_INT_VECTOR
:
812 intvector_close(res
);
828 /* Shouldn't happen */
832 ustr_deinit(&res
->fComment
);
837 void bundle_close(struct SRBRoot
*bundle
, UErrorCode
*status
) {
838 if (bundle
->fRoot
!= NULL
) {
839 res_close(bundle
->fRoot
);
842 if (bundle
->fLocale
!= NULL
) {
843 uprv_free(bundle
->fLocale
);
846 if (bundle
->fKeys
!= NULL
) {
847 uprv_free(bundle
->fKeys
);
853 /* Adding Functions */
854 void table_add(struct SResource
*table
, struct SResource
*res
, int linenumber
, UErrorCode
*status
) {
855 struct SResource
*current
= NULL
;
856 struct SResource
*prev
= NULL
;
857 struct SResTable
*list
;
859 if (U_FAILURE(*status
)) {
862 if (res
== &kNoResource
) {
866 /* remember this linenumber to report to the user if there is a duplicate key */
867 res
->line
= linenumber
;
869 /* here we need to traverse the list */
870 list
= &(table
->u
.fTable
);
872 if(table
->fType
== URES_TABLE
&& res
->fKey
> 0xffff) {
873 /* this table straddles the 64k strings boundary, update to a table32 */
874 table
->fType
= URES_TABLE32
;
877 * increase the size because count and each string offset
878 * increase from uint16_t to int32_t
880 table
->fSize
+= (1 + list
->fCount
) * 2;
884 if(list
->fCount
> (uint32_t)list
->fRoot
->fMaxTableLength
) {
885 list
->fRoot
->fMaxTableLength
= list
->fCount
;
889 * URES_TABLE: 6 bytes = 1 uint16_t key string offset + 1 uint32_t Resource
890 * URES_TABLE32: 8 bytes = 1 int32_t key string offset + 1 uint32_t Resource
892 table
->fSize
+= table
->fType
== URES_TABLE
? 6 : 8;
894 table
->u
.fTable
.fChildrenSize
+= res
->fSize
+ calcPadding(res
->fSize
);
896 if (res
->fType
== URES_TABLE
|| res
->fType
== URES_TABLE32
) {
897 table
->u
.fTable
.fChildrenSize
+= res
->u
.fTable
.fChildrenSize
;
898 } else if (res
->fType
== URES_ARRAY
) {
899 table
->u
.fTable
.fChildrenSize
+= res
->u
.fArray
.fChildrenSize
;
902 /* is list still empty? */
903 if (list
->fFirst
== NULL
) {
909 current
= list
->fFirst
;
911 while (current
!= NULL
) {
912 if (uprv_strcmp(((list
->fRoot
->fKeys
) + (current
->fKey
)), ((list
->fRoot
->fKeys
) + (res
->fKey
))) < 0) {
914 current
= current
->fNext
;
915 } else if (uprv_strcmp(((list
->fRoot
->fKeys
) + (current
->fKey
)), ((list
->fRoot
->fKeys
) + (res
->fKey
))) > 0) {
916 /* we're either in front of list, or in middle */
918 /* front of the list */
921 /* middle of the list */
925 res
->fNext
= current
;
928 /* Key already exists! ERROR! */
929 error(linenumber
, "duplicate key '%s' in table, first appeared at line %d", list
->fRoot
->fKeys
+ current
->fKey
, current
->line
);
930 *status
= U_UNSUPPORTED_ERROR
;
940 void array_add(struct SResource
*array
, struct SResource
*res
, UErrorCode
*status
) {
941 if (U_FAILURE(*status
)) {
945 if (array
->u
.fArray
.fFirst
== NULL
) {
946 array
->u
.fArray
.fFirst
= res
;
947 array
->u
.fArray
.fLast
= res
;
949 array
->u
.fArray
.fLast
->fNext
= res
;
950 array
->u
.fArray
.fLast
= res
;
953 (array
->u
.fArray
.fCount
)++;
955 array
->fSize
+= sizeof(uint32_t);
956 array
->u
.fArray
.fChildrenSize
+= res
->fSize
+ calcPadding(res
->fSize
);
958 if (res
->fType
== URES_TABLE
|| res
->fType
== URES_TABLE32
) {
959 array
->u
.fArray
.fChildrenSize
+= res
->u
.fTable
.fChildrenSize
;
960 } else if (res
->fType
== URES_ARRAY
) {
961 array
->u
.fArray
.fChildrenSize
+= res
->u
.fArray
.fChildrenSize
;
965 void intvector_add(struct SResource
*intvector
, int32_t value
, UErrorCode
*status
) {
966 if (U_FAILURE(*status
)) {
970 *(intvector
->u
.fIntVector
.fArray
+ intvector
->u
.fIntVector
.fCount
) = value
;
971 intvector
->u
.fIntVector
.fCount
++;
973 intvector
->fSize
+= sizeof(uint32_t);
978 void bundle_setlocale(struct SRBRoot
*bundle
, UChar
*locale
, UErrorCode
*status
) {
980 if(U_FAILURE(*status
)) {
984 if (bundle
->fLocale
!=NULL
) {
985 uprv_free(bundle
->fLocale
);
988 bundle
->fLocale
= (char*) uprv_malloc(sizeof(char) * (u_strlen(locale
)+1));
990 if(bundle
->fLocale
== NULL
) {
991 *status
= U_MEMORY_ALLOCATION_ERROR
;
995 /*u_strcpy(bundle->fLocale, locale);*/
996 u_UCharsToChars(locale
, bundle
->fLocale
, u_strlen(locale
)+1);
1002 bundle_addtag(struct SRBRoot
*bundle
, const char *tag
, UErrorCode
*status
) {
1003 int32_t keypos
, length
;
1005 if (U_FAILURE(*status
)) {
1010 /* do not set an error: the root table has a NULL tag */
1014 keypos
= bundle
->fKeyPoint
;
1016 bundle
->fKeyPoint
+= length
= (int32_t) (uprv_strlen(tag
) + 1);
1018 if (bundle
->fKeyPoint
>= bundle
->fKeysCapacity
) {
1019 /* overflow - resize the keys buffer */
1020 bundle
->fKeysCapacity
+= KEY_SPACE_SIZE
;
1021 bundle
->fKeys
= uprv_realloc(bundle
->fKeys
, bundle
->fKeysCapacity
);
1022 if(bundle
->fKeys
== NULL
) {
1023 *status
= U_MEMORY_ALLOCATION_ERROR
;
1028 uprv_memcpy(bundle
->fKeys
+ keypos
, tag
, length
);