ICU-868 Add new API to enumerate all of the tagged aliases

X-SVN-Rev: 9145
This commit is contained in:
George Rhoten 2002-07-13 16:32:16 +00:00
parent 02aa4c915f
commit 8d525d6c11
3 changed files with 223 additions and 6 deletions

View File

@ -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) {

View File

@ -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

View File

@ -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);
}