source: rtems-tools/linkers/rld-config.h @ 3f5e31f

4.104.115
Last change on this file since 3f5e31f was 097f1fd, checked in by Chris Johns <chrisj@…>, on 08/07/14 at 08:15:06

rtms-tld: Refactor the code to match a better configuration format.

  • Property mode set to 100644
File size: 6.7 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    /**
76     * Configuration record container.
77     */
78    typedef std::list < record > records;
79
80    /**
81     * Configuration section. A section contains a number of records and the
82     * records contain [1..n] items.
83     */
84    struct section
85    {
86      std::string name;  //< Name of the section.
87      records     recs;  //< The section's records.
88
89      /**
90       * Find a record and throw an error if not found.
91       */
92      const record& get_record (const std::string& name) const;
93
94      /**
95       * Return the single item in a record. If the record is duplicated an
96       * error is thrown.
97       */
98      std::string get_record_item (const std::string& name) const;
99
100      /**
101       * Return the list of items in a record in a strings container.
102       */
103      void get_record_items (const std::string& name, rld::strings& items_) const;
104    };
105
106    /**
107     * Configuration section container.
108     */
109    typedef std::list < section > sections;
110
111    /**
112     * Container of configuration file paths loaded.
113     */
114    typedef std::vector < std::string > paths;
115
116    /**
117     * The configuration.
118     */
119    class config
120    {
121    public:
122      /**
123       * Construct an empty configuration.
124       */
125      config();
126      virtual ~config();
127
128      /**
129       * Clear the current configuration.
130       */
131      void clear ();
132
133      /**
134       * Load a configuration.
135       */
136      void load (const std::string& name);
137
138      /**
139       * Process any include records in the section named. If the section has
140       * any records named 'include' split the items and include the
141       * configuration files.
142       */
143      void includes (const section& sec, bool must_exist = false);
144
145      /**
146       * Get the section and throw an error if not found.
147       */
148      const section& get_section (const std::string& name) const;
149
150      /**
151       * Get the paths of loaded configuration files.
152       */
153      const paths& get_paths () const;
154
155    private:
156
157      paths    paths_; /**< The path's of the loaded files. */
158      sections secs;   /**< The sections loaded from configuration files */
159    };
160
161    /**
162     * Return the items from a record.
163     */
164    template < typename T >
165    void parse_items (const rld::config::record& record,
166                      T&                         items_,
167                      bool                       clear = true,
168                      bool                       split = true)
169    {
170      if (clear)
171        items_.clear ();
172      for (rld::config::items::const_iterator ii = record.items_.begin ();
173           ii != record.items_.end ();
174           ++ii)
175      {
176        if (split)
177        {
178          rld::strings ss;
179          rld::split (ss, (*ii).text, ',');
180          std::copy (ss.begin (), ss.end (), std::back_inserter (items_));
181        }
182        else
183        {
184          items_.push_back ((*ii).text);
185        }
186      }
187    }
188
189    /**
190     * Return the items from a record in a section. Optionally raise an error
191     * if the record is not found and it is to be present.
192     */
193    template < typename T >
194    void parse_items (const rld::config::section& section,
195                      const std::string&          name,
196                      T&                          items_,
197                      bool                        present = false,
198                      bool                        clear = true,
199                      bool                        split = true)
200    {
201      if (clear)
202        items_.clear ();
203      const rld::config::record* rec = 0;
204      try
205      {
206        const rld::config::record& rr = section.get_record (name);
207        rec = &rr;
208      }
209      catch (rld::error re)
210      {
211        /*
212         * Ignore the error if it does not need to exist.
213         */
214        if (present)
215          throw rld::error ("not found", "record: " + section.name + name);
216      }
217
218      if (rec)
219        parse_items (*rec, items_, clear, split);
220    }
221
222    /**
223     * Return the items from a record in a section in the
224     * configuration. Optionally raise an error if the section is not found and
225     * it is to be present.
226     */
227    template < typename T >
228    void parse_items (const rld::config::config& config,
229                      const std::string&         section,
230                      const std::string&         record,
231                      T&                         items_,
232                      bool                       present = false)
233    {
234      items_.clear ();
235      const rld::config::section* sec = 0;
236      try
237      {
238        const rld::config::section& sr = config.get_section (section);
239        sec = &sr;
240      }
241      catch (rld::error re)
242      {
243        /*
244         * Ignore the error if it does not need to exist.
245         */
246        if (present)
247          throw rld::error ("not found", "section: " + section);
248      }
249
250      if (sec)
251        parse_items (*sec, record, items_);
252    }
253  }
254}
255
256#endif
Note: See TracBrowser for help on using the repository browser.