ruby_rnv 0.2.2 → 0.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 11b77ce5fa44a0112a7741b4ab4aa8ed452c3a3acf71eafa7d32c892e619bfe9
4
- data.tar.gz: ee3066b2c467a4b62539ac5b0bb1d83de10e5400a11ef18d7c93094bbc717881
3
+ metadata.gz: f72e473e7924c7c3e215b53e08311afcf6781bb17a3df2842300661e86b35601
4
+ data.tar.gz: e513f2403d0ae91f35fde8f4b81b264a3ff16bb0a6be5f1dc80b17f3aa00ddcc
5
5
  SHA512:
6
- metadata.gz: 26a579f0daef0bc13bc70102e66c9bc361bbd5ab4d043bffbf48200068357d628c31702f2178dea63e420496e0fc2b0253a61d5f4124437d24f0daa01880d0e2
7
- data.tar.gz: 9d01764589fecd74ba7c27114dc351dcb1eaddb1b69d86f9a4c0f2fa60e009917a29f5107b861d81065e6bd142d55c1758dc864199dcfaf9835a84a33d682e28
6
+ metadata.gz: b0ce856ca07f203e0a0a4307943a113ff703e5a32031946e463496d485b49bafbeeb42a9057b3d697a92a00294c5d79c29b6bc7be62565dc75a910f16b4c1dbf
7
+ data.tar.gz: 3a5028a2bf2d558a9a7501336fe190a994dc867dd9eef83fcf9ce38ff481f6c1743f77e9d5f604ee9f3d07e95840bf7d79870b163fabf9f866e7c122e40f570b
data/ext/rnv/extconf.rb CHANGED
@@ -3,7 +3,7 @@ require 'mkmf'
3
3
  CONFIG['warnflags'].gsub!(/-W.* /, '')
4
4
 
5
5
  $srcs = %w{src/rn.c src/rnc.c src/rnd.c src/rnl.c src/rnv.c src/rnx.c src/drv.c src/ary.c src/xsd.c src/xsd_tm.c
6
- src/sc.c src/u.c src/ht.c src/er.c src/xmlc.c src/s.c src/m.c src/rx.c ruby_rnv.c}
6
+ src/sc.c src/u.c src/ht.c src/er.c src/xmlc.c src/s.c src/m.c src/rx.c ruby_rnv_err.c ruby_rnv.c}
7
7
 
8
8
  $INCFLAGS << " -I$(srcdir)/src"
9
9
 
data/ext/rnv/ruby_rnv.c CHANGED
@@ -1,423 +1,40 @@
1
- #include <stdio.h>
2
- #include <stdlib.h>
3
- #include <stdarg.h>
4
- #include <fcntl.h> /*open,close*/
5
- #include <sys/types.h>
6
- #include <unistd.h> /*open,read,close*/
7
- #include <string.h> /*strerror*/
8
- #include <errno.h>
9
- #include <assert.h>
10
-
11
- #include "src/m.h"
12
- #include "src/s.h"
13
- #include "src/erbit.h"
14
- #include "src/drv.h"
15
- #include "src/rnl.h"
16
- #include "src/rnv.h"
17
- #include "src/rnx.h"
18
- #include "src/ll.h"
19
- #include "src/er.h"
20
- #include "src/erbit.h"
21
- #include "src/rnc.h"
22
- #include "src/rnd.h"
23
- #include "src/rx.h"
24
- #include "src/xsd.h"
25
-
26
- #include <ruby.h>
27
- #include <ruby/io.h>
1
+ #include "ruby_rnv.h"
28
2
 
29
3
  #define LEN_T XCL_LEN_T
30
4
  #define LIM_T XCL_LIM_T
31
5
 
