ulocdata.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  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) 2003-2016, International Business Machines *
  7. * Corporation and others. All Rights Reserved. *
  8. * *
  9. ******************************************************************************
  10. * file name: ulocdata.c
  11. * encoding: UTF-8
  12. * tab size: 8 (not used)
  13. * indentation:4
  14. *
  15. * created on: 2003Oct21
  16. * created by: Ram Viswanadha,John Emmons
  17. */
  18. #include "cmemory.h"
  19. #include "unicode/ustring.h"
  20. #include "unicode/ures.h"
  21. #include "unicode/uloc.h"
  22. #include "unicode/ulocdata.h"
  23. #include "uresimp.h"
  24. #include "ureslocs.h"
  25. #include "ulocimp.h"
  26. #define MEASUREMENT_SYSTEM "MeasurementSystem"
  27. #define PAPER_SIZE "PaperSize"
  28. /** A locale data object.
  29. * For usage in C programs.
  30. * @draft ICU 3.4
  31. */
  32. struct ULocaleData {
  33. /**
  34. * Controls the "No Substitute" behavior of this locale data object
  35. */
  36. UBool noSubstitute;
  37. /**
  38. * Pointer to the resource bundle associated with this locale data object
  39. */
  40. UResourceBundle *bundle;
  41. /**
  42. * Pointer to the lang resource bundle associated with this locale data object
  43. */
  44. UResourceBundle *langBundle;
  45. };
  46. U_CAPI ULocaleData* U_EXPORT2
  47. ulocdata_open(const char *localeID, UErrorCode *status)
  48. {
  49. ULocaleData *uld;
  50. if (U_FAILURE(*status)) {
  51. return nullptr;
  52. }
  53. uld = (ULocaleData *)uprv_malloc(sizeof(ULocaleData));
  54. if (uld == nullptr) {
  55. *status = U_MEMORY_ALLOCATION_ERROR;
  56. return(nullptr);
  57. }
  58. uld->langBundle = nullptr;
  59. uld->noSubstitute = false;
  60. uld->bundle = ures_open(nullptr, localeID, status);
  61. uld->langBundle = ures_open(U_ICUDATA_LANG, localeID, status);
  62. if (U_FAILURE(*status)) {
  63. uprv_free(uld);
  64. return nullptr;
  65. }
  66. return uld;
  67. }
  68. U_CAPI void U_EXPORT2
  69. ulocdata_close(ULocaleData *uld)
  70. {
  71. if ( uld != nullptr ) {
  72. ures_close(uld->langBundle);
  73. ures_close(uld->bundle);
  74. uprv_free(uld);
  75. }
  76. }
  77. U_CAPI void U_EXPORT2
  78. ulocdata_setNoSubstitute(ULocaleData *uld, UBool setting)
  79. {
  80. uld->noSubstitute = setting;
  81. }
  82. U_CAPI UBool U_EXPORT2
  83. ulocdata_getNoSubstitute(ULocaleData *uld)
  84. {
  85. return uld->noSubstitute;
  86. }
  87. U_CAPI USet* U_EXPORT2
  88. ulocdata_getExemplarSet(ULocaleData *uld, USet *fillIn,
  89. uint32_t options, ULocaleDataExemplarSetType extype, UErrorCode *status){
  90. static const char* const exemplarSetTypes[] = { "ExemplarCharacters",
  91. "AuxExemplarCharacters",
  92. "ExemplarCharactersIndex",
  93. "ExemplarCharactersPunctuation"};
  94. const char16_t *exemplarChars = nullptr;
  95. int32_t len = 0;
  96. UErrorCode localStatus = U_ZERO_ERROR;
  97. if (U_FAILURE(*status))
  98. return nullptr;
  99. exemplarChars = ures_getStringByKey(uld->bundle, exemplarSetTypes[extype], &len, &localStatus);
  100. if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
  101. localStatus = U_MISSING_RESOURCE_ERROR;
  102. }
  103. if (localStatus != U_ZERO_ERROR) {
  104. *status = localStatus;
  105. }
  106. if (U_FAILURE(*status))
  107. return nullptr;
  108. if(fillIn != nullptr)
  109. uset_applyPattern(fillIn, exemplarChars, len,
  110. USET_IGNORE_SPACE | options, status);
  111. else
  112. fillIn = uset_openPatternOptions(exemplarChars, len,
  113. USET_IGNORE_SPACE | options, status);
  114. return fillIn;
  115. }
  116. U_CAPI int32_t U_EXPORT2
  117. ulocdata_getDelimiter(ULocaleData *uld, ULocaleDataDelimiterType type,
  118. char16_t *result, int32_t resultLength, UErrorCode *status){
  119. static const char* const delimiterKeys[] = {
  120. "quotationStart",
  121. "quotationEnd",
  122. "alternateQuotationStart",
  123. "alternateQuotationEnd"
  124. };
  125. UResourceBundle *delimiterBundle;
  126. int32_t len = 0;
  127. const char16_t *delimiter = nullptr;
  128. UErrorCode localStatus = U_ZERO_ERROR;
  129. if (U_FAILURE(*status))
  130. return 0;
  131. delimiterBundle = ures_getByKey(uld->bundle, "delimiters", nullptr, &localStatus);
  132. if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
  133. localStatus = U_MISSING_RESOURCE_ERROR;
  134. }
  135. if (localStatus != U_ZERO_ERROR) {
  136. *status = localStatus;
  137. }
  138. if (U_FAILURE(*status)){
  139. ures_close(delimiterBundle);
  140. return 0;
  141. }
  142. delimiter = ures_getStringByKeyWithFallback(delimiterBundle, delimiterKeys[type], &len, &localStatus);
  143. ures_close(delimiterBundle);
  144. if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
  145. localStatus = U_MISSING_RESOURCE_ERROR;
  146. }
  147. if (localStatus != U_ZERO_ERROR) {
  148. *status = localStatus;
  149. }
  150. if (U_FAILURE(*status)){
  151. return 0;
  152. }
  153. u_strncpy(result,delimiter, resultLength);
  154. return len;
  155. }
  156. static UResourceBundle * measurementTypeBundleForLocale(const char *localeID, const char *measurementType, UErrorCode *status){
  157. char region[ULOC_COUNTRY_CAPACITY];
  158. UResourceBundle *rb;
  159. UResourceBundle *measTypeBundle = nullptr;
  160. ulocimp_getRegionForSupplementalData(localeID, true, region, ULOC_COUNTRY_CAPACITY, status);
  161. rb = ures_openDirect(nullptr, "supplementalData", status);
  162. ures_getByKey(rb, "measurementData", rb, status);
  163. if (rb != nullptr) {
  164. UResourceBundle *measDataBundle = ures_getByKey(rb, region, nullptr, status);
  165. if (U_SUCCESS(*status)) {
  166. measTypeBundle = ures_getByKey(measDataBundle, measurementType, nullptr, status);
  167. }
  168. if (*status == U_MISSING_RESOURCE_ERROR) {
  169. *status = U_ZERO_ERROR;
  170. if (measDataBundle != nullptr) {
  171. ures_close(measDataBundle);
  172. }
  173. measDataBundle = ures_getByKey(rb, "001", nullptr, status);
  174. measTypeBundle = ures_getByKey(measDataBundle, measurementType, nullptr, status);
  175. }
  176. ures_close(measDataBundle);
  177. }
  178. ures_close(rb);
  179. return measTypeBundle;
  180. }
  181. U_CAPI UMeasurementSystem U_EXPORT2
  182. ulocdata_getMeasurementSystem(const char *localeID, UErrorCode *status){
  183. UResourceBundle* measurement=nullptr;
  184. UMeasurementSystem system = UMS_LIMIT;
  185. if(status == nullptr || U_FAILURE(*status)){
  186. return system;
  187. }
  188. measurement = measurementTypeBundleForLocale(localeID, MEASUREMENT_SYSTEM, status);
  189. int32_t result = ures_getInt(measurement, status);
  190. if (U_SUCCESS(*status)) {
  191. system = static_cast<UMeasurementSystem>(result);
  192. }
  193. ures_close(measurement);
  194. return system;
  195. }
  196. U_CAPI void U_EXPORT2
  197. ulocdata_getPaperSize(const char* localeID, int32_t *height, int32_t *width, UErrorCode *status){
  198. UResourceBundle* paperSizeBundle = nullptr;
  199. const int32_t* paperSize=nullptr;
  200. int32_t len = 0;
  201. if(status == nullptr || U_FAILURE(*status)){
  202. return;
  203. }
  204. paperSizeBundle = measurementTypeBundleForLocale(localeID, PAPER_SIZE, status);
  205. paperSize = ures_getIntVector(paperSizeBundle, &len, status);
  206. if(U_SUCCESS(*status)){
  207. if(len < 2){
  208. *status = U_INTERNAL_PROGRAM_ERROR;
  209. }else{
  210. *height = paperSize[0];
  211. *width = paperSize[1];
  212. }
  213. }
  214. ures_close(paperSizeBundle);
  215. }
  216. U_CAPI void U_EXPORT2
  217. ulocdata_getCLDRVersion(UVersionInfo versionArray, UErrorCode *status) {
  218. UResourceBundle *rb = nullptr;
  219. rb = ures_openDirect(nullptr, "supplementalData", status);
  220. ures_getVersionByKey(rb, "cldrVersion", versionArray, status);
  221. ures_close(rb);
  222. }
  223. U_CAPI int32_t U_EXPORT2
  224. ulocdata_getLocaleDisplayPattern(ULocaleData *uld,
  225. char16_t *result,
  226. int32_t resultCapacity,
  227. UErrorCode *status) {
  228. UResourceBundle *patternBundle;
  229. int32_t len = 0;
  230. const char16_t *pattern = nullptr;
  231. UErrorCode localStatus = U_ZERO_ERROR;
  232. if (U_FAILURE(*status))
  233. return 0;
  234. patternBundle = ures_getByKey(uld->langBundle, "localeDisplayPattern", nullptr, &localStatus);
  235. if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
  236. localStatus = U_MISSING_RESOURCE_ERROR;
  237. }
  238. if (localStatus != U_ZERO_ERROR) {
  239. *status = localStatus;
  240. }
  241. if (U_FAILURE(*status)){
  242. ures_close(patternBundle);
  243. return 0;
  244. }
  245. pattern = ures_getStringByKey(patternBundle, "pattern", &len, &localStatus);
  246. ures_close(patternBundle);
  247. if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
  248. localStatus = U_MISSING_RESOURCE_ERROR;
  249. }
  250. if (localStatus != U_ZERO_ERROR) {
  251. *status = localStatus;
  252. }
  253. if (U_FAILURE(*status)){
  254. return 0;
  255. }
  256. u_strncpy(result, pattern, resultCapacity);
  257. return len;
  258. }
  259. U_CAPI int32_t U_EXPORT2
  260. ulocdata_getLocaleSeparator(ULocaleData *uld,
  261. char16_t *result,
  262. int32_t resultCapacity,
  263. UErrorCode *status) {
  264. UResourceBundle *separatorBundle;
  265. int32_t len = 0;
  266. const char16_t *separator = nullptr;
  267. UErrorCode localStatus = U_ZERO_ERROR;
  268. char16_t *p0, *p1;
  269. static const char16_t sub0[4] = { 0x007b, 0x0030, 0x007d , 0x0000 }; /* {0} */
  270. static const char16_t sub1[4] = { 0x007b, 0x0031, 0x007d , 0x0000 }; /* {1} */
  271. static const int32_t subLen = 3;
  272. if (U_FAILURE(*status))
  273. return 0;
  274. separatorBundle = ures_getByKey(uld->langBundle, "localeDisplayPattern", nullptr, &localStatus);
  275. if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
  276. localStatus = U_MISSING_RESOURCE_ERROR;
  277. }
  278. if (localStatus != U_ZERO_ERROR) {
  279. *status = localStatus;
  280. }
  281. if (U_FAILURE(*status)){
  282. ures_close(separatorBundle);
  283. return 0;
  284. }
  285. separator = ures_getStringByKey(separatorBundle, "separator", &len, &localStatus);
  286. ures_close(separatorBundle);
  287. if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
  288. localStatus = U_MISSING_RESOURCE_ERROR;
  289. }
  290. if (localStatus != U_ZERO_ERROR) {
  291. *status = localStatus;
  292. }
  293. if (U_FAILURE(*status)){
  294. return 0;
  295. }
  296. /* For backwards compatibility, if we have a pattern, return the portion between {0} and {1} */
  297. p0=u_strstr(separator, sub0);
  298. p1=u_strstr(separator, sub1);
  299. if (p0!=nullptr && p1!=nullptr && p0<=p1) {
  300. separator = (const char16_t *)p0 + subLen;
  301. len = static_cast<int32_t>(p1 - separator);
  302. /* Desired separator is no longer zero-terminated; handle that if necessary */
  303. if (len < resultCapacity) {
  304. u_strncpy(result, separator, len);
  305. result[len] = 0;
  306. return len;
  307. }
  308. }
  309. u_strncpy(result, separator, resultCapacity);
  310. return len;
  311. }