From ad13b181bed571265f83d53404b96150e2aeddcc Mon Sep 17 00:00:00 2001 From: wenchy Date: Fri, 15 Aug 2025 19:20:42 +0800 Subject: [PATCH 1/5] feat: use messager Name() accesser for consistent design --- cmd/protoc-gen-cpp-tableau-loader/hub.go | 2 +- cmd/protoc-gen-cpp-tableau-loader/shard.go | 2 +- cmd/protoc-gen-go-tableau-loader/hub.go | 2 +- .../src/protoconf/hub_shard0.pc.cc | 6 +++--- .../src/protoconf/hub_shard1.pc.cc | 14 ++++++------- .../protoconf/loader/hub.pc.go | 20 +++++++++---------- 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/cmd/protoc-gen-cpp-tableau-loader/hub.go b/cmd/protoc-gen-cpp-tableau-loader/hub.go index 63453bed..5acf90a9 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/hub.go +++ b/cmd/protoc-gen-cpp-tableau-loader/hub.go @@ -125,7 +125,7 @@ func generateHubCppTplSpec(g *protogen.GeneratedFile, protofiles []string, fileM func generateHubCppMsgContainerCtor(g *protogen.GeneratedFile, protofiles []string, fileMessagers map[string][]string) { for _, proto := range protofiles { for _, messager := range fileMessagers[proto] { - g.P(helper.Indent(1), strcase.ToSnake(messager), "_ = std::dynamic_pointer_cast<", messager, `>(GetMessager("`, messager, `"));`) + g.P(helper.Indent(1), strcase.ToSnake(messager), "_ = std::dynamic_pointer_cast<", messager, `>(GetMessager(`, messager, `::Name()));`) } } } diff --git a/cmd/protoc-gen-cpp-tableau-loader/shard.go b/cmd/protoc-gen-cpp-tableau-loader/shard.go index b1e0aeb7..3737e659 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/shard.go +++ b/cmd/protoc-gen-cpp-tableau-loader/shard.go @@ -109,7 +109,7 @@ func generateShardedHubCppFileContent(g *protogen.GeneratedFile, shardIndex int, g.P("void MessagerContainer::InitShard", shardIndex, "() {") for _, proto := range protofiles { for _, messager := range fileMessagers[proto] { - g.P(helper.Indent(1), strcase.ToSnake(messager), "_ = std::dynamic_pointer_cast<", messager, `>(GetMessager("`, messager, `"));`) + g.P(helper.Indent(1), strcase.ToSnake(messager), "_ = std::dynamic_pointer_cast<", messager, `>(GetMessager(`, messager, `::Name()));`) } } g.P("}") diff --git a/cmd/protoc-gen-go-tableau-loader/hub.go b/cmd/protoc-gen-go-tableau-loader/hub.go index 38df4dd2..1db4316d 100644 --- a/cmd/protoc-gen-go-tableau-loader/hub.go +++ b/cmd/protoc-gen-go-tableau-loader/hub.go @@ -36,7 +36,7 @@ func generateHub(gen *protogen.Plugin) { g.P("loadedTime: time.Now(),") g.P("}") for _, messager := range messagers { - g.P("messagerContainer.", strcase.ToLowerCamel(messager), `, _ = messagerMap["`, messager, `"].(*`, messager, ")") + g.P("messagerContainer.", strcase.ToLowerCamel(messager), `, _ = messagerMap[(&`, messager, `{}).Name()].(*`, messager, ")") } g.P("return messagerContainer") g.P("}") 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 d7fbeb61..a48b3804 100644 --- a/test/cpp-tableau-loader/src/protoconf/hub_shard0.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/hub_shard0.pc.cc @@ -25,9 +25,9 @@ const std::shared_ptr Hub::Get() const { } void MessagerContainer::InitShard0() { - hero_base_conf_ = std::dynamic_pointer_cast(GetMessager("HeroBaseConf")); - hero_conf_ = std::dynamic_pointer_cast(GetMessager("HeroConf")); - item_conf_ = std::dynamic_pointer_cast(GetMessager("ItemConf")); + hero_base_conf_ = std::dynamic_pointer_cast(GetMessager(HeroBaseConf::Name())); + hero_conf_ = std::dynamic_pointer_cast(GetMessager(HeroConf::Name())); + item_conf_ = std::dynamic_pointer_cast(GetMessager(ItemConf::Name())); } void Registry::InitShard0() { diff --git a/test/cpp-tableau-loader/src/protoconf/hub_shard1.pc.cc b/test/cpp-tableau-loader/src/protoconf/hub_shard1.pc.cc index e063eeeb..370d348e 100644 --- a/test/cpp-tableau-loader/src/protoconf/hub_shard1.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/hub_shard1.pc.cc @@ -45,13 +45,13 @@ const std::shared_ptr Hub::Get() const { } void MessagerContainer::InitShard1() { - patch_merge_conf_ = std::dynamic_pointer_cast(GetMessager("PatchMergeConf")); - patch_replace_conf_ = std::dynamic_pointer_cast(GetMessager("PatchReplaceConf")); - recursive_patch_conf_ = std::dynamic_pointer_cast(GetMessager("RecursivePatchConf")); - activity_conf_ = std::dynamic_pointer_cast(GetMessager("ActivityConf")); - chapter_conf_ = std::dynamic_pointer_cast(GetMessager("ChapterConf")); - task_conf_ = std::dynamic_pointer_cast(GetMessager("TaskConf")); - theme_conf_ = std::dynamic_pointer_cast(GetMessager("ThemeConf")); + patch_merge_conf_ = std::dynamic_pointer_cast(GetMessager(PatchMergeConf::Name())); + patch_replace_conf_ = std::dynamic_pointer_cast(GetMessager(PatchReplaceConf::Name())); + recursive_patch_conf_ = std::dynamic_pointer_cast(GetMessager(RecursivePatchConf::Name())); + activity_conf_ = std::dynamic_pointer_cast(GetMessager(ActivityConf::Name())); + chapter_conf_ = std::dynamic_pointer_cast(GetMessager(ChapterConf::Name())); + task_conf_ = std::dynamic_pointer_cast(GetMessager(TaskConf::Name())); + theme_conf_ = std::dynamic_pointer_cast(GetMessager(ThemeConf::Name())); } void Registry::InitShard1() { diff --git a/test/go-tableau-loader/protoconf/loader/hub.pc.go b/test/go-tableau-loader/protoconf/loader/hub.pc.go index a80fb21a..c81082f7 100644 --- a/test/go-tableau-loader/protoconf/loader/hub.pc.go +++ b/test/go-tableau-loader/protoconf/loader/hub.pc.go @@ -339,16 +339,16 @@ func newMessagerContainer(messagerMap MessagerMap) *messagerContainer { messagerMap: messagerMap, loadedTime: time.Now(), } - messagerContainer.heroConf, _ = messagerMap["HeroConf"].(*HeroConf) - messagerContainer.heroBaseConf, _ = messagerMap["HeroBaseConf"].(*HeroBaseConf) - messagerContainer.itemConf, _ = messagerMap["ItemConf"].(*ItemConf) - messagerContainer.patchReplaceConf, _ = messagerMap["PatchReplaceConf"].(*PatchReplaceConf) - messagerContainer.patchMergeConf, _ = messagerMap["PatchMergeConf"].(*PatchMergeConf) - messagerContainer.recursivePatchConf, _ = messagerMap["RecursivePatchConf"].(*RecursivePatchConf) - messagerContainer.activityConf, _ = messagerMap["ActivityConf"].(*ActivityConf) - messagerContainer.chapterConf, _ = messagerMap["ChapterConf"].(*ChapterConf) - messagerContainer.themeConf, _ = messagerMap["ThemeConf"].(*ThemeConf) - messagerContainer.taskConf, _ = messagerMap["TaskConf"].(*TaskConf) + messagerContainer.heroConf, _ = messagerMap[(&HeroConf{}).Name()].(*HeroConf) + messagerContainer.heroBaseConf, _ = messagerMap[(&HeroBaseConf{}).Name()].(*HeroBaseConf) + messagerContainer.itemConf, _ = messagerMap[(&ItemConf{}).Name()].(*ItemConf) + messagerContainer.patchReplaceConf, _ = messagerMap[(&PatchReplaceConf{}).Name()].(*PatchReplaceConf) + messagerContainer.patchMergeConf, _ = messagerMap[(&PatchMergeConf{}).Name()].(*PatchMergeConf) + messagerContainer.recursivePatchConf, _ = messagerMap[(&RecursivePatchConf{}).Name()].(*RecursivePatchConf) + messagerContainer.activityConf, _ = messagerMap[(&ActivityConf{}).Name()].(*ActivityConf) + messagerContainer.chapterConf, _ = messagerMap[(&ChapterConf{}).Name()].(*ChapterConf) + messagerContainer.themeConf, _ = messagerMap[(&ThemeConf{}).Name()].(*ThemeConf) + messagerContainer.taskConf, _ = messagerMap[(&TaskConf{}).Name()].(*TaskConf) return messagerContainer } From f7e0a1e72d623a2f5901343432c732fea819bc38 Mon Sep 17 00:00:00 2001 From: Kybxd <627940450@qq.com> Date: Fri, 15 Aug 2025 21:48:47 +0800 Subject: [PATCH 2/5] feat: use filesystem apis --- .../embed/load.pc.cc | 26 ++++----- .../embed/logger.pc.cc | 15 +++--- .../embed/logger.pc.h | 3 +- .../embed/util.pc.cc | 53 +++---------------- .../embed/util.pc.h | 23 +------- cmd/protoc-gen-cpp-tableau-loader/messager.go | 10 ++-- .../src/protoconf/hero_conf.pc.cc | 4 +- .../src/protoconf/item_conf.pc.cc | 2 +- .../src/protoconf/load.pc.cc | 26 ++++----- .../src/protoconf/logger.pc.cc | 15 +++--- .../src/protoconf/logger.pc.h | 3 +- .../src/protoconf/patch_conf.pc.cc | 6 +-- .../src/protoconf/test_conf.pc.cc | 8 +-- .../src/protoconf/util.pc.cc | 53 +++---------------- .../src/protoconf/util.pc.h | 23 +------- 15 files changed, 73 insertions(+), 197 deletions(-) diff --git a/cmd/protoc-gen-cpp-tableau-loader/embed/load.pc.cc b/cmd/protoc-gen-cpp-tableau-loader/embed/load.pc.cc index 0cf2d6c3..60a3556f 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/embed/load.pc.cc +++ b/cmd/protoc-gen-cpp-tableau-loader/embed/load.pc.cc @@ -73,7 +73,7 @@ bool LoadMessagerWithPatch(google::protobuf::Message& msg, const std::string& pa // ignore patch files when LoadMode::kModeOnlyMain specified return options->load_func(msg, path, fmt, nullptr); } - std::string name = util::GetProtoName(msg); + const std::string& name = msg.GetDescriptor()->name(); std::vector patch_paths; if (!options->patch_paths.empty()) { // patch path specified in PatchPaths, then use it instead of PatchDirs. @@ -81,13 +81,13 @@ bool LoadMessagerWithPatch(google::protobuf::Message& msg, const std::string& pa } else { std::string filename = name + util::Format2Ext(fmt); for (auto&& patch_dir : options->patch_dirs) { - patch_paths.emplace_back((std::filesystem::path(patch_dir) / filename).make_preferred().string()); + patch_paths.emplace_back((std::filesystem::path(patch_dir) / filename).string()); } } std::vector existed_patch_paths; for (auto&& patch_path : patch_paths) { - if (util::ExistsFile(patch_path)) { + if (std::filesystem::exists(patch_path)) { existed_patch_paths.emplace_back(patch_path); } } @@ -104,7 +104,7 @@ bool LoadMessagerWithPatch(google::protobuf::Message& msg, const std::string& pa case tableau::PATCH_REPLACE: { // just use the last "patch" file std::string& patch_path = existed_patch_paths.back(); - if (!options->load_func(msg, patch_path, util::Ext2Format(util::GetExt(patch_path)), options)) { + if (!options->load_func(msg, patch_path, util::GetFormat(patch_path), options)) { return false; } break; @@ -121,7 +121,7 @@ bool LoadMessagerWithPatch(google::protobuf::Message& msg, const std::string& pa std::unique_ptr _auto_release(msg.New()); // load patch_msg from each "patch" file for (auto&& patch_path : existed_patch_paths) { - if (!options->load_func(*patch_msg_ptr, patch_path, util::Ext2Format(util::GetExt(patch_path)), options)) { + if (!options->load_func(*patch_msg_ptr, patch_path, util::GetFormat(patch_path), options)) { return false; } if (!PatchMessage(msg, *patch_msg_ptr)) { @@ -131,11 +131,11 @@ bool LoadMessagerWithPatch(google::protobuf::Message& msg, const std::string& pa break; } default: { - SetErrMsg("unknown patch type: " + util::GetPatchName(patch)); + SetErrMsg("unknown patch type: " + tableau::Patch_Name(patch)); return false; } } - ATOM_DEBUG("patched(%s) %s by %s: %s", util::GetPatchName(patch).c_str(), name.c_str(), + ATOM_DEBUG("patched(%s) %s by %s: %s", tableau::Patch_Name(patch).c_str(), name.c_str(), ATOM_VECTOR_STR(existed_patch_paths).c_str(), msg.ShortDebugString().c_str()); return true; } @@ -170,25 +170,21 @@ bool LoadMessager(google::protobuf::Message& msg, const std::string& path, Forma bool LoadMessagerInDir(google::protobuf::Message& msg, const std::string& dir, Format fmt, std::shared_ptr options /* = nullptr*/) { - std::string name = util::GetProtoName(msg); + const std::string& name = msg.GetDescriptor()->name(); std::string path; if (options && !options->path.empty()) { // path specified in Paths, then use it instead of dir. path = options->path; - fmt = util::Ext2Format(util::GetExt(path)); + fmt = util::GetFormat(path); } if (path.empty()) { std::string filename = name + util::Format2Ext(fmt); - path = (std::filesystem::path(dir) / filename).make_preferred().string(); + path = (std::filesystem::path(dir) / filename).string(); } const google::protobuf::Descriptor* descriptor = msg.GetDescriptor(); - if (!descriptor) { - SetErrMsg("failed to get descriptor of message: " + name); - return false; - } // access the extension directly using the generated identifier - const tableau::WorksheetOptions worksheet_options = descriptor->options().GetExtension(tableau::worksheet); + const tableau::WorksheetOptions& worksheet_options = descriptor->options().GetExtension(tableau::worksheet); if (worksheet_options.patch() != tableau::PATCH_NONE) { return LoadMessagerWithPatch(msg, path, fmt, worksheet_options.patch(), options); } diff --git a/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc b/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc index 893b63a6..5f6198e4 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc +++ b/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc @@ -12,6 +12,7 @@ #include #endif +#include #include #include @@ -53,14 +54,12 @@ void SetDefaultLogger(Logger* logger) { g_default_logger = logger; } -int Logger::Init(const std::string& path, Level level) { - std::string dir = util::GetDir(path); - if (!dir.empty()) { - // prepare the specified directory - int status = util::Mkdir(dir); - if (status == -1) { - return status; - } +int Logger::Init(const std::filesystem::path& path, Level level) { + std::error_code ec; + std::filesystem::create_directories(path.parent_path(), ec); + if (ec) { + std::cerr << "system error: " << ec.message() << std::endl; + return -1; } ofs_.open(path, std::ofstream::out | std::ofstream::app); os_ = &ofs_; // use file stream as output stream diff --git a/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.h b/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.h index 8c26f011..ca212403 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.h +++ b/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.h @@ -1,4 +1,5 @@ #pragma once +#include #include #include #include @@ -49,7 +50,7 @@ class Logger { ~Logger() { ofs_.close(); } // Init the logger with the specified path. // NOTE: no guarantee of thread-safety. - int Init(const std::string& path, Level level); + int Init(const std::filesystem::path& path, Level level); // Set the writer for writing log. void SetWriter(Writer writer) { writer_ = writer; } // Log with guarantee of thread-safety. diff --git a/cmd/protoc-gen-cpp-tableau-loader/embed/util.pc.cc b/cmd/protoc-gen-cpp-tableau-loader/embed/util.pc.cc index 67dc773e..da57e612 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/embed/util.pc.cc +++ b/cmd/protoc-gen-cpp-tableau-loader/embed/util.pc.cc @@ -22,42 +22,18 @@ const std::string kTextExt = ".txt"; const std::string kBinExt = ".bin"; namespace util { -int Mkdir(const std::string& path) { - std::error_code ec; - if (!std::filesystem::create_directories(path, ec)) { - if (ec) { - std::cerr << "system error: " << ec.message() << std::endl; - return -1; - } - } - return 0; -} - -std::string GetDir(const std::string& path) { return std::filesystem::path(path).parent_path().string(); } - -bool ExistsFile(const std::string& filename) { return std::filesystem::exists(filename); } - bool ReadFile(const std::string& filename, std::string& content) { std::ifstream file(filename); if (!file.is_open()) { SetErrMsg("failed to open " + filename + ": " + strerror(errno)); return false; } - std::stringstream ss; - ss << file.rdbuf(); - content = ss.str(); + content.assign(std::istreambuf_iterator(file), {}); return true; } -std::string GetExt(const std::string& path) { - std::size_t pos = path.find_last_of("."); - if (pos != std::string::npos) { - return path.substr(pos); - } - return kEmpty; -} - -Format Ext2Format(const std::string& ext) { +Format GetFormat(const std::string& path) { + auto ext = std::filesystem::path(path).extension(); if (ext == kJSONExt) { return Format::kJSON; } else if (ext == kTextExt) { @@ -93,7 +69,7 @@ bool JSON2Message(const std::string& json, google::protobuf::Message& msg, status = google::protobuf::util::JsonStringToMessage(json, &msg); } if (!status.ok()) { - SetErrMsg("failed to parse " + GetProtoName(msg) + kJSONExt + ": " + status.ToString()); + SetErrMsg("failed to parse " + msg.GetDescriptor()->name() + kJSONExt + ": " + status.ToString()); return false; } return true; @@ -101,35 +77,20 @@ bool JSON2Message(const std::string& json, google::protobuf::Message& msg, bool Text2Message(const std::string& text, google::protobuf::Message& msg) { if (!google::protobuf::TextFormat::ParseFromString(text, &msg)) { - SetErrMsg("failed to parse " + GetProtoName(msg) + kTextExt); + SetErrMsg("failed to parse " + msg.GetDescriptor()->name() + kTextExt); return false; } return true; } + bool Bin2Message(const std::string& bin, google::protobuf::Message& msg) { if (!msg.ParseFromString(bin)) { - SetErrMsg("failed to parse " + GetProtoName(msg) + kBinExt); + SetErrMsg("failed to parse " + msg.GetDescriptor()->name() + kBinExt); return false; } return true; } -const std::string& GetProtoName(const google::protobuf::Message& msg) { - const auto* md = msg.GetDescriptor(); - return md != nullptr ? md->name() : kEmpty; -} - -std::string GetPatchName(tableau::Patch patch) { - auto* descriptor = tableau::Patch_descriptor(); - if (descriptor) { - auto* value = descriptor->FindValueByNumber(patch); - if (value) { - return value->name(); - } - } - return std::to_string(static_cast(patch)); -} - // refer: https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/stubs/logging.h void ProtobufLogHandler(google::protobuf::LogLevel level, const char* filename, int line, const std::string& msg) { static const std::unordered_map kLevelMap = {{google::protobuf::LOGLEVEL_INFO, log::kInfo}, diff --git a/cmd/protoc-gen-cpp-tableau-loader/embed/util.pc.h b/cmd/protoc-gen-cpp-tableau-loader/embed/util.pc.h index f2ed38c0..c7bdc213 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/embed/util.pc.h +++ b/cmd/protoc-gen-cpp-tableau-loader/embed/util.pc.h @@ -48,27 +48,11 @@ inline std::size_t SugaredHashCombine(const T& v, O... others) { return seed; } -// Mkdir makes dir recursively. -int Mkdir(const std::string& path); -// GetDir returns all but the last element of path, typically the path's -// directory. -std::string GetDir(const std::string& path); -// ExistsFile checks if a file exists. -bool ExistsFile(const std::string& filename); // ReadFile reads the file named by filename and returns the contents. bool ReadFile(const std::string& filename, std::string& content); -// GetExt returns the file name extension used by path. -// The extension is the suffix beginning at the final dot -// in the final element of path; it is empty if there is -// no dot. -std::string GetExt(const std::string& path); -// Convert file extension to Format type. -// NOTE: ext includes dot ".", such as: -// - kJSONExt: ".json" -// - kTextExt: ".txt" -// - kBinExt: ".bin" -Format Ext2Format(const std::string& ext); +// GetFormat returns the Format type used by path. +Format GetFormat(const std::string& path); // Empty string will be returned if an unsupported enum value has been passed, // and the error message can be obtained by GetErrMsg(). const std::string& Format2Ext(Format fmt); @@ -78,9 +62,6 @@ bool JSON2Message(const std::string& json, google::protobuf::Message& msg, bool Text2Message(const std::string& text, google::protobuf::Message& msg); bool Bin2Message(const std::string& bin, google::protobuf::Message& msg); -const std::string& GetProtoName(const google::protobuf::Message& msg); -std::string GetPatchName(tableau::Patch patch); - void ProtobufLogHandler(google::protobuf::LogLevel level, const char* filename, int line, const std::string& msg); class TimeProfiler { diff --git a/cmd/protoc-gen-cpp-tableau-loader/messager.go b/cmd/protoc-gen-cpp-tableau-loader/messager.go index 19f2e3a5..f7cf6be0 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/messager.go +++ b/cmd/protoc-gen-cpp-tableau-loader/messager.go @@ -56,7 +56,7 @@ func generateHppFileContent(file *protogen.File, g *protogen.GeneratedFile) { opts := message.Desc.Options().(*descriptorpb.MessageOptions) worksheet := proto.GetExtension(opts, tableaupb.E_Worksheet).(*tableaupb.WorksheetOptions) if worksheet != nil { - genHppMessage(file, g, message) + genHppMessage(g, message) messagerName := string(message.Desc.Name()) fileMessagers = append(fileMessagers, messagerName) } @@ -76,9 +76,8 @@ func generateHppFileContent(file *protogen.File, g *protogen.GeneratedFile) { } // genHppMessage generates a message definition. -func genHppMessage(file *protogen.File, g *protogen.GeneratedFile, message *protogen.Message) { - pkg := string(file.Desc.Package()) - cppFullName := strings.ReplaceAll(pkg, ".", "::") + "::" + string(message.Desc.Name()) +func genHppMessage(g *protogen.GeneratedFile, message *protogen.Message) { + cppFullName := helper.ParseCppClassType(message.Desc) messagerFullName := string(message.Desc.FullName()) indexDescriptor := index.ParseIndexDescriptor(message.Desc) @@ -154,9 +153,10 @@ func generateCppFileContent(file *protogen.File, g *protogen.GeneratedFile) { func genCppMessage(g *protogen.GeneratedFile, message *protogen.Message) { messagerName := string(message.Desc.Name()) messagerFullName := string(message.Desc.FullName()) + cppFullName := helper.ParseCppClassType(message.Desc) indexDescriptor := index.ParseIndexDescriptor(message.Desc) - g.P("const std::string ", messagerName, "::kProtoName = ", `"`, messagerName, `";`) + g.P("const std::string ", messagerName, "::kProtoName = ", cppFullName, `::GetDescriptor()->name();`) g.P() g.P("bool ", messagerName, "::Load(const std::string& dir, Format fmt, std::shared_ptr options /* = nullptr */) {") g.P(helper.Indent(1), "tableau::util::TimeProfiler profiler;") diff --git a/test/cpp-tableau-loader/src/protoconf/hero_conf.pc.cc b/test/cpp-tableau-loader/src/protoconf/hero_conf.pc.cc index d0182838..873a10e6 100644 --- a/test/cpp-tableau-loader/src/protoconf/hero_conf.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/hero_conf.pc.cc @@ -10,7 +10,7 @@ #include "util.pc.h" namespace tableau { -const std::string HeroConf::kProtoName = "HeroConf"; +const std::string HeroConf::kProtoName = protoconf::HeroConf::GetDescriptor()->name(); bool HeroConf::Load(const std::string& dir, Format fmt, std::shared_ptr options /* = nullptr */) { tableau::util::TimeProfiler profiler; @@ -69,7 +69,7 @@ const HeroConf::Hero_Attr_OrderedMap* HeroConf::GetOrderedMap(const std::string& return &iter->second.first; } -const std::string HeroBaseConf::kProtoName = "HeroBaseConf"; +const std::string HeroBaseConf::kProtoName = protoconf::HeroBaseConf::GetDescriptor()->name(); bool HeroBaseConf::Load(const std::string& dir, Format fmt, std::shared_ptr options /* = nullptr */) { tableau::util::TimeProfiler profiler; 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 a1460ba4..07723bbe 100644 --- a/test/cpp-tableau-loader/src/protoconf/item_conf.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/item_conf.pc.cc @@ -10,7 +10,7 @@ #include "util.pc.h" namespace tableau { -const std::string ItemConf::kProtoName = "ItemConf"; +const std::string ItemConf::kProtoName = protoconf::ItemConf::GetDescriptor()->name(); bool ItemConf::Load(const std::string& dir, Format fmt, std::shared_ptr options /* = nullptr */) { tableau::util::TimeProfiler profiler; diff --git a/test/cpp-tableau-loader/src/protoconf/load.pc.cc b/test/cpp-tableau-loader/src/protoconf/load.pc.cc index d08d3f93..4a57baa4 100644 --- a/test/cpp-tableau-loader/src/protoconf/load.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/load.pc.cc @@ -78,7 +78,7 @@ bool LoadMessagerWithPatch(google::protobuf::Message& msg, const std::string& pa // ignore patch files when LoadMode::kModeOnlyMain specified return options->load_func(msg, path, fmt, nullptr); } - std::string name = util::GetProtoName(msg); + const std::string& name = msg.GetDescriptor()->name(); std::vector patch_paths; if (!options->patch_paths.empty()) { // patch path specified in PatchPaths, then use it instead of PatchDirs. @@ -86,13 +86,13 @@ bool LoadMessagerWithPatch(google::protobuf::Message& msg, const std::string& pa } else { std::string filename = name + util::Format2Ext(fmt); for (auto&& patch_dir : options->patch_dirs) { - patch_paths.emplace_back((std::filesystem::path(patch_dir) / filename).make_preferred().string()); + patch_paths.emplace_back((std::filesystem::path(patch_dir) / filename).string()); } } std::vector existed_patch_paths; for (auto&& patch_path : patch_paths) { - if (util::ExistsFile(patch_path)) { + if (std::filesystem::exists(patch_path)) { existed_patch_paths.emplace_back(patch_path); } } @@ -109,7 +109,7 @@ bool LoadMessagerWithPatch(google::protobuf::Message& msg, const std::string& pa case tableau::PATCH_REPLACE: { // just use the last "patch" file std::string& patch_path = existed_patch_paths.back(); - if (!options->load_func(msg, patch_path, util::Ext2Format(util::GetExt(patch_path)), options)) { + if (!options->load_func(msg, patch_path, util::GetFormat(patch_path), options)) { return false; } break; @@ -126,7 +126,7 @@ bool LoadMessagerWithPatch(google::protobuf::Message& msg, const std::string& pa std::unique_ptr _auto_release(msg.New()); // load patch_msg from each "patch" file for (auto&& patch_path : existed_patch_paths) { - if (!options->load_func(*patch_msg_ptr, patch_path, util::Ext2Format(util::GetExt(patch_path)), options)) { + if (!options->load_func(*patch_msg_ptr, patch_path, util::GetFormat(patch_path), options)) { return false; } if (!PatchMessage(msg, *patch_msg_ptr)) { @@ -136,11 +136,11 @@ bool LoadMessagerWithPatch(google::protobuf::Message& msg, const std::string& pa break; } default: { - SetErrMsg("unknown patch type: " + util::GetPatchName(patch)); + SetErrMsg("unknown patch type: " + tableau::Patch_Name(patch)); return false; } } - ATOM_DEBUG("patched(%s) %s by %s: %s", util::GetPatchName(patch).c_str(), name.c_str(), + ATOM_DEBUG("patched(%s) %s by %s: %s", tableau::Patch_Name(patch).c_str(), name.c_str(), ATOM_VECTOR_STR(existed_patch_paths).c_str(), msg.ShortDebugString().c_str()); return true; } @@ -175,25 +175,21 @@ bool LoadMessager(google::protobuf::Message& msg, const std::string& path, Forma bool LoadMessagerInDir(google::protobuf::Message& msg, const std::string& dir, Format fmt, std::shared_ptr options /* = nullptr*/) { - std::string name = util::GetProtoName(msg); + const std::string& name = msg.GetDescriptor()->name(); std::string path; if (options && !options->path.empty()) { // path specified in Paths, then use it instead of dir. path = options->path; - fmt = util::Ext2Format(util::GetExt(path)); + fmt = util::GetFormat(path); } if (path.empty()) { std::string filename = name + util::Format2Ext(fmt); - path = (std::filesystem::path(dir) / filename).make_preferred().string(); + path = (std::filesystem::path(dir) / filename).string(); } const google::protobuf::Descriptor* descriptor = msg.GetDescriptor(); - if (!descriptor) { - SetErrMsg("failed to get descriptor of message: " + name); - return false; - } // access the extension directly using the generated identifier - const tableau::WorksheetOptions worksheet_options = descriptor->options().GetExtension(tableau::worksheet); + const tableau::WorksheetOptions& worksheet_options = descriptor->options().GetExtension(tableau::worksheet); if (worksheet_options.patch() != tableau::PATCH_NONE) { return LoadMessagerWithPatch(msg, path, fmt, worksheet_options.patch(), options); } diff --git a/test/cpp-tableau-loader/src/protoconf/logger.pc.cc b/test/cpp-tableau-loader/src/protoconf/logger.pc.cc index 99e62c6d..b5ae7651 100644 --- a/test/cpp-tableau-loader/src/protoconf/logger.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/logger.pc.cc @@ -17,6 +17,7 @@ #include #endif +#include #include #include @@ -58,14 +59,12 @@ void SetDefaultLogger(Logger* logger) { g_default_logger = logger; } -int Logger::Init(const std::string& path, Level level) { - std::string dir = util::GetDir(path); - if (!dir.empty()) { - // prepare the specified directory - int status = util::Mkdir(dir); - if (status == -1) { - return status; - } +int Logger::Init(const std::filesystem::path& path, Level level) { + std::error_code ec; + std::filesystem::create_directories(path.parent_path(), ec); + if (ec) { + std::cerr << "system error: " << ec.message() << std::endl; + return -1; } ofs_.open(path, std::ofstream::out | std::ofstream::app); os_ = &ofs_; // use file stream as output stream diff --git a/test/cpp-tableau-loader/src/protoconf/logger.pc.h b/test/cpp-tableau-loader/src/protoconf/logger.pc.h index 90090cc9..7248c61d 100644 --- a/test/cpp-tableau-loader/src/protoconf/logger.pc.h +++ b/test/cpp-tableau-loader/src/protoconf/logger.pc.h @@ -4,6 +4,7 @@ // - protoc v3.19.3 #pragma once +#include #include #include #include @@ -54,7 +55,7 @@ class Logger { ~Logger() { ofs_.close(); } // Init the logger with the specified path. // NOTE: no guarantee of thread-safety. - int Init(const std::string& path, Level level); + int Init(const std::filesystem::path& path, Level level); // Set the writer for writing log. void SetWriter(Writer writer) { writer_ = writer; } // Log with guarantee of thread-safety. diff --git a/test/cpp-tableau-loader/src/protoconf/patch_conf.pc.cc b/test/cpp-tableau-loader/src/protoconf/patch_conf.pc.cc index 66a14069..544f13e9 100644 --- a/test/cpp-tableau-loader/src/protoconf/patch_conf.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/patch_conf.pc.cc @@ -10,7 +10,7 @@ #include "util.pc.h" namespace tableau { -const std::string PatchReplaceConf::kProtoName = "PatchReplaceConf"; +const std::string PatchReplaceConf::kProtoName = protoconf::PatchReplaceConf::GetDescriptor()->name(); bool PatchReplaceConf::Load(const std::string& dir, Format fmt, std::shared_ptr options /* = nullptr */) { tableau::util::TimeProfiler profiler; @@ -20,7 +20,7 @@ bool PatchReplaceConf::Load(const std::string& dir, Format fmt, std::shared_ptr< return ok; } -const std::string PatchMergeConf::kProtoName = "PatchMergeConf"; +const std::string PatchMergeConf::kProtoName = protoconf::PatchMergeConf::GetDescriptor()->name(); bool PatchMergeConf::Load(const std::string& dir, Format fmt, std::shared_ptr options /* = nullptr */) { tableau::util::TimeProfiler profiler; @@ -38,7 +38,7 @@ const protoconf::Item* PatchMergeConf::Get(uint32_t id) const { return &iter->second; } -const std::string RecursivePatchConf::kProtoName = "RecursivePatchConf"; +const std::string RecursivePatchConf::kProtoName = protoconf::RecursivePatchConf::GetDescriptor()->name(); bool RecursivePatchConf::Load(const std::string& dir, Format fmt, std::shared_ptr options /* = nullptr */) { tableau::util::TimeProfiler profiler; 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 c178d100..1198d114 100644 --- a/test/cpp-tableau-loader/src/protoconf/test_conf.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/test_conf.pc.cc @@ -10,7 +10,7 @@ #include "util.pc.h" namespace tableau { -const std::string ActivityConf::kProtoName = "ActivityConf"; +const std::string ActivityConf::kProtoName = protoconf::ActivityConf::GetDescriptor()->name(); bool ActivityConf::Load(const std::string& dir, Format fmt, std::shared_ptr options /* = nullptr */) { tableau::util::TimeProfiler profiler; @@ -238,7 +238,7 @@ const protoconf::Section::SectionItem* ActivityConf::FindFirstAward(uint32_t id) } -const std::string ChapterConf::kProtoName = "ChapterConf"; +const std::string ChapterConf::kProtoName = protoconf::ChapterConf::GetDescriptor()->name(); bool ChapterConf::Load(const std::string& dir, Format fmt, std::shared_ptr options /* = nullptr */) { tableau::util::TimeProfiler profiler; @@ -256,7 +256,7 @@ const protoconf::ChapterConf::Chapter* ChapterConf::Get(uint64_t id) const { return &iter->second; } -const std::string ThemeConf::kProtoName = "ThemeConf"; +const std::string ThemeConf::kProtoName = protoconf::ThemeConf::GetDescriptor()->name(); bool ThemeConf::Load(const std::string& dir, Format fmt, std::shared_ptr options /* = nullptr */) { tableau::util::TimeProfiler profiler; @@ -286,7 +286,7 @@ const std::string* ThemeConf::Get(const std::string& name, const std::string& pa return &iter->second; } -const std::string TaskConf::kProtoName = "TaskConf"; +const std::string TaskConf::kProtoName = protoconf::TaskConf::GetDescriptor()->name(); bool TaskConf::Load(const std::string& dir, Format fmt, std::shared_ptr options /* = nullptr */) { tableau::util::TimeProfiler profiler; diff --git a/test/cpp-tableau-loader/src/protoconf/util.pc.cc b/test/cpp-tableau-loader/src/protoconf/util.pc.cc index 98ee62de..cdea4731 100644 --- a/test/cpp-tableau-loader/src/protoconf/util.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/util.pc.cc @@ -27,42 +27,18 @@ const std::string kTextExt = ".txt"; const std::string kBinExt = ".bin"; namespace util { -int Mkdir(const std::string& path) { - std::error_code ec; - if (!std::filesystem::create_directories(path, ec)) { - if (ec) { - std::cerr << "system error: " << ec.message() << std::endl; - return -1; - } - } - return 0; -} - -std::string GetDir(const std::string& path) { return std::filesystem::path(path).parent_path().string(); } - -bool ExistsFile(const std::string& filename) { return std::filesystem::exists(filename); } - bool ReadFile(const std::string& filename, std::string& content) { std::ifstream file(filename); if (!file.is_open()) { SetErrMsg("failed to open " + filename + ": " + strerror(errno)); return false; } - std::stringstream ss; - ss << file.rdbuf(); - content = ss.str(); + content.assign(std::istreambuf_iterator(file), {}); return true; } -std::string GetExt(const std::string& path) { - std::size_t pos = path.find_last_of("."); - if (pos != std::string::npos) { - return path.substr(pos); - } - return kEmpty; -} - -Format Ext2Format(const std::string& ext) { +Format GetFormat(const std::string& path) { + auto ext = std::filesystem::path(path).extension(); if (ext == kJSONExt) { return Format::kJSON; } else if (ext == kTextExt) { @@ -98,7 +74,7 @@ bool JSON2Message(const std::string& json, google::protobuf::Message& msg, status = google::protobuf::util::JsonStringToMessage(json, &msg); } if (!status.ok()) { - SetErrMsg("failed to parse " + GetProtoName(msg) + kJSONExt + ": " + status.ToString()); + SetErrMsg("failed to parse " + msg.GetDescriptor()->name() + kJSONExt + ": " + status.ToString()); return false; } return true; @@ -106,35 +82,20 @@ bool JSON2Message(const std::string& json, google::protobuf::Message& msg, bool Text2Message(const std::string& text, google::protobuf::Message& msg) { if (!google::protobuf::TextFormat::ParseFromString(text, &msg)) { - SetErrMsg("failed to parse " + GetProtoName(msg) + kTextExt); + SetErrMsg("failed to parse " + msg.GetDescriptor()->name() + kTextExt); return false; } return true; } + bool Bin2Message(const std::string& bin, google::protobuf::Message& msg) { if (!msg.ParseFromString(bin)) { - SetErrMsg("failed to parse " + GetProtoName(msg) + kBinExt); + SetErrMsg("failed to parse " + msg.GetDescriptor()->name() + kBinExt); return false; } return true; } -const std::string& GetProtoName(const google::protobuf::Message& msg) { - const auto* md = msg.GetDescriptor(); - return md != nullptr ? md->name() : kEmpty; -} - -std::string GetPatchName(tableau::Patch patch) { - auto* descriptor = tableau::Patch_descriptor(); - if (descriptor) { - auto* value = descriptor->FindValueByNumber(patch); - if (value) { - return value->name(); - } - } - return std::to_string(static_cast(patch)); -} - // refer: https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/stubs/logging.h void ProtobufLogHandler(google::protobuf::LogLevel level, const char* filename, int line, const std::string& msg) { static const std::unordered_map kLevelMap = {{google::protobuf::LOGLEVEL_INFO, log::kInfo}, diff --git a/test/cpp-tableau-loader/src/protoconf/util.pc.h b/test/cpp-tableau-loader/src/protoconf/util.pc.h index 6d5a94fc..ef6833a2 100644 --- a/test/cpp-tableau-loader/src/protoconf/util.pc.h +++ b/test/cpp-tableau-loader/src/protoconf/util.pc.h @@ -53,27 +53,11 @@ inline std::size_t SugaredHashCombine(const T& v, O... others) { return seed; } -// Mkdir makes dir recursively. -int Mkdir(const std::string& path); -// GetDir returns all but the last element of path, typically the path's -// directory. -std::string GetDir(const std::string& path); -// ExistsFile checks if a file exists. -bool ExistsFile(const std::string& filename); // ReadFile reads the file named by filename and returns the contents. bool ReadFile(const std::string& filename, std::string& content); -// GetExt returns the file name extension used by path. -// The extension is the suffix beginning at the final dot -// in the final element of path; it is empty if there is -// no dot. -std::string GetExt(const std::string& path); -// Convert file extension to Format type. -// NOTE: ext includes dot ".", such as: -// - kJSONExt: ".json" -// - kTextExt: ".txt" -// - kBinExt: ".bin" -Format Ext2Format(const std::string& ext); +// GetFormat returns the Format type used by path. +Format GetFormat(const std::string& path); // Empty string will be returned if an unsupported enum value has been passed, // and the error message can be obtained by GetErrMsg(). const std::string& Format2Ext(Format fmt); @@ -83,9 +67,6 @@ bool JSON2Message(const std::string& json, google::protobuf::Message& msg, bool Text2Message(const std::string& text, google::protobuf::Message& msg); bool Bin2Message(const std::string& bin, google::protobuf::Message& msg); -const std::string& GetProtoName(const google::protobuf::Message& msg); -std::string GetPatchName(tableau::Patch patch); - void ProtobufLogHandler(google::protobuf::LogLevel level, const char* filename, int line, const std::string& msg); class TimeProfiler { From 25d1e353a43cec2a80114939ca6ae4e3ecbf5d55 Mon Sep 17 00:00:00 2001 From: Kybxd <627940450@qq.com> Date: Fri, 15 Aug 2025 22:29:31 +0800 Subject: [PATCH 3/5] feat: use std::filesystem::path instead of std::string --- .../embed/load.pc.cc | 25 ++++++++++--------- .../embed/load.pc.h | 23 ++++++++++------- .../embed/util.pc.cc | 8 +++--- .../embed/util.pc.h | 6 ++--- cmd/protoc-gen-cpp-tableau-loader/hub.go | 8 +++--- cmd/protoc-gen-cpp-tableau-loader/messager.go | 5 ++-- .../src/hub/custom/item/custom_item_conf.h | 2 +- .../src/protoconf/hero_conf.pc.cc | 4 +-- .../src/protoconf/hero_conf.pc.h | 5 ++-- .../src/protoconf/hub.pc.cc | 4 +-- .../cpp-tableau-loader/src/protoconf/hub.pc.h | 4 +-- .../src/protoconf/item_conf.pc.cc | 2 +- .../src/protoconf/item_conf.pc.h | 3 ++- .../src/protoconf/load.pc.cc | 25 ++++++++++--------- .../src/protoconf/load.pc.h | 23 ++++++++++------- .../src/protoconf/patch_conf.pc.cc | 6 ++--- .../src/protoconf/patch_conf.pc.h | 7 +++--- .../src/protoconf/test_conf.pc.cc | 8 +++--- .../src/protoconf/test_conf.pc.h | 9 ++++--- .../src/protoconf/util.pc.cc | 8 +++--- .../src/protoconf/util.pc.h | 6 ++--- 21 files changed, 104 insertions(+), 87 deletions(-) diff --git a/cmd/protoc-gen-cpp-tableau-loader/embed/load.pc.cc b/cmd/protoc-gen-cpp-tableau-loader/embed/load.pc.cc index 60a3556f..8a0c591f 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/embed/load.pc.cc +++ b/cmd/protoc-gen-cpp-tableau-loader/embed/load.pc.cc @@ -6,6 +6,7 @@ #include "util.pc.h" namespace tableau { +const std::string Messager::kProtoName = ""; // Forward declaration of the PatchMessage function bool PatchMessage(google::protobuf::Message& dst, const google::protobuf::Message& src); @@ -64,8 +65,8 @@ std::shared_ptr ParseMessagerOptions(std::shared_ptr options /* = nullptr*/) { +bool LoadMessagerWithPatch(google::protobuf::Message& msg, const std::filesystem::path& path, Format fmt, + tableau::Patch patch, std::shared_ptr options /* = nullptr*/) { if (options == nullptr) { return LoadMessager(msg, path, fmt, nullptr); } @@ -74,18 +75,18 @@ bool LoadMessagerWithPatch(google::protobuf::Message& msg, const std::string& pa return options->load_func(msg, path, fmt, nullptr); } const std::string& name = msg.GetDescriptor()->name(); - std::vector patch_paths; + std::vector patch_paths; if (!options->patch_paths.empty()) { // patch path specified in PatchPaths, then use it instead of PatchDirs. patch_paths = options->patch_paths; } else { - std::string filename = name + util::Format2Ext(fmt); + std::filesystem::path filename = name + util::Format2Ext(fmt); for (auto&& patch_dir : options->patch_dirs) { - patch_paths.emplace_back((std::filesystem::path(patch_dir) / filename).string()); + patch_paths.emplace_back(patch_dir / filename); } } - std::vector existed_patch_paths; + std::vector existed_patch_paths; for (auto&& patch_path : patch_paths) { if (std::filesystem::exists(patch_path)) { existed_patch_paths.emplace_back(patch_path); @@ -103,7 +104,7 @@ bool LoadMessagerWithPatch(google::protobuf::Message& msg, const std::string& pa switch (patch) { case tableau::PATCH_REPLACE: { // just use the last "patch" file - std::string& patch_path = existed_patch_paths.back(); + std::filesystem::path& patch_path = existed_patch_paths.back(); if (!options->load_func(msg, patch_path, util::GetFormat(patch_path), options)) { return false; } @@ -140,7 +141,7 @@ bool LoadMessagerWithPatch(google::protobuf::Message& msg, const std::string& pa return true; } -bool LoadMessager(google::protobuf::Message& msg, const std::string& path, Format fmt, +bool LoadMessager(google::protobuf::Message& msg, const std::filesystem::path& path, Format fmt, std::shared_ptr options /* = nullptr*/) { std::string content; ReadFunc read_func = util::ReadFile; @@ -168,18 +169,18 @@ bool LoadMessager(google::protobuf::Message& msg, const std::string& path, Forma } } -bool LoadMessagerInDir(google::protobuf::Message& msg, const std::string& dir, Format fmt, +bool LoadMessagerInDir(google::protobuf::Message& msg, const std::filesystem::path& dir, Format fmt, std::shared_ptr options /* = nullptr*/) { const std::string& name = msg.GetDescriptor()->name(); - std::string path; + std::filesystem::path path; if (options && !options->path.empty()) { // path specified in Paths, then use it instead of dir. path = options->path; fmt = util::GetFormat(path); } if (path.empty()) { - std::string filename = name + util::Format2Ext(fmt); - path = (std::filesystem::path(dir) / filename).string(); + std::filesystem::path filename = name + util::Format2Ext(fmt); + path = dir / filename; } const google::protobuf::Descriptor* descriptor = msg.GetDescriptor(); diff --git a/cmd/protoc-gen-cpp-tableau-loader/embed/load.pc.h b/cmd/protoc-gen-cpp-tableau-loader/embed/load.pc.h index b37f05a8..63e0a831 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/embed/load.pc.h +++ b/cmd/protoc-gen-cpp-tableau-loader/embed/load.pc.h @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -20,10 +21,10 @@ struct MessagerOptions; class Hub; // ReadFunc reads the config file and returns its content. -using ReadFunc = std::function; +using ReadFunc = std::function; // LoadFunc defines a func which can load message's content based on the given // path, format, and options. -using LoadFunc = std::function options)>; // BaseOptions is the common struct for both global-level and messager-level @@ -34,7 +35,7 @@ struct BaseOptions { // Refer https://protobuf.dev/reference/cpp/api-docs/google.protobuf.util.json_util/#JsonParseOptions. std::optional ignore_unknown_fields; // Specify the directory paths for config patching. - std::vector patch_dirs; + std::vector patch_dirs; // Specify the loading mode for config patching. // - For LoadOptions, default is LoadMode::kModeAll. // - For MessagerOptions, inherit from LoadOptions if not set. @@ -63,10 +64,10 @@ struct MessagerOptions : public BaseOptions { // Path maps each messager name to a corresponding config file path. // If specified, then the main messager will be parsed from the file // directly, other than the specified load dir. - std::string path; + std::filesystem::path path; // Patch paths maps each messager name to one or multiple corresponding patch file paths. // If specified, then main messager will be patched. - std::vector patch_paths; + std::vector patch_paths; }; class Messager { @@ -77,10 +78,11 @@ class Messager { public: virtual ~Messager() = default; - static const std::string& Name() { return kEmpty; } + static const std::string& Name() { return kProtoName; } const Stats& GetStats() { return stats_; } // Load fills message from file in the specified directory and format. - virtual bool Load(const std::string& dir, Format fmt, std::shared_ptr options = nullptr) = 0; + virtual bool Load(const std::filesystem::path& dir, Format fmt, + std::shared_ptr options = nullptr) = 0; // Message returns the inner message data. virtual const google::protobuf::Message* Message() const { return nullptr; } // callback after all messagers loaded. @@ -90,6 +92,9 @@ class Messager { // callback after this messager loaded. virtual bool ProcessAfterLoad() { return true; }; Stats stats_; + + private: + static const std::string kProtoName; }; // ParseLoadOptions parses load options with default global-level options. @@ -98,8 +103,8 @@ std::shared_ptr ParseLoadOptions(std::shared_ptr ParseMessagerOptions(std::shared_ptr opts, const std::string& name); -bool LoadMessager(google::protobuf::Message& msg, const std::string& path, Format fmt = Format::kJSON, +bool LoadMessager(google::protobuf::Message& msg, const std::filesystem::path& path, Format fmt = Format::kJSON, std::shared_ptr options = nullptr); -bool LoadMessagerInDir(google::protobuf::Message& msg, const std::string& dir, Format fmt = Format::kJSON, +bool LoadMessagerInDir(google::protobuf::Message& msg, const std::filesystem::path& dir, Format fmt = Format::kJSON, std::shared_ptr options = nullptr); } // namespace tableau \ No newline at end of file diff --git a/cmd/protoc-gen-cpp-tableau-loader/embed/util.pc.cc b/cmd/protoc-gen-cpp-tableau-loader/embed/util.pc.cc index da57e612..11236ea3 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/embed/util.pc.cc +++ b/cmd/protoc-gen-cpp-tableau-loader/embed/util.pc.cc @@ -22,18 +22,18 @@ const std::string kTextExt = ".txt"; const std::string kBinExt = ".bin"; namespace util { -bool ReadFile(const std::string& filename, std::string& content) { +bool ReadFile(const std::filesystem::path& filename, std::string& content) { std::ifstream file(filename); if (!file.is_open()) { - SetErrMsg("failed to open " + filename + ": " + strerror(errno)); + SetErrMsg("failed to open " + filename.string() + ": " + strerror(errno)); return false; } content.assign(std::istreambuf_iterator(file), {}); return true; } -Format GetFormat(const std::string& path) { - auto ext = std::filesystem::path(path).extension(); +Format GetFormat(const std::filesystem::path& path) { + auto ext = path.extension(); if (ext == kJSONExt) { return Format::kJSON; } else if (ext == kTextExt) { diff --git a/cmd/protoc-gen-cpp-tableau-loader/embed/util.pc.h b/cmd/protoc-gen-cpp-tableau-loader/embed/util.pc.h index c7bdc213..72350710 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/embed/util.pc.h +++ b/cmd/protoc-gen-cpp-tableau-loader/embed/util.pc.h @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -18,7 +19,6 @@ enum class Format { kBin, }; -static const std::string kEmpty = ""; extern const std::string kUnknownExt; extern const std::string kJSONExt; extern const std::string kTextExt; @@ -49,10 +49,10 @@ inline std::size_t SugaredHashCombine(const T& v, O... others) { } // ReadFile reads the file named by filename and returns the contents. -bool ReadFile(const std::string& filename, std::string& content); +bool ReadFile(const std::filesystem::path& filename, std::string& content); // GetFormat returns the Format type used by path. -Format GetFormat(const std::string& path); +Format GetFormat(const std::filesystem::path& path); // Empty string will be returned if an unsupported enum value has been passed, // and the error message can be obtained by GetErrMsg(). const std::string& Format2Ext(Format fmt); diff --git a/cmd/protoc-gen-cpp-tableau-loader/hub.go b/cmd/protoc-gen-cpp-tableau-loader/hub.go index 5acf90a9..9674d74d 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/hub.go +++ b/cmd/protoc-gen-cpp-tableau-loader/hub.go @@ -179,12 +179,12 @@ class Hub { /***** Synchronous Loading *****/ // Load fills messages (in MessagerContainer) from files in the specified directory and format. - bool Load(const std::string& dir, Format fmt = Format::kJSON, std::shared_ptr options = nullptr); + bool Load(const std::filesystem::path& dir, Format fmt = Format::kJSON, std::shared_ptr options = nullptr); /***** Asynchronous Loading *****/ // Load configs into temp MessagerContainer, and you should call LoopOnce() in you app's main loop, // in order to take the temp MessagerContainer into effect. - bool AsyncLoad(const std::string& dir, Format fmt = Format::kJSON, + bool AsyncLoad(const std::filesystem::path& dir, Format fmt = Format::kJSON, std::shared_ptr options = nullptr); int LoopOnce(); // You'd better initialize the scheduler in the main thread. @@ -308,7 +308,7 @@ void Hub::InitOnce(std::shared_ptr options) { std::call_once(init_once_, [&]() { options_ = options; }); } -bool Hub::Load(const std::string& dir, Format fmt /* = Format::kJSON */, +bool Hub::Load(const std::filesystem::path& dir, Format fmt /* = Format::kJSON */, std::shared_ptr options /* = nullptr */) { auto msger_map = InternalLoad(dir, fmt, options); if (!msger_map) { @@ -322,7 +322,7 @@ bool Hub::Load(const std::string& dir, Format fmt /* = Format::kJSON */, return true; } -bool Hub::AsyncLoad(const std::string& dir, Format fmt /* = Format::kJSON */, +bool Hub::AsyncLoad(const std::filesystem::path& dir, Format fmt /* = Format::kJSON */, std::shared_ptr options /* = nullptr */) { auto msger_map = InternalLoad(dir, fmt, options); if (!msger_map) { diff --git a/cmd/protoc-gen-cpp-tableau-loader/messager.go b/cmd/protoc-gen-cpp-tableau-loader/messager.go index f7cf6be0..8734d486 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/messager.go +++ b/cmd/protoc-gen-cpp-tableau-loader/messager.go @@ -43,6 +43,7 @@ func generateCppFile(gen *protogen.Plugin, file *protogen.File) *protogen.Genera // generateHppFileContent generates type definitions. func generateHppFileContent(file *protogen.File, g *protogen.GeneratedFile) { g.P("#pragma once") + g.P("#include ") g.P("#include ") g.P() g.P(`#include "`, "load.", pcExt, `.h"`) @@ -84,7 +85,7 @@ func genHppMessage(g *protogen.GeneratedFile, message *protogen.Message) { g.P("class ", message.Desc.Name(), " : 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::string& dir, Format fmt, std::shared_ptr options = nullptr) override;") + 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() @@ -158,7 +159,7 @@ func genCppMessage(g *protogen.GeneratedFile, message *protogen.Message) { g.P("const std::string ", messagerName, "::kProtoName = ", cppFullName, `::GetDescriptor()->name();`) g.P() - g.P("bool ", messagerName, "::Load(const std::string& dir, Format fmt, std::shared_ptr options /* = nullptr */) {") + g.P("bool ", messagerName, "::Load(const std::filesystem::path& dir, Format fmt, std::shared_ptr options /* = nullptr */) {") g.P(helper.Indent(1), "tableau::util::TimeProfiler profiler;") g.P(helper.Indent(1), "bool loaded = LoadMessagerInDir(data_, dir, fmt, options);") g.P(helper.Indent(1), "bool ok = loaded ? ProcessAfterLoad() : false;") diff --git a/test/cpp-tableau-loader/src/hub/custom/item/custom_item_conf.h b/test/cpp-tableau-loader/src/hub/custom/item/custom_item_conf.h index 76835861..637d9e41 100644 --- a/test/cpp-tableau-loader/src/hub/custom/item/custom_item_conf.h +++ b/test/cpp-tableau-loader/src/hub/custom/item/custom_item_conf.h @@ -4,7 +4,7 @@ class CustomItemConf : public tableau::Messager { public: static const std::string& Name() { return kCustomName; }; - virtual bool Load(const std::string&, tableau::Format, + virtual bool Load(const std::filesystem::path&, tableau::Format, std::shared_ptr options = nullptr) override { return true; } diff --git a/test/cpp-tableau-loader/src/protoconf/hero_conf.pc.cc b/test/cpp-tableau-loader/src/protoconf/hero_conf.pc.cc index 873a10e6..b5433ffa 100644 --- a/test/cpp-tableau-loader/src/protoconf/hero_conf.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/hero_conf.pc.cc @@ -12,7 +12,7 @@ namespace tableau { const std::string HeroConf::kProtoName = protoconf::HeroConf::GetDescriptor()->name(); -bool HeroConf::Load(const std::string& dir, Format fmt, std::shared_ptr options /* = nullptr */) { +bool HeroConf::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; @@ -71,7 +71,7 @@ const HeroConf::Hero_Attr_OrderedMap* HeroConf::GetOrderedMap(const std::string& const std::string HeroBaseConf::kProtoName = protoconf::HeroBaseConf::GetDescriptor()->name(); -bool HeroBaseConf::Load(const std::string& dir, Format fmt, std::shared_ptr options /* = nullptr */) { +bool HeroBaseConf::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; 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 e07b07c4..006f646b 100644 --- a/test/cpp-tableau-loader/src/protoconf/hero_conf.pc.h +++ b/test/cpp-tableau-loader/src/protoconf/hero_conf.pc.h @@ -5,6 +5,7 @@ // source: hero_conf.proto #pragma once +#include #include #include "load.pc.h" @@ -15,7 +16,7 @@ namespace tableau { class HeroConf : public Messager { public: static const std::string& Name() { return kProtoName; } - virtual bool Load(const std::string& dir, Format fmt, std::shared_ptr options = nullptr) override; + 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_; } @@ -46,7 +47,7 @@ class HeroConf : public Messager { class HeroBaseConf : public Messager { public: static const std::string& Name() { return kProtoName; } - virtual bool Load(const std::string& dir, Format fmt, std::shared_ptr options = nullptr) override; + 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_; } diff --git a/test/cpp-tableau-loader/src/protoconf/hub.pc.cc b/test/cpp-tableau-loader/src/protoconf/hub.pc.cc index 4953d5e1..3c3658fc 100644 --- a/test/cpp-tableau-loader/src/protoconf/hub.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/hub.pc.cc @@ -19,7 +19,7 @@ void Hub::InitOnce(std::shared_ptr options) { std::call_once(init_once_, [&]() { options_ = options; }); } -bool Hub::Load(const std::string& dir, Format fmt /* = Format::kJSON */, +bool Hub::Load(const std::filesystem::path& dir, Format fmt /* = Format::kJSON */, std::shared_ptr options /* = nullptr */) { auto msger_map = InternalLoad(dir, fmt, options); if (!msger_map) { @@ -33,7 +33,7 @@ bool Hub::Load(const std::string& dir, Format fmt /* = Format::kJSON */, return true; } -bool Hub::AsyncLoad(const std::string& dir, Format fmt /* = Format::kJSON */, +bool Hub::AsyncLoad(const std::filesystem::path& dir, Format fmt /* = Format::kJSON */, std::shared_ptr options /* = nullptr */) { auto msger_map = InternalLoad(dir, fmt, options); if (!msger_map) { diff --git a/test/cpp-tableau-loader/src/protoconf/hub.pc.h b/test/cpp-tableau-loader/src/protoconf/hub.pc.h index e80c9710..73f1c068 100644 --- a/test/cpp-tableau-loader/src/protoconf/hub.pc.h +++ b/test/cpp-tableau-loader/src/protoconf/hub.pc.h @@ -44,12 +44,12 @@ class Hub { /***** Synchronous Loading *****/ // Load fills messages (in MessagerContainer) from files in the specified directory and format. - bool Load(const std::string& dir, Format fmt = Format::kJSON, std::shared_ptr options = nullptr); + bool Load(const std::filesystem::path& dir, Format fmt = Format::kJSON, std::shared_ptr options = nullptr); /***** Asynchronous Loading *****/ // Load configs into temp MessagerContainer, and you should call LoopOnce() in you app's main loop, // in order to take the temp MessagerContainer into effect. - bool AsyncLoad(const std::string& dir, Format fmt = Format::kJSON, + bool AsyncLoad(const std::filesystem::path& dir, Format fmt = Format::kJSON, std::shared_ptr options = nullptr); int LoopOnce(); // You'd better initialize the scheduler in the main thread. 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 07723bbe..98963d31 100644 --- a/test/cpp-tableau-loader/src/protoconf/item_conf.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/item_conf.pc.cc @@ -12,7 +12,7 @@ namespace tableau { const std::string ItemConf::kProtoName = protoconf::ItemConf::GetDescriptor()->name(); -bool ItemConf::Load(const std::string& dir, Format fmt, std::shared_ptr options /* = nullptr */) { +bool ItemConf::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; 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 308b99e1..f5e1b9c9 100644 --- a/test/cpp-tableau-loader/src/protoconf/item_conf.pc.h +++ b/test/cpp-tableau-loader/src/protoconf/item_conf.pc.h @@ -5,6 +5,7 @@ // source: item_conf.proto #pragma once +#include #include #include "load.pc.h" @@ -15,7 +16,7 @@ namespace tableau { class ItemConf : public Messager { public: static const std::string& Name() { return kProtoName; } - virtual bool Load(const std::string& dir, Format fmt, std::shared_ptr options = nullptr) override; + 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_; } diff --git a/test/cpp-tableau-loader/src/protoconf/load.pc.cc b/test/cpp-tableau-loader/src/protoconf/load.pc.cc index 4a57baa4..e83e15f0 100644 --- a/test/cpp-tableau-loader/src/protoconf/load.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/load.pc.cc @@ -11,6 +11,7 @@ #include "util.pc.h" namespace tableau { +const std::string Messager::kProtoName = ""; // Forward declaration of the PatchMessage function bool PatchMessage(google::protobuf::Message& dst, const google::protobuf::Message& src); @@ -69,8 +70,8 @@ std::shared_ptr ParseMessagerOptions(std::shared_ptr options /* = nullptr*/) { +bool LoadMessagerWithPatch(google::protobuf::Message& msg, const std::filesystem::path& path, Format fmt, + tableau::Patch patch, std::shared_ptr options /* = nullptr*/) { if (options == nullptr) { return LoadMessager(msg, path, fmt, nullptr); } @@ -79,18 +80,18 @@ bool LoadMessagerWithPatch(google::protobuf::Message& msg, const std::string& pa return options->load_func(msg, path, fmt, nullptr); } const std::string& name = msg.GetDescriptor()->name(); - std::vector patch_paths; + std::vector patch_paths; if (!options->patch_paths.empty()) { // patch path specified in PatchPaths, then use it instead of PatchDirs. patch_paths = options->patch_paths; } else { - std::string filename = name + util::Format2Ext(fmt); + std::filesystem::path filename = name + util::Format2Ext(fmt); for (auto&& patch_dir : options->patch_dirs) { - patch_paths.emplace_back((std::filesystem::path(patch_dir) / filename).string()); + patch_paths.emplace_back(patch_dir / filename); } } - std::vector existed_patch_paths; + std::vector existed_patch_paths; for (auto&& patch_path : patch_paths) { if (std::filesystem::exists(patch_path)) { existed_patch_paths.emplace_back(patch_path); @@ -108,7 +109,7 @@ bool LoadMessagerWithPatch(google::protobuf::Message& msg, const std::string& pa switch (patch) { case tableau::PATCH_REPLACE: { // just use the last "patch" file - std::string& patch_path = existed_patch_paths.back(); + std::filesystem::path& patch_path = existed_patch_paths.back(); if (!options->load_func(msg, patch_path, util::GetFormat(patch_path), options)) { return false; } @@ -145,7 +146,7 @@ bool LoadMessagerWithPatch(google::protobuf::Message& msg, const std::string& pa return true; } -bool LoadMessager(google::protobuf::Message& msg, const std::string& path, Format fmt, +bool LoadMessager(google::protobuf::Message& msg, const std::filesystem::path& path, Format fmt, std::shared_ptr options /* = nullptr*/) { std::string content; ReadFunc read_func = util::ReadFile; @@ -173,18 +174,18 @@ bool LoadMessager(google::protobuf::Message& msg, const std::string& path, Forma } } -bool LoadMessagerInDir(google::protobuf::Message& msg, const std::string& dir, Format fmt, +bool LoadMessagerInDir(google::protobuf::Message& msg, const std::filesystem::path& dir, Format fmt, std::shared_ptr options /* = nullptr*/) { const std::string& name = msg.GetDescriptor()->name(); - std::string path; + std::filesystem::path path; if (options && !options->path.empty()) { // path specified in Paths, then use it instead of dir. path = options->path; fmt = util::GetFormat(path); } if (path.empty()) { - std::string filename = name + util::Format2Ext(fmt); - path = (std::filesystem::path(dir) / filename).string(); + std::filesystem::path filename = name + util::Format2Ext(fmt); + path = dir / filename; } const google::protobuf::Descriptor* descriptor = msg.GetDescriptor(); diff --git a/test/cpp-tableau-loader/src/protoconf/load.pc.h b/test/cpp-tableau-loader/src/protoconf/load.pc.h index b9088234..b3233e8e 100644 --- a/test/cpp-tableau-loader/src/protoconf/load.pc.h +++ b/test/cpp-tableau-loader/src/protoconf/load.pc.h @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -25,10 +26,10 @@ struct MessagerOptions; class Hub; // ReadFunc reads the config file and returns its content. -using ReadFunc = std::function; +using ReadFunc = std::function; // LoadFunc defines a func which can load message's content based on the given // path, format, and options. -using LoadFunc = std::function options)>; // BaseOptions is the common struct for both global-level and messager-level @@ -39,7 +40,7 @@ struct BaseOptions { // Refer https://protobuf.dev/reference/cpp/api-docs/google.protobuf.util.json_util/#JsonParseOptions. std::optional ignore_unknown_fields; // Specify the directory paths for config patching. - std::vector patch_dirs; + std::vector patch_dirs; // Specify the loading mode for config patching. // - For LoadOptions, default is LoadMode::kModeAll. // - For MessagerOptions, inherit from LoadOptions if not set. @@ -68,10 +69,10 @@ struct MessagerOptions : public BaseOptions { // Path maps each messager name to a corresponding config file path. // If specified, then the main messager will be parsed from the file // directly, other than the specified load dir. - std::string path; + std::filesystem::path path; // Patch paths maps each messager name to one or multiple corresponding patch file paths. // If specified, then main messager will be patched. - std::vector patch_paths; + std::vector patch_paths; }; class Messager { @@ -82,10 +83,11 @@ class Messager { public: virtual ~Messager() = default; - static const std::string& Name() { return kEmpty; } + static const std::string& Name() { return kProtoName; } const Stats& GetStats() { return stats_; } // Load fills message from file in the specified directory and format. - virtual bool Load(const std::string& dir, Format fmt, std::shared_ptr options = nullptr) = 0; + virtual bool Load(const std::filesystem::path& dir, Format fmt, + std::shared_ptr options = nullptr) = 0; // Message returns the inner message data. virtual const google::protobuf::Message* Message() const { return nullptr; } // callback after all messagers loaded. @@ -95,6 +97,9 @@ class Messager { // callback after this messager loaded. virtual bool ProcessAfterLoad() { return true; }; Stats stats_; + + private: + static const std::string kProtoName; }; // ParseLoadOptions parses load options with default global-level options. @@ -103,8 +108,8 @@ std::shared_ptr ParseLoadOptions(std::shared_ptr ParseMessagerOptions(std::shared_ptr opts, const std::string& name); -bool LoadMessager(google::protobuf::Message& msg, const std::string& path, Format fmt = Format::kJSON, +bool LoadMessager(google::protobuf::Message& msg, const std::filesystem::path& path, Format fmt = Format::kJSON, std::shared_ptr options = nullptr); -bool LoadMessagerInDir(google::protobuf::Message& msg, const std::string& dir, Format fmt = Format::kJSON, +bool LoadMessagerInDir(google::protobuf::Message& msg, const std::filesystem::path& dir, Format fmt = Format::kJSON, std::shared_ptr options = nullptr); } // namespace tableau diff --git a/test/cpp-tableau-loader/src/protoconf/patch_conf.pc.cc b/test/cpp-tableau-loader/src/protoconf/patch_conf.pc.cc index 544f13e9..f197abca 100644 --- a/test/cpp-tableau-loader/src/protoconf/patch_conf.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/patch_conf.pc.cc @@ -12,7 +12,7 @@ namespace tableau { const std::string PatchReplaceConf::kProtoName = protoconf::PatchReplaceConf::GetDescriptor()->name(); -bool PatchReplaceConf::Load(const std::string& dir, Format fmt, std::shared_ptr options /* = nullptr */) { +bool PatchReplaceConf::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; @@ -22,7 +22,7 @@ bool PatchReplaceConf::Load(const std::string& dir, Format fmt, std::shared_ptr< const std::string PatchMergeConf::kProtoName = protoconf::PatchMergeConf::GetDescriptor()->name(); -bool PatchMergeConf::Load(const std::string& dir, Format fmt, std::shared_ptr options /* = nullptr */) { +bool PatchMergeConf::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; @@ -40,7 +40,7 @@ const protoconf::Item* PatchMergeConf::Get(uint32_t id) const { const std::string RecursivePatchConf::kProtoName = protoconf::RecursivePatchConf::GetDescriptor()->name(); -bool RecursivePatchConf::Load(const std::string& dir, Format fmt, std::shared_ptr options /* = nullptr */) { +bool RecursivePatchConf::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; 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 191fd685..d92a8c38 100644 --- a/test/cpp-tableau-loader/src/protoconf/patch_conf.pc.h +++ b/test/cpp-tableau-loader/src/protoconf/patch_conf.pc.h @@ -5,6 +5,7 @@ // source: patch_conf.proto #pragma once +#include #include #include "load.pc.h" @@ -15,7 +16,7 @@ namespace tableau { class PatchReplaceConf : public Messager { public: static const std::string& Name() { return kProtoName; } - virtual bool Load(const std::string& dir, Format fmt, std::shared_ptr options = nullptr) override; + 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_; } @@ -28,7 +29,7 @@ class PatchReplaceConf : public Messager { class PatchMergeConf : public Messager { public: static const std::string& Name() { return kProtoName; } - virtual bool Load(const std::string& dir, Format fmt, std::shared_ptr options = nullptr) override; + 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_; } @@ -43,7 +44,7 @@ class PatchMergeConf : public Messager { class RecursivePatchConf : public Messager { public: static const std::string& Name() { return kProtoName; } - virtual bool Load(const std::string& dir, Format fmt, std::shared_ptr options = nullptr) override; + 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_; } 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 1198d114..4d9dc39d 100644 --- a/test/cpp-tableau-loader/src/protoconf/test_conf.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/test_conf.pc.cc @@ -12,7 +12,7 @@ namespace tableau { const std::string ActivityConf::kProtoName = protoconf::ActivityConf::GetDescriptor()->name(); -bool ActivityConf::Load(const std::string& dir, Format fmt, std::shared_ptr options /* = nullptr */) { +bool ActivityConf::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; @@ -240,7 +240,7 @@ const protoconf::Section::SectionItem* ActivityConf::FindFirstAward(uint32_t id) const std::string ChapterConf::kProtoName = protoconf::ChapterConf::GetDescriptor()->name(); -bool ChapterConf::Load(const std::string& dir, Format fmt, std::shared_ptr options /* = nullptr */) { +bool ChapterConf::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; @@ -258,7 +258,7 @@ const protoconf::ChapterConf::Chapter* ChapterConf::Get(uint64_t id) const { const std::string ThemeConf::kProtoName = protoconf::ThemeConf::GetDescriptor()->name(); -bool ThemeConf::Load(const std::string& dir, Format fmt, std::shared_ptr options /* = nullptr */) { +bool ThemeConf::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; @@ -288,7 +288,7 @@ const std::string* ThemeConf::Get(const std::string& name, const std::string& pa const std::string TaskConf::kProtoName = protoconf::TaskConf::GetDescriptor()->name(); -bool TaskConf::Load(const std::string& dir, Format fmt, std::shared_ptr options /* = nullptr */) { +bool TaskConf::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; 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 2b12c0e0..bec18ae3 100644 --- a/test/cpp-tableau-loader/src/protoconf/test_conf.pc.h +++ b/test/cpp-tableau-loader/src/protoconf/test_conf.pc.h @@ -5,6 +5,7 @@ // source: test_conf.proto #pragma once +#include #include #include "load.pc.h" @@ -15,7 +16,7 @@ namespace tableau { class ActivityConf : public Messager { public: static const std::string& Name() { return kProtoName; } - virtual bool Load(const std::string& dir, Format fmt, std::shared_ptr options = nullptr) override; + 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_; } @@ -102,7 +103,7 @@ class ActivityConf : public Messager { class ChapterConf : public Messager { public: static const std::string& Name() { return kProtoName; } - virtual bool Load(const std::string& dir, Format fmt, std::shared_ptr options = nullptr) override; + 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_; } @@ -117,7 +118,7 @@ class ChapterConf : public Messager { class ThemeConf : public Messager { public: static const std::string& Name() { return kProtoName; } - virtual bool Load(const std::string& dir, Format fmt, std::shared_ptr options = nullptr) override; + 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_; } @@ -133,7 +134,7 @@ class ThemeConf : public Messager { class TaskConf : public Messager { public: static const std::string& Name() { return kProtoName; } - virtual bool Load(const std::string& dir, Format fmt, std::shared_ptr options = nullptr) override; + 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_; } diff --git a/test/cpp-tableau-loader/src/protoconf/util.pc.cc b/test/cpp-tableau-loader/src/protoconf/util.pc.cc index cdea4731..b404aee2 100644 --- a/test/cpp-tableau-loader/src/protoconf/util.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/util.pc.cc @@ -27,18 +27,18 @@ const std::string kTextExt = ".txt"; const std::string kBinExt = ".bin"; namespace util { -bool ReadFile(const std::string& filename, std::string& content) { +bool ReadFile(const std::filesystem::path& filename, std::string& content) { std::ifstream file(filename); if (!file.is_open()) { - SetErrMsg("failed to open " + filename + ": " + strerror(errno)); + SetErrMsg("failed to open " + filename.string() + ": " + strerror(errno)); return false; } content.assign(std::istreambuf_iterator(file), {}); return true; } -Format GetFormat(const std::string& path) { - auto ext = std::filesystem::path(path).extension(); +Format GetFormat(const std::filesystem::path& path) { + auto ext = path.extension(); if (ext == kJSONExt) { return Format::kJSON; } else if (ext == kTextExt) { diff --git a/test/cpp-tableau-loader/src/protoconf/util.pc.h b/test/cpp-tableau-loader/src/protoconf/util.pc.h index ef6833a2..3d917ef9 100644 --- a/test/cpp-tableau-loader/src/protoconf/util.pc.h +++ b/test/cpp-tableau-loader/src/protoconf/util.pc.h @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -23,7 +24,6 @@ enum class Format { kBin, }; -static const std::string kEmpty = ""; extern const std::string kUnknownExt; extern const std::string kJSONExt; extern const std::string kTextExt; @@ -54,10 +54,10 @@ inline std::size_t SugaredHashCombine(const T& v, O... others) { } // ReadFile reads the file named by filename and returns the contents. -bool ReadFile(const std::string& filename, std::string& content); +bool ReadFile(const std::filesystem::path& filename, std::string& content); // GetFormat returns the Format type used by path. -Format GetFormat(const std::string& path); +Format GetFormat(const std::filesystem::path& path); // Empty string will be returned if an unsupported enum value has been passed, // and the error message can be obtained by GetErrMsg(). const std::string& Format2Ext(Format fmt); From ff8abe7c1a97425f92308b717faa08dfc258b1ae Mon Sep 17 00:00:00 2001 From: Kybxd <627940450@qq.com> Date: Fri, 15 Aug 2025 22:33:50 +0800 Subject: [PATCH 4/5] fix: compile --- cmd/protoc-gen-cpp-tableau-loader/hub.go | 7 ++++--- test/cpp-tableau-loader/src/main.cpp | 8 +++----- test/cpp-tableau-loader/src/protoconf/hub.pc.cc | 2 +- test/cpp-tableau-loader/src/protoconf/hub.pc.h | 5 +++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/cmd/protoc-gen-cpp-tableau-loader/hub.go b/cmd/protoc-gen-cpp-tableau-loader/hub.go index 9674d74d..dee3a2cf 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/hub.go +++ b/cmd/protoc-gen-cpp-tableau-loader/hub.go @@ -179,7 +179,8 @@ class Hub { /***** Synchronous Loading *****/ // Load fills messages (in MessagerContainer) from files in the specified directory and format. - bool Load(const std::filesystem::path& dir, Format fmt = Format::kJSON, std::shared_ptr options = nullptr); + bool Load(const std::filesystem::path& dir, Format fmt = Format::kJSON, + std::shared_ptr options = nullptr); /***** Asynchronous Loading *****/ // Load configs into temp MessagerContainer, and you should call LoopOnce() in you app's main loop, @@ -212,7 +213,7 @@ class Hub { inline std::time_t GetLastLoadedTime() const; private: - std::shared_ptr InternalLoad(const std::string& dir, Format fmt = Format::kJSON, + std::shared_ptr InternalLoad(const std::filesystem::path& dir, Format fmt = Format::kJSON, std::shared_ptr options = nullptr) const; std::shared_ptr NewMessagerMap() const; std::shared_ptr GetMessagerContainerWithProvider() const; @@ -343,7 +344,7 @@ void Hub::InitScheduler() { sched_->Current(); } -std::shared_ptr Hub::InternalLoad(const std::string& dir, Format fmt /* = Format::kJSON */, +std::shared_ptr Hub::InternalLoad(const std::filesystem::path& dir, Format fmt /* = Format::kJSON */, std::shared_ptr options /* = nullptr */) const { // intercept protobuf error logs auto old_handler = google::protobuf::SetLogHandler(util::ProtobufLogHandler); diff --git a/test/cpp-tableau-loader/src/main.cpp b/test/cpp-tableau-loader/src/main.cpp index d298ff2e..f3a310ab 100644 --- a/test/cpp-tableau-loader/src/main.cpp +++ b/test/cpp-tableau-loader/src/main.cpp @@ -17,15 +17,13 @@ bool LoadWithPatch(std::shared_ptr options) { return Hub::Instance().Load("../../testdata/conf/", tableau::Format::kJSON, options); } -bool CustomReadFile(const std::string& filename, std::string& content) { +bool CustomReadFile(const std::filesystem::path& filename, std::string& content) { std::ifstream file(filename); if (!file.is_open()) { return false; } - std::stringstream ss; - ss << file.rdbuf(); - content = ss.str(); - ATOM_DEBUG("custom read %s sussess", filename.c_str()); + content.assign(std::istreambuf_iterator(file), {}); + ATOM_DEBUG("custom read %s success", filename.c_str()); return true; } diff --git a/test/cpp-tableau-loader/src/protoconf/hub.pc.cc b/test/cpp-tableau-loader/src/protoconf/hub.pc.cc index 3c3658fc..a89a9fe2 100644 --- a/test/cpp-tableau-loader/src/protoconf/hub.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/hub.pc.cc @@ -54,7 +54,7 @@ void Hub::InitScheduler() { sched_->Current(); } -std::shared_ptr Hub::InternalLoad(const std::string& dir, Format fmt /* = Format::kJSON */, +std::shared_ptr Hub::InternalLoad(const std::filesystem::path& dir, Format fmt /* = Format::kJSON */, std::shared_ptr options /* = nullptr */) const { // intercept protobuf error logs auto old_handler = google::protobuf::SetLogHandler(util::ProtobufLogHandler); diff --git a/test/cpp-tableau-loader/src/protoconf/hub.pc.h b/test/cpp-tableau-loader/src/protoconf/hub.pc.h index 73f1c068..35faa163 100644 --- a/test/cpp-tableau-loader/src/protoconf/hub.pc.h +++ b/test/cpp-tableau-loader/src/protoconf/hub.pc.h @@ -44,7 +44,8 @@ class Hub { /***** Synchronous Loading *****/ // Load fills messages (in MessagerContainer) from files in the specified directory and format. - bool Load(const std::filesystem::path& dir, Format fmt = Format::kJSON, std::shared_ptr options = nullptr); + bool Load(const std::filesystem::path& dir, Format fmt = Format::kJSON, + std::shared_ptr options = nullptr); /***** Asynchronous Loading *****/ // Load configs into temp MessagerContainer, and you should call LoopOnce() in you app's main loop, @@ -77,7 +78,7 @@ class Hub { inline std::time_t GetLastLoadedTime() const; private: - std::shared_ptr InternalLoad(const std::string& dir, Format fmt = Format::kJSON, + std::shared_ptr InternalLoad(const std::filesystem::path& dir, Format fmt = Format::kJSON, std::shared_ptr options = nullptr) const; std::shared_ptr NewMessagerMap() const; std::shared_ptr GetMessagerContainerWithProvider() const; From ffb5d3ecf52e120d83704320ef49e599269e7d9d Mon Sep 17 00:00:00 2001 From: wenchy Date: Fri, 15 Aug 2025 23:46:48 +0800 Subject: [PATCH 5/5] feat: return empty for Messager::Name() --- cmd/protoc-gen-cpp-tableau-loader/embed/load.pc.cc | 1 - cmd/protoc-gen-cpp-tableau-loader/embed/load.pc.h | 8 ++++---- cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc | 4 ++-- test/cpp-tableau-loader/src/protoconf/load.pc.cc | 1 - test/cpp-tableau-loader/src/protoconf/load.pc.h | 8 ++++---- test/cpp-tableau-loader/src/protoconf/logger.pc.cc | 4 ++-- 6 files changed, 12 insertions(+), 14 deletions(-) diff --git a/cmd/protoc-gen-cpp-tableau-loader/embed/load.pc.cc b/cmd/protoc-gen-cpp-tableau-loader/embed/load.pc.cc index 8a0c591f..2f5b68f6 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/embed/load.pc.cc +++ b/cmd/protoc-gen-cpp-tableau-loader/embed/load.pc.cc @@ -6,7 +6,6 @@ #include "util.pc.h" namespace tableau { -const std::string Messager::kProtoName = ""; // Forward declaration of the PatchMessage function bool PatchMessage(google::protobuf::Message& dst, const google::protobuf::Message& src); diff --git a/cmd/protoc-gen-cpp-tableau-loader/embed/load.pc.h b/cmd/protoc-gen-cpp-tableau-loader/embed/load.pc.h index 63e0a831..e8ba9118 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/embed/load.pc.h +++ b/cmd/protoc-gen-cpp-tableau-loader/embed/load.pc.h @@ -78,7 +78,10 @@ class Messager { public: virtual ~Messager() = default; - static const std::string& Name() { return kProtoName; } + static const std::string& Name() { + static const std::string kEmpty = ""; + return kEmpty; + } const Stats& GetStats() { return stats_; } // Load fills message from file in the specified directory and format. virtual bool Load(const std::filesystem::path& dir, Format fmt, @@ -92,9 +95,6 @@ class Messager { // callback after this messager loaded. virtual bool ProcessAfterLoad() { return true; }; Stats stats_; - - private: - static const std::string kProtoName; }; // ParseLoadOptions parses load options with default global-level options. diff --git a/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc b/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc index 5f6198e4..8f2e199c 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc +++ b/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc @@ -58,8 +58,8 @@ int Logger::Init(const std::filesystem::path& path, Level level) { std::error_code ec; std::filesystem::create_directories(path.parent_path(), ec); if (ec) { - std::cerr << "system error: " << ec.message() << std::endl; - return -1; + SetErrMsg("failed to create log directory: " + ec.message()); + return ec.value(); } ofs_.open(path, std::ofstream::out | std::ofstream::app); os_ = &ofs_; // use file stream as output stream diff --git a/test/cpp-tableau-loader/src/protoconf/load.pc.cc b/test/cpp-tableau-loader/src/protoconf/load.pc.cc index e83e15f0..62c0145f 100644 --- a/test/cpp-tableau-loader/src/protoconf/load.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/load.pc.cc @@ -11,7 +11,6 @@ #include "util.pc.h" namespace tableau { -const std::string Messager::kProtoName = ""; // Forward declaration of the PatchMessage function bool PatchMessage(google::protobuf::Message& dst, const google::protobuf::Message& src); diff --git a/test/cpp-tableau-loader/src/protoconf/load.pc.h b/test/cpp-tableau-loader/src/protoconf/load.pc.h index b3233e8e..87564d57 100644 --- a/test/cpp-tableau-loader/src/protoconf/load.pc.h +++ b/test/cpp-tableau-loader/src/protoconf/load.pc.h @@ -83,7 +83,10 @@ class Messager { public: virtual ~Messager() = default; - static const std::string& Name() { return kProtoName; } + static const std::string& Name() { + static const std::string kEmpty = ""; + return kEmpty; + } const Stats& GetStats() { return stats_; } // Load fills message from file in the specified directory and format. virtual bool Load(const std::filesystem::path& dir, Format fmt, @@ -97,9 +100,6 @@ class Messager { // callback after this messager loaded. virtual bool ProcessAfterLoad() { return true; }; Stats stats_; - - private: - static const std::string kProtoName; }; // ParseLoadOptions parses load options with default global-level options. diff --git a/test/cpp-tableau-loader/src/protoconf/logger.pc.cc b/test/cpp-tableau-loader/src/protoconf/logger.pc.cc index b5ae7651..a98045f3 100644 --- a/test/cpp-tableau-loader/src/protoconf/logger.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/logger.pc.cc @@ -63,8 +63,8 @@ int Logger::Init(const std::filesystem::path& path, Level level) { std::error_code ec; std::filesystem::create_directories(path.parent_path(), ec); if (ec) { - std::cerr << "system error: " << ec.message() << std::endl; - return -1; + SetErrMsg("failed to create log directory: " + ec.message()); + return ec.value(); } ofs_.open(path, std::ofstream::out | std::ofstream::app); os_ = &ofs_; // use file stream as output stream