[augeas-devel] [PATCH] Add API function aug_node_count to compute the subtree size

Francis Giraldeau francis.giraldeau at gmail.com
Mon Jan 24 02:07:08 UTC 2011


The new function aug_node_count computes the subtree size corresponding to a
given path expression. The count includes all descendants.

  * src/augeas.c : new API call implementation.
  * src/augeas_sym.version : export symbol
  * src/augtool.c : new command "count" to augtool
  * tests/test-api.c : unittests
---
 src/augeas.c           |   35 +++++++++++++++++++++++++++++++++++
 src/augeas.h           |   10 ++++++++++
 src/augeas_sym.version |    5 +++++
 src/augtool.c          |   24 ++++++++++++++++++++++++
 src/internal.h         |    2 ++
 tests/test-api.c       |   17 +++++++++++++++++
 6 files changed, 93 insertions(+), 0 deletions(-)

diff --git a/src/augeas.c b/src/augeas.c
index 25ca016..e03f02e 100644
--- a/src/augeas.c
+++ b/src/augeas.c
@@ -173,6 +173,14 @@ void tree_store_value(struct tree *tree, char **value) {
     tree_mark_dirty(tree);
 }
 
+int tree_size(struct tree *tree) {
+    int size = 1;
+    list_for_each(c, tree->children) {
+        size += tree_size(c);
+    }
+    return size;
+}
+
 int tree_set_value(struct tree *tree, const char *value) {
     char *v = NULL;
 
@@ -1350,6 +1358,33 @@ int aug_print(const struct augeas *aug, FILE *out, const char *pathin) {
     return -1;
 }
 
+int aug_node_count(const struct augeas *aug, const char *path) {
+    struct pathx *p;
+    struct tree *tree;
+    int r = 0;
+
+    api_entry(aug);
+
+    if (path == NULL || strlen(path) == 0) {
+        path = "/*";
+    }
+
+    p = pathx_aug_parse(aug, aug->origin, path, true);
+    ERR_BAIL(aug);
+
+    for (tree = pathx_first(p); tree != NULL; tree = pathx_next(p)) {
+        r += tree_size(tree);
+    }
+
+    free_pathx(p);
+
+    api_exit(aug);
+    return r;
+ error:
+    api_exit(aug);
+    return -1;
+}
+
 void aug_close(struct augeas *aug) {
     if (aug == NULL)
         return;
diff --git a/src/augeas.h b/src/augeas.h
index b4848cb..aa42b5a 100644
--- a/src/augeas.h
+++ b/src/augeas.h
@@ -276,6 +276,16 @@ int aug_load(augeas *aug);
  */
 int aug_print(const augeas *aug, FILE *out, const char *path);
 
+/* Function: aug_node_count
+ *
+ * Get the number of nodes in an augeas tree.
+ *
+ * Returns:
+ * number of nodes of the tree under PATH on success, or a negative value
+ * on failure
+ */
+int aug_node_count(const augeas *aug, const char *path);
+
 /* Function: aug_close
  *
  * Close this Augeas instance and free any storage associated with
diff --git a/src/augeas_sym.version b/src/augeas_sym.version
index 542f5fa..6dc1a8b 100644
--- a/src/augeas_sym.version
+++ b/src/augeas_sym.version
@@ -34,3 +34,8 @@ AUGEAS_0.11.0 {
     global:
       aug_setm;
 } AUGEAS_0.10.0;
+
+AUGEAS_0.12.0 {
+    global:
+      aug_node_count;
+} AUGEAS_0.11.0;
diff --git a/src/augtool.c b/src/augtool.c
index 7de8e9d..745e841 100644
--- a/src/augtool.c
+++ b/src/augtool.c
@@ -807,6 +807,29 @@ static const struct command_def cmd_print_def = {
     .help = "Print entries in the tree.  If PATH is given, printing starts there,\n otherwise the whole tree is printed"
 };
 
+static void cmd_node_count(struct command *cmd) {
+    const char *path = arg_value(cmd, "path");
+    int size;
+
+    size = aug_node_count(aug, path);
+    err_check(cmd);
+    printf("tree size: %d\n", size);
+}
+
+static const struct command_opt_def cmd_node_count_opts[] = {
+    { .type = CMD_PATH, .name = "path", .optional = true,
+      .help = "get the number of nodes of this subtree" },
+    CMD_OPT_DEF_LAST
+};
+
+static const struct command_def cmd_size_def = {
+    .name = "count",
+    .opts = cmd_node_count_opts,
+    .handler = cmd_node_count,
+    .synopsis = "size of this subtree",
+    .help = "Print the size of this tree.  If PATH is given, returns the size of the subtree there,\n otherwise, returns the size of the whole tree"
+};
+
 static void cmd_save(struct command *cmd) {
     int r;
     r = aug_save(aug);
@@ -966,6 +989,7 @@ static const struct command_def const *commands[] = {
     &cmd_match_def,
     &cmd_mv_def,
     &cmd_print_def,
+    &cmd_size_def,
     &cmd_rm_def,
     &cmd_save_def,
     &cmd_set_def,
diff --git a/src/internal.h b/src/internal.h
index 71c5d42..5289336 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -407,6 +407,8 @@ struct tree *tree_find(struct augeas *aug, const char *path);
  * Returns the node or NULL on error
  */
 struct tree *tree_find_cr(struct augeas *aug, const char *path);
+/* Get the size of this tree */
+int tree_size(struct tree *tree);
 
 /* Struct: memstream
  * Wrappers to simulate OPEN_MEMSTREAM where that's not available. The
diff --git a/tests/test-api.c b/tests/test-api.c
index 322f4a9..4ae21ac 100644
--- a/tests/test-api.c
+++ b/tests/test-api.c
@@ -222,6 +222,22 @@ static void testDefNodeCreateMeta(CuTest *tc) {
     aug_close(aug);
 }
 
+static void testTreeSize(CuTest *tc) {
+    int s1, s2, s3;
+    struct augeas *aug;
+
+    aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_LOAD);
+    CuAssertPtrNotNull(tc, aug);
+
+    s1 = aug_node_count(aug, "/augeas/version");
+    CuAssertIntEquals(tc, 8, s1);
+
+    s1 = aug_node_count(aug, "/");
+    s2 = aug_node_count(aug, "/augeas");
+    s3 = aug_node_count(aug, "/files");
+    CuAssertIntEquals(tc, s1, s2 + s3 + 1);
+}
+
 int main(void) {
     char *output = NULL;
     CuSuite* suite = CuSuiteNew();
@@ -232,6 +248,7 @@ int main(void) {
     SUITE_ADD_TEST(suite, testDefVarMeta);
     SUITE_ADD_TEST(suite, testDefNodeExistingMeta);
     SUITE_ADD_TEST(suite, testDefNodeCreateMeta);
+    SUITE_ADD_TEST(suite, testTreeSize);
 
     abs_top_srcdir = getenv("abs_top_srcdir");
     if (abs_top_srcdir == NULL)
-- 
1.7.1




More information about the augeas-devel mailing list