PageRenderTime 35ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/Src/Dependencies/Boost/libs/iostreams/test/detail/null_padded_codecvt.hpp

http://hadesmem.googlecode.com/
C++ Header | 275 lines | 220 code | 31 blank | 24 comment | 82 complexity | 0490e78fe65b7b5837170922b618822d MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.0, Apache-2.0, LGPL-3.0
  1. // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
  2. // (C) Copyright 2004-2007 Jonathan Turkanis
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
  5. // See http://www.boost.org/libs/iostreams for documentation.
  6. // Contains the definitions of two codecvt facets useful for testing code
  7. // conversion. Both represent the "null padded" character encoding described as
  8. // follows. A wide character can be represented by the encoding if its value V
  9. // is within the range of an unsigned char. The first char of the sequence
  10. // representing V is V % 3 + 1. This is followed by V % 3 null characters, and
  11. // finally by V itself.
  12. // The first codecvt facet, null_padded_codecvt, is statefull, with state_type
  13. // equal to int.
  14. // The second codecvt facet, stateless_null_padded_codecvt, is stateless. At
  15. // each point in a conversion, no characters are consumed unless there is room
  16. // in the output sequence to write an entire multibyte sequence.
  17. #ifndef BOOST_IOSTREAMS_TEST_NULL_PADDED_CODECVT_HPP_INCLUDED
  18. #define BOOST_IOSTREAMS_TEST_NULL_PADDED_CODECVT_HPP_INCLUDED
  19. #include <boost/config.hpp> // NO_STDC_NAMESPACE
  20. #include <boost/iostreams/detail/codecvt_helper.hpp>
  21. #include <boost/iostreams/detail/config/wide_streams.hpp>
  22. #include <cstddef> // mbstate_t.
  23. #include <locale> // codecvt.
  24. #include <boost/integer_traits.hpp> // const_max.
  25. #ifdef BOOST_NO_STDC_NAMESPACE
  26. namespace std { using ::mbstate_t; }
  27. #endif
  28. namespace boost { namespace iostreams { namespace test {
  29. //------------------Definition of null_padded_codecvt_state-------------------//
  30. class null_padded_codecvt_state {
  31. public:
  32. null_padded_codecvt_state(int val = 0) : val_(val) { }
  33. operator int() const { return val_; }
  34. int& val() { return val_; }
  35. const int& val() const { return val_; }
  36. private:
  37. int val_;
  38. };
  39. } } }
  40. BOOST_IOSTREAMS_CODECVT_SPEC(boost::iostreams::test::null_padded_codecvt_state)
  41. namespace boost { namespace iostreams { namespace test {
  42. //------------------Definition of null_padded_codevt--------------------------//
  43. //
  44. // state is initially 0. After a single character is consumed, state is set to
  45. // the number of characters in the current multibyte sequence and decremented
  46. // as each character is consumed until its value reaches 0 again.
  47. //
  48. class null_padded_codecvt
  49. : public iostreams::detail::codecvt_helper<
  50. wchar_t, char, null_padded_codecvt_state
  51. >
  52. {
  53. public:
  54. typedef null_padded_codecvt_state state_type;
  55. private:
  56. std::codecvt_base::result
  57. do_in( state_type& state, const char* first1, const char* last1,
  58. const char*& next1, wchar_t* first2, wchar_t* last2,
  59. wchar_t*& next2 ) const
  60. {
  61. using namespace std;
  62. if (state < 0 || state > 3)
  63. return codecvt_base::error;
  64. next1 = first1;
  65. next2 = first2;
  66. while (next2 != last2 && next1 != last1) {
  67. while (next1 != last1) {
  68. if (state == 0) {
  69. if (*next1 < 1 || *next1 > 3)
  70. return codecvt_base::error;
  71. state = *next1++;
  72. } else if (state == 1) {
  73. *next2++ = (unsigned char) *next1++;
  74. state = 0;
  75. break;
  76. } else {
  77. if (*next1++ != 0)
  78. return codecvt_base::error;
  79. --state.val();
  80. }
  81. }
  82. }
  83. return next2 == last2 ?
  84. codecvt_base::ok :
  85. codecvt_base::partial;
  86. }
  87. std::codecvt_base::result
  88. do_out( state_type& state, const wchar_t* first1, const wchar_t* last1,
  89. const wchar_t*& next1, char* first2, char* last2,
  90. char*& next2 ) const
  91. {
  92. using namespace std;
  93. if (state < 0 || state > 3)
  94. return codecvt_base::error;
  95. next1 = first1;
  96. next2 = first2;
  97. while (next1 != last1 && next2 != last2) {
  98. while (next2 != last2) {
  99. if (state == 0) {
  100. if (*next1 > integer_traits<unsigned char>::const_max)
  101. return codecvt_base::noconv;
  102. state = *next1 % 3 + 1;
  103. *next2++ = static_cast<char>(state);
  104. } else if (state == 1) {
  105. state = 0;
  106. *next2++ = static_cast<unsigned char>(*next1++);
  107. break;
  108. } else {
  109. --state.val();
  110. *next2++ = 0;
  111. }
  112. }
  113. }
  114. return next1 == last1 ?
  115. codecvt_base::ok :
  116. codecvt_base::partial;
  117. }
  118. std::codecvt_base::result
  119. do_unshift( state_type& state,
  120. char* /* first2 */,
  121. char* last2,
  122. char*& next2 ) const
  123. {
  124. using namespace std;
  125. next2 = last2;
  126. while (state.val()-- > 0)
  127. if (next2 != last2)
  128. *next2++ = 0;
  129. else
  130. return codecvt_base::partial;
  131. return codecvt_base::ok;
  132. }
  133. bool do_always_noconv() const throw() { return false; }
  134. int do_max_length() const throw() { return 4; }
  135. int do_encoding() const throw() { return -1; }
  136. int do_length( BOOST_IOSTREAMS_CODECVT_CV_QUALIFIER state_type& state,
  137. const char* first1, const char* last1,
  138. std::size_t len2 ) const throw()
  139. { // Implementation should follow that of do_in().
  140. int st = state;
  141. std::size_t result = 0;
  142. const char* next1 = first1;
  143. while (result < len2 && next1 != last1) {
  144. while (next1 != last1) {
  145. if (st == 0) {
  146. if (*next1 < 1 || *next1 > 3)
  147. return static_cast<int>(result); // error.
  148. st = *next1++;
  149. } else if (st == 1) {
  150. ++result;
  151. st = 0;
  152. break;
  153. } else {
  154. if (*next1++ != 0)
  155. return static_cast<int>(result); // error.
  156. --st;
  157. }
  158. }
  159. }
  160. return static_cast<int>(result);
  161. }
  162. };
  163. //------------------Definition of stateless_null_padded_codevt----------------//
  164. class stateless_null_padded_codecvt
  165. : public std::codecvt<wchar_t, char, std::mbstate_t>
  166. {
  167. std::codecvt_base::result
  168. do_in( state_type&, const char* first1, const char* last1,
  169. const char*& next1, wchar_t* first2, wchar_t* last2,
  170. wchar_t*& next2 ) const
  171. {
  172. using namespace std;
  173. for ( next1 = first1, next2 = first2;
  174. next1 != last1 && next2 != last2; )
  175. {
  176. int len = (unsigned char) *next1;
  177. if (len < 1 || len > 3)
  178. return codecvt_base::error;
  179. if (last1 - next1 < len + 1)
  180. return codecvt_base::partial;
  181. ++next1;
  182. while (len-- > 1)
  183. if (*next1++ != 0)
  184. return codecvt_base::error;
  185. *next2++ = (unsigned char) *next1++;
  186. }
  187. return next1 == last1 && next2 == last2 ?
  188. codecvt_base::ok :
  189. codecvt_base::partial;
  190. }
  191. std::codecvt_base::result
  192. do_out( state_type&, const wchar_t* first1, const wchar_t* last1,
  193. const wchar_t*& next1, char* first2, char* last2,
  194. char*& next2 ) const
  195. {
  196. using namespace std;
  197. for ( next1 = first1, next2 = first2;
  198. next1 != last1 && next2 != last2; )
  199. {
  200. if (*next1 > integer_traits<unsigned char>::const_max)
  201. return codecvt_base::noconv;
  202. int skip = *next1 % 3 + 2;
  203. if (last2 - next2 < skip)
  204. return codecvt_base::partial;
  205. *next2++ = static_cast<char>(--skip);
  206. while (skip-- > 1)
  207. *next2++ = 0;
  208. *next2++ = (unsigned char) *next1++;
  209. }
  210. return codecvt_base::ok;
  211. }
  212. std::codecvt_base::result
  213. do_unshift( state_type&,
  214. char* /* first2 */,
  215. char* /* last2 */,
  216. char*& /* next2 */ ) const
  217. {
  218. return std::codecvt_base::ok;
  219. }
  220. bool do_always_noconv() const throw() { return false; }
  221. int do_max_length() const throw() { return 4; }
  222. int do_encoding() const throw() { return -1; }
  223. int do_length( BOOST_IOSTREAMS_CODECVT_CV_QUALIFIER state_type&,
  224. const char* first1, const char* last1,
  225. std::size_t len2 ) const throw()
  226. { // Implementation should follow that of do_in().
  227. std::size_t result = 0;
  228. for ( const char* next1 = first1;
  229. next1 != last1 && result < len2; ++result)
  230. {
  231. int len = (unsigned char) *next1;
  232. if (len < 1 || len > 3 || last1 - next1 < len + 1)
  233. return static_cast<int>(result); // error.
  234. ++next1;
  235. while (len-- > 1)
  236. if (*next1++ != 0)
  237. return static_cast<int>(result); // error.
  238. ++next1;
  239. }
  240. return static_cast<int>(result);
  241. }
  242. };
  243. } } } // End namespaces detail, iostreams, boost.
  244. #endif // #ifndef BOOST_IOSTREAMS_TEST_NULL_PADDED_CODECVT_HPP_INCLUDED