text: // Tencent is pleased to support the open source community by making RapidJSON available.
  // 
  // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
  //
  // Licensed under the MIT License (the "License"); you may not use this file except
  // in compliance with the License. You may obtain a copy of the License at
  //
  // http://opensource.org/licenses/MIT
  //
  // Unless required by applicable law or agreed to in writing, software distributed 
  // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
  // CONDITIONS OF ANY KIND, either express or implied. See the License for the 
  // specific language governing permissions and limitations under the License.
  
  #ifndef RAPIDJSON_STRINGBUFFER_H_
  #define RAPIDJSON_STRINGBUFFER_H_
  
  #include "rapidjson.h"
  
  
  #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
  
  #include <utility> // std::move
  
  
  #endif
  
  #include "internal/stack.h"
  
  
  RAPIDJSON_NAMESPACE_BEGIN
  
  //! Represents an in-memory output stream.
  /*!
      \tparam Encoding Encoding of the stream.
      \tparam Allocator type for allocating memory buffer.
      \note implements Stream concept
  */
  template <typename Encoding, typename Allocator = CrtAllocator>
  class GenericStringBuffer {
   public:
    typedef typename Encoding::Ch Ch;
  
    GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}
  
  #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
    GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {}
    GenericStringBuffer& operator=(GenericStringBuffer&& rhs) {
      if (&rhs != this)
        stack_ = std::move(rhs.stack_);
      return *this;
    }
  #endif
  
    void Put(Ch c) { *stack_.template Push<Ch>() = c; }
    void Flush() {}
  
    void Clear() { stack_.Clear(); }
    void ShrinkToFit() {
      // Push and pop a null terminator. This is safe.
      *stack_.template Push<Ch>() = '\0';
      stack_.ShrinkToFit();
      stack_.template Pop<Ch>(1);
    }
    Ch* Push(size_t count) { return stack_.template Push<Ch>(count); }
    void Pop(size_t count) { stack_.template Pop<Ch>(count); }
  
    const Ch* GetString() const {
      // Push and pop a null terminator. This is safe.
      *stack_.template Push<Ch>() = '\0';
      stack_.template Pop<Ch>(1);
  
      return stack_.template Bottom<Ch>();
    }
  
    size_t GetSize() const { return stack_.GetSize(); }
  
    static const size_t kDefaultCapacity = 256;
    mutable internal::Stack<Allocator> stack_;
  
   private:
    // Prohibit copy constructor & assignment operator.
    GenericStringBuffer(const GenericStringBuffer&);
    GenericStringBuffer& operator=(const GenericStringBuffer&);
  };
  
  //! String buffer with UTF8 encoding
  typedef GenericStringBuffer<UTF8<> > StringBuffer;
  
  //! Implement specialized version of PutN() with memset() for better performance.
  template <>
  inline void PutN(GenericStringBuffer<UTF8<> >& stream, char c, size_t n) {
    std::memset(stream.stack_.Push<char>(n), c, n * sizeof(c));
  }
  
  RAPIDJSON_NAMESPACE_END
  
  #endif // RAPIDJSON_STRINGBUFFER_H_
  