Explorar o código

Update frozen docs

PUBLISHED_FROM=1a1e6afc15a72982fb4ca6c9c3c1a6a65908132c
Sergey Lyubka %!s(int64=9) %!d(string=hai) anos
pai
achega
3603c6a7d1

+ 5 - 210
README.md

@@ -1,216 +1,9 @@
 JSON parser and emitter for C/C++
 =================================
 
-# Features
-
-   * Portable to any environment
-   * Simple, easy to understand API
-   * Very small footprint
-   * No dependencies
-   * Code is strict ISO C and strict ISO C++ at the same time
-   * Specialized for embedded use case: prints and scans directly to/from
-     C/C++ variables
-   * Parser provides low-level callback API and high-level scanf-like API
-   * Supports superset of JSON: allows non-quoted identifiers as object keys
-   * Complete 100% test coverage
-
-# Parsing Usage Example
-
-```
-  // str has the following JSON string (notice keys are out of order):
-  // { "a": 123, "d": true, "b": [1, 2], "c": "hi" }
-
-  int a, b;
-  char *c;
-  json_scanf(str, strlen(str), "{ a:%d, b:%M, c:%Q, d:%B }",
-             &a, &b, &c, scan_array, my_data);
-
-
-  // This function is called by json_scanf() call above.
-  // str is "[1, 2]", user_data is my_data.
-  static void scan_array(const char *str, int len, void *user_data) {
-    struct json_token t;
-    int i;
-    printf("Parsing array: %.*s\n", len, str);
-    for (i = 0; json_scanf_array_elem(str, len, ".x", i, &t) > 0; i++) {
-      printf("Index %d, token [%.*s]\n", i, t.len, t.ptr);
-    }
-  }
-```
-
-# Printing Usage Example
-
-Note keys are not escaped. `json_printf()` escapes them.
-
-```
-  json_printf(&out, "{%Q: %d, x: [%B, %B], y: %Q}", "foo", 123, 0, -1, "hi");
-  // Result:
-  // {"foo": 123, "x": [false, true], "y": "hi"}
-```
-
-To print a complex object (for example, serialize a structure into an object),
-use `%M` format specifier:
-
-```
-  struct my_struct { int a, b; } mys = {1,2};
-  json_printf(&out, "{foo: %M, bar: %d}", print_my_struct, &mys, 3);
-  // Result:
-  // {"foo": {"a": 1, "b": 2}, "bar": 3}
-```
-
-```
-int print_my_struct(struct json_out *out, va_list *ap) {
-  struct my_struct *p = va_arg(*ap, struct my_struct *);
-  return json_printf(out, "{a: %d, b: %d}", p->a, p->b);
-}
-```
-
-# Low-level, callback based parsing API
-
-`json_parse()` calls given callback function for each scanned value.
-Callback receives path to the value, a JSON token that points to the value,
-and arbitrary user data pointer.
-
-The path is constructed using this rule:
-- Root element has "" (empty string) path
-- When an object starts, `.` (dot) is appended to the path
-- When an object key is parsed, a key name is appended to the path
-- When an array is parsed, for each element a `[ELEM_INDEX]` is appended
-
-For example, consider the following json string:
-`{ "foo": 123, "bar": [ 1, 2, { "baz": true } ] }`.
-The sequence of callback invocations will be as follows:
-- path: `.foo`, token: `123`
-- path: `.bar[0]`, token: `1`
-- path: `.bar[1]`, token: `2`
-- path: `.bar[2].baz`, token: `true`
-- path: `.bar[2]`, token: `{ "baz": true }`
-- path: `.bar`, token: `[ 1, 2, { "baz": true } ]`
-- path: ` ` (empty string), token: `{ "foo": 123, "bar": [ 1, 2, { "baz": true } ] }`
-
-If top-level element is an array: `[1, {"foo": 2}]`
-- path: `[0]`, token: `1`
-- path: `[1].foo`, token: `2`
-- path: `[1]`, token: `{"foo": 2}`
-- path: ` ` (empty string), token: `[1, {"foo": 2}]`
-
-If top-level element is an scalar: `true`
-- path: ` ` (empty string), token: `true`
-
-
-```
-/* Callback-based API */
-typedef void (*json_parse_callback_t)(void *callback_data, const char *path,
-                                      const struct json_token *token);
-
-/*
- * Parse `json_string`, invoking `callback` function for each JSON token.
- * Return number of bytes processed
- */
-int json_parse(const char *json_string, int json_string_length,
-               json_parse_callback_t callback, void *callback_data);
-```
-
-# High level scanf-like parsing API
-
-```
-/*
- * Scan JSON string `str`, performing scanf-like conversions according to `fmt`.
- * `fmt` uses `scanf()`-like format, with the following differences:
- *
- * 1. Object keys in the format string don't have to be quoted, e.g. "{key: %d}"
- * 2. Order of keys in an object does not matter.
- * 3. Several extra format specifiers are supported:
- *    - %B: consumes `int *`, expects boolean `true` or `false`.
- *    - %Q: consumes `char **`, expects quoted, JSON-encoded string. Scanned
- *       string is malloc-ed, caller must free() the string. Scanned string
- *       is a JSON decoded, unescaped UTF-8 string.
- *    - %M: consumes custom scanning function pointer and
- *       `void *user_data` parameter - see json_scanner_t definition.
- *
- * Return number of elements successfully scanned & converted.
- * Negative number means scan error.
- */
-int json_scanf(const char *str, int str_len, const char *fmt, ...);
-int json_vscanf(const char *str, int str_len, const char *fmt, va_list ap);
-
-/* json_scanf's %M handler  */
-typedef void (*json_scanner_t)(const char *str, int len, void *user_data);
-
-/*
- * Helper function to scan array item with given path and index.
- * Fills `token` with the matched JSON token.
- * Return 0 if no array element found, otherwise non-0.
- */
-int json_scanf_array_elem(const char *s, int len, const char *path, int index,
-                          struct json_token *token);
-```
-
-# Printing API
-
-Frozen printing API is pluggable. Out of the box, Frozen provides a way
-to print to a string buffer or to an opened file stream. It is easy to
-to tell Frozen to print to other destination - for example, to a socket, etc.
-Frozen does it by defining an "output context" descriptor, which has
-a pointer to low-level printing function. If you want to print to some other
-destination, just define your specific printing function and initialize
-output context with it.
-
-This is the definition of output context descriptor:
-
-```
-struct json_out {
-  int (*printer)(struct json_out *, const char *str, size_t len);
-  union {
-    struct {
-      char *buf;
-      size_t size;
-      size_t len;
-    } buf;
-    void *data;
-    FILE *fp;
-  } u;
-};
-```
-
-Frozen provides two helper macros to initialize two builtin output
-descriptors:
-
-```
-struct json_out out1 = JSON_OUT_BUF(buf, len);
-struct json_out out2 = JSON_OUT_FILE(fp);
-```
-
-```
-typedef int (*json_printf_callback_t)(struct json_out *, va_list *ap);
-
-/*
- * Generate formatted output into a given sting buffer.
- * String values get escaped when printed (see `%M` specifier).
- * This is a superset of printf() function, with extra format specifiers:
- *  - `%B` print json boolean, `true` or `false`. Accepts an `int`.
- *  - `%Q` print quoted escaped string or `null`. Accepts a `const char *`.
- *  - `%M` invokes a json_printf_callback_t function. That callback function
- *  can consume more parameters.
- *
- * json_printf() also auto-escapes keys.
- *
- * Return number of bytes printed. If the return value is bigger then the
- * supplied buffer, that is an indicator of overflow. In the overflow case,
- * overflown bytes are not printed.
- */
-int json_printf(struct json_out *, const char *fmt, ...);
-int json_vprintf(struct json_out *, const char *fmt, va_list ap);
-
-/*
- * Helper %M callback that prints contiguous C arrays.
- * Consumes void *array_ptr, size_t array_size, size_t elem_size, char *fmt
- * Return number of bytes printed.
- */
-int json_printf_array(struct json_out *, va_list *ap);
-
-```
+# Documentation
 
