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

Servo configuration files on the card: names, saving, listing, loading. More...

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "card_tree.h"

Go to the source code of this file.

Data Structures

struct  kst_store_io_t
 The card. More...
struct  kst_store_entry_t
 One row of a list. More...

Macros

#define KST_STORE_DIR   CARD_KST_CONF
 The folder of the card that holds the files, made level by level on the first save.
#define KST_STORE_EXT   ".TXT"
 The extension of every file, added by this layer.
#define KST_STORE_BASE_MAX   32
 Characters of a base name at most.
#define KST_STORE_NAME_MAX   (KST_STORE_BASE_MAX + 4 + 1)
 Room for a file name: base name, extension and terminator.
#define KST_STORE_FIRST   1
 The first and the last number of a proposed name.
#define KST_STORE_LAST   999
#define KST_STORE_PRESET_MAX   7
 Room for "KST999" and its terminator.
#define KST_STORE_RECORD   "KST"
 The base name this layer keeps free, in any case: "KST.TXT" in the directory is the caller's record of a write under way and no servo file.

Typedefs

typedef void(*) kst_store_visit_fn(const char *name, bool is_dir, void *visit_ctx)
 Receives one directory entry. name does not outlive the call.

Enumerations

enum  kst_store_name_t {
  KST_STORE_NAME_OK = 0 , KST_STORE_NAME_EMPTY = 1 , KST_STORE_NAME_TOO_LONG = 2 , KST_STORE_NAME_BAD_CHAR = 3 ,
  KST_STORE_NAME_RESERVED = 4 , KST_STORE_NAME_EDGE = 5
}
 Whether a base name is taken. More...
enum  kst_store_t {
  KST_STORE_OK = 0 , KST_STORE_ARG = 1 , KST_STORE_NO_CARD = 2 , KST_STORE_LIST_ERROR = 3 ,
  KST_STORE_NO_NUMBER = 4 , KST_STORE_BAD_NAME = 5 , KST_STORE_EXISTS = 6 , KST_STORE_CARD_FULL = 7 ,
  KST_STORE_WRITE_ERROR = 8 , KST_STORE_NOT_FOUND = 9 , KST_STORE_TOO_LARGE = 10 , KST_STORE_READ_ERROR = 11 ,
  KST_STORE_DENIED = 12
}
 The result of a call. More...
enum  kst_store_io_result_t {
  KST_STORE_IO_OK = 0 , KST_STORE_IO_EXISTS , KST_STORE_IO_FULL , KST_STORE_IO_ERROR ,
  KST_STORE_IO_DENIED
}
 What the create function reports. More...

Functions

kst_store_name_t kst_store_name_check (const char *base)
 Whether base is a base name this layer writes.
bool kst_store_file_name (const char *base, char *out, size_t out_size)
 The file name of base: the base name and KST_STORE_EXT.
kst_store_t kst_store_preset (const kst_store_io_t *io, char *base, size_t base_size)
 Propose a base name: "KST" and 3 digits, one above the highest number the directory holds.
kst_store_t kst_store_save (const kst_store_io_t *io, const char *base, const char *text, size_t len, kst_store_name_t *why)
 Write len bytes of text as the file of base.
kst_store_t kst_store_list (const kst_store_io_t *io, kst_store_entry_t *entries, size_t cap, size_t *count, size_t *total, size_t *skipped)
 List the files with KST_STORE_EXT.
kst_store_t kst_store_list_after (const kst_store_io_t *io, const char *after, kst_store_entry_t *entries, size_t cap, size_t *count, size_t *total, size_t *skipped)
 kst_store_list() from the file behind after on: entries receives the first cap files the order has behind the name after, a file name with its extension that need not exist.
kst_store_t kst_store_load (const kst_store_io_t *io, const char *name, char *buf, size_t cap, size_t *len)
 Read the file name, a name as kst_store_list() gives it, into buf. len receives the number of bytes.

