summaryrefslogtreecommitdiff
path: root/src/data_buffer.cpp
blob: c4c1d8b0cf3f540ee88b468710a5509f401570ae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/* SPDX-License-Identifier: Unlicense
 */

#include "data_buffer.h"

#include <cassert>
#include <cerrno>
#include <cstdlib>
#include <cstring>

void DataBuffer::Expand(size_t new_size)
{
    assert(buffer);
    if (new_size <= buffer_size) {
        return;
    }
    uint8_t *new_buffer{new uint8_t[new_size]};
    assert(new_buffer);
    memcpy(new_buffer, buffer, occupied_size);
    delete [] buffer;
    buffer = new_buffer;
    buffer_size = new_size;
}

DataBuffer::~DataBuffer()
{
    delete [] buffer;
    buffer = nullptr;
    buffer_size = 0;
    occupied_size = 0;
}

DataBuffer DataBuffer::FromStream(FILE *stream)
{
    DataBuffer db{};
    assert(db.buffer && db.buffer_size >= db.kInitialSize);
    while (1) {
        const size_t read_size = db.buffer_size - db.occupied_size;
        const size_t fread_ret = fread(
                db.buffer + db.occupied_size, sizeof(*db.buffer), read_size, stream);
        db.occupied_size += fread_ret;
        if (fread_ret >= db.buffer_size) {
            assert(fread_ret == db.buffer_size);
            db.Expand(db.buffer_size * 2);
        } else {
            const int err = errno;
            if (feof(stream)) {
                break;
            } else if (ferror(stream)) {
                fprintf(
                        stderr,
                        "DataBuffer::FromStream: fread(%zu): "
                        "Error (%d): \"%s\"\n",
                        read_size,
                        err,
                        strerror(err));
            } else if (db.buffer_size == db.occupied_size) {
                db.Expand(db.buffer_size * 2);
            } else {
                assert(false);
            }
        }
    }
    return db;
}