summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAn-Cheng Huang <ancheng@vyatta.com>2010-11-09 18:38:49 -0800
committerAn-Cheng Huang <ancheng@vyatta.com>2010-11-09 18:38:49 -0800
commit1e615a4e3f3681f8bd02d49d688001d61aa8b815 (patch)
treeed5ce2367d540d5414a283e1e2b9c2e20d0239cd
parentb8f85d2744a42eb18ac78451c29dc6de7bab5fea (diff)
downloadvyatta-cfg-1e615a4e3f3681f8bd02d49d688001d61aa8b815.tar.gz
vyatta-cfg-1e615a4e3f3681f8bd02d49d688001d61aa8b815.zip
initial rework of config output framework
* separate data from algorithm. * prepare for unified input/output framework.
-rw-r--r--Makefile.am6
-rw-r--r--src/cnode/cnode-algorithm.cpp411
-rw-r--r--src/cnode/cnode-algorithm.hpp30
-rw-r--r--src/cnode/cnode.cpp123
-rw-r--r--src/cnode/cnode.hpp70
-rw-r--r--src/cstore/cstore.hpp23
6 files changed, 655 insertions, 8 deletions
diff --git a/Makefile.am b/Makefile.am
index 903e4eb..69071ac 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -34,6 +34,8 @@ src_libvyatta_cfg_la_SOURCES += src/cstore/cstore.cpp
src_libvyatta_cfg_la_SOURCES += src/cstore/cstore-varref.cpp
src_libvyatta_cfg_la_SOURCES += src/cstore/cstore-node.cpp
src_libvyatta_cfg_la_SOURCES += src/cstore/unionfs/cstore-unionfs.cpp
+src_libvyatta_cfg_la_SOURCES += src/cnode/cnode.cpp
+src_libvyatta_cfg_la_SOURCES += src/cnode/cnode-algorithm.cpp
CLEANFILES = src/cli_parse.c src/cli_parse.h src/cli_def.c src/cli_val.c
LDADD = src/libvyatta-cfg.la
LDADD += /usr/lib/libglib-2.0.la
@@ -48,6 +50,10 @@ vcinc_HEADERS += src/cstore/cstore.hpp
vcuincdir = $(vcincdir)/unionfs
vcuinc_HEADERS = src/cstore/unionfs/cstore-unionfs.hpp
+vnincdir = $(vincludedir)/cnode
+vninc_HEADERS = src/cnode/cnode.hpp
+vninc_HEADERS += src/cnode/cnode-algorithm.hpp
+
sbin_PROGRAMS = src/priority
sbin_PROGRAMS += src/my_commit
sbin_PROGRAMS += src/exe_action
diff --git a/src/cnode/cnode-algorithm.cpp b/src/cnode/cnode-algorithm.cpp
new file mode 100644
index 0000000..9f67d7d
--- /dev/null
+++ b/src/cnode/cnode-algorithm.cpp
@@ -0,0 +1,411 @@
+/*
+ * Copyright (C) 2010 Vyatta, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include <cstore/cstore.hpp>
+#include <cnode/cnode.hpp>
+#include <cnode/cnode-algorithm.hpp>
+
+using namespace std;
+using namespace cnode;
+
+
+////// constants
+static const string PFX_DIFF_ADD = "+"; // added
+static const string PFX_DIFF_DEL = "-"; // deleted
+static const string PFX_DIFF_UPD = ">"; // changed
+static const string PFX_DIFF_NONE = " ";
+static const string PFX_DIFF_NULL = "";
+
+static const string PFX_DEACT_D = "!"; // deactivated
+static const string PFX_DEACT_DP = "D"; // deactivate pending
+static const string PFX_DEACT_AP = "A"; // activate pending
+static const string PFX_DEACT_NONE = " ";
+
+
+////// static (internal) functions
+static void
+_show_diff(CfgNode *cfg1, CfgNode *cfg2, int level, bool show_def,
+ bool hide_secret);
+
+static void
+_print_value_str(const string& name, const char *vstr, bool hide_secret)
+{
+ // handle secret hiding first
+ if (hide_secret) {
+ static const char *sname[] = { "passphrase", "password",
+ "pre-shared-secret", "key", NULL };
+ static size_t slen[] = { 10, 8, 17, 3, 0 };
+ size_t nlen = name.length();
+ for (size_t i = 0; sname[i]; i++) {
+ if (nlen < slen[i]) {
+ // can't match
+ continue;
+ }
+ if (name.find(sname[i], nlen - slen[i]) != name.npos) {
+ // found secret
+ printf("****************");
+ return;
+ }
+ }
+ }
+
+ const char *quote = "";
+ size_t vlen = strlen(vstr);
+ if (*vstr == 0 || strcspn(vstr, "*}{;\011\012\013\014\015 ") < vlen) {
+ quote = "\"";
+ }
+ printf("%s%s%s", quote, vstr, quote);
+}
+
+static void
+_diff_print_indent(CfgNode *cfg1, CfgNode *cfg2, int level,
+ const char *pfx_diff)
+{
+ const char *pfx_deact = PFX_DEACT_NONE.c_str();
+ if (cfg1 && cfg2) {
+ if (cfg1->isDeactivated()) {
+ if (cfg2->isDeactivated()) {
+ pfx_deact = PFX_DEACT_D.c_str();
+ } else {
+ pfx_deact = PFX_DEACT_AP.c_str();
+ }
+ } else {
+ if (cfg2->isDeactivated()) {
+ pfx_deact = PFX_DEACT_DP.c_str();
+ }
+ // 4th case handled by default
+ }
+ }
+
+ printf("%s %s", pfx_deact, pfx_diff);
+ for (int i = 0; i < level; i++) {
+ printf(" ");
+ }
+}
+
+static void
+_diff_print_comment(CfgNode *cfg1, CfgNode *cfg2, int level)
+{
+ const char *pfx_diff = PFX_DIFF_NONE.c_str();
+ string comment = "";
+ if (cfg1 != cfg2) {
+ string c1 = (cfg1 ? cfg1->getComment() : "");
+ string c2 = (cfg2 ? cfg2->getComment() : "");
+ if (c1 != "") {
+ if (c2 != "") {
+ // in both
+ comment = c2;
+ if (c1 != c2) {
+ pfx_diff = PFX_DIFF_UPD.c_str();
+ }
+ } else {
+ // only in cfg1
+ comment = c1;
+ pfx_diff = PFX_DIFF_DEL.c_str();
+ }
+ } else {
+ if (c2 != "") {
+ // only in cfg2
+ comment = c2;
+ pfx_diff = PFX_DIFF_ADD.c_str();
+ }
+ // 4th case handled by default
+ }
+ } else {
+ // same node => no diff
+ pfx_diff = PFX_DIFF_NULL.c_str();
+ }
+ if (comment == "") {
+ // no comment
+ return;
+ }
+ _diff_print_indent(cfg1, cfg2, level, pfx_diff);
+ printf("/* %s */\n", comment.c_str());
+}
+
+static bool
+_diff_check_and_show_leaf(CfgNode *cfg1, CfgNode *cfg2, int level,
+ bool show_def, bool hide_secret)
+{
+ if ((cfg1 && !cfg1->isLeaf()) || (cfg2 && !cfg2->isLeaf())) {
+ // not a leaf node
+ return false;
+ }
+
+ CfgNode *cfg = NULL;
+ const char *force_pfx_diff = NULL;
+ if (!cfg1) {
+ cfg = cfg2;
+ force_pfx_diff = PFX_DIFF_ADD.c_str();
+ } else {
+ cfg = cfg1;
+ if (!cfg2) {
+ force_pfx_diff = PFX_DIFF_DEL.c_str();
+ } else if (cfg1 == cfg2) {
+ force_pfx_diff = PFX_DIFF_NULL.c_str();
+ }
+ }
+
+ if (cfg->isMulti()) {
+ // multi-value node
+ _diff_print_comment(cfg1, cfg2, level);
+ if (force_pfx_diff) {
+ // simple case: just use the same diff prefix for all values
+ const vector<string>& vvec = cfg->getValues();
+ for (size_t i = 0; i < vvec.size(); i++) {
+ _diff_print_indent(cfg1, cfg2, level, force_pfx_diff);
+ printf("%s ", cfg->getName().c_str());
+ _print_value_str(cfg->getName(), vvec[i].c_str(), hide_secret);
+ printf("\n");
+ }
+ } else {
+ // need to actually do a diff.
+ // this follows the original perl logic.
+ const vector<string>& ovec = cfg1->getValues();
+ const vector<string>& nvec = cfg1->getValues();
+ vector<string> values;
+ vector<const char *> pfxs;
+ Cstore::MapT<string, bool> nmap;
+ for (size_t i = 0; i < nvec.size(); i++) {
+ nmap[nvec[i]] = true;
+ }
+ Cstore::MapT<string, bool> omap;
+ for (size_t i = 0; i < ovec.size(); i++) {
+ omap[ovec[i]] = true;
+ if (nmap.find(ovec[i]) == nmap.end()) {
+ values.push_back(ovec[i]);
+ pfxs.push_back(PFX_DIFF_DEL.c_str());
+ }
+ }
+
+ for (size_t i = 0; i < nvec.size(); i++) {
+ values.push_back(nvec[i]);
+ if (omap.find(nvec[i]) == omap.end()) {
+ pfxs.push_back(PFX_DIFF_ADD.c_str());
+ } else if (i < ovec.size() && nvec[i] == ovec[i]) {
+ pfxs.push_back(PFX_DIFF_NONE.c_str());
+ } else {
+ pfxs.push_back(PFX_DIFF_UPD.c_str());
+ }
+ }
+
+ for (size_t i = 0; i < values.size(); i++) {
+ _diff_print_indent(cfg1, cfg2, level, pfxs[i]);
+ printf("%s ", cfg->getName().c_str());
+ _print_value_str(cfg->getName(), values[i].c_str(), hide_secret);
+ printf("\n");
+ }
+ }
+ } else {
+ // single-value node
+ if (show_def || !cfg->isDefault()) {
+ const string& val = cfg->getValue();
+ if (!force_pfx_diff) {
+ const string& val1 = cfg1->getValue();
+ if (val == val1) {
+ force_pfx_diff = PFX_DIFF_NONE.c_str();
+ } else {
+ force_pfx_diff = PFX_DIFF_UPD.c_str();
+ }
+ }
+ _diff_print_indent(cfg1, cfg2, level, force_pfx_diff);
+ printf("%s ", cfg->getName().c_str());
+ _print_value_str(cfg->getName(), val.c_str(), hide_secret);
+ printf("\n");
+ }
+ }
+
+ return true;
+}
+
+static bool
+_diff_check_and_show_tag(CfgNode *cfg1, CfgNode *cfg2, int level,
+ bool show_def, bool hide_secret)
+{
+ if ((cfg1 && !cfg1->isTag()) || (cfg2 && !cfg2->isTag())) {
+ // not a tag node
+ return false;
+ }
+
+ vector<CfgNode *> vals1, vals2;
+ if (cfg1) {
+ vals1 = cfg1->getTagValues();
+ }
+ if (cfg2) {
+ vals2 = cfg2->getTagValues();
+ }
+
+ Cstore::MapT<string, bool> vmap;
+ Cstore::MapT<string, CfgNode *> vnmap1, vnmap2;
+ for (size_t i = 0; i < vals1.size(); i++) {
+ vmap[vals1[i]->getValue()] = true;
+ vnmap1[vals1[i]->getValue()] = vals1[i];
+ }
+ for (size_t i = 0; i < vals2.size(); i++) {
+ vmap[vals2[i]->getValue()] = true;
+ vnmap2[vals2[i]->getValue()] = vals2[i];
+ }
+
+ vector<string> values;
+ Cstore::MapT<string, bool>::iterator it = vmap.begin();
+ for (; it != vmap.end(); ++it) {
+ values.push_back((*it).first);
+ }
+ Cstore::sortNodes(values);
+
+ for (size_t i = 0; i < values.size(); i++) {
+ bool in1 = (vnmap1.find(values[i]) != vnmap1.end());
+ bool in2 = (vnmap2.find(values[i]) != vnmap2.end());
+ CfgNode *c1 = (in1 ? vnmap1[values[i]] : NULL);
+ CfgNode *c2 = (in2 ? vnmap2[values[i]] : NULL);
+ /* note: if the root is a tag node (level == -1), then need to make
+ * level 0 when calling tag values' show().
+ */
+ _show_diff(c1, c2, ((level >= 0) ? level : 0), show_def, hide_secret);
+ }
+ return true;
+}
+
+static void
+_diff_show_other(CfgNode *cfg1, CfgNode *cfg2, int level, bool show_def,
+ bool hide_secret)
+{
+ CfgNode *cfg = NULL;
+ const char *pfx_diff = PFX_DIFF_NONE.c_str();
+ if (!cfg1) {
+ cfg = cfg2;
+ pfx_diff = PFX_DIFF_ADD.c_str();
+ } else {
+ cfg = cfg1;
+ if (!cfg2) {
+ pfx_diff = PFX_DIFF_DEL.c_str();
+ } else if (cfg1 == cfg2) {
+ pfx_diff = PFX_DIFF_NULL.c_str();
+ }
+ }
+
+ const string& name = cfg->getName();
+ bool print_this = (level >= 0 && name.size() > 0);
+ if (print_this) {
+ _diff_print_comment(cfg1, cfg2, level);
+ _diff_print_indent(cfg1, cfg2, level, pfx_diff);
+ if (cfg->isValue()) {
+ // at tag value
+ printf("%s %s", name.c_str(), cfg->getValue().c_str());
+ } else {
+ // at intermediate node
+ printf("%s", name.c_str());
+ }
+ printf("%s\n", (cfg->isLeafTypeless() ? "" : " {"));
+ }
+
+ vector<CfgNode *> cnodes1, cnodes2;
+ if (cfg1) {
+ cnodes1 = cfg1->getChildNodes();
+ }
+ if (cfg2) {
+ cnodes2 = cfg2->getChildNodes();
+ }
+
+ Cstore::MapT<string, bool> map;
+ Cstore::MapT<string, CfgNode *> nmap1, nmap2;
+ for (size_t i = 0; i < cnodes1.size(); i++) {
+ map[cnodes1[i]->getName()] = true;
+ nmap1[cnodes1[i]->getName()] = cnodes1[i];
+ }
+ for (size_t i = 0; i < cnodes2.size(); i++) {
+ map[cnodes2[i]->getName()] = true;
+ nmap2[cnodes2[i]->getName()] = cnodes2[i];
+ }
+
+ vector<string> cnodes;
+ Cstore::MapT<string, bool>::iterator it = map.begin();
+ for (; it != map.end(); ++it) {
+ cnodes.push_back((*it).first);
+ }
+ Cstore::sortNodes(cnodes);
+
+ for (size_t i = 0; i < cnodes.size(); i++) {
+ bool in1 = (nmap1.find(cnodes[i]) != nmap1.end());
+ bool in2 = (nmap2.find(cnodes[i]) != nmap2.end());
+ CfgNode *c1 = (in1 ? nmap1[cnodes[i]] : NULL);
+ CfgNode *c2 = (in2 ? nmap2[cnodes[i]] : NULL);
+ _show_diff(c1, c2, level + 1, show_def, hide_secret);
+ }
+
+ if (print_this && !cfg->isLeafTypeless()) {
+ _diff_print_indent(cfg1, cfg2, level, pfx_diff);
+ printf("}\n");
+ }
+}
+
+static void
+_show_diff(CfgNode *cfg1, CfgNode *cfg2, int level, bool show_def,
+ bool hide_secret)
+{
+ /* cfg1 and cfg2 point to the same config node in two configs. a "diff"
+ * output is shown comparing the two configs recursively with this node
+ * as the root of the config tree.
+ *
+ * there are four possible scenarios:
+ * (1) (cfg1 && cfg2) && (cfg1 != cfg2): node exists in both config.
+ * (2) (cfg1 && cfg2) && (cfg1 == cfg2): the two point to the same config.
+ * this will be just a "show".
+ * (3) (!cfg1 && cfg2): node exists in cfg2 but not in cfg1 (added).
+ * (4) (cfg1 && !cfg2): node exists in cfg1 but not in cfg1 (deleted).
+ *
+ * calling this with both NULL is invalid.
+ */
+ if (!cfg1 && !cfg2) {
+ fprintf(stderr, "_show_diff error (both config NULL)\n");
+ exit(1);
+ }
+
+ if (_diff_check_and_show_leaf(cfg1, cfg2, level, show_def, hide_secret)) {
+ // leaf node has been shown. done.
+ return;
+ } else if (_diff_check_and_show_tag(cfg1, cfg2, level, show_def,
+ hide_secret)) {
+ // tag node has been shown. done.
+ return;
+ } else {
+ // intermediate node or tag value
+ _diff_show_other(cfg1, cfg2, level, show_def, hide_secret);
+ }
+}
+
+
+////// algorithms
+void
+cnode::show_diff(const CfgNode& cfg1, const CfgNode& cfg2, bool show_def,
+ bool hide_secret)
+{
+ if (cfg1.isInvalid() || cfg2.isInvalid()) {
+ printf("Specified configuration path is not valid\n");
+ return;
+ }
+ if (cfg1.isEmpty() && cfg2.isEmpty()) {
+ printf("Configuration under specified path is empty\n");
+ return;
+ }
+ _show_diff(const_cast<CfgNode *>(&cfg1), const_cast<CfgNode *>(&cfg2), -1,
+ show_def, hide_secret);
+}
+
diff --git a/src/cnode/cnode-algorithm.hpp b/src/cnode/cnode-algorithm.hpp
new file mode 100644
index 0000000..86bce81
--- /dev/null
+++ b/src/cnode/cnode-algorithm.hpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2010 Vyatta, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _CNODE_ALGORITHM_HPP_
+#define _CNODE_ALGORITHM_HPP_
+
+#include <cnode/cnode.hpp>
+
+namespace cnode {
+
+void show_diff(const CfgNode& cfg1, const CfgNode& cfg2, bool show_def,
+ bool hide_secret);
+
+} // namespace cnode
+
+#endif /* _CNODE_ALGORITHM_HPP_ */
+
diff --git a/src/cnode/cnode.cpp b/src/cnode/cnode.cpp
new file mode 100644
index 0000000..d1f519e
--- /dev/null
+++ b/src/cnode/cnode.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2010 Vyatta, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <cstdio>
+#include <cstring>
+#include <vector>
+#include <string>
+#include <algorithm>
+
+#include <cli_cstore.h>
+#include <cnode/cnode.hpp>
+
+using namespace std;
+using namespace cnode;
+
+////// constructors/destructors
+CfgNode::CfgNode(Cstore& cstore, vector<string>& path_comps,
+ bool active, bool recursive)
+ : _is_tag(false), _is_leaf(false), _is_multi(false), _is_value(false),
+ _is_default(false), _is_deactivated(false), _is_leaf_typeless(false),
+ _is_invalid(false), _is_empty(false)
+{
+ /* first get the def (only if path is not empty). if path is empty, i.e.,
+ * "root", treat it as an intermediate node.
+ */
+ if (path_comps.size() > 0) {
+ vtw_def def;
+ if (cstore.validateTmplPath(path_comps, false, def)) {
+ // got the def
+ _is_value = def.is_value;
+ _is_tag = (def.tag && !_is_value);
+ _is_leaf = (!_is_tag && !_is_value && def.def_type != ERROR_TYPE);
+ _is_multi = (_is_leaf && def.multi);
+ _is_default = cstore.cfgPathDefault(path_comps, active);
+ _is_deactivated = cstore.cfgPathDeactivated(path_comps, active);
+ cstore.cfgPathGetComment(path_comps, _comment, active);
+
+ if (_is_leaf && _is_value) {
+ /* recursion should never reach here. if path is specified by user,
+ * nothing further to do.
+ */
+ return;
+ }
+ } else {
+ // not a valid node
+ _is_invalid = true;
+ return;
+ }
+ }
+
+ // handle leaf node (note path_comps must be non-empty if this is leaf)
+ if (_is_leaf) {
+ _name = path_comps[path_comps.size() - 1];
+ if (_is_multi) {
+ // multi-value node
+ cstore.cfgPathGetValuesDA(path_comps, _values, active, true);
+ // ignore return value
+ } else {
+ // single-value node
+ cstore.cfgPathGetValueDA(path_comps, _value, active, true);
+ // ignore return value
+ }
+ return;
+ }
+
+ // handle intermediate (typeless) or tag
+ if (_is_value) {
+ // tag value
+ _name = path_comps[path_comps.size() - 2];
+ _value = path_comps[path_comps.size() - 1];
+ } else {
+ // tag node or typeless node
+ _name = (path_comps.size() > 0 ? path_comps[path_comps.size() - 1] : "");
+ }
+
+ // check child nodes
+ vector<string> cnodes;
+ cstore.cfgPathGetChildNodesDA(path_comps, cnodes, active, true);
+ if (cnodes.size() == 0) {
+ // empty subtree. done.
+ vector<string> tcnodes;
+ cstore.tmplGetChildNodes(path_comps, tcnodes);
+ if (tcnodes.size() == 0) {
+ // typeless leaf node
+ _is_leaf_typeless = true;
+ }
+ _is_empty = true;
+ return;
+ }
+
+ if (!recursive) {
+ // nothing further to do
+ return;
+ }
+
+ // recurse
+ for (size_t i = 0; i < cnodes.size(); i++) {
+ path_comps.push_back(cnodes[i]);
+ CfgNode *cn = new CfgNode(cstore, path_comps, active, recursive);
+ if (_is_tag && !_is_value) {
+ // tag node
+ _tag_values.push_back(cn);
+ } else {
+ // intermediate node or tag value
+ _child_nodes.push_back(cn);
+ }
+ path_comps.pop_back();
+ }
+}
+
diff --git a/src/cnode/cnode.hpp b/src/cnode/cnode.hpp
new file mode 100644
index 0000000..3143370
--- /dev/null
+++ b/src/cnode/cnode.hpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2010 Vyatta, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _CNODE_HPP_
+#define _CNODE_HPP_
+#include <vector>
+#include <string>
+
+#include <cstore/cstore.hpp>
+
+namespace cnode {
+
+class CfgNode {
+public:
+ CfgNode(Cstore& cstore, std::vector<string>& path_comps,
+ bool active = false, bool recursive = true);
+ ~CfgNode() {};
+
+ bool isTag() const { return _is_tag; }
+ bool isLeaf() const { return _is_leaf; }
+ bool isMulti() const { return _is_multi; }
+ bool isValue() const { return _is_value; }
+ bool isDefault() const { return _is_default; }
+ bool isDeactivated() const { return _is_deactivated; }
+ bool isLeafTypeless() const { return _is_leaf_typeless; }
+ bool isInvalid() const { return _is_invalid; }
+ bool isEmpty() const { return _is_empty; }
+
+ const std::string& getName() const { return _name; }
+ const std::string& getValue() const { return _value; }
+ const std::vector<std::string>& getValues() const { return _values; }
+ const std::string& getComment() const { return _comment; }
+ const std::vector<CfgNode *>& getTagValues() const { return _tag_values; }
+ const std::vector<CfgNode *>& getChildNodes() const { return _child_nodes; }
+
+private:
+ bool _is_tag;
+ bool _is_leaf;
+ bool _is_multi;
+ bool _is_value;
+ bool _is_default;
+ bool _is_deactivated;
+ bool _is_leaf_typeless;
+ bool _is_invalid;
+ bool _is_empty;
+ std::string _name;
+ std::string _value;
+ std::vector<std::string> _values;
+ std::string _comment;
+ std::vector<CfgNode *> _tag_values;
+ std::vector<CfgNode *> _child_nodes;
+};
+
+} // namespace cnode
+
+#endif /* _CNODE_HPP_ */
+
diff --git a/src/cstore/cstore.hpp b/src/cstore/cstore.hpp
index c7f179b..267dabe 100644
--- a/src/cstore/cstore.hpp
+++ b/src/cstore/cstore.hpp
@@ -78,6 +78,14 @@ public:
static const size_t MAX_CMD_OUTPUT_SIZE = 4096;
+ // for sorting
+ /* apparently unordered_map template does not work with "enum" type, so
+ * change this to simply unsigned ints to allow unifying all map types,
+ * i.e., "Cstore::MapT".
+ */
+ static const unsigned int SORT_DEFAULT;
+ static const unsigned int SORT_DEB_VERSION;
+ static const unsigned int SORT_NONE;
////// the public cstore interface
//// functions implemented in this base class
@@ -273,6 +281,11 @@ public:
get_child_nodes_status_da(path_comps, cmap, &sorted_keys);
};
+ // util functions
+ static void sortNodes(vector<string>& nvec,
+ unsigned int sort_alg = SORT_DEFAULT) {
+ sort_nodes(nvec, sort_alg);
+ };
/* these are internal API functions and operate on current cfg and
* tmpl paths during cstore operations. they are only used to work around
@@ -377,18 +390,12 @@ private:
////// implemented
// for sorting
- /* apparently unordered_map template does not work with "enum" type, so
- * change this to simply unsigned ints to allow unifying all map types,
- * i.e., "Cstore::MapT".
- */
- static const unsigned int SORT_DEFAULT;
- static const unsigned int SORT_DEB_VERSION;
- static const unsigned int SORT_NONE;
typedef bool (*SortFuncT)(std::string, std::string);
static MapT<unsigned int, SortFuncT> _sort_func_map;
static bool sort_func_deb_version(string a, string b);
- void sort_nodes(vector<string>& nvec, unsigned int sort_alg = SORT_DEFAULT);
+ static void sort_nodes(vector<string>& nvec,
+ unsigned int sort_alg = SORT_DEFAULT);
// init
static bool _init;