Browse Source

Make sure CC3200 enters boot loader reliably

PUBLISHED_FROM=805115dc15d0e510ed74bc48df65fce3e8d12150
Deomid Ryabkov 9 years ago
parent
commit
4b100eef24
3 changed files with 121 additions and 1 deletions
  1. 78 0
      frozen.c
  2. 9 1
      frozen.h
  3. 34 0
      unit_test.c

+ 78 - 0
frozen.c

@@ -463,6 +463,68 @@ int json_printer_file(struct json_out *out, const char *buf, size_t len) {
   return fwrite(buf, 1, len, out->u.fp);
   return fwrite(buf, 1, len, out->u.fp);
 }
 }
 
 
+static int b64idx(int c) {
+  if (c < 26) {
+    return c + 'A';
+  } else if (c < 52) {
+    return c - 26 + 'a';
+  } else if (c < 62) {
+    return c - 52 + '0';
+  } else {
+    return c == 62 ? '+' : '/';
+  }
+}
+
+static int b64rev(int c) {
+  if (c >= 'A' && c <= 'Z') {
+    return c - 'A';
+  } else if (c >= 'a' && c <= 'z') {
+    return c + 26 - 'a';
+  } else if (c >= '0' && c <= '9') {
+    return c + 52 - '0';
+  } else if (c == '+') {
+    return 62;
+  } else if (c == '/') {
+    return 63;
+  } else {
+    return 64;
+  }
+}
+
+static int b64enc(struct json_out *out, const unsigned char *p, int n) {
+  char buf[4];
+  int i, len = 0;
+  for (i = 0; i < n; i += 3) {
+    int a = p[i], b = i + 1 < n ? p[i + 1] : 0, c = i + 2 < n ? p[i + 2] : 0;
+    buf[0] = b64idx(a >> 2);
+    buf[1] = b64idx((a & 3) << 4 | (b >> 4));
+    buf[2] = b64idx((b & 15) << 2 | (c >> 6));
+    buf[3] = b64idx(c & 63);
+    if (i + 1 >= n) buf[2] = '=';
+    if (i + 2 >= n) buf[3] = '=';
+    len += out->printer(out, buf, sizeof(buf));
+  }
+  return len;
+}
+
+static int b64dec(const char *src, int n, char *dst) {
+  const char *end = src + n;
+  int len = 0;
+  while (src + 3 < end) {
+    int a = b64rev(src[0]), b = b64rev(src[1]), c = b64rev(src[2]),
+        d = b64rev(src[3]);
+    dst[len++] = (a << 2) | (b >> 4);
+    if (src[2] != '=') {
+      dst[len++] = (b << 4) | (c >> 2);
+      if (src[3] != '=') {
+        dst[len++] = (c << 6) | d;
+      }
+    }
+    src += 4;
+  }
+  return len;
+}
+
 int json_vprintf(struct json_out *out, const char *fmt, va_list xap) {
 int json_vprintf(struct json_out *out, const char *fmt, va_list xap) {
   int len = 0;
   int len = 0;
   const char *quote = "\"", *null = "null";
   const char *quote = "\"", *null = "null";
@@ -495,6 +557,10 @@ int json_vprintf(struct json_out *out, const char *fmt, va_list xap) {
         int val = va_arg(ap, int);
         int val = va_arg(ap, int);
         const char *str = val ? "true" : "false";
         const char *str = val ? "true" : "false";
         len += out->printer(out, str, strlen(str));
         len += out->printer(out, str, strlen(str));
+      } else if (fmt[1] == 'V') {
+        const unsigned char *p = va_arg(ap, const unsigned char *);
+        int n = va_arg(ap, int);
+        len += b64enc(out, p, n);
       } else if (fmt[1] == 'Q' ||
       } else if (fmt[1] == 'Q' ||
                  (fmt[1] == '.' && fmt[2] == '*' && fmt[3] == 'Q')) {
                  (fmt[1] == '.' && fmt[2] == '*' && fmt[3] == 'Q')) {
         size_t l = 0;
         size_t l = 0;
@@ -789,6 +855,17 @@ static void json_scanf_cb(void *callback_data, const char *name,
       }
       }
       break;
       break;
     }
     }
+    case 'V': {
+      char **dst = (char **) info->target;
+      int len = token->len * 4 / 3 + 2;
+      if ((*dst = (char *) malloc(len + 1)) != NULL) {
+        int n = b64dec(token->ptr, token->len, *dst);
+        (*dst)[n] = '\0';
+        *(int *) info->user_data = n;
+        info->num_conversions++;
+      }
+      break;
+    }
     case 'T':
     case 'T':
       info->num_conversions++;
       info->num_conversions++;
       *(struct json_token *) info->target = *token;
       *(struct json_token *) info->target = *token;
