xenserver: Warn when upgrading OVS on a bridged system.
[sliver-openvswitch.git] / lib / json.c
index a7039ba..0a8bca2 100644 (file)
@@ -277,7 +277,7 @@ json_real_create(double real)
 void
 json_object_put(struct json *json, const char *name, struct json *value)
 {
-    shash_add(json->u.object, name, value);
+    json_destroy(shash_replace(json->u.object, name, value));
 }
 
 void
@@ -607,7 +607,6 @@ json_lex_number(struct json_parser *p)
     const char *cp = ds_cstr(&p->buffer);
     unsigned long long int significand = 0;
     struct json_token token;
-    int sig_digits = 0;
     bool imprecise = false;
     bool negative = false;
     int pow10 = 0;
@@ -621,7 +620,6 @@ json_lex_number(struct json_parser *p)
     /* At least one integer digit, but 0 may not be used as a leading digit for
      * a longer number. */
     significand = 0;
-    sig_digits = 0;
     if (*cp == '0') {
         cp++;
         if (isdigit(*cp)) {
@@ -632,7 +630,6 @@ json_lex_number(struct json_parser *p)
         do {
             if (significand <= ULLONG_MAX / 10) {
                 significand = significand * 10 + (*cp - '0');
-                sig_digits++;
             } else {
                 pow10++;
                 if (*cp != '0') {
@@ -656,7 +653,6 @@ json_lex_number(struct json_parser *p)
         do {
             if (significand <= ULLONG_MAX / 10) {
                 significand = significand * 10 + (*cp - '0');
-                sig_digits++;
                 pow10--;
             } else if (*cp != '0') {
                 imprecise = true;
@@ -709,7 +705,6 @@ json_lex_number(struct json_parser *p)
      *
      * We suppress negative zeros as a matter of policy. */
     if (!significand) {
-        struct json_token token;
         token.type = T_INTEGER;
         token.u.integer = 0;
         json_parser_input(p, &token);
@@ -719,12 +714,10 @@ json_lex_number(struct json_parser *p)
     if (!imprecise) {
         while (pow10 > 0 && significand < ULLONG_MAX / 10) {
             significand *= 10;
-            sig_digits++;
             pow10--;
         }
         while (pow10 < 0 && significand % 10 == 0) {
             significand /= 10;
-            sig_digits--;
             pow10++;
         }
         if (pow10 == 0
@@ -753,19 +746,15 @@ json_lex_number(struct json_parser *p)
 static const char *
 json_lex_4hex(const char *cp, const char *end, int *valuep)
 {
-    int value, i;
+    unsigned int value;
 
     if (cp + 4 > end) {
         return "quoted string ends within \\u escape";
     }
 
-    value = 0;
-    for (i = 0; i < 4; i++) {
-        unsigned char c = *cp++;
-        if (!isxdigit(c)) {
-            return "malformed \\u escape";
-        }
-        value = (value << 4) | hexit_value(c);
+    value = hexits_value(cp, 4, NULL);
+    if (value == UINT_MAX) {
+        return "malformed \\u escape";
     }
     if (!value) {
         return "null bytes not supported in quoted strings";
@@ -832,7 +821,7 @@ json_string_unescape(const char *in, size_t in_len, char **outp)
     while (in < end) {
         if (*in == '"') {
             ds_clear(&out);
-            ds_put_cstr(&out, "quoted string may not include unescape \"");
+            ds_put_cstr(&out, "quoted string may not include unescaped \"");
             goto exit;
         }
         if (*in != '\\') {
@@ -1192,7 +1181,7 @@ json_parser_put_value(struct json_parser *p, struct json *value)
     }
 }
 
-static struct json_parser_node *
+static void
 json_parser_push(struct json_parser *p,
                  struct json *new_json, enum json_parse_state new_state)
 {
@@ -1211,11 +1200,10 @@ json_parser_push(struct json_parser *p,
         node = &p->stack[p->height++];
         node->json = new_json;
         p->parse_state = new_state;
-        return node;
     } else {
+        json_destroy(new_json);
         json_error(p, "input exceeds maximum nesting depth %d",
                    JSON_MAX_HEIGHT);
-        return NULL;
     }
 }
 
@@ -1428,17 +1416,17 @@ json_error(struct json_parser *p, const char *format, ...)
 #define SPACES_PER_LEVEL 2
 
 struct json_serializer {
-    struct ds ds;
+    struct ds *ds;
     int depth;
     int flags;
 };
 
-static void json_to_ds(const struct json *, struct json_serializer *);
-static void json_object_to_ds(const struct shash *object,
-                              struct json_serializer *);
-static void json_array_to_ds(const struct json_array *,
-                             struct json_serializer *);
-static void json_string_to_ds(const char *string, struct ds *);
+static void json_serialize(const struct json *, struct json_serializer *);
+static void json_serialize_object(const struct shash *object,
+                                  struct json_serializer *);
+static void json_serialize_array(const struct json_array *,
+                                 struct json_serializer *);
+static void json_serialize_string(const char *, struct ds *);
 
 /* Converts 'json' to a string in JSON format, encoded in UTF-8, and returns
  * that string.  The caller is responsible for freeing the returned string,
@@ -1456,19 +1444,30 @@ static void json_string_to_ds(const char *string, struct ds *);
  * object, since a bare literal does not satisfy the JSON grammar. */
 char *
 json_to_string(const struct json *json, int flags)
+{
+    struct ds ds;
+
+    ds_init(&ds);
+    json_to_ds(json, flags, &ds);
+    return ds_steal_cstr(&ds);
+}
+
+/* Same as json_to_string(), but the output is appended to 'ds'. */
+void
+json_to_ds(const struct json *json, int flags, struct ds *ds)
 {
     struct json_serializer s;
-    ds_init(&s.ds);
+
+    s.ds = ds;
     s.depth = 0;
     s.flags = flags;
-    json_to_ds(json, &s);
-    return ds_steal_cstr(&s.ds);
+    json_serialize(json, &s);
 }
 
 static void
-json_to_ds(const struct json *json, struct json_serializer *s)
+json_serialize(const struct json *json, struct json_serializer *s)
 {
-    struct ds *ds = &s->ds;
+    struct ds *ds = s->ds;
 
     switch (json->type) {
     case JSON_NULL:
@@ -1484,11 +1483,11 @@ json_to_ds(const struct json *json, struct json_serializer *s)
         break;
 
     case JSON_OBJECT:
-        json_object_to_ds(json->u.object, s);
+        json_serialize_object(json->u.object, s);
         break;
 
     case JSON_ARRAY:
-        json_array_to_ds(&json->u.array, s);
+        json_serialize_array(&json->u.array, s);
         break;
 
     case JSON_INTEGER:
@@ -1500,7 +1499,7 @@ json_to_ds(const struct json *json, struct json_serializer *s)
         break;
 
     case JSON_STRING:
-        json_string_to_ds(json->u.string, ds);
+        json_serialize_string(json->u.string, ds);
         break;
 
     case JSON_N_TYPES:
@@ -1513,34 +1512,34 @@ static void
 indent_line(struct json_serializer *s)
 {
     if (s->flags & JSSF_PRETTY) {
-        ds_put_char(&s->ds, '\n');
-        ds_put_char_multiple(&s->ds, ' ', SPACES_PER_LEVEL * s->depth);
+        ds_put_char(s->ds, '\n');
+        ds_put_char_multiple(s->ds, ' ', SPACES_PER_LEVEL * s->depth);
     }
 }
 
 static void
-json_object_member_to_ds(size_t i, const struct shash_node *node,
-                         struct json_serializer *s)
+json_serialize_object_member(size_t i, const struct shash_node *node,
+                             struct json_serializer *s)
 {
-    struct ds *ds = &s->ds;
+    struct ds *ds = s->ds;
 
     if (i) {
         ds_put_char(ds, ',');
         indent_line(s);
     }
 
-    json_string_to_ds(node->name, ds);
+    json_serialize_string(node->name, ds);
     ds_put_char(ds, ':');
     if (s->flags & JSSF_PRETTY) {
         ds_put_char(ds, ' ');
     }
-    json_to_ds(node->data, s);
+    json_serialize(node->data, s);
 }
 
 static void
-json_object_to_ds(const struct shash *object, struct json_serializer *s)
+json_serialize_object(const struct shash *object, struct json_serializer *s)
 {
-    struct ds *ds = &s->ds;
+    struct ds *ds = s->ds;
 
     ds_put_char(ds, '{');
 
@@ -1554,7 +1553,7 @@ json_object_to_ds(const struct shash *object, struct json_serializer *s)
         nodes = shash_sort(object);
         n = shash_count(object);
         for (i = 0; i < n; i++) {
-            json_object_member_to_ds(i, nodes[i], s);
+            json_serialize_object_member(i, nodes[i], s);
         }
         free(nodes);
     } else {
@@ -1563,7 +1562,7 @@ json_object_to_ds(const struct shash *object, struct json_serializer *s)
 
         i = 0;
         SHASH_FOR_EACH (node, object) {
-            json_object_member_to_ds(i++, node, s);
+            json_serialize_object_member(i++, node, s);
         }
     }
 
@@ -1572,9 +1571,9 @@ json_object_to_ds(const struct shash *object, struct json_serializer *s)
 }
 
 static void
-json_array_to_ds(const struct json_array *array, struct json_serializer *s)
+json_serialize_array(const struct json_array *array, struct json_serializer *s)
 {
-    struct ds *ds = &s->ds;
+    struct ds *ds = s->ds;
     size_t i;
 
     ds_put_char(ds, '[');
@@ -1588,7 +1587,7 @@ json_array_to_ds(const struct json_array *array, struct json_serializer *s)
                 ds_put_char(ds, ',');
                 indent_line(s);
             }
-            json_to_ds(array->elems[i], s);
+            json_serialize(array->elems[i], s);
         }
     }
 
@@ -1597,7 +1596,7 @@ json_array_to_ds(const struct json_array *array, struct json_serializer *s)
 }
 
 static void
-json_string_to_ds(const char *string, struct ds *ds)
+json_serialize_string(const char *string, struct ds *ds)
 {
     uint8_t c;