32
- typedef struct document
33
- {
34
- char *fn;
35
- int start;
36
- int current;
37
- int previous;
38
- int lastline;
39
- int lastcol;
40
- int level;
41
- int opened;
42
- int ok;
43
- char *text;
44
- int len_txt;
45
- int n_txt;
46
- int mixed;
47
- int nexp;
48
-
49
- rnv_t *rnv;
50
- rn_st_t *rn_st;
51
- rnc_st_t *rnc_st;
52
- rnx_st_t *rnx_st;
53
- drv_st_t *drv_st;
54
- rx_st_t *rx_st;
55
- rnd_st_t *rnd_st;
56
-
57
- } document_t;
58
-
59
- VALUE RNV;
60
-
61
- // convert error code to symbol
62
- ID errno_to_id(int erno)
63
- {
64
- ID id;
65
- switch (erno)
66
- {
67
- case (ERBIT_RNC | RNC_ER_IO):
68
- id = rb_intern("rnc_er_io");
69
- break;
70
- case (ERBIT_RNC | RNC_ER_UTF):
71
- id = rb_intern("rnc_er_urf");
72
- break;
73
- case (ERBIT_RNC | RNC_ER_XESC):
74
- id = rb_intern("rnc_er_xesc");
75
- break;
76
- case (ERBIT_RNC | RNC_ER_LEXP):
77
- id = rb_intern("rnc_er_lexp");
78
- break;
79
- case (ERBIT_RNC | RNC_ER_LLIT):
80
- id = rb_intern("rnc_er_llit");
81
- break;
82
- case (ERBIT_RNC | RNC_ER_LILL):
83
- id = rb_intern("rnc_er_lill");
84
- break;
85
- case (ERBIT_RNC | RNC_ER_SEXP):
86
- id = rb_intern("rnc_er_sexp");
87
- break;
88
- case (ERBIT_RNC | RNC_ER_SILL):
89
- id = rb_intern("rnc_er_still");
90
- break;
91
- case (ERBIT_RNC | RNC_ER_NOTGR):
92
- id = rb_intern("rnc_er_notgr");
93
- break;
94
- case (ERBIT_RNC | RNC_ER_EXT):
95
- id = rb_intern("rnc_er_ext");
96
- break;
97
- case (ERBIT_RNC | RNC_ER_DUPNS):
98
- id = rb_intern("rnc_er_dupns");
99
- break;
100
- case (ERBIT_RNC | RNC_ER_DUPDT):
101
- id = rb_intern("rnc_er_dupdt");
102
- break;
103
- case (ERBIT_RNC | RNC_ER_DFLTNS):
104
- id = rb_intern("rnc_er_dfltns");
105
- break;
106
- case (ERBIT_RNC | RNC_ER_DFLTDT):
107
- id = rb_intern("rnc_er_dfltdt");
108
- break;
109
- case (ERBIT_RNC | RNC_ER_NONS):
110
- id = rb_intern("rnc_er_nons");
111
- break;
112
- case (ERBIT_RNC | RNC_ER_NODT):
113
- id = rb_intern("rnc_er_nodt");
114
- break;
115
- case (ERBIT_RNC | RNC_ER_NCEX):
116
- id = rb_intern("rnc_er_ncex");
117
- break;
118
- case (ERBIT_RNC | RNC_ER_2HEADS):
119
- id = rb_intern("rnc_er_2heads");
120
- break;
121
- case (ERBIT_RNC | RNC_ER_COMBINE):
122
- id = rb_intern("rnc_er_combine");
123
- break;
124
- case (ERBIT_RNC | RNC_ER_OVRIDE):
125
- id = rb_intern("rnc_er_ovride");
126
- break;
127
- case (ERBIT_RNC | RNC_ER_EXPT):
128
- id = rb_intern("rnc_er_excpt");
129
- break;
130
- case (ERBIT_RNC | RNC_ER_INCONT):
131
- id = rb_intern("rnc_er_incont");
132
- break;
133
- case (ERBIT_RNC | RNC_ER_NOSTART):
134
- id = rb_intern("rnc_er_nostart");
135
- break;
136
- case (ERBIT_RNC | RNC_ER_UNDEF):
137
- id = rb_intern("rnc_er_undef");
138
- break;
139
-
140
- case (ERBIT_RND | RND_ER_LOOPST):
141
- id = rb_intern("rnd_er_loopst");
142
- break;
143
- case (ERBIT_RND | RND_ER_LOOPEL):
144
- id = rb_intern("rnd_er_loopel");
145
- break;
146
- case (ERBIT_RND | RND_ER_CTYPE):
147
- id = rb_intern("rnd_er_ctype");
148
- break;
149
- case (ERBIT_RND | RND_ER_BADSTART):
150
- id = rb_intern("rnd_er_badstart");
151
- break;
152
- case (ERBIT_RND | RND_ER_BADMORE):
153
- id = rb_intern("rnd_er_badmore");
154
- break;
155
- case (ERBIT_RND | RND_ER_BADEXPT):
156
- id = rb_intern("rnd_er_badexpt");
157
- break;
158
- case (ERBIT_RND | RND_ER_BADLIST):
159
- id = rb_intern("rnd_er_badlist");
160
- break;
161
- case (ERBIT_RND | RND_ER_BADATTR):
162
- id = rb_intern("rnd_er_badattr");
163
- break;
164
-
165
- case (ERBIT_RX | RX_ER_BADCH):
166
- id = rb_intern("rx_er_badch");
167
- break;
168
- case (ERBIT_RX | RX_ER_UNFIN):
169
- id = rb_intern("rx_er_unfin");
170
- break;
171
- case (ERBIT_RX | RX_ER_NOLSQ):
172
- id = rb_intern("rx_er_nolsq");
173
- break;
174
- case (ERBIT_RX | RX_ER_NORSQ):
175
- id = rb_intern("rx_er_norsq");
176
- break;
177
- case (ERBIT_RX | RX_ER_NOLCU):
178
- id = rb_intern("rx_er_nolcu");
179
- break;
180
- case (ERBIT_RX | RX_ER_NORCU):
181
- id = rb_intern("rx_er_norcu");
182
- break;
183
- case (ERBIT_RX | RX_ER_NOLPA):
184
- id = rb_intern("rx_er_nolpa");
185
- break;
186
- case (ERBIT_RX | RX_ER_NORPA):
187
- id = rb_intern("rx_er_norpa");
188
- break;
189
- case (ERBIT_RX | RX_ER_BADCL):
190
- id = rb_intern("rx_er_badcl");
191
- break;
192
- case (ERBIT_RX | RX_ER_NODGT):
193
- id = rb_intern("rx_er_nodgt");
194
- break;
195
- case (ERBIT_RX | RX_ER_DNUOB):
196
- id = rb_intern("rx_er_dnuob");
197
- break;
198
- case (ERBIT_RX | RX_ER_NOTRC):
199
- id = rb_intern("rx_er_notrc");
200
- break;
201
-
202
- case (ERBIT_XSD | XSD_ER_TYP):
203
- id = rb_intern("xsd_er_typ");
204
- break;
205
- case (ERBIT_XSD | XSD_ER_PAR):
206
- id = rb_intern("xsd_er_par");
207
- break;
208
- case (ERBIT_XSD | XSD_ER_PARVAL):
209
- id = rb_intern("xsd_er_parval");
210
- break;
211
- case (ERBIT_XSD | XSD_ER_VAL):
212
- id = rb_intern("xsd_er_val");
213
- break;
214
- case (ERBIT_XSD | XSD_ER_NPAT):
215
- id = rb_intern("xsd_er_npat");
216
- break;
217
- case (ERBIT_XSD | XSD_ER_WS):
218
- id = rb_intern("xsd_er_ws");
219
- break;
220
- case (ERBIT_XSD | XSD_ER_ENUM):
221
- id = rb_intern("xsd_er_enum");
222
- break;
223
-
224
- case (ERBIT_DRV | DRV_ER_NODTL):
225
- id = rb_intern("drv_er_nodtl");
226
- break;
227
-
228
- case (ERBIT_RNV | RNV_ER_ELEM):
229
- id = rb_intern("rnv_er_elem");
230
- break;
231
- case (ERBIT_RNV | RNV_ER_AKEY):
232
- id = rb_intern("rnv_er_akey");
233
- break;
234
- case (ERBIT_RNV | RNV_ER_AVAL):
235
- id = rb_intern("rnv_er_aval");
236
- break;
237
- case (ERBIT_RNV | RNV_ER_EMIS):
238
- id = rb_intern("rnv_er_emis");
239
- break;
240
- case (ERBIT_RNV | RNV_ER_AMIS):
241
- id = rb_intern("rnv_er_amis");
242
- break;
243
- case (ERBIT_RNV | RNV_ER_UFIN):
244
- id = rb_intern("rnv_er_ufin");
245
- break;
246
- case (ERBIT_RNV | RNV_ER_TEXT):
247
- id = rb_intern("rnv_er_text");
248
- break;
249
- case (ERBIT_RNV | RNV_ER_NOTX):
250
- id = rb_intern("rnv_er_notx");
251
- break;
252
-
253
- default:
254
- id = rb_intern("unknown");
255
- break;
256
- }
257
- return id;
258
- }
6
+ VALUE RNV, SchemaNotLoaded, Error, DataTypeLibrary, Document;
7
+
8
+ extern int ruby_verror_handler(void *data, int erno, char *format, va_list ap);
259
9
 