Detailed Description

Servo configuration files on the card: names, saving, listing, loading.

The files live in the folder KST_STORE_DIR of the card, BENCH/KST/CONF (card_tree.h), apart from the run logs. The folder KST of firmware 0.21 and older is not read. A file is "<base name>.TXT". The base name is a person's choice; kst_store_preset() proposes "KST001" to "KST999". This layer adds the extension and holds every name to what the card's file system and a desktop computer both take.

The panel's FAT (File Allocation Table) file system is built with long file names, 255 characters (CONFIG_FATFS_MAX_LFN). Its directory walk passes names of 63 characters or fewer, which leaves 59 for a base name. KST_STORE_BASE_MAX is 32: the length a list row and an entry field show. FAT keeps the case of a name and compares without it, so "Wing.TXT" and "WING.TXT" are one file; this layer compares the same way.

A save never replaces a file.

The card is reached through kst_store_io_t, 5 functions the caller supplies, so the layer runs on a host without a card. It handles bytes and names and knows nothing of the file's content.

Pure C, no ESP-IDF (Espressif Internet-of-Things Development Framework).

SPDX-License-Identifier: MIT

Macro Definition Documentation

◆ KST_STORE_RECORD

#define KST_STORE_RECORD   "KST"

The base name this layer keeps free, in any case: "KST.TXT" in the directory is the caller's record of a write under way and no servo file.

The name is refused as KST_STORE_NAME_RESERVED, so no save writes it and no load reads it; kst_store_list() leaves the file out and does not count it. The layer itself never reads, writes or removes the file.

Enumeration Type Documentation

◆ kst_store_io_result_t

What the create function reports.

Enumerator
KST_STORE_IO_EXISTS 

the name is taken; nothing was written

KST_STORE_IO_FULL 

no space; the function removed what it created

KST_STORE_IO_ERROR 

any other failure; likewise removed

KST_STORE_IO_DENIED 

the card takes no file: it is write protected, or the directory cannot be made because a file has its name. Nothing was written

◆ kst_store_name_t

Whether a base name is taken.

The numbers are stable.

Enumerator
KST_STORE_NAME_EMPTY 

no character, or NULL

KST_STORE_NAME_TOO_LONG 

more than KST_STORE_BASE_MAX characters

KST_STORE_NAME_BAD_CHAR 

a character outside 0x20 to 0x7E, or one of " * / : < > ? \ |

KST_STORE_NAME_RESERVED 

CON, PRN, AUX, NUL, COM1 to COM9 or LPT1 to LPT9, in any case, alone or in front of a full stop: a device name on a desktop computer. Or KST_STORE_RECORD, in any case

KST_STORE_NAME_EDGE 

a full stop or a space at the start or at the end

◆ kst_store_t

The result of a call.

The numbers are stable.

Enumerator
KST_STORE_ARG 

a NULL argument or a buffer too small

KST_STORE_NO_CARD 

no card is mounted

KST_STORE_LIST_ERROR 

the directory does not read to its end

KST_STORE_NO_NUMBER 

KST001 to KST999 are all taken

KST_STORE_BAD_NAME 

the name fails kst_store_name_check()

KST_STORE_EXISTS 

the name is taken; nothing is written

KST_STORE_NOT_FOUND 

no file has that name

KST_STORE_TOO_LARGE 

the file is larger than the buffer

KST_STORE_DENIED 

the card takes no file: it is write protected, or a file has the name of the directory

Function Documentation

◆ kst_store_file_name()

bool kst_store_file_name ( const char * base,
char * out,
size_t out_size )

The file name of base: the base name and KST_STORE_EXT.

False, with an empty string in out, for a base name that fails kst_store_name_check() and for an out_size under KST_STORE_NAME_MAX.

Parameters
baseThe base name.
outReceives the file name.
out_sizeSize of out, bytes.
Returns
true when out holds the file name.

◆ kst_store_list()

