2 *******************************************************************************
4 * Copyright (C) 2000-2006, 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
;
30 uint32_t res_write(UNewDataMemory
*mem
, struct SResource
*res
,
31 uint32_t usedOffset
, UErrorCode
*status
);
33 static const UDataInfo dataInfo
= {
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*/
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);
53 void setIncludeCopyright(UBool val
){
54 gIncludeCopyright
=val
;
57 UBool
getIncludeCopyright(void){
58 return gIncludeCopyright
;
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
));
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
));
81 static uint32_t array_write(UNewDataMemory
*mem
, struct SResource
*res
,
82 uint32_t usedOffset
, UErrorCode
*status
) {
83 uint32_t *resources
= NULL
;
86 struct SResource
*current
= NULL
;
88 if (U_FAILURE(*status
)) {
92 if (res
->u
.fArray
.fCount
> 0) {
93 resources
= (uint32_t *) uprv_malloc(sizeof(uint32_t) * res
->u
.fArray
.fCount
);
95 if (resources
== NULL
) {
96 *status
= U_MEMORY_ALLOCATION_ERROR
;
100 current
= res
->u
.fArray
.fFirst
;
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
;
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
);
113 usedOffset
= res_write(mem
, current
, usedOffset
, status
);
114 resources
[i
] = (current
->fType
<< 28) | (usedOffset
>> 2);
115 usedOffset
+= current
->fSize
+ calcPadding(current
->fSize
);
119 current
= current
->fNext
;
122 /* usedOffset += res->fSize + pad; */
124 udata_write32(mem
, res
->u
.fArray
.fCount
);
125 udata_writeBlock(mem
, resources
, sizeof(uint32_t) * res
->u
.fArray
.fCount
);
126 uprv_free(resources
);
129 udata_write32(mem
, 0);
135 static uint32_t intvector_write(UNewDataMemory
*mem
, struct SResource
*res
,
136 uint32_t usedOffset
, UErrorCode
*status
) {
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
]);
146 static uint32_t bin_write(UNewDataMemory
*mem
, struct SResource
*res
,
147 uint32_t usedOffset
, UErrorCode
*status
) {
149 uint32_t extrapad
= calcPadding(res
->fSize
);
150 uint32_t dataStart
= usedOffset
+ sizeof(res
->u
.fBinaryValue
.fLength
);
152 if (dataStart
% BIN_ALIGNMENT
) {
153 pad
= (BIN_ALIGNMENT
- dataStart
% BIN_ALIGNMENT
);
154 udata_writePadding(mem
, pad
);
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
);
162 udata_writePadding(mem
, (BIN_ALIGNMENT
- pad
+ extrapad
));
167 static uint32_t int_write(UNewDataMemory
*mem
, struct SResource
*res
,
168 uint32_t usedOffset
, UErrorCode
*status
) {
172 static uint32_t table_write(UNewDataMemory
*mem
, struct SResource
*res
,
173 uint32_t usedOffset
, UErrorCode
*status
) {
176 uint16_t *keys16
= NULL
;
177 int32_t *keys32
= NULL
;
178 uint32_t *resources
= NULL
;
180 struct SResource
*current
= NULL
;
182 if (U_FAILURE(*status
)) {
186 pad
= calcPadding(res
->fSize
);
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
;
196 keys32
= (int32_t *) uprv_malloc(sizeof(int32_t) * res
->u
.fTable
.fCount
);
197 if (keys32
== NULL
) {
198 *status
= U_MEMORY_ALLOCATION_ERROR
;
203 resources
= (uint32_t *) uprv_malloc(sizeof(uint32_t) * res
->u
.fTable
.fCount
);
205 if (resources
== NULL
) {
208 *status
= U_MEMORY_ALLOCATION_ERROR
;
212 current
= res
->u
.fTable
.fFirst
;
215 while (current
!= NULL
) {
216 assert(i
< res
->u
.fTable
.fCount
);
218 /* where the key is */
219 if(res
->fType
== URES_TABLE
) {
220 keys16
[i
] = (uint16_t) current
->fKey
;
222 keys32
[i
] = current
->fKey
;
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
;
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
);
234 usedOffset
= res_write(mem
, current
, usedOffset
, status
);
235 resources
[i
] = (current
->fType
<< 28) | (usedOffset
>> 2);
236 usedOffset
+= current
->fSize
+ calcPadding(current
->fSize
);
240 current
= current
->fNext
;
243 if(res
->fType
== URES_TABLE
) {
244 udata_write16(mem
, (uint16_t)res
->u
.fTable
.fCount
);
246 udata_writeBlock(mem
, keys16
, sizeof(uint16_t) * res
->u
.fTable
.fCount
);
247 udata_writePadding(mem
, pad
);
249 udata_write32(mem
, res
->u
.fTable
.fCount
);
251 udata_writeBlock(mem
, keys32
, sizeof(int32_t) * res
->u
.fTable
.fCount
);
254 udata_writeBlock(mem
, resources
, sizeof(uint32_t) * res
->u
.fTable
.fCount
);
258 uprv_free(resources
);
261 if(res
->fType
== URES_TABLE
) {
262 udata_write16(mem
, 0);
263 udata_writePadding(mem
, pad
);
265 udata_write32(mem
, 0);
272 uint32_t res_write(UNewDataMemory
*mem
, struct SResource
*res
,
273 uint32_t usedOffset
, UErrorCode
*status
) {
274 if (U_FAILURE(*status
)) {
279 switch (res
->fType
) {
281 return string_write (mem
, res
, usedOffset
, status
);
283 return alias_write (mem
, res
, usedOffset
, status
);
284 case URES_INT_VECTOR
:
285 return intvector_write (mem
, res
, usedOffset
, status
);
287 return bin_write (mem
, res
, usedOffset
, status
);
289 return int_write (mem
, res
, usedOffset
, status
);
291 return array_write (mem
, res
, usedOffset
, status
);
294 return table_write (mem
, res
, usedOffset
, status
);
301 *status
= U_INTERNAL_PROGRAM_ERROR
;
305 void bundle_write(struct SRBRoot
*bundle
, const char *outputDir
, const char *outputPkg
, char *writtenFilename
, int writtenFilenameLen
, UErrorCode
*status
) {
306 UNewDataMemory
*mem
= NULL
;
309 uint32_t usedOffset
= 0;
312 int32_t indexes
[URES_INDEX_TOP
];
314 if (writtenFilename
&& writtenFilenameLen
) {
315 *writtenFilename
= 0;
318 if (U_FAILURE(*status
)) {
322 if (writtenFilename
) {
323 int32_t off
= 0, len
= 0;
325 len
= (int32_t)uprv_strlen(outputDir
);
326 if (len
> writtenFilenameLen
) {
327 len
= writtenFilenameLen
;
329 uprv_strncpy(writtenFilename
, outputDir
, len
);
331 if (writtenFilenameLen
-= len
) {
333 writtenFilename
[off
] = U_FILE_SEP_CHAR
;
334 if (--writtenFilenameLen
) {
336 if(outputPkg
!= NULL
)
338 uprv_strcpy(writtenFilename
+off
, outputPkg
);
339 off
+= (int32_t)uprv_strlen(outputPkg
);
340 writtenFilename
[off
] = '_';
344 len
= (int32_t)uprv_strlen(bundle
->fLocale
);
345 if (len
> writtenFilenameLen
) {
346 len
= writtenFilenameLen
;
348 uprv_strncpy(writtenFilename
+ off
, bundle
->fLocale
, len
);
349 if (writtenFilenameLen
-= len
) {
352 if (len
> writtenFilenameLen
) {
353 len
= writtenFilenameLen
;
355 uprv_strncpy(writtenFilename
+ off
, ".res", len
);
363 uprv_strcpy(dataName
, outputPkg
);
364 uprv_strcat(dataName
, "_");
365 uprv_strcat(dataName
, bundle
->fLocale
);
369 uprv_strcpy(dataName
, bundle
->fLocale
);
372 mem
= udata_create(outputDir
, "res", dataName
, &dataInfo
, (gIncludeCopyright
==TRUE
)? U_COPYRIGHT_STRING
:NULL
, status
);
373 if(U_FAILURE(*status
)){
376 pad
= calcPadding(bundle
->fKeyPoint
);
378 usedOffset
= bundle
->fKeyPoint
+ pad
; /* top of the strings */
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);
384 /* write the root item */
385 udata_write32(mem
, root
);
387 /* add to top the size of the root item */
388 top
+= bundle
->fRoot
->fSize
;
389 top
+= calcPadding(top
);
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.
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
;
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
408 if(bundle
->noFallback
) {
409 indexes
[URES_INDEX_ATTRIBUTES
]=URES_ATT_NO_FALLBACK
;
412 /* write the indexes[] */
413 udata_writeBlock(mem
, indexes
, sizeof(indexes
));
415 /* write the table key strings */
416 udata_writeBlock(mem
, bundle
->fKeys
+URES_STRINGS_BOTTOM
,
417 bundle
->fKeyPoint
-URES_STRINGS_BOTTOM
);
419 /* write the padding bytes after the table key strings */
420 udata_writePadding(mem
, pad
);
422 /* write all of the bundle contents: the root item and its children */
423 usedOffset
= res_write(mem
, bundle
->fRoot
, usedOffset
, status
);
425 size
= udata_finish(mem
, status
);
427 fprintf(stderr
, "genrb error: wrote %u bytes but counted %u\n",
428 (int)size
, (int)top
);
429 *status
= U_INTERNAL_PROGRAM_ERROR
;
433 /* Opening Functions */
434 struct SResource
* res_open(const struct UString
* comment
, UErrorCode
* status
){
435 struct SResource
*res
;
437 if (U_FAILURE(*status
)) {
441 res
= (struct SResource
*) uprv_malloc(sizeof(struct SResource
));
444 *status
= U_MEMORY_ALLOCATION_ERROR
;
447 uprv_memset(res
, 0, sizeof(struct SResource
));
449 res
->fComment
= NULL
;
451 res
->fComment
= (struct UString
*) uprv_malloc(sizeof(struct UString
));
452 if(res
->fComment
== NULL
){
453 *status
= U_MEMORY_ALLOCATION_ERROR
;
457 ustr_init(res
->fComment
);
458 ustr_cpy(res
->fComment
, comment
, status
);
463 struct SResource
* table_open(struct SRBRoot
*bundle
, char *tag
, const struct UString
* comment
, UErrorCode
*status
) {
465 struct SResource
*res
= res_open(comment
, status
);
467 res
->fKey
= bundle_addtag(bundle
, tag
, status
);
469 if (U_FAILURE(*status
)) {
470 uprv_free(res
->fComment
);
478 * always open a table not a table32 in case it remains empty -
479 * try to use table32 only when necessary
481 res
->fType
= URES_TABLE
;
482 res
->fSize
= sizeof(uint16_t);
484 res
->u
.fTable
.fCount
= 0;
485 res
->u
.fTable
.fChildrenSize
= 0;
486 res
->u
.fTable
.fFirst
= NULL
;
487 res
->u
.fTable
.fRoot
= bundle
;
492 struct SResource
* array_open(struct SRBRoot
*bundle
, const char *tag
, const struct UString
* comment
, UErrorCode
*status
) {
494 struct SResource
*res
= res_open(comment
, status
);
496 if (U_FAILURE(*status
)) {
500 res
->fType
= URES_ARRAY
;
501 res
->fKey
= bundle_addtag(bundle
, tag
, status
);
503 if (U_FAILURE(*status
)) {
504 uprv_free(res
->fComment
);
510 res
->fSize
= sizeof(int32_t);
512 res
->u
.fArray
.fCount
= 0;
513 res
->u
.fArray
.fChildrenSize
= 0;
514 res
->u
.fArray
.fFirst
= NULL
;
515 res
->u
.fArray
.fLast
= NULL
;
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
);
523 if (U_FAILURE(*status
)) {
527 res
->fType
= URES_STRING
;
528 res
->fKey
= bundle_addtag(bundle
, tag
, status
);
530 if (U_FAILURE(*status
)) {
531 uprv_free(res
->fComment
);
538 res
->u
.fString
.fLength
= len
;
539 res
->u
.fString
.fChars
= (UChar
*) uprv_malloc(sizeof(UChar
) * (len
+ 1));
541 if (res
->u
.fString
.fChars
== NULL
) {
542 *status
= U_MEMORY_ALLOCATION_ERROR
;
547 uprv_memcpy(res
->u
.fString
.fChars
, value
, sizeof(UChar
) * (len
+ 1));
548 res
->fSize
= sizeof(int32_t) + sizeof(UChar
) * (len
+1);
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
);
557 if (U_FAILURE(*status
)) {
561 res
->fType
= URES_ALIAS
;
562 res
->fKey
= bundle_addtag(bundle
, tag
, status
);
564 if (U_FAILURE(*status
)) {
565 uprv_free(res
->fComment
);
572 res
->u
.fString
.fLength
= len
;
573 res
->u
.fString
.fChars
= (UChar
*) uprv_malloc(sizeof(UChar
) * (len
+ 1));
575 if (res
->u
.fString
.fChars
== NULL
) {
576 *status
= U_MEMORY_ALLOCATION_ERROR
;
581 uprv_memcpy(res
->u
.fString
.fChars
, value
, sizeof(UChar
) * (len
+ 1));
582 res
->fSize
= sizeof(int32_t) + sizeof(UChar
) * (len
+ 1);
588 struct SResource
* intvector_open(struct SRBRoot
*bundle
, char *tag
, const struct UString
* comment
, UErrorCode
*status
) {
589 struct SResource
*res
= res_open(comment
, status
);
591 if (U_FAILURE(*status
)) {
595 res
->fType
= URES_INT_VECTOR
;
596 res
->fKey
= bundle_addtag(bundle
, tag
, status
);
598 if (U_FAILURE(*status
)) {
599 uprv_free(res
->fComment
);
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
)) {
630 uprv_free(res
->fComment
);
637 res
->u
.fIntValue
.fValue
= value
;
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
);
645 if (U_FAILURE(*status
)) {
649 res
->fType
= URES_BINARY
;
650 res
->fKey
= bundle_addtag(bundle
, tag
, status
);
652 if (U_FAILURE(*status
)) {
653 uprv_free(res
->fComment
);
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
);
667 res
->u
.fBinaryValue
.fData
= (uint8_t *) uprv_malloc(sizeof(uint8_t) * length
);
669 if (res
->u
.fBinaryValue
.fData
== NULL
) {
670 *status
= U_MEMORY_ALLOCATION_ERROR
;
675 uprv_memcpy(res
->u
.fBinaryValue
.fData
, data
, length
);
678 res
->u
.fBinaryValue
.fData
= NULL
;
681 res
->fSize
= sizeof(int32_t) + sizeof(uint8_t) * length
+ BIN_ALIGNMENT
;
686 struct SRBRoot
*bundle_open(const struct UString
* comment
, UErrorCode
*status
) {
687 struct SRBRoot
*bundle
= NULL
;
689 if (U_FAILURE(*status
)) {
693 bundle
= (struct SRBRoot
*) uprv_malloc(sizeof(struct SRBRoot
));
695 if (bundle
== NULL
) {
696 *status
= U_MEMORY_ALLOCATION_ERROR
;
699 uprv_memset(bundle
, 0, sizeof(struct SRBRoot
));
701 bundle
->fLocale
= NULL
;
703 bundle
->fKeys
= (char *) uprv_malloc(sizeof(char) * KEY_SPACE_SIZE
);
704 bundle
->fKeysCapacity
= KEY_SPACE_SIZE
;
710 if (bundle
->fKeys
== NULL
) {
711 *status
= U_MEMORY_ALLOCATION_ERROR
;
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
);
721 bundle
->fRoot
= table_open(bundle
, NULL
, comment
, status
);
723 if (bundle
->fRoot
== NULL
|| U_FAILURE(*status
)) {
724 if (U_SUCCESS(*status
)) {
725 *status
= U_MEMORY_ALLOCATION_ERROR
;
728 uprv_free(bundle
->fKeys
);
737 /* Closing Functions */
738 void table_close(struct SResource
*table
, UErrorCode
*status
) {
739 struct SResource
*current
= NULL
;
740 struct SResource
*prev
= NULL
;
742 current
= table
->u
.fTable
.fFirst
;
744 while (current
!= NULL
) {
746 current
= current
->fNext
;
748 res_close(prev
, status
);
751 table
->u
.fTable
.fFirst
= NULL
;
754 void array_close(struct SResource
*array
, UErrorCode
*status
) {
755 struct SResource
*current
= NULL
;
756 struct SResource
*prev
= NULL
;
761 current
= array
->u
.fArray
.fFirst
;
763 while (current
!= NULL
) {
765 current
= current
->fNext
;
767 res_close(prev
, status
);
769 array
->u
.fArray
.fFirst
= NULL
;
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
;
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
;
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
;
793 void int_close(struct SResource
*intres
, UErrorCode
*status
) {
794 /* Intentionally left blank */
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
;
804 void res_close(struct SResource
*res
, UErrorCode
*status
) {
808 string_close(res
, status
);
811 alias_close(res
, status
);
813 case URES_INT_VECTOR
:
814 intvector_close(res
, status
);
817 bin_close(res
, status
);
820 int_close(res
, status
);
823 array_close(res
, status
);
827 table_close(res
, status
);
830 /* Shouldn't happen */
838 void bundle_close(struct SRBRoot
*bundle
, UErrorCode
*status
) {
839 struct SResource
*current
= NULL
;
840 struct SResource
*prev
= NULL
;
842 if (bundle
->fRoot
!= NULL
) {
843 current
= bundle
->fRoot
->u
.fTable
.fFirst
;
845 while (current
!= NULL
) {
847 current
= current
->fNext
;
849 res_close(prev
, status
);
852 uprv_free(bundle
->fRoot
);
855 if (bundle
->fLocale
!= NULL
) {
856 uprv_free(bundle
->fLocale
);
859 if (bundle
->fKeys
!= NULL
) {
860 uprv_free(bundle
->fKeys
);
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
;
872 if (U_FAILURE(*status
)) {
876 /* remember this linenumber to report to the user if there is a duplicate key */
877 res
->line
= linenumber
;
879 /* here we need to traverse the list */
880 list
= &(table
->u
.fTable
);
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
;
887 * increase the size because count and each string offset
888 * increase from uint16_t to int32_t
890 table
->fSize
+= (1 + list
->fCount
) * 2;
894 if(list
->fCount
> (uint32_t)list
->fRoot
->fMaxTableLength
) {
895 list
->fRoot
->fMaxTableLength
= list
->fCount
;
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
902 table
->fSize
+= table
->fType
== URES_TABLE
? 6 : 8;
904 table
->u
.fTable
.fChildrenSize
+= res
->fSize
+ calcPadding(res
->fSize
);
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
;
912 /* is list still empty? */
913 if (list
->fFirst
== NULL
) {
919 current
= list
->fFirst
;
921 while (current
!= NULL
) {
922 if (uprv_strcmp(((list
->fRoot
->fKeys
) + (current
->fKey
)), ((list
->fRoot
->fKeys
) + (res
->fKey
))) < 0) {
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 */
928 /* front of the list */
931 /* middle of the list */
935 res
->fNext
= current
;
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
;
950 void array_add(struct SResource
*array
, struct SResource
*res
, UErrorCode
*status
) {
951 if (U_FAILURE(*status
)) {
955 if (array
->u
.fArray
.fFirst
== NULL
) {
956 array
->u
.fArray
.fFirst
= res
;
957 array
->u
.fArray
.fLast
= res
;
959 array
->u
.fArray
.fLast
->fNext
= res
;
960 array
->u
.fArray
.fLast
= res
;
963 (array
->u
.fArray
.fCount
)++;
965 array
->fSize
+= sizeof(uint32_t);
966 array
->u
.fArray
.fChildrenSize
+= res
->fSize
+ calcPadding(res
->fSize
);
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
;
975 void intvector_add(struct SResource
*intvector
, int32_t value
, UErrorCode
*status
) {
976 if (U_FAILURE(*status
)) {
980 *(intvector
->u
.fIntVector
.fArray
+ intvector
->u
.fIntVector
.fCount
) = value
;
981 intvector
->u
.fIntVector
.fCount
++;
983 intvector
->fSize
+= sizeof(uint32_t);
988 void bundle_setlocale(struct SRBRoot
*bundle
, UChar
*locale
, UErrorCode
*status
) {
990 if(U_FAILURE(*status
)) {
994 if (bundle
->fLocale
!=NULL
) {
995 uprv_free(bundle
->fLocale
);
998 bundle
->fLocale
= (char*) uprv_malloc(sizeof(char) * (u_strlen(locale
)+1));
1000 if(bundle
->fLocale
== NULL
) {
1001 *status
= U_MEMORY_ALLOCATION_ERROR
;
1005 /*u_strcpy(bundle->fLocale, locale);*/
1006 u_UCharsToChars(locale
, bundle
->fLocale
, u_strlen(locale
)+1);
1012 bundle_addtag(struct SRBRoot
*bundle
, const char *tag
, UErrorCode
*status
) {
1013 int32_t keypos
, length
;
1015 if (U_FAILURE(*status
)) {
1020 /* do not set an error: the root table has a NULL tag */
1024 keypos
= bundle
->fKeyPoint
;
1026 bundle
->fKeyPoint
+= length
= (int32_t) (uprv_strlen(tag
) + 1);
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
;
1038 uprv_memcpy(bundle
->fKeys
+ keypos
, tag
, length
);