ucl 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. checksums.yaml +7 -0
  2. data/ext/extconf.rb +6 -0
  3. data/ext/ucl.c +210 -0
  4. data/ucl.gemspec +19 -0
  5. metadata +51 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 123bfade721343ef51a1b839b450365e7d2aa934e16e9d537a708582336aca60
4
+ data.tar.gz: c2f59b562e9a13fb4535e65055acf6d4fa8e140161ecb445875699314163cc93
5
+ SHA512:
6
+ metadata.gz: fe5a117504dd4694952d5555107a8c7c886ca25a5a2bebe5e52f394552fbf39386175040080a85dcaf4a240d7837af436a483255ae0f2411932de2b62bbed98f
7
+ data.tar.gz: ccebbfb07adabb8e892c855ccacf385ee79a81415b5f57a1b1ce50fffb7fb01e233902265bac6f6950fc3aa93e44f8a8067c122a08e029ce85df1348294bb94c
data/ext/extconf.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'mkmf'
2
+
3
+
4
+ have_library('ucl')
5
+
6
+ create_makefile("ucl")
data/ext/ucl.c ADDED
@@ -0,0 +1,210 @@
1
+ #include <ruby.h>
2
+ #include <ruby/io.h>
3
+ #include <ucl.h>
4
+ #include <stdio.h>
5
+ #include <stdbool.h>
6
+
7
+ /* Fake flag */
8
+ #define UCL_PARSER_KEY_SYMBOL (1 << 10)
9
+
10
+
11
+ /**
12
+ * Document-class: UCL
13
+ *
14
+ * UCL configuration file.
15
+ */
16
+
17
+ /**
18
+ * Document-class: UCL::Error
19
+ *
20
+ * Generic error raised by UCL.
21
+ */
22
+
23
+
24
+
25
+ static VALUE mUCL = Qundef;
26
+ static VALUE eUCLError = Qundef;
27
+
28
+
29
+ VALUE
30
+ _iterate_valid_ucl(ucl_object_t const *root, int flags)
31
+ {
32
+ const ucl_object_t *obj;
33
+ ucl_object_iter_t it = NULL;
34
+ const ucl_object_t *cur;
35
+ ucl_object_iter_t it_obj = NULL;
36
+
37
+ VALUE lst = rb_ary_new();
38
+
39
+ while ((obj = ucl_object_iterate (root, &it, false))) {
40
+ VALUE val;
41
+
42
+ switch (obj->type) {
43
+ case UCL_INT:
44
+ val = rb_ll2inum((long long)ucl_object_toint(obj));
45
+ break;
46
+
47
+ case UCL_FLOAT:
48
+ val = rb_float_new(ucl_object_todouble(obj));
49
+ break;
50
+
51
+ case UCL_STRING:
52
+ val = rb_str_new_cstr(ucl_object_tostring(obj));
53
+ break;
54
+
55
+ case UCL_BOOLEAN:
56
+ val = ucl_object_toboolean(obj) ? Qtrue : Qfalse;
57
+ break;
58
+
59
+ case UCL_TIME:
60
+ val = rb_float_new(ucl_object_todouble(obj));
61
+ break;
62
+
63
+ case UCL_OBJECT:
64
+ it_obj = NULL;
65
+ val = rb_hash_new();
66
+ while ((cur = ucl_object_iterate(obj, &it_obj, true))) {
67
+ const char *obj_key = ucl_object_key(cur);
68
+ VALUE key = (flags & UCL_PARSER_KEY_SYMBOL)
69
+ ? rb_id2sym(rb_intern(obj_key))
70
+ : rb_str_new_cstr(obj_key);
71
+ rb_hash_aset(val, key, _iterate_valid_ucl(cur, flags));
72
+ }
73
+ break;
74
+
75
+ case UCL_ARRAY:
76
+ it_obj = NULL;
77
+ val = rb_ary_new();
78
+ while ((cur = ucl_object_iterate (obj, &it_obj, true))) {
79
+ rb_ary_push(val, _iterate_valid_ucl(cur, flags));
80
+ }
81
+ break;
82
+
83
+ case UCL_USERDATA:
84
+ val = rb_str_new(obj->value.sv, obj->len);
85
+ break;
86
+
87
+ case UCL_NULL:
88
+ val = Qnil;
89
+ break;
90
+
91
+ default:
92
+ rb_bug("unhandled type (%d)", obj->type);
93
+
94
+ }
95
+ rb_ary_push(lst, val);
96
+
97
+ }
98
+
99
+ switch(RARRAY_LENINT(lst)) {
100
+ case 0: return Qnil;
101
+ case 1: return RARRAY_PTR(lst)[0];
102
+ default: return lst;
103
+ }
104
+ }
105
+
106
+
107
+
108
+ /**
109
+ * Parse a configuration file
110
+ *
111
+ * @param data [String]
112
+ * @param flags [Integer]
113
+ *
114
+ * @return configuration file as ruby objects.
115
+ */
116
+ static VALUE
117
+ ucl_s_parse(int argc, VALUE *argv, VALUE klass)
118
+ {
119
+ static int allowed_flags = UCL_PARSER_KEY_LOWERCASE |
120
+ UCL_PARSER_NO_TIME |
121
+ UCL_PARSER_DISABLE_MACRO |
122
+ UCL_PARSER_NO_FILEVARS ;
123
+
124
+ VALUE data, flags;
125
+ rb_scan_args(argc, argv, "11", &data, &flags);
126
+ if (NIL_P(flags)) flags = INT2FIX(0);
127
+
128
+ rb_check_type(data, T_STRING);
129
+ rb_check_type(flags, T_FIXNUM);
130
+
131
+ int c_flags = FIX2INT(flags) & allowed_flags;
132
+
133
+ struct ucl_parser *parser =
134
+ ucl_parser_new(c_flags | UCL_PARSER_NO_IMPLICIT_ARRAYS);
135
+
136
+ ucl_parser_add_chunk(parser,
137
+ (unsigned char *)RSTRING_PTR(data),
138
+ RSTRING_LEN(data));
139
+
140
+ if (ucl_parser_get_error(parser)) {
141
+ rb_raise(eUCLError, "%s", ucl_parser_get_error(parser));
142
+ }
143
+
144
+ ucl_object_t *root = ucl_parser_get_object(parser);
145
+
146
+ VALUE res = _iterate_valid_ucl(root, FIX2INT(flags));
147
+
148
+ if (parser != NULL) {
149
+ ucl_parser_free(parser);
150
+ }
151
+
152
+ if (root != NULL) {
153
+ ucl_object_unref(root);
154
+ }
155
+
156
+ return res;
157
+ }
158
+
159
+
160
+ /**
161
+ * Load configuration file
162
+ *
163
+ * @param file [String]
164
+ * @param flags [Integer]
165
+ *
166
+ * @example
167
+ * UCL.load_file('foo.conf', UCL::KEY_SYMBOL)
168
+ *
169
+ * @return configuration file as ruby objects.
170
+ */
171
+ static VALUE
172
+ ucl_s_load_file(int argc, VALUE *argv, VALUE klass)
173
+ {
174
+ VALUE file, flags;
175
+ rb_scan_args(argc, argv, "11", &file, &flags);
176
+
177
+ VALUE read_kwargs = rb_hash_new();
178
+ rb_hash_aset(read_kwargs, rb_id2sym(rb_intern("encoding")),
179
+ rb_str_new_cstr("BINARY"));
180
+
181
+ VALUE read_args[] = { file, read_kwargs };
182
+ VALUE data = rb_funcallv_kw(rb_cFile, rb_intern("read"),
183
+ 2, read_args, RB_PASS_KEYWORDS);
184
+
185
+ VALUE parse_args[] = { data, flags };
186
+ return ucl_s_parse(2, parse_args, klass);
187
+ }
188
+
189
+
190
+
191
+
192
+ void Init_ucl(void) {
193
+ /* Main classes */
194
+ mUCL = rb_define_class("UCL", rb_cObject);
195
+ eUCLError = rb_define_class_under(mUCL, "Error", rb_eStandardError);
196
+
197
+ /* Constants */
198
+ rb_define_const(mUCL, "KEY_LOWERCASE", INT2FIX(UCL_PARSER_KEY_LOWERCASE));
199
+ rb_define_const(mUCL, "NO_TIME", INT2FIX(UCL_PARSER_NO_TIME ));
200
+ rb_define_const(mUCL, "DISABLE_MACRO", INT2FIX(UCL_PARSER_DISABLE_MACRO));
201
+ rb_define_const(mUCL, "NO_FILEVARS", INT2FIX(UCL_PARSER_NO_FILEVARS ));
202
+ rb_define_const(mUCL, "KEY_SYMBOL", INT2FIX(UCL_PARSER_KEY_SYMBOL ));
203
+
204
+ /* Definitions */
205
+ rb_define_singleton_method(mUCL, "load_file", ucl_s_load_file, -1);
206
+ rb_define_singleton_method(mUCL, "parse", ucl_s_parse, -1);
207
+
208
+ }
209
+
210
+
data/ucl.gemspec ADDED
@@ -0,0 +1,19 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'ucl'
3
+ s.version = '0.1.0'
4
+ s.summary = " Universal configuration library parser"
5
+ s.description = <<~EOF
6
+
7
+ Read configuration file in UCL format (binding to the libucl).
8
+
9
+ EOF
10
+
11
+ s.homepage = 'https://github.com/sdalu/ruby-ucl'
12
+ s.license = 'MIT'
13
+
14
+ s.authors = [ "Stéphane D'Alu" ]
15
+ s.email = [ 'sdalu@sdalu.com' ]
16
+
17
+ s.extensions = [ 'ext/extconf.rb' ]
18
+ s.files = %w[ ucl.gemspec ] + Dir['ext/**/*.{c,h,rb}']
19
+ end
metadata ADDED
@@ -0,0 +1,51 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ucl
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Stéphane D'Alu
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-12-19 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: |2+
14
+
15
+ Read configuration file in UCL format (binding to the libucl).
16
+
17
+ email:
18
+ - sdalu@sdalu.com
19
+ executables: []
20
+ extensions:
21
+ - ext/extconf.rb
22
+ extra_rdoc_files: []
23
+ files:
24
+ - ext/extconf.rb
25
+ - ext/ucl.c
26
+ - ucl.gemspec
27
+ homepage: https://github.com/sdalu/ruby-ucl
28
+ licenses:
29
+ - MIT
30
+ metadata: {}
31
+ post_install_message:
32
+ rdoc_options: []
33
+ require_paths:
34
+ - lib
35
+ required_ruby_version: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ requirements: []
46
+ rubygems_version: 3.3.23
47
+ signing_key:
48
+ specification_version: 4
49
+ summary: Universal configuration library parser
50
+ test_files: []
51
+ ...