Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/core/StarZSTDCompression.cpp
blob: 733b1827f51cfd31d583c974956748371546b3d7 (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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include "StarZSTDCompression.hpp"
#include <zstd.h>

namespace Star {

CompressionStream::CompressionStream() : m_cStream(ZSTD_createCStream()) {
  ZSTD_CCtx_setParameter(m_cStream, ZSTD_c_enableLongDistanceMatching, 1);
  ZSTD_CCtx_setParameter(m_cStream, ZSTD_c_windowLog, 24);
  ZSTD_initCStream(m_cStream, 2);
}

CompressionStream::~CompressionStream() { ZSTD_freeCStream(m_cStream); }

ByteArray CompressionStream::compress(const char* in, size_t inLen) {
  size_t const cInSize  = ZSTD_CStreamInSize ();
  size_t const cOutSize = ZSTD_CStreamOutSize();
  ByteArray output(cOutSize, 0);
  size_t written = 0, read = 0;
  while (read < inLen) {
    ZSTD_inBuffer inBuffer = {in + read, min(cInSize, inLen - read), 0};
    ZSTD_outBuffer outBuffer = {output.ptr() + written, output.size() - written, 0};
    bool finished = false;
    do {
      size_t ret = ZSTD_compressStream2(m_cStream, &outBuffer, &inBuffer, ZSTD_e_flush);
      if (ZSTD_isError(ret)) {
        throw IOException(strf("ZSTD compression error {}", ZSTD_getErrorName(ret)));
        break;
      }

      if (outBuffer.pos == outBuffer.size) {
        output.resize(output.size() * 2);
        outBuffer.dst = output.ptr();
        outBuffer.size = output.size();
        continue;
      }

      finished = ret == 0 && inBuffer.pos == inBuffer.size;
    } while (!finished);

    read += inBuffer.pos;
    written += outBuffer.pos;
  }
  output.resize(written);
  return output;
}

DecompressionStream::DecompressionStream() : m_dStream(ZSTD_createDStream()) {
  ZSTD_DCtx_setParameter(m_dStream, ZSTD_d_windowLogMax, 25);
  ZSTD_initDStream(m_dStream);
}

DecompressionStream::~DecompressionStream() { ZSTD_freeDStream(m_dStream); }

ByteArray DecompressionStream::decompress(const char* in, size_t inLen) {
  size_t const dInSize  = ZSTD_DStreamInSize ();
  size_t const dOutSize = ZSTD_DStreamOutSize();
  ByteArray output(dOutSize, 0);
  size_t written = 0, read = 0;
  while (read < inLen) {
    ZSTD_inBuffer inBuffer = {in + read, min(dInSize, inLen - read), 0};
    ZSTD_outBuffer outBuffer = {output.ptr() + written, output.size() - written, 0};
    do {
      size_t ret = ZSTD_decompressStream(m_dStream, &outBuffer, &inBuffer);
      if (ZSTD_isError(ret)) {
        throw IOException(strf("ZSTD decompression error {}", ZSTD_getErrorName(ret)));
        break;
      }

      if (outBuffer.pos == outBuffer.size) {
        output.resize(output.size() * 2);
        outBuffer.dst = output.ptr();
        outBuffer.size = output.size();
        continue;
      }
    } while (inBuffer.pos < inBuffer.size);

    read += inBuffer.pos;
    written += outBuffer.pos;
  }
  output.resize(written);
  return output;
}

}