umsg.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708
  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) 1999-2012, International Business Machines
  7. * Corporation and others. All Rights Reserved.
  8. *
  9. *******************************************************************************
  10. * file name: umsg.cpp
  11. * encoding: UTF-8
  12. * tab size: 8 (not used)
  13. * indentation:4
  14. *
  15. * This is a C wrapper to MessageFormat C++ API.
  16. *
  17. * Change history:
  18. *
  19. * 08/5/2001 Ram Added C wrappers for C++ API. Changed implementation of old API's
  20. * Removed pattern parser.
  21. *
  22. */
  23. #include "unicode/utypes.h"
  24. #if !UCONFIG_NO_FORMATTING
  25. #include "unicode/umsg.h"
  26. #include "unicode/ustring.h"
  27. #include "unicode/fmtable.h"
  28. #include "unicode/msgfmt.h"
  29. #include "unicode/unistr.h"
  30. #include "cpputils.h"
  31. #include "uassert.h"
  32. #include "ustr_imp.h"
  33. U_NAMESPACE_BEGIN
  34. /**
  35. * This class isolates our access to private internal methods of
  36. * MessageFormat. It is never instantiated; it exists only for C++
  37. * access management.
  38. */
  39. class MessageFormatAdapter {
  40. public:
  41. static const Formattable::Type* getArgTypeList(const MessageFormat& m,
  42. int32_t& count);
  43. static UBool hasArgTypeConflicts(const MessageFormat& m) {
  44. return m.hasArgTypeConflicts;
  45. }
  46. };
  47. const Formattable::Type*
  48. MessageFormatAdapter::getArgTypeList(const MessageFormat& m,
  49. int32_t& count) {
  50. return m.getArgTypeList(count);
  51. }
  52. U_NAMESPACE_END
  53. U_NAMESPACE_USE
  54. U_CAPI int32_t
  55. u_formatMessage(const char *locale,
  56. const char16_t *pattern,
  57. int32_t patternLength,
  58. char16_t *result,
  59. int32_t resultLength,
  60. UErrorCode *status,
  61. ...)
  62. {
  63. va_list ap;
  64. int32_t actLen;
  65. //argument checking deferred to subsequent method calls
  66. // start vararg processing
  67. va_start(ap, status);
  68. actLen = u_vformatMessage(locale,pattern,patternLength,result,resultLength,ap,status);
  69. // end vararg processing
  70. va_end(ap);
  71. return actLen;
  72. }
  73. U_CAPI int32_t U_EXPORT2
  74. u_vformatMessage( const char *locale,
  75. const char16_t *pattern,
  76. int32_t patternLength,
  77. char16_t *result,
  78. int32_t resultLength,
  79. va_list ap,
  80. UErrorCode *status)
  81. {
  82. //argument checking deferred to subsequent method calls
  83. UMessageFormat *fmt = umsg_open(pattern,patternLength,locale,nullptr,status);
  84. int32_t retVal = umsg_vformat(fmt,result,resultLength,ap,status);
  85. umsg_close(fmt);
  86. return retVal;
  87. }
  88. U_CAPI int32_t
  89. u_formatMessageWithError(const char *locale,
  90. const char16_t *pattern,
  91. int32_t patternLength,
  92. char16_t *result,
  93. int32_t resultLength,
  94. UParseError *parseError,
  95. UErrorCode *status,
  96. ...)
  97. {
  98. va_list ap;
  99. int32_t actLen;
  100. //argument checking deferred to subsequent method calls
  101. // start vararg processing
  102. va_start(ap, status);
  103. actLen = u_vformatMessageWithError(locale,pattern,patternLength,result,resultLength,parseError,ap,status);
  104. // end vararg processing
  105. va_end(ap);
  106. return actLen;
  107. }
  108. U_CAPI int32_t U_EXPORT2
  109. u_vformatMessageWithError( const char *locale,
  110. const char16_t *pattern,
  111. int32_t patternLength,
  112. char16_t *result,
  113. int32_t resultLength,
  114. UParseError *parseError,
  115. va_list ap,
  116. UErrorCode *status)
  117. {
  118. //argument checking deferred to subsequent method calls
  119. UMessageFormat *fmt = umsg_open(pattern,patternLength,locale,parseError,status);
  120. int32_t retVal = umsg_vformat(fmt,result,resultLength,ap,status);
  121. umsg_close(fmt);
  122. return retVal;
  123. }
  124. // For parse, do the reverse of format:
  125. // 1. Call through to the C++ APIs
  126. // 2. Just assume the user passed in enough arguments.
  127. // 3. Iterate through each formattable returned, and assign to the arguments
  128. U_CAPI void
  129. u_parseMessage( const char *locale,
  130. const char16_t *pattern,
  131. int32_t patternLength,
  132. const char16_t *source,
  133. int32_t sourceLength,
  134. UErrorCode *status,
  135. ...)
  136. {
  137. va_list ap;
  138. //argument checking deferred to subsequent method calls
  139. // start vararg processing
  140. va_start(ap, status);
  141. u_vparseMessage(locale,pattern,patternLength,source,sourceLength,ap,status);
  142. // end vararg processing
  143. va_end(ap);
  144. }
  145. U_CAPI void U_EXPORT2
  146. u_vparseMessage(const char *locale,
  147. const char16_t *pattern,
  148. int32_t patternLength,
  149. const char16_t *source,
  150. int32_t sourceLength,
  151. va_list ap,
  152. UErrorCode *status)
  153. {
  154. //argument checking deferred to subsequent method calls
  155. UMessageFormat *fmt = umsg_open(pattern,patternLength,locale,nullptr,status);
  156. int32_t count = 0;
  157. umsg_vparse(fmt,source,sourceLength,&count,ap,status);
  158. umsg_close(fmt);
  159. }
  160. U_CAPI void
  161. u_parseMessageWithError(const char *locale,
  162. const char16_t *pattern,
  163. int32_t patternLength,
  164. const char16_t *source,
  165. int32_t sourceLength,
  166. UParseError *error,
  167. UErrorCode *status,
  168. ...)
  169. {
  170. va_list ap;
  171. //argument checking deferred to subsequent method calls
  172. // start vararg processing
  173. va_start(ap, status);
  174. u_vparseMessageWithError(locale,pattern,patternLength,source,sourceLength,ap,error,status);
  175. // end vararg processing
  176. va_end(ap);
  177. }
  178. U_CAPI void U_EXPORT2
  179. u_vparseMessageWithError(const char *locale,
  180. const char16_t *pattern,
  181. int32_t patternLength,
  182. const char16_t *source,
  183. int32_t sourceLength,
  184. va_list ap,
  185. UParseError *error,
  186. UErrorCode* status)
  187. {
  188. //argument checking deferred to subsequent method calls
  189. UMessageFormat *fmt = umsg_open(pattern,patternLength,locale,error,status);
  190. int32_t count = 0;
  191. umsg_vparse(fmt,source,sourceLength,&count,ap,status);
  192. umsg_close(fmt);
  193. }
  194. //////////////////////////////////////////////////////////////////////////////////
  195. //
  196. // Message format C API
  197. //
  198. /////////////////////////////////////////////////////////////////////////////////
  199. U_CAPI UMessageFormat* U_EXPORT2
  200. umsg_open( const char16_t *pattern,
  201. int32_t patternLength,
  202. const char *locale,
  203. UParseError *parseError,
  204. UErrorCode *status)
  205. {
  206. //check arguments
  207. if(status==nullptr || U_FAILURE(*status))
  208. {
  209. return 0;
  210. }
  211. if(pattern==nullptr||patternLength<-1){
  212. *status=U_ILLEGAL_ARGUMENT_ERROR;
  213. return 0;
  214. }
  215. UParseError tErr;
  216. if(parseError==nullptr)
  217. {
  218. parseError = &tErr;
  219. }
  220. int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength);
  221. UnicodeString patString(patternLength == -1, pattern, len);
  222. MessageFormat* retVal = new MessageFormat(patString,Locale(locale),*parseError,*status);
  223. if(retVal == nullptr) {
  224. *status = U_MEMORY_ALLOCATION_ERROR;
  225. return nullptr;
  226. }
  227. if (U_SUCCESS(*status) && MessageFormatAdapter::hasArgTypeConflicts(*retVal)) {
  228. *status = U_ARGUMENT_TYPE_MISMATCH;
  229. }
  230. return (UMessageFormat*)retVal;
  231. }
  232. U_CAPI void U_EXPORT2
  233. umsg_close(UMessageFormat* format)
  234. {
  235. //check arguments
  236. if(format==nullptr){
  237. return;
  238. }
  239. delete (MessageFormat*) format;
  240. }
  241. U_CAPI UMessageFormat U_EXPORT2
  242. umsg_clone(const UMessageFormat *fmt,
  243. UErrorCode *status)
  244. {
  245. //check arguments
  246. if(status==nullptr || U_FAILURE(*status)){
  247. return nullptr;
  248. }
  249. if(fmt==nullptr){
  250. *status = U_ILLEGAL_ARGUMENT_ERROR;
  251. return nullptr;
  252. }
  253. UMessageFormat retVal = (UMessageFormat)((MessageFormat*)fmt)->clone();
  254. if(retVal == 0) {
  255. *status = U_MEMORY_ALLOCATION_ERROR;
  256. return 0;
  257. }
  258. return retVal;
  259. }
  260. U_CAPI void U_EXPORT2
  261. umsg_setLocale(UMessageFormat *fmt, const char* locale)
  262. {
  263. //check arguments
  264. if(fmt==nullptr){
  265. return;
  266. }
  267. ((MessageFormat*)fmt)->setLocale(Locale(locale));
  268. }
  269. U_CAPI const char* U_EXPORT2
  270. umsg_getLocale(const UMessageFormat *fmt)
  271. {
  272. //check arguments
  273. if(fmt==nullptr){
  274. return "";
  275. }
  276. return ((const MessageFormat*)fmt)->getLocale().getName();
  277. }
  278. U_CAPI void U_EXPORT2
  279. umsg_applyPattern(UMessageFormat *fmt,
  280. const char16_t* pattern,
  281. int32_t patternLength,
  282. UParseError* parseError,
  283. UErrorCode* status)
  284. {
  285. //check arguments
  286. UParseError tErr;
  287. if(status ==nullptr||U_FAILURE(*status)){
  288. return ;
  289. }
  290. if(fmt==nullptr || (pattern==nullptr && patternLength!=0) || patternLength<-1) {
  291. *status=U_ILLEGAL_ARGUMENT_ERROR;
  292. return ;
  293. }
  294. if(parseError==nullptr){
  295. parseError = &tErr;
  296. }
  297. // UnicodeString(pattern, -1) calls u_strlen().
  298. ((MessageFormat*)fmt)->applyPattern(UnicodeString(pattern,patternLength),*parseError,*status);
  299. }
  300. U_CAPI int32_t U_EXPORT2
  301. umsg_toPattern(const UMessageFormat *fmt,
  302. char16_t* result,
  303. int32_t resultLength,
  304. UErrorCode* status)
  305. {
  306. //check arguments
  307. if(status ==nullptr||U_FAILURE(*status)){
  308. return -1;
  309. }
  310. if(fmt==nullptr||resultLength<0 || (resultLength>0 && result==0)){
  311. *status=U_ILLEGAL_ARGUMENT_ERROR;
  312. return -1;
  313. }
  314. UnicodeString res;
  315. if(!(result==nullptr && resultLength==0)) {
  316. // nullptr destination for pure preflighting: empty dummy string
  317. // otherwise, alias the destination buffer
  318. res.setTo(result, 0, resultLength);
  319. }
  320. ((const MessageFormat*)fmt)->toPattern(res);
  321. return res.extract(result, resultLength, *status);
  322. }
  323. U_CAPI int32_t
  324. umsg_format( const UMessageFormat *fmt,
  325. char16_t *result,
  326. int32_t resultLength,
  327. UErrorCode *status,
  328. ...)
  329. {
  330. va_list ap;
  331. int32_t actLen;
  332. //argument checking deferred to last method call umsg_vformat which
  333. //saves time when arguments are valid and we don't care when arguments are not
  334. //since we return an error anyway
  335. // start vararg processing
  336. va_start(ap, status);
  337. actLen = umsg_vformat(fmt,result,resultLength,ap,status);
  338. // end vararg processing
  339. va_end(ap);
  340. return actLen;
  341. }
  342. U_CAPI int32_t U_EXPORT2
  343. umsg_vformat( const UMessageFormat *fmt,
  344. char16_t *result,
  345. int32_t resultLength,
  346. va_list ap,
  347. UErrorCode *status)
  348. {
  349. //check arguments
  350. if(status==0 || U_FAILURE(*status))
  351. {
  352. return -1;
  353. }
  354. if(fmt==nullptr||resultLength<0 || (resultLength>0 && result==0)) {
  355. *status=U_ILLEGAL_ARGUMENT_ERROR;
  356. return -1;
  357. }
  358. int32_t count =0;
  359. const Formattable::Type* argTypes =
  360. MessageFormatAdapter::getArgTypeList(*(const MessageFormat*)fmt, count);
  361. // Allocate at least one element. Allocating an array of length
  362. // zero causes problems on some platforms (e.g. Win32).
  363. Formattable* args = new Formattable[count ? count : 1];
  364. // iterate through the vararg list, and get the arguments out
  365. for(int32_t i = 0; i < count; ++i) {
  366. char16_t *stringVal;
  367. double tDouble=0;
  368. int32_t tInt =0;
  369. int64_t tInt64 = 0;
  370. UDate tempDate = 0;
  371. switch(argTypes[i]) {
  372. case Formattable::kDate:
  373. tempDate = va_arg(ap, UDate);
  374. args[i].setDate(tempDate);
  375. break;
  376. case Formattable::kDouble:
  377. tDouble =va_arg(ap, double);
  378. args[i].setDouble(tDouble);
  379. break;
  380. case Formattable::kLong:
  381. tInt = va_arg(ap, int32_t);
  382. args[i].setLong(tInt);
  383. break;
  384. case Formattable::kInt64:
  385. tInt64 = va_arg(ap, int64_t);
  386. args[i].setInt64(tInt64);
  387. break;
  388. case Formattable::kString:
  389. // For some reason, a temporary is needed
  390. stringVal = va_arg(ap, char16_t*);
  391. if(stringVal){
  392. args[i].setString(UnicodeString(stringVal));
  393. }else{
  394. *status=U_ILLEGAL_ARGUMENT_ERROR;
  395. }
  396. break;
  397. case Formattable::kArray:
  398. // throw away this argument
  399. // this is highly platform-dependent, and probably won't work
  400. // so, if you try to skip arguments in the list (and not use them)
  401. // you'll probably crash
  402. va_arg(ap, int);
  403. break;
  404. case Formattable::kObject:
  405. // Unused argument number. Read and ignore a pointer argument.
  406. va_arg(ap, void*);
  407. break;
  408. default:
  409. // Unknown/unsupported argument type.
  410. UPRV_UNREACHABLE_EXIT;
  411. }
  412. }
  413. UnicodeString resultStr;
  414. FieldPosition fieldPosition(FieldPosition::DONT_CARE);
  415. /* format the message */
  416. ((const MessageFormat*)fmt)->format(args,count,resultStr,fieldPosition,*status);
  417. delete[] args;
  418. if(U_FAILURE(*status)){
  419. return -1;
  420. }
  421. return resultStr.extract(result, resultLength, *status);
  422. }
  423. U_CAPI void
  424. umsg_parse( const UMessageFormat *fmt,
  425. const char16_t *source,
  426. int32_t sourceLength,
  427. int32_t *count,
  428. UErrorCode *status,
  429. ...)
  430. {
  431. va_list ap;
  432. //argument checking deferred to last method call umsg_vparse which
  433. //saves time when arguments are valid and we don't care when arguments are not
  434. //since we return an error anyway
  435. // start vararg processing
  436. va_start(ap, status);
  437. umsg_vparse(fmt,source,sourceLength,count,ap,status);
  438. // end vararg processing
  439. va_end(ap);
  440. }
  441. U_CAPI void U_EXPORT2
  442. umsg_vparse(const UMessageFormat *fmt,
  443. const char16_t *source,
  444. int32_t sourceLength,
  445. int32_t *count,
  446. va_list ap,
  447. UErrorCode *status)
  448. {
  449. //check arguments
  450. if(status==nullptr||U_FAILURE(*status))
  451. {
  452. return;
  453. }
  454. if(fmt==nullptr||source==nullptr || sourceLength<-1 || count==nullptr){
  455. *status=U_ILLEGAL_ARGUMENT_ERROR;
  456. return;
  457. }
  458. if(sourceLength==-1){
  459. sourceLength=u_strlen(source);
  460. }
  461. UnicodeString srcString(source,sourceLength);
  462. Formattable *args = ((const MessageFormat*)fmt)->parse(srcString,*count,*status);
  463. UDate *aDate;
  464. double *aDouble;
  465. char16_t *aString;
  466. int32_t* aInt;
  467. int64_t* aInt64;
  468. UnicodeString temp;
  469. int len =0;
  470. // assign formattables to varargs
  471. for(int32_t i = 0; i < *count; i++) {
  472. switch(args[i].getType()) {
  473. case Formattable::kDate:
  474. aDate = va_arg(ap, UDate*);
  475. if(aDate){
  476. *aDate = args[i].getDate();
  477. }else{
  478. *status=U_ILLEGAL_ARGUMENT_ERROR;
  479. }
  480. break;
  481. case Formattable::kDouble:
  482. aDouble = va_arg(ap, double*);
  483. if(aDouble){
  484. *aDouble = args[i].getDouble();
  485. }else{
  486. *status=U_ILLEGAL_ARGUMENT_ERROR;
  487. }
  488. break;
  489. case Formattable::kLong:
  490. aInt = va_arg(ap, int32_t*);
  491. if(aInt){
  492. *aInt = (int32_t) args[i].getLong();
  493. }else{
  494. *status=U_ILLEGAL_ARGUMENT_ERROR;
  495. }
  496. break;
  497. case Formattable::kInt64:
  498. aInt64 = va_arg(ap, int64_t*);
  499. if(aInt64){
  500. *aInt64 = args[i].getInt64();
  501. }else{
  502. *status=U_ILLEGAL_ARGUMENT_ERROR;
  503. }
  504. break;
  505. case Formattable::kString:
  506. aString = va_arg(ap, char16_t*);
  507. if(aString){
  508. args[i].getString(temp);
  509. len = temp.length();
  510. temp.extract(0,len,aString);
  511. aString[len]=0;
  512. }else{
  513. *status= U_ILLEGAL_ARGUMENT_ERROR;
  514. }
  515. break;
  516. case Formattable::kObject:
  517. // This will never happen because MessageFormat doesn't
  518. // support kObject. When MessageFormat is changed to
  519. // understand MeasureFormats, modify this code to do the
  520. // right thing. [alan]
  521. UPRV_UNREACHABLE_EXIT;
  522. // better not happen!
  523. case Formattable::kArray:
  524. UPRV_UNREACHABLE_EXIT;
  525. }
  526. }
  527. // clean up
  528. delete [] args;
  529. }
  530. #define SINGLE_QUOTE ((char16_t)0x0027)
  531. #define CURLY_BRACE_LEFT ((char16_t)0x007B)
  532. #define CURLY_BRACE_RIGHT ((char16_t)0x007D)
  533. #define STATE_INITIAL 0
  534. #define STATE_SINGLE_QUOTE 1
  535. #define STATE_IN_QUOTE 2
  536. #define STATE_MSG_ELEMENT 3
  537. #define MAppend(c) if (len < destCapacity) dest[len++] = c; else len++
  538. int32_t umsg_autoQuoteApostrophe(const char16_t* pattern,
  539. int32_t patternLength,
  540. char16_t* dest,
  541. int32_t destCapacity,
  542. UErrorCode* ec)
  543. {
  544. int32_t state = STATE_INITIAL;
  545. int32_t braceCount = 0;
  546. int32_t len = 0;
  547. if (ec == nullptr || U_FAILURE(*ec)) {
  548. return -1;
  549. }
  550. if (pattern == nullptr || patternLength < -1 || (dest == nullptr && destCapacity > 0)) {
  551. *ec = U_ILLEGAL_ARGUMENT_ERROR;
  552. return -1;
  553. }
  554. U_ASSERT(destCapacity >= 0);
  555. if (patternLength == -1) {
  556. patternLength = u_strlen(pattern);
  557. }
  558. for (int i = 0; i < patternLength; ++i) {
  559. char16_t c = pattern[i];
  560. switch (state) {
  561. case STATE_INITIAL:
  562. switch (c) {
  563. case SINGLE_QUOTE:
  564. state = STATE_SINGLE_QUOTE;
  565. break;
  566. case CURLY_BRACE_LEFT:
  567. state = STATE_MSG_ELEMENT;
  568. ++braceCount;
  569. break;
  570. }
  571. break;
  572. case STATE_SINGLE_QUOTE:
  573. switch (c) {
  574. case SINGLE_QUOTE:
  575. state = STATE_INITIAL;
  576. break;
  577. case CURLY_BRACE_LEFT:
  578. case CURLY_BRACE_RIGHT:
  579. state = STATE_IN_QUOTE;
  580. break;
  581. default:
  582. MAppend(SINGLE_QUOTE);
  583. state = STATE_INITIAL;
  584. break;
  585. }
  586. break;
  587. case STATE_IN_QUOTE:
  588. switch (c) {
  589. case SINGLE_QUOTE:
  590. state = STATE_INITIAL;
  591. break;
  592. }
  593. break;
  594. case STATE_MSG_ELEMENT:
  595. switch (c) {
  596. case CURLY_BRACE_LEFT:
  597. ++braceCount;
  598. break;
  599. case CURLY_BRACE_RIGHT:
  600. if (--braceCount == 0) {
  601. state = STATE_INITIAL;
  602. }
  603. break;
  604. }
  605. break;
  606. default: // Never happens.
  607. break;
  608. }
  609. U_ASSERT(len >= 0);
  610. MAppend(c);
  611. }
  612. // End of scan
  613. if (state == STATE_SINGLE_QUOTE || state == STATE_IN_QUOTE) {
  614. MAppend(SINGLE_QUOTE);
  615. }
  616. return u_terminateUChars(dest, destCapacity, len, ec);
  617. }
  618. #endif /* #if !UCONFIG_NO_FORMATTING */