added some instructions for exp-tool/Makefile
[sliver-openvswitch.git] / ovsdb / ovsdb-idlc.in
index 3392c35..dfde735 100755 (executable)
@@ -25,10 +25,14 @@ def constify(cType, const):
     else:
         return cType
 
+def is_string_map(column):
+    return (column.type.key
+            and column.type.value
+            and column.type.key.type == ovs.db.types.StringType
+            and column.type.value.type == ovs.db.types.StringType)
+
 def cMembers(prefix, columnName, column, const):
     type = column.type
-    if is_optional_bool(type):
-        const = True
     if type.n_min == 1 and type.n_max == 1:
         singleton = True
         pointer = ''
@@ -142,6 +146,15 @@ struct %(s)s *%(s)s_insert(struct ovsdb_idl_txn *);
                     in cMembers(prefix, columnName, column, True)]
             print '%s);' % ', '.join(args)
 
+        print
+        for columnName, column in sorted(table.columns.iteritems()):
+            if not is_string_map(column):
+                continue
+            print "const char *%(s)s_get_%(c)s_value(const struct %(s)s *," \
+                    " const char *key, const char *default_value);" \
+                    % {'s': structName, 'c': columnName}
+
+
     # Table indexes.
     printEnum(["%sTABLE_%s" % (prefix.upper(), tableName.upper()) for tableName in sorted(schema.tables)] + ["%sN_TABLES" % prefix.upper()])
     print
@@ -167,10 +180,6 @@ def printEnum(members):
     print "    %s" % members[-1]
     print "};"
 
-def is_optional_bool(type):
-    return (type.key.type == ovs.db.types.BooleanType and not type.value
-            and type.n_min == 0 and type.n_max == 1)
-
 def printCIDLSource(schemaFile):
     schema = parseSchema(schemaFile)
     prefix = schema.idlPrefix
@@ -184,9 +193,32 @@ def printCIDLSource(schemaFile):
 #include "ovsdb-data.h"
 #include "ovsdb-error.h"
 
+#ifdef __CHECKER__
+/* Sparse dislikes sizeof(bool) ("warning: expression using sizeof bool"). */
+enum { sizeof_bool = 1 };
+#else
+enum { sizeof_bool = sizeof(bool) };
+#endif
+
 static bool inited;
 ''' % schema.idlHeader
 
+    try:
+        for table in schema.tables.itervalues():
+            for column in table.columns.itervalues():
+                if is_string_map(column):
+                    print """\
+static int
+bsearch_strcmp(const void *a_, const void *b_)
+{
+    char *const *a = a_;
+    char *const *b = b_;
+    return strcmp(*a, *b);
+}"""
+                    raise StopIteration
+    except StopIteration:
+        pass
+
     # Cast functions.
     for tableName, table in sorted(schema.tables.iteritems()):
         structName = "%s%s" % (prefix, tableName.lower())
@@ -221,23 +253,7 @@ static void
                 keyVar = "row->%s" % columnName
                 valueVar = None
 
-            if is_optional_bool(type):
-                # Special case for an optional bool.  This is only here because
-                # sparse does not like the "normal" case below ("warning:
-                # expression using sizeof bool").
-                print
-                print "    assert(inited);"
-                print "    if (datum->n >= 1) {"
-                print "        static const bool false_value = false;"
-                print "        static const bool true_value = true;"
-                print
-                print "        row->n_%s = 1;" % columnName
-                print "        %s = datum->keys[0].boolean ? &true_value : &false_value;" % keyVar
-                print "    } else {"
-                print "        row->n_%s = 0;" % columnName
-                print "        %s = NULL;" % keyVar
-                print "    }"
-            elif (type.n_min == 1 and type.n_max == 1) or type.is_optional_pointer():
+            if (type.n_min == 1 and type.n_max == 1) or type.is_optional_pointer():
                 print
                 print "    assert(inited);"
                 print "    if (datum->n >= 1) {"
@@ -289,9 +305,24 @@ static void
                 else:
                     indent = "        "
                 print "%sif (!row->n_%s) {" % (indent, columnName)
-                print "%s    %s = xmalloc(%s * sizeof *%s);" % (indent, keyVar, nMax, keyVar)
+
+                # Special case for boolean types.  This is only here because
+                # sparse does not like the "normal" case ("warning: expression
+                # using sizeof bool").
+                if type.key.type == ovs.db.types.BooleanType:
+                    sizeof = "sizeof_bool"
+                else:
+                    sizeof = "sizeof *%s" % keyVar
+                print "%s    %s = xmalloc(%s * %s);" % (indent, keyVar, nMax,
+                                                        sizeof)
                 if valueVar:
-                    print "%s    %s = xmalloc(%s * sizeof *%s);" % (indent, valueVar, nMax, valueVar)
+                    # Special case for boolean types (see above).
+                    if type.value.type == ovs.db.types.BooleanType:
+                        sizeof = " * sizeof_bool"
+                    else:
+                        sizeof = "sizeof *%s" % valueVar
+                    print "%s    %s = xmalloc(%s * %s);" % (indent, valueVar,
+                                                            nMax, sizeof)
                 print "%s}" % indent
                 print "%s%s[row->n_%s] = %s;" % (indent, keyVar, columnName, keySrc)
                 if valueVar:
@@ -305,15 +336,7 @@ static void
         # Unparse functions.
         for columnName, column in sorted(table.columns.iteritems()):
             type = column.type
-            if (type.key.type == ovs.db.types.BooleanType and not type.value
-                and type.n_min == 0 and type.n_max == 1):
-                print '''
-static void
-%(s)s_unparse_%(c)s(struct ovsdb_idl_row *row OVS_UNUSED)
-{
-    /* Nothing to do. */
-}''' % {'s': structName, 'c': columnName}
-            elif (type.n_min != 1 or type.n_max != 1) and not type.is_optional_pointer():
+            if (type.n_min != 1 or type.n_max != 1) and not type.is_optional_pointer():
                 print '''
 static void
 %(s)s_unparse_%(c)s(struct ovsdb_idl_row *row_)
@@ -492,6 +515,25 @@ const struct ovsdb_datum *
                    'C': columnName.upper()}
             print "}"
 
+        # String Map Helpers.
+        for columnName, column in sorted(table.columns.iteritems()):
+            if not is_string_map(column):
+                continue
+
+            print """
+const char * %(s)s_get_%(c)s_value(const struct %(s)s *row, const char *search_key, const char *default_value)
+{
+    char **keys = row->key_%(c)s;
+    char **values = row->value_%(c)s;
+    size_t n_keys = row->n_%(c)s;
+    char ** result_key;
+
+    assert(inited);
+    result_key = bsearch(&search_key, keys, n_keys, sizeof *keys,
+                         bsearch_strcmp);
+    return result_key ? values[result_key - keys] : default_value;
+}""" % {'s': structName, 'c': columnName}
+
         # Table columns.
         print "\nstruct ovsdb_idl_column %s_columns[%s_N_COLUMNS];" % (
             structName, structName.upper())
@@ -548,6 +590,7 @@ void
         print "    %s_columns_init();" % structName
     print "}"
 
+
 def ovsdb_escape(string):
     def escape(match):
         c = match.group(0)
@@ -569,8 +612,6 @@ def ovsdb_escape(string):
             return '\\x%02x' % ord(c)
     return re.sub(r'["\\\000-\037]', escape, string)
 
-
-
 def usage():
     print """\
 %(argv0)s: ovsdb schema compiler