1// Aseprite Config Library
2// Copyright (C) 2019-2020 Igara Studio S.A.
3// Copyright (C) 2014-2017 David Capello
4//
5// This file is released under the terms of the MIT license.
6// Read LICENSE.txt for more information.
7
8#ifdef HAVE_CONFIG_H
9#include "config.h"
10#endif
11
12#include "cfg/cfg.h"
13
14#include "base/file_handle.h"
15#include "base/string.h"
16
17#include <cstdlib>
18#include <iostream>
19#include <list>
20
21#include "SimpleIni.h"
22
23#include "base/log.h"
24
25namespace cfg {
26
27class CfgFile::CfgFileImpl {
28public:
29 const std::string& filename() const {
30 return m_filename;
31 }
32
33 void getAllSections(std::vector<std::string>& sections) const {
34 std::list<CSimpleIniA::Entry> sectionsList;
35 m_ini.GetAllSections(sectionsList);
36 sections.reserve(sectionsList.size());
37 for (const auto& section : sectionsList)
38 sections.push_back(section.pItem);
39 }
40
41 void getAllKeys(const char* section, std::vector<std::string>& keys) const {
42 std::list<CSimpleIniA::Entry> keysList;
43 if (!m_ini.GetAllKeys(section, keysList))
44 return;
45
46 keys.reserve(keysList.size());
47 for (const auto& k : keysList)
48 keys.push_back(k.pItem);
49 }
50
51 const char* getValue(const char* section, const char* name, const char* defaultValue) const {
52 return m_ini.GetValue(section, name, defaultValue);
53 }
54
55 bool getBoolValue(const char* section, const char* name, bool defaultValue) const {
56 return m_ini.GetBoolValue(section, name, defaultValue);
57 }
58
59 int getIntValue(const char* section, const char* name, int defaultValue) const {
60 return m_ini.GetLongValue(section, name, defaultValue);
61 }
62
63 double getDoubleValue(const char* section, const char* name, double defaultValue) const {
64 return m_ini.GetDoubleValue(section, name, defaultValue);
65 }
66
67 void setValue(const char* section, const char* name, const char* value) {
68 m_ini.SetValue(section, name, value);
69 }
70
71 void setBoolValue(const char* section, const char* name, bool value) {
72 m_ini.SetBoolValue(section, name, value);
73 }
74
75 void setIntValue(const char* section, const char* name, int value) {
76 m_ini.SetLongValue(section, name, value);
77 }
78
79 void setDoubleValue(const char* section, const char* name, double value) {
80 m_ini.SetDoubleValue(section, name, value);
81 }
82
83 void deleteValue(const char* section, const char* name) {
84 m_ini.Delete(section, name, true);
85 }
86
87 void deleteSection(const char* section) {
88 m_ini.Delete(section, nullptr, true);
89 }
90
91 void load(const std::string& filename) {
92 m_filename = filename;
93
94 base::FileHandle file(base::open_file(m_filename, "rb"));
95 if (file) {
96 m_ini.SetMultiLine();
97 SI_Error err = m_ini.LoadFile(file.get());
98 if (err != SI_OK) {
99 LOG(ERROR, "CFG: Error %d loading configuration from %s\n",
100 (int)err, m_filename.c_str());
101 }
102 }
103 }
104
105 void save() {
106 base::FileHandle file(base::open_file(m_filename, "wb"));
107 if (file) {
108 SI_Error err = m_ini.SaveFile(file.get());
109 if (err != SI_OK) {
110 LOG(ERROR, "CFG: Error %d saving configuration into %s\n",
111 (int)err, m_filename.c_str());
112 }
113 }
114 }
115
116private:
117 std::string m_filename;
118 CSimpleIniA m_ini;
119};
120
121CfgFile::CfgFile()
122 : m_impl(new CfgFileImpl)
123{
124}
125
126CfgFile::~CfgFile()
127{
128 delete m_impl;
129}
130
131const std::string& CfgFile::filename() const
132{
133 return m_impl->filename();
134}
135
136void CfgFile::getAllSections(std::vector<std::string>& sections) const
137{
138 m_impl->getAllSections(sections);
139}
140
141void CfgFile::getAllKeys(const char* section, std::vector<std::string>& keys) const
142{
143 m_impl->getAllKeys(section, keys);
144}
145
146const char* CfgFile::getValue(const char* section, const char* name, const char* defaultValue) const
147{
148 return m_impl->getValue(section, name, defaultValue);
149}
150
151bool CfgFile::getBoolValue(const char* section, const char* name, bool defaultValue)
152{
153 return m_impl->getBoolValue(section, name, defaultValue);
154}
155
156int CfgFile::getIntValue(const char* section, const char* name, int defaultValue)
157{
158 return m_impl->getIntValue(section, name, defaultValue);
159}
160
161double CfgFile::getDoubleValue(const char* section, const char* name, double defaultValue)
162{
163 return m_impl->getDoubleValue(section, name, defaultValue);
164}
165
166void CfgFile::setValue(const char* section, const char* name, const char* value)
167{
168 m_impl->setValue(section, name, value);
169}
170
171void CfgFile::setBoolValue(const char* section, const char* name, bool value)
172{
173 m_impl->setBoolValue(section, name, value);
174}
175
176void CfgFile::setIntValue(const char* section, const char* name, int value)
177{
178 m_impl->setIntValue(section, name, value);
179}
180
181void CfgFile::setDoubleValue(const char* section, const char* name, double value)
182{
183 m_impl->setDoubleValue(section, name, value);
184}
185
186void CfgFile::deleteValue(const char* section, const char* name)
187{
188 m_impl->deleteValue(section, name);
189}
190
191void CfgFile::deleteSection(const char* section)
192{
193 m_impl->deleteSection(section);
194}
195
196void CfgFile::load(const std::string& filename)
197{
198 m_impl->load(filename);
199}
200
201void CfgFile::save()
202{
203 m_impl->save();
204}
205
206} // namespace cfg
207