/src/icu/source/common/locdispnames.cpp
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | // © 2016 and later: Unicode, Inc. and others.  | 
2  |  | // License & terms of use: http://www.unicode.org/copyright.html  | 
3  |  | /*  | 
4  |  | *******************************************************************************  | 
5  |  | *  | 
6  |  | *   Copyright (C) 1997-2016, International Business Machines  | 
7  |  | *   Corporation and others.  All Rights Reserved.  | 
8  |  | *  | 
9  |  | *******************************************************************************  | 
10  |  | *   file name:  locdispnames.cpp  | 
11  |  | *   encoding:   UTF-8  | 
12  |  | *   tab size:   8 (not used)  | 
13  |  | *   indentation:4  | 
14  |  | *  | 
15  |  | *   created on: 2010feb25  | 
16  |  | *   created by: Markus W. Scherer  | 
17  |  | *  | 
18  |  | *   Code for locale display names, separated out from other .cpp files  | 
19  |  | *   that then do not depend on resource bundle code and display name data.  | 
20  |  | */  | 
21  |  |  | 
22  |  | #include "unicode/utypes.h"  | 
23  |  | #include "unicode/brkiter.h"  | 
24  |  | #include "unicode/locid.h"  | 
25  |  | #include "unicode/uenum.h"  | 
26  |  | #include "unicode/uloc.h"  | 
27  |  | #include "unicode/ures.h"  | 
28  |  | #include "unicode/ustring.h"  | 
29  |  | #include "bytesinkutil.h"  | 
30  |  | #include "charstr.h"  | 
31  |  | #include "cmemory.h"  | 
32  |  | #include "cstring.h"  | 
33  |  | #include "putilimp.h"  | 
34  |  | #include "ulocimp.h"  | 
35  |  | #include "uresimp.h"  | 
36  |  | #include "ureslocs.h"  | 
37  |  | #include "ustr_imp.h"  | 
38  |  |  | 
39  |  | // C++ API ----------------------------------------------------------------- ***  | 
40  |  |  | 
41  |  | U_NAMESPACE_BEGIN  | 
42  |  |  | 
43  |  | UnicodeString&  | 
44  |  | Locale::getDisplayLanguage(UnicodeString& dispLang) const  | 
45  | 0  | { | 
46  | 0  |     return this->getDisplayLanguage(getDefault(), dispLang);  | 
47  | 0  | }  | 
48  |  |  | 
49  |  | /*We cannot make any assumptions on the size of the output display strings  | 
50  |  | * Yet, since we are calling through to a C API, we need to set limits on  | 
51  |  | * buffer size. For all the following getDisplay functions we first attempt  | 
52  |  | * to fill up a stack allocated buffer. If it is to small we heap allocated  | 
53  |  | * the exact buffer we need copy it to the UnicodeString and delete it*/  | 
54  |  |  | 
55  |  | UnicodeString&  | 
56  |  | Locale::getDisplayLanguage(const Locale &displayLocale,  | 
57  | 0  |                            UnicodeString &result) const { | 
58  | 0  |     UChar *buffer;  | 
59  | 0  |     UErrorCode errorCode=U_ZERO_ERROR;  | 
60  | 0  |     int32_t length;  | 
61  |  | 
  | 
62  | 0  |     buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY);  | 
63  | 0  |     if(buffer==0) { | 
64  | 0  |         result.truncate(0);  | 
65  | 0  |         return result;  | 
66  | 0  |     }  | 
67  |  |  | 
68  | 0  |     length=uloc_getDisplayLanguage(fullName, displayLocale.fullName,  | 
69  | 0  |                                    buffer, result.getCapacity(),  | 
70  | 0  |                                    &errorCode);  | 
71  | 0  |     result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0);  | 
72  |  | 
  | 
73  | 0  |     if(errorCode==U_BUFFER_OVERFLOW_ERROR) { | 
74  | 0  |         buffer=result.getBuffer(length);  | 
75  | 0  |         if(buffer==0) { | 
76  | 0  |             result.truncate(0);  | 
77  | 0  |             return result;  | 
78  | 0  |         }  | 
79  | 0  |         errorCode=U_ZERO_ERROR;  | 
80  | 0  |         length=uloc_getDisplayLanguage(fullName, displayLocale.fullName,  | 
81  | 0  |                                        buffer, result.getCapacity(),  | 
82  | 0  |                                        &errorCode);  | 
83  | 0  |         result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0);  | 
84  | 0  |     }  | 
85  |  |  | 
86  | 0  |     return result;  | 
87  | 0  | }  | 
88  |  |  | 
89  |  | UnicodeString&  | 
90  |  | Locale::getDisplayScript(UnicodeString& dispScript) const  | 
91  | 0  | { | 
92  | 0  |     return this->getDisplayScript(getDefault(), dispScript);  | 
93  | 0  | }  | 
94  |  |  | 
95  |  | UnicodeString&  | 
96  |  | Locale::getDisplayScript(const Locale &displayLocale,  | 
97  | 0  |                           UnicodeString &result) const { | 
98  | 0  |     UChar *buffer;  | 
99  | 0  |     UErrorCode errorCode=U_ZERO_ERROR;  | 
100  | 0  |     int32_t length;  | 
101  |  | 
  | 
102  | 0  |     buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY);  | 
103  | 0  |     if(buffer==0) { | 
104  | 0  |         result.truncate(0);  | 
105  | 0  |         return result;  | 
106  | 0  |     }  | 
107  |  |  | 
108  | 0  |     length=uloc_getDisplayScript(fullName, displayLocale.fullName,  | 
109  | 0  |                                   buffer, result.getCapacity(),  | 
110  | 0  |                                   &errorCode);  | 
111  | 0  |     result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0);  | 
112  |  | 
  | 
