| Index: source/common/uresdata.cpp
|
| diff --git a/source/common/uresdata.cpp b/source/common/uresdata.cpp
|
| index fbfb56de6b52045f586f1228ac7891f015a1dcd2..44654dcf57973ce3bd6030bb4a7597491407aa54 100644
|
| --- a/source/common/uresdata.cpp
|
| +++ b/source/common/uresdata.cpp
|
| @@ -1,6 +1,8 @@
|
| +// Copyright (C) 2016 and later: Unicode, Inc. and others.
|
| +// License & terms of use: http://www.unicode.org/copyright.html
|
| /*
|
| *******************************************************************************
|
| -* Copyright (C) 1999-2015, International Business Machines Corporation
|
| +* Copyright (C) 1999-2016, International Business Machines Corporation
|
| * and others. All Rights Reserved.
|
| *******************************************************************************
|
| * file name: uresdata.cpp
|
| @@ -380,6 +382,36 @@ UBool isNoInheritanceMarker(const ResourceData *pResData, Resource res) {
|
| return FALSE;
|
| }
|
|
|
| +int32_t getStringArray(const ResourceData *pResData, const icu::ResourceArray &array,
|
| + icu::UnicodeString *dest, int32_t capacity,
|
| + UErrorCode &errorCode) {
|
| + if(U_FAILURE(errorCode)) {
|
| + return 0;
|
| + }
|
| + if(dest == NULL ? capacity != 0 : capacity < 0) {
|
| + errorCode = U_ILLEGAL_ARGUMENT_ERROR;
|
| + return 0;
|
| + }
|
| + int32_t length = array.getSize();
|
| + if(length == 0) {
|
| + return 0;
|
| + }
|
| + if(length > capacity) {
|
| + errorCode = U_BUFFER_OVERFLOW_ERROR;
|
| + return length;
|
| + }
|
| + for(int32_t i = 0; i < length; ++i) {
|
| + int32_t sLength;
|
| + const UChar *s = res_getString(pResData, array.internalGetResource(pResData, i), &sLength);
|
| + if(s == NULL) {
|
| + errorCode = U_RESOURCE_TYPE_MISMATCH;
|
| + return 0;
|
| + }
|
| + dest[i].setTo(TRUE, s, sLength);
|
| + }
|
| + return length;
|
| +}
|
| +
|
| } // namespace
|
|
|
| U_CAPI const UChar * U_EXPORT2
|
| @@ -463,42 +495,6 @@ res_countArrayItems(const ResourceData *pResData, Resource res) {
|
| }
|
| }
|
|
|
| -namespace {
|
| -
|
| -int32_t getArrayLength(const ResourceData *pResData, Resource res) {
|
| - uint32_t offset=RES_GET_OFFSET(res);
|
| - if(offset == 0) {
|
| - return 0;
|
| - }
|
| - int32_t type = RES_GET_TYPE(res);
|
| - if(type == URES_ARRAY) {
|
| - return *(pResData->pRoot+offset);
|
| - } else if(type == URES_ARRAY16) {
|
| - return pResData->p16BitUnits[offset];
|
| - } else {
|
| - return 0;
|
| - }
|
| -}
|
| -
|
| -int32_t getTableLength(const ResourceData *pResData, Resource res) {
|
| - uint32_t offset=RES_GET_OFFSET(res);
|
| - if(offset == 0) {
|
| - return 0;
|
| - }
|
| - int32_t type = RES_GET_TYPE(res);
|
| - if(type == URES_TABLE) {
|
| - return *((const uint16_t *)(pResData->pRoot+offset));
|
| - } else if(type == URES_TABLE16) {
|
| - return pResData->p16BitUnits[offset];
|
| - } else if(type == URES_TABLE32) {
|
| - return *(pResData->pRoot+offset);
|
| - } else {
|
| - return 0;
|
| - }
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| U_NAMESPACE_BEGIN
|
|
|
| ResourceDataValue::~ResourceDataValue() {}
|
| @@ -571,6 +567,130 @@ const uint8_t *ResourceDataValue::getBinary(int32_t &length, UErrorCode &errorCo
|
| return b;
|
| }
|
|
|
| +ResourceArray ResourceDataValue::getArray(UErrorCode &errorCode) const {
|
| + if(U_FAILURE(errorCode)) {
|
| + return ResourceArray();
|
| + }
|
| + const uint16_t *items16 = NULL;
|
| + const Resource *items32 = NULL;
|
| + uint32_t offset=RES_GET_OFFSET(res);
|
| + int32_t length = 0;
|
| + switch(RES_GET_TYPE(res)) {
|
| + case URES_ARRAY:
|
| + if (offset!=0) { // empty if offset==0
|
| + items32 = (const Resource *)pResData->pRoot+offset;
|
| + length = *items32++;
|
| + }
|
| + break;
|
| + case URES_ARRAY16:
|
| + items16 = pResData->p16BitUnits+offset;
|
| + length = *items16++;
|
| + break;
|
| + default:
|
| + errorCode = U_RESOURCE_TYPE_MISMATCH;
|
| + return ResourceArray();
|
| + }
|
| + return ResourceArray(items16, items32, length);
|
| +}
|
| +
|
| +ResourceTable ResourceDataValue::getTable(UErrorCode &errorCode) const {
|
| + if(U_FAILURE(errorCode)) {
|
| + return ResourceTable();
|
| + }
|
| + const uint16_t *keys16 = NULL;
|
| + const int32_t *keys32 = NULL;
|
| + const uint16_t *items16 = NULL;
|
| + const Resource *items32 = NULL;
|
| + uint32_t offset = RES_GET_OFFSET(res);
|
| + int32_t length = 0;
|
| + switch(RES_GET_TYPE(res)) {
|
| + case URES_TABLE:
|
| + if (offset != 0) { // empty if offset==0
|
| + keys16 = (const uint16_t *)(pResData->pRoot+offset);
|
| + length = *keys16++;
|
| + items32 = (const Resource *)(keys16+length+(~length&1));
|
| + }
|
| + break;
|
| + case URES_TABLE16:
|
| + keys16 = pResData->p16BitUnits+offset;
|
| + length = *keys16++;
|
| + items16 = keys16 + length;
|
| + break;
|
| + case URES_TABLE32:
|
| + if (offset != 0) { // empty if offset==0
|
| + keys32 = pResData->pRoot+offset;
|
| + length = *keys32++;
|
| + items32 = (const Resource *)keys32 + length;
|
| + }
|
| + break;
|
| + default:
|
| + errorCode = U_RESOURCE_TYPE_MISMATCH;
|
| + return ResourceTable();
|
| + }
|
| + return ResourceTable(keys16, keys32, items16, items32, length);
|
| +}
|
| +
|
| +UBool ResourceDataValue::isNoInheritanceMarker() const {
|
| + return ::isNoInheritanceMarker(pResData, res);
|
| +}
|
| +
|
| +int32_t ResourceDataValue::getStringArray(UnicodeString *dest, int32_t capacity,
|
| + UErrorCode &errorCode) const {
|
| + return ::getStringArray(pResData, getArray(errorCode), dest, capacity, errorCode);
|
| +}
|
| +
|
| +int32_t ResourceDataValue::getStringArrayOrStringAsArray(UnicodeString *dest, int32_t capacity,
|
| + UErrorCode &errorCode) const {
|
| + if(URES_IS_ARRAY(res)) {
|
| + return ::getStringArray(pResData, getArray(errorCode), dest, capacity, errorCode);
|
| + }
|
| + if(U_FAILURE(errorCode)) {
|
| + return 0;
|
| + }
|
| + if(dest == NULL ? capacity != 0 : capacity < 0) {
|
| + errorCode = U_ILLEGAL_ARGUMENT_ERROR;
|
| + return 0;
|
| + }
|
| + if(capacity < 1) {
|
| + errorCode = U_BUFFER_OVERFLOW_ERROR;
|
| + return 1;
|
| + }
|
| + int32_t sLength;
|
| + const UChar *s = res_getString(pResData, res, &sLength);
|
| + if(s != NULL) {
|
| + dest[0].setTo(TRUE, s, sLength);
|
| + return 1;
|
| + }
|
| + errorCode = U_RESOURCE_TYPE_MISMATCH;
|
| + return 0;
|
| +}
|
| +
|
| +UnicodeString ResourceDataValue::getStringOrFirstOfArray(UErrorCode &errorCode) const {
|
| + UnicodeString us;
|
| + if(U_FAILURE(errorCode)) {
|
| + return us;
|
| + }
|
| + int32_t sLength;
|
| + const UChar *s = res_getString(pResData, res, &sLength);
|
| + if(s != NULL) {
|
| + us.setTo(TRUE, s, sLength);
|
| + return us;
|
| + }
|
| + ResourceArray array = getArray(errorCode);
|
| + if(U_FAILURE(errorCode)) {
|
| + return us;
|
| + }
|
| + if(array.getSize() > 0) {
|
| + s = res_getString(pResData, array.internalGetResource(pResData, 0), &sLength);
|
| + if(s != NULL) {
|
| + us.setTo(TRUE, s, sLength);
|
| + return us;
|
| + }
|
| + }
|
| + errorCode = U_RESOURCE_TYPE_MISMATCH;
|
| + return us;
|
| +}
|
| +
|
| U_NAMESPACE_END
|
|
|
| static Resource
|
| @@ -691,91 +811,26 @@ res_getResource(const ResourceData *pResData, const char *key) {
|
| return res_getTableItemByKey(pResData, pResData->rootRes, &idx, &realKey);
|
| }
|
|
|
| -// TODO: Ported from Java, but enumerating at this low level may prevent us
|
| -// from doing necessary things, like resolving aliases,
|
| -// which need access to higher-level UResourceBundle code.
|
| -// Consider porting the low-level Container/Array/Table classes from Java,
|
| -// with getters for keys and values,
|
| -// and doing the enumeration in the higher-level code on top of those accessors.
|
| -U_CFUNC void
|
| -ures_getAllTableItems(const ResourceData *pResData, Resource table,
|
| - icu::ResourceDataValue &value, icu::ResourceTableSink &sink,
|
| - UErrorCode &errorCode) {
|
| - if(U_FAILURE(errorCode)) { return; }
|
| - const uint16_t *keys16 = NULL;
|
| - const int32_t *keys32 = NULL;
|
| - const uint16_t *items16 = NULL;
|
| - const Resource *items32 = NULL;
|
| - uint32_t offset = RES_GET_OFFSET(table);
|
| - int32_t length = 0;
|
| - switch(RES_GET_TYPE(table)) {
|
| - case URES_TABLE: {
|
| - if (offset != 0) { /* empty if offset==0 */
|
| - keys16 = (const uint16_t *)(pResData->pRoot+offset);
|
| - length = *keys16++;
|
| - items32 = (const Resource *)(keys16+length+(~length&1));
|
| - }
|
| - break;
|
| - }
|
| - case URES_TABLE16: {
|
| - keys16 = pResData->p16BitUnits+offset;
|
| - length = *keys16++;
|
| - items16 = keys16 + length;
|
| - break;
|
| - }
|
| - case URES_TABLE32: {
|
| - if (offset != 0) { /* empty if offset==0 */
|
| - keys32 = pResData->pRoot+offset;
|
| - length = *keys32++;
|
| - items32 = (const Resource *)keys32 + length;
|
| - }
|
| - break;
|
| - }
|
| - default:
|
| - errorCode = U_RESOURCE_TYPE_MISMATCH;
|
| - return;
|
| - }
|
|
|
| - for (int32_t i = 0; i < length; ++i) {
|
| - const char *key;
|
| +UBool icu::ResourceTable::getKeyAndValue(int32_t i,
|
| + const char *&key, icu::ResourceValue &value) const {
|
| + if(0 <= i && i < length) {
|
| + icu::ResourceDataValue &rdValue = static_cast<icu::ResourceDataValue &>(value);
|
| if (keys16 != NULL) {
|
| - key=RES_GET_KEY16(pResData, keys16[i]);
|
| + key = RES_GET_KEY16(rdValue.pResData, keys16[i]);
|
| } else {
|
| - key=RES_GET_KEY32(pResData, keys32[i]);
|
| + key = RES_GET_KEY32(rdValue.pResData, keys32[i]);
|
| }
|
| Resource res;
|
| if (items16 != NULL) {
|
| - res = makeResourceFrom16(pResData, items16[i]);
|
| + res = makeResourceFrom16(rdValue.pResData, items16[i]);
|
| } else {
|
| res = items32[i];
|
| }
|
| - int32_t type = RES_GET_TYPE(res);
|
| - if (URES_IS_ARRAY(type)) {
|
| - int32_t numItems = getArrayLength(pResData, res);
|
| - icu::ResourceArraySink *subSink = sink.getOrCreateArraySink(key, numItems, errorCode);
|
| - if (subSink != NULL) {
|
| - ures_getAllArrayItems(pResData, res, value, *subSink, errorCode);
|
| - }
|
| - } else if (URES_IS_TABLE(type)) {
|
| - int32_t numItems = getTableLength(pResData, res);
|
| - icu::ResourceTableSink *subSink = sink.getOrCreateTableSink(key, numItems, errorCode);
|
| - if (subSink != NULL) {
|
| - ures_getAllTableItems(pResData, res, value, *subSink, errorCode);
|
| - }
|
| - /* TODO: settle on how to deal with aliases, port to Java
|
| - } else if (type == URES_ALIAS) {
|
| - // aliases not handled in resource enumeration
|
| - errorCode = U_UNSUPPORTED_ERROR;
|
| - return; */
|
| - } else if (isNoInheritanceMarker(pResData, res)) {
|
| - sink.putNoFallback(key, errorCode);
|
| - } else {
|
| - value.setResource(res);
|
| - sink.put(key, value, errorCode);
|
| - }
|
| - if(U_FAILURE(errorCode)) { return; }
|
| + rdValue.setResource(res);
|
| + return TRUE;
|
| }
|
| - sink.leave(errorCode);
|
| + return FALSE;
|
| }
|
|
|
| U_CAPI Resource U_EXPORT2
|
| @@ -805,65 +860,21 @@ res_getArrayItem(const ResourceData *pResData, Resource array, int32_t indexR) {
|
| return RES_BOGUS;
|
| }
|
|
|
| -U_CFUNC void
|
| -ures_getAllArrayItems(const ResourceData *pResData, Resource array,
|
| - icu::ResourceDataValue &value, icu::ResourceArraySink &sink,
|
| - UErrorCode &errorCode) {
|
| - if(U_FAILURE(errorCode)) { return; }
|
| - const uint16_t *items16 = NULL;
|
| - const Resource *items32 = NULL;
|
| - uint32_t offset=RES_GET_OFFSET(array);
|
| - int32_t length = 0;
|
| - switch(RES_GET_TYPE(array)) {
|
| - case URES_ARRAY: {
|
| - if (offset!=0) { /* empty if offset==0 */
|
| - items32 = (const Resource *)pResData->pRoot+offset;
|
| - length = *items32++;
|
| - }
|
| - break;
|
| - }
|
| - case URES_ARRAY16: {
|
| - items16 = pResData->p16BitUnits+offset;
|
| - length = *items16++;
|
| - break;
|
| - }
|
| - default:
|
| - errorCode = U_RESOURCE_TYPE_MISMATCH;
|
| - return;
|
| +uint32_t icu::ResourceArray::internalGetResource(const ResourceData *pResData, int32_t i) const {
|
| + if (items16 != NULL) {
|
| + return makeResourceFrom16(pResData, items16[i]);
|
| + } else {
|
| + return items32[i];
|
| }
|
| +}
|
|
|
| - for (int32_t i = 0; i < length; ++i) {
|
| - Resource res;
|
| - if (items16 != NULL) {
|
| - res = makeResourceFrom16(pResData, items16[i]);
|
| - } else {
|
| - res = items32[i];
|
| - }
|
| - int32_t type = RES_GET_TYPE(res);
|
| - if (URES_IS_ARRAY(type)) {
|
| - int32_t numItems = getArrayLength(pResData, res);
|
| - icu::ResourceArraySink *subSink = sink.getOrCreateArraySink(i, numItems, errorCode);
|
| - if (subSink != NULL) {
|
| - ures_getAllArrayItems(pResData, res, value, *subSink, errorCode);
|
| - }
|
| - } else if (URES_IS_TABLE(type)) {
|
| - int32_t numItems = getTableLength(pResData, res);
|
| - icu::ResourceTableSink *subSink = sink.getOrCreateTableSink(i, numItems, errorCode);
|
| - if (subSink != NULL) {
|
| - ures_getAllTableItems(pResData, res, value, *subSink, errorCode);
|
| - }
|
| - /* TODO: settle on how to deal with aliases, port to Java
|
| - } else if (type == URES_ALIAS) {
|
| - // aliases not handled in resource enumeration
|
| - errorCode = U_UNSUPPORTED_ERROR;
|
| - return; */
|
| - } else {
|
| - value.setResource(res);
|
| - sink.put(i, value, errorCode);
|
| - }
|
| - if(U_FAILURE(errorCode)) { return; }
|
| +UBool icu::ResourceArray::getValue(int32_t i, icu::ResourceValue &value) const {
|
| + if(0 <= i && i < length) {
|
| + icu::ResourceDataValue &rdValue = static_cast<icu::ResourceDataValue &>(value);
|
| + rdValue.setResource(internalGetResource(rdValue.pResData, i));
|
| + return TRUE;
|
| }
|
| - sink.leave(errorCode);
|
| + return FALSE;
|
| }
|
|
|
| U_CFUNC Resource
|
| @@ -974,7 +985,7 @@ typedef struct Row {
|
| int32_t keyIndex, sortIndex;
|
| } Row;
|
|
|
| -static int32_t
|
| +static int32_t U_CALLCONV
|
| ures_compareRows(const void *context, const void *left, const void *right) {
|
| const char *keyChars=(const char *)context;
|
| return (int32_t)uprv_strcmp(keyChars+((const Row *)left)->keyIndex,
|
| @@ -1050,6 +1061,7 @@ ures_swapResource(const UDataSwapper *ds,
|
| switch(RES_GET_TYPE(res)) {
|
| case URES_ALIAS:
|
| /* physically same value layout as string, fall through */
|
| + U_FALLTHROUGH;
|
| case URES_STRING:
|
| count=udata_readInt32(ds, (int32_t)*p);
|
| /* swap length */
|
|
|