* -------------------------------------------------------------------------
* This file is part of the Vision SDK project.
* Copyright (c) 2025 Huawei Technologies Co.,Ltd.
*
* Vision SDK is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* 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 FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* -------------------------------------------------------------------------
* Description: Obtains key-value pairs in a file.
* Author: MindX SDK
* Create: 2020
* History: NA
*/
#ifndef CONFIG_UTIL_H
#define CONFIG_UTIL_H
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <map>
#include <typeinfo>
#include <nlohmann/json.hpp>
#include <algorithm>
#include <cctype>
#include "MxBase/ErrorCode/ErrorCode.h"
#include "MxBase/Log/Log.h"
namespace MxBase {
enum ConfigMode {
CONFIGJSON = 0,
CONFIGFILE,
CONFIGPM,
CONFIGCONTENT
};
class ConfigData {
public:
ConfigData();
ConfigData(const ConfigData &other);
ConfigData &operator = (const ConfigData &other);
~ConfigData() {};
public:
APP_ERROR SetJsonValue(const std::string &key, const std::string &value, int pos = -1);
APP_ERROR LoadLabels(const std::string &labelPath);
std::string GetClassName(const size_t classId);
template<typename T> APP_ERROR GetFileValue(const std::string &key, T &value) const
{
if (cfgFile_.count(key) == 0) {
return APP_ERR_COMM_NO_EXIST;
}
T valueBak = value;
if (*(typeid(T).name()) == 'b') {
std::string str = cfgFile_.find(key)->second;
std::transform(str.begin(), str.end(), str.begin(),
[](unsigned char c) { return std::tolower(c); });
if (!(std::stringstream(str) >> std::boolalpha >> value)) {
value = valueBak;
return APP_ERR_COMM_INVALID_PARAM;
}
} else {
std::string str = cfgFile_.find(key)->second;
if (!(std::stringstream(str) >> value)) {
value = valueBak;
return APP_ERR_COMM_INVALID_PARAM;
}
}
return APP_ERR_OK;
}
template<typename T> APP_ERROR GetFileValue(const std::string &key, T &value, const T &min, const T &max) const
{
if (cfgFile_.count(key) == 0) {
return APP_ERR_COMM_NO_EXIST;
}
T newValue;
if (*(typeid(T).name()) == 'b') {
std::string str = cfgFile_.find(key)->second;
std::transform(str.begin(), str.end(), str.begin(),
[](unsigned char c) { return std::tolower(c); });
if (!(std::stringstream(str) >> std::boolalpha >> newValue)) {
return APP_ERR_COMM_INVALID_PARAM;
}
} else {
std::string str = cfgFile_.find(key)->second;
if (!(std::stringstream(str) >> newValue)) {
return APP_ERR_COMM_INVALID_PARAM;
}
}
if (newValue < min) {
value = min;
LogInfo << "The value of the key from config is lower than the limit"
<< ", therefore it is set as min value instead.";
} else if (newValue > max) {
value = max;
LogInfo << "The value of the key from config is more than the limit"
<< ", therefore it is set as max value instead.";
} else {
value = newValue;
}
return APP_ERR_OK;
}
template<typename T> void GetFileValueWarn(const std::string &key, T &value) const
{
auto ret = GetFileValue<T>(key, value);
if (ret != APP_ERR_OK) {
LogWarn << GetErrorInfo(ret) << "Fail to read key from config.";
}
}
template<typename T> void GetFileValueWarn(const std::string &key, T &value, const T &min, const T &max) const
{
auto ret = GetFileValue<T>(key, value, min, max);
if (ret != APP_ERR_OK) {
LogWarn << GetErrorInfo(ret) << "Fail to read key from config.";
}
}
template<typename T> APP_ERROR SetFileValue(const std::string &key, const T &value)
{
if (key.empty()) {
LogError << "The key cannot be empty." << GetErrorInfo(APP_ERR_COMM_INVALID_PARAM);
return APP_ERR_COMM_INVALID_PARAM;
}
if (*(typeid(T).name()) == 'b') {
saveBuf_ << key << " = " << std::boolalpha << value << std::endl;
} else {
saveBuf_ << key << " = " << value << std::endl;
}
return APP_ERR_OK;
}
APP_ERROR InitFile(std::ifstream &inFile);
APP_ERROR InitJson(std::ifstream &inFile);
APP_ERROR InitContent(const std::string &content);
std::string GetCfgJson();
private:
nlohmann::json cfgJson_ = {};
std::map<std::string, std::string> cfgFile_ = {};
std::stringstream saveBuf_;
std::vector<std::string> labelVec_ = {};
};
class ConfigUtil {
public:
APP_ERROR LoadConfiguration(const std::string &config, ConfigData &data, ConfigMode mode = CONFIGJSON);
private:
std::ofstream outfile_;
};
}
#endif