From bda05d937265fba91bf660c2faa5957b7501d3d8 Mon Sep 17 00:00:00 2001
From: Marko Mikulicic <mkm@cesanta.com>
Date: Mon, 15 Feb 2016 13:29:29 +0000
Subject: [PATCH] Import frozen

    PUBLISHED_FROM=9f6f38e92b5952b9571d73569c2752b6805f15c5
---
 mongoose.c | 173 +++++++++++++++++++++++++++++++++++++++++------------
 mongoose.h |  32 +++++-----
 2 files changed, 150 insertions(+), 55 deletions(-)

diff --git a/mongoose.c b/mongoose.c
index 878653669..2ad27c345 100644
--- a/mongoose.c
+++ b/mongoose.c
@@ -543,7 +543,7 @@ double cs_time() {
  * See the GNU General Public License for more details.
  *
  * Alternatively, you can license this library under a commercial
- * license, as set out in <https://www.cesanta.com/license>.
+ * license, as set out in <http://cesanta.com/products.html>.
  */
 
 #define _CRT_SECURE_NO_WARNINGS /* Disable deprecation warning in VS2005+ */
@@ -578,8 +578,15 @@ struct frozen {
 static int parse_object(struct frozen *f);
 static int parse_value(struct frozen *f);
 
-#define EXPECT(cond, err_code) do { if (!(cond)) return (err_code); } while (0)
-#define TRY(expr) do { int _n = expr; if (_n < 0) return _n; } while (0)
+#define EXPECT(cond, err_code)      \
+  do {                              \
+    if (!(cond)) return (err_code); \
+  } while (0)
+#define TRY(expr)          \
+  do {                     \
+    int _n = expr;         \
+    if (_n < 0) return _n; \
+  } while (0)
 #define END_OF_STRING (-1)
 
 static int left(const struct frozen *f) {
@@ -596,12 +603,23 @@ static void skip_whitespaces(struct frozen *f) {
 
 static int cur(struct frozen *f) {
   skip_whitespaces(f);
-  return f->cur >= f->end ? END_OF_STRING : * (unsigned char *) f->cur;
+  return f->cur >= f->end ? END_OF_STRING : *(unsigned char *) f->cur;
 }
 
 static int test_and_skip(struct frozen *f, int expected) {
   int ch = cur(f);
-  if (ch == expected) { f->cur++; return 0; }
+  if (ch == expected) {
+    f->cur++;
+    return 0;
+  }
+  return ch == END_OF_STRING ? JSON_STRING_INCOMPLETE : JSON_STRING_INVALID;
+}
+
+static int test_no_skip(struct frozen *f, int expected) {
+  int ch = cur(f);
+  if (ch == expected) {
+    return 0;
+  }
   return ch == END_OF_STRING ? JSON_STRING_INCOMPLETE : JSON_STRING_INVALID;
 }
 
@@ -620,11 +638,19 @@ static int is_hex_digit(int ch) {
 static int get_escape_len(const char *s, int len) {
   switch (*s) {
     case 'u':
-      return len < 6 ? JSON_STRING_INCOMPLETE :
-        is_hex_digit(s[1]) && is_hex_digit(s[2]) &&
-        is_hex_digit(s[3]) && is_hex_digit(s[4]) ? 5 : JSON_STRING_INVALID;
-    case '"': case '\\': case '/': case 'b':
-    case 'f': case 'n': case 'r': case 't':
+      return len < 6 ? JSON_STRING_INCOMPLETE
+                     : is_hex_digit(s[1]) && is_hex_digit(s[2]) &&
+                               is_hex_digit(s[3]) && is_hex_digit(s[4])
+                           ? 5
+                           : JSON_STRING_INVALID;
+    case '"':
+    case '\\':
+    case '/':
+    case 'b':
+    case 'f':
+    case 'n':
+    case 'r':
+    case 't':
       return len < 2 ? JSON_STRING_INCOMPLETE : 1;
     default:
       return JSON_STRING_INVALID;
@@ -670,9 +696,12 @@ static int parse_identifier(struct frozen *f) {
 static int get_utf8_char_len(unsigned char ch) {
   if ((ch & 0x80) == 0) return 1;
   switch (ch & 0xf0) {
-    case 0xf0: return 4;
-    case 0xe0: return 3;
-    default: return 2;
+    case 0xf0:
+      return 4;
+    case 0xe0:
+      return 3;
+    default:
+      return 2;
   }
 }
 
@@ -682,9 +711,9 @@ static int parse_string(struct frozen *f) {
   TRY(test_and_skip(f, '"'));
   TRY(capture_ptr(f, f->cur, JSON_TYPE_STRING));
   for (; f->cur < f->end; f->cur += len) {
-    ch = * (unsigned char *) f->cur;
+    ch = *(unsigned char *) f->cur;
     len = get_utf8_char_len((unsigned char) ch);
-    EXPECT(ch >= 32 && len > 0, JSON_STRING_INVALID);  /* No control chars */
+    EXPECT(ch >= 32 && len > 0, JSON_STRING_INVALID); /* No control chars */
     EXPECT(len < left(f), JSON_STRING_INCOMPLETE);
     if (ch == '\\') {
       EXPECT((n = get_escape_len(f->cur + 1, left(f))) > 0, n);
@@ -764,14 +793,35 @@ static int parse_value(struct frozen *f) {
   int ch = cur(f);
 
   switch (ch) {
-    case '"': TRY(parse_string(f)); break;
-    case '{': TRY(parse_object(f)); break;
-    case '[': TRY(parse_array(f)); break;
-    case 'n': TRY(expect(f, "null", 4, JSON_TYPE_NULL)); break;
-    case 't': TRY(expect(f, "true", 4, JSON_TYPE_TRUE)); break;
-    case 'f': TRY(expect(f, "false", 5, JSON_TYPE_FALSE)); break;
-    case '-': case '0': case '1': case '2': case '3': case '4':
-    case '5': case '6': case '7': case '8': case '9':
+    case '"':
+      TRY(parse_string(f));
+      break;
+    case '{':
+      TRY(parse_object(f));
+      break;
+    case '[':
+      TRY(parse_array(f));
+      break;
+    case 'n':
+      TRY(expect(f, "null", 4, JSON_TYPE_NULL));
+      break;
+    case 't':
+      TRY(expect(f, "true", 4, JSON_TYPE_TRUE));
+      break;
+    case 'f':
+      TRY(expect(f, "false", 5, JSON_TYPE_FALSE));
+      break;
+    case '-':
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
       TRY(parse_number(f));
       break;
     default:
@@ -821,9 +871,19 @@ static int parse_object(struct frozen *f) {
 }
 
 static int doit(struct frozen *f) {
+  int ret = 0;
+
   if (f->cur == 0 || f->end < f->cur) return JSON_STRING_INVALID;
   if (f->end == f->cur) return JSON_STRING_INCOMPLETE;
-  TRY(parse_object(f));
+
+  if (0 == (ret = test_no_skip(f, '{'))) {
+    TRY(parse_object(f));
+  } else if (0 == (ret = test_no_skip(f, '['))) {
+    TRY(parse_array(f));
+  } else {
+    return ret;
+  }
+
   TRY(capture_ptr(f, f->cur, JSON_TYPE_EOF));
   capture_len(f, f->num_tokens, f->cur);
   return 0;
@@ -876,8 +936,9 @@ struct json_token *find_json_token(struct json_token *toks, const char *path) {
         ind += path[n] - '0';
       }
       if (path[n++] != ']') return 0;
-      skip = 1;  /* In objects, we skip 2 elems while iterating, in arrays 1. */
-    } else if (toks->type != JSON_TYPE_OBJECT) return 0;
+      skip = 1; /* In objects, we skip 2 elems while iterating, in arrays 1. */
+    } else if (toks->type != JSON_TYPE_OBJECT)
+      return 0;
     toks++;
     for (i = 0; i < toks[-1].num_desc; i += skip, ind2++) {
       /* ind == -1 indicated that we're iterating an array, not object */
@@ -919,20 +980,46 @@ int json_emit_quoted_str(char *s, int s_len, const char *str, int len) {
   const char *begin = s, *end = s + s_len, *str_end = str + len;
   char ch;
 
-#define EMIT(x) do { if (s < end) *s = x; s++; } while (0)
+#define EMIT(x)          \
+  do {                   \
+    if (s < end) *s = x; \
+    s++;                 \
+  } while (0)
 
   EMIT('"');
   while (str < str_end) {
     ch = *str++;
     switch (ch) {
-      case '"':  EMIT('\\'); EMIT('"'); break;
-      case '\\': EMIT('\\'); EMIT('\\'); break;
-      case '\b': EMIT('\\'); EMIT('b'); break;
-      case '\f': EMIT('\\'); EMIT('f'); break;
-      case '\n': EMIT('\\'); EMIT('n'); break;
-      case '\r': EMIT('\\'); EMIT('r'); break;
-      case '\t': EMIT('\\'); EMIT('t'); break;
-      default: EMIT(ch);
+      case '"':
+        EMIT('\\');
+        EMIT('"');
+        break;
+      case '\\':
+        EMIT('\\');
+        EMIT('\\');
+        break;
+      case '\b':
+        EMIT('\\');
+        EMIT('b');
+        break;
+      case '\f':
+        EMIT('\\');
+        EMIT('f');
+        break;
+      case '\n':
+        EMIT('\\');
+        EMIT('n');
+        break;
+      case '\r':
+        EMIT('\\');
+        EMIT('r');
+        break;
+      case '\t':
+        EMIT('\\');
+        EMIT('t');
+        break;
+      default:
+        EMIT(ch);
     }
   }
   EMIT('"');
@@ -960,18 +1047,26 @@ int json_emit_va(char *s, int s_len, const char *fmt, va_list ap) {
 
   while (*fmt != '\0') {
     switch (*fmt) {
-      case '[': case ']': case '{': case '}': case ',': case ':':
-      case ' ': case '\r': case '\n': case '\t':
+      case '[':
+      case ']':
+      case '{':
+      case '}':
+      case ',':
+      case ':':
+      case ' ':
+      case '\r':
+      case '\n':
+      case '\t':
         if (s < end) {
           *s = *fmt;
         }
         s++;
         break;
       case 'i':
-        s += json_emit_long(s, end - s, va_arg(ap, long));
+        s += json_emit_long(s, end - s, va_arg(ap, long) );
         break;
       case 'f':
-        s += json_emit_double(s, end - s, va_arg(ap, double));
+        s += json_emit_double(s, end - s, va_arg(ap, double) );
         break;
       case 'v':
         str = va_arg(ap, char *);
diff --git a/mongoose.h b/mongoose.h
index 3da51fd69..4ef90bb7b 100644
--- a/mongoose.h
+++ b/mongoose.h
@@ -840,7 +840,7 @@ size_t strnlen(const char *s, size_t maxlen);
  * See the GNU General Public License for more details.
  *
  * Alternatively, you can license this library under a commercial
- * license, as set out in <https://www.cesanta.com/license>.
+ * license, as set out in <http://cesanta.com/products.html>.
  */
 
 #ifndef FROZEN_HEADER_INCLUDED
@@ -853,27 +853,27 @@ extern "C" {
 #include <stdarg.h>
 
 enum json_type {
-  JSON_TYPE_EOF     = 0,      /* End of parsed tokens marker */
-  JSON_TYPE_STRING  = 1,
-  JSON_TYPE_NUMBER  = 2,
-  JSON_TYPE_OBJECT  = 3,
-  JSON_TYPE_TRUE    = 4,
-  JSON_TYPE_FALSE   = 5,
-  JSON_TYPE_NULL    = 6,
-  JSON_TYPE_ARRAY   = 7
+  JSON_TYPE_EOF = 0, /* End of parsed tokens marker */
+  JSON_TYPE_STRING = 1,
+  JSON_TYPE_NUMBER = 2,
+  JSON_TYPE_OBJECT = 3,
+  JSON_TYPE_TRUE = 4,
+  JSON_TYPE_FALSE = 5,
+  JSON_TYPE_NULL = 6,
+  JSON_TYPE_ARRAY = 7
 };
 
 struct json_token {
-  const char *ptr;      /* Points to the beginning of the token */
-  int len;              /* Token length */
-  int num_desc;         /* For arrays and object, total number of descendants */
-  enum json_type type;  /* Type of the token, possible values above */
+  const char *ptr;     /* Points to the beginning of the token */
+  int len;             /* Token length */
+  int num_desc;        /* For arrays and object, total number of descendants */
+  enum json_type type; /* Type of the token, possible values above */
 };
 
 /* Error codes */
-#define JSON_STRING_INVALID           -1
-#define JSON_STRING_INCOMPLETE        -2
-#define JSON_TOKEN_ARRAY_TOO_SMALL    -3
+#define JSON_STRING_INVALID -1
+#define JSON_STRING_INCOMPLETE -2
+#define JSON_TOKEN_ARRAY_TOO_SMALL -3
 
 int parse_json(const char *json_string, int json_string_length,
                struct json_token *tokens_array, int size_of_tokens_array);
-- 
GitLab