Compressed Macintosh resource data, Apple `'dcmp' (2)` format: C++11/STL parsing library

Compressed resource data in 'dcmp' (2) format, as stored in compressed resources with header type 9 and decompressor ID 2.

The 'dcmp' (2) decompressor resource is included in the System file of System 7.0 and later. This compression format is used for a few compressed resources in System 7.0's files (such as the System file). This decompressor is also included with and used by some other Apple applications, such as ResEdit. (Note: ResEdit includes the 'dcmp' (2) resource, but none of its resources actually use this decompressor.)

This compression format is based on simple dictionary coding, where each byte in the compressed data expands to two bytes, based on a lookup table (either included in the compressed data or provided by the decompressor). An alternative "tagged" compression format is also supported, which allows using two-byte literals in addition to single-byte table references, at the cost of requiring an extra "tag" byte every 16 output bytes, to differentiate literals and table references.

Application

Mac OS

KS implementation details

License: MIT
Minimal Kaitai Struct required: 0.8

This page hosts a formal specification of Compressed Macintosh resource data, Apple `'dcmp' (2)` format using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

Usage

Runtime library

All parsing code for C++11/STL generated by Kaitai Struct depends on the C++/STL runtime library. You have to install it before you can parse data.

For C++, the easiest way is to clone the runtime library sources and build them along with your project.

Code

