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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
/******************************************************************************/
/*                               libRustConfig                                */
/*                   rust wrapper around libconfig library                    */
/*                  https://github.com/hyperrealm/libconfig                   */
/*                                                                            */
/* Copyright (c) 2020                                       Ivan Semenkov     */
/* https://github.com/isemenkov/librustconfig               ivan@semenkov.pro */
/*                                                          Ukraine           */
/******************************************************************************/
/*                                                                            */
/* Permission is hereby granted,  free of charge,  to any person obtaining a  */
/* copy of this software and associated documentation files (the "Software"), */
/* to deal in the Software without restriction, including without limitation  */
/* the rights to use, copy,  modify, merge, publish, distribute,  sublicense, */
/* and/or  sell copies  of the Software,  and to permit persons  to whom  the */
/* Software  is furnished to  do  so,  subject to  the following  conditions: */
/*                                                                            */
/* The above copyright notice and this permission notice shall be included in */
/* all copies or substantial portions of the Software.                        */
/*                                                                            */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
/* IMPLIED,  INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF  MERCHANTABILITY, */
/* FITNESS  FOR A PARTICULAR PURPOSE  AND NONINFRINGEMENT. IN  NO EVENT SHALL */
/* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
/* LIABILITY,  WHETHER IN AN ACTION  OF CONTRACT,  TORT OR OTHERWISE, ARISING */
/* FROM,  OUT OF  OR IN  CONNECTION WITH  THE SOFTWARE  OR THE  USE OR  OTHER */
/* DEALINGS IN THE SOFTWARE.                                                  */
/*                                                                            */
/******************************************************************************/

#![allow(non_camel_case_types)]

extern crate libc;

use libc::{c_schar, c_short, c_ushort, c_int, c_uint, c_longlong, c_double};
use libc::FILE;
use std::os::raw::c_void;

pub const CONFIG_TYPE_NONE : c_short                                    = 0;
pub const CONFIG_TYPE_GROUP : c_short                                   = 1;
pub const CONFIG_TYPE_INT : c_short                                     = 2;
pub const CONFIG_TYPE_INT64 : c_short                                   = 3;
pub const CONFIG_TYPE_FLOAT : c_short                                   = 4;
pub const CONFIG_TYPE_STRING : c_short                                  = 5;
pub const CONFIG_TYPE_BOOL : c_short                                    = 6;
pub const CONFIG_TYPE_ARRAY : c_short                                   = 7;
pub const CONFIG_TYPE_LIST : c_short                                    = 8;

pub const CONFIG_FORMAT_DEFAULT : c_int                                 = 1;
pub const CONFIG_FORMAT_HEX : c_int                                     = 2;

pub const CONFIG_OPTION_AUTOCONVERT : c_int                             = 0x01;
pub const CONFIG_OPTION_SEMICOLON_SEPARATORS : c_int                    = 0x02;
pub const CONFIG_OPTION_COLON_ASSIGNMENT_FOR_GROUPS : c_int             = 0x04;
pub const CONFIG_OPTION_COLON_ASSIGNMENT_FOR_NON_GROUPS : c_int         = 0x08;
pub const CONFIG_OPTION_OPEN_BRACE_ON_SEPARATE_LINE : c_int             = 0x10;

pub const CONFIG_TRUE : c_int                                           = 1;
pub const CONFIG_FALSE : c_int                                          = 0;

#[repr(C)]
#[derive(Copy, Clone)]
pub enum config_error_t {
    CONFIG_ERR_NONE                                                     = 0,
    CONFIG_ERR_FILE_IO                                                  = 1,
    CONFIG_ERR_PARSE                                                    = 2,
}

#[repr(C)]
#[derive(Copy, Clone)]
pub union config_value_t {
    pub ival : c_int,
    pub llval : c_longlong,
    pub fval : c_double,
    pub sval : *mut c_schar,
    pub list : *mut config_list_t,
}

#[repr(C)]
#[derive(Copy, Clone)]
pub struct config_setting_t {
    pub name : *mut c_schar,
    pub setting_type : c_short,
    pub format : c_short,
    pub value : config_value_t,
    pub parent : *mut config_setting_t,
    pub config : *mut config_t,
    pub hook : *mut c_void,
    pub line : c_uint,
    pub file : *const c_schar,
}

#[repr(C)]
pub struct config_list_t {
    pub length : c_uint,
    pub elements : *mut *mut config_setting_t,
}

#[repr(C)]
pub struct config_t {
    pub root : *mut config_setting_t,
    pub destructor : Option<extern "C" fn(*mut c_void) -> ()>,
    pub tab_width : c_ushort,
    pub default_format : c_short,
    pub include_dir : *const c_schar,
    pub error_text : *const c_schar,
    pub error_file : *const c_schar,
    pub error_line : c_int,
    pub error_type : config_error_t,
    pub filenames : *mut *mut c_schar,
    pub num_filenames : c_uint,
}

pub type destructor_callback = extern "C" fn(ptr : *mut c_void) -> ();

