Yann Collet | e9dc204 | 2017-08-31 11:24:54 -0700 | [diff] [blame] | 1 | /* |
Elliott Hughes | 44aba64 | 2023-09-12 20:18:59 +0000 | [diff] [blame] | 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. |
Nick Terrell | c932520 | 2016-09-01 15:22:19 -0700 | [diff] [blame] | 3 | * All rights reserved. |
| 4 | * |
Yann Collet | e9dc204 | 2017-08-31 11:24:54 -0700 | [diff] [blame] | 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). |
Nick Terrell | c932520 | 2016-09-01 15:22:19 -0700 | [diff] [blame] | 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 | |
| 55 | ByteRange data() const { |
| 56 | return {data_.data(), data_.size()}; |
| 57 | } |
| 58 | |
| 59 | // Size of the next frame. |
| 60 | std::size_t frameSize() const { |
| 61 | return frameSize_; |
| 62 | } |
| 63 | }; |
| 64 | } |