260
- int ruby_verror_handler(rnv_t *rnv, int erno, char *format, va_list ap)
10
+ VALUE rb_datatype_push_error(VALUE self, VALUE r_msg)
261
11
  {
262
- VALUE self = (VALUE)rnv->user_data;
263
12
  document_t *document;
13
+ VALUE r_doc = rb_iv_get(self, "@document");
14
+ Data_Get_Struct(r_doc, document_t, document);
264
15
 
265
- Data_Get_Struct(self, document_t, document);
266
-
267
- rnx_st_t *rnx_st = document->rnx_st;
268
-
269
- VALUE errors = rb_iv_get(self, "@errors");
270
-
271
- VALUE error_array = rb_ary_new2(2);
272
- VALUE error_str = rb_vsprintf(format, ap);
273
- VALUE error_erno = ID2SYM(errno_to_id(erno));
16
+ Check_Type(r_msg, T_STRING);
274
17
 
275
- // lazyly strip with ruby
276
- rb_funcall(error_str, rb_intern("strip!"), 0);
18
+ if(document->rnv->verror_handler)
19
+ document->rnv->verror_handler((void *)r_doc, ERBIT_DTL, RSTRING_PTR(r_msg), NULL);
277
20
 
278
- VALUE err_class = rb_const_get(RNV, rb_intern("Error"));
279
- VALUE err_obj = rb_class_new_instance(0, NULL, err_class);
280
- rb_iv_set(err_obj, "@document", self);
281
- rb_iv_set(err_obj, "@code", error_erno);
282
- rb_iv_set(err_obj, "@message", error_str);
283
- rb_iv_set(err_obj, "@line", rb_iv_get(self, "@last_line"));
284
- rb_iv_set(err_obj, "@col", rb_iv_get(self, "@last_col"));
285
-
286
- VALUE expected = rb_str_new2("");
287
- if (erno & ERBIT_RNV)
288
- {
289
- if (document->nexp)
290
- {
291
- int req = 2, i = 0;
292
- char *s;
293
- while (req--)
294
- {
295
- rnx_expected(rnv, rnx_st, document->previous, req);
296
- if (i == rnv->rnx_n_exp)
297
- continue;
298
- if (rnv->rnx_n_exp > document->nexp)
299
- break;
300
-
301
- expected = rb_str_cat2(expected, (char *)(req ? "required:\n" : "allowed:\n"));
302
-
303
- for (; i != rnv->rnx_n_exp; ++i)
304
- {
305
- s = rnx_p2str(rnv, rnv->rnx_exp[i]);
306
- expected = rb_str_cat2(expected, "\t");
307
- expected = rb_str_cat2(expected, s);
308
- expected = rb_str_cat2(expected, "\n");
309
- m_free(s);
310
- }
311
- }
312
- }
313
- }
314
-
315
- rb_iv_set(err_obj, "@expected", expected);
316
-
317
- rb_ary_push(errors, err_obj);
318
- }
319
-
320
- /*
321
- * @return [String]
322
- */
323
- VALUE rb_error_inspect(VALUE self)
324
- {
325
- VALUE code = rb_iv_get(self, "@code");
326
- VALUE message = rb_iv_get(self, "@message");
327
- VALUE expected = rb_iv_get(self, "@expected");
328
- VALUE line = rb_iv_get(self, "@line");
329
- VALUE col = rb_iv_get(self, "@col");
330
-
331
- VALUE ret = rb_str_new2("#<RNV::Error ");
332
- ret = rb_str_cat2(ret, "code: :");
333
- ret = rb_str_append(ret, rb_obj_as_string(code));
334
- ret = rb_str_cat2(ret, ", ");
335
- ret = rb_str_cat2(ret, "message: '");
336
- ret = rb_str_append(ret, message);
337
- ret = rb_str_cat2(ret, "', ");
338
- ret = rb_str_cat2(ret, "expected: '");
339
- ret = rb_str_append(ret, expected);
340
- ret = rb_str_cat2(ret, "', ");
341
- ret = rb_str_cat2(ret, "line: ");
342
- ret = rb_str_append(ret, rb_obj_as_string(line));
343
- ret = rb_str_cat2(ret, ", ");
344
- ret = rb_str_cat2(ret, "col: ");
345
- ret = rb_str_append(ret, rb_obj_as_string(col));
346
- ret = rb_str_cat2(ret, ">");
347
- return ret;
21
+ return Qnil;
348
22
  }
