Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cmd/protoc-gen-cpp-tableau-loader/helper/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,7 @@ func GenGetArguments(keys []MapKey) string {
}
return params
}

func Indent(depth int) string {
return strings.Repeat(" ", depth)
}
8 changes: 4 additions & 4 deletions cmd/protoc-gen-cpp-tableau-loader/hub.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func generateHubHppTplSpec(gen *protogen.Plugin, g *protogen.GeneratedFile, prot
func generateHubHppMsgContainerMembers(gen *protogen.Plugin, g *protogen.GeneratedFile, protofiles []string, fileMessagers map[string][]string) {
for _, proto := range protofiles {
for _, messager := range fileMessagers[proto] {
g.P(" std::shared_ptr<", messager, "> ", strcase.ToSnake(messager), "_;")
g.P(helper.Indent(1), "std::shared_ptr<", messager, "> ", strcase.ToSnake(messager), "_;")
}
}
}
Expand All @@ -114,7 +114,7 @@ func generateHubCppTplSpec(gen *protogen.Plugin, g *protogen.GeneratedFile, prot
for _, messager := range fileMessagers[proto] {
g.P("template <>")
g.P("const std::shared_ptr<", messager, "> Hub::Get<", messager, ">() const {;")
g.P(" return GetMessagerContainer()->", strcase.ToSnake(messager), "_;")
g.P(helper.Indent(1), "return GetMessagerContainer()->", strcase.ToSnake(messager), "_;")
g.P("}")
g.P()
}
Expand All @@ -124,15 +124,15 @@ func generateHubCppTplSpec(gen *protogen.Plugin, g *protogen.GeneratedFile, prot
func generateHubCppMsgContainerCtor(gen *protogen.Plugin, g *protogen.GeneratedFile, protofiles []string, fileMessagers map[string][]string) {
for _, proto := range protofiles {
for _, messager := range fileMessagers[proto] {
g.P(" ", strcase.ToSnake(messager), "_ = std::dynamic_pointer_cast<", messager, `>((*msger_map_)["`, messager, `"]);`)
g.P(helper.Indent(1), strcase.ToSnake(messager), "_ = std::dynamic_pointer_cast<", messager, `>((*msger_map_)["`, messager, `"]);`)
}
}
}

func generateHubCppRegistry(gen *protogen.Plugin, g *protogen.GeneratedFile, protofiles []string, fileMessagers map[string][]string) {
for _, proto := range protofiles {
for _, messager := range fileMessagers[proto] {
g.P(" Register<", messager, ">();")
g.P(helper.Indent(1), "Register<", messager, ">();")
}
}
}
Expand Down
123 changes: 61 additions & 62 deletions cmd/protoc-gen-cpp-tableau-loader/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"fmt"
"strings"

"github.com/iancoleman/strcase"
"github.com/tableauio/loader/cmd/protoc-gen-cpp-tableau-loader/helper"
Expand All @@ -11,54 +10,54 @@ import (
)

func genHppIndexFinders(g *protogen.GeneratedFile, descriptor *index.IndexDescriptor) {
g.P(" // Index accessers.")
g.P(helper.Indent(1), "// Index accessers.")
for levelMessage := descriptor.LevelMessage; levelMessage != nil; levelMessage = levelMessage.NextLevel {
for _, index := range levelMessage.Indexes {
if len(index.ColFields) == 1 {
// single-column index
field := index.ColFields[0] // just take first field
g.P(" // Index: ", index.Index)
g.P(helper.Indent(1), "// Index: ", index.Index)
g.P(" public:")
vectorType := fmt.Sprintf("Index_%sVector", index.Name())
mapType := fmt.Sprintf("Index_%sMap", index.Name())
g.P(" using ", vectorType, " = std::vector<const ", helper.ParseCppClassType(index.MD), "*>;")
g.P(helper.Indent(1), "using ", vectorType, " = std::vector<const ", helper.ParseCppClassType(index.MD), "*>;")
keyType := helper.ParseCppType(field.FD)
g.P(" using ", mapType, " = std::unordered_map<", keyType, ", ", vectorType, ">;")
g.P(" const ", mapType, "& Find", index.Name(), "() const;")
g.P(" const ", vectorType, "* Find", index.Name(), "(", helper.ToConstRefType(keyType), " ", helper.ParseIndexFieldNameAsFuncParam(field.FD), ") const;")
g.P(" const ", helper.ParseCppClassType(index.MD), "* FindFirst", index.Name(), "(", helper.ToConstRefType(keyType), " ", helper.ParseIndexFieldNameAsFuncParam(field.FD), ") const;")
g.P(helper.Indent(1), "using ", mapType, " = std::unordered_map<", keyType, ", ", vectorType, ">;")
g.P(helper.Indent(1), "const ", mapType, "& Find", index.Name(), "() const;")
g.P(helper.Indent(1), "const ", vectorType, "* Find", index.Name(), "(", helper.ToConstRefType(keyType), " ", helper.ParseIndexFieldNameAsFuncParam(field.FD), ") const;")
g.P(helper.Indent(1), "const ", helper.ParseCppClassType(index.MD), "* FindFirst", index.Name(), "(", helper.ToConstRefType(keyType), " ", helper.ParseIndexFieldNameAsFuncParam(field.FD), ") const;")
g.P()

g.P(" private:")
indexContainerName := "index_" + strcase.ToSnake(index.Name()) + "_map_"
g.P(" ", mapType, " ", indexContainerName, ";")
g.P(helper.Indent(1), mapType, " ", indexContainerName, ";")
g.P()
} else {
// multi-column index
g.P(" // Index: ", index.Index)
g.P(helper.Indent(1), "// Index: ", index.Index)
g.P(" public:")
keyType := fmt.Sprintf("Index_%sKey", index.Name())
keyHasherType := fmt.Sprintf("Index_%sKeyHasher", index.Name())
vectorType := fmt.Sprintf("Index_%sVector", index.Name())
mapType := fmt.Sprintf("Index_%sMap", index.Name())

// generate key struct
g.P(" struct ", keyType, " {")
g.P(helper.Indent(1), "struct ", keyType, " {")
equality := ""
for i, field := range index.ColFields {
g.P(" ", helper.ParseCppType(field.FD), " ", helper.ParseIndexFieldNameAsKeyStructFieldName(field.FD), ";")
g.P(helper.Indent(2), helper.ParseCppType(field.FD), " ", helper.ParseIndexFieldNameAsKeyStructFieldName(field.FD), ";")
equality += helper.ParseIndexFieldNameAsKeyStructFieldName(field.FD) + " == other." + helper.ParseIndexFieldNameAsKeyStructFieldName(field.FD)
if i != len(index.ColFields)-1 {
equality += " && "
}
}
g.P(" bool operator==(const ", keyType, "& other) const {")
g.P(" return ", equality, ";")
g.P(" }")
g.P(" };")
g.P(helper.Indent(2), "bool operator==(const ", keyType, "& other) const {")
g.P(helper.Indent(3), "return ", equality, ";")
g.P(helper.Indent(2), "}")
g.P(helper.Indent(1), "};")

// generate key hasher struct
g.P(" struct ", keyHasherType, " {")
g.P(helper.Indent(1), "struct ", keyHasherType, " {")
combinedKeys := ""
for i, field := range index.ColFields {
key := "key." + helper.ParseIndexFieldNameAsKeyStructFieldName(field.FD)
Expand All @@ -67,33 +66,33 @@ func genHppIndexFinders(g *protogen.GeneratedFile, descriptor *index.IndexDescri
combinedKeys += ", "
}
}
g.P(" std::size_t operator()(const ", keyType, "& key) const {")
g.P(" return util::SugaredHashCombine(", combinedKeys, ");")
g.P(" }")
g.P(" };")
g.P(helper.Indent(2), "std::size_t operator()(const ", keyType, "& key) const {")
g.P(helper.Indent(3), "return util::SugaredHashCombine(", combinedKeys, ");")
g.P(helper.Indent(2), "}")
g.P(helper.Indent(1), "};")

g.P(" using ", vectorType, " = std::vector<const ", helper.ParseCppClassType(index.MD), "*>;")
g.P(" using ", mapType, " = std::unordered_map<", keyType, ", ", vectorType, ", ", keyHasherType, ">;")
g.P(" const ", mapType, "& Find", index.Name(), "() const;")
g.P(" const ", vectorType, "* Find", index.Name(), "(const ", keyType, "& key) const;")
g.P(" const ", helper.ParseCppClassType(index.MD), "* FindFirst", index.Name(), "(const ", keyType, "& key) const;")
g.P(helper.Indent(1), "using ", vectorType, " = std::vector<const ", helper.ParseCppClassType(index.MD), "*>;")
g.P(helper.Indent(1), "using ", mapType, " = std::unordered_map<", keyType, ", ", vectorType, ", ", keyHasherType, ">;")
g.P(helper.Indent(1), "const ", mapType, "& Find", index.Name(), "() const;")
g.P(helper.Indent(1), "const ", vectorType, "* Find", index.Name(), "(const ", keyType, "& key) const;")
g.P(helper.Indent(1), "const ", helper.ParseCppClassType(index.MD), "* FindFirst", index.Name(), "(const ", keyType, "& key) const;")
g.P()

g.P(" private:")
indexContainerName := "index_" + strcase.ToSnake(index.Name()) + "_map_"
g.P(" ", mapType, " ", indexContainerName, ";")
g.P(helper.Indent(1), mapType, " ", indexContainerName, ";")
g.P()
}
}
}
}

func genCppIndexLoader(g *protogen.GeneratedFile, descriptor *index.IndexDescriptor) {
g.P(" // Index init.")
g.P(helper.Indent(1), "// Index init.")
for levelMessage := descriptor.LevelMessage; levelMessage != nil; levelMessage = levelMessage.NextLevel {
for _, index := range levelMessage.Indexes {
indexContainerName := "index_" + strcase.ToSnake(index.Name()) + "_map_"
g.P(" ", indexContainerName, ".clear();")
g.P(helper.Indent(1), indexContainerName, ".clear();")
}
}
parentDataName := "data_"
Expand All @@ -109,23 +108,23 @@ func genCppIndexLoader(g *protogen.GeneratedFile, descriptor *index.IndexDescrip
if !levelMessage.NextLevel.NeedGen() {
break
}
g.P(strings.Repeat(" ", depth), "for (auto&& "+itemName+" : "+parentDataName+"."+helper.ParseIndexFieldName(levelMessage.FD)+"()) {")
g.P(helper.Indent(depth), "for (auto&& "+itemName+" : "+parentDataName+"."+helper.ParseIndexFieldName(levelMessage.FD)+"()) {")
parentDataName = itemName
if levelMessage.FD.IsMap() {
parentDataName = itemName + ".second"
}
depth++
}
for i := depth - 1; i > 0; i-- {
g.P(strings.Repeat(" ", i), "}")
g.P(helper.Indent(i), "}")
}
genIndexSorter(g, descriptor)
}

func genOneCppIndexLoader(g *protogen.GeneratedFile, depth int, index *index.LevelIndex, parentDataName string) {
indexContainerName := "index_" + strcase.ToSnake(index.Name()) + "_map_"
g.P(strings.Repeat(" ", depth), "{")
g.P(strings.Repeat(" ", depth+1), "// Index: ", index.Index)
g.P(helper.Indent(depth), "{")
g.P(helper.Indent(depth+1), "// Index: ", index.Index)
if len(index.ColFields) == 1 {
// single-column index
field := index.ColFields[0] // just take the first field
Expand All @@ -135,37 +134,37 @@ func genOneCppIndexLoader(g *protogen.GeneratedFile, depth int, index *index.Lev
for _, leveledFd := range field.LeveledFDList {
fieldName += "." + helper.ParseIndexFieldName(leveledFd) + "()"
}
g.P(strings.Repeat(" ", depth+1), "for (auto&& "+itemName+" : "+parentDataName+fieldName+") {")
g.P(helper.Indent(depth+1), "for (auto&& "+itemName+" : "+parentDataName+fieldName+") {")
key := itemName
if field.FD.Enum() != nil {
key = "static_cast<" + helper.ParseCppType(field.FD) + ">(" + key + ")"
}
g.P(strings.Repeat(" ", depth+2), indexContainerName, "["+key+"].push_back(&"+parentDataName+");")
g.P(strings.Repeat(" ", depth+1), "}")
g.P(helper.Indent(depth+2), indexContainerName, "["+key+"].push_back(&"+parentDataName+");")
g.P(helper.Indent(depth+1), "}")
} else {
fieldName := ""
for _, leveledFd := range field.LeveledFDList {
fieldName += "." + helper.ParseIndexFieldName(leveledFd) + "()"
}
key := parentDataName + fieldName
g.P(strings.Repeat(" ", depth+1), indexContainerName, "["+key+"].push_back(&"+parentDataName+");")
g.P(helper.Indent(depth+1), indexContainerName, "["+key+"].push_back(&"+parentDataName+");")
}
} else {
// multi-column index
generateOneCppMulticolumnIndex(g, depth, index, parentDataName, nil)
}
g.P(strings.Repeat(" ", depth), "}")
g.P(helper.Indent(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) {")
g.P(helper.Indent(1), "// Index(sort): ", index.Index)
g.P(helper.Indent(1), "for (auto&& item : ", indexContainerName, ") {")
g.P(helper.Indent(2), "std::sort(item.second.begin(), item.second.end(),")
g.P(helper.Indent(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 {
Expand All @@ -176,15 +175,15 @@ func genIndexSorter(g *protogen.GeneratedFile, descriptor *index.IndexDescriptor
fieldName += accessOperator + helper.ParseIndexFieldName(leveledFd) + "()"
}
if i == len(index.KeyFields)-1 {
g.P(strings.Repeat(" ", 8), "return a", fieldName, " < b", fieldName, ";")
g.P(helper.Indent(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), "}")
g.P(helper.Indent(8), "if (a", fieldName, " != b", fieldName, ") {")
g.P(helper.Indent(9), "return a", fieldName, " < b", fieldName, ";")
g.P(helper.Indent(8), "}")
}
}
g.P(strings.Repeat(" ", 7), "});")
g.P(strings.Repeat(" ", 1), "}")
g.P(helper.Indent(7), "});")
g.P(helper.Indent(1), "}")
}
}
}
Expand All @@ -202,8 +201,8 @@ func generateOneCppMulticolumnIndex(g *protogen.GeneratedFile, depth int, index
}
keyType := fmt.Sprintf("Index_%sKey", index.Name())
indexContainerName := "index_" + strcase.ToSnake(index.Name()) + "_map_"
g.P(strings.Repeat(" ", depth+1), keyType, " key{", keyParams, "};")
g.P(strings.Repeat(" ", depth+1), indexContainerName, "[key].push_back(&"+parentDataName+");")
g.P(helper.Indent(depth+1), keyType, " key{", keyParams, "};")
g.P(helper.Indent(depth+1), indexContainerName, "[key].push_back(&"+parentDataName+");")
return keys
}
field := index.ColFields[cursor]
Expand All @@ -213,14 +212,14 @@ func generateOneCppMulticolumnIndex(g *protogen.GeneratedFile, depth int, index
for _, leveledFd := range field.LeveledFDList {
fieldName += "." + helper.ParseIndexFieldName(leveledFd) + "()"
}
g.P(strings.Repeat(" ", depth+1), "for (auto&& "+itemName+" : "+parentDataName+fieldName+") {")
g.P(helper.Indent(depth+1), "for (auto&& "+itemName+" : "+parentDataName+fieldName+") {")
key := itemName
if field.FD.Enum() != nil {
key = "static_cast<" + helper.ParseCppType(field.FD) + ">(" + key + ")"
}
keys = append(keys, key)
keys = generateOneCppMulticolumnIndex(g, depth+1, index, parentDataName, keys)
g.P(strings.Repeat(" ", depth+1), "}")
g.P(helper.Indent(depth+1), "}")
} else {
fieldName := ""
for _, leveledFd := range field.LeveledFDList {
Expand Down Expand Up @@ -257,20 +256,20 @@ func genCppIndexFinders(g *protogen.GeneratedFile, descriptor *index.IndexDescri
}

g.P("const ", messagerName, "::", vectorType, "* "+messagerName+"::Find", index.Name(), "(", helper.ToConstRefType(keyType), " ", keyName, ") const {")
g.P(" auto iter = ", indexContainerName, ".find(", keyName, ");")
g.P(" if (iter == ", indexContainerName, ".end()) {")
g.P(" return nullptr;")
g.P(" }")
g.P(" return &iter->second;")
g.P(helper.Indent(1), "auto iter = ", indexContainerName, ".find(", keyName, ");")
g.P(helper.Indent(1), "if (iter == ", indexContainerName, ".end()) {")
g.P(helper.Indent(2), "return nullptr;")
g.P(helper.Indent(1), "}")
g.P(helper.Indent(1), "return &iter->second;")
g.P("}")
g.P()

g.P("const ", helper.ParseCppClassType(index.MD), "* "+messagerName+"::FindFirst", index.Name(), "(", helper.ToConstRefType(keyType), " ", keyName, ") const {")
g.P(" auto conf = Find", index.Name(), "(", keyName, ");")
g.P(" if (conf == nullptr || conf->size() == 0) {")
g.P(" return nullptr;")
g.P(" }")
g.P(" return (*conf)[0];")
g.P(helper.Indent(1), "auto conf = Find", index.Name(), "(", keyName, ");")
g.P(helper.Indent(1), "if (conf == nullptr || conf->size() == 0) {")
g.P(helper.Indent(2), "return nullptr;")
g.P(helper.Indent(1), "}")
g.P(helper.Indent(1), "return (*conf)[0];")
g.P("}")
g.P()
}
Expand Down
Loading