-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathc-ini.h
More file actions
151 lines (125 loc) · 5.13 KB
/
Copy pathc-ini.h
File metadata and controls
151 lines (125 loc) · 5.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#pragma once
/**
* Ini-File Handling
*
* XXX
*
* Possible extensions:
*
* * 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. Several of these are already implemented, but we should
* better document the details:
*
* * 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.
*
* * 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.
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <inttypes.h>
#include <stdlib.h>
#include <sys/types.h>
typedef struct CIniDomain CIniDomain;
typedef struct CIniEntry CIniEntry;
typedef struct CIniGroup CIniGroup;
typedef struct CIniReader CIniReader;
enum {
C_INI_MODE_EXTENDED_WHITESPACE = (1 << 0),
C_INI_MODE_KEEP_DUPLICATE_GROUPS = (1 << 1),
C_INI_MODE_MERGE_GROUPS = (1 << 2),
C_INI_MODE_KEEP_DUPLICATE_ENTRIES = (1 << 3),
C_INI_MODE_OVERRIDE_ENTRIES = (1 << 4),
};
/* 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_get_null_group(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(CIniReader **readerp);
CIniReader *c_ini_reader_free(CIniReader *reader);
void c_ini_reader_set_mode(CIniReader *reader, unsigned int mode);
unsigned int c_ini_reader_get_mode(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);
/* 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