349
23
 
350
- /*
351
- * @return [String]
352
- */
353
- VALUE rb_error_to_s(VALUE self)
24
+ void document_free(document_t *document)
354
25
  {
355
- VALUE message = rb_iv_get(self, "@message");
356
- VALUE expected = rb_iv_get(self, "@expected");
357
- VALUE line = rb_iv_get(self, "@line");
358
- VALUE col = rb_iv_get(self, "@col");
26
+ rnd_dispose(document->rnd_st);
27
+ rx_dispose(document->rx_st);
28
+ drv_dispose(document->drv_st);
359
29
 
360
- VALUE ret = rb_str_new2("");
30
+ rnc_dispose(document->rnc_st);
361
31
 
362
- ret = rb_str_append(ret, rb_obj_as_string(line));
363
- ret = rb_str_cat2(ret, ":");
364
- ret = rb_str_append(ret, rb_obj_as_string(col));
32
+ rn_dispose(document->rn_st);
365
33
 
366
- ret = rb_str_cat2(ret, ": error: ");
34
+ rnv_dispose(document->rnv);
367
35
 
368
- ret = rb_str_append(ret, message);
369
- ret = rb_str_cat2(ret, "\n");
370
- ret = rb_str_append(ret, expected);
371
-
372
- return ret;
373
- }
374
-
375
- void document_free(document_t *document)
376
- {
377
- // FIXME : introduce *_delete functions
378
- if (document->rnd_st->flat)
379
- free(document->rnd_st->flat);
380
- free(document->rnd_st);
381
-
382
- ht_dispose(&document->rx_st->ht_r);
383
- ht_dispose(&document->rx_st->ht_p);
384
- ht_dispose(&document->rx_st->ht_2);
385
- ht_dispose(&document->rx_st->ht_m);
386
- if (document->rx_st->regex)
387
- free(document->rx_st->regex);
388
- if (document->rx_st->pattern)
389
- free(document->rx_st->pattern);
390
- free(document->rx_st);
391
-
392
- if (document->drv_st->dtl)
393
- free(document->drv_st->dtl);
394
- ht_dispose(&document->drv_st->ht_m);
395
- free(document->drv_st);
396
-
397
- free(document->rnx_st);
398
-
399
- if (document->rnc_st->path)
400
- free(document->rnc_st->path);
401
- free(document->rnc_st);
402
-
403
- ht_dispose(&document->rn_st->ht_p);
404
- ht_dispose(&document->rn_st->ht_nc);
405
- ht_dispose(&document->rn_st->ht_s);
406
-
407
- free(document->rn_st);
408
-
409
- if (document->rnv->rn_pattern)
410
- free(document->rnv->rn_pattern);
411
- if (document->rnv->rn_nameclass)
412
- free(document->rnv->rn_nameclass);
413
- if (document->rnv->rn_string)
414
- free(document->rnv->rn_string);
415
- if (document->rnv->rnx_exp)
416
- free(document->rnv->rnx_exp);
417
-
418
- free(document->rnv);
419
-
420
- free(document->text);
36
+ if (document->text)
37
+ free(document->text);
421
38
 
422
39
  ruby_xfree(document);
423
40
  }
