GNU gettext is a popular solution in free/open source software world to do i18n/l10n of software, by providing translated strings that will substitute strings in original language (typically, English).
gettext .mo is a binary database format which stores these string translation pairs in an efficient binary format, ready to be used by gettext-enabled software. .mo format is a result of compilation of text-based .po files using msgfmt utility. The reverse conversion (.mo -> .po) is also possible using msgunfmt decompiler utility.
This page hosts a formal specification of gettext binary database using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing 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.
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.mo", 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);
gettext_mo_t data(&ks);
After that, one can get various attributes from the structure by invoking getter methods like:
data.signature() // => get signature
#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
/**
* [GNU gettext](https://www.gnu.org/software/gettext/) is a popular
* solution in free/open source software world to do i18n/l10n of
* software, by providing translated strings that will substitute
* strings in original language (typically, English).
*
* gettext .mo is a binary database format which stores these string
* translation pairs in an efficient binary format, ready to be used by
* gettext-enabled software. .mo format is a result of compilation of
* text-based .po files using
* [msgfmt](https://www.gnu.org/software/gettext/manual/html_node/msgfmt-Invocation.html#msgfmt-Invocation)
* utility. The reverse conversion (.mo -> .po) is also possible using
* [msgunfmt](https://www.gnu.org/software/gettext/manual/html_node/msgunfmt-Invocation.html#msgunfmt-Invocation)
* decompiler utility.
* \sa https://gitlab.com/worr/libintl Source
*/
class gettext_mo_t : public kaitai::kstruct {
public:
class hash_lookup_iteration_t;
class lookup_iteration_t;
class hashtable_lookup_t;
class mo_t;
gettext_mo_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, gettext_mo_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~gettext_mo_t();
class hash_lookup_iteration_t : public kaitai::kstruct {
public:
hash_lookup_iteration_t(uint32_t p_idx, uint32_t p_collision_step, kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, gettext_mo_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~hash_lookup_iteration_t();
private:
bool f_original;
std::string m_original;
public:
std::string original();
private:
bool f_translation;
std::string m_translation;
public:
std::string translation();
private:
bool f_next_idx;
int32_t m_next_idx;
public:
int32_t next_idx();
private:
bool f_next;
std::unique_ptr<hash_lookup_iteration_t> m_next;
public:
hash_lookup_iteration_t* next();
private:
uint32_t m_idx;
uint32_t m_collision_step;
gettext_mo_t* m__root;
kaitai::kstruct* m__parent;
public:
uint32_t idx() const { return m_idx; }
uint32_t collision_step() const { return m_collision_step; }
gettext_mo_t* _root() const { return m__root; }
kaitai::kstruct* _parent() const { return m__parent; }
};
class lookup_iteration_t : public kaitai::kstruct {
public:
lookup_iteration_t(hash_lookup_iteration_t* p_current, std::string p_query, kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, gettext_mo_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~lookup_iteration_t();
private:
bool f_found;
bool m_found;
public:
bool found();
private:
bool f_next;
std::unique_ptr<lookup_iteration_t> m_next;
bool n_next;
public:
bool _is_null_next() { next(); return n_next; };
private:
public:
lookup_iteration_t* next();
private:
hash_lookup_iteration_t* m_current;
std::string m_query;
gettext_mo_t* m__root;
kaitai::kstruct* m__parent;
public:
hash_lookup_iteration_t* current() const { return m_current; }
std::string query() const { return m_query; }
gettext_mo_t* _root() const { return m__root; }
kaitai::kstruct* _parent() const { return m__parent; }
};
/**
* def lookup(s:str, t:gettext_mo.GettextMo):
* try:
* l=gettext_mo.GettextMo.HashtableLookup(s, string_hash(s), t._io, _parent=t, _root=t)
* e=l.entry
* while(not e.found):
* e=e.next
* return e.current
* except:
* raise Exception("Not found "+s+" in the hashtable!")
*
* lookup(t.mo.originals[145].str, t)
* \sa https://gitlab.com/worr/libintl/raw/master/src/lib/libintl/gettext.c Source
*/
class hashtable_lookup_t : public kaitai::kstruct {
public:
hashtable_lookup_t(std::string p_query, uint32_t p_hash, kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, gettext_mo_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~hashtable_lookup_t();
private:
bool f_collision_step;
int32_t m_collision_step;
public:
int32_t collision_step();
private:
bool f_idx;
int32_t m_idx;
public:
int32_t idx();
private:
bool f_hash_lookup_iteration;
std::unique_ptr<hash_lookup_iteration_t> m_hash_lookup_iteration;
public:
hash_lookup_iteration_t* hash_lookup_iteration();
private:
bool f_entry;
std::unique_ptr<lookup_iteration_t> m_entry;
public:
lookup_iteration_t* entry();
private:
std::string m_query;
uint32_t m_hash;
gettext_mo_t* m__root;
kaitai::kstruct* m__parent;
public:
std::string query() const { return m_query; }
/**
* def string_hash(s):
* s=s.encode("utf-8")
* h = 0
* for i in range(len(s)):
* h = h << 4
* h += s[i]
* tmp = h & 0xF0000000
* if tmp != 0:
* h ^= tmp
* h ^= tmp >> 24
* return h
* \sa https://gitlab.com/worr/libintl/raw/master/src/lib/libintl/strhash.c Source
*/
uint32_t hash() const { return m_hash; }
gettext_mo_t* _root() const { return m__root; }
kaitai::kstruct* _parent() const { return m__parent; }
};
class mo_t : public kaitai::kstruct {
public:
class version_t;
class hashtable_item_t;
class descriptor_t;
mo_t(kaitai::kstream* p__io, gettext_mo_t* p__parent = nullptr, gettext_mo_t* p__root = nullptr);
private:
int m__is_le;
public:
private:
void _read();
void _read_le();
void _read_be();
void _clean_up();
public:
~mo_t();
class version_t : public kaitai::kstruct {
public:
version_t(kaitai::kstream* p__io, gettext_mo_t::mo_t* p__parent = nullptr, gettext_mo_t* p__root = nullptr, int p_is_le = -1);
private:
int m__is_le;
public:
private:
void _read();
void _read_le();
void _read_be();
void _clean_up();
public:
~version_t();
private:
bool f_major;
int32_t m_major;
public:
int32_t major();
private:
bool f_minor;
int32_t m_minor;
public:
int32_t minor();
private:
uint32_t m_version_raw;
gettext_mo_t* m__root;
gettext_mo_t::mo_t* m__parent;
public:
uint32_t version_raw() const { return m_version_raw; }
gettext_mo_t* _root() const { return m__root; }
gettext_mo_t::mo_t* _parent() const { return m__parent; }
};
class hashtable_item_t : public kaitai::kstruct {
public:
hashtable_item_t(kaitai::kstream* p__io, gettext_mo_t::mo_t* p__parent = nullptr, gettext_mo_t* p__root = nullptr, int p_is_le = -1);
private:
int m__is_le;
public:
private:
void _read();
void _read_le();
void _read_be();
void _clean_up();
public:
~hashtable_item_t();
private:
bool f_mask;
int32_t m_mask;
public:
int32_t mask();
private:
bool f_val_1;
int32_t m_val_1;
bool n_val_1;
public:
bool _is_null_val_1() { val_1(); return n_val_1; };
private:
public:
int32_t val_1();
private:
bool f_is_system_dependent;
bool m_is_system_dependent;
bool n_is_system_dependent;
public:
bool _is_null_is_system_dependent() { is_system_dependent(); return n_is_system_dependent; };
private:
public:
bool is_system_dependent();
private:
bool f_val;
int32_t m_val;
bool n_val;
public:
bool _is_null_val() { val(); return n_val; };
private:
public:
int32_t val();
private:
uint32_t m_raw_val;
gettext_mo_t* m__root;
gettext_mo_t::mo_t* m__parent;
public:
uint32_t raw_val() const { return m_raw_val; }
gettext_mo_t* _root() const { return m__root; }
gettext_mo_t::mo_t* _parent() const { return m__parent; }
};
class descriptor_t : public kaitai::kstruct {
public:
descriptor_t(kaitai::kstream* p__io, gettext_mo_t::mo_t* p__parent = nullptr, gettext_mo_t* p__root = nullptr, int p_is_le = -1);
private:
int m__is_le;
public:
private:
void _read();
void _read_le();
void _read_be();
void _clean_up();
public:
~descriptor_t();
private:
bool f_str;
std::string m_str;
public:
std::string str();
private:
uint32_t m_len_str;
uint32_t m_ofs_str;
gettext_mo_t* m__root;
gettext_mo_t::mo_t* m__parent;
public:
uint32_t len_str() const { return m_len_str; }
uint32_t ofs_str() const { return m_ofs_str; }
gettext_mo_t* _root() const { return m__root; }
gettext_mo_t::mo_t* _parent() const { return m__parent; }
};
private:
bool f_originals;
std::unique_ptr<std::vector<std::unique_ptr<descriptor_t>>> m_originals;
public:
std::vector<std::unique_ptr<descriptor_t>>* originals();
private:
bool f_translations;
std::unique_ptr<std::vector<std::unique_ptr<descriptor_t>>> m_translations;
public:
std::vector<std::unique_ptr<descriptor_t>>* translations();
private:
bool f_hashtable_items;
std::unique_ptr<std::vector<std::unique_ptr<hashtable_item_t>>> m_hashtable_items;
bool n_hashtable_items;
public:
bool _is_null_hashtable_items() { hashtable_items(); return n_hashtable_items; };
private:
public:
std::vector<std::unique_ptr<hashtable_item_t>>* hashtable_items();
private:
std::unique_ptr<version_t> m_version;
uint32_t m_num_translations;
uint32_t m_ofs_originals;
uint32_t m_ofs_translations;
uint32_t m_num_hashtable_items;
uint32_t m_ofs_hashtable_items;
gettext_mo_t* m__root;
gettext_mo_t* m__parent;
public:
version_t* version() const { return m_version.get(); }
uint32_t num_translations() const { return m_num_translations; }
uint32_t ofs_originals() const { return m_ofs_originals; }
uint32_t ofs_translations() const { return m_ofs_translations; }
uint32_t num_hashtable_items() const { return m_num_hashtable_items; }
uint32_t ofs_hashtable_items() const { return m_ofs_hashtable_items; }
gettext_mo_t* _root() const { return m__root; }
gettext_mo_t* _parent() const { return m__parent; }
};
private:
std::string m_signature;
std::unique_ptr<mo_t> m_mo;
gettext_mo_t* m__root;
kaitai::kstruct* m__parent;
public:
std::string signature() const { return m_signature; }
mo_t* mo() const { return m_mo.get(); }
gettext_mo_t* _root() const { return m__root; }
kaitai::kstruct* _parent() const { return m__parent; }
};
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
#include "gettext_mo.h"
#include "kaitai/exceptions.h"
gettext_mo_t::gettext_mo_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, gettext_mo_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = this;
m_mo = nullptr;
_read();
}
void gettext_mo_t::_read() {
m_signature = m__io->read_bytes(4);
m_mo = std::unique_ptr<mo_t>(new mo_t(m__io, this, m__root));
}
gettext_mo_t::~gettext_mo_t() {
_clean_up();
}
void gettext_mo_t::_clean_up() {
}
gettext_mo_t::hash_lookup_iteration_t::hash_lookup_iteration_t(uint32_t p_idx, uint32_t p_collision_step, kaitai::kstream* p__io, kaitai::kstruct* p__parent, gettext_mo_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_idx = p_idx;
m_collision_step = p_collision_step;
m_next = nullptr;
f_original = false;
f_translation = false;
f_next_idx = false;
f_next = false;
_read();
}
void gettext_mo_t::hash_lookup_iteration_t::_read() {
}
gettext_mo_t::hash_lookup_iteration_t::~hash_lookup_iteration_t() {
_clean_up();
}
void gettext_mo_t::hash_lookup_iteration_t::_clean_up() {
if (f_next) {
}
}
std::string gettext_mo_t::hash_lookup_iteration_t::original() {
if (f_original)
return m_original;
m_original = _root()->mo()->originals()->at(idx())->str();
f_original = true;
return m_original;
}
std::string gettext_mo_t::hash_lookup_iteration_t::translation() {
if (f_translation)
return m_translation;
m_translation = _root()->mo()->translations()->at(idx())->str();
f_translation = true;
return m_translation;
}
int32_t gettext_mo_t::hash_lookup_iteration_t::next_idx() {
if (f_next_idx)
return m_next_idx;
m_next_idx = ((idx() + collision_step()) - ((idx() >= (_root()->mo()->num_hashtable_items() - collision_step())) ? (_root()->mo()->num_hashtable_items()) : (0)));
f_next_idx = true;
return m_next_idx;
}
gettext_mo_t::hash_lookup_iteration_t* gettext_mo_t::hash_lookup_iteration_t::next() {
if (f_next)
return m_next.get();
std::streampos _pos = m__io->pos();
m__io->seek(0);
m_next = std::unique_ptr<hash_lookup_iteration_t>(new hash_lookup_iteration_t(_root()->mo()->hashtable_items()->at(next_idx())->val(), collision_step(), m__io, this, m__root));
m__io->seek(_pos);
f_next = true;
return m_next.get();
}
gettext_mo_t::lookup_iteration_t::lookup_iteration_t(hash_lookup_iteration_t* p_current, std::string p_query, kaitai::kstream* p__io, kaitai::kstruct* p__parent, gettext_mo_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_current = p_current;
m_query = p_query;
m_next = nullptr;
f_found = false;
f_next = false;
_read();
}
void gettext_mo_t::lookup_iteration_t::_read() {
}
gettext_mo_t::lookup_iteration_t::~lookup_iteration_t() {
_clean_up();
}
void gettext_mo_t::lookup_iteration_t::_clean_up() {
if (f_next && !n_next) {
}
}
bool gettext_mo_t::lookup_iteration_t::found() {
if (f_found)
return m_found;
m_found = query() == (current()->original());
f_found = true;
return m_found;
}
gettext_mo_t::lookup_iteration_t* gettext_mo_t::lookup_iteration_t::next() {
if (f_next)
return m_next.get();
n_next = true;
if (!(found())) {
n_next = false;
std::streampos _pos = m__io->pos();
m__io->seek(0);
m_next = std::unique_ptr<lookup_iteration_t>(new lookup_iteration_t(current()->next(), query(), m__io, this, m__root));
m__io->seek(_pos);
f_next = true;
}
return m_next.get();
}
gettext_mo_t::hashtable_lookup_t::hashtable_lookup_t(std::string p_query, uint32_t p_hash, kaitai::kstream* p__io, kaitai::kstruct* p__parent, gettext_mo_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_query = p_query;
m_hash = p_hash;
m_hash_lookup_iteration = nullptr;
m_entry = nullptr;
f_collision_step = false;
f_idx = false;
f_hash_lookup_iteration = false;
f_entry = false;
_read();
}
void gettext_mo_t::hashtable_lookup_t::_read() {
}
gettext_mo_t::hashtable_lookup_t::~hashtable_lookup_t() {
_clean_up();
}
void gettext_mo_t::hashtable_lookup_t::_clean_up() {
if (f_hash_lookup_iteration) {
}
if (f_entry) {
}
}
int32_t gettext_mo_t::hashtable_lookup_t::collision_step() {
if (f_collision_step)
return m_collision_step;
m_collision_step = (kaitai::kstream::mod(hash(), (_root()->mo()->num_hashtable_items() - 2)) + 1);
f_collision_step = true;
return m_collision_step;
}
int32_t gettext_mo_t::hashtable_lookup_t::idx() {
if (f_idx)
return m_idx;
m_idx = kaitai::kstream::mod(hash(), _root()->mo()->num_hashtable_items());
f_idx = true;
return m_idx;
}
gettext_mo_t::hash_lookup_iteration_t* gettext_mo_t::hashtable_lookup_t::hash_lookup_iteration() {
if (f_hash_lookup_iteration)
return m_hash_lookup_iteration.get();
std::streampos _pos = m__io->pos();
m__io->seek(0);
m_hash_lookup_iteration = std::unique_ptr<hash_lookup_iteration_t>(new hash_lookup_iteration_t(_root()->mo()->hashtable_items()->at(idx())->val(), collision_step(), m__io, this, m__root));
m__io->seek(_pos);
f_hash_lookup_iteration = true;
return m_hash_lookup_iteration.get();
}
gettext_mo_t::lookup_iteration_t* gettext_mo_t::hashtable_lookup_t::entry() {
if (f_entry)
return m_entry.get();
std::streampos _pos = m__io->pos();
m__io->seek(0);
m_entry = std::unique_ptr<lookup_iteration_t>(new lookup_iteration_t(hash_lookup_iteration(), query(), m__io, this, m__root));
m__io->seek(_pos);
f_entry = true;
return m_entry.get();
}
gettext_mo_t::mo_t::mo_t(kaitai::kstream* p__io, gettext_mo_t* p__parent, gettext_mo_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m__is_le = -1;
m_version = nullptr;
m_originals = nullptr;
m_translations = nullptr;
m_hashtable_items = nullptr;
f_originals = false;
f_translations = false;
f_hashtable_items = false;
_read();
}
void gettext_mo_t::mo_t::_read() {
{
std::string on = _root()->signature();
if (on == std::string("\xDE\x12\x04\x95", 4)) {
m__is_le = true;
}
else if (on == std::string("\x95\x04\x12\xDE", 4)) {
m__is_le = false;
}
}
if (m__is_le == -1) {
throw kaitai::undecided_endianness_error("/types/mo");
} else if (m__is_le == 1) {
_read_le();
} else {
_read_be();
}
}
void gettext_mo_t::mo_t::_read_le() {
m_version = std::unique_ptr<version_t>(new version_t(m__io, this, m__root, m__is_le));
m_num_translations = m__io->read_u4le();
m_ofs_originals = m__io->read_u4le();
m_ofs_translations = m__io->read_u4le();
m_num_hashtable_items = m__io->read_u4le();
m_ofs_hashtable_items = m__io->read_u4le();
}
void gettext_mo_t::mo_t::_read_be() {
m_version = std::unique_ptr<version_t>(new version_t(m__io, this, m__root, m__is_le));
m_num_translations = m__io->read_u4be();
m_ofs_originals = m__io->read_u4be();
m_ofs_translations = m__io->read_u4be();
m_num_hashtable_items = m__io->read_u4be();
m_ofs_hashtable_items = m__io->read_u4be();
}
gettext_mo_t::mo_t::~mo_t() {
_clean_up();
}
void gettext_mo_t::mo_t::_clean_up() {
if (f_originals) {
}
if (f_translations) {
}
if (f_hashtable_items && !n_hashtable_items) {
}
}
gettext_mo_t::mo_t::version_t::version_t(kaitai::kstream* p__io, gettext_mo_t::mo_t* p__parent, gettext_mo_t* p__root, int p_is_le) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m__is_le = p_is_le;
f_major = false;
f_minor = false;
_read();
}
void gettext_mo_t::mo_t::version_t::_read() {
if (m__is_le == -1) {
throw kaitai::undecided_endianness_error("/types/mo/types/version");
} else if (m__is_le == 1) {
_read_le();
} else {
_read_be();
}
}
void gettext_mo_t::mo_t::version_t::_read_le() {
m_version_raw = m__io->read_u4le();
}
void gettext_mo_t::mo_t::version_t::_read_be() {
m_version_raw = m__io->read_u4be();
}
gettext_mo_t::mo_t::version_t::~version_t() {
_clean_up();
}
void gettext_mo_t::mo_t::version_t::_clean_up() {
}
int32_t gettext_mo_t::mo_t::version_t::major() {
if (f_major)
return m_major;
m_major = (version_raw() >> 16);
f_major = true;
return m_major;
}
int32_t gettext_mo_t::mo_t::version_t::minor() {
if (f_minor)
return m_minor;
m_minor = (version_raw() & 65535);
f_minor = true;
return m_minor;
}
gettext_mo_t::mo_t::hashtable_item_t::hashtable_item_t(kaitai::kstream* p__io, gettext_mo_t::mo_t* p__parent, gettext_mo_t* p__root, int p_is_le) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m__is_le = p_is_le;
f_mask = false;
f_val_1 = false;
f_is_system_dependent = false;
f_val = false;
_read();
}
void gettext_mo_t::mo_t::hashtable_item_t::_read() {
if (m__is_le == -1) {
throw kaitai::undecided_endianness_error("/types/mo/types/hashtable_item");
} else if (m__is_le == 1) {
_read_le();
} else {
_read_be();
}
}
void gettext_mo_t::mo_t::hashtable_item_t::_read_le() {
m_raw_val = m__io->read_u4le();
}
void gettext_mo_t::mo_t::hashtable_item_t::_read_be() {
m_raw_val = m__io->read_u4be();
}
gettext_mo_t::mo_t::hashtable_item_t::~hashtable_item_t() {
_clean_up();
}
void gettext_mo_t::mo_t::hashtable_item_t::_clean_up() {
}
int32_t gettext_mo_t::mo_t::hashtable_item_t::mask() {
if (f_mask)
return m_mask;
m_mask = 2147483648UL;
f_mask = true;
return m_mask;
}
int32_t gettext_mo_t::mo_t::hashtable_item_t::val_1() {
if (f_val_1)
return m_val_1;
n_val_1 = true;
if (raw_val() != 0) {
n_val_1 = false;
m_val_1 = (raw_val() - 1);
}
f_val_1 = true;
return m_val_1;
}
bool gettext_mo_t::mo_t::hashtable_item_t::is_system_dependent() {
if (f_is_system_dependent)
return m_is_system_dependent;
n_is_system_dependent = true;
if (raw_val() != 0) {
n_is_system_dependent = false;
m_is_system_dependent = (val_1() & mask()) == 1;
}
f_is_system_dependent = true;
return m_is_system_dependent;
}
int32_t gettext_mo_t::mo_t::hashtable_item_t::val() {
if (f_val)
return m_val;
n_val = true;
if (raw_val() != 0) {
n_val = false;
m_val = (val_1() & ~(mask()));
}
f_val = true;
return m_val;
}
gettext_mo_t::mo_t::descriptor_t::descriptor_t(kaitai::kstream* p__io, gettext_mo_t::mo_t* p__parent, gettext_mo_t* p__root, int p_is_le) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m__is_le = p_is_le;
f_str = false;
_read();
}
void gettext_mo_t::mo_t::descriptor_t::_read() {
if (m__is_le == -1) {
throw kaitai::undecided_endianness_error("/types/mo/types/descriptor");
} else if (m__is_le == 1) {
_read_le();
} else {
_read_be();
}
}
void gettext_mo_t::mo_t::descriptor_t::_read_le() {
m_len_str = m__io->read_u4le();
m_ofs_str = m__io->read_u4le();
}
void gettext_mo_t::mo_t::descriptor_t::_read_be() {
m_len_str = m__io->read_u4be();
m_ofs_str = m__io->read_u4be();
}
gettext_mo_t::mo_t::descriptor_t::~descriptor_t() {
_clean_up();
}
void gettext_mo_t::mo_t::descriptor_t::_clean_up() {
if (f_str) {
}
}
std::string gettext_mo_t::mo_t::descriptor_t::str() {
if (f_str)
return m_str;
kaitai::kstream *io = _root()->_io();
std::streampos _pos = io->pos();
io->seek(ofs_str());
if (m__is_le == 1) {
m_str = kaitai::kstream::bytes_to_str(kaitai::kstream::bytes_terminate(io->read_bytes(len_str()), 0, false), std::string("UTF-8"));
} else {
m_str = kaitai::kstream::bytes_to_str(kaitai::kstream::bytes_terminate(io->read_bytes(len_str()), 0, false), std::string("UTF-8"));
}
io->seek(_pos);
f_str = true;
return m_str;
}
std::vector<std::unique_ptr<gettext_mo_t::mo_t::descriptor_t>>* gettext_mo_t::mo_t::originals() {
if (f_originals)
return m_originals.get();
kaitai::kstream *io = _root()->_io();
std::streampos _pos = io->pos();
io->seek(ofs_originals());
if (m__is_le == 1) {
m_originals = std::unique_ptr<std::vector<std::unique_ptr<descriptor_t>>>(new std::vector<std::unique_ptr<descriptor_t>>());
const int l_originals = num_translations();
for (int i = 0; i < l_originals; i++) {
m_originals->push_back(std::move(std::unique_ptr<descriptor_t>(new descriptor_t(io, this, m__root, m__is_le))));
}
} else {
m_originals = std::unique_ptr<std::vector<std::unique_ptr<descriptor_t>>>(new std::vector<std::unique_ptr<descriptor_t>>());
const int l_originals = num_translations();
for (int i = 0; i < l_originals; i++) {
m_originals->push_back(std::move(std::unique_ptr<descriptor_t>(new descriptor_t(io, this, m__root, m__is_le))));
}
}
io->seek(_pos);
f_originals = true;
return m_originals.get();
}
std::vector<std::unique_ptr<gettext_mo_t::mo_t::descriptor_t>>* gettext_mo_t::mo_t::translations() {
if (f_translations)
return m_translations.get();
kaitai::kstream *io = _root()->_io();
std::streampos _pos = io->pos();
io->seek(ofs_translations());
if (m__is_le == 1) {
m_translations = std::unique_ptr<std::vector<std::unique_ptr<descriptor_t>>>(new std::vector<std::unique_ptr<descriptor_t>>());
const int l_translations = num_translations();
for (int i = 0; i < l_translations; i++) {
m_translations->push_back(std::move(std::unique_ptr<descriptor_t>(new descriptor_t(io, this, m__root, m__is_le))));
}
} else {
m_translations = std::unique_ptr<std::vector<std::unique_ptr<descriptor_t>>>(new std::vector<std::unique_ptr<descriptor_t>>());
const int l_translations = num_translations();
for (int i = 0; i < l_translations; i++) {
m_translations->push_back(std::move(std::unique_ptr<descriptor_t>(new descriptor_t(io, this, m__root, m__is_le))));
}
}
io->seek(_pos);
f_translations = true;
return m_translations.get();
}
std::vector<std::unique_ptr<gettext_mo_t::mo_t::hashtable_item_t>>* gettext_mo_t::mo_t::hashtable_items() {
if (f_hashtable_items)
return m_hashtable_items.get();
n_hashtable_items = true;
if (ofs_hashtable_items() != 0) {
n_hashtable_items = false;
kaitai::kstream *io = _root()->_io();
std::streampos _pos = io->pos();
io->seek(ofs_hashtable_items());
if (m__is_le == 1) {
m_hashtable_items = std::unique_ptr<std::vector<std::unique_ptr<hashtable_item_t>>>(new std::vector<std::unique_ptr<hashtable_item_t>>());
const int l_hashtable_items = num_hashtable_items();
for (int i = 0; i < l_hashtable_items; i++) {
m_hashtable_items->push_back(std::move(std::unique_ptr<hashtable_item_t>(new hashtable_item_t(io, this, m__root, m__is_le))));
}
} else {
m_hashtable_items = std::unique_ptr<std::vector<std::unique_ptr<hashtable_item_t>>>(new std::vector<std::unique_ptr<hashtable_item_t>>());
const int l_hashtable_items = num_hashtable_items();
for (int i = 0; i < l_hashtable_items; i++) {
m_hashtable_items->push_back(std::move(std::unique_ptr<hashtable_item_t>(new hashtable_item_t(io, this, m__root, m__is_le))));
}
}
io->seek(_pos);
f_hashtable_items = true;
}
return m_hashtable_items.get();
}