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