@@ -426,13 +43,12 @@ VALUE rb_document_alloc(VALUE klass)
426
43
  {
427
44
  document_t *document = ruby_xmalloc(sizeof(document_t));
428
45
 
429
- document->rnv = malloc(sizeof(rnv_t));
430
- document->rn_st = malloc(sizeof(rn_st_t));
431
- document->rnc_st = malloc(sizeof(rnc_st_t));
432
- document->rnx_st = malloc(sizeof(rnx_st_t));
433
- document->drv_st = malloc(sizeof(drv_st_t));
434
- document->rx_st = malloc(sizeof(rx_st_t));
435
- document->rnd_st = malloc(sizeof(rnd_st_t));
46
+ document->rnv = calloc(1, sizeof(rnv_t));
47
+ document->rn_st = calloc(1, sizeof(rn_st_t));
48
+ document->rnc_st = calloc(1, sizeof(rnc_st_t));
49
+ document->drv_st = calloc(1, sizeof(drv_st_t));
50
+ document->rx_st = calloc(1, sizeof(rx_st_t));
51
+ document->rnd_st = calloc(1, sizeof(rnd_st_t));
436
52
 
437
53
  return Data_Wrap_Struct(klass, NULL, document_free, document);
438
54
  }
@@ -442,17 +58,31 @@ VALUE rb_document_init(VALUE self)
442
58
  document_t *document;
443
59
  Data_Get_Struct(self, document_t, document);
444
60
 
445
- rnl_init(document->rnv, document->rn_st, document->rnc_st, document->rnd_st);
61
+ document->rnv->verror_handler = &ruby_verror_handler;
62
+ document->rnv->user_data = (void *)self;
63
+
64
+ rnl_init(document->rnv, document->rnc_st, document->rn_st, document->rnd_st);
446
65
  rnv_init(document->rnv, document->drv_st, document->rn_st, document->rx_st);
447
- rnx_init(document->rnv, document->rnx_st);
66
+ rnx_init(document->rnv);
448
67
 
449
68
  document->opened = document->ok = 0;
450
- document->rnv->user_data = (void *)self;
451
- document->rnv->verror_handler = &ruby_verror_handler;
69
+
452
70
  document->nexp = 16; /* maximum number of candidates to display */
71
+ document->text = NULL;
453
72
 
454
73
  rb_iv_set(self, "@errors", rb_ary_new2(0));
455
74
 
75
+ rb_iv_set(self, "@libraries", rb_hash_new());
76
+
77
+ document->last_line = -1;
78
+ document->last_col = -1;
79
+
80
+ rb_iv_set(self, "@last_line", INT2NUM(-1));
81
+ rb_iv_set(self, "@last_col", INT2NUM(-1));
82
+
83
+ //document->rx_st->rx_compact = 1;
84
+ //document->drv_st->drv_compact = 1;
85
+
456
86
  return self;
457
87
  }
458
88
 
@@ -470,7 +100,7 @@ static void document_load(document_t *document)
470
100
  /*
471
101
  * load schema from a buffer
472
102
  * @param [String] r_str buffer
473
- * @return [String]
103
+ * @return [Boolean]
474
104
  */
475
105
  VALUE rb_document_load_string(VALUE self, VALUE r_str)
476
106
  {
@@ -489,40 +119,42 @@ VALUE rb_document_load_string(VALUE self, VALUE r_str)
489
119
  document->fn,
490
120
  RSTRING_PTR(r_str), RSTRING_LEN(r_str));
