LCOV - code coverage report
Current view: top level - include/hpactor/adt - stream_buffer.hpp (source / functions) Coverage Total Hit
Test: HPActor Coverage Lines: 86.7 % 30 26
Test Date: 2026-05-20 02:24:49 Functions: 75.0 % 28 21
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : // Copyright 2026 HPActor Contributors
       2                 :             : //
       3                 :             : // Licensed under the Apache License, Version 2.0 (the "License");
       4                 :             : // you may not use this file except in compliance with the License.
       5                 :             : // You may obtain a copy of the License at
       6                 :             : //
       7                 :             : //     http://www.apache.org/licenses/LICENSE-2.0
       8                 :             : //
       9                 :             : // Unless required by applicable law or agreed to in writing, software
      10                 :             : // distributed under the License is distributed on an "AS IS" BASIS,
      11                 :             : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12                 :             : // See the License for the specific language governing permissions and
      13                 :             : // limitations under the License.
      14                 :             : 
      15                 :             : #pragma once
      16                 :             : 
      17                 :             : #include <cstddef>
      18                 :             : #include <cstdint>
      19                 :             : #include <initializer_list>
      20                 :             : #include <type_traits>
      21                 :             : #include <vector>
      22                 :             : 
      23                 :             : namespace hpactor {
      24                 :             : namespace adt {
      25                 :             : 
      26                 :             : // StreamBuffer — contiguous byte buffer with O(1) consume and arena allocation.
      27                 :             : //
      28                 :             : // Combines ring-buffer semantics (read_pos_ offset tracks consumed prefix,
      29                 :             : // consume() only advances a pointer) with pre-allocated arena backing
      30                 :             : // (geometric growth from an initial capacity). Lazy compaction means
      31                 :             : // memmove is amortized to near-zero: it only triggers when read_pos_ exceeds
      32                 :             : // half the live data, or when capacity must grow.
      33                 :             : //
      34                 :             : // Provides a std::vector<uint8_t>-compatible API so it can serve as the
      35                 :             : // concrete type behind the `bytes` typedef.
      36                 :             : class StreamBuffer {
      37                 :             : public:
      38                 :             :     using value_type = uint8_t;
      39                 :             :     using size_type = std::size_t;
      40                 :             :     using difference_type = std::ptrdiff_t;
      41                 :             :     using reference = uint8_t&;
      42                 :             :     using const_reference = const uint8_t&;
      43                 :             :     using pointer = uint8_t*;
      44                 :             :     using const_pointer = const uint8_t*;
      45                 :             :     using iterator = pointer;
      46                 :             :     using const_iterator = const_pointer;
      47                 :             : 
      48                 :             :     static constexpr size_t kDefaultInitialCapacity = 65536;
      49                 :             :     static constexpr size_t kCompactThreshold = 65536;
      50                 :             : 
      51                 :             :     // ---- Constructors ----
      52                 :             : 
      53                 :         988 :     StreamBuffer() = default;
      54                 :             : 
      55                 :             :     // Create a buffer with count zero-initialized bytes (matches std::vector).
      56                 :             :     explicit StreamBuffer(size_t count);
      57                 :             : 
      58                 :             :     StreamBuffer(std::initializer_list<uint8_t> ilist);
      59                 :             :     StreamBuffer(size_t count, uint8_t value);
      60                 :             : 
      61                 :             :     template <typename InputIt, typename = std::enable_if_t<!std::is_integral_v<InputIt>>>
      62                 :             :     StreamBuffer(InputIt first, InputIt last);
      63                 :             : 
      64                 :     3248672 :     ~StreamBuffer() = default;
      65                 :             : 
      66                 :             :     // Create a buffer with pre-allocated capacity but size() == 0.
      67                 :             :     static StreamBuffer with_capacity(size_t cap);
      68                 :             : 
      69                 :             :     // ---- Copy ----
      70                 :             : 
      71                 :             :     StreamBuffer(const StreamBuffer& other);
      72                 :             :     StreamBuffer& operator=(const StreamBuffer& other);
      73                 :             : 
      74                 :             :     // ---- Move ----
      75                 :             : 
      76                 :     2125619 :     StreamBuffer(StreamBuffer&&) noexcept = default;
      77                 :     1001206 :     StreamBuffer& operator=(StreamBuffer&&) noexcept = default;
      78                 :             : 
      79                 :             :     // ---- Capacity ----
      80                 :             : 
      81                 :      122320 :     size_t size() const noexcept { return buf_.size() - read_pos_; }
      82                 :          21 :     bool empty() const noexcept { return size() == 0; }
      83                 :             :     size_t capacity() const noexcept { return buf_.capacity(); }
      84                 :             :     void reserve(size_t n);
      85                 :             :     void resize(size_t n);
      86                 :             :     void resize(size_t n, uint8_t value);
      87                 :             : 
      88                 :             :     // ---- Iterators ----
      89                 :             : 
      90                 :          68 :     iterator begin() noexcept {
      91                 :          68 :         maybe_compact();
      92                 :          68 :         return buf_.data() + read_pos_;
      93                 :             :     }
      94                 :          46 :     const_iterator begin() const noexcept { return buf_.data() + read_pos_; }
      95                 :             :     const_iterator cbegin() const noexcept { return begin(); }
      96                 :          55 :     iterator end() noexcept { return begin() + size(); }
      97                 :          18 :     const_iterator end() const noexcept { return begin() + size(); }
      98                 :             :     const_iterator cend() const noexcept { return end(); }
      99                 :             : 
     100                 :             :     // ---- Element access ----
     101                 :             : 
     102                 :             :     uint8_t& front() { return operator[](0); }
     103                 :             :     const uint8_t& front() const { return operator[](0); }
     104                 :             :     uint8_t& back() { return operator[](size() - 1); }
     105                 :             :     const uint8_t& back() const { return operator[](size() - 1); }
     106                 :             : 
     107                 :          13 :     uint8_t& operator[](size_t i) { return buf_[read_pos_ + i]; }
     108                 :         130 :     const uint8_t& operator[](size_t i) const { return buf_[read_pos_ + i]; }
     109                 :             : 
     110                 :          65 :     uint8_t* data() noexcept {
     111                 :          65 :         maybe_compact();
     112                 :          65 :         return buf_.data() + read_pos_;
     113                 :             :     }
     114                 :         187 :     const uint8_t* data() const noexcept { return buf_.data() + read_pos_; }
     115                 :             : 
     116                 :             :     // ---- Reserve + Write (direct I/O) ----
     117                 :             : 
     118                 :             :     uint8_t* reserve_tail(size_t n);
     119                 :             :     void commit_tail(size_t n);
     120                 :             : 
     121                 :             :     // ---- Append (copy-in) ----
     122                 :             : 
     123                 :             :     void append(const uint8_t* data, size_t len);
     124                 :             : 
     125                 :             :     // ---- Modifiers ----
     126                 :             : 
     127                 :             :     void push_back(uint8_t value);
     128                 :             : 
     129                 :             :     void assign(size_t count, uint8_t value);
     130                 :             :     template <typename InputIt>
     131                 :             :     void assign(InputIt first, InputIt last);
     132                 :             :     void assign(std::initializer_list<uint8_t> ilist);
     133                 :             : 
     134                 :             :     template <typename InputIt>
     135                 :             :     iterator insert(const_iterator pos, InputIt first, InputIt last);
     136                 :             : 
     137                 :             :     iterator insert(const_iterator pos, std::initializer_list<uint8_t> ilist);
     138                 :             : 
     139                 :             :     iterator erase(const_iterator first, const_iterator last);
     140                 :             : 
     141                 :             :     void clear() noexcept;
     142                 :             : 
     143                 :             :     // ---- Consume (StreamBuffer-specific, not in std::vector) ----
     144                 :             : 
     145                 :             :     void consume(size_t n);
     146                 :             :     void compact();
     147                 :             : 
     148                 :             :     // ---- Comparison ----
     149                 :             : 
     150                 :             :     bool operator==(const StreamBuffer& other) const;
     151                 :             :     bool operator!=(const StreamBuffer& other) const { return !(*this == other); }
     152                 :             : 
     153                 :             : private:
     154                 :             :     void ensure_capacity(size_t additional_bytes);
     155                 :             :     void maybe_compact();
     156                 :             : 
     157                 :             :     std::vector<uint8_t> buf_;
     158                 :             :     size_t read_pos_ = 0;
     159                 :             :     size_t reserve_tail_amount_ = 0;
     160                 :             : };
     161                 :             : 
     162                 :             : // ---- Template implementations ----
     163                 :             : 
     164                 :             : template <typename InputIt, typename>
     165                 :          34 : StreamBuffer::StreamBuffer(InputIt first, InputIt last) {
     166                 :          34 :     buf_.insert(buf_.end(), first, last);
     167                 :          34 : }
     168                 :             : 
     169                 :             : template <typename InputIt>
     170                 :           0 : void StreamBuffer::assign(InputIt first, InputIt last) {
     171                 :           0 :     clear();
     172                 :           0 :     buf_.assign(first, last);
     173                 :           0 : }
     174                 :             : 
     175                 :             : template <typename InputIt>
     176                 :          41 : auto StreamBuffer::insert(const_iterator pos, InputIt first, InputIt last) -> iterator {
     177                 :          41 :     size_t offset = static_cast<size_t>(pos - (buf_.data() + read_pos_));
     178                 :          41 :     compact();
     179                 :          41 :     auto it = buf_.insert(buf_.begin() + static_cast<std::ptrdiff_t>(offset), first, last);
     180                 :          41 :     return buf_.data() + static_cast<size_t>(it - buf_.begin());
     181                 :             : }
     182                 :             : 
     183                 :             : } // namespace adt
     184                 :             : } // namespace hpactor
        

Generated by: LCOV version 2.0-1