Logo ROOT  
Reference Guide
Loading...
Searching...
No Matches
RNTupleZip.hxx
Go to the documentation of this file.
1/// \file ROOT/RNTupleZip.hxx
2/// \author Jakob Blomer <jblomer@cern.ch>
3/// \date 2019-11-21
4
5/*************************************************************************
6 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
7 * All rights reserved. *
8 * *
9 * For the licensing terms see $ROOTSYS/LICENSE. *
10 * For the list of contributors see $ROOTSYS/README/CREDITS. *
11 *************************************************************************/
12
13#ifndef ROOT_RNTupleZip
14#define ROOT_RNTupleZip
15
16#include <RZip.h>
17#include <TError.h>
18
19#include <ROOT/RError.hxx>
20
21#include <algorithm>
22#include <array>
23#include <cstring>
24#include <functional>
25#include <memory>
26#include <utility>
27
28namespace ROOT {
29namespace Internal {
30
31// clang-format off
32/**
33\class ROOT::Internal::RNTupleCompressor
34\ingroup NTuple
35\brief Helper class to compress data blocks in the ROOT compression frame format
36*/
37// clang-format on
39public:
41 RNTupleCompressor(const RNTupleCompressor &other) = delete;
45
46 /// Returns the size of the compressed data, written into the provided output buffer.
47 static std::size_t Zip(const void *from, std::size_t nbytes, int compression, void *to)
48 {
49 R__ASSERT(from != nullptr);
50 R__ASSERT(to != nullptr);
51 auto cxLevel = compression % 100;
52 if (cxLevel == 0) {
53 memcpy(to, from, nbytes);
54 return nbytes;
55 }
56
57 auto cxAlgorithm = static_cast<ROOT::RCompressionSetting::EAlgorithm::EValues>(compression / 100);
58 unsigned int nZipBlocks = 1 + (nbytes - 1) / kMAXZIPBUF;
59 const char *source = static_cast<const char *>(from);
60 int szTarget = nbytes;
61 char *target = reinterpret_cast<char *>(to);
62 int szOutBlock = 0;
63 int szRemaining = nbytes;
64 size_t szZipData = 0;
65 for (unsigned int i = 0; i < nZipBlocks; ++i) {
66 int szSource = std::min(static_cast<int>(kMAXZIPBUF), szRemaining);
67 R__zipMultipleAlgorithm(cxLevel, &szSource, source, &szTarget, target, &szOutBlock, cxAlgorithm);
68 R__ASSERT(szOutBlock >= 0);
69 if ((szOutBlock == 0) || (szOutBlock >= szSource)) {
70 // Uncompressible block, we have to store the entire input data stream uncompressed
71 memcpy(to, from, nbytes);
72 return nbytes;
73 }
74
75 szZipData += szOutBlock;
76 source += szSource;
77 target += szOutBlock;
78 szRemaining -= szSource;
79 }
80 R__ASSERT(szRemaining == 0);
81 R__ASSERT(szZipData < nbytes);
82 return szZipData;
83 }
84};
85
86// clang-format off
87/**
88\class ROOT::Internal::RNTupleDecompressor
89\ingroup NTuple
90\brief Helper class to uncompress data blocks in the ROOT compression frame format
91*/
92// clang-format on
94public:
100
101 /**
102 * The nbytes parameter provides the size ls of the from buffer. The dataLen gives the size of the uncompressed data.
103 * The block is uncompressed iff nbytes == dataLen.
104 */
105 static void Unzip(const void *from, size_t nbytes, size_t dataLen, void *to)
106 {
107 if (dataLen == nbytes) {
108 memcpy(to, from, nbytes);
109 return;
110 }
111 R__ASSERT(dataLen > nbytes);
112
113 const unsigned char *source = static_cast<const unsigned char *>(from);
114 unsigned char *target = static_cast<unsigned char *>(to);
115 size_t szRemainingLen = dataLen;
116 size_t szRemainingNbytes = nbytes;
117 do {
118 if (R__unlikely(szRemainingNbytes < ROOT::Internal::kZipHeaderSize)) {
119 throw ROOT::RException(R__FAIL("zip buffer too short"));
120 }
121 int szSource;
122 int szTarget;
123 int retval = R__unzip_header(&szSource, source, &szTarget);
124 if (R__unlikely(!((retval == 0) && (szSource > 0) && (szTarget > szSource) &&
125 (static_cast<unsigned int>(szSource) <= szRemainingNbytes) &&
126 (static_cast<unsigned int>(szTarget) <= szRemainingLen)))) {
127 throw ROOT::RException(R__FAIL("failed to unzip buffer header"));
128 }
129
130 int unzipBytes = 0;
131 R__unzip(&szSource, source, &szTarget, target, &unzipBytes);
132 if (R__unlikely(unzipBytes != szTarget)) {
133 throw ROOT::RException(R__FAIL(std::string("unexpected length after unzipping the buffer (wanted: ") +
134 std::to_string(szTarget) + ", got: " + std::to_string(unzipBytes) + ")"));
135 }
136
137 target += szTarget;
138 source += szSource;
139 szRemainingNbytes -= szSource;
140 szRemainingLen -= unzipBytes;
141 } while (szRemainingLen > 0);
142 R__ASSERT(szRemainingLen == 0);
143 if (szRemainingNbytes > 0) {
144 throw ROOT::RException(R__FAIL(std::string("unexpected trailing bytes in zip buffer")));
145 }
146 }
147};
148
149} // namespace Internal
150} // namespace ROOT
151
152#endif
#define R__unlikely(expr)
Definition RConfig.hxx:586
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
Definition RError.hxx:299
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
RNTupleCompressor()=delete
RNTupleDecompressor()=delete
RNTupleCompressor & operator=(const RNTupleCompressor &other)=delete
static std::size_t Zip(const void *from, std::size_t nbytes, int compression, void *to)
Returns the size of the compressed data, written into the provided output buffer.
RNTupleCompressor(RNTupleCompressor &&other)=delete
RNTupleCompressor(const RNTupleCompressor &other)=delete
RNTupleCompressor & operator=(RNTupleCompressor &&other)=delete
RNTupleDecompressor(RNTupleDecompressor &&other)=delete
static void Unzip(const void *from, size_t nbytes, size_t dataLen, void *to)
The nbytes parameter provides the size ls of the from buffer.
RNTupleDecompressor(const RNTupleDecompressor &other)=delete
RNTupleDecompressor & operator=(const RNTupleDecompressor &other)=delete
RNTupleDecompressor & operator=(RNTupleDecompressor &&other)=delete
Base class for all ROOT issued exceptions.
Definition RError.hxx:78
EValues
Note: this is only temporarily a struct and will become a enum class hence the name convention used.
Definition Compression.h:88