servls.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. // © 2016 and later: Unicode, Inc. and others.
  2. // License & terms of use: http://www.unicode.org/copyright.html
  3. /**
  4. *******************************************************************************
  5. * Copyright (C) 2001-2014, International Business Machines Corporation and *
  6. * others. All Rights Reserved. *
  7. *******************************************************************************
  8. *
  9. *******************************************************************************
  10. */
  11. #include "unicode/utypes.h"
  12. #if !UCONFIG_NO_SERVICE
  13. #include "unicode/resbund.h"
  14. #include "uresimp.h"
  15. #include "cmemory.h"
  16. #include "servloc.h"
  17. #include "ustrfmt.h"
  18. #include "charstr.h"
  19. #include "uassert.h"
  20. #define UNDERSCORE_CHAR ((char16_t)0x005f)
  21. #define AT_SIGN_CHAR ((char16_t)64)
  22. #define PERIOD_CHAR ((char16_t)46)
  23. U_NAMESPACE_BEGIN
  24. ICULocaleService::ICULocaleService()
  25. : fallbackLocale(Locale::getDefault())
  26. {
  27. }
  28. ICULocaleService::ICULocaleService(const UnicodeString& dname)
  29. : ICUService(dname)
  30. , fallbackLocale(Locale::getDefault())
  31. {
  32. }
  33. ICULocaleService::~ICULocaleService()
  34. {
  35. }
  36. UObject*
  37. ICULocaleService::get(const Locale& locale, UErrorCode& status) const
  38. {
  39. return get(locale, LocaleKey::KIND_ANY, nullptr, status);
  40. }
  41. UObject*
  42. ICULocaleService::get(const Locale& locale, int32_t kind, UErrorCode& status) const
  43. {
  44. return get(locale, kind, nullptr, status);
  45. }
  46. UObject*
  47. ICULocaleService::get(const Locale& locale, Locale* actualReturn, UErrorCode& status) const
  48. {
  49. return get(locale, LocaleKey::KIND_ANY, actualReturn, status);
  50. }
  51. UObject*
  52. ICULocaleService::get(const Locale& locale, int32_t kind, Locale* actualReturn, UErrorCode& status) const
  53. {
  54. UObject* result = nullptr;
  55. if (U_FAILURE(status)) {
  56. return result;
  57. }
  58. UnicodeString locName(locale.getName(), -1, US_INV);
  59. if (locName.isBogus()) {
  60. status = U_MEMORY_ALLOCATION_ERROR;
  61. } else {
  62. ICUServiceKey* key = createKey(&locName, kind, status);
  63. if (key) {
  64. if (actualReturn == nullptr) {
  65. result = getKey(*key, status);
  66. } else {
  67. UnicodeString temp;
  68. result = getKey(*key, &temp, status);
  69. if (result != nullptr) {
  70. key->parseSuffix(temp);
  71. LocaleUtility::initLocaleFromName(temp, *actualReturn);
  72. }
  73. }
  74. delete key;
  75. }
  76. }
  77. return result;
  78. }
  79. URegistryKey
  80. ICULocaleService::registerInstance(UObject* objToAdopt, const UnicodeString& locale,
  81. UBool visible, UErrorCode& status)
  82. {
  83. Locale loc;
  84. LocaleUtility::initLocaleFromName(locale, loc);
  85. return registerInstance(objToAdopt, loc, LocaleKey::KIND_ANY,
  86. visible ? LocaleKeyFactory::VISIBLE : LocaleKeyFactory::INVISIBLE, status);
  87. }
  88. URegistryKey
  89. ICULocaleService::registerInstance(UObject* objToAdopt, const Locale& locale, UErrorCode& status)
  90. {
  91. return registerInstance(objToAdopt, locale, LocaleKey::KIND_ANY, LocaleKeyFactory::VISIBLE, status);
  92. }
  93. URegistryKey
  94. ICULocaleService::registerInstance(UObject* objToAdopt, const Locale& locale, int32_t kind, UErrorCode& status)
  95. {
  96. return registerInstance(objToAdopt, locale, kind, LocaleKeyFactory::VISIBLE, status);
  97. }
  98. URegistryKey
  99. ICULocaleService::registerInstance(UObject* objToAdopt, const Locale& locale, int32_t kind, int32_t coverage, UErrorCode& status)
  100. {
  101. ICUServiceFactory * factory = new SimpleLocaleKeyFactory(objToAdopt, locale, kind, coverage);
  102. if (factory != nullptr) {
  103. return registerFactory(factory, status);
  104. }
  105. delete objToAdopt;
  106. return nullptr;
  107. }
  108. #if 0
  109. URegistryKey
  110. ICULocaleService::registerInstance(UObject* objToAdopt, const UnicodeString& locale, UErrorCode& status)
  111. {
  112. return registerInstance(objToAdopt, locale, LocaleKey::KIND_ANY, LocaleKeyFactory::VISIBLE, status);
  113. }
  114. URegistryKey
  115. ICULocaleService::registerInstance(UObject* objToAdopt, const UnicodeString& locale, UBool visible, UErrorCode& status)
  116. {
  117. return registerInstance(objToAdopt, locale, LocaleKey::KIND_ANY,
  118. visible ? LocaleKeyFactory::VISIBLE : LocaleKeyFactory::INVISIBLE,
  119. status);
  120. }
  121. URegistryKey
  122. ICULocaleService::registerInstance(UObject* objToAdopt, const UnicodeString& locale, int32_t kind, int32_t coverage, UErrorCode& status)
  123. {
  124. ICUServiceFactory * factory = new SimpleLocaleKeyFactory(objToAdopt, locale, kind, coverage);
  125. if (factory != nullptr) {
  126. return registerFactory(factory, status);
  127. }
  128. delete objToAdopt;
  129. return nullptr;
  130. }
  131. #endif
  132. class ServiceEnumeration : public StringEnumeration {
  133. private:
  134. const ICULocaleService* _service;
  135. int32_t _timestamp;
  136. UVector _ids;
  137. int32_t _pos;
  138. private:
  139. ServiceEnumeration(const ICULocaleService* service, UErrorCode &status)
  140. : _service(service)
  141. , _timestamp(service->getTimestamp())
  142. , _ids(uprv_deleteUObject, nullptr, status)
  143. , _pos(0)
  144. {
  145. _service->getVisibleIDs(_ids, status);
  146. }
  147. ServiceEnumeration(const ServiceEnumeration &other, UErrorCode &status)
  148. : _service(other._service)
  149. , _timestamp(other._timestamp)
  150. , _ids(uprv_deleteUObject, nullptr, status)
  151. , _pos(0)
  152. {
  153. if(U_SUCCESS(status)) {
  154. int32_t i, length;
  155. length = other._ids.size();
  156. for(i = 0; i < length; ++i) {
  157. LocalPointer<UnicodeString> clonedId(((UnicodeString *)other._ids.elementAt(i))->clone(), status);
  158. _ids.adoptElement(clonedId.orphan(), status);
  159. }
  160. if(U_SUCCESS(status)) {
  161. _pos = other._pos;
  162. }
  163. }
  164. }
  165. public:
  166. static ServiceEnumeration* create(const ICULocaleService* service) {
  167. UErrorCode status = U_ZERO_ERROR;
  168. ServiceEnumeration* result = new ServiceEnumeration(service, status);
  169. if (U_SUCCESS(status)) {
  170. return result;
  171. }
  172. delete result;
  173. return nullptr;
  174. }
  175. virtual ~ServiceEnumeration();
  176. virtual StringEnumeration *clone() const override {
  177. UErrorCode status = U_ZERO_ERROR;
  178. ServiceEnumeration *cl = new ServiceEnumeration(*this, status);
  179. if(U_FAILURE(status)) {
  180. delete cl;
  181. cl = nullptr;
  182. }
  183. return cl;
  184. }
  185. UBool upToDate(UErrorCode& status) const {
  186. if (U_SUCCESS(status)) {
  187. if (_timestamp == _service->getTimestamp()) {
  188. return true;
  189. }
  190. status = U_ENUM_OUT_OF_SYNC_ERROR;
  191. }
  192. return false;
  193. }
  194. virtual int32_t count(UErrorCode& status) const override {
  195. return upToDate(status) ? _ids.size() : 0;
  196. }
  197. virtual const UnicodeString* snext(UErrorCode& status) override {
  198. if (upToDate(status) && (_pos < _ids.size())) {
  199. return (const UnicodeString*)_ids[_pos++];
  200. }
  201. return nullptr;
  202. }
  203. virtual void reset(UErrorCode& status) override {
  204. if (status == U_ENUM_OUT_OF_SYNC_ERROR) {
  205. status = U_ZERO_ERROR;
  206. }
  207. if (U_SUCCESS(status)) {
  208. _timestamp = _service->getTimestamp();
  209. _pos = 0;
  210. _service->getVisibleIDs(_ids, status);
  211. }
  212. }
  213. public:
  214. static UClassID U_EXPORT2 getStaticClassID();
  215. virtual UClassID getDynamicClassID() const override;
  216. };
  217. ServiceEnumeration::~ServiceEnumeration() {}
  218. UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ServiceEnumeration)
  219. StringEnumeration*
  220. ICULocaleService::getAvailableLocales() const
  221. {
  222. return ServiceEnumeration::create(this);
  223. }
  224. const UnicodeString&
  225. ICULocaleService::validateFallbackLocale() const
  226. {
  227. const Locale& loc = Locale::getDefault();
  228. ICULocaleService* ncThis = (ICULocaleService*)this;
  229. static UMutex llock;
  230. {
  231. Mutex mutex(&llock);
  232. if (loc != fallbackLocale) {
  233. ncThis->fallbackLocale = loc;
  234. LocaleUtility::initNameFromLocale(loc, ncThis->fallbackLocaleName);
  235. ncThis->clearServiceCache();
  236. }
  237. }
  238. return fallbackLocaleName;
  239. }
  240. ICUServiceKey*
  241. ICULocaleService::createKey(const UnicodeString* id, UErrorCode& status) const
  242. {
  243. return LocaleKey::createWithCanonicalFallback(id, &validateFallbackLocale(), status);
  244. }
  245. ICUServiceKey*
  246. ICULocaleService::createKey(const UnicodeString* id, int32_t kind, UErrorCode& status) const
  247. {
  248. return LocaleKey::createWithCanonicalFallback(id, &validateFallbackLocale(), kind, status);
  249. }
  250. U_NAMESPACE_END
  251. /* !UCONFIG_NO_SERVICE */
  252. #endif