rlibconfig 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ext/extconf.rb +11 -0
- data/ext/rlibconfig.c +700 -0
- metadata +45 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b45b2d7f4a2ef35bb0f1cb31bc9fa84cd1b2c969
|
4
|
+
data.tar.gz: f3e1575539ec2304d3c2291a813abe0e51765705
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fc82f67bb88c0712e5b6cced377c9ac27fdf459df9e7a3ced0592fc77afb23cc90212cf13df7241ea092262f6f95bd2bd83113c92efb46f7e3150f01eb90f4fc
|
7
|
+
data.tar.gz: d8d895a9fa0590b06c0223efef75fc732c6a7ddae0c6c47323b39bceb257423ef319a8acfa1d22986ddfbd67e7a1ae03f6269156f84f408a527b9e3e9dad3ede
|
data/ext/extconf.rb
ADDED
data/ext/rlibconfig.c
ADDED
@@ -0,0 +1,700 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <libconfig.h>
|
3
|
+
|
4
|
+
static VALUE cConfig, cConfigBaseSetting, cConfigSetting, cConfigAggregate;
|
5
|
+
static VALUE cConfigFormatDefault, cConfigFormatHex;
|
6
|
+
static VALUE cConfigFixnum, cConfigBignum, cConfigFloat, cConfigBoolean, cConfigString;
|
7
|
+
static VALUE cConfigGroup, cConfigList, cConfigArray;
|
8
|
+
|
9
|
+
static VALUE rSettingNameRegexp;
|
10
|
+
static VALUE aConfigSettings, aConfigScalars, aConfigAggregates;
|
11
|
+
static VALUE eConfigParseError, eSettingNotFoundError, eSettingFormatError, eSettingNameError;
|
12
|
+
|
13
|
+
static VALUE rconfig_wrap_value(config_setting_t* setting)
|
14
|
+
{
|
15
|
+
switch(config_setting_type(setting)) {
|
16
|
+
case CONFIG_TYPE_INT:
|
17
|
+
return LONG2FIX(config_setting_get_int(setting));
|
18
|
+
|
19
|
+
case CONFIG_TYPE_INT64:
|
20
|
+
return rb_ll2inum(config_setting_get_int64(setting));
|
21
|
+
|
22
|
+
case CONFIG_TYPE_FLOAT:
|
23
|
+
return rb_float_new(config_setting_get_float(setting));
|
24
|
+
|
25
|
+
case CONFIG_TYPE_STRING:
|
26
|
+
return rb_str_new2(config_setting_get_string(setting));
|
27
|
+
|
28
|
+
case CONFIG_TYPE_BOOL:
|
29
|
+
return config_setting_get_bool(setting) ? Qtrue : Qfalse;
|
30
|
+
|
31
|
+
default:
|
32
|
+
rb_bug("unknown value type %d", config_setting_type(setting));
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
static void rconfig_free_setting(config_setting_t* setting)
|
37
|
+
{
|
38
|
+
// dummy
|
39
|
+
}
|
40
|
+
|
41
|
+
static VALUE rconfig_prepare_setting(config_setting_t* setting)
|
42
|
+
{
|
43
|
+
VALUE wrapper = Data_Wrap_Struct(rb_cObject, 0, rconfig_free_setting, setting);
|
44
|
+
config_setting_set_hook(setting, (void*) wrapper);
|
45
|
+
return wrapper;
|
46
|
+
}
|
47
|
+
|
48
|
+
static void rconfig_destroy_setting(void* hook)
|
49
|
+
{
|
50
|
+
if(hook != NULL) {
|
51
|
+
VALUE wrapper = (VALUE) hook;
|
52
|
+
rb_iv_set(wrapper, "@setting", Qnil);
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
static VALUE rconfig_wrap_setting(config_setting_t* setting)
|
57
|
+
{
|
58
|
+
VALUE rbSetting = rconfig_prepare_setting(setting);
|
59
|
+
|
60
|
+
switch(config_setting_type(setting)) {
|
61
|
+
case CONFIG_TYPE_INT:
|
62
|
+
return rb_funcall(cConfigFixnum, rb_intern("new"), 2, LONG2FIX(config_setting_get_int(setting)), rbSetting);
|
63
|
+
|
64
|
+
case CONFIG_TYPE_INT64:
|
65
|
+
return rb_funcall(cConfigBignum, rb_intern("new"), 2, rb_ll2inum(config_setting_get_int64(setting)), rbSetting);
|
66
|
+
|
67
|
+
case CONFIG_TYPE_FLOAT:
|
68
|
+
return rb_funcall(cConfigFloat, rb_intern("new"), 2, rb_float_new(config_setting_get_float(setting)), rbSetting);
|
69
|
+
|
70
|
+
case CONFIG_TYPE_STRING:
|
71
|
+
return rb_funcall(cConfigString, rb_intern("new"), 2, rb_str_new2(config_setting_get_string(setting)), rbSetting);
|
72
|
+
|
73
|
+
case CONFIG_TYPE_BOOL:
|
74
|
+
return rb_funcall(cConfigBoolean, rb_intern("new"), 2, config_setting_get_bool(setting) ? Qtrue : Qfalse, rbSetting);
|
75
|
+
|
76
|
+
case CONFIG_TYPE_ARRAY:
|
77
|
+
return rb_funcall(cConfigArray, rb_intern("new"), 2, Qnil, rbSetting);
|
78
|
+
|
79
|
+
case CONFIG_TYPE_LIST:
|
80
|
+
return rb_funcall(cConfigList, rb_intern("new"), 1, rbSetting);
|
81
|
+
|
82
|
+
case CONFIG_TYPE_GROUP:
|
83
|
+
return rb_funcall(cConfigGroup, rb_intern("new"), 1, rbSetting);
|
84
|
+
|
85
|
+
default:
|
86
|
+
rb_bug("[r] unknown setting type %d", config_setting_type(setting));
|
87
|
+
}
|
88
|
+
}
|
89
|
+
|
90
|
+
static void rconfig_update_setting(config_setting_t* setting, VALUE value)
|
91
|
+
{
|
92
|
+
switch(config_setting_type(setting)) {
|
93
|
+
case CONFIG_TYPE_INT:
|
94
|
+
config_setting_set_int(setting, FIX2LONG(value));
|
95
|
+
break;
|
96
|
+
|
97
|
+
case CONFIG_TYPE_INT64:
|
98
|
+
if(TYPE(value) == T_BIGNUM)
|
99
|
+
config_setting_set_int64(setting, rb_big2ll(value));
|
100
|
+
else // T_FIXNUM
|
101
|
+
config_setting_set_int64(setting, FIX2INT(value));
|
102
|
+
break;
|
103
|
+
|
104
|
+
case CONFIG_TYPE_FLOAT:
|
105
|
+
// ruby1.9 check
|
106
|
+
#if HAVE_RB_BLOCK_CALL
|
107
|
+
config_setting_set_float(setting, RFLOAT(value)->float_value);
|
108
|
+
#else
|
109
|
+
config_setting_set_float(setting, RFLOAT(value)->value);
|
110
|
+
#endif
|
111
|
+
break;
|
112
|
+
|
113
|
+
case CONFIG_TYPE_STRING:
|
114
|
+
config_setting_set_string(setting, RSTRING_PTR(value));
|
115
|
+
break;
|
116
|
+
|
117
|
+
case CONFIG_TYPE_BOOL:
|
118
|
+
config_setting_set_bool(setting, value == Qtrue);
|
119
|
+
break;
|
120
|
+
|
121
|
+
default:
|
122
|
+
rb_bug("[w] unknown setting type %d", config_setting_type(setting));
|
123
|
+
}
|
124
|
+
}
|
125
|
+
|
126
|
+
static void rconfig_check_setting_type(VALUE object, VALUE value)
|
127
|
+
{
|
128
|
+
if(rb_obj_class(object) == cConfigFixnum) {
|
129
|
+
Check_Type(value, T_FIXNUM);
|
130
|
+
} else if(rb_obj_class(object) == cConfigBignum) {
|
131
|
+
if(TYPE(value) != T_BIGNUM && TYPE(value) != T_FIXNUM)
|
132
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected Fixnum or Bignum)", rb_obj_classname(value));
|
133
|
+
} else if(rb_obj_class(object) == cConfigFloat) {
|
134
|
+
Check_Type(value, T_FLOAT);
|
135
|
+
} else if(rb_obj_class(object) == cConfigString) {
|
136
|
+
Check_Type(value, T_STRING);
|
137
|
+
} else if(rb_obj_class(object) == cConfigBoolean) {
|
138
|
+
if(value != Qtrue && value != Qfalse)
|
139
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected boolean)", rb_obj_classname(value));
|
140
|
+
} else {
|
141
|
+
rb_raise(rb_eException, "never use Config::Setting itself");
|
142
|
+
}
|
143
|
+
}
|
144
|
+
|
145
|
+
static int rconfig_do_append(config_setting_t* setting, VALUE target, VALUE name)
|
146
|
+
{
|
147
|
+
int type;
|
148
|
+
if(rb_obj_class(target) == cConfigFixnum)
|
149
|
+
type = CONFIG_TYPE_INT;
|
150
|
+
else if(rb_obj_class(target) == cConfigBignum)
|
151
|
+
type = CONFIG_TYPE_INT64;
|
152
|
+
else if(rb_obj_class(target) == cConfigFloat)
|
153
|
+
type = CONFIG_TYPE_FLOAT;
|
154
|
+
else if(rb_obj_class(target) == cConfigString)
|
155
|
+
type = CONFIG_TYPE_STRING;
|
156
|
+
else if(rb_obj_class(target) == cConfigBoolean)
|
157
|
+
type = CONFIG_TYPE_BOOL;
|
158
|
+
else if(rb_obj_class(target) == cConfigGroup)
|
159
|
+
type = CONFIG_TYPE_GROUP;
|
160
|
+
else if(rb_obj_class(target) == cConfigList)
|
161
|
+
type = CONFIG_TYPE_LIST;
|
162
|
+
else if(rb_obj_class(target) == cConfigArray)
|
163
|
+
type = CONFIG_TYPE_ARRAY;
|
164
|
+
else
|
165
|
+
rb_bug("unknown setting class %s", rb_obj_classname(target));
|
166
|
+
|
167
|
+
config_setting_t* new_setting;
|
168
|
+
if(name == Qnil) {
|
169
|
+
new_setting = config_setting_add(setting, NULL, type);
|
170
|
+
} else {
|
171
|
+
Check_Type(name, T_STRING);
|
172
|
+
new_setting = config_setting_add(setting, RSTRING_PTR(name), type);
|
173
|
+
}
|
174
|
+
|
175
|
+
if(new_setting == NULL)
|
176
|
+
return 0;
|
177
|
+
|
178
|
+
VALUE rbNewSetting = rconfig_prepare_setting(new_setting);
|
179
|
+
rb_iv_set(target, "@setting", rbNewSetting);
|
180
|
+
|
181
|
+
if(rb_ary_includes(aConfigScalars, rb_obj_class(target)) == Qtrue)
|
182
|
+
rconfig_update_setting(new_setting, rb_iv_get(target, "@value"));
|
183
|
+
|
184
|
+
if(rb_ary_includes(aConfigAggregates, rb_obj_class(target)) == Qtrue) {
|
185
|
+
if(rb_obj_class(target) == cConfigGroup) {
|
186
|
+
VALUE hash = rb_iv_get(target, "@hash");
|
187
|
+
VALUE children = rb_funcall(hash, rb_intern("keys"), 0);
|
188
|
+
int i;
|
189
|
+
for(i = 0; i < RARRAY_LEN(children); i++) {
|
190
|
+
VALUE key = RARRAY_PTR(children)[i];
|
191
|
+
rconfig_do_append(new_setting, rb_hash_aref(hash, key), key);
|
192
|
+
}
|
193
|
+
} else {
|
194
|
+
VALUE children = rb_iv_get(target, "@list");
|
195
|
+
int i;
|
196
|
+
for(i = 0; i < RARRAY_LEN(children); i++) {
|
197
|
+
rconfig_do_append(new_setting, RARRAY_PTR(children)[i], Qnil);
|
198
|
+
}
|
199
|
+
}
|
200
|
+
}
|
201
|
+
|
202
|
+
return 1;
|
203
|
+
}
|
204
|
+
|
205
|
+
static VALUE rbConfigBaseSetting_initialize(VALUE self, VALUE setting)
|
206
|
+
{
|
207
|
+
if(setting != Qnil)
|
208
|
+
Check_Type(setting, T_DATA);
|
209
|
+
rb_iv_set(self, "@setting", setting);
|
210
|
+
|
211
|
+
return self;
|
212
|
+
}
|
213
|
+
|
214
|
+
static VALUE rbConfigBaseSetting_name(VALUE self)
|
215
|
+
{
|
216
|
+
if(rb_iv_get(self, "@setting") != Qnil) {
|
217
|
+
config_setting_t* setting = NULL;
|
218
|
+
Data_Get_Struct(rb_iv_get(self, "@setting"), config_setting_t, setting);
|
219
|
+
return rb_str_new2(config_setting_name(setting));
|
220
|
+
} else {
|
221
|
+
return Qnil;
|
222
|
+
}
|
223
|
+
}
|
224
|
+
|
225
|
+
static VALUE rbConfigBaseSetting_parent(VALUE self)
|
226
|
+
{
|
227
|
+
if(rb_iv_get(self, "@setting") != Qnil) {
|
228
|
+
config_setting_t* setting = NULL;
|
229
|
+
Data_Get_Struct(rb_iv_get(self, "@setting"), config_setting_t, setting);
|
230
|
+
return rconfig_wrap_setting(config_setting_parent(setting));
|
231
|
+
} else {
|
232
|
+
return Qnil;
|
233
|
+
}
|
234
|
+
}
|
235
|
+
|
236
|
+
static VALUE rbConfigBaseSetting_is_root(VALUE self)
|
237
|
+
{
|
238
|
+
if(rb_iv_get(self, "@setting") != Qnil) {
|
239
|
+
config_setting_t* setting = NULL;
|
240
|
+
Data_Get_Struct(rb_iv_get(self, "@setting"), config_setting_t, setting);
|
241
|
+
return config_setting_is_root(setting) ? Qtrue : Qfalse;
|
242
|
+
} else {
|
243
|
+
return Qnil;
|
244
|
+
}
|
245
|
+
}
|
246
|
+
|
247
|
+
static VALUE rbConfigBaseSetting_index(VALUE self)
|
248
|
+
{
|
249
|
+
if(rb_iv_get(self, "@setting") != Qnil) {
|
250
|
+
config_setting_t* setting = NULL;
|
251
|
+
Data_Get_Struct(rb_iv_get(self, "@setting"), config_setting_t, setting);
|
252
|
+
return INT2FIX(config_setting_index(setting));
|
253
|
+
} else {
|
254
|
+
return Qnil;
|
255
|
+
}
|
256
|
+
}
|
257
|
+
|
258
|
+
static VALUE rbConfigBaseSetting_line(VALUE self)
|
259
|
+
{
|
260
|
+
if(rb_iv_get(self, "@setting") != Qnil) {
|
261
|
+
config_setting_t* setting = NULL;
|
262
|
+
Data_Get_Struct(rb_iv_get(self, "@setting"), config_setting_t, setting);
|
263
|
+
return INT2FIX(config_setting_source_line(setting));
|
264
|
+
} else {
|
265
|
+
return Qnil;
|
266
|
+
}
|
267
|
+
}
|
268
|
+
|
269
|
+
static VALUE rbConfigSetting_initialize(int argc, VALUE* argv, VALUE self)
|
270
|
+
{
|
271
|
+
VALUE value, setting;
|
272
|
+
rb_scan_args(argc, argv, "11", &value, &setting);
|
273
|
+
|
274
|
+
rb_call_super(1, &setting);
|
275
|
+
|
276
|
+
rconfig_check_setting_type(self, value);
|
277
|
+
rb_iv_set(self, "@value", value);
|
278
|
+
|
279
|
+
if(rb_iv_get(self, "@setting") != Qnil) {
|
280
|
+
config_setting_t* c_setting = NULL;
|
281
|
+
Data_Get_Struct(rb_iv_get(self, "@setting"), config_setting_t, c_setting);
|
282
|
+
rb_iv_set(self, "@format", INT2FIX(config_setting_get_format(c_setting)));
|
283
|
+
} else {
|
284
|
+
rb_iv_set(self, "@format", cConfigFormatDefault);
|
285
|
+
}
|
286
|
+
|
287
|
+
return self;
|
288
|
+
}
|
289
|
+
|
290
|
+
static VALUE rbConfigSetting_get_value(VALUE self)
|
291
|
+
{
|
292
|
+
if(rb_iv_get(self, "@setting") != Qnil) {
|
293
|
+
config_setting_t* setting;
|
294
|
+
Data_Get_Struct(rb_iv_get(self, "@setting"), config_setting_t, setting);
|
295
|
+
return rconfig_wrap_value(setting);
|
296
|
+
} else {
|
297
|
+
return rb_iv_get(self, "@value");
|
298
|
+
}
|
299
|
+
}
|
300
|
+
|
301
|
+
static VALUE rbConfigSetting_set_value(VALUE self, VALUE new_value)
|
302
|
+
{
|
303
|
+
rconfig_check_setting_type(self, new_value);
|
304
|
+
|
305
|
+
if(rb_iv_get(self, "@setting") != Qnil) {
|
306
|
+
config_setting_t* setting;
|
307
|
+
Data_Get_Struct(rb_iv_get(self, "@setting"), config_setting_t, setting);
|
308
|
+
rconfig_update_setting(setting, new_value);
|
309
|
+
}
|
310
|
+
|
311
|
+
rb_iv_set(self, "@value", new_value);
|
312
|
+
|
313
|
+
return new_value;
|
314
|
+
}
|
315
|
+
|
316
|
+
static VALUE rbConfigSetting_get_format(VALUE self)
|
317
|
+
{
|
318
|
+
if(rb_iv_get(self, "@setting") != Qnil) {
|
319
|
+
config_setting_t* setting;
|
320
|
+
Data_Get_Struct(rb_iv_get(self, "@setting"), config_setting_t, setting);
|
321
|
+
return INT2FIX(config_setting_get_format(setting));
|
322
|
+
} else {
|
323
|
+
return rb_iv_get(self, "format");
|
324
|
+
}
|
325
|
+
}
|
326
|
+
|
327
|
+
static VALUE rbConfigSetting_set_format(VALUE self, VALUE new_format)
|
328
|
+
{
|
329
|
+
if(rb_iv_get(self, "@setting") != Qnil) {
|
330
|
+
config_setting_t* setting;
|
331
|
+
Data_Get_Struct(rb_iv_get(self, "@setting"), config_setting_t, setting);
|
332
|
+
if(!config_setting_set_format(setting, FIX2INT(new_format)))
|
333
|
+
rb_raise(eSettingFormatError, "invalid setting format %d", FIX2INT(new_format));
|
334
|
+
}
|
335
|
+
|
336
|
+
rb_iv_set(self, "@format", new_format);
|
337
|
+
|
338
|
+
return new_format;
|
339
|
+
}
|
340
|
+
|
341
|
+
static VALUE rbConfigAggregate_get(VALUE self, VALUE index);
|
342
|
+
|
343
|
+
static VALUE rbConfigAggregate_initialize(int argc, VALUE* argv, VALUE self)
|
344
|
+
{
|
345
|
+
VALUE setting = Qnil;
|
346
|
+
if(rb_obj_class(self) == cConfigGroup || rb_obj_class(self) == cConfigList) {
|
347
|
+
rb_scan_args(argc, argv, "01", &setting);
|
348
|
+
} else if(rb_obj_class(self) == cConfigArray) {
|
349
|
+
VALUE type = Qnil;
|
350
|
+
rb_scan_args(argc, argv, "02", &type, &setting);
|
351
|
+
|
352
|
+
if(type != Qnil && rb_ary_includes(aConfigScalars, type) != Qtrue)
|
353
|
+
rb_raise(rb_eTypeError, "invalid setting array type %s", rb_class2name(type));
|
354
|
+
|
355
|
+
rb_iv_set(self, "@type", type);
|
356
|
+
} else {
|
357
|
+
rb_raise(rb_eException, "never create Config::Aggregate itself");
|
358
|
+
}
|
359
|
+
|
360
|
+
rb_call_super(1, &setting);
|
361
|
+
|
362
|
+
rb_iv_set(self, "@list", rb_ary_new());
|
363
|
+
if(rb_obj_class(self) == cConfigGroup)
|
364
|
+
rb_iv_set(self, "@hash", rb_hash_new());
|
365
|
+
|
366
|
+
if(setting != Qnil && rb_obj_class(self) == cConfigArray) {
|
367
|
+
config_setting_t* c_setting;
|
368
|
+
Data_Get_Struct(setting, config_setting_t, c_setting);
|
369
|
+
if(config_setting_length(c_setting) > 0)
|
370
|
+
rb_iv_set(self, "@type", rb_obj_class(rbConfigAggregate_get(self, INT2FIX(0))));
|
371
|
+
}
|
372
|
+
|
373
|
+
return self;
|
374
|
+
}
|
375
|
+
|
376
|
+
static VALUE rbConfigAggregate_size(VALUE self)
|
377
|
+
{
|
378
|
+
config_setting_t* setting = NULL;
|
379
|
+
if(rb_iv_get(self, "@setting") != Qnil)
|
380
|
+
Data_Get_Struct(rb_iv_get(self, "@setting"), config_setting_t, setting);
|
381
|
+
|
382
|
+
if(setting)
|
383
|
+
return INT2FIX(config_setting_length(setting));
|
384
|
+
else
|
385
|
+
return INT2FIX(RARRAY_LEN(rb_iv_get(self, "@list")));
|
386
|
+
}
|
387
|
+
|
388
|
+
static VALUE rbConfigAggregate_get(VALUE self, VALUE index)
|
389
|
+
{
|
390
|
+
config_setting_t* setting = NULL;
|
391
|
+
if(rb_iv_get(self, "@setting") != Qnil)
|
392
|
+
Data_Get_Struct(rb_iv_get(self, "@setting"), config_setting_t, setting);
|
393
|
+
|
394
|
+
VALUE rbTarget = Qnil;
|
395
|
+
|
396
|
+
if(TYPE(index) == T_STRING && rb_obj_class(self) == cConfigGroup) {
|
397
|
+
if(setting) {
|
398
|
+
config_setting_t* target = config_setting_get_member(setting, RSTRING_PTR(index));
|
399
|
+
if(target)
|
400
|
+
rbTarget = rconfig_wrap_setting(target);
|
401
|
+
} else {
|
402
|
+
rbTarget = rb_hash_aref(rb_iv_get(self, "@hash"), index);
|
403
|
+
}
|
404
|
+
} else if(TYPE(index) == T_FIXNUM) {
|
405
|
+
if(setting) {
|
406
|
+
config_setting_t* target = config_setting_get_elem(setting, FIX2INT(index));
|
407
|
+
if(target)
|
408
|
+
rbTarget = rconfig_wrap_setting(target);
|
409
|
+
} else {
|
410
|
+
rbTarget = rb_ary_entry(rb_iv_get(self, "@list"), FIX2INT(index));
|
411
|
+
}
|
412
|
+
} else {
|
413
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected String or Fixnum)", rb_obj_classname(index));
|
414
|
+
}
|
415
|
+
|
416
|
+
if(rbTarget == Qnil)
|
417
|
+
if(TYPE(index) == T_STRING)
|
418
|
+
rb_raise(eSettingNotFoundError, "setting `%s' not found", RSTRING_PTR(index));
|
419
|
+
else
|
420
|
+
rb_raise(eSettingNotFoundError, "setting [%d] not found", FIX2INT(index));
|
421
|
+
|
422
|
+
return rbTarget;
|
423
|
+
}
|
424
|
+
|
425
|
+
static VALUE rbConfigAggregate_append(VALUE self, VALUE target)
|
426
|
+
{
|
427
|
+
config_setting_t* setting = NULL;
|
428
|
+
if(rb_iv_get(self, "@setting") != Qnil)
|
429
|
+
Data_Get_Struct(rb_iv_get(self, "@setting"), config_setting_t, setting);
|
430
|
+
|
431
|
+
Check_Type(target, T_OBJECT);
|
432
|
+
|
433
|
+
VALUE type = rb_iv_get(self, "@type");
|
434
|
+
if(rb_obj_class(self) == cConfigArray) {
|
435
|
+
if(type != Qnil && type != rb_obj_class(target))
|
436
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)", rb_obj_classname(target), rb_class2name(type));
|
437
|
+
if(type == Qnil && rb_ary_includes(aConfigScalars, rb_obj_class(target)) != Qtrue)
|
438
|
+
rb_raise(rb_eTypeError, "invalid setting array type %s", rb_obj_classname(target));
|
439
|
+
}
|
440
|
+
|
441
|
+
if(rb_ary_includes(aConfigSettings, rb_obj_class(target)) == Qtrue) {
|
442
|
+
if(setting)
|
443
|
+
rconfig_do_append(setting, target, Qnil);
|
444
|
+
rb_ary_push(rb_iv_get(self, "@list"), target);
|
445
|
+
} else {
|
446
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected Config::BaseSetting)", rb_obj_classname(target));
|
447
|
+
}
|
448
|
+
|
449
|
+
if(rb_obj_class(self) == cConfigArray && type == Qnil)
|
450
|
+
rb_iv_set(self, "@type", rb_obj_class(target));
|
451
|
+
|
452
|
+
return target;
|
453
|
+
}
|
454
|
+
|
455
|
+
static VALUE rbConfigGroup_append(VALUE self, VALUE name, VALUE target)
|
456
|
+
{
|
457
|
+
Check_Type(name, T_STRING);
|
458
|
+
Check_Type(target, T_OBJECT);
|
459
|
+
|
460
|
+
config_setting_t* setting = NULL;
|
461
|
+
if(rb_iv_get(self, "@setting") != Qnil)
|
462
|
+
Data_Get_Struct(rb_iv_get(self, "@setting"), config_setting_t, setting);
|
463
|
+
|
464
|
+
if(rb_ary_includes(aConfigSettings, rb_obj_class(target)) == Qtrue) {
|
465
|
+
if(rb_reg_match(rSettingNameRegexp, name) == Qnil)
|
466
|
+
rb_raise(eSettingNameError, "setting name `%s' contains invalid characters", RSTRING_PTR(name));
|
467
|
+
if(setting) {
|
468
|
+
if(!rconfig_do_append(setting, target, name))
|
469
|
+
rb_raise(eSettingNameError, "setting `%s' already exists", RSTRING_PTR(name));
|
470
|
+
} else if(rb_hash_aref(rb_iv_get(self, "@hash"), name) != Qnil) {
|
471
|
+
rb_raise(eSettingNameError, "setting `%s' already exists", RSTRING_PTR(name));
|
472
|
+
}
|
473
|
+
rb_ary_push(rb_iv_get(self, "@list"), target);
|
474
|
+
rb_hash_aset(rb_iv_get(self, "@hash"), name, target);
|
475
|
+
} else {
|
476
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected Config::BaseSetting)", rb_obj_classname(target));
|
477
|
+
}
|
478
|
+
|
479
|
+
return target;
|
480
|
+
}
|
481
|
+
|
482
|
+
static VALUE rbConfigAggregate_delete(VALUE self, VALUE target)
|
483
|
+
{
|
484
|
+
config_setting_t* setting = NULL;
|
485
|
+
if(rb_iv_get(self, "@setting") != Qnil)
|
486
|
+
Data_Get_Struct(rb_iv_get(self, "@setting"), config_setting_t, setting);
|
487
|
+
|
488
|
+
VALUE hash = rb_iv_get(self, "@hash"), list = rb_iv_get(self, "@list");
|
489
|
+
|
490
|
+
if(TYPE(target) == T_STRING && rb_obj_class(self) == cConfigGroup) {
|
491
|
+
if(setting)
|
492
|
+
config_setting_remove(setting, RSTRING_PTR(target));
|
493
|
+
|
494
|
+
rb_ary_delete_at(list, rb_hash_aref(hash, target));
|
495
|
+
rb_hash_delete(hash, target);
|
496
|
+
} else if(TYPE(target) == T_FIXNUM) {
|
497
|
+
int index = FIX2INT(target);
|
498
|
+
if(setting)
|
499
|
+
config_setting_remove_elem(setting, index);
|
500
|
+
|
501
|
+
if(rb_obj_class(self) == cConfigGroup)
|
502
|
+
rb_hash_delete(hash, rbConfigBaseSetting_name(rb_ary_entry(list, index)));
|
503
|
+
rb_ary_delete_at(list, index);
|
504
|
+
} else if(rb_ary_includes(aConfigSettings, rb_obj_class(target)) == Qtrue) {
|
505
|
+
VALUE name = rbConfigBaseSetting_name(target);
|
506
|
+
if(setting)
|
507
|
+
config_setting_remove(setting, RSTRING_PTR(name));
|
508
|
+
|
509
|
+
if(rb_obj_class(self) == cConfigGroup)
|
510
|
+
rb_hash_delete(hash, name);
|
511
|
+
rb_ary_delete(list, target);
|
512
|
+
} else {
|
513
|
+
if(rb_obj_class(self) == cConfigGroup)
|
514
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected String, Fixnum or Config::BaseSetting)", rb_obj_classname(target));
|
515
|
+
else
|
516
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected Fixnum or Config::BaseSetting)", rb_obj_classname(target));
|
517
|
+
}
|
518
|
+
|
519
|
+
return Qnil;
|
520
|
+
}
|
521
|
+
|
522
|
+
static VALUE rbConfig_initialize(VALUE self)
|
523
|
+
{
|
524
|
+
config_t* config = (config_t*) malloc(sizeof(config_t));
|
525
|
+
config_init(config);
|
526
|
+
config_set_destructor(config, &rconfig_destroy_setting);
|
527
|
+
|
528
|
+
VALUE rbConfig = Data_Wrap_Struct(rb_cObject, 0, config_destroy, config);
|
529
|
+
rb_iv_set(self, "@config", rbConfig);
|
530
|
+
|
531
|
+
return self;
|
532
|
+
}
|
533
|
+
|
534
|
+
static VALUE rbConfig_read_bang(VALUE self, VALUE path)
|
535
|
+
{
|
536
|
+
Check_Type(path, T_STRING);
|
537
|
+
|
538
|
+
config_t* config;
|
539
|
+
Data_Get_Struct(rb_iv_get(self, "@config"), config_t, config);
|
540
|
+
|
541
|
+
if(!config_read_file(config, RSTRING_PTR(path))) {
|
542
|
+
if(config_error_line(config) == 0)
|
543
|
+
rb_raise(rb_eIOError, "cannot load config: I/O error");
|
544
|
+
else
|
545
|
+
rb_raise(eConfigParseError, "cannot parse config on line %d: `%s'",
|
546
|
+
config_error_line(config), config_error_text(config));
|
547
|
+
}
|
548
|
+
|
549
|
+
return Qtrue;
|
550
|
+
}
|
551
|
+
|
552
|
+
static VALUE rbConfig_write_bang(VALUE self, VALUE path)
|
553
|
+
{
|
554
|
+
Check_Type(path, T_STRING);
|
555
|
+
|
556
|
+
config_t* config;
|
557
|
+
Data_Get_Struct(rb_iv_get(self, "@config"), config_t, config);
|
558
|
+
|
559
|
+
if(!config_write_file(config, RSTRING_PTR(path)))
|
560
|
+
rb_raise(rb_eIOError, "cannot save config: I/O error");
|
561
|
+
|
562
|
+
return Qtrue;
|
563
|
+
}
|
564
|
+
|
565
|
+
static VALUE rbConfig_read(VALUE self, VALUE path)
|
566
|
+
{
|
567
|
+
Check_Type(path, T_STRING);
|
568
|
+
|
569
|
+
config_t* config;
|
570
|
+
Data_Get_Struct(rb_iv_get(self, "@config"), config_t, config);
|
571
|
+
|
572
|
+
return config_read_file(config, RSTRING_PTR(path)) ? Qtrue : Qfalse;
|
573
|
+
}
|
574
|
+
|
575
|
+
static VALUE rbConfig_write(VALUE self, VALUE path)
|
576
|
+
{
|
577
|
+
Check_Type(path, T_STRING);
|
578
|
+
|
579
|
+
config_t* config;
|
580
|
+
Data_Get_Struct(rb_iv_get(self, "@config"), config_t, config);
|
581
|
+
|
582
|
+
return config_write_file(config, RSTRING_PTR(path)) ? Qtrue : Qfalse;
|
583
|
+
}
|
584
|
+
|
585
|
+
static VALUE rbConfig_root(VALUE self)
|
586
|
+
{
|
587
|
+
config_t* config;
|
588
|
+
Data_Get_Struct(rb_iv_get(self, "@config"), config_t, config);
|
589
|
+
|
590
|
+
return rconfig_wrap_setting(config_root_setting(config));
|
591
|
+
}
|
592
|
+
|
593
|
+
static VALUE rbConfig_lookup(VALUE self, VALUE handle)
|
594
|
+
{
|
595
|
+
if(TYPE(handle) == T_STRING) {
|
596
|
+
config_t* config;
|
597
|
+
Data_Get_Struct(rb_iv_get(self, "@config"), config_t, config);
|
598
|
+
|
599
|
+
config_setting_t* setting;
|
600
|
+
setting = config_lookup(config, RSTRING_PTR(handle));
|
601
|
+
|
602
|
+
if(setting == NULL)
|
603
|
+
rb_raise(eSettingNotFoundError, "setting `%s' not found", RSTRING_PTR(handle));
|
604
|
+
|
605
|
+
return rconfig_wrap_setting(setting);
|
606
|
+
} else if(TYPE(handle) == T_FIXNUM) {
|
607
|
+
return rbConfigAggregate_get(rbConfig_root(self), handle);
|
608
|
+
} else {
|
609
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected String or Fixnum)", rb_obj_classname(handle));
|
610
|
+
}
|
611
|
+
}
|
612
|
+
|
613
|
+
static VALUE rbConfig_append(VALUE self, VALUE name, VALUE target)
|
614
|
+
{
|
615
|
+
return rbConfigGroup_append(rbConfig_root(self), name, target);
|
616
|
+
}
|
617
|
+
|
618
|
+
static VALUE rbConfig_delete(VALUE self, VALUE name)
|
619
|
+
{
|
620
|
+
return rbConfigAggregate_delete(rbConfig_root(self), name);
|
621
|
+
}
|
622
|
+
|
623
|
+
static VALUE rbConfig_size(VALUE self)
|
624
|
+
{
|
625
|
+
return rbConfigAggregate_size(rbConfig_root(self));
|
626
|
+
}
|
627
|
+
|
628
|
+
void Init_rlibconfig()
|
629
|
+
{
|
630
|
+
cConfig = rb_define_class("LibConfig", rb_cObject);
|
631
|
+
rb_define_method(cConfig, "initialize", rbConfig_initialize, 0);
|
632
|
+
rb_define_method(cConfig, "read!", rbConfig_read_bang, 1);
|
633
|
+
rb_define_method(cConfig, "write!", rbConfig_write_bang, 1);
|
634
|
+
rb_define_method(cConfig, "read", rbConfig_read, 1);
|
635
|
+
rb_define_method(cConfig, "write", rbConfig_write, 1);
|
636
|
+
rb_define_method(cConfig, "root", rbConfig_root, 0);
|
637
|
+
rb_define_method(cConfig, "lookup", rbConfig_lookup, 1);
|
638
|
+
rb_define_method(cConfig, "[]", rbConfig_lookup, 1);
|
639
|
+
rb_define_method(cConfig, "append", rbConfig_append, 2);
|
640
|
+
rb_define_method(cConfig, "delete", rbConfig_delete, 1);
|
641
|
+
rb_define_method(cConfig, "size", rbConfig_size, 0);
|
642
|
+
|
643
|
+
cConfigBaseSetting = rb_define_class_under(cConfig, "BaseSetting", rb_cObject);
|
644
|
+
rb_define_method(cConfigBaseSetting, "initialize", rbConfigBaseSetting_initialize, 1);
|
645
|
+
rb_define_method(cConfigBaseSetting, "name", rbConfigBaseSetting_name, 0);
|
646
|
+
rb_define_method(cConfigBaseSetting, "parent", rbConfigBaseSetting_parent, 0);
|
647
|
+
rb_define_method(cConfigBaseSetting, "root?", rbConfigBaseSetting_is_root, 0);
|
648
|
+
rb_define_method(cConfigBaseSetting, "index", rbConfigBaseSetting_index, 0);
|
649
|
+
rb_define_method(cConfigBaseSetting, "line", rbConfigBaseSetting_line, 0);
|
650
|
+
|
651
|
+
cConfigSetting = rb_define_class_under(cConfig, "Setting", cConfigBaseSetting);
|
652
|
+
rb_define_method(cConfigSetting, "initialize", rbConfigSetting_initialize, -1);
|
653
|
+
rb_define_method(cConfigSetting, "value", rbConfigSetting_get_value, 0);
|
654
|
+
rb_define_method(cConfigSetting, "value=", rbConfigSetting_set_value, 1);
|
655
|
+
rb_define_method(cConfigSetting, "format", rbConfigSetting_get_format, 0);
|
656
|
+
rb_define_method(cConfigSetting, "format=", rbConfigSetting_set_format, 1);
|
657
|
+
|
658
|
+
cConfigFormatDefault = INT2FIX(CONFIG_FORMAT_DEFAULT);
|
659
|
+
rb_define_const(cConfig, "FORMAT_DEFAULT", cConfigFormatDefault);
|
660
|
+
cConfigFormatHex = INT2FIX(CONFIG_FORMAT_HEX);
|
661
|
+
rb_define_const(cConfig, "FORMAT_HEX", cConfigFormatHex);
|
662
|
+
|
663
|
+
cConfigFixnum = rb_define_class_under(cConfig, "Fixnum", cConfigSetting);
|
664
|
+
cConfigBignum = rb_define_class_under(cConfig, "Bignum", cConfigSetting);
|
665
|
+
cConfigFloat = rb_define_class_under(cConfig, "Float", cConfigSetting);
|
666
|
+
cConfigBoolean = rb_define_class_under(cConfig, "Boolean", cConfigSetting);
|
667
|
+
cConfigString = rb_define_class_under(cConfig, "String", cConfigSetting);
|
668
|
+
|
669
|
+
cConfigAggregate = rb_define_class_under(cConfig, "Aggregate", cConfigBaseSetting);
|
670
|
+
rb_define_method(cConfigAggregate, "initialize", rbConfigAggregate_initialize, -1);
|
671
|
+
rb_define_method(cConfigAggregate, "size", rbConfigAggregate_size, 0);
|
672
|
+
rb_define_method(cConfigAggregate, "get", rbConfigAggregate_get, 1);
|
673
|
+
rb_define_method(cConfigAggregate, "[]", rbConfigAggregate_get, 1);
|
674
|
+
rb_define_method(cConfigAggregate, "delete", rbConfigAggregate_delete, 1);
|
675
|
+
|
676
|
+
cConfigGroup = rb_define_class_under(cConfig, "Group", cConfigAggregate);
|
677
|
+
rb_define_method(cConfigGroup, "append", rbConfigGroup_append, 2);
|
678
|
+
cConfigArray = rb_define_class_under(cConfig, "Array", cConfigAggregate);
|
679
|
+
rb_define_method(cConfigArray, "append", rbConfigAggregate_append, 1);
|
680
|
+
rb_define_method(cConfigArray, "<<", rbConfigAggregate_append, 1);
|
681
|
+
cConfigList = rb_define_class_under(cConfig, "List", cConfigAggregate);
|
682
|
+
rb_define_method(cConfigList, "append", rbConfigAggregate_append, 1);
|
683
|
+
rb_define_method(cConfigList, "<<", rbConfigAggregate_append, 1);
|
684
|
+
|
685
|
+
aConfigScalars = rb_ary_new3(5, cConfigFixnum, cConfigBignum, cConfigFloat, cConfigBoolean, cConfigString);
|
686
|
+
aConfigAggregates = rb_ary_new3(3, cConfigGroup, cConfigArray, cConfigList);
|
687
|
+
aConfigSettings = rb_ary_plus(aConfigScalars, aConfigAggregates);
|
688
|
+
|
689
|
+
rb_define_const(cConfig, "SCALARS", aConfigScalars);
|
690
|
+
rb_define_const(cConfig, "AGGREGATES", aConfigAggregates);
|
691
|
+
rb_define_const(cConfig, "SETTINGS", aConfigSettings);
|
692
|
+
|
693
|
+
char* settingNameRegexp = "^[A-Za-z*][A-Za-z\\-_*]*$";
|
694
|
+
rSettingNameRegexp = rb_reg_new(settingNameRegexp, strlen(settingNameRegexp), 0);
|
695
|
+
|
696
|
+
eConfigParseError = rb_define_class("ConfigParseError", rb_eException);
|
697
|
+
eSettingNotFoundError = rb_define_class("SettingNotFoundError", rb_eException);
|
698
|
+
eSettingFormatError = rb_define_class("SettingFormatError", rb_eException);
|
699
|
+
eSettingNameError = rb_define_class("SettingNameError", rb_eException);
|
700
|
+
}
|
metadata
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rlibconfig
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- John Mah
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-04-15 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description:
|
14
|
+
email: johnmah@rogers.com
|
15
|
+
executables: []
|
16
|
+
extensions:
|
17
|
+
- ext/extconf.rb
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- ext/extconf.rb
|
21
|
+
- ext/rlibconfig.c
|
22
|
+
homepage:
|
23
|
+
licenses: []
|
24
|
+
metadata: {}
|
25
|
+
post_install_message:
|
26
|
+
rdoc_options: []
|
27
|
+
require_paths:
|
28
|
+
- lib
|
29
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
35
|
+
requirements:
|
36
|
+
- - ! '>='
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '0'
|
39
|
+
requirements: []
|
40
|
+
rubyforge_project:
|
41
|
+
rubygems_version: 2.2.2
|
42
|
+
signing_key:
|
43
|
+
specification_version: 4
|
44
|
+
summary: libconfig bindings
|
45
|
+
test_files: []
|