77![ GitHub Stars] ( https://img.shields.io/github/stars/diffstorm/ini_parser?style=social )
88![ Platforms] ( https://img.shields.io/badge/Platform-Linux%20%7C%20Windows%20%7C%20macOS-lightgrey )
99
10- A lightweight, single-header, speed and safety focused INI file parsing library written in C with C++ compatibility. Designed for simplicity and portability, this parser provides a low-footprint solution to decode INI format .
10+ A lightweight, single-header INI file parsing library written in C, with C++ compatibility. Focused on speed and safety, it offers a low-footprint, portable solution for decoding INI files. The library provides two APIs to suit different use cases: fast random access and memory-efficient streaming .
1111
1212## Features
13-
13+ - ** Dual Parsing Modes**
14+ - ** Context API** : Builds searchable structure (O(1) lookups)
15+ - ** Streaming API** : Zero-allocation event-based parsing
16+ - ** Memory Safe** : Automatic cleanup with context API
17+ - ** Unicode Ready** : Full UTF-8 support
1418- ** Robust Parsing** : Handles sections, key-value pairs, comments, and empty lines
1519- ** Memory Safe** : Automatic cleanup of allocated resources
1620- ** Whitespace Handling** : Trims leading/trailing spaces in sections and values
1721- ** Thread Safe** : Context-based design enables multi-instance usage
1822- ** Cross-Platform** : C99/C++11 compatible with no external dependencies
19- - ** Configurable** : Adjustable line length via ` INI_MAX_LINE_LENGTH `
23+ - ** Configurable** : Adjust line length (` INI_MAX_LINE_LENGTH ` ) and case sensitivity
24+
25+ ## API Comparison
26+
27+ | Feature | Context API (` ini_initialize ` ) | Streaming API (` ini_parse_stream ` ) |
28+ | ------------------------| --------------------------------| ------------------------------------|
29+ | ** Memory Usage** | Builds full structure | Constant memory |
30+ | ** Lookup Speed** | O(1) after init | N/A (sequential) |
31+ | ** Best For** | Small files, random access | Large files (>1GB), embedded |
32+ | ** Error Handling** | Post-parse validation | Immediate feedback |
33+ | ** Thread Safety** | Per-context isolation | Handler must be reentrant |
34+ | ** Max File Size** | Limited by memory | Unlimited |
35+ | ** Needs init?** | Yes (` ini_initialize ` | No |
36+ | ** Needs cleanup?** | Yes (` ini_cleanup ` ) | No |
37+
38+ ** Why No Initialization/Cleanup Needed for Streaming:**
39+ - Processes lines directly from input buffer
40+ - Doesn't build any persistent data structures
41+ - All temporary buffers are stack-allocated
42+ - User handles state via ` userdata ` parameter
43+
44+ ** Memory Diagram:**
45+ ```
46+ Context API: Streaming API:
47+ +---------------+ +-----------------+
48+ | ini_context_t | | Input Buffer |
49+ | - sections | +-----------------+
50+ | - keyValues | | Line Buffer | (stack)
51+ +---------------+ +-----------------+
52+ | Allocations | | Userdata |
53+ +---------------+ +-----------------+
54+ | No persistent |
55+ | state |
56+ +-----------------+
57+ ```
58+
59+ ## Choosing an API
60+
61+ ** Use Context API When:**
62+ - You need random access to values
63+ - Working with small to medium configs
64+ - Frequent lookups needed after parsing
65+
66+ ** Use Streaming API When:**
67+ - Processing large files (>100MB)
68+ - Memory-constrained environments
69+ - Simple validation/transformation needed
70+ - Direct loading to application structures
71+
72+ ## Streaming Parsing API
73+
74+ ### Core Components
75+
76+ ``` c
77+ typedef enum {
78+ INI_EVENT_SECTION, // New section found
79+ INI_EVENT_KEY_VALUE, // Key-value pair parsed
80+ INI_EVENT_COMMENT, // Comment line detected
81+ INI_EVENT_ERROR // Parse error encountered
82+ } ini_eventtype_t ;
83+
84+ typedef bool (* ini_handler)(
85+ ini_eventtype_t type, // Event type
86+ const char* section, // Current section (if applicable)
87+ const char* key, // Key name (for key-value events)
88+ const char* value, // Value or comment content
89+ void* userdata // Custom user context
90+ );
91+ ```
92+
93+ ### Functions
94+
95+ #### ` bool ini_parse_stream(const char* content, size_t length, ini_handler handler, void* userdata) `
96+ Processes INI content line-by-line
97+ - ` content ` : Input string (not modified)
98+ - ` length ` : Input length in bytes
99+ - ` handler ` : Callback for parsed events
100+ - ` userdata ` : Custom context pointer
101+ - ** Returns** : ` false ` if handler aborted parsing
20102
21- ## Components
103+ ### Usage Example
104+
105+ ``` c
106+ typedef struct {
107+ int sections;
108+ int keys;
109+ } ParserStats;
110+
111+ bool stats_handler (ini_eventtype_t type,
112+ const char* section,
113+ const char* key,
114+ const char* value,
115+ void* userdata) {
116+ ParserStats* stats = (ParserStats* )userdata;
117+
118+ switch(type) {
119+ case INI_EVENT_SECTION:
120+ stats->sections++;
121+ break;
122+ case INI_EVENT_KEY_VALUE:
123+ stats->keys++;
124+ printf("[ %s] %s = %s\n", section, key, value);
125+ break;
126+ case INI_EVENT_ERROR:
127+ fprintf(stderr, "Error in: %s\n", value);
128+ return false; // Abort parsing
129+ }
130+ return true;
131+ }
132+
133+ void process_large_ini(const char* content, size_t length) {
134+ ParserStats stats = {0};
135+ ini_parse_stream(content, length, stats_handler, &stats);
136+ printf("Parsed %d sections with %d keys\n", stats.sections, stats.keys);
137+ }
138+ ```
139+
140+ ## Context API
22141
23142### Core Structures
24143- **`ini_context_t`**: Manages parser state and stored sections
@@ -74,9 +193,35 @@ Retrieves value for specified section/key
74193- `maxLen`: Maximum buffer size
75194- **Returns**: `true` if value found and copied
76195
77- ### Configuration Macros
196+ ## Usage Example
197+
198+ ```c
199+ #include "ini_parser.h"
200+ #include <stdio.h>
201+
202+ int main() {
203+ const char *config =
204+ "[network]\n"
205+ "host = 127.0.0.1\n"
206+ "port = 8080\n";
207+
208+ ini_context_t ctx = {0};
209+ if (ini_initialize(&ctx, config, strlen(config))) {
210+ char host[256], port[16];
211+ if (ini_getValue(&ctx, "network", "host", host, sizeof(host)) &&
212+ ini_getValue(&ctx, "network", "port", port, sizeof(port))) {
213+ printf("Connecting to %s:%s\n", host, port);
214+ }
215+ ini_cleanup(&ctx);
216+ }
217+ return 0;
218+ }
219+ ```
220+
221+ ## Configuration Macros
78222- ` INI_MAX_LINE_LENGTH ` : Maximum allowed line length (default: 256)
79223- ` INI_PARSER_IMPLEMENTATION ` : Define to enable implementation inclusion
224+ - ` INI_ENABLE_CASE_SENSITIVITY ` : Enables case sensitivity for sections, keys and values.
80225
81226## Error Handling
82227The parser provides implicit error checking through boolean return values. Common failure scenarios:
@@ -100,35 +245,20 @@ cmake --build .
100245ctest --output-on-failure
101246```
102247
103- ## Usage Example
248+ ## Performance Tips
104249
105- ``` c
106- #include " ini_parser.h"
107- #include < stdio.h>
250+ 1 . ** Prefer Streaming API** for files >100MB
251+ 2 . ** Reuse Contexts** when possible
252+ 3 . ** Set INI_MAX_LINE_LENGTH** to match your data
253+ 4 . ** Avoid Case Sensitivity** unless required (` INI_ENABLE_CASE_SENSITIVITY ` )
254+ 5 . ** Batch Initializations** for multiple small configs
108255
109- int main () {
110- const char *config =
111- "[network]\n"
112- "host = 127.0.0.1\n"
113- "port = 8080\n";
114-
115- ini_context_t ctx = {0};
116- if (ini_initialize(&ctx, config, strlen(config))) {
117- char host[256], port[16];
118- if (ini_getValue(&ctx, "network", "host", host, sizeof(host)) &&
119- ini_getValue (&ctx, "network", "port", port, sizeof(port))) {
120- printf("Connecting to %s:%s\n", host, port);
121- }
122- ini_cleanup(&ctx);
123- }
124- return 0;
125- }
126- ```
256+ ## Quality Assurance
127257
128- ## Performance
129- - ** O(1) Lookups ** : Pre-parsed structure enables fast access
130- - ** Low Memory ** : Compact representation with single allocation
131- - ** Efficient Parsing ** : Linear time complexity O(n)
258+ - ** Valgrind Clean ** : Zero memory leaks
259+ - ** 100% Line Coverage ** : Comprehensive test suite
260+ - ** Fuzz Tested ** : AFL-integrated validation
261+ - ** SAN Enabled ** : Address/UB sanitizer support
132262
133263## :snowman : Author
134264
0 commit comments