Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RNTupleZip.hxx
Go to the documentation of this file.
1/// \file ROOT/RNTupleZip.hxx
2/// \ingroup NTuple ROOT7
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \date 2019-11-21
5/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
6/// is welcome!
7
8/*************************************************************************
9 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
10 * All rights reserved. *
11 * *
12 * For the licensing terms see $ROOTSYS/LICENSE. *
13 * For the list of contributors see $ROOTSYS/README/CREDITS. *
14 *************************************************************************/
15
16#ifndef ROOT7_RNTupleZip
17#define ROOT7_RNTupleZip
18
19#include <RZip.h>
20#include <TError.h>
21
22#include <algorithm>
23#include <array>
24#include <cstring>
25#include <functional>
26#include <memory>
27#include <utility>
28
29namespace ROOT {
30namespace Experimental {
31namespace Internal {
32
33// clang-format off
34/**
35\class ROOT::Experimental::Internal::RNTupleCompressor
36\ingroup NTuple
37\brief Helper class to compress data blocks in the ROOT compression frame format
38*/
39// clang-format on
41private:
42 using Buffer_t = std::array<unsigned char, kMAXZIPBUF>;
43 std::unique_ptr<Buffer_t> fZipBuffer;
44
45public:
46 /// Data might be overwritten, if a zipped block in the middle of a large input data stream
47 /// turns out to be uncompressible
48 using Writer_t = std::function<void(const void *buffer, size_t nbytes, size_t offset)>;
49 static Writer_t MakeMemCopyWriter(unsigned char *dest)
50 {
51 return [=](const void *b, size_t n, size_t o) { memcpy(dest + o, b, n); };
52 }
53 static constexpr size_t kMaxSingleBlock = kMAXZIPBUF;
54
55 RNTupleCompressor() : fZipBuffer(std::make_unique<Buffer_t>()) {}
56 RNTupleCompressor(const RNTupleCompressor &other) = delete;
60
61 /// Returns the size of the compressed data. Data is compressed in 16MB (kMAXZIPBUF) blocks and written
62 /// piecewise using the provided writer
63 size_t Zip(const void *from, size_t nbytes, int compression, Writer_t fnWriter)
64 {
65 R__ASSERT(from != nullptr);
66
67 auto cxLevel = compression % 100;
68 if (cxLevel == 0) {
69 fnWriter(from, nbytes, 0);
70 return nbytes;
71 }
72
73 auto cxAlgorithm = static_cast<ROOT::RCompressionSetting::EAlgorithm::EValues>(compression / 100);
74 unsigned int nZipBlocks = 1 + (nbytes - 1) / kMAXZIPBUF;
75 char *source = const_cast<char *>(static_cast<const char *>(from));
76 int szTarget = kMAXZIPBUF;
77 char *target = reinterpret_cast<char *>(fZipBuffer->data());
78 int szOutBlock = 0;
79 int szRemaining = nbytes;
80 size_t szZipData = 0;
81 for (unsigned int i = 0; i < nZipBlocks; ++i) {
82 int szSource = std::min(static_cast<int>(kMAXZIPBUF), szRemaining);
83 R__zipMultipleAlgorithm(cxLevel, &szSource, source, &szTarget, target, &szOutBlock, cxAlgorithm);
84 R__ASSERT(szOutBlock >= 0);
85 if ((szOutBlock == 0) || (szOutBlock >= szSource)) {
86 // Uncompressible block, we have to store the entire input data stream uncompressed
87 fnWriter(from, nbytes, 0);
88 return nbytes;
89 }
90
91 fnWriter(target, szOutBlock, szZipData);
92 szZipData += szOutBlock;
93 source += szSource;
94 szRemaining -= szSource;
95 }
96 R__ASSERT(szRemaining == 0);
97 R__ASSERT(szZipData < nbytes);
98 return szZipData;
99 }
100
101 /// Returns the size of the compressed data block. The data is written into the zip buffer.
102 /// This works only for small input buffer up to 16MB (kMAXZIPBUF)
103 size_t Zip(const void *from, size_t nbytes, int compression)
104 {
105 R__ASSERT(from != nullptr);
106 R__ASSERT(nbytes <= kMAXZIPBUF);
107
108 auto cxLevel = compression % 100;
109 if (cxLevel == 0) {
110 memcpy(fZipBuffer->data(), from, nbytes);
111 return nbytes;
112 }
113
114 auto cxAlgorithm = static_cast<ROOT::RCompressionSetting::EAlgorithm::EValues>(compression / 100);
115 int szSource = nbytes;
116 char *source = const_cast<char *>(static_cast<const char *>(from));
117 int szTarget = nbytes;
118 char *target = reinterpret_cast<char *>(fZipBuffer->data());
119 int szOut = 0;
120 R__zipMultipleAlgorithm(cxLevel, &szSource, source, &szTarget, target, &szOut, cxAlgorithm);
121 R__ASSERT(szOut >= 0);
122 if ((szOut > 0) && (static_cast<unsigned int>(szOut) < nbytes))
123 return szOut;
124
125 memcpy(fZipBuffer->data(), from, nbytes);
126 return nbytes;
127 }
128
129 /// Returns the size of the compressed data, written into the provided output buffer.
130 static std::size_t Zip(const void *from, std::size_t nbytes, int compression, void *to)
131 {
132 R__ASSERT(from != nullptr);
133 R__ASSERT(to != nullptr);
134 auto cxLevel = compression % 100;
135 if (cxLevel == 0) {
136 memcpy(to, from, nbytes);
137 return nbytes;
138 }
139
140 auto cxAlgorithm = static_cast<ROOT::RCompressionSetting::EAlgorithm::EValues>(compression / 100);
141 unsigned int nZipBlocks = 1 + (nbytes - 1) / kMAXZIPBUF;
142 char *source = const_cast<char *>(static_cast<const char *>(from));
143 int szTarget = nbytes;
144 char *target = reinterpret_cast<char *>(to);
145 int szOutBlock = 0;
146 int szRemaining = nbytes;
147 size_t szZipData = 0;
148 for (unsigned int i = 0; i < nZipBlocks; ++i) {
149 int szSource = std::min(static_cast<int>(kMAXZIPBUF), szRemaining);
150 R__zipMultipleAlgorithm(cxLevel, &szSource, source, &szTarget, target, &szOutBlock, cxAlgorithm);
151 R__ASSERT(szOutBlock >= 0);
152 if ((szOutBlock == 0) || (szOutBlock >= szSource)) {
153 // Uncompressible block, we have to store the entire input data stream uncompressed
154 memcpy(to, from, nbytes);
155 return nbytes;
156 }
157
158 szZipData += szOutBlock;
159 source += szSource;
160 target += szOutBlock;
161 szRemaining -= szSource;
162 }
163 R__ASSERT(szRemaining == 0);
164 R__ASSERT(szZipData < nbytes);
165 return szZipData;
166 }
167
168 void *GetZipBuffer() { return fZipBuffer->data(); }
169};
170
171// clang-format off
172/**
173\class ROOT::Experimental::Internal::RNTupleDecompressor
174\ingroup NTuple
175\brief Helper class to uncompress data blocks in the ROOT compression frame format
176*/
177// clang-format on
179private:
180 using Buffer_t = std::array<unsigned char, kMAXZIPBUF>;
181 std::unique_ptr<Buffer_t> fUnzipBuffer;
182
183public:
184 RNTupleDecompressor() : fUnzipBuffer(std::make_unique<Buffer_t>()) {}
189
190 /**
191 * The nbytes parameter provides the size ls of the from buffer. The dataLen gives the size of the uncompressed data.
192 * The block is uncompressed iff nbytes == dataLen.
193 */
194 static void Unzip(const void *from, size_t nbytes, size_t dataLen, void *to)
195 {
196 if (dataLen == nbytes) {
197 memcpy(to, from, nbytes);
198 return;
199 }
200 R__ASSERT(dataLen > nbytes);
201
202 unsigned char *source = const_cast<unsigned char *>(static_cast<const unsigned char *>(from));
203 unsigned char *target = static_cast<unsigned char *>(to);
204 int szRemaining = dataLen;
205 do {
206 int szSource;
207 int szTarget;
208 int retval = R__unzip_header(&szSource, source, &szTarget);
209 R__ASSERT(retval == 0);
210 R__ASSERT(szSource > 0);
211 R__ASSERT(szTarget > szSource);
212 R__ASSERT(static_cast<unsigned int>(szSource) <= nbytes);
213 R__ASSERT(static_cast<unsigned int>(szTarget) <= dataLen);
214
215 int unzipBytes = 0;
216 R__unzip(&szSource, source, &szTarget, target, &unzipBytes);
217 R__ASSERT(unzipBytes == szTarget);
218
219 target += szTarget;
220 source += szSource;
221 szRemaining -= unzipBytes;
222 } while (szRemaining > 0);
223 R__ASSERT(szRemaining == 0);
224 }
225
226 /**
227 * In-place decompression via unzip buffer
228 */
229 void Unzip(void *fromto, size_t nbytes, size_t dataLen)
230 {
231 R__ASSERT(dataLen <= kMAXZIPBUF);
232 Unzip(fromto, nbytes, dataLen, fUnzipBuffer->data());
233 memcpy(fromto, fUnzipBuffer->data(), dataLen);
234 }
235};
236
237} // namespace Internal
238} // namespace Experimental
239} // namespace ROOT
240
241#endif
#define b(i)
Definition RSha256.hxx:100
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t dest
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t target
void R__unzip(Int_t *nin, UChar_t *bufin, Int_t *lout, char *bufout, Int_t *nout)
int R__unzip_header(Int_t *nin, UChar_t *bufin, Int_t *lout)
Helper class to compress data blocks in the ROOT compression frame format.
size_t Zip(const void *from, size_t nbytes, int compression)
Returns the size of the compressed data block.
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.
std::function< void(const void *buffer, size_t nbytes, size_t offset)> Writer_t
Data might be overwritten, if a zipped block in the middle of a large input data stream turns out to ...
static Writer_t MakeMemCopyWriter(unsigned char *dest)
RNTupleCompressor & operator=(RNTupleCompressor &&other)=default
RNTupleCompressor(const RNTupleCompressor &other)=delete
size_t Zip(const void *from, size_t nbytes, int compression, Writer_t fnWriter)
Returns the size of the compressed data.
RNTupleCompressor(RNTupleCompressor &&other)=default
std::array< unsigned char, kMAXZIPBUF > Buffer_t
Helper class to uncompress data blocks in the ROOT compression frame format.
RNTupleDecompressor & operator=(RNTupleDecompressor &&other)=default
RNTupleDecompressor(const 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.
void Unzip(void *fromto, size_t nbytes, size_t dataLen)
In-place decompression via unzip buffer.
RNTupleDecompressor & operator=(const RNTupleDecompressor &other)=delete
std::array< unsigned char, kMAXZIPBUF > Buffer_t
RNTupleDecompressor(RNTupleDecompressor &&other)=default
const Int_t n
Definition legend1.C:16
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
EValues
Note: this is only temporarily a struct and will become a enum class hence the name convention used.
Definition Compression.h:88