LCOV - code coverage report
Current view: top level - core/core/utils - SPBuffer.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 161 167 96.4 %
Date: 2024-05-12 00:16:13 Functions: 100 117 85.5 %

          Line data    Source code
       1             : /**
       2             : Copyright (c) 2016-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_UTILS_SPBUFFER_H_
      25             : #define STAPPLER_CORE_UTILS_SPBUFFER_H_
      26             : 
      27             : #include "SPIOBuffer.h"
      28             : #include "SPStringStream.h"
      29             : #include "SPUnicode.h"
      30             : 
      31             : namespace STAPPLER_VERSIONIZED stappler {
      32             : 
      33             : template <typename Interface>
      34             : class BufferTemplate : public Interface::AllocBaseType {
      35             : public:
      36             :         using byte_type = uint8_t;
      37             :         static constexpr size_t defsize = 256;
      38             : 
      39       75375 :         BufferTemplate(size_t sz = defsize) {
      40       75375 :                 _buffer.resize(sz, 0);
      41       75375 :                 _ptr = (byte_type *)_buffer.data();
      42       75375 :                 _end = _ptr + sz;
      43       75375 :         }
      44             :         BufferTemplate(const BufferTemplate & rhs) : _buffer(rhs._buffer) {
      45             :                 _ptr = (byte_type *)(_buffer.data() + (rhs._ptr - rhs._buffer.data()));
      46             :                 _end = (byte_type *)(_buffer.data() + _buffer.size());
      47             :                 _input = rhs._input;
      48             :         }
      49          25 :         BufferTemplate(BufferTemplate && rhs) {
      50          25 :                 auto size = rhs._ptr - rhs._buffer.data();
      51          25 :                 _buffer = std::move(rhs._buffer);
      52          25 :                 _ptr = (byte_type *)(_buffer.data() + size);
      53          25 :                 _end = (byte_type *)(_buffer.data() + _buffer.size());
      54          25 :                 _input = rhs._input;
      55          25 :         }
      56             : 
      57          25 :         BufferTemplate & operator=(const BufferTemplate & rhs) {
      58          25 :                 auto size = rhs._ptr - rhs._buffer.data();
      59          25 :                 _buffer = rhs._buffer;
      60          25 :                 _ptr = (byte_type *)(_buffer.data() + size);
      61          25 :                 _end = (byte_type *)(_buffer.data() + _buffer.size());
      62          25 :                 _input = rhs._input;
      63          25 :                 return *this;
      64             :         }
      65          25 :         BufferTemplate & operator=(BufferTemplate && rhs) {
      66          25 :                 auto size = rhs._ptr - rhs._buffer.data();
      67          25 :                 _buffer = std::move(rhs._buffer);
      68          25 :                 _ptr = (byte_type *)(_buffer.data() + size);
      69          25 :                 _end = (byte_type *)(_buffer.data() + _buffer.size());
      70          25 :                 _input = rhs._input;
      71          25 :                 return *this;
      72             :         }
      73             : 
      74             :         template <typename CharType, typename std::enable_if<sizeof(CharType) == 1>::type * = nullptr>
      75      261575 :         size_t put(const CharType *ptr, size_t len) {
      76         925 :                 size_t ret = 0;
      77      524250 :                 while (ret < len) {
      78      262675 :                         const size_t bsize = _end - _ptr;
      79      262675 :                         if (bsize) {
      80      262100 :                                 const size_t remaining = len - ret;
      81      262100 :                                 const size_t nlen = min(bsize, remaining);
      82      262100 :                                 memcpy((void *)_ptr, (const void *)ptr, nlen);
      83      262100 :                                 ret += nlen;
      84      262100 :                                 ptr += nlen;
      85      262100 :                                 _ptr += nlen;
      86             :                         }
      87             : 
      88      262675 :                         if (ret < len) {
      89        1100 :                                 overflow(len - ret);
      90             :                         }
      91             :                 }
      92      261575 :                 if (_ptr > _buffer.data() + _input) {
      93      261425 :                         _input = _ptr - _buffer.data();
      94             :                 }
      95      261575 :                 return ret;
      96             :         }
      97             : 
      98             :         size_t putc(char16_t c) {
      99             :                 auto len = unicode::utf8EncodeLength(c);
     100             :                 if (_end - _ptr < len) {
     101             :                         overflow();
     102             :                 }
     103             :                 unicode::utf8EncodeBuf((char *)_ptr, c);
     104             :                 _ptr += len;
     105             : 
     106             :                 if (_ptr > _buffer.data() + _input) {
     107             :                         _input = _ptr - _buffer.data();
     108             :                 }
     109             :                 return len;
     110             :         }
     111             : 
     112         825 :         size_t putc(char c) {
     113         825 :                 if (_end == _ptr) {
     114           0 :                         overflow();
     115             :                 }
     116         825 :                 *_ptr = *((byte_type *)&c);
     117         825 :                 ++ _ptr;
     118             : 
     119         825 :                 if (_ptr > _buffer.data() + _input) {
     120         825 :                         _input = _ptr - _buffer.data();
     121             :                 }
     122         825 :                 return 1;
     123             :         }
     124             : 
     125             :         // toString interface adapter
     126             :         template <typename ... Args, std::enable_if_t<string::detail::IsFastToStringAvailable<Args...>::value> * = nullptr>
     127     2056625 :         StringView putStrings(Args && ... args) {
     128     2056625 :                 auto size = string::detail::getBufferSize(std::forward<Args>(args)...);
     129     2056625 :                 size_t emptyBytes = capacity() - (_ptr - _buffer.data());
     130     2056625 :                 if (emptyBytes < size) {
     131      139950 :                         overflow(emptyBytes);
     132             :                 }
     133             : 
     134     2056625 :                 char *start = (char *)_ptr;
     135     2056625 :                 auto s = string::detail::writeBuffer(start, std::forward<Args>(args)...);
     136     2056625 :                 if (s != size) {
     137           0 :                         std::cout << "Invalid buffer size for toString<fast>\n";
     138           0 :                         abort();
     139             :                 }
     140     2056625 :                 _ptr += s;
     141     2056625 :                 if (_ptr > _buffer.data() + _input) {
     142     2056625 :                         _input = _ptr - _buffer.data();
     143             :                 }
     144             : 
     145     2056625 :                 return StringView(start, s);
     146             :         }
     147             : 
     148             :         template <typename ... Args, std::enable_if_t<string::detail::IsFastToStringAvailable<Args...>::value> * = nullptr>
     149             :         StringView resetWithStrings(Args && ... args) {
     150             :                 clear();
     151             :                 return putStrings(std::forward<Args>(args)...);
     152             :         }
     153             : 
     154             :         template <typename Reader = StringView>
     155         775 :         Reader get() const {
     156         775 :                 return Reader((const typename Reader::CharType *)_buffer.data(), _ptr - _buffer.data());
     157             :         }
     158             : 
     159             :         template <typename Reader = StringView>
     160          25 :         Reader pop(size_t len) {
     161          25 :                 size_t sz = size();
     162          25 :                 len = min(len, sz);
     163          25 :                 Reader r((const typename Reader::CharType *)(_buffer.data() + sz - len), len);
     164          25 :                 _ptr = (byte_type *)(_buffer.data() + sz - len);
     165          25 :                 return r;
     166             :         }
     167             : 
     168             :         template <typename Reader = StringView>
     169          25 :         Reader read(size_t len) {
     170          25 :                 size_t input = _input;
     171          25 :                 size_t sz = size();
     172          25 :                 len = min(len, input - sz);
     173          25 :                 Reader r((const typename Reader::CharType *)(_buffer.data() + sz), len);
     174          25 :                 return r;
     175             :         }
     176             : 
     177       10900 :         void clear() {
     178       10900 :                 _ptr = (byte_type *)_buffer.data();
     179       10900 :                 _input = 0;
     180       10900 :         }
     181             : 
     182         175 :         bool seek(size_t pos) {
     183         175 :                 if (pos > _buffer.size()) {
     184          25 :                         overflow(pos - _buffer.size());
     185             :                 }
     186         175 :                 _ptr = _buffer.data() + pos;
     187         175 :                 if (_ptr > _buffer.data() + _input) {
     188          25 :                         _input = _ptr - _buffer.data();
     189             :                 }
     190         175 :                 return true;
     191             :         }
     192             : 
     193     2056700 :         size_t capacity() const {
     194     2056700 :                 return _buffer.size();
     195             :         }
     196             : 
     197        3850 :         size_t size() const {
     198        3850 :                 return _ptr - _buffer.data();
     199             :         }
     200             : 
     201         175 :         size_t input() const {
     202         175 :                 return _input;
     203             :         }
     204             : 
     205       13600 :         bool empty() const {
     206       13600 :                 return _ptr == _buffer.data();
     207             :         }
     208             : 
     209       72250 :         auto str() const -> typename Interface::StringType {
     210       72250 :                 return typename Interface::StringType((char *)_buffer.data(), _ptr - _buffer.data());
     211             :         }
     212             : 
     213          50 :         uint8_t * data() {
     214          50 :                 return _buffer.data();
     215             :         }
     216             : 
     217          50 :         uint8_t * prepare(size_t & size) {
     218          50 :                 clear();
     219          50 :                 auto c = capacity();
     220          50 :                 if (size > c) {
     221           0 :                         size = c;
     222             :                 }
     223          50 :                 return _ptr;
     224             :         }
     225             : 
     226          50 :         void save(uint8_t *, size_t nbytes) {
     227          50 :                 _ptr += nbytes;
     228          50 :                 if (_ptr > _buffer.data() + _input) {
     229          25 :                         _input = _ptr - _buffer.data();
     230             :                 }
     231          50 :         }
     232             : 
     233             : protected:
     234      141050 :         void overflow() {
     235      141050 :                 auto size = _ptr - _buffer.data();
     236      141050 :                 _buffer.resize(_buffer.size() * 2, 0);
     237      141050 :                 _ptr = (byte_type *)(_buffer.data() + size);
     238      141050 :                 _end = (byte_type *)(_buffer.data() + _buffer.size());
     239      141050 :         }
     240             : 
     241      141075 :         void overflow(size_t required) {
     242      141075 :                 if (required < _buffer.size()) {
     243      141050 :                         overflow();
     244             :                 } else {
     245          25 :                         auto size = _ptr - _buffer.data();
     246          25 :                         _buffer.resize(_buffer.size() + required, 0);
     247          25 :                         _ptr = (byte_type *)(_buffer.data() + size);
     248          25 :                         _end = (byte_type *)(_buffer.data() + _buffer.size());
     249             :                 }
     250      141075 :         }
     251             : 
     252             :         typename Interface::BytesType _buffer;
     253             :         uint8_t *_ptr = nullptr;
     254             :         uint8_t *_end = nullptr;
     255             :         size_t _input = 0;
     256             : };
     257             : 
     258             : template <size_t Size>
     259             : class StackBuffer {
     260             : public:
     261        6669 :         StackBuffer() { }
     262             :         StackBuffer(const StackBuffer & rhs) : _buf(rhs._buf), _size(rhs._size) { }
     263             :         StackBuffer(StackBuffer && rhs) : _buf(rhs._buf), _size(rhs._size) { }
     264             : 
     265             :         StackBuffer & operator=(const StackBuffer & rhs) {
     266             :                 _buf = rhs._buf;
     267             :                 _size = rhs._size;
     268             :                 return *this;
     269             :         }
     270             :         StackBuffer & operator=(StackBuffer && rhs) {
     271             :                 _buf = rhs._buf;
     272             :                 _size = rhs._size;
     273             :                 return *this;
     274             :         }
     275             : 
     276        6875 :         uint8_t & operator[] (size_t n) { return _buf[n]; }
     277             :         const uint8_t & operator[] (size_t n) const { return _buf[n]; }
     278             : 
     279             :         uint8_t & at(size_t n) { return _buf.at(n); }
     280             :         const uint8_t & at(size_t n) const { return _buf.at(n); }
     281             : 
     282      445463 :         size_t size() const { return _size; }
     283         525 :         size_t capacity() const { return Size; }
     284      645269 :         size_t remains() const { return Size - _size; }
     285             : 
     286             :         bool empty() const { return _size == 0; }
     287             :         bool full() const { return _size == Size; }
     288             : 
     289             :         void soft_clear() {
     290             :                 _size = 0;
     291             :         }
     292             : 
     293      647694 :         void clear() {
     294      647694 :                 memset(_buf.data(), 0, Size);
     295      647694 :                 _size = 0;
     296      647694 :         }
     297             : 
     298      436713 :         uint8_t *data() { return _buf.data(); }
     299             :         const uint8_t *data() const { return _buf.data(); }
     300             : 
     301             :         size_t put(const uint8_t *ptr, size_t s) {
     302             :                 if (s + _size > Size) {
     303             :                         s = Size - _size;
     304             :                 }
     305             : 
     306             :                 memcpy(_buf.data() + _size, ptr, s);
     307             :                 _size += s;
     308             :                 return s;
     309             :         }
     310             : 
     311             :         size_t putc(uint8_t c) {
     312             :                 return put(&c, 1);
     313             :         }
     314             : 
     315             :         template <typename Reader = StringView>
     316        3500 :         Reader get() const {
     317        3500 :                 return Reader((const typename Reader::CharType *)_buf.data(), _size);
     318             :         }
     319             : 
     320      642519 :         uint8_t * prepare(size_t & size) {
     321      642519 :                 clear();
     322      642519 :                 return prepare_preserve(size);
     323             :         }
     324             : 
     325      645269 :         uint8_t * prepare_preserve(size_t & size) {
     326      645269 :                 auto r = remains();
     327      645269 :                 if (r < size) {
     328           0 :                         size = r;
     329             :                 }
     330      645269 :                 return _buf.data() + _size;
     331             :         }
     332             : 
     333      645269 :         void save(uint8_t *data, size_t nbytes) {
     334      645269 :                 _size += nbytes;
     335      645269 :         }
     336             : 
     337             : protected:
     338             :         size_t _size = 0;
     339             :         std::array<uint8_t, Size> _buf;
     340             : };
     341             : 
     342             : }
     343             : 
     344             : namespace STAPPLER_VERSIONIZED stappler::io {
     345             : 
     346             : template <typename Interface>
     347             : struct BufferTraits<stappler::BufferTemplate<Interface>> {
     348             :         using type = stappler::BufferTemplate<Interface>;
     349             : 
     350          50 :         static uint8_t * PrepareFn(void *ptr, size_t & size) {
     351          50 :                 return ((type *)ptr)->prepare(size);
     352             :         }
     353             : 
     354             :         // save written bytes in buffer
     355          50 :         static void SaveFn(void *ptr, uint8_t *buf, size_t prepared, size_t nbytes) {
     356          50 :                 ((type *)ptr)->save(buf, nbytes);
     357          50 :         }
     358             : 
     359          25 :         static size_t SizeFn(void *ptr) { return ((type *)ptr)->size(); }
     360          25 :         static size_t CapacityFn(void *ptr) { return ((type *)ptr)->capacity(); }
     361          25 :         static uint8_t *DataFn(void *ptr) { return ((type *)ptr)->data(); }
     362          25 :         static void ClearFn(void *ptr) { ((type *)ptr)->clear(); }
     363             : };
     364             : 
     365             : template <size_t Size>
     366             : struct BufferTraits<StackBuffer<Size>> {
     367             :         using type = StackBuffer<Size>;
     368             : 
     369      642519 :         static uint8_t * PrepareFn(void *ptr, size_t & size) {
     370      642519 :                 return ((type *)ptr)->prepare(size);
     371             :         }
     372             : 
     373             :         // save written bytes in buffer
     374      642519 :         static void SaveFn(void *ptr, uint8_t *buf, size_t source, size_t nbytes) {
     375      642519 :                 ((type *)ptr)->save(buf, nbytes);
     376      642519 :         }
     377             : 
     378      424750 :         static size_t SizeFn(void *ptr) { return ((type *)ptr)->size(); }
     379         100 :         static size_t CapacityFn(void *ptr) { return ((type *)ptr)->capacity(); }
     380      424750 :         static uint8_t *DataFn(void *ptr) { return ((type *)ptr)->data(); }
     381           0 :         static void ClearFn(void *ptr) { ((type *)ptr)->clear(); }
     382             : };
     383             : 
     384             : }
     385             : 
     386             : #endif /* STAPPLER_CORE_UTILS_SPBUFFER_H_ */

Generated by: LCOV version 1.14