AUI Framework  develop
Cross-platform base for C++ UI apps
Loading...
Searching...
No Matches
AByteBuffer.h
    1/*
    2 * AUI Framework - Declarative UI toolkit for modern C++20
    3 * Copyright (C) 2020-2025 Alex2772 and Contributors
    4 *
    5 * SPDX-License-Identifier: MPL-2.0
    6 *
    7 * This Source Code Form is subject to the terms of the Mozilla Public
    8 * License, v. 2.0. If a copy of the MPL was not distributed with this
    9 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
   10 */
   11
   12#pragma once
   13
   14#include "AUI/Util/Assert.h"
   15#include "SharedPtr.h"
   16
   17#include <cstddef>
   18#include <cstring>
   19#include <string>
   20#include <stdexcept>
   21#include <cassert>
   22#include "AUI/Core.h"
   23#include <AUI/Traits/serializable.h>
   24#include "AByteBufferView.h"
   25
   26
   31class API_AUI_CORE AByteBuffer final: public IOutputStream {
   32private:
   33    char* mBuffer = nullptr;
   34    size_t mCapacity = 0;
   35    size_t mSize = 0;
   36
   37public:
   38    using iterator = char*;
   39
   40    AByteBuffer();
   41    AByteBuffer(const char* buffer, size_t size);
   42    explicit AByteBuffer(size_t initialCapacity);
   43    AByteBuffer(const unsigned char* buffer, size_t size);
   44    AByteBuffer(AByteBufferView other) {
   45        reserve(other.size());
   46        memcpy(mBuffer, other.data(), other.size());
   47        mSize = other.size();
   48    }
   49
   50    AByteBuffer(const AByteBuffer& other): AByteBuffer(AByteBufferView(other)) {}
   51    AByteBuffer(AByteBuffer&& other) noexcept;
   52
   53    ~AByteBuffer();
   54
   55    void write(const char* src, size_t size) override;
   56
   57
   58    [[nodiscard]]
   59    AByteBufferView slice(std::size_t offset, std::size_t size) const noexcept {
   60        return operator AByteBufferView().slice(offset, size);
   61    }
   62
   63    [[nodiscard]]
   64    AByteBufferView slice(std::size_t offset /* to end */) const noexcept {
   65        return operator AByteBufferView().slice(offset);
   66    }
   67
   73    void write(IInputStream& stream, size_t size);
   74
   75    operator AByteBufferView() const noexcept {
   76        return { mBuffer, mSize };
   77    }
   78
   79    void clear() {
   80        delete[] mBuffer;
   81        mBuffer = nullptr;
   82        mSize = mCapacity = 0;
   83    }
   84
   88    void reserve(size_t size);
   89
   93    void increaseInternalBuffer(size_t size) {
   94        reserve(mCapacity + size);
   95    }
   96
  101    void grow(size_t size) {
  102        auto availableToWrite = getAvailableToWrite();
  103        if (availableToWrite < size) {
  104            increaseInternalBuffer((glm::max)(getReserved() * 2, size_t(size - availableToWrite)));
  105        }
  106    }
  107
  111    size_t getAvailableToWrite() const {
  112        return getReserved() - getSize();
  113    }
  114
  115
  119    char* data() const
  120    {
  121        return mBuffer;
  122    }
  123
  130    template <typename T>
  131    T& at(size_t byteIndex)
  132    {
  133        return *reinterpret_cast<T*>(mBuffer + byteIndex);
  134    }
  135
  136
  143    template <typename T>
  144    const T& at(size_t byteIndex) const
  145    {
  146        return *reinterpret_cast<T*>(mBuffer + byteIndex);
  147    }
  148
  160    void setSize(size_t s) {
  161        AUI_ASSERTX(s <= mCapacity, "size cannot be greater than reserved buffer size; did you mean AByteBuffer::resize?");
  162        mSize = s;
  163    }
  164
  175    void increaseSize(size_t s) {
  176        mSize += s;
  177        AUI_ASSERTX(mSize <= mCapacity, "size cannot be greater than reserved buffer size; did you mean AByteBuffer::resize?");
  178    }
  179
  185    void resize(size_t s) {
  186        if (mCapacity < s) {
  187            reserve(s);
  188        }
  189        mSize = s;
  190    }
  191
  197    void reallocate(size_t s) {
  198        if (mCapacity != s) {
  199            delete[] mBuffer;
  200            if (s == 0) {
  201                mBuffer = nullptr;
  202            } else {
  203                mBuffer = new char[s];
  204            }
  205            mCapacity = s;
  206        }
  207        mSize = s;
  208    }
  209
  213    size_t getSize() const noexcept {
  214        return mSize;
  215    }
  216
  220    bool empty() const noexcept {
  221        return mSize == 0;
  222    }
  223
  227    size_t size() const noexcept {
  228        return mSize;
  229    }
  230
  234    size_t capacity() const noexcept {
  235        return mCapacity;
  236    }
  237
  241    size_t getReserved() const noexcept {
  242        return mCapacity;
  243    }
  244
  245    AByteBuffer& operator=(AByteBuffer&& other) noexcept {
  246        if (&other == this) {
  247            return *this;
  248        }
  249
  250        delete[] mBuffer;
  251        mBuffer = other.mBuffer;
  252        mCapacity = other.mCapacity;
  253        mSize = other.mSize;
  254
  255        other.mBuffer = nullptr;
  256        other.mCapacity = 0;
  257        other.mSize = 0;
  258
  259        return *this;
  260    }
  261    AByteBuffer& operator=(const AByteBuffer& other) {
  262        if (&other == this) {
  263            return *this;
  264        }
  265
  266        if (mCapacity < other.size()) {
  267            reallocate(other.size());
  268        }
  269        std::memcpy(mBuffer, other.data(), other.size());
  270        mSize = other.mSize;
  271
  272        return *this;
  273    }
  274
  275    bool operator==(const AByteBuffer& r) const;
  276    bool operator!=(const AByteBuffer& r) const;
  277
  278    char* begin()
  279    {
  280        return mBuffer;
  281    }
  282    char* end()
  283    {
  284        return mBuffer + mSize;
  285    }
  286    char* endReserved()
  287    {
  288        return mBuffer + mCapacity;
  289    }
  290    const char* begin() const
  291    {
  292        return mBuffer;
  293    }
  294    const char* end() const
  295    {
  296        return mBuffer + mSize;
  297    }
  298
  299
  300    template<typename T>
  301    T as() const {
  302        return AByteBufferView(*this).template as<T>();
  303    }
  304
  305    [[nodiscard]]
  306    AString toHexString() const {
  307        return AByteBufferView(*this).toHexString();
  308    }
  309
  310    [[nodiscard]]
  311    AString toBase64String() const {
  312        return AByteBufferView(*this).toBase64String();
  313    }
  314
  315    iterator erase(iterator begin, iterator end) noexcept {
  316        AUI_ASSERT(ownsIterator(begin));
  317        AUI_ASSERT(ownsIterator(end));
  318        std::memmove(begin, end, std::distance(end, AByteBuffer::end()));
  319        setSize(size() - std::distance(begin, end));
  320        return begin;
  321    }
  322
  323    [[nodiscard]]
  324    bool ownsIterator(iterator i) const noexcept {
  325        return i >= begin() && i <= end();
  326    }
  327
  328    static AByteBuffer fromStream(aui::no_escape<IInputStream> is);
  329    static AByteBuffer fromStream(aui::no_escape<IInputStream> is, size_t sizeRestriction);
  330
  331    static AByteBuffer fromString(const AString& string);
  332    static AByteBuffer fromHexString(const AString& string);
  333    static AByteBuffer fromBase64String(const AString& encodedString);
  334};
  335
  336API_AUI_CORE std::ostream& operator<<(std::ostream& o, AByteBufferView buffer);
  337
  338template<>
  340    static void write(IOutputStream& os, const AByteBuffer& value) {
  341        os.write(value.data(), value.size());
  342    }
  343};