+Read [Frozen documentation online](https://docs.cesanta.com/frozen)
 
 # Contributions
 
@@ -220,7 +13,9 @@ and send GitHub pull request. You retain the copyright on your contributions.
 
 # Licensing
 
-Frozen is released under commercial and [GNU GPL v.2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html) open source licenses.
+Frozen is released under commercial and
+[GNU GPL v.2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html)
+open source licenses.
 
 Commercial Projects:
 Once your project becomes commercialised GPLv2 licensing dictates that you need to either open your source fully or purchase a commercial license. Cesanta offer full, royalty-free commercial licenses without any GPL restrictions. If your needs require a custom license, we’d be happy to work on a solution with you. [Contact us for pricing.] (https://www.cesanta.com/contact)

+ 5 - 102
docs/api/intro.md

@@ -1,104 +1,7 @@
 ---
-title: "API documentation"
+title: API Reference
+items:
+  - { name: json_scanf.md }
+  - { name: json_printf.md }
+  - { name: json_parse.md }
 ---
-
-```c
-int parse_json(const char *json_string, int json_string_length,
-               struct json_token *tokens_array, int size_of_tokens_array);
-struct json_token *parse_json2(const char *json_string, int string_length);
-```
-
-`parse_json()` and `parse_json2()` parse JSON string.
-`parse_json()` needs pre-allocated tokens array or NULL, whereas
-`parse_json2()` allocates tokens array automatically.
-
-
-`parse_json()` tokenizes `json_string` of length `json_string_length`.
-If `tokens_array` is not `NULL`, then `parse_json()` will store tokens
-in the `tokens_array`. Token with type
-`JSON_TYPE_EOF` marks the end of parsed tokens. JSON token is defined as:
-
-```c
-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
-  int type;           // Type of the token, possible values below
-
-#define JSON_TYPE_EOF     0   // Not a real token, but end-of-tokens marker
-#define JSON_TYPE_STRING  1
-#define JSON_TYPE_NUMBER  2
-#define JSON_TYPE_OBJECT  3
-#define JSON_TYPE_TRUE    4
-#define JSON_TYPE_FALSE   5
-#define JSON_TYPE_NULL    6
-#define JSON_TYPE_ARRAY   7
-};
-```
-
-If `tokens_array` is `NULL`, then `parse_json` just checks the validity of the
-JSON string, and points where parsing stops. If `tokens_array` is not `NULL`,
-it must be pre-allocated by the caller. Note that `struct json_token` just
-points to the data inside `json_string`, it does not own the data. Thus the
-token's lifetime is identical to the lifetime of `json_string`, until
-`json_string` is freed or mutated. Return: On success, an offset inside
-`json_string` is returned where parsing has finished. On failure, a negative
-number is returned, one of:
-
-```c
-#define JSON_STRING_INVALID           -1
-#define JSON_STRING_INCOMPLETE        -2
-#define JSON_TOKEN_ARRAY_TOO_SMALL    -3
-```
-
-`parse_json2()` returns NULL on error and non-NULL on success.
-
-Below is an illustration on how JSON string gets tokenized:
-
-```
-JSON string:      {  "key_1" : "value_1",  "key_2": [ 12345, null  ]   }
-
-JSON_TYPE_OBJECT  |<-------------------------------------------------->|
-JSON_TYPE_STRING      |<->|
-JSON_TYPE_STRING                |<--->|
-JSON_TYPE_STRING                            |<->|
-JSON_TYPE_ARRAY                                     |<------------>|
-JSON_TYPE_NUMBER                                      |<->|
-JSON_TYPE_NULL                                               |<>|
-JSON_TYPE_EOF
-```
-
-<!-- -->
-
-```c
-    const struct json_token *find_json_token(const struct json_token *toks,
-                                             const char *path);
-```
-
-This is a convenience function to fetch specific values from the parsed
-string. `toks` must be a valid array, successfully populated by `parse_json()`.
-A `path` is a string, an accessor to the desired element of the JSON object,
-as if it was written in Javascript. For example, if parsed JSON string is  
-`"{ foo : { bar: [1, 2, 3] } }"`, then path `"foo.bar[0]"` would return a token
-that points to number `"1"`.  
-Return: pointer to the found token, or NULL on failure.
-
-```c
-struct json_out out = JSON_OUT_BUF(buf, len);
-struct json_out out = JSON_OUT_FILE(fp);
-
-typedef int (*json_printf_callback_t)(struct json_out *, va_list *ap);
-
-int json_printf(struct json_out *, const char *fmt, ...);
-int json_vprintf(struct json_out *, const char *fmt, va_list ap);
-```
-Generate formatted output into a given sting buffer.
-This is a superset of printf() function, with extra format specifiers:
-
-- `%B` print json boolean, `true` or `false`. Accepts an `int`.
-- `%I` print int64_t value. Accepts an `int64_t`.
-- `%Q` print quoted escaped string or `null`. Accepts a `const char *`.
-- `%M` invokes a json_printf_callback_t function. That callback function
- can consume more parameters.
-
-Return number of bytes printed.

+ 48 - 0
docs/api/json_parse.md

@@ -0,0 +1,48 @@
+---
+title: json_parse()
+---
+
+```c
+/* Callback-based API */
+typedef void (*json_parse_callback_t)(void *callback_data, const char *path,
+                                      const struct json_token *token);
+
+/*
+ * Parse `json_string`, invoking `callback` function for each JSON token.
+ * Return number of bytes processed
+ */
+int json_parse(const char *json_string, int json_string_length,
+               json_parse_callback_t callback, void *callback_data);
+```
+
+`json_parse()` is a low-level, callback based parsing API.
+`json_parse()` calls given callback function for each scanned value.
+
+Callback receives a path to the value, a JSON token that points to the value,
+and arbitrary user data pointer.
+
+The path is constructed using this rule:
+- Root element has "" (empty string) path
+- When an object starts, `.` (dot) is appended to the path
+- When an object key is parsed, a key name is appended to the path
+- When an array is parsed, for each element an `[ELEMENT_INDEX]` is appended
+
+For example, consider the following json string:
+`{ "foo": 123, "bar": [ 1, 2, { "baz": true } ] }`.
+The sequence of callback invocations will be as follows:
+- path: `.foo`, token: `123`
+- path: `.bar[0]`, token: `1`
+- path: `.bar[1]`, token: `2`
+- path: `.bar[2].baz`, token: `true`
+- path: `.bar[2]`, token: `{ "baz": true }`
+- path: `.bar`, token: `[ 1, 2, { "baz": true } ]`
+- path: ` ` (empty string), token: `{ "foo": 123, "bar": [ 1, 2, { "baz": true } ] }`
+
+If top-level element is an array: `[1, {"foo": 2}]`
+- path: `[0]`, token: `1`
+- path: `[1].foo`, token: `2`
+- path: `[1]`, token: `{"foo": 2}`
+- path: ` ` (empty string), token: `[1, {"foo": 2}]`
+
+If top-level element is an scalar: `true`
+- path: ` ` (empty string), token: `true`

+ 64 - 0
docs/api/json_printf.md

@@ -0,0 +1,64 @@
+---
+title: json_printf()
+---
+
+Frozen printing API is pluggable. Out of the box, Frozen provides a way
+to print to a string buffer or to an opened file stream. It is easy to
+to tell Frozen to print to other destination - for example, to a socket, etc.
+Frozen does it by defining an "output context" descriptor, which has
+a pointer to low-level printing function. If you want to print to some other
+destination, just define your specific printing function and initialize
+output context with it.
+
+This is the definition of output context descriptor:
+
+```c
+struct json_out {
+  int (*printer)(struct json_out *, const char *str, size_t len);
+  union {
+    struct {
+      char *buf;
+      size_t size;
+      size_t len;
+    } buf;
+    void *data;
+    FILE *fp;
+  } u;
+};
+```
+
+Frozen provides two helper macros to initialize two builtin output
+descriptors:
+
+```c
+struct json_out out1 = JSON_OUT_BUF(buf, len);
+struct json_out out2 = JSON_OUT_FILE(fp);
+```
+
+```c
+typedef int (*json_printf_callback_t)(struct json_out *, va_list *ap);
+int json_printf(struct json_out *, const char *fmt, ...);
+int json_vprintf(struct json_out *, const char *fmt, va_list ap);
+```
+
+Generate formatted output into a given sting buffer.
+String values get escaped when printed (see `%M` specifier).
+This is a superset of printf() function, with extra format specifiers:
+- `%B` print json boolean, `true` or `false`. Accepts an `int`.
+- `%Q` print quoted escaped string or `null`. Accepts a `const char *`.
+- `%M` invokes a json_printf_callback_t function. That callback function
+can consume more parameters.
+
+`json_printf()` also auto-escapes keys.
+
+Return number of bytes printed. If the return value is bigger then the
+supplied buffer, that is an indicator of overflow. In the overflow case,
+overflown bytes are not printed.
+
+```c
+int json_printf_array(struct json_out *, va_list *ap);
+```
+
+A helper `%M` callback that prints contiguous C arrays.
+Consumes `void *array_ptr, size_t array_size, size_t elem_size, char *fmt`
+Return number of bytes printed.

+ 47 - 0
docs/api/json_scanf.md

@@ -0,0 +1,47 @@
+---
+title: json_scanf()
+---
+
+```c
+int json_scanf(const char *str, int str_len, const char *fmt, ...);
+int json_vscanf(const char *str, int str_len, const char *fmt, va_list ap);
+
+/* json_scanf's %M handler  */
+typedef void (*json_scanner_t)(const char *str, int len, void *user_data);
+
+```
+
+Scan JSON string `str`, performing scanf-like conversions according to `fmt`.
+`fmt` uses `scanf()`-like format, with the following differences:
+
+1. Object keys in the format string don't have to be quoted, e.g. "{key: %d}"
+2. Order of keys in a format string does not matter, and format string may
+   omit keys to fetch only those that are of interest, for example,
+   assume `str` is a JSON string `{ "a": 123, "b": "hi", c: true }`.
+   We can fetch only the value of the `c` key:
+      ```C
+      int value = 0;
+      json_scanf(str, strlen(str), "{c: %B}", &value);
+      ```
+3. Several extra format specifiers are supported:
+   - %B: consumes `int *`, expects boolean `true` or `false`.
+   - %Q: consumes `char **`, expects quoted, JSON-encoded string. Scanned
+      string is malloc-ed, caller must free() the string. Scanned string
+      is a JSON decoded, unescaped UTF-8 string.
+   - %M: consumes custom scanning function pointer and
+      `void *user_data` parameter - see json_scanner_t definition.
+
+Return number of elements successfully scanned & converted.
+Negative number means scan error.
+
+
+```c
+int json_scanf_array_elem(const char *s, int len,
+                          const char *path,
+                          int index,
+                          struct json_token *token);
+```
+
+A helper function to scan array item with given path and index.
+Fills `token` with the matched JSON token.
+Return 0 if no array element found, otherwise non-0.

+ 6 - 0
docs/examples.md

@@ -0,0 +1,6 @@
+---
+title: "Examples"
+items:
+  - { type: file, name: conf-params.md }
+  - { type: file, name: gen-json.md }
+---

+ 0 - 28
docs/examples/conf-params.md

@@ -1,28 +0,0 @@
----
-title: "Accessing configuration parameters"
----
-
-```c
-#include "frozen.h"
-
-static const char *config_str = " { ports: [ 80, 443 ] } ";
-struct json_token tokens[10];
-int tokens_size = sizeof(tokens) / sizeof(tokens[0]);
-
-// Parse config string and make sure tokenization is correct
-ASSERT(parse_json(config_str, strlen(config_str), tokens, tokens_size) > 0);
-
-ASSERT(tokens[0].type == JSON_TYPE_OBJECT);   // Tokens are populated
-ASSERT(tokens[1].type == JSON_TYPE_STRING);   // in order of their
-ASSERT(tokens[2].type == JSON_TYPE_ARRAY);    // appearance in the
-ASSERT(tokens[3].type == JSON_TYPE_NUMBER);   // JSON string
-ASSERT(tokens[4].type == JSON_TYPE_NUMBER);
-ASSERT(tokens[5].type == JSON_TYPE_EOF);      // Last token is always EOF
-
-// Fetch port values
-ASSERT(find_json_token(tokens, "ports") == &tokens[2]);
-ASSERT(find_json_token(tokens, "ports[0]") == &tokens[3]);
-ASSERT(find_json_token(tokens, "ports[1]") == &tokens[4]);
-ASSERT(find_json_token(tokens, "ports[3]") == NULL);  // Outside boundaries
-ASSERT(find_json_token(tokens, "foo.bar") == NULL);   // Nonexistent
-```

+ 0 - 10
docs/examples/gen-json.md

@@ -1,10 +0,0 @@
----
-title: "Generating JSON string"
----
-
-```c
-char buf[1000];
-json_emit(buf, sizeof(buf), "{ s: [i, T, F, N] }", "foo", (long) -123);
-```
-
-Output: `{ "foo": [-123, true, false, null] }`

+ 3 - 3
docs/examples/intro.md

@@ -1,6 +1,6 @@
 ---
-title: "Examples"
+title: Examples
 items:
-  - { type: file, name: conf-params.md }
-  - { type: file, name: gen-json.md }
+  - { name: json_scanf.md }
+  - { name: json_printf.md }
 ---

+ 29 - 0
docs/examples/json_printf.md

@@ -0,0 +1,29 @@
+---
+title: json_printf() example
+---
+
+
+Note keys are not escaped. `json_printf()` escapes them.
+
+```c
+  json_printf(&out, "{%Q: %d, x: [%B, %B], y: %Q}", "foo", 123, 0, -1, "hi");
+  // Result:
+  // {"foo": 123, "x": [false, true], "y": "hi"}
+```
+
+To print a complex object (for example, serialize a structure into an object),
+use `%M` format specifier:
+
+```c
+  struct my_struct { int a, b; } mys = {1,2};
+  json_printf(&out, "{foo: %M, bar: %d}", print_my_struct, &mys, 3);
+  // Result:
+  // {"foo": {"a": 1, "b": 2}, "bar": 3}
+```
+
+```c
+int print_my_struct(struct json_out *out, va_list *ap) {
+  struct my_struct *p = va_arg(*ap, struct my_struct *);
+  return json_printf(out, "{a: %d, b: %d}", p->a, p->b);
+}
+```

+ 25 - 0
docs/examples/json_scanf.md

@@ -0,0 +1,25 @@
+---
+title: json_scanf() example
+---
+
+```c
+  // str has the following JSON string (notice keys are out of order):
+  // { "a": 123, "d": true, "b": [1, 2], "c": "hi" }
+
+  int a, b;
+  char *c;
+  json_scanf(str, strlen(str), "{ a:%d, b:%M, c:%Q, d:%B }",
+             &a, &b, &c, scan_array, my_data);
+
+
+  // This function is called by json_scanf() call above.
+  // str is "[1, 2]", user_data is my_data.
+  static void scan_array(const char *str, int len, void *user_data) {
+    struct json_token t;
+    int i;
+    printf("Parsing array: %.*s\n", len, str);
+    for (i = 0; json_scanf_array_elem(str, len, ".x", i, &t) > 0; i++) {
+      printf("Index %d, token [%.*s]\n", i, t.len, t.ptr);
+    }
+  }
+```

+ 14 - 0
docs/features.md

@@ -0,0 +1,14 @@
+---
+title: "Features"
+---
+
+- Portable to any environment
+- Simple, easy to understand API
+- Very small footprint
+- No dependencies
+- Code is strict ISO C and strict ISO C++ at the same time
+- Specialized for embedded use case: prints and scans directly to/from
+  C/C++ variables
+- Parser provides low-level callback API and high-level scanf-like API
+- Supports superset of JSON: allows non-quoted identifiers as object keys
+- Complete 100% test coverage

+ 0 - 11
docs/features/intro.md

@@ -1,11 +0,0 @@
----
-title: "Features"
----
-
-* Portable to any environment
-* Simple, easy to understand API
-* Very small footprint
-* No dependencies
-* Code is strict ISO C and strict ISO C++ at the same time
-* Supports superset of JSON: allows non-quoted identifiers as object keys
-* Complete 100% test coverage

+ 0 - 32
docs/how-to-use/intro.md

@@ -1,32 +0,0 @@
----
-title: "How to use it"
----
-
-   * Copy `frozen.c` and `frozen.h` to your project
-   * Add `frozen.c` to the list of source files
-   * Parsing with Frozen is done in two steps: first, split JSON string into
-      tokens by `parse_json()` or `parse_json2()`.  Second, search for certain
-      parameters in parsed string by `find_json_token()`. Below is an example,
-      error handling is omitted for clarity:
-
-```c
-#include <stdio.h>
-#include "frozen.h"
-
-int main(void) {
-  static const char *json = " { foo: 1, bar: 2 } ";
-  struct json_token *arr, *tok;
-
-  // Tokenize json string, fill in tokens array
-  arr = parse_json2(json, strlen(json));
-
-  // Search for parameter "bar" and print it's value
-  tok = find_json_token(arr, "bar");
-  printf("Value of bar is: [%.*s]\n", tok->len, tok->ptr);
-
-  // Do not forget to free allocated tokens array
-  free(arr);
-
-  return 0;
-}
-```

+ 5 - 5
docs/intro.md

@@ -3,9 +3,9 @@ title: Frozen - a JSON parser/emitter
 color: '#7A98B0'
 repo: https://github.com/cesanta/frozen
 items:
-  - { type: dir, name: features }
-  - { type: dir, name: how-to-use }
-  - { type: dir, name: api }
-  - { type: dir, name: examples }
-  - { type: dir, name: license }
+  - { name: features.md }
+  - { name: usage.md }
+  - { name: api }
+  - { name: examples }
+  - { name: license.md }
 ---

+ 2 - 7
docs/license/intro.md → docs/license.md

@@ -4,7 +4,7 @@ title: "License"
 
 Frozen is released under commercial and [GNU GPL
 v.2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html) open source
-licenses. 
+licenses.
 
 Commercial Projects: Once your project becomes commercialised GPLv2 licensing
 dictates that you need to either open your source fully or purchase a
@@ -14,9 +14,4 @@ happy to work on a solution with you. [Contact us for
 pricing](https://www.cesanta.com/contact).
 
 Prototyping: While your project is still in prototyping stage and not for sale,
-you can use Frozen’s open source code without license restrictions. 
-
-[Super Light DNS Resolver](https://github.com/cesanta/sldr), [Super Light
-Regexp Library](https://github.com/cesanta/slre), [Mongoose web
-server](https://github.com/cesanta/mongoose) are other projects by Cesanta
-Software, developed with the same philosophy of functionality and simplicity.
+you can use Frozen’s open source code without license restrictions.

+ 32 - 0
docs/usage.md

@@ -0,0 +1,32 @@
+---
+title: Usage
+---
+
+* Copy `frozen.c` and `frozen.h` to your project
+* Add `frozen.c` to the list of source files
+
+```c
+#include <stdio.h>
+#include <string.h>
+#include "frozen.h"
+
+int main(void) {
+  const char *str = "{ \"a\": 123, \"b\": true }";
+  int b = 0;
+
+  // Fetch boolean key "b" from the JSON string
+  json_scanf(str, strlen(str), "{b: %B}", &b);
+
+  printf("Result: %d\n", b);
+
+  return 0;
+}
+```
+
+Compile and run the code:
+
+```
+$ cc main.c frozen.c
+$ ./a.out
+Result: 1
+```