1*03ce13f7SAndroid Build Coastguard Worker // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*03ce13f7SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*03ce13f7SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*03ce13f7SAndroid Build Coastguard Worker //
7*03ce13f7SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
8*03ce13f7SAndroid Build Coastguard Worker //
9*03ce13f7SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*03ce13f7SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*03ce13f7SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*03ce13f7SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*03ce13f7SAndroid Build Coastguard Worker // limitations under the License.
14*03ce13f7SAndroid Build Coastguard Worker
15*03ce13f7SAndroid Build Coastguard Worker #include "Configurator.hpp"
16*03ce13f7SAndroid Build Coastguard Worker #include "Debug.hpp"
17*03ce13f7SAndroid Build Coastguard Worker
18*03ce13f7SAndroid Build Coastguard Worker #include <algorithm>
19*03ce13f7SAndroid Build Coastguard Worker #include <fstream>
20*03ce13f7SAndroid Build Coastguard Worker #include <istream>
21*03ce13f7SAndroid Build Coastguard Worker
22*03ce13f7SAndroid Build Coastguard Worker namespace {
trimSpaces(const std::string & str)23*03ce13f7SAndroid Build Coastguard Worker inline std::string trimSpaces(const std::string &str)
24*03ce13f7SAndroid Build Coastguard Worker {
25*03ce13f7SAndroid Build Coastguard Worker std::string trimmed = str;
26*03ce13f7SAndroid Build Coastguard Worker trimmed.erase(trimmed.begin(), std::find_if(trimmed.begin(), trimmed.end(), [](unsigned char c) {
27*03ce13f7SAndroid Build Coastguard Worker return !std::isspace(c);
28*03ce13f7SAndroid Build Coastguard Worker }));
29*03ce13f7SAndroid Build Coastguard Worker trimmed.erase(std::find_if(trimmed.rbegin(), trimmed.rend(), [](unsigned char c) {
30*03ce13f7SAndroid Build Coastguard Worker return !std::isspace(c);
31*03ce13f7SAndroid Build Coastguard Worker }).base(),
32*03ce13f7SAndroid Build Coastguard Worker trimmed.end());
33*03ce13f7SAndroid Build Coastguard Worker return trimmed;
34*03ce13f7SAndroid Build Coastguard Worker }
35*03ce13f7SAndroid Build Coastguard Worker } // namespace
36*03ce13f7SAndroid Build Coastguard Worker
37*03ce13f7SAndroid Build Coastguard Worker namespace sw {
38*03ce13f7SAndroid Build Coastguard Worker
Configurator(const std::string & filePath)39*03ce13f7SAndroid Build Coastguard Worker Configurator::Configurator(const std::string &filePath)
40*03ce13f7SAndroid Build Coastguard Worker {
41*03ce13f7SAndroid Build Coastguard Worker std::fstream file(filePath, std::ios::in);
42*03ce13f7SAndroid Build Coastguard Worker if(file.fail())
43*03ce13f7SAndroid Build Coastguard Worker {
44*03ce13f7SAndroid Build Coastguard Worker return;
45*03ce13f7SAndroid Build Coastguard Worker }
46*03ce13f7SAndroid Build Coastguard Worker readConfiguration(file);
47*03ce13f7SAndroid Build Coastguard Worker file.close();
48*03ce13f7SAndroid Build Coastguard Worker }
49*03ce13f7SAndroid Build Coastguard Worker
Configurator(std::istream & str)50*03ce13f7SAndroid Build Coastguard Worker Configurator::Configurator(std::istream &str)
51*03ce13f7SAndroid Build Coastguard Worker {
52*03ce13f7SAndroid Build Coastguard Worker readConfiguration(str);
53*03ce13f7SAndroid Build Coastguard Worker }
54*03ce13f7SAndroid Build Coastguard Worker
readConfiguration(std::istream & str)55*03ce13f7SAndroid Build Coastguard Worker bool Configurator::readConfiguration(std::istream &str)
56*03ce13f7SAndroid Build Coastguard Worker {
57*03ce13f7SAndroid Build Coastguard Worker std::string line;
58*03ce13f7SAndroid Build Coastguard Worker std::string sectionName;
59*03ce13f7SAndroid Build Coastguard Worker
60*03ce13f7SAndroid Build Coastguard Worker int lineNumber = 0;
61*03ce13f7SAndroid Build Coastguard Worker while(getline(str, line))
62*03ce13f7SAndroid Build Coastguard Worker {
63*03ce13f7SAndroid Build Coastguard Worker ++lineNumber;
64*03ce13f7SAndroid Build Coastguard Worker if(line.length())
65*03ce13f7SAndroid Build Coastguard Worker {
66*03ce13f7SAndroid Build Coastguard Worker if(line[line.length() - 1] == '\r')
67*03ce13f7SAndroid Build Coastguard Worker {
68*03ce13f7SAndroid Build Coastguard Worker line = line.substr(0, line.length() - 1);
69*03ce13f7SAndroid Build Coastguard Worker }
70*03ce13f7SAndroid Build Coastguard Worker
71*03ce13f7SAndroid Build Coastguard Worker if(!isprint(line[0]))
72*03ce13f7SAndroid Build Coastguard Worker {
73*03ce13f7SAndroid Build Coastguard Worker sw::warn("Cannot parse line %d of configuration, skipping line\n", lineNumber);
74*03ce13f7SAndroid Build Coastguard Worker return false;
75*03ce13f7SAndroid Build Coastguard Worker }
76*03ce13f7SAndroid Build Coastguard Worker
77*03ce13f7SAndroid Build Coastguard Worker std::string::size_type pLeft = line.find_first_of(";#[=");
78*03ce13f7SAndroid Build Coastguard Worker
79*03ce13f7SAndroid Build Coastguard Worker if(pLeft != std::string::npos)
80*03ce13f7SAndroid Build Coastguard Worker {
81*03ce13f7SAndroid Build Coastguard Worker switch(line[pLeft])
82*03ce13f7SAndroid Build Coastguard Worker {
83*03ce13f7SAndroid Build Coastguard Worker case '[':
84*03ce13f7SAndroid Build Coastguard Worker {
85*03ce13f7SAndroid Build Coastguard Worker std::string::size_type pRight = line.find_last_of("]");
86*03ce13f7SAndroid Build Coastguard Worker
87*03ce13f7SAndroid Build Coastguard Worker if(pRight != std::string::npos && pRight > pLeft)
88*03ce13f7SAndroid Build Coastguard Worker {
89*03ce13f7SAndroid Build Coastguard Worker sectionName = trimSpaces(line.substr(pLeft + 1, pRight - pLeft - 1));
90*03ce13f7SAndroid Build Coastguard Worker if(!sectionName.length())
91*03ce13f7SAndroid Build Coastguard Worker {
92*03ce13f7SAndroid Build Coastguard Worker sw::warn("Found empty section name at line %d of configuration\n", lineNumber);
93*03ce13f7SAndroid Build Coastguard Worker }
94*03ce13f7SAndroid Build Coastguard Worker }
95*03ce13f7SAndroid Build Coastguard Worker }
96*03ce13f7SAndroid Build Coastguard Worker break;
97*03ce13f7SAndroid Build Coastguard Worker case '=':
98*03ce13f7SAndroid Build Coastguard Worker {
99*03ce13f7SAndroid Build Coastguard Worker std::string key = trimSpaces(line.substr(0, pLeft));
100*03ce13f7SAndroid Build Coastguard Worker std::string value = trimSpaces(line.substr(pLeft + 1));
101*03ce13f7SAndroid Build Coastguard Worker if(!key.length() || !value.length())
102*03ce13f7SAndroid Build Coastguard Worker {
103*03ce13f7SAndroid Build Coastguard Worker sw::warn("Cannot parse key-value pair at line %d of configuration (key or value is empty), skipping key-value pair\n", lineNumber);
104*03ce13f7SAndroid Build Coastguard Worker }
105*03ce13f7SAndroid Build Coastguard Worker else
106*03ce13f7SAndroid Build Coastguard Worker {
107*03ce13f7SAndroid Build Coastguard Worker sections[sectionName].keyValuePairs[key] = value;
108*03ce13f7SAndroid Build Coastguard Worker }
109*03ce13f7SAndroid Build Coastguard Worker }
110*03ce13f7SAndroid Build Coastguard Worker break;
111*03ce13f7SAndroid Build Coastguard Worker case ';':
112*03ce13f7SAndroid Build Coastguard Worker case '#':
113*03ce13f7SAndroid Build Coastguard Worker // Ignore comments
114*03ce13f7SAndroid Build Coastguard Worker break;
115*03ce13f7SAndroid Build Coastguard Worker }
116*03ce13f7SAndroid Build Coastguard Worker }
117*03ce13f7SAndroid Build Coastguard Worker }
118*03ce13f7SAndroid Build Coastguard Worker }
119*03ce13f7SAndroid Build Coastguard Worker
120*03ce13f7SAndroid Build Coastguard Worker return sections.size() > 0;
121*03ce13f7SAndroid Build Coastguard Worker }
122*03ce13f7SAndroid Build Coastguard Worker
writeFile(const std::string & filePath,const std::string & title)123*03ce13f7SAndroid Build Coastguard Worker void Configurator::writeFile(const std::string &filePath, const std::string &title)
124*03ce13f7SAndroid Build Coastguard Worker {
125*03ce13f7SAndroid Build Coastguard Worker std::fstream file(filePath, std::ios::out);
126*03ce13f7SAndroid Build Coastguard Worker if(file.fail())
127*03ce13f7SAndroid Build Coastguard Worker {
128*03ce13f7SAndroid Build Coastguard Worker return;
129*03ce13f7SAndroid Build Coastguard Worker }
130*03ce13f7SAndroid Build Coastguard Worker
131*03ce13f7SAndroid Build Coastguard Worker file << "; " << title << std::endl
132*03ce13f7SAndroid Build Coastguard Worker << std::endl;
133*03ce13f7SAndroid Build Coastguard Worker
134*03ce13f7SAndroid Build Coastguard Worker for(const auto &[sectionName, section] : sections)
135*03ce13f7SAndroid Build Coastguard Worker {
136*03ce13f7SAndroid Build Coastguard Worker file << "[" << sectionName << "]" << std::endl;
137*03ce13f7SAndroid Build Coastguard Worker for(const auto &[key, value] : section.keyValuePairs)
138*03ce13f7SAndroid Build Coastguard Worker {
139*03ce13f7SAndroid Build Coastguard Worker file << key << "=" << value << std::endl;
140*03ce13f7SAndroid Build Coastguard Worker }
141*03ce13f7SAndroid Build Coastguard Worker file << std::endl;
142*03ce13f7SAndroid Build Coastguard Worker }
143*03ce13f7SAndroid Build Coastguard Worker
144*03ce13f7SAndroid Build Coastguard Worker file.close();
145*03ce13f7SAndroid Build Coastguard Worker }
146*03ce13f7SAndroid Build Coastguard Worker
getValueIfExists(const std::string & sectionName,const std::string & keyName) const147*03ce13f7SAndroid Build Coastguard Worker std::optional<std::string> Configurator::getValueIfExists(const std::string §ionName, const std::string &keyName) const
148*03ce13f7SAndroid Build Coastguard Worker {
149*03ce13f7SAndroid Build Coastguard Worker const auto section = sections.find(sectionName);
150*03ce13f7SAndroid Build Coastguard Worker if(section == sections.end())
151*03ce13f7SAndroid Build Coastguard Worker {
152*03ce13f7SAndroid Build Coastguard Worker return std::nullopt;
153*03ce13f7SAndroid Build Coastguard Worker }
154*03ce13f7SAndroid Build Coastguard Worker
155*03ce13f7SAndroid Build Coastguard Worker const auto keyValue = section->second.keyValuePairs.find(keyName);
156*03ce13f7SAndroid Build Coastguard Worker if(keyValue == section->second.keyValuePairs.end())
157*03ce13f7SAndroid Build Coastguard Worker {
158*03ce13f7SAndroid Build Coastguard Worker return std::nullopt;
159*03ce13f7SAndroid Build Coastguard Worker }
160*03ce13f7SAndroid Build Coastguard Worker
161*03ce13f7SAndroid Build Coastguard Worker return keyValue->second;
162*03ce13f7SAndroid Build Coastguard Worker }
163*03ce13f7SAndroid Build Coastguard Worker
getValue(const std::string & sectionName,const std::string & keyName,const std::string & defaultValue) const164*03ce13f7SAndroid Build Coastguard Worker std::string Configurator::getValue(const std::string §ionName, const std::string &keyName, const std::string &defaultValue) const
165*03ce13f7SAndroid Build Coastguard Worker {
166*03ce13f7SAndroid Build Coastguard Worker const auto value = getValueIfExists(sectionName, keyName);
167*03ce13f7SAndroid Build Coastguard Worker if(value)
168*03ce13f7SAndroid Build Coastguard Worker {
169*03ce13f7SAndroid Build Coastguard Worker return *value;
170*03ce13f7SAndroid Build Coastguard Worker }
171*03ce13f7SAndroid Build Coastguard Worker return defaultValue;
172*03ce13f7SAndroid Build Coastguard Worker }
173*03ce13f7SAndroid Build Coastguard Worker
addValue(const std::string & sectionName,const std::string & keyName,const std::string & value)174*03ce13f7SAndroid Build Coastguard Worker void Configurator::addValue(const std::string §ionName, const std::string &keyName, const std::string &value)
175*03ce13f7SAndroid Build Coastguard Worker {
176*03ce13f7SAndroid Build Coastguard Worker sections[sectionName].keyValuePairs[keyName] = value;
177*03ce13f7SAndroid Build Coastguard Worker }
178*03ce13f7SAndroid Build Coastguard Worker
getBoolean(const std::string & sectionName,const std::string & keyName,bool defaultValue) const179*03ce13f7SAndroid Build Coastguard Worker bool Configurator::getBoolean(const std::string §ionName, const std::string &keyName, bool defaultValue) const
180*03ce13f7SAndroid Build Coastguard Worker {
181*03ce13f7SAndroid Build Coastguard Worker auto strValue = getValueIfExists(sectionName, keyName);
182*03ce13f7SAndroid Build Coastguard Worker if(!strValue)
183*03ce13f7SAndroid Build Coastguard Worker {
184*03ce13f7SAndroid Build Coastguard Worker return defaultValue;
185*03ce13f7SAndroid Build Coastguard Worker }
186*03ce13f7SAndroid Build Coastguard Worker
187*03ce13f7SAndroid Build Coastguard Worker std::stringstream ss{ *strValue };
188*03ce13f7SAndroid Build Coastguard Worker
189*03ce13f7SAndroid Build Coastguard Worker bool val;
190*03ce13f7SAndroid Build Coastguard Worker ss >> val;
191*03ce13f7SAndroid Build Coastguard Worker if(ss.fail())
192*03ce13f7SAndroid Build Coastguard Worker {
193*03ce13f7SAndroid Build Coastguard Worker // Accept "true" and "false" as well.
194*03ce13f7SAndroid Build Coastguard Worker ss.clear();
195*03ce13f7SAndroid Build Coastguard Worker ss >> std::boolalpha >> val;
196*03ce13f7SAndroid Build Coastguard Worker }
197*03ce13f7SAndroid Build Coastguard Worker return val;
198*03ce13f7SAndroid Build Coastguard Worker }
199*03ce13f7SAndroid Build Coastguard Worker
getFloat(const std::string & sectionName,const std::string & keyName,double defaultValue) const200*03ce13f7SAndroid Build Coastguard Worker double Configurator::getFloat(const std::string §ionName, const std::string &keyName, double defaultValue) const
201*03ce13f7SAndroid Build Coastguard Worker {
202*03ce13f7SAndroid Build Coastguard Worker auto strValue = getValueIfExists(sectionName, keyName);
203*03ce13f7SAndroid Build Coastguard Worker if(!strValue)
204*03ce13f7SAndroid Build Coastguard Worker {
205*03ce13f7SAndroid Build Coastguard Worker return defaultValue;
206*03ce13f7SAndroid Build Coastguard Worker }
207*03ce13f7SAndroid Build Coastguard Worker
208*03ce13f7SAndroid Build Coastguard Worker std::stringstream ss{ *strValue };
209*03ce13f7SAndroid Build Coastguard Worker
210*03ce13f7SAndroid Build Coastguard Worker double val = 0;
211*03ce13f7SAndroid Build Coastguard Worker ss >> val;
212*03ce13f7SAndroid Build Coastguard Worker return val;
213*03ce13f7SAndroid Build Coastguard Worker }
214*03ce13f7SAndroid Build Coastguard Worker } // namespace sw
215