testsuite_character.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. // -*- C++ -*-
  2. // Testing character type and state type with char_traits and codecvt
  3. // specializations for the C++ library testsuite.
  4. //
  5. // Copyright (C) 2003-2022 Free Software Foundation, Inc.
  6. //
  7. // This file is part of the GNU ISO C++ Library. This library is free
  8. // software; you can redistribute it and/or modify it under the
  9. // terms of the GNU General Public License as published by the
  10. // Free Software Foundation; either version 3, or (at your option)
  11. // any later version.
  12. //
  13. // This library is distributed in the hope that it will be useful,
  14. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. // GNU General Public License for more details.
  17. //
  18. // You should have received a copy of the GNU General Public License along
  19. // with this library; see the file COPYING3. If not see
  20. // <http://www.gnu.org/licenses/>.
  21. //
  22. #ifndef _GLIBCXX_TESTSUITE_CHARACTER_H
  23. #define _GLIBCXX_TESTSUITE_CHARACTER_H
  24. #include <climits>
  25. #include <string> // for char_traits
  26. #include <locale> // for codecvt
  27. #include <algorithm> // for transform
  28. #include <ext/pod_char_traits.h>
  29. namespace __gnu_test
  30. {
  31. struct pod_int
  32. {
  33. int value;
  34. #if __cplusplus >= 201103L
  35. // For std::iota.
  36. pod_int&
  37. operator++()
  38. {
  39. ++value;
  40. return *this;
  41. }
  42. #endif
  43. };
  44. // For 20.1 requirements for instantiable type: equality comparable
  45. // and less than comparable.
  46. inline bool
  47. operator==(const pod_int& lhs, const pod_int& rhs)
  48. { return lhs.value == rhs.value; }
  49. inline bool
  50. operator<(const pod_int& lhs, const pod_int& rhs)
  51. { return lhs.value < rhs.value; }
  52. // For 26 numeric algorithms requirements, need addable,
  53. // subtractable, multiplicable.
  54. inline pod_int
  55. operator+(const pod_int& lhs, const pod_int& rhs)
  56. {
  57. pod_int ret = { lhs.value + rhs.value };
  58. return ret;
  59. }
  60. inline pod_int
  61. operator-(const pod_int& lhs, const pod_int& rhs)
  62. {
  63. pod_int ret = { lhs.value - rhs.value };
  64. return ret;
  65. }
  66. inline pod_int
  67. operator*(const pod_int& lhs, const pod_int& rhs)
  68. {
  69. pod_int ret = { lhs.value * rhs.value };
  70. return ret;
  71. }
  72. struct pod_state
  73. {
  74. unsigned long value;
  75. };
  76. inline bool
  77. operator==(const pod_state& lhs, const pod_state& rhs)
  78. { return lhs.value == rhs.value; }
  79. inline bool
  80. operator<(const pod_state& lhs, const pod_state& rhs)
  81. { return lhs.value < rhs.value; }
  82. // Alternate character types.
  83. using __gnu_cxx::character;
  84. typedef character<unsigned char, pod_int, pod_state> pod_char;
  85. typedef character<unsigned char, unsigned int, pod_state> pod_uchar;
  86. typedef character<unsigned short, unsigned int> pod_ushort;
  87. typedef character<unsigned int, unsigned long> pod_uint;
  88. }
  89. namespace __gnu_cxx
  90. {
  91. // Specializations.
  92. // pod_char
  93. template<>
  94. template<typename V2>
  95. inline __gnu_test::pod_char::char_type
  96. __gnu_test::pod_char::char_type::from(const V2& v)
  97. {
  98. char_type ret = { static_cast<value_type>(v.value) };
  99. return ret;
  100. }
  101. template<>
  102. template<typename V2>
  103. inline V2
  104. __gnu_test::pod_char::char_type::to(const char_type& c)
  105. {
  106. V2 ret = { c.value };
  107. return ret;
  108. }
  109. template<>
  110. template<typename V2>
  111. inline __gnu_test::pod_uchar::char_type
  112. __gnu_test::pod_uchar::char_type::from(const V2& v)
  113. {
  114. char_type ret;
  115. ret.value = (v >> 5);
  116. return ret;
  117. }
  118. template<>
  119. template<typename V2>
  120. inline V2
  121. __gnu_test::pod_uchar::char_type::to(const char_type& c)
  122. { return static_cast<V2>(c.value << 5); }
  123. } // namespace __gnu_cxx
  124. namespace std
  125. {
  126. // codecvt specialization
  127. //
  128. // The conversion performed by the specialization is not supposed to
  129. // be useful, rather it has been designed to demonstrate the
  130. // essential features of stateful conversions:
  131. // * Number and value of bytes for each internal character depends on the
  132. // state in addition to the character itself.
  133. // * Unshift produces an unshift sequence and resets the state. On input
  134. // the unshift sequence causes the state to be reset.
  135. //
  136. // The conversion for output is as follows:
  137. // 1. Calculate the value tmp by xor-ing the state and the internal
  138. // character
  139. // 2. Split tmp into either two or three bytes depending on the value of
  140. // state. Output those bytes.
  141. // 3. tmp becomes the new value of state.
  142. template<>
  143. class codecvt<__gnu_test::pod_uchar, char, __gnu_test::pod_state>
  144. : public __codecvt_abstract_base<__gnu_test::pod_uchar, char,
  145. __gnu_test::pod_state>
  146. {
  147. public:
  148. typedef codecvt_base::result result;
  149. typedef __gnu_test::pod_uchar intern_type;
  150. typedef char extern_type;
  151. typedef __gnu_test::pod_state state_type;
  152. typedef __codecvt_abstract_base<intern_type, extern_type, state_type>
  153. base_type;
  154. explicit codecvt(size_t refs = 0) : base_type(refs)
  155. { }
  156. static locale::id id;
  157. protected:
  158. ~codecvt()
  159. { }
  160. virtual result
  161. do_out(state_type& state, const intern_type* from,
  162. const intern_type* from_end, const intern_type*& from_next,
  163. extern_type* to, extern_type* to_limit,
  164. extern_type*& to_next) const
  165. {
  166. while (from < from_end && to < to_limit)
  167. {
  168. unsigned char tmp = (state.value ^ from->value);
  169. if (state.value & 0x8)
  170. {
  171. if (to >= to_limit - 2)
  172. break;
  173. *to++ = (tmp & 0x7);
  174. *to++ = ((tmp >> 3) & 0x7);
  175. *to++ = ((tmp >> 6) & 0x3);
  176. }
  177. else
  178. {
  179. if (to >= to_limit - 1)
  180. break;
  181. *to++ = (tmp & 0xf);
  182. *to++ = ((tmp >> 4) & 0xf);
  183. }
  184. state.value = tmp;
  185. ++from;
  186. }
  187. from_next = from;
  188. to_next = to;
  189. return (from < from_end) ? partial : ok;
  190. }
  191. virtual result
  192. do_in(state_type& state, const extern_type* from,
  193. const extern_type* from_end, const extern_type*& from_next,
  194. intern_type* to, intern_type* to_limit,
  195. intern_type*& to_next) const
  196. {
  197. while (from < from_end && to < to_limit)
  198. {
  199. unsigned char c = *from;
  200. if (c & 0xc0)
  201. {
  202. // Unshift sequence
  203. state.value &= c;
  204. ++from;
  205. continue;
  206. }
  207. unsigned char tmp;
  208. if (state.value & 0x8)
  209. {
  210. if (from >= from_end - 2)
  211. break;
  212. tmp = (*from++ & 0x7);
  213. tmp |= ((*from++ << 3) & 0x38);
  214. tmp |= ((*from++ << 6) & 0xc0);
  215. }
  216. else
  217. {
  218. if (from >= from_end - 1)
  219. break;
  220. tmp = (*from++ & 0xf);
  221. tmp |= ((*from++ << 4) & 0xf0);
  222. }
  223. to->value = (tmp ^ state.value);
  224. state.value = tmp;
  225. ++to;
  226. }
  227. from_next = from;
  228. to_next = to;
  229. return (from < from_end) ? partial : ok;
  230. }
  231. virtual result
  232. do_unshift(state_type& state, extern_type* to, extern_type* to_limit,
  233. extern_type*& to_next) const
  234. {
  235. for (unsigned int i = 0; i < CHAR_BIT; ++i)
  236. {
  237. unsigned int mask = (1 << i);
  238. if (state.value & mask)
  239. {
  240. if (to == to_limit)
  241. {
  242. to_next = to;
  243. return partial;
  244. }
  245. state.value &= ~mask;
  246. *to++ = static_cast<unsigned char>(~mask);
  247. }
  248. }
  249. to_next = to;
  250. return state.value == 0 ? ok : error;
  251. }
  252. virtual int
  253. do_encoding() const throw()
  254. { return -1; }
  255. virtual bool
  256. do_always_noconv() const throw()
  257. { return false; }
  258. virtual int
  259. do_length(state_type& state, const extern_type* from,
  260. const extern_type* end, size_t max) const
  261. {
  262. const extern_type* beg = from;
  263. while (from < end)
  264. {
  265. unsigned char c = *from;
  266. if (c & 0xc0)
  267. {
  268. // Unshift sequence
  269. state.value &= c;
  270. ++from;
  271. continue;
  272. }
  273. if (max == 0) break;
  274. unsigned char tmp;
  275. if (state.value & 0x8)
  276. {
  277. if (from >= end - 2)
  278. break;
  279. tmp = (*from++ & 0x7);
  280. tmp |= ((*from++ << 3) & 0x38);
  281. tmp |= ((*from++ << 6) & 0xc0);
  282. }
  283. else
  284. {
  285. if (from >= end - 1)
  286. break;
  287. tmp = (*from++ & 0xf);
  288. tmp |= ((*from++ << 4) & 0xf0);
  289. }
  290. state.value = tmp;
  291. --max;
  292. }
  293. return from - beg;
  294. }
  295. // Maximum 8 bytes unshift sequence followed by max 3 bytes for
  296. // one character.
  297. virtual int
  298. do_max_length() const throw()
  299. { return 11; }
  300. };
  301. template<>
  302. class ctype<__gnu_test::pod_uchar>
  303. : public __ctype_abstract_base<__gnu_test::pod_uchar>
  304. {
  305. public:
  306. typedef __gnu_test::pod_uchar char_type;
  307. explicit ctype(size_t refs = 0)
  308. : __ctype_abstract_base<__gnu_test::pod_uchar>(refs) { }
  309. static locale::id id;
  310. protected:
  311. ~ctype()
  312. { }
  313. virtual bool
  314. do_is(mask, char_type) const
  315. { return false; }
  316. virtual const char_type*
  317. do_is(const char_type* low, const char_type* high, mask* vec) const
  318. {
  319. fill_n(vec, high - low, mask());
  320. return high;
  321. }
  322. virtual const char_type*
  323. do_scan_is(mask, const char_type*, const char_type* high) const
  324. { return high; }
  325. virtual const char_type*
  326. do_scan_not(mask, const char_type* low, const char_type*) const
  327. { return low; }
  328. virtual char_type
  329. do_toupper(char_type c) const
  330. { return c; }
  331. virtual const char_type*
  332. do_toupper(char_type*, const char_type* high) const
  333. { return high; }
  334. virtual char_type
  335. do_tolower(char_type c) const
  336. { return c; }
  337. virtual const char_type*
  338. do_tolower(char_type*, const char_type* high) const
  339. { return high; }
  340. virtual char_type
  341. do_widen(char c) const
  342. { return __gnu_test::pod_uchar::from<char>(c); }
  343. virtual const char*
  344. do_widen(const char* low, const char* high, char_type* dest) const
  345. {
  346. transform(low, high, dest, &__gnu_test::pod_uchar::from<char>);
  347. return high;
  348. }
  349. virtual char
  350. do_narrow(char_type, char dfault) const
  351. { return dfault; }
  352. virtual const char_type*
  353. do_narrow(const char_type* low, const char_type* high,
  354. char dfault, char* dest) const
  355. {
  356. fill_n(dest, high - low, dfault);
  357. return high;
  358. }
  359. };
  360. // numpunct specializations
  361. template<>
  362. class numpunct<__gnu_test::pod_uint>
  363. : public locale::facet
  364. {
  365. public:
  366. typedef __gnu_test::pod_uint char_type;
  367. typedef basic_string<char_type> string_type;
  368. static locale::id id;
  369. explicit
  370. numpunct(size_t refs = 0)
  371. : locale::facet(refs)
  372. { }
  373. char_type
  374. decimal_point() const
  375. { return this->do_decimal_point(); }
  376. char_type
  377. thousands_sep() const
  378. { return this->do_thousands_sep(); }
  379. string
  380. grouping() const
  381. { return this->do_grouping(); }
  382. string_type
  383. truename() const
  384. { return this->do_truename(); }
  385. string_type
  386. falsename() const
  387. { return this->do_falsename(); }
  388. protected:
  389. ~numpunct()
  390. { }
  391. virtual char_type
  392. do_decimal_point() const
  393. { return char_type(); }
  394. virtual char_type
  395. do_thousands_sep() const
  396. { return char_type(); }
  397. virtual string
  398. do_grouping() const
  399. { return string(); }
  400. virtual string_type
  401. do_truename() const
  402. { return string_type(); }
  403. virtual string_type
  404. do_falsename() const
  405. { return string_type(); }
  406. };
  407. template<>
  408. class moneypunct<__gnu_test::pod_uint>
  409. : public locale::facet, public money_base
  410. {
  411. public:
  412. typedef __gnu_test::pod_uint char_type;
  413. typedef basic_string<char_type> string_type;
  414. static locale::id id;
  415. static const bool intl = false;
  416. explicit
  417. moneypunct(size_t refs = 0)
  418. : locale::facet(refs)
  419. { }
  420. char_type
  421. decimal_point() const
  422. { return this->do_decimal_point(); }
  423. char_type
  424. thousands_sep() const
  425. { return this->do_thousands_sep(); }
  426. string
  427. grouping() const
  428. { return this->do_grouping(); }
  429. string_type
  430. curr_symbol() const
  431. { return this->do_curr_symbol(); }
  432. string_type
  433. positive_sign() const
  434. { return this->do_positive_sign(); }
  435. string_type
  436. negative_sign() const
  437. { return this->do_negative_sign(); }
  438. int
  439. frac_digits() const
  440. { return this->do_frac_digits(); }
  441. pattern
  442. pos_format() const
  443. { return this->do_pos_format(); }
  444. pattern
  445. neg_format() const
  446. { return this->do_neg_format(); }
  447. protected:
  448. ~moneypunct()
  449. { }
  450. virtual char_type
  451. do_decimal_point() const
  452. { return char_type(); }
  453. virtual char_type
  454. do_thousands_sep() const
  455. { return char_type(); }
  456. virtual string
  457. do_grouping() const
  458. { return string(); }
  459. virtual string_type
  460. do_curr_symbol() const
  461. { return string_type(); }
  462. string_type
  463. do_positive_sign() const
  464. { return string_type(); }
  465. string_type
  466. do_negative_sign() const
  467. { return string_type(); }
  468. int
  469. do_frac_digits() const
  470. { return 0; }
  471. pattern
  472. do_pos_format() const
  473. { return pattern(); }
  474. pattern
  475. do_neg_format() const
  476. { return pattern(); }
  477. };
  478. } // namespace std
  479. #endif // _GLIBCXX_TESTSUITE_CHARACTER_H