113  | 0  |     if(errorCode==U_BUFFER_OVERFLOW_ERROR) { | 
114  | 0  |         buffer=result.getBuffer(length);  | 
115  | 0  |         if(buffer==0) { | 
116  | 0  |             result.truncate(0);  | 
117  | 0  |             return result;  | 
118  | 0  |         }  | 
119  | 0  |         errorCode=U_ZERO_ERROR;  | 
120  | 0  |         length=uloc_getDisplayScript(fullName, displayLocale.fullName,  | 
121  | 0  |                                       buffer, result.getCapacity(),  | 
122  | 0  |                                       &errorCode);  | 
123  | 0  |         result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0);  | 
124  | 0  |     }  | 
125  |  |  | 
126  | 0  |     return result;  | 
127  | 0  | }  | 
128  |  |  | 
129  |  | UnicodeString&  | 
130  |  | Locale::getDisplayCountry(UnicodeString& dispCntry) const  | 
131  | 0  | { | 
132  | 0  |     return this->getDisplayCountry(getDefault(), dispCntry);  | 
133  | 0  | }  | 
134  |  |  | 
135  |  | UnicodeString&  | 
136  |  | Locale::getDisplayCountry(const Locale &displayLocale,  | 
137  | 0  |                           UnicodeString &result) const { | 
138  | 0  |     UChar *buffer;  | 
139  | 0  |     UErrorCode errorCode=U_ZERO_ERROR;  | 
140  | 0  |     int32_t length;  | 
141  |  | 
  | 
142  | 0  |     buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY);  | 
143  | 0  |     if(buffer==0) { | 
144  | 0  |         result.truncate(0);  | 
145  | 0  |         return result;  | 
146  | 0  |     }  | 
147  |  |  | 
148  | 0  |     length=uloc_getDisplayCountry(fullName, displayLocale.fullName,  | 
149  | 0  |                                   buffer, result.getCapacity(),  | 
150  | 0  |                                   &errorCode);  | 
151  | 0  |     result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0);  | 
152  |  | 
  | 
153  | 0  |     if(errorCode==U_BUFFER_OVERFLOW_ERROR) { | 
154  | 0  |         buffer=result.getBuffer(length);  | 
155  | 0  |         if(buffer==0) { | 
156  | 0  |             result.truncate(0);  | 
157  | 0  |             return result;  | 
158  | 0  |         }  | 
159  | 0  |         errorCode=U_ZERO_ERROR;  | 
160  | 0  |         length=uloc_getDisplayCountry(fullName, displayLocale.fullName,  | 
161  | 0  |                                       buffer, result.getCapacity(),  | 
162  | 0  |                                       &errorCode);  | 
163  | 0  |         result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0);  | 
164  | 0  |     }  | 
165  |  |  | 
166  | 0  |     return result;  | 
167  | 0  | }  | 
168  |  |  | 
169  |  | UnicodeString&  | 
170  |  | Locale::getDisplayVariant(UnicodeString& dispVar) const  | 
171  | 0  | { | 
172  | 0  |     return this->getDisplayVariant(getDefault(), dispVar);  | 
173  | 0  | }  | 
174  |  |  | 
175  |  | UnicodeString&  | 
176  |  | Locale::getDisplayVariant(const Locale &displayLocale,  | 
177  | 0  |                           UnicodeString &result) const { | 
178  | 0  |     UChar *buffer;  | 
179  | 0  |     UErrorCode errorCode=U_ZERO_ERROR;  | 
180  | 0  |     int32_t length;  | 
181  |  | 
  | 
182  | 0  |     buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY);  | 
183  | 0  |     if(buffer==0) { | 
184  | 0  |         result.truncate(0);  | 
185  | 0  |         return result;  | 
186  | 0  |     }  | 
187  |  |  | 
188  | 0  |     length=uloc_getDisplayVariant(fullName, displayLocale.fullName,  | 
189  | 0  |                                   buffer, result.getCapacity(),  | 
190  | 0  |                                   &errorCode);  | 
191  | 0  |     result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0);  | 
192  |  | 
  | 
193  | 0  |     if(errorCode==U_BUFFER_OVERFLOW_ERROR) { | 
194  | 0  |         buffer=result.getBuffer(length);  | 
195  | 0  |         if(buffer==0) { | 
196  | 0  |             result.truncate(0);  | 
197  | 0  |             return result;  | 
198  | 0  |         }  | 
199  | 0  |         errorCode=U_ZERO_ERROR;  | 
200  | 0  |         length=uloc_getDisplayVariant(fullName, displayLocale.fullName,  | 
201  | 0  |                                       buffer, result.getCapacity(),  | 
202  | 0  |                                       &errorCode);  | 
203  | 0  |         result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0);  | 
204  | 0  |     }  | 
205  |  |  | 
206  | 0  |     return result;  | 
207  | 0  | }  | 
208  |  |  | 
209  |  | UnicodeString&  | 
210  |  | Locale::getDisplayName( UnicodeString& name ) const  | 
211  | 0  | { | 
212  | 0  |     return this->getDisplayName(getDefault(), name);  | 
213  | 0  | }  | 
214  |  |  | 
215  |  | UnicodeString&  | 
216  |  | Locale::getDisplayName(const Locale &displayLocale,  | 
217  | 0  |                        UnicodeString &result) const { | 
218  | 0  |     UChar *buffer;  | 
219  | 0  |     UErrorCode errorCode=U_ZERO_ERROR;  | 
220  | 0  |     int32_t length;  | 
221  |  | 
  | 
222  | 0  |     buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY);  | 
223  | 0  |     if(buffer==0) { | 
224  | 0  |         result.truncate(0);  | 
225  | 0  |         return result;  | 
226  | 0  |     }  | 
227  |  |  | 
228  | 0  |     length=uloc_getDisplayName(fullName, displayLocale.fullName,  | 
229  | 0  |                                buffer, result.getCapacity(),  | 
230  | 0  |                                &errorCode);  | 
231  | 0  |     result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0);  | 
232  |  | 
  | 
