ofp-actions: Assert variable actions have len>0.
[cascardo/ovs.git] / lib / smap.c
index 642804e..07dd23a 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012 Nicira, Inc.
+/* Copyright (c) 2012, 2014, 2015 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <config.h>
 #include "smap.h"
 
-#include <assert.h>
+#include <strings.h>
 
 #include "hash.h"
+#include "json.h"
+#include "packets.h"
+#include "uuid.h"
 
 static struct smap_node *smap_add__(struct smap *, char *, void *,
                                     size_t hash);
@@ -52,6 +55,15 @@ smap_add(struct smap *smap, const char *key, const char *value)
                       hash_bytes(key, key_len, 0));
 }
 
+/* Adds 'key' paired with 'value' to 'smap'.  Takes ownership of 'key' and
+ * 'value' (which will eventually be freed with free()).  It is the caller's
+ * responsibility to avoid duplicate keys if desirable. */
+struct smap_node *
+smap_add_nocopy(struct smap *smap, char *key, char *value)
+{
+    return smap_add__(smap, key, value, hash_bytes(key, strlen(key), 0));
+}
+
 /* Attempts to add 'key' to 'smap' associated with 'value'.  If 'key' already
  * exists in 'smap', does nothing and returns false.  Otherwise, performs the
  * addition and returns true. */
@@ -84,6 +96,16 @@ smap_add_format(struct smap *smap, const char *key, const char *format, ...)
                hash_bytes(key, key_len, 0));
 }
 
+/* Adds 'key' paired with a string representation of 'addr'. It is the
+ * caller's responsibility to avoid duplicate keys if desirable. */
+void
+smap_add_ipv6(struct smap *smap, const char *key, struct in6_addr *addr)
+{
+    char buf[INET6_ADDRSTRLEN];
+    ipv6_string_mapped(buf, addr);
+    smap_add(smap, key, buf);
+}
+
 /* Searches for 'key' in 'smap'.  If it does not already exists, adds it.
  * Otherwise, changes its value to 'value'. */
 void
@@ -124,6 +146,31 @@ smap_remove_node(struct smap *smap, struct smap_node *node)
     free(node);
 }
 
+/* Deletes 'node' from 'smap'.
+ *
+ * If 'keyp' is nonnull, stores the node's key in '*keyp' and transfers
+ * ownership to the caller.  Otherwise, frees the node's key.  Similarly for
+ * 'valuep' and the node's value. */
+void
+smap_steal(struct smap *smap, struct smap_node *node,
+           char **keyp, char **valuep)
+{
+    if (keyp) {
+        *keyp = node->key;
+    } else {
+        free(node->key);
+    }
+
+    if (valuep) {
+        *valuep = node->value;
+    } else {
+        free(node->value);
+    }
+
+    hmap_remove(&smap->map, &node->node);
+    free(node);
+}
+
 /* Removes all key-value pairs from 'smap'. */
 void
 smap_clear(struct smap *smap)
@@ -180,6 +227,16 @@ smap_get_int(const struct smap *smap, const char *key, int def)
     return value ? atoi(value) : def;
 }
 
+/* Gets the value associated with 'key' in 'smap' and converts it to a UUID
+ * using uuid_from_string().  Returns true if successful, false if 'key' is not
+ * in 'smap' or if 'key' does not have the correct syntax for a UUID. */
+bool
+smap_get_uuid(const struct smap *smap, const char *key, struct uuid *uuid)
+{
+    const char *value = smap_get(smap, key);
+    return value && uuid_from_string(uuid, value);
+}
+
 /* Returns true of there are no elements in 'smap'. */
 bool
 smap_is_empty(const struct smap *smap)
@@ -196,9 +253,9 @@ smap_count(const struct smap *smap)
 
 /* Initializes 'dst' as a clone of 'src. */
 void
-smap_clone(struct smap *dst, struct smap *src)
+smap_clone(struct smap *dst, const struct smap *src)
 {
-    struct smap_node *node;
+    const struct smap_node *node;
 
     smap_init(dst);
     SMAP_FOR_EACH (node, src) {
@@ -225,13 +282,68 @@ smap_sort(const struct smap *smap)
         SMAP_FOR_EACH (node, smap) {
             nodes[i++] = node;
         }
-        assert(i == n);
+        ovs_assert(i == n);
 
         qsort(nodes, n, sizeof *nodes, compare_nodes_by_key);
 
         return nodes;
     }
 }
+
+/* Adds each of the key-value pairs from 'json' (which must be a JSON object
+ * whose values are strings) to 'smap'.
+ *
+ * The caller must have initialized 'smap'.
+ *
+ * The caller retains ownership of 'json' and everything in it. */
+void
+smap_from_json(struct smap *smap, const struct json *json)
+{
+    const struct shash_node *node;
+
+    SHASH_FOR_EACH (node, json_object(json)) {
+        const struct json *value = node->data;
+        smap_add(smap, node->name, json_string(value));
+    }
+}
+
+/* Returns a JSON object that maps from the keys in 'smap' to their values.
+ *
+ * The caller owns the returned value and must eventually json_destroy() it.
+ *
+ * The caller retains ownership of 'smap' and everything in it. */
+struct json *
+smap_to_json(const struct smap *smap)
+{
+    const struct smap_node *node;
+    struct json *json;
+
+    json = json_object_create();
+    SMAP_FOR_EACH (node, smap) {
+        json_object_put_string(json, node->key, node->value);
+    }
+    return json;
+}
+
+/* Returns true if the two maps are equal, meaning that they have the same set
+ * of key-value pairs.
+ */
+bool
+smap_equal(const struct smap *smap1, const struct smap *smap2)
+{
+    if (smap_count(smap1) != smap_count(smap2)) {
+        return false;
+    }
+
+    const struct smap_node *node;
+    SMAP_FOR_EACH (node, smap1) {
+        const char *value2 = smap_get(smap2, node->key);
+        if (!value2 || strcmp(node->value, value2)) {
+            return false;
+        }
+    }
+    return true;
+}
 \f
 /* Private Helpers. */