491
121
 
492
- document_load(document);
493
- return INT2NUM(document->ok);
122
+ if (document->opened)
123
+ {
124
+ document_load(document);
125
+ return Qtrue;
126
+ }
127
+ else
128
+ return Qfalse;
494
129
  }
495
130
 
496
131
  /*
497
132
  * load schema from a file
498
133
  * @param [String] r_fn filename
499
- * @return [String]
134
+ * @return [Boolean]
500
135
  */
501
136
  VALUE rb_document_load_file(VALUE self, VALUE r_fn)
502
137
  {
503
138
  document_t *document;
504
139
  Data_Get_Struct(self, document_t, document);
505
140
 
506
- switch (TYPE(r_fn))
141
+ Check_Type(r_fn, T_STRING);
142
+
143
+ document->fn = RSTRING_PTR(r_fn);
144
+
145
+ document->opened = rnl_fn(document->rnv,
146
+ document->rnc_st,
147
+ document->rn_st,
148
+ document->rnd_st,
149
+ document->fn);
150
+
151
+ if (document->opened)
507
152
  {
508
- case T_STRING:
509
- document->fn = RSTRING_PTR(r_fn);
510
-
511
- document->opened = rnl_fn(document->rnv,
512
- document->rnc_st,
513
- document->rn_st,
514
- document->rnd_st,
515
- document->fn);
516
-
517
- break;
518
- case T_FILE: // TODO
519
- default:
520
- rb_raise(rb_eTypeError, "invalid argument");
521
- break;
153
+ document_load(document);
154
+ return Qtrue;
522
155
  }
523
-
524
- document_load(document);
525
- return INT2NUM(document->ok);
156
+ else
157
+ return Qfalse;
526
158
  }
527
159
 
528
160
  /*
@@ -540,6 +172,63 @@ VALUE rb_document_valid(VALUE self)
540
172
  return Qfalse;
541
173
  }
542
174
 
175
+ static int rb_dtl_equal(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, int uri, char *typ, char *val, char *s, int n)
176
+ {
177
+ VALUE self = (VALUE)rnv->user_data;
178
+ VALUE libraries = rb_iv_get(self, "@libraries");
179
+ VALUE lib = rb_hash_aref(libraries, INT2FIX(uri));
180
+
181
+ // do we need n here, do s always null terminated ?
182
+ VALUE ret = rb_funcall(lib, rb_intern("equal"), 3,
183
+ rb_str_new2(typ), rb_str_new2(val), rb_str_new2(s));
184
+
185
+ return RTEST(ret);
186
+ }
187
+
188
+ static int rb_dtl_allows(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, int uri, char *typ, char *ps, char *s, int n)
189
+ {
190
+ VALUE self = (VALUE)rnv->user_data;
191
+ VALUE libraries = rb_iv_get(self, "@libraries");
192
+ VALUE lib = rb_hash_aref(libraries, INT2FIX(uri));
193
+
194
+ // do we need n here, do s always null terminated ?
195
+ VALUE ret = rb_funcall(lib, rb_intern("allows"), 3,
196
+ rb_str_new2(typ), rb_str_new2(ps), rb_str_new2(s));
197
+
198
+ return RTEST(ret);
199
+ }
200
+
201
+ /*
202
+ * add a new datatype library
203
+ * @see https://www.oasis-open.org/committees/relax-ng/spec-20010811.html#IDA1I1R
204
+ * @param [String] r_ns unique ns URL for this datatype
205
+ * @param [RNV::DataTypeLibrary] r_cb_obj
206
+ * @return [nil]
207
+ */
208
+ VALUE rb_document_add_dtl(VALUE self, VALUE r_ns, VALUE r_cb_obj)
209
+ {
210
+ document_t *document;
211
+ Data_Get_Struct(self, document_t, document);
212
+
213
+ if (document->opened)
214
+ {
215
+ Check_Type(r_ns, T_STRING);
216
+
217
+ char *suri = RSTRING_PTR(r_ns);
218
+
219
+ drv_add_dtl(document->rnv, document->drv_st, document->rn_st, suri, &rb_dtl_equal, &rb_dtl_allows);
220
+
221
+ int uri = document->drv_st->dtl[document->drv_st->n_dtl - 1].uri;
222
+
223
+ VALUE libraries = rb_iv_get(self, "@libraries");
224
+
225
+ rb_iv_set(r_cb_obj, "@document", self);
226
+
227
+ rb_hash_aset(libraries, INT2FIX(uri), r_cb_obj);
228
+ }
229
+ return Qnil;
230
+ }
231
+
543
232
  static void flush_text(document_t *document)
