Skip to content

Repository files navigation

SDL_ini

A lightweight, single-header C library for reading and writing INI configuration files with SDL3.

Features

  • Single-header: Drop SDL_ini.h into your project
  • Pure SDL3: Uses only SDL3 APIs (SDL_malloc, SDL_IOStream, SDL_asprintf, etc)
  • Typed Properties: String, Int, Float, Double, Boolean
  • Case-Insensitive: Section and key lookups can be any case
  • Comments: # and ; comments and blank lines are preserved
  • Quoted Values: Values can be wrapped in "double quotes" to preserve leading/trailing whitespace
  • Globals: A NULL section appears before the first [section]
  • Enumeration: Iterate through sections and keys with callbacks

Usage

In exactly one C source file, define the implementation before including the header:

#define SDL_INI_IMPLEMENTATION
#include "SDL_ini.h"

In all other files, include the header normally:

#include "SDL_ini.h"

Quick Example

#define SDL_INI_IMPLEMENTATION
#include "SDL_ini.h"

int main(int argc, char *argv[])
{
    SDL_Init(0);

    // Creating and Saving
    SDL_ini *ini = INI_Create();
    INI_SetString(ini,  NULL,    "title",        "My Game");
    INI_SetInt(ini,     "Video", "width",      1920);
    INI_SetInt(ini,     "Video", "height",     1080);
    INI_SetBoolean(ini, "Video", "fullscreen", true);
    INI_SetFloat(ini,   "Audio", "volume",     0.85f);
    INI_Save(ini, "settings.ini");
    INI_Destroy(ini);

    // Loading
    SDL_ini *cfg = INI_Load("settings.ini");
    int w = (int)INI_GetInt(cfg, "Video", "width", 1280);
    bool fs = INI_GetBoolean(cfg, "Video", "fullscreen", false);
    INI_Destroy(cfg);

    SDL_Quit();
    return 0;
}

Produces settings.ini:

app = My Game

[Video]
width = 1920
height = 1080
fullscreen = true

[Audio]
volume = 0.85

API Reference

// Version

int INI_GetVersion(void);

// Lifecycle

SDL_ini *INI_Create(void);
SDL_ini *INI_Load_IO(SDL_IOStream *src, bool closeio);
SDL_ini *INI_Load(const char *file);
SDL_ini *INI_LoadString(const char *text);
SDL_ini *INI_LoadMultiple(const char **files);
bool INI_Save_IO(SDL_ini *ini, SDL_IOStream *dst, bool closeio);
bool INI_Save(SDL_ini *ini, const char *file);
char *INI_SaveString(SDL_ini *ini);
void INI_Destroy(SDL_ini *ini);

// Get

const char *INI_GetString(const SDL_ini *ini, const char *section, const char *key, const char *default_value);
Sint64 INI_GetInt(const SDL_ini *ini, const char *section, const char *key, Sint64 default_value);
float INI_GetFloat(const SDL_ini *ini, const char *section, const char *key, float default_value);
double INI_GetDouble(const SDL_ini *ini, const char *section, const char *key, double default_value);
bool INI_GetBoolean(const SDL_ini *ini, const char *section, const char *key, bool default_value);

// Query

bool INI_HasSection(const SDL_ini *ini, const char *section);
bool INI_HasKey(const SDL_ini *ini, const char *section, const char *key);
bool INI_HasValue(const SDL_ini *ini, const char *section, const char *key);
bool INI_IsDirty(const SDL_ini *ini);
void INI_SetDirty(SDL_ini *ini, bool dirty);

// Set

bool INI_SetString(SDL_ini *ini, const char *section, const char *key, const char *value);
bool INI_SetInt(SDL_ini *ini, const char *section, const char *key, Sint64 value);
bool INI_SetFloat(SDL_ini *ini, const char *section, const char *key, float value);
bool INI_SetDouble(SDL_ini *ini, const char *section, const char *key, double value);
bool INI_SetBoolean(SDL_ini *ini, const char *section, const char *key, bool value);
bool INI_RemoveKey(SDL_ini *ini, const char *section, const char *key);
bool INI_RemoveSection(SDL_ini *ini, const char *section);

// Merge

bool INI_Merge(SDL_ini *dest, const SDL_ini *src);
bool INI_Merge_IO(SDL_ini *dest, SDL_IOStream *src, bool closeio);
bool INI_MergeFile(SDL_ini *dest, const char *file);

// Enumerate

typedef void (SDLCALL *INI_EnumerateSectionsCallback)(void *userdata, const SDL_ini *ini, const char *section);
typedef void (SDLCALL *INI_EnumerateKeysCallback)(void *userdata, const SDL_ini *ini, const char *section, const char *key, const char *value);
void INI_EnumerateSections(const SDL_ini *ini, INI_EnumerateSectionsCallback callback, void *userdata);
void INI_EnumerateKeys(const SDL_ini *ini, const char *section, INI_EnumerateKeysCallback callback, void *userdata);

// Index-based iteration

int INI_GetSectionCount(const SDL_ini *ini);
const char *INI_GetSection(const SDL_ini *ini, int index);
int INI_GetKeyCount(const SDL_ini *ini, const char *section);
const char *INI_GetKey(const SDL_ini *ini, const char *section, int index);
const char *INI_GetKeyValue(const SDL_ini *ini, const char *section, int index);

INI File Format

; Comments start with ; or #
# This is also a comment

; Keys before any [section] belong in the NULL section
app_name = My Application

[Display]
; Values can optionally be double-quoted
width = 1920
title = "  My Game  "

[Flags]
fullscreen = true
vsync = off
  • Sections are delimited by [name]
  • Keys are separated from values by =
  • Comments begin with ; or #
  • Quoted values — surrounding "double quotes" are stripped on load and added on save when the value contains leading/trailing whitespace or is empty
  • Lookups are case-insensitive for both section names and keys

Building

CMake

cmake -B build
cmake --build build
ctest --test-dir build

Manual

cc test/SDL_ini_test.c -o SDL_ini_test $(pkg-config --cflags --libs sdl3)
./SDL_ini_test

Documentation

doxygen .Doxyfile

Coding Standards

clang-format -i SDL_ini.h test/SDL_ini_test.c

License

zlib

About

Single-header INI file library for SDL3.

Topics

Resources

Stars

Watchers

Forks

Releases

Contributors

Languages