| |
| /******************************************************************************* |
| * * |
| * COPYRIGHT: * |
| * (C) Copyright International Business Machines Corporation, 1998 * |
| * Licensed Material - Program-Property of IBM - All Rights Reserved. * |
| * US Government Users Restricted Rights - Use, duplication, or disclosure * |
| * restricted by GSA ADP Schedule Contract with IBM Corp. * |
| * * |
| *******************************************************************************/ |
| /* C++ wrappers for the ICUs Codeset Conversion Routines*/ |
| |
| class Locale; |
| class UnicodeString; |
| class Mutex; |
| |
| #include "utypes.h" |
| #include "resbund.h" |
| #include "cmemory.h" |
| #include "mutex.h" |
| extern "C" { |
| #include "ucnv_io.h" |
| #include "ucnv_bld.h" |
| #include "ucnv.h" |
| } |
| #include "convert.h" |
| |
| |
| |
| UnicodeConverterCPP::UnicodeConverterCPP() |
| { |
| UErrorCode err = ZERO_ERROR; |
| myUnicodeConverter = ucnv_open(NULL, &err); |
| } |
| UnicodeConverterCPP::UnicodeConverterCPP(const char* name, UErrorCode& err) |
| { |
| myUnicodeConverter = ucnv_open(name, &err); |
| } |
| |
| UnicodeConverterCPP::UnicodeConverterCPP(const UnicodeString& name, UErrorCode& err) |
| { |
| char myName[MAX_CONVERTER_NAME_LENGTH]; |
| int i; |
| name.extract(0, i = name.size(), myName); |
| myName[i]='\0'; |
| myUnicodeConverter = ucnv_open(myName, &err); |
| } |
| |
| |
| UnicodeConverterCPP::UnicodeConverterCPP(int32_t codepageNumber, |
| UCNV_PLATFORM platform, |
| UErrorCode& err) |
| { |
| myUnicodeConverter = ucnv_openCCSID(codepageNumber, |
| platform, |
| &err); |
| } |
| |
| UnicodeConverterCPP& UnicodeConverterCPP::operator=(const UnicodeConverterCPP& that) |
| { |
| { |
| /*Decrements the overwritten converter's ref count |
| *Increments the assigner converter's ref count |
| */ |
| Mutex updateReferenceCounters; |
| myUnicodeConverter->sharedData->referenceCounter--; |
| that.myUnicodeConverter->sharedData->referenceCounter++; |
| } |
| |
| *myUnicodeConverter = *(that.myUnicodeConverter); |
| return *this; |
| } |
| |
| bool_t UnicodeConverterCPP::operator==(const UnicodeConverterCPP& that) const |
| { |
| if ((myUnicodeConverter->sharedData == that.myUnicodeConverter->sharedData) && |
| (myUnicodeConverter->fromCharErrorBehaviour == that.myUnicodeConverter->fromCharErrorBehaviour) && |
| (myUnicodeConverter->toUnicodeStatus == that.myUnicodeConverter->toUnicodeStatus) && |
| (myUnicodeConverter->subCharLen == that.myUnicodeConverter->subCharLen) && |
| (icu_memcmp(myUnicodeConverter->subChar, that.myUnicodeConverter->subChar, myUnicodeConverter->subCharLen) == 0) && |
| (myUnicodeConverter->UCharErrorBufferLength == that.myUnicodeConverter->UCharErrorBufferLength) && |
| (myUnicodeConverter->charErrorBufferLength == that.myUnicodeConverter->charErrorBufferLength) && |
| (icu_memcmp(myUnicodeConverter->UCharErrorBuffer, that.myUnicodeConverter->UCharErrorBuffer, myUnicodeConverter->UCharErrorBufferLength) == 0) && |
| (icu_memcmp(myUnicodeConverter->charErrorBuffer, that.myUnicodeConverter->charErrorBuffer, myUnicodeConverter->charErrorBufferLength) == 0) && |
| (myUnicodeConverter->fromUCharErrorBehaviour == that.myUnicodeConverter->fromUCharErrorBehaviour)) |
| return TRUE; |
| else return FALSE; |
| } |
| |
| bool_t UnicodeConverterCPP::operator!=(const UnicodeConverterCPP& that) const |
| { |
| return !(*this == that); |
| } |
| |
| UnicodeConverterCPP::UnicodeConverterCPP(const UnicodeConverterCPP& that) |
| { |
| /*increments the referenceCounter to let the static table know |
| *it has one more client |
| */ |
| myUnicodeConverter = new UConverter; |
| { |
| Mutex updateReferenceCounter; |
| that.myUnicodeConverter->sharedData->referenceCounter++; |
| } |
| *myUnicodeConverter = *(that.myUnicodeConverter); |
| } |
| |
| |
| UnicodeConverterCPP::~UnicodeConverterCPP() |
| { |
| ucnv_close(myUnicodeConverter); |
| } |
| |
| void |
| UnicodeConverterCPP::fromUnicodeString(char* target, |
| int32_t& targetSize, |
| const UnicodeString& source, |
| UErrorCode& err) const |
| { |
| const UChar* mySource = NULL; |
| int32_t mySourceLength = 0; |
| UConverter myConverter; |
| char *myTarget = NULL; |
| |
| if (FAILURE(err)) return; |
| |
| if ((myUnicodeConverter == NULL) || source.isBogus() || (targetSize <= 0)) |
| { |
| err = ILLEGAL_ARGUMENT_ERROR; |
| return; |
| } |
| |
| /*makes a local copy of the UnicodeConverter*/ |
| myConverter = *myUnicodeConverter; |
| |
| /*Removes all state info on the UnicodeConverter*/ |
| ucnv_reset(&myConverter); |
| |
| |
| mySourceLength = source.size(); |
| mySource = source.getUChars(); |
| myTarget = target; |
| ucnv_fromUnicode(&myConverter, |
| &myTarget, |
| target + targetSize, |
| &mySource, |
| mySource + mySourceLength, |
| NULL, |
| TRUE, |
| &err); |
| targetSize = myTarget - target; |
| |
| return; |
| } |
| |
| void |
| UnicodeConverterCPP::toUnicodeString(UnicodeString& target, |
| const char* source, |
| int32_t sourceSize, |
| UErrorCode& err) const |
| { |
| const char* mySource = source; |
| const char* mySourceLimit = source + sourceSize; |
| UChar* myTargetUChars = NULL; |
| UChar* myTargetUCharsAlias = NULL; |
| int32_t myTargetUCharsLength = 0; |
| UConverter myConverter; |
| |
| if (FAILURE(err)) return; |
| if ((myUnicodeConverter == NULL) || target.isBogus() || (sourceSize <= 0)) |
| { |
| err = ILLEGAL_ARGUMENT_ERROR; |
| return; |
| } |
| |
| /*makes a local bitwise copy of the UnicodeConverter*/ |
| myConverter = *myUnicodeConverter; |
| |
| /*Removes all state info on the UnicodeConverter*/ |
| ucnv_reset(&myConverter); |
| /*Allocates the theoritically (Not counting added bytes from the error functions) max buffer |
| *on a "normal" call, only one iteration will be necessary. |
| */ |
| myTargetUChars = |
| (UChar*)icu_malloc(sizeof(UChar)*(myTargetUCharsLength = (sourceSize/(int32_t)getMinBytesPerChar()))); |
| |
| if (myTargetUChars == NULL) |
| { |
| err = MEMORY_ALLOCATION_ERROR; |
| return; |
| } |
| /*renders the target clean*/ |
| target.remove(); |
| |
| /*Will loop until (re-use the same buffer) until no more memory is requested |
| *or an error (other than INDEX_OUTOF_BOUNDS) is encountered |
| */ |
| do |
| { |
| err = ZERO_ERROR; |
| myTargetUCharsAlias = myTargetUChars; |
| ucnv_toUnicode(&myConverter, |
| &myTargetUCharsAlias, |
| myTargetUChars + myTargetUCharsLength, |
| &mySource, |
| mySourceLimit, |
| NULL, |
| TRUE, |
| &err); |
| |
| /*appends what we got thus far to the UnicodeString*/ |
| target.replace((UTextOffset)target.size(), |
| myTargetUCharsAlias - myTargetUChars, |
| myTargetUChars, |
| myTargetUCharsAlias - myTargetUChars); |
| /*Checks for the integrity of target (UnicodeString) as it adds data to it*/ |
| if (target.isBogus()) err = MEMORY_ALLOCATION_ERROR; |
| } while (err == INDEX_OUTOFBOUNDS_ERROR); |
| |
| |
| icu_free(myTargetUChars); |
| |
| return; |
| } |
| |
| |
| |
| void |
| UnicodeConverterCPP::fromUnicode(char*& target, |
| const char* targetLimit, |
| const UChar*& source, |
| const UChar* sourceLimit, |
| int32_t *offsets, |
| bool_t flush, |
| UErrorCode& err) |
| { |
| ucnv_fromUnicode(myUnicodeConverter, |
| &target, |
| targetLimit, |
| &source, |
| sourceLimit, |
| offsets, |
| flush, |
| &err); |
| } |
| |
| |
| |
| void |
| UnicodeConverterCPP::toUnicode(UChar*& target, |
| const UChar* targetLimit, |
| const char*& source, |
| const char* sourceLimit, |
| int32_t* offsets, |
| bool_t flush, |
| UErrorCode& err) |
| { |
| ucnv_toUnicode(myUnicodeConverter, |
| &target, |
| targetLimit, |
| &source, |
| sourceLimit, |
| offsets, |
| flush, |
| &err); |
| } |
| |
| const char* |
| UnicodeConverterCPP::getName(UErrorCode& err) const |
| { |
| return ucnv_getName(myUnicodeConverter, &err); |
| } |
| |
| int8_t |
| UnicodeConverterCPP::getMaxBytesPerChar() const |
| { |
| return ucnv_getMaxCharSize(myUnicodeConverter); |
| } |
| |
| int8_t |
| UnicodeConverterCPP::getMinBytesPerChar() const |
| { |
| return ucnv_getMinCharSize(myUnicodeConverter); |
| } |
| |
| void |
| UnicodeConverterCPP::getSubstitutionChars(char* subChars, |
| int8_t& len, |
| UErrorCode& err) const |
| { |
| ucnv_getSubstChars(myUnicodeConverter, |
| subChars, |
| &len, |
| &err); |
| } |
| |
| void |
| UnicodeConverterCPP::setSubstitutionChars(const char* subChars, |
| int8_t len, |
| UErrorCode& err) |
| { |
| ucnv_setSubstChars(myUnicodeConverter, |
| subChars, |
| len, |
| &err); |
| } |
| |
| |
| void |
| UnicodeConverterCPP::resetState() |
| { |
| ucnv_reset(myUnicodeConverter); |
| } |
| |
| |
| int32_t |
| UnicodeConverterCPP::getCodepage(UErrorCode& err) const |
| { |
| return ucnv_getCCSID(myUnicodeConverter, &err); |
| } |
| |
| UCNV_ToUCallBack |
| UnicodeConverterCPP::getMissingCharAction() const |
| { |
| return ucnv_getToUCallBack(myUnicodeConverter); |
| } |
| |
| UCNV_FromUCallBack |
| UnicodeConverterCPP::getMissingUnicodeAction() const |
| { |
| return ucnv_getFromUCallBack(myUnicodeConverter); |
| } |
| |
| |
| void |
| UnicodeConverterCPP::setMissingCharAction(UCNV_ToUCallBack action, |
| UErrorCode& err) |
| { |
| ucnv_setToUCallBack(myUnicodeConverter, action, &err); |
| } |
| |
| void |
| UnicodeConverterCPP::setMissingUnicodeAction(UCNV_FromUCallBack action, |
| UErrorCode& err) |
| { |
| ucnv_setFromUCallBack(myUnicodeConverter, action, &err); |
| } |
| |
| |
| void |
| UnicodeConverterCPP::getDisplayName(const Locale& displayLocale, |
| UnicodeString& displayName) const |
| { |
| |
| UErrorCode err = ZERO_ERROR; |
| ResourceBundle rb("", displayLocale, err); |
| char tablename[MAX_CONVERTER_NAME_LENGTH]; |
| |
| if (SUCCESS(err)) |
| { |
| rb.getString(UnicodeString(tablename), displayName, err); |
| } |
| |
| if (FAILURE(err)) |
| { |
| /*Error While creating the resource bundle use the internal name instead*/ |
| displayName.remove(); |
| displayName = getName(err); /*Get the raw ASCII name*/ |
| |
| } |
| |
| return; |
| |
| } |
| |
| |
| UCNV_PLATFORM |
| UnicodeConverterCPP::getCodepagePlatform(UErrorCode &err) const |
| { |
| return ucnv_getPlatform(myUnicodeConverter, &err); |
| } |
| |
| UCNV_TYPE UnicodeConverterCPP::getType() const |
| { |
| return ucnv_getType(myUnicodeConverter); |
| } |
| |
| void UnicodeConverterCPP::getStarters(bool_t starters[256], |
| UErrorCode& err) const |
| { |
| ucnv_getStarters(myUnicodeConverter, |
| starters, |
| &err); |
| return; |
| } |
| |
| const char* const* |
| UnicodeConverterCPP::getAvailableNames(int32_t& num, UErrorCode& err) |
| { |
| num = ucnv_countAvailable(); |
| return AVAILABLE_CONVERTERS_NAMES; |
| |
| } |
| |
| int32_t UnicodeConverterCPP::flushCache() |
| { |
| return ucnv_flushCache(); |
| } |
| |
| |
| |