LCOV - code coverage report
Current view: top level - core/core/memory - SPMemStringStream.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 55 69 79.7 %
Date: 2024-05-12 00:16:13 Functions: 20 25 80.0 %

          Line data    Source code
       1             : /**
       2             : Copyright (c) 2017-2022 Roman Katuntsev <sbkarr@stappler.org>
       3             : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
       4             : 
       5             : Permission is hereby granted, free of charge, to any person obtaining a copy
       6             : of this software and associated documentation files (the "Software"), to deal
       7             : in the Software without restriction, including without limitation the rights
       8             : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       9             : copies of the Software, and to permit persons to whom the Software is
      10             : furnished to do so, subject to the following conditions:
      11             : 
      12             : The above copyright notice and this permission notice shall be included in
      13             : all copies or substantial portions of the Software.
      14             : 
      15             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16             : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17             : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      18             : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      19             : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      20             : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      21             : THE SOFTWARE.
      22             : **/
      23             : 
      24             : #ifndef STAPPLER_CORE_MEMORY_SPMEMSTRINGSTREAM_H_
      25             : #define STAPPLER_CORE_MEMORY_SPMEMSTRINGSTREAM_H_
      26             : 
      27             : #include "SPMemString.h"
      28             : 
      29             : namespace STAPPLER_VERSIONIZED stappler::memory {
      30             : 
      31             : constexpr size_t basic_ostringbuf_bufsize = 256;
      32             : 
      33             : template<typename CharType>
      34             : class basic_ostringbuf final : public std::basic_streambuf<CharType, std::char_traits<CharType>>, public AllocPool {
      35             : public:
      36             :         using storage_type = storage_mem<CharType>;
      37             :         using allocator_type = Allocator<CharType>;
      38             :         using storage_allocator_type = Allocator<storage_mem<CharType>>;
      39             :         using traits_type = std::char_traits<CharType>;
      40             :         using size_type = size_t;
      41             :         using string_type = basic_string<CharType>;
      42             :         using mem_type = storage_mem<CharType, 1>;
      43             :         using char_type = CharType;
      44             :         using int_type = typename traits_type::int_type;
      45             :         using streambuf_type = std::basic_streambuf<CharType, std::char_traits<CharType>>;
      46             : 
      47       53325 :         basic_ostringbuf(size_type block = mem_type::get_soo_size(), const allocator_type &alloc = allocator_type()) noexcept
      48       53325 :         : _buf(alloc) {
      49       53324 :                 _buf.resize(block, 0);
      50             : 
      51       53325 :             char *base = &_buf.front();
      52       53324 :             streambuf_type::setp(base, base + _buf.size() - 1); // -1 to make overflow() easier
      53       53324 :         }
      54             :         basic_ostringbuf(CharType *ptr, size_type block, const allocator_type &alloc = allocator_type()) noexcept
      55             :         : _buf(alloc) {
      56             :                 _buf.assign_weak(ptr, block);
      57             : 
      58             :             char *base = &_buf.front();
      59             :             streambuf_type::setp(base, base + _buf.size() - 1); // -1 to make overflow() easier
      60             :         }
      61             :         basic_ostringbuf(basic_ostringbuf &&other, const allocator_type &alloc = allocator_type()) noexcept
      62             :         : _buf(std::move(other._buf), alloc)  {
      63             :             char *base = &_buf.front();
      64             :                 auto diff = (_buf.size() - 1) - (other.epptr() - other.pptr());
      65             :                 streambuf_type::setp(base + diff, base + _buf.size() - 1);
      66             :         }
      67             : 
      68           0 :         basic_ostringbuf &operator=(basic_ostringbuf &&other) noexcept {
      69           0 :                 _buf = move(other._buf);
      70           0 :                 char *base = &_buf.front();
      71           0 :                 auto diff = (_buf.size() - 1) - (other.epptr() - other.pptr());
      72           0 :                 streambuf_type::setp(base + diff, base + _buf.size() - 1);
      73           0 :                 return *this;
      74             :         }
      75             : 
      76       52124 :         virtual ~basic_ostringbuf() noexcept { }
      77             : 
      78       64500 :         bool empty() const noexcept {
      79       64500 :                 return streambuf_type::pptr() == _buf.data();
      80             :         }
      81             : 
      82      100848 :         size_type size() const noexcept {
      83      100848 :                 return (streambuf_type::pptr() - _buf.data());
      84             :         }
      85             : 
      86             :         CharType *data() noexcept {
      87             :                 return _buf.data();
      88             :         }
      89             : 
      90       48523 :         const CharType *data() const noexcept {
      91       48523 :                 return _buf.data();
      92             :         }
      93             : 
      94       52100 :         string_type str() const noexcept {
      95       52100 :                 string_type ret;
      96       52100 :                 ret.assign(_buf.data(), size());
      97       52100 :                 return ret;
      98             :         }
      99             : 
     100       46024 :         void clear() {
     101       46024 :             char *base = &_buf.front();
     102       46024 :             streambuf_type::setp(base, base + _buf.size() - 1); // -1 to make overflow() easier
     103       46025 :             memset(_buf.data(), 0, _buf.size());
     104       46025 :         }
     105             : 
     106         375 :         void reserve(size_t size) {
     107         375 :                 auto psize = (streambuf_type::pptr() - _buf.data());
     108         375 :                 _buf.reserve(size + 1);
     109         375 :                 _buf.resize(size + 1, 0);
     110             : 
     111         375 :             char *base = &_buf.front();
     112         375 :             streambuf_type::setp(base + psize, base + _buf.size() - 1); // -1 to make overflow() easier
     113         375 :         }
     114             : 
     115             :         basic_ostringbuf(const basic_ostringbuf &) = delete;
     116             :         basic_ostringbuf & operator = (const basic_ostringbuf &) = delete;
     117             : 
     118             :         const allocator_type &get_allocator() const noexcept { return _buf.get_allocator(); }
     119             : 
     120             : protected:
     121       34225 :         void make_flush() {
     122       34225 :                 auto diff = streambuf_type::pptr() - &_buf.front();
     123       34223 :                 _buf.resize(std::max(size_type(diff * 2), basic_ostringbuf_bufsize));
     124       34225 :                 char *base = &_buf.front();
     125       34225 :                 streambuf_type::setp(base + diff, base + _buf.size() - 1); // -1 to make overflow() easier
     126       34224 :         }
     127             : 
     128       34225 :     virtual int_type overflow(int_type ch) override {
     129       34225 :         if (ch != traits_type::eof()) {
     130       34225 :                         *streambuf_type::pptr() = ch;
     131       34225 :                         streambuf_type::pbump(1);
     132       34225 :                         make_flush();
     133       34224 :                         return ch;
     134             :                 }
     135             : 
     136           0 :                 return traits_type::eof();
     137             :     }
     138           0 :     virtual int sync() override {
     139           0 :         make_flush();
     140           0 :         return 0;
     141             :     }
     142             : 
     143             :     mem_type _buf;
     144             : };
     145             : 
     146             : 
     147             : template <typename CharType>
     148             : class basic_ostringstream final : public std::basic_ostream<CharType>, public AllocPool {
     149             : public:
     150             :         // Types:
     151             :         using char_type = CharType;
     152             :         using traits_type = std::char_traits<CharType>;
     153             : 
     154             :         using allocator_type = Allocator<CharType>;
     155             :         using int_type = typename traits_type::int_type;
     156             :         using pos_type = typename traits_type::pos_type;
     157             :         using off_type = typename traits_type::off_type;
     158             :         using size_type = size_t;
     159             : 
     160             :         // Non-standard types:
     161             :         using string_type = basic_string<CharType>;
     162             :         using stringbuf_type = basic_ostringbuf<CharType>;
     163             :         using ostream_type = std::basic_ostream<char_type>;
     164             : 
     165             : private:
     166             :         stringbuf_type _buf;
     167             : 
     168             : public:
     169             :         explicit
     170       53325 :         basic_ostringstream(size_type block = stringbuf_type::mem_type::get_soo_size(), const allocator_type &alloc = allocator_type()) noexcept
     171       53325 :         : ostream_type(&_buf), _buf(block, alloc) {
     172       53324 :                 this->init(&_buf);
     173       53324 :         }
     174             : 
     175             :         basic_ostringstream(CharType *ptr, size_type block, const allocator_type &alloc = allocator_type()) noexcept
     176             :         : ostream_type(&_buf), _buf(ptr, block, alloc) {
     177             :                 this->init(&_buf);
     178             :         }
     179             : 
     180             :         basic_ostringstream(basic_ostringstream && rhs) noexcept
     181             :         : ostream_type(std::move(rhs)), _buf(std::move(rhs._buf)) {
     182             :                 ostream_type::set_rdbuf(&_buf);
     183             :         }
     184             : 
     185           0 :         basic_ostringstream & operator=(basic_ostringstream && rhs) noexcept {
     186           0 :                 ostream_type::operator=(std::move(rhs));
     187           0 :                 _buf = std::move(rhs._buf);
     188           0 :                 return *this;
     189             :         }
     190             : 
     191       52124 :         ~basic_ostringstream() noexcept {}
     192             : 
     193             :         basic_ostringstream(const basic_ostringstream &) = delete;
     194             :         basic_ostringstream & operator=(const basic_ostringstream &) = delete;
     195             : 
     196             :         void swap(basic_ostringstream & rhs) {
     197             :                 ostream_type::swap(rhs);
     198             :                 _buf.swap(rhs._buf);
     199             :         }
     200             : 
     201             :         stringbuf_type * rdbuf() const {
     202             :                 return const_cast<stringbuf_type *>(&_buf);
     203             :         }
     204             : 
     205       52100 :         string_type str() const noexcept { return _buf.str(); }
     206       48525 :         string_type weak() const noexcept { return string_type::make_weak(data(), size()); }
     207       46025 :         void clear() { _buf.clear(); }
     208             : 
     209       64499 :         bool empty() const noexcept { return _buf.empty(); }
     210       48748 :         size_t size() const noexcept { return _buf.size(); }
     211             :         CharType *data() noexcept { return _buf.data(); }
     212       48523 :         const CharType *data() const noexcept { return _buf.data(); }
     213             : 
     214         375 :         void reserve(size_t size) { _buf.reserve(size); }
     215             : 
     216             :         const allocator_type &get_allocator() const noexcept { return _buf.get_allocator(); }
     217             : };
     218             : 
     219             : using ostringstream = basic_ostringstream<char>;
     220             : 
     221             : template<typename CharType> inline std::basic_ostream<CharType> &
     222         100 : operator << (std::basic_ostream<CharType> & os, const basic_ostringstream<CharType> & str) {
     223         100 :         return os << str.str();
     224             : }
     225             : 
     226             : }
     227             : 
     228             : #endif /* STAPPLER_CORE_MEMORY_SPMEMSTRINGSTREAM_H_ */

Generated by: LCOV version 1.14