rcbench
Servo and ESC test bench: panel, IOmcu and shared C
Loading...
Searching...
No Matches
kst_file.c File Reference

KST servo configuration as a text file: write and read. More...

#include "kst_file.h"
#include <string.h>

Data Structures

struct  buf_t
 The text as it grows. More...
struct  cur_t
 One line at a time, found by counting, as the automatic test's report is (servo_report.c): a cursor walks the lines in order and prints the one asked for. More...
struct  line_t
 One line of the file text, without its line end. More...
struct  edit_t
 State of a write that applies edits to a file's lines. More...

Macros

#define HEADER   "KST servo configuration, format "
 Start of the first line, before the format number.
#define TYPE_LINE   "Type: "
 Start of the servo type line.
#define REGISTERS   "registers"
 Keyword that starts the register count line.
#define CHECKSUM   "checksum"
 Keyword that starts the checksum line.
#define NOT_LOADED   " [not loaded]"
 Suffix on a field line that is not editable.
#define STR_LEN(s)
 Length of the string literal s, without its terminator.
#define REGS_PER_LINE   8u
 Registers on each line of the register block.
#define REG_LINES   (KST_REG_COUNT / REGS_PER_LINE)
 Lines of the register block.
#define REG_LINE_LEN   (3u + 3u * REGS_PER_LINE)
 "00:" and 8 times " xx".
#define CHECKSUM_LEN   (STR_LEN(CHECKSUM) + 9u)
 "checksum", a space and 8 digits.
#define NUMBER_MAX   9999999u
 A number in a file saturates here; no field encodes a value this high.
#define BOM   "\xEF\xBB\xBF"
 The byte order mark of UTF-8 (8-bit Unicode Transformation Format), which some editors put in front of a text.
#define CRC_START   0xFFFFFFFFu
 Initial value of the CRC-32 register.

Functions

static uint32_t crc_add (uint32_t crc, unsigned byte)
 CRC-32 of IEEE 802.3, 4 bits a step.
static void put_char (buf_t *b, char c)
 Append one character to a buffer.
static void put_str (buf_t *b, const char *s)
 Append a string to a buffer.
static void put_uint (buf_t *b, uint32_t v)
 Append an unsigned decimal number to a buffer.
static void put_hex (buf_t *b, uint32_t v, unsigned digits)
 Append the low digits of a value as upper-case hexadecimal digits.
static void put_row (buf_t *b, const uint8_t *regs, unsigned row)
 One line of the register block, without its line end.
static bool has_tenths (const kst_field_t *f)
 Check whether a field's unit has a tenths digit.
static void unit_text (const kst_field_t *f, char *out)
 What follows the number of a field's value, terminated: "us", "%", "s", "of 12" or nothing.
static void put_value (buf_t *b, kst_field_id_t id, const kst_field_t *f, uint16_t raw)
 Append the displayed value of a field, with its unit.
size_t kst_file_format (const kst_image_t *img, char *out, size_t out_size)
 Write the text of img into out.
static bool is_blank (char c)
 Check whether a character is a space or a tab.
static char lower (char c)
 Convert an ASCII upper-case letter to lower case.
static bool loose_eq (const char *s, size_t n, const char *ref)
 Whether s is ref, compared without case and without the spaces and tabs in either.
static void trim (const char **s, size_t *n)
 Skip leading spaces and tabs of a string.
static bool number (const char *s, size_t n, size_t *i, uint32_t *v)
 Decimal digits from s[*i] on.
static bool hex2 (const char *s, size_t n, size_t *i, unsigned *v)
 2 hexadecimal digits of either case from s[*i] on.
static bool next_line (cur_t *c, line_t *l)
 The next line: a complete one, or with open the bytes behind the last line end.
static bool blank_line (const line_t *l)
 Whether a line holds spaces and tabs only, or nothing.
static bool is_checksum_line (const char *s, size_t n)
 Whether the first word of a line is "checksum", in any case.
static bool has_checksum_line (const char *text, size_t len)
 Check whether a text has a line whose first word is "checksum".
static kst_file_err_t read_head (cur_t *c)
 Line 1: the header and a version this code reads.
static kst_type_t type_value (const char *s, size_t n)
 "V6" or "V8" in either case.
