ruby_rnv 0.2.4 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a97a5b35a39aa2ad603660b81b9c13e04375dafbc9f537fec0720357befd53f8
4
- data.tar.gz: 54dff4be913ec5e3e356cb43c5d58a936aa6aa76f38212212a19f3057875f22c
3
+ metadata.gz: 899300861f1a2b315f879d451a7a5ee472302fbdac26ea775a2e56e09793d98c
4
+ data.tar.gz: 4f2139ddde96c34a077e124600bb7cbbb0e98ef5db5fe5c57066bdcc8fd4c089
5
5
  SHA512:
6
- metadata.gz: bacdd196d95d59883413268ab7dc70d68bd39d4d93876ca156687aceabd7d76cd917a09dbeea4537a3f3c96cbc883bd6f7cd35bf152ac0c421e6e9183f14c2a9
7
- data.tar.gz: c43c097908014a8dc61fedab76ab407012077ec471fdc256aeca28d8261e3c90a4678f50a7b4308aa66efd96c008e1eb2e86f6fafe3ef1418b433b0da74a146c
6
+ metadata.gz: c9660b568d0a4fe092080bb095fd80125540ece28c669ecae73faa9391567a337fcd8799702b29bdcecd022b9613f76c3d9e6013f3c289000a5a98950bd67860
7
+ data.tar.gz: 63924d0755a95489733c62ccde564260750dcfea5e0a366e26d6663178b00e47d6ee095f18b8cee293c7c4eba457746a86cb9eedb696c7e63321449cbbf89536
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");
16
+ Check_Type(r_msg, T_STRING);
270
17
 
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));
18
+ if(document->rnv->verror_handler)
19
+ document->rnv->verror_handler((void *)r_doc, ERBIT_DTL, RSTRING_PTR(r_msg), NULL);
274
20
 
275
- // lazyly strip with ruby
276
- rb_funcall(error_str, rb_intern("strip!"), 0);
277
-
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
 
@@ -542,6 +172,63 @@ VALUE rb_document_valid(VALUE self)
542
172
  return Qfalse;
543
173
  }
544
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
+
545
232
  static void flush_text(document_t *document)
546
233
  {
547
234
  document->ok = rnv_text(document->rnv, document->drv_st, document->rn_st, document->rx_st,
@@ -551,7 +238,7 @@ static void flush_text(document_t *document)
551
238
  }
552
239
 
553
240
  /*
554
- * begin a new document
241
+ * begin parsing a new document
555
242
  * @return [nil]
556
243
  */
557
244
  VALUE rb_document_begin(VALUE self)
@@ -559,11 +246,22 @@ VALUE rb_document_begin(VALUE self)
559
246
  document_t *document;
560
247
  Data_Get_Struct(self, document_t, document);
561
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
+
562
255
  m_free(document->text);
563
256
  document->text = (char *)m_alloc(document->len_txt = LEN_T, sizeof(char));
564
257
 
565
258
  document->ok = document->current = document->previous = document->start;
566
259
 
260
+ document->last_line = 0;
261
+ document->last_col = 0;
262
+
263
+ document->level = 0;
264
+
567
265
  document->text[0] = '\0';
568
266
  document->n_txt = 0;
569
267
  document->mixed = 0;
@@ -574,14 +272,17 @@ VALUE rb_document_begin(VALUE self)
574
272
  /*
575
273
  * to be called by SAX characters handler
576
274
  * @param [String] r_str characters
577
- * @return [Integer]
275
+ * @return [Boolean]
578
276
  */
579
277
  VALUE rb_document_characters(VALUE self, VALUE r_str)
580
278
  {
581
279
  document_t *document;
582
280
  Data_Get_Struct(self, document_t, document);
583
281
 
584
- 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)
585
286
  {
586
287
  Check_Type(r_str, T_STRING);
587
288
  char *s = RSTRING_PTR(r_str);
@@ -602,21 +303,24 @@ VALUE rb_document_characters(VALUE self, VALUE r_str)
602
303
  document->text[document->n_txt] = '\0'; /* '\0' guarantees that the text is bounded, and strto[ld] work for data */
603
304
  }
604
305
 
605
- return INT2NUM(document->ok);
306
+ return RTEST(document->ok);
606
307
  }
607
308
 
608
309
  /*
609
310
  * to be called by SAX start tag handler
610
311
  * @param [String] r_name tag name, must be in the form 'NS_URI:TAG_NAME'
611
- * @param [Array<String>] r_attrs flattened array of tag attributes in the form ['NS_URI:ATTR_NAME','ATTR_VALUE']
612
- * @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]
613
314
  */
614
315
  VALUE rb_document_start_tag(VALUE self, VALUE r_name, VALUE r_attrs)
