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
57 changes: 56 additions & 1 deletion cmd/protoc-gen-cpp-tableau-loader/helper/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,61 @@ func ParseCppType(fd protoreflect.FieldDescriptor) string {
}
}

// ParseMapKeyType converts a FieldDescriptor to its map key type.
// fd must be an comparable type.
func ParseMapKeyType(fd protoreflect.FieldDescriptor) string {
switch fd.Kind() {
case protoreflect.BoolKind:
return "bool"
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind, protoreflect.EnumKind:
return "int32_t"
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
return "uint32_t"
case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
return "int64_t"
case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
return "uint64_t"
case protoreflect.FloatKind:
return "float"
case protoreflect.DoubleKind:
return "double"
case protoreflect.StringKind:
return "std::string"
default:
panic(fmt.Sprintf("unsupported kind: %d", fd.Kind()))
}
}

// ParseOrderedMapKeyType converts a FieldDescriptor to its treemap key type.
// fd must be an ordered type, or a message which can be converted to an ordered type.
func ParseOrderedMapKeyType(fd protoreflect.FieldDescriptor) string {
switch fd.Kind() {
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind, protoreflect.EnumKind:
return "int32_t"
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
return "uint32_t"
case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
return "int64_t"
case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
return "uint64_t"
case protoreflect.FloatKind:
return "float"
case protoreflect.DoubleKind:
return "double"
case protoreflect.StringKind:
return "std::string"
case protoreflect.MessageKind:
switch fd.Message().FullName() {
case "google.protobuf.Timestamp", "google.protobuf.Duration":
return "int64_t"
default:
}
fallthrough
default:
panic(fmt.Sprintf("unsupported kind: %d", fd.Kind()))
}
}

func ToConstRefType(cpptype string) string {
if cpptype == "std::string" {
return "const std::string&"
Expand Down Expand Up @@ -125,7 +180,7 @@ func AddMapKey(fd protoreflect.FieldDescriptor, keys []MapKey) []MapKey {
}
}
}
keys = append(keys, MapKey{ParseCppType(fd.MapKey()), name})
keys = append(keys, MapKey{ParseMapKeyType(fd.MapKey()), name})
return keys
}

Expand Down
30 changes: 19 additions & 11 deletions cmd/protoc-gen-cpp-tableau-loader/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@ func genHppIndexFinders(g *protogen.GeneratedFile, descriptor *index.IndexDescri
g.P(helper.Indent(1), "using ", vectorType, " = std::vector<const ", helper.ParseCppClassType(index.MD), "*>;")
keyType := helper.ParseCppType(field.FD)
g.P(helper.Indent(1), "using ", mapType, " = std::unordered_map<", keyType, ", ", vectorType, ">;")
g.P(helper.Indent(1), "// Finds the index (", index.Index, ") to value (", vectorType, ") hash map.")
g.P(helper.Indent(1), "// One key may correspond to multiple values, which are contained by a vector.")
g.P(helper.Indent(1), "const ", mapType, "& Find", index.Name(), "() const;")
g.P(helper.Indent(1), "// Finds a vector of all values of the given key.")
g.P(helper.Indent(1), "const ", vectorType, "* Find", index.Name(), "(", helper.ToConstRefType(keyType), " ", helper.ParseIndexFieldNameAsFuncParam(field.FD), ") const;")
g.P(helper.Indent(1), "// Finds the first value of the given key.")
g.P(helper.Indent(1), "const ", helper.ParseCppClassType(index.MD), "* FindFirst", index.Name(), "(", helper.ToConstRefType(keyType), " ", helper.ParseIndexFieldNameAsFuncParam(field.FD), ") const;")
g.P()

Expand Down Expand Up @@ -73,8 +77,12 @@ func genHppIndexFinders(g *protogen.GeneratedFile, descriptor *index.IndexDescri

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), "// Finds the index (", index.Index, ") to value (", vectorType, ") hash map.")
g.P(helper.Indent(1), "// One key may correspond to multiple values, which are contained by a vector.")
g.P(helper.Indent(1), "const ", mapType, "& Find", index.Name(), "() const;")
g.P(helper.Indent(1), "// Finds a vector of all values of the given key.")
g.P(helper.Indent(1), "const ", vectorType, "* Find", index.Name(), "(const ", keyType, "& key) const;")
g.P(helper.Indent(1), "// Finds the first value of the given key.")
g.P(helper.Indent(1), "const ", helper.ParseCppClassType(index.MD), "* FindFirst", index.Name(), "(const ", keyType, "& key) const;")
g.P()

