ICU-13417 Pass length from Locale::forLanguageTag() to ultag_parse().

If not passed a length, ultag_parse() will call uprv_strlen(), requiring
the input buffer to be NUL terminated. This is unnecessary.
This commit is contained in:
Fredrik Roubert 2018-09-18 16:53:22 -07:00 committed by Shane Carr
parent 1fa15f7e6e
commit cc6c31432e
No known key found for this signature in database
GPG key ID: FCED3B24AAB18B5C
3 changed files with 54 additions and 9 deletions

View file

@ -46,6 +46,7 @@
#include "cstring.h"
#include "uassert.h"
#include "uhash.h"
#include "ulocimp.h"
#include "ucln_cmn.h"
#include "ustr_imp.h"
#include "charstr.h"
@ -858,12 +859,6 @@ Locale::forLanguageTag(StringPiece tag, UErrorCode& status)
return result;
}
// TODO: Remove the need for a const char* to a NUL terminated buffer.
const CharString tag_nul(tag, status);
if (U_FAILURE(status)) {
return result;
}
// If a BCP-47 language tag is passed as the language parameter to the
// normal Locale constructor, it will actually fall back to invoking
// uloc_forLanguageTag() to parse it if it somehow is able to detect that
@ -893,8 +888,9 @@ Locale::forLanguageTag(StringPiece tag, UErrorCode& status)
return result;
}
reslen = uloc_forLanguageTag(
tag_nul.data(),
reslen = ulocimp_forLanguageTag(
tag.data(),
tag.length(),
buffer,
resultCapacity,
&parsedLength,

View file

@ -2416,6 +2416,23 @@ uloc_forLanguageTag(const char* langtag,
int32_t localeIDCapacity,
int32_t* parsedLength,
UErrorCode* status) {
return ulocimp_forLanguageTag(
langtag,
-1,
localeID,
localeIDCapacity,
parsedLength,
status);
}
U_CAPI int32_t U_EXPORT2
ulocimp_forLanguageTag(const char* langtag,
int32_t tagLen,
char* localeID,
int32_t localeIDCapacity,
int32_t* parsedLength,
UErrorCode* status) {
ULanguageTag *lt;
int32_t reslen = 0;
const char *subtag, *p;
@ -2423,7 +2440,7 @@ uloc_forLanguageTag(const char* langtag,
int32_t i, n;
UBool noRegion = TRUE;
lt = ultag_parse(langtag, -1, parsedLength, status);
lt = ultag_parse(langtag, tagLen, parsedLength, status);
if (U_FAILURE(*status)) {
return 0;
}

View file

@ -61,6 +61,38 @@ ulocimp_getCountry(const char *localeID,
char *country, int32_t countryCapacity,
const char **pEnd);
/**
* Returns a locale ID for the specified BCP47 language tag string.
* If the specified language tag contains any ill-formed subtags,
* the first such subtag and all following subtags are ignored.
* <p>
* This implements the 'Language-Tag' production of BCP47, and so
* supports grandfathered (regular and irregular) as well as private
* use language tags. Private use tags are represented as 'x-whatever',
* and grandfathered tags are converted to their canonical replacements
* where they exist. Note that a few grandfathered tags have no modern
* replacement, these will be converted using the fallback described in
* the first paragraph, so some information might be lost.
* @param langtag the input BCP47 language tag.
* @param tagLen the length of langtag, or -1 to call uprv_strlen().
* @param localeID the output buffer receiving a locale ID for the
* specified BCP47 language tag.
* @param localeIDCapacity the size of the locale ID output buffer.
* @param parsedLength if not NULL, successfully parsed length
* for the input language tag is set.
* @param err error information if receiving the locald ID
* failed.
* @return the length of the locale ID.
* @internal ICU 63
*/
U_STABLE int32_t U_EXPORT2
ulocimp_forLanguageTag(const char* langtag,
int32_t tagLen,
char* localeID,
int32_t localeIDCapacity,
int32_t* parsedLength,
UErrorCode* err);
/**
* Get the region to use for supplemental data lookup. Uses
* (1) any region specified by locale tag "rg"; if none then