Home | History | Annotate | Download | only in rapidjson
      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_FILEWRITESTREAM_H_
     16 #define RAPIDJSON_FILEWRITESTREAM_H_
     17 
     18 #include "rapidjson.h"
     19 #include <cstdio>
     20 
     21 RAPIDJSON_NAMESPACE_BEGIN
     22 
     23 //! Wrapper of C file stream for input using fread().
     24 /*!
     25     \note implements Stream concept
     26 */
     27 class FileWriteStream {
     28 public:
     29     typedef char Ch;    //!< Character type. Only support char.
     30 
     31     FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) {
     32         RAPIDJSON_ASSERT(fp_ != 0);
     33     }
     34 
     35     void Put(char c) {
     36         if (current_ >= bufferEnd_)
     37             Flush();
     38 
     39         *current_++ = c;
     40     }
     41 
     42     void PutN(char c, size_t n) {
     43         size_t avail = static_cast<size_t>(bufferEnd_ - current_);
     44         while (n > avail) {
     45             std::memset(current_, c, avail);
     46             current_ += avail;
     47             Flush();
     48             n -= avail;
     49             avail = static_cast<size_t>(bufferEnd_ - current_);
     50         }
     51 
     52         if (n > 0) {
     53             std::memset(current_, c, n);
     54             current_ += n;
     55         }
     56     }
     57 
     58     void Flush() {
     59         if (current_ != buffer_) {
     60             size_t result = fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
     61             if (result < static_cast<size_t>(current_ - buffer_)) {
     62                 // failure deliberately ignored at this time
     63                 // added to avoid warn_unused_result build errors
     64             }
     65             current_ = buffer_;
     66         }
     67     }
     68 
     69     // Not implemented
     70     char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
     71     char Take() { RAPIDJSON_ASSERT(false); return 0; }
     72     size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
     73     char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
     74     size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }
     75 
     76 private:
     77     // Prohibit copy constructor & assignment operator.
     78     FileWriteStream(const FileWriteStream&);
     79     FileWriteStream& operator=(const FileWriteStream&);
     80 
     81     std::FILE* fp_;
     82     char *buffer_;
     83     char *bufferEnd_;
     84     char *current_;
     85 };
     86 
     87 //! Implement specialized version of PutN() with memset() for better performance.
     88 template<>
     89 inline void PutN(FileWriteStream& stream, char c, size_t n) {
     90     stream.PutN(c, n);
     91 }
     92 
     93 RAPIDJSON_NAMESPACE_END
     94 
     95 #endif // RAPIDJSON_FILESTREAM_H_
     96