Acts like std::string_view but for AByteBuffer.
Definition AByteBufferView.h:24
std::vector-like growing array for byte storage.
Definition AByteBuffer.h:31
void reallocate(size_t s)
Definition AByteBuffer.h:197
void increaseSize(size_t s)
Definition AByteBuffer.h:175
size_t getAvailableToWrite() const
Definition AByteBuffer.h:111
void increaseInternalBuffer(size_t size)
Increases internal buffer.
Definition AByteBuffer.h:93
T & at(size_t byteIndex)
Gets value of specified type by byte index relative to the beginning of internal buffer.
Definition AByteBuffer.h:131
size_t size() const noexcept
Definition AByteBuffer.h:227
size_t capacity() const noexcept
Definition AByteBuffer.h:234
void write(const char *src, size_t size) override
Writes exact size bytes to stream. Blocking (waiting for write all data) is allowed.
const T & at(size_t byteIndex) const
Gets value of specified type by byte index relative to the beginning of internal buffer.
Definition AByteBuffer.h:144
void grow(size_t size)
If getReserved() - getSize() is less than size increases internal buffer size enough to store size by...
Definition AByteBuffer.h:101
void reserve(size_t size)
Resizes internal buffer.
void resize(size_t s)
Definition AByteBuffer.h:185
void setSize(size_t s)
Definition AByteBuffer.h:160
void write(IInputStream &stream, size_t size)
size_t getReserved() const noexcept
Definition AByteBuffer.h:241
size_t getSize() const noexcept
Definition AByteBuffer.h:213
bool empty() const noexcept
Definition AByteBuffer.h:220
char * data() const
Definition AByteBuffer.h:119
Represents an input stream.
Definition IInputStream.h:26
Definition IOutputStream.h:18
virtual void write(const char *src, size_t size)=0
Writes exact size bytes to stream. Blocking (waiting for write all data) is allowed.
#define AUI_ASSERT(condition)
Asserts that the passed condition evaluates to true.
Definition Assert.h:55
#define AUI_ASSERTX(condition, what)
Asserts that the passed condition evaluates to true. Adds extra message string.
Definition Assert.h:74
Definition serializable.h:26