Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RNTupleSerialize.cxx
Go to the documentation of this file.
1/// \file RNTupleSerialize.cxx
2/// \ingroup NTuple ROOT7
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \date 2021-08-02
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-2021, 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
17#include <ROOT/RColumnModel.hxx>
18#include <ROOT/RError.hxx>
21
22#include <RVersion.h>
23#include <RZip.h> // for R__crc32
24
25#include <cstring> // for memcpy
26#include <deque>
27#include <set>
28#include <unordered_map>
29
30template <typename T>
32
33
34namespace {
36
37std::uint32_t SerializeFieldV1(const ROOT::Experimental::RFieldDescriptor &fieldDesc,
38 ROOT::Experimental::DescriptorId_t onDiskParentId, void *buffer)
39{
40
41 auto base = reinterpret_cast<unsigned char *>(buffer);
42 auto pos = base;
43 void** where = (buffer == nullptr) ? &buffer : reinterpret_cast<void**>(&pos);
44
45 pos += RNTupleSerializer::SerializeRecordFramePreamble(*where);
46
47 pos += RNTupleSerializer::SerializeUInt32(fieldDesc.GetFieldVersion(), *where);
48 pos += RNTupleSerializer::SerializeUInt32(fieldDesc.GetTypeVersion(), *where);
49 pos += RNTupleSerializer::SerializeUInt32(onDiskParentId, *where);
50 pos += RNTupleSerializer::SerializeFieldStructure(fieldDesc.GetStructure(), *where);
51 if (fieldDesc.GetNRepetitions() > 0) {
52 pos += RNTupleSerializer::SerializeUInt16(RNTupleSerializer::kFlagRepetitiveField, *where);
53 pos += RNTupleSerializer::SerializeUInt64(fieldDesc.GetNRepetitions(), *where);
54 } else {
55 pos += RNTupleSerializer::SerializeUInt16(0, *where);
56 }
57 pos += RNTupleSerializer::SerializeString(fieldDesc.GetFieldName(), *where);
58 pos += RNTupleSerializer::SerializeString(fieldDesc.GetTypeName(), *where);
59 pos += RNTupleSerializer::SerializeString(fieldDesc.GetTypeAlias(), *where);
60 pos += RNTupleSerializer::SerializeString(fieldDesc.GetFieldDescription(), *where);
61
62 auto size = pos - base;
63 RNTupleSerializer::SerializeFramePostscript(base, size);
64
65 return size;
66}
67
68// clang-format off
69/// Serialize, in order, fields enumerated in `fieldList` to `buffer`. `firstOnDiskId` specifies the on-disk ID for the
70/// first element in the `fieldList` sequence. Before calling this function `RContext::MapSchema()` should have been
71/// called on `context` in order to map in-memory field IDs to their on-disk counterpart.
72/// \return The number of bytes written to the output buffer; if `buffer` is `nullptr` no data is serialized and the
73/// required buffer size is returned
74// clang-format on
75std::uint32_t SerializeFieldList(const ROOT::Experimental::RNTupleDescriptor &desc,
76 std::span<const ROOT::Experimental::DescriptorId_t> fieldList,
77 std::size_t firstOnDiskId,
79{
80 auto base = reinterpret_cast<unsigned char *>(buffer);
81 auto pos = base;
82 void** where = (buffer == nullptr) ? &buffer : reinterpret_cast<void**>(&pos);
83
84 auto fieldZeroId = desc.GetFieldZeroId();
85 ROOT::Experimental::DescriptorId_t onDiskFieldId = firstOnDiskId;
86 for (auto fieldId : fieldList) {
87 const auto &f = desc.GetFieldDescriptor(fieldId);
88 auto onDiskParentId =
89 (f.GetParentId() == fieldZeroId) ? onDiskFieldId : context.GetOnDiskFieldId(f.GetParentId());
90 pos += SerializeFieldV1(f, onDiskParentId, *where);
91 ++onDiskFieldId;
92 }
93
94 return pos - base;
95}
96
97RResult<std::uint32_t> DeserializeFieldV1(
98 const void *buffer,
99 std::uint32_t bufSize,
101{
102 using ENTupleStructure = ROOT::Experimental::ENTupleStructure;
103
104 auto base = reinterpret_cast<const unsigned char *>(buffer);
105 auto bytes = base;
106 std::uint32_t frameSize;
107 auto fnFrameSizeLeft = [&]() { return frameSize - static_cast<std::uint32_t>(bytes - base); };
108 auto result = RNTupleSerializer::DeserializeFrameHeader(bytes, bufSize, frameSize);
109 if (!result)
110 return R__FORWARD_ERROR(result);
111 bytes += result.Unwrap();
112
113 std::uint32_t fieldVersion;
114 std::uint32_t typeVersion;
115 std::uint32_t parentId;
116 // initialize properly for call to SerializeFieldStructure()
117 ENTupleStructure structure{ENTupleStructure::kLeaf};
118 std::uint16_t flags;
119 if (fnFrameSizeLeft() < 3 * sizeof(std::uint32_t) +
120 RNTupleSerializer::SerializeFieldStructure(structure, nullptr) +
121 sizeof(std::uint16_t))
122 {
123 return R__FAIL("field record frame too short");
124 }
125 bytes += RNTupleSerializer::DeserializeUInt32(bytes, fieldVersion);
126 bytes += RNTupleSerializer::DeserializeUInt32(bytes, typeVersion);
127 bytes += RNTupleSerializer::DeserializeUInt32(bytes, parentId);
128 auto res16 = RNTupleSerializer::DeserializeFieldStructure(bytes, structure);
129 if (!res16)
130 return R__FORWARD_ERROR(res16);
131 bytes += res16.Unwrap();
132 bytes += RNTupleSerializer::DeserializeUInt16(bytes, flags);
133 fieldDesc.FieldVersion(fieldVersion).TypeVersion(typeVersion).ParentId(parentId).Structure(structure);
134
135 if (flags & RNTupleSerializer::kFlagRepetitiveField) {
136 if (fnFrameSizeLeft() < sizeof(std::uint64_t))
137 return R__FAIL("field record frame too short");
138 std::uint64_t nRepetitions;
139 bytes += RNTupleSerializer::DeserializeUInt64(bytes, nRepetitions);
140 fieldDesc.NRepetitions(nRepetitions);
141 }
142
143 std::string fieldName;
144 std::string typeName;
145 std::string aliasName;
146 std::string description;
147 result = RNTupleSerializer::DeserializeString(bytes, fnFrameSizeLeft(), fieldName).Unwrap();
148 if (!result)
149 return R__FORWARD_ERROR(result);
150 bytes += result.Unwrap();
151 result = RNTupleSerializer::DeserializeString(bytes, fnFrameSizeLeft(), typeName).Unwrap();
152 if (!result)
153 return R__FORWARD_ERROR(result);
154 bytes += result.Unwrap();
155 result = RNTupleSerializer::DeserializeString(bytes, fnFrameSizeLeft(), aliasName).Unwrap();
156 if (!result)
157 return R__FORWARD_ERROR(result);
158 bytes += result.Unwrap();
159 result = RNTupleSerializer::DeserializeString(bytes, fnFrameSizeLeft(), description).Unwrap();
160 if (!result)
161 return R__FORWARD_ERROR(result);
162 bytes += result.Unwrap();
163 fieldDesc.FieldName(fieldName).TypeName(typeName).TypeAlias(aliasName).FieldDescription(description);
164
165 return frameSize;
166}
167
168std::uint32_t SerializeColumnListV1(const ROOT::Experimental::RNTupleDescriptor &desc,
169 std::span<const ROOT::Experimental::DescriptorId_t> fieldList,
171 void *buffer)
172{
173 using RColumnElementBase = ROOT::Experimental::Detail::RColumnElementBase;
174
175 auto base = reinterpret_cast<unsigned char *>(buffer);
176 auto pos = base;
177 void** where = (buffer == nullptr) ? &buffer : reinterpret_cast<void**>(&pos);
178
179 for (auto parentId : fieldList) {
180 for (const auto &c : desc.GetColumnIterable(parentId)) {
181 if (c.IsAliasColumn())
182 continue;
183
184 auto frame = pos;
185 pos += RNTupleSerializer::SerializeRecordFramePreamble(*where);
186
187 auto type = c.GetModel().GetType();
188 pos += RNTupleSerializer::SerializeColumnType(type, *where);
189 pos += RNTupleSerializer::SerializeUInt16(RColumnElementBase::GetBitsOnStorage(type), *where);
190 pos += RNTupleSerializer::SerializeUInt32(context.GetOnDiskFieldId(c.GetFieldId()), *where);
191 std::uint32_t flags = 0;
192 // TODO(jblomer): add support for descending columns in the column model
193 if (c.GetModel().GetIsSorted())
194 flags |= RNTupleSerializer::kFlagSortAscColumn;
195 // TODO(jblomer): fix for unsigned integer types
197 flags |= RNTupleSerializer::kFlagNonNegativeColumn;
198 pos += RNTupleSerializer::SerializeUInt32(flags, *where);
199
200 pos += RNTupleSerializer::SerializeFramePostscript(buffer ? frame : nullptr, pos - frame);
201 }
202 }
203
204 return pos - base;
205}
206
207RResult<std::uint32_t> DeserializeColumnV1(
208 const void *buffer,
209 std::uint32_t bufSize,
211{
213
214 auto base = reinterpret_cast<const unsigned char *>(buffer);
215 auto bytes = base;
216 std::uint32_t frameSize;
217 auto fnFrameSizeLeft = [&]() { return frameSize - static_cast<std::uint32_t>(bytes - base); };
218 auto result = RNTupleSerializer::DeserializeFrameHeader(bytes, bufSize, frameSize);
219 if (!result)
220 return R__FORWARD_ERROR(result);
221 bytes += result.Unwrap();
222
223 // Initialize properly for SerializeColumnType
224 EColumnType type{EColumnType::kIndex32};
225 std::uint16_t bitsOnStorage;
226 std::uint32_t fieldId;
227 std::uint32_t flags;
228 if (fnFrameSizeLeft() < RNTupleSerializer::SerializeColumnType(type, nullptr) +
229 sizeof(std::uint16_t) + 2 * sizeof(std::uint32_t))
230 {
231 return R__FAIL("column record frame too short");
232 }
233 auto res16 = RNTupleSerializer::DeserializeColumnType(bytes, type);
234 if (!res16)
235 return R__FORWARD_ERROR(res16);
236 bytes += res16.Unwrap();
237 bytes += RNTupleSerializer::DeserializeUInt16(bytes, bitsOnStorage);
238 bytes += RNTupleSerializer::DeserializeUInt32(bytes, fieldId);
239 bytes += RNTupleSerializer::DeserializeUInt32(bytes, flags);
240
242 return R__FAIL("column element size mismatch");
243
244 const bool isSorted = (flags & (RNTupleSerializer::kFlagSortAscColumn | RNTupleSerializer::kFlagSortDesColumn));
245 columnDesc.FieldId(fieldId).Model({type, isSorted});
246
247 return frameSize;
248}
249
250std::uint32_t SerializeLocatorPayloadURI(const ROOT::Experimental::RNTupleLocator &locator, unsigned char *buffer)
251{
252 const auto &uri = locator.GetPosition<std::string>();
253 if (uri.length() >= (1 << 16))
254 throw ROOT::Experimental::RException(R__FAIL("locator too large"));
255 if (buffer)
256 memcpy(buffer, uri.data(), uri.length());
257 return uri.length();
258}
259
260void DeserializeLocatorPayloadURI(const unsigned char *buffer, std::uint32_t payloadSize,
262{
263 locator.fBytesOnStorage = 0;
264 auto &uri = locator.fPosition.emplace<std::string>();
265 uri.resize(payloadSize);
266 memcpy(uri.data(), buffer, payloadSize);
267}
268
269std::uint32_t SerializeLocatorPayloadObject64(const ROOT::Experimental::RNTupleLocator &locator, unsigned char *buffer)
270{
272 if (buffer) {
273 RNTupleSerializer::SerializeUInt32(locator.fBytesOnStorage, buffer);
274 RNTupleSerializer::SerializeUInt64(data.fLocation, buffer + sizeof(std::uint32_t));
275 }
276 return sizeof(std::uint32_t) + sizeof(std::uint64_t);
277}
278
279void DeserializeLocatorPayloadObject64(const unsigned char *buffer, ROOT::Experimental::RNTupleLocator &locator)
280{
282 RNTupleSerializer::DeserializeUInt32(buffer, locator.fBytesOnStorage);
283 RNTupleSerializer::DeserializeUInt64(buffer + sizeof(std::uint32_t), data.fLocation);
284}
285
286std::uint32_t SerializeAliasColumnList(const ROOT::Experimental::RNTupleDescriptor &desc,
287 std::span<const ROOT::Experimental::DescriptorId_t> fieldList,
289 void *buffer)
290{
291 auto base = reinterpret_cast<unsigned char *>(buffer);
292 auto pos = base;
293 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
294
295 for (auto parentId : fieldList) {
296 for (const auto &c : desc.GetColumnIterable(parentId)) {
297 if (!c.IsAliasColumn())
298 continue;
299
300 auto frame = pos;
301 pos += RNTupleSerializer::SerializeRecordFramePreamble(*where);
302
303 pos += RNTupleSerializer::SerializeUInt32(context.GetOnDiskColumnId(c.GetPhysicalId()), *where);
304 pos += RNTupleSerializer::SerializeUInt32(context.GetOnDiskFieldId(c.GetFieldId()), *where);
305
306 pos += RNTupleSerializer::SerializeFramePostscript(buffer ? frame : nullptr, pos - frame);
307 }
308 }
309
310 return pos - base;
311}
312
313RResult<std::uint32_t> DeserializeAliasColumn(const void *buffer, std::uint32_t bufSize,
314 std::uint32_t &physicalColumnId, std::uint32_t &fieldId)
315{
316 auto base = reinterpret_cast<const unsigned char *>(buffer);
317 auto bytes = base;
318 std::uint32_t frameSize;
319 auto fnFrameSizeLeft = [&]() { return frameSize - static_cast<std::uint32_t>(bytes - base); };
320 auto result = RNTupleSerializer::DeserializeFrameHeader(bytes, bufSize, frameSize);
321 if (!result)
322 return R__FORWARD_ERROR(result);
323 bytes += result.Unwrap();
324
325 if (fnFrameSizeLeft() < 2 * sizeof(std::uint32_t)) {
326 return R__FAIL("alias column record frame too short");
327 }
328
329 bytes += RNTupleSerializer::DeserializeUInt32(bytes, physicalColumnId);
330 bytes += RNTupleSerializer::DeserializeUInt32(bytes, fieldId);
331
332 return frameSize;
333}
334
335} // anonymous namespace
336
337
339 const unsigned char *data, std::uint32_t length, std::uint32_t &crc32, void *buffer)
340{
341 if (buffer != nullptr) {
342 crc32 = R__crc32(0, nullptr, 0);
343 crc32 = R__crc32(crc32, data, length);
344 SerializeUInt32(crc32, buffer);
345 }
346 return 4;
347}
348
350 const unsigned char *data, std::uint32_t length, std::uint32_t &crc32)
351{
352 auto checksumReal = R__crc32(0, nullptr, 0);
353 checksumReal = R__crc32(checksumReal, data, length);
354 DeserializeUInt32(data + length, crc32);
355 if (crc32 != checksumReal)
356 return R__FAIL("CRC32 checksum mismatch");
357 return RResult<void>::Success();
358}
359
360
362 const unsigned char *data, std::uint32_t length)
363{
364 std::uint32_t crc32;
365 return R__FORWARD_RESULT(VerifyCRC32(data, length, crc32));
366}
367
368
369std::uint32_t ROOT::Experimental::Internal::RNTupleSerializer::SerializeInt16(std::int16_t val, void *buffer)
370{
371 if (buffer != nullptr) {
372 auto bytes = reinterpret_cast<unsigned char *>(buffer);
373 bytes[0] = (val & 0x00FF);
374 bytes[1] = (val & 0xFF00) >> 8;
375 }
376 return 2;
377}
378
379std::uint32_t ROOT::Experimental::Internal::RNTupleSerializer::DeserializeInt16(const void *buffer, std::int16_t &val)
380{
381 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
382 val = std::int16_t(bytes[0]) + (std::int16_t(bytes[1]) << 8);
383 return 2;
384}
385
386std::uint32_t ROOT::Experimental::Internal::RNTupleSerializer::SerializeUInt16(std::uint16_t val, void *buffer)
387{
388 return SerializeInt16(val, buffer);
389}
390
391std::uint32_t ROOT::Experimental::Internal::RNTupleSerializer::DeserializeUInt16(const void *buffer, std::uint16_t &val)
392{
393 return DeserializeInt16(buffer, *reinterpret_cast<std::int16_t *>(&val));
394}
395
396std::uint32_t ROOT::Experimental::Internal::RNTupleSerializer::SerializeInt32(std::int32_t val, void *buffer)
397{
398 if (buffer != nullptr) {
399 auto bytes = reinterpret_cast<unsigned char *>(buffer);
400 bytes[0] = (val & 0x000000FF);
401 bytes[1] = (val & 0x0000FF00) >> 8;
402 bytes[2] = (val & 0x00FF0000) >> 16;
403 bytes[3] = (val & 0xFF000000) >> 24;
404 }
405 return 4;
406}
407
408std::uint32_t ROOT::Experimental::Internal::RNTupleSerializer::DeserializeInt32(const void *buffer, std::int32_t &val)
409{
410 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
411 val = std::int32_t(bytes[0]) + (std::int32_t(bytes[1]) << 8) +
412 (std::int32_t(bytes[2]) << 16) + (std::int32_t(bytes[3]) << 24);
413 return 4;
414}
415
416std::uint32_t ROOT::Experimental::Internal::RNTupleSerializer::SerializeUInt32(std::uint32_t val, void *buffer)
417{
418 return SerializeInt32(val, buffer);
419}
420
421std::uint32_t ROOT::Experimental::Internal::RNTupleSerializer::DeserializeUInt32(const void *buffer, std::uint32_t &val)
422{
423 return DeserializeInt32(buffer, *reinterpret_cast<std::int32_t *>(&val));
424}
425
426std::uint32_t ROOT::Experimental::Internal::RNTupleSerializer::SerializeInt64(std::int64_t val, void *buffer)
427{
428 if (buffer != nullptr) {
429 auto bytes = reinterpret_cast<unsigned char *>(buffer);
430 bytes[0] = (val & 0x00000000000000FF);
431 bytes[1] = (val & 0x000000000000FF00) >> 8;
432 bytes[2] = (val & 0x0000000000FF0000) >> 16;
433 bytes[3] = (val & 0x00000000FF000000) >> 24;
434 bytes[4] = (val & 0x000000FF00000000) >> 32;
435 bytes[5] = (val & 0x0000FF0000000000) >> 40;
436 bytes[6] = (val & 0x00FF000000000000) >> 48;
437 bytes[7] = (val & 0xFF00000000000000) >> 56;
438 }
439 return 8;
440}
441
442std::uint32_t ROOT::Experimental::Internal::RNTupleSerializer::DeserializeInt64(const void *buffer, std::int64_t &val)
443{
444 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
445 val = std::int64_t(bytes[0]) + (std::int64_t(bytes[1]) << 8) +
446 (std::int64_t(bytes[2]) << 16) + (std::int64_t(bytes[3]) << 24) +
447 (std::int64_t(bytes[4]) << 32) + (std::int64_t(bytes[5]) << 40) +
448 (std::int64_t(bytes[6]) << 48) + (std::int64_t(bytes[7]) << 56);
449 return 8;
450}
451
452std::uint32_t ROOT::Experimental::Internal::RNTupleSerializer::SerializeUInt64(std::uint64_t val, void *buffer)
453{
454 return SerializeInt64(val, buffer);
455}
456
457std::uint32_t ROOT::Experimental::Internal::RNTupleSerializer::DeserializeUInt64(const void *buffer, std::uint64_t &val)
458{
459 return DeserializeInt64(buffer, *reinterpret_cast<std::int64_t *>(&val));
460}
461
462std::uint32_t ROOT::Experimental::Internal::RNTupleSerializer::SerializeString(const std::string &val, void *buffer)
463{
464 if (buffer) {
465 auto pos = reinterpret_cast<unsigned char *>(buffer);
466 pos += SerializeUInt32(val.length(), pos);
467 memcpy(pos, val.data(), val.length());
468 }
469 return sizeof(std::uint32_t) + val.length();
470}
471
473 const void *buffer, std::uint32_t bufSize, std::string &val)
474{
475 if (bufSize < sizeof(std::uint32_t))
476 return R__FAIL("string buffer too short");
477 bufSize -= sizeof(std::uint32_t);
478
479 auto base = reinterpret_cast<const unsigned char *>(buffer);
480 auto bytes = base;
481 std::uint32_t length;
482 bytes += DeserializeUInt32(buffer, length);
483 if (bufSize < length)
484 return R__FAIL("string buffer too short");
485
486 val.resize(length);
487 memcpy(&val[0], bytes, length);
488 return sizeof(std::uint32_t) + length;
489}
490
491
494{
496 switch (type) {
497 case EColumnType::kIndex64: return SerializeUInt16(0x01, buffer);
498 case EColumnType::kIndex32: return SerializeUInt16(0x02, buffer);
499 case EColumnType::kSwitch: return SerializeUInt16(0x03, buffer);
500 case EColumnType::kByte: return SerializeUInt16(0x04, buffer);
501 case EColumnType::kChar: return SerializeUInt16(0x05, buffer);
502 case EColumnType::kBit: return SerializeUInt16(0x06, buffer);
503 case EColumnType::kReal64: return SerializeUInt16(0x07, buffer);
504 case EColumnType::kReal32: return SerializeUInt16(0x08, buffer);
505 case EColumnType::kReal16: return SerializeUInt16(0x09, buffer);
506 case EColumnType::kInt64: return SerializeUInt16(0x0A, buffer);
507 case EColumnType::kInt32: return SerializeUInt16(0x0B, buffer);
508 case EColumnType::kInt16: return SerializeUInt16(0x0C, buffer);
509 case EColumnType::kInt8: return SerializeUInt16(0x0D, buffer);
510 case EColumnType::kSplitIndex64: return SerializeUInt16(0x0E, buffer);
511 case EColumnType::kSplitIndex32: return SerializeUInt16(0x0F, buffer);
512 case EColumnType::kSplitReal64: return SerializeUInt16(0x10, buffer);
513 case EColumnType::kSplitReal32: return SerializeUInt16(0x11, buffer);
514 case EColumnType::kSplitInt64: return SerializeUInt16(0x13, buffer);
515 case EColumnType::kSplitInt32: return SerializeUInt16(0x14, buffer);
516 case EColumnType::kSplitInt16: return SerializeUInt16(0x15, buffer);
517 default: throw RException(R__FAIL("ROOT bug: unexpected column type"));
518 }
519}
520
521
523 const void *buffer, ROOT::Experimental::EColumnType &type)
524{
526 std::uint16_t onDiskType;
527 auto result = DeserializeUInt16(buffer, onDiskType);
528 switch (onDiskType) {
529 case 0x01: type = EColumnType::kIndex64; break;
530 case 0x02: type = EColumnType::kIndex32; break;
531 case 0x03: type = EColumnType::kSwitch; break;
532 case 0x04: type = EColumnType::kByte; break;
533 case 0x05: type = EColumnType::kChar; break;
534 case 0x06: type = EColumnType::kBit; break;
535 case 0x07: type = EColumnType::kReal64; break;
536 case 0x08: type = EColumnType::kReal32; break;
537 case 0x09: type = EColumnType::kReal16; break;
538 case 0x0A: type = EColumnType::kInt64; break;
539 case 0x0B: type = EColumnType::kInt32; break;
540 case 0x0C: type = EColumnType::kInt16; break;
541 case 0x0D: type = EColumnType::kInt8; break;
542 case 0x0E: type = EColumnType::kSplitIndex64; break;
543 case 0x0F: type = EColumnType::kSplitIndex32; break;
544 case 0x10: type = EColumnType::kSplitReal64; break;
545 case 0x11: type = EColumnType::kSplitReal32; break;
546 case 0x13: type = EColumnType::kSplitInt64; break;
547 case 0x14: type = EColumnType::kSplitInt32; break;
548 case 0x15: type = EColumnType::kSplitInt16; break;
549 default: return R__FAIL("unexpected on-disk column type");
550 }
551 return result;
552}
553
554
556 ROOT::Experimental::ENTupleStructure structure, void *buffer)
557{
559 switch (structure) {
561 return SerializeUInt16(0x00, buffer);
563 return SerializeUInt16(0x01, buffer);
565 return SerializeUInt16(0x02, buffer);
567 return SerializeUInt16(0x03, buffer);
569 return SerializeUInt16(0x04, buffer);
570 default:
571 throw RException(R__FAIL("ROOT bug: unexpected field structure type"));
572 }
573}
574
575
577 const void *buffer, ROOT::Experimental::ENTupleStructure &structure)
578{
580 std::uint16_t onDiskValue;
581 auto result = DeserializeUInt16(buffer, onDiskValue);
582 switch (onDiskValue) {
583 case 0x00:
584 structure = ENTupleStructure::kLeaf;
585 break;
586 case 0x01:
588 break;
589 case 0x02:
590 structure = ENTupleStructure::kRecord;
591 break;
592 case 0x03:
593 structure = ENTupleStructure::kVariant;
594 break;
595 case 0x04:
597 break;
598 default:
599 return R__FAIL("unexpected on-disk field structure value");
600 }
601 return result;
602}
603
604
605/// Currently all enevelopes have the same version number (1). At a later point, different envelope types
606/// may have different version numbers
608{
609 auto base = reinterpret_cast<unsigned char *>(buffer);
610 auto pos = base;
611 void** where = (buffer == nullptr) ? &buffer : reinterpret_cast<void**>(&pos);
612
613 pos += SerializeUInt16(kEnvelopeCurrentVersion, *where);
614 pos += SerializeUInt16(kEnvelopeMinVersion, *where);
615 return pos - base;
616}
617
618
620 const unsigned char *envelope, std::uint32_t size, std::uint32_t &crc32, void *buffer)
621{
622 return SerializeCRC32(envelope, size, crc32, buffer);
623}
624
626 const unsigned char *envelope, std::uint32_t size, void *buffer)
627{
628 std::uint32_t crc32;
629 return SerializeEnvelopePostscript(envelope, size, crc32, buffer);
630}
631
632/// Currently all enevelopes have the same version number (1). At a later point, different envelope types
633/// may have different version numbers
635 const void *buffer, std::uint32_t bufSize, std::uint32_t &crc32)
636{
637 if (bufSize < (2 * sizeof(std::uint16_t) + sizeof(std::uint32_t)))
638 return R__FAIL("invalid envelope, too short");
639
640 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
641 auto base = bytes;
642
643 std::uint16_t protocolVersionAtWrite;
644 std::uint16_t protocolVersionMinRequired;
645 bytes += DeserializeUInt16(bytes, protocolVersionAtWrite);
646 // RNTuple compatible back to version 1 (but not to version 0)
647 if (protocolVersionAtWrite < 1)
648 return R__FAIL("The RNTuple format is too old (version 0)");
649
650 bytes += DeserializeUInt16(bytes, protocolVersionMinRequired);
651 if (protocolVersionMinRequired > kEnvelopeCurrentVersion) {
652 return R__FAIL(std::string("The RNTuple format is too new (version ") +
653 std::to_string(protocolVersionMinRequired) + ")");
654 }
655
656 // We defer the CRC32 check to the end to faciliate testing of forward/backward incompatibilities
657 auto result = VerifyCRC32(base, bufSize - 4, crc32);
658 if (!result)
659 return R__FORWARD_ERROR(result);
660
661 return sizeof(protocolVersionAtWrite) + sizeof(protocolVersionMinRequired);
662}
663
664
666 const void *buffer, std::uint32_t bufSize)
667{
668 std::uint32_t crc32;
669 return R__FORWARD_RESULT(DeserializeEnvelope(buffer, bufSize, crc32));
670}
671
672
674{
675 // Marker: multiply the final size with 1
676 return SerializeInt32(1, buffer);
677}
678
679
681 std::uint32_t nitems, void *buffer)
682{
683 if (nitems >= (1 << 28))
684 throw RException(R__FAIL("list frame too large: " + std::to_string(nitems)));
685
686 auto base = reinterpret_cast<unsigned char *>(buffer);
687 auto pos = base;
688 void** where = (buffer == nullptr) ? &buffer : reinterpret_cast<void**>(&pos);
689
690 // Marker: multiply the final size with -1
691 pos += RNTupleSerializer::SerializeInt32(-1, *where);
692 pos += SerializeUInt32(nitems, *where);
693 return pos - base;
694}
695
697 void *frame, std::int32_t size)
698{
699 if (size < 0)
700 throw RException(R__FAIL("frame too large: " + std::to_string(size)));
701 if (size < static_cast<std::int32_t>(sizeof(std::int32_t)))
702 throw RException(R__FAIL("frame too short: " + std::to_string(size)));
703 if (frame) {
704 std::int32_t marker;
705 DeserializeInt32(frame, marker);
706 if ((marker < 0) && (size < static_cast<std::int32_t>(2 * sizeof(std::int32_t))))
707 throw RException(R__FAIL("frame too short: " + std::to_string(size)));
708
709 SerializeInt32(marker * size, frame);
710 }
711 return 0;
712}
713
715 const void *buffer, std::uint32_t bufSize, std::uint32_t &frameSize, std::uint32_t &nitems)
716{
717 if (bufSize < sizeof(std::int32_t))
718 return R__FAIL("frame too short");
719
720 std::int32_t *ssize = reinterpret_cast<std::int32_t *>(&frameSize);
721 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
722 bytes += DeserializeInt32(bytes, *ssize);
723 if (*ssize >= 0) {
724 // Record frame
725 nitems = 1;
726 if (frameSize < sizeof(std::int32_t))
727 return R__FAIL("corrupt record frame size");
728 } else {
729 // List frame
730 if (bufSize < 2 * sizeof(std::int32_t))
731 return R__FAIL("frame too short");
732 bytes += DeserializeUInt32(bytes, nitems);
733 nitems &= (2 << 28) - 1;
734 *ssize = -(*ssize);
735 if (frameSize < 2 * sizeof(std::int32_t))
736 return R__FAIL("corrupt list frame size");
737 }
738
739 if (bufSize < frameSize)
740 return R__FAIL("frame too short");
741
742 return bytes - reinterpret_cast<const unsigned char *>(buffer);
743}
744
746 const void *buffer, std::uint32_t bufSize, std::uint32_t &frameSize)
747{
748 std::uint32_t nitems;
749 return R__FORWARD_RESULT(DeserializeFrameHeader(buffer, bufSize, frameSize, nitems));
750}
751
753 const std::vector<std::int64_t> &flags, void *buffer)
754{
755 if (flags.empty())
756 return SerializeInt64(0, buffer);
757
758 if (buffer) {
759 auto bytes = reinterpret_cast<unsigned char *>(buffer);
760
761 for (unsigned i = 0; i < flags.size(); ++i) {
762 if (flags[i] < 0)
763 throw RException(R__FAIL("feature flag out of bounds"));
764
765 // The MSb indicates that another Int64 follows; set this bit to 1 for all except the last element
766 if (i == (flags.size() - 1))
767 SerializeInt64(flags[i], bytes);
768 else
769 bytes += SerializeInt64(flags[i] | 0x8000000000000000, bytes);
770 }
771 }
772 return (flags.size() * sizeof(std::int64_t));
773}
774
776 const void *buffer, std::uint32_t bufSize, std::vector<std::int64_t> &flags)
777{
778 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
779
780 flags.clear();
781 std::int64_t f;
782 do {
783 if (bufSize < sizeof(std::int64_t))
784 return R__FAIL("feature flag buffer too short");
785 bytes += DeserializeInt64(bytes, f);
786 bufSize -= sizeof(std::int64_t);
787 flags.emplace_back(f & ~0x8000000000000000);
788 } while (f < 0);
789
790 return (flags.size() * sizeof(std::int64_t));
791}
792
794 const RNTupleLocator &locator, void *buffer)
795{
796 std::uint32_t size = 0;
797 if (locator.fType == RNTupleLocator::kTypeFile) {
798 if (static_cast<std::int32_t>(locator.fBytesOnStorage) < 0)
799 throw RException(R__FAIL("locator too large"));
800 size += SerializeUInt32(locator.fBytesOnStorage, buffer);
801 size += SerializeUInt64(locator.GetPosition<std::uint64_t>(),
802 buffer ? reinterpret_cast<unsigned char *>(buffer) + size : nullptr);
803 return size;
804 }
805
806 auto payloadp = buffer ? reinterpret_cast<unsigned char *>(buffer) + sizeof(std::int32_t) : nullptr;
807 switch (locator.fType) {
808 case RNTupleLocator::kTypeURI: size += SerializeLocatorPayloadURI(locator, payloadp); break;
809 case RNTupleLocator::kTypeDAOS: size += SerializeLocatorPayloadObject64(locator, payloadp); break;
810 default: throw RException(R__FAIL("locator has unknown type"));
811 }
812 std::int32_t head = sizeof(std::int32_t) + size;
813 head |= locator.fReserved << 16;
814 head |= static_cast<int>(locator.fType & 0x7F) << 24;
815 head = -head;
817 return size;
818}
819
821 const void *buffer, std::uint32_t bufSize, RNTupleLocator &locator)
822{
823 if (bufSize < sizeof(std::int32_t))
824 return R__FAIL("too short locator");
825
826 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
827 std::int32_t head;
828
829 bytes += DeserializeInt32(bytes, head);
830 bufSize -= sizeof(std::int32_t);
831 if (head < 0) {
832 head = -head;
833 const int type = head >> 24;
834 const std::uint32_t payloadSize = (static_cast<std::uint32_t>(head) & 0x0000FFFF) - sizeof(std::int32_t);
835 if (bufSize < payloadSize)
836 return R__FAIL("too short locator");
837 locator.fType = static_cast<RNTupleLocator::ELocatorType>(type);
838 locator.fReserved = static_cast<std::uint32_t>(head >> 16) & 0xFF;
839 switch (type) {
840 case RNTupleLocator::kTypeURI: DeserializeLocatorPayloadURI(bytes, payloadSize, locator); break;
841 case RNTupleLocator::kTypeDAOS: DeserializeLocatorPayloadObject64(bytes, locator); break;
842 default: return R__FAIL("unsupported locator type: " + std::to_string(type));
843 }
844 bytes += payloadSize;
845 } else {
846 if (bufSize < sizeof(std::uint64_t))
847 return R__FAIL("too short locator");
848 auto &offset = locator.fPosition.emplace<std::uint64_t>();
850 bytes += DeserializeUInt64(bytes, offset);
851 locator.fBytesOnStorage = head;
852 }
853
854 return bytes - reinterpret_cast<const unsigned char *>(buffer);
855}
856
858 const REnvelopeLink &envelopeLink, void *buffer)
859{
860 auto size = SerializeUInt32(envelopeLink.fUnzippedSize, buffer);
861 size += SerializeLocator(envelopeLink.fLocator,
862 buffer ? reinterpret_cast<unsigned char *>(buffer) + size : nullptr);
863 return size;
864}
865
867 const void *buffer, std::uint32_t bufSize, REnvelopeLink &envelopeLink)
868{
869 if (bufSize < sizeof(std::int32_t))
870 return R__FAIL("too short envelope link");
871
872 auto bytes = reinterpret_cast<const unsigned char *>(buffer);
873 bytes += DeserializeUInt32(bytes, envelopeLink.fUnzippedSize);
874 bufSize -= sizeof(std::uint32_t);
875 auto result = DeserializeLocator(bytes, bufSize, envelopeLink.fLocator);
876 if (!result)
877 return R__FORWARD_ERROR(result);
878 bytes += result.Unwrap();
879 return bytes - reinterpret_cast<const unsigned char *>(buffer);
880}
881
882
884 const RClusterSummary &clusterSummary, void *buffer)
885{
886 auto base = reinterpret_cast<unsigned char *>(buffer);
887 auto pos = base;
888 void** where = (buffer == nullptr) ? &buffer : reinterpret_cast<void**>(&pos);
889
890 auto frame = pos;
891 pos += SerializeRecordFramePreamble(*where);
892 pos += SerializeUInt64(clusterSummary.fFirstEntry, *where);
893 if (clusterSummary.fColumnGroupID >= 0) {
894 pos += SerializeInt64(-static_cast<int64_t>(clusterSummary.fNEntries), *where);
895 pos += SerializeUInt32(clusterSummary.fColumnGroupID, *where);
896 } else {
897 pos += SerializeInt64(static_cast<int64_t>(clusterSummary.fNEntries), *where);
898 }
899 auto size = pos - frame;
900 pos += SerializeFramePostscript(frame, size);
901 return size;
902}
903
904
906 const void *buffer, std::uint32_t bufSize, RClusterSummary &clusterSummary)
907{
908 auto base = reinterpret_cast<const unsigned char *>(buffer);
909 auto bytes = base;
910 std::uint32_t frameSize;
911 auto result = DeserializeFrameHeader(bytes, bufSize, frameSize);
912 if (!result)
913 return R__FORWARD_ERROR(result);
914 bytes += result.Unwrap();
915
916 auto fnBufSizeLeft = [&]() { return frameSize - static_cast<std::uint32_t>(bytes - base); };
917 if (fnBufSizeLeft() < 2 * sizeof(std::uint64_t))
918 return R__FAIL("too short cluster summary");
919
920 bytes += DeserializeUInt64(bytes, clusterSummary.fFirstEntry);
921 std::int64_t nEntries;
922 bytes += DeserializeInt64(bytes, nEntries);
923
924 if (nEntries < 0) {
925 if (fnBufSizeLeft() < sizeof(std::uint32_t))
926 return R__FAIL("too short cluster summary");
927 clusterSummary.fNEntries = -nEntries;
928 std::uint32_t columnGroupID;
929 bytes += DeserializeUInt32(bytes, columnGroupID);
930 clusterSummary.fColumnGroupID = columnGroupID;
931 } else {
932 clusterSummary.fNEntries = nEntries;
933 clusterSummary.fColumnGroupID = -1;
934 }
935
936 return frameSize;
937}
938
939
941 const RClusterGroup &clusterGroup, void *buffer)
942{
943 auto base = reinterpret_cast<unsigned char *>(buffer);
944 auto pos = base;
945 void** where = (buffer == nullptr) ? &buffer : reinterpret_cast<void**>(&pos);
946
947 auto frame = pos;
948 pos += SerializeRecordFramePreamble(*where);
949 pos += SerializeUInt32(clusterGroup.fNClusters, *where);
950 pos += SerializeEnvelopeLink(clusterGroup.fPageListEnvelopeLink, *where);
951 auto size = pos - frame;
952 pos += SerializeFramePostscript(frame, size);
953 return size;
954}
955
956
958 const void *buffer, std::uint32_t bufSize, RClusterGroup &clusterGroup)
959{
960 auto base = reinterpret_cast<const unsigned char *>(buffer);
961 auto bytes = base;
962
963 std::uint32_t frameSize;
964 auto result = DeserializeFrameHeader(bytes, bufSize, frameSize);
965 if (!result)
966 return R__FORWARD_ERROR(result);
967 bytes += result.Unwrap();
968
969 auto fnFrameSizeLeft = [&]() { return frameSize - static_cast<std::uint32_t>(bytes - base); };
970 if (fnFrameSizeLeft() < sizeof(std::uint32_t))
971 return R__FAIL("too short cluster group");
972
973 bytes += DeserializeUInt32(bytes, clusterGroup.fNClusters);
974 result = DeserializeEnvelopeLink(bytes, fnFrameSizeLeft(), clusterGroup.fPageListEnvelopeLink);
975 if (!result)
976 return R__FORWARD_ERROR(result);
977
978 return frameSize;
979}
980
982 bool forHeaderExtension)
983{
984 auto fieldZeroId = desc.GetFieldZeroId();
985 auto depthFirstTraversal = [&](std::span<DescriptorId_t> fieldTrees, auto doForEachField) {
986 std::deque<DescriptorId_t> idQueue{fieldTrees.begin(), fieldTrees.end()};
987 while (!idQueue.empty()) {
988 auto fieldId = idQueue.front();
989 idQueue.pop_front();
990 // Field zero has no physical representation nor columns of its own; recurse over its subfields only
991 if (fieldId != fieldZeroId)
992 doForEachField(fieldId);
993 unsigned i = 0;
994 for (const auto &f : desc.GetFieldIterable(fieldId))
995 idQueue.insert(idQueue.begin() + i++, f.GetId());
996 }
997 };
998
999 R__ASSERT(desc.GetNFields() > 0); // we must have at least a zero field
1000 if (!forHeaderExtension)
1001 R__ASSERT(GetHeaderExtensionOffset() == -1U);
1002
1003 std::vector<DescriptorId_t> fieldTrees;
1004 if (!forHeaderExtension) {
1005 fieldTrees.emplace_back(fieldZeroId);
1006 } else if (auto xHeader = desc.GetHeaderExtension()) {
1007 fieldTrees = xHeader->GetTopLevelFields(desc);
1008 }
1009 depthFirstTraversal(fieldTrees, [&](DescriptorId_t fieldId) { MapFieldId(fieldId); });
1010 depthFirstTraversal(fieldTrees, [&](DescriptorId_t fieldId) {
1011 for (const auto &c : desc.GetColumnIterable(fieldId))
1012 if (!c.IsAliasColumn())
1013 MapColumnId(c.GetLogicalId());
1014 });
1015 depthFirstTraversal(fieldTrees, [&](DescriptorId_t fieldId) {
1016 for (const auto &c : desc.GetColumnIterable(fieldId))
1017 if (c.IsAliasColumn())
1018 MapColumnId(c.GetLogicalId());
1019 });
1020
1021 // Anything added after this point is accounted for the header extension
1022 if (!forHeaderExtension)
1023 BeginHeaderExtension();
1024}
1025
1027 const RNTupleDescriptor &desc,
1028 const RContext &context,
1029 bool forHeaderExtension)
1030{
1031 auto base = reinterpret_cast<unsigned char *>(buffer);
1032 auto pos = base;
1033 void** where = (buffer == nullptr) ? &buffer : reinterpret_cast<void**>(&pos);
1034
1035 std::size_t nFields = 0, nColumns = 0, nAliasColumns = 0, fieldListOffset = 0;
1036 if (forHeaderExtension) {
1037 // A call to `RNTupleDescriptorBuilder::BeginHeaderExtension()` is not strictly required after serializing the
1038 // header, which may happen, e.g., in unit tests. Ensure an empty schema extension is serialized in this case
1039 if (auto xHeader = desc.GetHeaderExtension()) {
1040 nFields = xHeader->GetNFields();
1041 nColumns = xHeader->GetNPhysicalColumns();
1042 nAliasColumns = xHeader->GetNLogicalColumns() - xHeader->GetNPhysicalColumns();
1043 fieldListOffset = context.GetHeaderExtensionOffset();
1044 }
1045 } else {
1046 nFields = desc.GetNFields() - 1;
1047 nColumns = desc.GetNPhysicalColumns();
1048 nAliasColumns = desc.GetNLogicalColumns() - desc.GetNPhysicalColumns();
1049 }
1050 const auto &onDiskFields = context.GetOnDiskFieldList();
1051 std::span<const DescriptorId_t> fieldList{&(*(onDiskFields.cbegin() + fieldListOffset)), &(*onDiskFields.cend())};
1052
1053 auto frame = pos;
1054 pos += SerializeListFramePreamble(nFields, *where);
1055 pos += SerializeFieldList(desc, fieldList, /*firstOnDiskId=*/fieldListOffset, context, *where);
1056 pos += SerializeFramePostscript(buffer ? frame : nullptr, pos - frame);
1057
1058 frame = pos;
1059 pos += SerializeListFramePreamble(nColumns, *where);
1060 pos += SerializeColumnListV1(desc, fieldList, context, *where);
1061 pos += SerializeFramePostscript(buffer ? frame : nullptr, pos - frame);
1062
1063 frame = pos;
1064 pos += SerializeListFramePreamble(nAliasColumns, *where);
1065 pos += SerializeAliasColumnList(desc, fieldList, context, *where);
1066 pos += SerializeFramePostscript(buffer ? frame : nullptr, pos - frame);
1067
1068 // We don't use extra type information yet
1069 frame = pos;
1070 pos += SerializeListFramePreamble(0, *where);
1071 pos += SerializeFramePostscript(buffer ? frame : nullptr, pos - frame);
1072 return static_cast<std::uint32_t>(pos - base);
1073}
1074
1077 RNTupleDescriptorBuilder &descBuilder)
1078{
1079 auto base = reinterpret_cast<const unsigned char *>(buffer);
1080 auto bytes = base;
1081 auto fnBufSizeLeft = [&]() { return bufSize - (bytes - base); };
1083
1084 std::uint32_t frameSize;
1085 auto frame = bytes;
1086 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - frame); };
1087
1088 std::uint32_t nFields;
1089 result = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nFields);
1090 if (!result)
1091 return R__FORWARD_ERROR(result);
1092 bytes += result.Unwrap();
1093 // The zero field is always added before `DeserializeSchemaDescription()` is called
1094 const std::uint32_t fieldIdRangeBegin = descBuilder.GetDescriptor().GetNFields() - 1;
1095 for (unsigned i = 0; i < nFields; ++i) {
1096 std::uint32_t fieldId = fieldIdRangeBegin + i;
1097 RFieldDescriptorBuilder fieldBuilder;
1098 result = DeserializeFieldV1(bytes, fnFrameSizeLeft(), fieldBuilder);
1099 if (!result)
1100 return R__FORWARD_ERROR(result);
1101 bytes += result.Unwrap();
1102 if (fieldId == fieldBuilder.GetParentId())
1103 fieldBuilder.ParentId(kZeroFieldId);
1104 auto fieldDesc = fieldBuilder.FieldId(fieldId).MakeDescriptor();
1105 if (!fieldDesc)
1106 return R__FORWARD_ERROR(fieldDesc);
1107 auto parentId = fieldDesc.Inspect().GetParentId();
1108 descBuilder.AddField(fieldDesc.Unwrap());
1109 auto resVoid = descBuilder.AddFieldLink(parentId, fieldId);
1110 if (!resVoid)
1111 return R__FORWARD_ERROR(resVoid);
1112 }
1113 bytes = frame + frameSize;
1114
1115 std::uint32_t nColumns;
1116 frame = bytes;
1117 result = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nColumns);
1118 if (!result)
1119 return R__FORWARD_ERROR(result);
1120 bytes += result.Unwrap();
1121 const std::uint32_t columnIdRangeBegin = descBuilder.GetDescriptor().GetNLogicalColumns();
1122 std::unordered_map<DescriptorId_t, std::uint32_t> maxIndexes;
1123 for (unsigned i = 0; i < nColumns; ++i) {
1124 std::uint32_t columnId = columnIdRangeBegin + i;
1125 RColumnDescriptorBuilder columnBuilder;
1126 result = DeserializeColumnV1(bytes, fnFrameSizeLeft(), columnBuilder);
1127 if (!result)
1128 return R__FORWARD_ERROR(result);
1129 bytes += result.Unwrap();
1130
1131 std::uint32_t idx = 0;
1132 const auto fieldId = columnBuilder.GetFieldId();
1133 auto maxIdx = maxIndexes.find(fieldId);
1134 if (maxIdx != maxIndexes.end())
1135 idx = maxIdx->second + 1;
1136 maxIndexes[fieldId] = idx;
1137
1138 auto columnDesc = columnBuilder.Index(idx).LogicalColumnId(columnId).PhysicalColumnId(columnId).MakeDescriptor();
1139 if (!columnDesc)
1140 return R__FORWARD_ERROR(columnDesc);
1141 auto resVoid = descBuilder.AddColumn(columnDesc.Unwrap());
1142 if (!resVoid)
1143 return R__FORWARD_ERROR(resVoid);
1144 }
1145 bytes = frame + frameSize;
1146
1147 std::uint32_t nAliasColumns;
1148 frame = bytes;
1149 result = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nAliasColumns);
1150 if (!result)
1151 return R__FORWARD_ERROR(result);
1152 bytes += result.Unwrap();
1153 const std::uint32_t aliasColumnIdRangeBegin = columnIdRangeBegin + nColumns;
1154 for (unsigned i = 0; i < nAliasColumns; ++i) {
1155 std::uint32_t physicalId;
1156 std::uint32_t fieldId;
1157 result = DeserializeAliasColumn(bytes, fnFrameSizeLeft(), physicalId, fieldId);
1158 if (!result)
1159 return R__FORWARD_ERROR(result);
1160 bytes += result.Unwrap();
1161
1162 RColumnDescriptorBuilder columnBuilder;
1163 columnBuilder.LogicalColumnId(aliasColumnIdRangeBegin + i).PhysicalColumnId(physicalId).FieldId(fieldId);
1164 columnBuilder.Model(descBuilder.GetDescriptor().GetColumnDescriptor(physicalId).GetModel());
1165
1166 std::uint32_t idx = 0;
1167 auto maxIdx = maxIndexes.find(fieldId);
1168 if (maxIdx != maxIndexes.end())
1169 idx = maxIdx->second + 1;
1170 maxIndexes[fieldId] = idx;
1171
1172 auto aliasColumnDesc = columnBuilder.Index(idx).MakeDescriptor();
1173 if (!aliasColumnDesc)
1174 return R__FORWARD_ERROR(aliasColumnDesc);
1175 auto resVoid = descBuilder.AddColumn(aliasColumnDesc.Unwrap());
1176 if (!resVoid)
1177 return R__FORWARD_ERROR(resVoid);
1178 }
1179 bytes = frame + frameSize;
1180
1181 std::uint32_t nTypeInfo;
1182 frame = bytes;
1183 result = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nTypeInfo);
1184 if (!result)
1185 return R__FORWARD_ERROR(result);
1186 if (nTypeInfo > 0)
1187 R__LOG_WARNING(NTupleLog()) << "Extra type information is still unsupported! ";
1188 bytes = frame + frameSize;
1189
1190 return bytes - base;
1191}
1192
1196{
1197 RContext context;
1198
1199 auto base = reinterpret_cast<unsigned char *>(buffer);
1200 auto pos = base;
1201 void **where = (buffer == nullptr) ? &buffer : reinterpret_cast<void **>(&pos);
1202
1203 pos += SerializeEnvelopePreamble(*where);
1204 // So far we don't make use of feature flags
1205 pos += SerializeFeatureFlags(std::vector<std::int64_t>(), *where);
1206 pos += SerializeUInt32(kReleaseCandidateTag, *where);
1207 pos += SerializeString(desc.GetName(), *where);
1208 pos += SerializeString(desc.GetDescription(), *where);
1209 pos += SerializeString(std::string("ROOT v") + ROOT_RELEASE, *where);
1210
1211 context.MapSchema(desc, /*forHeaderExtension=*/false);
1212 pos += SerializeSchemaDescription(*where, desc, context);
1213
1214 std::uint32_t size = pos - base;
1215 std::uint32_t crc32 = 0;
1216 size += SerializeEnvelopePostscript(base, size, crc32, *where);
1217
1218 context.SetHeaderSize(size);
1219 context.SetHeaderCRC32(crc32);
1220 return context;
1221}
1222
1224 void *buffer, const RNTupleDescriptor &desc, std::span<DescriptorId_t> physClusterIDs, const RContext &context)
1225{
1226 auto base = reinterpret_cast<unsigned char *>(buffer);
1227 auto pos = base;
1228 void** where = (buffer == nullptr) ? &buffer : reinterpret_cast<void**>(&pos);
1229
1230 pos += SerializeEnvelopePreamble(*where);
1231 auto topMostFrame = pos;
1232 pos += SerializeListFramePreamble(physClusterIDs.size(), *where);
1233
1234 for (auto clusterId : physClusterIDs) {
1235 const auto &clusterDesc = desc.GetClusterDescriptor(context.GetMemClusterId(clusterId));
1236 // Get an ordered set of physical column ids
1237 std::set<DescriptorId_t> onDiskColumnIds;
1238 for (auto column : clusterDesc.GetColumnIds())
1239 onDiskColumnIds.insert(context.GetOnDiskColumnId(column));
1240
1241 auto outerFrame = pos;
1242 pos += SerializeListFramePreamble(onDiskColumnIds.size(), *where);
1243 for (auto onDiskId : onDiskColumnIds) {
1244 auto memId = context.GetMemColumnId(onDiskId);
1245 const auto &columnRange = clusterDesc.GetColumnRange(memId);
1246 const auto &pageRange = clusterDesc.GetPageRange(memId);
1247
1248 auto innerFrame = pos;
1249 pos += SerializeListFramePreamble(pageRange.fPageInfos.size(), *where);
1250
1251 for (const auto &pi : pageRange.fPageInfos) {
1252 pos += SerializeUInt32(pi.fNElements, *where);
1253 pos += SerializeLocator(pi.fLocator, *where);
1254 }
1255 pos += SerializeUInt64(columnRange.fFirstElementIndex, *where);
1256 pos += SerializeUInt32(columnRange.fCompressionSettings, *where);
1257
1258 pos += SerializeFramePostscript(buffer ? innerFrame : nullptr, pos - innerFrame);
1259 }
1260 pos += SerializeFramePostscript(buffer ? outerFrame : nullptr, pos - outerFrame);
1261 }
1262
1263 pos += SerializeFramePostscript(buffer ? topMostFrame : nullptr, pos - topMostFrame);
1264 std::uint32_t size = pos - base;
1265 size += SerializeEnvelopePostscript(base, size, *where);
1266 return size;
1267}
1268
1269std::uint32_t
1272 const RContext &context)
1273{
1274 auto base = reinterpret_cast<unsigned char *>(buffer);
1275 auto pos = base;
1276 void** where = (buffer == nullptr) ? &buffer : reinterpret_cast<void**>(&pos);
1277
1278 pos += SerializeEnvelopePreamble(*where);
1279
1280 // So far we don't make use of feature flags
1281 pos += SerializeFeatureFlags(std::vector<std::int64_t>(), *where);
1282 pos += SerializeUInt32(context.GetHeaderCRC32(), *where);
1283
1284 // Schema extension, i.e. incremental changes with respect to the header
1285 auto frame = pos;
1286 pos += SerializeRecordFramePreamble(*where);
1287 pos += SerializeSchemaDescription(*where, desc, context, /*forHeaderExtension=*/true);
1288 pos += SerializeFramePostscript(buffer ? frame : nullptr, pos - frame);
1289
1290 // So far no support for shared clusters (no column groups)
1291 frame = pos;
1292 pos += SerializeListFramePreamble(0, *where);
1293 pos += SerializeFramePostscript(buffer ? frame : nullptr, pos - frame);
1294
1295 // Cluster summaries
1296 const auto nClusterGroups = desc.GetNClusterGroups();
1297 unsigned int nClusters = 0;
1298 for (const auto &cgDesc : desc.GetClusterGroupIterable())
1299 nClusters += cgDesc.GetNClusters();
1300 frame = pos;
1301 pos += SerializeListFramePreamble(nClusters, *where);
1302 for (unsigned int i = 0; i < nClusterGroups; ++i) {
1303 const auto &cgDesc = desc.GetClusterGroupDescriptor(context.GetMemClusterGroupId(i));
1304 const auto nClustersInGroup = cgDesc.GetNClusters();
1305 const auto &clusterIds = cgDesc.GetClusterIds();
1306 for (unsigned int j = 0; j < nClustersInGroup; ++j) {
1307 const auto &clusterDesc = desc.GetClusterDescriptor(clusterIds[j]);
1308 RClusterSummary summary{clusterDesc.GetFirstEntryIndex(), clusterDesc.GetNEntries(), -1};
1309 pos += SerializeClusterSummary(summary, *where);
1310 }
1311 }
1312 pos += SerializeFramePostscript(buffer ? frame : nullptr, pos - frame);
1313
1314 // Cluster groups
1315 frame = pos;
1316 pos += SerializeListFramePreamble(nClusterGroups, *where);
1317 for (unsigned int i = 0; i < nClusterGroups; ++i) {
1318 const auto &cgDesc = desc.GetClusterGroupDescriptor(context.GetMemClusterGroupId(i));
1319 RClusterGroup clusterGroup;
1320 clusterGroup.fNClusters = cgDesc.GetNClusters();
1321 clusterGroup.fPageListEnvelopeLink.fUnzippedSize = cgDesc.GetPageListLength();
1322 clusterGroup.fPageListEnvelopeLink.fLocator = cgDesc.GetPageListLocator();
1323 pos += SerializeClusterGroup(clusterGroup, *where);
1324 }
1325 pos += SerializeFramePostscript(buffer ? frame : nullptr, pos - frame);
1326
1327 // So far no support for meta-data
1328 frame = pos;
1329 pos += SerializeListFramePreamble(0, *where);
1330 pos += SerializeFramePostscript(buffer ? frame : nullptr, pos - frame);
1331
1332 std::uint32_t size = pos - base;
1333 size += SerializeEnvelopePostscript(base, size, *where);
1334 return size;
1335}
1336
1338 const void *buffer, std::uint32_t bufSize, RNTupleDescriptorBuilder &descBuilder)
1339{
1340 auto base = reinterpret_cast<const unsigned char *>(buffer);
1341 auto bytes = base;
1342 auto fnBufSizeLeft = [&]() { return bufSize - (bytes - base); };
1344
1345 std::uint32_t crc32{0};
1346 result = DeserializeEnvelope(bytes, fnBufSizeLeft(), crc32);
1347 if (!result)
1348 return R__FORWARD_ERROR(result);
1349 bytes += result.Unwrap();
1350 descBuilder.SetHeaderCRC32(crc32);
1351
1352 std::vector<std::int64_t> featureFlags;
1353 result = DeserializeFeatureFlags(bytes, fnBufSizeLeft(), featureFlags);
1354 if (!result)
1355 return R__FORWARD_ERROR(result);
1356 bytes += result.Unwrap();
1357 for (auto f: featureFlags) {
1358 if (f)
1359 R__LOG_WARNING(NTupleLog()) << "Unsupported feature flag! " << f;
1360 }
1361
1362 std::uint32_t rcTag;
1363 if (fnBufSizeLeft() < static_cast<int>(sizeof(std::uint32_t)))
1364 return R__FAIL("header too short");
1365 bytes += DeserializeUInt32(bytes, rcTag);
1366 if (rcTag > 0) {
1367 R__LOG_WARNING(NTupleLog()) << "Pre-release format version: RC " << rcTag;
1368 }
1369
1370 std::string name;
1371 std::string description;
1372 std::string writer;
1373 result = DeserializeString(bytes, fnBufSizeLeft(), name);
1374 if (!result)
1375 return R__FORWARD_ERROR(result);
1376 bytes += result.Unwrap();
1377 result = DeserializeString(bytes, fnBufSizeLeft(), description);
1378 if (!result)
1379 return R__FORWARD_ERROR(result);
1380 bytes += result.Unwrap();
1381 result = DeserializeString(bytes, fnBufSizeLeft(), writer);
1382 if (!result)
1383 return R__FORWARD_ERROR(result);
1384 bytes += result.Unwrap();
1385 descBuilder.SetNTuple(name, description);
1386
1387 // Zero field
1388 descBuilder.AddField(
1389 RFieldDescriptorBuilder().FieldId(kZeroFieldId).Structure(ENTupleStructure::kRecord).MakeDescriptor().Unwrap());
1390 result = DeserializeSchemaDescription(bytes, fnBufSizeLeft(), descBuilder);
1391 if (!result)
1392 return R__FORWARD_ERROR(result);
1393
1394 return RResult<void>::Success();
1395}
1396
1397
1399 const void *buffer, std::uint32_t bufSize, RNTupleDescriptorBuilder &descBuilder)
1400{
1401 auto base = reinterpret_cast<const unsigned char *>(buffer);
1402 auto bytes = base;
1403 auto fnBufSizeLeft = [&]() { return bufSize - (bytes - base); };
1405
1406 result = DeserializeEnvelope(bytes, fnBufSizeLeft());
1407 if (!result)
1408 return R__FORWARD_ERROR(result);
1409 bytes += result.Unwrap();
1410
1411 std::vector<std::int64_t> featureFlags;
1412 result = DeserializeFeatureFlags(bytes, fnBufSizeLeft(), featureFlags);
1413 if (!result)
1414 return R__FORWARD_ERROR(result);
1415 bytes += result.Unwrap();
1416 for (auto f: featureFlags) {
1417 if (f)
1418 R__LOG_WARNING(NTupleLog()) << "Unsupported feature flag! " << f;
1419 }
1420
1421 std::uint32_t crc32{0};
1422 if (fnBufSizeLeft() < static_cast<int>(sizeof(std::uint32_t)))
1423 return R__FAIL("footer too short");
1424 bytes += DeserializeUInt32(bytes, crc32);
1425 if (crc32 != descBuilder.GetHeaderCRC32())
1426 return R__FAIL("CRC32 mismatch between header and footer");
1427
1428 std::uint32_t frameSize;
1429 auto frame = bytes;
1430 auto fnFrameSizeLeft = [&]() { return frameSize - (bytes - frame); };
1431
1432 result = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize);
1433 if (!result)
1434 return R__FORWARD_ERROR(result);
1435 bytes += result.Unwrap();
1436 if (fnFrameSizeLeft() > 0) {
1437 descBuilder.BeginHeaderExtension();
1438 result = DeserializeSchemaDescription(bytes, fnFrameSizeLeft(), descBuilder);
1439 if (!result)
1440 return R__FORWARD_ERROR(result);
1441 }
1442 bytes = frame + frameSize;
1443
1444 std::uint32_t nColumnGroups;
1445 frame = bytes;
1446 result = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nColumnGroups);
1447 if (!result)
1448 return R__FORWARD_ERROR(result);
1449 if (nColumnGroups > 0)
1450 return R__FAIL("sharded clusters are still unsupported");
1451 bytes = frame + frameSize;
1452
1453 std::uint32_t nClusterSummaries;
1454 frame = bytes;
1455 result = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nClusterSummaries);
1456 if (!result)
1457 return R__FORWARD_ERROR(result);
1458 bytes += result.Unwrap();
1459 for (std::uint32_t clusterId = 0; clusterId < nClusterSummaries; ++clusterId) {
1460 RClusterSummary clusterSummary;
1461 result = DeserializeClusterSummary(bytes, fnFrameSizeLeft(), clusterSummary);
1462 if (!result)
1463 return R__FORWARD_ERROR(result);
1464 bytes += result.Unwrap();
1465 if (clusterSummary.fColumnGroupID >= 0)
1466 return R__FAIL("sharded clusters are still unsupported");
1467 descBuilder.AddClusterSummary(clusterId, clusterSummary.fFirstEntry, clusterSummary.fNEntries);
1468 }
1469 bytes = frame + frameSize;
1470
1471 std::uint32_t nClusterGroups;
1472 frame = bytes;
1473 result = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nClusterGroups);
1474 if (!result)
1475 return R__FORWARD_ERROR(result);
1476 bytes += result.Unwrap();
1477 std::uint64_t clusterId = 0;
1478 for (std::uint32_t groupId = 0; groupId < nClusterGroups; ++groupId) {
1479 RClusterGroup clusterGroup;
1480 result = DeserializeClusterGroup(bytes, fnFrameSizeLeft(), clusterGroup);
1481 if (!result)
1482 return R__FORWARD_ERROR(result);
1483 bytes += result.Unwrap();
1484
1486 RClusterGroupDescriptorBuilder clusterGroupBuilder;
1487 clusterGroupBuilder.ClusterGroupId(groupId)
1490 for (std::uint64_t i = 0; i < clusterGroup.fNClusters; ++i)
1491 clusterGroupBuilder.AddCluster(clusterId + i);
1492 clusterId += clusterGroup.fNClusters;
1493 descBuilder.AddClusterGroup(std::move(clusterGroupBuilder));
1494 }
1495 bytes = frame + frameSize;
1496
1497 std::uint32_t nMDBlocks;
1498 frame = bytes;
1499 result = DeserializeFrameHeader(bytes, fnBufSizeLeft(), frameSize, nMDBlocks);
1500 if (!result)
1501 return R__FORWARD_ERROR(result);
1502 if (nMDBlocks > 0)
1503 R__LOG_WARNING(NTupleLog()) << "meta-data blocks are still unsupported";
1504 bytes = frame + frameSize;
1505
1506 return RResult<void>::Success();
1507}
1508
1509
1511 const void *buffer, std::uint32_t bufSize, std::vector<RClusterDescriptorBuilder> &clusters)
1512{
1513 auto base = reinterpret_cast<const unsigned char *>(buffer);
1514 auto bytes = base;
1515 auto fnBufSizeLeft = [&]() { return bufSize - (bytes - base); };
1517
1518 result = DeserializeEnvelope(bytes, fnBufSizeLeft());
1519 if (!result)
1520 return R__FORWARD_ERROR(result);
1521 bytes += result.Unwrap();
1522
1523 std::uint32_t topMostFrameSize;
1524 auto topMostFrame = bytes;
1525 auto fnTopMostFrameSizeLeft = [&]() { return topMostFrameSize - (bytes - topMostFrame); };
1526
1527 std::uint32_t nClusters;
1528 result = DeserializeFrameHeader(bytes, fnBufSizeLeft(), topMostFrameSize, nClusters);
1529 if (!result)
1530 return R__FORWARD_ERROR(result);
1531 bytes += result.Unwrap();
1532
1533 if (nClusters != clusters.size())
1534 return R__FAIL("mismatch of page list and cluster summaries");
1535
1536 for (std::uint32_t i = 0; i < nClusters; ++i) {
1537 std::uint32_t outerFrameSize;
1538 auto outerFrame = bytes;
1539 auto fnOuterFrameSizeLeft = [&]() { return outerFrameSize - (bytes - outerFrame); };
1540
1541 std::uint32_t nColumns;
1542 result = DeserializeFrameHeader(bytes, fnTopMostFrameSizeLeft(), outerFrameSize, nColumns);
1543 if (!result)
1544 return R__FORWARD_ERROR(result);
1545 bytes += result.Unwrap();
1546
1547 for (std::uint32_t j = 0; j < nColumns; ++j) {
1548 std::uint32_t innerFrameSize;
1549 auto innerFrame = bytes;
1550 auto fnInnerFrameSizeLeft = [&]() { return innerFrameSize - (bytes - innerFrame); };
1551
1552 std::uint32_t nPages;
1553 result = DeserializeFrameHeader(bytes, fnOuterFrameSizeLeft(), innerFrameSize, nPages);
1554 if (!result)
1555 return R__FORWARD_ERROR(result);
1556 bytes += result.Unwrap();
1557
1559 pageRange.fPhysicalColumnId = j;
1560 for (std::uint32_t k = 0; k < nPages; ++k) {
1561 if (fnInnerFrameSizeLeft() < static_cast<int>(sizeof(std::uint32_t)))
1562 return R__FAIL("inner frame too short");
1563 std::uint32_t nElements;
1564 RNTupleLocator locator;
1565 bytes += DeserializeUInt32(bytes, nElements);
1566 result = DeserializeLocator(bytes, fnInnerFrameSizeLeft(), locator);
1567 if (!result)
1568 return R__FORWARD_ERROR(result);
1569 pageRange.fPageInfos.push_back({nElements, locator});
1570 bytes += result.Unwrap();
1571 }
1572
1573 if (fnInnerFrameSizeLeft() < static_cast<int>(sizeof(std::uint32_t) + sizeof(std::uint64_t)))
1574 return R__FAIL("page list frame too short");
1575 std::uint64_t columnOffset;
1576 bytes += DeserializeUInt64(bytes, columnOffset);
1577 std::uint32_t compressionSettings;
1578 bytes += DeserializeUInt32(bytes, compressionSettings);
1579
1580 clusters[i].CommitColumnRange(j, columnOffset, compressionSettings, pageRange);
1581 bytes = innerFrame + innerFrameSize;
1582 }
1583
1584 bytes = outerFrame + outerFrameSize;
1585 }
1586
1587 return RResult<void>::Success();
1588}
#define R__FORWARD_ERROR(res)
Short-hand to return an RResult<T> in an error state (i.e. after checking)
Definition RError.hxx:307
#define R__FORWARD_RESULT(res)
Short-hand to return an RResult<T> value from a subroutine to the calling stack frame.
Definition RError.hxx:305
#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:303
#define R__LOG_WARNING(...)
Definition RLogger.hxx:363
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define ROOT_RELEASE
Definition RVersion.h:17
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
#define R__ASSERT(e)
Definition TError.h:118
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
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 result
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 length
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 nitems
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 bytes
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 Atom_t Time_t type
char name[80]
Definition TGX11.cxx:110
The available trivial, native content types of a column.
The serialization context is used for the piecewise serialization of a descriptor.
DescriptorId_t GetOnDiskColumnId(DescriptorId_t memId) const
const std::vector< DescriptorId_t > & GetOnDiskFieldList() const
Return a vector containing the in-memory field ID for each on-disk counterpart, in order,...
DescriptorId_t GetOnDiskFieldId(DescriptorId_t memId) const
DescriptorId_t GetMemColumnId(DescriptorId_t onDiskId) const
std::size_t GetHeaderExtensionOffset() const
Return the offset of the first element in fOnDisk2MemFieldIDs that is part of the schema extension.
DescriptorId_t GetMemClusterGroupId(DescriptorId_t onDiskId) const
DescriptorId_t GetMemClusterId(DescriptorId_t onDiskId) const
void MapSchema(const RNTupleDescriptor &desc, bool forHeaderExtension)
Map in-memory field and column IDs to their on-disk counterparts.
A helper class for serializing and deserialization of the RNTuple binary format.
static RResult< std::uint32_t > DeserializeString(const void *buffer, std::uint32_t bufSize, std::string &val)
static std::uint32_t SerializeFeatureFlags(const std::vector< std::int64_t > &flags, void *buffer)
static std::uint32_t SerializePageListV1(void *buffer, const RNTupleDescriptor &desc, std::span< DescriptorId_t > physClusterIDs, const RContext &context)
static std::uint32_t SerializeListFramePreamble(std::uint32_t nitems, void *buffer)
static RResult< std::uint32_t > DeserializeLocator(const void *buffer, std::uint32_t bufSize, RNTupleLocator &locator)
static std::uint32_t SerializeCRC32(const unsigned char *data, std::uint32_t length, std::uint32_t &crc32, void *buffer)
Writes a CRC32 checksum of the byte range given by data and length.
static std::uint16_t SerializeColumnType(ROOT::Experimental::EColumnType type, void *buffer)
static std::uint32_t DeserializeUInt16(const void *buffer, std::uint16_t &val)
static RResult< void > DeserializePageListV1(const void *buffer, std::uint32_t bufSize, std::vector< RClusterDescriptorBuilder > &clusters)
static std::uint32_t SerializeString(const std::string &val, void *buffer)
static RResult< std::uint32_t > DeserializeEnvelope(const void *buffer, std::uint32_t bufSize)
static std::uint32_t DeserializeUInt32(const void *buffer, std::uint32_t &val)
static std::uint32_t SerializeUInt64(std::uint64_t val, void *buffer)
static std::uint32_t DeserializeInt16(const void *buffer, std::int16_t &val)
static std::uint32_t SerializeClusterSummary(const RClusterSummary &clusterSummary, void *buffer)
static RContext SerializeHeaderV1(void *buffer, const RNTupleDescriptor &desc)
static RResult< void > DeserializeFooterV1(const void *buffer, std::uint32_t bufSize, RNTupleDescriptorBuilder &descBuilder)
static std::uint32_t SerializeInt16(std::int16_t val, void *buffer)
static RResult< std::uint32_t > DeserializeSchemaDescription(const void *buffer, std::uint32_t bufSize, RNTupleDescriptorBuilder &descBuilder)
static std::uint32_t SerializeSchemaDescription(void *buffer, const RNTupleDescriptor &desc, const RContext &context, bool forHeaderExtension=false)
Serialize the schema description in desc into buffer.
static std::uint32_t SerializeLocator(const RNTupleLocator &locator, void *buffer)
static std::uint32_t SerializeInt32(std::int32_t val, void *buffer)
static std::uint32_t SerializeEnvelopePreamble(void *buffer)
Currently all enevelopes have the same version number (1).
static RResult< std::uint16_t > DeserializeColumnType(const void *buffer, ROOT::Experimental::EColumnType &type)
static RResult< std::uint32_t > DeserializeClusterGroup(const void *buffer, std::uint32_t bufSize, RClusterGroup &clusterGroup)
static std::uint32_t DeserializeUInt64(const void *buffer, std::uint64_t &val)
static std::uint32_t DeserializeInt32(const void *buffer, std::int32_t &val)
static std::uint32_t DeserializeInt64(const void *buffer, std::int64_t &val)
static RResult< std::uint32_t > DeserializeEnvelopeLink(const void *buffer, std::uint32_t bufSize, REnvelopeLink &envelopeLink)
static std::uint32_t SerializeEnvelopePostscript(const unsigned char *envelope, std::uint32_t size, void *buffer)
static RResult< std::uint16_t > DeserializeFieldStructure(const void *buffer, ROOT::Experimental::ENTupleStructure &structure)
static std::uint32_t SerializeEnvelopeLink(const REnvelopeLink &envelopeLink, void *buffer)
static std::uint32_t SerializeRecordFramePreamble(void *buffer)
static std::uint32_t SerializeUInt16(std::uint16_t val, void *buffer)
static RResult< std::uint32_t > DeserializeFrameHeader(const void *buffer, std::uint32_t bufSize, std::uint32_t &frameSize, std::uint32_t &nitems)
static RResult< std::uint32_t > DeserializeFeatureFlags(const void *buffer, std::uint32_t bufSize, std::vector< std::int64_t > &flags)
static std::uint32_t SerializeClusterGroup(const RClusterGroup &clusterGroup, void *buffer)
static std::uint32_t SerializeFramePostscript(void *frame, std::int32_t size)
static std::uint32_t SerializeFooterV1(void *buffer, const RNTupleDescriptor &desc, const RContext &context)
static std::uint32_t SerializeInt64(std::int64_t val, void *buffer)
static RResult< void > VerifyCRC32(const unsigned char *data, std::uint32_t length, std::uint32_t &crc32)
Expects a CRC32 checksum in the 4 bytes following data + length and verifies it.
static std::uint16_t SerializeFieldStructure(ROOT::Experimental::ENTupleStructure structure, void *buffer)
While we could just interpret the enums as ints, we make the translation explicit in order to avoid a...
static std::uint32_t SerializeUInt32(std::uint32_t val, void *buffer)
static RResult< void > DeserializeHeaderV1(const void *buffer, std::uint32_t bufSize, RNTupleDescriptorBuilder &descBuilder)
static RResult< std::uint32_t > DeserializeClusterSummary(const void *buffer, std::uint32_t bufSize, RClusterSummary &clusterSummary)
A helper class for piece-wise construction of an RClusterGroupDescriptor.
RClusterGroupDescriptorBuilder & ClusterGroupId(DescriptorId_t clusterGroupId)
RClusterGroupDescriptorBuilder & PageListLength(std::uint32_t pageListLength)
RClusterGroupDescriptorBuilder & PageListLocator(const RNTupleLocator &pageListLocator)
A helper class for piece-wise construction of an RColumnDescriptor.
RColumnDescriptorBuilder & Model(const RColumnModel &model)
RResult< RColumnDescriptor > MakeDescriptor() const
Attempt to make a column descriptor.
RColumnDescriptorBuilder & FieldId(DescriptorId_t fieldId)
RColumnDescriptorBuilder & Index(std::uint32_t index)
RColumnDescriptorBuilder & LogicalColumnId(DescriptorId_t logicalColumnId)
RColumnDescriptorBuilder & PhysicalColumnId(DescriptorId_t physicalColumnId)
Base class for all ROOT issued exceptions.
Definition RError.hxx:78
A helper class for piece-wise construction of an RFieldDescriptor.
RFieldDescriptorBuilder & FieldName(const std::string &fieldName)
RFieldDescriptorBuilder & NRepetitions(std::uint64_t nRepetitions)
RFieldDescriptorBuilder & Structure(const ENTupleStructure &structure)
RResult< RFieldDescriptor > MakeDescriptor() const
Attempt to make a field descriptor.
RFieldDescriptorBuilder & TypeName(const std::string &typeName)
RFieldDescriptorBuilder & TypeVersion(std::uint32_t typeVersion)
RFieldDescriptorBuilder & ParentId(DescriptorId_t id)
RFieldDescriptorBuilder & FieldDescription(const std::string &fieldDescription)
RFieldDescriptorBuilder & FieldVersion(std::uint32_t fieldVersion)
RFieldDescriptorBuilder & TypeAlias(const std::string &typeAlias)
RFieldDescriptorBuilder & FieldId(DescriptorId_t fieldId)
Meta-data stored for every field of an ntuple.
A helper class for piece-wise construction of an RNTupleDescriptor.
void AddToOnDiskFooterSize(std::uint64_t size)
The real footer size also include the page list envelopes.
RResult< void > AddClusterSummary(DescriptorId_t clusterId, std::uint64_t firstEntry, std::uint64_t nEntries)
RResult< void > AddFieldLink(DescriptorId_t fieldId, DescriptorId_t linkId)
void SetNTuple(const std::string_view name, const std::string_view description)
const RNTupleDescriptor & GetDescriptor() const
void AddColumn(DescriptorId_t logicalId, DescriptorId_t physicalId, DescriptorId_t fieldId, const RColumnModel &model, std::uint32_t index)
void AddClusterGroup(RClusterGroupDescriptorBuilder &&clusterGroup)
void BeginHeaderExtension()
Mark the beginning of the header extension; any fields and columns added after a call to this functio...
void AddField(const RFieldDescriptor &fieldDesc)
The on-storage meta-data of an ntuple.
RClusterGroupDescriptorIterable GetClusterGroupIterable() const
DescriptorId_t GetFieldZeroId() const
Returns the logical parent of all top-level NTuple data fields.
RColumnDescriptorIterable GetColumnIterable(const RFieldDescriptor &fieldDesc) const
const RClusterDescriptor & GetClusterDescriptor(DescriptorId_t clusterId) const
RFieldDescriptorIterable GetFieldIterable(const RFieldDescriptor &fieldDesc) const
const RColumnDescriptor & GetColumnDescriptor(DescriptorId_t columnId) const
const RFieldDescriptor & GetFieldDescriptor(DescriptorId_t fieldId) const
const RClusterGroupDescriptor & GetClusterGroupDescriptor(DescriptorId_t clusterGroupId) const
const RHeaderExtension * GetHeaderExtension() const
Return header extension information; if the descriptor does not have a header extension,...
The class is used as a return type for operations that can fail; wraps a value of type T or an RError...
Definition RError.hxx:207
RLogChannel & NTupleLog()
Log channel for RNTuple diagnostics.
ENTupleStructure
The fields in the ntuple model tree can carry different structural information about the type system.
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
Records the parition of data into pages for a particular column in a particular cluster.
RNTupleLocator payload that is common for object stores using 64bit location information.
Generic information about the physical location of data.
ELocatorType
Values for the Type field in non-disk locators; see doc/specifications.md for details.
std::uint8_t fReserved
Reserved for use by concrete storage backends.
ELocatorType fType
For non-disk locators, the value for the Type field.
std::variant< std::uint64_t, std::string, RNTupleLocatorObject64 > fPosition
Simple on-disk locators consisting of a 64-bit offset use variant type uint64_t; extended locators ha...