encodings.h

Engine/source/persistence/rapidjson/encodings.h

More...

Classes:

class

Dynamically select encoding according to stream's runtime-specified UTF encoding type.

class

Specialization of Transcoder with same source and target encoding.

class

UTF-16 encoding.

class

UTF-16 big endian encoding.

class

UTF-16 little endian encoding.

class

UTF-32 encoding.

class

UTF-32 big endian encoding.

class

UTF-32 little endian enocoding.

class

UTF-8 encoding.

Namespaces:

namespace

Public Defines

define
COPY() c = is.Take(); *codepoint = (*codepoint << 6) | ((unsigned char)c & 0x3Fu)
define
COPY() os.Put(c = is.Take())
define
RAPIDJSON_ENCODINGS_FUNC(x) <Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
define
TAIL() (); (0x70)
define
TAIL() (); (0x70)
define
TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0)
define
TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0)

Detailed Description

Public Defines

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