diff --git a/src/common/db2.h b/src/common/db2.h index f4598da..c56172d 100644 --- a/src/common/db2.h +++ b/src/common/db2.h @@ -19,10 +19,41 @@ #include "common.h" #include "mmap.h" +#include +#include #include #include +std::string utf8_to_dbstr(const char8_t *s, int codepage = 1251) { + return str2str((const char *)s, CP_UTF8, codepage); +} +std::string utf8_to_dbstr(const char *s) { + return utf8_to_dbstr((const char8_t *)s); +} +std::string utf8_to_dbstr(const std::string &s) { + return utf8_to_dbstr((const char8_t *)s.c_str()); +} + +struct mem_stream { + std::vector d; + + template + operator T &() { + d.resize(d.size() + sizeof(T)); + auto p = d.data() + d.size() - sizeof(T); + auto &r = *(T *)p; + return r; + } + void operator+=(const mem_stream &s) { + d.append_range(s.d); + } + template + T &at(size_t i) { + return *(T *)(d.data() + i); + } +}; + struct db2 { using char20 = char[0x20]; @@ -127,10 +158,124 @@ struct db2 { db2_memory m; + auto begin(this auto &&d) {return d.m.begin();} + auto end(this auto &&d) {return d.m.end();} auto &operator[](this auto &&d, const std::string &s) { return d.m[s]; } - void save() { + auto to_json() const { + nlohmann::json ja; + for (auto &&[tn,t] : m) { + auto &jt = ja[tn]; + for (auto &&[vn,v] : t) { + auto &jv = jt[vn]; + for (auto &&[fn, fv] : v) { + std::visit(overload{ + [&](const int &v){jv[fn] = v;}, + [&](const float &v){jv[fn] = v;}, + [&](const std::string &v){jv[fn] = v;}, + }, fv); + } + } + } + return ja; + } + size_t fields_size() const { + size_t sz{}; + return sz; + } + size_t tables_size() const { + size_t sz{}; + return sz; + } + size_t tab_size() const { + return tables_size() + fields_size(); + } + size_t ind_size() const { + return tables_size() + fields_size(); + } + size_t dat_size() const { + return tables_size() + fields_size(); + } + void save(const path &fn) { + auto tabsz = tab_size(); + auto indsz = ind_size(); + auto datsz = dat_size(); + + auto s_to_char20 = [&](char20 &dst, const std::string &in) { + auto s = utf8_to_dbstr(in); + if (s.size() + 1 > sizeof(char20)) { + throw std::runtime_error{"too long string"}; + } + memcpy(dst, s.c_str(), s.size()); + }; + + mem_stream tabv,tabv_fields; + tab &tab_ = tabv; + auto get_tab = [&](){}; + int table_id{1}; + int total_fields{}; + for (auto &&[tn,td] : m) { + tab::table &t = tabv; + t.id = table_id; + s_to_char20(t.name, tn); + + std::set> fields; + for (auto &&[_,fd] : td) { + for (auto &&[fn,fv] : fd) { + fields.emplace(std::pair{fn,(field_type)fv.index()}); + } + } + int field_id{1}; + for (auto &&[fn,ft] : fields) { + tab::field &f = tabv_fields; + f.id = field_id; + f.table_id = table_id; + f.type = ft; + s_to_char20(f.name, fn); + ++total_fields; + } + + ++table_id; + } + tabv += tabv_fields; + { + auto &tab_ = tabv.at(0); + tab_.n_tables = m.size(); + tab_.n_fields = total_fields; + } + + mem_stream indv, datv; + for (auto &&[tn, td] : m) { + tab::table &t = tabv; + t.id = table_id; + s_to_char20(t.name, tn); + + std::set> fields; + for (auto &&[_, fd] : td) { + } + } + + + /*db2 x{}; + auto newdb = x.open(); + for (auto &&[t,vals] : ja.items()) { + for (auto &&[v,fields] : vals.items()) { + for (auto &&[f,val] : fields.items()) { + auto s = newdb(t, v, f); + if (0) { + } else if (val.is_number_float()) { + s = val.get(); + } else if (val.is_number_integer()) { + s = val.get(); + } else if (val.is_string()) { + s = val.get(); + } else { + throw std::logic_error{"bad type"}; + } + } + } + }*/ } }; @@ -183,68 +328,9 @@ struct db2 { } return m; } - /*auto to_json() const { - auto prepare_string = [](auto &&in) { - auto s = str2utf8(in); - boost::trim(s); - return s; - }; - - auto tbl = tab_.data->tables(); - nlohmann::json ja; - for (auto &&t : tbl) { - auto &jt = ja[prepare_string(t.name)]; - auto fields = tab_.data->fields(t.id); - for (auto &&v : ind_.data->values(t.id)) { - auto vn = prepare_string(v.name); - if (jt.contains(vn)) { - throw std::logic_error{"duplicate"}; - } - auto &jv = jt[vn]; - auto p = dat_.f.p + v.offset; - auto max = p + v.size; - while (p < max) { - auto vb = (db2::dat::field_value_base *)p; - p += sizeof(db2::dat::field_value_base); - auto f = std::ranges::find_if(fields, [&](auto &f) { - return f.id == vb->field_id; - }); - if (f == fields.end()) { - throw std::logic_error{"unknown field"}; - } - auto fn = prepare_string(f->name); - switch (f->type) { - case db2::field_type::integer: - jv[fn] = *(int *)p; - break; - case db2::field_type::float_: - jv[fn] = *(float *)p; - break; - case db2::field_type::string: - jv[fn] = prepare_string((const char *)p); - break; - default: - throw std::logic_error{"bad type"}; - } - p += vb->size; - } - } - } - }*/ }; auto open() { return files{*this, fn}; } - -private: - std::string utf8_to_dbstr(const std::string &s) const { - return utf8_to_dbstr((const char8_t *)s.c_str()); - } - std::string utf8_to_dbstr(const char *s) const { - return utf8_to_dbstr((const char8_t *)s); - } - std::string utf8_to_dbstr(const char8_t *s) const { - return str2str((const char *)s, CP_UTF8, codepage); - } }; diff --git a/src/db_extractor2/db_extractor2.cpp b/src/db_extractor2/db_extractor2.cpp index 3d4df53..6a84bf7 100644 --- a/src/db_extractor2/db_extractor2.cpp +++ b/src/db_extractor2/db_extractor2.cpp @@ -24,8 +24,6 @@ #include #include #include -#include -#include #include #include @@ -39,43 +37,9 @@ int main(int argc, char *argv[]) db2 db{db_fn}; auto f = db.open(); - auto tbl = f.to_map(); - - nlohmann::json ja; - for (auto &&[tn,t] : tbl) { - auto &jt = ja[tn]; - for (auto &&[vn,v] : t) { - auto &jv = jt[vn]; - for (auto &&[fn, fv] : v) { - std::visit(overload{ - [&](const int &v){jv[fn] = v;}, - [&](const float &v){jv[fn] = v;}, - [&](const std::string &v){jv[fn] = v;}, - }, fv); - } - } - } - write_file(path{db_fn} += ".json", ja.dump(1)); - - db2 x{path{db_fn} += "new"}; - auto newdb = x.open(); - for (auto &&[t,vals] : ja.items()) { - for (auto &&[v,fields] : vals.items()) { - for (auto &&[f,val] : fields.items()) { - auto s = newdb(t, v, f); - if (0) { - } else if (val.is_number_float()) { - s = val.get(); - } else if (val.is_number_integer()) { - s = val.get(); - } else if (val.is_string()) { - s = val.get(); - } else { - throw std::logic_error{"bad type"}; - } - } - } - } + auto m = f.to_map(); + write_file(path{db_fn} += ".json", m.to_json().dump(1)); + m.save(path{db_fn} += "new"); return 0; } diff --git a/sw.cpp b/sw.cpp index a7fc3e9..d6fb5fa 100644 --- a/sw.cpp +++ b/sw.cpp @@ -96,6 +96,7 @@ void build(Solution &s) auto &aim1_mod_maker = add_exe_with_common("aim1.mod_maker", "aim1_mod_maker"); // actually a library aim1_mod_maker.Public += "pub.egorpugin.primitives.command"_dep; + aim1_mod_maker.Public += "org.sw.demo.nlohmann.json.natvis"_dep; auto &aim1_community_fix = tools.addExecutable("examples.mods.aim1.community_fix"); {