ucl 0.1.0

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.
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
+ ...