source: rtems-tools/rtemstoolkit/rld-config.h @ 3618a62

Last change on this file since 3618a62 was 8531776, checked in by Chris Johns <chrisj@…>, on Mar 23, 2015 at 6:18:39 AM

rtemstoolkit: Add an array operator to return recs in a section.

  • Property mode set to 100644
File size: 7.2 KB
Line 
1/*
2 * Copyright (c) 2014, Chris Johns <chrisj@rtems.org>
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16/**
17 * @file
18 *
19 * @ingroup rtems_rld
20 *
21 * @brief INI Configuration reader.
22 *
23 */
24
25#if !defined (_RLD_CONFIG_H_)
26#define _RLD_CONFIG_H_
27
28#include <string>
29#include <list>
30#include <vector>
31
32#include <rld.h>
33
34namespace rld
35{
36  namespace config
37  {
38    /**
39     * The configuration item. This is a data component of a record contained
40     * in a section.
41     */
42    struct item
43    {
44      std::string text; /**< The text as read from the configuration. */
45
46      /**
47       * Construct an item.
48       */
49      item (const std::string& text);
50      item (const char*        text);
51    };
52
53    /**
54     * Configuration item container.
55     */
56    typedef std::vector < item > items;
57
58    /**
59     * Configuration record is a line in a section. There can be multiple
60     * records with the same key in a section. Keys are specific to a section.
61     */
62    struct record
63    {
64      std::string name;   //< Name of the record.
65      items       items_; //< The record's items.
66
67      /**
68       * Return true if there is only one item.
69       */
70      bool single () const {
71        return items_.size () == 1;
72      }
73
74      /**
75       * Operator to get an item.
76       */
77      const std::string& operator [] (int index) const {
78        return items_[index].text;
79      }
80    };
81
82    /**
83     * Configuration record container.
84     */
85    typedef std::list < record > records;
86
87    /**
88     * Configuration section. A section contains a number of records and the
89     * records contain [1..n] items.
90     */
91    struct section
92    {
93      std::string name;  //< Name of the section.
94      records     recs;  //< The section's records.
95
96      /**
97       * Has the section got a record ?
98       */
99      bool has_record (const std::string& name) const;
100
101      /**
102       * Find a record and throw an error if not found.
103       */
104      const record& get_record (const std::string& name) const;
105
106      /**
107       * Return the single item in a record. If the record is duplicated an
108       * error is thrown.
109       */
110      const std::string get_record_item (const std::string& name) const;
111
112      /**
113       * Return the list of items in a record in a strings container.
114       */
115      void get_record_items (const std::string& name, rld::strings& items_) const;
116    };
117
118    /**
119     * Configuration section container.
120     */
121    typedef std::list < section > sections;
122
123    /**
124     * Container of configuration file paths loaded.
125     */
126    typedef std::vector < std::string > paths;
127
128    /**
129     * The configuration.
130     */
131    class config
132    {
133    public:
134      /**
135       * Construct an empty configuration.
136       */
137      config(const std::string& search_path = "");
138
139      /**
140       * Desctruct the configuration object.
141       */
142      virtual ~config();
143
144      /**
145       * Set the search path.
146       */
147      void set_search_path (const std::string& search_path);
148
149      /**
150       * Clear the current configuration.
151       */
152      void clear ();
153
154      /**
155       * Load a configuration.
156       */
157      void load (const std::string& name);
158
159      /**
160       * Process any include records in the section named. If the section has
161       * any records named 'include' split the items and include the
162       * configuration files.
163       */
164      void includes (const section& sec, bool must_exist = true);
165
166      /**
167       * Get the section and throw an error if not found.
168       */
169      const section& get_section (const std::string& name) const;
170
171      /**
172       * Get the paths of loaded configuration files.
173       */
174      const paths& get_paths () const;
175
176    private:
177
178      paths    search; //< The paths to search for config files in.
179      paths    paths_; //< The path's of the loaded files.
180      sections secs;   //< The sections loaded from configuration files
181    };
182
183    /**
184     * Return the items from a record.
185     */
186    template < typename T >
187    void parse_items (const rld::config::record& record,
188                      T&                         items_,
189                      bool                       clear = true,
190                      bool                       split = true)
191    {
192      if (clear)
193        items_.clear ();
194      for (rld::config::items::const_iterator ii = record.items_.begin ();
195           ii != record.items_.end ();
196           ++ii)
197      {
198        if (split)
199        {
200          rld::strings ss;
201          rld::split (ss, (*ii).text, ',');
202          std::copy (ss.begin (), ss.end (), std::back_inserter (items_));
203        }
204        else
205        {
206          items_.push_back ((*ii).text);
207        }
208      }
209    }
210
211    /**
212     * Return the items from a record in a section. Optionally raise an error
213     * if the record is not found and it is to be present.
214     */
215    template < typename T >
216    void parse_items (const rld::config::section& section,
217                      const std::string&          name,
218                      T&                          items_,
219                      bool                        present = false,
220                      bool                        clear = true,
221                      bool                        split = true)
222    {
223      if (clear)
224        items_.clear ();
225      const rld::config::record* rec = 0;
226      try
227      {
228        const rld::config::record& rr = section.get_record (name);
229        rec = &rr;
230      }
231      catch (rld::error re)
232      {
233        /*
234         * Ignore the error if it does not need to exist.
235         */
236        if (present)
237          throw rld::error ("not found", "record: " + section.name + name);
238      }
239
240      if (rec)
241        parse_items (*rec, items_, clear, split);
242    }
243
244    /**
245     * Return the items from a record in a section in the
246     * configuration. Optionally raise an error if the section is not found and
247     * it is to be present.
248     */
249    template < typename T >
250    void parse_items (const rld::config::config& config,
251                      const std::string&         section,
252                      const std::string&         record,
253                      T&                         items_,
254                      bool                       present = false)
255    {
256      items_.clear ();
257      const rld::config::section* sec = 0;
258      try
259      {
260        const rld::config::section& sr = config.get_section (section);
261        sec = &sr;
262      }
263      catch (rld::error re)
264      {
265        /*
266         * Ignore the error if it does not need to exist.
267         */
268        if (present)
269          throw rld::error ("not found", "section: " + section);
270      }
271
272      if (sec)
273        parse_items (*sec, record, items_);
274    }
275  }
276}
277
278#endif
Note: See TracBrowser for help on using the repository browser.