Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,19 @@ jobs:
if [ -f $DMF_DIR/test_dmini.dmd ]; then
cp $DMF_DIR/test_dmini.dmd release_package/
fi

# Copy documentation and license

# Copy .dmr resource files
cp dmini.dmr release_package/
cp test_dmini.dmr release_package/

# Copy header files
mkdir -p release_package/include
cp include/dmini.h release_package/include/
cp $BUILD_DIR/dmini_defs.h release_package/include/

# Copy documentation
mkdir -p release_package/docs
cp -r docs/* release_package/docs/
cp README.md release_package/
cp LICENSE release_package/

Expand Down
30 changes: 30 additions & 0 deletions dmini.dmr
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# DMOD Resource File for dmini
# This file specifies where resources should be installed

# === Core Module ===
# Main module file - always installed
dmf=./dmini.dmf => ${DMOD_DMF_DIR}/${module}.dmf

# Compressed module
dmfc=./dmini.dmfc => ${DMOD_DMF_DIR}/${module}.dmfc

# Dependencies file (if exists)
dmd=./dmini.dmd => ${destination}/${module}.dmd

# Version information
version=./dmini_version.txt => ${destination}/${module}_version.txt

# === Documentation ===
# Module documentation in markdown format for dmf-man tool
docs=./docs => ${destination}/${module}/docs

# README file
readme=./README.md => ${destination}/${module}/README.md

# === Header Files ===
# Include directory with all headers (dmini.h and dmini_defs.h)
inc=./include => ${destination}/${module}/include

# === License ===
# License file
license=./LICENSE => ${destination}/${module}/LICENSE
200 changes: 200 additions & 0 deletions docs/dmini.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
# DMINI(3)

## NAME

dmini - DMOD INI File Parser Module

## SYNOPSIS

```c
#include "dmini.h"

dmini_context_t dmini_create(void);
void dmini_destroy(dmini_context_t ctx);

int dmini_parse_string(dmini_context_t ctx, const char* data);
int dmini_parse_file(dmini_context_t ctx, const char* filename);

int dmini_generate_string(dmini_context_t ctx, char* buffer, size_t buffer_size);
int dmini_generate_file(dmini_context_t ctx, const char* filename);

const char* dmini_get_string(dmini_context_t ctx, const char* section,
const char* key, const char* default_value);
int dmini_get_int(dmini_context_t ctx, const char* section,
const char* key, int default_value);

int dmini_set_string(dmini_context_t ctx, const char* section,
const char* key, const char* value);
int dmini_set_int(dmini_context_t ctx, const char* section,
const char* key, int value);

int dmini_has_section(dmini_context_t ctx, const char* section);
int dmini_has_key(dmini_context_t ctx, const char* section, const char* key);

int dmini_remove_section(dmini_context_t ctx, const char* section);
int dmini_remove_key(dmini_context_t ctx, const char* section, const char* key);
```

## DESCRIPTION

The **dmini** module provides a lightweight INI file parser and generator
optimized for embedded systems. It uses only DMOD SAL (System Abstraction
Layer) functions and implements memory-efficient line-by-line file I/O
operations.

### INI File Format

INI files consist of sections, key-value pairs, and comments:

* Sections are defined by `[section_name]`
* Key-value pairs are defined by `key=value`
* Comments start with `;` or `#`
* Whitespace is automatically trimmed from keys and values
* Keys without section headers belong to the global section

### Context Management

**dmini_create()** creates a new INI context for storing sections and
key-value pairs. Returns a context pointer or NULL on error.

**dmini_destroy()** frees all memory associated with an INI context.

### Parsing

**dmini_parse_string()** parses an INI file from a null-terminated string.
Returns DMINI_OK on success or an error code on failure.

**dmini_parse_file()** parses an INI file from a file path using SAL file
functions. Uses line-by-line reading with 256-byte buffers. Returns DMINI_OK
on success or an error code on failure.

### Generation

**dmini_generate_string()** generates an INI file string from the context.
If buffer is NULL, returns the required buffer size. If buffer is not NULL,
fills it with the INI data. Returns required buffer size or a negative error
code.

**dmini_generate_file()** generates an INI file from the context and writes
it directly to a file using line-by-line writing. Returns DMINI_OK on success
or an error code on failure.

### Data Access

**dmini_get_string()** retrieves a string value for the given section and key.
Pass NULL for section to access the global section. Returns the value string
or default_value if not found.

**dmini_get_int()** retrieves an integer value for the given section and key.
Pass NULL for section to access the global section. Returns the integer value
or default_value if not found.

**dmini_set_string()** sets a string value for the given section and key.
Creates the section if it doesn't exist. Pass NULL for section to access the
global section. Returns DMINI_OK on success or an error code on failure.

**dmini_set_int()** sets an integer value for the given section and key.
Creates the section if it doesn't exist. Pass NULL for section to access the
global section. Returns DMINI_OK on success or an error code on failure.

### Queries

**dmini_has_section()** checks if a section exists in the context. Returns 1
if the section exists, 0 otherwise.

**dmini_has_key()** checks if a key exists in the specified section. Pass NULL
for section to check the global section. Returns 1 if the key exists, 0
otherwise.

### Removal

**dmini_remove_section()** removes an entire section and all its keys from the
context. Returns DMINI_OK on success or an error code on failure.

**dmini_remove_key()** removes a single key from the specified section. Pass
NULL for section to remove from the global section. Returns DMINI_OK on
success or an error code on failure.

## RETURN VALUES

Functions return the following error codes:

* **DMINI_OK** (0) - Success
* **DMINI_ERR_GENERAL** (-1) - General error
* **DMINI_ERR_MEMORY** (-2) - Memory allocation error
* **DMINI_ERR_INVALID** (-3) - Invalid parameter
* **DMINI_ERR_NOT_FOUND** (-4) - Section or key not found
* **DMINI_ERR_FILE** (-5) - File I/O error

## EXAMPLES

### Basic Usage

```c
#include "dmini.h"

// Create context
dmini_context_t ctx = dmini_create();

// Parse INI file
dmini_parse_file(ctx, "config.ini");

// Read values
const char* host = dmini_get_string(ctx, "database", "host", "localhost");
int port = dmini_get_int(ctx, "database", "port", 5432);

// Modify values
dmini_set_string(ctx, "cache", "enabled", "true");
dmini_set_int(ctx, "cache", "size", 1024);

// Generate to file
dmini_generate_file(ctx, "output.ini");

// Cleanup
dmini_destroy(ctx);
```

### Querying Buffer Size

```c
// Query required buffer size
int size = dmini_generate_string(ctx, NULL, 0);

// Allocate buffer
char* buffer = Dmod_Malloc(size);

// Generate INI to buffer
dmini_generate_string(ctx, buffer, size);

// Use buffer...

// Free buffer
Dmod_Free(buffer);
```

### Working with Global Section

```c
// Set global key (no section)
dmini_set_string(ctx, NULL, "global_key", "global_value");

// Get global key
const char* val = dmini_get_string(ctx, NULL, "global_key", "default");
```

## MEMORY FOOTPRINT

* **dmini library**: 536B RAM, 5KB ROM
* **Line buffer**: 256 bytes (temporary, not persistent)

## SEE ALSO

dmod(3), dmod_loader(1)

## AUTHOR

Patryk Kubiak

## LICENSE

MIT License - Copyright (c) 2025 Choco-Technologies
12 changes: 12 additions & 0 deletions test_dmini.dmr
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# DMOD Resource File for test_dmini
# This file specifies where resources should be installed

# === Core Module ===
# Main module file - always installed
dmf=./test_dmini.dmf => ${DMOD_DMF_DIR}/${module}.dmf

# Compressed module
dmfc=./test_dmini.dmfc => ${DMOD_DMF_DIR}/${module}.dmfc

# Version information
version=./test_dmini_version.txt => ${destination}/${module}_version.txt