stream.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. // Tencent is pleased to support the open source community by making RapidJSON
  2. // available.
  3. //
  4. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All
  5. // rights reserved.
  6. //
  7. // Licensed under the MIT License (the "License"); you may not use this file
  8. // except in compliance with the License. You may obtain a copy of the License
  9. // at
  10. //
  11. // http://opensource.org/licenses/MIT
  12. //
  13. // Unless required by applicable law or agreed to in writing, software
  14. // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  15. // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  16. // License for the specific language governing permissions and limitations under
  17. // the License.
  18. #include "rapidjson.h"
  19. #ifndef RAPIDJSON_STREAM_H_
  20. #define RAPIDJSON_STREAM_H_
  21. #include "encodings.h"
  22. RAPIDJSON_NAMESPACE_BEGIN
  23. ///////////////////////////////////////////////////////////////////////////////
  24. // Stream
  25. /*! \class rapidjson::Stream
  26. \brief Concept for reading and writing characters.
  27. For read-only stream, no need to implement PutBegin(), Put(), Flush() and
  28. PutEnd().
  29. For write-only stream, only need to implement Put() and Flush().
  30. \code
  31. concept Stream {
  32. typename Ch; //!< Character type of the stream.
  33. //! Read the current character from stream without moving the read cursor.
  34. Ch Peek() const;
  35. //! Read the current character from stream and moving the read cursor to
  36. next character. Ch Take();
  37. //! Get the current read cursor.
  38. //! \return Number of characters read from start.
  39. size_t Tell();
  40. //! Begin writing operation at the current read pointer.
  41. //! \return The begin writer pointer.
  42. Ch* PutBegin();
  43. //! Write a character.
  44. void Put(Ch c);
  45. //! Flush the buffer.
  46. void Flush();
  47. //! End the writing operation.
  48. //! \param begin The begin write pointer returned by PutBegin().
  49. //! \return Number of characters written.
  50. size_t PutEnd(Ch* begin);
  51. }
  52. \endcode
  53. */
  54. //! Provides additional information for stream.
  55. /*!
  56. By using traits pattern, this type provides a default configuration for
  57. stream. For custom stream, this type can be specialized for other
  58. configuration. See TEST(Reader, CustomStringStream) in readertest.cpp for
  59. example.
  60. */
  61. template <typename Stream>
  62. struct StreamTraits {
  63. //! Whether to make local copy of stream for optimization during parsing.
  64. /*!
  65. By default, for safety, streams do not use local copy optimization.
  66. Stream that can be copied fast should specialize this, like
  67. StreamTraits<StringStream>.
  68. */
  69. enum { copyOptimization = 0 };
  70. };
  71. //! Reserve n characters for writing to a stream.
  72. template <typename Stream>
  73. inline void PutReserve(Stream &stream, size_t count) {
  74. (void)stream;
  75. (void)count;
  76. }
  77. //! Write character to a stream, presuming buffer is reserved.
  78. template <typename Stream>
  79. inline void PutUnsafe(Stream &stream, typename Stream::Ch c) {
  80. stream.Put(c);
  81. }
  82. //! Put N copies of a character to a stream.
  83. template <typename Stream, typename Ch>
  84. inline void PutN(Stream &stream, Ch c, size_t n) {
  85. PutReserve(stream, n);
  86. for (size_t i = 0; i < n; i++) PutUnsafe(stream, c);
  87. }
  88. ///////////////////////////////////////////////////////////////////////////////
  89. // GenericStreamWrapper
  90. //! A Stream Wrapper
  91. /*! \tThis string stream is a wrapper for any stream by just forwarding any
  92. \treceived message to the origin stream.
  93. \note implements Stream concept
  94. */
  95. #if defined(_MSC_VER) && _MSC_VER <= 1800
  96. RAPIDJSON_DIAG_PUSH
  97. RAPIDJSON_DIAG_OFF(4702) // unreachable code
  98. RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
  99. #endif
  100. template <typename InputStream, typename Encoding = UTF8<>>
  101. class GenericStreamWrapper {
  102. public:
  103. typedef typename Encoding::Ch Ch;
  104. GenericStreamWrapper(InputStream &is) : is_(is) {}
  105. Ch Peek() const { return is_.Peek(); }
  106. Ch Take() { return is_.Take(); }
  107. size_t Tell() { return is_.Tell(); }
  108. Ch *PutBegin() { return is_.PutBegin(); }
  109. void Put(Ch ch) { is_.Put(ch); }
  110. void Flush() { is_.Flush(); }
  111. size_t PutEnd(Ch *ch) { return is_.PutEnd(ch); }
  112. // wrapper for MemoryStream
  113. const Ch *Peek4() const { return is_.Peek4(); }
  114. // wrapper for AutoUTFInputStream
  115. UTFType GetType() const { return is_.GetType(); }
  116. bool HasBOM() const { return is_.HasBOM(); }
  117. protected:
  118. InputStream &is_;
  119. };
  120. #if defined(_MSC_VER) && _MSC_VER <= 1800
  121. RAPIDJSON_DIAG_POP
  122. #endif
  123. ///////////////////////////////////////////////////////////////////////////////
  124. // StringStream
  125. //! Read-only string stream.
  126. /*! \note implements Stream concept
  127. */
  128. template <typename Encoding>
  129. struct GenericStringStream {
  130. typedef typename Encoding::Ch Ch;
  131. GenericStringStream(const Ch *src) : src_(src), head_(src) {}
  132. Ch Peek() const { return *src_; }
  133. Ch Take() { return *src_++; }
  134. size_t Tell() const { return static_cast<size_t>(src_ - head_); }
  135. Ch *PutBegin() {
  136. RAPIDJSON_ASSERT(false);
  137. return 0;
  138. }
  139. void Put(Ch) { RAPIDJSON_ASSERT(false); }
  140. void Flush() { RAPIDJSON_ASSERT(false); }
  141. size_t PutEnd(Ch *) {
  142. RAPIDJSON_ASSERT(false);
  143. return 0;
  144. }
  145. const Ch *src_; //!< Current read position.
  146. const Ch *head_; //!< Original head of the string.
  147. };
  148. template <typename Encoding>
  149. struct StreamTraits<GenericStringStream<Encoding>> {
  150. enum { copyOptimization = 1 };
  151. };
  152. //! String stream with UTF8 encoding.
  153. typedef GenericStringStream<UTF8<>> StringStream;
  154. ///////////////////////////////////////////////////////////////////////////////
  155. // InsituStringStream
  156. //! A read-write string stream.
  157. /*! This string stream is particularly designed for in-situ parsing.
  158. \note implements Stream concept
  159. */
  160. template <typename Encoding>
  161. struct GenericInsituStringStream {
  162. typedef typename Encoding::Ch Ch;
  163. GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {}
  164. // Read
  165. Ch Peek() { return *src_; }
  166. Ch Take() { return *src_++; }
  167. size_t Tell() { return static_cast<size_t>(src_ - head_); }
  168. // Write
  169. void Put(Ch c) {
  170. RAPIDJSON_ASSERT(dst_ != 0);
  171. *dst_++ = c;
  172. }
  173. Ch *PutBegin() { return dst_ = src_; }
  174. size_t PutEnd(Ch *begin) { return static_cast<size_t>(dst_ - begin); }
  175. void Flush() {}
  176. Ch *Push(size_t count) {
  177. Ch *begin = dst_;
  178. dst_ += count;
  179. return begin;
  180. }
  181. void Pop(size_t count) { dst_ -= count; }
  182. Ch *src_;
  183. Ch *dst_;
  184. Ch *head_;
  185. };
  186. template <typename Encoding>
  187. struct StreamTraits<GenericInsituStringStream<Encoding>> {
  188. enum { copyOptimization = 1 };
  189. };
  190. //! Insitu string stream with UTF8 encoding.
  191. typedef GenericInsituStringStream<UTF8<>> InsituStringStream;
  192. RAPIDJSON_NAMESPACE_END
  193. #endif // RAPIDJSON_STREAM_H_