Home | History | Annotate | Download | only in utils
      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 
     42   bool HasProperty(const std::string &name) const {
     43     return map_.find(name) != map_.end();
     44   }
     45 
     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 
     58   const_iterator begin() const {
     59     return map_.begin();
     60   }
     61 
     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 
     90   bool HasSection(const std::string &section_name) const {
     91     return map_.find(section_name) != map_.end();
     92   }
     93 
     94   const ConfigSection &GetSection(const std::string &section_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 &section_name) const {
    101     return GetSection(section_name);
    102   }
    103 
    104   bool HasProperty(const std::string &section_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 
    113   std::string GetProperty(const std::string &section_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 
    122   const_iterator begin() const {
    123     return map_.begin();
    124   }
    125 
    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:
    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 
    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 
    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