static kst_file_err_t register_count (const char *s, size_t n)
 The number after "registers".
static bool register_row (const char *s, size_t n, unsigned row, bool strict, kst_image_t *img)
 One line of the register block into its 8 registers.
static bool checksum_fits (const line_t *l, uint32_t crc)
 Check whether a line equals the checksum line for a CRC value.
static bool crc_line (const line_t *l, uint32_t *crc)
 Add a line and its end as one LF.
static kst_file_err_t read_verified (cur_t *c, kst_file_t *f)
 The caller found a line whose first word is "checksum".
static bool shows (kst_field_id_t id, int32_t display)
 Whether a raw value of the field displays as display.
static bool field_value (kst_field_id_t id, const char *s, size_t n, kst_file_t *f, int32_t *typed, bool *closed)
 The value of field id as a person writes it.
static kst_file_err_t edited_line (edit_t *e, const char *s, size_t n, unsigned line, bool *closed)
 A line that is not empty, not a comment and not in the register block.
static void take_block_values (const edit_t *e, kst_file_t *f)
 An editable field whose line shows what the register block holds takes the block's raw value: several raw values of Max.
static kst_file_err_t read_edited (cur_t *c, kst_file_t *f)
 A text may end without a line end, as an editor leaves it.
kst_file_err_t kst_file_parse (const char *text, size_t len, kst_file_t *out, unsigned *line)
 Read len bytes of text.
static bool gives (const kst_file_t *file, kst_field_id_t id)
 Whether the file gives a value for the field.
static bool holds (const kst_file_t *file, kst_field_id_t id, const kst_image_t *img)
 Whether the file's value of a field is the value img holds.
static bool wanted_raw (const kst_file_t *file, kst_field_id_t id, uint16_t *raw)
 The raw value a load sets an editable field to.
static kst_field_id_t blame (const kst_file_t *file, const kst_image_t *servo, const kst_image_t *backup, const kst_file_load_t *load, kst_rules_t hard)
 The first field of the file, by line, whose value a broken hard rule needs: putting the servo's value back clears at least one of them.
kst_file_verdict_t kst_file_load (const kst_file_t *file, const kst_image_t *servo, const kst_image_t *backup, kst_file_load_t *out)
 Hold a file against the image read from the connected servo.

Variables

static const char k_hex [] = "0123456789ABCDEF"
 Upper-case hex digits, indexed by a nibble value.

Detailed Description

KST servo configuration as a text file: write and read.

SPDX-License-Identifier: MIT

Macro Definition Documentation

◆ STR_LEN

#define STR_LEN ( s)
Value:
(sizeof(s) - 1u)
#define s
Short name for esc_stick_s inside the five stick-class files.
Definition esc_stick_panel_int.h:295

Length of the string literal s, without its terminator.

Function Documentation

◆ crc_line()

bool crc_line ( const line_t * l,
uint32_t * crc )
static

Add a line and its end as one LF.

False for a line longer than the format has and for a character outside 0x20 to 0x7E.

◆ edited_line()

kst_file_err_t edited_line ( edit_t * e,
const char * s,
size_t n,
unsigned line,
bool * closed )
static

A line that is not empty, not a comment and not in the register block.

closed: see field_value(); the other lines show their end by their form.

◆ field_value()

bool field_value ( kst_field_id_t id,
const char * s,
size_t n,
kst_file_t * f,
int32_t * typed,
bool * closed )
static

The value of field id as a person writes it.

typed receives the number of a line without "raw". closed is set when the line shows its own end: a unit, a "[...]" or a remark behind the number. A line that ends in the digits of its number does not: a text cut inside that number reads the same.

◆ kst_file_format()

size_t kst_file_format ( const kst_image_t * img,
char * out,
size_t out_size )

Write the text of img into out.

Returns the number of bytes written. No terminator is written. Returns 0, with out in an unspecified state, for a NULL argument and for an out_size the text does not fit; KST_FILE_MAX always fits.

Every image is written, also one that breaks the layout fingerprint or a limit: the file states what a servo holds.

Parameters
imgImage to write.
outBuffer that receives the text.
out_sizeSize of out, in bytes.
Returns
Bytes written; 0 for a NULL argument or a buffer that is too small.

