aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2010-01-02 22:21:48 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2010-01-02 22:21:48 +0000
commit9ee3e69e7d5cc3a4ae500855fb57dbc36ac759b8 (patch)
treec76fd295d673641918a4019b92bc9a5fd5ccfdbe
parenta5c83d8107c3454685a592b46fbbec17a0eaf117 (diff)
downloadpaludis-9ee3e69e7d5cc3a4ae500855fb57dbc36ac759b8.tar.gz
paludis-9ee3e69e7d5cc3a4ae500855fb57dbc36ac759b8.tar.xz
Support sections in kv configs
-rw-r--r--paludis/util/config_file.cc54
-rw-r--r--paludis/util/config_file.hh2
-rw-r--r--paludis/util/config_file.se1
-rw-r--r--paludis/util/config_file_TEST.cc31
4 files changed, 85 insertions, 3 deletions
diff --git a/paludis/util/config_file.cc b/paludis/util/config_file.cc
index 5306fb1..5187a1d 100644
--- a/paludis/util/config_file.cc
+++ b/paludis/util/config_file.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2006, 2007, 2008, 2009 Ciaran McCreesh
+ * Copyright (c) 2006, 2007, 2008, 2009, 2010 Ciaran McCreesh
* Copyright (c) 2006 Danny van Dyk
*
* This file is part of the Paludis package manager. Paludis is free software;
@@ -334,6 +334,8 @@ namespace paludis
KeyValueConfigFileValues values;
+ std::string active_key_prefix;
+
Implementation(
const KeyValueConfigFileOptions & o,
const KeyValueConfigFile::DefaultFunction & d,
@@ -635,6 +637,48 @@ KeyValueConfigFile::KeyValueConfigFile(
continue;
}
+ /* is it a section? */
+ if (_imp->options[kvcfo_allow_sections] && parser.consume(simple_parser::exact("[")))
+ {
+ std::string sec_t, sec_s;
+ if (! parser.consume(+simple_parser::any_except(" \t\n$#\"'=\\]") >> sec_t))
+ throw ConfigFileError(sr.filename(), "Expected section name on line " + stringify(parser.current_line_number()));
+
+ if (! parser.consume(*simple_parser::any_of(" \t")))
+ throw InternalError(PALUDIS_HERE, "failed to consume a zero width match");
+
+ if (! parser.consume(simple_parser::exact("]")))
+ {
+ if (! parser.consume(+simple_parser::any_except(" \t\n$#\"\\]") >> sec_s))
+ throw ConfigFileError(sr.filename(), "Expected section name value on line "
+ + stringify(parser.current_line_number()));
+ if (! parser.consume(*simple_parser::any_of(" \t")))
+ throw InternalError(PALUDIS_HERE, "failed to consume a zero width match");
+ if (! parser.consume(simple_parser::exact("]")))
+ throw ConfigFileError(sr.filename(), "Expected ] on line "
+ + stringify(parser.current_line_number()));
+ }
+
+ if (! parser.consume(*simple_parser::any_of(" \t")))
+ throw InternalError(PALUDIS_HERE, "failed to consume a zero width match");
+ if (! parser.consume(*simple_parser::exact("\n")))
+ {
+ if (parser.eof())
+ Log::get_instance()->message("key_value_config_file.no_trailing_newline", ll_debug, lc_context)
+ << "No newline at end of file";
+ else
+ throw ConfigFileError(sr.filename(), "Expected newline after ']' at line "
+ + stringify(parser.current_line_number() + "'"));
+ }
+
+ if (sec_s.empty())
+ _imp->active_key_prefix = sec_t + "/";
+ else
+ _imp->active_key_prefix = sec_t + "/" + sec_s + "/";
+
+ continue;
+ }
+
/* ignore export, if appropriate */
if (_imp->options[kvcfo_ignore_export] && parser.consume(simple_parser::exact("export") &
+simple_parser::any_of(" \t")))
@@ -711,8 +755,11 @@ KeyValueConfigFile::KeyValueConfigFile(
break;
}
+ key = _imp->active_key_prefix + key;
_imp->values[key] = transformation_function()(*this, key, get(key), value);
}
+
+ _imp->active_key_prefix = "";
}
KeyValueConfigFile::~KeyValueConfigFile()
@@ -734,7 +781,10 @@ KeyValueConfigFile::end() const
std::string
KeyValueConfigFile::get(const std::string & s) const
{
- std::map<std::string, std::string>::const_iterator f(_imp->values.find(s));
+ std::map<std::string, std::string>::const_iterator f(_imp->values.find(_imp->active_key_prefix + s));
+ if (_imp->values.end() == f)
+ f = _imp->values.find(s);
+
if (_imp->values.end() == f)
return _imp->default_function(*this, s);
else
diff --git a/paludis/util/config_file.hh b/paludis/util/config_file.hh
index 9026ad7..0c21bf3 100644
--- a/paludis/util/config_file.hh
+++ b/paludis/util/config_file.hh
@@ -192,6 +192,8 @@ namespace paludis
* - Unless kvcfo_disallow_variables, variables using $foo and ${foo} are expanded.
* - Unless kvcfo_disallow_source, source path is legal.
* - Unless kvcfo_preserve_whitespace, leading and trailing whitespace on values is stripped.
+ * - If kvcfo_allow_sections, sections in the form "[foo]" and "[foo bar]" are allowed. A key
+ * 'baz' in section "[foo]" will be treated as "foo/baz", and "[foo bar]" as "foo/bar/baz".
*
* \ingroup g_config_file
* \nosubgrouping
diff --git a/paludis/util/config_file.se b/paludis/util/config_file.se
index ca139db..1c56bb0 100644
--- a/paludis/util/config_file.se
+++ b/paludis/util/config_file.se
@@ -39,6 +39,7 @@ make_enum_KeyValueConfigFileOption()
key kvcfo_ignore_export "Accept and ignore the word export at the beginning of a line"
key kvcfo_allow_inline_comments "Allow inline comments. \since 0.28"
key kvcfo_allow_multiple_assigns_per_line "Allow A='b' B='c' (and unquoted if kvcfo_disallow_space_inside_unquoted_values). \since 0.28"
+ key kvcfo_allow_sections "Allow [sections] \since 0.44"
doxygen_comment << "END"
/**
diff --git a/paludis/util/config_file_TEST.cc b/paludis/util/config_file_TEST.cc
index f5a46c1..dcd91b7 100644
--- a/paludis/util/config_file_TEST.cc
+++ b/paludis/util/config_file_TEST.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2006, 2007, 2008 Ciaran McCreesh
+ * Copyright (c) 2006, 2007, 2008, 2009, 2010 Ciaran McCreesh
*
* This file is part of the Paludis package manager. Paludis is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
@@ -479,5 +479,34 @@ namespace test_cases
TEST_CHECK_EQUAL(ff.get("five"), "five");
}
} test_key_value_config_file_multiple_assigns;
+
+ struct KeyValueConfigFileSectionsTest : TestCase
+ {
+ KeyValueConfigFileSectionsTest() : TestCase("key value config sections") { }
+
+ void run()
+ {
+ std::stringstream d_s;
+ d_s << "a = b" << std::endl;
+ d_s << "c = d" << std::endl;
+ d_s << "[foo]" << std::endl;
+ d_s << "a = c" << std::endl;
+ d_s << "[bar bar]" << std::endl;
+ d_s << "a = d" << std::endl;
+ d_s << "[var]" << std::endl;
+ d_s << "b = x" << std::endl;
+ d_s << "a = ${a} ${b} ${c}" << std::endl;
+ KeyValueConfigFile ff(d_s, KeyValueConfigFileOptions() + kvcfo_allow_sections,
+ &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation);
+
+ TEST_CHECK_EQUAL(std::distance(ff.begin(), ff.end()), 6);
+ TEST_CHECK_EQUAL(ff.get("a"), "b");
+ TEST_CHECK_EQUAL(ff.get("c"), "d");
+ TEST_CHECK_EQUAL(ff.get("foo/a"), "c");
+ TEST_CHECK_EQUAL(ff.get("bar/bar/a"), "d");
+ TEST_CHECK_EQUAL(ff.get("var/b"), "x");
+ TEST_CHECK_EQUAL(ff.get("var/a"), "b x d");
+ }
+ } test_key_value_config_file_sections;
}