Skip to content

AByteBuffer#

std::vector-like growing array for byte storage.

Header:#include <AUI/Common/AByteBuffer.h>
CMake:aui_link(my_target PUBLIC aui::core)

Detailed Description#

AByteBuffer holds raw binary data: file contents, network packets, compressed blobs. It is also an IOutputStream, so anything that can be written to a stream can be appended to it with operator<<.

Conversions#

AByteBuffer buffer = AByteBuffer::fromString("hello");     // bytes of the string, UTF-8
AString hex = buffer.toHexString();
AString base64 = buffer.toBase64String();
auto decoded = AByteBuffer::fromBase64String(base64);
AString text = AString::fromUtf8(decoded);
1
2
3
4
5
6
std::string_view text = "Building beautiful programs in pure C++ without chromium embedded framework";
AByteBuffer buffer(text.data(), text.size());
auto base64 = buffer.toBase64String();
EXPECT_EQ(base64, "QnVpbGRpbmcgYmVhdXRpZnVsIHByb2dyYW1zIGluIHB1cmUgQysrIHdpdGhvdXQgY2hyb21pdW0gZW1iZWRkZWQgZnJhbWV3b3Jr");
auto decoded = AString::fromUtf8(AByteBuffer::fromBase64String(base64));
EXPECT_EQ(decoded, text);

Reading from streams#

AByteBuffer::fromStream reads the stream to the end (or up to a size limit):

auto contents = AByteBuffer::fromStream(AFileInputStream("data.bin"));

Views#

slice() and the implicit conversion to AByteBufferView give a non-owning window into the buffer. A view is valid as long as the buffer is not resized or destroyed.

Compression helpers (aui::zlib::compress and aui::zlib::decompress) accept views and write into a buffer.

Public Methods#

at#


template<typename T >
T& AByteBuffer::at(size_t byteIndex)

Gets value of specified type by byte index relative to the beginning of internal buffer.

Arguments
byteIndex
byte offset realtive to the beginning of internal buffer
Returns
data

Examples:

examples/7guis/cells/src/AST.cpp

