encodings.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. #ifndef RAPIDJSON_ENCODINGS_H_
  2. #define RAPIDJSON_ENCODINGS_H_
  3. #include "rapidjson.h"
  4. namespace rapidjson {
  5. ///////////////////////////////////////////////////////////////////////////////
  6. // Encoding
  7. /*! \class rapidjson::Encoding
  8. \brief Concept for encoding of Unicode characters.
  9. \code
  10. concept Encoding {
  11. typename Ch; //! Type of character. A "character" is actually a code unit in unicode's definition.
  12. //! \brief Encode a Unicode codepoint to an output stream.
  13. //! \param os Output stream.
  14. //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively.
  15. template<typename OutputStream>
  16. static void Encode(OutputStream& os, unsigned codepoint);
  17. //! \brief Decode a Unicode codepoint from an input stream.
  18. //! \param is Input stream.
  19. //! \param codepoint Output of the unicode codepoint.
  20. //! \return true if a valid codepoint can be decoded from the stream.
  21. template <typename InputStream>
  22. static bool Decode(InputStream& is, unsigned* codepoint);
  23. //! \brief Validate one Unicode codepoint from an encoded stream.
  24. //! \param is Input stream to obtain codepoint.
  25. //! \param os Output for copying one codepoint.
  26. //! \return true if it is valid.
  27. //! \note This function just validating and copying the codepoint without actually decode it.
  28. template <typename InputStream, typename OutputStream>
  29. static bool Validate(InputStream& is, OutputStream& os);
  30. // The following functions are deal with byte streams.
  31. //! Take a character from input byte stream, skip BOM if exist.
  32. template <typename InputByteStream>
  33. static CharType TakeBOM(InputByteStream& is);
  34. //! Take a character from input byte stream.
  35. template <typename InputByteStream>
  36. static Ch Take(InputByteStream& is);
  37. //! Put BOM to output byte stream.
  38. template <typename OutputByteStream>
  39. static void PutBOM(OutputByteStream& os);
  40. //! Put a character to output byte stream.
  41. template <typename OutputByteStream>
  42. static void Put(OutputByteStream& os, Ch c);
  43. };
  44. \endcode
  45. */
  46. ///////////////////////////////////////////////////////////////////////////////
  47. // UTF8
  48. //! UTF-8 encoding.
  49. /*! http://en.wikipedia.org/wiki/UTF-8
  50. http://tools.ietf.org/html/rfc3629
  51. \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char.
  52. \implements Encoding
  53. */
  54. template<typename CharType = char>
  55. struct UTF8 {
  56. typedef CharType Ch;
  57. template<typename OutputStream>
  58. static void Encode(OutputStream& os, unsigned codepoint) {
  59. if (codepoint <= 0x7F)
  60. os.Put(codepoint & 0xFF);
  61. else if (codepoint <= 0x7FF) {
  62. os.Put(0xC0 | ((codepoint >> 6) & 0xFF));
  63. os.Put(0x80 | ((codepoint & 0x3F)));
  64. }
  65. else if (codepoint <= 0xFFFF) {
  66. os.Put(0xE0 | ((codepoint >> 12) & 0xFF));
  67. os.Put(0x80 | ((codepoint >> 6) & 0x3F));
  68. os.Put(0x80 | (codepoint & 0x3F));
  69. }
  70. else {
  71. RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
  72. os.Put(0xF0 | ((codepoint >> 18) & 0xFF));
  73. os.Put(0x80 | ((codepoint >> 12) & 0x3F));
  74. os.Put(0x80 | ((codepoint >> 6) & 0x3F));
  75. os.Put(0x80 | (codepoint & 0x3F));
  76. }
  77. }
  78. template <typename InputStream>
  79. static bool Decode(InputStream& is, unsigned* codepoint) {
  80. #define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | ((unsigned char)c & 0x3Fu)
  81. #define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0)
  82. #define TAIL() COPY(); TRANS(0x70)
  83. Ch c = is.Take();
  84. if (!(c & 0x80)) {
  85. *codepoint = (unsigned char)c;
  86. return true;
  87. }
  88. unsigned char type = GetRange((unsigned char)c);
  89. *codepoint = (0xFF >> type) & (unsigned char)c;
  90. bool result = true;
  91. switch (type) {
  92. case 2: TAIL(); return result;
  93. case 3: TAIL(); TAIL(); return result;
  94. case 4: COPY(); TRANS(0x50); TAIL(); return result;
  95. case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
  96. case 6: TAIL(); TAIL(); TAIL(); return result;
  97. case 10: COPY(); TRANS(0x20); TAIL(); return result;
  98. case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
  99. default: return false;
  100. }
  101. #undef COPY
  102. #undef TRANS
  103. #undef TAIL
  104. }
  105. template <typename InputStream, typename OutputStream>
  106. static bool Validate(InputStream& is, OutputStream& os) {
  107. #define COPY() os.Put(c = is.Take())
  108. #define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0)
  109. #define TAIL() COPY(); TRANS(0x70)
  110. Ch c;
  111. COPY();
  112. if (!(c & 0x80))
  113. return true;
  114. bool result = true;
  115. switch (GetRange((unsigned char)c)) {
  116. case 2: TAIL(); return result;
  117. case 3: TAIL(); TAIL(); return result;
  118. case 4: COPY(); TRANS(0x50); TAIL(); return result;
  119. case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
  120. case 6: TAIL(); TAIL(); TAIL(); return result;
  121. case 10: COPY(); TRANS(0x20); TAIL(); return result;
  122. case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
  123. default: return false;
  124. }
  125. #undef COPY
  126. #undef TRANS
  127. #undef TAIL
  128. }
  129. static unsigned char GetRange(unsigned char c) {
  130. // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
  131. // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types.
  132. static const unsigned char type[] = {
  133. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  134. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  135. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  136. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  137. 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
  138. 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
  139. 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
  140. 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
  141. 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
  142. 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
  143. };
  144. return type[c];
  145. }
  146. template <typename InputByteStream>
  147. static CharType TakeBOM(InputByteStream& is) {
  148. RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
  149. Ch c = Take(is);
  150. if ((unsigned char)c != 0xEFu) return c;
  151. c = is.Take();
  152. if ((unsigned char)c != 0xBBu) return c;
  153. c = is.Take();
  154. if ((unsigned char)c != 0xBFu) return c;
  155. c = is.Take();
  156. return c;
  157. }
  158. template <typename InputByteStream>
  159. static Ch Take(InputByteStream& is) {
  160. RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
  161. return is.Take();
  162. }
  163. template <typename OutputByteStream>
  164. static void PutBOM(OutputByteStream& os) {
  165. RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
  166. os.Put(0xEFu); os.Put(0xBBu); os.Put(0xBFu);
  167. }
  168. template <typename OutputByteStream>
  169. static void Put(OutputByteStream& os, Ch c) {
  170. RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
  171. os.Put(static_cast<typename OutputByteStream::Ch>(c));
  172. }
  173. };
  174. ///////////////////////////////////////////////////////////////////////////////
  175. // UTF16
  176. //! UTF-16 encoding.
  177. /*! http://en.wikipedia.org/wiki/UTF-16
  178. http://tools.ietf.org/html/rfc2781
  179. \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead.
  180. \implements Encoding
  181. \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
  182. For streaming, use UTF16LE and UTF16BE, which handle endianness.
  183. */
  184. template<typename CharType = wchar_t>
  185. struct UTF16 {
  186. typedef CharType Ch;
  187. RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);
  188. template<typename OutputStream>
  189. static void Encode(OutputStream& os, unsigned codepoint) {
  190. RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
  191. if (codepoint <= 0xFFFF) {
  192. RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
  193. os.Put(static_cast<typename OutputStream::Ch>(codepoint));
  194. }
  195. else {
  196. RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
  197. unsigned v = codepoint - 0x10000;
  198. os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
  199. os.Put((v & 0x3FF) | 0xDC00);
  200. }
  201. }
  202. template <typename InputStream>
  203. static bool Decode(InputStream& is, unsigned* codepoint) {
  204. RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
  205. Ch c = is.Take();
  206. if (c < 0xD800 || c > 0xDFFF) {
  207. *codepoint = c;
  208. return true;
  209. }
  210. else if (c <= 0xDBFF) {
  211. *codepoint = (c & 0x3FF) << 10;
  212. c = is.Take();
  213. *codepoint |= (c & 0x3FF);
  214. *codepoint += 0x10000;
  215. return c >= 0xDC00 && c <= 0xDFFF;
  216. }
  217. return false;
  218. }
  219. template <typename InputStream, typename OutputStream>
  220. static bool Validate(InputStream& is, OutputStream& os) {
  221. RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
  222. RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
  223. Ch c;
  224. os.Put(c = is.Take());
  225. if (c < 0xD800 || c > 0xDFFF)
  226. return true;
  227. else if (c <= 0xDBFF) {
  228. os.Put(c = is.Take());
  229. return c >= 0xDC00 && c <= 0xDFFF;
  230. }
  231. return false;
  232. }
  233. };
  234. //! UTF-16 little endian encoding.
  235. template<typename CharType = wchar_t>
  236. struct UTF16LE : UTF16<CharType> {
  237. template <typename InputByteStream>
  238. static CharType TakeBOM(InputByteStream& is) {
  239. RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
  240. CharType c = Take(is);
  241. return (unsigned short)c == 0xFEFFu ? Take(is) : c;
  242. }
  243. template <typename InputByteStream>
  244. static CharType Take(InputByteStream& is) {
  245. RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
  246. CharType c = (unsigned char)is.Take();
  247. c |= (unsigned char)is.Take() << 8;
  248. return c;
  249. }
  250. template <typename OutputByteStream>
  251. static void PutBOM(OutputByteStream& os) {
  252. RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
  253. os.Put(0xFFu); os.Put(0xFEu);
  254. }
  255. template <typename OutputByteStream>
  256. static void Put(OutputByteStream& os, CharType c) {
  257. RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
  258. os.Put(c & 0xFFu);
  259. os.Put((c >> 8) & 0xFFu);
  260. }
  261. };
  262. //! UTF-16 big endian encoding.
  263. template<typename CharType = wchar_t>
  264. struct UTF16BE : UTF16<CharType> {
  265. template <typename InputByteStream>
  266. static CharType TakeBOM(InputByteStream& is) {
  267. RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
  268. CharType c = Take(is);
  269. return (unsigned short)c == 0xFEFFu ? Take(is) : c;
  270. }
  271. template <typename InputByteStream>
  272. static CharType Take(InputByteStream& is) {
  273. RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
  274. CharType c = (unsigned char)is.Take() << 8;
  275. c |= (unsigned char)is.Take();
  276. return c;
  277. }
  278. template <typename OutputByteStream>
  279. static void PutBOM(OutputByteStream& os) {
  280. RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
  281. os.Put(0xFEu); os.Put(0xFFu);
  282. }
  283. template <typename OutputByteStream>
  284. static void Put(OutputByteStream& os, CharType c) {
  285. RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
  286. os.Put((c >> 8) & 0xFFu);
  287. os.Put(c & 0xFFu);
  288. }
  289. };
  290. ///////////////////////////////////////////////////////////////////////////////
  291. // UTF32
  292. //! UTF-32 encoding.
  293. /*! http://en.wikipedia.org/wiki/UTF-32
  294. \tparam Ch Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead.
  295. \implements Encoding
  296. \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
  297. For streaming, use UTF32LE and UTF32BE, which handle endianness.
  298. */
  299. template<typename CharType = unsigned>
  300. struct UTF32 {
  301. typedef CharType Ch;
  302. RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4);
  303. template<typename OutputStream>
  304. static void Encode(OutputStream& os, unsigned codepoint) {
  305. RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
  306. RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
  307. os.Put(codepoint);
  308. }
  309. template <typename InputStream>
  310. static bool Decode(InputStream& is, unsigned* codepoint) {
  311. RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
  312. Ch c = is.Take();
  313. *codepoint = c;
  314. return c <= 0x10FFFF;
  315. }
  316. template <typename InputStream, typename OutputStream>
  317. static bool Validate(InputStream& is, OutputStream& os) {
  318. RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
  319. Ch c;
  320. os.Put(c = is.Take());
  321. return c <= 0x10FFFF;
  322. }
  323. };
  324. //! UTF-32 little endian enocoding.
  325. template<typename CharType = unsigned>
  326. struct UTF32LE : UTF32<CharType> {
  327. template <typename InputByteStream>
  328. static CharType TakeBOM(InputByteStream& is) {
  329. RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
  330. CharType c = Take(is);
  331. return (unsigned)c == 0x0000FEFFu ? Take(is) : c;
  332. }
  333. template <typename InputByteStream>
  334. static CharType Take(InputByteStream& is) {
  335. RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
  336. CharType c = (unsigned char)is.Take();
  337. c |= (unsigned char)is.Take() << 8;
  338. c |= (unsigned char)is.Take() << 16;
  339. c |= (unsigned char)is.Take() << 24;
  340. return c;
  341. }
  342. template <typename OutputByteStream>
  343. static void PutBOM(OutputByteStream& os) {
  344. RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
  345. os.Put(0xFFu); os.Put(0xFEu); os.Put(0x00u); os.Put(0x00u);
  346. }
  347. template <typename OutputByteStream>
  348. static void Put(OutputByteStream& os, CharType c) {
  349. RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
  350. os.Put(c & 0xFFu);
  351. os.Put((c >> 8) & 0xFFu);
  352. os.Put((c >> 16) & 0xFFu);
  353. os.Put((c >> 24) & 0xFFu);
  354. }
  355. };
  356. //! UTF-32 big endian encoding.
  357. template<typename CharType = unsigned>
  358. struct UTF32BE : UTF32<CharType> {
  359. template <typename InputByteStream>
  360. static CharType TakeBOM(InputByteStream& is) {
  361. RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
  362. CharType c = Take(is);
  363. return (unsigned)c == 0x0000FEFFu ? Take(is) : c;
  364. }
  365. template <typename InputByteStream>
  366. static CharType Take(InputByteStream& is) {
  367. RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
  368. CharType c = (unsigned char)is.Take() << 24;
  369. c |= (unsigned char)is.Take() << 16;
  370. c |= (unsigned char)is.Take() << 8;
  371. c |= (unsigned char)is.Take();
  372. return c;
  373. }
  374. template <typename OutputByteStream>
  375. static void PutBOM(OutputByteStream& os) {
  376. RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
  377. os.Put(0x00u); os.Put(0x00u); os.Put(0xFEu); os.Put(0xFFu);
  378. }
  379. template <typename OutputByteStream>
  380. static void Put(OutputByteStream& os, CharType c) {
  381. RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
  382. os.Put((c >> 24) & 0xFFu);
  383. os.Put((c >> 16) & 0xFFu);
  384. os.Put((c >> 8) & 0xFFu);
  385. os.Put(c & 0xFFu);
  386. }
  387. };
  388. ///////////////////////////////////////////////////////////////////////////////
  389. // AutoUTF
  390. //! Runtime-specified UTF encoding type of a stream.
  391. enum UTFType {
  392. kUTF8 = 0, //!< UTF-8.
  393. kUTF16LE = 1, //!< UTF-16 little endian.
  394. kUTF16BE = 2, //!< UTF-16 big endian.
  395. kUTF32LE = 3, //!< UTF-32 little endian.
  396. kUTF32BE = 4, //!< UTF-32 big endian.
  397. };
  398. //! Dynamically select encoding according to stream's runtime-specified UTF encoding type.
  399. /*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType().
  400. */
  401. template<typename CharType>
  402. struct AutoUTF {
  403. typedef CharType Ch;
  404. #define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
  405. template<typename OutputStream>
  406. RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) {
  407. typedef void (*EncodeFunc)(OutputStream&, unsigned);
  408. static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };
  409. (*f[os.GetType()])(os, codepoint);
  410. }
  411. template <typename InputStream>
  412. RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) {
  413. typedef bool (*DecodeFunc)(InputStream&, unsigned*);
  414. static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) };
  415. return (*f[is.GetType()])(is, codepoint);
  416. }
  417. template <typename InputStream, typename OutputStream>
  418. RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
  419. typedef bool (*ValidateFunc)(InputStream&, OutputStream&);
  420. static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) };
  421. return (*f[is.GetType()])(is, os);
  422. }
  423. #undef RAPIDJSON_ENCODINGS_FUNC
  424. };
  425. ///////////////////////////////////////////////////////////////////////////////
  426. // Transcoder
  427. //! Encoding conversion.
  428. template<typename SourceEncoding, typename TargetEncoding>
  429. struct Transcoder {
  430. //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream.
  431. template<typename InputStream, typename OutputStream>
  432. RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
  433. unsigned codepoint;
  434. if (!SourceEncoding::Decode(is, &codepoint))
  435. return false;
  436. TargetEncoding::Encode(os, codepoint);
  437. return true;
  438. }
  439. //! Validate one Unicode codepoint from an encoded stream.
  440. template<typename InputStream, typename OutputStream>
  441. RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
  442. return Transcode(is, os); // Since source/target encoding is different, must transcode.
  443. }
  444. };
  445. //! Specialization of Transcoder with same source and target encoding.
  446. template<typename Encoding>
  447. struct Transcoder<Encoding, Encoding> {
  448. template<typename InputStream, typename OutputStream>
  449. RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
  450. os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class.
  451. return true;
  452. }
  453. template<typename InputStream, typename OutputStream>
  454. RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
  455. return Encoding::Validate(is, os); // source/target encoding are the same
  456. }
  457. };
  458. } // namespace rapidjson
  459. #endif // RAPIDJSON_ENCODINGS_H_