Skip to content

Instantly share code, notes, and snippets.

@dvdhrm
Created October 11, 2018 16:36
Show Gist options
  • Save dvdhrm/5dede9c9b5aa8196dcb9afd5a5621991 to your computer and use it in GitHub Desktop.
Save dvdhrm/5dede9c9b5aa8196dcb9afd5a5621991 to your computer and use it in GitHub Desktop.
API Proposal for c-ini
#pragma once
/**
* Ini-File Handling
*
* XXX
*
* Possible extensions:
*
* * For now the API does not include serializers / writers, but was written
* to allow for seamless addition of such calls. Ini-Files are
* human-readable files, and as such there rarely is the need to write them
* programmatically. If the need ever arises, we will have to extent the API
* to provide serializers and modifiers.
*
* * Several different INI formats exist. For now, we only support the
* desktop-entry-specification as released by XDG / freedesktop.org. Other
* formats should be straightforward to add.
*
* * The glib-keyfile implementation has a set of extensions over the XDG
* specification. We might consider implementing these.
*
* * Ignore a single trailing '\r'. This is ignored both as "\r\n" as well
* as at the end of the file in case there is no missing newline.
*
* * Whitespace are ignored at the beginning of all lines (including
* 'blank' lines and comments). Additionally, trailing a group SPACE and
* HORIZONTAL TAB are ignored (possibly a bug and meant to ignore all
* whitespace).
*
* Whitespace according to glib are independent of any locale, and they
* currently include:
*
* 0x09: HORIZONTAL TAB (\t)
* 0x0a: LINE FEED (\n)
* 0x0c: FORM FEED (\x0c)
* 0x0d: CARRIAGE RETURN (\r)
* 0x20: SPACE ( )
*
* * An 'Encoding=' key is interpreted in the first-group and first-group
* only. Anything but 'UTF-8' is rejected.
* There should be little reason to support this feature.
*
* * Identifiers are not restricted to ASCII. The restrictions are:
*
* * Group names must be non-empty, must not contain '[', ']', nor ASCII
* control characters. Invalid UTF-8 is accepted, though.
*
* * Keys must be non-empty, must not contain '[', ']', '=', nor spaces.
* Invalid UTF-8 is accepted, though.
* A key might have a trailing locale specifier enclosed in brackets,
* which must only contain alphanumeric codepoints, as well as '@',
* '.', '_', '-'.
*
* * The current parsers assume the data source is trusted. Meaning, while it
* does correctly verify validity of all content, it does not enforce limits
* on data lengths in any way. If the data source is not trusted, you would
* want to extend the parsers to refuse files with overlong entities, or
* overlong extents.
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <inttypes.h>
#include <stdlib.h>
typedef struct CIniDomain CIniDomain;
typedef struct CIniEntry CIniEntry;
typedef struct CIniGroup CIniGroup;
typedef struct CIniReader CIniReader;
enum {
_C_INI_E_SUCCESS,
C_INI_E_DUPLICATE,
_C_INI_E_N,
};
/* entries */
CIniEntry *c_ini_entry_ref(CIniEntry *entry);
CIniEntry *c_ini_entry_unref(CIniEntry *entry);
CIniEntry *c_ini_entry_next(CIniEntry *entry);
CIniEntry *c_ini_entry_previous(CIniEntry *entry);
const char *c_ini_entry_get_key(CIniEntry *entry, size_t *n_keyp);
const char *c_ini_entry_get_value(CIniEntry *entry, size_t *n_valuep);
/* groups */
CIniGroup *c_ini_group_ref(CIniGroup *group);
CIniGroup *c_ini_group_unref(CIniGroup *group);
CIniGroup *c_ini_group_next(CIniGroup *group);
CIniGroup *c_ini_group_previous(CIniGroup *group);
const char *c_ini_group_get_label(CIniGroup *group, size_t *n_groupp);
CIniEntry *c_ini_group_iterate(CIniGroup *group);
CIniEntry *c_ini_group_find(CIniGroup *group, const char *label, ssize_t n_label);
/* domains */
CIniDomain *c_ini_domain_ref(CIniDomain *domain);
CIniDomain *c_ini_domain_unref(CIniDomain *domain);
CIniGroup *c_ini_domain_iterate(CIniDomain *domain);
CIniGroup *c_ini_domain_find(CIniDomain *domain, const char *label, ssize_t n_label);
/* readers */
int c_ini_reader_new_xdg(CIniReader **readerp);
CIniReader *c_ini_reader_free(CIniReader *reader);
int c_ini_reader_feed(CIniReader *reader, const uint8_t *data, size_t n_data);
int c_ini_reader_seal(CIniReader *reader, CIniDomain **domainp);
int c_ini_reader_parse_xdg(CIniDomain **domainp, const uint8_t *data, size_t n_data);
/* inline helpers */
static inline void c_ini_entry_unrefp(CIniEntry **entry) {
if (*entry)
c_ini_entry_unref(*entry);
}
static inline void c_ini_group_unrefp(CIniGroup **group) {
if (*group)
c_ini_group_unref(*group);
}
static inline void c_ini_domain_unrefp(CIniDomain **domain) {
if (*domain)
c_ini_domain_unref(*domain);
}
static inline void c_ini_reader_freep(CIniReader **reader) {
if (*reader)
c_ini_reader_free(*reader);
}
#ifdef __cplusplus
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment