encodings.h
Engine/source/persistence/rapidjson/encodings.h
Classes:
class
Dynamically select encoding according to stream's runtime-specified UTF encoding type.
class
Encoding conversion.
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
