1 // © 2023 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 //
4 #include "unicode/bytestream.h"
5 #include "unicode/errorcode.h"
6 #include "unicode/stringpiece.h"
7 #include "unicode/utypes.h"
8 #include "unicode/ustring.h"
9 #include "unicode/ulocale.h"
10 #include "unicode/locid.h"
11
12 #include "bytesinkutil.h"
13 #include "charstr.h"
14 #include "cmemory.h"
15
16 U_NAMESPACE_USE
17 #define EXTERNAL(i) (reinterpret_cast<ULocale*>(i))
18 #define CONST_INTERNAL(e) (reinterpret_cast<const icu::Locale*>(e))
19 #define INTERNAL(e) (reinterpret_cast<icu::Locale*>(e))
20
21 ULocale*
ulocale_openForLocaleID(const char * localeID,int32_t length,UErrorCode * err)22 ulocale_openForLocaleID(const char* localeID, int32_t length, UErrorCode* err) {
23 if (U_FAILURE(*err)) { return nullptr; }
24 CharString str(length < 0 ? StringPiece(localeID) : StringPiece(localeID, length), *err);
25 if (U_FAILURE(*err)) { return nullptr; }
26 return EXTERNAL(icu::Locale::createFromName(str.data()).clone());
27 }
28
29 ULocale*
ulocale_openForLanguageTag(const char * tag,int32_t length,UErrorCode * err)30 ulocale_openForLanguageTag(const char* tag, int32_t length, UErrorCode* err) {
31 if (U_FAILURE(*err)) { return nullptr; }
32 Locale l = icu::Locale::forLanguageTag(length < 0 ? StringPiece(tag) : StringPiece(tag, length), *err);
33 if (U_FAILURE(*err)) { return nullptr; }
34 return EXTERNAL(l.clone());
35 }
36
37 void
ulocale_close(ULocale * locale)38 ulocale_close(ULocale* locale) {
39 delete INTERNAL(locale);
40 }
41
42 #define IMPL_ULOCALE_STRING_GETTER(N1, N2) \
43 const char* ulocale_get ## N1(const ULocale* locale) { \
44 if (locale == nullptr) return nullptr; \
45 return CONST_INTERNAL(locale)->get ## N2(); \
46 }
47
48 #define IMPL_ULOCALE_STRING_IDENTICAL_GETTER(N) IMPL_ULOCALE_STRING_GETTER(N, N)
49
50 #define IMPL_ULOCALE_GET_KEYWORD_VALUE(N) \
51 int32_t ulocale_get ##N ( \
52 const ULocale* locale, const char* keyword, int32_t keywordLength, \
53 char* valueBuffer, int32_t bufferCapacity, UErrorCode *err) { \
54 if (U_FAILURE(*err)) return 0; \
55 if (locale == nullptr) { \
56 *err = U_ILLEGAL_ARGUMENT_ERROR; \
57 return 0; \
58 } \
59 return ByteSinkUtil::viaByteSinkToTerminatedChars( \
60 valueBuffer, bufferCapacity, \
61 [&](ByteSink& sink, UErrorCode& status) { \
62 CONST_INTERNAL(locale)->get ## N( \
63 keywordLength < 0 ? StringPiece(keyword) : StringPiece(keyword, keywordLength), \
64 sink, status); \
65 }, \
66 *err); \
67 }
68
69 #define IMPL_ULOCALE_GET_KEYWORDS(N) \
70 UEnumeration* ulocale_get ## N(const ULocale* locale, UErrorCode *err) { \
71 if (U_FAILURE(*err)) return nullptr; \
72 if (locale == nullptr) { \
73 *err = U_ILLEGAL_ARGUMENT_ERROR; \
74 return nullptr; \
75 } \
76 return uenum_openFromStringEnumeration( \
77 CONST_INTERNAL(locale)->create ## N(*err), err); \
78 }
79
80 IMPL_ULOCALE_STRING_IDENTICAL_GETTER(Language)
IMPL_ULOCALE_STRING_IDENTICAL_GETTER(Script)81 IMPL_ULOCALE_STRING_IDENTICAL_GETTER(Script)
82 IMPL_ULOCALE_STRING_GETTER(Region, Country)
83 IMPL_ULOCALE_STRING_IDENTICAL_GETTER(Variant)
84 IMPL_ULOCALE_STRING_GETTER(LocaleID, Name)
85 IMPL_ULOCALE_STRING_IDENTICAL_GETTER(BaseName)
86 IMPL_ULOCALE_GET_KEYWORD_VALUE(KeywordValue)
87 IMPL_ULOCALE_GET_KEYWORD_VALUE(UnicodeKeywordValue)
88 IMPL_ULOCALE_GET_KEYWORDS(Keywords)
89 IMPL_ULOCALE_GET_KEYWORDS(UnicodeKeywords)
90
91 bool ulocale_isBogus(const ULocale* locale) {
92 if (locale == nullptr) return false;
93 return CONST_INTERNAL(locale)->isBogus();
94 }
95
96 /*eof*/
97