◆ kst_file_load()

kst_file_verdict_t kst_file_load ( const kst_file_t * file,
const kst_image_t * servo,
const kst_image_t * backup,
kst_file_load_t * out )

Hold a file against the image read from the connected servo.

servo is the servo's image as read last. backup is the image the limits compare with, as the caller passes it to kst_limits_edit() for an edit made by hand; a caller without a separate backup passes servo.

  1. Type. A file that states a type loads into a servo of that type (kst_type()) and into no other. A file that states no type passes: its values apply as input made by hand.
  2. Values. Only fields of access class KST_ACCESS_EDITABLE are taken: all of them from a verified file's registers, the named ones from an edited file's lines. A field of another class is never taken from a file; where the file holds another value than the servo it is in skipped, and the load goes on: the protection block, Servo / Gyro Servo, Lock and the pairing value never deny a load. An edited file's register block gives the raw value of an editable field whose line reads as the block shows, and no other value.
  3. Limits. The target goes through kst_limits_edit(backup, target, no unlock set), the check an edit made by hand goes through. A broken hard rule refuses the whole file. Soft rules are returned.

The caller passes the target of KST_FILE_LOAD_OK to kst_plan_edit() as it does with an edit made by hand; nothing here replaces that check.

Returns the verdict. out is untouched for KST_FILE_LOAD_ARG.

Parameters
fileThe file as read.
servoThe servo image as read last.
backupThe image the limits compare with.
outReceives the load result.
Returns
The verdict.

◆ kst_file_parse()

kst_file_err_t kst_file_parse ( const char * text,
size_t len,
kst_file_t * out,
unsigned * line )

Read len bytes of text.

out is written on KST_FILE_OK and on no other result. line, when not NULL, receives the number of the line the refusal is at, counted from 1, and 0 for a result that belongs to no line (KST_FILE_OK, KST_FILE_ERR_ARG, KST_FILE_ERR_OVERSIZED).

Nothing is checked against the fingerprint, an access class or a limit here; kst_file_load() does that against a servo.

Parameters
textText to read.
lenLength of text, in bytes.
outReceives the file on KST_FILE_OK.
lineReceives the line of a refusal; may be NULL.
Returns
KST_FILE_OK, or the reason the text is refused.

◆ lower()

char lower ( char c)
static

Convert an ASCII upper-case letter to lower case.

Other characters are returned unchanged.

◆ next_line()

bool next_line ( cur_t * c,
line_t * l )
static

The next line: a complete one, or with open the bytes behind the last line end.

False at the end of the text.

◆ number()

bool number ( const char * s,
size_t n,
size_t * i,
uint32_t * v )
static

Decimal digits from s[*i] on.

False without a digit.

◆ put_char()

void put_char ( buf_t * b,
char c )
static

Append one character to a buffer.

Characters past the capacity are counted but not stored.

◆ read_edited()

kst_file_err_t read_edited ( cur_t * c,
kst_file_t * f )
static

A text may end without a line end, as an editor leaves it.

The last line is then taken when it shows its own end, and the text is refused as truncated when it does not or when the line is not read: a text cut inside a line never gives a shortened number.

◆ read_verified()

kst_file_err_t read_verified ( cur_t * c,
kst_file_t * f )
static

The caller found a line whose first word is "checksum".

Every state below ends at that line or refuses before it, so the loop leaves with the checksum compared.

Behind the checksum line only blank lines pass. The checksum line is the one line taken without its line end: its 17 characters show it whole.

◆ register_row()

bool register_row ( const char * s,
size_t n,
unsigned row,
bool strict,
kst_image_t * img )
static

One line of the register block into its 8 registers.

strict takes the line as kst_file_format() writes it and no other.

◆ take_block_values()

void take_block_values ( const edit_t * e,
kst_file_t * f )
static

An editable field whose line shows what the register block holds takes the block's raw value: several raw values of Max.

Duty show as one percentage, and the line alone gives the one its number converts to.

◆ unit_text()

void unit_text ( const kst_field_t * f,
char * out )
static

What follows the number of a field's value, terminated: "us", "%", "s", "of 12" or nothing.

out holds 8 characters.