233  | 0  |     if(errorCode==U_BUFFER_OVERFLOW_ERROR) { | 
234  | 0  |         buffer=result.getBuffer(length);  | 
235  | 0  |         if(buffer==0) { | 
236  | 0  |             result.truncate(0);  | 
237  | 0  |             return result;  | 
238  | 0  |         }  | 
239  | 0  |         errorCode=U_ZERO_ERROR;  | 
240  | 0  |         length=uloc_getDisplayName(fullName, displayLocale.fullName,  | 
241  | 0  |                                    buffer, result.getCapacity(),  | 
242  | 0  |                                    &errorCode);  | 
243  | 0  |         result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0);  | 
244  | 0  |     }  | 
245  |  |  | 
246  | 0  |     return result;  | 
247  | 0  | }  | 
248  |  |  | 
249  |  | #if ! UCONFIG_NO_BREAK_ITERATION  | 
250  |  |  | 
251  |  | // -------------------------------------  | 
252  |  | // Gets the objectLocale display name in the default locale language.  | 
253  |  | UnicodeString& U_EXPORT2  | 
254  |  | BreakIterator::getDisplayName(const Locale& objectLocale,  | 
255  |  |                              UnicodeString& name)  | 
256  | 0  | { | 
257  | 0  |     return objectLocale.getDisplayName(name);  | 
258  | 0  | }  | 
259  |  |  | 
260  |  | // -------------------------------------  | 
261  |  | // Gets the objectLocale display name in the displayLocale language.  | 
262  |  | UnicodeString& U_EXPORT2  | 
263  |  | BreakIterator::getDisplayName(const Locale& objectLocale,  | 
264  |  |                              const Locale& displayLocale,  | 
265  |  |                              UnicodeString& name)  | 
266  | 0  | { | 
267  | 0  |     return objectLocale.getDisplayName(displayLocale, name);  | 
268  | 0  | }  | 
269  |  |  | 
270  |  | #endif  | 
271  |  |  | 
272  |  |  | 
273  |  | U_NAMESPACE_END  | 
274  |  |  | 
275  |  | // C API ------------------------------------------------------------------- ***  | 
276  |  |  | 
277  |  | U_NAMESPACE_USE  | 
278  |  |  | 
279  |  | /* ### Constants **************************************************/  | 
280  |  |  | 
281  |  | /* These strings describe the resources we attempt to load from  | 
282  |  |  the locale ResourceBundle data file.*/  | 
283  |  | static const char _kLanguages[]       = "Languages";  | 
284  |  | static const char _kScripts[]         = "Scripts";  | 
285  |  | static const char _kScriptsStandAlone[] = "Scripts%stand-alone";  | 
286  |  | static const char _kCountries[]       = "Countries";  | 
287  |  | static const char _kVariants[]        = "Variants";  | 
288  |  | static const char _kKeys[]            = "Keys";  | 
289  |  | static const char _kTypes[]           = "Types";  | 
290  |  | //static const char _kRootName[]        = "root";  | 
291  |  | static const char _kCurrency[]        = "currency";  | 
292  |  | static const char _kCurrencies[]      = "Currencies";  | 
293  |  | static const char _kLocaleDisplayPattern[] = "localeDisplayPattern";  | 
294  |  | static const char _kPattern[]         = "pattern";  | 
295  |  | static const char _kSeparator[]       = "separator";  | 
296  |  |  | 
297  |  | /* ### Display name **************************************************/  | 
298  |  |  | 
299  |  | static int32_t  | 
300  |  | _getStringOrCopyKey(const char *path, const char *locale,  | 
301  |  |                     const char *tableKey,   | 
302  |  |                     const char* subTableKey,  | 
303  |  |                     const char *itemKey,  | 
304  |  |                     const char *substitute,  | 
305  |  |                     UChar *dest, int32_t destCapacity,  | 
306  | 0  |                     UErrorCode *pErrorCode) { | 
307  | 0  |     const UChar *s = NULL;  | 
308  | 0  |     int32_t length = 0;  | 
309  |  | 
  | 
310  | 0  |     if(itemKey==NULL) { | 
311  |  |         /* top-level item: normal resource bundle access */  | 
312  | 0  |         icu::LocalUResourceBundlePointer rb(ures_open(path, locale, pErrorCode));  | 
313  |  | 
  | 
314  | 0  |         if(U_SUCCESS(*pErrorCode)) { | 
315  | 0  |             s=ures_getStringByKey(rb.getAlias(), tableKey, &length, pErrorCode);  | 
316  |  |             /* see comment about closing rb near "return item;" in _res_getTableStringWithFallback() */  | 
317  | 0  |         }  | 
318  | 0  |     } else { | 
319  |  |         /* Language code should not be a number. If it is, set the error code. */  | 
320  | 0  |         if (!uprv_strncmp(tableKey, "Languages", 9) && uprv_strtol(itemKey, NULL, 10)) { | 
321  | 0  |             *pErrorCode = U_MISSING_RESOURCE_ERROR;  | 
322  | 0  |         } else { | 
323  |  |             /* second-level item, use special fallback */  | 
324  | 0  |             s=uloc_getTableStringWithFallback(path, locale,  | 
325  | 0  |                                                tableKey,   | 
326  | 0  |                                                subTableKey,  | 
327  | 0  |                                                itemKey,  | 
328  | 0  |                                                &length,  | 
329  | 0  |                                                pErrorCode);  | 
330  | 0  |         }  | 
331  | 0  |     }  | 
332  |  | 
  | 
333  | 0  |     if(U_SUCCESS(*pErrorCode)) { | 
334  | 0  |         int32_t copyLength=uprv_min(length, destCapacity);  | 
335  | 0  |         if(copyLength>0 && s != NULL) { | 
336  | 0  |             u_memcpy(dest, s, copyLength);  | 
337  | 0  |         }  | 
338  | 0  |     } else { | 
339  |  |         /* no string from a resource bundle: convert the substitute */  | 
340  | 0  |         length=(int32_t)uprv_strlen(substitute);  | 
341  | 0  |         u_charsToUChars(substitute, dest, uprv_min(length, destCapacity));  | 
342  | 0  |         *pErrorCode=U_USING_DEFAULT_WARNING;  | 
343  | 0  |     }  | 
344  |  | 
  | 
345  | 0  |     return u_terminateUChars(dest, destCapacity, length, pErrorCode);  | 
346  | 0  | }  | 
347  |  |  | 
348  |  | typedef  int32_t U_CALLCONV UDisplayNameGetter(const char *, char *, int32_t, UErrorCode *);  | 
349  |  |  | 
350  |  | static int32_t  | 
351  |  | _getDisplayNameForComponent(const char *locale,  | 
352  |  |                             const char *displayLocale,  | 
353  |  |                             UChar *dest, int32_t destCapacity,  | 
354  |  |                             UDisplayNameGetter *getter,  | 
355  |  |                             const char *tag,  | 
356  | 0  |                             UErrorCode *pErrorCode) { | 
357  | 0  |     char localeBuffer[ULOC_FULLNAME_CAPACITY*4];  | 
358  | 0  |     int32_t length;  | 
359  | 0  |     UErrorCode localStatus;  | 
360  | 0  |     const char* root = NULL;  | 
361  |  |  | 
362  |  |     /* argument checking */  | 
363  | 0  |     if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { | 
364  | 0  |         return 0;  | 
365  | 0  |     }  | 
366  |  |  | 
367  | 0  |     if(destCapacity<0 || (destCapacity>0 && dest==NULL)) { | 
368  | 0  |         *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;  | 
369  | 0  |         return 0;  | 
370  | 0  |     }  | 
371  |  |  | 
372  | 0  |     localStatus = U_ZERO_ERROR;  | 
373  | 0  |     length=(*getter)(locale, localeBuffer, sizeof(localeBuffer), &localStatus);  | 
374  | 0  |     if(U_FAILURE(localStatus) || localStatus==U_STRING_NOT_TERMINATED_WARNING) { | 
375  | 0  |         *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;  | 
376  | 0  |         return 0;  | 
377  | 0  |     }  | 
378  | 0  |     if(length==0) { | 
379  |  |         // For the display name, we treat this as unknown language (ICU-20273).  | 
380  | 0  |         if (getter == uloc_getLanguage) { | 
381  | 0  |             uprv_strcpy(localeBuffer, "und");  | 
382  | 0  |         } else { | 
383  | 0  |             return u_terminateUChars(dest, destCapacity, 0, pErrorCode);  | 
384  | 0  |         }  | 
385  | 0  |     }  | 
386  |  |  | 
387  | 0  |     root = tag == _kCountries ? U_ICUDATA_REGION : U_ICUDATA_LANG;  | 
388  |  | 
  | 
389  | 0  |     return _getStringOrCopyKey(root, displayLocale,  | 
390  | 0  |                                tag, NULL, localeBuffer,  | 
391  | 0  |                                localeBuffer,  | 
392  | 0  |                                dest, destCapacity,  | 
393  | 0  |                                pErrorCode);  | 
394  | 0  | }  | 
395  |  |  | 
396  |  | U_CAPI int32_t U_EXPORT2  | 
397  |  | uloc_getDisplayLanguage(const char *locale,  | 
398  |  |                         const char *displayLocale,  | 
399  |  |                         UChar *dest, int32_t destCapacity,  | 
400  | 0  |                         UErrorCode *pErrorCode) { | 
401  | 0  |     return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,  | 
402  | 0  |                 uloc_getLanguage, _kLanguages, pErrorCode);  | 
403  | 0  | }  | 
404  |  |  | 
405  |  | U_CAPI int32_t U_EXPORT2  | 
406  |  | uloc_getDisplayScript(const char* locale,  | 
407  |  |                       const char* displayLocale,  | 
408  |  |                       UChar *dest, int32_t destCapacity,  | 
409  |  |                       UErrorCode *pErrorCode)  | 
410  | 0  | { | 
411  | 0  |     UErrorCode err = U_ZERO_ERROR;  | 
412  | 0  |     int32_t res = _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,  | 
413  | 0  |                 uloc_getScript, _kScriptsStandAlone, &err);  | 
414  |  | 
  | 
