1 /*
2 * Copyright 2017 The Android Open Source Project
3 * Copyright 2018-2019 NXP
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 #include "config.h"
18
19 #include <android-base/file.h>
20 #include <android-base/logging.h>
21 #include <android-base/parseint.h>
22 #include <android-base/strings.h>
23
24 #include "uwb_config.h"
25
26 using namespace ::std;
27 using namespace ::android::base;
28
29 namespace {
30
parseBytesString(std::string in,std::vector<uint8_t> & out)31 bool parseBytesString(std::string in, std::vector<uint8_t>& out) {
32 vector<string> values = Split(in, ":");
33 if (values.size() == 0) return false;
34 for (string value : values) {
35 if (value.length() != 2) return false;
36 uint8_t tmp = 0;
37 string hexified = "0x";
38 hexified.append(value);
39 if (!ParseUint(hexified.c_str(), &tmp)) return false;
40 out.push_back(tmp);
41 }
42 return true;
43 }
44
45 } // namespace
46
ConfigValue()47 ConfigValue::ConfigValue() {}
48
ConfigValue(std::string value)49 ConfigValue::ConfigValue(std::string value) {
50 // Don't allow empty strings
51 CHECK(!(value.empty()));
52 type_ = STRING;
53 value_string_ = value;
54 }
55
ConfigValue(unsigned value)56 ConfigValue::ConfigValue(unsigned value) {
57 type_ = UNSIGNED;
58 value_unsigned_ = value;
59 }
60
ConfigValue(std::vector<uint8_t> value)61 ConfigValue::ConfigValue(std::vector<uint8_t> value) {
62 CHECK(!(value.empty()));
63 type_ = BYTES;
64 value_bytes_ = value;
65 }
66
getType() const67 ConfigValue::Type ConfigValue::getType() const { return type_; }
68
getString() const69 std::string ConfigValue::getString() const {
70 CHECK(type_ == STRING);
71 return value_string_;
72 };
73
getUnsigned() const74 unsigned ConfigValue::getUnsigned() const {
75 CHECK(type_ == UNSIGNED);
76 return value_unsigned_;
77 };
78
getBytes() const79 std::vector<uint8_t> ConfigValue::getBytes() const {
80 CHECK(type_ == BYTES);
81 return value_bytes_;
82 };
83
parseFromString(std::string in)84 bool ConfigValue::parseFromString(std::string in) {
85 if (in.length() > 1 && in[0] == '"' && in[in.length() - 1] == '"') {
86 CHECK(in.length() > 2); // Don't allow empty strings
87 type_ = STRING;
88 value_string_ = in.substr(1, in.length() - 2);
89 return true;
90 }
91
92 if (in.length() > 1 && in[0] == '{' && in[in.length() - 1] == '}') {
93 CHECK(in.length() >= 4); // Needs at least one byte
94 type_ = BYTES;
95 return parseBytesString(in.substr(1, in.length() - 2), value_bytes_);
96 }
97
98 unsigned tmp = 0;
99 if (ParseUint(in.c_str(), &tmp)) {
100 type_ = UNSIGNED;
101 value_unsigned_ = tmp;
102 return true;
103 }
104
105 return false;
106 }
107
addConfig(const std::string & key,ConfigValue & value)108 void ConfigFile::addConfig(const std::string& key, ConfigValue& value) {
109 CHECK(!hasKey(key));
110 values_.emplace(key, value);
111 }
112
parseFromFile(const std::string & file_name)113 void ConfigFile::parseFromFile(const std::string& file_name) {
114 string config;
115 bool config_read = ReadFileToString(file_name, &config);
116 CHECK(config_read);
117 LOG(INFO) << "ConfigFile - Parsing file '" << file_name << "'";
118 parseFromString(config);
119 }
120
parseFromString(const std::string & config)121 void ConfigFile::parseFromString(const std::string& config) {
122 stringstream ss(config);
123 string line;
124 while (getline(ss, line)) {
125 line = Trim(line);
126 if (line.empty()) continue;
127 if (line.at(0) == '#') continue;
128 if (line.at(0) == 0) continue;
129
130 auto search = line.find('=');
131 CHECK(search != string::npos);
132
133 string key(Trim(line.substr(0, search)));
134 string value_string(Trim(line.substr(search + 1, string::npos)));
135
136 ConfigValue value;
137 bool value_parsed = value.parseFromString(value_string);
138 CHECK(value_parsed);
139 addConfig(key, value);
140
141 LOG(INFO) << "ConfigFile - [" << key << "] = " << value_string;
142 }
143 }
144
hasKey(const std::string & key)145 bool ConfigFile::hasKey(const std::string& key) {
146 return values_.count(key) != 0;
147 }
148
getValue(const std::string & key)149 ConfigValue& ConfigFile::getValue(const std::string& key) {
150 CHECK(values_.find(key) != values_.end());
151 auto search = values_.find(key);
152 return search->second;
153 }
154
getString(const std::string & key)155 std::string ConfigFile::getString(const std::string& key) {
156 return getValue(key).getString();
157 }
158
getUnsigned(const std::string & key)159 unsigned ConfigFile::getUnsigned(const std::string& key) {
160 return getValue(key).getUnsigned();
161 }
162
getBytes(const std::string & key)163 std::vector<uint8_t> ConfigFile::getBytes(const std::string& key) {
164 return getValue(key).getBytes();
165 }
166
isEmpty()167 bool ConfigFile::isEmpty() { return values_.empty(); }
clear()168 void ConfigFile::clear() { values_.clear(); }
169