static UBool versionFilter(UChar32 ch, void* context) { static const UVersionInfo none = { 0, 0, 0, 0 }; UVersionInfo v; u_charAge(ch, v); UVersionInfo* version = (UVersionInfo*)context; return uprv_memcmp(&v, &none, sizeof(v)) > 0 && uprv_memcmp(&v, version, sizeof(v)) <= 0; }
static int32_t findUnicodeVersion(const UVersionInfo version) { int32_t i; for(i=0; /* while(version>unicodeVersions[i]) {} */ i<UNI_VER_COUNT && uprv_memcmp(version, unicodeVersions[i], 4)>0; ++i) {} if(0<i && i<UNI_VER_COUNT && uprv_memcmp(version, unicodeVersions[i], 4)<0) { --i; /* fix 4.0.2 to land before 4.1, for valid x>=ucdVersion comparisons */ } return i; /* version>=unicodeVersions[i] && version<unicodeVersions[i+1]; possible: i==UNI_VER_COUNT */ }
UBool CollationKey::operator==(const CollationKey& source) const { return getLength() == source.getLength() && (this == &source || uprv_memcmp(getBytes(), source.getBytes(), getLength()) == 0); }
Collator * Collator::createInstance(const Locale &loc, UVersionInfo version, UErrorCode &status) { Collator *collator; UVersionInfo info; collator=new RuleBasedCollator(loc, status); /* test for NULL */ if (collator == 0) { status = U_MEMORY_ALLOCATION_ERROR; return 0; } if(U_SUCCESS(status)) { collator->getVersion(info); if(0!=uprv_memcmp(version, info, sizeof(UVersionInfo))) { delete collator; status=U_MISSING_RESOURCE_ERROR; return 0; } } return collator; }
UBool CollationKey::operator==(const CollationKey& source) const { return (this->fCount == source.fCount && (this->fBytes == source.fBytes || uprv_memcmp(this->fBytes, source.fBytes, this->fCount) == 0)); }
U_CAPI UBool U_EXPORT2 ulist_containsString(const UList * list, const char * data, int32_t length) { UBool result = FALSE; const UListNode * pointer = NULL; if (list != NULL && list->size != 0) { pointer = list->head; while (pointer != NULL) { if (length == uprv_strlen(pointer->data)) { if (uprv_memcmp(data, pointer->data, length) == 0) { result = TRUE; break; } } pointer = pointer->next; } } return result; }
//----------------------------------------------------------------------------- // // setAdd Set operation on UVector // dest = dest union source // Elements may only appear once and must be sorted. // //----------------------------------------------------------------------------- void RBBITableBuilder::setAdd(UVector *dest, UVector *source) { int32_t destOriginalSize = dest->size(); int32_t sourceSize = source->size(); int32_t di = 0; MaybeStackArray<void *, 16> destArray, sourceArray; // Handle small cases without malloc void **destPtr, **sourcePtr; void **destLim, **sourceLim; if (destOriginalSize > destArray.getCapacity()) { if (destArray.resize(destOriginalSize) == NULL) { return; } } destPtr = destArray.getAlias(); destLim = destPtr + destOriginalSize; // destArray.getArrayLimit()? if (sourceSize > sourceArray.getCapacity()) { if (sourceArray.resize(sourceSize) == NULL) { return; } } sourcePtr = sourceArray.getAlias(); sourceLim = sourcePtr + sourceSize; // sourceArray.getArrayLimit()? // Avoid multiple "get element" calls by getting the contents into arrays (void) dest->toArray(destPtr); (void) source->toArray(sourcePtr); dest->setSize(sourceSize+destOriginalSize, *fStatus); while (sourcePtr < sourceLim && destPtr < destLim) { if (*destPtr == *sourcePtr) { dest->setElementAt(*sourcePtr++, di++); destPtr++; } // This check is required for machines with segmented memory, like i5/OS. // Direct pointer comparison is not recommended. else if (uprv_memcmp(destPtr, sourcePtr, sizeof(void *)) < 0) { dest->setElementAt(*destPtr++, di++); } else { /* *sourcePtr < *destPtr */ dest->setElementAt(*sourcePtr++, di++); } } // At most one of these two cleanup loops will execute while (destPtr < destLim) { dest->setElementAt(*destPtr++, di++); } while (sourcePtr < sourceLim) { dest->setElementAt(*sourcePtr++, di++); } dest->setSize(di, *fStatus); }
/* test one string with the ICU and the reference BOCU-1 implementations */ static void roundtripBOCU1(UConverter *bocu1, int32_t number, const UChar *text, int32_t length) { UChar *roundtripRef, *roundtripICU; char *bocu1Ref, *bocu1ICU; int32_t bocu1RefLength, bocu1ICULength, roundtripRefLength, roundtripICULength; UErrorCode errorCode; roundtripRef = malloc(DEFAULT_BUFFER_SIZE * sizeof(UChar)); roundtripICU = malloc(DEFAULT_BUFFER_SIZE * sizeof(UChar)); bocu1Ref = malloc(DEFAULT_BUFFER_SIZE); bocu1ICU = malloc(DEFAULT_BUFFER_SIZE); /* Unicode -> BOCU-1 */ bocu1RefLength=writeString(text, length, (uint8_t *)bocu1Ref); errorCode=U_ZERO_ERROR; bocu1ICULength=ucnv_fromUChars(bocu1, bocu1ICU, DEFAULT_BUFFER_SIZE, text, length, &errorCode); if(U_FAILURE(errorCode)) { log_err("ucnv_fromUChars(BOCU-1, text(%d)[%d]) failed: %s\n", number, length, u_errorName(errorCode)); goto cleanup; } if(bocu1RefLength!=bocu1ICULength || 0!=uprv_memcmp(bocu1Ref, bocu1ICU, bocu1RefLength)) { log_err("Unicode(%d)[%d] -> BOCU-1: reference[%d]!=ICU[%d]\n", number, length, bocu1RefLength, bocu1ICULength); goto cleanup; } /* BOCU-1 -> Unicode */ roundtripRefLength=readString((uint8_t *)bocu1Ref, bocu1RefLength, roundtripRef); if(roundtripRefLength<0) { goto cleanup; /* readString() found an error and reported it */ } roundtripICULength=ucnv_toUChars(bocu1, roundtripICU, DEFAULT_BUFFER_SIZE, bocu1ICU, bocu1ICULength, &errorCode); if(U_FAILURE(errorCode)) { log_err("ucnv_toUChars(BOCU-1, text(%d)[%d]) failed: %s\n", number, length, u_errorName(errorCode)); goto cleanup; } if(length!=roundtripRefLength || 0!=u_memcmp(text, roundtripRef, length)) { log_err("BOCU-1 -> Unicode: original(%d)[%d]!=reference[%d]\n", number, length, roundtripRefLength); goto cleanup; } if(roundtripRefLength!=roundtripICULength || 0!=u_memcmp(roundtripRef, roundtripICU, roundtripRefLength)) { log_err("BOCU-1 -> Unicode: reference(%d)[%d]!=ICU[%d]\n", number, roundtripRefLength, roundtripICULength); goto cleanup; } cleanup: free(roundtripRef); free(roundtripICU); free(bocu1Ref); free(bocu1ICU); }
void CollationRegressionTest::TestT7189() { UErrorCode status = U_ZERO_ERROR; UCollator *coll; uint32_t i; static const UChar text1[][CollationRegressionTest::MAX_TOKEN_LEN] = { // "Achter De Hoven" { 0x41, 0x63, 0x68, 0x74, 0x65, 0x72, 0x20, 0x44, 0x65, 0x20, 0x48, 0x6F, 0x76, 0x65, 0x6E, 0x00 }, // "ABC" { 0x41, 0x42, 0x43, 0x00 }, // "HELLO world!" { 0x48, 0x45, 0x4C, 0x4C, 0x4F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x00 } }; static const UChar text2[][CollationRegressionTest::MAX_TOKEN_LEN] = { // "Achter de Hoven" { 0x41, 0x63, 0x68, 0x74, 0x65, 0x72, 0x20, 0x64, 0x65, 0x20, 0x48, 0x6F, 0x76, 0x65, 0x6E, 0x00 }, // "abc" { 0x61, 0x62, 0x63, 0x00 }, // "hello world!" { 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x00 } }; // Open the collator coll = ucol_openFromShortString("EO_S1", FALSE, NULL, &status); if (U_FAILURE(status)) { errln("Failed to create a collator for short string EO_S1"); return; } for (i = 0; i < sizeof(text1) / (CollationRegressionTest::MAX_TOKEN_LEN * sizeof(UChar)); i++) { uint8_t key1[100], key2[100]; int32_t len1, len2; len1 = calcKeyIncremental(coll, text1[i], -1, key1, sizeof(key1), status); if (U_FAILURE(status)) { errln(UnicodeString("Failed to get a partial collation key for ") + text1[i]); break; } len2 = calcKeyIncremental(coll, text2[i], -1, key2, sizeof(key2), status); if (U_FAILURE(status)) { errln(UnicodeString("Failed to get a partial collation key for ") + text2[i]); break; } if (len1 == len2 && uprv_memcmp(key1, key2, len1) == 0) { errln(UnicodeString("Failed: Identical key\n") + " text1: " + text1[i] + "\n" + " text2: " + text2[i] + "\n" + " key : " + TestUtility::hex(key1, len1)); } else { logln(UnicodeString("Keys produced -\n") + " text1: " + text1[i] + "\n" + " key1 : " + TestUtility::hex(key1, len1) + "\n" + " text2: " + text2[i] + "\n" + " key2 : " + TestUtility::hex(key2, len2)); } } ucol_close(coll); }
UBool CollationElementIterator::operator==( const CollationElementIterator& that) const { if (this == &that || m_data_ == that.m_data_) { return TRUE; } // option comparison if (m_data_->iteratordata_.coll != that.m_data_->iteratordata_.coll) { return FALSE; } // the constructor and setText always sets a length // and we only compare the string not the contents of the normalization // buffer int thislength = (int)(m_data_->iteratordata_.endp - m_data_->iteratordata_.string); int thatlength = (int)(that.m_data_->iteratordata_.endp - that.m_data_->iteratordata_.string); if (thislength != thatlength) { return FALSE; } if (uprv_memcmp(m_data_->iteratordata_.string, that.m_data_->iteratordata_.string, thislength * U_SIZEOF_UCHAR) != 0) { return FALSE; } if (getOffset() != that.getOffset()) { return FALSE; } // checking normalization buffer if ((m_data_->iteratordata_.flags & UCOL_ITER_HASLEN) == 0) { if ((that.m_data_->iteratordata_.flags & UCOL_ITER_HASLEN) != 0) { return FALSE; } // both are in the normalization buffer if (m_data_->iteratordata_.pos - m_data_->iteratordata_.writableBuffer.getBuffer() != that.m_data_->iteratordata_.pos - that.m_data_->iteratordata_.writableBuffer.getBuffer()) { // not in the same position in the normalization buffer return FALSE; } } else if ((that.m_data_->iteratordata_.flags & UCOL_ITER_HASLEN) == 0) { return FALSE; } // checking ce position return (m_data_->iteratordata_.CEpos - m_data_->iteratordata_.CEs) == (that.m_data_->iteratordata_.CEpos - that.m_data_->iteratordata_.CEs); }
//----------------------------------------------------------------------------- // // Operator == Consider two RBBIDataWrappers to be equal if they // refer to the same underlying data. Although // the data wrappers are normally shared between // iterator instances, it's possible to independently // open the same data twice, and get two instances, which // should still be ==. // //----------------------------------------------------------------------------- UBool RBBIDataWrapper::operator ==(const RBBIDataWrapper &other) const { if (fHeader == other.fHeader) { return TRUE; } if (fHeader->fLength != other.fHeader->fLength) { return FALSE; } if (uprv_memcmp(fHeader, other.fHeader, fHeader->fLength) == 0) { return TRUE; } return FALSE; }
U_CAPI UBool U_EXPORT2 ulist_containsString(const UList *list, const char *data, int32_t length) { if (list != NULL) { const UListNode *pointer; for (pointer = list->head; pointer != NULL; pointer = pointer->next) { if (length == uprv_strlen(pointer->data)) { if (uprv_memcmp(data, pointer->data, length) == 0) { return TRUE; } } } } return FALSE; }
UBool SearchIterator::operator==(const SearchIterator &that) const { if (this == &that) { return TRUE; } return (m_breakiterator_ == that.m_breakiterator_ && m_search_->isCanonicalMatch == that.m_search_->isCanonicalMatch && m_search_->isOverlap == that.m_search_->isOverlap && m_search_->matchedIndex == that.m_search_->matchedIndex && m_search_->matchedLength == that.m_search_->matchedLength && m_search_->textLength == that.m_search_->textLength && getOffset() == that.getOffset() && (uprv_memcmp(m_search_->text, that.m_search_->text, m_search_->textLength * sizeof(UChar)) == 0)); }
U_EXPORT UBool U_EXPORT2 operator==(const StringPiece& x, const StringPiece& y) { int32_t len = x.size(); if (len != y.size()) { return false; } if (len == 0) { return true; } const char* p = x.data(); const char* p2 = y.data(); // Test last byte in case strings share large common prefix --len; if (p[len] != p2[len]) return false; // At this point we can, but don't have to, ignore the last byte. return uprv_memcmp(p, p2, len) == 0; }
// Bitwise comparison for the collation keys. UCollationResult CollationKey::compareTo(const CollationKey& target, UErrorCode &status) const { if(U_SUCCESS(status)) { uint8_t *src = this->fBytes; uint8_t *tgt = target.fBytes; // are we comparing the same string if (src == tgt) return UCOL_EQUAL; int minLength; UCollationResult result; // are we comparing different lengths? if (this->fCount != target.fCount) { if (this->fCount < target.fCount) { minLength = this->fCount; result = UCOL_LESS; } else { minLength = target.fCount; result = UCOL_GREATER; } } else { minLength = target.fCount; result = UCOL_EQUAL; } if (minLength > 0) { int diff = uprv_memcmp(src, tgt, minLength); if (diff > 0) { return UCOL_GREATER; } else if (diff < 0) { return UCOL_LESS; } } return result; } else { return UCOL_EQUAL; } }
static void Test_aestrncpy(int32_t line, const uint8_t *expect, const uint8_t *src, int32_t len) { uint8_t str_buf[AESTRNCPY_SIZE] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; uint8_t *ret; log_verbose("\n%s:%d: Beginning test of uprv_aestrncpy(dst, src, %d)\n", __FILE__, line, len); ret = uprv_aestrncpy(str_buf, src, len); if(ret != str_buf) { log_err("\n%s:%d: FAIL: uprv_aestrncpy returned %p expected %p\n", __FILE__, line, (void*)ret, (void*)str_buf); } if(!uprv_memcmp(str_buf, expect, AESTRNCPY_SIZE)) { log_verbose("\n%s:%d: OK - compared OK.", __FILE__, line); log_verbose("\n%s:%d: expected: %s", __FILE__, line, dump_binline((uint8_t *)expect)); log_verbose("\n%s:%d: got : %s\n", __FILE__, line, dump_binline(str_buf)); } else { log_err ("\n%s:%d: FAIL: uprv_aestrncpy output differs", __FILE__, line); log_err ("\n%s:%d: expected: %s", __FILE__, line, dump_binline((uint8_t *)expect)); log_err ("\n%s:%d: got : %s\n", __FILE__, line, dump_binline(str_buf)); } }
// Bitwise comparison for the collation keys. UCollationResult CollationKey::compareTo(const CollationKey& target, UErrorCode &status) const { if(U_SUCCESS(status)) { const uint8_t *src = getBytes(); const uint8_t *tgt = target.getBytes(); // are we comparing the same string if (src == tgt) return UCOL_EQUAL; UCollationResult result; // are we comparing different lengths? int32_t minLength = getLength(); int32_t targetLength = target.getLength(); if (minLength < targetLength) { result = UCOL_LESS; } else if (minLength == targetLength) { result = UCOL_EQUAL; } else { minLength = targetLength; result = UCOL_GREATER; } if (minLength > 0) { int diff = uprv_memcmp(src, tgt, minLength); if (diff > 0) { return UCOL_GREATER; } else if (diff < 0) { return UCOL_LESS; } } return result; } else { return UCOL_EQUAL; } }
UCAConformanceTest::UCAConformanceTest() : rbUCA(NULL), testFile(NULL), status(U_ZERO_ERROR) { UCA = (RuleBasedCollator *)Collator::createInstance(Locale::getRoot(), status); if(U_FAILURE(status)) { dataerrln("Error - UCAConformanceTest: Unable to open UCA collator! - %s", u_errorName(status)); } const char *srcDir = IntlTest::getSourceTestData(status); if (U_FAILURE(status)) { dataerrln("Could not open test data %s", u_errorName(status)); return; } uprv_strcpy(testDataPath, srcDir); uprv_strcat(testDataPath, "CollationTest_"); UVersionInfo uniVersion; static const UVersionInfo v62 = { 6, 2, 0, 0 }; u_getUnicodeVersion(uniVersion); isAtLeastUCA62 = uprv_memcmp(uniVersion, v62, 4) >= 0; }
static void TestCaseTitle(void) { static const UChar beforeTitle[]= { 0x61, 0x42, 0x20, 0x69, 0x3c2, 0x20, 0xdf, 0x3c3, 0x2f, 0xfb03, 0xd93f, 0xdfff }, titleWord[]= { 0x41, 0x62, 0x20, 0x49, 0x3c2, 0x20, 0x53, 0x73, 0x3c3, 0x2f, 0x46, 0x66, 0x69, 0xd93f, 0xdfff }, titleChar[]= { 0x41, 0x42, 0x20, 0x49, 0x3a3, 0x20, 0x53, 0x73, 0x3a3, 0x2f, 0x46, 0x66, 0x69, 0xd93f, 0xdfff }; UChar buffer[32]; UBreakIterator *titleIterChars; int32_t length; UErrorCode errorCode; errorCode=U_ZERO_ERROR; titleIterChars=ubrk_open(UBRK_CHARACTER, "", beforeTitle, sizeof(beforeTitle)/U_SIZEOF_UCHAR, &errorCode); if(U_FAILURE(errorCode)) { log_err_status(errorCode, "error: ubrk_open(UBRK_CHARACTER)->%s\n", u_errorName(errorCode)); return; } /* titlecase with standard break iterator and in the same buffer */ uprv_memcpy(buffer, beforeTitle, sizeof(beforeTitle)); errorCode=U_ZERO_ERROR; length=u_strToTitle(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, buffer, sizeof(beforeTitle)/U_SIZEOF_UCHAR, NULL, "", &errorCode); if( U_FAILURE(errorCode) || length!=(sizeof(titleWord)/U_SIZEOF_UCHAR) || uprv_memcmp(titleWord, buffer, length*U_SIZEOF_UCHAR)!=0 || buffer[length]!=0 ) { log_err("error in u_strToTitle(standard iterator)=%ld error=%s string matches: %s\n", length, u_errorName(errorCode), uprv_memcmp(titleWord, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no"); } /* titlecase with UBRK_CHARACTERS and separate buffers */ buffer[0]=0xabcd; errorCode=U_ZERO_ERROR; length=u_strToTitle(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, beforeTitle, sizeof(beforeTitle)/U_SIZEOF_UCHAR, titleIterChars, "", &errorCode); if( U_FAILURE(errorCode) || length!=(sizeof(titleChar)/U_SIZEOF_UCHAR) || uprv_memcmp(titleChar, buffer, length*U_SIZEOF_UCHAR)!=0 || buffer[length]!=0 ) { log_err("error in u_strToTitle(UBRK_CHARACTERS)=%ld error=%s string matches: %s\n", length, u_errorName(errorCode), uprv_memcmp(titleChar, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no"); } /* test preflighting */ errorCode=U_ZERO_ERROR; length=u_strToTitle(NULL, 0, beforeTitle, sizeof(beforeTitle)/U_SIZEOF_UCHAR, titleIterChars, "", &errorCode); if( errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=(sizeof(titleChar)/U_SIZEOF_UCHAR) ) { log_err("error in u_strToTitle(UBRK_CHARACTERS pure preflighting)=%ld error=%s\n", length, u_errorName(errorCode)); } /* test error handling */ buffer[0]=0xabcd; errorCode=U_ZERO_ERROR; length=u_strToTitle(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, NULL, sizeof(beforeTitle)/U_SIZEOF_UCHAR, titleIterChars, "", &errorCode); if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR || buffer[0]!=0xabcd ) { log_err("error in u_strToTitle(UBRK_CHARACTERS src=NULL)=%ld error=%s buffer[0]==0x%lx\n", length, u_errorName(errorCode), buffer[0]); } buffer[0]=0xabcd; errorCode=U_ZERO_ERROR; length=u_strToTitle(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, beforeTitle, -2, titleIterChars, "", &errorCode); if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR || buffer[0]!=0xabcd ) { log_err("error in u_strToTitle(UBRK_CHARACTERS srcLength=-2)=%ld error=%s buffer[0]==0x%lx\n", length, u_errorName(errorCode), buffer[0]); } ubrk_close(titleIterChars); }
// Bitwise comparison for the collation keys. // NOTE: this is somewhat messy 'cause we can't count // on memcmp returning the exact values which match // Collator::EComparisonResult Collator::EComparisonResult CollationKey::compareTo(const CollationKey& target) const { uint8_t *src = this->fBytes; uint8_t *tgt = target.fBytes; // are we comparing the same string if (src == tgt) return Collator::EQUAL; /* int count = (this->fCount < target.fCount) ? this->fCount : target.fCount; if (count == 0) { // If count is 0, at least one of the keys is empty. // An empty key is always LESS than a non-empty one // and EQUAL to another empty if (this->fCount < target.fCount) { return Collator::LESS; } if (this->fCount > target.fCount) { return Collator::GREATER; } return Collator::EQUAL; } */ int minLength; Collator::EComparisonResult result; // are we comparing different lengths? if (this->fCount != target.fCount) { if (this->fCount < target.fCount) { minLength = this->fCount; result = Collator::LESS; } else { minLength = target.fCount; result = Collator::GREATER; } } else { minLength = target.fCount; result = Collator::EQUAL; } if (minLength > 0) { int diff = uprv_memcmp(src, tgt, minLength); if (diff > 0) { return Collator::GREATER; } else if (diff < 0) { return Collator::LESS; } } return result; /* if (result < 0) { return Collator::LESS; } if (result > 0) { return Collator::GREATER; } return Collator::EQUAL; */ }
/** * Main Windows time zone detection function. Returns the Windows * time zone, translated to an ICU time zone, or NULL upon failure. */ U_CFUNC const char* U_EXPORT2 uprv_detectWindowsTimeZone() { UErrorCode status = U_ZERO_ERROR; UResourceBundle* bundle = NULL; char* icuid = NULL; char apiStdName[MAX_LENGTH_ID]; char regStdName[MAX_LENGTH_ID]; char tmpid[MAX_LENGTH_ID]; int32_t len; int id; int errorCode; UChar ISOcodeW[3]; /* 2 letter iso code in UTF-16*/ char ISOcodeA[3]; /* 2 letter iso code in ansi */ LONG result; TZI tziKey; TZI tziReg; TIME_ZONE_INFORMATION apiTZI; BOOL isVistaOrHigher; BOOL tryPreVistaFallback; OSVERSIONINFO osVerInfo; /* Obtain TIME_ZONE_INFORMATION from the API, and then convert it to TZI. We could also interrogate the registry directly; we do this below if needed. */ uprv_memset(&apiTZI, 0, sizeof(apiTZI)); uprv_memset(&tziKey, 0, sizeof(tziKey)); uprv_memset(&tziReg, 0, sizeof(tziReg)); GetTimeZoneInformation(&apiTZI); tziKey.bias = apiTZI.Bias; uprv_memcpy((char *)&tziKey.standardDate, (char*)&apiTZI.StandardDate, sizeof(apiTZI.StandardDate)); uprv_memcpy((char *)&tziKey.daylightDate, (char*)&apiTZI.DaylightDate, sizeof(apiTZI.DaylightDate)); /* Convert the wchar_t* standard name to char* */ uprv_memset(apiStdName, 0, sizeof(apiStdName)); wcstombs(apiStdName, apiTZI.StandardName, MAX_LENGTH_ID); tmpid[0] = 0; id = GetUserGeoID(GEOCLASS_NATION); errorCode = GetGeoInfoW(id,GEO_ISO2,ISOcodeW,3,0); u_strToUTF8(ISOcodeA, 3, NULL, ISOcodeW, 3, &status); bundle = ures_openDirect(NULL, "windowsZones", &status); ures_getByKey(bundle, "mapTimezones", bundle, &status); /* Windows Vista+ provides us with a "TimeZoneKeyName" that is not localized and can be used to directly map a name in our bundle. Try to use that first if we're on Vista or higher */ uprv_memset(&osVerInfo, 0, sizeof(osVerInfo)); osVerInfo.dwOSVersionInfoSize = sizeof(osVerInfo); GetVersionEx(&osVerInfo); isVistaOrHigher = osVerInfo.dwMajorVersion >= 6; /* actually includes Windows Server 2008 as well, but don't worry about it */ tryPreVistaFallback = TRUE; if(isVistaOrHigher) { result = getTZKeyName(regStdName, sizeof(regStdName)); if(ERROR_SUCCESS == result) { UResourceBundle* winTZ = ures_getByKey(bundle, regStdName, NULL, &status); if(U_SUCCESS(status)) { const UChar* icuTZ = NULL; if (errorCode != 0) { icuTZ = ures_getStringByKey(winTZ, ISOcodeA, &len, &status); } if (errorCode==0 || icuTZ==NULL) { /* fallback to default "001" and reset status */ status = U_ZERO_ERROR; icuTZ = ures_getStringByKey(winTZ, "001", &len, &status); } if(U_SUCCESS(status)) { int index=0; while (! (*icuTZ == '\0' || *icuTZ ==' ')) { tmpid[index++]=(char)(*icuTZ++); /* safe to assume 'char' is ASCII compatible on windows */ } tmpid[index]='\0'; tryPreVistaFallback = FALSE; } } ures_close(winTZ); } } if(tryPreVistaFallback) { /* Note: We get the winid not from static tables but from resource bundle. */ while (U_SUCCESS(status) && ures_hasNext(bundle)) { UBool idFound = FALSE; const char* winid; UResourceBundle* winTZ = ures_getNextResource(bundle, NULL, &status); if (U_FAILURE(status)) { break; } winid = ures_getKey(winTZ); result = getTZI(winid, &tziReg); if (result == ERROR_SUCCESS) { /* Windows alters the DaylightBias in some situations. Using the bias and the rules suffices, so overwrite these unreliable fields. */ tziKey.standardBias = tziReg.standardBias; tziKey.daylightBias = tziReg.daylightBias; if (uprv_memcmp((char *)&tziKey, (char*)&tziReg, sizeof(tziKey)) == 0) { const UChar* icuTZ = NULL; if (errorCode != 0) { icuTZ = ures_getStringByKey(winTZ, ISOcodeA, &len, &status); } if (errorCode==0 || icuTZ==NULL) { /* fallback to default "001" and reset status */ status = U_ZERO_ERROR; icuTZ = ures_getStringByKey(winTZ, "001", &len, &status); } if (U_SUCCESS(status)) { /* Get the standard name from the registry key to compare with the one from Windows API call. */ uprv_memset(regStdName, 0, sizeof(regStdName)); result = getSTDName(winid, regStdName, sizeof(regStdName)); if (result == ERROR_SUCCESS) { if (uprv_strcmp(apiStdName, regStdName) == 0) { idFound = TRUE; } } /* tmpid buffer holds the ICU timezone ID corresponding to the timezone ID from Windows. * If none is found, tmpid buffer will contain a fallback ID (i.e. the time zone ID matching * the current time zone information) */ if (idFound || tmpid[0] == 0) { /* if icuTZ has more than one city, take only the first (i.e. terminate icuTZ at first space) */ int index=0; while (! (*icuTZ == '\0' || *icuTZ ==' ')) { tmpid[index++]=(char)(*icuTZ++); /* safe to assume 'char' is ASCII compatible on windows */ } tmpid[index]='\0'; } } } } ures_close(winTZ); if (idFound) { break; } } } /* * Copy the timezone ID to icuid to be returned. */ if (tmpid[0] != 0) { len = uprv_strlen(tmpid); icuid = (char*)uprv_calloc(len + 1, sizeof(char)); if (icuid != NULL) { uprv_strcpy(icuid, tmpid); } } ures_close(bundle); return icuid; }
U_CFUNC const char* U_EXPORT2 uprv_detectWindowsTimeZone() { UErrorCode status = U_ZERO_ERROR; UResourceBundle* bundle = NULL; char* icuid = NULL; LONG result; TZI tziKey; TZI tziReg; TIME_ZONE_INFORMATION apiTZI; /* Obtain TIME_ZONE_INFORMATION from the API, and then convert it to TZI. We could also interrogate the registry directly; we do this below if needed. */ uprv_memset(&apiTZI, 0, sizeof(apiTZI)); uprv_memset(&tziKey, 0, sizeof(tziKey)); uprv_memset(&tziReg, 0, sizeof(tziReg)); GetTimeZoneInformation(&apiTZI); tziKey.bias = apiTZI.Bias; uprv_memcpy((char *)&tziKey.standardDate, (char*)&apiTZI.StandardDate, sizeof(apiTZI.StandardDate)); uprv_memcpy((char *)&tziKey.daylightDate, (char*)&apiTZI.DaylightDate, sizeof(apiTZI.DaylightDate)); bundle = ures_openDirect(NULL, "windowsZones", &status); ures_getByKey(bundle, "mapTimezones", bundle, &status); /* Note: We get the winid not from static tables but from resource bundle. */ while (U_SUCCESS(status) && ures_hasNext(bundle)) { const char* winid; int32_t len; UResourceBundle* winTZ = ures_getNextResource(bundle, NULL, &status); if (U_FAILURE(status)) { break; } winid = ures_getKey(winTZ); result = getTZI(winid, &tziReg); if (result == ERROR_SUCCESS) { /* Windows alters the DaylightBias in some situations. Using the bias and the rules suffices, so overwrite these unreliable fields. */ tziKey.standardBias = tziReg.standardBias; tziKey.daylightBias = tziReg.daylightBias; if (uprv_memcmp((char *)&tziKey, (char*)&tziReg, sizeof(tziKey)) == 0) { const UChar* icuTZ = ures_getStringByKey(winTZ, "001", &len, &status); if (U_SUCCESS(status)) { icuid = (char*)uprv_malloc(sizeof(char) * (len + 1)); uprv_memset(icuid, 0, len + 1); u_austrncpy(icuid, icuTZ, len); } } } ures_close(winTZ); if (icuid != NULL) { break; } } ures_close(bundle); return icuid; }
static void TestAppendChar(){ static const uint8_t s[11]={0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x00}; static const uint32_t test[]={ /*append-position(unsafe), CHAR to be appended */ 0, 0x10401, 2, 0x0028, 2, 0x007f, 3, 0xd801, 1, 0x20402, 8, 0x10401, 5, 0xc0, 5, 0xc1, 5, 0xfd, 6, 0x80, 6, 0x81, 6, 0xbf, 7, 0xfe, /*append-position(safe), CHAR to be appended */ 0, 0x10401, 2, 0x0028, 3, 0x7f, 3, 0xd801, /* illegal for UTF-8 starting with Unicode 3.2 */ 1, 0x20402, 9, 0x10401, 5, 0xc0, 5, 0xc1, 5, 0xfd, 6, 0x80, 6, 0x81, 6, 0xbf, 7, 0xfe, }; static const uint16_t movedOffset[]={ /*offset-moved-to(unsafe)*/ 4, /*for append-pos: 0 , CHAR 0x10401*/ 3, 3, 6, 5, 12, 7, 7, 7, 8, 8, 8, 9, /*offset-moved-to(safe)*/ 4, /*for append-pos: 0, CHAR 0x10401*/ 3, 4, 6, 5, 11, 7, 7, 7, 8, 8, 8, 9, }; static const uint8_t result[][11]={ /*unsafe*/ {0xF0, 0x90, 0x90, 0x81, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x00}, {0x61, 0x62, 0x28, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x00}, {0x61, 0x62, 0x7f, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x00}, {0x61, 0x62, 0x63, 0xed, 0xa0, 0x81, 0x67, 0x68, 0x69, 0x6a, 0x00}, {0x61, 0xF0, 0xa0, 0x90, 0x82, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x00}, {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0xF0, 0x90, 0x90}, {0x61, 0x62, 0x63, 0x64, 0x65, 0xc3, 0x80, 0x68, 0x69, 0x6a, 0x00}, {0x61, 0x62, 0x63, 0x64, 0x65, 0xc3, 0x81, 0x68, 0x69, 0x6a, 0x00}, {0x61, 0x62, 0x63, 0x64, 0x65, 0xc3, 0xbd, 0x68, 0x69, 0x6a, 0x00}, {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0xc2, 0x80, 0x69, 0x6a, 0x00}, {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0xc2, 0x81, 0x69, 0x6a, 0x00}, {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0xc2, 0xbf, 0x69, 0x6a, 0x00}, {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0xc3, 0xbe, 0x6a, 0x00}, /*safe*/ {0xF0, 0x90, 0x90, 0x81, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x00}, {0x61, 0x62, 0x28, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x00}, {0x61, 0x62, 0x63, 0x7f, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x00}, {0x61, 0x62, 0x63, 0xef, 0xbf, 0xbf, 0x67, 0x68, 0x69, 0x6a, 0x00}, {0x61, 0xF0, 0xa0, 0x90, 0x82, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x00}, {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0xc2, 0x9f}, /*gets UTF8_ERROR_VALUE_2 which takes 2 bytes 0xc0, 0x9f*/ {0x61, 0x62, 0x63, 0x64, 0x65, 0xc3, 0x80, 0x68, 0x69, 0x6a, 0x00}, {0x61, 0x62, 0x63, 0x64, 0x65, 0xc3, 0x81, 0x68, 0x69, 0x6a, 0x00}, {0x61, 0x62, 0x63, 0x64, 0x65, 0xc3, 0xbd, 0x68, 0x69, 0x6a, 0x00}, {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0xc2, 0x80, 0x69, 0x6a, 0x00}, {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0xc2, 0x81, 0x69, 0x6a, 0x00}, {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0xc2, 0xbf, 0x69, 0x6a, 0x00}, {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0xc3, 0xbe, 0x6a, 0x00}, }; uint16_t i, count=0; uint8_t str[12]; uint32_t offset; /* UChar32 c=0;*/ uint16_t size=sizeof(s)/sizeof(s[0]); for(i=0; i<sizeof(test)/sizeof(test[0]); i=(uint16_t)(i+2)){ uprv_memcpy(str, s, size); offset=test[i]; if(count<13){ UTF8_APPEND_CHAR_UNSAFE(str, offset, test[i+1]); if(offset != movedOffset[count]){ log_err("ERROR: UTF8_APPEND_CHAR_UNSAFE failed to move the offset correctly for count=%d.\nExpectedOffset=%d currentOffset=%d\n", count, movedOffset[count], offset); } if(uprv_memcmp(str, result[count], size) !=0){ log_err("ERROR: UTF8_APPEND_CHAR_UNSAFE failed for count=%d. \nExpected:", count); printUChars(result[count], size); log_err("\nGot: "); printUChars(str, size); log_err("\n"); } }else{ UTF8_APPEND_CHAR_SAFE(str, offset, size, test[i+1]); if(offset != movedOffset[count]){ log_err("ERROR: UTF8_APPEND_CHAR_SAFE failed to move the offset correctly for count=%d.\nExpectedOffset=%d currentOffset=%d\n", count, movedOffset[count], offset); } if(uprv_memcmp(str, result[count], size) !=0){ log_err("ERROR: UTF8_APPEND_CHAR_SAFE failed for count=%d. \nExpected:", count); printUChars(result[count], size); log_err("\nGot: "); printUChars(str, size); log_err("\n"); } /*call the API instead of MACRO uprv_memcpy(str, s, size); offset=test[i]; c=test[i+1]; if((uint32_t)(c)<=0x7f) { (str)[(offset)++]=(uint8_t)(c); } else { (offset)=utf8_appendCharSafeBody(str, (int32_t)(offset), (int32_t)(size), c); } if(offset != movedOffset[count]){ log_err("ERROR: utf8_appendCharSafeBody() failed to move the offset correctly for count=%d.\nExpectedOffset=%d currentOffset=%d\n", count, movedOffset[count], offset); } if(uprv_memcmp(str, result[count], size) !=0){ log_err("ERROR: utf8_appendCharSafeBody() failed for count=%d. \nExpected:", count); printUChars(result[count], size); printf("\nGot: "); printUChars(str, size); printf("\n"); } */ } count++; } }
static void U_CALLCONV unicodeDataLineFn(void *context, char *fields[][2], int32_t fieldCount, UErrorCode *pErrorCode) { uint32_t decomp[40]; Norm norm; const char *s; char *end; uint32_t code, value; int32_t length; UBool isCompat, something=FALSE; /* ignore First and Last entries for ranges */ if( *fields[1][0]=='<' && (length=(int32_t)(fields[1][1]-fields[1][0]))>=9 && (0==uprv_memcmp(", First>", fields[1][1]-8, 8) || 0==uprv_memcmp(", Last>", fields[1][1]-7, 7)) ) { return; } /* reset the properties */ uprv_memset(&norm, 0, sizeof(Norm)); /* get the character code, field 0 */ code=(uint32_t)uprv_strtoul(fields[0][0], &end, 16); if(end<=fields[0][0] || end!=fields[0][1]) { fprintf(stderr, "gennorm: syntax error in field 0 at %s\n", fields[0][0]); *pErrorCode=U_PARSE_ERROR; exit(U_PARSE_ERROR); } /* get canonical combining class, field 3 */ value=(uint32_t)uprv_strtoul(fields[3][0], &end, 10); if(end<=fields[3][0] || end!=fields[3][1] || value>0xff) { fprintf(stderr, "gennorm: syntax error in field 3 at %s\n", fields[0][0]); *pErrorCode=U_PARSE_ERROR; exit(U_PARSE_ERROR); } if(value>0) { norm.udataCC=(uint8_t)value; something=TRUE; } /* get the decomposition, field 5 */ if(fields[5][0]<fields[5][1]) { if(*(s=fields[5][0])=='<') { ++s; isCompat=TRUE; /* skip and ignore the compatibility type name */ do { if(s==fields[5][1]) { /* missing '>' */ fprintf(stderr, "gennorm: syntax error in field 5 at %s\n", fields[0][0]); *pErrorCode=U_PARSE_ERROR; exit(U_PARSE_ERROR); } } while(*s++!='>'); } else { isCompat=FALSE; } /* parse the decomposition string */ length=u_parseCodePoints(s, decomp, sizeof(decomp)/4, pErrorCode); if(U_FAILURE(*pErrorCode)) { fprintf(stderr, "gennorm error parsing UnicodeData.txt decomposition of U+%04lx - %s\n", (long)code, u_errorName(*pErrorCode)); exit(*pErrorCode); } /* store the string */ if(length>0) { something=TRUE; if(isCompat) { norm.lenNFKD=(uint8_t)length; norm.nfkd=decomp; } else { if(length>2) { fprintf(stderr, "gennorm: error - length of NFD(U+%04lx) = %ld >2 in UnicodeData - illegal\n", (long)code, (long)length); *pErrorCode=U_PARSE_ERROR; exit(U_PARSE_ERROR); } norm.lenNFD=(uint8_t)length; norm.nfd=decomp; } } } /* check for non-character code points */ if((code&0xfffe)==0xfffe || (uint32_t)(code-0xfdd0)<0x20 || code>0x10ffff) { fprintf(stderr, "gennorm: error - properties for non-character code point U+%04lx\n", (long)code); *pErrorCode=U_PARSE_ERROR; exit(U_PARSE_ERROR); } if(something) { /* there are normalization values, so store them */ #if 0 if(beVerbose) { printf("store values for U+%04lx: cc=%d, lenNFD=%ld, lenNFKD=%ld\n", (long)code, norm.udataCC, (long)norm.lenNFD, (long)norm.lenNFKD); } #endif storeNorm(code, &norm); } }
static void U_CALLCONV derivedNormalizationPropertiesLineFn(void *context, char *fields[][2], int32_t fieldCount, UErrorCode *pErrorCode) { UChar string[32]; char *s; uint32_t start, end; int32_t count; uint8_t qcFlags; /* get code point range */ count=u_parseCodePointRange(fields[0][0], &start, &end, pErrorCode); if(U_FAILURE(*pErrorCode)) { fprintf(stderr, "gennorm: error parsing DerivedNormalizationProperties.txt mapping at %s\n", fields[0][0]); exit(*pErrorCode); } /* ignore hangul - handle explicitly */ if(start==0xac00) { return; } /* get property - ignore unrecognized ones */ s=(char *)u_skipWhitespace(fields[1][0]); if(*s=='N' && s[1]=='F') { /* quick check flag */ qcFlags=0x11; s+=2; if(*s=='K') { qcFlags<<=1; ++s; } if(*s=='C' && s[1]=='_') { s+=2; } else if(*s=='D' && s[1]=='_') { qcFlags<<=2; s+=2; } else { return; } if(0==uprv_memcmp(s, "NO", 2)) { qcFlags&=0xf; } else if(0==uprv_memcmp(s, "MAYBE", 5)) { qcFlags&=0x30; } else if(0==uprv_memcmp(s, "QC", 2) && *(s=(char *)u_skipWhitespace(s+2))==';') { /* * Unicode 4.0.1: * changes single field "NFD_NO" -> two fields "NFD_QC; N" etc. */ /* start of the field */ s=(char *)u_skipWhitespace(s+1); if(*s=='N') { qcFlags&=0xf; } else if(*s=='M') { qcFlags&=0x30; } else { return; /* do nothing for "Yes" because it's the default value */ } } else { return; /* do nothing for "Yes" because it's the default value */ } /* set this flag for all code points in this range */ while(start<=end) { setQCFlags(start++, qcFlags); } } else if(0==uprv_memcmp(s, "Comp_Ex", 7) || 0==uprv_memcmp(s, "Full_Composition_Exclusion", 26)) { /* full composition exclusion */ while(start<=end) { setCompositionExclusion(start++); } } else if( ((0==uprv_memcmp(s, "FNC", 3) && *(s=(char *)u_skipWhitespace(s+3))==';') || (0==uprv_memcmp(s, "FC_NFKC", 7) && *(s=(char *)u_skipWhitespace(s+7))==';')) ) { /* FC_NFKC_Closure, parse field 2 to get the string */ char *t; /* start of the field */ s=(char *)u_skipWhitespace(s+1); /* find the end of the field */ for(t=s; *t!=';' && *t!='#' && *t!=0 && *t!='\n' && *t!='\r'; ++t) {} *t=0; string[0]=(UChar)u_parseString(s, string+1, 31, NULL, pErrorCode); if(U_FAILURE(*pErrorCode)) { fprintf(stderr, "gennorm error: illegal FNC string at %s\n", fields[0][0]); exit(*pErrorCode); } while(start<=end) { setFNC(start++, string); } } }
/* Try titlecasing with options. */ static void TestUCaseMapToTitle(void) { /* "a 'CaT. A 'dOg! 'eTc." where '=U+02BB */ /* * Note: The sentence BreakIterator does not recognize a '.' * as a sentence terminator if it is followed by lowercase. * That is why the example has the '!'. */ static const UChar beforeTitle[]= { 0x61, 0x20, 0x2bb, 0x43, 0x61, 0x54, 0x2e, 0x20, 0x41, 0x20, 0x2bb, 0x64, 0x4f, 0x67, 0x21, 0x20, 0x2bb, 0x65, 0x54, 0x63, 0x2e }, titleWord[]= { 0x41, 0x20, 0x2bb, 0x43, 0x61, 0x74, 0x2e, 0x20, 0x41, 0x20, 0x2bb, 0x44, 0x6f, 0x67, 0x21, 0x20, 0x2bb, 0x45, 0x74, 0x63, 0x2e }, titleWordNoAdjust[]={ 0x41, 0x20, 0x2bb, 0x63, 0x61, 0x74, 0x2e, 0x20, 0x41, 0x20, 0x2bb, 0x64, 0x6f, 0x67, 0x21, 0x20, 0x2bb, 0x65, 0x74, 0x63, 0x2e }, titleSentNoLower[]= { 0x41, 0x20, 0x2bb, 0x43, 0x61, 0x54, 0x2e, 0x20, 0x41, 0x20, 0x2bb, 0x64, 0x4f, 0x67, 0x21, 0x20, 0x2bb, 0x45, 0x54, 0x63, 0x2e }; UChar buffer[32]; UCaseMap *csm; UBreakIterator *sentenceIter; const UBreakIterator *iter; int32_t length; UErrorCode errorCode; errorCode=U_ZERO_ERROR; csm=ucasemap_open("", 0, &errorCode); if(U_FAILURE(errorCode)) { log_err("ucasemap_open(\"\") failed - %s\n", u_errorName(errorCode)); return; } iter=ucasemap_getBreakIterator(csm); if(iter!=NULL) { log_err("ucasemap_getBreakIterator() returns %p!=NULL before setting any iterator or titlecasing\n", iter); } /* Use default UBreakIterator: Word breaks. */ length=ucasemap_toTitle(csm, buffer, UPRV_LENGTHOF(buffer), beforeTitle, UPRV_LENGTHOF(beforeTitle), &errorCode); if( U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(titleWord) || 0!=u_memcmp(buffer, titleWord, length) || buffer[length]!=0 ) { log_err_status(errorCode, "ucasemap_toTitle(default iterator)=%ld failed - %s\n", (long)length, u_errorName(errorCode)); } if (U_SUCCESS(errorCode)) { iter=ucasemap_getBreakIterator(csm); if(iter==NULL) { log_err("ucasemap_getBreakIterator() returns NULL after titlecasing\n"); } } /* Try U_TITLECASE_NO_BREAK_ADJUSTMENT. */ ucasemap_setOptions(csm, U_TITLECASE_NO_BREAK_ADJUSTMENT, &errorCode); if(U_FAILURE(errorCode)) { log_err_status(errorCode, "error: ucasemap_setOptions(U_TITLECASE_NO_BREAK_ADJUSTMENT) failed - %s\n", u_errorName(errorCode)); return; } length=ucasemap_toTitle(csm, buffer, UPRV_LENGTHOF(buffer), beforeTitle, UPRV_LENGTHOF(beforeTitle), &errorCode); if( U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(titleWordNoAdjust) || 0!=u_memcmp(buffer, titleWordNoAdjust, length) || buffer[length]!=0 ) { log_err("ucasemap_toTitle(default iterator, no break adjustment)=%ld failed - %s\n", (long)length, u_errorName(errorCode)); } /* Set a sentence break iterator. */ errorCode=U_ZERO_ERROR; sentenceIter=ubrk_open(UBRK_SENTENCE, "", NULL, 0, &errorCode); if(U_FAILURE(errorCode)) { log_err("error: ubrk_open(UBRK_SENTENCE) failed - %s\n", u_errorName(errorCode)); ucasemap_close(csm); return; } ucasemap_setBreakIterator(csm, sentenceIter, &errorCode); if(U_FAILURE(errorCode)) { log_err("error: ucasemap_setBreakIterator(sentence iterator) failed - %s\n", u_errorName(errorCode)); ubrk_close(sentenceIter); ucasemap_close(csm); return; } iter=ucasemap_getBreakIterator(csm); if(iter!=sentenceIter) { log_err("ucasemap_getBreakIterator() returns %p!=%p after setting the iterator\n", iter, sentenceIter); } ucasemap_setOptions(csm, U_TITLECASE_NO_LOWERCASE, &errorCode); if(U_FAILURE(errorCode)) { log_err("error: ucasemap_setOptions(U_TITLECASE_NO_LOWERCASE) failed - %s\n", u_errorName(errorCode)); return; } /* Use the sentence break iterator with the option. Preflight first. */ length=ucasemap_toTitle(csm, NULL, 0, beforeTitle, UPRV_LENGTHOF(beforeTitle), &errorCode); if( errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=UPRV_LENGTHOF(titleSentNoLower) ) { log_err("ucasemap_toTitle(preflight sentence break iterator, no lowercasing)=%ld failed - %s\n", (long)length, u_errorName(errorCode)); } errorCode=U_ZERO_ERROR; buffer[0]=0; length=ucasemap_toTitle(csm, buffer, UPRV_LENGTHOF(buffer), beforeTitle, UPRV_LENGTHOF(beforeTitle), &errorCode); if( U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(titleSentNoLower) || 0!=u_memcmp(buffer, titleSentNoLower, length) || buffer[length]!=0 ) { log_err("ucasemap_toTitle(sentence break iterator, no lowercasing)=%ld failed - %s\n", (long)length, u_errorName(errorCode)); } /* UTF-8 C API coverage. More thorough test via C++ intltest's StringCaseTest::TestCasing(). */ { char utf8BeforeTitle[64], utf8TitleSentNoLower[64], utf8[64]; int32_t utf8BeforeTitleLength, utf8TitleSentNoLowerLength; errorCode=U_ZERO_ERROR; u_strToUTF8(utf8BeforeTitle, (int32_t)sizeof(utf8BeforeTitle), &utf8BeforeTitleLength, beforeTitle, UPRV_LENGTHOF(beforeTitle), &errorCode); u_strToUTF8(utf8TitleSentNoLower, (int32_t)sizeof(utf8TitleSentNoLower), &utf8TitleSentNoLowerLength, titleSentNoLower, UPRV_LENGTHOF(titleSentNoLower), &errorCode); length=ucasemap_utf8ToTitle(csm, utf8, (int32_t)sizeof(utf8), utf8BeforeTitle, utf8BeforeTitleLength, &errorCode); if( U_FAILURE(errorCode) || length!=utf8TitleSentNoLowerLength || 0!=uprv_memcmp(utf8, utf8TitleSentNoLower, length) || utf8[length]!=0 ) { log_err("ucasemap_utf8ToTitle(sentence break iterator, no lowercasing)=%ld failed - %s\n", (long)length, u_errorName(errorCode)); } } ucasemap_close(csm); }
static void TestCaseCompare(void) { static const UChar mixed[]= { 0x61, 0x42, 0x131, 0x3a3, 0xdf, 0xfb03, 0xd93f, 0xdfff, 0 }, otherDefault[]= { 0x41, 0x62, 0x131, 0x3c3, 0x73, 0x53, 0x46, 0x66, 0x49, 0xd93f, 0xdfff, 0 }, otherExcludeSpecialI[]={ 0x41, 0x62, 0x131, 0x3c3, 0x53, 0x73, 0x66, 0x46, 0x69, 0xd93f, 0xdfff, 0 }, different[]= { 0x41, 0x62, 0x131, 0x3c3, 0x73, 0x53, 0x46, 0x66, 0x49, 0xd93f, 0xdffd, 0 }; UVersionInfo unicodeVersion={ 0, 0, 17, 89 }, unicode_3_1={ 3, 1, 0, 0 }; int32_t result, lenMixed, lenOtherDefault, lenOtherExcludeSpecialI, lenDifferent; UErrorCode errorCode; UBool isUnicode_3_1; errorCode=U_ZERO_ERROR; lenMixed=u_strlen(mixed); lenOtherDefault=u_strlen(otherDefault); (void)lenOtherDefault; /* Suppress set but not used warning. */ lenOtherExcludeSpecialI=u_strlen(otherExcludeSpecialI); lenDifferent=u_strlen(different); /* if unicodeVersion()>=3.1 then test exclude-special-i cases as well */ u_getUnicodeVersion(unicodeVersion); isUnicode_3_1= uprv_memcmp(unicodeVersion, unicode_3_1, 4)>=0; (void)isUnicode_3_1; /* Suppress set but not used warning. */ /* test u_strcasecmp() */ result=u_strcasecmp(mixed, otherDefault, U_FOLD_CASE_DEFAULT); if(result!=0) { log_err("error: u_strcasecmp(mixed, other, default)=%ld instead of 0\n", result); } result=u_strCaseCompare(mixed, -1, otherDefault, -1, U_FOLD_CASE_DEFAULT, &errorCode); if(result!=0) { log_err("error: u_strCaseCompare(mixed, other, default)=%ld instead of 0\n", result); } /* test u_strcasecmp() - exclude special i */ result=u_strcasecmp(mixed, otherExcludeSpecialI, U_FOLD_CASE_EXCLUDE_SPECIAL_I); if(result!=0) { log_err("error: u_strcasecmp(mixed, other, exclude special i)=%ld instead of 0\n", result); } result=u_strCaseCompare(mixed, lenMixed, otherExcludeSpecialI, lenOtherExcludeSpecialI, U_FOLD_CASE_EXCLUDE_SPECIAL_I, &errorCode); if(result!=0) { log_err("error: u_strCaseCompare(mixed, other, exclude special i)=%ld instead of 0\n", result); } /* test u_strcasecmp() */ result=u_strcasecmp(mixed, different, U_FOLD_CASE_DEFAULT); if(result<=0) { log_err("error: u_strcasecmp(mixed, different, default)=%ld instead of positive\n", result); } result=u_strCaseCompare(mixed, -1, different, lenDifferent, U_FOLD_CASE_DEFAULT, &errorCode); if(result<=0) { log_err("error: u_strCaseCompare(mixed, different, default)=%ld instead of positive\n", result); } /* test u_strncasecmp() - stop before the sharp s (U+00df) */ result=u_strncasecmp(mixed, different, 4, U_FOLD_CASE_DEFAULT); if(result!=0) { log_err("error: u_strncasecmp(mixed, different, 4, default)=%ld instead of 0\n", result); } result=u_strCaseCompare(mixed, 4, different, 4, U_FOLD_CASE_DEFAULT, &errorCode); if(result!=0) { log_err("error: u_strCaseCompare(mixed, 4, different, 4, default)=%ld instead of 0\n", result); } /* test u_strncasecmp() - stop in the middle of the sharp s (U+00df) */ result=u_strncasecmp(mixed, different, 5, U_FOLD_CASE_DEFAULT); if(result<=0) { log_err("error: u_strncasecmp(mixed, different, 5, default)=%ld instead of positive\n", result); } result=u_strCaseCompare(mixed, 5, different, 5, U_FOLD_CASE_DEFAULT, &errorCode); if(result<=0) { log_err("error: u_strCaseCompare(mixed, 5, different, 5, default)=%ld instead of positive\n", result); } /* test u_memcasecmp() - stop before the sharp s (U+00df) */ result=u_memcasecmp(mixed, different, 4, U_FOLD_CASE_DEFAULT); if(result!=0) { log_err("error: u_memcasecmp(mixed, different, 4, default)=%ld instead of 0\n", result); } /* test u_memcasecmp() - stop in the middle of the sharp s (U+00df) */ result=u_memcasecmp(mixed, different, 5, U_FOLD_CASE_DEFAULT); if(result<=0) { log_err("error: u_memcasecmp(mixed, different, 5, default)=%ld instead of positive\n", result); } }
static void TestCaseFolding(void) { /* * CaseFolding.txt says about i and its cousins: * 0049; C; 0069; # LATIN CAPITAL LETTER I * 0049; T; 0131; # LATIN CAPITAL LETTER I * * 0130; F; 0069 0307; # LATIN CAPITAL LETTER I WITH DOT ABOVE * 0130; T; 0069; # LATIN CAPITAL LETTER I WITH DOT ABOVE * That's all. * See CaseFolding.txt and the Unicode Standard for how to apply the case foldings. */ static const UChar32 simple[]={ /* input, default, exclude special i */ 0x61, 0x61, 0x61, 0x49, 0x69, 0x131, 0x130, 0x130, 0x69, 0x131, 0x131, 0x131, 0xdf, 0xdf, 0xdf, 0xfb03, 0xfb03, 0xfb03, 0x1040e,0x10436,0x10436, 0x5ffff,0x5ffff,0x5ffff }; static const UChar mixed[]= { 0x61, 0x42, 0x130, 0x49, 0x131, 0x3d0, 0xdf, 0xfb03, 0xd93f, 0xdfff }, foldedDefault[]= { 0x61, 0x62, 0x69, 0x307, 0x69, 0x131, 0x3b2, 0x73, 0x73, 0x66, 0x66, 0x69, 0xd93f, 0xdfff }, foldedExcludeSpecialI[]={ 0x61, 0x62, 0x69, 0x131, 0x131, 0x3b2, 0x73, 0x73, 0x66, 0x66, 0x69, 0xd93f, 0xdfff }; UVersionInfo unicodeVersion={ 0, 0, 17, 89 }, unicode_3_1={ 3, 1, 0, 0 }; const UChar32 *p; int32_t i; UChar buffer[32]; int32_t length; UErrorCode errorCode; UBool isUnicode_3_1; /* if unicodeVersion()>=3.1 then test exclude-special-i cases as well */ u_getUnicodeVersion(unicodeVersion); isUnicode_3_1= uprv_memcmp(unicodeVersion, unicode_3_1, 4)>=0; /* test simple case folding */ p=simple; for(i=0; i<sizeof(simple)/12; p+=3, ++i) { if(u_foldCase(p[0], U_FOLD_CASE_DEFAULT)!=p[1]) { log_err("error: u_foldCase(0x%04lx, default)=0x%04lx instead of 0x%04lx\n", p[0], u_foldCase(p[0], U_FOLD_CASE_DEFAULT), p[1]); return; } if(isUnicode_3_1 && u_foldCase(p[0], U_FOLD_CASE_EXCLUDE_SPECIAL_I)!=p[2]) { log_err("error: u_foldCase(0x%04lx, exclude special i)=0x%04lx instead of 0x%04lx\n", p[0], u_foldCase(p[0], U_FOLD_CASE_EXCLUDE_SPECIAL_I), p[2]); return; } } /* test full string case folding with default option and separate buffers */ buffer[0]=0xabcd; errorCode=U_ZERO_ERROR; length=u_strFoldCase(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, mixed, sizeof(mixed)/U_SIZEOF_UCHAR, U_FOLD_CASE_DEFAULT, &errorCode); if( U_FAILURE(errorCode) || length!=(sizeof(foldedDefault)/U_SIZEOF_UCHAR) || uprv_memcmp(foldedDefault, buffer, length*U_SIZEOF_UCHAR)!=0 || buffer[length]!=0 ) { log_err("error in u_strFoldCase(default)=%ld error=%s string matches: %s\n", length, u_errorName(errorCode), uprv_memcmp(foldedDefault, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no"); } /* exclude special i */ if(isUnicode_3_1) { buffer[0]=0xabcd; errorCode=U_ZERO_ERROR; length=u_strFoldCase(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, mixed, sizeof(mixed)/U_SIZEOF_UCHAR, U_FOLD_CASE_EXCLUDE_SPECIAL_I, &errorCode); if( U_FAILURE(errorCode) || length!=(sizeof(foldedExcludeSpecialI)/U_SIZEOF_UCHAR) || uprv_memcmp(foldedExcludeSpecialI, buffer, length*U_SIZEOF_UCHAR)!=0 || buffer[length]!=0 ) { log_err("error in u_strFoldCase(exclude special i)=%ld error=%s string matches: %s\n", length, u_errorName(errorCode), uprv_memcmp(foldedExcludeSpecialI, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no"); } } /* test full string case folding with default option and in the same buffer */ uprv_memcpy(buffer, mixed, sizeof(mixed)); buffer[sizeof(mixed)/U_SIZEOF_UCHAR]=0; errorCode=U_ZERO_ERROR; length=u_strFoldCase(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, buffer, -1, /* implicit srcLength */ U_FOLD_CASE_DEFAULT, &errorCode); if( U_FAILURE(errorCode) || length!=(sizeof(foldedDefault)/U_SIZEOF_UCHAR) || uprv_memcmp(foldedDefault, buffer, length*U_SIZEOF_UCHAR)!=0 || buffer[length]!=0 ) { log_err("error in u_strFoldCase(default same buffer)=%ld error=%s string matches: %s\n", length, u_errorName(errorCode), uprv_memcmp(foldedDefault, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no"); } /* test full string case folding, exclude special i, in the same buffer */ if(isUnicode_3_1) { uprv_memcpy(buffer, mixed, sizeof(mixed)); errorCode=U_ZERO_ERROR; length=u_strFoldCase(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, buffer, sizeof(mixed)/U_SIZEOF_UCHAR, U_FOLD_CASE_EXCLUDE_SPECIAL_I, &errorCode); if( U_FAILURE(errorCode) || length!=(sizeof(foldedExcludeSpecialI)/U_SIZEOF_UCHAR) || uprv_memcmp(foldedExcludeSpecialI, buffer, length*U_SIZEOF_UCHAR)!=0 || buffer[length]!=0 ) { log_err("error in u_strFoldCase(exclude special i same buffer)=%ld error=%s string matches: %s\n", length, u_errorName(errorCode), uprv_memcmp(foldedExcludeSpecialI, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no"); } } /* test preflighting */ buffer[0]=buffer[2]=0xabcd; errorCode=U_ZERO_ERROR; length=u_strFoldCase(buffer, 2, /* set destCapacity=2 */ mixed, sizeof(mixed)/U_SIZEOF_UCHAR, U_FOLD_CASE_DEFAULT, &errorCode); if( errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=(sizeof(foldedDefault)/U_SIZEOF_UCHAR) || uprv_memcmp(foldedDefault, buffer, 2*U_SIZEOF_UCHAR)!=0 || buffer[2]!=0xabcd ) { log_err("error in u_strFoldCase(default preflighting)=%ld error=%s string matches: %s\n", length, u_errorName(errorCode), uprv_memcmp(foldedDefault, buffer, 2*U_SIZEOF_UCHAR)==0 && buffer[2]==0xabcd ? "yes" : "no"); } errorCode=U_ZERO_ERROR; length=u_strFoldCase(NULL, 0, mixed, sizeof(mixed)/U_SIZEOF_UCHAR, U_FOLD_CASE_DEFAULT, &errorCode); if( errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=(sizeof(foldedDefault)/U_SIZEOF_UCHAR) ) { log_err("error in u_strFoldCase(default pure preflighting)=%ld error=%s\n", length, u_errorName(errorCode)); } /* test error handling */ errorCode=U_ZERO_ERROR; length=u_strFoldCase(NULL, sizeof(buffer)/U_SIZEOF_UCHAR, mixed, sizeof(mixed)/U_SIZEOF_UCHAR, U_FOLD_CASE_DEFAULT, &errorCode); if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { log_err("error in u_strFoldCase(default dest=NULL)=%ld error=%s\n", length, u_errorName(errorCode)); } buffer[0]=0xabcd; errorCode=U_ZERO_ERROR; length=u_strFoldCase(buffer, -1, mixed, sizeof(mixed)/U_SIZEOF_UCHAR, U_FOLD_CASE_DEFAULT, &errorCode); if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR || buffer[0]!=0xabcd ) { log_err("error in u_strFoldCase(default destCapacity=-1)=%ld error=%s buffer[0]==0x%lx\n", length, u_errorName(errorCode), buffer[0]); } buffer[0]=0xabcd; errorCode=U_ZERO_ERROR; length=u_strFoldCase(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, NULL, sizeof(mixed)/U_SIZEOF_UCHAR, U_FOLD_CASE_EXCLUDE_SPECIAL_I, &errorCode); if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR || buffer[0]!=0xabcd ) { log_err("error in u_strFoldCase(exclude special i src=NULL)=%ld error=%s buffer[0]==0x%lx\n", length, u_errorName(errorCode), buffer[0]); } buffer[0]=0xabcd; errorCode=U_ZERO_ERROR; length=u_strFoldCase(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, mixed, -2, U_FOLD_CASE_EXCLUDE_SPECIAL_I, &errorCode); if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR || buffer[0]!=0xabcd ) { log_err("error in u_strFoldCase(exclude special i srcLength=-2)=%ld error=%s buffer[0]==0x%lx\n", length, u_errorName(errorCode), buffer[0]); } }
static void TestCaseDutchTitle(void) { static const UChar beforeTitle[]= { 0x69, 0x6A, 0x73, 0x73, 0x45, 0x6c, 0x20, 0x69, 0x67, 0x6c, 0x4f, 0x6f , 0x20 , 0x49, 0x4A, 0x53, 0x53, 0x45, 0x4C }, titleRoot[]= { 0x49, 0x6A, 0x73, 0x73, 0x65, 0x6c, 0x20, 0x49, 0x67, 0x6c, 0x6f, 0x6f , 0x20 , 0x49, 0x6A, 0x73, 0x73, 0x65, 0x6C }, titleDutch[]= { 0x49, 0x4A, 0x73, 0x73, 0x65, 0x6c, 0x20, 0x49, 0x67, 0x6c, 0x6f, 0x6f , 0x20 , 0x49, 0x4A, 0x73, 0x73, 0x65, 0x6C }; UChar buffer[32]; UBreakIterator *titleIterWord; int32_t length; UErrorCode errorCode; errorCode=U_ZERO_ERROR; titleIterWord=ubrk_open(UBRK_WORD, "", beforeTitle, sizeof(beforeTitle)/U_SIZEOF_UCHAR, &errorCode); if(U_FAILURE(errorCode)) { log_err_status(errorCode, "error: ubrk_open(UBRK_WORD)->%s\n", u_errorName(errorCode)); return; } /* titlecase with default locale */ buffer[0]=0xabcd; errorCode=U_ZERO_ERROR; length=u_strToTitle(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, beforeTitle, sizeof(beforeTitle)/U_SIZEOF_UCHAR, titleIterWord, "", &errorCode); if( U_FAILURE(errorCode) || length!=(sizeof(titleRoot)/U_SIZEOF_UCHAR) || uprv_memcmp(titleRoot, buffer, length*U_SIZEOF_UCHAR)!=0 || buffer[length]!=0 ) { char charsOut[21]; u_UCharsToChars(buffer,charsOut,sizeof(charsOut)); log_err("error in u_strToTitle(UBRK_CHARACTERS)=%ld error=%s root locale string matches: %s\noutput buffer is {%s}\n", length, u_errorName(errorCode), uprv_memcmp(titleRoot, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no", charsOut); } /* titlecase with Dutch locale */ buffer[0]=0xabcd; errorCode=U_ZERO_ERROR; length=u_strToTitle(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, beforeTitle, sizeof(beforeTitle)/U_SIZEOF_UCHAR, titleIterWord, "nl", &errorCode); if( U_FAILURE(errorCode) || length!=(sizeof(titleDutch)/U_SIZEOF_UCHAR) || uprv_memcmp(titleDutch, buffer, length*U_SIZEOF_UCHAR)!=0 || buffer[length]!=0 ) { char charsOut[21]; u_UCharsToChars(buffer,charsOut,sizeof(charsOut)); log_err("error in u_strToTitle(UBRK_CHARACTERS)=%ld error=%s dutch locale string matches: %s\noutput buffer is {%s}\n", length, u_errorName(errorCode), uprv_memcmp(titleDutch, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no", charsOut); } ubrk_close(titleIterWord); }
static void TestCaseLower(void) { static const UChar beforeLower[]= { 0x61, 0x42, 0x49, 0x3a3, 0xdf, 0x3a3, 0x2f, 0xd93f, 0xdfff }, lowerRoot[]= { 0x61, 0x62, 0x69, 0x3c3, 0xdf, 0x3c2, 0x2f, 0xd93f, 0xdfff }, lowerTurkish[]={ 0x61, 0x62, 0x131, 0x3c3, 0xdf, 0x3c2, 0x2f, 0xd93f, 0xdfff }; UChar buffer[32]; int32_t length; UErrorCode errorCode; /* lowercase with root locale and separate buffers */ buffer[0]=0xabcd; errorCode=U_ZERO_ERROR; length=u_strToLower(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, beforeLower, sizeof(beforeLower)/U_SIZEOF_UCHAR, "", &errorCode); if( U_FAILURE(errorCode) || length!=(sizeof(lowerRoot)/U_SIZEOF_UCHAR) || uprv_memcmp(lowerRoot, buffer, length*U_SIZEOF_UCHAR)!=0 || buffer[length]!=0 ) { log_err("error in u_strToLower(root locale)=%ld error=%s string matches: %s\t\nlowerRoot=%s\t\nbuffer=%s\n", length, u_errorName(errorCode), uprv_memcmp(lowerRoot, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no", aescstrdup(lowerRoot,-1), aescstrdup(buffer,-1)); } /* lowercase with turkish locale and in the same buffer */ uprv_memcpy(buffer, beforeLower, sizeof(beforeLower)); buffer[sizeof(beforeLower)/U_SIZEOF_UCHAR]=0; errorCode=U_ZERO_ERROR; length=u_strToLower(buffer, sizeof(buffer)/U_SIZEOF_UCHAR, buffer, -1, /* implicit srcLength */ "tr", &errorCode); if( U_FAILURE(errorCode) || length!=(sizeof(lowerTurkish)/U_SIZEOF_UCHAR) || uprv_memcmp(lowerTurkish, buffer, length*U_SIZEOF_UCHAR)!=0 || buffer[length]!=0 ) { log_err("error in u_strToLower(turkish locale)=%ld error=%s string matches: %s\n", length, u_errorName(errorCode), uprv_memcmp(lowerTurkish, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no"); } /* test preflighting */ buffer[0]=buffer[2]=0xabcd; errorCode=U_ZERO_ERROR; length=u_strToLower(buffer, 2, /* set destCapacity=2 */ beforeLower, sizeof(beforeLower)/U_SIZEOF_UCHAR, "", &errorCode); if( errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=(sizeof(lowerRoot)/U_SIZEOF_UCHAR) || uprv_memcmp(lowerRoot, buffer, 2*U_SIZEOF_UCHAR)!=0 || buffer[2]!=0xabcd ) { log_err("error in u_strToLower(root locale preflighting)=%ld error=%s string matches: %s\n", length, u_errorName(errorCode), uprv_memcmp(lowerRoot, buffer, 2*U_SIZEOF_UCHAR)==0 && buffer[2]==0xabcd ? "yes" : "no"); } /* test error handling */ errorCode=U_ZERO_ERROR; length=u_strToLower(NULL, sizeof(buffer)/U_SIZEOF_UCHAR, beforeLower, sizeof(beforeLower)/U_SIZEOF_UCHAR, "", &errorCode); if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) { log_err("error in u_strToLower(root locale dest=NULL)=%ld error=%s\n", length, u_errorName(errorCode)); } buffer[0]=0xabcd; errorCode=U_ZERO_ERROR; length=u_strToLower(buffer, -1, beforeLower, sizeof(beforeLower)/U_SIZEOF_UCHAR, "", &errorCode); if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR || buffer[0]!=0xabcd ) { log_err("error in u_strToLower(root locale destCapacity=-1)=%ld error=%s buffer[0]==0x%lx\n", length, u_errorName(errorCode), buffer[0]); } }