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:
Tue Dec 03 12:56:25 2019 -0600
Revision:
18:c2631e985780
Parent:
16:a004191a79ab
Updated MaximInterface to version 2.1.

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_ENCODEDSTREAM_H_
IanBenzMaxim 0:33d4e66780c0 16 #define RAPIDJSON_ENCODEDSTREAM_H_
IanBenzMaxim 0:33d4e66780c0 17
IanBenzMaxim 0:33d4e66780c0 18 #include "stream.h"
IanBenzMaxim 0:33d4e66780c0 19 #include "memorystream.h"
IanBenzMaxim 0:33d4e66780c0 20
IanBenzMaxim 0:33d4e66780c0 21 #ifdef __GNUC__
IanBenzMaxim 0:33d4e66780c0 22 RAPIDJSON_DIAG_PUSH
IanBenzMaxim 0:33d4e66780c0 23 RAPIDJSON_DIAG_OFF(effc++)
IanBenzMaxim 0:33d4e66780c0 24 #endif
IanBenzMaxim 0:33d4e66780c0 25
IanBenzMaxim 0:33d4e66780c0 26 #ifdef __clang__
IanBenzMaxim 0:33d4e66780c0 27 RAPIDJSON_DIAG_PUSH
IanBenzMaxim 0:33d4e66780c0 28 RAPIDJSON_DIAG_OFF(padded)
IanBenzMaxim 0:33d4e66780c0 29 #endif
IanBenzMaxim 0:33d4e66780c0 30
IanBenzMaxim 0:33d4e66780c0 31 RAPIDJSON_NAMESPACE_BEGIN
IanBenzMaxim 0:33d4e66780c0 32
IanBenzMaxim 0:33d4e66780c0 33 //! Input byte stream wrapper with a statically bound encoding.
IanBenzMaxim 0:33d4e66780c0 34 /*!
IanBenzMaxim 0:33d4e66780c0 35 \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
IanBenzMaxim 0:33d4e66780c0 36 \tparam InputByteStream Type of input byte stream. For example, FileReadStream.
IanBenzMaxim 0:33d4e66780c0 37 */
IanBenzMaxim 0:33d4e66780c0 38 template <typename Encoding, typename InputByteStream>
IanBenzMaxim 0:33d4e66780c0 39 class EncodedInputStream {
IanBenzMaxim 0:33d4e66780c0 40 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 41 public:
IanBenzMaxim 0:33d4e66780c0 42 typedef typename Encoding::Ch Ch;
IanBenzMaxim 0:33d4e66780c0 43
IanBenzMaxim 0:33d4e66780c0 44 EncodedInputStream(InputByteStream& is) : is_(is) {
IanBenzMaxim 0:33d4e66780c0 45 current_ = Encoding::TakeBOM(is_);
IanBenzMaxim 0:33d4e66780c0 46 }
IanBenzMaxim 0:33d4e66780c0 47
IanBenzMaxim 0:33d4e66780c0 48 Ch Peek() const { return current_; }
IanBenzMaxim 0:33d4e66780c0 49 Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; }
IanBenzMaxim 0:33d4e66780c0 50 size_t Tell() const { return is_.Tell(); }
IanBenzMaxim 0:33d4e66780c0 51
IanBenzMaxim 0:33d4e66780c0 52 // Not implemented
IanBenzMaxim 0:33d4e66780c0 53 void Put(Ch) { RAPIDJSON_ASSERT(false); }
IanBenzMaxim 0:33d4e66780c0 54 void Flush() { RAPIDJSON_ASSERT(false); }
IanBenzMaxim 0:33d4e66780c0 55 Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
IanBenzMaxim 0:33d4e66780c0 56 size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
IanBenzMaxim 0:33d4e66780c0 57
IanBenzMaxim 0:33d4e66780c0 58 private:
IanBenzMaxim 0:33d4e66780c0 59 EncodedInputStream(const EncodedInputStream&);
IanBenzMaxim 0:33d4e66780c0 60 EncodedInputStream& operator=(const EncodedInputStream&);
IanBenzMaxim 0:33d4e66780c0 61
IanBenzMaxim 0:33d4e66780c0 62 InputByteStream& is_;
IanBenzMaxim 0:33d4e66780c0 63 Ch current_;
IanBenzMaxim 0:33d4e66780c0 64 };
IanBenzMaxim 0:33d4e66780c0 65
IanBenzMaxim 0:33d4e66780c0 66 //! Specialized for UTF8 MemoryStream.
IanBenzMaxim 0:33d4e66780c0 67 template <>
IanBenzMaxim 0:33d4e66780c0 68 class EncodedInputStream<UTF8<>, MemoryStream> {
IanBenzMaxim 0:33d4e66780c0 69 public:
IanBenzMaxim 0:33d4e66780c0 70 typedef UTF8<>::Ch Ch;
IanBenzMaxim 0:33d4e66780c0 71
IanBenzMaxim 0:33d4e66780c0 72 EncodedInputStream(MemoryStream& is) : is_(is) {
IanBenzMaxim 0:33d4e66780c0 73 if (static_cast<unsigned char>(is_.Peek()) == 0xEFu) is_.Take();
IanBenzMaxim 0:33d4e66780c0 74 if (static_cast<unsigned char>(is_.Peek()) == 0xBBu) is_.Take();
IanBenzMaxim 0:33d4e66780c0 75 if (static_cast<unsigned char>(is_.Peek()) == 0xBFu) is_.Take();
IanBenzMaxim 0:33d4e66780c0 76 }
IanBenzMaxim 0:33d4e66780c0 77 Ch Peek() const { return is_.Peek(); }
IanBenzMaxim 0:33d4e66780c0 78 Ch Take() { return is_.Take(); }
IanBenzMaxim 0:33d4e66780c0 79 size_t Tell() const { return is_.Tell(); }
IanBenzMaxim 0:33d4e66780c0 80
IanBenzMaxim 0:33d4e66780c0 81 // Not implemented
IanBenzMaxim 0:33d4e66780c0 82 void Put(Ch) {}
IanBenzMaxim 0:33d4e66780c0 83 void Flush() {}
IanBenzMaxim 0:33d4e66780c0 84 Ch* PutBegin() { return 0; }
IanBenzMaxim 0:33d4e66780c0 85 size_t PutEnd(Ch*) { return 0; }
IanBenzMaxim 0:33d4e66780c0 86
IanBenzMaxim 0:33d4e66780c0 87 MemoryStream& is_;
IanBenzMaxim 0:33d4e66780c0 88
IanBenzMaxim 0:33d4e66780c0 89 private:
IanBenzMaxim 0:33d4e66780c0 90 EncodedInputStream(const EncodedInputStream&);
IanBenzMaxim 0:33d4e66780c0 91 EncodedInputStream& operator=(const EncodedInputStream&);
IanBenzMaxim 0:33d4e66780c0 92 };
IanBenzMaxim 0:33d4e66780c0 93
IanBenzMaxim 0:33d4e66780c0 94 //! Output byte stream wrapper with statically bound encoding.
IanBenzMaxim 0:33d4e66780c0 95 /*!
IanBenzMaxim 0:33d4e66780c0 96 \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
IanBenzMaxim 0:33d4e66780c0 97 \tparam OutputByteStream Type of input byte stream. For example, FileWriteStream.
IanBenzMaxim 0:33d4e66780c0 98 */
IanBenzMaxim 0:33d4e66780c0 99 template <typename Encoding, typename OutputByteStream>
IanBenzMaxim 0:33d4e66780c0 100 class EncodedOutputStream {
IanBenzMaxim 0:33d4e66780c0 101 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 102 public:
IanBenzMaxim 0:33d4e66780c0 103 typedef typename Encoding::Ch Ch;
IanBenzMaxim 0:33d4e66780c0 104
IanBenzMaxim 0:33d4e66780c0 105 EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) {
IanBenzMaxim 0:33d4e66780c0 106 if (putBOM)
IanBenzMaxim 0:33d4e66780c0 107 Encoding::PutBOM(os_);
IanBenzMaxim 0:33d4e66780c0 108 }
IanBenzMaxim 0:33d4e66780c0 109
IanBenzMaxim 0:33d4e66780c0 110 void Put(Ch c) { Encoding::Put(os_, c); }
IanBenzMaxim 0:33d4e66780c0 111 void Flush() { os_.Flush(); }
IanBenzMaxim 0:33d4e66780c0 112
IanBenzMaxim 0:33d4e66780c0 113 // Not implemented
IanBenzMaxim 0:33d4e66780c0 114 Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
IanBenzMaxim 0:33d4e66780c0 115 Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
IanBenzMaxim 0:33d4e66780c0 116 size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
IanBenzMaxim 0:33d4e66780c0 117 Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
IanBenzMaxim 0:33d4e66780c0 118 size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
IanBenzMaxim 0:33d4e66780c0 119
IanBenzMaxim 0:33d4e66780c0 120 private:
IanBenzMaxim 0:33d4e66780c0 121 EncodedOutputStream(const EncodedOutputStream&);
IanBenzMaxim 0:33d4e66780c0 122 EncodedOutputStream& operator=(const EncodedOutputStream&);
IanBenzMaxim 0:33d4e66780c0 123
IanBenzMaxim 0:33d4e66780c0 124 OutputByteStream& os_;
IanBenzMaxim 0:33d4e66780c0 125 };
IanBenzMaxim 0:33d4e66780c0 126
IanBenzMaxim 0:33d4e66780c0 127 #define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
IanBenzMaxim 0:33d4e66780c0 128
IanBenzMaxim 0:33d4e66780c0 129 //! Input stream wrapper with dynamically bound encoding and automatic encoding detection.
IanBenzMaxim 0:33d4e66780c0 130 /*!
IanBenzMaxim 0:33d4e66780c0 131 \tparam CharType Type of character for reading.
IanBenzMaxim 0:33d4e66780c0 132 \tparam InputByteStream type of input byte stream to be wrapped.
IanBenzMaxim 0:33d4e66780c0 133 */
IanBenzMaxim 0:33d4e66780c0 134 template <typename CharType, typename InputByteStream>
IanBenzMaxim 0:33d4e66780c0 135 class AutoUTFInputStream {
IanBenzMaxim 0:33d4e66780c0 136 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 137 public:
IanBenzMaxim 0:33d4e66780c0 138 typedef CharType Ch;
IanBenzMaxim 0:33d4e66780c0 139
IanBenzMaxim 0:33d4e66780c0 140 //! Constructor.
IanBenzMaxim 0:33d4e66780c0 141 /*!
IanBenzMaxim 0:33d4e66780c0 142 \param is input stream to be wrapped.
IanBenzMaxim 0:33d4e66780c0 143 \param type UTF encoding type if it is not detected from the stream.
IanBenzMaxim 0:33d4e66780c0 144 */
IanBenzMaxim 0:33d4e66780c0 145 AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) {
IanBenzMaxim 0:33d4e66780c0 146 RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
IanBenzMaxim 0:33d4e66780c0 147 DetectType();
IanBenzMaxim 0:33d4e66780c0 148 static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
IanBenzMaxim 0:33d4e66780c0 149 takeFunc_ = f[type_];
IanBenzMaxim 0:33d4e66780c0 150 current_ = takeFunc_(*is_);
IanBenzMaxim 0:33d4e66780c0 151 }
IanBenzMaxim 0:33d4e66780c0 152
IanBenzMaxim 0:33d4e66780c0 153 UTFType GetType() const { return type_; }
IanBenzMaxim 0:33d4e66780c0 154 bool HasBOM() const { return hasBOM_; }
IanBenzMaxim 0:33d4e66780c0 155
IanBenzMaxim 0:33d4e66780c0 156 Ch Peek() const { return current_; }
IanBenzMaxim 0:33d4e66780c0 157 Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; }
IanBenzMaxim 0:33d4e66780c0 158 size_t Tell() const { return is_->Tell(); }
IanBenzMaxim 0:33d4e66780c0 159
IanBenzMaxim 0:33d4e66780c0 160 // Not implemented
IanBenzMaxim 0:33d4e66780c0 161 void Put(Ch) { RAPIDJSON_ASSERT(false); }
IanBenzMaxim 0:33d4e66780c0 162 void Flush() { RAPIDJSON_ASSERT(false); }
IanBenzMaxim 0:33d4e66780c0 163 Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
IanBenzMaxim 0:33d4e66780c0 164 size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
IanBenzMaxim 0:33d4e66780c0 165
IanBenzMaxim 0:33d4e66780c0 166 private:
IanBenzMaxim 0:33d4e66780c0 167 AutoUTFInputStream(const AutoUTFInputStream&);
IanBenzMaxim 0:33d4e66780c0 168 AutoUTFInputStream& operator=(const AutoUTFInputStream&);
IanBenzMaxim 0:33d4e66780c0 169
IanBenzMaxim 0:33d4e66780c0 170 // Detect encoding type with BOM or RFC 4627
IanBenzMaxim 0:33d4e66780c0 171 void DetectType() {
IanBenzMaxim 0:33d4e66780c0 172 // BOM (Byte Order Mark):
IanBenzMaxim 0:33d4e66780c0 173 // 00 00 FE FF UTF-32BE
IanBenzMaxim 0:33d4e66780c0 174 // FF FE 00 00 UTF-32LE
IanBenzMaxim 0:33d4e66780c0 175 // FE FF UTF-16BE
IanBenzMaxim 0:33d4e66780c0 176 // FF FE UTF-16LE
IanBenzMaxim 0:33d4e66780c0 177 // EF BB BF UTF-8
IanBenzMaxim 0:33d4e66780c0 178
IanBenzMaxim 0:33d4e66780c0 179 const unsigned char* c = reinterpret_cast<const unsigned char *>(is_->Peek4());
IanBenzMaxim 0:33d4e66780c0 180 if (!c)
IanBenzMaxim 0:33d4e66780c0 181 return;
IanBenzMaxim 0:33d4e66780c0 182
IanBenzMaxim 0:33d4e66780c0 183 unsigned bom = static_cast<unsigned>(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24));
IanBenzMaxim 0:33d4e66780c0 184 hasBOM_ = false;
IanBenzMaxim 0:33d4e66780c0 185 if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
IanBenzMaxim 0:33d4e66780c0 186 else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
IanBenzMaxim 0:33d4e66780c0 187 else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); }
IanBenzMaxim 0:33d4e66780c0 188 else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); }
IanBenzMaxim 0:33d4e66780c0 189 else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); }
IanBenzMaxim 0:33d4e66780c0 190
IanBenzMaxim 0:33d4e66780c0 191 // RFC 4627: Section 3
IanBenzMaxim 0:33d4e66780c0 192 // "Since the first two characters of a JSON text will always be ASCII
IanBenzMaxim 0:33d4e66780c0 193 // characters [RFC0020], it is possible to determine whether an octet
IanBenzMaxim 0:33d4e66780c0 194 // stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
IanBenzMaxim 0:33d4e66780c0 195 // at the pattern of nulls in the first four octets."
IanBenzMaxim 0:33d4e66780c0 196 // 00 00 00 xx UTF-32BE
IanBenzMaxim 0:33d4e66780c0 197 // 00 xx 00 xx UTF-16BE
IanBenzMaxim 0:33d4e66780c0 198 // xx 00 00 00 UTF-32LE
IanBenzMaxim 0:33d4e66780c0 199 // xx 00 xx 00 UTF-16LE
IanBenzMaxim 0:33d4e66780c0 200 // xx xx xx xx UTF-8
IanBenzMaxim 0:33d4e66780c0 201
IanBenzMaxim 0:33d4e66780c0 202 if (!hasBOM_) {
IanBenzMaxim 0:33d4e66780c0 203 unsigned pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0);
IanBenzMaxim 0:33d4e66780c0 204 switch (pattern) {
IanBenzMaxim 0:33d4e66780c0 205 case 0x08: type_ = kUTF32BE; break;
IanBenzMaxim 0:33d4e66780c0 206 case 0x0A: type_ = kUTF16BE; break;
IanBenzMaxim 0:33d4e66780c0 207 case 0x01: type_ = kUTF32LE; break;
IanBenzMaxim 0:33d4e66780c0 208 case 0x05: type_ = kUTF16LE; break;
IanBenzMaxim 0:33d4e66780c0 209 case 0x0F: type_ = kUTF8; break;
IanBenzMaxim 0:33d4e66780c0 210 default: break; // Use type defined by user.
IanBenzMaxim 0:33d4e66780c0 211 }
IanBenzMaxim 0:33d4e66780c0 212 }
IanBenzMaxim 0:33d4e66780c0 213
IanBenzMaxim 0:33d4e66780c0 214 // Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
IanBenzMaxim 0:33d4e66780c0 215 if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
IanBenzMaxim 0:33d4e66780c0 216 if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
IanBenzMaxim 0:33d4e66780c0 217 }
IanBenzMaxim 0:33d4e66780c0 218
IanBenzMaxim 0:33d4e66780c0 219 typedef Ch (*TakeFunc)(InputByteStream& is);
IanBenzMaxim 0:33d4e66780c0 220 InputByteStream* is_;
IanBenzMaxim 0:33d4e66780c0 221 UTFType type_;
IanBenzMaxim 0:33d4e66780c0 222 Ch current_;
IanBenzMaxim 0:33d4e66780c0 223 TakeFunc takeFunc_;
IanBenzMaxim 0:33d4e66780c0 224 bool hasBOM_;
IanBenzMaxim 0:33d4e66780c0 225 };
IanBenzMaxim 0:33d4e66780c0 226
IanBenzMaxim 0:33d4e66780c0 227 //! Output stream wrapper with dynamically bound encoding and automatic encoding detection.
IanBenzMaxim 0:33d4e66780c0 228 /*!
IanBenzMaxim 0:33d4e66780c0 229 \tparam CharType Type of character for writing.
IanBenzMaxim 0:33d4e66780c0 230 \tparam OutputByteStream type of output byte stream to be wrapped.
IanBenzMaxim 0:33d4e66780c0 231 */
IanBenzMaxim 0:33d4e66780c0 232 template <typename CharType, typename OutputByteStream>
IanBenzMaxim 0:33d4e66780c0 233 class AutoUTFOutputStream {
IanBenzMaxim 0:33d4e66780c0 234 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
IanBenzMaxim 0:33d4e66780c0 235 public:
IanBenzMaxim 0:33d4e66780c0 236 typedef CharType Ch;
IanBenzMaxim 0:33d4e66780c0 237
IanBenzMaxim 0:33d4e66780c0 238 //! Constructor.
IanBenzMaxim 0:33d4e66780c0 239 /*!
IanBenzMaxim 0:33d4e66780c0 240 \param os output stream to be wrapped.
IanBenzMaxim 0:33d4e66780c0 241 \param type UTF encoding type.
IanBenzMaxim 0:33d4e66780c0 242 \param putBOM Whether to write BOM at the beginning of the stream.
IanBenzMaxim 0:33d4e66780c0 243 */
IanBenzMaxim 0:33d4e66780c0 244 AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) {
IanBenzMaxim 0:33d4e66780c0 245 RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
IanBenzMaxim 0:33d4e66780c0 246
IanBenzMaxim 0:33d4e66780c0 247 // Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
IanBenzMaxim 0:33d4e66780c0 248 if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
IanBenzMaxim 0:33d4e66780c0 249 if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
IanBenzMaxim 0:33d4e66780c0 250
IanBenzMaxim 0:33d4e66780c0 251 static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };
IanBenzMaxim 0:33d4e66780c0 252 putFunc_ = f[type_];
IanBenzMaxim 0:33d4e66780c0 253
IanBenzMaxim 0:33d4e66780c0 254 if (putBOM)
IanBenzMaxim 0:33d4e66780c0 255 PutBOM();
IanBenzMaxim 0:33d4e66780c0 256 }
IanBenzMaxim 0:33d4e66780c0 257
IanBenzMaxim 0:33d4e66780c0 258 UTFType GetType() const { return type_; }
IanBenzMaxim 0:33d4e66780c0 259
IanBenzMaxim 0:33d4e66780c0 260 void Put(Ch c) { putFunc_(*os_, c); }
IanBenzMaxim 0:33d4e66780c0 261 void Flush() { os_->Flush(); }
IanBenzMaxim 0:33d4e66780c0 262
IanBenzMaxim 0:33d4e66780c0 263 // Not implemented
IanBenzMaxim 0:33d4e66780c0 264 Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
IanBenzMaxim 0:33d4e66780c0 265 Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
IanBenzMaxim 0:33d4e66780c0 266 size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
IanBenzMaxim 0:33d4e66780c0 267 Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
IanBenzMaxim 0:33d4e66780c0 268 size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
IanBenzMaxim 0:33d4e66780c0 269
IanBenzMaxim 0:33d4e66780c0 270 private:
IanBenzMaxim 0:33d4e66780c0 271 AutoUTFOutputStream(const AutoUTFOutputStream&);
IanBenzMaxim 0:33d4e66780c0 272 AutoUTFOutputStream& operator=(const AutoUTFOutputStream&);
IanBenzMaxim 0:33d4e66780c0 273
IanBenzMaxim 0:33d4e66780c0 274 void PutBOM() {
IanBenzMaxim 0:33d4e66780c0 275 typedef void (*PutBOMFunc)(OutputByteStream&);
IanBenzMaxim 0:33d4e66780c0 276 static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) };
IanBenzMaxim 0:33d4e66780c0 277 f[type_](*os_);
IanBenzMaxim 0:33d4e66780c0 278 }
IanBenzMaxim 0:33d4e66780c0 279
IanBenzMaxim 0:33d4e66780c0 280 typedef void (*PutFunc)(OutputByteStream&, Ch);
IanBenzMaxim 0:33d4e66780c0 281
IanBenzMaxim 0:33d4e66780c0 282 OutputByteStream* os_;
IanBenzMaxim 0:33d4e66780c0 283 UTFType type_;
IanBenzMaxim 0:33d4e66780c0 284 PutFunc putFunc_;
IanBenzMaxim 0:33d4e66780c0 285 };
IanBenzMaxim 0:33d4e66780c0 286
IanBenzMaxim 0:33d4e66780c0 287 #undef RAPIDJSON_ENCODINGS_FUNC
IanBenzMaxim 0:33d4e66780c0 288
IanBenzMaxim 0:33d4e66780c0 289 RAPIDJSON_NAMESPACE_END
IanBenzMaxim 0:33d4e66780c0 290
IanBenzMaxim 0:33d4e66780c0 291 #ifdef __clang__
IanBenzMaxim 0:33d4e66780c0 292 RAPIDJSON_DIAG_POP
IanBenzMaxim 0:33d4e66780c0 293 #endif
IanBenzMaxim 0:33d4e66780c0 294
IanBenzMaxim 0:33d4e66780c0 295 #ifdef __GNUC__
IanBenzMaxim 0:33d4e66780c0 296 RAPIDJSON_DIAG_POP
IanBenzMaxim 0:33d4e66780c0 297 #endif
IanBenzMaxim 0:33d4e66780c0 298
IanBenzMaxim 0:33d4e66780c0 299 #endif // RAPIDJSON_FILESTREAM_H_