1 // Tencent is pleased to support the open source community by making RapidJSON available. 2 // 3 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 // 5 // Licensed under the MIT License (the "License"); you may not use this file except 6 // in compliance with the License. You may obtain a copy of the License at 7 // 8 // http://opensource.org/licenses/MIT 9 // 10 // Unless required by applicable law or agreed to in writing, software distributed 11 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 // specific language governing permissions and limitations under the License. 14 15 #ifndef RAPIDJSON_ISTREAMWRAPPER_H_ 16 #define RAPIDJSON_ISTREAMWRAPPER_H_ 17 18 #include "stream.h" 19 #include <iosfwd> 20 21 #ifdef __clang__ 22 RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(padded)23RAPIDJSON_DIAG_OFF(padded) 24 #endif 25 26 #ifdef _MSC_VER 27 RAPIDJSON_DIAG_PUSH 28 RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized 29 #endif 30 31 RAPIDJSON_NAMESPACE_BEGIN 32 33 //! Wrapper of \c std::basic_istream into RapidJSON's Stream concept. 34 /*! 35 The classes can be wrapped including but not limited to: 36 37 - \c std::istringstream 38 - \c std::stringstream 39 - \c std::wistringstream 40 - \c std::wstringstream 41 - \c std::ifstream 42 - \c std::fstream 43 - \c std::wifstream 44 - \c std::wfstream 45 46 \tparam StreamType Class derived from \c std::basic_istream. 47 */ 48 49 template <typename StreamType> 50 class BasicIStreamWrapper { 51 public: 52 typedef typename StreamType::char_type Ch; 53 BasicIStreamWrapper(StreamType& stream) : stream_(stream), count_(), peekBuffer_() {} 54 55 Ch Peek() const { 56 typename StreamType::int_type c = stream_.peek(); 57 return RAPIDJSON_LIKELY(c != StreamType::traits_type::eof()) ? static_cast<Ch>(c) : '\0'; 58 } 59 60 Ch Take() { 61 typename StreamType::int_type c = stream_.get(); 62 if (RAPIDJSON_LIKELY(c != StreamType::traits_type::eof())) { 63 count_++; 64 return static_cast<Ch>(c); 65 } 66 else 67 return '\0'; 68 } 69 70 // tellg() may return -1 when failed. So we count by ourself. 71 size_t Tell() const { return count_; } 72 73 Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 74 void Put(Ch) { RAPIDJSON_ASSERT(false); } 75 void Flush() { RAPIDJSON_ASSERT(false); } 76 size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } 77 78 // For encoding detection only. 79 const Ch* Peek4() const { 80 RAPIDJSON_ASSERT(sizeof(Ch) == 1); // Only usable for byte stream. 81 int i; 82 bool hasError = false; 83 for (i = 0; i < 4; ++i) { 84 typename StreamType::int_type c = stream_.get(); 85 if (c == StreamType::traits_type::eof()) { 86 hasError = true; 87 stream_.clear(); 88 break; 89 } 90 peekBuffer_[i] = static_cast<Ch>(c); 91 } 92 for (--i; i >= 0; --i) 93 stream_.putback(peekBuffer_[i]); 94 return !hasError ? peekBuffer_ : 0; 95 } 96 97 private: 98 BasicIStreamWrapper(const BasicIStreamWrapper&); 99 BasicIStreamWrapper& operator=(const BasicIStreamWrapper&); 100 101 StreamType& stream_; 102 size_t count_; //!< Number of characters read. Note: 103 mutable Ch peekBuffer_[4]; 104 }; 105 106 typedef BasicIStreamWrapper<std::istream> IStreamWrapper; 107 typedef BasicIStreamWrapper<std::wistream> WIStreamWrapper; 108 109 #if defined(__clang__) || defined(_MSC_VER) 110 RAPIDJSON_DIAG_POP 111 #endif 112 113 RAPIDJSON_NAMESPACE_END 114 115 #endif // RAPIDJSON_ISTREAMWRAPPER_H_ 116