544
233
  {
545
234
  document->ok = rnv_text(document->rnv, document->drv_st, document->rn_st, document->rx_st,
@@ -549,7 +238,7 @@ static void flush_text(document_t *document)
549
238
  }
550
239
 
551
240
  /*
552
- * begin a new document
241
+ * begin parsing a new document
553
242
  * @return [nil]
554
243
  */
555
244
  VALUE rb_document_begin(VALUE self)
@@ -557,11 +246,22 @@ VALUE rb_document_begin(VALUE self)
557
246
  document_t *document;
558
247
  Data_Get_Struct(self, document_t, document);
559
248
 
249
+ if (!document->opened)
250
+ rb_raise(SchemaNotLoaded, "schema was not loaded correctly");
251
+
252
+ // reset errors
253
+ rb_iv_set(self, "@errors", rb_ary_new2(0));
254
+
560
255
  m_free(document->text);
561
256
  document->text = (char *)m_alloc(document->len_txt = LEN_T, sizeof(char));
562
257
 
563
258
  document->ok = document->current = document->previous = document->start;
564
259
 
260
+ document->last_line = 0;
261
+ document->last_col = 0;
262
+
263
+ document->level = 0;
264
+
565
265
  document->text[0] = '\0';
566
266
  document->n_txt = 0;
567
267
  document->mixed = 0;
@@ -572,14 +272,17 @@ VALUE rb_document_begin(VALUE self)
572
272
  /*
573
273
  * to be called by SAX characters handler
574
274
  * @param [String] r_str characters
575
- * @return [Integer]
275
+ * @return [Boolean]
576
276
  */
577
277
  VALUE rb_document_characters(VALUE self, VALUE r_str)
578
278
  {
579
279
  document_t *document;
580
280
  Data_Get_Struct(self, document_t, document);
581
281
 
582
- if (document->opened && document->current != document->rnv->rn_notAllowed)
282
+ if (!document->opened)
283
+ rb_raise(SchemaNotLoaded, "schema was not loaded correctly");
284
+
285
+ if (document->current != document->rnv->rn_notAllowed)
583
286
  {
584
287
  Check_Type(r_str, T_STRING);
585
288
  char *s = RSTRING_PTR(r_str);
@@ -600,21 +303,24 @@ VALUE rb_document_characters(VALUE self, VALUE r_str)
600
303
  document->text[document->n_txt] = '\0'; /* '\0' guarantees that the text is bounded, and strto[ld] work for data */
601
304
  }
602
305
 
603
- return INT2NUM(document->ok);
306
+ return RTEST(document->ok);
604
307
  }
605
308
 
606
309
  /*
607
310
  * to be called by SAX start tag handler
608
311
  * @param [String] r_name tag name, must be in the form 'NS_URI:TAG_NAME'
609
- * @param [Array<String>] r_attrs flattened array of tag attributes in the form ['NS_URI:ATTR_NAME','ATTR_VALUE']
610
- * @return [Integer]
312
+ * @param [Array<Array<String>>] r_attrs flattened array of tag attributes in the form [['NS_URI:ATTR_NAME','ATTR_VALUE']]
313
+ * @return [Boolean]
611
314
  */
612
315
  VALUE rb_document_start_tag(VALUE self, VALUE r_name, VALUE r_attrs)
613
316
  {
614
317
  document_t *document;
615
318
  Data_Get_Struct(self, document_t, document);
616
319
 
617
- if (document->opened && document->current != document->rnv->rn_notAllowed)
320
+ if (!document->opened)
321
+ rb_raise(SchemaNotLoaded, "schema was not loaded correctly");
322
+
323
+ if (document->current != document->rnv->rn_notAllowed)
618
324
  {
619
325
  int i;
620
326
  char *name;
@@ -624,20 +330,22 @@ VALUE rb_document_start_tag(VALUE self, VALUE r_name, VALUE r_attrs)
624
330
  name = RSTRING_PTR(r_name);
625
331
 
626
332
  Check_Type(r_attrs, T_ARRAY);
627
- unsigned int attrs_len = RARRAY_LEN(r_attrs);
333
+
334
+ // lazyly flatten with ruby
335
+ VALUE r_flat_attrs = rb_funcall(r_attrs, rb_intern("flatten"), 0);
336
+ unsigned int attrs_len = RARRAY_LEN(r_flat_attrs);
628
337
 
629
338
  attrs = malloc(sizeof(char *) * (attrs_len + 1));
630
339
 
631
340
  for (i = 0; i < attrs_len; i++)
632
341
  {
633
- attrs[i] = RSTRING_PTR(rb_ary_entry(r_attrs, i));
342
+ attrs[i] = RSTRING_PTR(rb_ary_entry(r_flat_attrs, i));
634
343
  }
635
344
  attrs[attrs_len] = 0; // zero terminated
636
345
 
637
346
  document->mixed = 1;
638
347
 
639
348
  flush_text(document);
640
- //printf("RNV START %d/%d %s %d\n", current, previous, name, attrs_len);
641
349
  document->ok = rnv_start_tag(document->rnv, document->drv_st, document->rn_st, document->rx_st,
642
350
  &document->current, &document->previous, (char *)name, (char **)attrs) &&
643
351
  document->ok;
@@ -645,21 +353,28 @@ VALUE rb_document_start_tag(VALUE self, VALUE r_name, VALUE r_attrs)
645
353
  document->mixed = 0;
646
354
  free(attrs);
647
355
  }
356
+ else
357
+ {
358
+ ++document->level;
359
+ }
648
360
 
649
- return INT2NUM(document->ok);
361
+ return RTEST(document->ok);
650
362
  }
651
363
 
652
364
  /*
653
365
  * to be called by SAX end tag handler
654
366
  * @param [String] r_name tag name, must be in the form 'NS_URI:TAG_NAME'
655
- * @return [Integer]
367
+ * @return [Boolean]
656
368
  */
657
369
  VALUE rb_document_end_tag(VALUE self, VALUE r_name)
658
370
  {
659
371
  document_t *document;
660
372
  Data_Get_Struct(self, document_t, document);
661
373
 
662
- if (document->opened && document->current != document->rnv->rn_notAllowed)
374
+ if (!document->opened)
375
+ rb_raise(SchemaNotLoaded, "schema was not loaded correctly");
376
+
377
+ if (document->current != document->rnv->rn_notAllowed)
663
378
  {
664
379
  char *name;
665
380
 
@@ -668,15 +383,21 @@ VALUE rb_document_end_tag(VALUE self, VALUE r_name)
668
383
 
669
384
  flush_text(document);
670
385
 
671
- //printf("RNV END %d/%d %s\n", current, previous, name);
672
386
  document->ok = rnv_end_tag(document->rnv, document->drv_st, document->rn_st,
673
387
  &document->current, &document->previous, (char *)name) &&
674
388
  document->ok;
675
389
 
676
390
  document->mixed = 1;
677
391
  }
392
+ else
393
+ {
394
+ if (document->level == 0)
395
+ document->current = document->previous;
396
+ else
397
+ --document->level;
398
+ }
678
399
 
679
- return INT2NUM(document->ok);
400
+ return RTEST(document->ok);
680
401
  }
681
402
 
682
403
  // The initialization method for this module
@@ -684,21 +405,15 @@ void Init_rnv()
684
405
  {
685
406
  RNV = rb_define_module("RNV");
686
407
 
687
- VALUE Error = rb_define_class_under(RNV, "Error", rb_cObject);
408
+ SchemaNotLoaded = rb_define_class_under(RNV, "SchemaNotLoaded", rb_eStandardError);
688
409
 
689
- rb_define_method(Error, "inspect", rb_error_inspect, 0);
690
- rb_define_method(Error, "to_s", rb_error_to_s, 0);
410
+ Error = rb_define_class_under(RNV, "Error", rb_cObject);
691
411
 
692
412
  /*
693
413
  * error symbol code
694
414
  * @return [Symbol]
695
415
  */
696
416
  rb_define_attr(Error, "code", 1, 0);
697
- /*
698
- * error message
699
- * @return [String]
700
- */
701
- rb_define_attr(Error, "message", 1, 0);
702
417
  /*
703
418
  * error line
704
419
  * @return [Integer]
@@ -710,7 +425,17 @@ void Init_rnv()
710
425
  */
711
426
  rb_define_attr(Error, "col", 1, 0);
712
427
 
713
- VALUE Document = rb_define_class_under(RNV, "Document", rb_cObject);
428
+ DataTypeLibrary = rb_define_class_under(RNV, "DataTypeLibrary", rb_cObject);
429
+
430
+ /*
431
+ * document in which library is registered
432
+ * @return [RNV::Document]
433
+ */
434
+ rb_define_attr(DataTypeLibrary, "document", 1, 0);
435
+
436
+ rb_define_method(DataTypeLibrary, "push_error", rb_datatype_push_error, 1);
437
+
438
+ Document = rb_define_class_under(RNV, "Document", rb_cObject);
714
439
 
715
440
  rb_define_alloc_func(Document, rb_document_alloc);
716
441
  rb_define_method(Document, "initialize", rb_document_init, 0);
@@ -719,6 +444,8 @@ void Init_rnv()
719
444
  rb_define_method(Document, "load_string", rb_document_load_string, 1);
720
445
  rb_define_method(Document, "valid?", rb_document_valid, 0);
721
446
 
447
+ rb_define_method(Document, "add_datatype_library", rb_document_add_dtl, 2);
448
+
722
449
  rb_define_method(Document, "start_document", rb_document_begin, 0);
723
450
  rb_define_method(Document, "start_tag", rb_document_start_tag, 2);
724
451
  rb_define_method(Document, "characters", rb_document_characters, 1);