Using Kaitai Struct in C++/STL usually consists of 3 steps.

  1. We need to create an STL input stream (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.bin", std::ifstream::binary);
    
    #include <sstream>
    
    std::istringstream is(str);
    
    #include <sstream>
    
    const char buf[] = { ... };
    std::string str(buf, sizeof buf);
    std::istringstream is(str);
    
  2. We need to wrap our input stream into Kaitai stream:
    #include "kaitai/kaitaistream.h"
    
    kaitai::kstream ks(&is);
    
  3. And finally, we can invoke the parsing:
    dcmp_2_t data(&ks);
    

After that, one can get various attributes from the structure by invoking getter methods like:

data.custom_lookup_table() // => The custom lookup table to be used instead of the default lookup table.

data.header_parameters() // => The parsed decompressor-specific parameters from the compressed resource header.

C++11/STL source code to parse Compressed Macintosh resource data, Apple `'dcmp' (2)` format

dcmp_2.h

#pragma once

// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild

#include "kaitai/kaitaistruct.h"
#include <stdint.h>
#include <memory>
#include <vector>

#if KAITAI_STRUCT_VERSION < 9000L
#error "Incompatible Kaitai Struct C++/STL API: version 0.9 or later is required"
#endif

/**
 * Compressed resource data in `'dcmp' (2)` format,
 * as stored in compressed resources with header type `9` and decompressor ID `2`.
 * 
 * The `'dcmp' (2)` decompressor resource is included in the System file of System 7.0 and later.
 * This compression format is used for a few compressed resources in System 7.0's files
 * (such as the System file).
 * This decompressor is also included with and used by some other Apple applications,
 * such as ResEdit.
 * (Note: ResEdit includes the `'dcmp' (2)` resource,
 * but none of its resources actually use this decompressor.)
 * 
 * This compression format is based on simple dictionary coding,
 * where each byte in the compressed data expands to two bytes,
 * based on a lookup table
 * (either included in the compressed data or provided by the decompressor).
 * An alternative "tagged" compression format is also supported,
 * which allows using two-byte literals in addition to single-byte table references,
 * at the cost of requiring an extra "tag" byte every 16 output bytes,
 * to differentiate literals and table references.
 * \sa https://github.com/dgelessus/python-rsrcfork/blob/f891a6e/src/rsrcfork/compress/dcmp2.py Source
 */

class dcmp_2_t : public kaitai::kstruct {

public:
    class header_parameters_t;
    class untagged_data_t;
    class tagged_data_t;
    class bytes_with_io_t;

    dcmp_2_t(uint32_t p_len_decompressed, bytes_with_io_t* p_header_parameters_with_io, kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, dcmp_2_t* p__root = nullptr);

private:
    void _read();
    void _clean_up();

public:
    ~dcmp_2_t();

    /**
     * Decompressor-specific parameters for this compression format,
     * as stored in the compressed resource header.
     */

    class header_parameters_t : public kaitai::kstruct {

    public:
        class flags_t;

        header_parameters_t(kaitai::kstream* p__io, dcmp_2_t* p__parent = nullptr, dcmp_2_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~header_parameters_t();

        /**
         * Flags for the decompressor,
         * as stored in the decompressor-specific parameters.
         */

        class flags_t : public kaitai::kstruct {

        public:

            flags_t(kaitai::kstream* p__io, dcmp_2_t::header_parameters_t* p__parent = nullptr, dcmp_2_t* p__root = nullptr);

        private:
            void _read();
            void _clean_up();

        public:
            ~flags_t();

        private:
            bool f_as_int;
            uint8_t m_as_int;

        public:

            /**
             * The flags as a packed integer,
             * as they are stored in the data.
             */
            uint8_t as_int();

        private:
            uint64_t m_reserved;
            bool m_tagged;
            bool m_has_custom_lookup_table;
            dcmp_2_t* m__root;
            dcmp_2_t::header_parameters_t* m__parent;

        public:

            /**
             * These flags have no known usage or meaning and should always be zero.
             */
            uint64_t reserved() const { return m_reserved; }

            /**
             * Whether the "tagged" variant of this compression format should be used,
             * rather than the default "untagged" variant.
             */
            bool tagged() const { return m_tagged; }

            /**
             * Whether a custom lookup table is included before the compressed data,
             * which should be used instead of the default hardcoded lookup table.
             */
            bool has_custom_lookup_table() const { return m_has_custom_lookup_table; }
            dcmp_2_t* _root() const { return m__root; }
            dcmp_2_t::header_parameters_t* _parent() const { return m__parent; }
        };

    private:
        bool f_num_custom_lookup_table_entries;
        int32_t m_num_custom_lookup_table_entries;
        bool n_num_custom_lookup_table_entries;

    public:
        bool _is_null_num_custom_lookup_table_entries() { num_custom_lookup_table_entries(); return n_num_custom_lookup_table_entries; };

    private:

    public:

        /**
         * The number of entries in the custom lookup table.
         * Only used if a custom lookup table is present.
         */
        int32_t num_custom_lookup_table_entries();

    private:
        uint16_t m_unknown;
        uint8_t m_num_custom_lookup_table_entries_m1;
        std::unique_ptr<flags_t> m_flags;
        dcmp_2_t* m__root;
        dcmp_2_t* m__parent;

    public:

        /**
         * The meaning of this field is unknown.
         * It does not appear to have any effect on the format of the compressed data or the decompression process.
         * 
         * The value of this field is usually zero and otherwise a small integer (< 10).
         * For `'lpch'` resources,
         * the value is always nonzero,
         * and sometimes larger than usual.
         */
        uint16_t unknown() const { return m_unknown; }

        /**
         * The number of entries in the custom lookup table,
         * minus one.
         * 
         * If the default lookup table is used rather than a custom one,
         * this value is zero.
         */
        uint8_t num_custom_lookup_table_entries_m1() const { return m_num_custom_lookup_table_entries_m1; }

        /**
         * Various flags that affect the format of the compressed data and the decompression process.
         */
        flags_t* flags() const { return m_flags.get(); }
        dcmp_2_t* _root() const { return m__root; }
        dcmp_2_t* _parent() const { return m__parent; }
    };

    /**
     * Compressed data in the "untagged" variant of the format.
     */

    class untagged_data_t : public kaitai::kstruct {

    public:

        untagged_data_t(kaitai::kstream* p__io, dcmp_2_t* p__parent = nullptr, dcmp_2_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~untagged_data_t();

    private:
        std::unique_ptr<std::vector<uint8_t>> m_table_references;
        dcmp_2_t* m__root;
        dcmp_2_t* m__parent;

    public:

        /**
         * References into the lookup table.
         * Each reference is an integer that is expanded to two bytes by looking it up in the table.
         */
        std::vector<uint8_t>* table_references() const { return m_table_references.get(); }
        dcmp_2_t* _root() const { return m__root; }
        dcmp_2_t* _parent() const { return m__parent; }
    };

    /**
     * Compressed data in the "tagged" variant of the format.
     */

    class tagged_data_t : public kaitai::kstruct {

    public:
        class chunk_t;

        tagged_data_t(kaitai::kstream* p__io, dcmp_2_t* p__parent = nullptr, dcmp_2_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~tagged_data_t();

        /**
         * A single tagged chunk of compressed data.
         * 
         * Each chunk expands to 16 bytes of decompressed data.
         * In compressed form,
         * the chunks have a variable length
         * (between 9 and 17 bytes)
         * depending on the value of the tag byte.
         */

        class chunk_t : public kaitai::kstruct {

        public:

            chunk_t(kaitai::kstream* p__io, dcmp_2_t::tagged_data_t* p__parent = nullptr, dcmp_2_t* p__root = nullptr);

        private:
            void _read();
            void _clean_up();

        public:
            ~chunk_t();

        private:
            std::unique_ptr<std::vector<bool>> m_tag;
            std::unique_ptr<std::vector<uint8_t>> m_units;
            dcmp_2_t* m__root;
            dcmp_2_t::tagged_data_t* m__parent;

        public:

            /**
             * The bits of the tag byte control the format and meaning of the 8 compressed data units that follow the tag byte.
             */
            std::vector<bool>* tag() const { return m_tag.get(); }

            /**
             * The compressed data units in this chunk.
             * 
             * The format and meaning of each unit is controlled by the bit in the tag byte with the same index.
             * If the bit is 0 (false),
             * the unit is a pair of bytes,
             * which are literally copied to the decompressed data.
             * If the bit is 1 (true),
             * the unit is a reference into the lookup table,
             * an integer which is expanded to two bytes by looking it up in the table.
             */
            std::vector<uint8_t>* units() const { return m_units.get(); }
            dcmp_2_t* _root() const { return m__root; }
            dcmp_2_t::tagged_data_t* _parent() const { return m__parent; }
        };

    private:
        std::unique_ptr<std::vector<std::unique_ptr<chunk_t>>> m_chunks;
        dcmp_2_t* m__root;
        dcmp_2_t* m__parent;

    public:

        /**
         * The tagged chunks that make up the compressed data.
         */
        std::vector<std::unique_ptr<chunk_t>>* chunks() const { return m_chunks.get(); }
        dcmp_2_t* _root() const { return m__root; }
        dcmp_2_t* _parent() const { return m__parent; }
    };

private:
    bool f_header_parameters;
    std::unique_ptr<header_parameters_t> m_header_parameters;

public:

    /**
     * The parsed decompressor-specific parameters from the compressed resource header.
     */
    header_parameters_t* header_parameters();

private:
    bool f_is_len_decompressed_odd;
    bool m_is_len_decompressed_odd;

public:

    /**
     * Whether the length of the decompressed data is odd.
     * This affects the meaning of the last byte of the compressed data.
     */
    bool is_len_decompressed_odd();

private:
    bool f_default_lookup_table;
    std::unique_ptr<std::vector<std::string>> m_default_lookup_table;

public:

    /**
     * The default lookup table,
     * which is used if no custom lookup table is included with the compressed data.
     */
    std::vector<std::string>* default_lookup_table();

private:
    bool f_lookup_table;
    std::vector<std::string>* m_lookup_table;

public:

    /**
     * The lookup table to be used for this compressed data.
     */
    std::vector<std::string>* lookup_table();

private:
    std::unique_ptr<std::vector<std::string>> m_custom_lookup_table;
    bool n_custom_lookup_table;

public:
    bool _is_null_custom_lookup_table() { custom_lookup_table(); return n_custom_lookup_table; };

private:
    std::unique_ptr<kaitai::kstruct> m_data;
    std::string m_last_byte;
    bool n_last_byte;

public:
    bool _is_null_last_byte() { last_byte(); return n_last_byte; };

private:
    uint32_t m_len_decompressed;
    bytes_with_io_t* m_header_parameters_with_io;
    dcmp_2_t* m__root;
    kaitai::kstruct* m__parent;
    std::string m__raw_data;
    std::unique_ptr<kaitai::kstream> m__io__raw_data;

public:

    /**
     * The custom lookup table to be used instead of the default lookup table.
     */
    std::vector<std::string>* custom_lookup_table() const { return m_custom_lookup_table.get(); }

    /**
     * The compressed data.
     * The structure of the data varies depending on whether the "tagged" or "untagged" variant of the compression format is used.
     */
    kaitai::kstruct* data() const { return m_data.get(); }

    /**
     * The last byte of the decompressed data,
     * stored literally.
     * Only present if the decompressed data has an odd length.
     * 
     * This special case is necessary because the compressed data is otherwise always stored in two-byte groups,
     * either literally or as table references,
     * so otherwise there would be no way to compress odd-length resources using this format.
     */
    std::string last_byte() const { return m_last_byte; }

    /**
     * The length of the decompressed data in bytes,
     * from the compressed resource header.
     */
    uint32_t len_decompressed() const { return m_len_decompressed; }

    /**
     * The unparsed decompressor-specific parameters,
     * from the compressed resource header.
     */
    bytes_with_io_t* header_parameters_with_io() const { return m_header_parameters_with_io; }
    dcmp_2_t* _root() const { return m__root; }
    kaitai::kstruct* _parent() const { return m__parent; }
    std::string _raw_data() const { return m__raw_data; }
    kaitai::kstream* _io__raw_data() const { return m__io__raw_data.get(); }
};

dcmp_2.cpp

// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild

#include "dcmp_2.h"
#include "bytes_with_io.h"

dcmp_2_t::dcmp_2_t(uint32_t p_len_decompressed, bytes_with_io_t* p_header_parameters_with_io, kaitai::kstream* p__io, kaitai::kstruct* p__parent, dcmp_2_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = this;
    m_len_decompressed = p_len_decompressed;
    m_header_parameters_with_io = p_header_parameters_with_io;
    m_custom_lookup_table = nullptr;
    m__io__raw_data = nullptr;
    m_header_parameters = nullptr;
    f_header_parameters = false;
    f_is_len_decompressed_odd = false;
    f_default_lookup_table = false;
    f_lookup_table = false;
    _read();
}

void dcmp_2_t::_read() {
    n_custom_lookup_table = true;
    if (header_parameters()->flags()->has_custom_lookup_table()) {
        n_custom_lookup_table = false;
        m_custom_lookup_table = std::unique_ptr<std::vector<std::string>>(new std::vector<std::string>());
        const int l_custom_lookup_table = header_parameters()->num_custom_lookup_table_entries();
        for (int i = 0; i < l_custom_lookup_table; i++) {
            m_custom_lookup_table->push_back(std::move(m__io->read_bytes(2)));
        }
    }
    {
        bool on = header_parameters()->flags()->tagged();
        if (on == true) {
            m__raw_data = m__io->read_bytes(((_io()->size() - _io()->pos()) - ((is_len_decompressed_odd()) ? (1) : (0))));
            m__io__raw_data = std::unique_ptr<kaitai::kstream>(new kaitai::kstream(m__raw_data));
            m_data = std::unique_ptr<tagged_data_t>(new tagged_data_t(m__io__raw_data.get(), this, m__root));
        }
        else {
            m__raw_data = m__io->read_bytes(((_io()->size() - _io()->pos()) - ((is_len_decompressed_odd()) ? (1) : (0))));
            m__io__raw_data = std::unique_ptr<kaitai::kstream>(new kaitai::kstream(m__raw_data));
            m_data = std::unique_ptr<untagged_data_t>(new untagged_data_t(m__io__raw_data.get(), this, m__root));
        }
    }
    n_last_byte = true;
    if (is_len_decompressed_odd()) {
        n_last_byte = false;
        m_last_byte = m__io->read_bytes(1);
    }
}

dcmp_2_t::~dcmp_2_t() {
    _clean_up();
}

void dcmp_2_t::_clean_up() {
    if (!n_custom_lookup_table) {
    }
    if (!n_last_byte) {
    }
    if (f_header_parameters) {
    }
}

dcmp_2_t::header_parameters_t::header_parameters_t(kaitai::kstream* p__io, dcmp_2_t* p__parent, dcmp_2_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m_flags = nullptr;
    f_num_custom_lookup_table_entries = false;
    _read();
}

void dcmp_2_t::header_parameters_t::_read() {
    m_unknown = m__io->read_u2be();
    m_num_custom_lookup_table_entries_m1 = m__io->read_u1();
    m_flags = std::unique_ptr<flags_t>(new flags_t(m__io, this, m__root));
}

dcmp_2_t::header_parameters_t::~header_parameters_t() {
    _clean_up();
}

void dcmp_2_t::header_parameters_t::_clean_up() {
}

dcmp_2_t::header_parameters_t::flags_t::flags_t(kaitai::kstream* p__io, dcmp_2_t::header_parameters_t* p__parent, dcmp_2_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    f_as_int = false;
    _read();
}

void dcmp_2_t::header_parameters_t::flags_t::_read() {
    m_reserved = m__io->read_bits_int_be(6);
    m_tagged = m__io->read_bits_int_be(1);
    m_has_custom_lookup_table = m__io->read_bits_int_be(1);
}

dcmp_2_t::header_parameters_t::flags_t::~flags_t() {
    _clean_up();
}

void dcmp_2_t::header_parameters_t::flags_t::_clean_up() {
    if (f_as_int) {
    }
}

uint8_t dcmp_2_t::header_parameters_t::flags_t::as_int() {
    if (f_as_int)
        return m_as_int;
    std::streampos _pos = m__io->pos();
    m__io->seek(0);
    m_as_int = m__io->read_u1();
    m__io->seek(_pos);
    f_as_int = true;
    return m_as_int;
}

int32_t dcmp_2_t::header_parameters_t::num_custom_lookup_table_entries() {
    if (f_num_custom_lookup_table_entries)
        return m_num_custom_lookup_table_entries;
    n_num_custom_lookup_table_entries = true;
    if (flags()->has_custom_lookup_table()) {
        n_num_custom_lookup_table_entries = false;
        m_num_custom_lookup_table_entries = (num_custom_lookup_table_entries_m1() + 1);
    }
    f_num_custom_lookup_table_entries = true;
    return m_num_custom_lookup_table_entries;
}

dcmp_2_t::untagged_data_t::untagged_data_t(kaitai::kstream* p__io, dcmp_2_t* p__parent, dcmp_2_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m_table_references = nullptr;
    _read();
}

void dcmp_2_t::untagged_data_t::_read() {
    m_table_references = std::unique_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>());
    {
        int i = 0;
        while (!m__io->is_eof()) {
            m_table_references->push_back(std::move(m__io->read_u1()));
            i++;
        }
    }
}

dcmp_2_t::untagged_data_t::~untagged_data_t() {
    _clean_up();
}

void dcmp_2_t::untagged_data_t::_clean_up() {
}

dcmp_2_t::tagged_data_t::tagged_data_t(kaitai::kstream* p__io, dcmp_2_t* p__parent, dcmp_2_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m_chunks = nullptr;
    _read();
}

void dcmp_2_t::tagged_data_t::_read() {
    m_chunks = std::unique_ptr<std::vector<std::unique_ptr<chunk_t>>>(new std::vector<std::unique_ptr<chunk_t>>());
    {
        int i = 0;
        while (!m__io->is_eof()) {
            m_chunks->push_back(std::move(std::unique_ptr<chunk_t>(new chunk_t(m__io, this, m__root))));
            i++;
        }
    }
}

dcmp_2_t::tagged_data_t::~tagged_data_t() {
    _clean_up();
}

void dcmp_2_t::tagged_data_t::_clean_up() {
}

dcmp_2_t::tagged_data_t::chunk_t::chunk_t(kaitai::kstream* p__io, dcmp_2_t::tagged_data_t* p__parent, dcmp_2_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m_tag = nullptr;
    m_units = nullptr;
    _read();
}

void dcmp_2_t::tagged_data_t::chunk_t::_read() {
    m_tag = std::unique_ptr<std::vector<bool>>(new std::vector<bool>());
    const int l_tag = 8;
    for (int i = 0; i < l_tag; i++) {
        m_tag->push_back(std::move(m__io->read_bits_int_be(1)));
    }
    m__io->align_to_byte();
    m__raw_units = std::unique_ptr<std::vector<std::string>>(new std::vector<std::string>());
    m__io__raw_units = std::unique_ptr<std::vector<std::unique_ptr<kaitai::kstream>>>(new std::vector<std::unique_ptr<kaitai::kstream>>());
    m_units = std::unique_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>());
    {
        int i = 0;
        uint8_t _;
        do {
            {
                bool on = tag()->at(i);
                if (on == true) {
                    _ = m__io->read_u1();
                    m_units->push_back(_);
                }
                else {
                    _ = m__io->read_bytes(((tag()->at(i)) ? (1) : (2)));
                    m__raw_units->push_back(_);
                }
            }
            i++;
        } while (!( ((i >= 7) || (_io()->is_eof())) ));
    }
}

dcmp_2_t::tagged_data_t::chunk_t::~chunk_t() {
    _clean_up();
}

void dcmp_2_t::tagged_data_t::chunk_t::_clean_up() {
}

dcmp_2_t::header_parameters_t* dcmp_2_t::header_parameters() {
    if (f_header_parameters)
        return m_header_parameters.get();
    kaitai::kstream *io = header_parameters_with_io()->_io();
    std::streampos _pos = io->pos();
    io->seek(0);
    m_header_parameters = std::unique_ptr<header_parameters_t>(new header_parameters_t(io, this, m__root));
    io->seek(_pos);
    f_header_parameters = true;
    return m_header_parameters.get();
}

bool dcmp_2_t::is_len_decompressed_odd() {
    if (f_is_len_decompressed_odd)
        return m_is_len_decompressed_odd;
    m_is_len_decompressed_odd = kaitai::kstream::mod(len_decompressed(), 2) != 0;
    f_is_len_decompressed_odd = true;
    return m_is_len_decompressed_odd;
}

std::vector<std::string>* dcmp_2_t::default_lookup_table() {
    if (f_default_lookup_table)
        return m_default_lookup_table.get();
    m_default_lookup_table = std::unique_ptr<std::vector<std::string>>(new std::vector<std::string>{std::string("\x00\x00", 2), std::string("\x00\x08", 2), std::string("\x4E\xBA", 2), std::string("\x20\x6E", 2), std::string("\x4E\x75", 2), std::string("\x00\x0C", 2), std::string("\x00\x04", 2), std::string("\x70\x00", 2), std::string("\x00\x10", 2), std::string("\x00\x02", 2), std::string("\x48\x6E", 2), std::string("\xFF\xFC", 2), std::string("\x60\x00", 2), std::string("\x00\x01", 2), std::string("\x48\xE7", 2), std::string("\x2F\x2E", 2), std::string("\x4E\x56", 2), std::string("\x00\x06", 2), std::string("\x4E\x5E", 2), std::string("\x2F\x00", 2), std::string("\x61\x00", 2), std::string("\xFF\xF8", 2), std::string("\x2F\x0B", 2), std::string("\xFF\xFF", 2), std::string("\x00\x14", 2), std::string("\x00\x0A", 2), std::string("\x00\x18", 2), std::string("\x20\x5F", 2), std::string("\x00\x0E", 2), std::string("\x20\x50", 2), std::string("\x3F\x3C", 2), std::string("\xFF\xF4", 2), std::string("\x4C\xEE", 2), std::string("\x30\x2E", 2), std::string("\x67\x00", 2), std::string("\x4C\xDF", 2), std::string("\x26\x6E", 2), std::string("\x00\x12", 2), std::string("\x00\x1C", 2), std::string("\x42\x67", 2), std::string("\xFF\xF0", 2), std::string("\x30\x3C", 2), std::string("\x2F\x0C", 2), std::string("\x00\x03", 2), std::string("\x4E\xD0", 2), std::string("\x00\x20", 2), std::string("\x70\x01", 2), std::string("\x00\x16", 2), std::string("\x2D\x40", 2), std::string("\x48\xC0", 2), std::string("\x20\x78", 2), std::string("\x72\x00", 2), std::string("\x58\x8F", 2), std::string("\x66\x00", 2), std::string("\x4F\xEF", 2), std::string("\x42\xA7", 2), std::string("\x67\x06", 2), std::string("\xFF\xFA", 2), std::string("\x55\x8F", 2), std::string("\x28\x6E", 2), std::string("\x3F\x00", 2), std::string("\xFF\xFE", 2), std::string("\x2F\x3C", 2), std::string("\x67\x04", 2), std::string("\x59\x8F", 2), std::string("\x20\x6B", 2), std::string("\x00\x24", 2), std::string("\x20\x1F", 2), std::string("\x41\xFA", 2), std::string("\x81\xE1", 2), std::string("\x66\x04", 2), std::string("\x67\x08", 2), std::string("\x00\x1A", 2), std::string("\x4E\xB9", 2), std::string("\x50\x8F", 2), std::string("\x20\x2E", 2), std::string("\x00\x07", 2), std::string("\x4E\xB0", 2), std::string("\xFF\xF2", 2), std::string("\x3D\x40", 2), std::string("\x00\x1E", 2), std::string("\x20\x68", 2), std::string("\x66\x06", 2), std::string("\xFF\xF6", 2), std::string("\x4E\xF9", 2), std::string("\x08\x00", 2), std::string("\x0C\x40", 2), std::string("\x3D\x7C", 2), std::string("\xFF\xEC", 2), std::string("\x00\x05", 2), std::string("\x20\x3C", 2), std::string("\xFF\xE8", 2), std::string("\xDE\xFC", 2), std::string("\x4A\x2E", 2), std::string("\x00\x30", 2), std::string("\x00\x28", 2), std::string("\x2F\x08", 2), std::string("\x20\x0B", 2), std::string("\x60\x02", 2), std::string("\x42\x6E", 2), std::string("\x2D\x48", 2), std::string("\x20\x53", 2), std::string("\x20\x40", 2), std::string("\x18\x00", 2), std::string("\x60\x04", 2), std::string("\x41\xEE", 2), std::string("\x2F\x28", 2), std::string("\x2F\x01", 2), std::string("\x67\x0A", 2), std::string("\x48\x40", 2), std::string("\x20\x07", 2), std::string("\x66\x08", 2), std::string("\x01\x18", 2), std::string("\x2F\x07", 2), std::string("\x30\x28", 2), std::string("\x3F\x2E", 2), std::string("\x30\x2B", 2), std::string("\x22\x6E", 2), std::string("\x2F\x2B", 2), std::string("\x00\x2C", 2), std::string("\x67\x0C", 2), std::string("\x22\x5F", 2), std::string("\x60\x06", 2), std::string("\x00\xFF", 2), std::string("\x30\x07", 2), std::string("\xFF\xEE", 2), std::string("\x53\x40", 2), std::string("\x00\x40", 2), std::string("\xFF\xE4", 2), std::string("\x4A\x40", 2), std::string("\x66\x0A", 2), std::string("\x00\x0F", 2), std::string("\x4E\xAD", 2), std::string("\x70\xFF", 2), std::string("\x22\xD8", 2), std::string("\x48\x6B", 2), std::string("\x00\x22", 2), std::string("\x20\x4B", 2), std::string("\x67\x0E", 2), std::string("\x4A\xAE", 2), std::string("\x4E\x90", 2), std::string("\xFF\xE0", 2), std::string("\xFF\xC0", 2), std::string("\x00\x2A", 2), std::string("\x27\x40", 2), std::string("\x67\x02", 2), std::string("\x51\xC8", 2), std::string("\x02\xB6", 2), std::string("\x48\x7A", 2), std::string("\x22\x78", 2), std::string("\xB0\x6E", 2), std::string("\xFF\xE6", 2), std::string("\x00\x09", 2), std::string("\x32\x2E", 2), std::string("\x3E\x00", 2), std::string("\x48\x41", 2), std::string("\xFF\xEA", 2), std::string("\x43\xEE", 2), std::string("\x4E\x71", 2), std::string("\x74\x00", 2), std::string("\x2F\x2C", 2), std::string("\x20\x6C", 2), std::string("\x00\x3C", 2), std::string("\x00\x26", 2), std::string("\x00\x50", 2), std::string("\x18\x80", 2), std::string("\x30\x1F", 2), std::string("\x22\x00", 2), std::string("\x66\x0C", 2), std::string("\xFF\xDA", 2), std::string("\x00\x38", 2), std::string("\x66\x02", 2), std::string("\x30\x2C", 2), std::string("\x20\x0C", 2), std::string("\x2D\x6E", 2), std::string("\x42\x40", 2), std::string("\xFF\xE2", 2), std::string("\xA9\xF0", 2), std::string("\xFF\x00", 2), std::string("\x37\x7C", 2), std::string("\xE5\x80", 2), std::string("\xFF\xDC", 2), std::string("\x48\x68", 2), std::string("\x59\x4F", 2), std::string("\x00\x34", 2), std::string("\x3E\x1F", 2), std::string("\x60\x08", 2), std::string("\x2F\x06", 2), std::string("\xFF\xDE", 2), std::string("\x60\x0A", 2), std::string("\x70\x02", 2), std::string("\x00\x32", 2), std::string("\xFF\xCC", 2), std::string("\x00\x80", 2), std::string("\x22\x51", 2), std::string("\x10\x1F", 2), std::string("\x31\x7C", 2), std::string("\xA0\x29", 2), std::string("\xFF\xD8", 2), std::string("\x52\x40", 2), std::string("\x01\x00", 2), std::string("\x67\x10", 2), std::string("\xA0\x23", 2), std::string("\xFF\xCE", 2), std::string("\xFF\xD4", 2), std::string("\x20\x06", 2), std::string("\x48\x78", 2), std::string("\x00\x2E", 2), std::string("\x50\x4F", 2), std::string("\x43\xFA", 2), std::string("\x67\x12", 2), std::string("\x76\x00", 2), std::string("\x41\xE8", 2), std::string("\x4A\x6E", 2), std::string("\x20\xD9", 2), std::string("\x00\x5A", 2), std::string("\x7F\xFF", 2), std::string("\x51\xCA", 2), std::string("\x00\x5C", 2), std::string("\x2E\x00", 2), std::string("\x02\x40", 2), std::string("\x48\xC7", 2), std::string("\x67\x14", 2), std::string("\x0C\x80", 2), std::string("\x2E\x9F", 2), std::string("\xFF\xD6", 2), std::string("\x80\x00", 2), std::string("\x10\x00", 2), std::string("\x48\x42", 2), std::string("\x4A\x6B", 2), std::string("\xFF\xD2", 2), std::string("\x00\x48", 2), std::string("\x4A\x47", 2), std::string("\x4E\xD1", 2), std::string("\x20\x6F", 2), std::string("\x00\x41", 2), std::string("\x60\x0C", 2), std::string("\x2A\x78", 2), std::string("\x42\x2E", 2), std::string("\x32\x00", 2), std::string("\x65\x74", 2), std::string("\x67\x16", 2), std::string("\x00\x44", 2), std::string("\x48\x6D", 2), std::string("\x20\x08", 2), std::string("\x48\x6C", 2), std::string("\x0B\x7C", 2), std::string("\x26\x40", 2), std::string("\x04\x00", 2), std::string("\x00\x68", 2), std::string("\x20\x6D", 2), std::string("\x00\x0D", 2), std::string("\x2A\x40", 2), std::string("\x00\x0B", 2), std::string("\x00\x3E", 2), std::string("\x02\x20", 2)});
    f_default_lookup_table = true;
    return m_default_lookup_table.get();
}

std::vector<std::string>* dcmp_2_t::lookup_table() {
    if (f_lookup_table)
        return m_lookup_table;
    m_lookup_table = ((header_parameters()->flags()->has_custom_lookup_table()) ? (custom_lookup_table()) : (default_lookup_table()));
    f_lookup_table = true;
    return m_lookup_table;
}