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