/* * Check for the alias from the string or alias resource res. */ static void checkAlias(const char *itemName, Resource res, const UChar *alias, int32_t length, UBool useResSuffix, CheckDependency check, void *context, UErrorCode *pErrorCode) { int32_t i; if(!uprv_isInvariantUString(alias, length)) { fprintf(stderr, "icupkg/ures_enumDependencies(%s res=%08x) alias string contains non-invariant characters\n", itemName, res); *pErrorCode=U_INVALID_CHAR_FOUND; return; } // extract the locale ID from alias strings like // locale_ID/key1/key2/key3 // locale_ID // search for the first slash for(i=0; i<length && alias[i]!=SLASH; ++i) {} if(res_getPublicType(res)==URES_ALIAS) { // ignore aliases with an initial slash: // /ICUDATA/... and /pkgname/... go to a different package // /LOCALE/... are for dynamic sideways fallbacks and don't go to a fixed bundle if(i==0) { return; // initial slash ('/') } // ignore the intra-bundle path starting from the first slash ('/') length=i; } else /* URES_STRING */ { // the whole string should only consist of a locale ID if(i!=length) { fprintf(stderr, "icupkg/ures_enumDependencies(%s res=%08x) %%ALIAS contains a '/'\n", itemName, res); *pErrorCode=U_UNSUPPORTED_ERROR; return; } } // convert the Unicode string to char * char localeID[32]; if(length>=(int32_t)sizeof(localeID)) { fprintf(stderr, "icupkg/ures_enumDependencies(%s res=%08x) alias locale ID length %ld too long\n", itemName, res, (long)length); *pErrorCode=U_BUFFER_OVERFLOW_ERROR; return; } u_UCharsToChars(alias, localeID, length); localeID[length]=0; checkIDSuffix(itemName, localeID, -1, (useResSuffix ? ".res" : ""), check, context, pErrorCode); }
/* * Enumerate one resource item and its children and extract dependencies from * aliases. */ static void ures_enumDependencies(const char *itemName, const ResourceData *pResData, Resource res, const char *inKey, const char *parentKey, int32_t depth, CheckDependency check, void *context, Package *pkg, UErrorCode *pErrorCode) { switch(res_getPublicType(res)) { case URES_STRING: { UBool useResSuffix = TRUE; // Check for %%ALIAS if(depth==1 && inKey!=NULL) { if(0!=strcmp(inKey, "%%ALIAS")) { break; } } // Check for %%DEPENDENCY else if(depth==2 && parentKey!=NULL) { if(0!=strcmp(parentKey, "%%DEPENDENCY")) { break; } useResSuffix = FALSE; } else { // we ignore all other strings break; } int32_t length; const UChar *alias=res_getString(pResData, res, &length); checkAlias(itemName, res, alias, length, useResSuffix, check, context, pErrorCode); } break; case URES_ALIAS: { int32_t length; const UChar *alias=res_getAlias(pResData, res, &length); checkAlias(itemName, res, alias, length, TRUE, check, context, pErrorCode); } break; case URES_TABLE: { /* recurse */ int32_t count=res_countArrayItems(pResData, res); for(int32_t i=0; i<count; ++i) { const char *itemKey; Resource item=res_getTableItemByIndex(pResData, res, i, &itemKey); ures_enumDependencies( itemName, pResData, item, itemKey, inKey, depth+1, check, context, pkg, pErrorCode); if(U_FAILURE(*pErrorCode)) { fprintf(stderr, "icupkg/ures_enumDependencies(%s table res=%08x)[%d].recurse(%s: %08x) failed\n", itemName, res, i, itemKey, item); break; } } } break; case URES_ARRAY: { /* recurse */ int32_t count=res_countArrayItems(pResData, res); for(int32_t i=0; i<count; ++i) { Resource item=res_getArrayItem(pResData, res, i); ures_enumDependencies( itemName, pResData, item, NULL, inKey, depth+1, check, context, pkg, pErrorCode); if(U_FAILURE(*pErrorCode)) { fprintf(stderr, "icupkg/ures_enumDependencies(%s array res=%08x)[%d].recurse(%08x) failed\n", itemName, res, i, item); break; } } } break; default: break; } }
static void printOutBundle(UFILE *out, UResourceBundle *resource, int32_t indent, const char *pname, UErrorCode *status) { static const UChar cr[] = { 0xA }; // LF /* int32_t noOfElements = ures_getSize(resource);*/ int32_t i = 0; const char *key = ures_getKey(resource); switch(ures_getType(resource)) { case URES_STRING : { int32_t len=0; const UChar* thestr = ures_getString(resource, &len, status); UChar *string = quotedString(thestr); /* TODO: String truncation */ if(opt_truncate && len > truncsize) { char msg[128]; printIndent(out, indent); sprintf(msg, "// WARNING: this resource, size %li is truncated to %li\n", (long)len, (long)(truncsize/2)); printCString(out, msg, -1); len = truncsize/2; } printIndent(out, indent); if(key != NULL) { static const UChar openStr[] = { 0x0020, 0x007B, 0x0020, 0x0022 }; /* " { \"" */ static const UChar closeStr[] = { 0x0022, 0x0020, 0x007D }; /* "\" }" */ printCString(out, key, (int32_t)uprv_strlen(key)); printString(out, openStr, UPRV_LENGTHOF(openStr)); printString(out, string, len); printString(out, closeStr, UPRV_LENGTHOF(closeStr)); } else { static const UChar openStr[] = { 0x0022 }; /* "\"" */ static const UChar closeStr[] = { 0x0022, 0x002C }; /* "\"," */ printString(out, openStr, UPRV_LENGTHOF(openStr)); printString(out, string, (int32_t)(u_strlen(string))); printString(out, closeStr, UPRV_LENGTHOF(closeStr)); } if(verbose) { printCString(out, "// STRING", -1); } printString(out, cr, UPRV_LENGTHOF(cr)); uprv_free(string); } break; case URES_INT : { static const UChar openStr[] = { 0x003A, 0x0069, 0x006E, 0x0074, 0x0020, 0x007B, 0x0020 }; /* ":int { " */ static const UChar closeStr[] = { 0x0020, 0x007D }; /* " }" */ UChar num[20]; printIndent(out, indent); if(key != NULL) { printCString(out, key, -1); } printString(out, openStr, UPRV_LENGTHOF(openStr)); uprv_itou(num, 20, ures_getInt(resource, status), 10, 0); printString(out, num, u_strlen(num)); printString(out, closeStr, UPRV_LENGTHOF(closeStr)); if(verbose) { printCString(out, "// INT", -1); } printString(out, cr, UPRV_LENGTHOF(cr)); break; } case URES_BINARY : { int32_t len = 0; const int8_t *data = (const int8_t *)ures_getBinary(resource, &len, status); if(opt_truncate && len > truncsize) { char msg[128]; printIndent(out, indent); sprintf(msg, "// WARNING: this resource, size %li is truncated to %li\n", (long)len, (long)(truncsize/2)); printCString(out, msg, -1); len = truncsize; } if(U_SUCCESS(*status)) { static const UChar openStr[] = { 0x003A, 0x0062, 0x0069, 0x006E, 0x0061, 0x0072, 0x0079, 0x0020, 0x007B, 0x0020 }; /* ":binary { " */ static const UChar closeStr[] = { 0x0020, 0x007D, 0x0020 }; /* " } " */ printIndent(out, indent); if(key != NULL) { printCString(out, key, -1); } printString(out, openStr, UPRV_LENGTHOF(openStr)); for(i = 0; i<len; i++) { printHex(out, *data++); } printString(out, closeStr, UPRV_LENGTHOF(closeStr)); if(verbose) { printCString(out, " // BINARY", -1); } printString(out, cr, UPRV_LENGTHOF(cr)); } else { reportError(pname, status, "getting binary value"); } } break; case URES_INT_VECTOR : { int32_t len = 0; const int32_t *data = ures_getIntVector(resource, &len, status); if(U_SUCCESS(*status)) { static const UChar openStr[] = { 0x003A, 0x0069, 0x006E, 0x0074, 0x0076, 0x0065, 0x0063, 0x0074, 0x006F, 0x0072, 0x0020, 0x007B, 0x0020 }; /* ":intvector { " */ static const UChar closeStr[] = { 0x0020, 0x007D, 0x0020 }; /* " } " */ UChar num[20]; printIndent(out, indent); if(key != NULL) { printCString(out, key, -1); } printString(out, openStr, UPRV_LENGTHOF(openStr)); for(i = 0; i < len - 1; i++) { int32_t numLen = uprv_itou(num, 20, data[i], 10, 0); num[numLen++] = 0x002C; /* ',' */ num[numLen++] = 0x0020; /* ' ' */ num[numLen] = 0; printString(out, num, u_strlen(num)); } if(len > 0) { uprv_itou(num, 20, data[len - 1], 10, 0); printString(out, num, u_strlen(num)); } printString(out, closeStr, UPRV_LENGTHOF(closeStr)); if(verbose) { printCString(out, "// INTVECTOR", -1); } printString(out, cr, UPRV_LENGTHOF(cr)); } else { reportError(pname, status, "getting int vector"); } } break; case URES_TABLE : case URES_ARRAY : { static const UChar openStr[] = { 0x007B }; /* "{" */ static const UChar closeStr[] = { 0x007D, '\n' }; /* "}\n" */ UResourceBundle *t = NULL; ures_resetIterator(resource); printIndent(out, indent); if(key != NULL) { printCString(out, key, -1); } printString(out, openStr, UPRV_LENGTHOF(openStr)); if(verbose) { if(ures_getType(resource) == URES_TABLE) { printCString(out, "// TABLE", -1); } else { printCString(out, "// ARRAY", -1); } } printString(out, cr, UPRV_LENGTHOF(cr)); if(suppressAliases == FALSE) { while(U_SUCCESS(*status) && ures_hasNext(resource)) { t = ures_getNextResource(resource, t, status); if(U_SUCCESS(*status)) { printOutBundle(out, t, indent+indentsize, pname, status); } else { reportError(pname, status, "While processing table"); *status = U_ZERO_ERROR; } } } else { /* we have to use low level access to do this */ Resource r; int32_t resSize = ures_getSize(resource); UBool isTable = (UBool)(ures_getType(resource) == URES_TABLE); for(i = 0; i < resSize; i++) { /* need to know if it's an alias */ if(isTable) { r = res_getTableItemByIndex(&resource->fResData, resource->fRes, i, &key); } else { r = res_getArrayItem(&resource->fResData, resource->fRes, i); } if(U_SUCCESS(*status)) { if(res_getPublicType(r) == URES_ALIAS) { printOutAlias(out, resource, r, key, indent+indentsize, pname, status); } else { t = ures_getByIndex(resource, i, t, status); printOutBundle(out, t, indent+indentsize, pname, status); } } else { reportError(pname, status, "While processing table"); *status = U_ZERO_ERROR; } } } printIndent(out, indent); printString(out, closeStr, UPRV_LENGTHOF(closeStr)); ures_close(t); } break; default: break; } }