diff --git a/cmd/protoc-gen-cpp-tableau-loader/index.go b/cmd/protoc-gen-cpp-tableau-loader/index.go index ce9f408d..e33ef465 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/index.go +++ b/cmd/protoc-gen-cpp-tableau-loader/index.go @@ -106,14 +106,20 @@ func genCppIndexLoader(g *protogen.GeneratedFile, descriptor *index.IndexDescrip if levelMessage.FD == nil { break } + if !levelMessage.NextLevel.NeedGen() { + break + } g.P(strings.Repeat(" ", depth), "for (auto&& "+itemName+" : "+parentDataName+"."+helper.ParseIndexFieldName(levelMessage.FD)+"()) {") parentDataName = itemName if levelMessage.FD.IsMap() { parentDataName = itemName + ".second" } - defer g.P(strings.Repeat(" ", depth), "}") depth++ } + for i := depth - 1; i > 0; i-- { + g.P(strings.Repeat(" ", i), "}") + } + genIndexSorter(g, descriptor) } func genOneCppIndexLoader(g *protogen.GeneratedFile, depth int, index *index.LevelIndex, parentDataName string) { @@ -148,31 +154,40 @@ func genOneCppIndexLoader(g *protogen.GeneratedFile, depth int, index *index.Lev // multi-column index generateOneCppMulticolumnIndex(g, depth, index, parentDataName, nil) } - if len(index.KeyFields) != 0 { - g.P(strings.Repeat(" ", depth+1), "for (auto&& item : ", indexContainerName, ") {") - g.P(strings.Repeat(" ", depth+2), "std::sort(item.second.begin(), item.second.end(),") - g.P(strings.Repeat(" ", depth+7), "[](const ", helper.ParseCppClassType(index.MD), "* a, const ", helper.ParseCppClassType(index.MD), "* b) {") - for i, field := range index.KeyFields { - fieldName := "" - for i, leveledFd := range field.LeveledFDList { - accessOperator := "." - if i == 0 { - accessOperator = "->" + g.P(strings.Repeat(" ", depth), "}") +} + +func genIndexSorter(g *protogen.GeneratedFile, descriptor *index.IndexDescriptor) { + for levelMessage := descriptor.LevelMessage; levelMessage != nil; levelMessage = levelMessage.NextLevel { + for _, index := range levelMessage.Indexes { + indexContainerName := "index_" + strcase.ToSnake(index.Name()) + "_map_" + if len(index.KeyFields) != 0 { + g.P(" // Index(sort): ", index.Index) + g.P(strings.Repeat(" ", 1), "for (auto&& item : ", indexContainerName, ") {") + g.P(strings.Repeat(" ", 2), "std::sort(item.second.begin(), item.second.end(),") + g.P(strings.Repeat(" ", 7), "[](const ", helper.ParseCppClassType(index.MD), "* a, const ", helper.ParseCppClassType(index.MD), "* b) {") + for i, field := range index.KeyFields { + fieldName := "" + for i, leveledFd := range field.LeveledFDList { + accessOperator := "." + if i == 0 { + accessOperator = "->" + } + fieldName += accessOperator + helper.ParseIndexFieldName(leveledFd) + "()" + } + if i == len(index.KeyFields)-1 { + g.P(strings.Repeat(" ", 8), "return a", fieldName, " < b", fieldName, ";") + } else { + g.P(strings.Repeat(" ", 8), "if (a", fieldName, " != b", fieldName, ") {") + g.P(strings.Repeat(" ", 9), "return a", fieldName, " < b", fieldName, ";") + g.P(strings.Repeat(" ", 8), "}") + } } - fieldName += accessOperator + helper.ParseIndexFieldName(leveledFd) + "()" - } - if i == len(index.KeyFields)-1 { - g.P(strings.Repeat(" ", depth+8), "return a", fieldName, " < b", fieldName, ";") - } else { - g.P(strings.Repeat(" ", depth+8), "if (a", fieldName, " != b", fieldName, ") {") - g.P(strings.Repeat(" ", depth+9), "return a", fieldName, " < b", fieldName, ";") - g.P(strings.Repeat(" ", depth+8), "}") + g.P(strings.Repeat(" ", 7), "});") + g.P(strings.Repeat(" ", 1), "}") } } - g.P(strings.Repeat(" ", depth+7), "});") - g.P(strings.Repeat(" ", depth+1), "}") } - g.P(strings.Repeat(" ", depth), "}") } func generateOneCppMulticolumnIndex(g *protogen.GeneratedFile, depth int, index *index.LevelIndex, parentDataName string, keys []string) []string { diff --git a/cmd/protoc-gen-cpp-tableau-loader/main.go b/cmd/protoc-gen-cpp-tableau-loader/main.go index fcb20e5b..856dbd9c 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/main.go +++ b/cmd/protoc-gen-cpp-tableau-loader/main.go @@ -40,7 +40,6 @@ func main() { - messager: only generate "*.pc.h/cc" for each .proto files. `) shards = flags.Int("shards", 1, "count of generated hub cpp files for distributed compiling speed-up") - flag.Parse() protogen.Options{ ParamFunc: flags.Set, diff --git a/cmd/protoc-gen-go-tableau-loader/index.go b/cmd/protoc-gen-go-tableau-loader/index.go index e61af74b..2e6db04a 100644 --- a/cmd/protoc-gen-go-tableau-loader/index.go +++ b/cmd/protoc-gen-go-tableau-loader/index.go @@ -68,11 +68,17 @@ func genIndexLoader(gen *protogen.Plugin, g *protogen.GeneratedFile, descriptor if levelMessage.FD == nil { break } + if !levelMessage.NextLevel.NeedGen() { + break + } g.P("for _, ", itemName, " := range "+parentDataName+".Get"+helper.ParseIndexFieldName(gen, levelMessage.FD)+"() {") parentDataName = itemName - defer g.P("}") depth++ } + for i := depth - 1; i > 0; i-- { + g.P("}") + } + genIndexSorter(gen, g, descriptor) } func genOneIndexLoader(gen *protogen.Plugin, g *protogen.GeneratedFile, depth int, index *index.LevelIndex, @@ -105,26 +111,35 @@ func genOneIndexLoader(gen *protogen.Plugin, g *protogen.GeneratedFile, depth in // multi-column index generateOneMulticolumnIndex(gen, g, depth, index, parentDataName, messagerName, nil) } - if len(index.KeyFields) != 0 { - g.P("for _, item := range x.", indexContainerName, " {") - g.P(sortPackage.Ident("Slice"), "(item, func(i, j int) bool {") - for i, field := range index.KeyFields { - fieldName := "" - for _, leveledFd := range field.LeveledFDList { - fieldName += ".Get" + helper.ParseIndexFieldName(gen, leveledFd) + "()" - } - if i == len(index.KeyFields)-1 { - g.P("return item[i]", fieldName, " < item[j]", fieldName) - } else { - g.P("if item[i]", fieldName, " != item[j]", fieldName, " {") - g.P("return item[i]", fieldName, " < item[j]", fieldName) + g.P("}") +} + +func genIndexSorter(gen *protogen.Plugin, g *protogen.GeneratedFile, descriptor *index.IndexDescriptor) { + for levelMessage := descriptor.LevelMessage; levelMessage != nil; levelMessage = levelMessage.NextLevel { + for _, index := range levelMessage.Indexes { + indexContainerName := "index" + strcase.ToCamel(index.Name()) + "Map" + if len(index.KeyFields) != 0 { + g.P(" // Index(sort): ", index.Index) + g.P("for _, item := range x.", indexContainerName, " {") + g.P(sortPackage.Ident("Slice"), "(item, func(i, j int) bool {") + for i, field := range index.KeyFields { + fieldName := "" + for _, leveledFd := range field.LeveledFDList { + fieldName += ".Get" + helper.ParseIndexFieldName(gen, leveledFd) + "()" + } + if i == len(index.KeyFields)-1 { + g.P("return item[i]", fieldName, " < item[j]", fieldName) + } else { + g.P("if item[i]", fieldName, " != item[j]", fieldName, " {") + g.P("return item[i]", fieldName, " < item[j]", fieldName) + g.P("}") + } + } + g.P("})") g.P("}") } } - g.P("})") - g.P("}") } - g.P("}") } func generateOneMulticolumnIndex(gen *protogen.Plugin, g *protogen.GeneratedFile, diff --git a/cmd/protoc-gen-go-tableau-loader/main.go b/cmd/protoc-gen-go-tableau-loader/main.go index bb9ebb28..d6199ffc 100644 --- a/cmd/protoc-gen-go-tableau-loader/main.go +++ b/cmd/protoc-gen-go-tableau-loader/main.go @@ -15,7 +15,6 @@ var pkg *string func main() { var flags flag.FlagSet pkg = flags.String("pkg", "tableau", "tableau package name") - flag.Parse() protogen.Options{ ParamFunc: flags.Set, diff --git a/internal/index/descriptor.go b/internal/index/descriptor.go index 808abeb3..a15e6693 100644 --- a/internal/index/descriptor.go +++ b/internal/index/descriptor.go @@ -54,6 +54,13 @@ type LevelMessage struct { Indexes []*LevelIndex } +func (l *LevelMessage) NeedGen() bool { + if l == nil { + return false + } + return len(l.Indexes) != 0 || l.NextLevel.NeedGen() +} + type LevelIndex struct { *Index MD protoreflect.MessageDescriptor 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 98454bc4..d8527ca3 100644 --- a/test/cpp-tableau-loader/src/protoconf/item_conf.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/item_conf.pc.cc @@ -47,12 +47,6 @@ bool ItemConf::ProcessAfterLoad() { for (auto&& item2 : item1.second.param_list()) { index_item_info_map_[item2].push_back(&item1.second); } - for (auto&& item : index_item_info_map_) { - std::sort(item.second.begin(), item.second.end(), - [](const protoconf::ItemConf::Item* a, const protoconf::ItemConf::Item* b) { - return a->id() < b->id(); - }); - } } { // Index: Default@ItemDefaultInfo @@ -68,15 +62,6 @@ bool ItemConf::ProcessAfterLoad() { // Index: (ID,Name)@AwardItem Index_AwardItemKey key{item1.second.id(), item1.second.name()}; index_award_item_map_[key].push_back(&item1.second); - for (auto&& item : index_award_item_map_) { - std::sort(item.second.begin(), item.second.end(), - [](const protoconf::ItemConf::Item* a, const protoconf::ItemConf::Item* b) { - if (a->type() != b->type()) { - return a->type() < b->type(); - } - return a->use_effect().type() < b->use_effect().type(); - }); - } } { // Index: (ID,Type,Param,ExtType)@SpecialItem @@ -106,6 +91,23 @@ bool ItemConf::ProcessAfterLoad() { index_use_effect_type_map_[item1.second.use_effect().type()].push_back(&item1.second); } } + // Index(sort): Param@ItemInfo + for (auto&& item : index_item_info_map_) { + std::sort(item.second.begin(), item.second.end(), + [](const protoconf::ItemConf::Item* a, const protoconf::ItemConf::Item* b) { + return a->id() < b->id(); + }); + } + // Index(sort): (ID,Name)@AwardItem + for (auto&& item : index_award_item_map_) { + std::sort(item.second.begin(), item.second.end(), + [](const protoconf::ItemConf::Item* a, const protoconf::ItemConf::Item* b) { + if (a->type() != b->type()) { + return a->type() < b->type(); + } + return a->use_effect().type() < b->use_effect().type(); + }); + } return true; } 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 0ca93691..be18610c 100644 --- a/test/cpp-tableau-loader/src/protoconf/test_conf.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/test_conf.pc.cc @@ -56,12 +56,6 @@ bool ActivityConf::ProcessAfterLoad() { { // Index: ChapterName@NamedChapter index_named_chapter_map_[item2.second.chapter_name()].push_back(&item2.second); - for (auto&& item : index_named_chapter_map_) { - std::sort(item.second.begin(), item.second.end(), - [](const protoconf::ActivityConf::Activity::Chapter* a, const protoconf::ActivityConf::Activity::Chapter* b) { - return a->award_id() < b->award_id(); - }); - } } for (auto&& item3 : item2.second.section_map()) { for (auto&& item4 : item3.second.section_item_list()) { @@ -73,6 +67,13 @@ bool ActivityConf::ProcessAfterLoad() { } } } + // Index(sort): ChapterName@NamedChapter + for (auto&& item : index_named_chapter_map_) { + std::sort(item.second.begin(), item.second.end(), + [](const protoconf::ActivityConf::Activity::Chapter* a, const protoconf::ActivityConf::Activity::Chapter* b) { + return a->award_id() < b->award_id(); + }); + } return true; } @@ -228,7 +229,7 @@ const ActivityConf::Index_AwardVector* ActivityConf::FindAward(uint32_t id) cons return &iter->second; } -const protoconf::Item* ActivityConf::FindFirstAward(uint32_t id) const { +const protoconf::Section::SectionItem* ActivityConf::FindFirstAward(uint32_t id) const { auto conf = FindAward(id); if (conf == nullptr || conf->size() == 0) { return nullptr; 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 c45246eb..6d434e9d 100644 --- a/test/cpp-tableau-loader/src/protoconf/test_conf.pc.h +++ b/test/cpp-tableau-loader/src/protoconf/test_conf.pc.h @@ -88,11 +88,11 @@ class ActivityConf : public Messager { // Index: SectionItemID@Award public: - using Index_AwardVector = std::vector; + using Index_AwardVector = std::vector; using Index_AwardMap = std::unordered_map; const Index_AwardMap& FindAward() const; const Index_AwardVector* FindAward(uint32_t id) const; - const protoconf::Item* FindFirstAward(uint32_t id) const; + const protoconf::Section::SectionItem* FindFirstAward(uint32_t id) const; private: Index_AwardMap index_award_map_; diff --git a/test/go-tableau-loader/protoconf/loader/item_conf.pc.go b/test/go-tableau-loader/protoconf/loader/item_conf.pc.go index b1ecb52c..432f2d9b 100644 --- a/test/go-tableau-loader/protoconf/loader/item_conf.pc.go +++ b/test/go-tableau-loader/protoconf/loader/item_conf.pc.go @@ -174,11 +174,6 @@ func (x *ItemConf) processAfterLoad() error { key := item2 x.indexItemInfoMap[key] = append(x.indexItemInfoMap[key], item1) } - for _, item := range x.indexItemInfoMap { - sort.Slice(item, func(i, j int) bool { - return item[i].GetId() < item[j].GetId() - }) - } } { // Index: Default@ItemDefaultInfo @@ -196,14 +191,6 @@ func (x *ItemConf) processAfterLoad() error { // Index: (ID,Name)@AwardItem key := ItemConf_Index_AwardItemKey{item1.GetId(), item1.GetName()} x.indexAwardItemMap[key] = append(x.indexAwardItemMap[key], item1) - for _, item := range x.indexAwardItemMap { - sort.Slice(item, func(i, j int) bool { - if item[i].GetType() != item[j].GetType() { - return item[i].GetType() < item[j].GetType() - } - return item[i].GetUseEffect().GetType() < item[j].GetUseEffect().GetType() - }) - } } { // Index: (ID,Type,Param,ExtType)@SpecialItem @@ -237,6 +224,21 @@ func (x *ItemConf) processAfterLoad() error { x.indexUseEffectTypeMap[key] = append(x.indexUseEffectTypeMap[key], item1) } } + // Index(sort): Param@ItemInfo + for _, item := range x.indexItemInfoMap { + sort.Slice(item, func(i, j int) bool { + return item[i].GetId() < item[j].GetId() + }) + } + // Index(sort): (ID,Name)@AwardItem + for _, item := range x.indexAwardItemMap { + sort.Slice(item, func(i, j int) bool { + if item[i].GetType() != item[j].GetType() { + return item[i].GetType() < item[j].GetType() + } + return item[i].GetUseEffect().GetType() < item[j].GetUseEffect().GetType() + }) + } return nil } diff --git a/test/go-tableau-loader/protoconf/loader/test_conf.pc.go b/test/go-tableau-loader/protoconf/loader/test_conf.pc.go index 6c5460aa..beaa009f 100644 --- a/test/go-tableau-loader/protoconf/loader/test_conf.pc.go +++ b/test/go-tableau-loader/protoconf/loader/test_conf.pc.go @@ -43,7 +43,7 @@ type ActivityConf_Index_ChapterMap = map[uint32][]*protoconf.ActivityConf_Activi type ActivityConf_Index_NamedChapterMap = map[string][]*protoconf.ActivityConf_Activity_Chapter // Index: SectionItemID@Award -type ActivityConf_Index_AwardMap = map[uint32][]*protoconf.Item +type ActivityConf_Index_AwardMap = map[uint32][]*protoconf.Section_SectionItem // ActivityConf is a wrapper around protobuf message: protoconf.ActivityConf. // @@ -172,11 +172,6 @@ func (x *ActivityConf) processAfterLoad() error { // Index: ChapterName@NamedChapter key := item2.GetChapterName() x.indexNamedChapterMap[key] = append(x.indexNamedChapterMap[key], item2) - for _, item := range x.indexNamedChapterMap { - sort.Slice(item, func(i, j int) bool { - return item[i].GetAwardId() < item[j].GetAwardId() - }) - } } for _, item3 := range item2.GetSectionMap() { for _, item4 := range item3.GetSectionItemList() { @@ -189,6 +184,12 @@ func (x *ActivityConf) processAfterLoad() error { } } } + // Index(sort): ChapterName@NamedChapter + for _, item := range x.indexNamedChapterMap { + sort.Slice(item, func(i, j int) bool { + return item[i].GetAwardId() < item[j].GetAwardId() + }) + } return nil } @@ -363,20 +364,20 @@ func (x *ActivityConf) FindFirstNamedChapter(chapterName string) *protoconf.Acti // Index: SectionItemID@Award -// FindAwardMap returns the index(SectionItemID@Award) to value(protoconf.Item) map. +// FindAwardMap returns the index(SectionItemID@Award) to value(protoconf.Section_SectionItem) map. // One key may correspond to multiple values, which are contained by a slice. func (x *ActivityConf) FindAwardMap() ActivityConf_Index_AwardMap { return x.indexAwardMap } // FindAward returns a slice of all values of the given key. -func (x *ActivityConf) FindAward(id uint32) []*protoconf.Item { +func (x *ActivityConf) FindAward(id uint32) []*protoconf.Section_SectionItem { return x.indexAwardMap[id] } // FindFirstAward returns the first value of the given key, // or nil if the key correspond to no value. -func (x *ActivityConf) FindFirstAward(id uint32) *protoconf.Item { +func (x *ActivityConf) FindFirstAward(id uint32) *protoconf.Section_SectionItem { val := x.indexAwardMap[id] if len(val) > 0 { return val[0] diff --git a/test/proto/test_conf.proto b/test/proto/test_conf.proto index e10950da..39123b64 100644 --- a/test/proto/test_conf.proto +++ b/test/proto/test_conf.proto @@ -61,7 +61,14 @@ message ActivityConf { message Section { uint32 section_id = 1 [(tableau.field) = { name: "SectionID" }]; string section_name = 2 [(tableau.field) = { name: "SectionName" }]; - repeated Item section_item_list = 3 [(tableau.field) = { name: "SectionItem" layout: LAYOUT_HORIZONTAL }]; + repeated SectionItem section_item_list = 3 [(tableau.field) = { name: "SectionItem" layout: LAYOUT_HORIZONTAL }]; + message SectionItem { + uint32 id = 1 [(tableau.field) = { name: "ID" }]; + int32 num = 2 [(tableau.field) = { name: "Num" }]; + repeated protoconf.Item decompose_item_list = 3 [ + (tableau.field) = { name: "DecomposeItem" layout: LAYOUT_HORIZONTAL } + ]; // do not generate for-range loops for index at this level + } map section_rank_map = 4 [(tableau.field) = { layout: LAYOUT_VERTICAL }]; }