xref: /aosp_15_r20/external/swiftshader/src/System/Configurator.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
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 &sectionName, 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 &sectionName, 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 &sectionName, 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 &sectionName, 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 &sectionName, 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