* Copyright (c) 2025 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.
*/
#ifndef FUSION_ENGINE_INC_COMMON_STRING_UTILS_H_
#define FUSION_ENGINE_INC_COMMON_STRING_UTILS_H_
#include <algorithm>
#include <cstdio>
#include <string>
#include <vector>
#include "common/fe_log.h"
#include "graph/types.h"
#include "graph/utils/type_utils.h"
const size_t INPLACE_SIZE = 2;
const int64_t NUM_TEN = 10;
namespace fe {
using std::string;
class StringUtils {
public:
static void TransStringToListListInt(const string &outputInplaceAbility, std::vector<std::vector<int64_t>> &res) {
bool num_flag = false;
std::vector<int64_t> output_inplace;
size_t i = 0;
int64_t data = 0;
uint32_t left_brace_num = 0;
while (i < outputInplaceAbility.size()) {
if (outputInplaceAbility[i] == '{') {
left_brace_num++;
}
while (i < outputInplaceAbility.size() && isdigit(outputInplaceAbility[i])) {
int64_t tmp_data = outputInplaceAbility[i++] - '0';
data = data * NUM_TEN + tmp_data;
num_flag = true;
}
if (num_flag) {
output_inplace.emplace_back(data);
num_flag = false;
data = 0;
}
char right_brace = outputInplaceAbility[i];
if (!IsValidOutputInplace(right_brace, output_inplace, res, left_brace_num)) {
res.clear();
FE_LOGW("The value of outputInplaceAbility %s is invalid, and valid value is {{a,b},{c,d}....}",
outputInplaceAbility.c_str());
return;
}
i++;
}
IsOutputPair(left_brace_num, res, outputInplaceAbility);
}
static void IsOutputPair(const uint32_t &left_brace_num, std::vector<std::vector<int64_t>> &res,
const string &outputInplaceAbility) {
if (left_brace_num != 0) {
res.clear();
FE_LOGW("The pair value of outputInplaceAbility %s is invalid, and valid value is {{a,b},{c,d}....}",
outputInplaceAbility.c_str());
}
}
static bool IsValidOutputInplace(const char &ch, std::vector<int64_t> &output_inplace,
std::vector<std::vector<int64_t>> &res, uint32_t &left_brace_num) {
if (ch != '}') {
return true;
}
if (left_brace_num > 0) {
left_brace_num--;
if (output_inplace.size() == INPLACE_SIZE) {
res.emplace_back(output_inplace);
output_inplace.clear();
return true;
}
if (left_brace_num == 0) {
return true;
}
return false;
}
return false;
}
* @brief split string
* @link http://stackoverflow.com/questions/236129/how-to-split-a-string-in-c
* @param [in] str : string need to be split
* @param [in] pattern : separator
* @return string vector after split
*/
static std::vector<string> Split(const string &str, char pattern) {
std::vector<string> res_vec;
string str_pattern;
str_pattern += pattern;
res_vec = Split(str, str_pattern);
return res_vec;
}
static std::vector<string> Split(const string &str, const string &pattern) {
std::vector<string> res_vec;
if (str.empty()) {
return res_vec;
}
string str_and_pattern = str + pattern;
size_t pos = str_and_pattern.find(pattern);
size_t size = str_and_pattern.size();
while (pos != string::npos) {
string sub_str = str_and_pattern.substr(0, pos);
res_vec.push_back(sub_str);
str_and_pattern = str_and_pattern.substr(pos + pattern.size(), size);
pos = str_and_pattern.find(pattern);
}
return res_vec;
}
static void SplitWithTrim(const string &str, char pattern, std::vector<string> &res_vec) {
if (str.empty() || pattern == ' ') {
return;
}
string str_and_pattern = str + pattern;
size_t pos = str_and_pattern.find(pattern);
size_t size = str_and_pattern.size();
while (pos != string::npos) {
string sub_str = str_and_pattern.substr(0, pos);
(void)Trim(sub_str);
if (!sub_str.empty()) {
res_vec.push_back(sub_str);
}
str_and_pattern = str_and_pattern.substr(pos + 1, size);
pos = str_and_pattern.find(pattern);
}
}
static string &Ltrim(string &s) {
#if __cplusplus >= 201103L
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int c) { return !std::isspace(c); }));
#else
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
#endif
return s;
}
static string &Rtrim(string &s) {
#if __cplusplus >= 201103L
s.erase(std::find_if(s.rbegin(), s.rend(), [](int c) { return !std::isspace(c); }).base(), s.end());
#else
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
#endif
return s;
}
* @brief remove the white space at the begining and end position of string
* @param [in] s : the string need to be trim
* @return the string after trim
*/
static string &Trim(string &s) { return Ltrim(Rtrim(s)); }
* @brief whether a string is start with a specific string(prefix)
* @param [in] str : a string to be compared
* @param [in] prefix : a string prefix
* @return true else false
*/
static bool StartWith(const string &str, const string prefix) {
return ((str.size() >= prefix.size()) && (str.compare(0, prefix.size(), prefix) == 0));
}
static bool EndWith(const string &str, const string &suffix) {
if (str.length() < suffix.length()) {
return false;
}
string sub_str = str.substr(str.length() - suffix.length());
return sub_str == suffix;
}
* @brief transfer a string to upper string
* @param [in] str : a string to be transfer
* @return None
*/
static void ToUpperString(string &str) { transform(str.begin(), str.end(), str.begin(), (int (*)(int))toupper); }
* @brief transfer a string to lower string
* @param [in] str : a string to be transfer
* @return None
*/
static void ToLowerString(string &str) { transform(str.begin(), str.end(), str.begin(), (int (*)(int))tolower); }
* @brief whether a string match another string, after triming space
* @param [in] left : a string to be matched
* @param [in] right : a string to be matched
* @return true else false
*/
static bool MatchString(string left, string right) {
if (Trim(left) == Trim(right)) {
return true;
}
return false;
}
static bool MatchWithoutCase(string left, string right) {
StringUtils::ToLowerString(left);
StringUtils::ToLowerString(right);
if (Trim(left) == Trim(right)) {
return true;
}
return false;
}
* check whether the input str is integer
* @param[in] str input string
* @param[out] true/false
*/
static bool IsInteger(const string &str) {
if (str.empty()) {
return false;
}
for (auto c : str) {
if (!isdigit(c)) {
return false;
}
}
return true;
}
template <typename CONTAINER>
static string IntegerVecToString(const CONTAINER &integer_vec) {
string result = "{";
for (auto ele : integer_vec) {
string ele_str;
using DT = typename std::remove_cv<decltype(ele)>::type;
if (std::is_enum<DT>::value) {
if (std::is_same<ge::Format, DT>::value) {
ele_str = ge::TypeUtils::FormatToSerialString(static_cast<ge::Format>(ele));
} else if (std::is_same<ge::DataType, DT>::value) {
ele_str = ge::TypeUtils::DataTypeToSerialString(static_cast<ge::DataType >(ele));
} else {
ele_str = std::to_string(ele);
}
} else {
ele_str = std::to_string(ele);
}
result += ele_str;
result += ",";
}
if (result.empty()) {
return "";
}
if (result.back() == ',') {
result = result.substr(0, result.length() - 1);
}
result += "}";
return result;
}
static std::string StrVecToString(const std::vector<std::string> &str_vec) {
std::string result = "[";
bool is_first = true;
for (const std::string &str : str_vec) {
if (is_first) {
is_first = false;
} else {
result += ",";
}
result += str;
}
result += "]";
return result;
}
template <typename T>
static string MapKeyToString(const std::map<string, T> &map) {
string result = "[";
bool is_first = true;
for (const auto& pair : map) {
if (is_first) {
is_first = false;
} else {
result += ",";
}
result += pair.first;
}
result += "]";
return result;
}
};
}
#endif