From d08363f3ba59152351d68019cede9f9085727c3b Mon Sep 17 00:00:00 2001 From: Kybxd <627940450@qq.com> Date: Wed, 17 Dec 2025 14:10:41 +0800 Subject: [PATCH 1/3] fix: calling Get on a possibly nil treemap --- .../indexes/orderedindex.go | 8 ++++++-- .../protoconf/loader/index_conf.pc.go | 12 ++++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/cmd/protoc-gen-go-tableau-loader/indexes/orderedindex.go b/cmd/protoc-gen-go-tableau-loader/indexes/orderedindex.go index b11fc1d8..5ab40268 100644 --- a/cmd/protoc-gen-go-tableau-loader/indexes/orderedindex.go +++ b/cmd/protoc-gen-go-tableau-loader/indexes/orderedindex.go @@ -357,10 +357,14 @@ func (x *Generator) genOrderedIndexFinders() { x.g.P("// Find", index.Name(), i, " finds a slice of all values of the given key(s) in the upper ", loadutil.Ordinal(i), "-level treemap") x.g.P("// specified by (", partArgs, ").") x.g.P("func (x *", messagerName, ") Find", index.Name(), i, "(", partParams, ", ", params, ") []*", x.mapValueType(index), " {") + x.g.P("m := x.Find", index.Name(), "Map", i, "(", partArgs, ")") + x.g.P("if m == nil {") + x.g.P("return nil") + x.g.P("}") if len(index.ColFields) == 1 { - x.g.P("val, _ := x.Find", index.Name(), "Map", i, "(", partArgs, ").Get(", args, ")") + x.g.P("val, _ := m.Get(", args, ")") } else { - x.g.P("val, _ := x.Find", index.Name(), "Map", i, "(", partArgs, ").Get(", x.orderedIndexMapKeyType(index), "{", args, "})") + x.g.P("val, _ := m.Get(", x.orderedIndexMapKeyType(index), "{", args, "})") } x.g.P("return val") x.g.P("}") diff --git a/test/go-tableau-loader/protoconf/loader/index_conf.pc.go b/test/go-tableau-loader/protoconf/loader/index_conf.pc.go index b645bc1d..0be9152c 100644 --- a/test/go-tableau-loader/protoconf/loader/index_conf.pc.go +++ b/test/go-tableau-loader/protoconf/loader/index_conf.pc.go @@ -191,7 +191,11 @@ func (x *FruitConf) FindItemMap1(fruitType int32) *FruitConf_OrderedIndex_ItemMa // FindItem1 finds a slice of all values of the given key(s) in the upper 1st-level treemap // specified by (fruitType). func (x *FruitConf) FindItem1(fruitType int32, price int32) []*protoconf.FruitConf_Fruit_Item { - val, _ := x.FindItemMap1(fruitType).Get(price) + m := x.FindItemMap1(fruitType) + if m == nil { + return nil + } + val, _ := m.Get(price) return val } @@ -472,7 +476,11 @@ func (x *Fruit2Conf) FindItemMap1(fruitType int32) *Fruit2Conf_OrderedIndex_Item // FindItem1 finds a slice of all values of the given key(s) in the upper 1st-level treemap // specified by (fruitType). func (x *Fruit2Conf) FindItem1(fruitType int32, price int32) []*protoconf.Fruit2Conf_Fruit_Country_Item { - val, _ := x.FindItemMap1(fruitType).Get(price) + m := x.FindItemMap1(fruitType) + if m == nil { + return nil + } + val, _ := m.Get(price) return val } From f17c10096398042ab4c9e9132b7fb8cd8fc4e69d Mon Sep 17 00:00:00 2001 From: Kybxd <627940450@qq.com> Date: Wed, 17 Dec 2025 15:08:54 +0800 Subject: [PATCH 2/3] refactor: add test cases Fruit4Conf and destructor for cpp Messagers --- .../indexes/index.go | 2 +- .../indexes/ordered_index.go | 2 +- cmd/protoc-gen-cpp-tableau-loader/messager.go | 1 + .../src/protoconf/hero_conf.pc.h | 2 + .../cpp-tableau-loader/src/protoconf/hub.pc.h | 5 + .../src/protoconf/hub_shard0.pc.cc | 7 + .../src/protoconf/index_conf.pc.cc | 322 ++++++++++++- .../src/protoconf/index_conf.pc.h | 136 ++++++ .../src/protoconf/item_conf.pc.cc | 24 +- .../src/protoconf/item_conf.pc.h | 1 + .../src/protoconf/patch_conf.pc.h | 3 + .../src/protoconf/test_conf.pc.cc | 18 +- .../src/protoconf/test_conf.pc.h | 4 + .../protoconf/loader/hub.pc.go | 4 + .../protoconf/loader/index_conf.pc.go | 427 ++++++++++++++++++ .../protoconf/loader/messager_container.pc.go | 6 + test/proto/index_conf.proto | 40 +- test/testdata/conf/Fruit4Conf.json | 1 + 18 files changed, 971 insertions(+), 34 deletions(-) create mode 100644 test/testdata/conf/Fruit4Conf.json diff --git a/cmd/protoc-gen-cpp-tableau-loader/indexes/index.go b/cmd/protoc-gen-cpp-tableau-loader/indexes/index.go index 689f1ab8..62835c99 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/indexes/index.go +++ b/cmd/protoc-gen-cpp-tableau-loader/indexes/index.go @@ -300,7 +300,7 @@ func (x *Generator) genCppIndexFinders() { messagerName := x.messagerName() x.g.P("// Index: ", index.Index) - x.g.P("const ", messagerName, "::", mapType, "& ", messagerName, "::Find", index.Name(), "Map() const { return ", indexContainerName, " ;}") + x.g.P("const ", messagerName, "::", mapType, "& ", messagerName, "::Find", index.Name(), "Map() const { return ", indexContainerName, "; }") x.g.P() keys := x.indexKeys(index) diff --git a/cmd/protoc-gen-cpp-tableau-loader/indexes/ordered_index.go b/cmd/protoc-gen-cpp-tableau-loader/indexes/ordered_index.go index 365482fb..78caca55 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/indexes/ordered_index.go +++ b/cmd/protoc-gen-cpp-tableau-loader/indexes/ordered_index.go @@ -290,7 +290,7 @@ func (x *Generator) genCppOrderedIndexFinders() { messagerName := x.messagerName() x.g.P("// OrderedIndex: ", index.Index) - x.g.P("const ", messagerName, "::", mapType, "& ", messagerName, "::Find", index.Name(), "Map() const { return ", indexContainerName, " ;}") + x.g.P("const ", messagerName, "::", mapType, "& ", messagerName, "::Find", index.Name(), "Map() const { return ", indexContainerName, "; }") x.g.P() keys := x.orderedIndexKeys(index) diff --git a/cmd/protoc-gen-cpp-tableau-loader/messager.go b/cmd/protoc-gen-cpp-tableau-loader/messager.go index db1c9eaa..4637b216 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/messager.go +++ b/cmd/protoc-gen-cpp-tableau-loader/messager.go @@ -92,6 +92,7 @@ func genHppMessage(g *protogen.GeneratedFile, message *protogen.Message) { g.P(helper.Indent(1), "virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override;") g.P(helper.Indent(1), "const ", cppFullName, "& Data() const { return data_; }") g.P(helper.Indent(1), "const google::protobuf::Message* Message() const override { return &data_; }") + g.P(helper.Indent(1), "virtual ~", message.Desc.Name(), "() = default;") g.P() if orderedMapGenerator.NeedGenerate() || indexGenerator.NeedGenerate() { diff --git a/test/cpp-tableau-loader/src/protoconf/hero_conf.pc.h b/test/cpp-tableau-loader/src/protoconf/hero_conf.pc.h index 8c3204d4..1d993cfe 100644 --- a/test/cpp-tableau-loader/src/protoconf/hero_conf.pc.h +++ b/test/cpp-tableau-loader/src/protoconf/hero_conf.pc.h @@ -19,6 +19,7 @@ class HeroConf : public Messager { virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; const protoconf::HeroConf& Data() const { return data_; } const google::protobuf::Message* Message() const override { return &data_; } + virtual ~HeroConf() = default; private: virtual bool ProcessAfterLoad() override final; @@ -50,6 +51,7 @@ class HeroBaseConf : public Messager { virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; const protoconf::HeroBaseConf& Data() const { return data_; } const google::protobuf::Message* Message() const override { return &data_; } + virtual ~HeroBaseConf() = default; public: const base::Hero* Get(const std::string& name) const; diff --git a/test/cpp-tableau-loader/src/protoconf/hub.pc.h b/test/cpp-tableau-loader/src/protoconf/hub.pc.h index fb85329d..723a1b83 100644 --- a/test/cpp-tableau-loader/src/protoconf/hub.pc.h +++ b/test/cpp-tableau-loader/src/protoconf/hub.pc.h @@ -134,6 +134,10 @@ class Fruit3Conf; template <> const std::shared_ptr Hub::Get() const; +class Fruit4Conf; +template <> +const std::shared_ptr Hub::Get() const; + class FruitConf; template <> const std::shared_ptr Hub::Get() const; @@ -188,6 +192,7 @@ class MessagerContainer { std::shared_ptr hero_conf_; std::shared_ptr fruit_2_conf_; std::shared_ptr fruit_3_conf_; + std::shared_ptr fruit_4_conf_; std::shared_ptr fruit_conf_; std::shared_ptr item_conf_; std::shared_ptr patch_merge_conf_; diff --git a/test/cpp-tableau-loader/src/protoconf/hub_shard0.pc.cc b/test/cpp-tableau-loader/src/protoconf/hub_shard0.pc.cc index f9c04280..820082e6 100644 --- a/test/cpp-tableau-loader/src/protoconf/hub_shard0.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/hub_shard0.pc.cc @@ -30,6 +30,11 @@ const std::shared_ptr Hub::Get() const { return GetMessagerContainerWithProvider()->fruit_3_conf_; } +template <> +const std::shared_ptr Hub::Get() const { + return GetMessagerContainerWithProvider()->fruit_4_conf_; +} + template <> const std::shared_ptr Hub::Get() const { return GetMessagerContainerWithProvider()->fruit_conf_; @@ -45,6 +50,7 @@ void MessagerContainer::InitShard0() { hero_conf_ = std::dynamic_pointer_cast(GetMessager(HeroConf::Name())); fruit_2_conf_ = std::dynamic_pointer_cast(GetMessager(Fruit2Conf::Name())); fruit_3_conf_ = std::dynamic_pointer_cast(GetMessager(Fruit3Conf::Name())); + fruit_4_conf_ = std::dynamic_pointer_cast(GetMessager(Fruit4Conf::Name())); fruit_conf_ = std::dynamic_pointer_cast(GetMessager(FruitConf::Name())); item_conf_ = std::dynamic_pointer_cast(GetMessager(ItemConf::Name())); } @@ -54,6 +60,7 @@ void Registry::InitShard0() { Register(); Register(); Register(); + Register(); Register(); Register(); } diff --git a/test/cpp-tableau-loader/src/protoconf/index_conf.pc.cc b/test/cpp-tableau-loader/src/protoconf/index_conf.pc.cc index 0e703d09..0d576a68 100644 --- a/test/cpp-tableau-loader/src/protoconf/index_conf.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/index_conf.pc.cc @@ -72,7 +72,7 @@ const protoconf::FruitConf::Fruit::Item* FruitConf::Get(int32_t fruit_type, int3 } // OrderedIndex: Price -const FruitConf::OrderedIndex_ItemMap& FruitConf::FindItemMap() const { return ordered_index_item_map_ ;} +const FruitConf::OrderedIndex_ItemMap& FruitConf::FindItemMap() const { return ordered_index_item_map_; } const FruitConf::OrderedIndex_ItemVector* FruitConf::FindItem(int32_t price) const { auto iter = ordered_index_item_map_.find(price); @@ -193,7 +193,7 @@ const protoconf::Fruit2Conf::Fruit* Fruit2Conf::Get(int32_t fruit_type) const { } // Index: CountryName -const Fruit2Conf::Index_CountryMap& Fruit2Conf::FindCountryMap() const { return index_country_map_ ;} +const Fruit2Conf::Index_CountryMap& Fruit2Conf::FindCountryMap() const { return index_country_map_; } const Fruit2Conf::Index_CountryVector* Fruit2Conf::FindCountry(const std::string& name) const { auto iter = index_country_map_.find(name); @@ -212,7 +212,7 @@ const protoconf::Fruit2Conf::Fruit::Country* Fruit2Conf::FindFirstCountry(const } // Index: CountryItemAttrName -const Fruit2Conf::Index_AttrMap& Fruit2Conf::FindAttrMap() const { return index_attr_map_ ;} +const Fruit2Conf::Index_AttrMap& Fruit2Conf::FindAttrMap() const { return index_attr_map_; } const Fruit2Conf::Index_AttrVector* Fruit2Conf::FindAttr(const std::string& name) const { auto iter = index_attr_map_.find(name); @@ -259,7 +259,7 @@ const protoconf::Fruit2Conf::Fruit::Country::Item::Attr* Fruit2Conf::FindFirstAt } // OrderedIndex: CountryItemPrice -const Fruit2Conf::OrderedIndex_ItemMap& Fruit2Conf::FindItemMap() const { return ordered_index_item_map_ ;} +const Fruit2Conf::OrderedIndex_ItemMap& Fruit2Conf::FindItemMap() const { return ordered_index_item_map_; } const Fruit2Conf::OrderedIndex_ItemVector* Fruit2Conf::FindItem(int32_t price) const { auto iter = ordered_index_item_map_.find(price); @@ -361,7 +361,7 @@ bool Fruit3Conf::ProcessAfterLoad() { } // Index: CountryName -const Fruit3Conf::Index_CountryMap& Fruit3Conf::FindCountryMap() const { return index_country_map_ ;} +const Fruit3Conf::Index_CountryMap& Fruit3Conf::FindCountryMap() const { return index_country_map_; } const Fruit3Conf::Index_CountryVector* Fruit3Conf::FindCountry(const std::string& name) const { auto iter = index_country_map_.find(name); @@ -380,7 +380,7 @@ const protoconf::Fruit3Conf::Fruit::Country* Fruit3Conf::FindFirstCountry(const } // Index: CountryItemAttrName -const Fruit3Conf::Index_AttrMap& Fruit3Conf::FindAttrMap() const { return index_attr_map_ ;} +const Fruit3Conf::Index_AttrMap& Fruit3Conf::FindAttrMap() const { return index_attr_map_; } const Fruit3Conf::Index_AttrVector* Fruit3Conf::FindAttr(const std::string& name) const { auto iter = index_attr_map_.find(name); @@ -399,7 +399,7 @@ const protoconf::Fruit3Conf::Fruit::Country::Item::Attr* Fruit3Conf::FindFirstAt } // OrderedIndex: CountryItemPrice -const Fruit3Conf::OrderedIndex_ItemMap& Fruit3Conf::FindItemMap() const { return ordered_index_item_map_ ;} +const Fruit3Conf::OrderedIndex_ItemMap& Fruit3Conf::FindItemMap() const { return ordered_index_item_map_; } const Fruit3Conf::OrderedIndex_ItemVector* Fruit3Conf::FindItem(int32_t price) const { auto iter = ordered_index_item_map_.find(price); @@ -417,4 +417,312 @@ const protoconf::Fruit3Conf::Fruit::Country::Item* Fruit3Conf::FindFirstItem(int return conf->front(); } +const std::string Fruit4Conf::kProtoName = protoconf::Fruit4Conf::GetDescriptor()->name(); + +bool Fruit4Conf::Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options /* = nullptr */) { + tableau::util::TimeProfiler profiler; + bool loaded = LoadMessagerInDir(data_, dir, fmt, options); + bool ok = loaded ? ProcessAfterLoad() : false; + stats_.duration = profiler.Elapse(); + return ok; +} + +bool Fruit4Conf::ProcessAfterLoad() { + // Index init. + index_country_map_.clear(); + index_country_map1_.clear(); + index_attr_map_.clear(); + index_attr_map1_.clear(); + index_attr_map2_.clear(); + for (auto&& item1 : data_.fruit_map()) { + auto k1 = item1.first; + for (auto&& item2 : item1.second.country_map()) { + auto k2 = item2.first; + { + // Index: CountryName + index_country_map_[item2.second.name()].push_back(&item2.second); + index_country_map1_[k1][item2.second.name()].push_back(&item2.second); + } + for (auto&& item3 : item2.second.item_map()) { + auto k3 = item3.first; + for (auto&& item4 : item3.second.attr_list()) { + { + // Index: CountryItemAttrName + index_attr_map_[item4.name()].push_back(&item4); + index_attr_map1_[k1][item4.name()].push_back(&item4); + index_attr_map2_[{k1, k2}][item4.name()].push_back(&item4); + } + } + } + } + } + // OrderedIndex init. + ordered_index_item_map_.clear(); + ordered_index_item_map1_.clear(); + ordered_index_item_map2_.clear(); + for (auto&& item1 : data_.fruit_map()) { + auto k1 = item1.first; + for (auto&& item2 : item1.second.country_map()) { + auto k2 = item2.first; + for (auto&& item3 : item2.second.item_map()) { + auto k3 = item3.first; + { + // OrderedIndex: CountryItemPrice + ordered_index_item_map_[item3.second.price()].push_back(&item3.second); + ordered_index_item_map1_[k1][item3.second.price()].push_back(&item3.second); + ordered_index_item_map2_[{k1, k2}][item3.second.price()].push_back(&item3.second); + } + } + } + } + // OrderedIndex(sort): CountryItemPrice + auto ordered_index_item_map_sorter = [](const protoconf::Fruit4Conf::Fruit::Country::Item* a, + const protoconf::Fruit4Conf::Fruit::Country::Item* b) { + return a->id() < b->id(); + }; + for (auto&& item : ordered_index_item_map_) { + std::sort(item.second.begin(), item.second.end(), ordered_index_item_map_sorter); + } + for (auto&& item : ordered_index_item_map1_) { + for (auto&& item1 : item.second) { + std::sort(item1.second.begin(), item1.second.end(), ordered_index_item_map_sorter); + } + } + for (auto&& item : ordered_index_item_map2_) { + for (auto&& item1 : item.second) { + std::sort(item1.second.begin(), item1.second.end(), ordered_index_item_map_sorter); + } + } + return true; +} + +const protoconf::Fruit4Conf::Fruit* Fruit4Conf::Get(int32_t fruit_type) const { + auto iter = data_.fruit_map().find(fruit_type); + if (iter == data_.fruit_map().end()) { + return nullptr; + } + return &iter->second; +} + +const protoconf::Fruit4Conf::Fruit::Country* Fruit4Conf::Get(int32_t fruit_type, int32_t id) const { + const auto* conf = Get(fruit_type); + if (conf == nullptr) { + return nullptr; + } + auto iter = conf->country_map().find(id); + if (iter == conf->country_map().end()) { + return nullptr; + } + return &iter->second; +} + +const protoconf::Fruit4Conf::Fruit::Country::Item* Fruit4Conf::Get(int32_t fruit_type, int32_t id, int32_t id3) const { + const auto* conf = Get(fruit_type, id); + if (conf == nullptr) { + return nullptr; + } + auto iter = conf->item_map().find(id3); + if (iter == conf->item_map().end()) { + return nullptr; + } + return &iter->second; +} + +// Index: CountryName +const Fruit4Conf::Index_CountryMap& Fruit4Conf::FindCountryMap() const { return index_country_map_; } + +const Fruit4Conf::Index_CountryVector* Fruit4Conf::FindCountry(const std::string& name) const { + auto iter = index_country_map_.find(name); + if (iter == index_country_map_.end()) { + return nullptr; + } + return &iter->second; +} + +const protoconf::Fruit4Conf::Fruit::Country* Fruit4Conf::FindFirstCountry(const std::string& name) const { + auto conf = FindCountry(name); + if (conf == nullptr || conf->empty()) { + return nullptr; + } + return conf->front(); +} + +const Fruit4Conf::Index_CountryMap* Fruit4Conf::FindCountryMap(int32_t fruit_type) const { + auto iter = index_country_map1_.find(fruit_type); + if (iter == index_country_map1_.end()) { + return nullptr; + } + return &iter->second; +} + +const Fruit4Conf::Index_CountryVector* Fruit4Conf::FindCountry(int32_t fruit_type, const std::string& name) const { + auto map = FindCountryMap(fruit_type); + if (map == nullptr) { + return nullptr; + } + auto iter = map->find(name); + if (iter == map->end()) { + return nullptr; + } + return &iter->second; +} + +const protoconf::Fruit4Conf::Fruit::Country* Fruit4Conf::FindFirstCountry(int32_t fruit_type, const std::string& name) const { + auto conf = FindCountry(fruit_type, name); + if (conf == nullptr || conf->empty()) { + return nullptr; + } + return conf->front(); +} + +// Index: CountryItemAttrName +const Fruit4Conf::Index_AttrMap& Fruit4Conf::FindAttrMap() const { return index_attr_map_; } + +const Fruit4Conf::Index_AttrVector* Fruit4Conf::FindAttr(const std::string& name) const { + auto iter = index_attr_map_.find(name); + if (iter == index_attr_map_.end()) { + return nullptr; + } + return &iter->second; +} + +const protoconf::Fruit4Conf::Fruit::Country::Item::Attr* Fruit4Conf::FindFirstAttr(const std::string& name) const { + auto conf = FindAttr(name); + if (conf == nullptr || conf->empty()) { + return nullptr; + } + return conf->front(); +} + +const Fruit4Conf::Index_AttrMap* Fruit4Conf::FindAttrMap(int32_t fruit_type) const { + auto iter = index_attr_map1_.find(fruit_type); + if (iter == index_attr_map1_.end()) { + return nullptr; + } + return &iter->second; +} + +const Fruit4Conf::Index_AttrVector* Fruit4Conf::FindAttr(int32_t fruit_type, const std::string& name) const { + auto map = FindAttrMap(fruit_type); + if (map == nullptr) { + return nullptr; + } + auto iter = map->find(name); + if (iter == map->end()) { + return nullptr; + } + return &iter->second; +} + +const protoconf::Fruit4Conf::Fruit::Country::Item::Attr* Fruit4Conf::FindFirstAttr(int32_t fruit_type, const std::string& name) const { + auto conf = FindAttr(fruit_type, name); + if (conf == nullptr || conf->empty()) { + return nullptr; + } + return conf->front(); +} + +const Fruit4Conf::Index_AttrMap* Fruit4Conf::FindAttrMap(int32_t fruit_type, int32_t id) const { + auto iter = index_attr_map2_.find({fruit_type, id}); + if (iter == index_attr_map2_.end()) { + return nullptr; + } + return &iter->second; +} + +const Fruit4Conf::Index_AttrVector* Fruit4Conf::FindAttr(int32_t fruit_type, int32_t id, const std::string& name) const { + auto map = FindAttrMap(fruit_type, id); + if (map == nullptr) { + return nullptr; + } + auto iter = map->find(name); + if (iter == map->end()) { + return nullptr; + } + return &iter->second; +} + +const protoconf::Fruit4Conf::Fruit::Country::Item::Attr* Fruit4Conf::FindFirstAttr(int32_t fruit_type, int32_t id, const std::string& name) const { + auto conf = FindAttr(fruit_type, id, name); + if (conf == nullptr || conf->empty()) { + return nullptr; + } + return conf->front(); +} + +// OrderedIndex: CountryItemPrice +const Fruit4Conf::OrderedIndex_ItemMap& Fruit4Conf::FindItemMap() const { return ordered_index_item_map_; } + +const Fruit4Conf::OrderedIndex_ItemVector* Fruit4Conf::FindItem(int32_t price) const { + auto iter = ordered_index_item_map_.find(price); + if (iter == ordered_index_item_map_.end()) { + return nullptr; + } + return &iter->second; +} + +const protoconf::Fruit4Conf::Fruit::Country::Item* Fruit4Conf::FindFirstItem(int32_t price) const { + auto conf = FindItem(price); + if (conf == nullptr || conf->empty()) { + return nullptr; + } + return conf->front(); +} + +const Fruit4Conf::OrderedIndex_ItemMap* Fruit4Conf::FindItemMap(int32_t fruit_type) const { + auto iter = ordered_index_item_map1_.find(fruit_type); + if (iter == ordered_index_item_map1_.end()) { + return nullptr; + } + return &iter->second; +} + +const Fruit4Conf::OrderedIndex_ItemVector* Fruit4Conf::FindItem(int32_t fruit_type, int32_t price) const { + auto map = FindItemMap(fruit_type); + if (map == nullptr) { + return nullptr; + } + auto iter = map->find(price); + if (iter == map->end()) { + return nullptr; + } + return &iter->second; +} + +const protoconf::Fruit4Conf::Fruit::Country::Item* Fruit4Conf::FindFirstItem(int32_t fruit_type, int32_t price) const { + auto conf = FindItem(fruit_type, price); + if (conf == nullptr || conf->empty()) { + return nullptr; + } + return conf->front(); +} + +const Fruit4Conf::OrderedIndex_ItemMap* Fruit4Conf::FindItemMap(int32_t fruit_type, int32_t id) const { + auto iter = ordered_index_item_map2_.find({fruit_type, id}); + if (iter == ordered_index_item_map2_.end()) { + return nullptr; + } + return &iter->second; +} + +const Fruit4Conf::OrderedIndex_ItemVector* Fruit4Conf::FindItem(int32_t fruit_type, int32_t id, int32_t price) const { + auto map = FindItemMap(fruit_type, id); + if (map == nullptr) { + return nullptr; + } + auto iter = map->find(price); + if (iter == map->end()) { + return nullptr; + } + return &iter->second; +} + +const protoconf::Fruit4Conf::Fruit::Country::Item* Fruit4Conf::FindFirstItem(int32_t fruit_type, int32_t id, int32_t price) const { + auto conf = FindItem(fruit_type, id, price); + if (conf == nullptr || conf->empty()) { + return nullptr; + } + return conf->front(); +} + } // namespace tableau diff --git a/test/cpp-tableau-loader/src/protoconf/index_conf.pc.h b/test/cpp-tableau-loader/src/protoconf/index_conf.pc.h index 230d03d3..64c2af5e 100644 --- a/test/cpp-tableau-loader/src/protoconf/index_conf.pc.h +++ b/test/cpp-tableau-loader/src/protoconf/index_conf.pc.h @@ -19,6 +19,7 @@ class FruitConf : public Messager { virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; const protoconf::FruitConf& Data() const { return data_; } const google::protobuf::Message* Message() const override { return &data_; } + virtual ~FruitConf() = default; private: virtual bool ProcessAfterLoad() override final; @@ -63,6 +64,7 @@ class Fruit2Conf : public Messager { virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; const protoconf::Fruit2Conf& Data() const { return data_; } const google::protobuf::Message* Message() const override { return &data_; } + virtual ~Fruit2Conf() = default; private: virtual bool ProcessAfterLoad() override final; @@ -146,6 +148,7 @@ class Fruit3Conf : public Messager { virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; const protoconf::Fruit3Conf& Data() const { return data_; } const google::protobuf::Message* Message() const override { return &data_; } + virtual ~Fruit3Conf() = default; private: virtual bool ProcessAfterLoad() override final; @@ -203,6 +206,138 @@ class Fruit3Conf : public Messager { OrderedIndex_ItemMap ordered_index_item_map_; }; +class Fruit4Conf : public Messager { + public: + static const std::string& Name() { return kProtoName; } + virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; + const protoconf::Fruit4Conf& Data() const { return data_; } + const google::protobuf::Message* Message() const override { return &data_; } + virtual ~Fruit4Conf() = default; + + private: + virtual bool ProcessAfterLoad() override final; + + public: + const protoconf::Fruit4Conf::Fruit* Get(int32_t fruit_type) const; + const protoconf::Fruit4Conf::Fruit::Country* Get(int32_t fruit_type, int32_t id) const; + const protoconf::Fruit4Conf::Fruit::Country::Item* Get(int32_t fruit_type, int32_t id, int32_t id3) const; + + private: + static const std::string kProtoName; + protoconf::Fruit4Conf data_; + + // LevelIndex keys. + public: + struct LevelIndex_Fruit_CountryKey { + int32_t fruit_type; + int32_t id; +#if __cplusplus >= 202002L + bool operator==(const LevelIndex_Fruit_CountryKey& other) const = default; +#else + bool operator==(const LevelIndex_Fruit_CountryKey& other) const { + return std::tie(fruit_type, id) == std::tie(other.fruit_type, other.id); + } +#endif + }; + struct LevelIndex_Fruit_CountryKeyHasher { + std::size_t operator()(const LevelIndex_Fruit_CountryKey& key) const { + return util::SugaredHashCombine(key.fruit_type, key.id); + } + }; + + // Index accessers. + // Index: CountryName + public: + using Index_CountryVector = std::vector; + using Index_CountryMap = std::unordered_map; + // Finds the index: key(CountryName) to value(Index_CountryVector) hashmap. + // One key may correspond to multiple values, which are represented by a vector. + const Index_CountryMap& FindCountryMap() const; + // Finds a vector of all values of the given key(s). + const Index_CountryVector* FindCountry(const std::string& name) const; + // Finds the first value of the given key(s). + const protoconf::Fruit4Conf::Fruit::Country* FindFirstCountry(const std::string& name) const; + // Finds the index: key(CountryName) to value(Index_CountryVector), + // which is the upper 1st-level hashmap specified by (fruit_type). + // One key may correspond to multiple values, which are represented by a vector. + const Index_CountryMap* FindCountryMap(int32_t fruit_type) const; + // Finds a vector of all values of the given key(s) in the upper 1st-level hashmap specified by (fruit_type). + const Index_CountryVector* FindCountry(int32_t fruit_type, const std::string& name) const; + // Finds the first value of the given key(s) in the upper 1st-level hashmap specified by (fruit_type). + const protoconf::Fruit4Conf::Fruit::Country* FindFirstCountry(int32_t fruit_type, const std::string& name) const; + + private: + Index_CountryMap index_country_map_; + std::unordered_map index_country_map1_; + + // Index: CountryItemAttrName + public: + using Index_AttrVector = std::vector; + using Index_AttrMap = std::unordered_map; + // Finds the index: key(CountryItemAttrName) to value(Index_AttrVector) hashmap. + // One key may correspond to multiple values, which are represented by a vector. + const Index_AttrMap& FindAttrMap() const; + // Finds a vector of all values of the given key(s). + const Index_AttrVector* FindAttr(const std::string& name) const; + // Finds the first value of the given key(s). + const protoconf::Fruit4Conf::Fruit::Country::Item::Attr* FindFirstAttr(const std::string& name) const; + // Finds the index: key(CountryItemAttrName) to value(Index_AttrVector), + // which is the upper 1st-level hashmap specified by (fruit_type). + // One key may correspond to multiple values, which are represented by a vector. + const Index_AttrMap* FindAttrMap(int32_t fruit_type) const; + // Finds a vector of all values of the given key(s) in the upper 1st-level hashmap specified by (fruit_type). + const Index_AttrVector* FindAttr(int32_t fruit_type, const std::string& name) const; + // Finds the first value of the given key(s) in the upper 1st-level hashmap specified by (fruit_type). + const protoconf::Fruit4Conf::Fruit::Country::Item::Attr* FindFirstAttr(int32_t fruit_type, const std::string& name) const; + // Finds the index: key(CountryItemAttrName) to value(Index_AttrVector), + // which is the upper 2nd-level hashmap specified by (fruit_type, id). + // One key may correspond to multiple values, which are represented by a vector. + const Index_AttrMap* FindAttrMap(int32_t fruit_type, int32_t id) const; + // Finds a vector of all values of the given key(s) in the upper 2nd-level hashmap specified by (fruit_type, id). + const Index_AttrVector* FindAttr(int32_t fruit_type, int32_t id, const std::string& name) const; + // Finds the first value of the given key(s) in the upper 2nd-level hashmap specified by (fruit_type, id). + const protoconf::Fruit4Conf::Fruit::Country::Item::Attr* FindFirstAttr(int32_t fruit_type, int32_t id, const std::string& name) const; + + private: + Index_AttrMap index_attr_map_; + std::unordered_map index_attr_map1_; + std::unordered_map index_attr_map2_; + + // OrderedIndex accessers. + // OrderedIndex: CountryItemPrice + public: + using OrderedIndex_ItemVector = std::vector; + using OrderedIndex_ItemMap = std::map; + // Finds the ordered index: key(CountryItemPrice) to value(OrderedIndex_ItemVector) map. + // One key may correspond to multiple values, which are represented by a vector. + const OrderedIndex_ItemMap& FindItemMap() const; + // Finds a vector of all values of the given key(s). + const OrderedIndex_ItemVector* FindItem(int32_t price) const; + // Finds the first value of the given key(s). + const protoconf::Fruit4Conf::Fruit::Country::Item* FindFirstItem(int32_t price) const; + // Finds the ordered index: key(CountryItemPrice) to value(OrderedIndex_ItemVector), + // which is the upper 1st-level map specified by (fruit_type). + // One key may correspond to multiple values, which are represented by a vector. + const OrderedIndex_ItemMap* FindItemMap(int32_t fruit_type) const; + // Finds a vector of all values of the given key(s) in the upper 1st-level map specified by (fruit_type). + const OrderedIndex_ItemVector* FindItem(int32_t fruit_type, int32_t price) const; + // Finds the first value of the given key(s) in the upper 1st-level map specified by (fruit_type). + const protoconf::Fruit4Conf::Fruit::Country::Item* FindFirstItem(int32_t fruit_type, int32_t price) const; + // Finds the ordered index: key(CountryItemPrice) to value(OrderedIndex_ItemVector), + // which is the upper 2nd-level map specified by (fruit_type, id). + // One key may correspond to multiple values, which are represented by a vector. + const OrderedIndex_ItemMap* FindItemMap(int32_t fruit_type, int32_t id) const; + // Finds a vector of all values of the given key(s) in the upper 2nd-level map specified by (fruit_type, id). + const OrderedIndex_ItemVector* FindItem(int32_t fruit_type, int32_t id, int32_t price) const; + // Finds the first value of the given key(s) in the upper 2nd-level map specified by (fruit_type, id). + const protoconf::Fruit4Conf::Fruit::Country::Item* FindFirstItem(int32_t fruit_type, int32_t id, int32_t price) const; + + private: + OrderedIndex_ItemMap ordered_index_item_map_; + std::unordered_map ordered_index_item_map1_; + std::unordered_map ordered_index_item_map2_; +}; + } // namespace tableau namespace protoconf { @@ -210,4 +345,5 @@ namespace protoconf { using FruitConfMgr = tableau::FruitConf; using Fruit2ConfMgr = tableau::Fruit2Conf; using Fruit3ConfMgr = tableau::Fruit3Conf; +using Fruit4ConfMgr = tableau::Fruit4Conf; } // namespace protoconf diff --git a/test/cpp-tableau-loader/src/protoconf/item_conf.pc.cc b/test/cpp-tableau-loader/src/protoconf/item_conf.pc.cc index 6216a72c..91908e90 100644 --- a/test/cpp-tableau-loader/src/protoconf/item_conf.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/item_conf.pc.cc @@ -156,7 +156,7 @@ const ItemConf::OrderedMap_ItemMap* ItemConf::GetOrderedMap() const { } // Index: Type -const ItemConf::Index_ItemMap& ItemConf::FindItemMap() const { return index_item_map_ ;} +const ItemConf::Index_ItemMap& ItemConf::FindItemMap() const { return index_item_map_; } const ItemConf::Index_ItemVector* ItemConf::FindItem(protoconf::FruitType type) const { auto iter = index_item_map_.find(type); @@ -175,7 +175,7 @@ const protoconf::ItemConf::Item* ItemConf::FindFirstItem(protoconf::FruitType ty } // Index: Param@ItemInfo -const ItemConf::Index_ItemInfoMap& ItemConf::FindItemInfoMap() const { return index_item_info_map_ ;} +const ItemConf::Index_ItemInfoMap& ItemConf::FindItemInfoMap() const { return index_item_info_map_; } const ItemConf::Index_ItemInfoVector* ItemConf::FindItemInfo(int32_t param) const { auto iter = index_item_info_map_.find(param); @@ -194,7 +194,7 @@ const protoconf::ItemConf::Item* ItemConf::FindFirstItemInfo(int32_t param) cons } // Index: Default@ItemDefaultInfo -const ItemConf::Index_ItemDefaultInfoMap& ItemConf::FindItemDefaultInfoMap() const { return index_item_default_info_map_ ;} +const ItemConf::Index_ItemDefaultInfoMap& ItemConf::FindItemDefaultInfoMap() const { return index_item_default_info_map_; } const ItemConf::Index_ItemDefaultInfoVector* ItemConf::FindItemDefaultInfo(const std::string& default_) const { auto iter = index_item_default_info_map_.find(default_); @@ -213,7 +213,7 @@ const protoconf::ItemConf::Item* ItemConf::FindFirstItemDefaultInfo(const std::s } // Index: ExtType@ItemExtInfo -const ItemConf::Index_ItemExtInfoMap& ItemConf::FindItemExtInfoMap() const { return index_item_ext_info_map_ ;} +const ItemConf::Index_ItemExtInfoMap& ItemConf::FindItemExtInfoMap() const { return index_item_ext_info_map_; } const ItemConf::Index_ItemExtInfoVector* ItemConf::FindItemExtInfo(protoconf::FruitType ext_type) const { auto iter = index_item_ext_info_map_.find(ext_type); @@ -232,7 +232,7 @@ const protoconf::ItemConf::Item* ItemConf::FindFirstItemExtInfo(protoconf::Fruit } // Index: (ID,Name)@AwardItem -const ItemConf::Index_AwardItemMap& ItemConf::FindAwardItemMap() const { return index_award_item_map_ ;} +const ItemConf::Index_AwardItemMap& ItemConf::FindAwardItemMap() const { return index_award_item_map_; } const ItemConf::Index_AwardItemVector* ItemConf::FindAwardItem(uint32_t id, const std::string& name) const { auto iter = index_award_item_map_.find({id, name}); @@ -251,7 +251,7 @@ const protoconf::ItemConf::Item* ItemConf::FindFirstAwardItem(uint32_t id, const } // Index: (ID,Type,Param,ExtType)@SpecialItem -const ItemConf::Index_SpecialItemMap& ItemConf::FindSpecialItemMap() const { return index_special_item_map_ ;} +const ItemConf::Index_SpecialItemMap& ItemConf::FindSpecialItemMap() const { return index_special_item_map_; } const ItemConf::Index_SpecialItemVector* ItemConf::FindSpecialItem(uint32_t id, protoconf::FruitType type, int32_t param, protoconf::FruitType ext_type) const { auto iter = index_special_item_map_.find({id, type, param, ext_type}); @@ -270,7 +270,7 @@ const protoconf::ItemConf::Item* ItemConf::FindFirstSpecialItem(uint32_t id, pro } // Index: PathDir@ItemPathDir -const ItemConf::Index_ItemPathDirMap& ItemConf::FindItemPathDirMap() const { return index_item_path_dir_map_ ;} +const ItemConf::Index_ItemPathDirMap& ItemConf::FindItemPathDirMap() const { return index_item_path_dir_map_; } const ItemConf::Index_ItemPathDirVector* ItemConf::FindItemPathDir(const std::string& dir) const { auto iter = index_item_path_dir_map_.find(dir); @@ -289,7 +289,7 @@ const protoconf::ItemConf::Item* ItemConf::FindFirstItemPathDir(const std::strin } // Index: PathName@ItemPathName -const ItemConf::Index_ItemPathNameMap& ItemConf::FindItemPathNameMap() const { return index_item_path_name_map_ ;} +const ItemConf::Index_ItemPathNameMap& ItemConf::FindItemPathNameMap() const { return index_item_path_name_map_; } const ItemConf::Index_ItemPathNameVector* ItemConf::FindItemPathName(const std::string& name) const { auto iter = index_item_path_name_map_.find(name); @@ -308,7 +308,7 @@ const protoconf::ItemConf::Item* ItemConf::FindFirstItemPathName(const std::stri } // Index: PathFriendID@ItemPathFriendID -const ItemConf::Index_ItemPathFriendIDMap& ItemConf::FindItemPathFriendIDMap() const { return index_item_path_friend_id_map_ ;} +const ItemConf::Index_ItemPathFriendIDMap& ItemConf::FindItemPathFriendIDMap() const { return index_item_path_friend_id_map_; } const ItemConf::Index_ItemPathFriendIDVector* ItemConf::FindItemPathFriendID(uint32_t id) const { auto iter = index_item_path_friend_id_map_.find(id); @@ -327,7 +327,7 @@ const protoconf::ItemConf::Item* ItemConf::FindFirstItemPathFriendID(uint32_t id } // Index: UseEffectType@UseEffectType -const ItemConf::Index_UseEffectTypeMap& ItemConf::FindUseEffectTypeMap() const { return index_use_effect_type_map_ ;} +const ItemConf::Index_UseEffectTypeMap& ItemConf::FindUseEffectTypeMap() const { return index_use_effect_type_map_; } const ItemConf::Index_UseEffectTypeVector* ItemConf::FindUseEffectType(protoconf::UseEffect::Type type) const { auto iter = index_use_effect_type_map_.find(type); @@ -346,7 +346,7 @@ const protoconf::ItemConf::Item* ItemConf::FindFirstUseEffectType(protoconf::Use } // OrderedIndex: ExtType@ExtType -const ItemConf::OrderedIndex_ExtTypeMap& ItemConf::FindExtTypeMap() const { return ordered_index_ext_type_map_ ;} +const ItemConf::OrderedIndex_ExtTypeMap& ItemConf::FindExtTypeMap() const { return ordered_index_ext_type_map_; } const ItemConf::OrderedIndex_ExtTypeVector* ItemConf::FindExtType(protoconf::FruitType ext_type) const { auto iter = ordered_index_ext_type_map_.find(ext_type); @@ -365,7 +365,7 @@ const protoconf::ItemConf::Item* ItemConf::FindFirstExtType(protoconf::FruitType } // OrderedIndex: (Param,ExtType)@ParamExtType -const ItemConf::OrderedIndex_ParamExtTypeMap& ItemConf::FindParamExtTypeMap() const { return ordered_index_param_ext_type_map_ ;} +const ItemConf::OrderedIndex_ParamExtTypeMap& ItemConf::FindParamExtTypeMap() const { return ordered_index_param_ext_type_map_; } const ItemConf::OrderedIndex_ParamExtTypeVector* ItemConf::FindParamExtType(int32_t param, protoconf::FruitType ext_type) const { auto iter = ordered_index_param_ext_type_map_.find({param, ext_type}); diff --git a/test/cpp-tableau-loader/src/protoconf/item_conf.pc.h b/test/cpp-tableau-loader/src/protoconf/item_conf.pc.h index 543816b2..7761b547 100644 --- a/test/cpp-tableau-loader/src/protoconf/item_conf.pc.h +++ b/test/cpp-tableau-loader/src/protoconf/item_conf.pc.h @@ -19,6 +19,7 @@ class ItemConf : public Messager { virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; const protoconf::ItemConf& Data() const { return data_; } const google::protobuf::Message* Message() const override { return &data_; } + virtual ~ItemConf() = default; private: virtual bool ProcessAfterLoad() override final; diff --git a/test/cpp-tableau-loader/src/protoconf/patch_conf.pc.h b/test/cpp-tableau-loader/src/protoconf/patch_conf.pc.h index 1c19060a..ce78208c 100644 --- a/test/cpp-tableau-loader/src/protoconf/patch_conf.pc.h +++ b/test/cpp-tableau-loader/src/protoconf/patch_conf.pc.h @@ -19,6 +19,7 @@ class PatchReplaceConf : public Messager { virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; const protoconf::PatchReplaceConf& Data() const { return data_; } const google::protobuf::Message* Message() const override { return &data_; } + virtual ~PatchReplaceConf() = default; private: @@ -32,6 +33,7 @@ class PatchMergeConf : public Messager { virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; const protoconf::PatchMergeConf& Data() const { return data_; } const google::protobuf::Message* Message() const override { return &data_; } + virtual ~PatchMergeConf() = default; public: const protoconf::Item* Get(uint32_t id) const; @@ -47,6 +49,7 @@ class RecursivePatchConf : public Messager { virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; const protoconf::RecursivePatchConf& Data() const { return data_; } const google::protobuf::Message* Message() const override { return &data_; } + virtual ~RecursivePatchConf() = default; public: const protoconf::RecursivePatchConf::Shop* Get(uint32_t shop_id) const; diff --git a/test/cpp-tableau-loader/src/protoconf/test_conf.pc.cc b/test/cpp-tableau-loader/src/protoconf/test_conf.pc.cc index bcd76c15..f3a2ac66 100644 --- a/test/cpp-tableau-loader/src/protoconf/test_conf.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/test_conf.pc.cc @@ -179,7 +179,7 @@ const ActivityConf::OrderedMap_int32Map* ActivityConf::GetOrderedMap(uint64_t ac } // Index: ActivityName -const ActivityConf::Index_ActivityMap& ActivityConf::FindActivityMap() const { return index_activity_map_ ;} +const ActivityConf::Index_ActivityMap& ActivityConf::FindActivityMap() const { return index_activity_map_; } const ActivityConf::Index_ActivityVector* ActivityConf::FindActivity(const std::string& activity_name) const { auto iter = index_activity_map_.find(activity_name); @@ -198,7 +198,7 @@ const protoconf::ActivityConf::Activity* ActivityConf::FindFirstActivity(const s } // Index: ChapterID -const ActivityConf::Index_ChapterMap& ActivityConf::FindChapterMap() const { return index_chapter_map_ ;} +const ActivityConf::Index_ChapterMap& ActivityConf::FindChapterMap() const { return index_chapter_map_; } const ActivityConf::Index_ChapterVector* ActivityConf::FindChapter(uint32_t chapter_id) const { auto iter = index_chapter_map_.find(chapter_id); @@ -245,7 +245,7 @@ const protoconf::ActivityConf::Activity::Chapter* ActivityConf::FindFirstChapter } // Index: ChapterName@NamedChapter -const ActivityConf::Index_NamedChapterMap& ActivityConf::FindNamedChapterMap() const { return index_named_chapter_map_ ;} +const ActivityConf::Index_NamedChapterMap& ActivityConf::FindNamedChapterMap() const { return index_named_chapter_map_; } const ActivityConf::Index_NamedChapterVector* ActivityConf::FindNamedChapter(const std::string& chapter_name) const { auto iter = index_named_chapter_map_.find(chapter_name); @@ -292,7 +292,7 @@ const protoconf::ActivityConf::Activity::Chapter* ActivityConf::FindFirstNamedCh } // Index: SectionItemID@Award -const ActivityConf::Index_AwardMap& ActivityConf::FindAwardMap() const { return index_award_map_ ;} +const ActivityConf::Index_AwardMap& ActivityConf::FindAwardMap() const { return index_award_map_; } const ActivityConf::Index_AwardVector* ActivityConf::FindAward(uint32_t id) const { auto iter = index_award_map_.find(id); @@ -501,7 +501,7 @@ const protoconf::TaskConf::Task* TaskConf::Get(int64_t id) const { } // Index: ActivityID -const TaskConf::Index_TaskMap& TaskConf::FindTaskMap() const { return index_task_map_ ;} +const TaskConf::Index_TaskMap& TaskConf::FindTaskMap() const { return index_task_map_; } const TaskConf::Index_TaskVector* TaskConf::FindTask(int64_t activity_id) const { auto iter = index_task_map_.find(activity_id); @@ -520,7 +520,7 @@ const protoconf::TaskConf::Task* TaskConf::FindFirstTask(int64_t activity_id) co } // OrderedIndex: Goal@OrderedTask -const TaskConf::OrderedIndex_OrderedTaskMap& TaskConf::FindOrderedTaskMap() const { return ordered_index_ordered_task_map_ ;} +const TaskConf::OrderedIndex_OrderedTaskMap& TaskConf::FindOrderedTaskMap() const { return ordered_index_ordered_task_map_; } const TaskConf::OrderedIndex_OrderedTaskVector* TaskConf::FindOrderedTask(int64_t goal) const { auto iter = ordered_index_ordered_task_map_.find(goal); @@ -539,7 +539,7 @@ const protoconf::TaskConf::Task* TaskConf::FindFirstOrderedTask(int64_t goal) co } // OrderedIndex: Expiry@TaskExpiry -const TaskConf::OrderedIndex_TaskExpiryMap& TaskConf::FindTaskExpiryMap() const { return ordered_index_task_expiry_map_ ;} +const TaskConf::OrderedIndex_TaskExpiryMap& TaskConf::FindTaskExpiryMap() const { return ordered_index_task_expiry_map_; } const TaskConf::OrderedIndex_TaskExpiryVector* TaskConf::FindTaskExpiry(int64_t expiry) const { auto iter = ordered_index_task_expiry_map_.find(expiry); @@ -558,7 +558,7 @@ const protoconf::TaskConf::Task* TaskConf::FindFirstTaskExpiry(int64_t expiry) c } // OrderedIndex: Expiry@SortedTaskExpiry -const TaskConf::OrderedIndex_SortedTaskExpiryMap& TaskConf::FindSortedTaskExpiryMap() const { return ordered_index_sorted_task_expiry_map_ ;} +const TaskConf::OrderedIndex_SortedTaskExpiryMap& TaskConf::FindSortedTaskExpiryMap() const { return ordered_index_sorted_task_expiry_map_; } const TaskConf::OrderedIndex_SortedTaskExpiryVector* TaskConf::FindSortedTaskExpiry(int64_t expiry) const { auto iter = ordered_index_sorted_task_expiry_map_.find(expiry); @@ -577,7 +577,7 @@ const protoconf::TaskConf::Task* TaskConf::FindFirstSortedTaskExpiry(int64_t exp } // OrderedIndex: (Expiry,ActivityID)@ActivityExpiry -const TaskConf::OrderedIndex_ActivityExpiryMap& TaskConf::FindActivityExpiryMap() const { return ordered_index_activity_expiry_map_ ;} +const TaskConf::OrderedIndex_ActivityExpiryMap& TaskConf::FindActivityExpiryMap() const { return ordered_index_activity_expiry_map_; } const TaskConf::OrderedIndex_ActivityExpiryVector* TaskConf::FindActivityExpiry(int64_t expiry, int64_t activity_id) const { auto iter = ordered_index_activity_expiry_map_.find({expiry, activity_id}); diff --git a/test/cpp-tableau-loader/src/protoconf/test_conf.pc.h b/test/cpp-tableau-loader/src/protoconf/test_conf.pc.h index c6b68a68..a099ed4e 100644 --- a/test/cpp-tableau-loader/src/protoconf/test_conf.pc.h +++ b/test/cpp-tableau-loader/src/protoconf/test_conf.pc.h @@ -19,6 +19,7 @@ class ActivityConf : public Messager { virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; const protoconf::ActivityConf& Data() const { return data_; } const google::protobuf::Message* Message() const override { return &data_; } + virtual ~ActivityConf() = default; private: virtual bool ProcessAfterLoad() override final; @@ -176,6 +177,7 @@ class ChapterConf : public Messager { virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; const protoconf::ChapterConf& Data() const { return data_; } const google::protobuf::Message* Message() const override { return &data_; } + virtual ~ChapterConf() = default; public: const protoconf::ChapterConf::Chapter* Get(uint64_t id) const; @@ -191,6 +193,7 @@ class ThemeConf : public Messager { virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; const protoconf::ThemeConf& Data() const { return data_; } const google::protobuf::Message* Message() const override { return &data_; } + virtual ~ThemeConf() = default; public: const protoconf::ThemeConf::Theme* Get(const std::string& name) const; @@ -207,6 +210,7 @@ class TaskConf : public Messager { virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; const protoconf::TaskConf& Data() const { return data_; } const google::protobuf::Message* Message() const override { return &data_; } + virtual ~TaskConf() = default; private: virtual bool ProcessAfterLoad() override final; diff --git a/test/go-tableau-loader/protoconf/loader/hub.pc.go b/test/go-tableau-loader/protoconf/loader/hub.pc.go index 39e845f3..f4df4d73 100644 --- a/test/go-tableau-loader/protoconf/loader/hub.pc.go +++ b/test/go-tableau-loader/protoconf/loader/hub.pc.go @@ -232,6 +232,10 @@ func (h *Hub) GetFruit3Conf() *Fruit3Conf { return h.mc.Load().GetFruit3Conf() } +func (h *Hub) GetFruit4Conf() *Fruit4Conf { + return h.mc.Load().GetFruit4Conf() +} + func (h *Hub) GetItemConf() *ItemConf { return h.mc.Load().GetItemConf() } diff --git a/test/go-tableau-loader/protoconf/loader/index_conf.pc.go b/test/go-tableau-loader/protoconf/loader/index_conf.pc.go index 0be9152c..839f16f5 100644 --- a/test/go-tableau-loader/protoconf/loader/index_conf.pc.go +++ b/test/go-tableau-loader/protoconf/loader/index_conf.pc.go @@ -696,6 +696,430 @@ func (x *Fruit3Conf) FindFirstItem(price int32) *protoconf.Fruit3Conf_Fruit_Coun return nil } +// LevelIndex keys. +type Fruit4Conf_LevelIndex_Fruit_CountryKey struct { + FruitType int32 + Id int32 +} + +// Index types. +// Index: CountryName +type Fruit4Conf_Index_CountryMap = map[string][]*protoconf.Fruit4Conf_Fruit_Country + +// Index: CountryItemAttrName +type Fruit4Conf_Index_AttrMap = map[string][]*protoconf.Fruit4Conf_Fruit_Country_Item_Attr + +// OrderedIndex types. +// OrderedIndex: CountryItemPrice +type Fruit4Conf_OrderedIndex_ItemMap = treemap.TreeMap[int32, []*protoconf.Fruit4Conf_Fruit_Country_Item] + +// Fruit4Conf is a wrapper around protobuf message: protoconf.Fruit4Conf. +// +// It is designed for three goals: +// +// 1. Easy use: simple yet powerful accessers. +// 2. Elegant API: concise and clean functions. +// 3. Extensibility: Map, OrdererdMap, Index, OrderedIndex... +type Fruit4Conf struct { + UnimplementedMessager + data, originalData *protoconf.Fruit4Conf + indexCountryMap Fruit4Conf_Index_CountryMap + indexCountryMap1 map[int32]Fruit4Conf_Index_CountryMap + indexAttrMap Fruit4Conf_Index_AttrMap + indexAttrMap1 map[int32]Fruit4Conf_Index_AttrMap + indexAttrMap2 map[Fruit4Conf_LevelIndex_Fruit_CountryKey]Fruit4Conf_Index_AttrMap + orderedIndexItemMap *Fruit4Conf_OrderedIndex_ItemMap + orderedIndexItemMap1 map[int32]*Fruit4Conf_OrderedIndex_ItemMap + orderedIndexItemMap2 map[Fruit4Conf_LevelIndex_Fruit_CountryKey]*Fruit4Conf_OrderedIndex_ItemMap +} + +// Name returns the Fruit4Conf's message name. +func (x *Fruit4Conf) Name() string { + return string((*protoconf.Fruit4Conf)(nil).ProtoReflect().Descriptor().Name()) +} + +// Data returns the Fruit4Conf's inner message data. +func (x *Fruit4Conf) Data() *protoconf.Fruit4Conf { + if x != nil { + return x.data + } + return nil +} + +// Load loads Fruit4Conf's content in the given dir, based on format and messager options. +func (x *Fruit4Conf) Load(dir string, format format.Format, opts *load.MessagerOptions) error { + start := time.Now() + defer func() { + x.Stats.Duration = time.Since(start) + }() + x.data = &protoconf.Fruit4Conf{} + err := load.LoadMessagerInDir(x.data, dir, format, opts) + if err != nil { + return err + } + if x.backup { + x.originalData = proto.Clone(x.data).(*protoconf.Fruit4Conf) + } + return x.processAfterLoad() +} + +// Store stores Fruit4Conf's content to file in the specified directory and format. +// Available formats: JSON, Bin, and Text. +func (x *Fruit4Conf) Store(dir string, format format.Format, options ...store.Option) error { + return store.Store(x.Data(), dir, format, options...) +} + +// Message returns the Fruit4Conf's inner message data. +func (x *Fruit4Conf) Message() proto.Message { + return x.Data() +} + +// Messager returns the current messager. +func (x *Fruit4Conf) Messager() Messager { + return x +} + +// originalMessage returns the Fruit4Conf's original inner message. +func (x *Fruit4Conf) originalMessage() proto.Message { + if x != nil { + return x.originalData + } + return nil +} + +// processAfterLoad runs after this messager is loaded. +func (x *Fruit4Conf) processAfterLoad() error { + // Index init. + x.indexCountryMap = make(Fruit4Conf_Index_CountryMap) + x.indexCountryMap1 = make(map[int32]Fruit4Conf_Index_CountryMap) + x.indexAttrMap = make(Fruit4Conf_Index_AttrMap) + x.indexAttrMap1 = make(map[int32]Fruit4Conf_Index_AttrMap) + x.indexAttrMap2 = make(map[Fruit4Conf_LevelIndex_Fruit_CountryKey]Fruit4Conf_Index_AttrMap) + for k1, v1 := range x.data.GetFruitMap() { + _ = k1 + for k2, v2 := range v1.GetCountryMap() { + _ = k2 + { + // Index: CountryName + key := v2.GetName() + x.indexCountryMap[key] = append(x.indexCountryMap[key], v2) + if x.indexCountryMap1[k1] == nil { + x.indexCountryMap1[k1] = make(Fruit4Conf_Index_CountryMap) + } + x.indexCountryMap1[k1][key] = append(x.indexCountryMap1[k1][key], v2) + } + for k3, v3 := range v2.GetItemMap() { + _ = k3 + for _, v4 := range v3.GetAttrList() { + { + // Index: CountryItemAttrName + key := v4.GetName() + x.indexAttrMap[key] = append(x.indexAttrMap[key], v4) + if x.indexAttrMap1[k1] == nil { + x.indexAttrMap1[k1] = make(Fruit4Conf_Index_AttrMap) + } + x.indexAttrMap1[k1][key] = append(x.indexAttrMap1[k1][key], v4) + indexAttrMap2Keys := Fruit4Conf_LevelIndex_Fruit_CountryKey{k1, k2} + if x.indexAttrMap2[indexAttrMap2Keys] == nil { + x.indexAttrMap2[indexAttrMap2Keys] = make(Fruit4Conf_Index_AttrMap) + } + x.indexAttrMap2[indexAttrMap2Keys][key] = append(x.indexAttrMap2[indexAttrMap2Keys][key], v4) + } + } + } + } + } + // OrderedIndex init. + x.orderedIndexItemMap = treemap.New[int32, []*protoconf.Fruit4Conf_Fruit_Country_Item]() + x.orderedIndexItemMap1 = make(map[int32]*Fruit4Conf_OrderedIndex_ItemMap) + x.orderedIndexItemMap2 = make(map[Fruit4Conf_LevelIndex_Fruit_CountryKey]*Fruit4Conf_OrderedIndex_ItemMap) + for k1, v1 := range x.data.GetFruitMap() { + _ = k1 + for k2, v2 := range v1.GetCountryMap() { + _ = k2 + for k3, v3 := range v2.GetItemMap() { + _ = k3 + { + // OrderedIndex: CountryItemPrice + key := v3.GetPrice() + value, _ := x.orderedIndexItemMap.Get(key) + x.orderedIndexItemMap.Put(key, append(value, v3)) + if x.orderedIndexItemMap1[k1] == nil { + x.orderedIndexItemMap1[k1] = treemap.New[int32, []*protoconf.Fruit4Conf_Fruit_Country_Item]() + } + orderedIndexItemMap1Value, _ := x.orderedIndexItemMap1[k1].Get(key) + x.orderedIndexItemMap1[k1].Put(key, append(orderedIndexItemMap1Value, v3)) + orderedIndexItemMap2Keys := Fruit4Conf_LevelIndex_Fruit_CountryKey{k1, k2} + if x.orderedIndexItemMap2[orderedIndexItemMap2Keys] == nil { + x.orderedIndexItemMap2[orderedIndexItemMap2Keys] = treemap.New[int32, []*protoconf.Fruit4Conf_Fruit_Country_Item]() + } + orderedIndexItemMap2Value, _ := x.orderedIndexItemMap2[orderedIndexItemMap2Keys].Get(key) + x.orderedIndexItemMap2[orderedIndexItemMap2Keys].Put(key, append(orderedIndexItemMap2Value, v3)) + } + } + } + } + // OrderedIndex(sort): CountryItemPrice + orderedIndexItemMapSorter := func(itemList []*protoconf.Fruit4Conf_Fruit_Country_Item) func(i, j int) bool { + return func(i, j int) bool { + return itemList[i].GetId() < itemList[j].GetId() + } + } + x.orderedIndexItemMap.Range(func(key int32, itemList []*protoconf.Fruit4Conf_Fruit_Country_Item) bool { + sort.Slice(itemList, orderedIndexItemMapSorter(itemList)) + return true + }) + for _, itemMap := range x.orderedIndexItemMap1 { + itemMap.Range(func(key int32, itemList []*protoconf.Fruit4Conf_Fruit_Country_Item) bool { + sort.Slice(itemList, orderedIndexItemMapSorter(itemList)) + return true + }) + } + for _, itemMap := range x.orderedIndexItemMap2 { + itemMap.Range(func(key int32, itemList []*protoconf.Fruit4Conf_Fruit_Country_Item) bool { + sort.Slice(itemList, orderedIndexItemMapSorter(itemList)) + return true + }) + } + return nil +} + +// Get1 finds value in the 1st-level map. It will return +// NotFound error if the key is not found. +func (x *Fruit4Conf) Get1(fruitType int32) (*protoconf.Fruit4Conf_Fruit, error) { + d := x.Data().GetFruitMap() + if val, ok := d[fruitType]; !ok { + return nil, fmt.Errorf("fruitType(%v) %w", fruitType, ErrNotFound) + } else { + return val, nil + } +} + +// Get2 finds value in the 2nd-level map. It will return +// NotFound error if the key is not found. +func (x *Fruit4Conf) Get2(fruitType int32, id int32) (*protoconf.Fruit4Conf_Fruit_Country, error) { + conf, err := x.Get1(fruitType) + if err != nil { + return nil, err + } + d := conf.GetCountryMap() + if val, ok := d[id]; !ok { + return nil, fmt.Errorf("id(%v) %w", id, ErrNotFound) + } else { + return val, nil + } +} + +// Get3 finds value in the 3rd-level map. It will return +// NotFound error if the key is not found. +func (x *Fruit4Conf) Get3(fruitType int32, id int32, id3 int32) (*protoconf.Fruit4Conf_Fruit_Country_Item, error) { + conf, err := x.Get2(fruitType, id) + if err != nil { + return nil, err + } + d := conf.GetItemMap() + if val, ok := d[id3]; !ok { + return nil, fmt.Errorf("id3(%v) %w", id3, ErrNotFound) + } else { + return val, nil + } +} + +// Index: CountryName + +// FindCountryMap finds the index: key(CountryName) to value(protoconf.Fruit4Conf_Fruit_Country) map. +// One key may correspond to multiple values, which are represented by a slice. +func (x *Fruit4Conf) FindCountryMap() Fruit4Conf_Index_CountryMap { + return x.indexCountryMap +} + +// FindCountry finds a slice of all values of the given key(s). +func (x *Fruit4Conf) FindCountry(name string) []*protoconf.Fruit4Conf_Fruit_Country { + return x.indexCountryMap[name] +} + +// FindFirstCountry finds the first value of the given key(s), +// or nil if no value found. +func (x *Fruit4Conf) FindFirstCountry(name string) *protoconf.Fruit4Conf_Fruit_Country { + val := x.FindCountry(name) + if len(val) > 0 { + return val[0] + } + return nil +} + +// FindCountryMap1 finds the index: key(CountryName) to value(protoconf.Fruit4Conf_Fruit_Country), +// which is the upper 1st-level map specified by (fruitType). +// One key may correspond to multiple values, which are represented by a slice. +func (x *Fruit4Conf) FindCountryMap1(fruitType int32) Fruit4Conf_Index_CountryMap { + return x.indexCountryMap1[fruitType] +} + +// FindCountry1 finds a slice of all values of the given key(s) in the upper 1st-level map +// specified by (fruitType). +func (x *Fruit4Conf) FindCountry1(fruitType int32, name string) []*protoconf.Fruit4Conf_Fruit_Country { + return x.FindCountryMap1(fruitType)[name] +} + +// FindFirstCountry1 finds the first value of the given key(s) in the upper 1st-level map +// specified by (fruitType), or nil if no value found. +func (x *Fruit4Conf) FindFirstCountry1(fruitType int32, name string) *protoconf.Fruit4Conf_Fruit_Country { + val := x.FindCountry1(fruitType, name) + if len(val) > 0 { + return val[0] + } + return nil +} + +// Index: CountryItemAttrName + +// FindAttrMap finds the index: key(CountryItemAttrName) to value(protoconf.Fruit4Conf_Fruit_Country_Item_Attr) map. +// One key may correspond to multiple values, which are represented by a slice. +func (x *Fruit4Conf) FindAttrMap() Fruit4Conf_Index_AttrMap { + return x.indexAttrMap +} + +// FindAttr finds a slice of all values of the given key(s). +func (x *Fruit4Conf) FindAttr(name string) []*protoconf.Fruit4Conf_Fruit_Country_Item_Attr { + return x.indexAttrMap[name] +} + +// FindFirstAttr finds the first value of the given key(s), +// or nil if no value found. +func (x *Fruit4Conf) FindFirstAttr(name string) *protoconf.Fruit4Conf_Fruit_Country_Item_Attr { + val := x.FindAttr(name) + if len(val) > 0 { + return val[0] + } + return nil +} + +// FindAttrMap1 finds the index: key(CountryItemAttrName) to value(protoconf.Fruit4Conf_Fruit_Country_Item_Attr), +// which is the upper 1st-level map specified by (fruitType). +// One key may correspond to multiple values, which are represented by a slice. +func (x *Fruit4Conf) FindAttrMap1(fruitType int32) Fruit4Conf_Index_AttrMap { + return x.indexAttrMap1[fruitType] +} + +// FindAttr1 finds a slice of all values of the given key(s) in the upper 1st-level map +// specified by (fruitType). +func (x *Fruit4Conf) FindAttr1(fruitType int32, name string) []*protoconf.Fruit4Conf_Fruit_Country_Item_Attr { + return x.FindAttrMap1(fruitType)[name] +} + +// FindFirstAttr1 finds the first value of the given key(s) in the upper 1st-level map +// specified by (fruitType), or nil if no value found. +func (x *Fruit4Conf) FindFirstAttr1(fruitType int32, name string) *protoconf.Fruit4Conf_Fruit_Country_Item_Attr { + val := x.FindAttr1(fruitType, name) + if len(val) > 0 { + return val[0] + } + return nil +} + +// FindAttrMap2 finds the index: key(CountryItemAttrName) to value(protoconf.Fruit4Conf_Fruit_Country_Item_Attr), +// which is the upper 2nd-level map specified by (fruitType, id). +// One key may correspond to multiple values, which are represented by a slice. +func (x *Fruit4Conf) FindAttrMap2(fruitType int32, id int32) Fruit4Conf_Index_AttrMap { + return x.indexAttrMap2[Fruit4Conf_LevelIndex_Fruit_CountryKey{fruitType, id}] +} + +// FindAttr2 finds a slice of all values of the given key(s) in the upper 2nd-level map +// specified by (fruitType, id). +func (x *Fruit4Conf) FindAttr2(fruitType int32, id int32, name string) []*protoconf.Fruit4Conf_Fruit_Country_Item_Attr { + return x.FindAttrMap2(fruitType, id)[name] +} + +// FindFirstAttr2 finds the first value of the given key(s) in the upper 2nd-level map +// specified by (fruitType, id), or nil if no value found. +func (x *Fruit4Conf) FindFirstAttr2(fruitType int32, id int32, name string) *protoconf.Fruit4Conf_Fruit_Country_Item_Attr { + val := x.FindAttr2(fruitType, id, name) + if len(val) > 0 { + return val[0] + } + return nil +} + +// OrderedIndex: CountryItemPrice + +// FindItemMap finds the ordered index: key(CountryItemPrice) to value(protoconf.Fruit4Conf_Fruit_Country_Item) treemap. +// One key may correspond to multiple values, which are represented by a slice. +func (x *Fruit4Conf) FindItemMap() *Fruit4Conf_OrderedIndex_ItemMap { + return x.orderedIndexItemMap +} + +// FindItem finds a slice of all values of the given key(s). +func (x *Fruit4Conf) FindItem(price int32) []*protoconf.Fruit4Conf_Fruit_Country_Item { + val, _ := x.orderedIndexItemMap.Get(price) + return val +} + +// FindFirstItem finds the first value of the given key(s), +// or nil if no value found. +func (x *Fruit4Conf) FindFirstItem(price int32) *protoconf.Fruit4Conf_Fruit_Country_Item { + val := x.FindItem(price) + if len(val) > 0 { + return val[0] + } + return nil +} + +// FindItemMap1 finds the index: key(CountryItemPrice) to value(protoconf.Fruit4Conf_Fruit_Country_Item), +// which is the upper 1st-level treemap specified by (fruitType). +// One key may correspond to multiple values, which are represented by a slice. +func (x *Fruit4Conf) FindItemMap1(fruitType int32) *Fruit4Conf_OrderedIndex_ItemMap { + return x.orderedIndexItemMap1[fruitType] +} + +// FindItem1 finds a slice of all values of the given key(s) in the upper 1st-level treemap +// specified by (fruitType). +func (x *Fruit4Conf) FindItem1(fruitType int32, price int32) []*protoconf.Fruit4Conf_Fruit_Country_Item { + m := x.FindItemMap1(fruitType) + if m == nil { + return nil + } + val, _ := m.Get(price) + return val +} + +// FindFirstItem1 finds the first value of the given key(s) in the upper 1st-level treemap +// specified by (fruitType), or nil if no value found. +func (x *Fruit4Conf) FindFirstItem1(fruitType int32, price int32) *protoconf.Fruit4Conf_Fruit_Country_Item { + val := x.FindItem1(fruitType, price) + if len(val) > 0 { + return val[0] + } + return nil +} + +// FindItemMap2 finds the index: key(CountryItemPrice) to value(protoconf.Fruit4Conf_Fruit_Country_Item), +// which is the upper 2nd-level treemap specified by (fruitType, id). +// One key may correspond to multiple values, which are represented by a slice. +func (x *Fruit4Conf) FindItemMap2(fruitType int32, id int32) *Fruit4Conf_OrderedIndex_ItemMap { + return x.orderedIndexItemMap2[Fruit4Conf_LevelIndex_Fruit_CountryKey{fruitType, id}] +} + +// FindItem2 finds a slice of all values of the given key(s) in the upper 2nd-level treemap +// specified by (fruitType, id). +func (x *Fruit4Conf) FindItem2(fruitType int32, id int32, price int32) []*protoconf.Fruit4Conf_Fruit_Country_Item { + m := x.FindItemMap2(fruitType, id) + if m == nil { + return nil + } + val, _ := m.Get(price) + return val +} + +// FindFirstItem2 finds the first value of the given key(s) in the upper 2nd-level treemap +// specified by (fruitType, id), or nil if no value found. +func (x *Fruit4Conf) FindFirstItem2(fruitType int32, id int32, price int32) *protoconf.Fruit4Conf_Fruit_Country_Item { + val := x.FindItem2(fruitType, id, price) + if len(val) > 0 { + return val[0] + } + return nil +} + func init() { Register(func() Messager { return new(FruitConf) @@ -706,4 +1130,7 @@ func init() { Register(func() Messager { return new(Fruit3Conf) }) + Register(func() Messager { + return new(Fruit4Conf) + }) } diff --git a/test/go-tableau-loader/protoconf/loader/messager_container.pc.go b/test/go-tableau-loader/protoconf/loader/messager_container.pc.go index e95289d3..e74c69a7 100644 --- a/test/go-tableau-loader/protoconf/loader/messager_container.pc.go +++ b/test/go-tableau-loader/protoconf/loader/messager_container.pc.go @@ -18,6 +18,7 @@ type MessagerContainer struct { fruitConf *FruitConf fruit2Conf *Fruit2Conf fruit3Conf *Fruit3Conf + fruit4Conf *Fruit4Conf itemConf *ItemConf patchReplaceConf *PatchReplaceConf patchMergeConf *PatchMergeConf @@ -37,6 +38,7 @@ func newMessagerContainer(messagerMap MessagerMap) *MessagerContainer { fruitConf: GetMessager[*FruitConf](messagerMap), fruit2Conf: GetMessager[*Fruit2Conf](messagerMap), fruit3Conf: GetMessager[*Fruit3Conf](messagerMap), + fruit4Conf: GetMessager[*Fruit4Conf](messagerMap), itemConf: GetMessager[*ItemConf](messagerMap), patchReplaceConf: GetMessager[*PatchReplaceConf](messagerMap), patchMergeConf: GetMessager[*PatchMergeConf](messagerMap), @@ -82,6 +84,10 @@ func (mc *MessagerContainer) GetFruit3Conf() *Fruit3Conf { return mc.fruit3Conf } +func (mc *MessagerContainer) GetFruit4Conf() *Fruit4Conf { + return mc.fruit4Conf +} + func (mc *MessagerContainer) GetItemConf() *ItemConf { return mc.itemConf } diff --git a/test/proto/index_conf.proto b/test/proto/index_conf.proto index f990160f..2ac16a4a 100644 --- a/test/proto/index_conf.proto +++ b/test/proto/index_conf.proto @@ -42,8 +42,9 @@ message Fruit2Conf { protoconf.FruitType fruit_type = 1 [(tableau.field) = { name: "FruitType" }]; repeated Country country_list = 2 [(tableau.field) = { name: "Country" layout: LAYOUT_HORIZONTAL }]; message Country { - string name = 1 [(tableau.field) = { name: "Name" }]; - map item_map = 2 [(tableau.field) = { name: "Item" key: "ID" layout: LAYOUT_HORIZONTAL }]; + int32 id = 1 [(tableau.field) = { name: "ID" }]; + string name = 2 [(tableau.field) = { name: "Name" }]; + map item_map = 3 [(tableau.field) = { name: "Item" key: "ID" layout: LAYOUT_HORIZONTAL }]; message Item { int32 id = 1 [(tableau.field) = { name: "ID" }]; int32 price = 2 [(tableau.field) = { name: "Price" }]; @@ -71,8 +72,39 @@ message Fruit3Conf { protoconf.FruitType fruit_type = 1 [(tableau.field) = { name: "FruitType" }]; repeated Country country_list = 2 [(tableau.field) = { name: "Country" layout: LAYOUT_HORIZONTAL }]; message Country { - string name = 1 [(tableau.field) = { name: "Name" }]; - map item_map = 2 [(tableau.field) = { name: "Item" key: "ID" layout: LAYOUT_HORIZONTAL }]; + int32 id = 1 [(tableau.field) = { name: "ID" }]; + string name = 2 [(tableau.field) = { name: "Name" }]; + map item_map = 3 [(tableau.field) = { name: "Item" key: "ID" layout: LAYOUT_HORIZONTAL }]; + message Item { + int32 id = 1 [(tableau.field) = { name: "ID" }]; + int32 price = 2 [(tableau.field) = { name: "Price" }]; + repeated Attr attr_list = 3 [(tableau.field) = { name: "Attr" layout: LAYOUT_HORIZONTAL }]; + message Attr { + string name = 1 [(tableau.field) = { name: "Name" }]; + int32 value = 2 [(tableau.field) = { name: "Value" }]; + } + } + } + } +} + +// Nesting: map -> map -> map -> list +message Fruit4Conf { + option (tableau.worksheet) = { + name: "Fruit4Conf" + index: "CountryName" + index: "CountryItemAttrName" + ordered_index: "CountryItemPrice" + }; + + map fruit_map = 1 [(tableau.field) = { key: "FruitType" layout: LAYOUT_VERTICAL }]; + message Fruit { + protoconf.FruitType fruit_type = 1 [(tableau.field) = { name: "FruitType" }]; + map country_map = 2 [(tableau.field) = { name: "Country" key: "ID" layout: LAYOUT_HORIZONTAL }]; + message Country { + int32 id = 1 [(tableau.field) = { name: "ID" }]; + string name = 2 [(tableau.field) = { name: "Name" }]; + map item_map = 3 [(tableau.field) = { name: "Item" key: "ID" layout: LAYOUT_HORIZONTAL }]; message Item { int32 id = 1 [(tableau.field) = { name: "ID" }]; int32 price = 2 [(tableau.field) = { name: "Price" }]; diff --git a/test/testdata/conf/Fruit4Conf.json b/test/testdata/conf/Fruit4Conf.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/test/testdata/conf/Fruit4Conf.json @@ -0,0 +1 @@ +{} \ No newline at end of file From 42f644c1378257143b70e2a726782b1b89cba172 Mon Sep 17 00:00:00 2001 From: Kybxd <627940450@qq.com> Date: Fri, 19 Dec 2025 16:21:20 +0800 Subject: [PATCH 3/3] feat(cpp): finalize messagers --- cmd/protoc-gen-cpp-tableau-loader/messager.go | 5 ++--- .../src/protoconf/hero_conf.pc.h | 8 +++----- .../src/protoconf/index_conf.pc.h | 20 ++++++++----------- .../src/protoconf/item_conf.pc.h | 5 ++--- .../src/protoconf/patch_conf.pc.h | 9 +++------ .../src/protoconf/test_conf.pc.h | 16 ++++++--------- 6 files changed, 24 insertions(+), 39 deletions(-) diff --git a/cmd/protoc-gen-cpp-tableau-loader/messager.go b/cmd/protoc-gen-cpp-tableau-loader/messager.go index 4637b216..9c4ff8be 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/messager.go +++ b/cmd/protoc-gen-cpp-tableau-loader/messager.go @@ -86,18 +86,17 @@ func genHppMessage(g *protogen.GeneratedFile, message *protogen.Message) { orderedMapGenerator := orderedmap.NewGenerator(g, message) indexGenerator := indexes.NewGenerator(g, indexDescriptor, message) - g.P("class ", message.Desc.Name(), " : public Messager {") + g.P("class ", message.Desc.Name(), " final : public Messager {") g.P(" public:") g.P(helper.Indent(1), "static const std::string& Name() { return kProtoName; }") g.P(helper.Indent(1), "virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override;") g.P(helper.Indent(1), "const ", cppFullName, "& Data() const { return data_; }") g.P(helper.Indent(1), "const google::protobuf::Message* Message() const override { return &data_; }") - g.P(helper.Indent(1), "virtual ~", message.Desc.Name(), "() = default;") g.P() if orderedMapGenerator.NeedGenerate() || indexGenerator.NeedGenerate() { g.P(" private:") - g.P(helper.Indent(1), "virtual bool ProcessAfterLoad() override final;") + g.P(helper.Indent(1), "virtual bool ProcessAfterLoad() override;") g.P() } diff --git a/test/cpp-tableau-loader/src/protoconf/hero_conf.pc.h b/test/cpp-tableau-loader/src/protoconf/hero_conf.pc.h index 1d993cfe..54a7ccd3 100644 --- a/test/cpp-tableau-loader/src/protoconf/hero_conf.pc.h +++ b/test/cpp-tableau-loader/src/protoconf/hero_conf.pc.h @@ -13,16 +13,15 @@ #include "hero_conf.pb.h" namespace tableau { -class HeroConf : public Messager { +class HeroConf final : public Messager { public: static const std::string& Name() { return kProtoName; } virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; const protoconf::HeroConf& Data() const { return data_; } const google::protobuf::Message* Message() const override { return &data_; } - virtual ~HeroConf() = default; private: - virtual bool ProcessAfterLoad() override final; + virtual bool ProcessAfterLoad() override; public: const protoconf::HeroConf::Hero* Get(const std::string& name) const; @@ -45,13 +44,12 @@ class HeroConf : public Messager { OrderedMap_HeroMap ordered_map_; }; -class HeroBaseConf : public Messager { +class HeroBaseConf final : public Messager { public: static const std::string& Name() { return kProtoName; } virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; const protoconf::HeroBaseConf& Data() const { return data_; } const google::protobuf::Message* Message() const override { return &data_; } - virtual ~HeroBaseConf() = default; public: const base::Hero* Get(const std::string& name) const; diff --git a/test/cpp-tableau-loader/src/protoconf/index_conf.pc.h b/test/cpp-tableau-loader/src/protoconf/index_conf.pc.h index 64c2af5e..a96cc6fb 100644 --- a/test/cpp-tableau-loader/src/protoconf/index_conf.pc.h +++ b/test/cpp-tableau-loader/src/protoconf/index_conf.pc.h @@ -13,16 +13,15 @@ #include "index_conf.pb.h" namespace tableau { -class FruitConf : public Messager { +class FruitConf final : public Messager { public: static const std::string& Name() { return kProtoName; } virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; const protoconf::FruitConf& Data() const { return data_; } const google::protobuf::Message* Message() const override { return &data_; } - virtual ~FruitConf() = default; private: - virtual bool ProcessAfterLoad() override final; + virtual bool ProcessAfterLoad() override; public: const protoconf::FruitConf::Fruit* Get(int32_t fruit_type) const; @@ -58,16 +57,15 @@ class FruitConf : public Messager { std::unordered_map ordered_index_item_map1_; }; -class Fruit2Conf : public Messager { +class Fruit2Conf final : public Messager { public: static const std::string& Name() { return kProtoName; } virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; const protoconf::Fruit2Conf& Data() const { return data_; } const google::protobuf::Message* Message() const override { return &data_; } - virtual ~Fruit2Conf() = default; private: - virtual bool ProcessAfterLoad() override final; + virtual bool ProcessAfterLoad() override; public: const protoconf::Fruit2Conf::Fruit* Get(int32_t fruit_type) const; @@ -142,16 +140,15 @@ class Fruit2Conf : public Messager { std::unordered_map ordered_index_item_map1_; }; -class Fruit3Conf : public Messager { +class Fruit3Conf final : public Messager { public: static const std::string& Name() { return kProtoName; } virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; const protoconf::Fruit3Conf& Data() const { return data_; } const google::protobuf::Message* Message() const override { return &data_; } - virtual ~Fruit3Conf() = default; private: - virtual bool ProcessAfterLoad() override final; + virtual bool ProcessAfterLoad() override; private: @@ -206,16 +203,15 @@ class Fruit3Conf : public Messager { OrderedIndex_ItemMap ordered_index_item_map_; }; -class Fruit4Conf : public Messager { +class Fruit4Conf final : public Messager { public: static const std::string& Name() { return kProtoName; } virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; const protoconf::Fruit4Conf& Data() const { return data_; } const google::protobuf::Message* Message() const override { return &data_; } - virtual ~Fruit4Conf() = default; private: - virtual bool ProcessAfterLoad() override final; + virtual bool ProcessAfterLoad() override; public: const protoconf::Fruit4Conf::Fruit* Get(int32_t fruit_type) const; diff --git a/test/cpp-tableau-loader/src/protoconf/item_conf.pc.h b/test/cpp-tableau-loader/src/protoconf/item_conf.pc.h index 7761b547..22d3ddff 100644 --- a/test/cpp-tableau-loader/src/protoconf/item_conf.pc.h +++ b/test/cpp-tableau-loader/src/protoconf/item_conf.pc.h @@ -13,16 +13,15 @@ #include "item_conf.pb.h" namespace tableau { -class ItemConf : public Messager { +class ItemConf final : public Messager { public: static const std::string& Name() { return kProtoName; } virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; const protoconf::ItemConf& Data() const { return data_; } const google::protobuf::Message* Message() const override { return &data_; } - virtual ~ItemConf() = default; private: - virtual bool ProcessAfterLoad() override final; + virtual bool ProcessAfterLoad() override; public: const protoconf::ItemConf::Item* Get(uint32_t id) const; diff --git a/test/cpp-tableau-loader/src/protoconf/patch_conf.pc.h b/test/cpp-tableau-loader/src/protoconf/patch_conf.pc.h index ce78208c..f9358c8f 100644 --- a/test/cpp-tableau-loader/src/protoconf/patch_conf.pc.h +++ b/test/cpp-tableau-loader/src/protoconf/patch_conf.pc.h @@ -13,13 +13,12 @@ #include "patch_conf.pb.h" namespace tableau { -class PatchReplaceConf : public Messager { +class PatchReplaceConf final : public Messager { public: static const std::string& Name() { return kProtoName; } virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; const protoconf::PatchReplaceConf& Data() const { return data_; } const google::protobuf::Message* Message() const override { return &data_; } - virtual ~PatchReplaceConf() = default; private: @@ -27,13 +26,12 @@ class PatchReplaceConf : public Messager { protoconf::PatchReplaceConf data_; }; -class PatchMergeConf : public Messager { +class PatchMergeConf final : public Messager { public: static const std::string& Name() { return kProtoName; } virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; const protoconf::PatchMergeConf& Data() const { return data_; } const google::protobuf::Message* Message() const override { return &data_; } - virtual ~PatchMergeConf() = default; public: const protoconf::Item* Get(uint32_t id) const; @@ -43,13 +41,12 @@ class PatchMergeConf : public Messager { protoconf::PatchMergeConf data_; }; -class RecursivePatchConf : public Messager { +class RecursivePatchConf final : public Messager { public: static const std::string& Name() { return kProtoName; } virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; const protoconf::RecursivePatchConf& Data() const { return data_; } const google::protobuf::Message* Message() const override { return &data_; } - virtual ~RecursivePatchConf() = default; public: const protoconf::RecursivePatchConf::Shop* Get(uint32_t shop_id) const; diff --git a/test/cpp-tableau-loader/src/protoconf/test_conf.pc.h b/test/cpp-tableau-loader/src/protoconf/test_conf.pc.h index a099ed4e..76de3246 100644 --- a/test/cpp-tableau-loader/src/protoconf/test_conf.pc.h +++ b/test/cpp-tableau-loader/src/protoconf/test_conf.pc.h @@ -13,16 +13,15 @@ #include "test_conf.pb.h" namespace tableau { -class ActivityConf : public Messager { +class ActivityConf final : public Messager { public: static const std::string& Name() { return kProtoName; } virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; const protoconf::ActivityConf& Data() const { return data_; } const google::protobuf::Message* Message() const override { return &data_; } - virtual ~ActivityConf() = default; private: - virtual bool ProcessAfterLoad() override final; + virtual bool ProcessAfterLoad() override; public: const protoconf::ActivityConf::Activity* Get(uint64_t activity_id) const; @@ -171,13 +170,12 @@ class ActivityConf : public Messager { std::unordered_map index_award_map2_; }; -class ChapterConf : public Messager { +class ChapterConf final : public Messager { public: static const std::string& Name() { return kProtoName; } virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; const protoconf::ChapterConf& Data() const { return data_; } const google::protobuf::Message* Message() const override { return &data_; } - virtual ~ChapterConf() = default; public: const protoconf::ChapterConf::Chapter* Get(uint64_t id) const; @@ -187,13 +185,12 @@ class ChapterConf : public Messager { protoconf::ChapterConf data_; }; -class ThemeConf : public Messager { +class ThemeConf final : public Messager { public: static const std::string& Name() { return kProtoName; } virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; const protoconf::ThemeConf& Data() const { return data_; } const google::protobuf::Message* Message() const override { return &data_; } - virtual ~ThemeConf() = default; public: const protoconf::ThemeConf::Theme* Get(const std::string& name) const; @@ -204,16 +201,15 @@ class ThemeConf : public Messager { protoconf::ThemeConf data_; }; -class TaskConf : public Messager { +class TaskConf final : public Messager { public: static const std::string& Name() { return kProtoName; } virtual bool Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options = nullptr) override; const protoconf::TaskConf& Data() const { return data_; } const google::protobuf::Message* Message() const override { return &data_; } - virtual ~TaskConf() = default; private: - virtual bool ProcessAfterLoad() override final; + virtual bool ProcessAfterLoad() override; public: const protoconf::TaskConf::Task* Get(int64_t id) const;