LCOV - code coverage report
Current view: top level - ezlibs - ezStackString.hpp (source / functions) Coverage Total Hit
Test: Coverage (llvm-cov → lcov → genhtml) Lines: 98.3 % 119 117
Test Date: 2025-09-16 22:55:37 Functions: 100.0 % 47 47
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 56.4 % 94 53

             Branch data     Line data    Source code
       1                 :             : #pragma once
       2                 :             : 
       3                 :             : #include <cstring>
       4                 :             : #include <stdexcept>
       5                 :             : #include <type_traits>
       6                 :             : 
       7                 :             : namespace ez {
       8                 :             : 
       9                 :             : /*
      10                 :             : this class is a string who have a pre defined size and content saved in stack
      11                 :             : faster if all operations are made idnide the pre defiend stack buffer
      12                 :             : when the size grow out of the pre defined size its moving to heap
      13                 :             : */
      14                 :             : 
      15                 :             : template <typename TChar, size_t StackChunkSize = 256, size_t HeapChunkSize = StackChunkSize>
      16                 :             : class StackString {
      17                 :             :     static_assert(std::is_trivial<TChar>::value, "TChar must be a trivial type");
      18                 :             : 
      19                 :             :     size_t _heapSize{};  // capacity allocated in _heapData
      20                 :             :     size_t _heapLength{};  // actual length used in _heapData
      21                 :             :     TChar* _heapData{};  // heap buffer (null if using stack)
      22                 :             :     size_t _stackLength{};  // actual length in _stackData
      23                 :             :     TChar _stackData[StackChunkSize + 1]{};  // stack buffer (+1 for null terminator)
      24                 :             : 
      25                 :             : public:
      26                 :             :     static constexpr size_t npos = static_cast<size_t>(-1);
      27                 :             : 
      28                 :             : public:
      29                 :             :     StackString() = default;
      30                 :          11 :     explicit StackString(const TChar* str) { append(str); }
      31                 :             : 
      32                 :           1 :     StackString(const StackString& other) { append(other.c_str()); }
      33                 :             : 
      34                 :           3 :     StackString(StackString&& other) noexcept : _heapSize(other._heapSize), _heapLength(other._heapLength), _heapData(other._heapData), _stackLength(other._stackLength) {
      35                 :           3 :         std::memcpy(_stackData, other._stackData, sizeof(_stackData));
      36                 :           3 :         other._heapData = nullptr;
      37                 :           3 :         other._heapSize = 0;
      38                 :           3 :         other._heapLength = 0;
      39                 :           3 :         other._stackLength = 0;
      40                 :           3 :         other._stackData[0] = TChar(0);
      41                 :           3 :     }
      42                 :             : 
      43                 :             :     StackString& operator=(const StackString& other) {
      44                 :             :         if (this != &other) {
      45                 :             :             clear();
      46                 :             :             append(other.c_str());
      47                 :             :         }
      48                 :             :         return *this;
      49                 :             :     }
      50                 :             : 
      51                 :             :     StackString& operator=(StackString&& other) {
      52                 :             :         if (this != &other) {
      53                 :             :             clear();
      54                 :             :             delete[] _heapData;
      55                 :             :             _heapSize = other._heapSize;
      56                 :             :             _heapLength = other._heapLength;
      57                 :             :             _heapData = other._heapData;
      58                 :             :             _stackLength = other._stackLength;
      59                 :             :             std::memcpy(_stackData, other._stackData, sizeof(_stackData));
      60                 :             :             other._heapData = nullptr;
      61                 :             :             other._heapSize = 0;
      62                 :             :             other._heapLength = 0;
      63                 :             :             other._stackLength = 0;
      64                 :             :             other._stackData[0] = TChar(0);
      65                 :             :         }
      66                 :             :         return *this;
      67                 :             :     }
      68                 :             : 
      69                 :          15 :     ~StackString() { delete[] _heapData; }
      70                 :             : 
      71                 :           1 :     void clear() {
      72                 :           1 :         _stackLength = 0;
      73                 :           1 :         _stackData[0] = TChar(0);
      74                 :           1 :         delete[] _heapData;
      75                 :           1 :         _heapData = nullptr;
      76                 :           1 :         _heapSize = 0;
      77                 :           1 :         _heapLength = 0;
      78                 :           1 :     }
      79                 :             : 
      80                 :           5 :     bool usingHeap() const { return _heapData != nullptr; }
      81 [ -  + ][ -  + ]:          18 :     const TChar* c_str() const { return _heapData ? _heapData : _stackData; }
         [ +  - ][ -  + ]
                 [ +  + ]
      82 [ -  + ][ +  + ]:          37 :     size_t size() const { return _heapData ? _heapLength : _stackLength; }
         [ -  + ][ -  + ]
                 [ -  + ]
      83                 :             : 
      84                 :          22 :     void reserve(size_t newSize) {
      85                 :          22 :         if (HeapChunkSize == 0) {
      86 [ #  # ][ #  # ]:           3 :             if (newSize > StackChunkSize) {
         [ #  # ][ #  # ]
                 [ +  + ]
      87                 :           1 :                 throw std::runtime_error("Heap allocation disabled");
      88                 :           1 :             }
      89                 :           2 :             return;
      90                 :           3 :         }
      91 [ +  + ][ -  + ]:          19 :         if (_heapData) {
         [ #  # ][ -  + ]
                 [ -  + ]
      92 [ #  # ][ #  # ]:           1 :             if (newSize <= _heapSize) {
         [ #  # ][ -  + ]
                 [ #  # ]
      93                 :           0 :                 return;
      94                 :           0 :             }
      95                 :           1 :             size_t newCap = ((newSize / HeapChunkSize) + 1) * HeapChunkSize;
      96                 :           1 :             TChar* newData = new TChar[newCap + 1];
      97                 :           1 :             std::memcpy(newData, _heapData, _heapLength * sizeof(TChar));
      98                 :           1 :             newData[_heapLength] = TChar(0);
      99                 :           1 :             delete[] _heapData;
     100                 :           1 :             _heapData = newData;
     101                 :           1 :             _heapSize = newCap;
     102                 :          18 :         } else {
     103 [ +  - ][ +  - ]:          18 :             if (newSize <= StackChunkSize) {
         [ +  + ][ #  # ]
                 [ +  + ]
     104                 :          15 :                 return;
     105                 :          15 :             }
     106                 :           3 :             size_t newCap = ((newSize / HeapChunkSize) + 1) * HeapChunkSize;
     107                 :           3 :             _heapData = new TChar[newCap + 1];
     108                 :           3 :             std::memcpy(_heapData, _stackData, _stackLength * sizeof(TChar));
     109                 :           3 :             _heapLength = _stackLength;
     110                 :           3 :             _heapData[_heapLength] = TChar(0);
     111                 :           3 :             _heapSize = newCap;
     112                 :           3 :         }
     113                 :          19 :     }
     114                 :             : 
     115                 :          22 :     void append(const TChar* str) {
     116                 :          22 :         const size_t len = std::char_traits<TChar>::length(str);
     117                 :          22 :         const size_t currentLen = size();
     118                 :          22 :         const size_t totalLen = currentLen + len;
     119                 :          22 :         reserve(totalLen);
     120 [ -  + ][ -  + ]:          22 :         if (_heapData) {
         [ +  + ][ -  + ]
                 [ +  + ]
     121                 :           4 :             std::memcpy(_heapData + _heapLength, str, len * sizeof(TChar));
     122                 :           4 :             _heapLength += len;
     123                 :           4 :             _heapData[_heapLength] = TChar(0);
     124                 :          18 :         } else {
     125                 :          18 :             std::memcpy(_stackData + _stackLength, str, len * sizeof(TChar));
     126                 :          18 :             _stackLength += len;
     127                 :          18 :             _stackData[_stackLength] = TChar(0);
     128                 :          18 :         }
     129                 :          22 :     }
     130                 :             : 
     131                 :           2 :     void append(TChar c) {
     132                 :           2 :         TChar tmp[2] = {c, TChar(0)};
     133                 :           2 :         append(tmp);
     134                 :           2 :     }
     135                 :             : 
     136                 :           7 :     StackString& operator+=(const TChar* str) {
     137                 :           7 :         append(str);
     138                 :           7 :         return *this;
     139                 :           7 :     }
     140                 :             : 
     141                 :           1 :     StackString& operator+=(TChar c) {
     142                 :           1 :         append(c);
     143                 :           1 :         return *this;
     144                 :           1 :     }
     145                 :             : 
     146                 :           5 :     TChar& operator[](size_t index) {
     147         [ +  + ]:           5 :         if (index >= size()) {
     148                 :           2 :             throw std::out_of_range("StackString index out of range");
     149                 :           2 :         }
     150         [ +  + ]:           3 :         return _heapData ? _heapData[index] : _stackData[index];
     151                 :           5 :     }
     152                 :             : 
     153                 :           4 :     const TChar& at(size_t index) const {
     154         [ +  + ]:           4 :         if (index >= size()) {
     155                 :           2 :             throw std::out_of_range("StackString index out of range");
     156                 :           2 :         }
     157         [ +  + ]:           2 :         return _heapData ? _heapData[index] : _stackData[index];
     158                 :           4 :     }
     159                 :             : 
     160                 :           4 :     size_t find(const TChar* needle, size_t pos = 0) const {
     161                 :           4 :         const TChar* haystack = c_str();
     162                 :           4 :         const size_t hayLen = size();
     163                 :           4 :         const size_t needleLen = std::char_traits<TChar>::length(needle);
     164 [ +  + ][ -  + ]:           4 :         if (needleLen == 0 || pos > hayLen || needleLen > hayLen - pos) {
                 [ -  + ]
     165                 :           1 :             return npos;
     166                 :           1 :         }
     167         [ +  + ]:          23 :         for (size_t i = pos; i <= hayLen - needleLen; ++i) {
     168         [ +  + ]:          22 :             if (std::char_traits<TChar>::compare(haystack + i, needle, needleLen) == 0) {
     169                 :           2 :                 return i;
     170                 :           2 :             }
     171                 :          22 :         }
     172                 :           1 :         return npos;
     173                 :           3 :     }
     174                 :             : 
     175                 :           2 :     StackString substr(size_t pos, size_t count = npos) const {
     176                 :           2 :         const size_t len = size();
     177         [ +  + ]:           2 :         if (pos > len) {
     178                 :           1 :             throw std::out_of_range("substr position out of range");
     179                 :           1 :         }
     180 [ -  + ][ -  + ]:           1 :         size_t actualCount = (count == npos || pos + count > len) ? len - pos : count;
     181                 :           1 :         const TChar* src = c_str() + pos;
     182                 :           1 :         TChar* tmp = new TChar[actualCount + 1];
     183                 :           1 :         std::memcpy(tmp, src, actualCount * sizeof(TChar));
     184                 :           1 :         tmp[actualCount] = TChar(0);
     185                 :             : 
     186                 :           1 :         StackString result(tmp);
     187                 :           1 :         delete[] tmp;
     188                 :           1 :         return result;
     189                 :           2 :     }
     190                 :             : };
     191                 :             : 
     192                 :             : }  // namespace ez
        

Generated by: LCOV version 2.0-1