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

The CSV reader's byte layer: the sources behind the read/rewind function pointers, the row splitter that handles quoting and line endings, and the delimiter sniffer. More...

#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include "log_csv.h"
#include "log_csv_int.h"

Macros

#define SNIFF_LINES   25
 Most non-blank lines the delimiter sniffer looks at.

Functions

static size_t mem_read (void *ctx, char *buf, size_t max)
 Read from a memory source.
static bool mem_rewind (void *ctx)
 Rewind a memory source to its start.
static bool mem_size (void *ctx, size_t *bytes)
 Length of a memory source.
static bool mem_seek (void *ctx, size_t offset)
 Move a memory source's read position.
void log_source_memory (log_source_t *src, log_mem_ctx_t *ctx, const char *text, size_t len)
 A source over a block of memory.
static size_t file_read (void *ctx, char *buf, size_t max)
 Read from a stdio file.
static bool file_error (void *ctx)
 Whether the last read of a stdio file failed.
static bool file_rewind (void *ctx)
 Rewind a stdio file to its start.
static bool file_size (void *ctx, size_t *bytes)
 fseek and ftell take a long: 2GiB less 1 byte on the panel.
static bool file_seek (void *ctx, size_t offset)
 Move a stdio file's read position.
void log_source_stdio (log_source_t *src, void *file)
 A source over an open stdio stream. file is a FILE*.
void log_reader_init (log_reader_t *r, log_source_t *src)
 Set up a row splitter.
static int reader_fill (log_reader_t *r)
 Refill the read-ahead buffer when it is empty.
static int reader_getc (log_reader_t *r)
 Read one byte, skipping a leading byte order mark.
static int reader_peek (log_reader_t *r)
 Look at the next byte without taking it.
int log_reader_row (log_reader_t *r, char delimiter, char *store, size_t store_size, char **fields, int max_fields, int *total_fields)
 Read one row.
const char * log_csv_delimiter_label (char delimiter)
 Label of a delimiter.
static int count_fields (const char *s, size_t len, char delimiter)
 Count the fields a delimiter makes in one line.
char log_csv_sniff (const char *sample, size_t len)
 Guess the delimiter from a text sample: the most consistent, widest split.

Variables

static char s_empty [1] = ""
 Empty field text, for fields that did not fit the store.
const char log_csv_delimiters [4] = { ';', ',', '\t', '|' }
 The candidate delimiters, in the order they are scored.

Detailed Description

The CSV reader's byte layer: the sources behind the read/rewind function pointers, the row splitter that handles quoting and line endings, and the delimiter sniffer.

A source is a string in memory (tests, the sniff sample) or a stdio file (the card); the row splitter reads either through log_source_t and never holds more than one buffer of it. The splitter and the sniffer take no allocation; the allocator and the analysis built on them are in log_csv.c.

SPDX-License-Identifier: MIT

Function Documentation

◆ count_fields()

int count_fields ( const char * s,
size_t len,
char delimiter )
static

Count the fields a delimiter makes in one line.

Delimiters inside a quoted field are not counted.

Parameters
sThe line.
lenLength of the line, bytes.
delimiterThe candidate delimiter.
Returns
The number of fields, at least 1.

◆ file_error()

bool file_error ( void * ctx)
static

Whether the last read of a stdio file failed.

Parameters
ctxThe FILE *.
Returns
true when the stream has its error flag set.

◆ file_read()

size_t file_read ( void * ctx,
char * buf,
size_t max )
static

Read from a stdio file.

Parameters
ctxThe FILE *.
bufReceives the bytes.
maxCapacity of buf, bytes.
Returns
Bytes read; 0 at the end of the file or on an error.

◆ file_rewind()

bool file_rewind ( void * ctx)
static

Rewind a stdio file to its start.

Parameters
ctxThe FILE *.
Returns
true when the seek succeeded.

◆ file_seek()

bool file_seek ( void * ctx,
size_t offset )
static

Move a stdio file's read position.

Parameters
ctxThe FILE *.
offsetNew position, bytes from the start.
Returns
true when the seek succeeded; false when offset exceeds LONG_MAX.

