istreamwrapper.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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. #ifndef RAPIDJSON_ISTREAMWRAPPER_H_
  19. #define RAPIDJSON_ISTREAMWRAPPER_H_
  20. #include <ios>
  21. #include <iosfwd>
  22. #include "stream.h"
  23. #ifdef __clang__
  24. RAPIDJSON_DIAG_PUSH
  25. RAPIDJSON_DIAG_OFF(padded)
  26. #elif defined(_MSC_VER)
  27. RAPIDJSON_DIAG_PUSH
  28. RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be
  29. // default initialized
  30. #endif
  31. RAPIDJSON_NAMESPACE_BEGIN
  32. //! Wrapper of \c std::basic_istream into RapidJSON's Stream concept.
  33. /*!
  34. The classes can be wrapped including but not limited to:
  35. - \c std::istringstream
  36. - \c std::stringstream
  37. - \c std::wistringstream
  38. - \c std::wstringstream
  39. - \c std::ifstream
  40. - \c std::fstream
  41. - \c std::wifstream
  42. - \c std::wfstream
  43. \tparam StreamType Class derived from \c std::basic_istream.
  44. */
  45. template <typename StreamType>
  46. class BasicIStreamWrapper {
  47. public:
  48. typedef typename StreamType::char_type Ch;
  49. //! Constructor.
  50. /*!
  51. \param stream stream opened for read.
  52. */
  53. BasicIStreamWrapper(StreamType &stream)
  54. : stream_(stream),
  55. buffer_(peekBuffer_),
  56. bufferSize_(4),
  57. bufferLast_(0),
  58. current_(buffer_),
  59. readCount_(0),
  60. count_(0),
  61. eof_(false) {
  62. Read();
  63. }
  64. //! Constructor.
  65. /*!
  66. \param stream stream opened for read.
  67. \param buffer user-supplied buffer.
  68. \param bufferSize size of buffer in bytes. Must >=4 bytes.
  69. */
  70. BasicIStreamWrapper(StreamType &stream, char *buffer, size_t bufferSize)
  71. : stream_(stream),
  72. buffer_(buffer),
  73. bufferSize_(bufferSize),
  74. bufferLast_(0),
  75. current_(buffer_),
  76. readCount_(0),
  77. count_(0),
  78. eof_(false) {
  79. RAPIDJSON_ASSERT(bufferSize >= 4);
  80. Read();
  81. }
  82. Ch Peek() const { return *current_; }
  83. Ch Take() {
  84. Ch c = *current_;
  85. Read();
  86. return c;
  87. }
  88. size_t Tell() const {
  89. return count_ + static_cast<size_t>(current_ - buffer_);
  90. }
  91. // Not implemented
  92. void Put(Ch) { RAPIDJSON_ASSERT(false); }
  93. void Flush() { RAPIDJSON_ASSERT(false); }
  94. Ch *PutBegin() {
  95. RAPIDJSON_ASSERT(false);
  96. return 0;
  97. }
  98. size_t PutEnd(Ch *) {
  99. RAPIDJSON_ASSERT(false);
  100. return 0;
  101. }
  102. // For encoding detection only.
  103. const Ch *Peek4() const {
  104. return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0;
  105. }
  106. private:
  107. BasicIStreamWrapper();
  108. BasicIStreamWrapper(const BasicIStreamWrapper &);
  109. BasicIStreamWrapper &operator=(const BasicIStreamWrapper &);
  110. void Read() {
  111. if (current_ < bufferLast_)
  112. ++current_;
  113. else if (!eof_) {
  114. count_ += readCount_;
  115. readCount_ = bufferSize_;
  116. bufferLast_ = buffer_ + readCount_ - 1;
  117. current_ = buffer_;
  118. if (!stream_.read(buffer_, static_cast<std::streamsize>(bufferSize_))) {
  119. readCount_ = static_cast<size_t>(stream_.gcount());
  120. *(bufferLast_ = buffer_ + readCount_) = '\0';
  121. eof_ = true;
  122. }
  123. }
  124. }
  125. StreamType &stream_;
  126. Ch peekBuffer_[4], *buffer_;
  127. size_t bufferSize_;
  128. Ch *bufferLast_;
  129. Ch *current_;
  130. size_t readCount_;
  131. size_t count_; //!< Number of characters read
  132. bool eof_;
  133. };
  134. typedef BasicIStreamWrapper<std::istream> IStreamWrapper;
  135. typedef BasicIStreamWrapper<std::wistream> WIStreamWrapper;
  136. #if defined(__clang__) || defined(_MSC_VER)
  137. RAPIDJSON_DIAG_POP
  138. #endif
  139. RAPIDJSON_NAMESPACE_END
  140. #endif // RAPIDJSON_ISTREAMWRAPPER_H_