|
rcbench
Servo and ESC test bench: panel, IOmcu and shared C
|
Read one ESC profile from JSON. More...
#include "esc_json_int.h"#include "esc_profile.h"#include <stdio.h>#include <stdlib.h>#include <string.h>Data Structures | |
| struct | name_at_t |
| A model name and where it stands in the file. More... | |
| struct | dec_t |
| State of one decoding pass over the tokens. More... | |
Macros | |
| #define | FAIL(d, ...) |
| The first reason stands. | |
| #define | COUNT(a) |
| Number of entries in a static array. | |
Functions | |
| static void * | take (dec_t *d, size_t n, size_t align) |
| Take aligned bytes from the block being filled. | |
| static int64_t | member (const dec_t *d, uint32_t obj, const char *key) |
The value of key in the object at token obj, or -1. | |
| static const char * | copy_str (dec_t *d, uint32_t ti) |
| A string token's text, decoded into the block. | |
| static size_t | decoded_len (const dec_t *d, uint32_t ti) |
| A string token's length once decoded, in bytes: UTF-8, as the generator measures it. | |
| static const char * | get_str (dec_t *d, uint32_t obj, const char *key, const char *where, bool empty_ok, bool null_ok) |
| Read a string member. | |
| static bool | get_num (dec_t *d, uint32_t obj, const char *key, const char *where, int64_t lo, int64_t hi, bool null_ok, int64_t *out) |
| A whole number in lo..hi; *out untouched for null when null_ok. | |
| static bool | get_bool (dec_t *d, uint32_t obj, const char *key, const char *where, bool absent_ok) |
| Read a boolean member. | |
| static int | get_enum (dec_t *d, uint32_t obj, const char *key, const char *where, const char *const *names, int count) |
The index of key's string value in names, or -1 after a FAIL(). | |
| static int64_t | get_obj (dec_t *d, uint32_t obj, const char *key, const char *where, ttype_t type) |
| Read a member that must be an object or an array. | |
| static bool | key_ok (const char *k, size_t max, bool dash) |
| Check an id or key: 1 to max of a-z, 0-9 and one separator. | |
| static int | by_name (const void *a, const void *b) |
| Sort comparison of model names, then by position. | |
| static int | name_is (const void *key, const void *elem) |
| Search comparison of a name with a name_at_t. | |
| static void | decode_models (dec_t *d, uint32_t root, esc_profile_t *p) |
| Decode the models array of a profile. | |
| static bool | has_model (const dec_t *d, const char *name) |
| Whether a profile has a model with a name. | |
| static esc_throttle_t | moves_from (const esc_profile_t *p) |
| Where the stick is when a value's own moves (after_select) begin: the profile's store move, else the move that stores the value; ESC_THR_NONE for a profile with no select move. | |
| static void | decode_values (dec_t *d, uint32_t arr, const char *iw, esc_item_t *it, esc_throttle_t before) |
| Decode the values array of one item. | |
| static void | decode_items (dec_t *d, uint32_t root, esc_profile_t *p) |
| Decode the items array of a profile. | |
| static void | decode_manual (dec_t *d, uint32_t root, esc_profile_t *p) |
| The operator's steps at the ESC: absent or null, none. | |
| static void | decode (dec_t *d, esc_profile_t *p) |
| Decode a whole profile from the tokens. | |
| bool | esc_profile_parse (const char *json, size_t len, esc_profile_t *out, void **block, char *err, size_t err_size) |
| Parse one profile file. | |
Variables | |
| static const char *const | k_scheme [] |
| Allowed values of the enumerated members, as the JSON spells them. | |
| static const char *const | k_encoding [] |
| static const char *const | k_announce [] |
| static const char *const | k_auto [] = { "full", "assisted", "none" } |
| static const char *const | k_throttle [] = { "min", "mid", "max", "none" } |
| static const char *const | k_when [] |
| static const char *const | k_changes [] = { "one", "many" } |
| static const char *const | k_manual [] |
| static const char *const | k_cells [] = { "lipo", "nimh" } |
Read one ESC profile from JSON.
See esc_profile.h.
Two stages. The text is first cut into tokens: one per value, each with the index one past its last descendant, so a reader skips a subtree in one step and never recurses to find a key. Then the profile is decoded from the tokens twice: once with no block, which only adds up the bytes every string and array will need, and once into a block of exactly that size. One allocation per profile, and free() of it releases everything. The first stage is esc_json_lex.c; esc_json_int.h is what it gives this file.
The rules are tools/gen_esc_profiles.py's. The host suite parses every profile of record and compares it with the generated table, so a rule that differs between the two fails there.
SPDX-License-Identifier: MIT
| #define COUNT | ( | a | ) |
Number of entries in a static array.
| a | The array. |
| #define FAIL | ( | d, | |
| ... ) |
The first reason stands.
A macro rather than a variadic function: the arguments go straight to snprintf(), and there is no va_list to get wrong.
|
static |
|
static |
A string token's text, decoded into the block.
Never longer than the text it came from: no escape decodes to more bytes than it is written in.
| d | The decoding state. |
| ti | Index of the string token. |
|
static |
Decode a whole profile from the tokens.
Run once to size the block and once to fill it.
| d | The decoding state. |
| p | Receives the profile. |
|
static |
Decode the items array of a profile.
| d | The decoding state. |
| root | Index of the root object token. |
| p | Receives the items. |
|
static |
The operator's steps at the ESC: absent or null, none.
Only an assisted profile has them, 1 to ESC_MANUAL_MAX, in the order a run meets them.
| d | The decoding state. |
| root | Index of the root object token. |
| p | Receives the steps. |
|
static |
Decode the models array of a profile.
Model names must be unique within the profile.
| d | The decoding state. |
| root | Index of the root object token. |
| p | Receives the models. |
|
static |
Decode the values array of one item.
| d | The decoding state. |
| arr | Index of the values array token. |
| iw | Path of the item, for the reason text. |
| it | The item that receives the values. |
| before | Stick position before the item's first value move. |
|
static |
A string token's length once decoded, in bytes: UTF-8, as the generator measures it.
The sizing pass has no copy to measure.
| d | The decoding state. |
| ti | Index of the string token. |
| bool esc_profile_parse | ( | const char * | json, |
| size_t | len, | ||
| esc_profile_t * | out, | ||
| void ** | block, | ||
| char * | err, | ||
| size_t | err_size ) |
Parse one profile file.
Everything the profile points at – strings, models, items, values – is placed in one block from malloc(); *block receives it and free(*block) releases the lot. On failure nothing is allocated and err (when not NULL) holds a line for the operator, e.g. "items[2].values: empty".
| json | The file's bytes. |
| len | Length of json in bytes. |
| out | Receives the parsed profile. |
| block | Receives the malloc() block that holds the profile. |
| err | Message for the operator, or NULL. |
| err_size | Size of err in bytes. |
out is a usable profile
|
static |
Read a boolean member.
| d | The decoding state. |
| obj | Index of the object token. |
| key | The member name. |
| where | Path of the object, for the reason text. |
| absent_ok | true when an absent member reads as false. |
absent_ok is set.
|
static |
The index of key's string value in names, or -1 after a FAIL().
| d | The decoding state. |
| obj | Index of the object token. |
| key | The member name. |
| where | Path of the object, for the reason text. |
| names | The allowed values. |
| count | Number of entries in names. |
names, or -1 after a FAIL().
|
static |
A whole number in lo..hi; *out untouched for null when null_ok.
| d | The decoding state. |
| obj | Index of the object token. |
| key | The member name. |
| where | Path of the object, for the reason text. |
| lo | Smallest allowed value. |
| hi | Largest allowed value. |
| null_ok | true when a missing or null member is allowed. |
| out | Receives the value. |
out.
|
static |
Read a member that must be an object or an array.
| d | The decoding state. |
| obj | Index of the object token. |
| key | The member name. |
| where | Path of the object, for the reason text. |
| type | T_OBJ or T_ARR. |
|
static |
Read a string member.
Fails when the member is absent or not a string, or is empty while empty_ok is false. A null member is "" when null_ok is set.
| d | The decoding state. |
| obj | Index of the object token. |
| key | The member name. |
| where | Path of the object, for the reason text. |
| empty_ok | true when an empty string is allowed. |
| null_ok | true when a missing or null member is allowed. |
|
static |
Whether a profile has a model with a name.
| d | The decoding state, with the sorted model names. |
| name | The model name. |
|
static |
Check an id or key: 1 to max of a-z, 0-9 and one separator.
| k | The text to check. |
| max | Longest allowed length, characters. |
| dash | true for "-" as the separator, false for "_". |
|
static |
The value of key in the object at token obj, or -1.
| d | The decoding state. |
| obj | Index of the object token. |
| key | The key to find. |
|
static |
Where the stick is when a value's own moves (after_select) begin: the profile's store move, else the move that stores the value; ESC_THR_NONE for a profile with no select move.
| p | The profile. |
|
static |
|
static |
Take aligned bytes from the block being filled.
While sizing, only the used count moves; while filling, the bytes are handed out from the block.
| d | The decoding state. |
| n | Bytes wanted. |
| align | Alignment of the returned pointer, bytes. |
|
static |
|
static |
|
static |
|
static |
Allowed values of the enumerated members, as the JSON spells them.
|
static |