Skip to content

Commit

Permalink
v3.0.0
Browse files Browse the repository at this point in the history
(Incompatible with v2.x usage, although the underlying changes are minor.)

The biggest change is new function/struct names. The snakecase has been replaced to reduce long lines of code when using the library.

Each struct has its name prefixing the function name, followed by _read. This makes a clean assocation between each type (e.g. `TFHeader` and `TFHeader_read`).

`enum tf_err_t` -> `TFError`
`tf_err_str` -> `TFError_string`
`struct tf_var_header_t` -> `TFVarHeader`
`tf_read_var_header` -> `TFVarHeader_read`
`struct tf_file_header_t` -> `TFHeader`
`tf_read_file_header` -> `TFHeader_read`
...

Ignoring the new typedefs, the struct names are mostly unchanged with the exception of `struct tf_file_header_t` being shortened to `struct tf_header_t`.

There were multiple errors describing undersized buffers provided to _read functions. They have been unified into a single `TF_EINVALID_BUFFER_SIZE` error value.

The previously definable macro, TINYFSEQ_MEMCPY, was replaced with usage of `__builtin_memcpy`.
  • Loading branch information
Cryptkeeper committed Dec 20, 2023
1 parent 4c274a8 commit aeb161f
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 227 deletions.
12 changes: 7 additions & 5 deletions .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,22 @@
BasedOnStyle: LLVM
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: AcrossComments
AlignConsecutiveDeclarations: AcrossComments
AlignConsecutiveAssignments: Consecutive
AlignConsecutiveMacros: Consecutive
AlignOperands: Align
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Always
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: Always
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterReturnType: None
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
BinPackParameters: false
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: false
Expand All @@ -34,7 +36,7 @@ BreakBeforeBinaryOperators: None
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
ColumnLimit: 0
ColumnLimit: 80
CompactNamespaces: false
ContinuationIndentWidth: 8
IndentCaseLabels: true
Expand Down
36 changes: 10 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,15 @@
# libtinyfseq

A single-file library (~150 LOC) for decoding FSEQ (.fseq) v2.0+ sequence files developed and popularized by
the [fpp](https://github.com/FalconChristmas/fpp) and [xLights](https://github.com/smeighan/xLights) programs.
Additional documentation for the file format is available
at [Cryptkeeper/fseq-file-format](https://github.com/Cryptkeeper/fseq-file-format).
A single-file library (~150 LOC) for decoding FSEQ (.fseq) v2.0+ sequence files developed and popularized by the [fpp](https://github.com/FalconChristmas/fpp) and [xLights](https://github.com/smeighan/xLights) programs. Additional documentation for the file format is available at [Cryptkeeper/fseq-file-format](https://github.com/Cryptkeeper/fseq-file-format).

## Installation

- Download and copy `tinyfseq.h` into your project locally, or to your toolchain's include paths
- `#include "tinyfseq.h"` as expected (you may need to modify the path).
- Define `TINYFSEQ_IMPLEMENTATION` in a single C/C++ source code
file ([more info on using single-file libraries](https://github.com/nothings/stb#how-do-i-use-these-libraries))
- Define `TINYFSEQ_IMPLEMENTATION` in a single C/C++ source code file ([more info on using single-file libraries](https://github.com/nothings/stb#how-do-i-use-these-libraries))

A short example of including libtinyfseq and decoding a file header is available in [`example.c`](example.c)

## Library Configuration

Prior to including `tinyfseq.h`, two definition based options are available:

1. `TINYFSEQ_MEMCPY` allows you to override the selected `memcpy` function with whatever is best for your platform (
currently a basic freestanding implementation, `tf_memcpy_impl`)
2. `TINYFSEQ_STRIP_ERR_STRINGS` replaces all literal strings returned by `tf_err_str` with `"NULL"` (as a string) to
reduce the compiled binary size

## Compatibility

- libtinyfseq uses `stdint.h` for fixed-size int types
Expand All @@ -31,19 +18,16 @@ Prior to including `tinyfseq.h`, two definition based options are available:

## Usage

libtinyfseq only defines three functions for reading the various components of a FSEQ file. See [tinyfseq.h](tinyfseq.h)
for comments describing their usage.

| Function | Schema |
| ----------------------- | ------------------------------------------------------------ |
| `tf_read_file_header` | https://github.com/Cryptkeeper/fseq-file-format#header |
| `tf_read_var_header` | https://github.com/Cryptkeeper/fseq-file-format#variable |
| `tf_read_channel_range` | https://github.com/Cryptkeeper/fseq-file-format#sparse-range |
libtinyfseq provides decoding functions for the following components of a FSEQ file. See [tinyfseq.h](tinyfseq.h) for comments describing their specific usage.

Two additional utility functions are provided:
| Function | Schema | Type |
| ------------------------- | ----------------------------------------------------------------- | -------------------- |
| `TFHeader_read` | https://github.com/Cryptkeeper/fseq-file-format#header | `TFHeader` |
| `TFVarHeader_read` | https://github.com/Cryptkeeper/fseq-file-format#variable | `TFVarHeader` |
| `TFChannelRange_read` | https://github.com/Cryptkeeper/fseq-file-format#sparse-range | `TFChannelRange` |
| `TFCompressionBlock_read` | https://github.com/Cryptkeeper/fseq-file-format#compression-block | `TFCompressionBlock` |

1. `tf_sequence_duration_seconds` for calculating the duration of a given sequence in seconds
2. `tf_err_str` for mapping `enum tf_err_t` values into their string names
All decoding functions return a `TFError` value, with `TF_OK` indicating success. If an error occurs, the value will be non-zero. An error string can be retrieved via `TFError_string` (and should _not_ be freed by the caller).

## License

Expand Down
25 changes: 16 additions & 9 deletions example.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,26 +42,33 @@ static uint8_t FILE_DATA[] = {
'U',
};

int main() {
int main(const int argc, char **const argv) {
(void) argc;
(void) argv;

printf("using tinyfseq v%s\n", TINYFSEQ_VERSION);

struct tf_file_header_t header;
TFHeader header;
TFError err;

// read the "embedded" file, FILE_DATA
enum tf_err_t err;
if ((err = tf_read_file_header(FILE_DATA, sizeof(FILE_DATA), &header, NULL))) {
return err;
if ((err = TFHeader_read(FILE_DATA, sizeof(FILE_DATA), &header, NULL))) {
printf("libtinyfseq error: %s\n", TFError_string(err));

return 1;
}

// TODO: use header fields, read variables, etc.

// sequenceUid is an uint64_t that normally stores a timestamp
// instead it carries an 8-byte string message
// this assert call validates the decoded header prior to printing the char values
assert(header.sequenceUid == 6147230170719669321);

int bit_idx;
for (bit_idx = 0; bit_idx < 64; bit_idx += 8) {
uint64_t bit_mask = ((uint64_t) 0xFFu) << bit_idx;
printf("%c", (uint8_t) ((header.sequenceUid & bit_mask) >> bit_idx));
for (int i = 0; i < 64; i += 8) {
const uint64_t mask = (uint64_t) 0xFFu << i;

printf("%c", (uint8_t) ((header.sequenceUid & mask) >> i));
}

printf("\n");
Expand Down
Loading

0 comments on commit aeb161f

Please sign in to comment.