rippled
Loading...
Searching...
No Matches
CompressionAlgorithms.h
1#ifndef XRPL_COMPRESSIONALGORITHMS_H_INCLUDED
2#define XRPL_COMPRESSIONALGORITHMS_H_INCLUDED
3
4#include <xrpl/basics/contract.h>
5
6#include <lz4.h>
7
8#include <algorithm>
9#include <cstdint>
10#include <stdexcept>
11#include <vector>
12
13namespace xrpl {
14
15namespace compression_algorithms {
16
25template <typename BufferFactory>
27lz4Compress(void const* in, std::size_t inSize, BufferFactory&& bf)
28{
29 if (inSize > UINT32_MAX)
30 Throw<std::runtime_error>("lz4 compress: invalid size");
31
32 auto const outCapacity = LZ4_compressBound(inSize);
33
34 // Request the caller to allocate and return the buffer to hold compressed
35 // data
36 auto compressed = bf(outCapacity);
37
38 auto compressedSize = LZ4_compress_default(
39 reinterpret_cast<char const*>(in), reinterpret_cast<char*>(compressed), inSize, outCapacity);
40 if (compressedSize == 0)
41 Throw<std::runtime_error>("lz4 compress: failed");
42
43 return compressedSize;
44}
45
53inline std::size_t
55 std::uint8_t const* in,
56 std::size_t inSizeUnchecked,
57 std::uint8_t* decompressed,
58 std::size_t decompressedSizeUnchecked)
59{
60 int const inSize = static_cast<int>(inSizeUnchecked);
61 int const decompressedSize = static_cast<int>(decompressedSizeUnchecked);
62
63 if (inSize <= 0)
64 Throw<std::runtime_error>("lz4Decompress: integer overflow (input)");
65
66 if (decompressedSize <= 0)
67 Throw<std::runtime_error>("lz4Decompress: integer overflow (output)");
68
69 if (LZ4_decompress_safe(
70 reinterpret_cast<char const*>(in), reinterpret_cast<char*>(decompressed), inSize, decompressedSize) !=
71 decompressedSize)
72 Throw<std::runtime_error>("lz4Decompress: failed");
73
74 return decompressedSize;
75}
76
85template <typename InputStream>
87lz4Decompress(InputStream& in, std::size_t inSize, std::uint8_t* decompressed, std::size_t decompressedSize)
88{
90 std::uint8_t const* chunk = nullptr;
91 int chunkSize = 0;
92 int copiedInSize = 0;
93 auto const currentBytes = in.ByteCount();
94
95 // Use the first chunk if it is >= inSize bytes of the compressed message.
96 // Otherwise copy inSize bytes of chunks into compressed buffer and
97 // use the buffer to decompress.
98 while (in.Next(reinterpret_cast<void const**>(&chunk), &chunkSize))
99 {
100 if (copiedInSize == 0)
101 {
102 if (chunkSize >= inSize)
103 {
104 copiedInSize = inSize;
105 break;
106 }
107 compressed.resize(inSize);
108 }
109
110 chunkSize = chunkSize < (inSize - copiedInSize) ? chunkSize : (inSize - copiedInSize);
111
112 std::copy(chunk, chunk + chunkSize, compressed.data() + copiedInSize);
113
114 copiedInSize += chunkSize;
115
116 if (copiedInSize == inSize)
117 {
118 chunk = compressed.data();
119 break;
120 }
121 }
122
123 // Put back unused bytes
124 if (in.ByteCount() > (currentBytes + copiedInSize))
125 in.BackUp(in.ByteCount() - currentBytes - copiedInSize);
126
127 if ((copiedInSize == 0 && chunkSize < inSize) || (copiedInSize > 0 && copiedInSize != inSize))
128 Throw<std::runtime_error>("lz4 decompress: insufficient input size");
129
130 return lz4Decompress(chunk, inSize, decompressed, decompressedSize);
131}
132
133} // namespace compression_algorithms
134
135} // namespace xrpl
136
137#endif // XRPL_COMPRESSIONALGORITHMS_H_INCLUDED
T copy(T... args)
T data(T... args)
std::size_t lz4Decompress(std::uint8_t const *in, std::size_t inSizeUnchecked, std::uint8_t *decompressed, std::size_t decompressedSizeUnchecked)
std::size_t lz4Compress(void const *in, std::size_t inSize, BufferFactory &&bf)
LZ4 block compression.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
T resize(T... args)