1 // Copyright (C) 2019 The Android Open Source Project
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 "utils/config_file.h"
16 
17 #include "utils/string_utils.h"
18 
19 #include <fstream>
20 #include <map>
21 #include <string>
22 
23 
24 namespace header_checker {
25 namespace utils {
26 
27 
ParseFile(std::istream & istream)28 ConfigFile ConfigParser::ParseFile(std::istream &istream) {
29   ConfigParser parser(istream);
30   return parser.ParseFile();
31 }
32 
33 
ParseFile(const std::string & path)34 ConfigFile ConfigParser::ParseFile(const std::string &path) {
35   std::ifstream stream(path, std::ios_base::in);
36   return ParseFile(stream);
37 }
38 
39 
ParseFile()40 ConfigFile ConfigParser::ParseFile() {
41   size_t line_no = 0;
42   std::string line;
43   while (std::getline(stream_, line)) {
44     ParseLine(++line_no, line);
45   }
46   return std::move(cfg_);
47 }
48 
49 
ParseLine(size_t line_no,std::string_view line)50 void ConfigParser::ParseLine(size_t line_no, std::string_view line) {
51   if (line.empty() || line[0] == ';' || line[0] == '#') {
52     // Skip empty or comment line.
53     return;
54   }
55 
56   // Parse section name line.
57   if (line[0] == '[') {
58     std::string::size_type pos = line.rfind(']');
59     if (pos == std::string::npos) {
60       ReportError(line_no, "bad section name line");
61       return;
62     }
63     std::string_view section_name = line.substr(1, pos - 1);
64     section_ = &cfg_.map_[std::string(section_name)];
65     return;
66   }
67 
68   // Parse key-value line.
69   std::string::size_type pos = line.find('=');
70   if (pos == std::string::npos) {
71     ReportError(line_no, "bad key-value line");
72     return;
73   }
74 
75   // Add key-value entry to current section.
76   std::string_view key = Trim(line.substr(0, pos));
77   std::string_view value = Trim(line.substr(pos + 1));
78 
79   if (!section_) {
80     section_ = &cfg_.map_[""];
81   }
82   section_->map_[std::string(key)] = std::string(value);
83 }
84 
85 
86 }  // namespace utils
87 }  // namespace header_checker
88