415  | 0  |     if (destCapacity == 0 && err == U_BUFFER_OVERFLOW_ERROR) { | 
416  |  |         // For preflight, return the max of the value and the fallback.  | 
417  | 0  |         int32_t fallback_res = _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,  | 
418  | 0  |                                                            uloc_getScript, _kScripts, pErrorCode);  | 
419  | 0  |         return (fallback_res > res) ? fallback_res : res;  | 
420  | 0  |     }  | 
421  | 0  |     if ( err == U_USING_DEFAULT_WARNING ) { | 
422  | 0  |         return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,  | 
423  | 0  |                                            uloc_getScript, _kScripts, pErrorCode);  | 
424  | 0  |     } else { | 
425  | 0  |         *pErrorCode = err;  | 
426  | 0  |         return res;  | 
427  | 0  |     }  | 
428  | 0  | }  | 
429  |  |  | 
430  |  | static int32_t  | 
431  |  | uloc_getDisplayScriptInContext(const char* locale,  | 
432  |  |                       const char* displayLocale,  | 
433  |  |                       UChar *dest, int32_t destCapacity,  | 
434  |  |                       UErrorCode *pErrorCode)  | 
435  | 0  | { | 
436  | 0  |     return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,  | 
437  | 0  |                     uloc_getScript, _kScripts, pErrorCode);  | 
438  | 0  | }  | 
439  |  |  | 
440  |  | U_CAPI int32_t U_EXPORT2  | 
441  |  | uloc_getDisplayCountry(const char *locale,  | 
442  |  |                        const char *displayLocale,  | 
443  |  |                        UChar *dest, int32_t destCapacity,  | 
444  | 0  |                        UErrorCode *pErrorCode) { | 
445  | 0  |     return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,  | 
446  | 0  |                 uloc_getCountry, _kCountries, pErrorCode);  | 
447  | 0  | }  | 
448  |  |  | 
449  |  | /*  | 
450  |  |  * TODO separate variant1_variant2_variant3...  | 
451  |  |  * by getting each tag's display string and concatenating them with ", "  | 
452  |  |  * in between - similar to uloc_getDisplayName()  | 
453  |  |  */  | 
454  |  | U_CAPI int32_t U_EXPORT2  | 
455  |  | uloc_getDisplayVariant(const char *locale,  | 
456  |  |                        const char *displayLocale,  | 
457  |  |                        UChar *dest, int32_t destCapacity,  | 
458  | 0  |                        UErrorCode *pErrorCode) { | 
459  | 0  |     return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,  | 
460  | 0  |                 uloc_getVariant, _kVariants, pErrorCode);  | 
461  | 0  | }  | 
462  |  |  | 
463  |  | /* Instead of having a separate pass for 'special' patterns, reintegrate the two  | 
464  |  |  * so we don't get bitten by preflight bugs again.  We can be reasonably efficient  | 
465  |  |  * without two separate code paths, this code isn't that performance-critical.  | 
466  |  |  *  | 
467  |  |  * This code is general enough to deal with patterns that have a prefix or swap the  | 
468  |  |  * language and remainder components, since we gave developers enough rope to do such  | 
469  |  |  * things if they futz with the pattern data.  But since we don't give them a way to  | 
470  |  |  * specify a pattern for arbitrary combinations of components, there's not much use in  | 
471  |  |  * that.  I don't think our data includes such patterns, the only variable I know if is  | 
472  |  |  * whether there is a space before the open paren, or not.  Oh, and zh uses different  | 
473  |  |  * chars than the standard open/close paren (which ja and ko use, btw).  | 
474  |  |  */  | 
475  |  | U_CAPI int32_t U_EXPORT2  | 
476  |  | uloc_getDisplayName(const char *locale,  | 
477  |  |                     const char *displayLocale,  | 
478  |  |                     UChar *dest, int32_t destCapacity,  | 
479  |  |                     UErrorCode *pErrorCode)  | 
480  | 0  | { | 
481  | 0  |     static const UChar defaultSeparator[9] = { 0x007b, 0x0030, 0x007d, 0x002c, 0x0020, 0x007b, 0x0031, 0x007d, 0x0000 }; /* "{0}, {1}" */ | 
482  | 0  |     static const UChar sub0[4] = { 0x007b, 0x0030, 0x007d , 0x0000 } ; /* {0} */ | 
483  | 0  |     static const UChar sub1[4] = { 0x007b, 0x0031, 0x007d , 0x0000 } ; /* {1} */ | 
484  | 0  |     static const int32_t subLen = 3;  | 
485  | 0  |     static const UChar defaultPattern[10] = { | 
486  | 0  |         0x007b, 0x0030, 0x007d, 0x0020, 0x0028, 0x007b, 0x0031, 0x007d, 0x0029, 0x0000  | 
487  | 0  |     }; /* {0} ({1}) */ | 
488  | 0  |     static const int32_t defaultPatLen = 9;  | 
489  | 0  |     static const int32_t defaultSub0Pos = 0;  | 
490  | 0  |     static const int32_t defaultSub1Pos = 5;  | 
491  |  | 
  | 
492  | 0  |     int32_t length; /* of formatted result */  | 
493  |  | 
  | 
494  | 0  |     const UChar *separator;  | 
495  | 0  |     int32_t sepLen = 0;  | 
496  | 0  |     const UChar *pattern;  | 
497  | 0  |     int32_t patLen = 0;  | 
498  | 0  |     int32_t sub0Pos, sub1Pos;  | 
499  |  |       | 
500  | 0  |     UChar formatOpenParen         = 0x0028; // (  | 
501  | 0  |     UChar formatReplaceOpenParen  = 0x005B; // [  | 
502  | 0  |     UChar formatCloseParen        = 0x0029; // )  | 
503  | 0  |     UChar formatReplaceCloseParen = 0x005D; // ]  | 
504  |  | 
  | 
505  | 0  |     UBool haveLang = TRUE; /* assume true, set false if we find we don't have  | 
506  |  |                               a lang component in the locale */  | 
507  | 0  |     UBool haveRest = TRUE; /* assume true, set false if we find we don't have  | 
508  |  |                               any other component in the locale */  | 
509  | 0  |     UBool retry = FALSE; /* set true if we need to retry, see below */  | 
510  |  | 
  | 
511  | 0  |     int32_t langi = 0; /* index of the language substitution (0 or 1), virtually always 0 */  | 
512  |  | 
  | 
513  | 0  |     if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { | 
514  | 0  |         return 0;  | 
515  | 0  |     }  | 
516  |  |  | 
517  | 0  |     if(destCapacity<0 || (destCapacity>0 && dest==NULL)) { | 
518  | 0  |         *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;  | 
519  | 0  |         return 0;  | 
520  | 0  |     }  | 
521  |  |  | 
522  | 0  |     { | 
523  | 0  |         UErrorCode status = U_ZERO_ERROR;  | 
524  |  | 
  | 
525  | 0  |         icu::LocalUResourceBundlePointer locbundle(  | 
526  | 0  |                 ures_open(U_ICUDATA_LANG, displayLocale, &status));  | 
527  | 0  |         icu::LocalUResourceBundlePointer dspbundle(  | 
528  | 0  |                 ures_getByKeyWithFallback(locbundle.getAlias(), _kLocaleDisplayPattern, NULL, &status));  | 
529  |  | 
  | 
530  | 0  |         separator=ures_getStringByKeyWithFallback(dspbundle.getAlias(), _kSeparator, &sepLen, &status);  | 
531  | 0  |         pattern=ures_getStringByKeyWithFallback(dspbundle.getAlias(), _kPattern, &patLen, &status);  | 
532  | 0  |     }  | 
533  |  |  | 
534  |  |     /* If we couldn't find any data, then use the defaults */  | 
535  | 0  |     if(sepLen == 0) { | 
536  | 0  |        separator = defaultSeparator;  | 
537  | 0  |     }  | 
538  |  |     /* #10244: Even though separator is now a pattern, it is awkward to handle it as such  | 
539  |  |      * here since we are trying to build the display string in place in the dest buffer,  | 
540  |  |      * and to handle it as a pattern would entail having separate storage for the  | 
541  |  |      * substrings that need to be combined (the first of which may be the result of  | 
542  |  |      * previous such combinations). So for now we continue to treat the portion between  | 
543  |  |      * {0} and {1} as a string to be appended when joining substrings, ignoring anything | 
544  |  |      * that is before {0} or after {1} (no existing separator pattern has any such thing). | 
545  |  |      * This is similar to how pattern is handled below.  | 
546  |  |      */  | 
547  | 0  |     { | 
548  | 0  |         UChar *p0=u_strstr(separator, sub0);  | 
549  | 0  |         UChar *p1=u_strstr(separator, sub1);  | 
550  | 0  |         if (p0==NULL || p1==NULL || p1<p0) { | 
551  | 0  |             *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;  | 
552  | 0  |             return 0;  | 
553  | 0  |         }  | 
554  | 0  |         separator = (const UChar *)p0 + subLen;  | 
555  | 0  |         sepLen = static_cast<int32_t>(p1 - separator);  | 
556  | 0  |     }  | 
557  |  |  | 
558  | 0  |     if(patLen==0 || (patLen==defaultPatLen && !u_strncmp(pattern, defaultPattern, patLen))) { | 
559  | 0  |         pattern=defaultPattern;  | 
560  | 0  |         patLen=defaultPatLen;  | 
561  | 0  |         sub0Pos=defaultSub0Pos;  | 
562  | 0  |         sub1Pos=defaultSub1Pos;  | 
563  |  |         // use default formatOpenParen etc. set above  | 
564  | 0  |     } else { /* non-default pattern */ | 
565  | 0  |         UChar *p0=u_strstr(pattern, sub0);  | 
566  | 0  |         UChar *p1=u_strstr(pattern, sub1);  | 
567  | 0  |         if (p0==NULL || p1==NULL) { | 
568  | 0  |             *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;  | 
569  | 0  |             return 0;  | 
570  | 0  |         }  | 
571  | 0  |         sub0Pos = static_cast<int32_t>(p0-pattern);  | 
572  | 0  |         sub1Pos = static_cast<int32_t>(p1-pattern);  | 
573  | 0  |         if (sub1Pos < sub0Pos) { /* a very odd pattern */ | 
574  | 0  |             int32_t t=sub0Pos; sub0Pos=sub1Pos; sub1Pos=t;  | 
575  | 0  |             langi=1;  | 
576  | 0  |         }  | 
577  | 0  |         if (u_strchr(pattern, 0xFF08) != NULL) { | 
578  | 0  |             formatOpenParen         = 0xFF08; // fullwidth (  | 
579  | 0  |             formatReplaceOpenParen  = 0xFF3B; // fullwidth [  | 
580  | 0  |             formatCloseParen        = 0xFF09; // fullwidth )  | 
581  | 0  |             formatReplaceCloseParen = 0xFF3D; // fullwidth ]  | 
582  | 0  |         }  | 
583  | 0  |     }  | 
584  |  |  | 
585  |  |     /* We loop here because there is one case in which after the first pass we could need to  | 
586  |  |      * reextract the data.  If there's initial padding before the first element, we put in  | 
587  |  |      * the padding and then write that element.  If it turns out there's no second element,  | 
588  |  |      * we didn't need the padding.  If we do need the data (no preflight), and the first element  | 
589  |  |      * would have fit but for the padding, we need to reextract.  In this case (only) we  | 
590  |  |      * adjust the parameters so padding is not added, and repeat.  | 
591  |  |      */  | 
592  | 0  |     do { | 
593  | 0  |         UChar* p=dest;  | 
594  | 0  |         int32_t patPos=0; /* position in the pattern, used for non-substitution portions */  | 
595  | 0  |         int32_t langLen=0; /* length of language substitution */  | 
596  | 0  |         int32_t langPos=0; /* position in output of language substitution */  | 
597  | 0  |         int32_t restLen=0; /* length of 'everything else' substitution */  | 
598  | 0  |         int32_t restPos=0; /* position in output of 'everything else' substitution */  | 
599  | 0  |         icu::LocalUEnumerationPointer kenum; /* keyword enumeration */  | 
600  |  |  | 
601  |  |         /* prefix of pattern, extremely likely to be empty */  | 
602  | 0  |         if(sub0Pos) { | 
603  | 0  |             if(destCapacity >= sub0Pos) { | 
604  | 0  |                 while (patPos < sub0Pos) { | 
605  | 0  |                     *p++ = pattern[patPos++];  | 
606  | 0  |                 }  | 
607  | 0  |             } else { | 
608  | 0  |                 patPos=sub0Pos;  | 
609  | 0  |             }  | 
610  | 0  |             length=sub0Pos;  | 
611  | 0  |         } else { | 
612  | 0  |             length=0;  | 
613  | 0  |         }  | 
614  |  | 
  | 
615  | 0  |         for(int32_t subi=0,resti=0;subi<2;) { /* iterate through patterns 0 and 1*/ | 
616  | 0  |             UBool subdone = FALSE; /* set true when ready to move to next substitution */  | 
617  |  |  | 
618  |  |             /* prep p and cap for calls to get display components, pin cap to 0 since  | 
619  |  |                they complain if cap is negative */  | 
620  | 0  |             int32_t cap=destCapacity-length;  | 
621  | 0  |             if (cap <= 0) { | 
622  | 0  |                 cap=0;  | 
623  | 0  |             } else { | 
624  | 0  |                 p=dest+length;  | 
625  | 0  |             }  | 
626  |  | 
  | 
627  | 0  |             if (subi == langi) { /* {0}*/ | 
628  | 0  |                 if(haveLang) { | 
629  | 0  |                     langPos=length;  | 
630  | 0  |                     langLen=uloc_getDisplayLanguage(locale, displayLocale, p, cap, pErrorCode);  | 
631  | 0  |                     length+=langLen;  | 
632  | 0  |                     haveLang=langLen>0;  | 
633  | 0  |                 }  | 
634  | 0  |                 subdone=TRUE;  | 
635  | 0  |             } else { /* {1} */ | 
636  | 0  |                 if(!haveRest) { | 
637  | 0  |                     subdone=TRUE;  | 
638  | 0  |                 } else { | 
639  | 0  |                     int32_t len; /* length of component (plus other stuff) we just fetched */  | 
640  | 0  |                     switch(resti++) { | 
641  | 0  |                         case 0:  | 
642  | 0  |                             restPos=length;  | 
643  | 0  |                             len=uloc_getDisplayScriptInContext(locale, displayLocale, p, cap, pErrorCode);  | 
644  | 0  |                             break;  | 
645  | 0  |                         case 1:  | 
646  | 0  |                             len=uloc_getDisplayCountry(locale, displayLocale, p, cap, pErrorCode);  | 
647  | 0  |                             break;  | 
648  | 0  |                         case 2:  | 
649  | 0  |                             len=uloc_getDisplayVariant(locale, displayLocale, p, cap, pErrorCode);  | 
650  | 0  |                             break;  | 
651  | 0  |                         case 3:  | 
652  | 0  |                             kenum.adoptInstead(uloc_openKeywords(locale, pErrorCode));  | 
653  | 0  |                             U_FALLTHROUGH;  | 
654  | 0  |                         default: { | 
655  | 0  |                             const char* kw=uenum_next(kenum.getAlias(), &len, pErrorCode);  | 
656  | 0  |                             if (kw == NULL) { | 
657  | 0  |                                 len=0; /* mark that we didn't add a component */  | 
658  | 0  |                                 subdone=TRUE;  | 
659  | 0  |                             } else { | 
660  |  |                                 /* incorporating this behavior into the loop made it even more complex,  | 
661  |  |                                    so just special case it here */  | 
662  | 0  |                                 len = uloc_getDisplayKeyword(kw, displayLocale, p, cap, pErrorCode);  | 
663  | 0  |                                 if(len) { | 
664  | 0  |                                     if(len < cap) { | 
665  | 0  |                                         p[len]=0x3d; /* '=', assume we'll need it */  | 
666  | 0  |                                     }  | 
667  | 0  |                                     len+=1;  | 
668  |  |  | 
669  |  |                                     /* adjust for call to get keyword */  | 
670  | 0  |                                     cap-=len;  | 
671  | 0  |                                     if(cap <= 0) { | 
672  | 0  |                                         cap=0;  | 
673  | 0  |                                     } else { | 
674  | 0  |                                         p+=len;  | 
675  | 0  |                                     }  | 
676  | 0  |                                 }  | 
677  |  |                                 /* reset for call below */  | 
678  | 0  |                                 if(*pErrorCode == U_BUFFER_OVERFLOW_ERROR) { | 
679  | 0  |                                     *pErrorCode=U_ZERO_ERROR;  | 
680  | 0  |                                 }  | 
681  | 0  |                                 int32_t vlen = uloc_getDisplayKeywordValue(locale, kw, displayLocale,  | 
682  | 0  |                                                                            p, cap, pErrorCode);  | 
683  | 0  |                                 if(len) { | 
684  | 0  |                                     if(vlen==0) { | 
685  | 0  |                                         --len; /* remove unneeded '=' */  | 
686  | 0  |                                     }  | 
687  |  |                                     /* restore cap and p to what they were at start */  | 
688  | 0  |                                     cap=destCapacity-length;  | 
689  | 0  |                                     if(cap <= 0) { | 
690  | 0  |                                         cap=0;  | 
691  | 0  |                                     } else { | 
692  | 0  |                                         p=dest+length;  | 
693  | 0  |                                     }  | 
694  | 0  |                                 }  | 
695  | 0  |                                 len+=vlen; /* total we added for key + '=' + value */  | 
696  | 0  |                             }  | 
697  | 0  |                         } break;  | 
698  | 0  |                     } /* end switch */  | 
699  |  |  | 
700  | 0  |                     if (len>0) { | 
701  |  |                         /* we added a component, so add separator and write it if there's room. */  | 
702  | 0  |                         if(len+sepLen<=cap) { | 
703  | 0  |                             const UChar * plimit = p + len;  | 
704  | 0  |                             for (; p < plimit; p++) { | 
705  | 0  |                                 if (*p == formatOpenParen) { | 
706  | 0  |                                     *p = formatReplaceOpenParen;  | 
707  | 0  |                                 } else if (*p == formatCloseParen) { | 
708  | 0  |                                     *p = formatReplaceCloseParen;  | 
709  | 0  |                                 }  | 
710  | 0  |                             }  | 
711  | 0  |                             for(int32_t i=0;i<sepLen;++i) { | 
712  | 0  |                                 *p++=separator[i];  | 
713  | 0  |                             }  | 
714  | 0  |                         }  | 
715  | 0  |                         length+=len+sepLen;  | 
716  | 0  |                     } else if(subdone) { | 
717  |  |                         /* remove separator if we added it */  | 
718  | 0  |                         if (length!=restPos) { | 
719  | 0  |                             length-=sepLen;  | 
720  | 0  |                         }  | 
721  | 0  |                         restLen=length-restPos;  | 
722  | 0  |                         haveRest=restLen>0;  | 
723  | 0  |                     }  | 
724  | 0  |                 }  | 
725  | 0  |             }  | 
726  |  |  | 
727  | 0  |             if(*pErrorCode == U_BUFFER_OVERFLOW_ERROR) { | 
728  | 0  |                 *pErrorCode=U_ZERO_ERROR;  | 
729  | 0  |             }  | 
730  |  | 
  | 
731  | 0  |             if(subdone) { | 
732  | 0  |                 if(haveLang && haveRest) { | 
733  |  |                     /* append internal portion of pattern, the first time,  | 
734  |  |                        or last portion of pattern the second time */  | 
735  | 0  |                     int32_t padLen;  | 
736  | 0  |                     patPos+=subLen;  | 
737  | 0  |                     padLen=(subi==0 ? sub1Pos : patLen)-patPos;  | 
738  | 0  |                     if(length+padLen <= destCapacity) { | 
739  | 0  |                         p=dest+length;  | 
740  | 0  |                         for(int32_t i=0;i<padLen;++i) { | 
741  | 0  |                             *p++=pattern[patPos++];  | 
742  | 0  |                         }  | 
743  | 0  |                     } else { | 
744  | 0  |                         patPos+=padLen;  | 
745  | 0  |                     }  | 
746  | 0  |                     length+=padLen;  | 
747  | 0  |                 } else if(subi==0) { | 
748  |  |                     /* don't have first component, reset for second component */  | 
749  | 0  |                     sub0Pos=0;  | 
750  | 0  |                     length=0;  | 
751  | 0  |                 } else if(length>0) { | 
752  |  |                     /* true length is the length of just the component we got. */  | 
753  | 0  |                     length=haveLang?langLen:restLen;  | 
754  | 0  |                     if(dest && sub0Pos!=0) { | 
755  | 0  |                         if (sub0Pos+length<=destCapacity) { | 
756  |  |                             /* first component not at start of result,  | 
757  |  |                                but we have full component in buffer. */  | 
758  | 0  |                             u_memmove(dest, dest+(haveLang?langPos:restPos), length);  | 
759  | 0  |                         } else { | 
760  |  |                             /* would have fit, but didn't because of pattern prefix. */  | 
761  | 0  |                             sub0Pos=0; /* stops initial padding (and a second retry,  | 
762  |  |                                           so we won't end up here again) */  | 
763  | 0  |                             retry=TRUE;  | 
764  | 0  |                         }  | 
765  | 0  |                     }  | 
766  | 0  |                 }  | 
767  |  | 
  | 
768  | 0  |                 ++subi; /* move on to next substitution */  | 
769  | 0  |             }  | 
770  | 0  |         }  | 
771  | 0  |     } while(retry);  | 
772  |  |  | 
773  | 0  |     return u_terminateUChars(dest, destCapacity, length, pErrorCode);  | 
774  | 0  | }  | 
775  |  |  | 
776  |  | U_CAPI int32_t U_EXPORT2  | 
777  |  | uloc_getDisplayKeyword(const char* keyword,  | 
778  |  |                        const char* displayLocale,  | 
779  |  |                        UChar* dest,  | 
780  |  |                        int32_t destCapacity,  | 
781  | 0  |                        UErrorCode* status){ | 
782  |  |  | 
783  |  |     /* argument checking */  | 
784  | 0  |     if(status==NULL || U_FAILURE(*status)) { | 
785  | 0  |         return 0;  | 
786  | 0  |     }  | 
787  |  |  | 
788  | 0  |     if(destCapacity<0 || (destCapacity>0 && dest==NULL)) { | 
789  | 0  |         *status=U_ILLEGAL_ARGUMENT_ERROR;  | 
790  | 0  |         return 0;  | 
791  | 0  |     }  | 
792  |  |  | 
793  |  |  | 
794  |  |     /* pass itemKey=NULL to look for a top-level item */  | 
795  | 0  |     return _getStringOrCopyKey(U_ICUDATA_LANG, displayLocale,  | 
796  | 0  |                                _kKeys, NULL,   | 
797  | 0  |                                keyword,   | 
798  | 0  |                                keyword,        | 
799  | 0  |                                dest, destCapacity,  | 
800  | 0  |                                status);  | 
801  |  | 
  | 
802  | 0  | }  | 
803  |  |  | 
804  |  |  | 
805  | 0  | #define UCURRENCY_DISPLAY_NAME_INDEX 1  | 
806  |  |  | 
807  |  | U_CAPI int32_t U_EXPORT2  | 
808  |  | uloc_getDisplayKeywordValue(   const char* locale,  | 
809  |  |                                const char* keyword,  | 
810  |  |                                const char* displayLocale,  | 
811  |  |                                UChar* dest,  | 
812  |  |                                int32_t destCapacity,  | 
813  | 0  |                                UErrorCode* status){ | 
814  |  |  | 
815  |  |  | 
816  |  |     /* argument checking */  | 
817  | 0  |     if(status==NULL || U_FAILURE(*status)) { | 
818  | 0  |         return 0;  | 
819  | 0  |     }  | 
820  |  |  | 
821  | 0  |     if(destCapacity<0 || (destCapacity>0 && dest==NULL)) { | 
822  | 0  |         *status=U_ILLEGAL_ARGUMENT_ERROR;  | 
823  | 0  |         return 0;  | 
824  | 0  |     }  | 
825  |  |  | 
826  |  |     /* get the keyword value */  | 
827  | 0  |     CharString keywordValue;  | 
828  | 0  |     { | 
829  | 0  |         CharStringByteSink sink(&keywordValue);  | 
830  | 0  |         ulocimp_getKeywordValue(locale, keyword, sink, status);  | 
831  | 0  |     }  | 
832  |  |  | 
833  |  |     /*   | 
834  |  |      * if the keyword is equal to currency .. then to get the display name   | 
835  |  |      * we need to do the fallback ourselves  | 
836  |  |      */  | 
837  | 0  |     if(uprv_stricmp(keyword, _kCurrency)==0){ | 
838  |  | 
  | 
839  | 0  |         int32_t dispNameLen = 0;  | 
840  | 0  |         const UChar *dispName = NULL;  | 
841  |  | 
  | 
842  | 0  |         icu::LocalUResourceBundlePointer bundle(  | 
843  | 0  |                 ures_open(U_ICUDATA_CURR, displayLocale, status));  | 
844  | 0  |         icu::LocalUResourceBundlePointer currencies(  | 
845  | 0  |                 ures_getByKey(bundle.getAlias(), _kCurrencies, NULL, status));  | 
846  | 0  |         icu::LocalUResourceBundlePointer currency(  | 
847  | 0  |                 ures_getByKeyWithFallback(currencies.getAlias(), keywordValue.data(), NULL, status));  | 
848  |  | 
  | 
849  | 0  |         dispName = ures_getStringByIndex(currency.getAlias(), UCURRENCY_DISPLAY_NAME_INDEX, &dispNameLen, status);  | 
850  |  | 
  | 
851  | 0  |         if(U_FAILURE(*status)){ | 
852  | 0  |             if(*status == U_MISSING_RESOURCE_ERROR){ | 
853  |  |                 /* we just want to write the value over if nothing is available */  | 
854  | 0  |                 *status = U_USING_DEFAULT_WARNING;  | 
855  | 0  |             }else{ | 
856  | 0  |                 return 0;  | 
857  | 0  |             }  | 
858  | 0  |         }  | 
859  |  |  | 
860  |  |         /* now copy the dispName over if not NULL */  | 
861  | 0  |         if(dispName != NULL){ | 
862  | 0  |             if(dispNameLen <= destCapacity){ | 
863  | 0  |                 u_memcpy(dest, dispName, dispNameLen);  | 
864  | 0  |                 return u_terminateUChars(dest, destCapacity, dispNameLen, status);  | 
865  | 0  |             }else{ | 
866  | 0  |                 *status = U_BUFFER_OVERFLOW_ERROR;  | 
867  | 0  |                 return dispNameLen;  | 
868  | 0  |             }  | 
869  | 0  |         }else{ | 
870  |  |             /* we have not found the display name for the value .. just copy over */  | 
871  | 0  |             if(keywordValue.length() <= destCapacity){ | 
872  | 0  |                 u_charsToUChars(keywordValue.data(), dest, keywordValue.length());  | 
873  | 0  |                 return u_terminateUChars(dest, destCapacity, keywordValue.length(), status);  | 
874  | 0  |             }else{ | 
875  | 0  |                  *status = U_BUFFER_OVERFLOW_ERROR;  | 
876  | 0  |                 return keywordValue.length();  | 
877  | 0  |             }  | 
878  | 0  |         }  | 
879  |  |  | 
880  |  |           | 
881  | 0  |     }else{ | 
882  |  | 
  | 
883  | 0  |         return _getStringOrCopyKey(U_ICUDATA_LANG, displayLocale,  | 
884  | 0  |                                    _kTypes, keyword,   | 
885  | 0  |                                    keywordValue.data(),  | 
886  | 0  |                                    keywordValue.data(),  | 
887  | 0  |                                    dest, destCapacity,  | 
888  | 0  |                                    status);  | 
889  | 0  |     }  | 
890  | 0  | }  |