kst_store_t kst_store_list ( const kst_store_io_t * io,
kst_store_entry_t * entries,
size_t cap,
size_t * count,
size_t * total,
size_t * skipped )

List the files with KST_STORE_EXT.

The order: by name without case. The files named "KST" and 3 digits stand in one run at the place of "KST000", by falling number. kst_store_preset() gives a later file the higher number until KST999 is taken, so the run starts with the latest of them.

entries receives the first cap of them. count is the number written, total the number of files that qualify, skipped the number of files with the extension whose base name fails kst_store_name_check(): those are not listed and not loaded. The file named KST_STORE_RECORD is in none of the 3 numbers. Each of the 3 may be NULL. Directories are not listed. A directory without a file gives KST_STORE_OK and a count of 0.

Parameters
ioThe card functions.
entriesReceives the listed names.
capCapacity of entries, in entries.
countReceives the number of entries written, or NULL.
totalReceives the number of qualifying files, or NULL.
skippedReceives the number of files with a bad name, or NULL.
Returns
KST_STORE_OK, or the reason the directory did not list.

◆ kst_store_list_after()

kst_store_t kst_store_list_after ( const kst_store_io_t * io,
const char * after,
kst_store_entry_t * entries,
size_t cap,
size_t * count,
size_t * total,
size_t * skipped )

kst_store_list() from the file behind after on: entries receives the first cap files the order has behind the name after, a file name with its extension that need not exist.

NULL lists from the first file on. total and skipped count the whole directory as kst_store_list() does.

A caller reaches every file of a directory in a buffer of cap entries by passing the last name of one call to the next; each call walks the directory once.

Parameters
ioThe card functions.
afterThe file name to list after, or NULL.
entriesReceives the listed names.
capCapacity of entries, in entries.
countReceives the number of entries written, or NULL.
totalReceives the number of qualifying files, or NULL.
skippedReceives the number of files with a bad name, or NULL.
Returns
KST_STORE_OK, or the reason the directory did not list.

◆ kst_store_load()

kst_store_t kst_store_load ( const kst_store_io_t * io,
const char * name,
char * buf,
size_t cap,
size_t * len )

Read the file name, a name as kst_store_list() gives it, into buf. len receives the number of bytes.

No terminator is written.

Parameters
ioThe card functions.
nameThe file name.
bufReceives the bytes.
capCapacity of buf, bytes.
lenReceives the number of bytes read.
Returns
KST_STORE_OK, or the reason the file was not read.

◆ kst_store_name_check()

kst_store_name_t kst_store_name_check ( const char * base)

Whether base is a base name this layer writes.

Parameters
baseThe base name, without extension.
Returns
KST_STORE_NAME_OK, or the first rule the name breaks.

◆ kst_store_preset()

kst_store_t kst_store_preset ( const kst_store_io_t * io,
char * base,
size_t base_size )

Propose a base name: "KST" and 3 digits, one above the highest number the directory holds.

A gap below the highest number is not filled, so a higher number is a later file. With KST999 taken the lowest free number is proposed. Files and directories count, in any case; a file with another name counts for nothing.

base_size is KST_STORE_PRESET_MAX or more.

Parameters
ioThe card functions.
baseReceives the proposed base name.
base_sizeSize of base, bytes.
Returns
KST_STORE_OK, or the reason no name was proposed.

◆ kst_store_save()

kst_store_t kst_store_save ( const kst_store_io_t * io,
const char * base,
const char * text,
size_t len,
kst_store_name_t * why )

Write len bytes of text as the file of base.

KST_STORE_BAD_NAME leaves the reason in why, when not NULL. A name the directory holds, compared without case, gives KST_STORE_EXISTS and the file stays as it is.

Parameters
ioThe card functions.
baseThe base name of the file.
textThe bytes to write.
lenNumber of bytes in text.
whyReceives the name reason when refused, or NULL.
Returns
KST_STORE_OK, or the reason the file was not written.