/* * Copyright 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include using namespace ::std; using namespace ::android::base; namespace { bool parseBytesString(std::string in, std::vector& out) { vector values = Split(in, ":"); if (values.size() == 0) return false; for (const string& value : values) { if (value.length() != 2) return false; uint8_t tmp = 0; string hexified = "0x"; hexified.append(value); if (!ParseUint(hexified.c_str(), &tmp)) return false; out.push_back(tmp); } return true; } } // namespace ConfigValue::ConfigValue() {} ConfigValue::ConfigValue(std::string value) { // Don't allow empty strings CHECK(!(value.empty())); type_ = STRING; value_string_ = value; } ConfigValue::ConfigValue(unsigned value) { type_ = UNSIGNED; value_unsigned_ = value; } ConfigValue::ConfigValue(std::vector value) { CHECK(!(value.empty())); type_ = BYTES; value_bytes_ = value; } ConfigValue::Type ConfigValue::getType() const { return type_; } std::string ConfigValue::getString() const { CHECK(type_ == STRING); return value_string_; }; unsigned ConfigValue::getUnsigned() const { CHECK(type_ == UNSIGNED); return value_unsigned_; }; std::vector ConfigValue::getBytes() const { CHECK(type_ == BYTES); return value_bytes_; }; bool ConfigValue::parseFromString(std::string in) { if (in.length() > 1 && in[0] == '"' && in[in.length() - 1] == '"') { CHECK(in.length() > 2); // Don't allow empty strings type_ = STRING; value_string_ = in.substr(1, in.length() - 2); return true; } if (in.length() > 1 && in[0] == '{' && in[in.length() - 1] == '}') { CHECK(in.length() >= 4); // Needs at least one byte type_ = BYTES; return parseBytesString(in.substr(1, in.length() - 2), value_bytes_); } unsigned tmp = 0; if (ParseUint(in.c_str(), &tmp)) { type_ = UNSIGNED; value_unsigned_ = tmp; return true; } return false; } void ConfigFile::addConfig(const std::string& key, ConfigValue& value) { CHECK(!hasKey(key)); values_.emplace(key, value); } void ConfigFile::parseFromFile(const std::string& file_name) { string config; bool config_read = ReadFileToString(file_name, &config); CHECK(config_read); LOG(INFO) << "ConfigFile - Parsing file '" << file_name << "'"; parseFromString(config); } void ConfigFile::parseFromString(const std::string& config) { stringstream ss(config); string line; while (getline(ss, line)) { line = Trim(line); if (line.empty()) continue; if (line.at(0) == '#') continue; if (line.at(0) == 0) continue; auto search = line.find('='); CHECK(search != string::npos); string key(Trim(line.substr(0, search))); string value_string(Trim(line.substr(search + 1, string::npos))); ConfigValue value; bool value_parsed = value.parseFromString(value_string); CHECK(value_parsed); addConfig(key, value); LOG(INFO) << "ConfigFile - [" << key << "] = " << value_string; } } bool ConfigFile::hasKey(const std::string& key) { return values_.count(key) != 0; } ConfigValue& ConfigFile::getValue(const std::string& key) { auto search = values_.find(key); CHECK(search != values_.end()); return search->second; } std::string ConfigFile::getString(const std::string& key) { return getValue(key).getString(); } unsigned ConfigFile::getUnsigned(const std::string& key) { return getValue(key).getUnsigned(); } std::vector ConfigFile::getBytes(const std::string& key) { return getValue(key).getBytes(); } bool ConfigFile::isEmpty() { return values_.empty(); } void ConfigFile::clear() { values_.clear(); }