@@ -817,6 +894,7 @@ int json_vscanf(const char *s, int len, const char *fmt, va_list ap) {
       info.type = fmt[i + 1];
       info.type = fmt[i + 1];
       switch (fmt[i + 1]) {
       switch (fmt[i + 1]) {
         case 'M':
         case 'M':
+        case 'V':
           info.user_data = va_arg(ap, void *);
           info.user_data = va_arg(ap, void *);
         /* FALLTHROUGH */
         /* FALLTHROUGH */
         case 'B':
         case 'B':

+ 9 - 1
frozen.h

@@ -138,6 +138,7 @@ typedef int (*json_printf_callback_t)(struct json_out *, va_list *ap);
  * This is a superset of printf() function, with extra format specifiers:
  * This is a superset of printf() function, with extra format specifiers:
  *  - `%B` print json boolean, `true` or `false`. Accepts an `int`.
  *  - `%B` print json boolean, `true` or `false`. Accepts an `int`.
  *  - `%Q` print quoted escaped string or `null`. Accepts a `const char *`.
  *  - `%Q` print quoted escaped string or `null`. Accepts a `const char *`.
+ *  - `%V` print quoted base64-encoded string. Accepts a `const char *`, `int`.
  *  - `%M` invokes a json_printf_callback_t function. That callback function
  *  - `%M` invokes a json_printf_callback_t function. That callback function
  *  can consume more parameters.
  *  can consume more parameters.
  *
  *
@@ -165,6 +166,10 @@ int json_printf_array(struct json_out *, va_list *ap);
  *    - %B: consumes `int *`, expects boolean `true` or `false`.
  *    - %B: consumes `int *`, expects boolean `true` or `false`.
  *    - %Q: consumes `char **`, expects quoted, JSON-encoded string. Scanned
  *    - %Q: consumes `char **`, expects quoted, JSON-encoded string. Scanned
  *       string is malloc-ed, caller must free() the string.
  *       string is malloc-ed, caller must free() the string.
+ *    - %V: consumes `char **`, `int *`. Expects base64-encoded string.
+ *       Result string is base64-decoded, malloced and NUL-terminated.
+ *       The length of result string is stored in `int *` placeholder.
+ *       Caller must free() the result.
  *    - %M: consumes custom scanning function pointer and
  *    - %M: consumes custom scanning function pointer and
  *       `void *user_data` parameter - see json_scanner_t definition.
  *       `void *user_data` parameter - see json_scanner_t definition.
  *    - %T: consumes `struct json_token *`, fills it out with matched token.
  *    - %T: consumes `struct json_token *`, fills it out with matched token.
@@ -189,8 +194,11 @@ int json_scanf_array_elem(const char *s, int len, const char *path, int index,
 /*
 /*
  * Unescape JSON-encoded string src,slen into dst, dlen.
  * Unescape JSON-encoded string src,slen into dst, dlen.
  * src and dst may overlap.
  * src and dst may overlap.
+ * If destination buffer is too small (or zero-length), result string is not
+ * written but the length is counted nevertheless (similar to snprintf).
+ * Return the length of unescaped string in bytes.
  */
  */
-// size_t json_unescape(const char *src, size_t slen, char *dst, size_t dlen);
+int json_unescape(const char *src, int slen, char *dst, int dlen);
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }

+ 34 - 0
unit_test.c

@@ -301,6 +301,20 @@ static const char *test_json_printf(void) {
     ASSERT(strcmp(buf, result) == 0);
     ASSERT(strcmp(buf, result) == 0);
   }
   }
 
 
+  {
+    struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
+    memset(buf, 0, sizeof(buf));
+    ASSERT(json_printf(&out, "%V", "a2", 2) > 0);
+    ASSERT(strcmp(buf, "YTI=") == 0);
+  }
+
+  {
+    struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
+    memset(buf, 0, sizeof(buf));
+    ASSERT(json_printf(&out, "%V", "\x00 \x01 \x02 abc", 9) > 0);
+    ASSERT(strcmp(buf, "ACABIAIgYWJj") == 0);
+  }
+
   return NULL;
   return NULL;
 }
 }
 
 
@@ -475,6 +489,26 @@ static const char *test_scanf(void) {
     free(result);
     free(result);
   }
   }
 
 
+  {
+    const char *str = "{a : \"YTI=\" }";
+    int len;
+    char *result;
+    ASSERT(json_scanf(str, strlen(str), "{a: %V}", &result, &len) == 1);
+    ASSERT(len == 2);
+    ASSERT(strcmp(result, "a2") == 0);
+    free(result);
+  }
+
+  {
+    const char *str = "{a : \"0L/RgNC40LLQtdGC0Ys=\" }";
+    int len;
+    char *result;
+    ASSERT(json_scanf(str, strlen(str), "{a: %V}", &result, &len) == 1);
+    ASSERT(len == 14);
+    ASSERT(strcmp(result, "приветы") == 0);
+    free(result);
+  }
+
   return NULL;
   return NULL;
 }
 }