Lib
QOLを高める
config.cpp
Go to the documentation of this file.
1 #include "stdafx.h"
2 #include "include/config.h"
3 #include "include/debug.h"
4 #include <cstdio>
5 
6 namespace yappy {
7 namespace config {
8 
9 
10 using error::throwTrace;
12 
13 ConfigFile::ConfigFile(const wchar_t *fileName, InitList keyAndDefaults) :
14  m_fileName(fileName),
15  m_defaults(keyAndDefaults),
16  m_map()
17 {}
18 
20 {}
21 
23 {
24  debug::writeLine(L"Load config");
25 
26  std::regex re(R"(\s*(\S+?)\s*=\s*(\S*)\s*)");
27  std::cmatch match;
28 
29  FILE *tmpfp = nullptr;
30  if (::_wfopen_s(&tmpfp, m_fileName, L"r") != 0) {
31  save();
32  if (::_wfopen_s(&tmpfp, m_fileName, L"r") != 0) {
33  throwTrace<FrameworkError>("Load config file failed");
34  }
35  }
36  util::FilePtr fp(tmpfp);
37 
38  char line[LineCharMax];
39  while (::fgets(line, LineCharMax, fp.get()) != nullptr) {
40  size_t len = ::strlen(line);
41  if (line[len - 1] == '\n') {
42  // legal line
43  if (std::regex_match(line, match, re)) {
44  const std::string key = match.str(1);
45  const std::string value = match.str(2);
46  debug::writef(L"key: %s, value: %s",
47  util::utf82wc(key.c_str()).get(),
48  util::utf82wc(value.c_str()).get());
49  m_map[key] = value;
50  }
51  }
52  else {
53  // illegal line
54  while (::fgets(line, LineCharMax, fp.get()) != nullptr) {
55  // ignore to next LF
56  size_t len = ::strlen(line);
57  if (line[len - 1] == '\n') {
58  break;
59  }
60  }
61  }
62  }
63  fp.reset();
64 }
65 
67 {
68  debug::writeLine(L"Save config");
69 
70  FILE *tmpfp = nullptr;
71  if (::_wfopen_s(&tmpfp, m_fileName, L"w") != 0) {
72  throwTrace<FrameworkError>("Save config file failed");
73  }
74  util::FilePtr fp(tmpfp);
75 
76  for (const auto &pair : m_defaults) {
77  const std::string &key = pair.first;
78  const std::string &value = getString(key);
79  ::fprintf_s(fp.get(), "%s=%s\n", key.c_str(), value.c_str());
80  }
81 }
82 
83 void ConfigFile::setString(const std::string &key, const std::string &value)
84 {
85  if (m_defaults.find(key) == m_defaults.end()) {
86  throwTrace<std::invalid_argument>("Key not found: " + key);
87  }
88  m_map[key] = value;
89 }
90 
91 const std::string &ConfigFile::getString(const std::string &key) const
92 {
93  auto res = m_map.find(key);
94  if (res == m_map.end()) {
95  res = m_defaults.find(key);
96  if (res == m_defaults.end()) {
97  throwTrace<std::invalid_argument>("Key not found: " + key);
98  }
99  }
100  return res->second;
101 }
102 
103 bool ConfigFile::getBool(const std::string &key)
104 {
105  {
106  const std::string &value = getString(key);
107  if (value == BoolStrTrue) {
108  return true;
109  }
110  else if (value == BoolStrFalse) {
111  return false;
112  }
113  }
114  m_map.erase(key);
115  {
116  const std::string &value = getString(key);
117  if (value == BoolStrTrue) {
118  return true;
119  }
120  else if (value == BoolStrFalse) {
121  return false;
122  }
123  else {
124  throwTrace<std::logic_error>("Invalid default bool: " + value);
125  }
126  }
127 
128 }
129 
130 int ConfigFile::getInt(const std::string &key)
131 {
132  {
133  const std::string &value = getString(key);
134  try {
135  size_t idx = 0;
136  int ivalue = std::stoi(value, &idx, 0);
137  if (idx != value.size())
138  throwTrace<std::invalid_argument>(value);
139  return ivalue;
140  }
141  catch (const std::logic_error &) {
142  // go through
143  }
144  }
145  m_map.erase(key);
146  {
147  const std::string &value = getString(key);
148  try {
149  size_t idx = 0;
150  int ivalue = std::stoi(value, &idx, 0);
151  if (idx != value.size()) {
152  throwTrace<std::invalid_argument>(value);
153  }
154  return ivalue;
155  }
156  catch (const std::logic_error &) {
157  throwTrace<std::logic_error>("Invalid default int: " + value);
158  }
159  }
160 }
161 
162 } // namespace config
163 } // namespace yappy
const char *const BoolStrTrue
Definition: config.h:18
const char *const BoolStrFalse
Definition: config.h:19
Debug utilities.
std::unique_ptr< FILE, FileDeleter > FilePtr
unique_ptr of FILE with FileDeleter.
Definition: util.h:98
void writef(const wchar_t *fmt,...) noexcept
Write debug message using format string like printf.
Definition: debug.cpp:103
int getInt(const std::string &key)
Definition: config.cpp:130
Definition: config.cpp:6
void setString(const std::string &key, const std::string &value)
Definition: config.cpp:83
void writeLine(const wchar_t *str=L"") noexcept
Write debug string and new line.
Definition: debug.h:64
const std::string & getString(const std::string &key) const
Definition: config.cpp:91
ConfigFile(const wchar_t *fileName, InitList keyAndDefaults)
Definition: config.cpp:13
bool getBool(const std::string &key)
Definition: config.cpp:103
std::unique_ptr< wchar_t[]> utf82wc(const char *in)
UTF-8 to wide char.
Definition: util.h:117
static const size_t LineCharMax
Definition: config.h:17
std::initializer_list< MapType::value_type > InitList
Definition: config.h:15