#[link(name = "config")]
extern "C" {
    pub fn config_read (config : *mut config_t, stream : *mut FILE) -> c_int;
    pub fn config_write (config : *const config_t, stream : *mut FILE);

    pub fn config_set_options (config : *mut config_t, options : c_int);
    pub fn config_get_options (config : *const config_t) -> c_int;

    pub fn config_set_auto_convert (config : *mut config_t, flag : c_int);
    pub fn config_get_auto_convert (config : *const config_t) -> c_int;

    pub fn config_read_string (config : *mut config_t, str : *const c_schar)
        -> c_int;

    pub fn config_read_file (config : *mut config_t, filename : *const c_schar)
        -> c_int;
    pub fn config_write_file (config : *mut config_t, filename : *const c_schar)
        -> c_int;

    pub fn config_set_destructor (config : *mut config_t, destructor :
        destructor_callback);
    pub fn config_set_include_dir (config : *mut config_t, include_dir :
        *const c_schar);

    pub fn config_init (config : *mut config_t);
    pub fn config_destroy (config : *mut config_t);

    pub fn config_setting_get_int (setting : *const config_setting_t) -> c_int;
    pub fn config_setting_get_int64 (setting : *const config_setting_t)
        -> c_longlong;
    pub fn config_setting_get_float (setting : *const config_setting_t)
        -> c_double;
    pub fn config_setting_get_bool (setting : *const config_setting_t)
        -> c_int;
    pub fn config_setting_get_string (setting : *const config_setting_t)
        -> *const c_schar;

    pub fn config_setting_lookup_int (setting : *const config_setting_t,
        name : *const c_schar, value : *mut c_int) -> c_int;
    pub fn config_setting_lookup_int64 (setting : *const config_setting_t,
        name : *const c_schar, value : *mut c_longlong) -> c_int;
    pub fn config_setting_lookup_float (setting : *const config_setting_t,
        name : *const c_schar, value : *mut c_double) -> c_int;
    pub fn config_setting_lookup_bool (setting : *const config_setting_t,
        name : *const c_schar, value : *mut c_int) -> c_int;
    pub fn config_setting_lookup_string (setting : *const config_setting_t,
        name : *const c_schar, value : *const *mut c_schar) -> c_int;

    pub fn config_setting_set_int (setting : *mut config_setting_t, value :
        c_int) -> c_int;
    pub fn config_setting_set_int64 (setting : *mut config_setting_t, value :
        c_longlong) -> c_int;
    pub fn config_setting_set_float (setting : *mut config_setting_t, value :
        c_double) -> c_int;
    pub fn config_setting_set_bool (setting : *mut config_setting_t, value :
        c_int) -> c_int;
    pub fn config_setting_set_string (setting : *mut config_setting_t, value :
        *const c_schar) -> c_int;

    pub fn config_setting_set_format (setting : *mut config_setting_t, format :
        c_short) -> c_int;
    pub fn config_setting_get_format (setting : *const config_setting_t)
        -> c_short;

    pub fn config_setting_get_int_elem (setting : *const config_setting_t, idx :
        c_int) -> c_int;
    pub fn config_setting_get_int64_elem (setting : *const config_setting_t,
        idx : c_int) -> c_longlong;
    pub fn config_setting_get_float_elem (setting : *const config_setting_t,
        idx : c_int) -> c_double;
    pub fn config_setting_get_bool_elem (setting : *const config_setting_t,
        idx : c_int) -> c_int;
    pub fn config_setting_get_string_elem (setting : *const config_setting_t,
        idx : c_int) -> *const c_schar;

    pub fn config_setting_set_int_elem (setting : *mut config_setting_t, idx :
        c_int, value : c_int) -> *mut config_setting_t;
    pub fn config_setting_set_int64_elem (setting : *mut config_setting_t, idx :
        c_int, value : c_longlong) -> *mut config_setting_t;
    pub fn config_setting_set_float_elem (setting : *mut config_setting_t, idx :
        c_int, value : c_double) -> *mut config_setting_t;
    pub fn config_setting_set_bool_elem (setting : *mut config_setting_t, idx :
        c_int, value : c_int) -> *mut config_setting_t;
    pub fn config_setting_set_string_elem (setting : *mut config_setting_t,
        idx : c_int, value : *const c_schar) -> *mut config_setting_t;

    pub fn config_setting_index (setting : *const config_setting_t) -> c_int;

    pub fn config_setting_length (setting : *const config_setting_t) -> c_int;
    pub fn config_setting_get_elem (setting : *const config_setting_t, idx :
        c_uint) -> *mut config_setting_t;

    pub fn config_setting_get_member (setting : *const config_setting_t, name :
        *const c_schar) -> *mut config_setting_t;

    pub fn config_setting_add (parent : *mut config_setting_t, name :
        *const c_schar, value_type : c_int) -> *mut config_setting_t;
    pub fn config_setting_remove (parent : *mut config_setting_t, name :
        *const c_schar) -> c_int;
    pub fn config_setting_remove_elem (parent : *mut config_setting_t, idx :
        c_uint) -> c_int;
    pub fn config_setting_set_hook (setting : *mut config_setting_t, hook :
        *mut c_void);

    pub fn config_lookup (config : *const config_t, path : *const c_schar)
        -> *mut config_setting_t;
    pub fn config_setting_lookup (setting : *mut config_setting_t, path :
        *const c_schar) -> *mut config_setting_t;

    pub fn config_lookup_int (config : *const config_t, path : *const c_schar,
        value : *mut c_int) -> c_int;
    pub fn config_lookup_int64 (config : *const config_t, path : *const c_schar,
        value : *mut c_longlong) -> c_int;
    pub fn config_lookup_float (config : *const config_t, path : *const c_schar,
        value : *mut c_double) -> c_int;
    pub fn config_lookup_bool (config : *const config_t, path : *const c_schar,
        value : *mut c_int) -> c_int;
    pub fn config_lookup_string (config : *const config_t, path :
        *const c_schar, value : *const *mut c_schar) -> c_int;
}