615
316
  {
616
317
  document_t *document;
617
318
  Data_Get_Struct(self, document_t, document);
618
319
 
619
- 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)
620
324
  {
621
325
  int i;
622
326
  char *name;
@@ -626,20 +330,22 @@ VALUE rb_document_start_tag(VALUE self, VALUE r_name, VALUE r_attrs)
626
330
  name = RSTRING_PTR(r_name);
627
331
 
628
332
  Check_Type(r_attrs, T_ARRAY);
629
- 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);
630
337
 
631
338
  attrs = malloc(sizeof(char *) * (attrs_len + 1));
632
339
 
633
340
  for (i = 0; i < attrs_len; i++)
634
341
  {
635
- attrs[i] = RSTRING_PTR(rb_ary_entry(r_attrs, i));
342
+ attrs[i] = RSTRING_PTR(rb_ary_entry(r_flat_attrs, i));
636
343
  }
637
344
  attrs[attrs_len] = 0; // zero terminated
638
345
 
639
346
  document->mixed = 1;
640
347
 
641
348
  flush_text(document);
642
- //printf("RNV START %d/%d %s %d\n", current, previous, name, attrs_len);
643
349
  document->ok = rnv_start_tag(document->rnv, document->drv_st, document->rn_st, document->rx_st,
644
350
  &document->current, &document->previous, (char *)name, (char **)attrs) &&
645
351
  document->ok;
@@ -647,21 +353,28 @@ VALUE rb_document_start_tag(VALUE self, VALUE r_name, VALUE r_attrs)
647
353
  document->mixed = 0;
648
354
  free(attrs);
649
355
  }
356
+ else
357
+ {
358
+ ++document->level;
359
+ }
650
360
 
651
- return INT2NUM(document->ok);
361
+ return RTEST(document->ok);
652
362
  }
653
363
 
654
364
  /*
655
365
  * to be called by SAX end tag handler
656
366
  * @param [String] r_name tag name, must be in the form 'NS_URI:TAG_NAME'
657
- * @return [Integer]
367
+ * @return [Boolean]
658
368
  */
659
369
  VALUE rb_document_end_tag(VALUE self, VALUE r_name)
660
370
  {
661
371
  document_t *document;
662
372
  Data_Get_Struct(self, document_t, document);
663
373
 
664
- 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)
665
378
  {
666
379
  char *name;
667
380
 
@@ -670,15 +383,21 @@ VALUE rb_document_end_tag(VALUE self, VALUE r_name)
670
383
 
671
384
  flush_text(document);
672
385
 
673
- //printf("RNV END %d/%d %s\n", current, previous, name);
674
386
  document->ok = rnv_end_tag(document->rnv, document->drv_st, document->rn_st,
675
387
  &document->current, &document->previous, (char *)name) &&
676
388
  document->ok;
677
389
 
678
390
  document->mixed = 1;
679
391
  }
392
+ else
393
+ {
394
+ if (document->level == 0)
395
+ document->current = document->previous;
396
+ else
397
+ --document->level;
398
+ }
680
399
 
681
- return INT2NUM(document->ok);
400
+ return RTEST(document->ok);
682
401
  }
683
402
 
684
403
  // The initialization method for this module
@@ -686,21 +405,15 @@ void Init_rnv()
686
405
  {
687
406
  RNV = rb_define_module("RNV");
688
407
 
689
- VALUE Error = rb_define_class_under(RNV, "Error", rb_cObject);
408
+ SchemaNotLoaded = rb_define_class_under(RNV, "SchemaNotLoaded", rb_eStandardError);
690
409
 
691
- rb_define_method(Error, "inspect", rb_error_inspect, 0);
692
- rb_define_method(Error, "to_s", rb_error_to_s, 0);
410
+ Error = rb_define_class_under(RNV, "Error", rb_cObject);
693
411
 
694
412
  /*
695
413
  * error symbol code
696
414
  * @return [Symbol]
697
415
  */
698
416
  rb_define_attr(Error, "code", 1, 0);
699
- /*
700
- * error message
701
- * @return [String]
702
- */
703
- rb_define_attr(Error, "message", 1, 0);
704
417
  /*
705
418
  * error line
706
419
  * @return [Integer]
@@ -712,7 +425,17 @@ void Init_rnv()
712
425
  */
713
426
  rb_define_attr(Error, "col", 1, 0);
714
427
 
715
- 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);
716
439
 
717
440
  rb_define_alloc_func(Document, rb_document_alloc);
718
441
  rb_define_method(Document, "initialize", rb_document_init, 0);
@@ -721,6 +444,8 @@ void Init_rnv()
721
444
  rb_define_method(Document, "load_string", rb_document_load_string, 1);
722
445
  rb_define_method(Document, "valid?", rb_document_valid, 0);
723
446
 
447
+ rb_define_method(Document, "add_datatype_library", rb_document_add_dtl, 2);
448
+
724
449
  rb_define_method(Document, "start_document", rb_document_begin, 0);
725
450
  rb_define_method(Document, "start_tag", rb_document_start_tag, 2);
726
451
  rb_define_method(Document, "characters", rb_document_characters, 1);