◆ file_size()

bool file_size ( void * ctx,
size_t * bytes )
static

fseek and ftell take a long: 2GiB less 1 byte on the panel.

A file longer than that answers false, and the analysis reads it on instead.

Parameters
ctxThe FILE *.
bytesReceives the length, bytes.
Returns
true when the length was read.

◆ log_csv_delimiter_label()

const char * log_csv_delimiter_label ( char delimiter)

Label of a delimiter.

Parameters
delimiterThe delimiter.
Returns
A static text.

◆ log_csv_sniff()

char log_csv_sniff ( const char * sample,
size_t len )

Guess the delimiter from a text sample: the most consistent, widest split.

Parameters
sampleThe sample text.
lenLength of sample, bytes.
Returns
The delimiter.

◆ log_reader_init()

void log_reader_init ( log_reader_t * r,
log_source_t * src )

Set up a row splitter.

Parameters
rThe splitter.
srcThe input.

◆ log_reader_row()

int log_reader_row ( log_reader_t * r,
char delimiter,
char * store,
size_t store_size,
char ** fields,
int max_fields,
int * total_fields )

Read one row.

A row ends at its line feed (0x0A). Input that ends inside a row – a write cut off by a power loss or a full card – leaves a row nothing proves complete: a number cut after two of its four digits still parses, and the field count can still match the header. That row is not returned: the call answers -1 as at the end of input and sets r->cut.

Parameters
rThe splitter.
delimiterThe field delimiter.
storescratch for the field text; fields point into it
store_sizeSize of store, bytes.
fieldsreceives one pointer per field, up to max_fields
max_fieldsCapacity of fields, in pointers.
total_fieldsreceives the true field count, which may exceed max_fields; that is how a ragged row is spotted
Returns
the number of fields stored, or -1 at end of input

◆ log_source_memory()

void log_source_memory ( log_source_t * src,
log_mem_ctx_t * ctx,
const char * text,
size_t len )

A source over a block of memory.

Parameters
srcReceives the source.
ctxHolds the read position; set to the start of text.
textThe bytes read.
lenLength of text, bytes.

◆ log_source_stdio()

void log_source_stdio ( log_source_t * src,
void * file )

A source over an open stdio stream. file is a FILE*.

Parameters
srcReceives the source.
fileAn open stream, a FILE *.

◆ mem_read()

size_t mem_read ( void * ctx,
char * buf,
size_t max )
static

Read from a memory source.

Parameters
ctxThe log_mem_ctx_t.
bufReceives the bytes.
maxCapacity of buf, bytes.
Returns
Bytes copied; 0 at the end of the text.

◆ mem_rewind()

bool mem_rewind ( void * ctx)
static

Rewind a memory source to its start.

Parameters
ctxThe log_mem_ctx_t.
Returns
true, always.

◆ mem_seek()

bool mem_seek ( void * ctx,
size_t offset )
static

Move a memory source's read position.

Parameters
ctxThe log_mem_ctx_t.
offsetNew position, bytes from the start.
Returns
false when offset is past the end.

◆ mem_size()

bool mem_size ( void * ctx,
size_t * bytes )
static

Length of a memory source.

Parameters
ctxThe log_mem_ctx_t.
bytesReceives the length, bytes.
Returns
true, always.

◆ reader_fill()

int reader_fill ( log_reader_t * r)
static

Refill the read-ahead buffer when it is empty.

Sets failed when the source reports an error at its end.

Parameters
rThe row splitter.
Returns
1 when bytes are buffered, 0 at the end of input.

◆ reader_getc()

int reader_getc ( log_reader_t * r)
static

Read one byte, skipping a leading byte order mark.

Parameters
rThe row splitter.
Returns
The byte, 0 to 255, or -1 at the end of input.

◆ reader_peek()

int reader_peek ( log_reader_t * r)
static

Look at the next byte without taking it.

Parameters
rThe row splitter.
Returns
The byte, 0 to 255, or -1 at the end of input.