7GUIs Cells — Spreadsheet processor (Excel).

                });
            }
        };
        auto out = std::make_unique<FunctionCall>();
        out->function = functions::predefined().at(expect<token::Identifier>().name.uppercase());
        mIterator++;
        expect<token::LPar>();
        mIterator++;

        for (;;) {

template<typename T >
const T& AByteBuffer::at(size_t byteIndex)

Gets value of specified type by byte index relative to the beginning of internal buffer.

Arguments
byteIndex
byte offset realtive to the beginning of internal buffer
Returns
data

Examples:

capacity#


size_t AByteBuffer::capacity()
Returns
size of whole buffer (including possibly invalid data)

data#


char* AByteBuffer::data()
Returns
Internal buffer.

Examples:

examples/ui/views/src/ExampleWindow.cpp

Views Example — All-in-one views building example.

void ExampleWindow::onDragDrop(const ADragNDrop::DropEvent& event) {
    ASurface::onDragDrop(event);

    for (const auto& [k, v] : event.data.data()) {
        ALogger::info("Drop") << "[" << k << "] = " << AString::fromUtf8(v);
    }

    auto surface = createOverlappingSurface({ 0, 0 }, { 100, 100 }, false);
    _<AViewContainer> popup = Vertical {

empty#


bool AByteBuffer::empty()
Returns
true if size == 0

Examples:

examples/7guis/cells/src/Formula.cpp

7GUIs Cells — Spreadsheet processor (Excel).

    return precompile(expression)(spreadsheet);
}

formula::Precompiled formula::precompile(const AString& expression) {
    if (expression.empty()) {
        return [](const Spreadsheet&) { return std::nullopt; };
    }
    if (auto d = expression.toDouble()) {
        return [d = *d](const Spreadsheet&) { return d; };
    }
examples/7guis/crud/src/main.cpp

7GUIs CRUD — Create/Read/Update/Delete example.

    AProperty<AVector<_<User>>> mUsers;
    User mEditedUser;
    AProperty<_<User>> mSelectedUser;
    AProperty<AString> mFilterPrefix;
    APropertyPrecomputed<bool> mCreateEnabled = [this] { return !(mEditedUser.surname->empty() || mEditedUser.name->empty()); };
    APropertyPrecomputed<bool> mDeleteEnabled = [this] { return mSelectedUser != nullptr; };
    APropertyPrecomputed<bool> mUpdateEnabled = [this] { return mCreateEnabled && mDeleteEnabled; };

    void createClicked() {
        mUsers.writeScope() << aui::ptr::manage_shared(new User {
examples/app/notes/src/main.cpp

Notes App — Note taking app that demonstrates usage of AListModel, AProperty, user data saving and loading.

/// [notePreview]
_<AView> notePreview(const _<Note>& note) {
    auto stringOneLinePreview = [](const AString& s) -> AString {
        if (s.empty()) {
            return "Empty";
        }
        return s.restrictLength(100, "").replacedAll('\n', ' ');
    };
examples/ui/contacts/src/main.cpp

AUI Contacts — Usage of AUI_DECLARATIVE_FOR to make a contacts-like application.

static constexpr auto CONTACTS_SORT = ranges::actions::sort(std::less {}, [](const _<Contact>& c) -> decltype(auto) { return *c->displayName; });

static AChar groupLetter(const AString& s) {
    return s.empty() ? AChar(U'_') : s.utf8().first();
}

class ContactsWindow : public AWindow {
public:
    ContactsWindow() : AWindow("AUI Contacts", 600_dp, 300_dp) {
examples/ui/contacts/src/view/ContactDetailsView.cpp

AUI Contacts — Usage of AUI_DECLARATIVE_FOR to make a contacts-like application.

namespace {
_<AView> profilePhoto(const _<Contact>& contact) {
    return Centered {
        Label {
          AUI_REACT(contact->displayName->empty() ? "?" : AString(1, contact->displayName->first()).uppercase())
        } AUI_OVERRIDE_STYLE { Opacity(0.5f), FontSize { 32_dp } },
    } AUI_OVERRIDE_STYLE {
        FixedSize { 64_dp },
        BorderRadius { 32_dp },
        BackgroundGradient { AColor::GRAY.lighter(0.5f), AColor::GRAY, 163_deg },

getAvailableToWrite#


size_t AByteBuffer::getAvailableToWrite()
Returns
delta between internal buffer size and payload size.

getReserved#


size_t AByteBuffer::getReserved()
Returns
size of internal buffer. Must be greater that getSize()

getSize#


size_t AByteBuffer::getSize()
Returns
size of payload (valid data)

Examples:

examples/app/fractal/src/FractalView.cpp

Fractal Example — Fractal viewer application demonstrating usage of custom shaders.

    AView::render(context);

    mShader.use();
    mTexture->bind();
    context.render.rectangle(ACustomShaderBrush {}, { 0, 0 }, getSize());
}

void FractalView::onLayout(glm::ivec2 size) {
    AView::onLayout(size);
    mShader.use();
examples/app/game_of_life/src/main.cpp

Game of Life — Game of Life implementation that uses advanced large dynamic data rendering techniques such as ITexture, AImage to be GPU friendly. The computation is performed in AThreadPool.

        }
        auto drawGrid = [&] {
            ASmallVector<std::pair<glm::vec2, glm::vec2>, 128 * 2> points;
            for (int i = 1; i < mCells->size().x; ++i) {
                points << std::make_pair(glm::vec2(i * SCALE, 0.f), glm::vec2(i * SCALE, getSize().y));
            }
            for (int i = 1; i < mCells->size().y; ++i) {
                points << std::make_pair(glm::vec2(0.f, i * SCALE), glm::vec2(getSize().x, i * SCALE));
            }
            ctx.render.lines(ASolidBrush { AColor::GRAY }, points);
examples/ui/embedded_sdl/src/main.cpp

SDL3 — This code demonstrates how to integrate the AUI Framework with SDL3 to create a window with OpenGL rendering.

    }

    void beginPaint(ASurface& window) override {
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        glViewport(0, 0, window.getSize().x, window.getSize().y);
        m_renderer->beginPaint(window.getSize());
        glClearColor(1, 1, 1, 1);
        glClear(GL_COLOR_BUFFER_BIT);
    }
    void endPaint(ASurface& window) override {

grow#


void AByteBuffer::grow(size_t size)

If getReserved() - getSize() is less than size increases internal buffer size enough to store size bytes.

increaseInternalBuffer#


void AByteBuffer::increaseInternalBuffer(size_t size)

Increases internal buffer.

increaseSize#


void AByteBuffer::increaseSize(size_t s)
Arguments
s
new size of the payload

Forces new size of the buffer.

Sneaky assert:
Assert fails when new size is greater that reserved buffer size. Use AByteBuffer::resize to avoid this.

reallocate#


void AByteBuffer::reallocate(size_t s)
Arguments
s
new size of the payload

Resizes the buffer WITHOUT keeping it's contents. When reserved buffer size is differs from the new size, buffer is reallocated with new size.

reserve#


void AByteBuffer::reserve(size_t size)

Resizes internal buffer.

Examples:

examples/ui/views/src/DemoGraphView.cpp

Views Example — All-in-one views building example.

{
    setFixedSize({ 5_dp * POINT_COUNT, 100_dp }); // set fixed size


    mPoints.reserve(POINT_COUNT);
    for (std::size_t i = 0; i < POINT_COUNT; ++i) {
        // map a sinusoid to view
        mPoints << glm::vec2{ 5_dp * float(i), 100_dp * ((glm::sin(i / 10.f) + 1.f) / 2.f) };
    }
}

resize#


void AByteBuffer::resize(size_t s)
Arguments
s
new size of the payload

Resizes the buffer keeping it's contents. When reserved buffer size is less than the new size, buffer is reallocated with new size.

Examples:

examples/7guis/cells/src/Spreadsheet.h

7GUIs Cells — Spreadsheet processor (Excel).

class Spreadsheet {
public:
    explicit Spreadsheet(glm::uvec2 size) : mSize(size) {
        mCells.resize(size.x * size.y);
        for (auto& v : mCells) {
            v = std::make_unique<Cell>();
            v->spreadsheet = this;
        }
    }
examples/7guis/cells/src/main.cpp

7GUIs Cells — Spreadsheet processor (Excel).

            AGridSplitter::Builder()
                    .noDefaultSpacers()
                    .withItems([&] {
                        AVector<AVector<_<AView>>> views;
                        views.resize(mState->spreadsheet.size().y + 1);
                        for (auto& c : views) {
                            c.resize(mState->spreadsheet.size().x + 1);
                        }

                        views[0][0] = _new<AView>();   // blank
examples/app/minesweeper/src/MinesweeperWindow.cpp

Minesweeper Game — Minesweeper game implementation driven by ass.

    mReveal = false;
    mBombsPlanted = false;
    mGrid->setLayout(std::make_unique<AGridLayout>(columns, rows));
    mField.clear();
    mField.resize(columns * rows);

    for (int i = 0; i < columns * rows; ++i) {
        int x = i % columns;
        int y = i / columns;
        auto cell = _new<CellView>(fieldAt(x, y));

setSize#


void AByteBuffer::setSize(size_t s)
Arguments
s
new size of the payload

Forces new size of the buffer.

Sneaky assert:
Assert fails when new size is greater that reserved buffer size. Use AByteBuffer::resize to avoid this.

size#


size_t AByteBuffer::size()
Returns
size of payload (valid data)

Examples:

examples/7guis/cells/src/Functions.cpp

7GUIs Cells — Spreadsheet processor (Excel).

              return double(accumulator);
            } },
        { "IF",
            [](Ctx ctx) {
              if (ctx.args.size() != 3) {
                  throw AException("ARG");
              }
              auto condition = std::get_if<double>(&ctx.args[0]);
              if (condition == nullptr) {
                  throw AException("ARG0");
examples/ui/infinite_lazy_list/src/main.cpp

Infinite Lazy List — Usage of AUI_DECLARATIVE_FOR to make an infinite lazy list.

    AObject::connect(state->needMore.changed, AObject::GENERIC_OBSERVER, [state](bool newState){
        if (!newState) { // we're interested in transitions to true state only.
            return;
        }
        auto loadFrom = state->items->size(); // base index to load from.
        state->asyncTasks << AUI_THREADPOOL {
            // perform "loading" task on a worker thread.

            AThread::sleep(500ms); // imitate hard work here

write#


void AByteBuffer::write(IInputStream& stream, size_t size)
Arguments
stream
size

Reads exact size bytes from stream.