* Copyright (c) 2026 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
#include "framework/runtime/dump/dump_config.h"
#include "framework/common/debug/ge_log.h"
#include "framework/common/debug/log.h"
#include <ctime>
namespace ge {
namespace dump {
namespace {
std::string GetCurrentTimeStr() {
const std::time_t now = std::time(nullptr);
const std::tm *const ptm = std::localtime(&now);
if (ptm == nullptr) {
GELOGE(ge::FAILED, "localtime failed, return empty time string");
return "";
}
constexpr int32_t kTimeBufferLen = 32;
char buffer[kTimeBufferLen + 1] = {};
(void)std::strftime(buffer, static_cast<size_t>(kTimeBufferLen), "%Y%m%d%H%M%S", ptm);
return std::string(buffer);
}
}
DumpConfig& DumpConfig::Instance() {
static DumpConfig instance;
return instance;
}
bool DumpConfig::IsDataDumpEnabled() const {
std::lock_guard<std::mutex> lock(mutex_);
return data_dump_enabled_;
}
bool DumpConfig::IsExceptionDumpEnabled() const {
std::lock_guard<std::mutex> lock(mutex_);
return exception_dump_enabled_;
}
bool DumpConfig::IsOverflowDumpEnabled() const {
std::lock_guard<std::mutex> lock(mutex_);
return overflow_dump_enabled_;
}
void DumpConfig::SetDataDumpEnabled(bool enabled) {
std::lock_guard<std::mutex> lock(mutex_);
data_dump_enabled_ = enabled;
}
void DumpConfig::SetExceptionDumpEnabled(bool enabled) {
std::lock_guard<std::mutex> lock(mutex_);
exception_dump_enabled_ = enabled;
}
void DumpConfig::SetOverflowDumpEnabled(bool enabled) {
std::lock_guard<std::mutex> lock(mutex_);
overflow_dump_enabled_ = enabled;
}
const std::string& DumpConfig::GetDumpPath() const {
std::lock_guard<std::mutex> lock(mutex_);
return dump_path_;
}
const std::string& DumpConfig::GetDumpStep() const {
std::lock_guard<std::mutex> lock(mutex_);
return dump_step_;
}
const std::string& DumpConfig::GetDumpMode() const {
std::lock_guard<std::mutex> lock(mutex_);
return dump_mode_;
}
const std::string& DumpConfig::GetDumpData() const {
std::lock_guard<std::mutex> lock(mutex_);
return dump_data_;
}
const std::unordered_set<std::string>& DumpConfig::GetOpList() const {
std::lock_guard<std::mutex> lock(mutex_);
return op_list_;
}
void DumpConfig::SetDumpPath(const std::string& path) {
std::lock_guard<std::mutex> lock(mutex_);
dump_path_ = path;
}
void DumpConfig::SetDumpStep(const std::string& step) {
std::lock_guard<std::mutex> lock(mutex_);
dump_step_ = step;
}
void DumpConfig::SetDumpMode(const std::string& mode) {
std::lock_guard<std::mutex> lock(mutex_);
dump_mode_ = mode;
}
void DumpConfig::SetDumpData(const std::string& data) {
std::lock_guard<std::mutex> lock(mutex_);
dump_data_ = data;
}
void DumpConfig::SetOpList(const std::unordered_set<std::string>& op_list) {
std::lock_guard<std::mutex> lock(mutex_);
op_list_ = op_list;
}
void DumpConfig::Reset() {
std::lock_guard<std::mutex> lock(mutex_);
data_dump_enabled_ = false;
exception_dump_enabled_ = false;
overflow_dump_enabled_ = false;
dump_path_.clear();
dump_step_.clear();
dump_mode_.clear();
dump_data_.clear();
op_list_.clear();
dump_level_.clear();
dump_status_.clear();
dump_op_switch_.clear();
dump_debug_.clear();
dump_stats_.clear();
dump_scene_.clear();
model_dump_config_list_.clear();
op_debug_mode_ = 0U;
}
const std::string& DumpConfig::GetDumpLevel() const {
std::lock_guard<std::mutex> lock(mutex_);
return dump_level_;
}
const std::string& DumpConfig::GetDumpStatus() const {
std::lock_guard<std::mutex> lock(mutex_);
return dump_status_;
}
const std::string& DumpConfig::GetDumpOpSwitch() const {
std::lock_guard<std::mutex> lock(mutex_);
return dump_op_switch_;
}
const std::string& DumpConfig::GetDumpDebug() const {
std::lock_guard<std::mutex> lock(mutex_);
return dump_debug_;
}
uint32_t DumpConfig::GetOpDebugMode() const {
std::lock_guard<std::mutex> lock(mutex_);
return op_debug_mode_;
}
const std::vector<std::string>& DumpConfig::GetDumpStats() const {
std::lock_guard<std::mutex> lock(mutex_);
return dump_stats_;
}
const std::string& DumpConfig::GetDumpScene() const {
std::lock_guard<std::mutex> lock(mutex_);
return dump_scene_;
}
const std::vector<ModelDumpConfig>& DumpConfig::GetModelDumpConfigList() const {
std::lock_guard<std::mutex> lock(mutex_);
return model_dump_config_list_;
}
bool DumpConfig::NeedDump() const {
std::lock_guard<std::mutex> lock(mutex_);
if ((!model_dump_config_list_.empty()) ||
(dump_op_switch_ == GE_DUMP_STATUS_ON) ||
(dump_debug_ == GE_DUMP_STATUS_ON) ||
(!dump_scene_.empty())) {
return true;
}
return false;
}
bool DumpConfig::IsOpNeedDump(const std::string& op_name) const {
std::lock_guard<std::mutex> lock(mutex_);
if (model_dump_config_list_.empty()) {
return true;
}
for (const auto& model_config : model_dump_config_list_) {
if (model_config.layers.empty() && model_config.watcher_nodes.empty()) {
return true;
}
for (const auto& layer : model_config.layers) {
if (op_name == layer) {
return true;
}
}
for (const auto& node : model_config.watcher_nodes) {
if (op_name == node) {
return true;
}
}
}
return false;
}
Status DumpConfig::ParseAndValidate(const char* dumpData, int32_t size) {
GELOGI("Start to parse and validate dump config, size: %d", size);
if (dumpData == nullptr || size <= 0) {
GELOGI("Dump data is null or empty, no dump config to parse");
return SUCCESS;
}
std::string jsonStr(dumpData, size);
nlohmann::json js;
try {
js = nlohmann::json::parse(jsonStr);
} catch (...) {
GELOGE(ACL_GE_INVALID_DUMP_CONFIG, "[Parse][DumpConfig]Failed to parse dump json string");
REPORT_INNER_ERR_MSG("E19999", "Failed to parse dump json string");
return FAILED;
}
if (!IsValidDumpConfig(js)) {
GELOGE(ACL_GE_INVALID_DUMP_CONFIG, "[Check][DumpConfig]Dump config validation failed");
return FAILED;
}
Status ret = ParseDumpConfigFromJson(js);
if (ret != SUCCESS) {
GELOGE(ACL_GE_INVALID_DUMP_CONFIG, "[Parse][DumpConfig]Failed to parse dump config from json");
return ret;
}
const nlohmann::json& jsDumpConfig = js.contains(GE_DUMP) ? js[GE_DUMP] : js;
CheckUnsupportedConfigs(jsDumpConfig);
GELOGI("Parse and validate dump config successfully");
return SUCCESS;
}
bool DumpConfig::IsValidDumpConfig(const nlohmann::json& js) const {
GELOGI("Start to execute IsValidDumpConfig.");
if (!js.contains(GE_DUMP)) {
GELOGI("no dump item, no need to do dump!");
return true;
}
const nlohmann::json& jsDumpConfig = js[GE_DUMP];
if (jsDumpConfig.contains(GE_DUMP_SCENE)) {
std::string dumpScene;
return CheckDumpSceneSwitch(jsDumpConfig, dumpScene);
}
if (IsDumpDebugEnabled(jsDumpConfig)) {
return DumpDebugCheck(jsDumpConfig);
}
return ValidateNormalDumpConfig(jsDumpConfig);
}
bool DumpConfig::IsDumpDebugEnabled(const nlohmann::json& jsDumpConfig) {
std::string dumpDebug = GE_DUMP_DEBUG_DEFAULT;
if (jsDumpConfig.contains(GE_DUMP_DEBUG)) {
dumpDebug = jsDumpConfig[GE_DUMP_DEBUG].get<std::string>();
}
return (dumpDebug == GE_DUMP_STATUS_ON);
}
bool DumpConfig::ValidateNormalDumpConfig(const nlohmann::json& jsDumpConfig) {
if (!ValidateDumpPath(jsDumpConfig)) {
return false;
}
if (!ValidateDumpMode(jsDumpConfig)) {
return false;
}
if (!ValidateDumpLevel(jsDumpConfig)) {
return false;
}
return ValidateOtherDumpConfigs(jsDumpConfig);
}
bool DumpConfig::ValidateDumpPath(const nlohmann::json& jsDumpConfig) {
if (!jsDumpConfig.contains(GE_DUMP_PATH)) {
GELOGE(ACL_GE_INVALID_DUMP_CONFIG, "[Check][DumpConfig]dump_path field in dump config does not exist");
REPORT_INNER_ERR_MSG("E19999", "dump_path field in dump config does not exist");
return false;
}
const std::string dumpPath = jsDumpConfig[GE_DUMP_PATH].get<std::string>();
if (dumpPath.empty()) {
GELOGE(ACL_GE_INVALID_DUMP_CONFIG, "[Check][DumpConfig]dump_path field is null in config");
REPORT_INNER_ERR_MSG("E19999", "dump_path field is null in config");
return false;
}
return CheckDumpPath(jsDumpConfig);
}
bool DumpConfig::ValidateDumpMode(const nlohmann::json& jsDumpConfig) {
std::string dumpMode = GE_DUMP_MODE_DEFAULT;
if (jsDumpConfig.contains(GE_DUMP_MODE)) {
dumpMode = jsDumpConfig[GE_DUMP_MODE].get<std::string>();
}
const std::vector<std::string> validModes = {
GE_DUMP_MODE_INPUT, GE_DUMP_MODE_OUTPUT, GE_DUMP_MODE_ALL
};
if (std::find(validModes.begin(), validModes.end(), dumpMode) == validModes.end()) {
GELOGE(ACL_GE_INVALID_DUMP_CONFIG,
"[Check][DumpConfig]dump_mode value[%s] error in config, only supports input/output/all",
dumpMode.c_str());
REPORT_INNER_ERR_MSG("E19999",
"dump_mode value[%s] error in config, only supports input/output/all",
dumpMode.c_str());
return false;
}
GELOGD("dump_mode value[%s] is valid", dumpMode.c_str());
return true;
}
bool DumpConfig::ValidateDumpLevel(const nlohmann::json& jsDumpConfig) {
std::string dumpLevel = GE_DUMP_LEVEL_DEFAULT;
if (jsDumpConfig.contains(GE_DUMP_LEVEL)) {
dumpLevel = jsDumpConfig[GE_DUMP_LEVEL].get<std::string>();
}
const std::vector<std::string> validLevels = {
GE_DUMP_LEVEL_OP, GE_DUMP_LEVEL_KERNEL, GE_DUMP_LEVEL_ALL
};
if (std::find(validLevels.begin(), validLevels.end(), dumpLevel) == validLevels.end()) {
GELOGE(ACL_GE_INVALID_DUMP_CONFIG,
"[Check][DumpConfig]dump_level value[%s] error in config, only supports op/kernel/all",
dumpLevel.c_str());
REPORT_INNER_ERR_MSG("E19999",
"dump_level value[%s] error in config, only supports op/kernel/all",
dumpLevel.c_str());
return false;
}
GELOGD("dump_level value[%s] is valid", dumpLevel.c_str());
return true;
}
bool DumpConfig::ValidateOtherDumpConfigs(const nlohmann::json& jsDumpConfig) {
return CheckDumpStep(jsDumpConfig) &&
CheckDumplist(jsDumpConfig, GetDumpLevel(jsDumpConfig)) &&
DumpStatsCheck(jsDumpConfig);
}
std::string DumpConfig::GetDumpLevel(const nlohmann::json& jsDumpConfig) {
if (jsDumpConfig.contains(GE_DUMP_LEVEL)) {
return jsDumpConfig[GE_DUMP_LEVEL].get<std::string>();
}
return GE_DUMP_LEVEL_DEFAULT;
}
void DumpConfig::CheckUnsupportedConfigs(const nlohmann::json& jsDumpConfig) {
if (jsDumpConfig.contains(GE_DUMP_OP_SWITCH)) {
GELOGW("[OM2 Dump] dump_op_switch is not supported in OM2 dump mode, configuration will be ignored");
}
if (jsDumpConfig.contains(GE_DUMP_LIST)) {
const auto& dumpList = jsDumpConfig[GE_DUMP_LIST];
if (dumpList.is_array() && !dumpList.empty()) {
for (const auto& modelJson : dumpList) {
if (modelJson.contains(GE_DUMP_OPTYPE_BLACKLIST)) {
GELOGW("[OM2 Dump] optype_blacklist in dump_list is not supported in OM2 dump mode, configuration will be ignored");
}
if (modelJson.contains(GE_DUMP_OPNAME_BLACKLIST)) {
GELOGW("[OM2 Dump] opname_blacklist in dump_list is not supported in OM2 dump mode, configuration will be ignored");
}
if (modelJson.contains(GE_DUMP_OPNAME_RANGE)) {
GELOGW("[OM2 Dump] opname_range in dump_list is not supported in OM2 dump mode, configuration will be ignored");
}
}
}
}
if (jsDumpConfig.contains(GE_DUMP_SCENE)) {
std::string dumpScene = jsDumpConfig[GE_DUMP_SCENE].get<std::string>();
if ((dumpScene == GE_DUMP_EXCEPTION_AIC_ERR_BRIEF) || (dumpScene == GE_DUMP_LITE_EXCEPTION)) {
GELOGW("[OM2 Dump] dump_scene value '%s' (L0 exception dump) is not supported in OM2, only L1 (aic_err_norm_dump) and L2 (aic_err_detail_dump) exception dump are supported", dumpScene.c_str());
}
}
}
bool DumpConfig::CheckDumpSceneSwitch(const nlohmann::json& jsDumpConfig, std::string& dumpScene) {
if (!jsDumpConfig.contains(GE_DUMP_SCENE)) {
GELOGE(ACL_GE_INVALID_DUMP_CONFIG, "[Check][DumpConfig]dump_scene field does not exist");
return false;
}
dumpScene = jsDumpConfig[GE_DUMP_SCENE].get<std::string>();
const std::vector<std::string> validScenes = {
GE_DUMP_LITE_EXCEPTION, GE_DUMP_EXCEPTION_AIC_ERR_BRIEF,
GE_DUMP_EXCEPTION_AIC_ERR_NORM, GE_DUMP_EXCEPTION_AIC_ERR_DETAIL,
GE_DUMP_SCENE_WATCHER
};
if (std::find(validScenes.begin(), validScenes.end(), dumpScene) == validScenes.end()) {
GELOGE(ACL_GE_INVALID_DUMP_CONFIG, "[Check][DumpConfig]dump_scene value[%s] is invalid",
dumpScene.c_str());
return false;
}
GELOGD("dump_scene value[%s] is valid", dumpScene.c_str());
return true;
}
bool DumpConfig::CheckDumpPath(const nlohmann::json& jsDumpConfig) {
(void)jsDumpConfig;
return true;
}
bool DumpConfig::CheckDumpStep(const nlohmann::json& jsDumpConfig) {
(void)jsDumpConfig;
return true;
}
bool DumpConfig::CheckDumplist(const nlohmann::json& jsDumpConfig, const std::string& dumpLevel) {
(void)jsDumpConfig;
(void)dumpLevel;
return true;
}
bool DumpConfig::CheckDumpOpSwitch(const std::string& dumpOpSwitch) {
const std::vector<std::string> validSwitches = {GE_DUMP_STATUS_ON, GE_DUMP_STATUS_OFF};
return std::find(validSwitches.begin(), validSwitches.end(), dumpOpSwitch) != validSwitches.end();
}
bool DumpConfig::CheckIpAddress(const DumpConfig& config) {
(void)config;
return true;
}
bool DumpConfig::ValidateIpAddress(const std::string& ipAddress) {
(void)ipAddress;
return true;
}
bool DumpConfig::IsDumpPathValid(const std::string& dumpPath) {
return dumpPath.size() <= MAX_DUMP_PATH_LENGTH;
}
bool DumpConfig::DumpDebugCheck(const nlohmann::json& jsDumpConfig) {
(void)jsDumpConfig;
return true;
}
bool DumpConfig::DumpStatsCheck(const nlohmann::json& jsDumpConfig) {
(void)jsDumpConfig;
return true;
}
Status DumpConfig::ParseDumpConfigFromJson(const nlohmann::json& dumpJson) {
std::lock_guard<std::mutex> lock(mutex_);
if (!dumpJson.contains(GE_DUMP)) {
GELOGI("no dump item, no need to parse dump config!");
return SUCCESS;
}
const nlohmann::json& jsDumpConfig = dumpJson[GE_DUMP];
ParseBasicConfigurations(jsDumpConfig);
ParseComplexConfigs(jsDumpConfig);
if (!dump_path_.empty()) {
if (dump_path_[dump_path_.size() - 1U] != '/') {
dump_path_ += "/";
}
dump_path_ += GetCurrentTimeStr() + "/";
}
if ((dump_status_ == GE_DUMP_STATUS_ON) || !model_dump_config_list_.empty()) {
data_dump_enabled_ = true;
GELOGI("Data dump enabled, dump_status: %s, model config count: %zu",
dump_status_.c_str(), model_dump_config_list_.size());
}
if (!dump_scene_.empty()) {
exception_dump_enabled_ = true;
GELOGI("Exception dump enabled, dump_scene: %s", dump_scene_.c_str());
}
if (dump_debug_ == GE_DUMP_STATUS_ON) {
overflow_dump_enabled_ = true;
GELOGI("Overflow dump enabled, dump_path: %s", dump_path_.c_str());
}
GELOGI("Parse dump config from json successfully, dump_mode: %s, dump_level: %s, dump_step: %s",
dump_mode_.c_str(), dump_level_.c_str(), dump_step_.c_str());
return SUCCESS;
}
void DumpConfig::ParseBasicConfigurations(const nlohmann::json& dumpJson) {
dump_path_ = GetConfigWithDefault(dumpJson, GE_DUMP_PATH, "");
dump_mode_ = GetConfigWithDefault(dumpJson, GE_DUMP_MODE, GE_DUMP_MODE_DEFAULT);
dump_status_ = GetConfigWithDefault(dumpJson, GE_DUMP_STATUS, GE_DUMP_STATUS_DEFAULT);
dump_op_switch_ = GetConfigWithDefault(dumpJson, GE_DUMP_OP_SWITCH, GE_DUMP_OP_SWITCH_DEFAULT);
dump_debug_ = GetConfigWithDefault(dumpJson, GE_DUMP_DEBUG, GE_DUMP_DEBUG_DEFAULT);
dump_step_ = GetConfigWithDefault(dumpJson, GE_DUMP_STEP, GE_DUMP_STEP_DEFAULT);
dump_data_ = GetConfigWithDefault(dumpJson, GE_DUMP_DATA, GE_DUMP_DATA_DEFAULT);
dump_level_ = GetConfigWithDefault(dumpJson, GE_DUMP_LEVEL, GE_DUMP_LEVEL_DEFAULT);
dump_scene_ = GetConfigWithDefault(dumpJson, GE_DUMP_SCENE, GE_DUMP_SCENE_DEFAULT);
if (dump_debug_ == GE_DUMP_STATUS_ON) {
op_debug_mode_ = kAllOverflow;
dump_status_ = GE_DUMP_STATUS_OFF;
} else {
op_debug_mode_ = 0U;
}
}
void DumpConfig::ParseComplexConfigs(const nlohmann::json& dumpJson) {
if (dumpJson.contains(GE_DUMP_STATS) && dumpJson[GE_DUMP_STATS].is_array()) {
ParseStringArray(dumpJson[GE_DUMP_STATS], dump_stats_);
}
if (dumpJson.contains(GE_DUMP_LIST) && dumpJson[GE_DUMP_LIST].is_array()) {
ParseModelDumpConfigList(dumpJson[GE_DUMP_LIST], model_dump_config_list_);
}
}
std::string DumpConfig::GetConfigWithDefault(const nlohmann::json& json,
const std::string& key,
const std::string& defaultValue) {
if (json.contains(key)) {
return json[key].get<std::string>();
}
return defaultValue;
}
void DumpConfig::ParseStringArray(const nlohmann::json& jsonArray, std::vector<std::string>& output) {
output.clear();
for (const auto& item : jsonArray) {
output.push_back(item.get<std::string>());
}
}
void DumpConfig::ParseModelDumpConfigList(const nlohmann::json& jsonArray, std::vector<ModelDumpConfig>& output) {
output.clear();
for (const auto& modelJson : jsonArray) {
ModelDumpConfig modelConfig;
if (ParseModelDumpConfig(modelJson, modelConfig)) {
output.push_back(modelConfig);
}
}
}
bool DumpConfig::ParseModelDumpConfig(const nlohmann::json& modelJson, ModelDumpConfig& modelConfig) {
if (!CheckDumpModelConfig(modelJson)) {
return false;
}
if (modelJson.contains(GE_DUMP_MODEL_NAME)) {
modelConfig.model_name = modelJson[GE_DUMP_MODEL_NAME].get<std::string>();
}
if (modelJson.contains(GE_DUMP_LAYER) && modelJson[GE_DUMP_LAYER].is_array()) {
modelConfig.layers.clear();
for (const auto& layer : modelJson[GE_DUMP_LAYER]) {
modelConfig.layers.push_back(layer.get<std::string>());
}
}
if (modelJson.contains(GE_DUMP_WATCHER_NODES) && modelJson[GE_DUMP_WATCHER_NODES].is_array()) {
modelConfig.watcher_nodes.clear();
for (const auto& node : modelJson[GE_DUMP_WATCHER_NODES]) {
modelConfig.watcher_nodes.push_back(node.get<std::string>());
}
}
if (modelJson.contains(GE_DUMP_OPTYPE_BLACKLIST) && modelJson[GE_DUMP_OPTYPE_BLACKLIST].is_array()) {
modelConfig.optype_blacklist.clear();
for (const auto& blacklistJson : modelJson[GE_DUMP_OPTYPE_BLACKLIST]) {
DumpBlacklist blacklist;
ParseBlacklist(blacklistJson, blacklist);
modelConfig.optype_blacklist.push_back(blacklist);
}
}
if (modelJson.contains(GE_DUMP_OPNAME_BLACKLIST) && modelJson[GE_DUMP_OPNAME_BLACKLIST].is_array()) {
modelConfig.opname_blacklist.clear();
for (const auto& blacklistJson : modelJson[GE_DUMP_OPNAME_BLACKLIST]) {
DumpBlacklist blacklist;
ParseBlacklist(blacklistJson, blacklist);
modelConfig.opname_blacklist.push_back(blacklist);
}
}
if (modelJson.contains(GE_DUMP_OPNAME_RANGE) && modelJson[GE_DUMP_OPNAME_RANGE].is_array()) {
modelConfig.dump_op_ranges.clear();
for (const auto& rangeJson : modelJson[GE_DUMP_OPNAME_RANGE]) {
if (rangeJson.contains(GE_DUMP_OPNAME_RANGE_BEGIN) && rangeJson.contains(GE_DUMP_OPNAME_RANGE_END)) {
std::string begin = rangeJson[GE_DUMP_OPNAME_RANGE_BEGIN].get<std::string>();
std::string end = rangeJson[GE_DUMP_OPNAME_RANGE_END].get<std::string>();
modelConfig.dump_op_ranges.emplace_back(begin, end);
}
}
}
return true;
}
bool DumpConfig::CheckDumpModelConfig(const nlohmann::json& modelJson) {
(void)modelJson;
return true;
}
void DumpConfig::ParseBlacklist(const nlohmann::json& blacklistJson, DumpBlacklist& blacklist) {
if (blacklistJson.contains(GE_DUMP_BLACKLIST_NAME)) {
blacklist.name = blacklistJson[GE_DUMP_BLACKLIST_NAME].get<std::string>();
}
if (blacklistJson.contains(GE_DUMP_BLACKLIST_POS) && blacklistJson[GE_DUMP_BLACKLIST_POS].is_array()) {
blacklist.pos.clear();
for (const auto& pos : blacklistJson[GE_DUMP_BLACKLIST_POS]) {
blacklist.pos.push_back(pos.get<std::string>());
}
}
}
std::vector<std::string> DumpConfig::Split(const std::string &str, const char_t * const delimiter) {
std::vector<std::string> result;
size_t start = 0;
size_t end = str.find(delimiter);
while (end != std::string::npos) {
result.push_back(str.substr(start, end - start));
start = end + 1;
end = str.find(delimiter, start);
}
result.push_back(str.substr(start));
return result;
}
}
}