Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-21 10:13:01

0001 // Tencent is pleased to support the open source community by making RapidJSON available.
0002 // 
0003 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
0004 //
0005 // Licensed under the MIT License (the "License"); you may not use this file except
0006 // in compliance with the License. You may obtain a copy of the License at
0007 //
0008 // http://opensource.org/licenses/MIT
0009 //
0010 // Unless required by applicable law or agreed to in writing, software distributed 
0011 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
0012 // CONDITIONS OF ANY KIND, either express or implied. See the License for the 
0013 // specific language governing permissions and limitations under the License.
0014 
0015 #ifndef RAPIDJSON_ENCODINGS_H_
0016 #define RAPIDJSON_ENCODINGS_H_
0017 
0018 #include "rapidjson.h"
0019 
0020 #if defined(_MSC_VER) && !defined(__clang__)
0021 RAPIDJSON_DIAG_PUSH
0022 RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data
0023 RAPIDJSON_DIAG_OFF(4702)  // unreachable code
0024 #elif defined(__GNUC__)
0025 RAPIDJSON_DIAG_PUSH
0026 RAPIDJSON_DIAG_OFF(effc++)
0027 RAPIDJSON_DIAG_OFF(overflow)
0028 #endif
0029 
0030 RAPIDJSON_NAMESPACE_BEGIN
0031 
0032 ///////////////////////////////////////////////////////////////////////////////
0033 // Encoding
0034 
0035 /*! \class rapidjson::Encoding
0036     \brief Concept for encoding of Unicode characters.
0037 
0038 \code
0039 concept Encoding {
0040     typename Ch;    //! Type of character. A "character" is actually a code unit in unicode's definition.
0041 
0042     enum { supportUnicode = 1 }; // or 0 if not supporting unicode
0043 
0044     //! \brief Encode a Unicode codepoint to an output stream.
0045     //! \param os Output stream.
0046     //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively.
0047     template<typename OutputStream>
0048     static void Encode(OutputStream& os, unsigned codepoint);
0049 
0050     //! \brief Decode a Unicode codepoint from an input stream.
0051     //! \param is Input stream.
0052     //! \param codepoint Output of the unicode codepoint.
0053     //! \return true if a valid codepoint can be decoded from the stream.
0054     template <typename InputStream>
0055     static bool Decode(InputStream& is, unsigned* codepoint);
0056 
0057     //! \brief Validate one Unicode codepoint from an encoded stream.
0058     //! \param is Input stream to obtain codepoint.
0059     //! \param os Output for copying one codepoint.
0060     //! \return true if it is valid.
0061     //! \note This function just validating and copying the codepoint without actually decode it.
0062     template <typename InputStream, typename OutputStream>
0063     static bool Validate(InputStream& is, OutputStream& os);
0064 
0065     // The following functions are deal with byte streams.
0066 
0067     //! Take a character from input byte stream, skip BOM if exist.
0068     template <typename InputByteStream>
0069     static CharType TakeBOM(InputByteStream& is);
0070 
0071     //! Take a character from input byte stream.
0072     template <typename InputByteStream>
0073     static Ch Take(InputByteStream& is);
0074 
0075     //! Put BOM to output byte stream.
0076     template <typename OutputByteStream>
0077     static void PutBOM(OutputByteStream& os);
0078 
0079     //! Put a character to output byte stream.
0080     template <typename OutputByteStream>
0081     static void Put(OutputByteStream& os, Ch c);
0082 };
0083 \endcode
0084 */
0085 
0086 ///////////////////////////////////////////////////////////////////////////////
0087 // UTF8
0088 
0089 //! UTF-8 encoding.
0090 /*! http://en.wikipedia.org/wiki/UTF-8
0091     http://tools.ietf.org/html/rfc3629
0092     \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char.
0093     \note implements Encoding concept
0094 */
0095 template<typename CharType = char>
0096 struct UTF8 {
0097     typedef CharType Ch;
0098 
0099     enum { supportUnicode = 1 };
0100 
0101     template<typename OutputStream>
0102     static void Encode(OutputStream& os, unsigned codepoint) {
0103         if (codepoint <= 0x7F) 
0104             os.Put(static_cast<Ch>(codepoint & 0xFF));
0105         else if (codepoint <= 0x7FF) {
0106             os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
0107             os.Put(static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
0108         }
0109         else if (codepoint <= 0xFFFF) {
0110             os.Put(static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
0111             os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
0112             os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
0113         }
0114         else {
0115             RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
0116             os.Put(static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
0117             os.Put(static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
0118             os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
0119             os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
0120         }
0121     }
0122 
0123     template<typename OutputStream>
0124     static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
0125         if (codepoint <= 0x7F) 
0126             PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
0127         else if (codepoint <= 0x7FF) {
0128             PutUnsafe(os, static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
0129             PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
0130         }
0131         else if (codepoint <= 0xFFFF) {
0132             PutUnsafe(os, static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
0133             PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
0134             PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F)));
0135         }
0136         else {
0137             RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
0138             PutUnsafe(os, static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
0139             PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
0140             PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
0141             PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F)));
0142         }
0143     }
0144 
0145     template <typename InputStream>
0146     static bool Decode(InputStream& is, unsigned* codepoint) {
0147 #define RAPIDJSON_COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu)
0148 #define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
0149 #define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70)
0150         typename InputStream::Ch c = is.Take();
0151         if (!(c & 0x80)) {
0152             *codepoint = static_cast<unsigned char>(c);
0153             return true;
0154         }
0155 
0156         unsigned char type = GetRange(static_cast<unsigned char>(c));
0157         if (type >= 32) {
0158             *codepoint = 0;
0159         } else {
0160             *codepoint = (0xFFu >> type) & static_cast<unsigned char>(c);
0161         }
0162         bool result = true;
0163         switch (type) {
0164         case 2: RAPIDJSON_TAIL(); return result;
0165         case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
0166         case 4: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x50); RAPIDJSON_TAIL(); return result;
0167         case 5: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x10); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
0168         case 6: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
0169         case 10: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x20); RAPIDJSON_TAIL(); return result;
0170         case 11: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x60); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
0171         default: return false;
0172         }
0173 #undef RAPIDJSON_COPY
0174 #undef RAPIDJSON_TRANS
0175 #undef RAPIDJSON_TAIL
0176     }
0177 
0178     template <typename InputStream, typename OutputStream>
0179     static bool Validate(InputStream& is, OutputStream& os) {
0180 #define RAPIDJSON_COPY() os.Put(c = is.Take())
0181 #define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
0182 #define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70)
0183         Ch c;
0184         RAPIDJSON_COPY();
0185         if (!(c & 0x80))
0186             return true;
0187 
0188         bool result = true;
0189         switch (GetRange(static_cast<unsigned char>(c))) {
0190         case 2: RAPIDJSON_TAIL(); return result;
0191         case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
0192         case 4: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x50); RAPIDJSON_TAIL(); return result;
0193         case 5: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x10); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
0194         case 6: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
0195         case 10: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x20); RAPIDJSON_TAIL(); return result;
0196         case 11: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x60); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
0197         default: return false;
0198         }
0199 #undef RAPIDJSON_COPY
0200 #undef RAPIDJSON_TRANS
0201 #undef RAPIDJSON_TAIL
0202     }
0203 
0204     static unsigned char GetRange(unsigned char c) {
0205         // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
0206         // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types.
0207         static const unsigned char type[] = {
0208             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,
0209             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,
0210             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,
0211             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,
0212             0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
0213             0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
0214             0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0215             0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0216             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,
0217             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,
0218         };
0219         return type[c];
0220     }
0221 
0222     template <typename InputByteStream>
0223     static CharType TakeBOM(InputByteStream& is) {
0224         RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
0225         typename InputByteStream::Ch c = Take(is);
0226         if (static_cast<unsigned char>(c) != 0xEFu) return c;
0227         c = is.Take();
0228         if (static_cast<unsigned char>(c) != 0xBBu) return c;
0229         c = is.Take();
0230         if (static_cast<unsigned char>(c) != 0xBFu) return c;
0231         c = is.Take();
0232         return c;
0233     }
0234 
0235     template <typename InputByteStream>
0236     static Ch Take(InputByteStream& is) {
0237         RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
0238         return static_cast<Ch>(is.Take());
0239     }
0240 
0241     template <typename OutputByteStream>
0242     static void PutBOM(OutputByteStream& os) {
0243         RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
0244         os.Put(static_cast<typename OutputByteStream::Ch>(0xEFu));
0245         os.Put(static_cast<typename OutputByteStream::Ch>(0xBBu));
0246         os.Put(static_cast<typename OutputByteStream::Ch>(0xBFu));
0247     }
0248 
0249     template <typename OutputByteStream>
0250     static void Put(OutputByteStream& os, Ch c) {
0251         RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
0252         os.Put(static_cast<typename OutputByteStream::Ch>(c));
0253     }
0254 };
0255 
0256 ///////////////////////////////////////////////////////////////////////////////
0257 // UTF16
0258 
0259 //! UTF-16 encoding.
0260 /*! http://en.wikipedia.org/wiki/UTF-16
0261     http://tools.ietf.org/html/rfc2781
0262     \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead.
0263     \note implements Encoding concept
0264 
0265     \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
0266     For streaming, use UTF16LE and UTF16BE, which handle endianness.
0267 */
0268 template<typename CharType = wchar_t>
0269 struct UTF16 {
0270     typedef CharType Ch;
0271     RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);
0272 
0273     enum { supportUnicode = 1 };
0274 
0275     template<typename OutputStream>
0276     static void Encode(OutputStream& os, unsigned codepoint) {
0277         RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
0278         if (codepoint <= 0xFFFF) {
0279             RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair 
0280             os.Put(static_cast<typename OutputStream::Ch>(codepoint));
0281         }
0282         else {
0283             RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
0284             unsigned v = codepoint - 0x10000;
0285             os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
0286             os.Put(static_cast<typename OutputStream::Ch>((v & 0x3FF) | 0xDC00));
0287         }
0288     }
0289 
0290 
0291     template<typename OutputStream>
0292     static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
0293         RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
0294         if (codepoint <= 0xFFFF) {
0295             RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair 
0296             PutUnsafe(os, static_cast<typename OutputStream::Ch>(codepoint));
0297         }
0298         else {
0299             RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
0300             unsigned v = codepoint - 0x10000;
0301             PutUnsafe(os, static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
0302             PutUnsafe(os, static_cast<typename OutputStream::Ch>((v & 0x3FF) | 0xDC00));
0303         }
0304     }
0305 
0306     template <typename InputStream>
0307     static bool Decode(InputStream& is, unsigned* codepoint) {
0308         RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
0309         typename InputStream::Ch c = is.Take();
0310         if (c < 0xD800 || c > 0xDFFF) {
0311             *codepoint = static_cast<unsigned>(c);
0312             return true;
0313         }
0314         else if (c <= 0xDBFF) {
0315             *codepoint = (static_cast<unsigned>(c) & 0x3FF) << 10;
0316             c = is.Take();
0317             *codepoint |= (static_cast<unsigned>(c) & 0x3FF);
0318             *codepoint += 0x10000;
0319             return c >= 0xDC00 && c <= 0xDFFF;
0320         }
0321         return false;
0322     }
0323 
0324     template <typename InputStream, typename OutputStream>
0325     static bool Validate(InputStream& is, OutputStream& os) {
0326         RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
0327         RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
0328         typename InputStream::Ch c;
0329         os.Put(static_cast<typename OutputStream::Ch>(c = is.Take()));
0330         if (c < 0xD800 || c > 0xDFFF)
0331             return true;
0332         else if (c <= 0xDBFF) {
0333             os.Put(c = is.Take());
0334             return c >= 0xDC00 && c <= 0xDFFF;
0335         }
0336         return false;
0337     }
0338 };
0339 
0340 //! UTF-16 little endian encoding.
0341 template<typename CharType = wchar_t>
0342 struct UTF16LE : UTF16<CharType> {
0343     template <typename InputByteStream>
0344     static CharType TakeBOM(InputByteStream& is) {
0345         RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
0346         CharType c = Take(is);
0347         return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
0348     }
0349 
0350     template <typename InputByteStream>
0351     static CharType Take(InputByteStream& is) {
0352         RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
0353         unsigned c = static_cast<uint8_t>(is.Take());
0354         c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
0355         return static_cast<CharType>(c);
0356     }
0357 
0358     template <typename OutputByteStream>
0359     static void PutBOM(OutputByteStream& os) {
0360         RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
0361         os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
0362         os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
0363     }
0364 
0365     template <typename OutputByteStream>
0366     static void Put(OutputByteStream& os, CharType c) {
0367         RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
0368         os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));
0369         os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
0370     }
0371 };
0372 
0373 //! UTF-16 big endian encoding.
0374 template<typename CharType = wchar_t>
0375 struct UTF16BE : UTF16<CharType> {
0376     template <typename InputByteStream>
0377     static CharType TakeBOM(InputByteStream& is) {
0378         RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
0379         CharType c = Take(is);
0380         return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
0381     }
0382 
0383     template <typename InputByteStream>
0384     static CharType Take(InputByteStream& is) {
0385         RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
0386         unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
0387         c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take()));
0388         return static_cast<CharType>(c);
0389     }
0390 
0391     template <typename OutputByteStream>
0392     static void PutBOM(OutputByteStream& os) {
0393         RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
0394         os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
0395         os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
0396     }
0397 
0398     template <typename OutputByteStream>
0399     static void Put(OutputByteStream& os, CharType c) {
0400         RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
0401         os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
0402         os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));
0403     }
0404 };
0405 
0406 ///////////////////////////////////////////////////////////////////////////////
0407 // UTF32
0408 
0409 //! UTF-32 encoding. 
0410 /*! http://en.wikipedia.org/wiki/UTF-32
0411     \tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead.
0412     \note implements Encoding concept
0413 
0414     \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
0415     For streaming, use UTF32LE and UTF32BE, which handle endianness.
0416 */
0417 template<typename CharType = unsigned>
0418 struct UTF32 {
0419     typedef CharType Ch;
0420     RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4);
0421 
0422     enum { supportUnicode = 1 };
0423 
0424     template<typename OutputStream>
0425     static void Encode(OutputStream& os, unsigned codepoint) {
0426         RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
0427         RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
0428         os.Put(codepoint);
0429     }
0430 
0431     template<typename OutputStream>
0432     static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
0433         RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
0434         RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
0435         PutUnsafe(os, codepoint);
0436     }
0437 
0438     template <typename InputStream>
0439     static bool Decode(InputStream& is, unsigned* codepoint) {
0440         RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
0441         Ch c = is.Take();
0442         *codepoint = c;
0443         return c <= 0x10FFFF;
0444     }
0445 
0446     template <typename InputStream, typename OutputStream>
0447     static bool Validate(InputStream& is, OutputStream& os) {
0448         RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
0449         Ch c;
0450         os.Put(c = is.Take());
0451         return c <= 0x10FFFF;
0452     }
0453 };
0454 
0455 //! UTF-32 little endian enocoding.
0456 template<typename CharType = unsigned>
0457 struct UTF32LE : UTF32<CharType> {
0458     template <typename InputByteStream>
0459     static CharType TakeBOM(InputByteStream& is) {
0460         RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
0461         CharType c = Take(is);
0462         return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;
0463     }
0464 
0465     template <typename InputByteStream>
0466     static CharType Take(InputByteStream& is) {
0467         RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
0468         unsigned c = static_cast<uint8_t>(is.Take());
0469         c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
0470         c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
0471         c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
0472         return static_cast<CharType>(c);
0473     }
0474 
0475     template <typename OutputByteStream>
0476     static void PutBOM(OutputByteStream& os) {
0477         RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
0478         os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
0479         os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
0480         os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
0481         os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
0482     }
0483 
0484     template <typename OutputByteStream>
0485     static void Put(OutputByteStream& os, CharType c) {
0486         RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
0487         os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu));
0488         os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
0489         os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
0490         os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));
0491     }
0492 };
0493 
0494 //! UTF-32 big endian encoding.
0495 template<typename CharType = unsigned>
0496 struct UTF32BE : UTF32<CharType> {
0497     template <typename InputByteStream>
0498     static CharType TakeBOM(InputByteStream& is) {
0499         RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
0500         CharType c = Take(is);
0501         return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c; 
0502     }
0503 
0504     template <typename InputByteStream>
0505     static CharType Take(InputByteStream& is) {
0506         RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
0507         unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
0508         c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
0509         c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
0510         c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take()));
0511         return static_cast<CharType>(c);
0512     }
0513 
0514     template <typename OutputByteStream>
0515     static void PutBOM(OutputByteStream& os) {
0516         RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
0517         os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
0518         os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
0519         os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
0520         os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
0521     }
0522 
0523     template <typename OutputByteStream>
0524     static void Put(OutputByteStream& os, CharType c) {
0525         RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
0526         os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));
0527         os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
0528         os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
0529         os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu));
0530     }
0531 };
0532 
0533 ///////////////////////////////////////////////////////////////////////////////
0534 // ASCII
0535 
0536 //! ASCII encoding.
0537 /*! http://en.wikipedia.org/wiki/ASCII
0538     \tparam CharType Code unit for storing 7-bit ASCII data. Default is char.
0539     \note implements Encoding concept
0540 */
0541 template<typename CharType = char>
0542 struct ASCII {
0543     typedef CharType Ch;
0544 
0545     enum { supportUnicode = 0 };
0546 
0547     template<typename OutputStream>
0548     static void Encode(OutputStream& os, unsigned codepoint) {
0549         RAPIDJSON_ASSERT(codepoint <= 0x7F);
0550         os.Put(static_cast<Ch>(codepoint & 0xFF));
0551     }
0552 
0553     template<typename OutputStream>
0554     static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
0555         RAPIDJSON_ASSERT(codepoint <= 0x7F);
0556         PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
0557     }
0558 
0559     template <typename InputStream>
0560     static bool Decode(InputStream& is, unsigned* codepoint) {
0561         uint8_t c = static_cast<uint8_t>(is.Take());
0562         *codepoint = c;
0563         return c <= 0X7F;
0564     }
0565 
0566     template <typename InputStream, typename OutputStream>
0567     static bool Validate(InputStream& is, OutputStream& os) {
0568         uint8_t c = static_cast<uint8_t>(is.Take());
0569         os.Put(static_cast<typename OutputStream::Ch>(c));
0570         return c <= 0x7F;
0571     }
0572 
0573     template <typename InputByteStream>
0574     static CharType TakeBOM(InputByteStream& is) {
0575         RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
0576         uint8_t c = static_cast<uint8_t>(Take(is));
0577         return static_cast<Ch>(c);
0578     }
0579 
0580     template <typename InputByteStream>
0581     static Ch Take(InputByteStream& is) {
0582         RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
0583         return static_cast<Ch>(is.Take());
0584     }
0585 
0586     template <typename OutputByteStream>
0587     static void PutBOM(OutputByteStream& os) {
0588         RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
0589         (void)os;
0590     }
0591 
0592     template <typename OutputByteStream>
0593     static void Put(OutputByteStream& os, Ch c) {
0594         RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
0595         os.Put(static_cast<typename OutputByteStream::Ch>(c));
0596     }
0597 };
0598 
0599 ///////////////////////////////////////////////////////////////////////////////
0600 // AutoUTF
0601 
0602 //! Runtime-specified UTF encoding type of a stream.
0603 enum UTFType {
0604     kUTF8 = 0,      //!< UTF-8.
0605     kUTF16LE = 1,   //!< UTF-16 little endian.
0606     kUTF16BE = 2,   //!< UTF-16 big endian.
0607     kUTF32LE = 3,   //!< UTF-32 little endian.
0608     kUTF32BE = 4    //!< UTF-32 big endian.
0609 };
0610 
0611 //! Dynamically select encoding according to stream's runtime-specified UTF encoding type.
0612 /*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType().
0613 */
0614 template<typename CharType>
0615 struct AutoUTF {
0616     typedef CharType Ch;
0617 
0618     enum { supportUnicode = 1 };
0619 
0620 #define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
0621 
0622     template<typename OutputStream>
0623     static RAPIDJSON_FORCEINLINE void Encode(OutputStream& os, unsigned codepoint) {
0624         typedef void (*EncodeFunc)(OutputStream&, unsigned);
0625         static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };
0626         (*f[os.GetType()])(os, codepoint);
0627     }
0628 
0629     template<typename OutputStream>
0630     static RAPIDJSON_FORCEINLINE void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
0631         typedef void (*EncodeFunc)(OutputStream&, unsigned);
0632         static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) };
0633         (*f[os.GetType()])(os, codepoint);
0634     }
0635 
0636     template <typename InputStream>
0637     static RAPIDJSON_FORCEINLINE bool Decode(InputStream& is, unsigned* codepoint) {
0638         typedef bool (*DecodeFunc)(InputStream&, unsigned*);
0639         static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) };
0640         return (*f[is.GetType()])(is, codepoint);
0641     }
0642 
0643     template <typename InputStream, typename OutputStream>
0644     static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
0645         typedef bool (*ValidateFunc)(InputStream&, OutputStream&);
0646         static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) };
0647         return (*f[is.GetType()])(is, os);
0648     }
0649 
0650 #undef RAPIDJSON_ENCODINGS_FUNC
0651 };
0652 
0653 ///////////////////////////////////////////////////////////////////////////////
0654 // Transcoder
0655 
0656 //! Encoding conversion.
0657 template<typename SourceEncoding, typename TargetEncoding>
0658 struct Transcoder {
0659     //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream.
0660     template<typename InputStream, typename OutputStream>
0661     static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) {
0662         unsigned codepoint;
0663         if (!SourceEncoding::Decode(is, &codepoint))
0664             return false;
0665         TargetEncoding::Encode(os, codepoint);
0666         return true;
0667     }
0668 
0669     template<typename InputStream, typename OutputStream>
0670     static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
0671         unsigned codepoint;
0672         if (!SourceEncoding::Decode(is, &codepoint))
0673             return false;
0674         TargetEncoding::EncodeUnsafe(os, codepoint);
0675         return true;
0676     }
0677 
0678     //! Validate one Unicode codepoint from an encoded stream.
0679     template<typename InputStream, typename OutputStream>
0680     static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
0681         return Transcode(is, os);   // Since source/target encoding is different, must transcode.
0682     }
0683 };
0684 
0685 // Forward declaration.
0686 template<typename Stream>
0687 inline void PutUnsafe(Stream& stream, typename Stream::Ch c);
0688 
0689 //! Specialization of Transcoder with same source and target encoding.
0690 template<typename Encoding>
0691 struct Transcoder<Encoding, Encoding> {
0692     template<typename InputStream, typename OutputStream>
0693     static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) {
0694         os.Put(is.Take());  // Just copy one code unit. This semantic is different from primary template class.
0695         return true;
0696     }
0697     
0698     template<typename InputStream, typename OutputStream>
0699     static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
0700         PutUnsafe(os, is.Take());  // Just copy one code unit. This semantic is different from primary template class.
0701         return true;
0702     }
0703     
0704     template<typename InputStream, typename OutputStream>
0705     static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
0706         return Encoding::Validate(is, os);  // source/target encoding are the same
0707     }
0708 };
0709 
0710 RAPIDJSON_NAMESPACE_END
0711 
0712 #if defined(__GNUC__) || (defined(_MSC_VER) && !defined(__clang__))
0713 RAPIDJSON_DIAG_POP
0714 #endif
0715 
0716 #endif // RAPIDJSON_ENCODINGS_H_