summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAn-Cheng Huang <ancheng@vyatta.com>2011-03-17 11:48:54 -0700
committerAn-Cheng Huang <ancheng@vyatta.com>2011-03-17 11:48:54 -0700
commiteb9f5718d412022015bb65eb08c30785c79e79e6 (patch)
treebe0b6a9de27965e39c44c5c8a88adf9caa13abf8 /src
parentcda3f423c311fd30e8cc24e2de67d99baf352b2a (diff)
downloadvyatta-cfg-eb9f5718d412022015bb65eb08c30785c79e79e6.tar.gz
vyatta-cfg-eb9f5718d412022015bb65eb08c30785c79e79e6.zip
add config path abstraction and high-level caching
* part of the config backend cleanup/optimization work. * improves the performance of "load" (w/o commit) by ~55% and "show" by ~15%.
Diffstat (limited to 'src')
-rw-r--r--src/cli_bin.cpp25
-rw-r--r--src/cli_cstore.h2
-rw-r--r--src/cli_shell_api.cpp92
-rw-r--r--src/cnode/cnode-algorithm.cpp126
-rw-r--r--src/cnode/cnode-algorithm.hpp16
-rw-r--r--src/cnode/cnode.cpp25
-rw-r--r--src/cnode/cnode.hpp26
-rw-r--r--src/cparse/cparse.ypp25
-rw-r--r--src/cstore/cpath.hpp88
-rw-r--r--src/cstore/cstore-c.cpp33
-rw-r--r--src/cstore/cstore-varref.cpp69
-rw-r--r--src/cstore/cstore-varref.hpp10
-rw-r--r--src/cstore/cstore.cpp1250
-rw-r--r--src/cstore/cstore.hpp214
-rw-r--r--src/cstore/ctemplate.hpp9
-rw-r--r--src/cstore/svector.hpp345
-rw-r--r--src/cstore/unionfs/cstore-unionfs.cpp407
-rw-r--r--src/cstore/unionfs/cstore-unionfs.hpp117
-rw-r--r--src/cstore/unionfs/fspath.hpp92
19 files changed, 1756 insertions, 1215 deletions
diff --git a/src/cli_bin.cpp b/src/cli_bin.cpp
index 20da924..4d32c15 100644
--- a/src/cli_bin.cpp
+++ b/src/cli_bin.cpp
@@ -80,7 +80,7 @@ static const bool op_need_cfg_node_args[] = {
#define OP_need_cfg_node_args op_need_cfg_node_args[op_idx]
static void
-doSet(Cstore& cstore, const vector<string>& path_comps)
+doSet(Cstore& cstore, const Cpath& path_comps)
{
if (!cstore.validateSetPath(path_comps)) {
bye("invalid set path\n");
@@ -91,7 +91,7 @@ doSet(Cstore& cstore, const vector<string>& path_comps)
}
static void
-doDelete(Cstore& cstore, const vector<string>& path_comps)
+doDelete(Cstore& cstore, const Cpath& path_comps)
{
if (!cstore.deleteCfgPath(path_comps)) {
bye("delete failed\n");
@@ -99,7 +99,7 @@ doDelete(Cstore& cstore, const vector<string>& path_comps)
}
static void
-doActivate(Cstore& cstore, const vector<string>& path_comps)
+doActivate(Cstore& cstore, const Cpath& path_comps)
{
if (!cstore.validateActivatePath(path_comps)) {
bye("%s validate failed", OP_str);
@@ -110,7 +110,7 @@ doActivate(Cstore& cstore, const vector<string>& path_comps)
}
static void
-doDeactivate(Cstore& cstore, const vector<string>& path_comps)
+doDeactivate(Cstore& cstore, const Cpath& path_comps)
{
if (!cstore.validateDeactivatePath(path_comps)) {
bye("%s validate failed", OP_str);
@@ -121,7 +121,7 @@ doDeactivate(Cstore& cstore, const vector<string>& path_comps)
}
static void
-doRename(Cstore& cstore, const vector<string>& path_comps)
+doRename(Cstore& cstore, const Cpath& path_comps)
{
if (!cstore.validateRenameArgs(path_comps)) {
bye("invalid rename args\n");
@@ -132,7 +132,7 @@ doRename(Cstore& cstore, const vector<string>& path_comps)
}
static void
-doCopy(Cstore& cstore, const vector<string>& path_comps)
+doCopy(Cstore& cstore, const Cpath& path_comps)
{
if (!cstore.validateCopyArgs(path_comps)) {
bye("invalid copy args\n");
@@ -143,7 +143,7 @@ doCopy(Cstore& cstore, const vector<string>& path_comps)
}
static void
-doComment(Cstore& cstore, const vector<string>& path_comps)
+doComment(Cstore& cstore, const Cpath& path_comps)
{
if (!cstore.commentCfgPath(path_comps)) {
bye("comment cfg path failed\n");
@@ -151,7 +151,7 @@ doComment(Cstore& cstore, const vector<string>& path_comps)
}
static void
-doDiscard(Cstore& cstore, const vector<string>& args)
+doDiscard(Cstore& cstore, const Cpath& args)
{
if (args.size() > 0) {
OUTPUT_USER("Invalid discard command\n");
@@ -163,7 +163,7 @@ doDiscard(Cstore& cstore, const vector<string>& args)
}
static void
-doMove(Cstore& cstore, const vector<string>& path_comps)
+doMove(Cstore& cstore, const Cpath& path_comps)
{
if (!cstore.validateMoveArgs(path_comps)) {
bye("invalid move args\n");
@@ -174,7 +174,7 @@ doMove(Cstore& cstore, const vector<string>& path_comps)
}
typedef void (*OpFuncT)(Cstore& cstore,
- const vector<string>& path_comps);
+ const Cpath& path_comps);
OpFuncT OpFunc[] = {
&doSet,
&doDelete,
@@ -214,10 +214,7 @@ main(int argc, char **argv)
// actual CLI operations use the edit levels from environment, so pass true.
Cstore *cstore = Cstore::createCstore(true);
- vector<string> path_comps;
- for (int i = 1; i < argc; i++) {
- path_comps.push_back(argv[i]);
- }
+ Cpath path_comps(const_cast<const char **>(argv + 1), argc - 1);
// call the op function
OpFunc[op_idx](*cstore, path_comps);
diff --git a/src/cli_cstore.h b/src/cli_cstore.h
index 5f0b061..6f4ec51 100644
--- a/src/cli_cstore.h
+++ b/src/cli_cstore.h
@@ -109,8 +109,6 @@ typedef struct {
boolean tag;
boolean multi;
vtw_list actions[top_act];
- int is_value; /* this is used by the config store to indicate whether
- * the last path component is a "value". */
} vtw_def;
/* extern variables */
diff --git a/src/cli_shell_api.cpp b/src/cli_shell_api.cpp
index 41d18e2..8fea74a 100644
--- a/src/cli_shell_api.cpp
+++ b/src/cli_shell_api.cpp
@@ -63,7 +63,7 @@ int op_show_commands = 0;
char *op_show_cfg1 = NULL;
char *op_show_cfg2 = NULL;
-typedef void (*OpFuncT)(Cstore& cstore, const vector<string>& args);
+typedef void (*OpFuncT)(Cstore& cstore, const Cpath& args);
typedef struct {
const char *op_name;
@@ -77,7 +77,7 @@ typedef struct {
/* outputs an environment string to be "eval"ed */
static void
-getSessionEnv(Cstore& cstore, const vector<string>& args)
+getSessionEnv(Cstore& cstore, const Cpath& args)
{
// need a "session-specific" cstore so ignore the default one
string env;
@@ -88,7 +88,7 @@ getSessionEnv(Cstore& cstore, const vector<string>& args)
/* outputs an environment string to be "eval"ed */
static void
-getEditEnv(Cstore& cstore, const vector<string>& args)
+getEditEnv(Cstore& cstore, const Cpath& args)
{
string env;
if (!cstore.getEditEnv(args, env)) {
@@ -99,7 +99,7 @@ getEditEnv(Cstore& cstore, const vector<string>& args)
/* outputs an environment string to be "eval"ed */
static void
-getEditUpEnv(Cstore& cstore, const vector<string>& args)
+getEditUpEnv(Cstore& cstore, const Cpath& args)
{
string env;
if (!cstore.getEditUpEnv(env)) {
@@ -110,7 +110,7 @@ getEditUpEnv(Cstore& cstore, const vector<string>& args)
/* outputs an environment string to be "eval"ed */
static void
-getEditResetEnv(Cstore& cstore, const vector<string>& args)
+getEditResetEnv(Cstore& cstore, const Cpath& args)
{
string env;
if (!cstore.getEditResetEnv(env)) {
@@ -120,14 +120,14 @@ getEditResetEnv(Cstore& cstore, const vector<string>& args)
}
static void
-editLevelAtRoot(Cstore& cstore, const vector<string>& args)
+editLevelAtRoot(Cstore& cstore, const Cpath& args)
{
exit(cstore.editLevelAtRoot() ? 0 : 1);
}
/* outputs an environment string to be "eval"ed */
static void
-getCompletionEnv(Cstore& cstore, const vector<string>& args)
+getCompletionEnv(Cstore& cstore, const Cpath& args)
{
string env;
if (!cstore.getCompletionEnv(args, env)) {
@@ -138,15 +138,19 @@ getCompletionEnv(Cstore& cstore, const vector<string>& args)
/* outputs a string */
static void
-getEditLevelStr(Cstore& cstore, const vector<string>& args)
+getEditLevelStr(Cstore& cstore, const Cpath& args)
{
- vector<string> lvec;
+ Cpath lvec;
cstore.getEditLevel(lvec);
- print_vec(lvec, " ", "");
+ vector<string> vec;
+ for (size_t i = 0; i < lvec.size(); i++) {
+ vec.push_back(lvec[i]);
+ }
+ print_vec(vec, " ", "");
}
static void
-markSessionUnsaved(Cstore& cstore, const vector<string>& args)
+markSessionUnsaved(Cstore& cstore, const Cpath& args)
{
if (!cstore.markSessionUnsaved()) {
exit(1);
@@ -154,7 +158,7 @@ markSessionUnsaved(Cstore& cstore, const vector<string>& args)
}
static void
-unmarkSessionUnsaved(Cstore& cstore, const vector<string>& args)
+unmarkSessionUnsaved(Cstore& cstore, const Cpath& args)
{
if (!cstore.unmarkSessionUnsaved()) {
exit(1);
@@ -162,7 +166,7 @@ unmarkSessionUnsaved(Cstore& cstore, const vector<string>& args)
}
static void
-sessionUnsaved(Cstore& cstore, const vector<string>& args)
+sessionUnsaved(Cstore& cstore, const Cpath& args)
{
if (!cstore.sessionUnsaved()) {
exit(1);
@@ -170,7 +174,7 @@ sessionUnsaved(Cstore& cstore, const vector<string>& args)
}
static void
-sessionChanged(Cstore& cstore, const vector<string>& args)
+sessionChanged(Cstore& cstore, const Cpath& args)
{
if (!cstore.sessionChanged()) {
exit(1);
@@ -178,7 +182,7 @@ sessionChanged(Cstore& cstore, const vector<string>& args)
}
static void
-teardownSession(Cstore& cstore, const vector<string>& args)
+teardownSession(Cstore& cstore, const Cpath& args)
{
if (!cstore.teardownSession()) {
exit(1);
@@ -186,7 +190,7 @@ teardownSession(Cstore& cstore, const vector<string>& args)
}
static void
-setupSession(Cstore& cstore, const vector<string>& args)
+setupSession(Cstore& cstore, const Cpath& args)
{
if (!cstore.setupSession()) {
exit(1);
@@ -194,7 +198,7 @@ setupSession(Cstore& cstore, const vector<string>& args)
}
static void
-inSession(Cstore& cstore, const vector<string>& args)
+inSession(Cstore& cstore, const Cpath& args)
{
if (!cstore.inSession()) {
exit(1);
@@ -203,21 +207,21 @@ inSession(Cstore& cstore, const vector<string>& args)
/* same as exists() in Perl API */
static void
-exists(Cstore& cstore, const vector<string>& args)
+exists(Cstore& cstore, const Cpath& args)
{
exit(cstore.cfgPathExists(args, false) ? 0 : 1);
}
/* same as existsOrig() in Perl API */
static void
-existsActive(Cstore& cstore, const vector<string>& args)
+existsActive(Cstore& cstore, const Cpath& args)
{
exit(cstore.cfgPathExists(args, true) ? 0 : 1);
}
/* same as isEffective() in Perl API */
static void
-existsEffective(Cstore& cstore, const vector<string>& args)
+existsEffective(Cstore& cstore, const Cpath& args)
{
exit(cstore.cfgPathEffective(args) ? 0 : 1);
}
@@ -235,7 +239,7 @@ existsEffective(Cstore& cstore, const vector<string>& args)
* eval "nodes=($(cli-shell-api listNodes interfaces))"
*/
static void
-listNodes(Cstore& cstore, const vector<string>& args)
+listNodes(Cstore& cstore, const Cpath& args)
{
vector<string> cnodes;
cstore.cfgPathGetChildNodes(args, cnodes, false);
@@ -248,7 +252,7 @@ listNodes(Cstore& cstore, const vector<string>& args)
* "eval"ed into an array of nodes. see listNodes above.
*/
static void
-listActiveNodes(Cstore& cstore, const vector<string>& args)
+listActiveNodes(Cstore& cstore, const Cpath& args)
{
vector<string> cnodes;
cstore.cfgPathGetChildNodes(args, cnodes, true);
@@ -261,7 +265,7 @@ listActiveNodes(Cstore& cstore, const vector<string>& args)
* "eval"ed into an array of nodes. see listNodes above.
*/
static void
-listEffectiveNodes(Cstore& cstore, const vector<string>& args)
+listEffectiveNodes(Cstore& cstore, const Cpath& args)
{
vector<string> cnodes;
cstore.cfgPathGetEffectiveChildNodes(args, cnodes);
@@ -270,7 +274,7 @@ listEffectiveNodes(Cstore& cstore, const vector<string>& args)
/* same as returnValue() in Perl API. outputs a string. */
static void
-returnValue(Cstore& cstore, const vector<string>& args)
+returnValue(Cstore& cstore, const Cpath& args)
{
string val;
if (!cstore.cfgPathGetValue(args, val, false)) {
@@ -281,7 +285,7 @@ returnValue(Cstore& cstore, const vector<string>& args)
/* same as returnOrigValue() in Perl API. outputs a string. */
static void
-returnActiveValue(Cstore& cstore, const vector<string>& args)
+returnActiveValue(Cstore& cstore, const Cpath& args)
{
string val;
if (!cstore.cfgPathGetValue(args, val, true)) {
@@ -292,7 +296,7 @@ returnActiveValue(Cstore& cstore, const vector<string>& args)
/* same as returnEffectiveValue() in Perl API. outputs a string. */
static void
-returnEffectiveValue(Cstore& cstore, const vector<string>& args)
+returnEffectiveValue(Cstore& cstore, const Cpath& args)
{
string val;
if (!cstore.cfgPathGetEffectiveValue(args, val)) {
@@ -322,7 +326,7 @@ returnEffectiveValue(Cstore& cstore, const vector<string>& args)
* failure would result in an empty array after the eval.
*/
static void
-returnValues(Cstore& cstore, const vector<string>& args)
+returnValues(Cstore& cstore, const Cpath& args)
{
vector<string> vvec;
if (!cstore.cfgPathGetValues(args, vvec, false)) {
@@ -337,7 +341,7 @@ returnValues(Cstore& cstore, const vector<string>& args)
* "eval"ed into an array of values. see returnValues above.
*/
static void
-returnActiveValues(Cstore& cstore, const vector<string>& args)
+returnActiveValues(Cstore& cstore, const Cpath& args)
{
vector<string> vvec;
if (!cstore.cfgPathGetValues(args, vvec, true)) {
@@ -352,7 +356,7 @@ returnActiveValues(Cstore& cstore, const vector<string>& args)
* "eval"ed into an array of values. see returnValues above.
*/
static void
-returnEffectiveValues(Cstore& cstore, const vector<string>& args)
+returnEffectiveValues(Cstore& cstore, const Cpath& args)
{
vector<string> vvec;
if (!cstore.cfgPathGetEffectiveValues(args, vvec)) {
@@ -365,24 +369,31 @@ returnEffectiveValues(Cstore& cstore, const vector<string>& args)
* the validity of any "tag values" along the path.
*/
static void
-validateTmplPath(Cstore& cstore, const vector<string>& args)
+validateTmplPath(Cstore& cstore, const Cpath& args)
{
- exit(cstore.validateTmplPath(args, false) ? 0 : 1);
+ printf("validate:");
+ Cpath p;
+ for (size_t i = 0; i < args.size(); i++) {
+ p.push(args[i]);
+ printf(" [%s]", p[i]);
+ }
+ printf("\n");
+ exit(cstore.validateTmplPath(p, false) ? 0 : 1);
}
/* checks if specified path is a valid "template path", *including* the
* validity of any "tag values" along the path.
*/
static void
-validateTmplValPath(Cstore& cstore, const vector<string>& args)
+validateTmplValPath(Cstore& cstore, const Cpath& args)
{
exit(cstore.validateTmplPath(args, true) ? 0 : 1);
}
static void
-showCfg(Cstore& cstore, const vector<string>& args)
+showCfg(Cstore& cstore, const Cpath& args)
{
- vector<string> nargs(args);
+ Cpath nargs(args);
bool active_only = (!cstore.inSession() || op_show_active_only);
bool working_only = (cstore.inSession() && op_show_working_only);
cnode::CfgNode aroot(cstore, nargs, true, true);
@@ -396,7 +407,7 @@ showCfg(Cstore& cstore, const vector<string>& args)
// just show the working config (no diff)
cnode::show_cfg(wroot, op_show_show_defaults, op_show_hide_secrets);
} else {
- vector<string> cur_path;
+ Cpath cur_path;
cstore.getEditLevel(cur_path);
cnode::show_cfg_diff(aroot, wroot, cur_path, op_show_show_defaults,
op_show_hide_secrets, op_show_context_diff);
@@ -434,7 +445,7 @@ showCfg(Cstore& cstore, const vector<string>& args)
* both "args" and "edit level" are ignored.
*/
static void
-showConfig(Cstore& cstore, const vector<string>& args)
+showConfig(Cstore& cstore, const Cpath& args)
{
string cfg1 = cnode::ACTIVE_CFG;
string cfg2 = cnode::WORKING_CFG;
@@ -456,9 +467,9 @@ showConfig(Cstore& cstore, const vector<string>& args)
}
static void
-loadFile(Cstore& cstore, const vector<string>& args)
+loadFile(Cstore& cstore, const Cpath& args)
{
- if (!cstore.loadFile(args[0].c_str())) {
+ if (!cstore.loadFile(args[0])) {
// loadFile failed
exit(1);
}
@@ -582,10 +593,7 @@ main(int argc, char **argv)
exit(1);
}
- vector<string> args;
- for (int i = 0; i < nargs; i++) {
- args.push_back(nargv[i]);
- }
+ Cpath args(const_cast<const char **>(nargv), nargs);
// call the op function
Cstore *cstore = Cstore::createCstore(OP_use_edit);
diff --git a/src/cnode/cnode-algorithm.cpp b/src/cnode/cnode-algorithm.cpp
index 9256e7c..c6b91f9 100644
--- a/src/cnode/cnode-algorithm.cpp
+++ b/src/cnode/cnode-algorithm.cpp
@@ -40,14 +40,13 @@ const string cnode::WORKING_CFG = "@WORKING";
////// static (internal) functions
static void
_show_diff(const CfgNode *cfg1, const CfgNode *cfg2, int level,
- vector<string>& cur_path, vector<string>& last_ctx,
- bool show_def, bool hide_secret, bool context_diff);
+ Cpath& cur_path, Cpath& last_ctx, bool show_def,
+ bool hide_secret, bool context_diff);
static void
_get_cmds_diff(const CfgNode *cfg1, const CfgNode *cfg2,
- vector<string>& cur_path, vector<vector<string> >& del_list,
- vector<vector<string> >& set_list,
- vector<vector<string> >& com_list);
+ Cpath& cur_path, vector<Cpath>& del_list,
+ vector<Cpath>& set_list, vector<Cpath>& com_list);
/* compare the values of a "multi" node in the two configs. the values and
* the "prefix" of each value are returned in "values" and "pfxs",
@@ -155,21 +154,21 @@ _cmp_non_leaf_nodes(const CfgNode *cfg1, const CfgNode *cfg2,
}
static void
-_add_path_to_list(vector<vector<string> >& list, vector<string>& path,
- const string *nptr, const string *vptr)
+_add_path_to_list(vector<Cpath>& list, Cpath& path, const string *nptr,
+ const string *vptr)
{
if (nptr) {
- path.push_back(*nptr);
+ path.push(*nptr);
}
if (vptr) {
- path.push_back(*vptr);
+ path.push(*vptr);
}
list.push_back(path);
if (vptr) {
- path.pop_back();
+ path.pop();
}
if (nptr) {
- path.pop_back();
+ path.pop();
}
}
@@ -221,7 +220,7 @@ _diff_print_indent(const CfgNode *cfg1, const CfgNode *cfg2, int level,
* like in JUNOS "show | compare".
*/
static void
-_diff_print_context(vector<string>& cur_path, vector<string>& last_ctx)
+_diff_print_context(Cpath& cur_path, Cpath& last_ctx)
{
if (last_ctx == cur_path) {
// don't repeat the context if it's still the same as the last one
@@ -230,7 +229,7 @@ _diff_print_context(vector<string>& cur_path, vector<string>& last_ctx)
last_ctx = cur_path;
printf("[edit");
for (size_t i = 0; i < cur_path.size(); i++) {
- printf(" %s", cur_path[i].c_str());
+ printf(" %s", cur_path[i]);
}
printf("]\n");
}
@@ -249,8 +248,7 @@ _diff_print_context(vector<string>& cur_path, vector<string>& last_ctx)
*/
static bool
_diff_print_comment(const CfgNode *cfg1, const CfgNode *cfg2, int level,
- vector<string>& cur_path, vector<string>& last_ctx,
- bool context_diff)
+ Cpath& cur_path, Cpath& last_ctx, bool context_diff)
{
const char *pfx_diff = PFX_DIFF_NONE.c_str();
string comment = "";
@@ -307,8 +305,8 @@ _diff_print_comment(const CfgNode *cfg1, const CfgNode *cfg2, int level,
static bool
_diff_check_and_show_leaf(const CfgNode *cfg1, const CfgNode *cfg2, int level,
- vector<string>& cur_path, vector<string>& last_ctx,
- bool show_def, bool hide_secret, bool context_diff)
+ Cpath& cur_path, Cpath& last_ctx, bool show_def,
+ bool hide_secret, bool context_diff)
{
if ((cfg1 && !cfg1->isLeaf()) || (cfg2 && !cfg2->isLeaf())) {
// not a leaf node
@@ -424,8 +422,8 @@ _diff_check_and_show_leaf(const CfgNode *cfg1, const CfgNode *cfg2, int level,
static void
_diff_show_other(const CfgNode *cfg1, const CfgNode *cfg2, int level,
- vector<string>& cur_path, vector<string>& last_ctx,
- bool show_def, bool hide_secret, bool context_diff)
+ Cpath& cur_path, Cpath& last_ctx, bool show_def,
+ bool hide_secret, bool context_diff)
{
bool orig_cdiff = context_diff;
const char *pfx_diff = PFX_DIFF_NONE.c_str();
@@ -522,9 +520,9 @@ _diff_show_other(const CfgNode *cfg1, const CfgNode *cfg2, int level,
}
}
- cur_path.push_back(name);
+ cur_path.push(name);
if (is_value) {
- cur_path.push_back(value);
+ cur_path.push(value);
}
} else {
next_level = (level >= 0 ? level : 0);
@@ -537,9 +535,9 @@ _diff_show_other(const CfgNode *cfg1, const CfgNode *cfg2, int level,
// finish printing "this" node if necessary
if (print_this) {
- cur_path.pop_back();
+ cur_path.pop();
if (is_value) {
- cur_path.pop_back();
+ cur_path.pop();
}
if (!orig_cdiff || pfx_diff != PFX_DIFF_NONE.c_str()) {
/* not context diff OR there is a difference => print closing '}'
@@ -556,8 +554,8 @@ _diff_show_other(const CfgNode *cfg1, const CfgNode *cfg2, int level,
static void
_show_diff(const CfgNode *cfg1, const CfgNode *cfg2, int level,
- vector<string>& cur_path, vector<string>& last_ctx,
- bool show_def, bool hide_secret, bool context_diff)
+ Cpath& cur_path, Cpath& last_ctx, bool show_def,
+ bool hide_secret, bool context_diff)
{
// if doesn't exist, treat as NULL
if (cfg1 && !cfg1->exists()) {
@@ -613,8 +611,8 @@ _show_diff(const CfgNode *cfg1, const CfgNode *cfg2, int level,
static void
_get_comment_diff_cmd(const CfgNode *cfg1, const CfgNode *cfg2,
- vector<string>& cur_path,
- vector<vector<string> >& com_list, const string *val)
+ Cpath& cur_path, vector<Cpath>& com_list,
+ const string *val)
{
const string *comment = NULL;
const string *name = NULL;
@@ -652,22 +650,20 @@ _get_comment_diff_cmd(const CfgNode *cfg1, const CfgNode *cfg2,
}
if (comment) {
if (val) {
- cur_path.push_back(*name);
+ cur_path.push(*name);
name = val;
}
_add_path_to_list(com_list, cur_path, name, comment);
if (val) {
- cur_path.pop_back();
+ cur_path.pop();
}
}
}
static bool
_get_cmds_diff_leaf(const CfgNode *cfg1, const CfgNode *cfg2,
- vector<string>& cur_path,
- vector<vector<string> >& del_list,
- vector<vector<string> >& set_list,
- vector<vector<string> >& com_list)
+ Cpath& cur_path, vector<Cpath>& del_list,
+ vector<Cpath>& set_list, vector<Cpath>& com_list)
{
if ((cfg1 && !cfg1->isLeaf()) || (cfg2 && !cfg2->isLeaf())) {
// not a leaf node
@@ -675,7 +671,7 @@ _get_cmds_diff_leaf(const CfgNode *cfg1, const CfgNode *cfg2,
}
const CfgNode *cfg = NULL;
- vector<vector<string> > *list = NULL;
+ vector<Cpath> *list = NULL;
if (cfg1) {
cfg = cfg1;
if (!cfg2) {
@@ -736,12 +732,10 @@ _get_cmds_diff_leaf(const CfgNode *cfg1, const CfgNode *cfg2,
static void
_get_cmds_diff_other(const CfgNode *cfg1, const CfgNode *cfg2,
- vector<string>& cur_path,
- vector<vector<string> >& del_list,
- vector<vector<string> >& set_list,
- vector<vector<string> >& com_list)
+ Cpath& cur_path, vector<Cpath>& del_list,
+ vector<Cpath>& set_list, vector<Cpath>& com_list)
{
- vector<vector<string> > *list = NULL;
+ vector<Cpath> *list = NULL;
if (cfg1) {
if (!cfg2) {
// exists in cfg1 but not in cfg2 => delete and stop recursion
@@ -773,9 +767,9 @@ _get_cmds_diff_other(const CfgNode *cfg1, const CfgNode *cfg2,
const string *val = (is_value ? &value : NULL);
_get_comment_diff_cmd(cfg1, cfg2, cur_path, com_list, val);
- cur_path.push_back(name);
+ cur_path.push(name);
if (is_value) {
- cur_path.push_back(value);
+ cur_path.push(value);
}
}
for (size_t i = 0; i < rcnodes1.size(); i++) {
@@ -784,17 +778,16 @@ _get_cmds_diff_other(const CfgNode *cfg1, const CfgNode *cfg2,
}
if (add_this) {
if (is_value) {
- cur_path.pop_back();
+ cur_path.pop();
}
- cur_path.pop_back();
+ cur_path.pop();
}
}
static void
_get_cmds_diff(const CfgNode *cfg1, const CfgNode *cfg2,
- vector<string>& cur_path, vector<vector<string> >& del_list,
- vector<vector<string> >& set_list,
- vector<vector<string> >& com_list)
+ Cpath& cur_path, vector<Cpath>& del_list,
+ vector<Cpath>& set_list, vector<Cpath>& com_list)
{
// if doesn't exist, treat as NULL
if (cfg1 && !cfg1->exists()) {
@@ -820,12 +813,12 @@ _get_cmds_diff(const CfgNode *cfg1, const CfgNode *cfg2,
}
static void
-_print_cmds_list(const char *op, vector<vector<string> >& list)
+_print_cmds_list(const char *op, vector<Cpath>& list)
{
for (size_t i = 0; i < list.size(); i++) {
printf("%s", op);
for (size_t j = 0; j < list[i].size(); j++) {
- printf(" '%s'", list[i][j].c_str());
+ printf(" '%s'", list[i][j]);
}
printf("\n");
}
@@ -834,8 +827,8 @@ _print_cmds_list(const char *op, vector<vector<string> >& list)
////// algorithms
void
cnode::show_cfg_diff(const CfgNode& cfg1, const CfgNode& cfg2,
- vector<string>& cur_path, bool show_def,
- bool hide_secret, bool context_diff)
+ Cpath& cur_path, bool show_def, bool hide_secret,
+ bool context_diff)
{
if (cfg1.isInvalid() || cfg2.isInvalid()) {
printf("Specified configuration path is not valid\n");
@@ -847,7 +840,7 @@ cnode::show_cfg_diff(const CfgNode& cfg1, const CfgNode& cfg2,
return;
}
// use an invalid value for initial last_ctx
- vector<string> last_ctx(1, "");
+ Cpath last_ctx;
_show_diff(&cfg1, &cfg2, -1, cur_path, last_ctx, show_def, hide_secret,
context_diff);
}
@@ -855,17 +848,17 @@ cnode::show_cfg_diff(const CfgNode& cfg1, const CfgNode& cfg2,
void
cnode::show_cfg(const CfgNode& cfg, bool show_def, bool hide_secret)
{
- vector<string> cur_path;
+ Cpath cur_path;
show_cfg_diff(cfg, cfg, cur_path, show_def, hide_secret);
}
void
cnode::show_cmds_diff(const CfgNode& cfg1, const CfgNode& cfg2)
{
- vector<string> cur_path;
- vector<vector<string> > del_list;
- vector<vector<string> > set_list;
- vector<vector<string> > com_list;
+ Cpath cur_path;
+ vector<Cpath> del_list;
+ vector<Cpath> set_list;
+ vector<Cpath> com_list;
_get_cmds_diff(&cfg1, &cfg2, cur_path, del_list, set_list, com_list);
_print_cmds_list("delete", del_list);
@@ -881,32 +874,31 @@ cnode::show_cmds(const CfgNode& cfg)
void
cnode::get_cmds_diff(const CfgNode& cfg1, const CfgNode& cfg2,
- vector<vector<string> >& del_list,
- vector<vector<string> >& set_list,
- vector<vector<string> >& com_list)
+ vector<Cpath>& del_list, vector<Cpath>& set_list,
+ vector<Cpath>& com_list)
{
- vector<string> cur_path;
+ Cpath cur_path;
_get_cmds_diff(&cfg1, &cfg2, cur_path, del_list, set_list, com_list);
}
void
-cnode::get_cmds(const CfgNode& cfg, vector<vector<string> >& set_list,
- vector<vector<string> >& com_list)
+cnode::get_cmds(const CfgNode& cfg, vector<Cpath>& set_list,
+ vector<Cpath>& com_list)
{
- vector<string> cur_path;
- vector<vector<string> > del_list;
+ Cpath cur_path;
+ vector<Cpath> del_list;
_get_cmds_diff(&cfg, &cfg, cur_path, del_list, set_list, com_list);
}
void
cnode::showConfig(const string& cfg1, const string& cfg2,
- const vector<string>& path, bool show_def, bool hide_secret,
+ const Cpath& path, bool show_def, bool hide_secret,
bool context_diff, bool show_cmds)
{
tr1::shared_ptr<CfgNode> aroot, wroot, croot1, croot2;
tr1::shared_ptr<Cstore> cstore;
- vector<string> rpath(path);
- vector<string> cur_path;
+ Cpath rpath(path);
+ Cpath cur_path;
if ((cfg1 == ACTIVE_CFG || cfg1 == WORKING_CFG)
&& (cfg2 == ACTIVE_CFG || cfg2 == WORKING_CFG)) {
diff --git a/src/cnode/cnode-algorithm.hpp b/src/cnode/cnode-algorithm.hpp
index c473d6a..2f8995d 100644
--- a/src/cnode/cnode-algorithm.hpp
+++ b/src/cnode/cnode-algorithm.hpp
@@ -22,9 +22,8 @@
namespace cnode {
void show_cfg_diff(const CfgNode& cfg1, const CfgNode& cfg2,
- vector<string>& cur_path,
- bool show_def = false, bool hide_secret = false,
- bool context_diff = false);
+ Cpath& cur_path, bool show_def = false,
+ bool hide_secret = false, bool context_diff = false);
void show_cfg(const CfgNode& cfg, bool show_def = false,
bool hide_secret = false);
@@ -32,17 +31,16 @@ void show_cmds_diff(const CfgNode& cfg1, const CfgNode& cfg2);
void show_cmds(const CfgNode& cfg);
void get_cmds_diff(const CfgNode& cfg1, const CfgNode& cfg2,
- vector<vector<string> >& del_list,
- vector<vector<string> >& set_list,
- vector<vector<string> >& com_list);
-void get_cmds(const CfgNode& cfg, vector<vector<string> >& set_list,
- vector<vector<string> >& com_list);
+ vector<Cpath>& del_list, vector<Cpath>& set_list,
+ vector<Cpath>& com_list);
+void get_cmds(const CfgNode& cfg, vector<Cpath>& set_list,
+ vector<Cpath>& com_list);
extern const string ACTIVE_CFG;
extern const string WORKING_CFG;
void showConfig(const string& cfg1, const string& cfg2,
- const vector<string>& path, bool show_def = false,
+ const Cpath& path, bool show_def = false,
bool hide_secret = false, bool context_diff = false,
bool show_cmds = false);
diff --git a/src/cnode/cnode.cpp b/src/cnode/cnode.cpp
index f484fb1..cd4f6cf 100644
--- a/src/cnode/cnode.cpp
+++ b/src/cnode/cnode.cpp
@@ -28,20 +28,19 @@ using namespace cnode;
////// constructors/destructors
-CfgNode::CfgNode(vector<string>& path_comps, char *name, char *val,
- char *comment, int deact, Cstore *cstore,
- bool tag_if_invalid)
+CfgNode::CfgNode(Cpath& path_comps, char *name, char *val, char *comment,
+ int deact, Cstore *cstore, bool tag_if_invalid)
: _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(true), _exists(true)
{
if (name && name[0]) {
// name must be non-empty
- path_comps.push_back(name);
+ path_comps.push(name);
}
if (val) {
// value could be empty
- path_comps.push_back(val);
+ path_comps.push(val);
}
while (1) {
@@ -50,7 +49,7 @@ CfgNode::CfgNode(vector<string>& path_comps, char *name, char *val,
break;
}
- auto_ptr<Ctemplate> def(cstore->parseTmpl(path_comps, false));
+ tr1::shared_ptr<Ctemplate> def(cstore->parseTmpl(path_comps, false));
if (def.get()) {
// got the def
_is_tag = def->isTag();
@@ -106,16 +105,16 @@ CfgNode::CfgNode(vector<string>& path_comps, char *name, char *val,
} else {
_value = val;
}
- path_comps.pop_back();
+ path_comps.pop();
}
if (name && name[0]) {
_name = name;
- path_comps.pop_back();
+ path_comps.pop();
}
}
-CfgNode::CfgNode(Cstore& cstore, vector<string>& path_comps,
- bool active, bool recursive)
+CfgNode::CfgNode(Cstore& cstore, Cpath& 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), _exists(true)
@@ -124,7 +123,7 @@ CfgNode::CfgNode(Cstore& cstore, vector<string>& path_comps,
* "root", treat it as an intermediate node.
*/
if (path_comps.size() > 0) {
- auto_ptr<Ctemplate> def(cstore.parseTmpl(path_comps, false));
+ tr1::shared_ptr<Ctemplate> def(cstore.parseTmpl(path_comps, false));
if (def.get()) {
// got the def
if (!cstore.cfgPathExists(path_comps, active)) {
@@ -202,10 +201,10 @@ CfgNode::CfgNode(Cstore& cstore, vector<string>& path_comps,
// recurse
for (size_t i = 0; i < cnodes.size(); i++) {
- path_comps.push_back(cnodes[i]);
+ path_comps.push(cnodes[i]);
CfgNode *cn = new CfgNode(cstore, path_comps, active, recursive);
_child_nodes.push_back(cn);
- path_comps.pop_back();
+ path_comps.pop();
}
}
diff --git a/src/cnode/cnode.hpp b/src/cnode/cnode.hpp
index b7afc36..a684514 100644
--- a/src/cnode/cnode.hpp
+++ b/src/cnode/cnode.hpp
@@ -27,10 +27,10 @@ using namespace cstore;
class CfgNode {
public:
- CfgNode(vector<string>& path_comps, char *name, char *val, char *comment,
+ CfgNode(Cpath& path_comps, char *name, char *val, char *comment,
int deact, Cstore *cstore, bool tag_if_invalid = false);
- CfgNode(Cstore& cstore, std::vector<string>& path_comps,
- bool active = false, bool recursive = true);
+ CfgNode(Cstore& cstore, Cpath& path_comps, bool active = false,
+ bool recursive = true);
~CfgNode() {};
bool isTag() const { return _is_tag; }
@@ -44,11 +44,11 @@ public:
bool isEmpty() const { return _is_empty; }
bool exists() const { return _exists; }
- 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 *>& getChildNodes() const { return _child_nodes; }
+ const string& getName() const { return _name; }
+ const string& getValue() const { return _value; }
+ const vector<string>& getValues() const { return _values; }
+ const string& getComment() const { return _comment; }
+ const vector<CfgNode *>& getChildNodes() const { return _child_nodes; }
void addMultiValue(char *val) { _values.push_back(val); }
void addChildNode(CfgNode *cnode) {
@@ -68,11 +68,11 @@ private:
bool _is_invalid;
bool _is_empty;
bool _exists;
- std::string _name;
- std::string _value;
- std::vector<std::string> _values;
- std::string _comment;
- std::vector<CfgNode *> _child_nodes;
+ string _name;
+ string _value;
+ vector<string> _values;
+ string _comment;
+ vector<CfgNode *> _child_nodes;
};
} // namespace cnode
diff --git a/src/cparse/cparse.ypp b/src/cparse/cparse.ypp
index 24abbad..6b5d5c6 100644
--- a/src/cparse/cparse.ypp
+++ b/src/cparse/cparse.ypp
@@ -1,7 +1,6 @@
%{
#include <cstdio>
#include <vector>
-#include <map>
#include <string>
#include <cstore/cstore.hpp>
@@ -39,25 +38,25 @@ static char *ncomment = NULL;
static char *nname = NULL;
static char *nval = NULL;
-// XXX optimize: use unordered_map with non-vector
-static map<vector<string>, CfgNode *> node_map;
+typedef Cstore::MapT<Cpath, CfgNode *, CpathHash> NmapT;
+static NmapT node_map;
static Cstore *cstore_ = NULL;
static CfgNode *cur_node = NULL;
static CfgNode *cur_parent = NULL;
static vector<CfgNode *> cur_path;
-static vector<string> pcomps;
+static Cpath pcomps;
static vector<bool> pcomp_is_value;
static void
add_node()
{
- pcomps.push_back(nname);
+ pcomps.push(nname);
CfgNode *onode = NULL;
- map<vector<string>, CfgNode *>::iterator it = node_map.find(pcomps);
+ NmapT::iterator it = node_map.find(pcomps);
if (it != node_map.end()) {
onode = it->second;
}
- pcomps.pop_back();
+ pcomps.pop();
if (onode) {
if (nval) {
if (onode->isMulti()) {
@@ -92,9 +91,9 @@ add_node()
mapped_node = p;
}
cur_parent->addChildNode(mapped_node);
- pcomps.push_back(nname);
+ pcomps.push(nname);
node_map[pcomps] = mapped_node;
- pcomps.pop_back();
+ pcomps.pop();
}
}
@@ -104,10 +103,10 @@ go_down()
cur_path.push_back(cur_parent);
cur_parent = cur_node;
- pcomps.push_back(nname);
+ pcomps.push(nname);
pcomp_is_value.push_back(false);
if (nval) {
- pcomps.push_back(nval);
+ pcomps.push(nval);
pcomp_is_value.push_back(true);
}
}
@@ -119,10 +118,10 @@ go_up()
cur_path.pop_back();
if (pcomp_is_value.back()) {
- pcomps.pop_back();
+ pcomps.pop();
pcomp_is_value.pop_back();
}
- pcomps.pop_back();
+ pcomps.pop();
pcomp_is_value.pop_back();
}
diff --git a/src/cstore/cpath.hpp b/src/cstore/cpath.hpp
new file mode 100644
index 0000000..ed26a92
--- /dev/null
+++ b/src/cstore/cpath.hpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2011 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 _CPATH_HPP_
+#define _CPATH_HPP_
+#include <string>
+
+#include <cstore/svector.hpp>
+
+namespace cstore { // begin namespace cstore
+
+class Cpath {
+public:
+ Cpath() : _data() {};
+ Cpath(const Cpath& p) : _data() { operator=(p); };
+ Cpath(const char *comps[], size_t num_comps) : _data() {
+ for (size_t i = 0; i < num_comps; i++) {
+ push(comps[i]);
+ }
+ };
+ ~Cpath() {};
+
+ void push(const char *comp) { _data.push_back(comp); };
+ void push(const std::string& comp) { _data.push_back(comp.c_str()); };
+ void pop() { _data.pop_back(); };
+ void pop(std::string& last) { _data.pop_back(last); };
+ void clear() { _data.assign("", 0); };
+
+ Cpath& operator=(const Cpath& p) {
+ _data = p._data;
+ return *this;
+ };
+ Cpath& operator/=(const Cpath& p) {
+ _data /= p._data;
+ return *this;
+ }
+ Cpath operator/(const Cpath& rhs) {
+ Cpath lhs(*this);
+ lhs /= rhs;
+ return lhs;
+ };
+
+ bool operator==(const Cpath& rhs) const {
+ return (_data == rhs._data);
+ };
+ const char *operator[](size_t idx) const {
+ return _data[idx];
+ };
+
+ size_t size() const { return _data.size(); };
+ size_t hash() const { return _data.hash(); };
+ const char *back() const {
+ return (size() > 0 ? _data[size() - 1] : NULL);
+ };
+
+private:
+ struct CpathParams {
+ static const char separator = 0;
+ static const size_t static_num_elems = 24;
+ static const size_t static_buf_len = 256;
+ };
+
+ cstore::svector<CpathParams> _data;
+};
+
+struct CpathHash {
+ inline size_t operator()(const Cpath& p) const {
+ return p.hash();
+ };
+};
+
+} // end namespace cstore
+
+#endif /* _CPATH_HPP_ */
+
diff --git a/src/cstore/cstore-c.cpp b/src/cstore/cstore-c.cpp
index 06f0067..86b544e 100644
--- a/src/cstore/cstore-c.cpp
+++ b/src/cstore/cstore-c.cpp
@@ -24,14 +24,6 @@
using namespace cstore;
-static void
-_get_str_vec(vector<string>& vec, const char *strs[], int num_strs)
-{
- for (int i = 0; i < num_strs; i++) {
- vec.push_back(strs[i]);
- }
-}
-
void *
cstore_init(void)
{
@@ -51,10 +43,9 @@ cstore_validate_tmpl_path(void *handle, const char *path_comps[],
int num_comps, int validate_tags)
{
if (handle) {
- vector<string> vs;
- _get_str_vec(vs, path_comps, num_comps);
+ Cpath p(path_comps, num_comps);
Cstore *cs = (Cstore *) handle;
- return (cs->validateTmplPath(vs, validate_tags) ? 1 : 0);
+ return (cs->validateTmplPath(p, validate_tags) ? 1 : 0);
}
return 0;
}
@@ -63,10 +54,9 @@ int
cstore_cfg_path_exists(void *handle, const char *path_comps[], int num_comps)
{
if (handle) {
- vector<string> vs;
- _get_str_vec(vs, path_comps, num_comps);
+ Cpath p(path_comps, num_comps);
Cstore *cs = (Cstore *) handle;
- return (cs->cfgPathExists(vs) ? 1 : 0);
+ return (cs->cfgPathExists(p) ? 1 : 0);
}
return 0;
}
@@ -99,10 +89,9 @@ cstore_cfg_path_deactivated(void *handle, const char *path_comps[],
int num_comps, int in_active)
{
if (handle) {
- vector<string> vs;
- _get_str_vec(vs, path_comps, num_comps);
+ Cpath p(path_comps, num_comps);
Cstore *cs = (Cstore *) handle;
- return (cs->cfgPathDeactivated(vs, in_active) ? 1 : 0);
+ return (cs->cfgPathDeactivated(p, in_active) ? 1 : 0);
}
return 0;
}
@@ -112,11 +101,10 @@ cstore_cfg_path_get_effective_value(void *handle, const char *path_comps[],
int num_comps)
{
if (handle) {
- vector<string> vs;
- _get_str_vec(vs, path_comps, num_comps);
+ Cpath p(path_comps, num_comps);
Cstore *cs = (Cstore *) handle;
string val;
- if (!cs->cfgPathGetEffectiveValue(vs, val)) {
+ if (!cs->cfgPathGetEffectiveValue(p, val)) {
return NULL;
}
@@ -138,10 +126,9 @@ cstore_unmark_cfg_path_changed(void *handle, const char *path_comps[],
int num_comps)
{
if (handle) {
- vector<string> vs;
- _get_str_vec(vs, path_comps, num_comps);
+ Cpath p(path_comps, num_comps);
Cstore *cs = (Cstore *) handle;
- return (cs->unmarkCfgPathChanged(vs) ? 1 : 0);
+ return (cs->unmarkCfgPathChanged(p) ? 1 : 0);
}
return 0;
}
diff --git a/src/cstore/cstore-varref.cpp b/src/cstore/cstore-varref.cpp
index 2878dd0..2ec3c51 100644
--- a/src/cstore/cstore-varref.cpp
+++ b/src/cstore/cstore-varref.cpp
@@ -37,9 +37,15 @@ Cstore::VarRef::VarRef(Cstore *cstore, const string& ref_str, bool active)
}
_absolute = (ref_str[0] == '/');
+ vector<string> tmp;
while (!_absolute && !_cstore->cfg_path_at_root()) {
- _orig_path_comps.insert(_orig_path_comps.begin(),
- _cstore->pop_cfg_path());
+ string last;
+ _cstore->pop_cfg_path(last);
+ tmp.push_back(last);
+ }
+ while (tmp.size() > 0) {
+ _orig_path_comps.push(tmp.back());
+ tmp.pop_back();
}
_cstore->reset_paths();
/* at this point, cstore paths are at root. _orig_path_comps contains
@@ -48,14 +54,14 @@ Cstore::VarRef::VarRef(Cstore *cstore, const string& ref_str, bool active)
size_t si = (_absolute ? 1 : 0);
size_t sn = 0;
- vector<string> rcomps;
+ Cpath rcomps;
while (si < ref_str.length()
&& (sn = ref_str.find('/', si)) != ref_str.npos) {
- rcomps.push_back(ref_str.substr(si, sn - si));
+ rcomps.push(ref_str.substr(si, sn - si));
si = sn + 1;
}
if (si < ref_str.length()) {
- rcomps.push_back(ref_str.substr(si));
+ rcomps.push(ref_str.substr(si));
}
// NOTE: if path ends in '/', the trailing slash is ignored.
@@ -63,7 +69,7 @@ Cstore::VarRef::VarRef(Cstore *cstore, const string& ref_str, bool active)
_at_string = get_at_string();
// process ref
- vector<string> pcomps = _orig_path_comps;
+ Cpath pcomps(_orig_path_comps);
process_ref(rcomps, pcomps, ERROR_TYPE);
}
@@ -77,23 +83,24 @@ Cstore::VarRef::VarRef(Cstore *cstore, const string& ref_str, bool active)
* actual config (working or active).
*/
void
-Cstore::VarRef::process_ref(const vector<string>& ref_comps,
- const vector<string>& cur_path_comps,
+Cstore::VarRef::process_ref(const Cpath& ref_comps,
+ const Cpath& cur_path_comps,
vtw_type_e def_type)
{
if (ref_comps.size() == 0) {
// done
- _paths.push_back(pair<vector<string>,
- vtw_type_e>(cur_path_comps, def_type));
+ _paths.push_back(pair<Cpath, vtw_type_e>(cur_path_comps, def_type));
return;
}
- vector<string> rcomps = ref_comps;
- vector<string> pcomps = cur_path_comps;
- string cr_comp= rcomps.front();
- rcomps.erase(rcomps.begin());
+ Cpath rcomps;
+ Cpath pcomps(cur_path_comps);
+ string cr_comp = ref_comps[0];
+ for (size_t i = 1; i < ref_comps.size(); i++) {
+ rcomps.push(ref_comps[i]);
+ }
- auto_ptr<Ctemplate> def(_cstore->parseTmpl(pcomps, false));
+ tr1::shared_ptr<Ctemplate> def(_cstore->parseTmpl(pcomps, false));
bool got_tmpl = (def.get() != 0);
bool handle_leaf = false;
if (cr_comp == "@") {
@@ -106,19 +113,18 @@ Cstore::VarRef::process_ref(const vector<string>& ref_comps,
return;
}
if (pcomps.size() == _orig_path_comps.size()) {
- if (pcomps.size() == 0
- || equal(pcomps.begin(), pcomps.end(), _orig_path_comps.begin())) {
+ if (pcomps.size() == 0 || pcomps == _orig_path_comps) {
/* we are at the original path. this is a self-reference, e.g.,
* $VAR(@), so use the "at string".
*/
- pcomps.push_back(_at_string);
+ pcomps.push(_at_string);
process_ref(rcomps, pcomps, def->getType(1));
return;
}
}
if (pcomps.size() < _orig_path_comps.size()) {
// within the original path. @ translates to the path comp.
- pcomps.push_back(_orig_path_comps[pcomps.size()]);
+ pcomps.push(_orig_path_comps[pcomps.size()]);
process_ref(rcomps, pcomps, def->getType(1));
return;
}
@@ -135,8 +141,8 @@ Cstore::VarRef::process_ref(const vector<string>& ref_comps,
// invalid path
return;
}
- pcomps.pop_back();
- def.reset(_cstore->parseTmpl(pcomps, false));
+ pcomps.pop();
+ def = _cstore->parseTmpl(pcomps, false);
if (!def.get()) {
// invalid tmpl path
return;
@@ -147,7 +153,7 @@ Cstore::VarRef::process_ref(const vector<string>& ref_comps,
// invalid path
return;
}
- pcomps.pop_back();
+ pcomps.pop();
}
process_ref(rcomps, pcomps, ERROR_TYPE);
} else if (cr_comp == "@@") {
@@ -168,9 +174,9 @@ Cstore::VarRef::process_ref(const vector<string>& ref_comps,
vector<string> cnodes;
_cstore->cfgPathGetChildNodes(pcomps, cnodes, _active);
for (size_t i = 0; i < cnodes.size(); i++) {
- pcomps.push_back(cnodes[i]);
+ pcomps.push(cnodes[i]);
process_ref(rcomps, pcomps, def->getType(1));
- pcomps.pop_back();
+ pcomps.pop();
}
} else {
// handle leaf node
@@ -185,9 +191,9 @@ Cstore::VarRef::process_ref(const vector<string>& ref_comps,
return;
}
// within the original path. take the original tag value.
- pcomps.push_back(_orig_path_comps[pcomps.size()]);
+ pcomps.push(_orig_path_comps[pcomps.size()]);
}
- pcomps.push_back(cr_comp);
+ pcomps.push(cr_comp);
process_ref(rcomps, pcomps, ERROR_TYPE);
}
@@ -205,9 +211,9 @@ Cstore::VarRef::process_ref(const vector<string>& ref_comps,
}
val += vals[i];
}
- pcomps.push_back(val);
+ pcomps.push(val);
// treat "joined" multi-values as TEXT_TYPE
- _paths.push_back(pair<vector<string>, vtw_type_e>(pcomps, TEXT_TYPE));
+ _paths.push_back(pair<Cpath, vtw_type_e>(pcomps, TEXT_TYPE));
// at leaf. stop recursion.
} else {
// single-value node
@@ -215,9 +221,8 @@ Cstore::VarRef::process_ref(const vector<string>& ref_comps,
if (!_cstore->cfgPathGetValue(pcomps, val, _active)) {
return;
}
- pcomps.push_back(val);
- _paths.push_back(pair<vector<string>, vtw_type_e>(pcomps,
- def->getType(1)));
+ pcomps.push(val);
+ _paths.push_back(pair<Cpath, vtw_type_e>(pcomps, def->getType(1)));
// at leaf. stop recursion.
}
}
@@ -273,7 +278,7 @@ Cstore::VarRef::getValue(string& value, vtw_type_e& def_type)
}
bool
-Cstore::VarRef::getSetPath(vector<string>& path_comps)
+Cstore::VarRef::getSetPath(Cpath& path_comps)
{
/* XXX this function is currently unused and untested. see setVarRef()
* in Cstore for more information.
diff --git a/src/cstore/cstore-varref.hpp b/src/cstore/cstore-varref.hpp
index 3b842a9..acfe4d1 100644
--- a/src/cstore/cstore-varref.hpp
+++ b/src/cstore/cstore-varref.hpp
@@ -30,18 +30,18 @@ public:
~VarRef() {};
bool getValue(string& value, vtw_type_e& def_type);
- bool getSetPath(vector<string>& path_comps);
+ bool getSetPath(Cpath& path_comps);
private:
Cstore *_cstore;
bool _active;
bool _absolute;
string _at_string;
- vector<string> _orig_path_comps;
- vector<pair<vector<string>, vtw_type_e> > _paths;
+ Cpath _orig_path_comps;
+ vector<pair<Cpath, vtw_type_e> > _paths;
- void process_ref(const vector<string>& ref_comps,
- const vector<string>& cur_path_comps, vtw_type_e def_type);
+ void process_ref(const Cpath& ref_comps,
+ const Cpath& cur_path_comps, vtw_type_e def_type);
};
} // end namespace cstore
diff --git a/src/cstore/cstore.cpp b/src/cstore/cstore.cpp
index 91d82e3..70f1c55 100644
--- a/src/cstore/cstore.cpp
+++ b/src/cstore/cstore.cpp
@@ -37,7 +37,7 @@
#include <cnode/cnode-algorithm.hpp>
#include <cparse/cparse.hpp>
-using namespace cstore;
+namespace cstore { // begin namespace cstore
////// constants
//// node status
@@ -103,14 +103,14 @@ Cstore::Cstore(string& env)
Cstore *
Cstore::createCstore(bool use_edit_level)
{
- return (new UnionfsCstore(use_edit_level));
+ return (new unionfs::UnionfsCstore(use_edit_level));
}
// for "specific session" (see UnionfsCstore constructor for details)
Cstore *
Cstore::createCstore(const string& session_id, string& env)
{
- return (new UnionfsCstore(session_id, env));
+ return (new unionfs::UnionfsCstore(session_id, env));
}
@@ -120,10 +120,10 @@ Cstore::createCstore(const string& session_id, string& env)
* return true if valid. otherwise return false.
*/
bool
-Cstore::validateTmplPath(const vector<string>& path_comps, bool validate_vals)
+Cstore::validateTmplPath(const Cpath& path_comps, bool validate_vals)
{
// if we can get parsed tmpl, path is valid
- auto_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, validate_vals));
+ tr1::shared_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, validate_vals));
return (def.get() != 0);
}
@@ -131,8 +131,8 @@ Cstore::validateTmplPath(const vector<string>& path_comps, bool validate_vals)
* note: if last path component is "value" (i.e., def.is_value), parsed
* template is actually at "full path - 1". see get_parsed_tmpl() for details.
*/
-Ctemplate *
-Cstore::parseTmpl(const vector<string>& path_comps, bool validate_vals)
+tr1::shared_ptr<Ctemplate>
+Cstore::parseTmpl(const Cpath& path_comps, bool validate_vals)
{
return get_parsed_tmpl(path_comps, validate_vals);
}
@@ -142,7 +142,7 @@ Cstore::parseTmpl(const vector<string>& path_comps, bool validate_vals)
* return true if successful. otherwise return false.
*/
bool
-Cstore::getParsedTmpl(const vector<string>& path_comps,
+Cstore::getParsedTmpl(const Cpath& path_comps,
Cstore::MapT<string, string>& tmap, bool allow_val)
{
/* currently this function is used outside actual CLI operations, mainly
@@ -152,7 +152,7 @@ Cstore::getParsedTmpl(const vector<string>& path_comps,
*
* anyway, not validating values in the following call.
*/
- auto_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, false));
+ tr1::shared_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, false));
if (!def.get()) {
return false;
}
@@ -210,26 +210,25 @@ Cstore::getParsedTmpl(const vector<string>& path_comps,
* note: if specified path is at a "tag node", "node.tag" will be returned.
*/
void
-Cstore::tmplGetChildNodes(const vector<string>& path_comps,
+Cstore::tmplGetChildNodes(const Cpath& path_comps,
vector<string>& cnodes)
{
- SAVE_PATHS;
+ auto_ptr<SavePaths> save(create_save_paths());
append_tmpl_path(path_comps);
get_all_tmpl_child_node_names(cnodes);
sort_nodes(cnodes);
- RESTORE_PATHS;
}
/* delete specified "logical path" from "working config".
* return true if successful. otherwise return false.
*/
bool
-Cstore::deleteCfgPath(const vector<string>& path_comps)
+Cstore::deleteCfgPath(const Cpath& path_comps)
{
ASSERT_IN_SESSION;
string terr;
- auto_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, false, terr));
+ tr1::shared_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, false, terr));
if (!def.get()) {
output_user("%s\n", terr.c_str());
return false;
@@ -251,7 +250,7 @@ Cstore::deleteCfgPath(const vector<string>& path_comps)
*/
if (def->getDefault()) {
// case 1. construct path for value file.
- SAVE_PATHS;
+ auto_ptr<SavePaths> save(create_save_paths());
append_cfg_path(path_comps);
if (def->isValue()) {
// last comp is "value". need to go up 1 level.
@@ -263,13 +262,12 @@ Cstore::deleteCfgPath(const vector<string>& path_comps)
* also deactivated. note that unmark_deactivated() succeeds if it's
* not marked deactivated. also mark "changed".
*/
- bool ret = (write_value(def->getDefault()) && mark_display_default()
- && unmark_deactivated() && mark_changed_with_ancestors());
- if (!ret) {
+ if (!(write_value(def->getDefault()) && mark_display_default()
+ && unmark_deactivated() && mark_changed_with_ancestors())) {
output_user("Failed to set default value during delete\n");
+ return false;
}
- RESTORE_PATHS;
- return ret;
+ return true;
}
/* case 2.
@@ -287,7 +285,7 @@ Cstore::deleteCfgPath(const vector<string>& path_comps)
* => remove node
*/
bool ret = false;
- SAVE_PATHS;
+ auto_ptr<SavePaths> save(create_save_paths());
append_cfg_path(path_comps);
if (!def->isValue()) {
// sub-case (2)
@@ -311,7 +309,6 @@ Cstore::deleteCfgPath(const vector<string>& path_comps)
// mark changed
ret = mark_changed_with_ancestors();
}
- RESTORE_PATHS;
if (!ret) {
output_user("Failed to delete specified config path\n");
}
@@ -322,20 +319,19 @@ Cstore::deleteCfgPath(const vector<string>& path_comps)
* return true if valid. otherwise return false.
*/
bool
-Cstore::validateSetPath(const vector<string>& path_comps)
+Cstore::validateSetPath(const Cpath& path_comps)
{
ASSERT_IN_SESSION;
// if we can get parsed tmpl, path is valid
string terr;
- auto_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, true, terr));
+ tr1::shared_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, true, terr));
if (!def.get()) {
output_user("%s\n", terr.c_str());
return false;
}
- bool ret = true;
- SAVE_PATHS;
+ auto_ptr<SavePaths> save(create_save_paths());
if (!def->isValue()) {
if (!def->isTypeless()) {
/* disallow setting value node without value
@@ -344,7 +340,7 @@ Cstore::validateSetPath(const vector<string>& path_comps)
* (single-value, multi-value, and tag) must be set with value.
*/
output_user("The specified configuration node requires a value\n");
- ret = false;
+ return false;
} else {
/* typeless node
* note: XXX the following is present in the original logic, perhaps
@@ -355,24 +351,23 @@ Cstore::validateSetPath(const vector<string>& path_comps)
*/
append_cfg_path(path_comps);
append_tmpl_path(path_comps);
- if (!validate_val(def.get(), "")) {
- ret = false;
+ if (!validate_val(def, "")) {
+ return false;
}
}
}
- RESTORE_PATHS;
- return ret;
+ return true;
}
/* check if specified "logical path" is valid for "activate" operation
* return true if valid. otherwise return false.
*/
bool
-Cstore::validateActivatePath(const vector<string>& path_comps)
+Cstore::validateActivatePath(const Cpath& path_comps)
{
ASSERT_IN_SESSION;
- auto_ptr<Ctemplate> def(validate_act_deact(path_comps, "activate"));
+ tr1::shared_ptr<Ctemplate> def(validate_act_deact(path_comps, "activate"));
if (!def.get()) {
return false;
}
@@ -381,35 +376,35 @@ Cstore::validateActivatePath(const vector<string>& path_comps)
"deactivate\ncommand has been performed.\n");
return false;
}
- bool ret = true;
+
if (def->isTagValue() && def->getTagLimit() > 0) {
// we are activating a tag, and there is a limit on number of tags.
vector<string> cnodes;
- SAVE_PATHS;
+ auto_ptr<SavePaths> save(create_save_paths());
append_cfg_path(path_comps);
- string t = pop_cfg_path();
+ string t;
+ pop_cfg_path(t);
// get child nodes, excluding deactivated ones.
get_all_child_node_names(cnodes, false, false);
if (def->getTagLimit() <= cnodes.size()) {
// limit exceeded
output_user("Cannot activate \"%s\": number of values exceeds limit "
"(%d allowed)\n", t.c_str(), def->getTagLimit());
- ret = false;
+ return false;
}
- RESTORE_PATHS;
}
- return ret;
+ return true;
}
/* check if specified "logical path" is valid for "deactivate" operation
* return true if valid. otherwise return false.
*/
bool
-Cstore::validateDeactivatePath(const vector<string>& path_comps)
+Cstore::validateDeactivatePath(const Cpath& path_comps)
{
ASSERT_IN_SESSION;
- auto_ptr<Ctemplate> def(validate_act_deact(path_comps, "deactivate"));
+ tr1::shared_ptr<Ctemplate> def(validate_act_deact(path_comps, "deactivate"));
return (def.get() != 0);
}
@@ -419,12 +414,12 @@ Cstore::validateDeactivatePath(const vector<string>& path_comps)
* operation and return true.
*/
bool
-Cstore::getEditEnv(const vector<string>& path_comps, string& env)
+Cstore::getEditEnv(const Cpath& path_comps, string& env)
{
ASSERT_IN_SESSION;
string terr;
- auto_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, false, terr));
+ tr1::shared_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, false, terr));
if (!def.get()) {
output_user("%s\n", terr.c_str());
return false;
@@ -453,11 +448,10 @@ Cstore::getEditEnv(const vector<string>& path_comps, string& env)
return false;
}
}
- SAVE_PATHS;
+ auto_ptr<SavePaths> save(create_save_paths());
append_cfg_path(path_comps);
append_tmpl_path(path_comps);
get_edit_env(env);
- RESTORE_PATHS;
/* doing the save/restore above to be consistent with the rest of the API.
* however, after the caller evals the returned environment string, the
* levels in "this" will become out-of-sync with the environment. so
@@ -488,14 +482,14 @@ Cstore::getEditUpEnv(string& env)
}
string terr;
- vector<string> path_comps;
- auto_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, false, terr));
+ Cpath path_comps;
+ tr1::shared_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, false, terr));
if (!def.get()) {
// this should not happen since it's using existing levels
output_user("%s\n", terr.c_str());
return false;
}
- SAVE_PATHS;
+ auto_ptr<SavePaths> save(create_save_paths());
if (def->isTagValue()) {
// edit level is at "tag value". go up 1 extra level.
pop_cfg_path();
@@ -504,7 +498,6 @@ Cstore::getEditUpEnv(string& env)
pop_cfg_path();
pop_tmpl_path();
get_edit_env(env);
- RESTORE_PATHS;
// also see getEditEnv for comment on save/restore above
return true;
@@ -518,13 +511,12 @@ Cstore::getEditResetEnv(string& env)
{
ASSERT_IN_SESSION;
- SAVE_PATHS;
+ auto_ptr<SavePaths> save(create_save_paths());
while (!edit_level_at_root()) {
pop_cfg_path();
pop_tmpl_path();
}
get_edit_env(env);
- RESTORE_PATHS;
// also see getEditEnv for comment on save/restore above
return true;
@@ -537,15 +529,17 @@ Cstore::getEditResetEnv(string& env)
* first path element (which can be empty string).
*/
bool
-Cstore::getCompletionEnv(const vector<string>& comps, string& env)
+Cstore::getCompletionEnv(const Cpath& comps, string& env)
{
ASSERT_IN_SESSION;
- vector<string> pcomps = comps;
- string cmd = pcomps[0];
- string last_comp = pcomps.back();
- pcomps.erase(pcomps.begin());
- pcomps.pop_back();
+ string cmd = comps[0];
+ string last_comp = comps.back();
+ Cpath pcomps;
+ for (size_t i = 1; i < (comps.size() - 1); i++) {
+ pcomps.push(comps[i]);
+ }
+
bool exists_only = (cmd == "delete" || cmd == "show"
|| cmd == "comment" || cmd == "activate"
|| cmd == "deactivate");
@@ -553,290 +547,294 @@ Cstore::getCompletionEnv(const vector<string>& comps, string& env)
/* at this point, pcomps contains the command line arguments minus the
* "command" and the last one.
*/
- bool ret = false;
- SAVE_PATHS;
- do {
- bool is_typeless = true;
- bool is_leaf_value = false;
- bool is_value = false;
- auto_ptr<Ctemplate> def;
- if (pcomps.size() > 0) {
- def.reset(get_parsed_tmpl(pcomps, false));
- if (!def.get()) {
- // invalid path
- break;
- }
- if (exists_only && !cfg_path_exists(pcomps, false, true)) {
- // invalid path for the command (must exist)
- break;
- }
- append_cfg_path(pcomps);
- append_tmpl_path(pcomps);
- is_typeless = def->isTypeless();
- is_leaf_value = def->isLeafValue();
- is_value = def->isValue();
- } else {
- /* we are at root. default values simulate a typeless node so nop.
- * note that in this case def is "empty", so must ensure that it's
- * not used.
- */
+ auto_ptr<SavePaths> save(create_save_paths());
+ bool is_typeless = true;
+ bool is_leaf_value = false;
+ bool is_value = false;
+ tr1::shared_ptr<Ctemplate> def;
+ if (pcomps.size() > 0) {
+ def = get_parsed_tmpl(pcomps, false);
+ if (!def.get()) {
+ // invalid path
+ return false;
+ }
+ if (exists_only && !cfg_path_exists(pcomps, false, true)) {
+ // invalid path for the command (must exist)
+ return false;
}
+ append_cfg_path(pcomps);
+ append_tmpl_path(pcomps);
+ is_typeless = def->isTypeless();
+ is_leaf_value = def->isLeafValue();
+ is_value = def->isValue();
+ } else {
+ /* we are at root. default values simulate a typeless node so nop.
+ * note that in this case def is "empty", so must ensure that it's
+ * not used.
+ */
+ }
- /* at this point, cfg and tmpl paths are constructed up to the comp
- * before last_comp, and def is parsed.
+ /* at this point, cfg and tmpl paths are constructed up to the comp
+ * before last_comp, and def is parsed.
+ */
+ if (is_leaf_value) {
+ // invalid path (this means the comp before last_comp is a leaf value)
+ return false;
+ }
+
+ vector<string> comp_vals;
+ string comp_string;
+ string comp_help;
+ vector<pair<string, string> > help_pairs;
+ bool last_comp_val = true;
+ if (is_typeless || is_value) {
+ /* path so far is at a typeless node OR a tag value (tag already
+ * checked above):
+ * completions: from tmpl children.
+ * help:
+ * values: same as completions.
+ * text: "help" from child templates.
+ *
+ * note: for such completions, we filter non-existent nodes if
+ * necessary.
+ *
+ * also, the "root" node case above will reach this block, so
+ * must not use def in this block.
*/
- if (is_leaf_value) {
- // invalid path (this means the comp before last_comp is a leaf value)
- break;
+ vector<string> ufvec;
+ if (exists_only) {
+ // only return existing config nodes
+ get_all_child_node_names(ufvec, false, true);
+ } else {
+ // return all template children
+ get_all_tmpl_child_node_names(ufvec);
}
+ for (size_t i = 0; i < ufvec.size(); i++) {
+ if (last_comp == ""
+ || ufvec[i].compare(0, last_comp.length(), last_comp) == 0) {
+ comp_vals.push_back(ufvec[i]);
+ }
+ }
+ if (comp_vals.size() == 0) {
+ // no matches
+ return false;
+ }
+ sort(comp_vals.begin(), comp_vals.end());
- vector<string> comp_vals;
- string comp_string;
- string comp_help;
- vector<pair<string, string> > help_pairs;
- bool last_comp_val = true;
- if (is_typeless || is_value) {
- /* path so far is at a typeless node OR a tag value (tag already
- * checked above):
- * completions: from tmpl children.
- * help:
- * values: same as completions.
- * text: "help" from child templates.
- *
- * note: for such completions, we filter non-existent nodes if
- * necessary.
- *
- * also, the "root" node case above will reach this block, so
- * must not use def in this block.
- */
- vector<string> ufvec;
- if (exists_only) {
- // only return existing config nodes
- get_all_child_node_names(ufvec, false, true);
+ /* loop below calls get_parsed_tmpl(), which takes the whole path.
+ * so need to save current paths and reset them before (and restore them
+ * after).
+ */
+ auto_ptr<SavePaths> save1(create_save_paths());
+ reset_paths();
+ for (size_t i = 0; i < comp_vals.size(); i++) {
+ pair<string, string> hpair(comp_vals[i], "");
+ pcomps.push(comp_vals[i]);
+ tr1::shared_ptr<Ctemplate> cdef(get_parsed_tmpl(pcomps, false));
+ if (cdef.get() && cdef->getNodeHelp()) {
+ hpair.second = cdef->getNodeHelp();
} else {
- // return all template children
- get_all_tmpl_child_node_names(ufvec);
- }
- for (size_t i = 0; i < ufvec.size(); i++) {
- if (last_comp == ""
- || ufvec[i].compare(0, last_comp.length(), last_comp) == 0) {
- comp_vals.push_back(ufvec[i]);
- }
- }
- if (comp_vals.size() == 0) {
- // no matches
- break;
+ hpair.second = "<No help text available>";
}
- sort(comp_vals.begin(), comp_vals.end());
- for (size_t i = 0; i < comp_vals.size(); i++) {
- pair<string, string> hpair(comp_vals[i], "");
- push_tmpl_path(hpair.first);
- auto_ptr<Ctemplate> cdef(tmpl_parse());
- if (cdef.get() && cdef->getNodeHelp()) {
- hpair.second = cdef->getNodeHelp();
- } else {
- hpair.second = "<No help text available>";
- }
- help_pairs.push_back(hpair);
- pop_tmpl_path();
- }
- // last comp is not value
- last_comp_val = false;
+ help_pairs.push_back(hpair);
+ pcomps.pop();
+ }
+ // last comp is not value
+ last_comp_val = false;
+ } else {
+ /* path so far is at a "value node".
+ * note: follow the original implementation and don't filter
+ * non-existent values for such completions
+ *
+ * also, cannot be "root" node if we reach here, so def can be used.
+ */
+ // first, handle completions.
+ if (def->isTag()) {
+ // it's a "tag node". get completions from tag values.
+ get_all_child_node_names(comp_vals, false, true);
} else {
- /* path so far is at a "value node".
- * note: follow the original implementation and don't filter
- * non-existent values for such completions
- *
- * also, cannot be "root" node if we reach here, so def can be used.
+ // it's a "leaf value node". get completions from values.
+ read_value_vec(comp_vals, false);
+ }
+ /* more possible completions from this node's template:
+ * "allowed"
+ * "enumeration"
+ * "$VAR(@) in ..."
+ */
+ if (def->getEnumeration() || def->getAllowed()) {
+ /* do "enumeration" or "allowed".
+ * note: emulate original implementation and set up COMP_WORDS and
+ * COMP_CWORD environment variables. these are needed by some
+ * "allowed" scripts.
*/
- // first, handle completions.
- if (def->isTag()) {
- // it's a "tag node". get completions from tag values.
- get_all_child_node_names(comp_vals, false, true);
+ ostringstream cword_count;
+ cword_count << (comps.size() - 1);
+ string cmd_str = ("export " + C_ENV_SHELL_CWORD_COUNT + "="
+ + cword_count.str() + "; ");
+ cmd_str += ("export " + C_ENV_SHELL_CWORDS + "=(");
+ for (size_t i = 0; i < comps.size(); i++) {
+ cmd_str += " '";
+ cmd_str += comps[i];
+ cmd_str += "'";
+ }
+ cmd_str += "); ";
+ if (def->getEnumeration()) {
+ cmd_str += (C_ENUM_SCRIPT_DIR + "/" + def->getEnumeration());
} else {
- // it's a "leaf value node". get completions from values.
- read_value_vec(comp_vals, false);
+ string astr = def->getAllowed();
+ shell_escape_squotes(astr);
+ cmd_str += "_cstore_internal_allowed () { eval '";
+ cmd_str += astr;
+ cmd_str += "'; }; _cstore_internal_allowed";
}
- /* more possible completions from this node's template:
- * "allowed"
- * "enumeration"
- * "$VAR(@) in ..."
- */
- if (def->getEnumeration() || def->getAllowed()) {
- /* do "enumeration" or "allowed".
- * note: emulate original implementation and set up COMP_WORDS and
- * COMP_CWORD environment variables. these are needed by some
- * "allowed" scripts.
- */
- ostringstream cword_count;
- cword_count << (comps.size() - 1);
- string cmd_str = ("export " + C_ENV_SHELL_CWORD_COUNT + "="
- + cword_count.str() + "; ");
- cmd_str += ("export " + C_ENV_SHELL_CWORDS + "=(");
- for (size_t i = 0; i < comps.size(); i++) {
- cmd_str += (" '" + comps[i] + "'");
- }
- cmd_str += "); ";
- if (def->getEnumeration()) {
- cmd_str += (C_ENUM_SCRIPT_DIR + "/" + def->getEnumeration());
- } else {
- string astr = def->getAllowed();
- shell_escape_squotes(astr);
- cmd_str += "_cstore_internal_allowed () { eval '";
- cmd_str += astr;
- cmd_str += "'; }; _cstore_internal_allowed";
- }
- char *buf = (char *) malloc(MAX_CMD_OUTPUT_SIZE);
- int ret = get_shell_command_output(cmd_str.c_str(), buf,
- MAX_CMD_OUTPUT_SIZE);
- if (ret > 0) {
- // '<' and '>' need to be escaped
- char *ptr = buf;
- while (*ptr) {
- if (*ptr == '<' || *ptr == '>') {
- comp_string += "\\";
- }
- comp_string += *ptr;
- ptr++;
+ char *buf = (char *) malloc(MAX_CMD_OUTPUT_SIZE);
+ int ret = get_shell_command_output(cmd_str.c_str(), buf,
+ MAX_CMD_OUTPUT_SIZE);
+ if (ret > 0) {
+ // '<' and '>' need to be escaped
+ char *ptr = buf;
+ while (*ptr) {
+ if (*ptr == '<' || *ptr == '>') {
+ comp_string += "\\";
}
+ comp_string += *ptr;
+ ptr++;
}
- /* note that for "enumeration" and "allowed", comp_string is the
- * complete output of the command and it is to be evaled by the
- * shell into an array of values.
- */
- free(buf);
- } else if (def->getActions(syntax_act)->vtw_list_head) {
- // look for "self ref in values" from syntax
- const valstruct *vals = get_syntax_self_in_valstruct(
- def->getActions(syntax_act)->vtw_list_head);
- if (vals) {
- if (vals->cnt == 0 && vals->val) {
- comp_vals.push_back(vals->val);
- } else if (vals->cnt > 0) {
- for (int i = 0; i < vals->cnt; i++) {
- if (vals->vals[i]) {
- comp_vals.push_back(vals->vals[i]);
- }
+ }
+ /* note that for "enumeration" and "allowed", comp_string is the
+ * complete output of the command and it is to be evaled by the
+ * shell into an array of values.
+ */
+ free(buf);
+ } else if (def->getActions(syntax_act)->vtw_list_head) {
+ // look for "self ref in values" from syntax
+ const valstruct *vals = get_syntax_self_in_valstruct(
+ def->getActions(syntax_act)->vtw_list_head);
+ if (vals) {
+ if (vals->cnt == 0 && vals->val) {
+ comp_vals.push_back(vals->val);
+ } else if (vals->cnt > 0) {
+ for (int i = 0; i < vals->cnt; i++) {
+ if (vals->vals[i]) {
+ comp_vals.push_back(vals->vals[i]);
}
}
}
}
+ }
- // now handle help.
- if (def->getCompHelp()) {
- // "comp_help" exists.
- comp_help = def->getCompHelp();
- shell_escape_squotes(comp_help);
- }
- if (def->getValHelp()) {
- // has val_help. first separate individual lines.
- size_t start = 0, i = 0;
- vector<string> vhelps;
- for (i = 0; (def->getValHelp())[i]; i++) {
- if ((def->getValHelp())[i] == '\n') {
- vhelps.push_back(string(&((def->getValHelp())[start]), i - start));
- start = i + 1;
- }
- }
- if (start < i) {
+ // now handle help.
+ if (def->getCompHelp()) {
+ // "comp_help" exists.
+ comp_help = def->getCompHelp();
+ shell_escape_squotes(comp_help);
+ }
+ if (def->getValHelp()) {
+ // has val_help. first separate individual lines.
+ size_t start = 0, i = 0;
+ vector<string> vhelps;
+ for (i = 0; (def->getValHelp())[i]; i++) {
+ if ((def->getValHelp())[i] == '\n') {
vhelps.push_back(string(&((def->getValHelp())[start]), i - start));
+ start = i + 1;
}
+ }
+ if (start < i) {
+ vhelps.push_back(string(&((def->getValHelp())[start]), i - start));
+ }
- // process each line
- for (i = 0; i < vhelps.size(); i++) {
- size_t sc;
- if ((sc = vhelps[i].find(';')) == vhelps[i].npos) {
- // no ';'
- if (i == 0 && !def->isTypeless(1)) {
- // first val_help. pair with "type".
- help_pairs.push_back(pair<string, string>(
- def->getTypeName(1), vhelps[i]));
- }
- if (i == 1 && !def->isTypeless(2)) {
- // second val_help. pair with second "type".
- help_pairs.push_back(pair<string, string>(
- def->getTypeName(2), vhelps[i]));
- }
- } else {
- // ';' at index sc
+ // process each line
+ for (i = 0; i < vhelps.size(); i++) {
+ size_t sc;
+ if ((sc = vhelps[i].find(';')) == vhelps[i].npos) {
+ // no ';'
+ if (i == 0 && !def->isTypeless(1)) {
+ // first val_help. pair with "type".
help_pairs.push_back(pair<string, string>(
- vhelps[i].substr(0, sc),
- vhelps[i].substr(sc + 1)));
+ def->getTypeName(1), vhelps[i]));
}
+ if (i == 1 && !def->isTypeless(2)) {
+ // second val_help. pair with second "type".
+ help_pairs.push_back(pair<string, string>(
+ def->getTypeName(2), vhelps[i]));
+ }
+ } else {
+ // ';' at index sc
+ help_pairs.push_back(pair<string, string>(
+ vhelps[i].substr(0, sc),
+ vhelps[i].substr(sc + 1)));
}
- } else if (!def->isTypeless(1) && def->getNodeHelp()) {
- // simple case. just use "type" and "help"
- help_pairs.push_back(pair<string, string>(def->getTypeName(1),
- def->getNodeHelp()));
}
+ } else if (!def->isTypeless(1) && def->getNodeHelp()) {
+ // simple case. just use "type" and "help"
+ help_pairs.push_back(pair<string, string>(def->getTypeName(1),
+ def->getNodeHelp()));
}
+ }
- /* from this point on cannot use def (since the "root" node case
- * can reach here).
- */
+ /* from this point on cannot use def (since the "root" node case
+ * can reach here).
+ */
- // this var is the array of possible completions
- env = (C_ENV_SHAPI_COMP_VALS + "=(");
- for (size_t i = 0; i < comp_vals.size(); i++) {
- shell_escape_squotes(comp_vals[i]);
- env += ("'" + comp_vals[i] + "' ");
+ // this var is the array of possible completions
+ env = (C_ENV_SHAPI_COMP_VALS + "=(");
+ for (size_t i = 0; i < comp_vals.size(); i++) {
+ shell_escape_squotes(comp_vals[i]);
+ env += ("'" + comp_vals[i] + "' ");
+ }
+ /* as mentioned above, comp_string is the complete command output.
+ * let the shell eval it into the array since we don't want to
+ * re-implement the shell interpretation here.
+ *
+ * note that as a result, we will not be doing the filtering here.
+ * instead, the completion script will do the filtering on
+ * the resulting comp_values array. should be straightforward since
+ * there's no "existence filtering", only "prefix filtering".
+ */
+ env += (comp_string + "); ");
+
+ /* this var indicates whether the last comp is "value"
+ * follow original implementation: if last comp is value, completion
+ * script needs to do the following.
+ * use comp_help if exists
+ * prefix filter comp_values
+ * replace any <*> in comp_values with ""
+ * convert help items to data representation
+ */
+ env += (C_ENV_SHAPI_LCOMP_VAL + "=");
+ env += (last_comp_val ? "true; " : "false; ");
+
+ // this var is the "comp_help" string
+ env += (C_ENV_SHAPI_COMP_HELP + "='" + comp_help + "'; ");
+
+ // this var is the array of "help items", i.e., type names, etc.
+ string hitems = (C_ENV_SHAPI_HELP_ITEMS + "=(");
+ // this var is the array of "help strings" corresponding to the items
+ string hstrs = (C_ENV_SHAPI_HELP_STRS + "=(");
+ for (size_t i = 0; i < help_pairs.size(); i++) {
+ string hi = help_pairs[i].first;
+ string hs = help_pairs[i].second;
+ shell_escape_squotes(hi);
+ shell_escape_squotes(hs);
+ // get rid of leading/trailing "space" chars in help string
+ while (hi.size() > 0 && isspace(hi[0])) {
+ hi.erase(0, 1);
}
- /* as mentioned above, comp_string is the complete command output.
- * let the shell eval it into the array since we don't want to
- * re-implement the shell interpretation here.
- *
- * note that as a result, we will not be doing the filtering here.
- * instead, the completion script will do the filtering on
- * the resulting comp_values array. should be straightforward since
- * there's no "existence filtering", only "prefix filtering".
- */
- env += (comp_string + "); ");
-
- /* this var indicates whether the last comp is "value"
- * follow original implementation: if last comp is value, completion
- * script needs to do the following.
- * use comp_help if exists
- * prefix filter comp_values
- * replace any <*> in comp_values with ""
- * convert help items to data representation
- */
- env += (C_ENV_SHAPI_LCOMP_VAL + "=");
- env += (last_comp_val ? "true; " : "false; ");
-
- // this var is the "comp_help" string
- env += (C_ENV_SHAPI_COMP_HELP + "='" + comp_help + "'; ");
-
- // this var is the array of "help items", i.e., type names, etc.
- string hitems = (C_ENV_SHAPI_HELP_ITEMS + "=(");
- // this var is the array of "help strings" corresponding to the items
- string hstrs = (C_ENV_SHAPI_HELP_STRS + "=(");
- for (size_t i = 0; i < help_pairs.size(); i++) {
- string hi = help_pairs[i].first;
- string hs = help_pairs[i].second;
- shell_escape_squotes(hi);
- shell_escape_squotes(hs);
- // get rid of leading/trailing "space" chars in help string
- while (hi.size() > 0 && isspace(hi[0])) {
- hi.erase(0, 1);
- }
- while (hs.size() > 0 && isspace(hs[0])) {
- hs.erase(0, 1);
- }
- while (hi.size() > 0 && isspace(hi[hi.size() - 1])) {
- hi.erase(hi.size() - 1);
- }
- while (hs.size() > 0 && isspace(hs[hs.size() - 1])) {
- hs.erase(hs.size() - 1);
- }
- hitems += ("'" + hi + "' ");
- hstrs += ("'" + hs + "' ");
+ while (hs.size() > 0 && isspace(hs[0])) {
+ hs.erase(0, 1);
}
- env += (hitems + "); " + hstrs + "); ");
- ret = true;
- } while(0);
- RESTORE_PATHS;
- return ret;
+ while (hi.size() > 0 && isspace(hi[hi.size() - 1])) {
+ hi.erase(hi.size() - 1);
+ }
+ while (hs.size() > 0 && isspace(hs[hs.size() - 1])) {
+ hs.erase(hs.size() - 1);
+ }
+ hitems += ("'" + hi + "' ");
+ hstrs += ("'" + hs + "' ");
+ }
+ env += (hitems + "); " + hstrs + "); ");
+ return true;
}
/* set specified "logical path" in "working config".
@@ -844,7 +842,7 @@ Cstore::getCompletionEnv(const vector<string>& comps, string& env)
* note: assume specified path is valid (i.e., validateSetPath()).
*/
bool
-Cstore::setCfgPath(const vector<string>& path_comps)
+Cstore::setCfgPath(const Cpath& path_comps)
{
ASSERT_IN_SESSION;
@@ -855,7 +853,7 @@ Cstore::setCfgPath(const vector<string>& path_comps)
* return true if valid. otherwise return false.
*/
bool
-Cstore::validateRenameArgs(const vector<string>& args)
+Cstore::validateRenameArgs(const Cpath& args)
{
ASSERT_IN_SESSION;
@@ -866,7 +864,7 @@ Cstore::validateRenameArgs(const vector<string>& args)
* return true if valid. otherwise return false.
*/
bool
-Cstore::validateCopyArgs(const vector<string>& args)
+Cstore::validateCopyArgs(const Cpath& args)
{
ASSERT_IN_SESSION;
@@ -877,22 +875,20 @@ Cstore::validateCopyArgs(const vector<string>& args)
* return true if valid. otherwise return false.
*/
bool
-Cstore::validateMoveArgs(const vector<string>& args)
+Cstore::validateMoveArgs(const Cpath& args)
{
ASSERT_IN_SESSION;
- vector<string> epath;
- vector<string> nargs;
+ Cpath epath;
+ Cpath nargs;
if (!conv_move_args_for_rename(args, epath, nargs)) {
output_user("Invalid move command\n");
return false;
}
- SAVE_PATHS;
+ auto_ptr<SavePaths> save(create_save_paths());
append_cfg_path(epath);
append_tmpl_path(epath);
- bool ret = validate_rename_copy(nargs, "move");
- RESTORE_PATHS;
- return ret;
+ return validate_rename_copy(nargs, "move");
}
/* perform rename in "working config" according to specified args.
@@ -900,13 +896,13 @@ Cstore::validateMoveArgs(const vector<string>& args)
* note: assume args are already validated (i.e., validateRenameArgs()).
*/
bool
-Cstore::renameCfgPath(const vector<string>& args)
+Cstore::renameCfgPath(const Cpath& args)
{
ASSERT_IN_SESSION;
- string otagnode = args[0];
- string otagval = args[1];
- string ntagval = args[4];
+ const char *otagnode = args[0];
+ const char *otagval = args[1];
+ const char *ntagval = args[4];
push_cfg_path(otagnode);
/* also mark changed. note that it's marking the "tag node" but not the
* "tag values" since one is being "deleted" and the other is being
@@ -923,13 +919,13 @@ Cstore::renameCfgPath(const vector<string>& args)
* note: assume args are already validated (i.e., validateCopyArgs()).
*/
bool
-Cstore::copyCfgPath(const vector<string>& args)
+Cstore::copyCfgPath(const Cpath& args)
{
ASSERT_IN_SESSION;
- string otagnode = args[0];
- string otagval = args[1];
- string ntagval = args[4];
+ const char *otagnode = args[0];
+ const char *otagval = args[1];
+ const char *ntagval = args[4];
push_cfg_path(otagnode);
/* also mark changed. note that it's marking the "tag node" but not the
* new "tag value" since it is being "added" anyway.
@@ -944,7 +940,7 @@ Cstore::copyCfgPath(const vector<string>& args)
* return true if valid. otherwise return false.
*/
bool
-Cstore::commentCfgPath(const vector<string>& args)
+Cstore::commentCfgPath(const Cpath& args)
{
ASSERT_IN_SESSION;
@@ -952,13 +948,13 @@ Cstore::commentCfgPath(const vector<string>& args)
* follow the original implementation: the last arg is the comment, and
* everything else is part of the path.
*/
- vector<string> path_comps(args);
- string comment = args.back();
- path_comps.pop_back();
+ Cpath path_comps(args);
+ string comment;
+ path_comps.pop(comment);
// check the path
string terr;
- auto_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, false, terr));
+ tr1::shared_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, false, terr));
if (!def.get()) {
output_user("%s\n", terr.c_str());
return false;
@@ -994,22 +990,23 @@ Cstore::commentCfgPath(const vector<string>& args)
return false;
}
- SAVE_PATHS;
- append_cfg_path(path_comps);
- bool ret;
- if (comment == "") {
- // follow original impl: empty comment => remove it
- ret = remove_comment();
- if (!ret) {
- output_user("Failed to remove comment for specified config node\n");
- }
- } else {
- ret = set_comment(comment);
- if (!ret) {
- output_user("Failed to add comment for specified config node\n");
+ bool ret = false;
+ {
+ auto_ptr<SavePaths> save(create_save_paths());
+ append_cfg_path(path_comps);
+ if (comment == "") {
+ // follow original impl: empty comment => remove it
+ ret = remove_comment();
+ if (!ret) {
+ output_user("Failed to remove comment for specified config node\n");
+ }
+ } else {
+ ret = set_comment(comment);
+ if (!ret) {
+ output_user("Failed to add comment for specified config node\n");
+ }
}
}
- RESTORE_PATHS;
if (ret) {
// mark the root as changed for "comment"
ret = mark_changed_with_ancestors();
@@ -1043,22 +1040,20 @@ Cstore::discardChanges()
* note: assume args are already validated (i.e., validateMoveArgs()).
*/
bool
-Cstore::moveCfgPath(const vector<string>& args)
+Cstore::moveCfgPath(const Cpath& args)
{
ASSERT_IN_SESSION;
- vector<string> epath;
- vector<string> nargs;
+ Cpath epath;
+ Cpath nargs;
if (!conv_move_args_for_rename(args, epath, nargs)) {
output_user("Invalid move command\n");
return false;
}
- SAVE_PATHS;
+ auto_ptr<SavePaths> save(create_save_paths());
append_cfg_path(epath);
append_tmpl_path(epath);
- bool ret = renameCfgPath(nargs);
- RESTORE_PATHS;
- return ret;
+ return renameCfgPath(nargs);
}
/* check if specified "logical path" exists in working config (i.e., the union)
@@ -1066,7 +1061,7 @@ Cstore::moveCfgPath(const vector<string>& args)
* return true if it exists. otherwise return false.
*/
bool
-Cstore::cfgPathExists(const vector<string>& path_comps, bool active_cfg)
+Cstore::cfgPathExists(const Cpath& path_comps, bool active_cfg)
{
if (!active_cfg) {
ASSERT_IN_SESSION;
@@ -1077,7 +1072,7 @@ Cstore::cfgPathExists(const vector<string>& path_comps, bool active_cfg)
// same as above but "deactivate-aware"
bool
-Cstore::cfgPathExistsDA(const vector<string>& path_comps, bool active_cfg,
+Cstore::cfgPathExistsDA(const Cpath& path_comps, bool active_cfg,
bool include_deactivated)
{
if (!active_cfg) {
@@ -1090,7 +1085,7 @@ Cstore::cfgPathExistsDA(const vector<string>& path_comps, bool active_cfg,
/* check if specified "logical path" has been deleted in working config.
*/
bool
-Cstore::cfgPathDeleted(const vector<string>& path_comps)
+Cstore::cfgPathDeleted(const Cpath& path_comps)
{
ASSERT_IN_SESSION;
@@ -1102,7 +1097,7 @@ Cstore::cfgPathDeleted(const vector<string>& path_comps)
/* check if specified "logical path" has been added in working config.
*/
bool
-Cstore::cfgPathAdded(const vector<string>& path_comps)
+Cstore::cfgPathAdded(const Cpath& path_comps)
{
ASSERT_IN_SESSION;
@@ -1130,25 +1125,23 @@ Cstore::cfgPathAdded(const vector<string>& path_comps)
* (3) cfg_node_changed()
*/
bool
-Cstore::cfgPathChanged(const vector<string>& path_comps)
+Cstore::cfgPathChanged(const Cpath& path_comps)
{
ASSERT_IN_SESSION;
if (cfgPathDeleted(path_comps) || cfgPathAdded(path_comps)) {
return true;
}
- SAVE_PATHS;
+ auto_ptr<SavePaths> save(create_save_paths());
append_cfg_path(path_comps);
- bool ret = cfg_node_changed();
- RESTORE_PATHS;
- return ret;
+ return cfg_node_changed();
}
/* get names of "deleted" child nodes of specified path during commit
* operation. names are returned in cnodes.
*/
void
-Cstore::cfgPathGetDeletedChildNodes(const vector<string>& path_comps,
+Cstore::cfgPathGetDeletedChildNodes(const Cpath& path_comps,
vector<string>& cnodes)
{
ASSERT_IN_SESSION;
@@ -1158,7 +1151,7 @@ Cstore::cfgPathGetDeletedChildNodes(const vector<string>& path_comps,
// same as above but "deactivate-aware"
void
-Cstore::cfgPathGetDeletedChildNodesDA(const vector<string>& path_comps,
+Cstore::cfgPathGetDeletedChildNodesDA(const Cpath& path_comps,
vector<string>& cnodes,
bool include_deactivated)
{
@@ -1189,8 +1182,7 @@ Cstore::cfgPathGetDeletedChildNodesDA(const vector<string>& path_comps,
* status is purely based on the presence/absence of a value.
*/
void
-Cstore::cfgPathGetDeletedValues(const vector<string>& path_comps,
- vector<string>& dvals)
+Cstore::cfgPathGetDeletedValues(const Cpath& path_comps, vector<string>& dvals)
{
ASSERT_IN_SESSION;
@@ -1199,7 +1191,7 @@ Cstore::cfgPathGetDeletedValues(const vector<string>& path_comps,
// same as above but DA
void
-Cstore::cfgPathGetDeletedValuesDA(const vector<string>& path_comps,
+Cstore::cfgPathGetDeletedValuesDA(const Cpath& path_comps,
vector<string>& dvals,
bool include_deactivated)
{
@@ -1229,15 +1221,15 @@ Cstore::cfgPathGetDeletedValuesDA(const vector<string>& path_comps,
* "marked deactivated".
*/
bool
-Cstore::cfgPathDeactivated(const vector<string>& path_comps, bool active_cfg)
+Cstore::cfgPathDeactivated(const Cpath& path_comps, bool active_cfg)
{
if (!active_cfg) {
ASSERT_IN_SESSION;
}
- vector<string> ppath;
+ Cpath ppath;
for (size_t i = 0; i < path_comps.size(); i++) {
- ppath.push_back(path_comps[i]);
+ ppath.push(path_comps[i]);
if (cfgPathMarkedDeactivated(ppath, active_cfg)) {
// an ancestor or itself is marked deactivated
return true;
@@ -1252,26 +1244,23 @@ Cstore::cfgPathDeactivated(const vector<string>& path_comps, bool active_cfg)
* performed on the node.
*/
bool
-Cstore::cfgPathMarkedDeactivated(const vector<string>& path_comps,
- bool active_cfg)
+Cstore::cfgPathMarkedDeactivated(const Cpath& path_comps, bool active_cfg)
{
if (!active_cfg) {
ASSERT_IN_SESSION;
}
- SAVE_PATHS;
+ auto_ptr<SavePaths> save(create_save_paths());
append_cfg_path(path_comps);
- bool ret = marked_deactivated(active_cfg);
- RESTORE_PATHS;
- return ret;
+ return marked_deactivated(active_cfg);
}
/* get names of child nodes of specified path in working config or active
* config. names are returned in cnodes.
*/
void
-Cstore::cfgPathGetChildNodes(const vector<string>& path_comps,
- vector<string>& cnodes, bool active_cfg)
+Cstore::cfgPathGetChildNodes(const Cpath& path_comps, vector<string>& cnodes,
+ bool active_cfg)
{
if (!active_cfg) {
ASSERT_IN_SESSION;
@@ -1282,9 +1271,8 @@ Cstore::cfgPathGetChildNodes(const vector<string>& path_comps,
// same as above but "deactivate-aware"
void
-Cstore::cfgPathGetChildNodesDA(const vector<string>& path_comps,
- vector<string>& cnodes, bool active_cfg,
- bool include_deactivated)
+Cstore::cfgPathGetChildNodesDA(const Cpath& path_comps, vector<string>& cnodes,
+ bool active_cfg, bool include_deactivated)
{
if (!active_cfg) {
ASSERT_IN_SESSION;
@@ -1296,10 +1284,11 @@ Cstore::cfgPathGetChildNodesDA(const vector<string>& path_comps,
*/
return;
}
- SAVE_PATHS;
- append_cfg_path(path_comps);
- get_all_child_node_names(cnodes, active_cfg, include_deactivated);
- RESTORE_PATHS;
+ {
+ auto_ptr<SavePaths> save(create_save_paths());
+ append_cfg_path(path_comps);
+ get_all_child_node_names(cnodes, active_cfg, include_deactivated);
+ }
sort_nodes(cnodes);
}
@@ -1310,7 +1299,7 @@ Cstore::cfgPathGetChildNodesDA(const vector<string>& path_comps,
* otherwise return true.
*/
bool
-Cstore::cfgPathGetValue(const vector<string>& path_comps, string& value,
+Cstore::cfgPathGetValue(const Cpath& path_comps, string& value,
bool active_cfg)
{
if (!active_cfg) {
@@ -1322,14 +1311,14 @@ Cstore::cfgPathGetValue(const vector<string>& path_comps, string& value,
// same as above but "deactivate-aware"
bool
-Cstore::cfgPathGetValueDA(const vector<string>& path_comps, string& value,
+Cstore::cfgPathGetValueDA(const Cpath& path_comps, string& value,
bool active_cfg, bool include_deactivated)
{
if (!active_cfg) {
ASSERT_IN_SESSION;
}
- auto_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, false));
+ tr1::shared_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, false));
if (!def.get()) {
// invalid node
return false;
@@ -1349,18 +1338,16 @@ Cstore::cfgPathGetValueDA(const vector<string>& path_comps, string& value,
return false;
}
vector<string> vvec;
- SAVE_PATHS;
+ auto_ptr<SavePaths> save(create_save_paths());
append_cfg_path(path_comps);
- bool ret = false;
if (read_value_vec(vvec, active_cfg)) {
if (vvec.size() >= 1) {
// if for some reason we got multiple values, just take the first one.
value = vvec[0];
- ret = true;
+ return true;
}
}
- RESTORE_PATHS;
- return ret;
+ return false;
}
/* get values of specified multi-value node.
@@ -1370,8 +1357,8 @@ Cstore::cfgPathGetValueDA(const vector<string>& path_comps, string& value,
* otherwise return true.
*/
bool
-Cstore::cfgPathGetValues(const vector<string>& path_comps,
- vector<string>& values, bool active_cfg)
+Cstore::cfgPathGetValues(const Cpath& path_comps, vector<string>& values,
+ bool active_cfg)
{
if (!active_cfg) {
ASSERT_IN_SESSION;
@@ -1382,15 +1369,14 @@ Cstore::cfgPathGetValues(const vector<string>& path_comps,
// same as above but "deactivate-aware"
bool
-Cstore::cfgPathGetValuesDA(const vector<string>& path_comps,
- vector<string>& values, bool active_cfg,
- bool include_deactivated)
+Cstore::cfgPathGetValuesDA(const Cpath& path_comps, vector<string>& values,
+ bool active_cfg, bool include_deactivated)
{
if (!active_cfg) {
ASSERT_IN_SESSION;
}
- auto_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, false));
+ tr1::shared_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, false));
if (!def.get()) {
// invalid node
return false;
@@ -1409,11 +1395,9 @@ Cstore::cfgPathGetValuesDA(const vector<string>& path_comps,
// specified node doesn't exist
return false;
}
- SAVE_PATHS;
+ auto_ptr<SavePaths> save(create_save_paths());
append_cfg_path(path_comps);
- bool ret = read_value_vec(values, active_cfg);
- RESTORE_PATHS;
- return ret;
+ return read_value_vec(values, active_cfg);
}
/* get comment of specified node.
@@ -1423,18 +1407,16 @@ Cstore::cfgPathGetValuesDA(const vector<string>& path_comps,
* otherwise return true.
*/
bool
-Cstore::cfgPathGetComment(const vector<string>& path_comps, string& comment,
+Cstore::cfgPathGetComment(const Cpath& path_comps, string& comment,
bool active_cfg)
{
if (!active_cfg) {
ASSERT_IN_SESSION;
}
- SAVE_PATHS;
+ auto_ptr<SavePaths> save(create_save_paths());
append_cfg_path(path_comps);
- bool ret = get_comment(comment, active_cfg);
- RESTORE_PATHS;
- return ret;
+ return get_comment(comment, active_cfg);
}
/* return whether specified path is "default". if a node is "default", it
@@ -1442,17 +1424,15 @@ Cstore::cfgPathGetComment(const vector<string>& path_comps, string& comment,
* active_cfg: whether to observe active config.
*/
bool
-Cstore::cfgPathDefault(const vector<string>& path_comps, bool active_cfg)
+Cstore::cfgPathDefault(const Cpath& path_comps, bool active_cfg)
{
if (!active_cfg) {
ASSERT_IN_SESSION;
}
- SAVE_PATHS;
+ auto_ptr<SavePaths> save(create_save_paths());
append_cfg_path(path_comps);
- bool ret = marked_display_default(active_cfg);
- RESTORE_PATHS;
- return ret;
+ return marked_display_default(active_cfg);
}
/* the following functions are observers of the "effective" config.
@@ -1534,9 +1514,9 @@ Cstore::cfgPathDefault(const vector<string>& path_comps, bool active_cfg)
// return whether specified path is "effective".
bool
-Cstore::cfgPathEffective(const vector<string>& path_comps)
+Cstore::cfgPathEffective(const Cpath& path_comps)
{
- auto_ptr<Ctemplate> def(parseTmpl(path_comps, false));
+ tr1::shared_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, false));
if (!def.get()) {
// invalid path
return false;
@@ -1553,19 +1533,17 @@ Cstore::cfgPathEffective(const vector<string>& path_comps)
// case (1)
return true;
}
- bool ret = false;
- SAVE_PATHS;
+
+ auto_ptr<SavePaths> save(create_save_paths());
append_cfg_path(path_comps);
if (!in_active && in_work) {
// check if case (2)
- ret = marked_committed(def.get(), true);
+ return marked_committed(def, true);
} else if (in_active && !in_work) {
// check if case (3)
- ret = !marked_committed(def.get(), false);
+ return !marked_committed(def, false);
}
- RESTORE_PATHS;
-
- return ret;
+ return false;
}
/* get names of "effective" child nodes of specified path during commit
@@ -1573,7 +1551,7 @@ Cstore::cfgPathEffective(const vector<string>& path_comps)
* names are returned in cnodes.
*/
void
-Cstore::cfgPathGetEffectiveChildNodes(const vector<string>& path_comps,
+Cstore::cfgPathGetEffectiveChildNodes(const Cpath& path_comps,
vector<string>& cnodes)
{
if (!inSession()) {
@@ -1596,15 +1574,15 @@ Cstore::cfgPathGetEffectiveChildNodes(const vector<string>& path_comps,
}
// get only the effective ones from the union
- vector<string> ppath = path_comps;
+ Cpath ppath(path_comps);
MapT<string, bool>::iterator it = cmap.begin();
for (; it != cmap.end(); ++it) {
string c = (*it).first;
- ppath.push_back(c);
+ ppath.push(c);
if (cfgPathEffective(ppath)) {
cnodes.push_back(c);
}
- ppath.pop_back();
+ ppath.pop();
}
sort_nodes(cnodes);
}
@@ -1614,15 +1592,14 @@ Cstore::cfgPathGetEffectiveChildNodes(const vector<string>& path_comps,
* return true if successful. otherwise return false.
*/
bool
-Cstore::cfgPathGetEffectiveValue(const vector<string>& path_comps,
- string& value)
+Cstore::cfgPathGetEffectiveValue(const Cpath& path_comps, string& value)
{
if (!inSession()) {
// not in a config session. use active config only.
return cfgPathGetValue(path_comps, value, true);
}
- vector<string> ppath = path_comps;
+ Cpath ppath(path_comps);
string oval, nval;
bool oret = cfgPathGetValue(path_comps, oval, true);
bool nret = cfgPathGetValue(path_comps, nval, false);
@@ -1630,7 +1607,7 @@ Cstore::cfgPathGetEffectiveValue(const vector<string>& path_comps,
// all 4 combinations of oret and nret are covered below
if (nret) {
// got new value
- ppath.push_back(nval);
+ ppath.push(nval);
if (cfgPathEffective(ppath)) {
// nval already effective
value = nval;
@@ -1644,7 +1621,7 @@ Cstore::cfgPathGetEffectiveValue(const vector<string>& path_comps,
}
} else if (oret) {
// got oval only
- ppath.push_back(oval);
+ ppath.push(oval);
if (cfgPathEffective(ppath)) {
// oval still effective
value = oval;
@@ -1659,7 +1636,7 @@ Cstore::cfgPathGetEffectiveValue(const vector<string>& path_comps,
* return true if successful. otherwise return false.
*/
bool
-Cstore::cfgPathGetEffectiveValues(const vector<string>& path_comps,
+Cstore::cfgPathGetEffectiveValues(const Cpath& path_comps,
vector<string>& values)
{
if (!inSession()) {
@@ -1682,15 +1659,15 @@ Cstore::cfgPathGetEffectiveValues(const vector<string>& path_comps,
}
// get only the effective ones from the union
- vector<string> ppath = path_comps;
+ Cpath ppath(path_comps);
MapT<string, bool>::iterator it = vmap.begin();
for (; it != vmap.end(); ++it) {
string c = (*it).first;
- ppath.push_back(c);
+ ppath.push(c);
if (cfgPathEffective(ppath)) {
values.push_back(c);
}
- ppath.pop_back();
+ ppath.pop();
}
return (values.size() > 0);
}
@@ -1704,20 +1681,18 @@ Cstore::cfgPathGetEffectiveValues(const vector<string>& path_comps,
* otherwise return NULL.
*/
char *
-Cstore::getVarRef(const string& ref_str, vtw_type_e& type, bool from_active)
+Cstore::getVarRef(const char *ref_str, vtw_type_e& type, bool from_active)
{
- char *ret = NULL;
- SAVE_PATHS;
+ auto_ptr<SavePaths> save(create_save_paths());
VarRef vref(this, ref_str, from_active);
string val;
vtw_type_e t;
if (vref.getValue(val, t)) {
type = t;
// follow original implementation. caller is supposed to free this.
- ret = strdup(val.c_str());
+ return strdup(val.c_str());
}
- RESTORE_PATHS;
- return ret;
+ return NULL;
}
/* set the node corresponding to specified variable ref string to specified
@@ -1729,7 +1704,7 @@ Cstore::getVarRef(const string& ref_str, vtw_type_e& type, bool from_active)
* return true if successful. otherwise return false.
*/
bool
-Cstore::setVarRef(const string& ref_str, const string& value, bool to_active)
+Cstore::setVarRef(const char *ref_str, const char *value, bool to_active)
{
/* XXX functions in cli_new only performs "set var ref" operations (e.g.,
* '$VAR(@) = ""', which sets current node's value to empty string)
@@ -1744,23 +1719,21 @@ Cstore::setVarRef(const string& ref_str, const string& value, bool to_active)
* from high-level functions). as a result, this function is unused
* and untested at the moment. must revisit when converting commit.
*/
- SAVE_PATHS;
+ auto_ptr<SavePaths> save(create_save_paths());
VarRef vref(this, ref_str, to_active);
- vector<string> pcomps;
- bool ret = false;
+ Cpath pcomps;
if (vref.getSetPath(pcomps)) {
reset_paths();
- auto_ptr<Ctemplate> def(get_parsed_tmpl(pcomps, false));
+ tr1::shared_ptr<Ctemplate> def(get_parsed_tmpl(pcomps, false));
if (def.get() && def->isSingleLeafNode()) {
// currently only support single-value node
append_cfg_path(pcomps);
if (write_value(value, to_active)) {
- ret = true;
+ return true;
}
}
}
- RESTORE_PATHS;
- return ret;
+ return false;
}
/* perform deactivate operation on a node, i.e., make the node
@@ -1770,7 +1743,7 @@ Cstore::setVarRef(const string& ref_str, const string& value, bool to_active)
* that had been marked deactivated are unmarked.
*/
bool
-Cstore::markCfgPathDeactivated(const vector<string>& path_comps)
+Cstore::markCfgPathDeactivated(const Cpath& path_comps)
{
ASSERT_IN_SESSION;
@@ -1780,13 +1753,11 @@ Cstore::markCfgPathDeactivated(const vector<string>& path_comps)
return true;
}
- SAVE_PATHS;
+ auto_ptr<SavePaths> save(create_save_paths());
append_cfg_path(path_comps);
// note: also mark changed
- bool ret = (mark_deactivated() && unmark_deactivated_descendants()
- && mark_changed_with_ancestors());
- RESTORE_PATHS;
- return ret;
+ return (mark_deactivated() && unmark_deactivated_descendants()
+ && mark_changed_with_ancestors());
}
/* perform activate operation on a node, i.e., make the node no longer
@@ -1794,16 +1765,14 @@ Cstore::markCfgPathDeactivated(const vector<string>& path_comps)
* note: assume all validations have been peformed (see activate.cpp).
*/
bool
-Cstore::unmarkCfgPathDeactivated(const vector<string>& path_comps)
+Cstore::unmarkCfgPathDeactivated(const Cpath& path_comps)
{
ASSERT_IN_SESSION;
- SAVE_PATHS;
+ auto_ptr<SavePaths> save(create_save_paths());
append_cfg_path(path_comps);
// note: also mark changed
- bool ret = (unmark_deactivated() && mark_changed_with_ancestors());
- RESTORE_PATHS;
- return ret;
+ return (unmark_deactivated() && mark_changed_with_ancestors());
}
// load specified config file
@@ -1830,29 +1799,29 @@ Cstore::loadFile(const char *filename)
}
// get the config tree from the active config
- vector<string> args;
+ Cpath args;
cnode::CfgNode aroot(*this, args, true, true);
// get the "commands diff" between the two
- vector<vector<string> > del_list;
- vector<vector<string> > set_list;
- vector<vector<string> > com_list;
+ vector<Cpath> del_list;
+ vector<Cpath> set_list;
+ vector<Cpath> com_list;
cnode::get_cmds_diff(aroot, *froot, del_list, set_list, com_list);
// "apply" the changes to the working config
for (size_t i = 0; i < del_list.size(); i++) {
if (!deleteCfgPath(del_list[i])) {
- print_str_vec("Delete [", "] failed\n", del_list[i], "'");
+ print_path_vec("Delete [", "] failed\n", del_list[i], "'");
}
}
for (size_t i = 0; i < set_list.size(); i++) {
if (!validateSetPath(set_list[i]) || !setCfgPath(set_list[i])) {
- print_str_vec("Set [", "] failed\n", set_list[i], "'");
+ print_path_vec("Set [", "] failed\n", set_list[i], "'");
}
}
for (size_t i = 0; i < com_list.size(); i++) {
if (!commentCfgPath(com_list[i])) {
- print_str_vec("Comment [", "] failed\n", com_list[i], "'");
+ print_path_vec("Comment [", "] failed\n", com_list[i], "'");
}
}
@@ -1907,19 +1876,20 @@ Cstore::loadFile(const char *filename)
* return true if successful. otherwise return false.
*/
bool
-Cstore::unmarkCfgPathChanged(const vector<string>& path_comps)
+Cstore::unmarkCfgPathChanged(const Cpath& path_comps)
{
ASSERT_IN_SESSION;
- SAVE_PATHS;
+ auto_ptr<SavePaths> save(create_save_paths());
append_cfg_path(path_comps);
- bool ret = unmark_changed_with_descendants();
- RESTORE_PATHS;
- return ret;
+ return unmark_changed_with_descendants();
}
////// protected functions
+Cstore::SavePaths::~SavePaths() {
+}
+
void
Cstore::output_user(const char *fmt, ...)
{
@@ -1991,12 +1961,17 @@ Cstore::sort_nodes(vector<string>& nvec, unsigned int sort_alg)
/* try to append the logical path to template path.
* is_tag: (output) whether the last component is a "tag".
* return false if logical path is not valid. otherwise return true.
+ *
+ * note: if the last comp is already "node.tag", is_tag won't be set.
+ * currently this should only happen when get_parsed_tmpl() "borrows"
+ * comps from the current tmpl path, in which case this is not
+ * a problem.
*/
bool
-Cstore::append_tmpl_path(const vector<string>& path_comps, bool& is_tag)
+Cstore::append_tmpl_path(const Cpath& path_comps, bool& is_tag)
{
- is_tag = false;
for (size_t i = 0; i < path_comps.size(); i++) {
+ is_tag = false;
push_tmpl_path(path_comps[i]);
if (tmpl_node_exists()) {
// got exact match. continue to next component.
@@ -2007,10 +1982,7 @@ Cstore::append_tmpl_path(const vector<string>& path_comps, bool& is_tag)
push_tmpl_path_tag();
if (tmpl_node_exists()) {
// got tag match. continue to next component.
- if (i == (path_comps.size() - 1)) {
- // last comp
- is_tag = true;
- }
+ is_tag = true;
continue;
}
// not a valid path
@@ -2019,9 +1991,12 @@ Cstore::append_tmpl_path(const vector<string>& path_comps, bool& is_tag)
return true;
}
+typedef Cstore::MapT<Cpath, tr1::shared_ptr<Ctemplate>, CpathHash> TmplCacheT;
+static TmplCacheT _tmpl_cache;
+
/* check whether specified "logical path" is valid template path.
* then template at the path is parsed.
- * path_comps: vector of path components.
+ * path_comps: path components.
* validate_vals: whether to validate all "values" along specified path.
* error: (output) error message if failed.
* return parsed template if successful. otherwise return 0.
@@ -2029,44 +2004,53 @@ Cstore::append_tmpl_path(const vector<string>& path_comps, bool& is_tag)
* also, if last path component is value (i.e., isValue()), the template
* parsed is actually at "full path - 1".
*/
-Ctemplate *
-Cstore::get_parsed_tmpl(const vector<string>& path_comps, bool validate_vals,
+tr1::shared_ptr<Ctemplate>
+Cstore::get_parsed_tmpl(const Cpath& path_comps, bool validate_vals,
string& error)
{
- Ctemplate *rtmpl = 0;
+ tr1::shared_ptr<Ctemplate> rtmpl;
// default error message
error = "The specified configuration node is not valid";
- if (tmpl_path_at_root() && path_comps.size() == 0) {
- // empty path not valid
- return rtmpl;
+ bool do_caching = false;
+ if (tmpl_path_at_root()) {
+ if (path_comps.size() == 0) {
+ // empty path not valid
+ return rtmpl;
+ }
+ // we are starting from root => caching applies
+ do_caching = true;
+ TmplCacheT::iterator p = _tmpl_cache.find(path_comps);
+ if (p != _tmpl_cache.end()) {
+ // return cached
+ return p->second;
+ }
}
- /* note: this function may be invoked recursively (depth 1) when
- * validating values, i.e., validate_value will process variable
- * reference, which calls this indirectly to get templates.
- * so need special save/restore identifier.
- */
- const char *not_validating = "get_parsed_tmpl_not_validating";
- if (validate_vals) {
- SAVE_PATHS;
- } else {
- save_paths(not_validating);
- }
+ auto_ptr<SavePaths> save(create_save_paths());
+
/* need at least 1 comp to work. 2 comps if last comp is value.
* so pop tmpl_path and prepend them. note that path_comps remain
* constant.
*/
- vector<string> *pcomps = const_cast<vector<string> *>(&path_comps);
- vector<string> new_path_comps;
- if (path_comps.size() < 2) {
- new_path_comps = path_comps;
- pcomps = &new_path_comps;
- for (unsigned int i = 0; i < 2 && pcomps->size() < 2; i++) {
+ Cpath *pcomps = const_cast<Cpath *>(&path_comps);
+ Cpath new_path_comps;
+ size_t p_size = path_comps.size();
+ if (p_size < 2) {
+ Cpath tmp;
+ for (unsigned int i = 0; i < 2 && (i + p_size) < 2; i++) {
if (!tmpl_path_at_root()) {
- pcomps->insert(pcomps->begin(), pop_tmpl_path());
+ string last;
+ pop_tmpl_path(last);
+ tmp.push(last);
}
}
+ while (tmp.size() > 0) {
+ new_path_comps.push(tmp.back());
+ tmp.pop();
+ }
+ new_path_comps /= path_comps;
+ pcomps = &new_path_comps;
}
do {
/* cases for template path:
@@ -2089,7 +2073,7 @@ Cstore::get_parsed_tmpl(const vector<string>& path_comps, bool validate_vals,
// first scan up to "full path - 1"
bool valid = true;
for (size_t i = 0; i < (pcomps->size() - 1); i++) {
- if ((*pcomps)[i] == "") {
+ if ((*pcomps)[i][0] == 0) {
// only the last component is potentially allowed to be empty str
valid = false;
break;
@@ -2104,7 +2088,8 @@ Cstore::get_parsed_tmpl(const vector<string>& path_comps, bool validate_vals,
* pop it.
*/
pop_tmpl_path();
- if (!validate_val(0, (*pcomps)[i])) {
+ tr1::shared_ptr<Ctemplate> ttmpl(tmpl_parse());
+ if (!validate_val(ttmpl, (*pcomps)[i])) {
// invalid value
error = "Value validation failed";
valid = false;
@@ -2133,19 +2118,19 @@ Cstore::get_parsed_tmpl(const vector<string>& path_comps, bool validate_vals,
* we haven't done anything yet.
*/
if (pcomps->size() > 1) {
- auto_ptr<Ctemplate> ttmpl(tmpl_parse());
+ tr1::shared_ptr<Ctemplate> ttmpl(tmpl_parse());
if (ttmpl.get()) {
if (ttmpl->isTag() || ttmpl->isMulti() || !ttmpl->isTypeless()) {
// case (2). last component is "value".
if (validate_vals) {
// validate value
- if (!validate_val(ttmpl.get(), (*pcomps)[pcomps->size() - 1])) {
+ if (!validate_val(ttmpl, (*pcomps)[pcomps->size() - 1])) {
// invalid value
error = "Value validation failed";
break;
}
}
- rtmpl = ttmpl.release();
+ rtmpl = ttmpl;
rtmpl->setIsValue(true);
break;
}
@@ -2153,7 +2138,7 @@ Cstore::get_parsed_tmpl(const vector<string>& path_comps, bool validate_vals,
// if no valid template or not a value, it's not case (2) so continue.
}
// now check last component
- if ((*pcomps)[pcomps->size() - 1] == "") {
+ if ((*pcomps)[pcomps->size() - 1][0] == 0) {
// only value is potentially allowed to be empty str
break;
}
@@ -2161,8 +2146,9 @@ Cstore::get_parsed_tmpl(const vector<string>& path_comps, bool validate_vals,
// no need to push cfg path (only needed for validate_val())
if (tmpl_node_exists()) {
// case (1). last component is "node".
- if (!(rtmpl = tmpl_parse())) {
- exit_internal("failed to parse tmpl [%s]\n",
+ rtmpl.reset(tmpl_parse());
+ if (!rtmpl.get()) {
+ exit_internal("get_parsed_tmpl: failed to parse tmpl [%s]\n",
tmpl_path_to_str().c_str());
}
rtmpl->setIsValue(false);
@@ -2170,10 +2156,10 @@ Cstore::get_parsed_tmpl(const vector<string>& path_comps, bool validate_vals,
}
// case (3) (fall through)
} while (0);
- if (validate_vals) {
- RESTORE_PATHS;
- } else {
- restore_paths(not_validating);
+
+ if (do_caching && rtmpl.get()) {
+ // only cache if we got a valid template
+ _tmpl_cache[path_comps] = rtmpl;
}
return rtmpl;
}
@@ -2182,14 +2168,15 @@ Cstore::get_parsed_tmpl(const vector<string>& path_comps, bool validate_vals,
* "deactivate" operation.
* return parsed template if valid. otherwise return 0.
*/
-Ctemplate *
-Cstore::validate_act_deact(const vector<string>& path_comps, const string& op)
+tr1::shared_ptr<Ctemplate>
+Cstore::validate_act_deact(const Cpath& path_comps, const char *op)
{
string terr;
- auto_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, false, terr));
+ tr1::shared_ptr<Ctemplate> def(get_parsed_tmpl(path_comps, false, terr));
+ tr1::shared_ptr<Ctemplate> none;
if (!def.get()) {
output_user("%s\n", terr.c_str());
- return 0;
+ return none;
}
{
/* XXX this is a temporary workaround for bug 5708, which should be
@@ -2198,76 +2185,72 @@ Cstore::validate_act_deact(const vector<string>& path_comps, const string& op)
* this workaround should be removed and the bug fixed properly.
*/
if (!def->isTag() && !def->isTypeless()) {
- output_user("Cannot %s a leaf configuration node\n", op.c_str());
- return 0;
+ output_user("Cannot %s a leaf configuration node\n", op);
+ return none;
}
}
if (def->isLeafValue()) {
/* last component is a value of a single- or multi-value node (i.e.,
* a leaf value) => not allowed
*/
- output_user("Cannot %s a leaf configuration value\n", op.c_str());
- return 0;
+ output_user("Cannot %s a leaf configuration value\n", op);
+ return none;
}
if (!cfg_path_exists(path_comps, false, true)) {
output_user("Nothing to %s (the specified %s does not exist)\n",
- op.c_str(),
- (!def->isValue() || def->isTag()) ? "node" : "value");
- return 0;
+ op, (!def->isValue() || def->isTag()) ? "node" : "value");
+ return none;
}
- return def.release();
+ return def;
}
/* check if specified args is valid for "rename" or "copy" operation.
* return true if valid. otherwise return false.
*/
bool
-Cstore::validate_rename_copy(const vector<string>& args, const string& op)
+Cstore::validate_rename_copy(const Cpath& args, const char *op)
{
- if (args.size() != 5 || args[2] != "to") {
- output_user("Invalid %s command\n", op.c_str());
+ if (args.size() != 5 || strcmp(args[2], "to") != 0) {
+ output_user("Invalid %s command\n", op);
return false;
}
- string otagnode = args[0];
- string otagval = args[1];
- string ntagnode = args[3];
- string ntagval = args[4];
- if (otagnode != ntagnode) {
- output_user("Cannot %s from \"%s\" to \"%s\"\n",
- op.c_str(), otagnode.c_str(), ntagnode.c_str());
+ const char *otagnode = args[0];
+ const char *otagval = args[1];
+ const char *ntagnode = args[3];
+ const char *ntagval = args[4];
+ if (strcmp(otagnode, ntagnode) != 0) {
+ output_user("Cannot %s from \"%s\" to \"%s\"\n", op, otagnode, ntagnode);
return false;
}
// check the old path
- vector<string> ppath;
- ppath.push_back(otagnode);
- ppath.push_back(otagval);
+ Cpath ppath;
+ ppath.push(otagnode);
+ ppath.push(otagval);
string terr;
- auto_ptr<Ctemplate> def(get_parsed_tmpl(ppath, false, terr));
+ tr1::shared_ptr<Ctemplate> def(get_parsed_tmpl(ppath, false, terr));
if (!def.get()) {
output_user("%s\n", terr.c_str());
return false;
}
if (!def->isTagValue()) {
// can only rename "tagnode tagvalue"
- output_user("Cannot %s under \"%s\"\n", op.c_str(), otagnode.c_str());
+ output_user("Cannot %s under \"%s\"\n", op, otagnode);
return false;
}
if (!cfg_path_exists(ppath, false, true)) {
- output_user("Configuration \"%s %s\" does not exist\n",
- otagnode.c_str(), otagval.c_str());
+ output_user("Configuration \"%s %s\" does not exist\n", otagnode, otagval);
return false;
}
// check the new path
- ppath.pop_back();
- ppath.push_back(ntagval);
+ ppath.pop();
+ ppath.push(ntagval);
if (cfg_path_exists(ppath, false, true)) {
- output_user("Configuration \"%s %s\" already exists\n",
- ntagnode.c_str(), ntagval.c_str());
+ output_user("Configuration \"%s %s\" already exists\n", ntagnode, ntagval);
return false;
}
- def.reset(get_parsed_tmpl(ppath, true, terr));
+ def = get_parsed_tmpl(ppath, true, terr);
if (!def.get()) {
output_user("%s\n", terr.c_str());
return false;
@@ -2277,9 +2260,8 @@ Cstore::validate_rename_copy(const vector<string>& args, const string& op)
// convert args for "move" to be used for equivalent "rename" operation
bool
-Cstore::conv_move_args_for_rename(const vector<string>& args,
- vector<string>& edit_path_comps,
- vector<string>& rn_args)
+Cstore::conv_move_args_for_rename(const Cpath& args, Cpath& edit_path_comps,
+ Cpath& rn_args)
{
/* note:
* "move interfaces ethernet eth2 vif 100 to 200"
@@ -2294,13 +2276,13 @@ Cstore::conv_move_args_for_rename(const vector<string>& args,
return false;
}
for (size_t i = 0; i < (num_args - 4); i++) {
- edit_path_comps.push_back(args[i]);
+ edit_path_comps.push(args[i]);
}
- rn_args.push_back(args[num_args - 4]); // vif
- rn_args.push_back(args[num_args - 3]); // 100
- rn_args.push_back(args[num_args - 2]); // to
- rn_args.push_back(args[num_args - 4]); // vif
- rn_args.push_back(args[num_args - 1]); // 200
+ rn_args.push(args[num_args - 4]); // vif
+ rn_args.push(args[num_args - 3]); // 100
+ rn_args.push(args[num_args - 2]); // to
+ rn_args.push(args[num_args - 4]); // vif
+ rn_args.push(args[num_args - 1]); // 200
return true;
}
@@ -2310,19 +2292,21 @@ Cstore::conv_move_args_for_rename(const vector<string>& args,
* return true if it exists. otherwise return false.
*/
bool
-Cstore::cfg_path_exists(const vector<string>& path_comps,
- bool active_cfg, bool include_deactivated)
+Cstore::cfg_path_exists(const Cpath& path_comps, bool active_cfg,
+ bool include_deactivated)
{
- SAVE_PATHS;
- append_cfg_path(path_comps);
- // first check if it's a "node".
- bool ret = cfg_node_exists(active_cfg);
- if (!ret) {
- // doesn't exist as a node. maybe a value?
- pop_cfg_path();
- ret = cfg_value_exists(path_comps[path_comps.size() - 1], active_cfg);
+ bool ret = false;
+ {
+ auto_ptr<SavePaths> save(create_save_paths());
+ append_cfg_path(path_comps);
+ // first check if it's a "node".
+ ret = cfg_node_exists(active_cfg);
+ if (!ret) {
+ // doesn't exist as a node. maybe a value?
+ pop_cfg_path();
+ ret = cfg_value_exists(path_comps[path_comps.size() - 1], active_cfg);
+ }
}
- RESTORE_PATHS;
if (ret && !include_deactivated
&& cfgPathDeactivated(path_comps, active_cfg)) {
// don't include deactivated
@@ -2337,25 +2321,24 @@ Cstore::cfg_path_exists(const vector<string>& path_comps,
* note: assume specified path is valid (i.e., validateSetPath()).
*/
bool
-Cstore::set_cfg_path(const vector<string>& path_comps, bool output)
+Cstore::set_cfg_path(const Cpath& path_comps, bool output)
{
- vector<string> ppath;
- auto_ptr<Ctemplate> def;
+ Cpath ppath;
+ tr1::shared_ptr<Ctemplate> def;
bool ret = true;
bool path_exists = true;
// do the set from the top down
- SAVE_PATHS;
for (size_t i = 0; i < path_comps.size(); i++) {
// partial path
- ppath.push_back(path_comps[i]);
+ ppath.push(path_comps[i]);
// get template at this level
- def.reset(get_parsed_tmpl(ppath, false));
+ def = get_parsed_tmpl(ppath, false);
if (!def.get()) {
output_internal("paths[%s,%s]\n", cfg_path_to_str().c_str(),
tmpl_path_to_str().c_str());
for (size_t i = 0; i < ppath.size(); i++) {
- output_internal(" [%s]\n", ppath[i].c_str());
+ output_internal(" [%s]\n", ppath[i]);
}
exit_internal("failed to get tmpl during set. not validate first?\n");
}
@@ -2364,6 +2347,10 @@ Cstore::set_cfg_path(const vector<string>& path_comps, bool output)
if (cfg_path_exists(ppath, false, true)) {
continue;
}
+
+ // paths have not been changed up to this point. now save them.
+ auto_ptr<SavePaths> save(create_save_paths());
+
path_exists = false;
// this level not in working. set it.
@@ -2372,14 +2359,19 @@ Cstore::set_cfg_path(const vector<string>& path_comps, bool output)
if (!def->isValue()) {
// this level is a "node"
- if (!add_node() || !create_default_children()) {
+ if (!add_node()) {
+ ret = false;
+ break;
+ }
+ if (!def->isTag() && !create_default_children(ppath)) {
+ // failed to create default child nodes for a typeless node
ret = false;
break;
}
} else if (def->isTag()) {
// this level is a "tag value".
// add the tag, taking the max tag limit into consideration.
- if (!add_tag(def->getTagLimit()) || !create_default_children()) {
+ if (!add_tag(def->getTagLimit()) || !create_default_children(ppath)) {
ret = false;
break;
}
@@ -2406,11 +2398,10 @@ Cstore::set_cfg_path(const vector<string>& path_comps, bool output)
ret = false;
break;
}
- RESTORE_PATHS;
}
- RESTORE_PATHS; // if "break" was hit
if (ret && def->isValue() && def->getDefault()) {
+ auto_ptr<SavePaths> save(create_save_paths());
/* a node with default has been explicitly set. needs to be marked
* as non-default for display purposes.
*
@@ -2450,7 +2441,6 @@ Cstore::set_cfg_path(const vector<string>& path_comps, bool output)
ret = mark_changed_with_ancestors();
}
}
- RESTORE_PATHS;
}
if (path_exists) {
// whole path already exists
@@ -2471,7 +2461,7 @@ Cstore::set_cfg_path(const vector<string>& path_comps, bool output)
* note: this function is NOT "deactivate-aware".
*/
void
-Cstore::get_child_nodes_status(const vector<string>& path_comps,
+Cstore::get_child_nodes_status(const Cpath& path_comps,
Cstore::MapT<string, string>& cmap,
vector<string> *sorted_keys)
{
@@ -2489,11 +2479,11 @@ Cstore::get_child_nodes_status(const vector<string>& path_comps,
}
// get the status of each one
- vector<string> ppath = path_comps;
+ Cpath ppath(path_comps);
MapT<string, bool>::iterator it = umap.begin();
for (; it != umap.end(); ++it) {
string c = (*it).first;
- ppath.push_back(c);
+ ppath.push(c);
if (sorted_keys) {
sorted_keys->push_back(c);
}
@@ -2507,7 +2497,7 @@ Cstore::get_child_nodes_status(const vector<string>& path_comps,
} else {
cmap[c] = C_NODE_STATUS_STATIC;
}
- ppath.pop_back();
+ ppath.pop();
}
if (sorted_keys) {
sort_nodes(*sorted_keys);
@@ -2521,7 +2511,7 @@ Cstore::get_child_nodes_status(const vector<string>& path_comps,
* note: this follows the original perl API listNodeStatus() implementation.
*/
void
-Cstore::get_child_nodes_status_da(const vector<string>& path_comps,
+Cstore::get_child_nodes_status_da(const Cpath& path_comps,
Cstore::MapT<string, string>& cmap,
vector<string> *sorted_keys)
{
@@ -2538,9 +2528,9 @@ Cstore::get_child_nodes_status_da(const vector<string>& path_comps,
// get all nodes in working config
vector<string> work_nodes;
cfgPathGetChildNodesDA(path_comps, work_nodes, false);
- vector<string> ppath = path_comps;
+ Cpath ppath(path_comps);
for (size_t i = 0; i < work_nodes.size(); i++) {
- ppath.push_back(work_nodes[i]);
+ ppath.push(work_nodes[i]);
if (sorted_keys) {
sorted_keys->push_back(work_nodes[i]);
}
@@ -2561,17 +2551,16 @@ Cstore::get_child_nodes_status_da(const vector<string>& path_comps,
&& cfg_path_exists(ppath, false, true)) {
cmap[work_nodes[i]] = C_NODE_STATUS_ADDED;
} else {
- SAVE_PATHS;
+ auto_ptr<SavePaths> save(create_save_paths());
append_cfg_path(ppath);
if (cfg_node_changed()) {
cmap[work_nodes[i]] = C_NODE_STATUS_CHANGED;
} else {
cmap[work_nodes[i]] = C_NODE_STATUS_STATIC;
}
- RESTORE_PATHS;
}
- ppath.pop_back();
+ ppath.pop();
}
if (sorted_keys) {
sort_nodes(*sorted_keys);
@@ -2592,7 +2581,8 @@ Cstore::remove_tag()
// go up one level and check if that was the last tag
bool ret = true;
- string c = pop_cfg_path();
+ string c;
+ pop_cfg_path(c);
vector<string> cnodes;
// get child nodes, including deactivated ones.
get_all_child_node_names(cnodes, false, true);
@@ -2602,7 +2592,7 @@ Cstore::remove_tag()
ret = false;
}
}
- push_cfg_path(c);
+ push_cfg_path(c.c_str());
return ret;
}
@@ -2656,33 +2646,21 @@ Cstore::cfg_value_exists(const string& value, bool active_cfg)
}
/* validate value at current template path.
- * def: pointer to parsed template. NULL if none.
+ * def: pointer to parsed template.
* val: value to be validated.
* return true if valid. otherwise return false.
* note: current template and cfg paths both point to the node,
* not the value.
*/
bool
-Cstore::validate_val(const Ctemplate *def, const string& value)
+Cstore::validate_val(const tr1::shared_ptr<Ctemplate>& def, const char *value)
{
- auto_ptr<Ctemplate> ndef;
- if (!def) {
- ndef.reset(tmpl_parse());
- if (!(def = ndef.get())) {
- exit_internal("failed to parse tmpl [%s]\n", tmpl_path_to_str().c_str());
- }
- if (def->isTypeless()) {
- // not a value node
- exit_internal("validating non-value node [%s]\n",
- tmpl_path_to_str().c_str());
- }
+ if (!def.get()) {
+ exit_internal("validate_val: no tmpl [%s]\n", tmpl_path_to_str().c_str());
}
// validate_value() may change "value". make a copy first.
- size_t vlen = value.size();
- char *vbuf = (char *) malloc(vlen + 1);
- strncpy(vbuf, value.c_str(), vlen + 1);
- vbuf[vlen] = 0;
+ char *vbuf = strdup(value);
bool ret = validate_val_impl(def, vbuf);
free(vbuf);
return ret;
@@ -2696,7 +2674,8 @@ Cstore::validate_val(const Ctemplate *def, const string& value)
bool
Cstore::add_tag(unsigned int tlimit)
{
- string t = pop_cfg_path();
+ string t;
+ pop_cfg_path(t);
vector<string> cnodes;
// get child nodes, excluding deactivated ones.
get_all_child_node_names(cnodes, false, false);
@@ -2717,7 +2696,7 @@ Cstore::add_tag(unsigned int tlimit)
// neither of the above. just add the tag.
ret = add_child_node(t);
} while (0);
- push_cfg_path(t);
+ push_cfg_path(t.c_str());
return ret;
}
@@ -2770,7 +2749,7 @@ Cstore::get_all_child_node_names(vector<string>& cnodes, bool active_cfg,
get_all_child_node_names_impl(nodes, active_cfg);
for (size_t i = 0; i < nodes.size(); i++) {
if (!include_deactivated) {
- push_cfg_path(nodes[i]);
+ push_cfg_path(nodes[i].c_str());
bool skip = marked_deactivated(active_cfg);
pop_cfg_path();
if (skip) {
@@ -2782,31 +2761,36 @@ Cstore::get_all_child_node_names(vector<string>& cnodes, bool active_cfg,
}
/* create all child nodes of current work path that have default values
+ * path_comps: path components. MUST match the work path and is only
+ * needed for the get_parsed_tmpl() call.
* return true if successful. otherwise return false.
* note: assume current work path has just been created so no child
* nodes exist.
*/
bool
-Cstore::create_default_children()
+Cstore::create_default_children(const Cpath& path_comps)
{
vector<string> tcnodes;
get_all_tmpl_child_node_names(tcnodes);
+
bool ret = true;
+ Cpath pcomps(path_comps);
+ // need to save/reset/restore paths for get_parsed_tmpl()
+ auto_ptr<SavePaths> save(create_save_paths());
+ reset_paths();
for (size_t i = 0; i < tcnodes.size(); i++) {
- push_tmpl_path(tcnodes[i]);
- if (tmpl_node_exists()) {
- auto_ptr<Ctemplate> def(tmpl_parse());
- if (def.get() && def->getDefault()) {
- // has default value. set it.
- push_cfg_path(tcnodes[i]);
- if (!add_node() || !write_value(def->getDefault())
- || !mark_display_default()) {
- ret = false;
- }
- pop_cfg_path();
+ pcomps.push(tcnodes[i]);
+ tr1::shared_ptr<Ctemplate> def(get_parsed_tmpl(pcomps, false));
+ if (def.get() && def->getDefault()) {
+ // has default value. set it.
+ append_cfg_path(pcomps);
+ if (!add_node() || !write_value(def->getDefault())
+ || !mark_display_default()) {
+ ret = false;
}
+ reset_paths();
}
- pop_tmpl_path();
+ pcomps.pop();
if (!ret) {
break;
}
@@ -2820,7 +2804,7 @@ Cstore::create_default_children()
void
Cstore::get_edit_env(string& env)
{
- vector<string> lvec;
+ Cpath lvec;
get_edit_level(lvec);
string lvl;
for (size_t i = 0; i < lvec.size(); i++) {
@@ -2860,15 +2844,15 @@ Cstore::shell_escape_squotes(string& str)
// print a vector of strings
void
-Cstore::print_str_vec(const char *pre, const char *post,
- const vector<string>& vec, const char *quote)
+Cstore::print_path_vec(const char *pre, const char *post,
+ const Cpath& pvec, const char *quote)
{
output_user("%s", pre);
- for (size_t i = 0; i < vec.size(); i++) {
+ for (size_t i = 0; i < pvec.size(); i++) {
if (i > 0) {
output_user(" ");
}
- output_user("%s%s%s", quote, vec[i].c_str(), quote);
+ output_user("%s%s%s", quote, pvec[i], quote);
}
output_user("%s", post);
}
@@ -2931,3 +2915,5 @@ Cstore::vexit_internal(const char *fmt, va_list alist)
}
}
+} // end namespace cstore
+
diff --git a/src/cstore/cstore.hpp b/src/cstore/cstore.hpp
index 6a76f31..62677c1 100644
--- a/src/cstore/cstore.hpp
+++ b/src/cstore/cstore.hpp
@@ -22,6 +22,7 @@
#include <tr1/unordered_map>
#include <cli_cstore.h>
+#include <cstore/cpath.hpp>
#include <cstore/ctemplate.hpp>
/* declare perl internal functions. just need these two so don't include
@@ -40,12 +41,6 @@ extern "C" void* Perl_get_context(void)
__func__);
-/* macros for saving/restoring paths.
- * note: this allows "nested" save/restore invocations but NOT recursive ones.
- */
-#define SAVE_PATHS save_paths(&__func__)
-#define RESTORE_PATHS restore_paths(&__func__)
-
namespace cstore { // begin namespace cstore
using namespace std;
@@ -61,8 +56,8 @@ public:
static Cstore *createCstore(const string& session_id, string& env);
// types
- template<class K, class V>
- class MapT : public tr1::unordered_map<K, V> {};
+ template<class K, class V, class H = tr1::hash<K> >
+ class MapT : public tr1::unordered_map<K, V, H> {};
// constants
static const string C_NODE_STATUS_DELETED;
@@ -100,12 +95,12 @@ public:
////// the public cstore interface
//// functions implemented in this base class
// these operate on template path
- bool validateTmplPath(const vector<string>& path_comps, bool validate_vals);
- Ctemplate *parseTmpl(const vector<string>& path_comps, bool validate_vals);
- bool getParsedTmpl(const vector<string>& path_comps,
- MapT<string, string>& tmap, bool allow_val = true);
- void tmplGetChildNodes(const vector<string>& path_comps,
- vector<string>& cnodes);
+ bool validateTmplPath(const Cpath& path_comps, bool validate_vals);
+ tr1::shared_ptr<Ctemplate> parseTmpl(const Cpath& path_comps,
+ bool validate_vals);
+ bool getParsedTmpl(const Cpath& path_comps, MapT<string, string>& tmap,
+ bool allow_val = true);
+ void tmplGetChildNodes(const Cpath& path_comps, vector<string>& cnodes);
/******
* functions for actual CLI operations:
@@ -127,39 +122,39 @@ public:
* be used by anything other than the listed operations.
*/
// set
- bool validateSetPath(const vector<string>& path_comps);
- bool setCfgPath(const vector<string>& path_comps);
+ bool validateSetPath(const Cpath& path_comps);
+ bool setCfgPath(const Cpath& path_comps);
// delete
- bool deleteCfgPath(const vector<string>& path_comps);
+ bool deleteCfgPath(const Cpath& path_comps);
// activate (actually "unmark deactivated" since it is 2-state, not 3)
- bool validateActivatePath(const vector<string>& path_comps);
- bool unmarkCfgPathDeactivated(const vector<string>& path_comps);
+ bool validateActivatePath(const Cpath& path_comps);
+ bool unmarkCfgPathDeactivated(const Cpath& path_comps);
// deactivate
- bool validateDeactivatePath(const vector<string>& path_comps);
- bool markCfgPathDeactivated(const vector<string>& path_comps);
+ bool validateDeactivatePath(const Cpath& path_comps);
+ bool markCfgPathDeactivated(const Cpath& path_comps);
// rename
- bool validateRenameArgs(const vector<string>& args);
- bool renameCfgPath(const vector<string>& args);
+ bool validateRenameArgs(const Cpath& args);
+ bool renameCfgPath(const Cpath& args);
// copy
- bool validateCopyArgs(const vector<string>& args);
- bool copyCfgPath(const vector<string>& args);
+ bool validateCopyArgs(const Cpath& args);
+ bool copyCfgPath(const Cpath& args);
// comment
- bool commentCfgPath(const vector<string>& args);
+ bool commentCfgPath(const Cpath& args);
// discard
bool discardChanges();
// move
- bool validateMoveArgs(const vector<string>& args);
- bool moveCfgPath(const vector<string>& args);
+ bool validateMoveArgs(const Cpath& args);
+ bool moveCfgPath(const Cpath& args);
// edit-related
- bool getEditEnv(const vector<string>& path_comps, string& env);
+ bool getEditEnv(const Cpath& path_comps, string& env);
bool getEditUpEnv(string& env);
bool getEditResetEnv(string& env);
bool editLevelAtRoot() {
return edit_level_at_root();
};
// completion-related
- bool getCompletionEnv(const vector<string>& comps, string& env);
- void getEditLevel(vector<string>& comps) {
+ bool getCompletionEnv(const Cpath& comps, string& env);
+ void getEditLevel(Cpath& comps) {
get_edit_level(comps);
};
// session-related
@@ -171,7 +166,7 @@ public:
virtual bool teardownSession() = 0;
virtual bool inSession() = 0;
// commit
- bool unmarkCfgPathChanged(const vector<string>& path_comps);
+ bool unmarkCfgPathChanged(const Cpath& path_comps);
// load
bool loadFile(const char *filename);
@@ -190,34 +185,32 @@ public:
* config, of course).
*/
// observers for "working config" (by default) OR "active config"
- bool cfgPathExists(const vector<string>& path_comps,
- bool active_cfg = false);
- void cfgPathGetChildNodes(const vector<string>& path_comps,
- vector<string>& cnodes, bool active_cfg = false);
- bool cfgPathGetValue(const vector<string>& path_comps, string& value,
+ bool cfgPathExists(const Cpath& path_comps, bool active_cfg = false);
+ void cfgPathGetChildNodes(const Cpath& path_comps, vector<string>& cnodes,
+ bool active_cfg = false);
+ bool cfgPathGetValue(const Cpath& path_comps, string& value,
bool active_cfg = false);
- bool cfgPathGetValues(const vector<string>& path_comps,
- vector<string>& values, bool active_cfg = false);
- bool cfgPathGetComment(const vector<string>& path_comps, string& comment,
+ bool cfgPathGetValues(const Cpath& path_comps, vector<string>& values,
+ bool active_cfg = false);
+ bool cfgPathGetComment(const Cpath& path_comps, string& comment,
bool active_cfg = false);
- bool cfgPathDefault(const vector<string>& path_comps,
- bool active_cfg = false);
+ bool cfgPathDefault(const Cpath& path_comps, bool active_cfg = false);
/* observers for working AND active configs (at the same time).
* MUST ONLY be used during config session.
*/
- bool cfgPathDeleted(const vector<string>& path_comps);
- bool cfgPathAdded(const vector<string>& path_comps);
- bool cfgPathChanged(const vector<string>& path_comps);
- void cfgPathGetDeletedChildNodes(const vector<string>& path_comps,
+ bool cfgPathDeleted(const Cpath& path_comps);
+ bool cfgPathAdded(const Cpath& path_comps);
+ bool cfgPathChanged(const Cpath& path_comps);
+ void cfgPathGetDeletedChildNodes(const Cpath& path_comps,
vector<string>& cnodes);
- void cfgPathGetDeletedValues(const vector<string>& path_comps,
+ void cfgPathGetDeletedValues(const Cpath& path_comps,
vector<string>& dvals);
- void cfgPathGetChildNodesStatus(const vector<string>& path_comps,
+ void cfgPathGetChildNodesStatus(const Cpath& path_comps,
MapT<string, string>& cmap) {
get_child_nodes_status(path_comps, cmap, NULL);
};
- void cfgPathGetChildNodesStatus(const vector<string>& path_comps,
+ void cfgPathGetChildNodesStatus(const Cpath& path_comps,
MapT<string, string>& cmap,
vector<string>& sorted_keys) {
get_child_nodes_status(path_comps, cmap, &sorted_keys);
@@ -227,12 +220,11 @@ public:
* session and outside a config session. more detailed information
* can be found in the source file.
*/
- bool cfgPathEffective(const vector<string>& path_comps);
- void cfgPathGetEffectiveChildNodes(const vector<string>& path_comps,
+ bool cfgPathEffective(const Cpath& path_comps);
+ void cfgPathGetEffectiveChildNodes(const Cpath& path_comps,
vector<string>& cnodes);
- bool cfgPathGetEffectiveValue(const vector<string>& path_comps,
- string& value);
- bool cfgPathGetEffectiveValues(const vector<string>& path_comps,
+ bool cfgPathGetEffectiveValue(const Cpath& path_comps, string& value);
+ bool cfgPathGetEffectiveValues(const Cpath& path_comps,
vector<string>& values);
/******
@@ -253,36 +245,32 @@ public:
* passed in when calling them.
*/
// working or active config
- bool cfgPathDeactivated(const vector<string>& path_comps,
- bool active_cfg = false);
- bool cfgPathMarkedDeactivated(const vector<string>& path_comps,
+ bool cfgPathDeactivated(const Cpath& path_comps, bool active_cfg = false);
+ bool cfgPathMarkedDeactivated(const Cpath& path_comps,
bool active_cfg = false);
- bool cfgPathExistsDA(const vector<string>& path_comps,
- bool active_cfg = false,
+ bool cfgPathExistsDA(const Cpath& path_comps, bool active_cfg = false,
bool include_deactivated = true);
- void cfgPathGetChildNodesDA(const vector<string>& path_comps,
- vector<string>& cnodes,
+ void cfgPathGetChildNodesDA(const Cpath& path_comps, vector<string>& cnodes,
bool active_cfg = false,
bool include_deactivated = true);
- bool cfgPathGetValueDA(const vector<string>& path_comps, string& value,
+ bool cfgPathGetValueDA(const Cpath& path_comps, string& value,
bool active_cfg = false,
bool include_deactivated = true);
- bool cfgPathGetValuesDA(const vector<string>& path_comps,
- vector<string>& values,
+ bool cfgPathGetValuesDA(const Cpath& path_comps, vector<string>& values,
bool active_cfg = false,
bool include_deactivated = true);
// working AND active configs
- void cfgPathGetDeletedChildNodesDA(const vector<string>& path_comps,
+ void cfgPathGetDeletedChildNodesDA(const Cpath& path_comps,
vector<string>& cnodes,
bool include_deactivated = true);
- void cfgPathGetDeletedValuesDA(const vector<string>& path_comps,
+ void cfgPathGetDeletedValuesDA(const Cpath& path_comps,
vector<string>& dvals,
bool include_deactivated = true);
- void cfgPathGetChildNodesStatusDA(const vector<string>& path_comps,
+ void cfgPathGetChildNodesStatusDA(const Cpath& path_comps,
MapT<string, string>& cmap) {
get_child_nodes_status_da(path_comps, cmap, NULL);
};
- void cfgPathGetChildNodesStatusDA(const vector<string>& path_comps,
+ void cfgPathGetChildNodesStatusDA(const Cpath& path_comps,
MapT<string, string>& cmap,
vector<string>& sorted_keys) {
get_child_nodes_status_da(path_comps, cmap, &sorted_keys);
@@ -299,10 +287,15 @@ public:
* the limitations of the original CLI library implementation and MUST NOT
* be used by anyone other than the original CLI library.
*/
- char *getVarRef(const string& ref_str, vtw_type_e& type, bool from_active);
- bool setVarRef(const string& ref_str, const string& value, bool to_active);
+ char *getVarRef(const char *ref_str, vtw_type_e& type, bool from_active);
+ bool setVarRef(const char *ref_str, const char *value, bool to_active);
protected:
+ class SavePaths {
+ public:
+ virtual ~SavePaths() = 0;
+ };
+
////// functions for subclasses
static void output_user(const char *fmt, ...);
static void output_user_err(const char *fmt, ...);
@@ -323,15 +316,16 @@ private:
* the same as before invocation.
*/
// begin path modifiers
- virtual void push_tmpl_path(const string& path_comp) = 0;
+ virtual void push_tmpl_path(const char *path_comp) = 0;
virtual void push_tmpl_path_tag() = 0;
- virtual string pop_tmpl_path() = 0;
- virtual void push_cfg_path(const string& path_comp) = 0;
- virtual string pop_cfg_path() = 0;
- virtual void append_cfg_path(const vector<string>& path_comps) = 0;
+ virtual void pop_tmpl_path() = 0;
+ virtual void pop_tmpl_path(string& last) = 0;
+ virtual void push_cfg_path(const char *path_comp) = 0;
+ virtual void pop_cfg_path() = 0;
+ virtual void pop_cfg_path(string& last) = 0;
+ virtual void append_cfg_path(const Cpath& path_comps) = 0;
virtual void reset_paths() = 0;
- virtual void save_paths(const void *handle = NULL) = 0;
- virtual void restore_paths(const void *handle = NULL) = 0;
+ virtual auto_ptr<SavePaths> create_save_paths() = 0;
virtual bool cfg_path_at_root() = 0;
virtual bool tmpl_path_at_root() = 0;
// end path modifiers
@@ -348,8 +342,8 @@ private:
virtual bool write_value_vec(const vector<string>& vvec,
bool active_cfg = false) = 0;
virtual bool add_node() = 0;
- virtual bool rename_child_node(const string& oname, const string& nname) = 0;
- virtual bool copy_child_node(const string& oname, const string& nname) = 0;
+ virtual bool rename_child_node(const char *oname, const char *nname) = 0;
+ virtual bool copy_child_node(const char *oname, const char *nname) = 0;
virtual bool mark_display_default() = 0;
virtual bool unmark_display_default() = 0;
virtual bool mark_deactivated() = 0;
@@ -372,10 +366,12 @@ private:
virtual bool marked_display_default(bool active_cfg) = 0;
// observers during commit operation
- virtual bool marked_committed(const Ctemplate *def, bool is_set) = 0;
+ virtual bool marked_committed(const tr1::shared_ptr<Ctemplate>& def,
+ bool is_set) = 0;
// these operate on both current tmpl and work paths
- virtual bool validate_val_impl(const Ctemplate *def, char *value) = 0;
+ virtual bool validate_val_impl(const tr1::shared_ptr<Ctemplate>& def,
+ char *value) = 0;
// observers for "edit/tmpl levels" (for "edit"-related operations)
/* note that these should be handled in the base class since they
@@ -390,7 +386,7 @@ private:
*/
virtual string get_edit_level_path() = 0;
virtual string get_tmpl_level_path() = 0;
- virtual void get_edit_level(vector<string>& path_comps) = 0;
+ virtual void get_edit_level(Cpath& path_comps) = 0;
virtual bool edit_level_at_root() = 0;
// these are for testing/debugging
@@ -417,15 +413,17 @@ private:
}
// begin path modifiers (only these can change path permanently)
- bool append_tmpl_path(const vector<string>& path_comps, bool& is_tag);
- bool append_tmpl_path(const vector<string>& path_comps) {
+ bool append_tmpl_path(const Cpath& path_comps, bool& is_tag);
+ bool append_tmpl_path(const Cpath& path_comps) {
bool dummy;
return append_tmpl_path(path_comps, dummy);
};
- bool append_tmpl_path(const string& path_comp, bool& is_tag) {
- return append_tmpl_path(vector<string>(1, path_comp), is_tag);
+ bool append_tmpl_path(const char *path_comp, bool& is_tag) {
+ Cpath p;
+ p.push(path_comp);
+ return append_tmpl_path(p, is_tag);
};
- bool append_tmpl_path(const string& path_comp) {
+ bool append_tmpl_path(const char *path_comp) {
bool dummy;
return append_tmpl_path(path_comp, dummy);
};
@@ -433,26 +431,26 @@ private:
// these require full path
// (note: get_parsed_tmpl also uses current tmpl path)
- Ctemplate *get_parsed_tmpl(const vector<string>& path_comps,
- bool validate_vals, string& error);
- Ctemplate *get_parsed_tmpl(const vector<string>& path_comps,
- bool validate_vals) {
+ tr1::shared_ptr<Ctemplate> get_parsed_tmpl(const Cpath& path_comps,
+ bool validate_vals,
+ string& error);
+ tr1::shared_ptr<Ctemplate> get_parsed_tmpl(const Cpath& path_comps,
+ bool validate_vals) {
string dummy;
return get_parsed_tmpl(path_comps, validate_vals, dummy);
};
- Ctemplate *validate_act_deact(const vector<string>& path_comps,
- const string& op);
- bool validate_rename_copy(const vector<string>& args, const string& op);
- bool conv_move_args_for_rename(const vector<string>& args,
- vector<string>& edit_path_comps,
- vector<string>& rn_args);
- bool cfg_path_exists(const vector<string>& path_comps,
- bool active_cfg, bool include_deactivated);
- bool set_cfg_path(const vector<string>& path_comps, bool output);
- void get_child_nodes_status(const vector<string>& path_comps,
+ tr1::shared_ptr<Ctemplate> validate_act_deact(const Cpath& path_comps,
+ const char *op);
+ bool validate_rename_copy(const Cpath& args, const char *op);
+ bool conv_move_args_for_rename(const Cpath& args, Cpath& edit_path_comps,
+ Cpath& rn_args);
+ bool cfg_path_exists(const Cpath& path_comps, bool active_cfg,
+ bool include_deactivated);
+ bool set_cfg_path(const Cpath& path_comps, bool output);
+ void get_child_nodes_status(const Cpath& path_comps,
Cstore::MapT<string, string>& cmap,
vector<string> *sorted_keys);
- void get_child_nodes_status_da(const vector<string>& path_comps,
+ void get_child_nodes_status_da(const Cpath& path_comps,
Cstore::MapT<string, string>& cmap,
vector<string> *sorted_keys);
@@ -466,7 +464,7 @@ private:
bool add_tag(unsigned int tlimit);
bool add_value_to_multi(unsigned int mlimit, const string& value);
bool add_child_node(const string& name) {
- push_cfg_path(name);
+ push_cfg_path(name.c_str());
bool ret = add_node();
pop_cfg_path();
return ret;
@@ -478,15 +476,17 @@ private:
bool cfg_value_exists(const string& value, bool active_cfg);
// these operate on both current tmpl and work paths
- bool validate_val(const Ctemplate *def, const string& value);
- bool create_default_children();
+ bool validate_val(const tr1::shared_ptr<Ctemplate>& def, const char *value);
+ bool create_default_children(const Cpath& path_comps); /* this requires
+ * path_comps but DOES operate on current work path.
+ */
void get_edit_env(string& env);
// util functions
string get_shell_prompt(const string& level);
void shell_escape_squotes(string& str);
- void print_str_vec(const char *pre, const char *post,
- const vector<string>& vec, const char *quote);
+ void print_path_vec(const char *pre, const char *post,
+ const Cpath& pvec, const char *quote);
// output functions
static void voutput_user(FILE *out, FILE *dout, const char *fmt,
diff --git a/src/cstore/ctemplate.hpp b/src/cstore/ctemplate.hpp
index 1915273..e970a5d 100644
--- a/src/cstore/ctemplate.hpp
+++ b/src/cstore/ctemplate.hpp
@@ -28,10 +28,10 @@ using namespace std;
class Ctemplate {
public:
- Ctemplate(tr1::shared_ptr<vtw_def> def) : _def(def) {};
+ Ctemplate(tr1::shared_ptr<vtw_def> def) : _def(def), _is_value(false) {};
~Ctemplate() {};
- bool isValue() const { return _def->is_value; };
+ bool isValue() const { return _is_value; };
bool isMulti() const { return _def->multi; };
bool isTag() const { return _def->tag; };
bool isTagNode() const { return (isTag() && !isValue()); };
@@ -90,7 +90,7 @@ public:
unsigned int getTagLimit() const { return _def->def_tag; };
unsigned int getMultiLimit() const { return _def->def_multi; };
- void setIsValue(bool is_val) { _def->is_value = is_val; };
+ void setIsValue(bool is_val) { _is_value = is_val; };
const vtw_def *getDef() const {
/* XXX this is a hack for code that has not been converted and is still
@@ -118,6 +118,9 @@ private:
* handled properly.
*/
tr1::shared_ptr<vtw_def> _def;
+ bool _is_value; /* whether the last path component is a "value". set by
+ * the cstore in get_parsed_tmpl().
+ */
};
} // end namespace cstore
diff --git a/src/cstore/svector.hpp b/src/cstore/svector.hpp
new file mode 100644
index 0000000..fd63297
--- /dev/null
+++ b/src/cstore/svector.hpp
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2011 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 _SVECTOR_HPP_
+#define _SVECTOR_HPP_
+#include <cstdlib>
+#include <cstring>
+#include <string>
+#include <tr1/functional>
+
+namespace cstore {
+
+template<int v>
+struct Int2Type {
+ enum {
+ value = v
+ };
+};
+
+template<class P>
+class svector {
+public:
+ static const char ELEM_SEP = P::separator;
+ static const bool RAW_CSTR_DATA = (ELEM_SEP != 0);
+ static const bool RANDOM_ACCESS = (ELEM_SEP == 0);
+ static const size_t STATIC_NUM_ELEMS = P::static_num_elems;
+ static const size_t STATIC_BUF_LEN = P::static_buf_len;
+
+ svector();
+ svector(const svector<P>& v);
+ svector(const char *raw_cstr);
+ svector(const std::string& str);
+ svector(const char *raw_data, size_t dlen);
+ ~svector();
+
+ void push_back(const char *e);
+ void pop_back();
+ void pop_back(std::string& last);
+
+ svector<P>& operator=(const char *raw_cstr) {
+ assign(raw_cstr);
+ return *this;
+ };
+ svector<P>& operator=(const std::string& str) {
+ return operator=(str.c_str());
+ };
+ svector<P>& operator=(const svector<P>& v);
+ svector<P>& operator/=(const svector<P>& v);
+ svector<P> operator/(const svector<P>& v) {
+ svector<P> lhs(*this);
+ lhs /= v;
+ return lhs;
+ };
+ void assign(const char *raw_cstr) {
+ assign_raw_cstr(raw_cstr, Int2Type<RAW_CSTR_DATA>());
+ };
+ void assign(const char *raw_data, size_t dlen);
+
+ bool operator==(const svector<P>& rhs) const {
+ return (_len == rhs._len && memcmp(_data, rhs._data, _len) == 0);
+ };
+ const char *operator[](size_t idx) const {
+ return elem_at(idx, Int2Type<RANDOM_ACCESS>());
+ };
+
+ size_t size() const { return _num_elems; };
+ size_t length() const { return _len; };
+ const char *get_cstr() const {
+ return get_raw_cstr(Int2Type<RAW_CSTR_DATA>());
+ };
+ const char *get_data(size_t& dlen) const {
+ dlen = _len;
+ return _data;
+ };
+ size_t hash() const {
+ return std::tr1::_Fnv_hash<sizeof(size_t)>::hash(_data, _len);
+ };
+
+private:
+ size_t _num_elems;
+ size_t _len;
+ size_t _ebuf_size;
+ size_t _buf_size;
+ char **_elems;
+ char *_elems_buf[STATIC_NUM_ELEMS];
+ char **_elems_dbuf;
+ char *_data;
+ char _data_buf[STATIC_BUF_LEN];
+ char *_data_dbuf;
+
+ void grow_data();
+ void grow_elems();
+ void inc_num_elems() {
+ ++_num_elems;
+ if (_num_elems >= _ebuf_size) {
+ grow_elems();
+ }
+ };
+ void assign_raw_cstr(const char *raw_cstr, Int2Type<true>) {
+ assign(raw_cstr, strlen(raw_cstr));
+ };
+ const char *get_raw_cstr(Int2Type<true>) const {
+ return _data;
+ };
+ const char *elem_at(size_t idx, Int2Type<true>) const {
+ return (idx < _num_elems ? (_elems[idx] + 1) : NULL);
+ }
+};
+
+template<class P>
+svector<P>::svector()
+ : _num_elems(0), _len(0), _ebuf_size(STATIC_NUM_ELEMS),
+ _buf_size(STATIC_BUF_LEN), _elems(_elems_buf), _elems_dbuf(0),
+ _data(_data_buf), _data_dbuf(0)
+{
+ _elems[0] = _data;
+ _data[0] = 0;
+}
+
+template<class P>
+svector<P>::svector(const svector<P>& v)
+ : _num_elems(0), _len(0), _ebuf_size(STATIC_NUM_ELEMS),
+ _buf_size(STATIC_BUF_LEN), _elems(_elems_buf), _elems_dbuf(0),
+ _data(_data_buf), _data_dbuf(0)
+{
+ _elems[0] = _data;
+ _data[0] = 0;
+ operator=(v);
+}
+
+template<class P>
+svector<P>::svector(const char *raw_cstr)
+ : _num_elems(0), _len(0), _ebuf_size(STATIC_NUM_ELEMS),
+ _buf_size(STATIC_BUF_LEN), _elems(_elems_buf), _elems_dbuf(0),
+ _data(_data_buf), _data_dbuf(0)
+{
+ assign(raw_cstr);
+}
+
+template<class P>
+svector<P>::svector(const std::string& str)
+ : _num_elems(0), _len(0), _ebuf_size(STATIC_NUM_ELEMS),
+ _buf_size(STATIC_BUF_LEN), _elems(_elems_buf), _elems_dbuf(0),
+ _data(_data_buf), _data_dbuf(0)
+{
+ assign(str.c_str());
+}
+
+template<class P>
+svector<P>::svector(const char *raw_data, size_t dlen)
+ : _num_elems(0), _len(0), _ebuf_size(STATIC_NUM_ELEMS),
+ _buf_size(STATIC_BUF_LEN), _elems(_elems_buf), _elems_dbuf(0),
+ _data(_data_buf), _data_dbuf(0)
+{
+ assign(raw_data, dlen);
+}
+
+template<class P>
+svector<P>::~svector()
+{
+ if (_elems_dbuf) {
+ delete [] _elems_dbuf;
+ }
+ if (_data_dbuf) {
+ delete [] _data_dbuf;
+ }
+}
+
+template<class P> void
+svector<P>::push_back(const char *e)
+{
+ size_t elen = strlen(e);
+ while ((_len + elen + 2) >= _buf_size) {
+ // make sure there's space for (data + SEP + e + 0)
+ grow_data();
+ }
+
+ char *start = _elems[_num_elems];
+ *start = ELEM_SEP;
+ memcpy(start + 1, e, elen + 1);
+ inc_num_elems();
+ _len += (elen + 1);
+ _elems[_num_elems] = start + 1 + elen;
+}
+
+template<class P> void
+svector<P>::pop_back()
+{
+ if (_num_elems == 0) {
+ return;
+ }
+ --_num_elems;
+ _len = _elems[_num_elems] - _data;
+ _data[_len] = 0;
+}
+
+template<class P> void
+svector<P>::pop_back(std::string& last)
+{
+ if (_num_elems == 0) {
+ return;
+ }
+ last = _elems[_num_elems - 1] + 1;
+ pop_back();
+}
+
+template<class P> svector<P>&
+svector<P>::operator=(const svector<P>& v)
+{
+ if (this == &v) {
+ return *this;
+ }
+
+ while (_buf_size < v._buf_size) {
+ grow_data();
+ }
+ if (_ebuf_size >= v._ebuf_size) {
+ _num_elems = v._num_elems;
+ } else {
+ _num_elems = 0;
+ while (_num_elems < v._num_elems) {
+ inc_num_elems();
+ }
+ }
+ _len = v._len;
+ memcpy(_data, v._data, _len + 1);
+ memcpy(_elems, v._elems, sizeof(char *) * (_num_elems + 1));
+ const char *o0 = _elems[0];
+ for (size_t i = 0; i <= _num_elems; i++) {
+ _elems[i] = _data + (_elems[i] - o0);
+ }
+ return *this;
+}
+
+template<class P> svector<P>&
+svector<P>::operator/=(const svector<P>& v)
+{
+ while ((_len + v._len + 1) >= _buf_size) {
+ // make sure there's space for (data + data + 0)
+ grow_data();
+ }
+
+ size_t v_num_elems = v._num_elems;
+ size_t olen = _len;
+ memcpy(_data + _len, v._data, v._len + 1);
+ _len += v._len;
+ for (size_t i = 1; i <= v_num_elems; i++) {
+ inc_num_elems();
+ _elems[_num_elems] = _data + olen + (v._elems[i] - v._data);
+ }
+ return *this;
+}
+
+template<class P> void
+svector<P>::assign(const char *raw_data, size_t dlen)
+{
+ _num_elems = 0;
+ _len = 0;
+ _elems[0] = _data;
+ if (dlen == 0 || (dlen == 1 && raw_data[0] == ELEM_SEP)) {
+ _data[0] = 0;
+ return;
+ }
+
+ while ((dlen + 2) >= _buf_size) {
+ // make sure there's space for (SEP + raw_data + 0)
+ grow_data();
+ }
+ _len = dlen;
+
+ if (raw_data[0] != ELEM_SEP) {
+ _data[0] = ELEM_SEP;
+ memcpy(_data + 1, raw_data, _len + 1);
+ ++_len;
+ } else {
+ memcpy(_data, raw_data, _len + 1);
+ }
+ for (size_t i = 1; i < _len; i++) {
+ if (_data[i] == ELEM_SEP) {
+ inc_num_elems();
+ _elems[_num_elems] = &(_data[i]);
+ }
+ }
+ inc_num_elems();
+ _elems[_num_elems] = _data + _len;
+}
+
+template<class P> void
+svector<P>::grow_data()
+{
+ char *tmp = new char[_buf_size + STATIC_BUF_LEN];
+ if (!tmp) {
+ // doomed
+ exit(1);
+ }
+ memcpy(tmp, _data, _len + 1);
+
+ if (tmp != _data_dbuf) {
+ for (size_t i = 0; i <= _num_elems; i++) {
+ _elems[i] = tmp + (_elems[i] - _data);
+ }
+ }
+
+ if (_data_dbuf) {
+ delete [] _data_dbuf;
+ }
+ _data_dbuf = tmp;
+ _data = _data_dbuf;
+ _buf_size += STATIC_BUF_LEN;
+}
+
+template<class P> void
+svector<P>::grow_elems()
+{
+ char **tmp = new char *[_ebuf_size + STATIC_NUM_ELEMS];
+ if (!tmp) {
+ // doomed
+ exit(1);
+ }
+ memcpy(tmp, _elems, _ebuf_size * sizeof(char *));
+ if (_elems_dbuf) {
+ delete [] _elems_dbuf;
+ }
+ _elems_dbuf = tmp;
+ _elems = _elems_dbuf;
+ _ebuf_size += STATIC_NUM_ELEMS;
+}
+
+} // end namespace cstore
+
+#endif /* _SVECTOR_HPP_ */
+
diff --git a/src/cstore/unionfs/cstore-unionfs.cpp b/src/cstore/unionfs/cstore-unionfs.cpp
index b59ddd3..f926540 100644
--- a/src/cstore/unionfs/cstore-unionfs.cpp
+++ b/src/cstore/unionfs/cstore-unionfs.cpp
@@ -26,7 +26,8 @@
#include <cli_cstore.h>
#include <cstore/unionfs/cstore-unionfs.hpp>
-using namespace cstore;
+namespace cstore { // begin namespace cstore
+namespace unionfs { // begin namespace unionfs
////// constants
// environment vars defining root dirs
@@ -205,7 +206,8 @@ UnionfsCstore::UnionfsCstore(bool use_edit_level)
* starts with '/', so only append it if it is at least two chars
* (i.e., it is not "/").
*/
- tmpl_path /= val;
+ FsPath tlvl(val);
+ tmpl_path /= tlvl;
}
}
_init_fs_escape_chars();
@@ -239,11 +241,11 @@ UnionfsCstore::UnionfsCstore(const string& sid, string& env)
string declr = " declare -x -r "; // readonly vars
env += " umask 002; {";
- env += (declr + C_ENV_ACTIVE_ROOT + "=" + active_root.file_string());
- env += (declr + C_ENV_CHANGE_ROOT + "=" + change_root.file_string() + ";");
- env += (declr + C_ENV_WORK_ROOT + "=" + work_root.file_string() + ";");
- env += (declr + C_ENV_TMP_ROOT + "=" + tmp_root.file_string() + ";");
- env += (declr + C_ENV_TMPL_ROOT + "=" + tmpl_root.file_string() + ";");
+ env += (declr + C_ENV_ACTIVE_ROOT + "=" + active_root.path_cstr());
+ env += (declr + C_ENV_CHANGE_ROOT + "=" + change_root.path_cstr() + ";");
+ env += (declr + C_ENV_WORK_ROOT + "=" + work_root.path_cstr() + ";");
+ env += (declr + C_ENV_TMP_ROOT + "=" + tmp_root.path_cstr() + ";");
+ env += (declr + C_ENV_TMPL_ROOT + "=" + tmpl_root.path_cstr() + ";");
env += " } >&/dev/null || true";
// set up path strings using level vars
@@ -254,7 +256,8 @@ UnionfsCstore::UnionfsCstore(const string& sid, string& env)
}
if ((val = getenv(C_ENV_TMPL_LEVEL.c_str())) && val[0] && val[1]) {
// see comment in the other constructor
- tmpl_path /= val;
+ FsPath tlvl(val);
+ tmpl_path /= tlvl;
}
_init_fs_escape_chars();
@@ -269,14 +272,14 @@ UnionfsCstore::~UnionfsCstore()
bool
UnionfsCstore::markSessionUnsaved()
{
- b_fs::path marker = work_root / C_MARKER_UNSAVED;
- if (path_exists(marker.file_string().c_str())) {
+ FsPath marker = work_root;
+ marker.push(C_MARKER_UNSAVED);
+ if (path_exists(marker)) {
// already marked. treat as success.
return true;
}
- if (!create_file(marker.file_string())) {
- output_internal("failed to mark unsaved [%s]\n",
- marker.file_string().c_str());
+ if (!create_file(marker)) {
+ output_internal("failed to mark unsaved [%s]\n", marker.path_cstr());
return false;
}
return true;
@@ -285,16 +288,16 @@ UnionfsCstore::markSessionUnsaved()
bool
UnionfsCstore::unmarkSessionUnsaved()
{
- b_fs::path marker = work_root / C_MARKER_UNSAVED;
- if (!path_exists(marker.file_string().c_str())) {
+ FsPath marker = work_root;
+ marker.push(C_MARKER_UNSAVED);
+ if (!path_exists(marker)) {
// not marked. treat as success.
return true;
}
try {
- b_fs::remove(marker);
+ b_fs::remove(marker.path_cstr());
} catch (...) {
- output_internal("failed to unmark unsaved [%s]\n",
- marker.file_string().c_str());
+ output_internal("failed to unmark unsaved [%s]\n", marker.path_cstr());
return false;
}
return true;
@@ -303,15 +306,17 @@ UnionfsCstore::unmarkSessionUnsaved()
bool
UnionfsCstore::sessionUnsaved()
{
- b_fs::path marker = work_root / C_MARKER_UNSAVED;
- return path_exists(marker.file_string().c_str());
+ FsPath marker = work_root;
+ marker.push(C_MARKER_UNSAVED);
+ return path_exists(marker);
}
bool
UnionfsCstore::sessionChanged()
{
- b_fs::path marker = work_root / C_MARKER_CHANGED;
- return path_exists(marker.file_string().c_str());
+ FsPath marker = work_root;
+ marker.push(C_MARKER_CHANGED);
+ return path_exists(marker);
}
/* set up the session associated with this object.
@@ -321,15 +326,15 @@ UnionfsCstore::sessionChanged()
bool
UnionfsCstore::setupSession()
{
- if (!path_exists(work_root.file_string().c_str())) {
+ if (!path_exists(work_root)) {
// session doesn't exist. create dirs.
try {
- b_fs::create_directories(work_root);
- b_fs::create_directories(change_root);
- b_fs::create_directories(tmp_root);
- if (!path_exists(active_root.file_string().c_str())) {
+ b_fs::create_directories(work_root.path_cstr());
+ b_fs::create_directories(change_root.path_cstr());
+ b_fs::create_directories(tmp_root.path_cstr());
+ if (!path_exists(active_root)) {
// this should only be needed on boot
- b_fs::create_directories(active_root);
+ b_fs::create_directories(active_root.path_cstr());
}
} catch (...) {
output_internal("setup session failed to create session directories\n");
@@ -337,17 +342,20 @@ UnionfsCstore::setupSession()
}
// union mount
- string mopts = ("dirs=" + change_root.file_string() + "=rw:"
- + active_root.file_string() + "=ro");
- if (mount("unionfs", work_root.file_string().c_str(), "unionfs", 0,
+ string mopts = "dirs=";
+ mopts += change_root.path_cstr();
+ mopts += "=rw:";
+ mopts += active_root.path_cstr();
+ mopts += "=ro";
+ if (mount("unionfs", work_root.path_cstr(), "unionfs", 0,
mopts.c_str()) != 0) {
output_internal("setup session mount failed [%s][%s]\n",
- strerror(errno), work_root.file_string().c_str());
+ strerror(errno), work_root.path_cstr());
return false;
}
- } else if (!path_is_directory(work_root.file_string().c_str())) {
+ } else if (!path_is_directory(work_root)) {
output_internal("setup session not dir [%s]\n",
- work_root.file_string().c_str());
+ work_root.path_cstr());
return false;
}
return true;
@@ -361,10 +369,9 @@ bool
UnionfsCstore::teardownSession()
{
// check if session exists
- string wstr = work_root.file_string();
+ string wstr = work_root.path_cstr();
if (wstr.empty() || wstr.find(C_DEF_WORK_PREFIX) != 0
- || !path_exists(work_root.file_string().c_str())
- || !path_is_directory(work_root.file_string().c_str())) {
+ || !path_exists(work_root) || !path_is_directory(work_root)) {
// no session
output_internal("teardown invalid session [%s]\n", wstr.c_str());
return false;
@@ -380,9 +387,9 @@ UnionfsCstore::teardownSession()
// remove session directories
bool ret = false;
try {
- if (b_fs::remove_all(work_root) != 0
- && b_fs::remove_all(change_root) != 0
- && b_fs::remove_all(tmp_root) != 0) {
+ if (b_fs::remove_all(work_root.path_cstr()) != 0
+ && b_fs::remove_all(change_root.path_cstr()) != 0
+ && b_fs::remove_all(tmp_root.path_cstr()) != 0) {
ret = true;
}
} catch (...) {
@@ -400,10 +407,9 @@ UnionfsCstore::teardownSession()
bool
UnionfsCstore::inSession()
{
- string wstr = work_root.file_string();
+ string wstr = work_root.path_cstr();
return (!wstr.empty() && wstr.find(C_DEF_WORK_PREFIX) == 0
- && path_exists(work_root.file_string().c_str())
- && path_is_directory(work_root.file_string().c_str()));
+ && path_exists(work_root) && path_is_directory(work_root));
}
@@ -414,11 +420,11 @@ UnionfsCstore::inSession()
bool
UnionfsCstore::tmpl_node_exists()
{
- return (path_exists(tmpl_path.file_string().c_str())
- && path_is_directory(tmpl_path.file_string().c_str()));
+ return (path_exists(tmpl_path) && path_is_directory(tmpl_path));
}
-typedef Cstore::MapT<string, tr1::shared_ptr<vtw_def> > ParsedTmplCacheT;
+typedef Cstore::MapT<FsPath, tr1::shared_ptr<vtw_def>, FsPathHash>
+ ParsedTmplCacheT;
static ParsedTmplCacheT _parsed_tmpl_cache;
/* parse template at current tmpl_path and return an allocated Ctemplate
@@ -427,14 +433,14 @@ static ParsedTmplCacheT _parsed_tmpl_cache;
Ctemplate *
UnionfsCstore::tmpl_parse()
{
- b_fs::path tp = tmpl_path / C_DEF_NAME;
- if (!path_exists(tp.file_string().c_str())
- || !path_is_regular(tp.file_string().c_str())) {
+ FsPath tp = tmpl_path;
+ tp.push(C_DEF_NAME);
+ if (!path_exists(tp) || !path_is_regular(tp)) {
// invalid
return 0;
}
- ParsedTmplCacheT::iterator p = _parsed_tmpl_cache.find(tp.file_string());
+ ParsedTmplCacheT::iterator p = _parsed_tmpl_cache.find(tp);
if (p != _parsed_tmpl_cache.end()) {
// found in cache
return (new Ctemplate(p->second));
@@ -443,9 +449,9 @@ UnionfsCstore::tmpl_parse()
// new template => parse
tr1::shared_ptr<vtw_def> def(new vtw_def);
vtw_def *_def = def.get();
- if (_def && parse_def(_def, tp.file_string().c_str(), 0) == 0) {
+ if (_def && parse_def(_def, tp.path_cstr(), 0) == 0) {
// succes => cache and return
- _parsed_tmpl_cache[tp.file_string()] = def;
+ _parsed_tmpl_cache[tp] = def;
return (new Ctemplate(def));
}
return 0;
@@ -454,9 +460,8 @@ UnionfsCstore::tmpl_parse()
bool
UnionfsCstore::cfg_node_exists(bool active_cfg)
{
- b_fs::path p = (active_cfg ? get_active_path() : get_work_path());
- return (path_exists(p.file_string().c_str())
- && path_is_directory(p.file_string().c_str()));
+ FsPath p = (active_cfg ? get_active_path() : get_work_path());
+ return (path_exists(p) && path_is_directory(p));
}
bool
@@ -464,7 +469,7 @@ UnionfsCstore::add_node()
{
bool ret = true;
try {
- if (!b_fs::create_directory(get_work_path())) {
+ if (!b_fs::create_directory(get_work_path().path_cstr())) {
// already exists. shouldn't call this function.
ret = false;
}
@@ -473,7 +478,7 @@ UnionfsCstore::add_node()
}
if (!ret) {
output_internal("failed to add node [%s]\n",
- get_work_path().file_string().c_str());
+ get_work_path().path_cstr());
}
return ret;
}
@@ -481,15 +486,15 @@ UnionfsCstore::add_node()
bool
UnionfsCstore::remove_node()
{
- if (!path_exists(get_work_path().file_string().c_str())
- || !path_is_directory(get_work_path().file_string().c_str())) {
+ if (!path_exists(get_work_path())
+ || !path_is_directory(get_work_path())) {
output_internal("remove non-existent node [%s]\n",
- get_work_path().file_string().c_str());
+ get_work_path().path_cstr());
return false;
}
bool ret = false;
try {
- if (b_fs::remove_all(get_work_path()) != 0) {
+ if (b_fs::remove_all(get_work_path().path_cstr()) != 0) {
ret = true;
}
} catch (...) {
@@ -497,7 +502,7 @@ UnionfsCstore::remove_node()
}
if (!ret) {
output_internal("failed to remove node [%s]\n",
- get_work_path().file_string().c_str());
+ get_work_path().path_cstr());
}
return ret;
}
@@ -506,7 +511,7 @@ void
UnionfsCstore::get_all_child_node_names_impl(vector<string>& cnodes,
bool active_cfg)
{
- b_fs::path p = (active_cfg ? get_active_path() : get_work_path());
+ FsPath p = (active_cfg ? get_active_path() : get_work_path());
get_all_child_dir_names(p, cnodes);
/* XXX special cases to emulate original perl API behavior.
@@ -530,8 +535,8 @@ UnionfsCstore::get_all_child_node_names_impl(vector<string>& cnodes,
bool
UnionfsCstore::read_value_vec(vector<string>& vvec, bool active_cfg)
{
- b_fs::path vpath = (active_cfg ? get_active_path() : get_work_path());
- vpath /= C_VAL_NAME;
+ FsPath vpath = (active_cfg ? get_active_path() : get_work_path());
+ vpath.push(C_VAL_NAME);
string ostr;
if (!read_whole_file(vpath, ostr)) {
@@ -564,14 +569,13 @@ UnionfsCstore::read_value_vec(vector<string>& vvec, bool active_cfg)
bool
UnionfsCstore::write_value_vec(const vector<string>& vvec, bool active_cfg)
{
- b_fs::path wp = (active_cfg ? get_active_path() : get_work_path());
- wp /= C_VAL_NAME;
+ FsPath wp = (active_cfg ? get_active_path() : get_work_path());
+ wp.push(C_VAL_NAME);
- if (path_exists(wp.file_string().c_str())
- && !path_is_regular(wp.file_string().c_str())) {
+ if (path_exists(wp) && !path_is_regular(wp)) {
// not a file
output_internal("failed to write node value (file) [%s]\n",
- wp.file_string().c_str());
+ wp.path_cstr());
return false;
}
@@ -584,9 +588,9 @@ UnionfsCstore::write_value_vec(const vector<string>& vvec, bool active_cfg)
ostr += vvec[i];
}
- if (!write_file(wp.file_string().c_str(), ostr)) {
+ if (!write_file(wp, ostr)) {
output_internal("failed to write node value (write) [%s]\n",
- wp.file_string().c_str());
+ wp.path_cstr());
return false;
}
@@ -594,16 +598,16 @@ UnionfsCstore::write_value_vec(const vector<string>& vvec, bool active_cfg)
}
bool
-UnionfsCstore::rename_child_node(const string& oname, const string& nname)
+UnionfsCstore::rename_child_node(const char *oname, const char *nname)
{
- b_fs::path opath = get_work_path() / oname;
- b_fs::path npath = get_work_path() / nname;
- if (!path_exists(opath.file_string().c_str())
- || !path_is_directory(opath.file_string().c_str())
- || path_exists(npath.file_string().c_str())) {
+ FsPath opath = get_work_path();
+ opath.push(oname);
+ FsPath npath = get_work_path();
+ npath.push(nname);
+ if (!path_exists(opath) || !path_is_directory(opath)
+ || path_exists(npath)) {
output_internal("cannot rename node [%s,%s,%s]\n",
- get_work_path().file_string().c_str(),
- oname.c_str(), nname.c_str());
+ get_work_path().path_cstr(), oname, nname);
return false;
}
bool ret = true;
@@ -614,39 +618,37 @@ UnionfsCstore::rename_child_node(const string& oname, const string& nname)
* do it the hard way.
*/
recursive_copy_dir(opath, npath);
- if (b_fs::remove_all(opath) == 0) {
+ if (b_fs::remove_all(opath.path_cstr()) == 0) {
ret = false;
}
} catch (...) {
ret = false;
}
if (!ret) {
- output_internal("failed to rename node [%s,%s]\n",
- opath.file_string().c_str(),
- npath.file_string().c_str());
+ output_internal("failed to rename node [%s,%s]\n", opath.path_cstr(),
+ npath.path_cstr());
}
return ret;
}
bool
-UnionfsCstore::copy_child_node(const string& oname, const string& nname)
+UnionfsCstore::copy_child_node(const char *oname, const char *nname)
{
- b_fs::path opath = get_work_path() / oname;
- b_fs::path npath = get_work_path() / nname;
- if (!path_exists(opath.file_string().c_str())
- || !path_is_directory(opath.file_string().c_str())
- || path_exists(npath.file_string().c_str())) {
+ FsPath opath = get_work_path();
+ opath.push(oname);
+ FsPath npath = get_work_path();
+ npath.push(nname);
+ if (!path_exists(opath) || !path_is_directory(opath)
+ || path_exists(npath)) {
output_internal("cannot copy node [%s,%s,%s]\n",
- get_work_path().file_string().c_str(),
- oname.c_str(), nname.c_str());
+ get_work_path().path_cstr(), oname, nname);
return false;
}
try {
recursive_copy_dir(opath, npath);
} catch (...) {
output_internal("failed to copy node [%s,%s,%s]\n",
- get_work_path().file_string().c_str(),
- oname.c_str(), nname.c_str());
+ get_work_path().path_cstr(), oname, nname);
return false;
}
return true;
@@ -655,14 +657,15 @@ UnionfsCstore::copy_child_node(const string& oname, const string& nname)
bool
UnionfsCstore::mark_display_default()
{
- b_fs::path marker = get_work_path() / C_MARKER_DEF_VALUE;
- if (path_exists(marker.file_string().c_str())) {
+ FsPath marker = get_work_path();
+ marker.push(C_MARKER_DEF_VALUE);
+ if (path_exists(marker)) {
// already marked. treat as success.
return true;
}
- if (!create_file(marker.file_string())) {
+ if (!create_file(marker)) {
output_internal("failed to mark default [%s]\n",
- get_work_path().file_string().c_str());
+ get_work_path().path_cstr());
return false;
}
return true;
@@ -671,16 +674,17 @@ UnionfsCstore::mark_display_default()
bool
UnionfsCstore::unmark_display_default()
{
- b_fs::path marker = get_work_path() / C_MARKER_DEF_VALUE;
- if (!path_exists(marker.file_string().c_str())) {
+ FsPath marker = get_work_path();
+ marker.push(C_MARKER_DEF_VALUE);
+ if (!path_exists(marker)) {
// not marked. treat as success.
return true;
}
try {
- b_fs::remove(marker);
+ b_fs::remove(marker.path_cstr());
} catch (...) {
output_internal("failed to unmark default [%s]\n",
- get_work_path().file_string().c_str());
+ get_work_path().path_cstr());
return false;
}
return true;
@@ -689,30 +693,31 @@ UnionfsCstore::unmark_display_default()
bool
UnionfsCstore::marked_display_default(bool active_cfg)
{
- b_fs::path marker = (active_cfg ? get_active_path() : get_work_path())
- / C_MARKER_DEF_VALUE;
- return path_exists(marker.file_string().c_str());
+ FsPath marker = (active_cfg ? get_active_path() : get_work_path());
+ marker.push(C_MARKER_DEF_VALUE);
+ return path_exists(marker);
}
bool
UnionfsCstore::marked_deactivated(bool active_cfg)
{
- b_fs::path p = (active_cfg ? get_active_path() : get_work_path());
- b_fs::path marker = p / C_MARKER_DEACTIVATE;
- return path_exists(marker.file_string().c_str());
+ FsPath marker = (active_cfg ? get_active_path() : get_work_path());
+ marker.push(C_MARKER_DEACTIVATE);
+ return path_exists(marker);
}
bool
UnionfsCstore::mark_deactivated()
{
- b_fs::path marker = get_work_path() / C_MARKER_DEACTIVATE;
- if (path_exists(marker.file_string().c_str())) {
+ FsPath marker = get_work_path();
+ marker.push(C_MARKER_DEACTIVATE);
+ if (path_exists(marker)) {
// already marked. treat as success.
return true;
}
- if (!create_file(marker.file_string())) {
+ if (!create_file(marker)) {
output_internal("failed to mark deactivated [%s]\n",
- get_work_path().file_string().c_str());
+ get_work_path().path_cstr());
return false;
}
return true;
@@ -721,16 +726,17 @@ UnionfsCstore::mark_deactivated()
bool
UnionfsCstore::unmark_deactivated()
{
- b_fs::path marker = get_work_path() / C_MARKER_DEACTIVATE;
- if (!path_exists(marker.file_string().c_str())) {
+ FsPath marker = get_work_path();
+ marker.push(C_MARKER_DEACTIVATE);
+ if (!path_exists(marker)) {
// not deactivated. treat as success.
return true;
}
try {
- b_fs::remove(marker);
+ b_fs::remove(marker.path_cstr());
} catch (...) {
output_internal("failed to unmark deactivated [%s]\n",
- get_work_path().file_string().c_str());
+ get_work_path().path_cstr());
return false;
}
return true;
@@ -742,20 +748,21 @@ UnionfsCstore::unmark_deactivated_descendants()
bool ret = false;
do {
// sanity check
- if (!path_is_directory(get_work_path().file_string().c_str())) {
+ if (!path_is_directory(get_work_path())) {
break;
}
try {
vector<b_fs::path> markers;
- b_fs::recursive_directory_iterator di(get_work_path());
+ b_fs::recursive_directory_iterator di(get_work_path().path_cstr());
for (; di != b_fs::recursive_directory_iterator(); ++di) {
if (!path_is_regular(di->path().file_string().c_str())
|| di->path().filename() != C_MARKER_DEACTIVATE) {
// not marker
continue;
}
- if (di->path().parent_path() == get_work_path()) {
+ const char *ppath = di->path().parent_path().file_string().c_str();
+ if (strcmp(ppath, get_work_path().path_cstr()) == 0) {
// don't unmark the node itself
continue;
}
@@ -771,7 +778,7 @@ UnionfsCstore::unmark_deactivated_descendants()
} while (0);
if (!ret) {
output_internal("failed to unmark deactivated descendants [%s]\n",
- get_work_path().file_string().c_str());
+ get_work_path().path_cstr());
}
return ret;
}
@@ -780,29 +787,27 @@ UnionfsCstore::unmark_deactivated_descendants()
bool
UnionfsCstore::mark_changed_with_ancestors()
{
- b_fs::path opath = mutable_cfg_path; // use a copy
+ FsPath opath = mutable_cfg_path; // use a copy
bool done = false;
while (!done) {
- b_fs::path marker = work_root;
+ FsPath marker = work_root;
if (opath.has_parent_path()) {
marker /= opath;
pop_path(opath);
} else {
done = true;
}
- if (!path_exists(marker.file_string().c_str())
- || !path_is_directory(marker.file_string().c_str())) {
+ if (!path_exists(marker) || !path_is_directory(marker)) {
// don't do anything if the node is not there
continue;
}
- marker /= C_MARKER_CHANGED;
- if (path_exists(marker.file_string().c_str())) {
+ marker.push(C_MARKER_CHANGED);
+ if (path_exists(marker)) {
// reached a node already marked => done
break;
}
- if (!create_file(marker.file_string())) {
- output_internal("failed to mark changed [%s]\n",
- marker.file_string().c_str());
+ if (!create_file(marker)) {
+ output_internal("failed to mark changed [%s]\n", marker.path_cstr());
return false;
}
}
@@ -817,7 +822,7 @@ UnionfsCstore::unmark_changed_with_descendants()
{
try {
vector<b_fs::path> markers;
- b_fs::recursive_directory_iterator di(get_work_path());
+ b_fs::recursive_directory_iterator di(get_work_path().path_cstr());
for (; di != b_fs::recursive_directory_iterator(); ++di) {
if (!path_is_regular(di->path().file_string().c_str())
|| di->path().filename() != C_MARKER_CHANGED) {
@@ -831,7 +836,7 @@ UnionfsCstore::unmark_changed_with_descendants()
}
} catch (...) {
output_internal("failed to unmark changed with descendants [%s]\n",
- get_work_path().file_string().c_str());
+ get_work_path().path_cstr());
return false;
}
return true;
@@ -841,15 +846,15 @@ UnionfsCstore::unmark_changed_with_descendants()
bool
UnionfsCstore::remove_comment()
{
- b_fs::path cfile = get_work_path() / C_COMMENT_FILE;
- if (!path_exists(cfile.file_string().c_str())) {
+ FsPath cfile = get_work_path();
+ cfile.push(C_COMMENT_FILE);
+ if (!path_exists(cfile)) {
return false;
}
try {
- b_fs::remove(cfile);
+ b_fs::remove(cfile.path_cstr());
} catch (...) {
- output_internal("failed to remove comment [%s]\n",
- cfile.file_string().c_str());
+ output_internal("failed to remove comment [%s]\n", cfile.path_cstr());
return false;
}
return true;
@@ -859,8 +864,9 @@ UnionfsCstore::remove_comment()
bool
UnionfsCstore::set_comment(const string& comment)
{
- b_fs::path cfile = get_work_path() / C_COMMENT_FILE;
- return write_file(cfile.file_string(), comment);
+ FsPath cfile = get_work_path();
+ cfile.push(C_COMMENT_FILE);
+ return write_file(cfile, comment);
}
// discard all changes in working config
@@ -875,7 +881,7 @@ UnionfsCstore::discard_changes(unsigned long long& num_removed)
vector<b_fs::path> directories;
try {
// iterate through all entries in change root
- b_fs::directory_iterator di(change_root);
+ b_fs::directory_iterator di(change_root.path_cstr());
for (; di != b_fs::directory_iterator(); ++di) {
if (path_is_directory(di->path().file_string().c_str())) {
directories.push_back(di->path());
@@ -894,8 +900,7 @@ UnionfsCstore::discard_changes(unsigned long long& num_removed)
num_removed += b_fs::remove_all(directories[i]);
}
} catch (...) {
- output_internal("discard failed [%s]\n",
- change_root.file_string().c_str());
+ output_internal("discard failed [%s]\n", change_root.path_cstr());
ret = false;
}
@@ -911,8 +916,8 @@ UnionfsCstore::discard_changes(unsigned long long& num_removed)
bool
UnionfsCstore::get_comment(string& comment, bool active_cfg)
{
- b_fs::path cfile = (active_cfg ? get_active_path() : get_work_path());
- cfile /= C_COMMENT_FILE;
+ FsPath cfile = (active_cfg ? get_active_path() : get_work_path());
+ cfile.push(C_COMMENT_FILE);
return read_whole_file(cfile, comment);
}
@@ -920,8 +925,9 @@ UnionfsCstore::get_comment(string& comment, bool active_cfg)
bool
UnionfsCstore::cfg_node_changed()
{
- b_fs::path marker = get_work_path() / C_MARKER_CHANGED;
- return path_exists(marker.file_string().c_str());
+ FsPath marker = get_work_path();
+ marker.push(C_MARKER_CHANGED);
+ return path_exists(marker);
}
/* XXX currently "committed marking" is done inside commit.
@@ -934,14 +940,17 @@ UnionfsCstore::cfg_node_changed()
* be only one operation on the path).
*/
bool
-UnionfsCstore::marked_committed(const Ctemplate *def, bool is_set)
+UnionfsCstore::marked_committed(const tr1::shared_ptr<Ctemplate>& def,
+ bool is_set)
{
- b_fs::path cpath = mutable_cfg_path;
- string com_str = cpath.file_string() + "/";
+ FsPath cpath = mutable_cfg_path;
+ string com_str = cpath.path_cstr();
+ com_str += "/";
if (def->isLeafValue()) {
// path includes leaf value. construct the right string.
- string val = _unescape_path_name(cpath.filename());
- cpath = cpath.parent_path();
+ string val;
+ cpath.pop(val);
+ val = _unescape_path_name(val);
/* XXX current commit implementation escapes value strings for
* single-value nodes but not for multi-value nodes for some
* reason. the following match current behavior.
@@ -949,14 +958,17 @@ UnionfsCstore::marked_committed(const Ctemplate *def, bool is_set)
if (!def->isMulti()) {
val = _escape_path_name(val);
}
- com_str = cpath.file_string() + "/value:" + val;
+ com_str = cpath.path_cstr();
+ com_str += "/value:";
+ com_str += val;
}
com_str = (is_set ? "+ " : "- ") + com_str;
return committed_marker_exists(com_str);
}
bool
-UnionfsCstore::validate_val_impl(const Ctemplate *def, char *value)
+UnionfsCstore::validate_val_impl(const tr1::shared_ptr<Ctemplate>& def,
+ char *value)
{
/* XXX filesystem paths/accesses are completely embedded in var ref lib.
* for now, treat the lib as a unionfs-specific implementation.
@@ -971,16 +983,23 @@ UnionfsCstore::validate_val_impl(const Ctemplate *def, char *value)
}
void
-UnionfsCstore::get_edit_level(vector<string>& pcomps) {
- b_fs::path opath = mutable_cfg_path; // use a copy
+UnionfsCstore::get_edit_level(Cpath& pcomps) {
+ FsPath opath = mutable_cfg_path; // use a copy
+ vector<string> tmp;
while (opath.has_parent_path()) {
- pcomps.insert(pcomps.begin(), pop_path(opath));
+ string last;
+ pop_path(opath, last);
+ tmp.push_back(last);
+ }
+ while (tmp.size() > 0) {
+ pcomps.push(tmp.back());
+ tmp.pop_back();
}
}
string
UnionfsCstore::cfg_path_to_str() {
- string cpath = mutable_cfg_path.file_string();
+ string cpath = mutable_cfg_path.path_cstr();
if (cpath.length() == 0) {
cpath = "/";
}
@@ -990,8 +1009,8 @@ UnionfsCstore::cfg_path_to_str() {
string
UnionfsCstore::tmpl_path_to_str() {
// return only the mutable part
- string tpath = tmpl_path.file_string();
- tpath.erase(0, tmpl_root.file_string().length());
+ string tpath = tmpl_path.path_cstr();
+ tpath.erase(0, tmpl_root.length());
if (tpath.length() == 0) {
tpath = "/";
}
@@ -1001,33 +1020,35 @@ UnionfsCstore::tmpl_path_to_str() {
////// private functions
void
-UnionfsCstore::push_path(b_fs::path& old_path, const string& new_comp)
+UnionfsCstore::push_path(FsPath& old_path, const char *new_comp)
{
string comp = _escape_path_name(new_comp);
- old_path /= comp;
+ old_path.push(comp);
}
-string
-UnionfsCstore::pop_path(b_fs::path& path)
+void
+UnionfsCstore::pop_path(FsPath& path)
{
- string ret = _unescape_path_name(path.filename());
- /* note: contrary to documentation, remove_filename() does not remove
- * trailing slash.
- */
- path = path.parent_path();
- return ret;
+ path.pop();
}
void
-UnionfsCstore::get_all_child_dir_names(b_fs::path root, vector<string>& nodes)
+UnionfsCstore::pop_path(FsPath& path, string& last)
{
- if (!path_exists(root.file_string().c_str())
- || !path_is_directory(root.file_string().c_str())) {
+ path.pop(last);
+ last = _unescape_path_name(last);
+}
+
+void
+UnionfsCstore::get_all_child_dir_names(const FsPath& root,
+ vector<string>& nodes)
+{
+ if (!path_exists(root) || !path_is_directory(root)) {
// not a valid root. nop.
return;
}
try {
- b_fs::directory_iterator di(root);
+ b_fs::directory_iterator di(root.path_cstr());
for (; di != b_fs::directory_iterator(); ++di) {
// must be directory
if (!path_is_directory(di->path().file_string().c_str())) {
@@ -1047,7 +1068,7 @@ UnionfsCstore::get_all_child_dir_names(b_fs::path root, vector<string>& nodes)
}
bool
-UnionfsCstore::write_file(const string& file, const string& data)
+UnionfsCstore::write_file(const FsPath& file, const string& data)
{
if (data.size() > C_UNIONFS_MAX_FILE_SIZE) {
output_internal("write_file too large\n");
@@ -1055,13 +1076,14 @@ UnionfsCstore::write_file(const string& file, const string& data)
}
try {
// make sure the path exists
- b_fs::path fpath(file);
- b_fs::create_directories(fpath.parent_path());
+ FsPath ppath(file);
+ ppath.pop();
+ b_fs::create_directories(ppath.path_cstr());
// write the file
ofstream fout;
fout.exceptions(ofstream::failbit | ofstream::badbit);
- fout.open(file.c_str(), ios_base::out | ios_base::trunc);
+ fout.open(file.path_cstr(), ios_base::out | ios_base::trunc);
fout << data;
fout.close();
} catch (...) {
@@ -1071,23 +1093,22 @@ UnionfsCstore::write_file(const string& file, const string& data)
}
bool
-UnionfsCstore::read_whole_file(const b_fs::path& fpath, string& data)
+UnionfsCstore::read_whole_file(const FsPath& fpath, string& data)
{
/* must exist, be a regular file, and smaller than limit (we're going
* to read the whole thing).
*/
- if (!path_exists(fpath.file_string().c_str())
- || !path_is_regular(fpath.file_string().c_str())) {
+ if (!path_exists(fpath) || !path_is_regular(fpath)) {
return false;
}
try {
- if (b_fs::file_size(fpath) > C_UNIONFS_MAX_FILE_SIZE) {
+ if (b_fs::file_size(fpath.path_cstr()) > C_UNIONFS_MAX_FILE_SIZE) {
output_internal("read_whole_file too large\n");
return false;
}
stringbuf sbuf;
- ifstream fin(fpath.file_string().c_str());
+ ifstream fin(fpath.path_cstr());
fin >> &sbuf;
fin.close();
/* note: if file contains just a newline => (eof() && fail())
@@ -1132,22 +1153,21 @@ UnionfsCstore::committed_marker_exists(const string& marker)
* will throw exception (from b_fs) if fail.
*/
void
-UnionfsCstore::recursive_copy_dir(const b_fs::path& src, const b_fs::path& dst)
+UnionfsCstore::recursive_copy_dir(const FsPath& src, const FsPath& dst)
{
- string src_str = src.file_string();
- string dst_str = dst.file_string();
- b_fs::create_directory(dst);
+ string src_str = src.path_cstr();
+ string dst_str = dst.path_cstr();
+ b_fs::create_directory(dst.path_cstr());
- b_fs::recursive_directory_iterator di(src);
+ b_fs::recursive_directory_iterator di(src_str);
for (; di != b_fs::recursive_directory_iterator(); ++di) {
- b_fs::path opath = di->path();
- string nname = opath.file_string();
+ const char *oname = di->path().file_string().c_str();
+ string nname = oname;
nname.replace(0, src_str.length(), dst_str);
- b_fs::path npath = nname;
- if (path_is_directory(opath.file_string().c_str())) {
- b_fs::create_directory(npath);
+ if (path_is_directory(oname)) {
+ b_fs::create_directory(nname);
} else {
- b_fs::copy_file(opath, npath);
+ b_fs::copy_file(oname, nname);
}
}
}
@@ -1182,3 +1202,6 @@ UnionfsCstore::path_is_regular(const char *path)
return b_fs::is_regular(result);
}
+} // end namespace unionfs
+} // end namespace cstore
+
diff --git a/src/cstore/unionfs/cstore-unionfs.hpp b/src/cstore/unionfs/cstore-unionfs.hpp
index 53c6396..afb65a6 100644
--- a/src/cstore/unionfs/cstore-unionfs.hpp
+++ b/src/cstore/unionfs/cstore-unionfs.hpp
@@ -28,8 +28,10 @@
#include <cli_cstore.h>
#include <cstore/cstore.hpp>
+#include <cstore/unionfs/fspath.hpp>
namespace cstore { // begin namespace cstore
+namespace unionfs { // begin namespace unionfs
namespace b_fs = boost::filesystem;
namespace b_s = boost::system;
@@ -80,21 +82,19 @@ private:
static const size_t C_UNIONFS_MAX_FILE_SIZE = 262144;
// root dirs (constant)
- b_fs::path work_root; // working root (union)
- b_fs::path active_root; // active root (readonly part of union)
- b_fs::path change_root; // change root (r/w part of union)
- b_fs::path tmp_root; // temp root
- b_fs::path tmpl_root; // template root
+ FsPath work_root; // working root (union)
+ FsPath active_root; // active root (readonly part of union)
+ FsPath change_root; // change root (r/w part of union)
+ FsPath tmp_root; // temp root
+ FsPath tmpl_root; // template root
// path buffers
- b_fs::path mutable_cfg_path; // mutable part of config path
- b_fs::path tmpl_path; // whole template path
- Cstore::MapT<const void *, pair<b_fs::path, b_fs::path> > saved_paths;
- // saved mutable part of cfg path and whole template path
+ FsPath mutable_cfg_path; // mutable part of config path
+ FsPath tmpl_path; // whole template path
////// virtual functions defined in base class
// begin path modifiers
- void push_tmpl_path(const string& new_comp) {
+ void push_tmpl_path(const char *new_comp) {
push_path(tmpl_path, new_comp);
};
void push_tmpl_path_tag() {
@@ -105,18 +105,24 @@ private:
* however, since current C_TAG_NAME doesn't contain any escape
* sequences, this cannot happen for now.
*/
- tmpl_path /= C_TAG_NAME;
+ tmpl_path.push(C_TAG_NAME);
};
- string pop_tmpl_path() {
- return pop_path(tmpl_path);
+ void pop_tmpl_path() {
+ pop_path(tmpl_path);
};
- void push_cfg_path(const string& new_comp) {
+ void pop_tmpl_path(string& last) {
+ pop_path(tmpl_path, last);
+ };
+ void push_cfg_path(const char *new_comp) {
push_path(mutable_cfg_path, new_comp);
};
- string pop_cfg_path() {
- return pop_path(mutable_cfg_path);
+ void pop_cfg_path() {
+ pop_path(mutable_cfg_path);
+ };
+ void pop_cfg_path(string& last) {
+ pop_path(mutable_cfg_path, last);
};
- void append_cfg_path(const vector<string>& path_comps) {
+ void append_cfg_path(const Cpath& path_comps) {
for (size_t i = 0; i < path_comps.size(); i++) {
push_cfg_path(path_comps[i]);
}
@@ -125,27 +131,31 @@ private:
tmpl_path = tmpl_root;
mutable_cfg_path = "";
};
- void save_paths(const void *handle = NULL) {
- pair<b_fs::path, b_fs::path> p;
- p.first = mutable_cfg_path;
- p.second = tmpl_path;
- saved_paths[handle] = p;
- };
- void restore_paths(const void *handle = NULL) {
- Cstore::MapT<const void *, pair<b_fs::path, b_fs::path> >::iterator it
- = saved_paths.find(handle);
- if (it == saved_paths.end()) {
- exit_internal("restore_paths: handle not found\n");
- }
- pair<b_fs::path, b_fs::path> p = it->second;
- mutable_cfg_path = p.first;
- tmpl_path = p.second;
+
+ class UnionfsSavePaths : public SavePaths {
+ public:
+ UnionfsSavePaths(UnionfsCstore *cs)
+ : cstore(cs), cpath(cs->mutable_cfg_path), tpath(cs->tmpl_path) {};
+
+ ~UnionfsSavePaths() {
+ cstore->mutable_cfg_path = cpath;
+ cstore->tmpl_path = tpath;
+ };
+
+ private:
+ UnionfsCstore *cstore;
+ FsPath cpath;
+ FsPath tpath;
};
+ auto_ptr<SavePaths> create_save_paths() {
+ return auto_ptr<SavePaths>(new UnionfsSavePaths(this));
+ };
+
bool cfg_path_at_root() {
return (!mutable_cfg_path.has_parent_path());
};
bool tmpl_path_at_root() {
- return (tmpl_path.file_string() == tmpl_root.file_string());
+ return (tmpl_path == tmpl_root);
};
// end path modifiers
@@ -161,8 +171,8 @@ private:
get_all_child_dir_names(tmpl_path, cnodes);
};
bool write_value_vec(const vector<string>& vvec, bool active_cfg);
- bool rename_child_node(const string& oname, const string& nname);
- bool copy_child_node(const string& oname, const string& nname);
+ bool rename_child_node(const char *oname, const char *nname);
+ bool copy_child_node(const char *oname, const char *nname);
bool mark_display_default();
bool unmark_display_default();
bool mark_deactivated();
@@ -185,10 +195,10 @@ private:
bool marked_display_default(bool active_cfg);
// observers during commit operation
- bool marked_committed(const Ctemplate *def, bool is_set);
+ bool marked_committed(const tr1::shared_ptr<Ctemplate>& def, bool is_set);
// these operate on both current tmpl and work paths
- bool validate_val_impl(const Ctemplate *def, char *value);
+ bool validate_val_impl(const tr1::shared_ptr<Ctemplate>& def, char *value);
// observers for "edit/tmpl levels" (for "edit"-related operations).
// note that these should be moved to base class in the future.
@@ -198,7 +208,7 @@ private:
string get_tmpl_level_path() {
return tmpl_path_to_str();
};
- void get_edit_level(vector<string>& path_comps);
+ void get_edit_level(Cpath& path_comps);
bool edit_level_at_root() {
return cfg_path_at_root();
};
@@ -208,19 +218,20 @@ private:
string tmpl_path_to_str();
////// private functions
- b_fs::path get_work_path() { return (work_root / mutable_cfg_path); };
- b_fs::path get_active_path() { return (active_root / mutable_cfg_path); };
- b_fs::path get_change_path() { return (change_root / mutable_cfg_path); };
- void push_path(b_fs::path& old_path, const string& new_comp);
- string pop_path(b_fs::path& path);
- void get_all_child_dir_names(b_fs::path root, vector<string>& nodes);
- bool write_file(const string& file, const string& data);
- bool create_file(const string& file) {
+ FsPath get_work_path() { return (work_root / mutable_cfg_path); };
+ FsPath get_active_path() { return (active_root / mutable_cfg_path); };
+ FsPath get_change_path() { return (change_root / mutable_cfg_path); };
+ void push_path(FsPath& old_path, const char *new_comp);
+ void pop_path(FsPath& path);
+ void pop_path(FsPath& path, string& last);
+ void get_all_child_dir_names(const FsPath& root, vector<string>& nodes);
+ bool write_file(const FsPath& file, const string& data);
+ bool create_file(const FsPath& file) {
return write_file(file, "");
};
- bool read_whole_file(const b_fs::path& file, string& data);
+ bool read_whole_file(const FsPath& file, string& data);
bool committed_marker_exists(const string& marker);
- void recursive_copy_dir(const b_fs::path& src, const b_fs::path& dst);
+ void recursive_copy_dir(const FsPath& src, const FsPath& dst);
// boost fs operations wrappers
bool b_fs_get_file_status(const char *path, b_fs::file_status& fs) {
@@ -229,10 +240,20 @@ private:
return (!ec);
};
bool path_exists(const char *path);
+ bool path_exists(const FsPath& path) {
+ return path_exists(path.path_cstr());
+ };
bool path_is_directory(const char *path);
+ bool path_is_directory(const FsPath& path) {
+ return path_is_directory(path.path_cstr());
+ };
bool path_is_regular(const char *path);
+ bool path_is_regular(const FsPath& path) {
+ return path_is_regular(path.path_cstr());
+ };
};
+} // end namespace unionfs
} // end namespace cstore
#endif /* _CSTORE_UNIONFS_H_ */
diff --git a/src/cstore/unionfs/fspath.hpp b/src/cstore/unionfs/fspath.hpp
new file mode 100644
index 0000000..35985ed
--- /dev/null
+++ b/src/cstore/unionfs/fspath.hpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2011 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 _FSPATH_HPP_
+#define _FSPATH_HPP_
+#include <string>
+
+#include <cstore/svector.hpp>
+
+namespace cstore { // begin namespace cstore
+namespace unionfs { // begin namespace unionfs
+
+class FsPath {
+public:
+ FsPath() : _data() {};
+ explicit FsPath(const char *full_path) : _data() { operator=(full_path); };
+ explicit FsPath(const std::string& full_path) : _data() {
+ operator=(full_path);
+ };
+ FsPath(const FsPath& p) : _data() { operator=(p); };
+ ~FsPath() {};
+
+ void push(const char *comp) { _data.push_back(comp); };
+ void push(const std::string& comp) { _data.push_back(comp.c_str()); };
+ void pop() { _data.pop_back(); };
+ void pop(std::string& last) { _data.pop_back(last); };
+
+ FsPath& operator=(const char *full_path) {
+ _data = full_path;
+ return *this;
+ };
+ FsPath& operator=(const std::string& full_path) {
+ _data = full_path;
+ return *this;
+ };
+ FsPath& operator=(const FsPath& p) {
+ _data = p._data;
+ return *this;
+ };
+ FsPath& operator/=(const FsPath& p) {
+ _data /= p._data;
+ return *this;
+ }
+ FsPath operator/(const FsPath& rhs) {
+ FsPath lhs(*this);
+ lhs /= rhs;
+ return lhs;
+ };
+
+ bool operator==(const FsPath& rhs) const {
+ return (_data == rhs._data);
+ };
+
+ size_t length() const { return _data.length(); };
+ bool has_parent_path() const { return (_data.size() > 0); };
+ const char *path_cstr() const { return _data.get_cstr(); };
+ size_t hash() const { return _data.hash(); };
+
+private:
+ struct FsPathParams {
+ static const char separator = '/';
+ static const size_t static_num_elems = 24;
+ static const size_t static_buf_len = 256;
+ };
+
+ cstore::svector<FsPathParams> _data;
+};
+
+struct FsPathHash {
+ inline size_t operator()(const FsPath& p) const {
+ return p.hash();
+ };
+};
+
+} // end namespace unionfs
+} // end namespace cstore
+
+#endif /* _FSPATH_HPP_ */
+