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

Last change on this file since 3618a62 was 5025439, checked in by Chris Johns <chrisj@…>, on Sep 21, 2014 at 4:24:37 AM

rtems-tld: Add config options, fix void args, and SCore traces.

  • Property mode set to 100644
File size: 5.8 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#include <errno.h>
26
27#include <rld-config.h>
28
29#include <SimpleIni.h>
30
31namespace rld
32{
33  namespace config
34  {
35    item::item (const std::string& text)
36      : text (text)
37    {
38    }
39
40    item::item (const char* text)
41      : text (text)
42    {
43    }
44
45    bool
46    section::has_record (const std::string& name) const
47    {
48      for (records::const_iterator ri = recs.begin ();
49           ri != recs.end ();
50           ++ri)
51      {
52        if ((*ri).name == name)
53          return true;
54      }
55      return false;
56    }
57
58    const record&
59    section::get_record (const std::string& name) const
60    {
61      for (records::const_iterator ri = recs.begin ();
62           ri != recs.end ();
63           ++ri)
64      {
65        if ((*ri).name == name)
66          return *ri;
67      }
68
69      throw rld::error ("not found", "config record: " + this->name + '/' + name);
70    }
71
72    const std::string
73    section::get_record_item (const std::string& rec_name) const
74    {
75      const record& rec = get_record (rec_name);
76      if (rec.items_.size () != 1)
77        throw rld::error ("duplicate", "record item: " + name + '/' + rec_name);
78      return rec.items_[0].text;
79    }
80
81    void
82    section::get_record_items (const std::string& rec_name, rld::strings& items) const
83    {
84      const record& rec = get_record (rec_name);
85      items.clear ();
86      for (rld::config::items::const_iterator ii = rec.items_.begin ();
87           ii != rec.items_.end ();
88           ++ii)
89      {
90        items.push_back ((*ii).text);
91      }
92    }
93
94    config::config(const std::string& search_path)
95    {
96      set_search_path (search_path);
97    }
98
99    config::~config()
100    {
101    }
102
103    void
104    config::set_search_path (const std::string& search_path)
105    {
106      if (!search_path.empty ())
107        rld::path::path_split (search_path, search);
108    }
109
110    void
111    config::clear ()
112    {
113      secs.clear ();
114    }
115
116    void
117    config::load (const std::string& path)
118    {
119      CSimpleIniCaseA ini (false, true, true);
120
121      std::string checked_path;
122
123      if (rld::path::check_file (path))
124      {
125        checked_path = path;
126      }
127      else
128      {
129        bool found = false;
130        for (rld::path::paths::const_iterator spi = search.begin ();
131             spi != search.end ();
132             ++spi)
133        {
134          rld::path::path_join (*spi, path, checked_path);
135          if (rld::path::check_file (checked_path))
136          {
137            found = true;
138            break;
139          }
140        }
141        if (!found)
142          throw rld::error ("Not found.", "load config: " + path);
143      }
144
145      if (ini.LoadFile (checked_path.c_str ()) != SI_OK)
146        throw rld::error (::strerror (errno), "load config: " + path);
147
148      paths_.push_back (checked_path);
149
150      /*
151       * Merge the loaded configuration into our configuration.
152       */
153
154      CSimpleIniCaseA::TNamesDepend skeys;
155
156      ini.GetAllSections(skeys);
157
158      for (CSimpleIniCaseA::TNamesDepend::const_iterator si = skeys.begin ();
159           si != skeys.end ();
160           ++si)
161      {
162        section sec;
163
164        sec.name = (*si).pItem;
165
166        CSimpleIniCaseA::TNamesDepend rkeys;
167
168        ini.GetAllKeys((*si).pItem, rkeys);
169
170        for (CSimpleIniCaseA::TNamesDepend::const_iterator ri = rkeys.begin ();
171             ri != rkeys.end ();
172             ++ri)
173        {
174          record rec;
175
176          rec.name = (*ri).pItem;
177
178          CSimpleIniCaseA::TNamesDepend vals;
179
180          ini.GetAllValues((*si).pItem, (*ri).pItem, vals);
181
182          for (CSimpleIniCaseA::TNamesDepend::const_iterator vi = vals.begin ();
183               vi != vals.end ();
184               ++vi)
185          {
186            rec.items_.push_back (item ((*vi).pItem));
187          }
188
189          sec.recs.push_back (rec);
190        }
191
192        secs.push_back (sec);
193
194        if (sec.name == "includes")
195          includes(sec);
196      }
197    }
198
199
200    void
201    config::includes (const section& sec, bool must_exist)
202    {
203      bool have_includes = false;
204
205      try
206      {
207        rld::strings is;
208        parse_items (sec, "include", is);
209
210        have_includes = true;
211
212        /*
213         * Include records are a paths which we can load.
214         */
215
216        for (rld::strings::const_iterator isi = is.begin ();
217             isi != is.end ();
218             ++isi)
219        {
220          load (*isi);
221        }
222      }
223      catch (rld::error re)
224      {
225        /*
226         * No include records, must be all inlined. If we have includes it must
227         * be another error so throw it.
228         */
229        if (have_includes || (!have_includes && must_exist))
230          throw;
231      }
232    }
233
234    const section&
235    config::get_section (const std::string& name) const
236    {
237      for (sections::const_iterator si = secs.begin ();
238           si != secs.end ();
239           ++si)
240      {
241        if ((*si).name == name)
242          return *si;
243      }
244
245      throw error ("not found", "config section: " + name);
246    }
247
248    const paths&
249    config::get_paths () const
250    {
251      return paths_;
252    }
253  }
254}
Note: See TracBrowser for help on using the repository browser.