DeepCover Embedded Security in IoT: Public-key Secured Data Paths

Dependencies:   MaximInterface

The MAXREFDES155# is an internet-of-things (IoT) embedded-security reference design, built to authenticate and control a sensing node using elliptic-curve-based public-key cryptography with control and notification from a web server.

The hardware includes an ARM® mbed™ shield and attached sensor endpoint. The shield contains a DS2476 DeepCover® ECDSA/SHA-2 coprocessor, Wifi communication, LCD push-button controls, and status LEDs. The sensor endpoint is attached to the shield using a 300mm cable and contains a DS28C36 DeepCover ECDSA/SHA-2 authenticator, IR-thermal sensor, and aiming laser for the IR sensor. The MAXREFDES155# is equipped with a standard Arduino® form-factor shield connector for immediate testing using an mbed board such as the MAX32600MBED#. The combination of these two devices represent an IoT device. Communication to the web server is accomplished with the shield Wifi circuitry. Communication from the shield to the attached sensor module is accomplished over I2C . The sensor module represents an IoT endpoint that generates small data with a requirement for message authenticity/integrity and secure on/off operational control.

The design is hierarchical with each mbed platform and shield communicating data from the sensor node to a web server that maintains a centralized log and dispatches notifications as necessary. The simplicity of this design enables rapid integration into any star-topology IoT network to provide security with the low overhead and cost provided by the ECDSA-P256 asymmetric-key and SHA-256 symmetric-key algorithms.

More information about the MAXREFDES155# is available on the Maxim Integrated website.

