ulocbuilder.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. // © 2023 and later: Unicode, Inc. and others.
  2. // License & terms of use: http://www.unicode.org/copyright.html
  3. #include <utility>
  4. #include "unicode/bytestream.h"
  5. #include "unicode/localebuilder.h"
  6. #include "unicode/locid.h"
  7. #include "unicode/stringpiece.h"
  8. #include "unicode/umachine.h"
  9. #include "unicode/ulocbuilder.h"
  10. #include "bytesinkutil.h"
  11. #include "cstring.h"
  12. #include "ustr_imp.h"
  13. using icu::StringPiece;
  14. #define EXTERNAL(i) (reinterpret_cast<ULocaleBuilder*>(i))
  15. #define INTERNAL(e) (reinterpret_cast<icu::LocaleBuilder*>(e))
  16. #define CONST_INTERNAL(e) (reinterpret_cast<const icu::LocaleBuilder*>(e))
  17. ULocaleBuilder* ulocbld_open() {
  18. return EXTERNAL(new icu::LocaleBuilder());
  19. }
  20. void ulocbld_close(ULocaleBuilder* builder) {
  21. if (builder == nullptr) return;
  22. delete INTERNAL(builder);
  23. }
  24. void ulocbld_setLocale(ULocaleBuilder* builder, const char* locale, int32_t length) {
  25. if (builder == nullptr) return;
  26. icu::Locale l;
  27. if (length < 0 || locale[length] == '\0') {
  28. l = icu::Locale(locale);
  29. } else {
  30. if (length >= ULOC_FULLNAME_CAPACITY) {
  31. l.setToBogus();
  32. } else {
  33. // locale is not null termined but Locale API require one.
  34. // Create a null termined version in buf.
  35. char buf[ULOC_FULLNAME_CAPACITY];
  36. uprv_memcpy(buf, locale, length);
  37. buf[length] = '\0';
  38. l = icu::Locale(buf);
  39. }
  40. }
  41. INTERNAL(builder)->setLocale(l);
  42. }
  43. void
  44. ulocbld_adoptULocale(ULocaleBuilder* builder, ULocale* locale) {
  45. if (builder == nullptr) return;
  46. INTERNAL(builder)->setLocale(*(reinterpret_cast<const icu::Locale*>(locale)));
  47. ulocale_close(locale);
  48. }
  49. #define STRING_PIECE(s, l) ((l)<0 ? StringPiece(s) : StringPiece((s), (l)))
  50. #define IMPL_ULOCBLD_SETTER(N) \
  51. void ulocbld_##N(ULocaleBuilder* bld, const char* s, int32_t l) { \
  52. if (bld == nullptr) return; \
  53. INTERNAL(bld)->N(STRING_PIECE(s,l)); \
  54. }
  55. IMPL_ULOCBLD_SETTER(setLanguageTag)
  56. IMPL_ULOCBLD_SETTER(setLanguage)
  57. IMPL_ULOCBLD_SETTER(setScript)
  58. IMPL_ULOCBLD_SETTER(setRegion)
  59. IMPL_ULOCBLD_SETTER(setVariant)
  60. IMPL_ULOCBLD_SETTER(addUnicodeLocaleAttribute)
  61. IMPL_ULOCBLD_SETTER(removeUnicodeLocaleAttribute)
  62. void ulocbld_setExtension(ULocaleBuilder* builder, char key, const char* value, int32_t length) {
  63. if (builder == nullptr) return;
  64. INTERNAL(builder)->setExtension(key, STRING_PIECE(value, length));
  65. }
  66. void ulocbld_setUnicodeLocaleKeyword(
  67. ULocaleBuilder* builder, const char* key, int32_t keyLength,
  68. const char* type, int32_t typeLength) {
  69. if (builder == nullptr) return;
  70. INTERNAL(builder)->setUnicodeLocaleKeyword(
  71. STRING_PIECE(key, keyLength), STRING_PIECE(type, typeLength));
  72. }
  73. void ulocbld_clear(ULocaleBuilder* builder) {
  74. if (builder == nullptr) return;
  75. INTERNAL(builder)->clear();
  76. }
  77. void ulocbld_clearExtensions(ULocaleBuilder* builder) {
  78. if (builder == nullptr) return;
  79. INTERNAL(builder)->clearExtensions();
  80. }
  81. ULocale* ulocbld_buildULocale(ULocaleBuilder* builder, UErrorCode* err) {
  82. if (builder == nullptr) {
  83. *err = U_ILLEGAL_ARGUMENT_ERROR;
  84. return nullptr;
  85. }
  86. icu::Locale l = INTERNAL(builder)->build(*err);
  87. if (U_FAILURE(*err)) return nullptr;
  88. icu::Locale* r = l.clone();
  89. if (r == nullptr) {
  90. *err = U_MEMORY_ALLOCATION_ERROR;
  91. return nullptr;
  92. }
  93. return reinterpret_cast<ULocale*>(r);
  94. }
  95. int32_t ulocbld_buildLocaleID(ULocaleBuilder* builder,
  96. char* buffer, int32_t bufferCapacity, UErrorCode* err) {
  97. if (U_FAILURE(*err)) { return 0; }
  98. if (builder == nullptr) {
  99. *err = U_ILLEGAL_ARGUMENT_ERROR;
  100. return 0;
  101. }
  102. icu::Locale l = INTERNAL(builder)->build(*err);
  103. if (U_FAILURE(*err)) { return 0; }
  104. int32_t length = static_cast<int32_t>(uprv_strlen(l.getName()));
  105. if (0 < length && length <= bufferCapacity) {
  106. uprv_memcpy(buffer, l.getName(), length);
  107. }
  108. return u_terminateChars(buffer, bufferCapacity, length, err);
  109. }
  110. int32_t ulocbld_buildLanguageTag(ULocaleBuilder* builder,
  111. char* buffer, int32_t bufferCapacity, UErrorCode* err) {
  112. if (U_FAILURE(*err)) { return 0; }
  113. if (builder == nullptr) {
  114. *err = U_ILLEGAL_ARGUMENT_ERROR;
  115. return 0;
  116. }
  117. icu::Locale l = INTERNAL(builder)->build(*err);
  118. return icu::ByteSinkUtil::viaByteSinkToTerminatedChars(
  119. buffer, bufferCapacity,
  120. [&](icu::ByteSink& sink, UErrorCode& status) {
  121. l.toLanguageTag(sink, status);
  122. },
  123. *err);
  124. }
  125. UBool ulocbld_copyErrorTo(const ULocaleBuilder* builder, UErrorCode *outErrorCode) {
  126. if (builder == nullptr) {
  127. *outErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
  128. return true;
  129. }
  130. return CONST_INTERNAL(builder)->copyErrorTo(*outErrorCode);
  131. }