ICU-868 Add new API to enumerate all of the tagged aliases
X-SVN-Rev: 9145
This commit is contained in:
parent
02aa4c915f
commit
8d525d6c11
@ -36,6 +36,7 @@
|
||||
#include "cstring.h"
|
||||
#include "cmemory.h"
|
||||
#include "ucnv_io.h"
|
||||
#include "uenumimp.h"
|
||||
#include "ucln_cmn.h"
|
||||
|
||||
/* Format of cnvalias.icu -----------------------------------------------------
|
||||
@ -142,6 +143,12 @@
|
||||
*
|
||||
*/
|
||||
|
||||
typedef struct UAliasContext {
|
||||
uint32_t stanardNum;
|
||||
uint32_t convNum;
|
||||
uint32_t listIdx;
|
||||
} UAliasContext;
|
||||
|
||||
static const char DATA_NAME[] = "cnvalias";
|
||||
static const char DATA_TYPE[] = "icu";
|
||||
|
||||
@ -290,7 +297,7 @@ ucnv_io_cleanup()
|
||||
converterListNum = 0;
|
||||
tagListNum = 0;
|
||||
aliasListNum = 0;
|
||||
untaggedConvArraySize = 0;
|
||||
untaggedConvArraySize = 0;
|
||||
taggedAliasArraySize = 0;
|
||||
taggedAliasListsSize = 0;
|
||||
stringTableSize = 0;
|
||||
@ -415,10 +422,125 @@ ucnv_io_getConverterName(const char *alias, UErrorCode *pErrorCode) {
|
||||
if (convNum < converterListNum) {
|
||||
return GET_STRING(converterList[convNum]);
|
||||
}
|
||||
/* else converter not found */
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int32_t U_CALLCONV
|
||||
ucnv_io_countStandardAliases(UEnumeration *enumerator, UErrorCode *pErrorCode) {
|
||||
int32_t value = -1;
|
||||
if (!pErrorCode || U_FAILURE(*pErrorCode)) {
|
||||
return -1;
|
||||
}
|
||||
if (enumerator) {
|
||||
UAliasContext *myContext = (UAliasContext *)(enumerator->context);
|
||||
uint32_t listOffset = taggedAliasArray[myContext->stanardNum*converterListNum + myContext->convNum];
|
||||
|
||||
if (listOffset) {
|
||||
value = taggedAliasLists[listOffset];
|
||||
}
|
||||
else {
|
||||
value = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
*pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static const char* U_CALLCONV
|
||||
ucnv_io_nextStandardAliases(UEnumeration *enumerator,
|
||||
int32_t* resultLength,
|
||||
UErrorCode *pErrorCode)
|
||||
{
|
||||
if (!pErrorCode || U_FAILURE(*pErrorCode)) {
|
||||
return NULL;
|
||||
}
|
||||
if (enumerator) {
|
||||
UAliasContext *myContext = (UAliasContext *)(enumerator->context);
|
||||
uint32_t listOffset = taggedAliasArray[myContext->stanardNum*converterListNum + myContext->convNum];
|
||||
|
||||
if (listOffset) {
|
||||
uint32_t listCount = taggedAliasLists[listOffset];
|
||||
const uint16_t *currList = taggedAliasLists + listOffset + 1;
|
||||
|
||||
if (myContext->listIdx < listCount) {
|
||||
return GET_STRING(currList[myContext->listIdx++]);
|
||||
}
|
||||
}
|
||||
/* Either we accessed a zero length list, or we enumerated too far. */
|
||||
*pErrorCode = U_INDEX_OUTOFBOUNDS_ERROR;
|
||||
}
|
||||
else {
|
||||
*pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void U_CALLCONV
|
||||
ucnv_io_resetStandardAliases(UEnumeration *enumerator, UErrorCode *pErrorCode) {
|
||||
if (pErrorCode && U_SUCCESS(*pErrorCode)) {
|
||||
if (enumerator) {
|
||||
((UAliasContext *)(enumerator->context))->listIdx = 0;
|
||||
}
|
||||
else {
|
||||
*pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void U_CALLCONV
|
||||
ucnv_io_closeUEnumeration(UEnumeration *enumerator) {
|
||||
uprv_free(enumerator->context);
|
||||
uprv_free(enumerator);
|
||||
}
|
||||
|
||||
/* Enumerate the aliases for the specified converter and standard tag */
|
||||
static const UEnumeration gEnumAliases = {
|
||||
NULL,
|
||||
ucnv_io_closeUEnumeration,
|
||||
ucnv_io_countStandardAliases,
|
||||
NULL,
|
||||
ucnv_io_nextStandardAliases,
|
||||
ucnv_io_resetStandardAliases
|
||||
};
|
||||
|
||||
U_CAPI UEnumeration *
|
||||
ucnv_openStandardNames(const char *convName,
|
||||
const char *standard,
|
||||
UErrorCode *pErrorCode)
|
||||
{
|
||||
UEnumeration *myEnum = NULL;
|
||||
if (haveAliasData(pErrorCode) && isAlias(convName, pErrorCode)) {
|
||||
uint32_t convNum = findConverter(convName, pErrorCode);
|
||||
uint32_t tagNum = getTagNumber(standard);
|
||||
if (tagNum < (tagListNum - NUM_RESERVED_TAGS) && convNum < converterListNum) {
|
||||
UAliasContext *myContext;
|
||||
|
||||
myEnum = uprv_malloc(sizeof(UEnumeration));
|
||||
if (myEnum == NULL) {
|
||||
*pErrorCode = U_MEMORY_ALLOCATION_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
uprv_memcpy(myEnum, &gEnumAliases, sizeof(UEnumeration));
|
||||
myContext = uprv_malloc(sizeof(UAliasContext));
|
||||
if (myContext == NULL) {
|
||||
*pErrorCode = U_MEMORY_ALLOCATION_ERROR;
|
||||
uprv_free(myEnum);
|
||||
return NULL;
|
||||
}
|
||||
myEnum->context = myContext;
|
||||
myContext->stanardNum = tagNum;
|
||||
myContext->convNum = convNum;
|
||||
myContext->listIdx = 0;
|
||||
}
|
||||
/* else converter or tag not found */
|
||||
}
|
||||
return myEnum;
|
||||
}
|
||||
|
||||
U_CFUNC uint16_t
|
||||
ucnv_io_countAliases(const char *alias, UErrorCode *pErrorCode) {
|
||||
if(haveAliasData(pErrorCode) && isAlias(alias, pErrorCode)) {
|
||||
@ -430,7 +552,9 @@ ucnv_io_countAliases(const char *alias, UErrorCode *pErrorCode) {
|
||||
if (listOffset) {
|
||||
return taggedAliasLists[listOffset];
|
||||
}
|
||||
/* else this shouldn't happen. internal program error */
|
||||
}
|
||||
/* else converter not found */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -453,7 +577,9 @@ ucnv_io_getAliases(const char *alias, uint16_t start, const char **aliases, UErr
|
||||
aliases[currAlias] = GET_STRING(currList[currAlias]);
|
||||
}
|
||||
}
|
||||
/* else this shouldn't happen. internal program error */
|
||||
}
|
||||
/* else converter not found */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -476,7 +602,9 @@ ucnv_io_getAlias(const char *alias, uint16_t n, UErrorCode *pErrorCode) {
|
||||
}
|
||||
*pErrorCode = U_INDEX_OUTOFBOUNDS_ERROR;
|
||||
}
|
||||
/* else this shouldn't happen. internal program error */
|
||||
}
|
||||
/* else converter not found */
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -503,7 +631,7 @@ ucnv_getStandard(uint16_t n, UErrorCode *pErrorCode) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
U_CFUNC const char * U_EXPORT2
|
||||
U_CAPI const char * U_EXPORT2
|
||||
ucnv_getStandardName(const char *alias, const char *standard, UErrorCode *pErrorCode) {
|
||||
if (haveAliasData(pErrorCode) && isAlias(alias, pErrorCode)) {
|
||||
uint32_t idx;
|
||||
@ -562,11 +690,11 @@ void
|
||||
ucnv_io_flushAvailableConverterCache() {
|
||||
if (availableConverters) {
|
||||
umtx_lock(NULL);
|
||||
availableConverterCount = 0;
|
||||
uprv_free((char **)availableConverters);
|
||||
availableConverters = NULL;
|
||||
umtx_unlock(NULL);
|
||||
}
|
||||
availableConverterCount = 0;
|
||||
}
|
||||
|
||||
static UBool haveAvailableConverterList(UErrorCode *pErrorCode) {
|
||||
|
@ -35,6 +35,7 @@ typedef struct UConverter UConverter;
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
#include "unicode/ucnv_err.h"
|
||||
#include "unicode/uenum.h"
|
||||
|
||||
U_CDECL_BEGIN
|
||||
|
||||
@ -1017,6 +1018,34 @@ ucnv_getAlias(const char *alias, uint16_t n, UErrorCode *pErrorCode);
|
||||
U_CAPI void U_EXPORT2
|
||||
ucnv_getAliases(const char *alias, const char **aliases, UErrorCode *pErrorCode);
|
||||
|
||||
/**
|
||||
* Return a new UEnumeration object for enumerating all the
|
||||
* alias names for a given converter that are recognized by a standard.
|
||||
* This method only enumerates the listed entries in the alias file.
|
||||
* The convrtrs.txt file can be modified to change the results of
|
||||
* this function.
|
||||
* The first result in this list is the same result given by
|
||||
* <code>ucnv_getStandardName</code>, which is the default alias for
|
||||
* the specified standard name. The returned object must be closed with
|
||||
* <code>uenum_close</code> when you are done with the object.
|
||||
*
|
||||
* @param convName original converter name
|
||||
* @param standard name of the standard governing the names; MIME and IANA
|
||||
* are such standards
|
||||
* @param pErrorCode The error code
|
||||
* @return A UEnumeration object for getting all aliases that are recognized
|
||||
* by a standard. If any of the parameters are invalid, NULL
|
||||
* is returned.
|
||||
* @see ucnv_getStandardName
|
||||
* @see uenum_close
|
||||
* @see uenum_next
|
||||
*/
|
||||
U_CAPI UEnumeration *
|
||||
ucnv_openStandardNames(const char *convName,
|
||||
const char *standard,
|
||||
UErrorCode *pErrorCode);
|
||||
|
||||
|
||||
/**
|
||||
* Gives the number of standards associated to converter names.
|
||||
* @return number of standards
|
||||
|
@ -17,6 +17,9 @@
|
||||
#include "cstring.h"
|
||||
#include "cintltst.h"
|
||||
|
||||
#define ARRAY_SIZE(array) (int32_t)(sizeof array / sizeof array[0])
|
||||
|
||||
static void TestStandardName(void);
|
||||
static void TestStandardNames(void);
|
||||
|
||||
void addStandardNamesTest(TestNode** root);
|
||||
@ -25,7 +28,8 @@ void addStandardNamesTest(TestNode** root);
|
||||
void
|
||||
addStandardNamesTest(TestNode** root)
|
||||
{
|
||||
addTest(root, &TestStandardNames, "stdnmtst/TestStandardNames");
|
||||
addTest(root, &TestStandardName, "stdnmtst/TestStandardName");
|
||||
addTest(root, &TestStandardNames, "stdnmtst/TestStandardNames");
|
||||
}
|
||||
|
||||
static int dotestname(const char *name, const char *standard, const char *expected) {
|
||||
@ -47,7 +51,7 @@ static int dotestname(const char *name, const char *standard, const char *expect
|
||||
return res;
|
||||
}
|
||||
|
||||
static void TestStandardNames()
|
||||
static void TestStandardName()
|
||||
{
|
||||
int res = 1;
|
||||
|
||||
@ -86,8 +90,64 @@ static void TestStandardNames()
|
||||
/*dotestname("cp1252", "MIME", "windows-1252") &&*/
|
||||
dotestname("ascii", "MIME", "us-ascii") &&
|
||||
dotestname("ascii", "IANA", "ANSI_X3.4-1968") &&
|
||||
dotestname("cp850", "IANA", "IBM850")) {
|
||||
dotestname("cp850", "IANA", "IBM850"))
|
||||
{
|
||||
log_verbose("PASS: getting IANA and MIME stadard names works\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static UBool doTestNames(const char *name, const char *standard, const char **expected, int32_t size) {
|
||||
UErrorCode err = U_ZERO_ERROR;
|
||||
UEnumeration *myEnum = ucnv_openStandardNames(name, standard, &err);
|
||||
int32_t enumCount = uenum_count(myEnum, &err);
|
||||
int32_t idx;
|
||||
if (size != enumCount) {
|
||||
log_err("FAIL: different size arrays. Got %d. Expected %d\n", enumCount, size);
|
||||
return 0;
|
||||
}
|
||||
if (size < 0 && myEnum) {
|
||||
log_err("FAIL: size < 0, but recieved an actual object\n");
|
||||
return 0;
|
||||
}
|
||||
log_verbose("\n%s %s\n", name, standard);
|
||||
for (idx = 0; idx < enumCount; idx++) {
|
||||
const char *enumName = uenum_next(myEnum, NULL, &err);
|
||||
const char *testName = expected[idx];
|
||||
if (uprv_strcmp(enumName, testName) != 0 || U_FAILURE(err)) {
|
||||
log_err("FAIL: uenum_next(%d) == \"%s\". expected \"%s\", error=%s\n",
|
||||
idx, enumName, testName, u_errorName(err));
|
||||
}
|
||||
log_verbose("%s\n", enumName);
|
||||
err = U_ZERO_ERROR;
|
||||
}
|
||||
uenum_close(myEnum);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void TestStandardNames()
|
||||
{
|
||||
UErrorCode err = U_ZERO_ERROR;
|
||||
static const char *asciiIANA[] = {
|
||||
"ANSI_X3.4-1968",
|
||||
"US-ASCII",
|
||||
"ASCII",
|
||||
"ANSI_X3.4-1986",
|
||||
"ISO_646.irv:1991",
|
||||
"ISO646-US",
|
||||
"us",
|
||||
"csASCII",
|
||||
"iso-ir-6",
|
||||
"cp367",
|
||||
};
|
||||
static const char *asciiMIME[] = {
|
||||
"US-ASCII"
|
||||
};
|
||||
doTestNames("ASCII", "IANA", asciiIANA, ARRAY_SIZE(asciiIANA));
|
||||
doTestNames("US-ASCII", "IANA", asciiIANA, ARRAY_SIZE(asciiIANA));
|
||||
doTestNames("ASCII", "MIME", asciiMIME, ARRAY_SIZE(asciiMIME));
|
||||
doTestNames("ascii", "mime", asciiMIME, ARRAY_SIZE(asciiMIME));
|
||||
|
||||
doTestNames("ASCII", "crazy", asciiMIME, -1);
|
||||
doTestNames("crazy", "MIME", asciiMIME, -1);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user