Expand Down Expand Up @@ -108,7 +116,7 @@ func genCppIndexLoader(g *protogen.GeneratedFile, descriptor *index.IndexDescrip
if !levelMessage.NextLevel.NeedGen() {
break
}
g.P(helper.Indent(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"
Expand All @@ -134,20 +142,20 @@ func genOneCppIndexLoader(g *protogen.GeneratedFile, depth int, index *index.Lev
for _, leveledFd := range field.LeveledFDList {
fieldName += "." + helper.ParseIndexFieldName(leveledFd) + "()"
}
g.P(helper.Indent(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(helper.Indent(depth+2), indexContainerName, "["+key+"].push_back(&"+parentDataName+");")
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(helper.Indent(depth+1), indexContainerName, "["+key+"].push_back(&"+parentDataName+");")
g.P(helper.Indent(depth+1), indexContainerName, "[", key, "].push_back(&", parentDataName, ");")
}
} else {
// multi-column index
Expand Down Expand Up @@ -202,7 +210,7 @@ func generateOneCppMulticolumnIndex(g *protogen.GeneratedFile, depth int, index
keyType := fmt.Sprintf("Index_%sKey", index.Name())
indexContainerName := "index_" + strcase.ToSnake(index.Name()) + "_map_"
g.P(helper.Indent(depth+1), keyType, " key{", keyParams, "};")
g.P(helper.Indent(depth+1), indexContainerName, "[key].push_back(&"+parentDataName+");")
g.P(helper.Indent(depth+1), indexContainerName, "[key].push_back(&", parentDataName, ");")
return keys
}
field := index.ColFields[cursor]
Expand All @@ -212,7 +220,7 @@ func generateOneCppMulticolumnIndex(g *protogen.GeneratedFile, depth int, index
for _, leveledFd := range field.LeveledFDList {
fieldName += "." + helper.ParseIndexFieldName(leveledFd) + "()"
}
g.P(helper.Indent(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 + ")"
Expand Down Expand Up @@ -240,7 +248,7 @@ func genCppIndexFinders(g *protogen.GeneratedFile, descriptor *index.IndexDescri
indexContainerName := "index_" + strcase.ToSnake(index.Name()) + "_map_"

g.P("// Index: ", index.Index)
g.P("const ", messagerName, "::", mapType, "& "+messagerName+"::Find", index.Name(), "() const { return "+indexContainerName+" ;}")
g.P("const ", messagerName, "::", mapType, "& ", messagerName, "::Find", index.Name(), "() const { return ", indexContainerName, " ;}")
g.P()

var keyType, keyName string
Expand All @@ -255,7 +263,7 @@ func genCppIndexFinders(g *protogen.GeneratedFile, descriptor *index.IndexDescri
keyName = "key"
}

g.P("const ", messagerName, "::", vectorType, "* "+messagerName+"::Find", index.Name(), "(", helper.ToConstRefType(keyType), " ", keyName, ") const {")
g.P("const ", messagerName, "::", vectorType, "* ", messagerName, "::Find", index.Name(), "(", helper.ToConstRefType(keyType), " ", keyName, ") const {")
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;")
Expand All @@ -264,12 +272,12 @@ func genCppIndexFinders(g *protogen.GeneratedFile, descriptor *index.IndexDescri
g.P("}")
g.P()

g.P("const ", helper.ParseCppClassType(index.MD), "* "+messagerName+"::FindFirst", index.Name(), "(", helper.ToConstRefType(keyType), " ", keyName, ") const {")
g.P("const ", helper.ParseCppClassType(index.MD), "* ", messagerName, "::FindFirst", index.Name(), "(", helper.ToConstRefType(keyType), " ", keyName, ") const {")
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(1), "if (conf == nullptr || conf->empty()) {")
g.P(helper.Indent(2), "return nullptr;")
g.P(helper.Indent(1), "}")
g.P(helper.Indent(1), "return (*conf)[0];")
g.P(helper.Indent(1), "return conf->front();")
g.P("}")
g.P()
}
Expand Down
14 changes: 12 additions & 2 deletions cmd/protoc-gen-cpp-tableau-loader/messager.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func genHppMessage(g *protogen.GeneratedFile, message *protogen.Message) {
g.P(helper.Indent(1), "const google::protobuf::Message* Message() const override { return &data_; }")
g.P()

if options.NeedGenOrderedMap(message.Desc, options.LangCPP) || options.NeedGenIndex(message.Desc, options.LangCPP) {
if options.NeedGenOrderedMap(message.Desc, options.LangCPP) || options.NeedGenIndex(message.Desc, options.LangCPP) || options.NeedGenOrderedIndex(message.Desc, options.LangCPP) {
g.P(" private:")
g.P(helper.Indent(1), "virtual bool ProcessAfterLoad() override final;")
g.P()
Expand All @@ -110,6 +110,9 @@ func genHppMessage(g *protogen.GeneratedFile, message *protogen.Message) {
g.P()
genHppIndexFinders(g, indexDescriptor)
}
if options.NeedGenOrderedIndex(message.Desc, options.LangCPP) {
genHppOrderedIndexFinders(g, indexDescriptor)
}
g.P("};")
g.P()
}
Expand Down Expand Up @@ -168,14 +171,17 @@ func genCppMessage(g *protogen.GeneratedFile, message *protogen.Message) {
g.P("}")
g.P()

if options.NeedGenOrderedMap(message.Desc, options.LangCPP) || options.NeedGenIndex(message.Desc, options.LangCPP) {
if options.NeedGenOrderedMap(message.Desc, options.LangCPP) || options.NeedGenIndex(message.Desc, options.LangCPP) || options.NeedGenOrderedIndex(message.Desc, options.LangCPP) {
g.P("bool ", messagerName, "::ProcessAfterLoad() {")
if options.NeedGenOrderedMap(message.Desc, options.LangCPP) {
genCppOrderedMapLoader(g, message.Desc, 1, messagerFullName)
}
if options.NeedGenIndex(message.Desc, options.LangCPP) {
genCppIndexLoader(g, indexDescriptor)
}
if options.NeedGenOrderedIndex(message.Desc, options.LangCPP) {
genCppOrderedIndexLoader(g, indexDescriptor)
}
g.P(helper.Indent(1), "return true;")
g.P("}")
g.P()
Expand All @@ -188,6 +194,10 @@ func genCppMessage(g *protogen.GeneratedFile, message *protogen.Message) {
genCppIndexFinders(g, indexDescriptor, messagerName)
g.P()
}
if options.NeedGenOrderedIndex(message.Desc, options.LangCPP) {
genCppOrderedIndexFinders(g, indexDescriptor, messagerName)
g.P()
}
}

func genCppMapGetters(g *protogen.GeneratedFile, md protoreflect.MessageDescriptor, depth int, keys []helper.MapKey, messagerName string) {
Expand Down
Loading