inicpp
C++ parser of INI files with schema validation.
string_utils.cpp
1 #include "string_utils.h"
2 #include "exception.h"
3 #include <algorithm>
4 #include <string>
5 
6 namespace inicpp
7 {
8  namespace string_utils
9  {
10  std::string left_trim(const std::string &str)
11  {
12  auto front = std::find_if(str.begin(), str.end(), [](int c) { return !std::isspace(c); });
13  return std::string(front, str.end());
14  }
15 
16  std::string right_trim(const std::string &str)
17  {
18  auto back = std::find_if(str.rbegin(), str.rend(), [](int c) { return !std::isspace(c); }).base();
19  return std::string(str.begin(), back);
20  }
21 
22  std::string trim(const std::string &str)
23  {
24  auto front = std::find_if(str.begin(), str.end(), [](int c) { return !std::isspace(c); });
25  auto back = std::find_if(str.rbegin(), str.rend(), [](int c) { return !std::isspace(c); }).base();
26 
27  if (back <= front) {
28  return "";
29  }
30  return std::string(front, back);
31  }
32 
33  bool find_needle(const std::string &haystack, const std::string &needle)
34  {
35  return (haystack.find(needle) == std::string::npos ? false : true);
36  }
37 
38  bool starts_with(const std::string &str, const std::string &search_str)
39  {
40  size_t search_str_length = search_str.length();
41 
42  if (search_str_length > str.length()) {
43  return false;
44  }
45 
46  for (size_t i = 0; i < search_str_length; ++i) {
47  if (str[i] != search_str[i]) {
48  return false;
49  }
50  }
51 
52  return true;
53  }
54 
55  bool ends_with(const std::string &str, const std::string &search_str)
56  {
57  size_t search_str_length = search_str.length();
58  size_t str_length = str.length();
59 
60  if (search_str_length > str.length()) {
61  return false;
62  }
63 
64  for (size_t i = 0; i < search_str_length; ++i) {
65  if (str[str_length - i - 1] != search_str[search_str_length - i - 1]) {
66  return false;
67  }
68  }
69 
70  return true;
71  }
72 
73  std::vector<std::string> split(const std::string &str, char delim)
74  {
75  std::vector<std::string> result;
76  std::stringstream stream(str);
77  std::string item;
78 
79  while (std::getline(stream, item, delim)) {
80  result.push_back(item);
81  }
82  return result;
83  }
84 
85 
86  template <> string_ini_t parse_string<string_ini_t>(const std::string &value, const std::string &)
87  {
88  return value;
89  }
90  template <> boolean_ini_t parse_string<boolean_ini_t>(const std::string &value, const std::string &option_name)
91  {
92  if (value == "0" || value == "f" || value == "n" || value == "off" || value == "no" ||
93  value == "disabled") {
94  return false;
95  } else if (value == "1" || value == "t" || value == "y" || value == "on" || value == "yes" ||
96  value == "enabled") {
97  return true;
98  } else {
100  "Option '" + option_name + "' parsing failed: String '" + value + "' is not valid boolean type.");
101  }
102  }
103 
104  template <> enum_ini_t parse_string<enum_ini_t>(const std::string &value, const std::string &)
105  {
106  return enum_ini_t(value);
107  }
108 
109  template <> float_ini_t parse_string<float_ini_t>(const std::string &value, const std::string &option_name)
110  {
111  try {
112  return std::stod(value);
113  } catch (std::exception &e) {
114  throw invalid_type_exception("Option '" + option_name + "' parsing failed: " + e.what());
115  }
116  }
117 
118  template <> signed_ini_t parse_string<signed_ini_t>(const std::string &value, const std::string &option_name)
119  {
120  try {
121  std::string binary_prefix = "0b";
122  if (std::equal(binary_prefix.begin(), binary_prefix.end(), value.begin())) {
123  // this is binary number
124  return std::stoll(value.substr(2), 0, 2);
125  } else {
126  // decimal and hexadecimal number can handle stoll itself
127  return std::stoll(value, 0, 0);
128  }
129  } catch (std::exception &e) {
130  throw invalid_type_exception("Option '" + option_name + "' parsing failed: " + e.what());
131  }
132  }
133 
134  template <>
135  unsigned_ini_t parse_string<unsigned_ini_t>(const std::string &value, const std::string &option_name)
136  {
137  try {
138  std::string binary_prefix = "0b";
139  if (std::equal(binary_prefix.begin(), binary_prefix.end(), value.begin())) {
140  // this is binary number
141  return std::stoull(value.substr(2), 0, 2);
142  } else {
143  // decimal and hexadecimal number can handle stoull itself
144  return std::stoull(value, 0, 0);
145  }
146  } catch (std::exception &e) {
147  throw invalid_type_exception("Option '" + option_name + "' parsing failed: " + e.what());
148  }
149  }
150  }
151 
152  namespace inistd
153  {
154  std::string to_string(const enum_ini_t &value)
155  {
156  return static_cast<std::string>(value);
157  }
158  }
159 }
float_ini_t parse_string< float_ini_t >(const std::string &value, const std::string &option_name)
std::string trim(const std::string &str)
signed_ini_t parse_string< signed_ini_t >(const std::string &value, const std::string &option_name)
std::string right_trim(const std::string &str)
bool starts_with(const std::string &str, const std::string &search_str)
string_ini_t parse_string< string_ini_t >(const std::string &value, const std::string &)
Definition: config.h:15
bool ends_with(const std::string &str, const std::string &search_str)
std::string to_string(const enum_ini_t &value)
unsigned_ini_t parse_string< unsigned_ini_t >(const std::string &value, const std::string &option_name)
std::vector< std::string > split(const std::string &str, char delim)
enum_ini_t parse_string< enum_ini_t >(const std::string &value, const std::string &option_name)
boolean_ini_t parse_string< boolean_ini_t >(const std::string &value, const std::string &option_name)
bool find_needle(const std::string &haystack, const std::string &needle)
std::string left_trim(const std::string &str)