Revision: 74169
          http://sourceforge.net/p/brlcad/code/74169
Author:   starseeker
Date:     2019-10-17 22:09:10 +0000 (Thu, 17 Oct 2019)
Log Message:
-----------
Extend the attr list subcommand to optionally accept key and value filters, to 
allow for summary printing not just of all the attributes in a .g, but all the 
unique key/value assignments.  This, for example, can be used to get a listing 
of all unique material_id values in a database.

Modified Paths:
--------------
    brlcad/trunk/src/libged/attr.cpp

Modified: brlcad/trunk/src/libged/attr.cpp
===================================================================
--- brlcad/trunk/src/libged/attr.cpp    2019-10-17 21:16:00 UTC (rev 74168)
+++ brlcad/trunk/src/libged/attr.cpp    2019-10-17 22:09:10 UTC (rev 74169)
@@ -25,9 +25,12 @@
 
 #include "common.h"
 
+#include <set>
 #include <string.h>
+#include <stdlib.h>
 
 #include "bu/getopt.h"
+#include "bu/path.h"
 #include "bu/sort.h"
 #include "./ged_private.h"
 
@@ -147,6 +150,94 @@
        return ATTR_UNKNOWN;
 }
 
+struct avsncmp {
+    bool operator () (const std::pair<std::string, std::string> &p_left, const 
std::pair<std::string, std::string> &p_right)
+    {
+       long l1, l2;
+       char *endptr = NULL;
+       if (p_left.first != p_right.first) {
+           return p_left < p_right;
+       }
+       errno = 0;
+       endptr = NULL;
+       l1 = strtol(p_left.second.c_str(), &endptr, 0);
+       if (endptr != NULL && strlen(endptr) > 0) {
+           return p_left < p_right;
+       }
+       errno = 0;
+       endptr = NULL;
+       l2 = strtol(p_right.second.c_str(), &endptr, 0);
+       if (endptr != NULL && strlen(endptr) > 0) {
+           return p_left < p_right;
+       }
+       return l1 < l2;
+    }
+};
+
+static int
+attr_list(struct ged *gedp, size_t path_cnt, struct directory **paths, int 
argc, const char **argv)
+{
+    if (argc > 2) {
+       bu_vls_printf(gedp->ged_result_str, "Usage: attr list obj_pattern 
[key_pattern [value_pattern]]");
+       return GED_HELP;
+    }
+    struct bu_attribute_value_pair *avpp;
+    std::set<std::pair<std::string, std::string>, avsncmp> uniq_avp;
+    for (size_t i = 0; i < path_cnt; i++) {
+       struct directory *dp = paths[i];
+       struct bu_attribute_value_set lavs;
+       bu_avs_init_empty(&lavs);
+       if (db5_get_attributes(gedp->ged_wdbp->dbip, &lavs, dp)) {
+           bu_vls_printf(gedp->ged_result_str, "Cannot get attributes for 
object %s\n", dp->d_namep);
+           bu_avs_free(&lavs);
+           return GED_ERROR;
+       }
+       size_t j = 0;
+       for (j = 0, avpp = lavs.avp; j < lavs.count; j++, avpp++) {
+           /* If we have a key-only filter, filter printing based on matching
+            * to that filter.  If we also have a value filter, print the value 
as well according to value
+            * matches. */
+           if (!argc) {
+               uniq_avp.insert(std::make_pair(std::string(avpp->name), 
std::string("")));
+               continue;
+           }
+           if (argc == 1) {
+               if (!bu_path_match(argv[0], avpp->name, 0)) {
+                   uniq_avp.insert(std::make_pair(std::string(avpp->name), 
std::string("")));
+               }
+               continue;
+           }
+           if (argc == 2) {
+               if (!bu_path_match(argv[0], avpp->name, 0) && 
!bu_path_match(argv[1], avpp->value, 0)) {
+                   uniq_avp.insert(std::make_pair(std::string(avpp->name), 
std::string(avpp->value)));
+               }
+               continue;
+           }
+       }
+       bu_avs_free(&lavs);
+    }
+    /* List all the attributes. */
+    std::set<std::pair<std::string, std::string>>::iterator u_it;
+    for (u_it = uniq_avp.begin(); u_it != uniq_avp.end(); u_it++) {
+       if (!argc) {
+           bu_vls_printf(gedp->ged_result_str, "%s\n", u_it->first.c_str());
+           continue;
+       }
+       if (argc == 1) {
+           bu_vls_printf(gedp->ged_result_str, "%s\n", u_it->first.c_str());
+           continue;
+       }
+       if (argc == 2) {
+           bu_vls_printf(gedp->ged_result_str, "%s=%s\n", u_it->first.c_str(), 
u_it->second.c_str());
+           continue;
+       }
+    }
+
+    return GED_OK;
+}
+ 
+
+
 HIDDEN void
 attr_print(struct ged *gedp, struct bu_attribute_value_set *avs, int argc, 
const char **argv)
 {
@@ -437,28 +528,9 @@
            }
        }
     } else if (scmd == ATTR_LIST) {
-       struct bu_attribute_value_set avs;
-       bu_avs_init_empty(&avs);
 
-       for (i = 0; i < path_cnt; i++) {
-           struct bu_attribute_value_set lavs;
-           bu_avs_init_empty(&lavs);
-           dp = paths[i];
-           if (db5_get_attributes(gedp->ged_wdbp->dbip, &lavs, dp)) {
-               bu_vls_printf(gedp->ged_result_str, "Cannot get attributes for 
object %s\n", dp->d_namep);
-               ret = GED_ERROR;
-               goto ged_attr_memfree;
-           }
-           bu_avs_merge(&avs, &lavs);
-           bu_avs_free(&lavs);
-       }
-       /* Now that we have them all, sort */
-       bu_sort(&avs.avp[0], avs.count, sizeof(struct bu_attribute_value_pair), 
attr_cmp, NULL);
-       /* list all the attributes */
-       for (i = 0, avpp = avs.avp; i < avs.count; i++, avpp++) {
-           bu_vls_printf(gedp->ged_result_str, "%s\n", avpp->name);
-       }
-       bu_avs_free(&avs);
+       return attr_list(gedp, path_cnt, paths, argc - 3, &(argv[3]));
+
     } else if (scmd == ATTR_COPY) {
        const char *oattr, *nattr;
 

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.



_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits

Reply via email to