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 "cstring.h"
|
||||||
#include "cmemory.h"
|
#include "cmemory.h"
|
||||||
#include "ucnv_io.h"
|
#include "ucnv_io.h"
|
||||||
|
#include "uenumimp.h"
|
||||||
#include "ucln_cmn.h"
|
#include "ucln_cmn.h"
|
||||||
|
|
||||||
/* Format of cnvalias.icu -----------------------------------------------------
|
/* 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_NAME[] = "cnvalias";
|
||||||
static const char DATA_TYPE[] = "icu";
|
static const char DATA_TYPE[] = "icu";
|
||||||
|
|
||||||
@ -290,7 +297,7 @@ ucnv_io_cleanup()
|
|||||||
converterListNum = 0;
|
converterListNum = 0;
|
||||||
tagListNum = 0;
|
tagListNum = 0;
|
||||||
aliasListNum = 0;
|
aliasListNum = 0;
|
||||||
untaggedConvArraySize = 0;
|
untaggedConvArraySize = 0;
|
||||||
taggedAliasArraySize = 0;
|
taggedAliasArraySize = 0;
|
||||||
taggedAliasListsSize = 0;
|
taggedAliasListsSize = 0;
|
||||||
stringTableSize = 0;
|
stringTableSize = 0;
|
||||||
@ -415,10 +422,125 @@ ucnv_io_getConverterName(const char *alias, UErrorCode *pErrorCode) {
|
|||||||
if (convNum < converterListNum) {
|
if (convNum < converterListNum) {
|
||||||
return GET_STRING(converterList[convNum]);
|
return GET_STRING(converterList[convNum]);
|
||||||
}
|
}
|
||||||
|
/* else converter not found */
|
||||||
}
|
}
|
||||||
return NULL;
|
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
|
U_CFUNC uint16_t
|
||||||
ucnv_io_countAliases(const char *alias, UErrorCode *pErrorCode) {
|
ucnv_io_countAliases(const char *alias, UErrorCode *pErrorCode) {
|
||||||
if(haveAliasData(pErrorCode) && isAlias(alias, pErrorCode)) {
|
if(haveAliasData(pErrorCode) && isAlias(alias, pErrorCode)) {
|
||||||
@ -430,7 +552,9 @@ ucnv_io_countAliases(const char *alias, UErrorCode *pErrorCode) {
|
|||||||
if (listOffset) {
|
if (listOffset) {
|
||||||
return taggedAliasLists[listOffset];
|
return taggedAliasLists[listOffset];
|
||||||
}
|
}
|
||||||
|
/* else this shouldn't happen. internal program error */
|
||||||
}
|
}
|
||||||
|
/* else converter not found */
|
||||||
}
|
}
|
||||||
return 0;
|
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]);
|
aliases[currAlias] = GET_STRING(currList[currAlias]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* else this shouldn't happen. internal program error */
|
||||||
}
|
}
|
||||||
|
/* else converter not found */
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -476,7 +602,9 @@ ucnv_io_getAlias(const char *alias, uint16_t n, UErrorCode *pErrorCode) {
|
|||||||
}
|
}
|
||||||
*pErrorCode = U_INDEX_OUTOFBOUNDS_ERROR;
|
*pErrorCode = U_INDEX_OUTOFBOUNDS_ERROR;
|
||||||
}
|
}
|
||||||
|
/* else this shouldn't happen. internal program error */
|
||||||
}
|
}
|
||||||
|
/* else converter not found */
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -503,7 +631,7 @@ ucnv_getStandard(uint16_t n, UErrorCode *pErrorCode) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
U_CFUNC const char * U_EXPORT2
|
U_CAPI const char * U_EXPORT2
|
||||||
ucnv_getStandardName(const char *alias, const char *standard, UErrorCode *pErrorCode) {
|
ucnv_getStandardName(const char *alias, const char *standard, UErrorCode *pErrorCode) {
|
||||||
if (haveAliasData(pErrorCode) && isAlias(alias, pErrorCode)) {
|
if (haveAliasData(pErrorCode) && isAlias(alias, pErrorCode)) {
|
||||||
uint32_t idx;
|
uint32_t idx;
|
||||||
@ -562,11 +690,11 @@ void
|
|||||||
ucnv_io_flushAvailableConverterCache() {
|
ucnv_io_flushAvailableConverterCache() {
|
||||||
if (availableConverters) {
|
if (availableConverters) {
|
||||||
umtx_lock(NULL);
|
umtx_lock(NULL);
|
||||||
|
availableConverterCount = 0;
|
||||||
uprv_free((char **)availableConverters);
|
uprv_free((char **)availableConverters);
|
||||||
availableConverters = NULL;
|
availableConverters = NULL;
|
||||||
umtx_unlock(NULL);
|
umtx_unlock(NULL);
|
||||||
}
|
}
|
||||||
availableConverterCount = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static UBool haveAvailableConverterList(UErrorCode *pErrorCode) {
|
static UBool haveAvailableConverterList(UErrorCode *pErrorCode) {
|
||||||
|
@ -35,6 +35,7 @@ typedef struct UConverter UConverter;
|
|||||||
|
|
||||||
#include "unicode/utypes.h"
|
#include "unicode/utypes.h"
|
||||||
#include "unicode/ucnv_err.h"
|
#include "unicode/ucnv_err.h"
|
||||||
|
#include "unicode/uenum.h"
|
||||||
|
|
||||||
U_CDECL_BEGIN
|
U_CDECL_BEGIN
|
||||||
|
|
||||||
@ -1017,6 +1018,34 @@ ucnv_getAlias(const char *alias, uint16_t n, UErrorCode *pErrorCode);
|
|||||||
U_CAPI void U_EXPORT2
|
U_CAPI void U_EXPORT2
|
||||||
ucnv_getAliases(const char *alias, const char **aliases, UErrorCode *pErrorCode);
|
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.
|
* Gives the number of standards associated to converter names.
|
||||||
* @return number of standards
|
* @return number of standards
|
||||||
|
@ -17,6 +17,9 @@
|
|||||||
#include "cstring.h"
|
#include "cstring.h"
|
||||||
#include "cintltst.h"
|
#include "cintltst.h"
|
||||||
|
|
||||||
|
#define ARRAY_SIZE(array) (int32_t)(sizeof array / sizeof array[0])
|
||||||
|
|
||||||
|
static void TestStandardName(void);
|
||||||
static void TestStandardNames(void);
|
static void TestStandardNames(void);
|
||||||
|
|
||||||
void addStandardNamesTest(TestNode** root);
|
void addStandardNamesTest(TestNode** root);
|
||||||
@ -25,7 +28,8 @@ void addStandardNamesTest(TestNode** root);
|
|||||||
void
|
void
|
||||||
addStandardNamesTest(TestNode** root)
|
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) {
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void TestStandardNames()
|
static void TestStandardName()
|
||||||
{
|
{
|
||||||
int res = 1;
|
int res = 1;
|
||||||
|
|
||||||
@ -86,8 +90,64 @@ static void TestStandardNames()
|
|||||||
/*dotestname("cp1252", "MIME", "windows-1252") &&*/
|
/*dotestname("cp1252", "MIME", "windows-1252") &&*/
|
||||||
dotestname("ascii", "MIME", "us-ascii") &&
|
dotestname("ascii", "MIME", "us-ascii") &&
|
||||||
dotestname("ascii", "IANA", "ANSI_X3.4-1968") &&
|
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");
|
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