This page hosts a formal specification of Zchunk using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.
All C++11/STL code generated by Kaitai Struct depends on the Kaitai Struct runtime library for C++/STL. You must add this dependency to your project before you can parse or serialize any data.
For C++, the easiest way is to clone the runtime library sources and build them along with your project.
Using Kaitai Struct in C++/STL usually consists of 3 steps.
std::istream). One can open local file for that, or use existing std::string or char* buffer.
#include <fstream>
std::ifstream is("path/to/local/file.zck", std::ifstream::binary);
#include <sstream>
std::istringstream is(str);
#include <sstream>
const char buf[] = { ... };
std::string str(buf, sizeof buf);
std::istringstream is(str);
#include "kaitai/kaitaistream.h"
kaitai::kstream ks(&is);
zchunk_t data(&ks);
After that, one can get various attributes from the structure by invoking getter methods like:
data.dict() // => Custom dictionary used when compressing each chunk. It's compressed itself
without a dictionary.
The official zchunk specification calls this section "Compressed Dict".
It's also called a "dictionary chunk". `zck_read_header -c` presents it as
"chunk 0" (which is always shown in the chunk table, but can have size 0
if the dictionary is not in use).
#pragma once
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
class zchunk_t;
#include "kaitai/kaitaistruct.h"
#include <stdint.h>
#include <memory>
#include <set>
#include <vector>
#if KAITAI_STRUCT_VERSION < 11000L
#error "Incompatible Kaitai Struct C++/STL API: version 0.11 or later is required"
#endif
/**
* \sa https://github.com/zchunk/zchunk/blob/99e51afa38c723e7c25834c2c3b305d20ef55d04/zchunk_format.txt Source
*/
class zchunk_t : public kaitai::kstruct {
public:
class checksum_type_t;
class chunk_t;
class compressed_integer_t;
class header_lead_t;
class header_without_lead_t;
class index_t;
class optional_element_t;
class preface_t;
enum checksum_types_t {
CHECKSUM_TYPES_SHA1 = 0,
CHECKSUM_TYPES_SHA256 = 1,
CHECKSUM_TYPES_SHA512 = 2,
CHECKSUM_TYPES_SHA512_128 = 3
};
static bool _is_defined_checksum_types_t(checksum_types_t v);
private:
static const std::set<checksum_types_t> _values_checksum_types_t;
public:
enum compression_types_t {
COMPRESSION_TYPES_NONE = 0,
COMPRESSION_TYPES_ZSTD = 2
};
static bool _is_defined_compression_types_t(compression_types_t v);
private:
static const std::set<compression_types_t> _values_compression_types_t;
public:
zchunk_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, zchunk_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~zchunk_t();
class checksum_type_t : public kaitai::kstruct {
public:
checksum_type_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, zchunk_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~checksum_type_t();
private:
bool f_len_checksum;
int8_t m_len_checksum;
public:
int8_t len_checksum();
private:
bool f_value;
checksum_types_t m_value;
public:
checksum_types_t value();
private:
std::unique_ptr<compressed_integer_t> m_raw;
zchunk_t* m__root;
kaitai::kstruct* m__parent;
public:
/**
* Raw integer, don't read this field - access `value` instead.
*/
compressed_integer_t* raw() const { return m_raw.get(); }
zchunk_t* _root() const { return m__root; }
kaitai::kstruct* _parent() const { return m__parent; }
};
class chunk_t : public kaitai::kstruct {
public:
chunk_t(uint32_t p_len_checksum, bool p_has_data_streams, bool p_has_uncompressed_source, kaitai::kstream* p__io, zchunk_t::index_t* p__parent = nullptr, zchunk_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~chunk_t();
private:
std::unique_ptr<compressed_integer_t> m_chunk_stream;
bool n_chunk_stream;
public:
bool _is_null_chunk_stream() { chunk_stream(); return n_chunk_stream; };
private:
std::string m_chunk_checksum;
std::string m_uncompressed_chunk_checksum;
bool n_uncompressed_chunk_checksum;
public:
bool _is_null_uncompressed_chunk_checksum() { uncompressed_chunk_checksum(); return n_uncompressed_chunk_checksum; };
private:
std::unique_ptr<compressed_integer_t> m_len_chunk;
std::unique_ptr<compressed_integer_t> m_len_uncompressed_chunk;
uint32_t m_len_checksum;
bool m_has_data_streams;
bool m_has_uncompressed_source;
zchunk_t* m__root;
zchunk_t::index_t* m__parent;
public:
compressed_integer_t* chunk_stream() const { return m_chunk_stream.get(); }
std::string chunk_checksum() const { return m_chunk_checksum; }
/**
* Checksum of the uncompressed chunk. Used to detect whether a chunk
* from an uncompressed source is identical to the compressed chunk.
*/
std::string uncompressed_chunk_checksum() const { return m_uncompressed_chunk_checksum; }
compressed_integer_t* len_chunk() const { return m_len_chunk.get(); }
compressed_integer_t* len_uncompressed_chunk() const { return m_len_uncompressed_chunk.get(); }
uint32_t len_checksum() const { return m_len_checksum; }
bool has_data_streams() const { return m_has_data_streams; }
bool has_uncompressed_source() const { return m_has_uncompressed_source; }
zchunk_t* _root() const { return m__root; }
zchunk_t::index_t* _parent() const { return m__parent; }
};
/**
* Like `/common/vlq_base128_le` (LEB128), but the logic of the
* "continuation" flag in the most significant bit is inverted, so instead of
* `has_next`, it is called `is_last` (if the highest bit is set to zero, it
* means "continue", whereas in standard LEB128, the highest bit set to
* **one** means "continue"). Therefore, we cannot simply import
* `/common/vlq_base128_le` and use it, because it is incompatible.
*/
class compressed_integer_t : public kaitai::kstruct {
public:
class group_t;
compressed_integer_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, zchunk_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~compressed_integer_t();
/**
* One byte group, clearly divided into 7-bit "value" chunk and 1-bit "continuation" flag.
*/
class group_t : public kaitai::kstruct {
public:
group_t(int32_t p_idx, kaitai::kstream* p__io, zchunk_t::compressed_integer_t* p__parent = nullptr, zchunk_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~group_t();
private:
bool m_is_last;
uint64_t m_value;
int32_t m_idx;
zchunk_t* m__root;
zchunk_t::compressed_integer_t* m__parent;
public:
/**
* If `true`, then this is the last byte of the compressed integer.
*
* Since this implementation only supports serialized values up to 10
* bytes, this must be `true` in the 10th group (`groups[9]`).
*/
bool is_last() const { return m_is_last; }
/**
* The 7-bit (base128) numeric value chunk of this group
*
* Since this implementation only supports integer values up to 64 bits,
* the `value` in the 10th group (`groups[9]`) can only be `0` or `1`
* (otherwise the width of the represented value would be 65 bits or
* more, which is not supported).
*/
uint64_t value() const { return m_value; }
int32_t idx() const { return m_idx; }
zchunk_t* _root() const { return m__root; }
zchunk_t::compressed_integer_t* _parent() const { return m__parent; }
};
private:
bool f_len;
int32_t m_len;
public:
int32_t len();
private:
bool f_value;
uint64_t m_value;
public:
/**
* Resulting unsigned value as normal integer
*/
uint64_t value();
private:
std::unique_ptr<std::vector<std::unique_ptr<group_t>>> m_groups;
zchunk_t* m__root;
kaitai::kstruct* m__parent;
public:
std::vector<std::unique_ptr<group_t>>* groups() const { return m_groups.get(); }
zchunk_t* _root() const { return m__root; }
kaitai::kstruct* _parent() const { return m__parent; }
};
class header_lead_t : public kaitai::kstruct {
public:
header_lead_t(kaitai::kstream* p__io, zchunk_t* p__parent = nullptr, zchunk_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~header_lead_t();
private:
bool f_is_detached_header;
bool m_is_detached_header;
public:
/**
* Determines whether this file is a zchunk detached header (`.zhr`). If
* not, it is a complete zchunk file (`.zck`).
*/
bool is_detached_header();
private:
std::string m_magic;
std::unique_ptr<checksum_type_t> m_overall_checksum_type;
std::unique_ptr<compressed_integer_t> m_len_header_rest;
std::string m_header_checksum;
zchunk_t* m__root;
zchunk_t* m__parent;
public:
/**
* There are two valid magic numbers for zchunk files:
*
* * `'\0ZCK1'` identifies a zchunk version 1 file (`.zck`)
* * `'\0ZHR1'` identifies a zchunk version 1 detached header file (`.zhr`)
*/
std::string magic() const { return m_magic; }
/**
* Type of the checksum used for `header_checksum` and
* `_root.header_rest.preface.data_checksum`.
*/
checksum_type_t* overall_checksum_type() const { return m_overall_checksum_type.get(); }
/**
* Size of the header, not including the lead
*/
compressed_integer_t* len_header_rest() const { return m_len_header_rest.get(); }
/**
* Checksum of the entire header, which consists of `_root.lead` and
* `_root.header_rest` (i.e. everything from the beginning of the file to
* the end of `_root.header_rest`), not including the `header_checksum`
* field itself (i.e. the input for the checksum algorithm is a
* concatenation of the bytes preceding the `header_checksum` field with
* the bytes following it).
*
* For detached headers, the checksum is calculated as if the `magic`
* field were set to `'\0ZCK1'`, so that it matches the checksum in the
* full zchunk file.
*/
std::string header_checksum() const { return m_header_checksum; }
zchunk_t* _root() const { return m__root; }
zchunk_t* _parent() const { return m__parent; }
};
class header_without_lead_t : public kaitai::kstruct {
public:
header_without_lead_t(kaitai::kstream* p__io, zchunk_t* p__parent = nullptr, zchunk_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~header_without_lead_t();
private:
std::unique_ptr<preface_t> m_preface;
std::unique_ptr<compressed_integer_t> m_len_index;
std::unique_ptr<index_t> m_index;
std::unique_ptr<compressed_integer_t> m_num_signatures;
zchunk_t* m__root;
zchunk_t* m__parent;
std::string m__raw_index;
std::unique_ptr<kaitai::kstream> m__io__raw_index;
public:
preface_t* preface() const { return m_preface.get(); }
compressed_integer_t* len_index() const { return m_len_index.get(); }
index_t* index() const { return m_index.get(); }
/**
* Must be 0. The reference implementation also rejects any file with a
* non-zero "Signature count", throwing a fatal error stating "Signatures
* aren't supported yet" - see
* [`src/lib/header.c:259-264`](https://github.com/zchunk/zchunk/blob/99e51afa38c723e7c25834c2c3b305d20ef55d04/src/lib/header.c#L259-L264).
*
* Although the structure of signatures is defined [in the official
* textual
* specification](https://github.com/zchunk/zchunk/blob/99e51afa38c723e7c25834c2c3b305d20ef55d04/zchunk_format.txt#L219-L252),
* no signature types are defined, and as of this writing no publicly
* known implementation generates or interprets these signatures.
* Therefore, we've decided not to implement them here either.
*
* For more details, see
* <https://github.com/kaitai-io/kaitai_struct_formats/pull/539#discussion_r3713109887>.
*/
compressed_integer_t* num_signatures() const { return m_num_signatures.get(); }
zchunk_t* _root() const { return m__root; }
zchunk_t* _parent() const { return m__parent; }
std::string _raw_index() const { return m__raw_index; }
kaitai::kstream* _io__raw_index() const { return m__io__raw_index.get(); }
};
class index_t : public kaitai::kstruct {
public:
index_t(kaitai::kstream* p__io, zchunk_t::header_without_lead_t* p__parent = nullptr, zchunk_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~index_t();
private:
bool f_num_data_chunks;
int32_t m_num_data_chunks;
public:
/**
* Number of data chunks. `num_chunks` counts the dictionary as chunk 0,
* so it is one greater than this number.
*/
int32_t num_data_chunks();
private:
std::unique_ptr<checksum_type_t> m_chunk_checksum_type;
std::unique_ptr<compressed_integer_t> m_num_chunks;
std::unique_ptr<compressed_integer_t> m_dict_stream;
bool n_dict_stream;
public:
bool _is_null_dict_stream() { dict_stream(); return n_dict_stream; };
private:
std::string m_dict_checksum;
std::string m_uncompressed_dict_checksum;
bool n_uncompressed_dict_checksum;
public:
bool _is_null_uncompressed_dict_checksum() { uncompressed_dict_checksum(); return n_uncompressed_dict_checksum; };
private:
std::unique_ptr<compressed_integer_t> m_len_dict;
std::unique_ptr<compressed_integer_t> m_len_uncompressed_dict;
std::unique_ptr<std::vector<std::unique_ptr<chunk_t>>> m_chunks_metadata;
zchunk_t* m__root;
zchunk_t::header_without_lead_t* m__parent;
public:
/**
* Type of the checksum used for `dict_checksum` and for all
* `chunks_metadata[...].chunk_checksum` and
* `chunks_metadata[...].uncompressed_chunk_checksum`.
*/
checksum_type_t* chunk_checksum_type() const { return m_chunk_checksum_type.get(); }
/**
* Number of chunks, **including** the dictionary chunk.
*
* Must be at least 1, because the dictionary chunk is always present,
* even if it is empty. The reference implementation also fails when the
* number of chunks is 0, see
* [`src/lib/index/index_read.c:181-184`](https://github.com/zchunk/zchunk/blob/99e51afa38c723e7c25834c2c3b305d20ef55d04/src/lib/index/index_read.c#L181-L184).
*/
compressed_integer_t* num_chunks() const { return m_num_chunks.get(); }
/**
* If present, it must always be 0.
* \sa https://github.com/zchunk/zchunk/blob/99e51afa38c723e7c25834c2c3b305d20ef55d04/zchunk_format.txt#L159-L162 Source
*/
compressed_integer_t* dict_stream() const { return m_dict_stream.get(); }
std::string dict_checksum() const { return m_dict_checksum; }
/**
* Checksum of the uncompressed dictionary. It has no real use, as the
* uncompressed source won't have a dictionary.
*/
std::string uncompressed_dict_checksum() const { return m_uncompressed_dict_checksum; }
compressed_integer_t* len_dict() const { return m_len_dict.get(); }
compressed_integer_t* len_uncompressed_dict() const { return m_len_uncompressed_dict.get(); }
/**
* Metadata of the data chunks. The dictionary is chunk 0 and its
* metadata is stored in the `*dict*` fields above, so there is one fewer
* entry here than indicated by `num_chunks`.
*/
std::vector<std::unique_ptr<chunk_t>>* chunks_metadata() const { return m_chunks_metadata.get(); }
zchunk_t* _root() const { return m__root; }
zchunk_t::header_without_lead_t* _parent() const { return m__parent; }
};
class optional_element_t : public kaitai::kstruct {
public:
optional_element_t(kaitai::kstream* p__io, zchunk_t::preface_t* p__parent = nullptr, zchunk_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~optional_element_t();
private:
std::unique_ptr<compressed_integer_t> m_element_id;
std::unique_ptr<compressed_integer_t> m_len_data;
std::string m_data;
zchunk_t* m__root;
zchunk_t::preface_t* m__parent;
public:
compressed_integer_t* element_id() const { return m_element_id.get(); }
compressed_integer_t* len_data() const { return m_len_data.get(); }
std::string data() const { return m_data; }
zchunk_t* _root() const { return m__root; }
zchunk_t::preface_t* _parent() const { return m__parent; }
};
class preface_t : public kaitai::kstruct {
public:
preface_t(kaitai::kstream* p__io, zchunk_t::header_without_lead_t* p__parent = nullptr, zchunk_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~preface_t();
private:
bool f_compression_type;
compression_types_t m_compression_type;
public:
compression_types_t compression_type();
private:
bool f_has_data_streams;
bool m_has_data_streams;
public:
bool has_data_streams();
private:
bool f_has_optional_elements;
bool m_has_optional_elements;
public:
bool has_optional_elements();
private:
bool f_has_uncompressed_source;
bool m_has_uncompressed_source;
public:
/**
* The file may be applied against an uncompressed source. This adds an
* uncompressed checksum to every index entry, including the dictionary.
*/
bool has_uncompressed_source();
private:
std::string m_data_checksum;
std::unique_ptr<compressed_integer_t> m_flags;
std::unique_ptr<compressed_integer_t> m_compression_type_int;
std::unique_ptr<compressed_integer_t> m_num_optional_elements;
bool n_num_optional_elements;
public:
bool _is_null_num_optional_elements() { num_optional_elements(); return n_num_optional_elements; };
private:
std::unique_ptr<std::vector<std::unique_ptr<optional_element_t>>> m_optional_elements;
bool n_optional_elements;
public:
bool _is_null_optional_elements() { optional_elements(); return n_optional_elements; };
private:
zchunk_t* m__root;
zchunk_t::header_without_lead_t* m__parent;
public:
/**
* Total data checksum. Checksum of everything after the header,
* including the compressed dictionary (`_root.dict`) and all compressed
* chunks (`_root.chunks`). The type of this checksum is
* `_root.lead.overall_checksum_type.value`.
*
* If `has_uncompressed_source` is true, this checksum must not be
* checked and should not be generated. In that case, the reference
* implementation writes it as all zeros - see the sample file
* [`mini-uncomp-cksums.zck`](https://github.com/kaitai-io/kaitai_struct_samples/blob/1d2fe11c971fb7e86f343b77a1ed341a0217e86a/archive/zchunk/README.md#mini-uncomp-cksumszck).
*/
std::string data_checksum() const { return m_data_checksum; }
/**
* Compressed integer containing a bitmask of the flags. All unused flags
* MUST be set to 0. If a decoder sees a flag set that it doesn't
* recognize, it MUST exit with an error.
* \sa https://github.com/zchunk/zchunk/blob/99e51afa38c723e7c25834c2c3b305d20ef55d04/zchunk_format.txt#L78-L81 Source
*/
compressed_integer_t* flags() const { return m_flags.get(); }
/**
* Raw integer, don't read this field - access `compression_type`
* instead.
*/
compressed_integer_t* compression_type_int() const { return m_compression_type_int.get(); }
/**
* If present, it must be at least 1. This is because if there are no
* optional elements, `has_optional_elements` must be false, and then
* neither this field nor `optional_elements` is present.
* \sa https://github.com/zchunk/zchunk/blob/99e51afa38c723e7c25834c2c3b305d20ef55d04/zchunk_format.txt#L99-L102 Source
*/
compressed_integer_t* num_optional_elements() const { return m_num_optional_elements.get(); }
std::vector<std::unique_ptr<optional_element_t>>* optional_elements() const { return m_optional_elements.get(); }
zchunk_t* _root() const { return m__root; }
zchunk_t::header_without_lead_t* _parent() const { return m__parent; }
};
private:
std::unique_ptr<header_lead_t> m_lead;
std::unique_ptr<header_without_lead_t> m_header_rest;
std::string m_dict;
std::unique_ptr<std::vector<std::string>> m_chunks;
bool n_chunks;
public:
bool _is_null_chunks() { chunks(); return n_chunks; };
private:
zchunk_t* m__root;
kaitai::kstruct* m__parent;
std::string m__raw_header_rest;
std::unique_ptr<kaitai::kstream> m__io__raw_header_rest;
public:
header_lead_t* lead() const { return m_lead.get(); }
header_without_lead_t* header_rest() const { return m_header_rest.get(); }
/**
* Custom dictionary used when compressing each chunk. It's compressed itself
* without a dictionary.
*
* The official zchunk specification calls this section "Compressed Dict".
* It's also called a "dictionary chunk". `zck_read_header -c` presents it as
* "chunk 0" (which is always shown in the chunk table, but can have size 0
* if the dictionary is not in use).
*/
std::string dict() const { return m_dict; }
/**
* Chunks of data, each compressed with the custom dictionary `dict` (if
* applicable).
*
* They are not included in a detached header (`.zhr`) file. Detached headers
* contain the dictionary, but none of the data chunks.
*/
std::vector<std::string>* chunks() const { return m_chunks.get(); }
zchunk_t* _root() const { return m__root; }
kaitai::kstruct* _parent() const { return m__parent; }
std::string _raw_header_rest() const { return m__raw_header_rest; }
kaitai::kstream* _io__raw_header_rest() const { return m__io__raw_header_rest.get(); }
};
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
#include "zchunk.h"
#include "kaitai/exceptions.h"
const std::set<zchunk_t::checksum_types_t> zchunk_t::_values_checksum_types_t{
zchunk_t::CHECKSUM_TYPES_SHA1,
zchunk_t::CHECKSUM_TYPES_SHA256,
zchunk_t::CHECKSUM_TYPES_SHA512,
zchunk_t::CHECKSUM_TYPES_SHA512_128,
};
bool zchunk_t::_is_defined_checksum_types_t(zchunk_t::checksum_types_t v) {
return zchunk_t::_values_checksum_types_t.find(v) != zchunk_t::_values_checksum_types_t.end();
}
const std::set<zchunk_t::compression_types_t> zchunk_t::_values_compression_types_t{
zchunk_t::COMPRESSION_TYPES_NONE,
zchunk_t::COMPRESSION_TYPES_ZSTD,
};
bool zchunk_t::_is_defined_compression_types_t(zchunk_t::compression_types_t v) {
return zchunk_t::_values_compression_types_t.find(v) != zchunk_t::_values_compression_types_t.end();
}
zchunk_t::zchunk_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, zchunk_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root ? p__root : this;
m_lead = nullptr;
m_header_rest = nullptr;
m__io__raw_header_rest = nullptr;
m_chunks = nullptr;
_read();
}
void zchunk_t::_read() {
m_lead = std::unique_ptr<header_lead_t>(new header_lead_t(m__io, this, m__root));
m__raw_header_rest = m__io->read_bytes(lead()->len_header_rest()->value());
m__io__raw_header_rest = std::unique_ptr<kaitai::kstream>(new kaitai::kstream(m__raw_header_rest));
m_header_rest = std::unique_ptr<header_without_lead_t>(new header_without_lead_t(m__io__raw_header_rest.get(), this, m__root));
m_dict = m__io->read_bytes(header_rest()->index()->len_dict()->value());
n_chunks = true;
if (!(lead()->is_detached_header())) {
n_chunks = false;
m_chunks = std::unique_ptr<std::vector<std::string>>(new std::vector<std::string>());
const int l_chunks = header_rest()->index()->chunks_metadata()->size();
for (int i = 0; i < l_chunks; i++) {
m_chunks->push_back(std::move(m__io->read_bytes(header_rest()->index()->chunks_metadata()->at(i)->len_chunk()->value())));
}
}
}
zchunk_t::~zchunk_t() {
_clean_up();
}
void zchunk_t::_clean_up() {
if (!n_chunks) {
}
}
zchunk_t::checksum_type_t::checksum_type_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, zchunk_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_raw = nullptr;
f_len_checksum = false;
f_value = false;
_read();
}
void zchunk_t::checksum_type_t::_read() {
m_raw = std::unique_ptr<compressed_integer_t>(new compressed_integer_t(m__io, this, m__root));
{
std::unique_ptr<compressed_integer_t> _ = m_raw;
if (!(len_checksum() != 0)) {
throw kaitai::validation_expr_error<std::unique_ptr<zchunk_t::compressed_integer_t>>(m_raw, m__io, std::string("/types/checksum_type/seq/0"));
}
}
}
zchunk_t::checksum_type_t::~checksum_type_t() {
_clean_up();
}
void zchunk_t::checksum_type_t::_clean_up() {
}
int8_t zchunk_t::checksum_type_t::len_checksum() {
if (f_len_checksum)
return m_len_checksum;
f_len_checksum = true;
m_len_checksum = ((value() == zchunk_t::CHECKSUM_TYPES_SHA1) ? (20) : (((value() == zchunk_t::CHECKSUM_TYPES_SHA256) ? (32) : (((value() == zchunk_t::CHECKSUM_TYPES_SHA512) ? (64) : (((value() == zchunk_t::CHECKSUM_TYPES_SHA512_128) ? (16) : (0))))))));
return m_len_checksum;
}
zchunk_t::checksum_types_t zchunk_t::checksum_type_t::value() {
if (f_value)
return m_value;
f_value = true;
m_value = static_cast<zchunk_t::checksum_types_t>(raw()->value());
return m_value;
}
zchunk_t::chunk_t::chunk_t(uint32_t p_len_checksum, bool p_has_data_streams, bool p_has_uncompressed_source, kaitai::kstream* p__io, zchunk_t::index_t* p__parent, zchunk_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_len_checksum = p_len_checksum;
m_has_data_streams = p_has_data_streams;
m_has_uncompressed_source = p_has_uncompressed_source;
m_chunk_stream = nullptr;
m_len_chunk = nullptr;
m_len_uncompressed_chunk = nullptr;
_read();
}
void zchunk_t::chunk_t::_read() {
n_chunk_stream = true;
if (has_data_streams()) {
n_chunk_stream = false;
m_chunk_stream = std::unique_ptr<compressed_integer_t>(new compressed_integer_t(m__io, this, m__root));
}
m_chunk_checksum = m__io->read_bytes(len_checksum());
n_uncompressed_chunk_checksum = true;
if (has_uncompressed_source()) {
n_uncompressed_chunk_checksum = false;
m_uncompressed_chunk_checksum = m__io->read_bytes(len_checksum());
}
m_len_chunk = std::unique_ptr<compressed_integer_t>(new compressed_integer_t(m__io, this, m__root));
m_len_uncompressed_chunk = std::unique_ptr<compressed_integer_t>(new compressed_integer_t(m__io, this, m__root));
}
zchunk_t::chunk_t::~chunk_t() {
_clean_up();
}
void zchunk_t::chunk_t::_clean_up() {
if (!n_chunk_stream) {
}
if (!n_uncompressed_chunk_checksum) {
}
}
zchunk_t::compressed_integer_t::compressed_integer_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, zchunk_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_groups = nullptr;
f_len = false;
f_value = false;
_read();
}
void zchunk_t::compressed_integer_t::_read() {
m_groups = std::unique_ptr<std::vector<std::unique_ptr<group_t>>>(new std::vector<std::unique_ptr<group_t>>());
{
int i = 0;
group_t* _;
do {
_ = new group_t(i, m__io, this, m__root);
m_groups->push_back(std::move(std::unique_ptr<group_t>(_)));
i++;
} while (!(_->is_last()));
}
}
zchunk_t::compressed_integer_t::~compressed_integer_t() {
_clean_up();
}
void zchunk_t::compressed_integer_t::_clean_up() {
}
zchunk_t::compressed_integer_t::group_t::group_t(int32_t p_idx, kaitai::kstream* p__io, zchunk_t::compressed_integer_t* p__parent, zchunk_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_idx = p_idx;
_read();
}
void zchunk_t::compressed_integer_t::group_t::_read() {
m_is_last = m__io->read_bits_int_be(1);
if (!(m_is_last == ((idx() == 9) ? (true) : (is_last())))) {
throw kaitai::validation_not_equal_error<bool>(((idx() == 9) ? (true) : (is_last())), m_is_last, m__io, std::string("/types/compressed_integer/types/group/seq/0"));
}
m_value = m__io->read_bits_int_be(7);
if (!(m_value <= static_cast<uint64_t>(((idx() == 9) ? (1) : (127))))) {
throw kaitai::validation_greater_than_error<uint64_t>(static_cast<uint64_t>(((idx() == 9) ? (1) : (127))), m_value, m__io, std::string("/types/compressed_integer/types/group/seq/1"));
}
}
zchunk_t::compressed_integer_t::group_t::~group_t() {
_clean_up();
}
void zchunk_t::compressed_integer_t::group_t::_clean_up() {
}
int32_t zchunk_t::compressed_integer_t::len() {
if (f_len)
return m_len;
f_len = true;
m_len = groups()->size();
return m_len;
}
uint64_t zchunk_t::compressed_integer_t::value() {
if (f_value)
return m_value;
f_value = true;
m_value = static_cast<uint64_t>(((((((((groups()->at(0)->value() | ((len() >= 2) ? (groups()->at(1)->value() << 7) : (0))) | ((len() >= 3) ? (groups()->at(2)->value() << 14) : (0))) | ((len() >= 4) ? (groups()->at(3)->value() << 21) : (0))) | ((len() >= 5) ? (groups()->at(4)->value() << 28) : (0))) | ((len() >= 6) ? (groups()->at(5)->value() << 35) : (0))) | ((len() >= 7) ? (groups()->at(6)->value() << 42) : (0))) | ((len() >= 8) ? (groups()->at(7)->value() << 49) : (0))) | ((len() >= 9) ? (groups()->at(8)->value() << 56) : (0))) | ((len() >= 10) ? (groups()->at(9)->value() << 63) : (0)));
return m_value;
}
zchunk_t::header_lead_t::header_lead_t(kaitai::kstream* p__io, zchunk_t* p__parent, zchunk_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_overall_checksum_type = nullptr;
m_len_header_rest = nullptr;
f_is_detached_header = false;
_read();
}
void zchunk_t::header_lead_t::_read() {
m_magic = m__io->read_bytes(5);
if (!( ((m_magic == std::string("\x00\x5A\x43\x4B\x31", 5)) || (m_magic == std::string("\x00\x5A\x48\x52\x31", 5))) )) {
throw kaitai::validation_not_any_of_error<std::string>(m_magic, m__io, std::string("/types/header_lead/seq/0"));
}
m_overall_checksum_type = std::unique_ptr<checksum_type_t>(new checksum_type_t(m__io, this, m__root));
m_len_header_rest = std::unique_ptr<compressed_integer_t>(new compressed_integer_t(m__io, this, m__root));
m_header_checksum = m__io->read_bytes(overall_checksum_type()->len_checksum());
}
zchunk_t::header_lead_t::~header_lead_t() {
_clean_up();
}
void zchunk_t::header_lead_t::_clean_up() {
}
bool zchunk_t::header_lead_t::is_detached_header() {
if (f_is_detached_header)
return m_is_detached_header;
f_is_detached_header = true;
m_is_detached_header = magic().at(2) == 72;
return m_is_detached_header;
}
zchunk_t::header_without_lead_t::header_without_lead_t(kaitai::kstream* p__io, zchunk_t* p__parent, zchunk_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_preface = nullptr;
m_len_index = nullptr;
m_index = nullptr;
m__io__raw_index = nullptr;
m_num_signatures = nullptr;
_read();
}
void zchunk_t::header_without_lead_t::_read() {
m_preface = std::unique_ptr<preface_t>(new preface_t(m__io, this, m__root));
m_len_index = std::unique_ptr<compressed_integer_t>(new compressed_integer_t(m__io, this, m__root));
m__raw_index = m__io->read_bytes(len_index()->value());
m__io__raw_index = std::unique_ptr<kaitai::kstream>(new kaitai::kstream(m__raw_index));
m_index = std::unique_ptr<index_t>(new index_t(m__io__raw_index.get(), this, m__root));
m_num_signatures = std::unique_ptr<compressed_integer_t>(new compressed_integer_t(m__io, this, m__root));
{
std::unique_ptr<compressed_integer_t> _ = m_num_signatures;
if (!(_->value() == 0)) {
throw kaitai::validation_expr_error<std::unique_ptr<zchunk_t::compressed_integer_t>>(m_num_signatures, m__io, std::string("/types/header_without_lead/seq/3"));
}
}
}
zchunk_t::header_without_lead_t::~header_without_lead_t() {
_clean_up();
}
void zchunk_t::header_without_lead_t::_clean_up() {
}
zchunk_t::index_t::index_t(kaitai::kstream* p__io, zchunk_t::header_without_lead_t* p__parent, zchunk_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_chunk_checksum_type = nullptr;
m_num_chunks = nullptr;
m_dict_stream = nullptr;
m_len_dict = nullptr;
m_len_uncompressed_dict = nullptr;
m_chunks_metadata = nullptr;
f_num_data_chunks = false;
_read();
}
void zchunk_t::index_t::_read() {
m_chunk_checksum_type = std::unique_ptr<checksum_type_t>(new checksum_type_t(m__io, this, m__root));
m_num_chunks = std::unique_ptr<compressed_integer_t>(new compressed_integer_t(m__io, this, m__root));
{
std::unique_ptr<compressed_integer_t> _ = m_num_chunks;
if (!(_->value() >= 1)) {
throw kaitai::validation_expr_error<std::unique_ptr<zchunk_t::compressed_integer_t>>(m_num_chunks, m__io, std::string("/types/index/seq/1"));
}
}
n_dict_stream = true;
if (_parent()->preface()->has_data_streams()) {
n_dict_stream = false;
m_dict_stream = std::unique_ptr<compressed_integer_t>(new compressed_integer_t(m__io, this, m__root));
{
std::unique_ptr<compressed_integer_t> _ = m_dict_stream;
if (!(_->value() == 0)) {
throw kaitai::validation_expr_error<std::unique_ptr<zchunk_t::compressed_integer_t>>(m_dict_stream, m__io, std::string("/types/index/seq/2"));
}
}
}
m_dict_checksum = m__io->read_bytes(chunk_checksum_type()->len_checksum());
n_uncompressed_dict_checksum = true;
if (_parent()->preface()->has_uncompressed_source()) {
n_uncompressed_dict_checksum = false;
m_uncompressed_dict_checksum = m__io->read_bytes(chunk_checksum_type()->len_checksum());
}
m_len_dict = std::unique_ptr<compressed_integer_t>(new compressed_integer_t(m__io, this, m__root));
m_len_uncompressed_dict = std::unique_ptr<compressed_integer_t>(new compressed_integer_t(m__io, this, m__root));
m_chunks_metadata = std::unique_ptr<std::vector<std::unique_ptr<chunk_t>>>(new std::vector<std::unique_ptr<chunk_t>>());
const int l_chunks_metadata = num_data_chunks();
for (int i = 0; i < l_chunks_metadata; i++) {
m_chunks_metadata->push_back(std::move(std::unique_ptr<chunk_t>(new chunk_t(chunk_checksum_type()->len_checksum(), _parent()->preface()->has_data_streams(), _parent()->preface()->has_uncompressed_source(), m__io, this, m__root))));
}
}
zchunk_t::index_t::~index_t() {
_clean_up();
}
void zchunk_t::index_t::_clean_up() {
if (!n_dict_stream) {
}
if (!n_uncompressed_dict_checksum) {
}
}
int32_t zchunk_t::index_t::num_data_chunks() {
if (f_num_data_chunks)
return m_num_data_chunks;
f_num_data_chunks = true;
m_num_data_chunks = num_chunks()->value() - 1;
return m_num_data_chunks;
}
zchunk_t::optional_element_t::optional_element_t(kaitai::kstream* p__io, zchunk_t::preface_t* p__parent, zchunk_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_element_id = nullptr;
m_len_data = nullptr;
_read();
}
void zchunk_t::optional_element_t::_read() {
m_element_id = std::unique_ptr<compressed_integer_t>(new compressed_integer_t(m__io, this, m__root));
m_len_data = std::unique_ptr<compressed_integer_t>(new compressed_integer_t(m__io, this, m__root));
m_data = m__io->read_bytes(len_data()->value());
}
zchunk_t::optional_element_t::~optional_element_t() {
_clean_up();
}
void zchunk_t::optional_element_t::_clean_up() {
}
zchunk_t::preface_t::preface_t(kaitai::kstream* p__io, zchunk_t::header_without_lead_t* p__parent, zchunk_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_flags = nullptr;
m_compression_type_int = nullptr;
m_num_optional_elements = nullptr;
m_optional_elements = nullptr;
f_compression_type = false;
f_has_data_streams = false;
f_has_optional_elements = false;
f_has_uncompressed_source = false;
_read();
}
void zchunk_t::preface_t::_read() {
m_data_checksum = m__io->read_bytes(_root()->lead()->overall_checksum_type()->len_checksum());
m_flags = std::unique_ptr<compressed_integer_t>(new compressed_integer_t(m__io, this, m__root));
{
std::unique_ptr<compressed_integer_t> _ = m_flags;
if (!(_->value() <= 7)) {
throw kaitai::validation_expr_error<std::unique_ptr<zchunk_t::compressed_integer_t>>(m_flags, m__io, std::string("/types/preface/seq/1"));
}
}
m_compression_type_int = std::unique_ptr<compressed_integer_t>(new compressed_integer_t(m__io, this, m__root));
{
std::unique_ptr<compressed_integer_t> _ = m_compression_type_int;
if (!( ((_->value() == zchunk_t::COMPRESSION_TYPES_NONE) || (_->value() == zchunk_t::COMPRESSION_TYPES_ZSTD)) )) {
throw kaitai::validation_expr_error<std::unique_ptr<zchunk_t::compressed_integer_t>>(m_compression_type_int, m__io, std::string("/types/preface/seq/2"));
}
}
n_num_optional_elements = true;
if (has_optional_elements()) {
n_num_optional_elements = false;
m_num_optional_elements = std::unique_ptr<compressed_integer_t>(new compressed_integer_t(m__io, this, m__root));
{
std::unique_ptr<compressed_integer_t> _ = m_num_optional_elements;
if (!(_->value() >= 1)) {
throw kaitai::validation_expr_error<std::unique_ptr<zchunk_t::compressed_integer_t>>(m_num_optional_elements, m__io, std::string("/types/preface/seq/3"));
}
}
}
n_optional_elements = true;
if (has_optional_elements()) {
n_optional_elements = false;
m_optional_elements = std::unique_ptr<std::vector<std::unique_ptr<optional_element_t>>>(new std::vector<std::unique_ptr<optional_element_t>>());
const int l_optional_elements = num_optional_elements()->value();
for (int i = 0; i < l_optional_elements; i++) {
m_optional_elements->push_back(std::move(std::unique_ptr<optional_element_t>(new optional_element_t(m__io, this, m__root))));
}
}
}
zchunk_t::preface_t::~preface_t() {
_clean_up();
}
void zchunk_t::preface_t::_clean_up() {
if (!n_num_optional_elements) {
}
if (!n_optional_elements) {
}
}
zchunk_t::compression_types_t zchunk_t::preface_t::compression_type() {
if (f_compression_type)
return m_compression_type;
f_compression_type = true;
m_compression_type = static_cast<zchunk_t::compression_types_t>(compression_type_int()->value());
return m_compression_type;
}
bool zchunk_t::preface_t::has_data_streams() {
if (f_has_data_streams)
return m_has_data_streams;
f_has_data_streams = true;
m_has_data_streams = (flags()->value() & 1) != 0;
return m_has_data_streams;
}
bool zchunk_t::preface_t::has_optional_elements() {
if (f_has_optional_elements)
return m_has_optional_elements;
f_has_optional_elements = true;
m_has_optional_elements = (flags()->value() & 2) != 0;
return m_has_optional_elements;
}
bool zchunk_t::preface_t::has_uncompressed_source() {
if (f_has_uncompressed_source)
return m_has_uncompressed_source;
f_has_uncompressed_source = true;
m_has_uncompressed_source = (flags()->value() & 4) != 0;
return m_has_uncompressed_source;
}