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 #ifndef CONFIG_FILE_H_ 16 #define CONFIG_FILE_H_ 17 18 #include <cassert> 19 #include <iosfwd> 20 #include <map> 21 #include <string> 22 23 24 namespace header_checker { 25 namespace utils { 26 27 28 class ConfigParser; 29 30 31 class ConfigSection { 32 public: 33 using MapType = std::map<std::string, std::string>; 34 using const_iterator = MapType::const_iterator; 35 36 37 public: 38 ConfigSection() = default; 39 ConfigSection(ConfigSection &&) = default; 40 ConfigSection &operator=(ConfigSection &&) = default; 41 HasProperty(const std::string & name)42 bool HasProperty(const std::string &name) const { 43 return map_.find(name) != map_.end(); 44 } 45 GetProperty(const std::string & name)46 std::string GetProperty(const std::string &name) const { 47 auto &&it = map_.find(name); 48 if (it == map_.end()) { 49 return ""; 50 } 51 return it->second; 52 } 53 54 std::string operator[](const std::string &name) const { 55 return GetProperty(name); 56 } 57 begin()58 const_iterator begin() const { 59 return map_.begin(); 60 } 61 end()62 const_iterator end() const { 63 return map_.end(); 64 } 65 66 67 private: 68 ConfigSection(const ConfigSection &) = delete; 69 ConfigSection &operator=(const ConfigSection &) = delete; 70 71 72 private: 73 std::map<std::string, std::string> map_; 74 75 friend class ConfigParser; 76 }; 77 78 79 class ConfigFile { 80 public: 81 using MapType = std::map<std::string, ConfigSection>; 82 using const_iterator = MapType::const_iterator; 83 84 85 public: 86 ConfigFile() = default; 87 ConfigFile(ConfigFile &&) = default; 88 ConfigFile &operator=(ConfigFile &&) = default; 89 HasSection(const std::string & section_name)90 bool HasSection(const std::string §ion_name) const { 91 return map_.find(section_name) != map_.end(); 92 } 93 GetSection(const std::string & section_name)94 const ConfigSection &GetSection(const std::string §ion_name) const { 95 auto &&it = map_.find(section_name); 96 assert(it != map_.end()); 97 return it->second; 98 } 99 100 const ConfigSection &operator[](const std::string §ion_name) const { 101 return GetSection(section_name); 102 } 103 HasProperty(const std::string & section_name,const std::string & property_name)104 bool HasProperty(const std::string §ion_name, 105 const std::string &property_name) const { 106 auto &&it = map_.find(section_name); 107 if (it == map_.end()) { 108 return false; 109 } 110 return it->second.HasProperty(property_name); 111 } 112 GetProperty(const std::string & section_name,const std::string & property_name)113 std::string GetProperty(const std::string §ion_name, 114 const std::string &property_name) const { 115 auto &&it = map_.find(section_name); 116 if (it == map_.end()) { 117 return ""; 118 } 119 return it->second.GetProperty(property_name); 120 } 121 begin()122 const_iterator begin() const { 123 return map_.begin(); 124 } 125 end()126 const_iterator end() const { 127 return map_.end(); 128 } 129 130 131 private: 132 ConfigFile(const ConfigFile &) = delete; 133 ConfigFile &operator=(const ConfigFile &) = delete; 134 135 136 private: 137 std::map<std::string, ConfigSection> map_; 138 139 friend class ConfigParser; 140 }; 141 142 143 class ConfigParser { 144 public: 145 using ErrorListener = std::function<void (size_t, const char *)>; 146 147 148 public: ConfigParser(std::istream & stream)149 ConfigParser(std::istream &stream) 150 : stream_(stream), section_(nullptr) { } 151 152 ConfigFile ParseFile(); 153 154 static ConfigFile ParseFile(std::istream &istream); 155 156 static ConfigFile ParseFile(const std::string &path); 157 SetErrorListener(ErrorListener listener)158 void SetErrorListener(ErrorListener listener) { 159 error_listener_ = std::move(listener); 160 } 161 162 163 private: 164 void ParseLine(size_t line_no, std::string_view line); 165 ReportError(size_t line_no,const char * cause)166 void ReportError(size_t line_no, const char *cause) { 167 if (error_listener_) { 168 error_listener_(line_no, cause); 169 } 170 } 171 172 173 private: 174 ConfigParser(const ConfigParser &) = delete; 175 ConfigParser &operator=(const ConfigParser &) = delete; 176 177 178 private: 179 std::istream &stream_; 180 181 ErrorListener error_listener_; 182 183 ConfigSection *section_; 184 185 ConfigFile cfg_; 186 }; 187 188 189 } // namespace utils 190 } // namespace header_checker 191 192 193 #endif // CONFIG_FILE_H_ 194