1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "Configurator.hpp"
16
17 #include <fstream>
18 #include <iostream>
19
20 using namespace std;
21
22 #include <ctype.h>
23 #include <stdarg.h>
24 #include <stdio.h>
25
26 #if defined(__unix__)
27 # include <unistd.h>
28 #endif
29
30 namespace sw {
31
Configurator(string iniPath)32 Configurator::Configurator(string iniPath)
33 {
34 path = iniPath;
35
36 readFile();
37 }
38
~Configurator()39 Configurator::~Configurator()
40 {
41 }
42
readFile()43 bool Configurator::readFile()
44 {
45 #if defined(__unix__)
46 if(access(path.c_str(), R_OK) != 0)
47 {
48 return false;
49 }
50 #endif
51
52 fstream file(path.c_str(), ios::in);
53 if(file.fail()) return false;
54
55 string line;
56 string keyName;
57
58 while(getline(file, line))
59 {
60 if(line.length())
61 {
62 if(line[line.length() - 1] == '\r')
63 {
64 line = line.substr(0, line.length() - 1);
65 }
66
67 if(!isprint(line[0]))
68 {
69 // printf("Failing on char %d\n", line[0]);
70 file.close();
71 return false;
72 }
73
74 string::size_type pLeft = line.find_first_of(";#[=");
75
76 if(pLeft != string::npos)
77 {
78 switch(line[pLeft])
79 {
80 case '[':
81 {
82 string::size_type pRight = line.find_last_of("]");
83
84 if(pRight != string::npos && pRight > pLeft)
85 {
86 keyName = line.substr(pLeft + 1, pRight - pLeft - 1);
87 addKeyName(keyName);
88 }
89 }
90 break;
91 case '=':
92 {
93 string valueName = line.substr(0, pLeft);
94 string value = line.substr(pLeft + 1);
95 addValue(keyName, valueName, value);
96 }
97 break;
98 case ';':
99 case '#':
100 // Ignore comments
101 break;
102 }
103 }
104 }
105 }
106
107 file.close();
108
109 if(names.size())
110 {
111 return true;
112 }
113
114 return false;
115 }
116
writeFile(std::string title)117 void Configurator::writeFile(std::string title)
118 {
119 #if defined(__unix__)
120 if(access(path.c_str(), W_OK) != 0)
121 {
122 return;
123 }
124 #endif
125
126 fstream file(path.c_str(), ios::out);
127 if(file.fail()) return;
128
129 file << "; " << title << endl
130 << endl;
131
132 for(unsigned int keyID = 0; keyID < sections.size(); keyID++)
133 {
134 file << "[" << names[keyID] << "]" << endl;
135
136 for(unsigned int valueID = 0; valueID < sections[keyID].names.size(); valueID++)
137 {
138 file << sections[keyID].names[valueID] << "=" << sections[keyID].values[valueID] << endl;
139 }
140
141 file << endl;
142 }
143
144 file.close();
145 }
146
findKey(string keyName) const147 int Configurator::findKey(string keyName) const
148 {
149 for(unsigned int keyID = 0; keyID < names.size(); keyID++)
150 {
151 if(names[keyID] == keyName)
152 {
153 return keyID;
154 }
155 }
156
157 return -1;
158 }
159
findValue(unsigned int keyID,string valueName) const160 int Configurator::findValue(unsigned int keyID, string valueName) const
161 {
162 if(!sections.size() || keyID >= sections.size())
163 {
164 return -1;
165 }
166
167 for(unsigned int valueID = 0; valueID < sections[keyID].names.size(); ++valueID)
168 {
169 if(sections[keyID].names[valueID] == valueName)
170 {
171 return valueID;
172 }
173 }
174
175 return -1;
176 }
177
addKeyName(string keyName)178 unsigned int Configurator::addKeyName(string keyName)
179 {
180 names.resize(names.size() + 1, keyName);
181 sections.resize(sections.size() + 1);
182 return (unsigned int)names.size() - 1;
183 }
184
addValue(string const keyName,string const valueName,string const value)185 void Configurator::addValue(string const keyName, string const valueName, string const value)
186 {
187 int keyID = findKey(keyName);
188
189 if(keyID == -1)
190 {
191 keyID = addKeyName(keyName);
192 }
193
194 int valueID = findValue(keyID, valueName);
195
196 if(valueID == -1)
197 {
198 sections[keyID].names.resize(sections[keyID].names.size() + 1, valueName);
199 sections[keyID].values.resize(sections[keyID].values.size() + 1, value);
200 }
201 else
202 {
203 sections[keyID].values[valueID] = value;
204 }
205 }
206
getValue(string keyName,string valueName,string defaultValue) const207 string Configurator::getValue(string keyName, string valueName, string defaultValue) const
208 {
209 int keyID = findKey(keyName);
210 if(keyID == -1) return defaultValue;
211 int valueID = findValue((unsigned int)keyID, valueName);
212 if(valueID == -1) return defaultValue;
213
214 return sections[keyID].values[valueID];
215 }
216
getInteger(string keyName,string valueName,int defaultValue) const217 int Configurator::getInteger(string keyName, string valueName, int defaultValue) const
218 {
219 char svalue[256];
220
221 sprintf(svalue, "%d", defaultValue);
222
223 return atoi(getValue(keyName, valueName, svalue).c_str());
224 }
225
getBoolean(string keyName,string valueName,bool defaultValue) const226 bool Configurator::getBoolean(string keyName, string valueName, bool defaultValue) const
227 {
228 return getInteger(keyName, valueName, (int)defaultValue) != 0;
229 }
230
getFloat(string keyName,string valueName,double defaultValue) const231 double Configurator::getFloat(string keyName, string valueName, double defaultValue) const
232 {
233 char svalue[256];
234
235 sprintf(svalue, "%f", defaultValue);
236
237 return atof(getValue(keyName, valueName, svalue).c_str());
238 }
239
getFormatted(string keyName,string valueName,char * format,void * v1,void * v2,void * v3,void * v4,void * v5,void * v6,void * v7,void * v8,void * v9,void * v10,void * v11,void * v12,void * v13,void * v14,void * v15,void * v16)240 unsigned int Configurator::getFormatted(string keyName, string valueName, char *format,
241 void *v1, void *v2, void *v3, void *v4,
242 void *v5, void *v6, void *v7, void *v8,
243 void *v9, void *v10, void *v11, void *v12,
244 void *v13, void *v14, void *v15, void *v16)
245 {
246 string value = getValue(keyName, valueName);
247
248 if(!value.length()) return false;
249
250 unsigned int nVals = sscanf(value.c_str(), format,
251 v1, v2, v3, v4, v5, v6, v7, v8,
252 v9, v10, v11, v12, v13, v14, v15, v16);
253
254 return nVals;
255 }
256
257 } // namespace sw
258