Committer:
IanBenzMaxim
Date:
Fri Feb 24 11:23:12 2017 -0600
Revision:
0:33d4e66780c0
Initial commit.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
IanBenzMaxim 0:33d4e66780c0 1 // Tencent is pleased to support the open source community by making RapidJSON available.
IanBenzMaxim 0:33d4e66780c0 2 //
IanBenzMaxim 0:33d4e66780c0 3 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
IanBenzMaxim 0:33d4e66780c0 4 //
IanBenzMaxim 0:33d4e66780c0 5 // Licensed under the MIT License (the "License"); you may not use this file except
IanBenzMaxim 0:33d4e66780c0 6 // in compliance with the License. You may obtain a copy of the License at
IanBenzMaxim 0:33d4e66780c0 7 //
IanBenzMaxim 0:33d4e66780c0 8 // http://opensource.org/licenses/MIT
IanBenzMaxim 0:33d4e66780c0 9 //
IanBenzMaxim 0:33d4e66780c0 10 // Unless required by applicable law or agreed to in writing, software distributed
IanBenzMaxim 0:33d4e66780c0 11 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
IanBenzMaxim 0:33d4e66780c0 12 // CONDITIONS OF ANY KIND, either express or implied. See the License for the
IanBenzMaxim 0:33d4e66780c0 13 // specific language governing permissions and limitations under the License.
IanBenzMaxim 0:33d4e66780c0 14
IanBenzMaxim 0:33d4e66780c0 15 #ifndef RAPIDJSON_ENCODINGS_H_
IanBenzMaxim 0:33d4e66780c0 16 #define RAPIDJSON_ENCODINGS_H_
IanBenzMaxim 0:33d4e66780c0 17
IanBenzMaxim 0:33d4e66780c0 18 #include "rapidjson.h"
IanBenzMaxim 0:33d4e66780c0 19
IanBenzMaxim 0:33d4e66780c0 20 #ifdef _MSC_VER
IanBenzMaxim 0:33d4e66780c0 21 RAPIDJSON_DIAG_PUSH
IanBenzMaxim 0:33d4e66780c0 22 RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data
IanBenzMaxim 0:33d4e66780c0 23 RAPIDJSON_DIAG_OFF(4702) // unreachable code
IanBenzMaxim 0:33d4e66780c0 24 #elif defined(__GNUC__)
IanBenzMaxim 0:33d4e66780c0 25 RAPIDJSON_DIAG_PUSH
IanBenzMaxim 0:33d4e66780c0 26 RAPIDJSON_DIAG_OFF(effc++)
IanBenzMaxim 0:33d4e66780c0 27 RAPIDJSON_DIAG_OFF(overflow)
IanBenzMaxim 0:33d4e66780c0 28 #endif
IanBenzMaxim 0:33d4e66780c0 29
IanBenzMaxim 0:33d4e66780c0 30 RAPIDJSON_NAMESPACE_BEGIN
IanBenzMaxim 0:33d4e66780c0 31
IanBenzMaxim 0:33d4e66780c0 32 ///////////////////////////////////////////////////////////////////////////////
IanBenzMaxim 0:33d4e66780c0 33 // Encoding
IanBenzMaxim 0:33d4e66780c0 34
IanBenzMaxim 0:33d4e66780c0 35 /*! \class rapidjson::Encoding
IanBenzMaxim 0:33d4e66780c0 36 \brief Concept for encoding of Unicode characters.
IanBenzMaxim 0:33d4e66780c0 37
IanBenzMaxim 0:33d4e66780c0 38 \code
IanBenzMaxim 0:33d4e66780c0 39 concept Encoding {
IanBenzMaxim 0:33d4e66780c0 40 typename Ch; //! Type of character. A "character" is actually a code unit in unicode's definition.
IanBenzMaxim 0:33d4e66780c0 41
IanBenzMaxim 0:33d4e66780c0 42 enum { supportUnicode = 1 }; // or 0 if not supporting unicode
IanBenzMaxim 0:33d4e66780c0 43
IanBenzMaxim 0:33d4e66780c0 44 //! \brief Encode a Unicode codepoint to an output stream.
IanBenzMaxim 0:33d4e66780c0 45 //! \param os Output stream.
IanBenzMaxim 0:33d4e66780c0 46 //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively.
IanBenzMaxim 0:33d4e66780c0 47 template<typename OutputStream>
IanBenzMaxim 0:33d4e66780c0 48 static void Encode(OutputStream& os, unsigned codepoint);
IanBenzMaxim 0:33d4e66780c0 49
IanBenzMaxim 0:33d4e66780c0 50 //! \brief Decode a Unicode codepoint from an input stream.
IanBenzMaxim 0:33d4e66780c0 51 //! \param is Input stream.
IanBenzMaxim 0:33d4e66780c0 52 //! \param codepoint Output of the unicode codepoint.
IanBenzMaxim 0:33d4e66780c0 53 //! \return true if a valid codepoint can be decoded from the stream.
IanBenzMaxim 0:33d4e66780c0 54 template <typename InputStream>
IanBenzMaxim 0:33d4e66780c0 55 static bool Decode(InputStream& is, unsigned* codepoint);
IanBenzMaxim 0:33d4e66780c0 56
IanBenzMaxim 0:33d4e66780c0 57 //! \brief Validate one Unicode codepoint from an encoded stream.
IanBenzMaxim 0:33d4e66780c0 58 //! \param is Input stream to obtain codepoint.
IanBenzMaxim 0:33d4e66780c0 59 //! \param os Output for copying one codepoint.
IanBenzMaxim 0:33d4e66780c0 60 //! \return true if it is valid.
IanBenzMaxim 0:33d4e66780c0 61 //! \note This function just validating and copying the codepoint without actually decode it.
IanBenzMaxim 0:33d4e66780c0 62 template <typename InputStream, typename OutputStream>
IanBenzMaxim 0:33d4e66780c0 63 static bool Validate(InputStream& is, OutputStream& os);
IanBenzMaxim 0:33d4e66780c0 64
IanBenzMaxim 0:33d4e66780c0 65 // The following functions are deal with byte streams.
IanBenzMaxim 0:33d4e66780c0 66
IanBenzMaxim 0:33d4e66780c0 67 //! Take a character from input byte stream, skip BOM if exist.
IanBenzMaxim 0:33d4e66780c0 68 template <typename InputByteStream>
IanBenzMaxim 0:33d4e66780c0 69 static CharType TakeBOM(InputByteStream& is);
IanBenzMaxim 0:33d4e66780c0 70
IanBenzMaxim 0:33d4e66780c0 71 //! Take a character from input byte stream.
IanBenzMaxim 0:33d4e66780c0 72 template <typename InputByteStream>
IanBenzMaxim 0:33d4e66780c0 73 static Ch Take(InputByteStream& is);
IanBenzMaxim 0:33d4e66780c0 74
IanBenzMaxim 0:33d4e66780c0 75 //! Put BOM to output byte stream.
IanBenzMaxim 0:33d4e66780c0 76 template <typename OutputByteStream>
IanBenzMaxim 0:33d4e66780c0 77 static void PutBOM(OutputByteStream& os);
IanBenzMaxim 0:33d4e66780c0 78
IanBenzMaxim 0:33d4e66780c0 79 //! Put a character to output byte stream.
IanBenzMaxim 0:33d4e66780c0 80 template <typename OutputByteStream>
IanBenzMaxim 0:33d4e66780c0 81 static void Put(OutputByteStream& os, Ch c);
IanBenzMaxim 0:33d4e66780c0 82 };
IanBenzMaxim 0:33d4e66780c0 83 \endcode
IanBenzMaxim 0:33d4e66780c0 84 */
IanBenzMaxim 0:33d4e66780c0 85
IanBenzMaxim 0:33d4e66780c0 86 ///////////////////////////////////////////////////////////////////////////////
IanBenzMaxim 0:33d4e66780c0 87 // UTF8
IanBenzMaxim 0:33d4e66780c0 88
IanBenzMaxim 0:33d4e66780c0 89 //! UTF-8 encoding.
IanBenzMaxim 0:33d4e66780c0 90 /*! http://en.wikipedia.org/wiki/UTF-8
IanBenzMaxim 0:33d4e66780c0 91 http://tools.ietf.org/html/rfc3629
IanBenzMaxim 0:33d4e66780c0 92 \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char.
IanBenzMaxim 0:33d4e66780c0 93 \note implements Encoding concept
IanBenzMaxim 0:33d4e66780c0 94 */
IanBenzMaxim 0:33d4e66780c0 95 template<typename CharType = char>
IanBenzMaxim 0:33d4e66780c0 96 struct UTF8 {
IanBenzMaxim 0:33d4e66780c0 97 typedef CharType Ch;
IanBenzMaxim 0:33d4e66780c0 98
IanBenzMaxim 0:33d4e66780c0 99 enum { supportUnicode = 1 };
IanBenzMaxim 0:33d4e66780c0 100
IanBenzMaxim 0:33d4e66780c0 101 template<typename OutputStream>
IanBenzMaxim 0:33d4e66780c0 102 static void Encode(OutputStream& os, unsigned codepoint) {
IanBenzMaxim 0:33d4e66780c0 103 if (codepoint <= 0x7F)
IanBenzMaxim 0:33d4e66780c0 104 os.Put(static_cast<Ch>(codepoint & 0xFF));
IanBenzMaxim 0:33d4e66780c0 105 else if (codepoint <= 0x7FF) {
IanBenzMaxim 0:33d4e66780c0 106 os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
IanBenzMaxim 0:33d4e66780c0 107 os.Put(static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
IanBenzMaxim 0:33d4e66780c0 108 }
IanBenzMaxim 0:33d4e66780c0 109 else if (codepoint <= 0xFFFF) {
IanBenzMaxim 0:33d4e66780c0 110 os.Put(static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
IanBenzMaxim 0:33d4e66780c0 111 os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
IanBenzMaxim 0:33d4e66780c0 112 os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
IanBenzMaxim 0:33d4e66780c0 113 }
IanBenzMaxim 0:33d4e66780c0 114 else {
IanBenzMaxim 0:33d4e66780c0 115 RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
IanBenzMaxim 0:33d4e66780c0 116 os.Put(static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
IanBenzMaxim 0:33d4e66780c0 117 os.Put(static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
IanBenzMaxim 0:33d4e66780c0 118 os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
IanBenzMaxim 0:33d4e66780c0 119 os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
IanBenzMaxim 0:33d4e66780c0 120 }
IanBenzMaxim 0:33d4e66780c0 121 }
IanBenzMaxim 0:33d4e66780c0 122
IanBenzMaxim 0:33d4e66780c0 123 template<typename OutputStream>
IanBenzMaxim 0:33d4e66780c0 124 static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
IanBenzMaxim 0:33d4e66780c0 125 if (codepoint <= 0x7F)
IanBenzMaxim 0:33d4e66780c0 126 PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
IanBenzMaxim 0:33d4e66780c0 127 else if (codepoint <= 0x7FF) {
IanBenzMaxim 0:33d4e66780c0 128 PutUnsafe(os, static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
IanBenzMaxim 0:33d4e66780c0 129 PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
IanBenzMaxim 0:33d4e66780c0 130 }
IanBenzMaxim 0:33d4e66780c0 131 else if (codepoint <= 0xFFFF) {
IanBenzMaxim 0:33d4e66780c0 132 PutUnsafe(os, static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
IanBenzMaxim 0:33d4e66780c0 133 PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
IanBenzMaxim 0:33d4e66780c0 134 PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F)));
IanBenzMaxim 0:33d4e66780c0 135 }
IanBenzMaxim 0:33d4e66780c0 136 else {
IanBenzMaxim 0:33d4e66780c0 137 RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
IanBenzMaxim 0:33d4e66780c0 138 PutUnsafe(os, static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
IanBenzMaxim 0:33d4e66780c0 139 PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
IanBenzMaxim 0:33d4e66780c0 140 PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
IanBenzMaxim 0:33d4e66780c0 141 PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F)));
IanBenzMaxim 0:33d4e66780c0 142 }
IanBenzMaxim 0:33d4e66780c0 143 }
IanBenzMaxim 0:33d4e66780c0 144
IanBenzMaxim 0:33d4e66780c0 145 template <typename InputStream>
IanBenzMaxim 0:33d4e66780c0 146 static bool Decode(InputStream& is, unsigned* codepoint) {
IanBenzMaxim 0:33d4e66780c0 147 #define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu)
IanBenzMaxim 0:33d4e66780c0 148 #define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
IanBenzMaxim 0:33d4e66780c0 149 #define TAIL() COPY(); TRANS(0x70)
IanBenzMaxim 0:33d4e66780c0 150 typename InputStream::Ch c = is.Take();
IanBenzMaxim 0:33d4e66780c0 151 if (!(c & 0x80)) {
IanBenzMaxim 0:33d4e66780c0 152 *codepoint = static_cast<unsigned char>(c);
IanBenzMaxim 0:33d4e66780c0 153 return true;
IanBenzMaxim 0:33d4e66780c0 154 }
IanBenzMaxim 0:33d4e66780c0 155
IanBenzMaxim 0:33d4e66780c0 156 unsigned char type = GetRange(static_cast<unsigned char>(c));
IanBenzMaxim 0:33d4e66780c0 157 if (type >= 32) {
IanBenzMaxim 0:33d4e66780c0 158 *codepoint = 0;
IanBenzMaxim 0:33d4e66780c0 159 } else {
IanBenzMaxim 0:33d4e66780c0 160 *codepoint = (0xFF >> type) & static_cast<unsigned char>(c);
IanBenzMaxim 0:33d4e66780c0 161 }
IanBenzMaxim 0:33d4e66780c0 162 bool result = true;
IanBenzMaxim 0:33d4e66780c0 163 switch (type) {
IanBenzMaxim 0:33d4e66780c0 164 case 2: TAIL(); return result;
IanBenzMaxim 0:33d4e66780c0 165 case 3: TAIL(); TAIL(); return result;
IanBenzMaxim 0:33d4e66780c0 166 case 4: COPY(); TRANS(0x50); TAIL(); return result;
IanBenzMaxim 0:33d4e66780c0 167 case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
IanBenzMaxim 0:33d4e66780c0 168 case 6: TAIL(); TAIL(); TAIL(); return result;
IanBenzMaxim 0:33d4e66780c0 169 case 10: COPY(); TRANS(0x20); TAIL(); return result;
IanBenzMaxim 0:33d4e66780c0 170 case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
IanBenzMaxim 0:33d4e66780c0 171 default: return false;
IanBenzMaxim 0:33d4e66780c0 172 }
IanBenzMaxim 0:33d4e66780c0 173 #undef COPY
IanBenzMaxim 0:33d4e66780c0 174 #undef TRANS
IanBenzMaxim 0:33d4e66780c0 175 #undef TAIL
IanBenzMaxim 0:33d4e66780c0 176 }
IanBenzMaxim 0:33d4e66780c0 177
IanBenzMaxim 0:33d4e66780c0 178 template <typename InputStream, typename OutputStream>
IanBenzMaxim 0:33d4e66780c0 179 static bool Validate(InputStream& is, OutputStream& os) {
IanBenzMaxim 0:33d4e66780c0 180 #define COPY() os.Put(c = is.Take())
IanBenzMaxim 0:33d4e66780c0 181 #define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
IanBenzMaxim 0:33d4e66780c0 182 #define TAIL() COPY(); TRANS(0x70)
IanBenzMaxim 0:33d4e66780c0 183 Ch c;
IanBenzMaxim 0:33d4e66780c0 184 COPY();
IanBenzMaxim 0:33d4e66780c0 185 if (!(c & 0x80))
IanBenzMaxim 0:33d4e66780c0 186 return true;
IanBenzMaxim 0:33d4e66780c0 187
IanBenzMaxim 0:33d4e66780c0 188 bool result = true;
IanBenzMaxim 0:33d4e66780c0 189 switch (GetRange(static_cast<unsigned char>(c))) {
IanBenzMaxim 0:33d4e66780c0 190 case 2: TAIL(); return result;
IanBenzMaxim 0:33d4e66780c0 191 case 3: TAIL(); TAIL(); return result;
IanBenzMaxim 0:33d4e66780c0 192 case 4: COPY(); TRANS(0x50); TAIL(); return result;
IanBenzMaxim 0:33d4e66780c0 193 case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
IanBenzMaxim 0:33d4e66780c0 194 case 6: TAIL(); TAIL(); TAIL(); return result;
IanBenzMaxim 0:33d4e66780c0 195 case 10: COPY(); TRANS(0x20); TAIL(); return result;
IanBenzMaxim 0:33d4e66780c0 196 case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
IanBenzMaxim 0:33d4e66780c0 197 default: return false;
IanBenzMaxim 0:33d4e66780c0 198 }
IanBenzMaxim 0:33d4e66780c0 199 #undef COPY
IanBenzMaxim 0:33d4e66780c0 200 #undef TRANS
IanBenzMaxim 0:33d4e66780c0 201 #undef TAIL
IanBenzMaxim 0:33d4e66780c0 202 }
IanBenzMaxim 0:33d4e66780c0 203
IanBenzMaxim 0:33d4e66780c0 204 static unsigned char GetRange(unsigned char c) {
IanBenzMaxim 0:33d4e66780c0 205 // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
IanBenzMaxim 0:33d4e66780c0 206 // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types.
IanBenzMaxim 0:33d4e66780c0 207 static const unsigned char type[] = {
IanBenzMaxim 0:33d4e66780c0 208 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,
IanBenzMaxim 0:33d4e66780c0 209 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,
IanBenzMaxim 0:33d4e66780c0 210 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,
IanBenzMaxim 0:33d4e66780c0 211 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,
IanBenzMaxim 0:33d4e66780c0 212 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
IanBenzMaxim 0:33d4e66780c0 213 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
IanBenzMaxim 0:33d4e66780c0 214 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
IanBenzMaxim 0:33d4e66780c0 215 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
IanBenzMaxim 0:33d4e66780c0 216 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,
IanBenzMaxim 0:33d4e66780c0 217 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,
IanBenzMaxim 0:33d4e66780c0 218 };
IanBenzMaxim 0:33d4e66780c0 219 return type[c];
IanBenzMaxim 0:33d4e66780c0 220 }
IanBenzMaxim 0:33d4e66780c0 221
IanBenzMaxim 0:33d4e66780c0 222 template <typename InputByteStream>
IanBenzMaxim 0:33d4e66780c0 223 static CharType TakeBOM(InputByteStream& is) {
IanBenzMaxim 0:33d4e66780c0 224 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 225 typename InputByteStream::Ch c = Take(is);
IanBenzMaxim 0:33d4e66780c0 226 if (static_cast<unsigned char>(c) != 0xEFu) return c;
IanBenzMaxim 0:33d4e66780c0 227 c = is.Take();
IanBenzMaxim 0:33d4e66780c0 228 if (static_cast<unsigned char>(c) != 0xBBu) return c;
IanBenzMaxim 0:33d4e66780c0 229 c = is.Take();
IanBenzMaxim 0:33d4e66780c0 230 if (static_cast<unsigned char>(c) != 0xBFu) return c;
IanBenzMaxim 0:33d4e66780c0 231 c = is.Take();
IanBenzMaxim 0:33d4e66780c0 232 return c;
IanBenzMaxim 0:33d4e66780c0 233 }
IanBenzMaxim 0:33d4e66780c0 234
IanBenzMaxim 0:33d4e66780c0 235 template <typename InputByteStream>
IanBenzMaxim 0:33d4e66780c0 236 static Ch Take(InputByteStream& is) {
IanBenzMaxim 0:33d4e66780c0 237 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 238 return static_cast<Ch>(is.Take());
IanBenzMaxim 0:33d4e66780c0 239 }
IanBenzMaxim 0:33d4e66780c0 240
IanBenzMaxim 0:33d4e66780c0 241 template <typename OutputByteStream>
IanBenzMaxim 0:33d4e66780c0 242 static void PutBOM(OutputByteStream& os) {
IanBenzMaxim 0:33d4e66780c0 243 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 244 os.Put(static_cast<typename OutputByteStream::Ch>(0xEFu));
IanBenzMaxim 0:33d4e66780c0 245 os.Put(static_cast<typename OutputByteStream::Ch>(0xBBu));
IanBenzMaxim 0:33d4e66780c0 246 os.Put(static_cast<typename OutputByteStream::Ch>(0xBFu));
IanBenzMaxim 0:33d4e66780c0 247 }
IanBenzMaxim 0:33d4e66780c0 248
IanBenzMaxim 0:33d4e66780c0 249 template <typename OutputByteStream>
IanBenzMaxim 0:33d4e66780c0 250 static void Put(OutputByteStream& os, Ch c) {
IanBenzMaxim 0:33d4e66780c0 251 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 252 os.Put(static_cast<typename OutputByteStream::Ch>(c));
IanBenzMaxim 0:33d4e66780c0 253 }
IanBenzMaxim 0:33d4e66780c0 254 };
IanBenzMaxim 0:33d4e66780c0 255
IanBenzMaxim 0:33d4e66780c0 256 ///////////////////////////////////////////////////////////////////////////////
IanBenzMaxim 0:33d4e66780c0 257 // UTF16
IanBenzMaxim 0:33d4e66780c0 258
IanBenzMaxim 0:33d4e66780c0 259 //! UTF-16 encoding.
IanBenzMaxim 0:33d4e66780c0 260 /*! http://en.wikipedia.org/wiki/UTF-16
IanBenzMaxim 0:33d4e66780c0 261 http://tools.ietf.org/html/rfc2781
IanBenzMaxim 0:33d4e66780c0 262 \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead.
IanBenzMaxim 0:33d4e66780c0 263 \note implements Encoding concept
IanBenzMaxim 0:33d4e66780c0 264
IanBenzMaxim 0:33d4e66780c0 265 \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
IanBenzMaxim 0:33d4e66780c0 266 For streaming, use UTF16LE and UTF16BE, which handle endianness.
IanBenzMaxim 0:33d4e66780c0 267 */
IanBenzMaxim 0:33d4e66780c0 268 template<typename CharType = wchar_t>
IanBenzMaxim 0:33d4e66780c0 269 struct UTF16 {
IanBenzMaxim 0:33d4e66780c0 270 typedef CharType Ch;
IanBenzMaxim 0:33d4e66780c0 271 RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);
IanBenzMaxim 0:33d4e66780c0 272
IanBenzMaxim 0:33d4e66780c0 273 enum { supportUnicode = 1 };
IanBenzMaxim 0:33d4e66780c0 274
IanBenzMaxim 0:33d4e66780c0 275 template<typename OutputStream>
IanBenzMaxim 0:33d4e66780c0 276 static void Encode(OutputStream& os, unsigned codepoint) {
IanBenzMaxim 0:33d4e66780c0 277 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
IanBenzMaxim 0:33d4e66780c0 278 if (codepoint <= 0xFFFF) {
IanBenzMaxim 0:33d4e66780c0 279 RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
IanBenzMaxim 0:33d4e66780c0 280 os.Put(static_cast<typename OutputStream::Ch>(codepoint));
IanBenzMaxim 0:33d4e66780c0 281 }
IanBenzMaxim 0:33d4e66780c0 282 else {
IanBenzMaxim 0:33d4e66780c0 283 RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
IanBenzMaxim 0:33d4e66780c0 284 unsigned v = codepoint - 0x10000;
IanBenzMaxim 0:33d4e66780c0 285 os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
IanBenzMaxim 0:33d4e66780c0 286 os.Put((v & 0x3FF) | 0xDC00);
IanBenzMaxim 0:33d4e66780c0 287 }
IanBenzMaxim 0:33d4e66780c0 288 }
IanBenzMaxim 0:33d4e66780c0 289
IanBenzMaxim 0:33d4e66780c0 290
IanBenzMaxim 0:33d4e66780c0 291 template<typename OutputStream>
IanBenzMaxim 0:33d4e66780c0 292 static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
IanBenzMaxim 0:33d4e66780c0 293 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
IanBenzMaxim 0:33d4e66780c0 294 if (codepoint <= 0xFFFF) {
IanBenzMaxim 0:33d4e66780c0 295 RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
IanBenzMaxim 0:33d4e66780c0 296 PutUnsafe(os, static_cast<typename OutputStream::Ch>(codepoint));
IanBenzMaxim 0:33d4e66780c0 297 }
IanBenzMaxim 0:33d4e66780c0 298 else {
IanBenzMaxim 0:33d4e66780c0 299 RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
IanBenzMaxim 0:33d4e66780c0 300 unsigned v = codepoint - 0x10000;
IanBenzMaxim 0:33d4e66780c0 301 PutUnsafe(os, static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
IanBenzMaxim 0:33d4e66780c0 302 PutUnsafe(os, (v & 0x3FF) | 0xDC00);
IanBenzMaxim 0:33d4e66780c0 303 }
IanBenzMaxim 0:33d4e66780c0 304 }
IanBenzMaxim 0:33d4e66780c0 305
IanBenzMaxim 0:33d4e66780c0 306 template <typename InputStream>
IanBenzMaxim 0:33d4e66780c0 307 static bool Decode(InputStream& is, unsigned* codepoint) {
IanBenzMaxim 0:33d4e66780c0 308 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
IanBenzMaxim 0:33d4e66780c0 309 typename InputStream::Ch c = is.Take();
IanBenzMaxim 0:33d4e66780c0 310 if (c < 0xD800 || c > 0xDFFF) {
IanBenzMaxim 0:33d4e66780c0 311 *codepoint = static_cast<unsigned>(c);
IanBenzMaxim 0:33d4e66780c0 312 return true;
IanBenzMaxim 0:33d4e66780c0 313 }
IanBenzMaxim 0:33d4e66780c0 314 else if (c <= 0xDBFF) {
IanBenzMaxim 0:33d4e66780c0 315 *codepoint = (static_cast<unsigned>(c) & 0x3FF) << 10;
IanBenzMaxim 0:33d4e66780c0 316 c = is.Take();
IanBenzMaxim 0:33d4e66780c0 317 *codepoint |= (static_cast<unsigned>(c) & 0x3FF);
IanBenzMaxim 0:33d4e66780c0 318 *codepoint += 0x10000;
IanBenzMaxim 0:33d4e66780c0 319 return c >= 0xDC00 && c <= 0xDFFF;
IanBenzMaxim 0:33d4e66780c0 320 }
IanBenzMaxim 0:33d4e66780c0 321 return false;
IanBenzMaxim 0:33d4e66780c0 322 }
IanBenzMaxim 0:33d4e66780c0 323
IanBenzMaxim 0:33d4e66780c0 324 template <typename InputStream, typename OutputStream>
IanBenzMaxim 0:33d4e66780c0 325 static bool Validate(InputStream& is, OutputStream& os) {
IanBenzMaxim 0:33d4e66780c0 326 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
IanBenzMaxim 0:33d4e66780c0 327 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
IanBenzMaxim 0:33d4e66780c0 328 typename InputStream::Ch c;
IanBenzMaxim 0:33d4e66780c0 329 os.Put(static_cast<typename OutputStream::Ch>(c = is.Take()));
IanBenzMaxim 0:33d4e66780c0 330 if (c < 0xD800 || c > 0xDFFF)
IanBenzMaxim 0:33d4e66780c0 331 return true;
IanBenzMaxim 0:33d4e66780c0 332 else if (c <= 0xDBFF) {
IanBenzMaxim 0:33d4e66780c0 333 os.Put(c = is.Take());
IanBenzMaxim 0:33d4e66780c0 334 return c >= 0xDC00 && c <= 0xDFFF;
IanBenzMaxim 0:33d4e66780c0 335 }
IanBenzMaxim 0:33d4e66780c0 336 return false;
IanBenzMaxim 0:33d4e66780c0 337 }
IanBenzMaxim 0:33d4e66780c0 338 };
IanBenzMaxim 0:33d4e66780c0 339
IanBenzMaxim 0:33d4e66780c0 340 //! UTF-16 little endian encoding.
IanBenzMaxim 0:33d4e66780c0 341 template<typename CharType = wchar_t>
IanBenzMaxim 0:33d4e66780c0 342 struct UTF16LE : UTF16<CharType> {
IanBenzMaxim 0:33d4e66780c0 343 template <typename InputByteStream>
IanBenzMaxim 0:33d4e66780c0 344 static CharType TakeBOM(InputByteStream& is) {
IanBenzMaxim 0:33d4e66780c0 345 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 346 CharType c = Take(is);
IanBenzMaxim 0:33d4e66780c0 347 return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
IanBenzMaxim 0:33d4e66780c0 348 }
IanBenzMaxim 0:33d4e66780c0 349
IanBenzMaxim 0:33d4e66780c0 350 template <typename InputByteStream>
IanBenzMaxim 0:33d4e66780c0 351 static CharType Take(InputByteStream& is) {
IanBenzMaxim 0:33d4e66780c0 352 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 353 unsigned c = static_cast<uint8_t>(is.Take());
IanBenzMaxim 0:33d4e66780c0 354 c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
IanBenzMaxim 0:33d4e66780c0 355 return static_cast<CharType>(c);
IanBenzMaxim 0:33d4e66780c0 356 }
IanBenzMaxim 0:33d4e66780c0 357
IanBenzMaxim 0:33d4e66780c0 358 template <typename OutputByteStream>
IanBenzMaxim 0:33d4e66780c0 359 static void PutBOM(OutputByteStream& os) {
IanBenzMaxim 0:33d4e66780c0 360 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 361 os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
IanBenzMaxim 0:33d4e66780c0 362 os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
IanBenzMaxim 0:33d4e66780c0 363 }
IanBenzMaxim 0:33d4e66780c0 364
IanBenzMaxim 0:33d4e66780c0 365 template <typename OutputByteStream>
IanBenzMaxim 0:33d4e66780c0 366 static void Put(OutputByteStream& os, CharType c) {
IanBenzMaxim 0:33d4e66780c0 367 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 368 os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));
IanBenzMaxim 0:33d4e66780c0 369 os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
IanBenzMaxim 0:33d4e66780c0 370 }
IanBenzMaxim 0:33d4e66780c0 371 };
IanBenzMaxim 0:33d4e66780c0 372
IanBenzMaxim 0:33d4e66780c0 373 //! UTF-16 big endian encoding.
IanBenzMaxim 0:33d4e66780c0 374 template<typename CharType = wchar_t>
IanBenzMaxim 0:33d4e66780c0 375 struct UTF16BE : UTF16<CharType> {
IanBenzMaxim 0:33d4e66780c0 376 template <typename InputByteStream>
IanBenzMaxim 0:33d4e66780c0 377 static CharType TakeBOM(InputByteStream& is) {
IanBenzMaxim 0:33d4e66780c0 378 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 379 CharType c = Take(is);
IanBenzMaxim 0:33d4e66780c0 380 return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
IanBenzMaxim 0:33d4e66780c0 381 }
IanBenzMaxim 0:33d4e66780c0 382
IanBenzMaxim 0:33d4e66780c0 383 template <typename InputByteStream>
IanBenzMaxim 0:33d4e66780c0 384 static CharType Take(InputByteStream& is) {
IanBenzMaxim 0:33d4e66780c0 385 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 386 unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
IanBenzMaxim 0:33d4e66780c0 387 c |= static_cast<uint8_t>(is.Take());
IanBenzMaxim 0:33d4e66780c0 388 return static_cast<CharType>(c);
IanBenzMaxim 0:33d4e66780c0 389 }
IanBenzMaxim 0:33d4e66780c0 390
IanBenzMaxim 0:33d4e66780c0 391 template <typename OutputByteStream>
IanBenzMaxim 0:33d4e66780c0 392 static void PutBOM(OutputByteStream& os) {
IanBenzMaxim 0:33d4e66780c0 393 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 394 os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
IanBenzMaxim 0:33d4e66780c0 395 os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
IanBenzMaxim 0:33d4e66780c0 396 }
IanBenzMaxim 0:33d4e66780c0 397
IanBenzMaxim 0:33d4e66780c0 398 template <typename OutputByteStream>
IanBenzMaxim 0:33d4e66780c0 399 static void Put(OutputByteStream& os, CharType c) {
IanBenzMaxim 0:33d4e66780c0 400 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 401 os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
IanBenzMaxim 0:33d4e66780c0 402 os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));
IanBenzMaxim 0:33d4e66780c0 403 }
IanBenzMaxim 0:33d4e66780c0 404 };
IanBenzMaxim 0:33d4e66780c0 405
IanBenzMaxim 0:33d4e66780c0 406 ///////////////////////////////////////////////////////////////////////////////
IanBenzMaxim 0:33d4e66780c0 407 // UTF32
IanBenzMaxim 0:33d4e66780c0 408
IanBenzMaxim 0:33d4e66780c0 409 //! UTF-32 encoding.
IanBenzMaxim 0:33d4e66780c0 410 /*! http://en.wikipedia.org/wiki/UTF-32
IanBenzMaxim 0:33d4e66780c0 411 \tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead.
IanBenzMaxim 0:33d4e66780c0 412 \note implements Encoding concept
IanBenzMaxim 0:33d4e66780c0 413
IanBenzMaxim 0:33d4e66780c0 414 \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
IanBenzMaxim 0:33d4e66780c0 415 For streaming, use UTF32LE and UTF32BE, which handle endianness.
IanBenzMaxim 0:33d4e66780c0 416 */
IanBenzMaxim 0:33d4e66780c0 417 template<typename CharType = unsigned>
IanBenzMaxim 0:33d4e66780c0 418 struct UTF32 {
IanBenzMaxim 0:33d4e66780c0 419 typedef CharType Ch;
IanBenzMaxim 0:33d4e66780c0 420 RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4);
IanBenzMaxim 0:33d4e66780c0 421
IanBenzMaxim 0:33d4e66780c0 422 enum { supportUnicode = 1 };
IanBenzMaxim 0:33d4e66780c0 423
IanBenzMaxim 0:33d4e66780c0 424 template<typename OutputStream>
IanBenzMaxim 0:33d4e66780c0 425 static void Encode(OutputStream& os, unsigned codepoint) {
IanBenzMaxim 0:33d4e66780c0 426 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
IanBenzMaxim 0:33d4e66780c0 427 RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
IanBenzMaxim 0:33d4e66780c0 428 os.Put(codepoint);
IanBenzMaxim 0:33d4e66780c0 429 }
IanBenzMaxim 0:33d4e66780c0 430
IanBenzMaxim 0:33d4e66780c0 431 template<typename OutputStream>
IanBenzMaxim 0:33d4e66780c0 432 static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
IanBenzMaxim 0:33d4e66780c0 433 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
IanBenzMaxim 0:33d4e66780c0 434 RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
IanBenzMaxim 0:33d4e66780c0 435 PutUnsafe(os, codepoint);
IanBenzMaxim 0:33d4e66780c0 436 }
IanBenzMaxim 0:33d4e66780c0 437
IanBenzMaxim 0:33d4e66780c0 438 template <typename InputStream>
IanBenzMaxim 0:33d4e66780c0 439 static bool Decode(InputStream& is, unsigned* codepoint) {
IanBenzMaxim 0:33d4e66780c0 440 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
IanBenzMaxim 0:33d4e66780c0 441 Ch c = is.Take();
IanBenzMaxim 0:33d4e66780c0 442 *codepoint = c;
IanBenzMaxim 0:33d4e66780c0 443 return c <= 0x10FFFF;
IanBenzMaxim 0:33d4e66780c0 444 }
IanBenzMaxim 0:33d4e66780c0 445
IanBenzMaxim 0:33d4e66780c0 446 template <typename InputStream, typename OutputStream>
IanBenzMaxim 0:33d4e66780c0 447 static bool Validate(InputStream& is, OutputStream& os) {
IanBenzMaxim 0:33d4e66780c0 448 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
IanBenzMaxim 0:33d4e66780c0 449 Ch c;
IanBenzMaxim 0:33d4e66780c0 450 os.Put(c = is.Take());
IanBenzMaxim 0:33d4e66780c0 451 return c <= 0x10FFFF;
IanBenzMaxim 0:33d4e66780c0 452 }
IanBenzMaxim 0:33d4e66780c0 453 };
IanBenzMaxim 0:33d4e66780c0 454
IanBenzMaxim 0:33d4e66780c0 455 //! UTF-32 little endian enocoding.
IanBenzMaxim 0:33d4e66780c0 456 template<typename CharType = unsigned>
IanBenzMaxim 0:33d4e66780c0 457 struct UTF32LE : UTF32<CharType> {
IanBenzMaxim 0:33d4e66780c0 458 template <typename InputByteStream>
IanBenzMaxim 0:33d4e66780c0 459 static CharType TakeBOM(InputByteStream& is) {
IanBenzMaxim 0:33d4e66780c0 460 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 461 CharType c = Take(is);
IanBenzMaxim 0:33d4e66780c0 462 return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;
IanBenzMaxim 0:33d4e66780c0 463 }
IanBenzMaxim 0:33d4e66780c0 464
IanBenzMaxim 0:33d4e66780c0 465 template <typename InputByteStream>
IanBenzMaxim 0:33d4e66780c0 466 static CharType Take(InputByteStream& is) {
IanBenzMaxim 0:33d4e66780c0 467 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 468 unsigned c = static_cast<uint8_t>(is.Take());
IanBenzMaxim 0:33d4e66780c0 469 c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
IanBenzMaxim 0:33d4e66780c0 470 c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
IanBenzMaxim 0:33d4e66780c0 471 c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
IanBenzMaxim 0:33d4e66780c0 472 return static_cast<CharType>(c);
IanBenzMaxim 0:33d4e66780c0 473 }
IanBenzMaxim 0:33d4e66780c0 474
IanBenzMaxim 0:33d4e66780c0 475 template <typename OutputByteStream>
IanBenzMaxim 0:33d4e66780c0 476 static void PutBOM(OutputByteStream& os) {
IanBenzMaxim 0:33d4e66780c0 477 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 478 os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
IanBenzMaxim 0:33d4e66780c0 479 os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
IanBenzMaxim 0:33d4e66780c0 480 os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
IanBenzMaxim 0:33d4e66780c0 481 os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
IanBenzMaxim 0:33d4e66780c0 482 }
IanBenzMaxim 0:33d4e66780c0 483
IanBenzMaxim 0:33d4e66780c0 484 template <typename OutputByteStream>
IanBenzMaxim 0:33d4e66780c0 485 static void Put(OutputByteStream& os, CharType c) {
IanBenzMaxim 0:33d4e66780c0 486 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 487 os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu));
IanBenzMaxim 0:33d4e66780c0 488 os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
IanBenzMaxim 0:33d4e66780c0 489 os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
IanBenzMaxim 0:33d4e66780c0 490 os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));
IanBenzMaxim 0:33d4e66780c0 491 }
IanBenzMaxim 0:33d4e66780c0 492 };
IanBenzMaxim 0:33d4e66780c0 493
IanBenzMaxim 0:33d4e66780c0 494 //! UTF-32 big endian encoding.
IanBenzMaxim 0:33d4e66780c0 495 template<typename CharType = unsigned>
IanBenzMaxim 0:33d4e66780c0 496 struct UTF32BE : UTF32<CharType> {
IanBenzMaxim 0:33d4e66780c0 497 template <typename InputByteStream>
IanBenzMaxim 0:33d4e66780c0 498 static CharType TakeBOM(InputByteStream& is) {
IanBenzMaxim 0:33d4e66780c0 499 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 500 CharType c = Take(is);
IanBenzMaxim 0:33d4e66780c0 501 return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;
IanBenzMaxim 0:33d4e66780c0 502 }
IanBenzMaxim 0:33d4e66780c0 503
IanBenzMaxim 0:33d4e66780c0 504 template <typename InputByteStream>
IanBenzMaxim 0:33d4e66780c0 505 static CharType Take(InputByteStream& is) {
IanBenzMaxim 0:33d4e66780c0 506 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 507 unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
IanBenzMaxim 0:33d4e66780c0 508 c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
IanBenzMaxim 0:33d4e66780c0 509 c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
IanBenzMaxim 0:33d4e66780c0 510 c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take()));
IanBenzMaxim 0:33d4e66780c0 511 return static_cast<CharType>(c);
IanBenzMaxim 0:33d4e66780c0 512 }
IanBenzMaxim 0:33d4e66780c0 513
IanBenzMaxim 0:33d4e66780c0 514 template <typename OutputByteStream>
IanBenzMaxim 0:33d4e66780c0 515 static void PutBOM(OutputByteStream& os) {
IanBenzMaxim 0:33d4e66780c0 516 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 517 os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
IanBenzMaxim 0:33d4e66780c0 518 os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
IanBenzMaxim 0:33d4e66780c0 519 os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
IanBenzMaxim 0:33d4e66780c0 520 os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
IanBenzMaxim 0:33d4e66780c0 521 }
IanBenzMaxim 0:33d4e66780c0 522
IanBenzMaxim 0:33d4e66780c0 523 template <typename OutputByteStream>
IanBenzMaxim 0:33d4e66780c0 524 static void Put(OutputByteStream& os, CharType c) {
IanBenzMaxim 0:33d4e66780c0 525 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 526 os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));
IanBenzMaxim 0:33d4e66780c0 527 os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
IanBenzMaxim 0:33d4e66780c0 528 os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
IanBenzMaxim 0:33d4e66780c0 529 os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu));
IanBenzMaxim 0:33d4e66780c0 530 }
IanBenzMaxim 0:33d4e66780c0 531 };
IanBenzMaxim 0:33d4e66780c0 532
IanBenzMaxim 0:33d4e66780c0 533 ///////////////////////////////////////////////////////////////////////////////
IanBenzMaxim 0:33d4e66780c0 534 // ASCII
IanBenzMaxim 0:33d4e66780c0 535
IanBenzMaxim 0:33d4e66780c0 536 //! ASCII encoding.
IanBenzMaxim 0:33d4e66780c0 537 /*! http://en.wikipedia.org/wiki/ASCII
IanBenzMaxim 0:33d4e66780c0 538 \tparam CharType Code unit for storing 7-bit ASCII data. Default is char.
IanBenzMaxim 0:33d4e66780c0 539 \note implements Encoding concept
IanBenzMaxim 0:33d4e66780c0 540 */
IanBenzMaxim 0:33d4e66780c0 541 template<typename CharType = char>
IanBenzMaxim 0:33d4e66780c0 542 struct ASCII {
IanBenzMaxim 0:33d4e66780c0 543 typedef CharType Ch;
IanBenzMaxim 0:33d4e66780c0 544
IanBenzMaxim 0:33d4e66780c0 545 enum { supportUnicode = 0 };
IanBenzMaxim 0:33d4e66780c0 546
IanBenzMaxim 0:33d4e66780c0 547 template<typename OutputStream>
IanBenzMaxim 0:33d4e66780c0 548 static void Encode(OutputStream& os, unsigned codepoint) {
IanBenzMaxim 0:33d4e66780c0 549 RAPIDJSON_ASSERT(codepoint <= 0x7F);
IanBenzMaxim 0:33d4e66780c0 550 os.Put(static_cast<Ch>(codepoint & 0xFF));
IanBenzMaxim 0:33d4e66780c0 551 }
IanBenzMaxim 0:33d4e66780c0 552
IanBenzMaxim 0:33d4e66780c0 553 template<typename OutputStream>
IanBenzMaxim 0:33d4e66780c0 554 static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
IanBenzMaxim 0:33d4e66780c0 555 RAPIDJSON_ASSERT(codepoint <= 0x7F);
IanBenzMaxim 0:33d4e66780c0 556 PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
IanBenzMaxim 0:33d4e66780c0 557 }
IanBenzMaxim 0:33d4e66780c0 558
IanBenzMaxim 0:33d4e66780c0 559 template <typename InputStream>
IanBenzMaxim 0:33d4e66780c0 560 static bool Decode(InputStream& is, unsigned* codepoint) {
IanBenzMaxim 0:33d4e66780c0 561 uint8_t c = static_cast<uint8_t>(is.Take());
IanBenzMaxim 0:33d4e66780c0 562 *codepoint = c;
IanBenzMaxim 0:33d4e66780c0 563 return c <= 0X7F;
IanBenzMaxim 0:33d4e66780c0 564 }
IanBenzMaxim 0:33d4e66780c0 565
IanBenzMaxim 0:33d4e66780c0 566 template <typename InputStream, typename OutputStream>
IanBenzMaxim 0:33d4e66780c0 567 static bool Validate(InputStream& is, OutputStream& os) {
IanBenzMaxim 0:33d4e66780c0 568 uint8_t c = static_cast<uint8_t>(is.Take());
IanBenzMaxim 0:33d4e66780c0 569 os.Put(static_cast<typename OutputStream::Ch>(c));
IanBenzMaxim 0:33d4e66780c0 570 return c <= 0x7F;
IanBenzMaxim 0:33d4e66780c0 571 }
IanBenzMaxim 0:33d4e66780c0 572
IanBenzMaxim 0:33d4e66780c0 573 template <typename InputByteStream>
IanBenzMaxim 0:33d4e66780c0 574 static CharType TakeBOM(InputByteStream& is) {
IanBenzMaxim 0:33d4e66780c0 575 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 576 uint8_t c = static_cast<uint8_t>(Take(is));
IanBenzMaxim 0:33d4e66780c0 577 return static_cast<Ch>(c);
IanBenzMaxim 0:33d4e66780c0 578 }
IanBenzMaxim 0:33d4e66780c0 579
IanBenzMaxim 0:33d4e66780c0 580 template <typename InputByteStream>
IanBenzMaxim 0:33d4e66780c0 581 static Ch Take(InputByteStream& is) {
IanBenzMaxim 0:33d4e66780c0 582 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 583 return static_cast<Ch>(is.Take());
IanBenzMaxim 0:33d4e66780c0 584 }
IanBenzMaxim 0:33d4e66780c0 585
IanBenzMaxim 0:33d4e66780c0 586 template <typename OutputByteStream>
IanBenzMaxim 0:33d4e66780c0 587 static void PutBOM(OutputByteStream& os) {
IanBenzMaxim 0:33d4e66780c0 588 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 589 (void)os;
IanBenzMaxim 0:33d4e66780c0 590 }
IanBenzMaxim 0:33d4e66780c0 591
IanBenzMaxim 0:33d4e66780c0 592 template <typename OutputByteStream>
IanBenzMaxim 0:33d4e66780c0 593 static void Put(OutputByteStream& os, Ch c) {
IanBenzMaxim 0:33d4e66780c0 594 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 595 os.Put(static_cast<typename OutputByteStream::Ch>(c));
IanBenzMaxim 0:33d4e66780c0 596 }
IanBenzMaxim 0:33d4e66780c0 597 };
IanBenzMaxim 0:33d4e66780c0 598
IanBenzMaxim 0:33d4e66780c0 599 ///////////////////////////////////////////////////////////////////////////////
IanBenzMaxim 0:33d4e66780c0 600 // AutoUTF
IanBenzMaxim 0:33d4e66780c0 601
IanBenzMaxim 0:33d4e66780c0 602 //! Runtime-specified UTF encoding type of a stream.
IanBenzMaxim 0:33d4e66780c0 603 enum UTFType {
IanBenzMaxim 0:33d4e66780c0 604 kUTF8 = 0, //!< UTF-8.
IanBenzMaxim 0:33d4e66780c0 605 kUTF16LE = 1, //!< UTF-16 little endian.
IanBenzMaxim 0:33d4e66780c0 606 kUTF16BE = 2, //!< UTF-16 big endian.
IanBenzMaxim 0:33d4e66780c0 607 kUTF32LE = 3, //!< UTF-32 little endian.
IanBenzMaxim 0:33d4e66780c0 608 kUTF32BE = 4 //!< UTF-32 big endian.
IanBenzMaxim 0:33d4e66780c0 609 };
IanBenzMaxim 0:33d4e66780c0 610
IanBenzMaxim 0:33d4e66780c0 611 //! Dynamically select encoding according to stream's runtime-specified UTF encoding type.
IanBenzMaxim 0:33d4e66780c0 612 /*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType().
IanBenzMaxim 0:33d4e66780c0 613 */
IanBenzMaxim 0:33d4e66780c0 614 template<typename CharType>
IanBenzMaxim 0:33d4e66780c0 615 struct AutoUTF {
IanBenzMaxim 0:33d4e66780c0 616 typedef CharType Ch;
IanBenzMaxim 0:33d4e66780c0 617
IanBenzMaxim 0:33d4e66780c0 618 enum { supportUnicode = 1 };
IanBenzMaxim 0:33d4e66780c0 619
IanBenzMaxim 0:33d4e66780c0 620 #define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
IanBenzMaxim 0:33d4e66780c0 621
IanBenzMaxim 0:33d4e66780c0 622 template<typename OutputStream>
IanBenzMaxim 0:33d4e66780c0 623 RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) {
IanBenzMaxim 0:33d4e66780c0 624 typedef void (*EncodeFunc)(OutputStream&, unsigned);
IanBenzMaxim 0:33d4e66780c0 625 static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };
IanBenzMaxim 0:33d4e66780c0 626 (*f[os.GetType()])(os, codepoint);
IanBenzMaxim 0:33d4e66780c0 627 }
IanBenzMaxim 0:33d4e66780c0 628
IanBenzMaxim 0:33d4e66780c0 629 template<typename OutputStream>
IanBenzMaxim 0:33d4e66780c0 630 RAPIDJSON_FORCEINLINE static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
IanBenzMaxim 0:33d4e66780c0 631 typedef void (*EncodeFunc)(OutputStream&, unsigned);
IanBenzMaxim 0:33d4e66780c0 632 static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) };
IanBenzMaxim 0:33d4e66780c0 633 (*f[os.GetType()])(os, codepoint);
IanBenzMaxim 0:33d4e66780c0 634 }
IanBenzMaxim 0:33d4e66780c0 635
IanBenzMaxim 0:33d4e66780c0 636 template <typename InputStream>
IanBenzMaxim 0:33d4e66780c0 637 RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) {
IanBenzMaxim 0:33d4e66780c0 638 typedef bool (*DecodeFunc)(InputStream&, unsigned*);
IanBenzMaxim 0:33d4e66780c0 639 static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) };
IanBenzMaxim 0:33d4e66780c0 640 return (*f[is.GetType()])(is, codepoint);
IanBenzMaxim 0:33d4e66780c0 641 }
IanBenzMaxim 0:33d4e66780c0 642
IanBenzMaxim 0:33d4e66780c0 643 template <typename InputStream, typename OutputStream>
IanBenzMaxim 0:33d4e66780c0 644 RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
IanBenzMaxim 0:33d4e66780c0 645 typedef bool (*ValidateFunc)(InputStream&, OutputStream&);
IanBenzMaxim 0:33d4e66780c0 646 static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) };
IanBenzMaxim 0:33d4e66780c0 647 return (*f[is.GetType()])(is, os);
IanBenzMaxim 0:33d4e66780c0 648 }
IanBenzMaxim 0:33d4e66780c0 649
IanBenzMaxim 0:33d4e66780c0 650 #undef RAPIDJSON_ENCODINGS_FUNC
IanBenzMaxim 0:33d4e66780c0 651 };
IanBenzMaxim 0:33d4e66780c0 652
IanBenzMaxim 0:33d4e66780c0 653 ///////////////////////////////////////////////////////////////////////////////
IanBenzMaxim 0:33d4e66780c0 654 // Transcoder
IanBenzMaxim 0:33d4e66780c0 655
IanBenzMaxim 0:33d4e66780c0 656 //! Encoding conversion.
IanBenzMaxim 0:33d4e66780c0 657 template<typename SourceEncoding, typename TargetEncoding>
IanBenzMaxim 0:33d4e66780c0 658 struct Transcoder {
IanBenzMaxim 0:33d4e66780c0 659 //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream.
IanBenzMaxim 0:33d4e66780c0 660 template<typename InputStream, typename OutputStream>
IanBenzMaxim 0:33d4e66780c0 661 RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
IanBenzMaxim 0:33d4e66780c0 662 unsigned codepoint;
IanBenzMaxim 0:33d4e66780c0 663 if (!SourceEncoding::Decode(is, &codepoint))
IanBenzMaxim 0:33d4e66780c0 664 return false;
IanBenzMaxim 0:33d4e66780c0 665 TargetEncoding::Encode(os, codepoint);
IanBenzMaxim 0:33d4e66780c0 666 return true;
IanBenzMaxim 0:33d4e66780c0 667 }
IanBenzMaxim 0:33d4e66780c0 668
IanBenzMaxim 0:33d4e66780c0 669 template<typename InputStream, typename OutputStream>
IanBenzMaxim 0:33d4e66780c0 670 RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
IanBenzMaxim 0:33d4e66780c0 671 unsigned codepoint;
IanBenzMaxim 0:33d4e66780c0 672 if (!SourceEncoding::Decode(is, &codepoint))
IanBenzMaxim 0:33d4e66780c0 673 return false;
IanBenzMaxim 0:33d4e66780c0 674 TargetEncoding::EncodeUnsafe(os, codepoint);
IanBenzMaxim 0:33d4e66780c0 675 return true;
IanBenzMaxim 0:33d4e66780c0 676 }
IanBenzMaxim 0:33d4e66780c0 677
IanBenzMaxim 0:33d4e66780c0 678 //! Validate one Unicode codepoint from an encoded stream.
IanBenzMaxim 0:33d4e66780c0 679 template<typename InputStream, typename OutputStream>
IanBenzMaxim 0:33d4e66780c0 680 RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
IanBenzMaxim 0:33d4e66780c0 681 return Transcode(is, os); // Since source/target encoding is different, must transcode.
IanBenzMaxim 0:33d4e66780c0 682 }
IanBenzMaxim 0:33d4e66780c0 683 };
IanBenzMaxim 0:33d4e66780c0 684
IanBenzMaxim 0:33d4e66780c0 685 // Forward declaration.
IanBenzMaxim 0:33d4e66780c0 686 template<typename Stream>
IanBenzMaxim 0:33d4e66780c0 687 inline void PutUnsafe(Stream& stream, typename Stream::Ch c);
IanBenzMaxim 0:33d4e66780c0 688
IanBenzMaxim 0:33d4e66780c0 689 //! Specialization of Transcoder with same source and target encoding.
IanBenzMaxim 0:33d4e66780c0 690 template<typename Encoding>
IanBenzMaxim 0:33d4e66780c0 691 struct Transcoder<Encoding, Encoding> {
IanBenzMaxim 0:33d4e66780c0 692 template<typename InputStream, typename OutputStream>
IanBenzMaxim 0:33d4e66780c0 693 RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
IanBenzMaxim 0:33d4e66780c0 694 os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class.
IanBenzMaxim 0:33d4e66780c0 695 return true;
IanBenzMaxim 0:33d4e66780c0 696 }
IanBenzMaxim 0:33d4e66780c0 697
IanBenzMaxim 0:33d4e66780c0 698 template<typename InputStream, typename OutputStream>
IanBenzMaxim 0:33d4e66780c0 699 RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
IanBenzMaxim 0:33d4e66780c0 700 PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class.
IanBenzMaxim 0:33d4e66780c0 701 return true;
IanBenzMaxim 0:33d4e66780c0 702 }
IanBenzMaxim 0:33d4e66780c0 703
IanBenzMaxim 0:33d4e66780c0 704 template<typename InputStream, typename OutputStream>
IanBenzMaxim 0:33d4e66780c0 705 RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
IanBenzMaxim 0:33d4e66780c0 706 return Encoding::Validate(is, os); // source/target encoding are the same
IanBenzMaxim 0:33d4e66780c0 707 }
IanBenzMaxim 0:33d4e66780c0 708 };
IanBenzMaxim 0:33d4e66780c0 709
IanBenzMaxim 0:33d4e66780c0 710 RAPIDJSON_NAMESPACE_END
IanBenzMaxim 0:33d4e66780c0 711
IanBenzMaxim 0:33d4e66780c0 712 #if defined(__GNUC__) || defined(_MSC_VER)
IanBenzMaxim 0:33d4e66780c0 713 RAPIDJSON_DIAG_POP
IanBenzMaxim 0:33d4e66780c0 714 #endif
IanBenzMaxim 0:33d4e66780c0 715
IanBenzMaxim 0:33d4e66780c0 716 #endif // RAPIDJSON_ENCODINGS_H_