pub fn config_get_include_dir (config : *const config_t) -> *const c_schar {
    unsafe { (*config).include_dir }
}

pub fn config_setting_type (setting : *const config_setting_t) -> c_int {
    unsafe { (*setting).setting_type as c_int }
}

pub fn config_setting_is_group (setting : *const config_setting_t) -> c_int {
    match unsafe { (*setting).setting_type } {
        CONFIG_TYPE_GROUP => { CONFIG_TRUE },
        _ => { CONFIG_FALSE }
    }
}

pub fn config_setting_is_array (setting : *const config_setting_t) -> c_int {
    match unsafe { (*setting).setting_type } {
        CONFIG_TYPE_ARRAY => { CONFIG_TRUE },
        _ => { CONFIG_FALSE }
    }
}

pub fn config_setting_is_list (setting : *const config_setting_t) -> c_int {
    match unsafe { (*setting).setting_type } {
        CONFIG_TYPE_LIST => { CONFIG_TRUE },
        _ => { CONFIG_FALSE }
    }
}

pub fn config_setting_is_aggregate (setting : *const config_setting_t) 
    -> c_int {
    match unsafe { (*setting).setting_type } {
        CONFIG_TYPE_GROUP |
        CONFIG_TYPE_LIST |
        CONFIG_TYPE_ARRAY => { CONFIG_TRUE },
        _ => { CONFIG_FALSE }
    }
}

pub fn config_setting_is_number (setting : *const config_setting_t) -> c_int {
    match unsafe { (*setting).setting_type } {
        CONFIG_TYPE_INT |
        CONFIG_TYPE_INT64 |
        CONFIG_TYPE_FLOAT => { CONFIG_TRUE },
        _ => { CONFIG_FALSE }
    }
}

pub fn config_setting_is_scalar (setting : *const config_setting_t) -> c_int {
    match unsafe { (*setting).setting_type } {
        CONFIG_TYPE_BOOL |
        CONFIG_TYPE_STRING |
        CONFIG_TYPE_INT |
        CONFIG_TYPE_INT64 |
        CONFIG_TYPE_FLOAT => { CONFIG_TRUE },
        _ => { CONFIG_FALSE }
    }
}

pub fn config_setting_name (setting : *const config_setting_t) 
    -> *const c_schar {
    unsafe { (*setting).name }
}

pub fn config_setting_parent (setting : *const config_setting_t)
    -> *mut config_setting_t {
    unsafe { (*setting).parent }
}

pub fn config_setting_is_root (setting : *const config_setting_t) -> c_int {
    if unsafe { (*setting).parent.is_null() } {
        CONFIG_TRUE
    } else {
        CONFIG_FALSE
    }
}

pub fn config_root_setting (config : *const config_t) -> *mut config_setting_t {
    unsafe { (*config).root }
}

pub fn config_set_default_format (config : *mut config_t, value : c_short) {
    unsafe { (*config).default_format = value };
}

pub fn config_get_default_format (config : *const config_t) -> c_short {
    unsafe { (*config).default_format }
}

pub fn config_set_tab_width (config : *mut config_t, value : c_ushort) {
    unsafe { (*config).tab_width = value & 0x0F };
}

pub fn config_get_tab_width (config : *const config_t) -> c_ushort {
    unsafe { (*config).tab_width }
}

pub fn config_setting_source_line (config : *const config_setting_t) -> c_uint {
    unsafe { (*config).line }
}

pub fn config_setting_source_file (config : *const config_setting_t) 
    -> *const c_schar {
    unsafe { (*config).file }
}

pub fn config_error_text (config : *const config_t) -> *const c_schar {
    unsafe { (*config).error_text }
}

pub fn config_error_file (config : *const config_t) -> *const c_schar {
    unsafe { (*config).error_file }
}

pub fn config_error_line (config : *const config_t) -> c_int {
    unsafe { (*config).error_line }
}

pub fn config_error_type (config : *const config_t) -> config_error_t {
    unsafe { (*config).error_type }
}