static int32_t caseMap(const UCaseMap *csm, uint8_t *dest, int32_t destCapacity, const uint8_t *src, int32_t srcLength, int32_t toWhichCase, UErrorCode *pErrorCode) { UCaseContext csc={ NULL }; int32_t destLength; /* check argument values */ if(U_FAILURE(*pErrorCode)) { return 0; } if( destCapacity<0 || (dest==NULL && destCapacity>0) || src==NULL || srcLength<-1 ) { *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; return 0; } /* get the string length */ if(srcLength==-1) { srcLength=uprv_strlen((const char *)src); } /* check for overlapping source and destination */ if( dest!=NULL && ((src>=dest && src<(dest+destCapacity)) || (dest>=src && dest<(src+srcLength))) ) { *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; return 0; } destLength=0; csc.p=(void *)src; csc.limit=srcLength; if(toWhichCase==TO_LOWER) { destLength=_caseMap(csm, ucase_toFullLower, dest, destCapacity, src, &csc, 0, srcLength, pErrorCode); } else /* if(toWhichCase==TO_UPPER) */ { destLength=_caseMap(csm, ucase_toFullUpper, dest, destCapacity, src, &csc, 0, srcLength, pErrorCode); } return u_terminateChars((char *)dest, destCapacity, destLength, pErrorCode); }
U_NAMESPACE_END // The following must at least allow for rg key value (6) plus terminator (1). #define ULOC_RG_BUFLEN 8 U_CAPI int32_t U_EXPORT2 ulocimp_getRegionForSupplementalData(const char *localeID, UBool inferRegion, char *region, int32_t regionCapacity, UErrorCode* status) { if (U_FAILURE(*status)) { return 0; } char rgBuf[ULOC_RG_BUFLEN]; UErrorCode rgStatus = U_ZERO_ERROR; // First check for rg keyword value int32_t rgLen = uloc_getKeywordValue(localeID, "rg", rgBuf, ULOC_RG_BUFLEN, &rgStatus); if (U_FAILURE(rgStatus) || rgLen != 6) { rgLen = 0; } else { // rgBuf guaranteed to be zero terminated here, with text len 6 char *rgPtr = rgBuf; for (; *rgPtr!= 0; rgPtr++) { *rgPtr = uprv_toupper(*rgPtr); } rgLen = (uprv_strcmp(rgBuf+2, "ZZZZ") == 0)? 2: 0; } if (rgLen == 0) { // No valid rg keyword value, try for unicode_region_subtag rgLen = uloc_getCountry(localeID, rgBuf, ULOC_RG_BUFLEN, status); if (U_FAILURE(*status)) { rgLen = 0; } else if (rgLen == 0 && inferRegion) { // no unicode_region_subtag but inferRegion TRUE, try likely subtags char locBuf[ULOC_FULLNAME_CAPACITY]; rgStatus = U_ZERO_ERROR; (void)uloc_addLikelySubtags(localeID, locBuf, ULOC_FULLNAME_CAPACITY, &rgStatus); if (U_SUCCESS(rgStatus)) { rgLen = uloc_getCountry(locBuf, rgBuf, ULOC_RG_BUFLEN, status); if (U_FAILURE(*status)) { rgLen = 0; } } } } rgBuf[rgLen] = 0; uprv_strncpy(region, rgBuf, regionCapacity); return u_terminateChars(region, regionCapacity, rgLen, status); }
int32_t ucasemap_mapUTF8(int32_t caseLocale, uint32_t options, UCASEMAP_BREAK_ITERATOR_PARAM char *dest, int32_t destCapacity, const char *src, int32_t srcLength, UTF8CaseMapper *stringCaseMapper, icu::Edits *edits, UErrorCode &errorCode) { /* check argument values */ if(U_FAILURE(errorCode)) { return 0; } if( destCapacity<0 || (dest==NULL && destCapacity>0) || (src==NULL && srcLength!=0) || srcLength<-1 ) { errorCode=U_ILLEGAL_ARGUMENT_ERROR; return 0; } /* get the string length */ if(srcLength==-1) { srcLength=(int32_t)uprv_strlen((const char *)src); } /* check for overlapping source and destination */ if( dest!=NULL && ((src>=dest && src<(dest+destCapacity)) || (dest>=src && dest<(src+srcLength))) ) { errorCode=U_ILLEGAL_ARGUMENT_ERROR; return 0; } CheckedArrayByteSink sink(dest, destCapacity); if (edits != nullptr && (options & U_EDITS_NO_RESET) == 0) { edits->reset(); } stringCaseMapper(caseLocale, options, UCASEMAP_BREAK_ITERATOR (const uint8_t *)src, srcLength, sink, edits, errorCode); sink.Flush(); if (U_SUCCESS(errorCode)) { if (sink.Overflowed()) { errorCode = U_BUFFER_OVERFLOW_ERROR; } else if (edits != nullptr) { edits->copyErrorTo(errorCode); } } return u_terminateChars(dest, destCapacity, sink.NumberOfBytesAppended(), &errorCode); }
U_CAPI int32_t U_EXPORT2 u_parseUTF8(const char *source, int32_t sLen, char *dest, int32_t destCapacity, UErrorCode *status) { const char *read = source; int32_t i = 0; unsigned int value = 0; if(sLen == -1) { sLen = (int32_t)strlen(source); } while(read < source+sLen) { sscanf(read, "%2x", &value); if(i < destCapacity) { dest[i] = (char)value; } i++; read += 2; } return u_terminateChars(dest, destCapacity, i, status); }
U_CFUNC int32_t ucasemap_mapUTF8(const UCaseMap *csm, uint8_t *dest, int32_t destCapacity, const uint8_t *src, int32_t srcLength, UTF8CaseMapper *stringCaseMapper, UErrorCode *pErrorCode) { int32_t destLength; /* check argument values */ if(U_FAILURE(*pErrorCode)) { return 0; } if( destCapacity<0 || (dest==NULL && destCapacity>0) || src==NULL || srcLength<-1 ) { *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; return 0; } /* get the string length */ if(srcLength==-1) { srcLength=(int32_t)uprv_strlen((const char *)src); } /* check for overlapping source and destination */ if( dest!=NULL && ((src>=dest && src<(dest+destCapacity)) || (dest>=src && dest<(src+srcLength))) ) { *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; return 0; } destLength=stringCaseMapper(csm, dest, destCapacity, src, srcLength, pErrorCode); return u_terminateChars((char *)dest, destCapacity, destLength, pErrorCode); }
static int32_t _uloc_minimizeSubtags(const char* localeID, char* minimizedLocaleID, int32_t minimizedLocaleIDCapacity, UErrorCode* err) { /** * ULOC_FULLNAME_CAPACITY will provide enough capacity * that we can build a string that contains the language, * script and region code without worrying about overrunning * the user-supplied buffer. **/ char maximizedTagBuffer[ULOC_FULLNAME_CAPACITY]; int32_t maximizedTagBufferLength = sizeof(maximizedTagBuffer); char lang[ULOC_LANG_CAPACITY]; int32_t langLength = sizeof(lang); char script[ULOC_SCRIPT_CAPACITY]; int32_t scriptLength = sizeof(script); char region[ULOC_COUNTRY_CAPACITY]; int32_t regionLength = sizeof(region); const char* trailing = ""; int32_t trailingLength = 0; int32_t trailingIndex = 0; if(U_FAILURE(*err)) { goto error; } else if (localeID == NULL || minimizedLocaleID == NULL || minimizedLocaleIDCapacity <= 0) { goto error; } trailingIndex = parseTagString( localeID, lang, &langLength, script, &scriptLength, region, ®ionLength, err); if(U_FAILURE(*err)) { /* Overflow indicates an illegal argument error */ if (*err == U_BUFFER_OVERFLOW_ERROR) { *err = U_ILLEGAL_ARGUMENT_ERROR; } goto error; } /* Find the spot where the variants or the keywords begin, if any. */ while (_isIDSeparator(localeID[trailingIndex])) { trailingIndex++; } trailing = &localeID[trailingIndex]; trailingLength = (int32_t)uprv_strlen(trailing); CHECK_TRAILING_VARIANT_SIZE(trailing, trailingLength); createTagString( lang, langLength, script, scriptLength, region, regionLength, NULL, 0, maximizedTagBuffer, maximizedTagBufferLength, err); if(U_FAILURE(*err)) { goto error; } /** * First, we need to first get the maximization * from AddLikelySubtags. **/ maximizedTagBufferLength = uloc_addLikelySubtags( maximizedTagBuffer, maximizedTagBuffer, maximizedTagBufferLength, err); if(U_FAILURE(*err)) { goto error; } /** * Start first with just the language. **/ { char tagBuffer[ULOC_FULLNAME_CAPACITY]; const int32_t tagBufferLength = createLikelySubtagsString( lang, langLength, NULL, 0, NULL, 0, NULL, 0, tagBuffer, sizeof(tagBuffer), err); if(U_FAILURE(*err)) { goto error; } else if (uprv_strnicmp( maximizedTagBuffer, tagBuffer, tagBufferLength) == 0) { return createTagString( lang, langLength, NULL, 0, NULL, 0, trailing, trailingLength, minimizedLocaleID, minimizedLocaleIDCapacity, err); } } /** * Next, try the language and region. **/ if (regionLength > 0) { char tagBuffer[ULOC_FULLNAME_CAPACITY]; const int32_t tagBufferLength = createLikelySubtagsString( lang, langLength, NULL, 0, region, regionLength, NULL, 0, tagBuffer, sizeof(tagBuffer), err); if(U_FAILURE(*err)) { goto error; } else if (uprv_strnicmp( maximizedTagBuffer, tagBuffer, tagBufferLength) == 0) { return createTagString( lang, langLength, NULL, 0, region, regionLength, trailing, trailingLength, minimizedLocaleID, minimizedLocaleIDCapacity, err); } } /** * Finally, try the language and script. This is our last chance, * since trying with all three subtags would only yield the * maximal version that we already have. **/ if (scriptLength > 0 && regionLength > 0) { char tagBuffer[ULOC_FULLNAME_CAPACITY]; const int32_t tagBufferLength = createLikelySubtagsString( lang, langLength, script, scriptLength, NULL, 0, NULL, 0, tagBuffer, sizeof(tagBuffer), err); if(U_FAILURE(*err)) { goto error; } else if (uprv_strnicmp( maximizedTagBuffer, tagBuffer, tagBufferLength) == 0) { return createTagString( lang, langLength, script, scriptLength, NULL, 0, trailing, trailingLength, minimizedLocaleID, minimizedLocaleIDCapacity, err); } } { /** * If we got here, return the locale ID parameter. **/ const int32_t localeIDLength = (int32_t)uprv_strlen(localeID); uprv_memcpy( minimizedLocaleID, localeID, localeIDLength <= minimizedLocaleIDCapacity ? localeIDLength : minimizedLocaleIDCapacity); return u_terminateChars( minimizedLocaleID, minimizedLocaleIDCapacity, localeIDLength, err); } error: if (!U_FAILURE(*err)) { *err = U_ILLEGAL_ARGUMENT_ERROR; } return -1; }
static int32_t _uloc_addLikelySubtags(const char* localeID, char* maximizedLocaleID, int32_t maximizedLocaleIDCapacity, UErrorCode* err) { char lang[ULOC_LANG_CAPACITY]; int32_t langLength = sizeof(lang); char script[ULOC_SCRIPT_CAPACITY]; int32_t scriptLength = sizeof(script); char region[ULOC_COUNTRY_CAPACITY]; int32_t regionLength = sizeof(region); const char* trailing = ""; int32_t trailingLength = 0; int32_t trailingIndex = 0; int32_t resultLength = 0; if(U_FAILURE(*err)) { goto error; } else if (localeID == NULL || maximizedLocaleID == NULL || maximizedLocaleIDCapacity <= 0) { goto error; } trailingIndex = parseTagString( localeID, lang, &langLength, script, &scriptLength, region, ®ionLength, err); if(U_FAILURE(*err)) { /* Overflow indicates an illegal argument error */ if (*err == U_BUFFER_OVERFLOW_ERROR) { *err = U_ILLEGAL_ARGUMENT_ERROR; } goto error; } /* Find the length of the trailing portion. */ while (_isIDSeparator(localeID[trailingIndex])) { trailingIndex++; } trailing = &localeID[trailingIndex]; trailingLength = (int32_t)uprv_strlen(trailing); CHECK_TRAILING_VARIANT_SIZE(trailing, trailingLength); resultLength = createLikelySubtagsString( lang, langLength, script, scriptLength, region, regionLength, trailing, trailingLength, maximizedLocaleID, maximizedLocaleIDCapacity, err); if (resultLength == 0) { const int32_t localIDLength = (int32_t)uprv_strlen(localeID); /* * If we get here, we need to return localeID. */ uprv_memcpy( maximizedLocaleID, localeID, localIDLength <= maximizedLocaleIDCapacity ? localIDLength : maximizedLocaleIDCapacity); resultLength = u_terminateChars( maximizedLocaleID, maximizedLocaleIDCapacity, localIDLength, err); } return resultLength; error: if (!U_FAILURE(*err)) { *err = U_ILLEGAL_ARGUMENT_ERROR; } return -1; }
static int32_t U_CALLCONV createLikelySubtagsString( const char* lang, int32_t langLength, const char* script, int32_t scriptLength, const char* region, int32_t regionLength, const char* variants, int32_t variantsLength, char* tag, int32_t tagCapacity, UErrorCode* err) { /** * ULOC_FULLNAME_CAPACITY will provide enough capacity * that we can build a string that contains the language, * script and region code without worrying about overrunning * the user-supplied buffer. **/ char tagBuffer[ULOC_FULLNAME_CAPACITY]; char likelySubtagsBuffer[ULOC_FULLNAME_CAPACITY]; int32_t tagBufferLength = 0; if(U_FAILURE(*err)) { goto error; } /** * Try the language with the script and region first. **/ if (scriptLength > 0 && regionLength > 0) { const char* likelySubtags = NULL; tagBufferLength = createTagString( lang, langLength, script, scriptLength, region, regionLength, NULL, 0, tagBuffer, sizeof(tagBuffer), err); if(U_FAILURE(*err)) { goto error; } likelySubtags = findLikelySubtags( tagBuffer, likelySubtagsBuffer, sizeof(likelySubtagsBuffer), err); if(U_FAILURE(*err)) { goto error; } if (likelySubtags != NULL) { /* Always use the language tag from the maximal string, since it may be more specific than the one provided. */ return createTagStringWithAlternates( NULL, 0, NULL, 0, NULL, 0, variants, variantsLength, likelySubtags, tag, tagCapacity, err); } } /** * Try the language with just the script. **/ if (scriptLength > 0) { const char* likelySubtags = NULL; tagBufferLength = createTagString( lang, langLength, script, scriptLength, NULL, 0, NULL, 0, tagBuffer, sizeof(tagBuffer), err); if(U_FAILURE(*err)) { goto error; } likelySubtags = findLikelySubtags( tagBuffer, likelySubtagsBuffer, sizeof(likelySubtagsBuffer), err); if(U_FAILURE(*err)) { goto error; } if (likelySubtags != NULL) { /* Always use the language tag from the maximal string, since it may be more specific than the one provided. */ return createTagStringWithAlternates( NULL, 0, NULL, 0, region, regionLength, variants, variantsLength, likelySubtags, tag, tagCapacity, err); } } /** * Try the language with just the region. **/ if (regionLength > 0) { const char* likelySubtags = NULL; createTagString( lang, langLength, NULL, 0, region, regionLength, NULL, 0, tagBuffer, sizeof(tagBuffer), err); if(U_FAILURE(*err)) { goto error; } likelySubtags = findLikelySubtags( tagBuffer, likelySubtagsBuffer, sizeof(likelySubtagsBuffer), err); if(U_FAILURE(*err)) { goto error; } if (likelySubtags != NULL) { /* Always use the language tag from the maximal string, since it may be more specific than the one provided. */ return createTagStringWithAlternates( NULL, 0, script, scriptLength, NULL, 0, variants, variantsLength, likelySubtags, tag, tagCapacity, err); } } /** * Finally, try just the language. **/ { const char* likelySubtags = NULL; createTagString( lang, langLength, NULL, 0, NULL, 0, NULL, 0, tagBuffer, sizeof(tagBuffer), err); if(U_FAILURE(*err)) { goto error; } likelySubtags = findLikelySubtags( tagBuffer, likelySubtagsBuffer, sizeof(likelySubtagsBuffer), err); if(U_FAILURE(*err)) { goto error; } if (likelySubtags != NULL) { /* Always use the language tag from the maximal string, since it may be more specific than the one provided. */ return createTagStringWithAlternates( NULL, 0, script, scriptLength, region, regionLength, variants, variantsLength, likelySubtags, tag, tagCapacity, err); } } return u_terminateChars( tag, tagCapacity, 0, err); error: if (!U_FAILURE(*err)) { *err = U_ILLEGAL_ARGUMENT_ERROR; } return -1; }
/** * Parse the language, script, and region subtags from a tag string, and copy the * results into the corresponding output parameters. The buffers are null-terminated, * unless overflow occurs. * * The langLength, scriptLength, and regionLength parameters are input/output * parameters, and must contain the capacity of their corresponding buffers on * input. On output, they will contain the actual length of the buffers, not * including the null terminator. * * If the length of any of the output subtags exceeds the capacity of the corresponding * buffer, the function copies as many bytes to the output buffer as it can, and returns * the error U_BUFFER_OVERFLOW_ERROR. It will not parse any more subtags once overflow * occurs. * * If an illegal argument is provided, the function returns the error * U_ILLEGAL_ARGUMENT_ERROR. * * @param localeID The locale ID to parse. * @param lang The language tag buffer. * @param langLength The length of the language tag. * @param script The script tag buffer. * @param scriptLength The length of the script tag. * @param region The region tag buffer. * @param regionLength The length of the region tag. * @param err A pointer to a UErrorCode for error reporting. * @return The number of chars of the localeID parameter consumed. **/ static int32_t U_CALLCONV parseTagString( const char* localeID, char* lang, int32_t* langLength, char* script, int32_t* scriptLength, char* region, int32_t* regionLength, UErrorCode* err) { const char* position = localeID; int32_t subtagLength = 0; if(U_FAILURE(*err) || localeID == NULL || lang == NULL || langLength == NULL || script == NULL || scriptLength == NULL || region == NULL || regionLength == NULL) { goto error; } subtagLength = ulocimp_getLanguage(position, lang, *langLength, &position); u_terminateChars(lang, *langLength, subtagLength, err); /* * Note that we explicit consider U_STRING_NOT_TERMINATED_WARNING * to be an error, because it indicates the user-supplied tag is * not well-formed. */ if(U_FAILURE(*err)) { goto error; } *langLength = subtagLength; /* * If no language was present, use the value of unknownLanguage * instead. Otherwise, move past any separator. */ if (*langLength == 0) { uprv_strcpy( lang, unknownLanguage); *langLength = (int32_t)uprv_strlen(lang); } else if (_isIDSeparator(*position)) { ++position; } subtagLength = ulocimp_getScript(position, script, *scriptLength, &position); u_terminateChars(script, *scriptLength, subtagLength, err); if(U_FAILURE(*err)) { goto error; } *scriptLength = subtagLength; if (*scriptLength > 0) { if (uprv_strnicmp(script, unknownScript, *scriptLength) == 0) { /** * If the script part is the "unknown" script, then don't return it. **/ *scriptLength = 0; } /* * Move past any separator. */ if (_isIDSeparator(*position)) { ++position; } } subtagLength = ulocimp_getCountry(position, region, *regionLength, &position); u_terminateChars(region, *regionLength, subtagLength, err); if(U_FAILURE(*err)) { goto error; } *regionLength = subtagLength; if (*regionLength > 0) { if (uprv_strnicmp(region, unknownRegion, *regionLength) == 0) { /** * If the region part is the "unknown" region, then don't return it. **/ *regionLength = 0; } } else if (*position != 0 && *position != '@') { /* back up over consumed trailing separator */ --position; } exit: return (int32_t)(position - localeID); error: /** * If we get here, we have no explicit error, it's the result of an * illegal argument. **/ if (!U_FAILURE(*err)) { *err = U_ILLEGAL_ARGUMENT_ERROR; } goto exit; }
/** * Create a tag string from the supplied parameters. The lang, script and region * parameters may be NULL pointers. If they are, their corresponding length parameters * must be less than or equal to 0. * * If any of the language, script or region parameters are empty, and the alternateTags * parameter is not NULL, it will be parsed for potential language, script and region tags * to be used when constructing the new tag. If the alternateTags parameter is NULL, or * it contains no language tag, the default tag for the unknown language is used. * * If the length of the new string exceeds the capacity of the output buffer, * the function copies as many bytes to the output buffer as it can, and returns * the error U_BUFFER_OVERFLOW_ERROR. * * If an illegal argument is provided, the function returns the error * U_ILLEGAL_ARGUMENT_ERROR. * * Note that this function can return the warning U_STRING_NOT_TERMINATED_WARNING if * the tag string fits in the output buffer, but the null terminator doesn't. * * @param lang The language tag to use. * @param langLength The length of the language tag. * @param script The script tag to use. * @param scriptLength The length of the script tag. * @param region The region tag to use. * @param regionLength The length of the region tag. * @param trailing Any trailing data to append to the new tag. * @param trailingLength The length of the trailing data. * @param alternateTags A string containing any alternate tags. * @param tag The output buffer. * @param tagCapacity The capacity of the output buffer. * @param err A pointer to a UErrorCode for error reporting. * @return The length of the tag string, which may be greater than tagCapacity, or -1 on error. **/ static int32_t U_CALLCONV createTagStringWithAlternates( const char* lang, int32_t langLength, const char* script, int32_t scriptLength, const char* region, int32_t regionLength, const char* trailing, int32_t trailingLength, const char* alternateTags, char* tag, int32_t tagCapacity, UErrorCode* err) { if (U_FAILURE(*err)) { goto error; } else if (tag == NULL || tagCapacity <= 0 || langLength >= ULOC_LANG_CAPACITY || scriptLength >= ULOC_SCRIPT_CAPACITY || regionLength >= ULOC_COUNTRY_CAPACITY) { goto error; } else { /** * ULOC_FULLNAME_CAPACITY will provide enough capacity * that we can build a string that contains the language, * script and region code without worrying about overrunning * the user-supplied buffer. **/ char tagBuffer[ULOC_FULLNAME_CAPACITY]; int32_t tagLength = 0; int32_t capacityRemaining = tagCapacity; UBool regionAppended = FALSE; if (langLength > 0) { appendTag( lang, langLength, tagBuffer, &tagLength); } else if (alternateTags == NULL) { /* * Append the value for an unknown language, if * we found no language. */ appendTag( unknownLanguage, (int32_t)uprv_strlen(unknownLanguage), tagBuffer, &tagLength); } else { /* * Parse the alternateTags string for the language. */ char alternateLang[ULOC_LANG_CAPACITY]; int32_t alternateLangLength = sizeof(alternateLang); alternateLangLength = uloc_getLanguage( alternateTags, alternateLang, alternateLangLength, err); if(U_FAILURE(*err) || alternateLangLength >= ULOC_LANG_CAPACITY) { goto error; } else if (alternateLangLength == 0) { /* * Append the value for an unknown language, if * we found no language. */ appendTag( unknownLanguage, (int32_t)uprv_strlen(unknownLanguage), tagBuffer, &tagLength); } else { appendTag( alternateLang, alternateLangLength, tagBuffer, &tagLength); } } if (scriptLength > 0) { appendTag( script, scriptLength, tagBuffer, &tagLength); } else if (alternateTags != NULL) { /* * Parse the alternateTags string for the script. */ char alternateScript[ULOC_SCRIPT_CAPACITY]; const int32_t alternateScriptLength = uloc_getScript( alternateTags, alternateScript, sizeof(alternateScript), err); if (U_FAILURE(*err) || alternateScriptLength >= ULOC_SCRIPT_CAPACITY) { goto error; } else if (alternateScriptLength > 0) { appendTag( alternateScript, alternateScriptLength, tagBuffer, &tagLength); } } if (regionLength > 0) { appendTag( region, regionLength, tagBuffer, &tagLength); regionAppended = TRUE; } else if (alternateTags != NULL) { /* * Parse the alternateTags string for the region. */ char alternateRegion[ULOC_COUNTRY_CAPACITY]; const int32_t alternateRegionLength = uloc_getCountry( alternateTags, alternateRegion, sizeof(alternateRegion), err); if (U_FAILURE(*err) || alternateRegionLength >= ULOC_COUNTRY_CAPACITY) { goto error; } else if (alternateRegionLength > 0) { appendTag( alternateRegion, alternateRegionLength, tagBuffer, &tagLength); regionAppended = TRUE; } } { const int32_t toCopy = tagLength >= tagCapacity ? tagCapacity : tagLength; /** * Copy the partial tag from our internal buffer to the supplied * target. **/ uprv_memcpy( tag, tagBuffer, toCopy); capacityRemaining -= toCopy; } if (trailingLength > 0) { if (*trailing != '@' && capacityRemaining > 0) { tag[tagLength++] = '_'; --capacityRemaining; if (capacityRemaining > 0 && !regionAppended) { /* extra separator is required */ tag[tagLength++] = '_'; --capacityRemaining; } } if (capacityRemaining > 0) { /* * Copy the trailing data into the supplied buffer. Use uprv_memmove, since we * don't know if the user-supplied buffers overlap. */ const int32_t toCopy = trailingLength >= capacityRemaining ? capacityRemaining : trailingLength; uprv_memmove( &tag[tagLength], trailing, toCopy); } } tagLength += trailingLength; return u_terminateChars( tag, tagCapacity, tagLength, err); } error: /** * An overflow indicates the locale ID passed in * is ill-formed. If we got here, and there was * no previous error, it's an implicit overflow. **/ if (*err == U_BUFFER_OVERFLOW_ERROR || U_SUCCESS(*err)) { *err = U_ILLEGAL_ARGUMENT_ERROR; } return -1; }
static int32_t caseMap(const UCaseMap *csm, uint8_t *dest, int32_t destCapacity, const uint8_t *src, int32_t srcLength, int32_t toWhichCase, UErrorCode *pErrorCode) { int32_t destLength; /* check argument values */ if(U_FAILURE(*pErrorCode)) { return 0; } if( destCapacity<0 || (dest==NULL && destCapacity>0) || src==NULL || srcLength<-1 ) { *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; return 0; } /* get the string length */ if(srcLength==-1) { srcLength=(int32_t)uprv_strlen((const char *)src); } /* check for overlapping source and destination */ if( dest!=NULL && ((src>=dest && src<(dest+destCapacity)) || (dest>=src && dest<(src+srcLength))) ) { *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; return 0; } destLength=0; if(toWhichCase==FOLD_CASE) { destLength=utf8_foldCase(csm->csp, dest, destCapacity, src, srcLength, csm->options, pErrorCode); } else { UCaseContext csc={ NULL }; csc.p=(void *)src; csc.limit=srcLength; if(toWhichCase==TO_LOWER) { destLength=_caseMap(csm, ucase_toFullLower, dest, destCapacity, src, &csc, 0, srcLength, pErrorCode); } else if(toWhichCase==TO_UPPER) { destLength=_caseMap(csm, ucase_toFullUpper, dest, destCapacity, src, &csc, 0, srcLength, pErrorCode); } else /* if(toWhichCase==TO_TITLE) */ { #if UCONFIG_NO_BREAK_ITERATION *pErrorCode=U_UNSUPPORTED_ERROR; #else /* UCaseMap is actually non-const in toTitle() APIs. */ UCaseMap *tmp = (UCaseMap *)csm; destLength=_toTitle(tmp, dest, destCapacity, src, &csc, srcLength, pErrorCode); #endif } } return u_terminateChars((char *)dest, destCapacity, destLength, pErrorCode); }