{"id":15048953,"url":"https://github.com/supurloop/ssf","last_synced_at":"2026-04-01T21:14:49.012Z","repository":{"id":38413016,"uuid":"256834986","full_name":"supurloop/ssf","owner":"supurloop","description":"Small System Framework  -  JSON parser/generator, Reed-Solomon, finite state machine framework, and other high quality interfaces for embedded systems.","archived":false,"fork":false,"pushed_at":"2026-03-14T20:42:18.000Z","size":1674,"stargazers_count":26,"open_issues_count":0,"forks_count":5,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-03-15T05:44:12.177Z","etag":null,"topics":["base64-decoding","base64-encoding","byte-fifo-interface","c-language","crc16","crc32","embedded","embedded-systems","finite-state-machine","fletcher-checksum","forward-error-correction","ini-parser","json-parser","linked-list","memory-pool","reed-solomon","sha2","tlv","ubjson"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/supurloop.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-04-18T19:22:45.000Z","updated_at":"2026-03-14T20:38:53.000Z","dependencies_parsed_at":"2023-12-17T15:31:07.792Z","dependency_job_id":"89dbefea-ee2a-49b1-a4fd-0936c7cce09a","html_url":"https://github.com/supurloop/ssf","commit_stats":null,"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"purl":"pkg:github/supurloop/ssf","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/supurloop%2Fssf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/supurloop%2Fssf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/supurloop%2Fssf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/supurloop%2Fssf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/supurloop","download_url":"https://codeload.github.com/supurloop/ssf/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/supurloop%2Fssf/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31292096,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T13:12:26.723Z","status":"ssl_error","status_checked_at":"2026-04-01T13:12:25.102Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["base64-decoding","base64-encoding","byte-fifo-interface","c-language","crc16","crc32","embedded","embedded-systems","finite-state-machine","fletcher-checksum","forward-error-correction","ini-parser","json-parser","linked-list","memory-pool","reed-solomon","sha2","tlv","ubjson"],"created_at":"2024-09-24T21:17:19.604Z","updated_at":"2026-04-01T21:14:49.002Z","avatar_url":"https://github.com/supurloop.png","language":"C","readme":"# ssf\n\nSmall System Framework\n\nA hardened, easily portable, API consistent, C source code library of production ready functionality for small memory embedded systems.\n\n[Overview](#overview) | [Design Principles](#designprinciples) | [Porting](#porting) | [Interfaces](#interfaces) | [Conclusion](#conclusion)\n\n\u003ca id=\"overview\"\u003e\u003c/a\u003e\n\n## Overview\n\nThis code framework was specifically designed:\n\n1. To run on embedded systems that have constrained program and data memories.\n2. To minimize the potential for common coding errors and immediately detect and report runtime errors.\n\nMicroprocessors with \u003e4KB RAM and \u003e32KB program memory should easily be able to utilize this framework.\nPortions of the framework will work on even smaller microcontrollers.\n\n\u003ca id=\"designprinciples\"\u003e\u003c/a\u003e\n\n## Design Principles\n\n### No Dependencies \n\nWhen you use the SSF, you just need the SSF and not a single other external dependency except for a few C standard library calls. No new definitions for basic data types that complicate your code base and cloud your mind; SSF uses \u003cstdint.h\u003e and \u003cstdbool.h\u003e for basic data types.\n\n### No Error Codes\n\nToo often API error codes are ignored in part or in whole, or improperly handled due to overloaded encodings (ex. \u003c0=error, 0=ignored, \u003e0=length)\n\nEither a SSF API call will always succeed, or it will return a boolean: true on success and false on failure.\nThat's it. Any function outputs are handled via the parameter list.\nThis makes application error handling simple to implement, and much less prone to errors.\n\n### Militant Buffer and C String Overrun Protection\n\nAll SSF interfaces require the total allocated size of buffers and C strings to be passed as arguments.\nThe SSF API will never write beyond the end of a buffer or C string.\nAll C strings returned by a successful SSF API call are guaranteed to be NULL terminated.\n\nUse the Safe C string SSF API to replace crash inducing strlen(), strcat(), strcpy(), and strcmp(), and other \"safe\" C library calls that don't always ensure NULL termination like strncpy().\n\n### Design by Contract\n\nTo help ensure correctness the framework uses Design by Contract techniques to immediately catch common errors that tend to creep into systems and cause problems at the worst possible times.\n\nDesign by Contract uses assertions, conditional code that ensures that the state of the system at runtime is operating within the allowable tolerances. The assertion interface uses several macros that hint at the assertions purpose. SSF_REQUIRE() is used to check function input parameters. SSF_ENSURE() is used to check the return result of a function. SSF_ASSERT() is used to check any other system state. SSF_ERROR() always forces an assertion.\n\nThe framework does NOT use assertions when operating on inputs that likely come from external sources. For example, the SSF JSON parser will NOT assert if the input string is not valid JSON syntax, but it will assert if a NULL pointer is passed in as the pointer to the input.\n\nThe framework will also detect common errors like using interfaces before they have been properly initialized.\n\n### Hardened and Tested\n\nFor the main port testing platforms of Windows, Linux, and Mac OS, all relevant compiler warnings are turned on. SSF compiles cleanly on them all.\n\nSSF is linted using Visual Studio's static analysis tool with no warnings.\n \nSSF has been reviewed for buffer overflows and general correctness by Claude Code.\n \nEvery SSF interface has a suite of unit tests that MUST PASS completely on all of the main port testing platforms.\n \nThe author uses various modules of SSF in several different commercial products using a variety of microcontrollers and toolchains.\n \n\u003ca id=\"porting\"\u003e\u003c/a\u003e\n\n## Porting\n\nThis framework has been successfully ported and unit tested on the following platforms: Windows Visual Studio 32/64-bit, Linux 32/64-bit (GCC), MAC OS X, PIC32 (XC32), PIC24 (XC16), MSP430 (TI 15.12.3.LTS), and many others. You should only need to change [`ssfport.c` and `ssfport.h`](ssfport.md) to implement a successful port.\n\nThe code will compile cleanly and not report any analyzer(Lint) warnings under Windows in Visual Studio using the ssf.sln solution file.\nThe code will compile cleanly under Linux. ./build-linux.sh will create the ssf executable in the source directory.\nThe code will compile cleanly under OS X. ./build-macos.sh will create the ssf executable in the source directory.\n\nThe Windows, Linux, and Mac OS builds are setup to output all compiler warnings.\n\nFor other platforms there are only a few essential tasks that must be completed:\n\n-   Copy the top level source files except main.c and some or all of the submodules into your project sources and add them to your build environment.\n-   In ssfport.h make sure SSF_TICKS_PER_SEC is set to the number of system ticks per second on your platform.\n-   Map SSFPortGetTick64() to an existing function that returns the number of system ticks since boot, or\n    implement SSFPortGetTick64() in ssfport.c if a simple mapping is not possible.\n-   In ssfport.h make sure to follow the instructions for the byte order macros.\n-   Run the unit tests for the modules you intend to use.\n\nOnly a few modules in the framework use system ticks, so you can stub out SSFPortGetTick64() if it is not needed.\nIf the framework runs in a multi-threaded environment and uses non-reentrant modules define SSF_CONFIG_ENABLE_THREAD_SUPPORT and implement the OS synchronization primitives.\n\n### SSFPortAssert()\n\nFor a production ready embedded system you should properly implement SSFPortAssert().\n\nFirst, I recommend that it should somehow safely record the file and line number where the assertion occurred so that it can be reported on the next boot.\n\nSecond, the system should be automatically reset rather than sitting forever in a loop.\n\nThird, the system should have a safe boot mode that kicks in if the system reboots quickly many times in a row.\n\n### RTOS Support\n\nYou may have heard the terms bare-metal or superloop to describe single thread of execution systems that lack an OS.\nThis library is designed to primarily* run in a single thread of execution which avoids much of the overhead and pitfalls associated with RTOSes.\n(*See Byte FIFO Interface for an explanation of how to deal with interrupts.)\n\nVery few small memory systems need to have a threaded/tasked/real-time capable OS.\nRTOSes introduce significant complexity, and in particular a dizzying amount of opportunity for introducing subtle race conditions (BUGS) that are easy to create and difficult to find and fix.\n\nThat said this framework can run perfectly fine with an RTOS, Windows, or Linux, so long as some precautions are taken.\n\nExcept for the finite state machine, RTC, and heap modules, all interfaces are reentrant.\nThis means that calls into those interfaces from different execution contexts will not interfere with each other.\n\nFor example, you can have linked list object A in task 1 and linked list object B in task 2 and they will be managed independently and correctly, so long as they are only accessed from the context of their respective task.\n\nTo ensure safe operation of the non-renetrant modules in a multi-threaded system SSF_SM_CONFIG_ENABLE_THREAD_SUPPORT must be enabled and synchronization macros must be implemented.\n\n### Deinitialization\n\nThis library has added support to deinitialize interfaces that have initialization functions. Primarily deinitialization was added to allow the library to better integrate with unit test frameworks.\n\n\u003ca id=\"interfaces\"\u003e\u003c/a\u003e\n\n## Interfaces\n\n\u003e **Size estimates** are for ARM Cortex-M (Thumb-2) compiled with maximum size optimization (-Os).\n\u003e Flash includes compiled code and any ROM lookup tables. Static RAM is memory permanently\n\u003e consumed by the module itself; it excludes user-allocated objects. Peak Stack is the maximum\n\u003e call-stack usage during any single API call, including all nested frames and local working\n\u003e buffers. Heap indicates whether the module calls `malloc`/`free` during normal operation.\n\u003e Reentrant indicates whether the module can be safely called from independent execution\n\u003e contexts simultaneously — i.e., it holds no shared mutable state between calls.\n\n#### [Data Structures](_struct/README.md)\n\nEfficient data structure primitives for embedded systems, designed to avoid dynamic memory fragmentation and catch misuse at runtime.\n\n| Module | Description | Flash | Static RAM | Peak Stack | Heap | Reentrant |\n|--------|-------------|-------|------------|------------|------|-----------|\n| [Byte FIFO](_struct/ssfbfifo.md) | Interrupt-safe byte FIFO with single-byte and multi-byte put/get | ~900 B | — | ~80 B | — | Yes |\n| [Linked List](_struct/ssfll.md) | Doubly-linked list supporting FIFO and stack behaviors | ~800 B | — | ~64 B | — | Yes |\n| [Memory Pool](_struct/ssfmpool.md) | Fixed-size block memory pool with no fragmentation | ~800 B | — | ~96 B | — | Yes |\n| [Heap](_struct/ssfheap.md) | Integrity-checked heap with double-free detection and mark-based ownership tracking | ~3.5 KB | — | ~96 B | — | No¹⁹ |\n\n#### [Codecs](_codec/README.md)\n\nEncoding and decoding interfaces for common data formats, all with strict buffer size enforcement and null-terminated output guarantees.\n\n| Module | Description | Flash | Static RAM | Peak Stack | Heap | Reentrant |\n|--------|-------------|-------|------------|------------|------|-----------|\n| [Base64](_codec/ssfbase64.md) | Base64 encoder/decoder | ~700 B | — | ~64 B | — | Yes |\n| [Hex ASCII](_codec/ssfhex.md) | Binary-to-hex ASCII encoder/decoder | ~600 B | — | ~64 B | — | Yes |\n| [JSON](_codec/ssfjson.md) | JSON parser/generator with path-based field access and in-place update | ~7 KB | — | ~250 B⁹ | — | Yes |\n| [TLV](_codec/ssftlv.md) | Type-Length-Value encoder/decoder | ~1.2 KB | — | ~96 B | — | Yes |\n| [INI](_codec/ssfini.md) | INI file parser/generator | ~3.5 KB | — | ~64 B | — | Yes |\n| [UBJSON](_codec/ssfubjson.md) | Universal Binary JSON parser/generator | ~9 KB | — | ~270 B¹⁰ | — | Yes |\n| [Decimal](_codec/ssfdec.md) | Integer-to-decimal string converter | ~2.5 KB | — | ~96 B | — | Yes |\n| [Safe Strings](_codec/ssfstr.md) | Safe C string interface replacing crash-prone standard functions | ~1.2 KB | — | ~64 B | — | Yes |\n| [Generic Object](_codec/ssfgobj.md) | BETA: Hierarchical generic object parser/generator for cross-codec in-memory representation | ~3 KB | ~8 B | ~160 B¹¹ | yes¹⁵ | Yes¹⁷ |\n\n⁹ Recursive parser; stack scales with `SSF_JSON_CONFIG_MAX_IN_DEPTH` (default 4). Estimate uses the default depth; each additional nesting level adds ~64 B.\n\n¹⁰ Recursive parser; stack scales with `SSF_UBJSON_CONFIG_MAX_IN_DEPTH` (default 4). Estimate uses the default depth; each additional nesting level adds ~68 B.\n\n¹¹ Recursive iteration; stack scales with `SSF_GOBJ_CONFIG_MAX_IN_DEPTH` (default 4). Estimate uses the default depth; each additional nesting level adds ~40 B.\n\n¹⁷ No shared mutable state in production builds. Reentrancy depends on the platform `malloc`/`free` implementation; most production C libraries provide thread-safe allocators.\n\n#### [Error Detection Codes (EDC)](_edc/README.md)\n\nData integrity interfaces for detecting transmission and storage errors.\n\n| Module | Description | Flash | Static RAM | Peak Stack | Heap | Reentrant |\n|--------|-------------|-------|------------|------------|------|-----------|\n| [Fletcher Checksum](_edc/ssffcsum.md) | 16-bit Fletcher checksum | ~120 B | — | ~48 B | — | Yes |\n| [CRC-16](_edc/ssfcrc16.md) | 16-bit CRC (XMODEM/CCITT-16) | ~650 B¹ | — | ~32 B | — | Yes |\n| [CRC-32](_edc/ssfcrc32.md) | 32-bit CRC (CCITT-32) | ~1.2 KB² | — | ~32 B | — | Yes |\n\n¹ Includes 512 B lookup table. ² Includes 1 KB lookup table.\n\n#### [Error Correction Codes (ECC)](_ecc/README.md)\n\nForward error correction for recovering data corrupted during transmission or storage.\n\n| Module | Description | Flash | Static RAM | Peak Stack | Heap | Reentrant |\n|--------|-------------|-------|------------|------------|------|-----------|\n| [Reed-Solomon](_ecc/README.md) | Reed-Solomon forward error correction encoder/decoder | ~4.5 KB³ | — | ~600 B¹² | — | Yes |\n\n³ Includes ~768 B of GF(256) logarithm, exponent, and inverse lookup tables.\n\n¹² Peak stack occurs in the error locator function, which holds four `GFPoly_t` working polynomials on the stack. Each polynomial is `SSF_RS_MAX_CHUNK_SIZE + SSF_RS_MAX_SYMBOLS` bytes (default 135 B). Stack scales with these configuration constants.\n\n#### [Cryptography](_crypto/README.md)\n\nCryptographic primitives for hashing, encryption, and random number generation.\n\n| Module | Description | Flash | Static RAM | Peak Stack | Heap | Reentrant |\n|--------|-------------|-------|------------|------------|------|-----------|\n| [SHA-2](_crypto/ssfsha2.md) | SHA-2 hash (SHA-224/256/384/512/512-224/512-256), one-shot and incremental | ~3 KB⁴ | — | ~800 B¹³ | — | Yes |\n| [AES](_crypto/ssfaes.md) | AES block cipher (128/192/256-bit key) | ~2 KB⁵ | — | ~300 B¹⁴ | — | Yes |\n| [AES-GCM](_crypto/ssfaesgcm.md) | AES-GCM authenticated encryption/decryption | ~3.5 KB⁶ | — | ~128 B | — | Yes |\n| [PRNG](_crypto/ssfprng.md) | Cryptographically capable pseudo-random number generator | ~500 B | — | ~96 B | — | Yes |\n\n⁴ Includes ~896 B of SHA-256 and SHA-512 round constants. ⁵ Includes 512 B S-box and inverse S-box tables. ⁶ Requires AES module; figure is for GCM logic only.\n\n¹³ SHA-512 block processing (`_SSFSHA2_64Block`) dominates: the message schedule `w[80]` of `uint64_t` alone consumes 640 B of stack. SHA-256 peak is ~400 B.\n\n¹⁴ The AES key schedule is expanded into a local `w[60]` array of `uint32_t` (240 B) on every encrypt/decrypt call. The AES-256 key schedule is the worst case.\n\n#### [Storage](_storage/README.md)\n\nReliable non-volatile storage with versioning and integrity checking for configuration data.\n\n| Module | Description | Flash | Static RAM | Peak Stack | Heap | Reentrant |\n|--------|-------------|-------|------------|------------|------|-----------|\n| [Storage](_storage/README.md) | Version-controlled interface for reliably storing configuration to NV storage | ~1.2 KB | — | ~100 B | — | Yes |\n\n#### [Finite State Machine](_fsm/README.md)\n\nEvent-driven state machine framework suitable for both bare-metal and RTOS environments.\n\n| Module | Description | Flash | Static RAM | Peak Stack | Heap | Reentrant |\n|--------|-------------|-------|------------|------------|------|-----------|\n| [Finite State Machine](_fsm/README.md) | Event-driven finite state machine framework with optional RTOS integration | ~2.5 KB | ~150 B⁷ | ~64 B | yes¹⁶ | No¹⁹ |\n\n⁷ Static RAM scales with `SSF_SM_MAX` (number of configured state machines). Estimate is for the default single-SM configuration; excludes user-supplied event and timer pool memory.\n\n¹⁶ Events and timers are allocated from user-configured fixed-size pools (no heap). System `malloc` is called only when an event carries a data payload larger than `sizeof(pointer)` (4 B on ARM).\n\n¹⁹ Enable `SSF_CONFIG_ENABLE_THREAD_SUPPORT` and implement the corresponding synchronization macros in `ssfport.h` to make this module safe for concurrent multi-context use.\n\n#### [Debug](_debug/README.md)\n\nDebug and diagnostic interfaces for runtime tracing.\n\n| Module | Description | Flash | Static RAM | Peak Stack | Heap | Reentrant |\n|--------|-------------|-------|------------|------------|------|-----------|\n| [Debug Trace](_debug/ssftrace.md) | FIFO-backed debug trace buffer with automatic oldest-byte discard and optional mutex protection | ~200 B | — | ~48 B | — | Yes²⁰ |\n\n²⁰ Each `SSFTrace_t` instance is independent. When `SSF_CONFIG_ENABLE_THREAD_SUPPORT == 1`, the macros acquire and release a per-instance mutex around each access, making concurrent use from multiple contexts safe.\n\n#### [Time](_time/README.md)\n\nTime management interfaces covering raw tick time, calendar conversion, and ISO 8601 string formatting.\n\n| Module | Description | Flash | Static RAM | Peak Stack | Heap | Reentrant |\n|--------|-------------|-------|------------|------------|------|-----------|\n| [RTC](_time/ssfrtc.md) | Unix time real-time clock interface | ~900 B | ~20 B⁸ | ~48 B | — | Yes¹⁸ |\n| [Date/Time](_time/ssfdtime.md) | Unix time to calendar date/time struct conversion | ~1.8 KB | — | ~96 B | — | Yes |\n| [ISO 8601](_time/ssfiso8601.md) | ISO 8601 date/time string formatting and parsing with timezone support | ~1.8 KB | — | ~120 B | — | Yes |\n\n⁸ RTC static RAM holds two initialization flags and two 64-bit tick reference values.\n\n¹⁵ Each `SSFGObjInit` call allocates one `SSFGObj_t` node struct (~48 B) via system `malloc`. `SSFGObjSetLabel` and `SSFGObjSet*` add further per-field allocations for labels and value data.\n\n¹⁸ Concurrent calls to `SSFRTCGetUnixNow` from multiple contexts are safe (read-only after init). Enable `SSF_CONFIG_ENABLE_THREAD_SUPPORT` if `SSFRTCSetUnixNow` may be called concurrently with `SSFRTCGetUnixNow`.\n\n\u003ca id=\"conclusion\"\u003e\u003c/a\u003e\n\n## Conclusion\n\nI built this framework for primarily myself, although I hope you can find a good use for it.\n\nSpecial thanks to my son, Calvin, for researching, implementing, and debugging the AES Block and AES-GCM interfaces!\n\nDrop me a line if you have a question or comment.\n\nJim Higgins\n\nPresident\n\nSupurloop Software\n\njim@supurloop.com\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsupurloop%2Fssf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsupurloop%2Fssf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsupurloop%2Fssf/lists"}