HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
gzip.hpp
1// Copyright Take Vos 2020.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "../container/container.hpp"
8#include "../file/file.hpp"
9#include "../parser/parser.hpp"
10#include "../macros.hpp"
11#include "inflate.hpp"
12#include <cstddef>
13#include <filesystem>
14
15hi_export_module(hikogui.codec.gzip);
16
17hi_export namespace hi { inline namespace v1 {
18namespace detail {
19
21 uint8_t ID1;
22 uint8_t ID2;
23 uint8_t CM;
24 uint8_t FLG;
26 uint8_t XFL;
27 uint8_t OS;
28};
29
30[[nodiscard]] inline bstring gzip_decompress_member(std::span<std::byte const> bytes, std::size_t &offset, std::size_t max_size)
31{
32 auto const header = make_placement_ptr<gzip_member_header>(bytes, offset);
33
34 hi_check(header->ID1 == 31, "GZIP Member header ID1 must be 31");
35 hi_check(header->ID2 == 139, "GZIP Member header ID2 must be 139");
36 hi_check(header->CM == 8, "GZIP Member header CM must be 8");
37 hi_check((header->FLG & 0xe0) == 0, "GZIP Member header FLG reserved bits must be 0");
38 hi_check(header->XFL == 2 or header->XFL == 4, "GZIP Member header XFL must be 2 or 4");
39 [[maybe_unused]] auto const FTEXT = to_bool(header->FLG & 1);
40 auto const FHCRC = to_bool(header->FLG & 2);
41 auto const FEXTRA = to_bool(header->FLG & 4);
42 auto const FNAME = to_bool(header->FLG & 8);
43 auto const FCOMMENT = to_bool(header->FLG & 16);
44
45 if (FEXTRA) {
46 auto const XLEN = **make_placement_ptr<little_uint16_buf_t>(bytes, offset);
47 offset += XLEN;
48 }
49
50 if (FNAME) {
51 auto c = std::byte{};
52 do {
53 hi_check(offset < bytes.size(), "GZIP Member header FNAME reading beyond end of buffer");
54 c = bytes[offset++];
55 } while (c != std::byte{0});
56 }
57
58 if (FCOMMENT) {
59 auto c = std::byte{};
60 do {
61 hi_check(offset < bytes.size(), "GZIP Member header FCOMMENT reading beyond end of buffer");
62 c = bytes[offset++];
63 } while (c != std::byte{0});
64 }
65
66 if (FHCRC) {
67 [[maybe_unused]] auto const CRC16 = make_placement_ptr<little_uint16_buf_t>(bytes, offset);
68 }
69
70 auto r = inflate(bytes, offset, max_size);
71
72 [[maybe_unused]] auto CRC32 = **make_placement_ptr<little_uint32_buf_t>(bytes, offset);
73 [[maybe_unused]] auto ISIZE = **make_placement_ptr<little_uint32_buf_t>(bytes, offset);
74
75 hi_check(
76 ISIZE == (size(r) & 0xffffffff),
77 "GZIP Member header ISIZE must be same as the lower 32 bits of the inflated size.");
78 return r;
79}
80
81}
82
83hi_export [[nodiscard]] inline bstring gzip_decompress(std::span<std::byte const> bytes, std::size_t max_size)
84{
85 auto r = bstring{};
86
87 auto offset = 0_uz;
88 while (offset < bytes.size()) {
89 auto member = detail::gzip_decompress_member(bytes, offset, max_size);
90 max_size -= member.size();
91 r.append(member);
92 }
93
94 return r;
95}
96
97hi_export [[nodiscard]] inline bstring gzip_decompress(std::filesystem::path const &path, std::size_t max_size = 0x01000000)
98{
99 return gzip_decompress(as_span<std::byte const>(file_view{path}), max_size);
100}
101
102}} // namespace hi::inline v1
Defines the file class.
The HikoGUI namespace.
Definition array_generic.hpp:20
hi_export bstring inflate(std::span< std::byte const > bytes, std::size_t &offset, std::size_t max_size=0x0100 '0000)
Inflate compressed data using the deflate algorithm bytes should include at least 32 bit of trailer,...
Definition inflate.hpp:358
DOXYGEN BUG.
Definition algorithm_misc.hpp:20