aboutsummaryrefslogtreecommitdiffstats
path: root/vespalib/src/vespa/vespalib/data/lz4_input_decoder.cpp
blob: c4d7cd3602aca28551d5628225088307859d56a7 (plain) (blame)
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "lz4_input_decoder.h"
#include <lz4frame.h>
#include <cassert>

namespace vespalib {

void
Lz4InputDecoder::fail(const char *reason)
{
    _failed = true;
    _reason = reason;
    _eof = true;
}

void
Lz4InputDecoder::decode_more()
{
    assert((_pos == _used) && !_eof);
    Memory memory = _input.obtain();
    size_t input_size = memory.size;
    size_t output_size = _buffer.size();
    auto decode_res = LZ4F_decompress(_ctx,
                                      &_buffer[0], &output_size,
                                      memory.data, &input_size,
                                      nullptr);
    if (LZ4F_isError(decode_res)) {
        fail(LZ4F_getErrorName(decode_res));
    } else {
        assert(input_size <= memory.size);
        assert(output_size <= _buffer.size());
        _input.evict(input_size);
        _used = output_size;
        _pos = 0;
        if ((input_size == 0) && (output_size == 0)) {
            auto fini_res = LZ4F_freeDecompressionContext(_ctx);
            _ctx = nullptr;
            _eof = true;
            if (LZ4F_isError(fini_res)) {
                fail(LZ4F_getErrorName(fini_res));
            }
        }
    }
}

Lz4InputDecoder::Lz4InputDecoder(Input &input, size_t buffer_size)
    : _input(input),
      _buffer(buffer_size, 0),
      _used(0),
      _pos(0),
      _eof(false),
      _failed(false),
      _reason(),
      _ctx(nullptr)
{
    auto init_res = LZ4F_createDecompressionContext(&_ctx, LZ4F_VERSION);
    if (LZ4F_isError(init_res)) {
        fail(LZ4F_getErrorName(init_res));
    }
}

Lz4InputDecoder::~Lz4InputDecoder()
{
    LZ4F_freeDecompressionContext(_ctx);
}

Memory
Lz4InputDecoder::obtain()
{
    while ((_pos == _used) && !_eof) {
        decode_more();
    }
    return Memory(&_buffer[_pos], (_used - _pos));
}

Input &
Lz4InputDecoder::evict(size_t bytes)
{
    _pos += bytes;
    return *this;
}

} // namespace vespalib