mirror of
https://git.rtems.org/rtems-tools/
synced 2025-05-17 09:42:03 +08:00
279 lines
7.2 KiB
C++
279 lines
7.2 KiB
C++
/*
|
|
* Copyright (c) 2014, Chris Johns <chrisj@rtems.org>
|
|
*
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
/**
|
|
* @file
|
|
*
|
|
* @ingroup rtems_rld
|
|
*
|
|
* @brief INI Configuration reader.
|
|
*
|
|
*/
|
|
|
|
#if !defined (_RLD_CONFIG_H_)
|
|
#define _RLD_CONFIG_H_
|
|
|
|
#include <string>
|
|
#include <list>
|
|
#include <vector>
|
|
|
|
#include <rld.h>
|
|
|
|
namespace rld
|
|
{
|
|
namespace config
|
|
{
|
|
/**
|
|
* The configuration item. This is a data component of a record contained
|
|
* in a section.
|
|
*/
|
|
struct item
|
|
{
|
|
std::string text; /**< The text as read from the configuration. */
|
|
|
|
/**
|
|
* Construct an item.
|
|
*/
|
|
item (const std::string& text);
|
|
item (const char* text);
|
|
};
|
|
|
|
/**
|
|
* Configuration item container.
|
|
*/
|
|
typedef std::vector < item > items;
|
|
|
|
/**
|
|
* Configuration record is a line in a section. There can be multiple
|
|
* records with the same key in a section. Keys are specific to a section.
|
|
*/
|
|
struct record
|
|
{
|
|
std::string name; //< Name of the record.
|
|
items items_; //< The record's items.
|
|
|
|
/**
|
|
* Return true if there is only one item.
|
|
*/
|
|
bool single () const {
|
|
return items_.size () == 1;
|
|
}
|
|
|
|
/**
|
|
* Operator to get an item.
|
|
*/
|
|
const std::string& operator [] (int index) const {
|
|
return items_[index].text;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Configuration record container.
|
|
*/
|
|
typedef std::list < record > records;
|
|
|
|
/**
|
|
* Configuration section. A section contains a number of records and the
|
|
* records contain [1..n] items.
|
|
*/
|
|
struct section
|
|
{
|
|
std::string name; //< Name of the section.
|
|
records recs; //< The section's records.
|
|
|
|
/**
|
|
* Has the section got a record ?
|
|
*/
|
|
bool has_record (const std::string& name) const;
|
|
|
|
/**
|
|
* Find a record and throw an error if not found.
|
|
*/
|
|
const record& get_record (const std::string& name) const;
|
|
|
|
/**
|
|
* Return the single item in a record. If the record is duplicated an
|
|
* error is thrown.
|
|
*/
|
|
const std::string get_record_item (const std::string& name) const;
|
|
|
|
/**
|
|
* Return the list of items in a record in a strings container.
|
|
*/
|
|
void get_record_items (const std::string& name, rld::strings& items_) const;
|
|
};
|
|
|
|
/**
|
|
* Configuration section container.
|
|
*/
|
|
typedef std::list < section > sections;
|
|
|
|
/**
|
|
* Container of configuration file paths loaded.
|
|
*/
|
|
typedef std::vector < std::string > paths;
|
|
|
|
/**
|
|
* The configuration.
|
|
*/
|
|
class config
|
|
{
|
|
public:
|
|
/**
|
|
* Construct an empty configuration.
|
|
*/
|
|
config(const std::string& search_path = "");
|
|
|
|
/**
|
|
* Desctruct the configuration object.
|
|
*/
|
|
virtual ~config();
|
|
|
|
/**
|
|
* Set the search path.
|
|
*/
|
|
void set_search_path (const std::string& search_path);
|
|
|
|
/**
|
|
* Clear the current configuration.
|
|
*/
|
|
void clear ();
|
|
|
|
/**
|
|
* Load a configuration.
|
|
*/
|
|
void load (const std::string& name);
|
|
|
|
/**
|
|
* Process any include records in the section named. If the section has
|
|
* any records named 'include' split the items and include the
|
|
* configuration files.
|
|
*/
|
|
void includes (const section& sec, bool must_exist = true);
|
|
|
|
/**
|
|
* Get the section and throw an error if not found.
|
|
*/
|
|
const section& get_section (const std::string& name) const;
|
|
|
|
/**
|
|
* Get the paths of loaded configuration files.
|
|
*/
|
|
const paths& get_paths () const;
|
|
|
|
private:
|
|
|
|
paths search; //< The paths to search for config files in.
|
|
paths paths_; //< The path's of the loaded files.
|
|
sections secs; //< The sections loaded from configuration files
|
|
};
|
|
|
|
/**
|
|
* Return the items from a record.
|
|
*/
|
|
template < typename T >
|
|
void parse_items (const rld::config::record& record,
|
|
T& items_,
|
|
bool clear = true,
|
|
bool split = true)
|
|
{
|
|
if (clear)
|
|
items_.clear ();
|
|
for (rld::config::items::const_iterator ii = record.items_.begin ();
|
|
ii != record.items_.end ();
|
|
++ii)
|
|
{
|
|
if (split)
|
|
{
|
|
rld::strings ss;
|
|
rld::split (ss, (*ii).text, ',');
|
|
std::copy (ss.begin (), ss.end (), std::back_inserter (items_));
|
|
}
|
|
else
|
|
{
|
|
items_.push_back ((*ii).text);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return the items from a record in a section. Optionally raise an error
|
|
* if the record is not found and it is to be present.
|
|
*/
|
|
template < typename T >
|
|
void parse_items (const rld::config::section& section,
|
|
const std::string& name,
|
|
T& items_,
|
|
bool present = false,
|
|
bool clear = true,
|
|
bool split = true)
|
|
{
|
|
if (clear)
|
|
items_.clear ();
|
|
const rld::config::record* rec = 0;
|
|
try
|
|
{
|
|
const rld::config::record& rr = section.get_record (name);
|
|
rec = &rr;
|
|
}
|
|
catch (rld::error re)
|
|
{
|
|
/*
|
|
* Ignore the error if it does not need to exist.
|
|
*/
|
|
if (present)
|
|
throw rld::error ("not found", "record: " + section.name + name);
|
|
}
|
|
|
|
if (rec)
|
|
parse_items (*rec, items_, clear, split);
|
|
}
|
|
|
|
/**
|
|
* Return the items from a record in a section in the
|
|
* configuration. Optionally raise an error if the section is not found and
|
|
* it is to be present.
|
|
*/
|
|
template < typename T >
|
|
void parse_items (const rld::config::config& config,
|
|
const std::string& section,
|
|
const std::string& record,
|
|
T& items_,
|
|
bool present = false)
|
|
{
|
|
items_.clear ();
|
|
const rld::config::section* sec = 0;
|
|
try
|
|
{
|
|
const rld::config::section& sr = config.get_section (section);
|
|
sec = &sr;
|
|
}
|
|
catch (rld::error re)
|
|
{
|
|
/*
|
|
* Ignore the error if it does not need to exist.
|
|
*/
|
|
if (present)
|
|
throw rld::error ("not found", "section: " + section);
|
|
}
|
|
|
|
if (sec)
|
|
parse_items (*sec, record, items_);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|