1 /*
2  * Copyright (c) 2016-present, Facebook, Inc.
3  * All rights reserved.
4  *
5  * This source code is licensed under both the BSD-style license (found in the
6  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7  * in the COPYING file in the root directory of this source tree).
8  */
9 #pragma once
10 
11 #include "utils/Range.h"
12 
13 #include <array>
14 #include <cstddef>
15 #include <cstdint>
16 #include <cstdio>
17 
18 namespace pzstd {
19 /**
20  * We put a skippable frame before each frame.
21  * It contains a skippable frame magic number, the size of the skippable frame,
22  * and the size of the next frame.
23  * Each skippable frame is exactly 12 bytes in little endian format.
24  * The first 8 bytes are for compatibility with the ZSTD format.
25  * If we have N threads, the output will look like
26  *
27  * [0x184D2A50|4|size1] [frame1 of size size1]
28  * [0x184D2A50|4|size2] [frame2 of size size2]
29  * ...
30  * [0x184D2A50|4|sizeN] [frameN of size sizeN]
31  *
32  * Each sizeX is 4 bytes.
33  *
34  * These skippable frames should allow us to skip through the compressed file
35  * and only load at most N pages.
36  */
37 class SkippableFrame {
38  public:
39   static constexpr std::size_t kSize = 12;
40 
41  private:
42   std::uint32_t frameSize_;
43   std::array<std::uint8_t, kSize> data_;
44   static constexpr std::uint32_t kSkippableFrameMagicNumber = 0x184D2A50;
45   // Could be improved if the size fits in less bytes
46   static constexpr std::uint32_t kFrameContentsSize = kSize - 8;
47 
48  public:
49    // Write the skippable frame to data_ in LE format.
50   explicit SkippableFrame(std::uint32_t size);
51 
52   // Read the skippable frame from bytes in LE format.
53   static std::size_t tryRead(ByteRange bytes);
54 
data()55   ByteRange data() const {
56     return {data_.data(), data_.size()};
57   }
58 
59   // Size of the next frame.
frameSize()60   std::size_t frameSize() const {
61     return frameSize_;
62   }
63 };
64 }
65