Torque3D Documentation / _generateds / encodedstream.h

encodedstream.h

Engine/source/persistence/rapidjson/encodedstream.h

More...

Classes:

class

Input stream wrapper with dynamically bound encoding and automatic encoding detection.

class

Output stream wrapper with dynamically bound encoding and automatic encoding detection.

class

Input byte stream wrapper with a statically bound encoding.

class

Output byte stream wrapper with statically bound encoding.

Namespaces:

namespace

Public Defines

define
RAPIDJSON_ENCODINGS_FUNC(x) <Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x

Detailed Description

Public Defines

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