2 *******************************************************************************
4 * Copyright (C) 2000-2004, 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, 1, 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 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
;
402 /* write the indexes[] */
403 udata_writeBlock(mem
, indexes
, sizeof(indexes
));
405 /* write the table key strings */
406 udata_writeBlock(mem
, bundle
->fKeys
+URES_STRINGS_BOTTOM
,
407 bundle
->fKeyPoint
-URES_STRINGS_BOTTOM
);
409 /* write the padding bytes after the table key strings */
410 udata_writePadding(mem
, pad
);
412 /* write all of the bundle contents: the root item and its children */
413 usedOffset
= res_write(mem
, bundle
->fRoot
, usedOffset
, status
);
415 size
= udata_finish(mem
, status
);
417 fprintf(stderr
, "genrb error: wrote %u bytes but counted %u\n",
418 (int)size
, (int)top
);
419 *status
= U_INTERNAL_PROGRAM_ERROR
;
423 /* Opening Functions */
424 struct SResource
* res_open(const struct UString
* comment
, UErrorCode
* status
){
425 struct SResource
*res
;
427 if (U_FAILURE(*status
)) {
431 res
= (struct SResource
*) uprv_malloc(sizeof(struct SResource
));
434 *status
= U_MEMORY_ALLOCATION_ERROR
;
437 uprv_memset(res
, 0, sizeof(struct SResource
));
439 res
->fComment
= NULL
;
441 res
->fComment
= (struct UString
*) uprv_malloc(sizeof(struct UString
));
442 if(res
->fComment
== NULL
){
443 *status
= U_MEMORY_ALLOCATION_ERROR
;
446 ustr_init(res
->fComment
);
447 ustr_cpy(res
->fComment
, comment
, status
);
452 struct SResource
* table_open(struct SRBRoot
*bundle
, char *tag
, const struct UString
* comment
, UErrorCode
*status
) {
454 struct SResource
*res
= res_open(comment
, status
);
456 res
->fKey
= bundle_addtag(bundle
, tag
, status
);
458 if (U_FAILURE(*status
)) {
459 uprv_free(res
->fComment
);
467 * always open a table not a table32 in case it remains empty -
468 * try to use table32 only when necessary
470 res
->fType
= URES_TABLE
;
471 res
->fSize
= sizeof(uint16_t);
473 res
->u
.fTable
.fCount
= 0;
474 res
->u
.fTable
.fChildrenSize
= 0;
475 res
->u
.fTable
.fFirst
= NULL
;
476 res
->u
.fTable
.fRoot
= bundle
;
481 struct SResource
* array_open(struct SRBRoot
*bundle
, char *tag
, const struct UString
* comment
, UErrorCode
*status
) {
483 struct SResource
*res
= res_open(comment
, status
);
485 if (U_FAILURE(*status
)) {
489 res
->fType
= URES_ARRAY
;
490 res
->fKey
= bundle_addtag(bundle
, tag
, status
);
492 if (U_FAILURE(*status
)) {
493 uprv_free(res
->fComment
);
499 res
->fSize
= sizeof(int32_t);
501 res
->u
.fArray
.fCount
= 0;
502 res
->u
.fArray
.fChildrenSize
= 0;
503 res
->u
.fArray
.fFirst
= NULL
;
504 res
->u
.fArray
.fLast
= NULL
;
509 struct 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
);
512 if (U_FAILURE(*status
)) {
516 res
->fType
= URES_STRING
;
517 res
->fKey
= bundle_addtag(bundle
, tag
, status
);
519 if (U_FAILURE(*status
)) {
520 uprv_free(res
->fComment
);
527 res
->u
.fString
.fLength
= len
;
528 res
->u
.fString
.fChars
= (UChar
*) uprv_malloc(sizeof(UChar
) * (len
+ 1));
530 if (res
->u
.fString
.fChars
== NULL
) {
531 *status
= U_MEMORY_ALLOCATION_ERROR
;
536 uprv_memcpy(res
->u
.fString
.fChars
, value
, sizeof(UChar
) * (len
+ 1));
537 res
->fSize
= sizeof(int32_t) + sizeof(UChar
) * (len
+1);
542 /* TODO: make alias_open and string_open use the same code */
543 struct 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
);
546 if (U_FAILURE(*status
)) {
550 res
->fType
= URES_ALIAS
;
551 res
->fKey
= bundle_addtag(bundle
, tag
, status
);
553 if (U_FAILURE(*status
)) {
554 uprv_free(res
->fComment
);
561 res
->u
.fString
.fLength
= len
;
562 res
->u
.fString
.fChars
= (UChar
*) uprv_malloc(sizeof(UChar
) * (len
+ 1));
564 if (res
->u
.fString
.fChars
== NULL
) {
565 *status
= U_MEMORY_ALLOCATION_ERROR
;
570 uprv_memcpy(res
->u
.fString
.fChars
, value
, sizeof(UChar
) * (len
+ 1));
571 res
->fSize
= sizeof(int32_t) + sizeof(UChar
) * (len
+ 1);
577 struct SResource
* intvector_open(struct SRBRoot
*bundle
, char *tag
, const struct UString
* comment
, UErrorCode
*status
) {
578 struct SResource
*res
= res_open(comment
, status
);
580 if (U_FAILURE(*status
)) {
584 res
->fType
= URES_INT_VECTOR
;
585 res
->fKey
= bundle_addtag(bundle
, tag
, status
);
587 if (U_FAILURE(*status
)) {
588 uprv_free(res
->fComment
);
594 res
->fSize
= sizeof(int32_t);
596 res
->u
.fIntVector
.fCount
= 0;
597 res
->u
.fIntVector
.fArray
= (uint32_t *) uprv_malloc(sizeof(uint32_t) * RESLIST_MAX_INT_VECTOR
);
599 if (res
->u
.fIntVector
.fArray
== NULL
) {
600 *status
= U_MEMORY_ALLOCATION_ERROR
;
608 struct 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
);
611 if (U_FAILURE(*status
)) {
615 res
->fType
= URES_INT
;
616 res
->fKey
= bundle_addtag(bundle
, tag
, status
);
618 if (U_FAILURE(*status
)) {
619 uprv_free(res
->fComment
);
626 res
->u
.fIntValue
.fValue
= value
;
631 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
) {
632 struct SResource
*res
= res_open(comment
, status
);
634 if (U_FAILURE(*status
)) {
638 res
->fType
= URES_BINARY
;
639 res
->fKey
= bundle_addtag(bundle
, tag
, status
);
641 if (U_FAILURE(*status
)) {
642 uprv_free(res
->fComment
);
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
);
656 res
->u
.fBinaryValue
.fData
= (uint8_t *) uprv_malloc(sizeof(uint8_t) * length
);
658 if (res
->u
.fBinaryValue
.fData
== NULL
) {
659 *status
= U_MEMORY_ALLOCATION_ERROR
;
664 uprv_memcpy(res
->u
.fBinaryValue
.fData
, data
, length
);
667 res
->u
.fBinaryValue
.fData
= NULL
;
670 res
->fSize
= sizeof(int32_t) + sizeof(uint8_t) * length
+ BIN_ALIGNMENT
;
675 struct SRBRoot
*bundle_open(const struct UString
* comment
, UErrorCode
*status
) {
676 struct SRBRoot
*bundle
= NULL
;
678 if (U_FAILURE(*status
)) {
682 bundle
= (struct SRBRoot
*) uprv_malloc(sizeof(struct SRBRoot
));
684 if (bundle
== NULL
) {
685 *status
= U_MEMORY_ALLOCATION_ERROR
;
688 uprv_memset(bundle
, 0, sizeof(struct SRBRoot
));
690 bundle
->fLocale
= NULL
;
692 bundle
->fKeys
= (char *) uprv_malloc(sizeof(char) * KEY_SPACE_SIZE
);
693 bundle
->fKeysCapacity
= KEY_SPACE_SIZE
;
699 if (bundle
->fKeys
== NULL
) {
700 *status
= U_MEMORY_ALLOCATION_ERROR
;
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
);
710 bundle
->fRoot
= table_open(bundle
, NULL
, comment
, status
);
712 if (bundle
->fRoot
== NULL
|| U_FAILURE(*status
)) {
713 if (U_SUCCESS(*status
)) {
714 *status
= U_MEMORY_ALLOCATION_ERROR
;
717 uprv_free(bundle
->fKeys
);
726 /* Closing Functions */
727 void table_close(struct SResource
*table
, UErrorCode
*status
) {
728 struct SResource
*current
= NULL
;
729 struct SResource
*prev
= NULL
;
731 current
= table
->u
.fTable
.fFirst
;
733 while (current
!= NULL
) {
735 current
= current
->fNext
;
737 res_close(prev
, status
);
740 table
->u
.fTable
.fFirst
= NULL
;
743 void array_close(struct SResource
*array
, UErrorCode
*status
) {
744 struct SResource
*current
= NULL
;
745 struct SResource
*prev
= NULL
;
747 current
= array
->u
.fArray
.fFirst
;
749 while (current
!= NULL
) {
751 current
= current
->fNext
;
753 res_close(prev
, status
);
755 array
->u
.fArray
.fFirst
= NULL
;
758 void 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
;
765 void 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
;
772 void 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
;
779 void int_close(struct SResource
*intres
, UErrorCode
*status
) {
780 /* Intentionally left blank */
783 void 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
;
790 void res_close(struct SResource
*res
, UErrorCode
*status
) {
794 string_close(res
, status
);
797 alias_close(res
, status
);
799 case URES_INT_VECTOR
:
800 intvector_close(res
, status
);
803 bin_close(res
, status
);
806 int_close(res
, status
);
809 array_close(res
, status
);
813 table_close(res
, status
);
816 /* Shouldn't happen */
824 void bundle_close(struct SRBRoot
*bundle
, UErrorCode
*status
) {
825 struct SResource
*current
= NULL
;
826 struct SResource
*prev
= NULL
;
828 if (bundle
->fRoot
!= NULL
) {
829 current
= bundle
->fRoot
->u
.fTable
.fFirst
;
831 while (current
!= NULL
) {
833 current
= current
->fNext
;
835 res_close(prev
, status
);
838 uprv_free(bundle
->fRoot
);
841 if (bundle
->fLocale
!= NULL
) {
842 uprv_free(bundle
->fLocale
);
845 if (bundle
->fKeys
!= NULL
) {
846 uprv_free(bundle
->fKeys
);
852 /* Adding Functions */
853 void 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
;
858 if (U_FAILURE(*status
)) {
862 /* remember this linenumber to report to the user if there is a duplicate key */
863 res
->line
= linenumber
;
865 /* here we need to traverse the list */
866 list
= &(table
->u
.fTable
);
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
;
873 * increase the size because count and each string offset
874 * increase from uint16_t to int32_t
876 table
->fSize
+= (1 + list
->fCount
) * 2;
880 if(list
->fCount
> (uint32_t)list
->fRoot
->fMaxTableLength
) {
881 list
->fRoot
->fMaxTableLength
= list
->fCount
;
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
888 table
->fSize
+= table
->fType
== URES_TABLE
? 6 : 8;
890 table
->u
.fTable
.fChildrenSize
+= res
->fSize
+ calcPadding(res
->fSize
);
892 if (res
->fType
== URES_TABLE
|| res
->fType
== URES_TABLE32
) {
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
;
898 /* is list still empty? */
899 if (list
->fFirst
== NULL
) {
905 current
= list
->fFirst
;
907 while (current
!= NULL
) {
908 if (uprv_strcmp(((list
->fRoot
->fKeys
) + (current
->fKey
)), ((list
->fRoot
->fKeys
) + (res
->fKey
))) < 0) {
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 */
914 /* front of the list */
917 /* middle of the list */
921 res
->fNext
= current
;
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
;
936 void array_add(struct SResource
*array
, struct SResource
*res
, UErrorCode
*status
) {
937 if (U_FAILURE(*status
)) {
941 if (array
->u
.fArray
.fFirst
== NULL
) {
942 array
->u
.fArray
.fFirst
= res
;
943 array
->u
.fArray
.fLast
= res
;
945 array
->u
.fArray
.fLast
->fNext
= res
;
946 array
->u
.fArray
.fLast
= res
;
949 (array
->u
.fArray
.fCount
)++;
951 array
->fSize
+= sizeof(uint32_t);
952 array
->u
.fArray
.fChildrenSize
+= res
->fSize
+ calcPadding(res
->fSize
);
954 if (res
->fType
== URES_TABLE
|| res
->fType
== URES_TABLE32
) {
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
;
961 void intvector_add(struct SResource
*intvector
, int32_t value
, UErrorCode
*status
) {
962 if (U_FAILURE(*status
)) {
966 *(intvector
->u
.fIntVector
.fArray
+ intvector
->u
.fIntVector
.fCount
) = value
;
967 intvector
->u
.fIntVector
.fCount
++;
969 intvector
->fSize
+= sizeof(uint32_t);
974 void bundle_setlocale(struct SRBRoot
*bundle
, UChar
*locale
, UErrorCode
*status
) {
976 if(U_FAILURE(*status
)) {
980 if (bundle
->fLocale
!=NULL
) {
981 uprv_free(bundle
->fLocale
);
984 bundle
->fLocale
= (char*) uprv_malloc(sizeof(char) * (u_strlen(locale
)+1));
986 if(bundle
->fLocale
== NULL
) {
987 *status
= U_MEMORY_ALLOCATION_ERROR
;
991 /*u_strcpy(bundle->fLocale, locale);*/
992 u_UCharsToChars(locale
, bundle
->fLocale
, u_strlen(locale
)+1);
998 bundle_addtag(struct SRBRoot
*bundle
, const char *tag
, UErrorCode
*status
) {
999 int32_t keypos
, length
;
1001 if (U_FAILURE(*status
)) {
1006 /* do not set an error: the root table has a NULL tag */
1010 keypos
= bundle
->fKeyPoint
;
1012 bundle
->fKeyPoint
+= length
= (int32_t) (uprv_strlen(tag
) + 1);
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
;
1024 uprv_memcpy(bundle
->fKeys
+ keypos
, tag
, length
);