ruby_rnv 0.3.0 → 0.5.0

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: 076d290b71d2baddf3f6655f99471138ba7a348ce04ac509f246a92c007d2c27
4
- data.tar.gz: '014108a35aacd5f4c78804ef9740f40e314b9f28968f038f0746375acc259fff'
3
+ metadata.gz: a6b0736317b7df5919818cfeee87155c51ec58018c4462ebf1909a587dc7315c
4
+ data.tar.gz: 0cadcded8c1682eb0efad0d14dafb3a1643fecafae41d3637f3a77c8cfa05ae3
5
5
  SHA512:
6
- metadata.gz: 4e79a6d9727dbf1736df5b972acc8fb609b996ed224cf7346e42269af7777a07be42dad27ce11ae7db2d151be1a5c27d39169301289537d45ec12303aab129e7
7
- data.tar.gz: a52f9058d874dd8083a892e0aff3ca55f68bae0bbc6f34446b31bf1922ee0d74e14693ab4d2ef6bb2cf270a1f384cf0b9f32fc1dbe764dbb6e4d2bd936ca7b0d
6
+ metadata.gz: 7af568949b3eac5192f3bda69315b493fc0bf4509376b6930bedc0ab59768fe13ab01258cbec95dd922145c074f514d0e94517706f519abc1559538893729561
7
+ data.tar.gz: 50ca7148720191a98ed9428f12421cfc50323c7162bf84f43aa92713c7a3526fba2cb16c5d86d7fb7ccc7fbb4836afa9ab69cf64843711206bb7df9442dd37b5
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,366 +1,37 @@
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, SchemaNotLoaded, Error, Document;
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;
259
7
 
260
- int ruby_verror_handler(rnv_t *rnv, int erno, char *format, va_list ap)
8
+ extern int ruby_verror_handler(void *data, int erno, char *format, va_list ap);
9
+
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));
274
-
275
- // lazyly strip with ruby
276
- rb_funcall(error_str, rb_intern("strip!"), 0);
277
-
278
- VALUE err_class = 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
- }
16
+ Check_Type(r_msg, T_STRING);
314
17
 
315
- rb_iv_set(err_obj, "@expected", expected);
18
+ if(document->rnv->verror_handler)
19
+ document->rnv->verror_handler((void *)r_doc, ERBIT_DTL, RSTRING_PTR(r_msg), NULL);
316
20
 
317
- rb_ary_push(errors, err_obj);
21
+ return Qnil;
318
22
  }
319
23
 
320
24
  void document_free(document_t *document)
321
25
  {
322
- // FIXME : introduce *_delete functions
323
- if (document->rnd_st->flat)
324
- free(document->rnd_st->flat);
325
- free(document->rnd_st);
326
-
327
- ht_dispose(&document->rx_st->ht_r);
328
- ht_dispose(&document->rx_st->ht_p);
329
- ht_dispose(&document->rx_st->ht_2);
330
- ht_dispose(&document->rx_st->ht_m);
331
- if (document->rx_st->regex)
332
- free(document->rx_st->regex);
333
- if (document->rx_st->pattern)
334
- free(document->rx_st->pattern);
335
- free(document->rx_st);
336
-
337
- if (document->drv_st->dtl)
338
- free(document->drv_st->dtl);
339
- ht_dispose(&document->drv_st->ht_m);
340
- free(document->drv_st);
341
-
342
- free(document->rnx_st);
343
-
344
- if (document->rnc_st->path)
345
- free(document->rnc_st->path);
346
- free(document->rnc_st);
347
-
348
- ht_dispose(&document->rn_st->ht_p);
349
- ht_dispose(&document->rn_st->ht_nc);
350
- ht_dispose(&document->rn_st->ht_s);
351
-
352
- free(document->rn_st);
353
-
354
- if (document->rnv->rn_pattern)
355
- free(document->rnv->rn_pattern);
356
- if (document->rnv->rn_nameclass)
357
- free(document->rnv->rn_nameclass);
358
- if (document->rnv->rn_string)
359
- free(document->rnv->rn_string);
360
- if (document->rnv->rnx_exp)
361
- free(document->rnv->rnx_exp);
362
-
363
- free(document->rnv);
26
+ rnd_dispose(document->rnd_st);
27
+ rx_dispose(document->rx_st);
28
+ drv_dispose(document->drv_st);
29
+
30
+ rnc_dispose(document->rnc_st);
31
+
32
+ rn_dispose(document->rn_st);
33
+
34
+ rnv_dispose(document->rnv);
364
35
 
365
36
  if (document->text)
366
37
  free(document->text);
@@ -372,13 +43,12 @@ VALUE rb_document_alloc(VALUE klass)
372
43
  {
373
44
  document_t *document = ruby_xmalloc(sizeof(document_t));
374
45
 
375
- document->rnv = malloc(sizeof(rnv_t));
376
- document->rn_st = malloc(sizeof(rn_st_t));
377
- document->rnc_st = malloc(sizeof(rnc_st_t));
378
- document->rnx_st = malloc(sizeof(rnx_st_t));
379
- document->drv_st = malloc(sizeof(drv_st_t));
380
- document->rx_st = malloc(sizeof(rx_st_t));
381
- 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));
382
52
 
383
53
  return Data_Wrap_Struct(klass, NULL, document_free, document);
384
54
  }
@@ -388,20 +58,31 @@ VALUE rb_document_init(VALUE self)
388
58
  document_t *document;
389
59
  Data_Get_Struct(self, document_t, document);
390
60
 
391
- 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);
392
65
  rnv_init(document->rnv, document->drv_st, document->rn_st, document->rx_st);
393
- rnx_init(document->rnv, document->rnx_st);
66
+ rnx_init(document->rnv);
394
67
 
395
68
  document->opened = document->ok = 0;
396
- document->rnv->user_data = (void *)self;
397
- document->rnv->verror_handler = &ruby_verror_handler;
398
- document->nexp = 16; /* maximum number of candidates to display */
69
+
70
+ document->nexp = 256; /* maximum number of candidates to display */
399
71
  document->text = NULL;
400
72
 
401
73
  rb_iv_set(self, "@errors", rb_ary_new2(0));
402
74
 
403
75
  rb_iv_set(self, "@libraries", rb_hash_new());
404
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
+
405
86
  return self;
406
87
  }
407
88
 
@@ -491,22 +172,15 @@ VALUE rb_document_valid(VALUE self)
491
172
  return Qfalse;
492
173
  }
493
174
 
494
- static void flush_text(document_t *document)
495
- {
496
- document->ok = rnv_text(document->rnv, document->drv_st, document->rn_st, document->rx_st,
497
- &document->current, &document->previous, document->text, document->n_txt, document->mixed) &&
498
- document->ok;
499
- document->text[document->n_txt = 0] = '\0';
500
- }
501
-
502
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)
503
176
  {
504
177
  VALUE self = (VALUE)rnv->user_data;
505
178
  VALUE libraries = rb_iv_get(self, "@libraries");
506
179
  VALUE lib = rb_hash_aref(libraries, INT2FIX(uri));
507
180
 
508
- VALUE ret = rb_funcall(lib, rb_intern("equal"), 4,
509
- rb_str_new2(typ), rb_str_new2(val), rb_str_new2(s), INT2FIX(n));
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));
510
184
 
511
185
  return RTEST(ret);
512
186
  }
@@ -517,8 +191,9 @@ static int rb_dtl_allows(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, int uri, ch
517
191
  VALUE libraries = rb_iv_get(self, "@libraries");
518
192
  VALUE lib = rb_hash_aref(libraries, INT2FIX(uri));
519
193
 
520
- VALUE ret = rb_funcall(lib, rb_intern("allows"), 4,
521
- rb_str_new2(typ), rb_str_new2(ps), rb_str_new2(s), INT2FIX(n));
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));
522
197
 
523
198
  return RTEST(ret);
524
199
  }
@@ -547,11 +222,21 @@ VALUE rb_document_add_dtl(VALUE self, VALUE r_ns, VALUE r_cb_obj)
547
222
 
548
223
  VALUE libraries = rb_iv_get(self, "@libraries");
549
224
 
225
+ rb_iv_set(r_cb_obj, "@document", self);
226
+
550
227
  rb_hash_aset(libraries, INT2FIX(uri), r_cb_obj);
551
228
  }
552
229
  return Qnil;
553
230
  }
554
231
 
232
+ static void flush_text(document_t *document)
233
+ {
234
+ document->ok = rnv_text(document->rnv, document->drv_st, document->rn_st, document->rx_st,
235
+ &document->current, &document->previous, document->text, document->n_txt, document->mixed) &&
236
+ document->ok;
237
+ document->text[document->n_txt = 0] = '\0';
238
+ }
239
+
555
240
  /*
556
241
  * begin parsing a new document
557
242
  * @return [nil]
@@ -572,6 +257,11 @@ VALUE rb_document_begin(VALUE self)
572
257
 
573
258
  document->ok = document->current = document->previous = document->start;
574
259
 
260
+ document->last_line = 0;
261
+ document->last_col = 0;
262
+
263
+ document->level = 0;
264
+
575
265
  document->text[0] = '\0';
576
266
  document->n_txt = 0;
577
267
  document->mixed = 0;
@@ -663,6 +353,10 @@ VALUE rb_document_start_tag(VALUE self, VALUE r_name, VALUE r_attrs)
663
353
  document->mixed = 0;
664
354
  free(attrs);
665
355
  }
356
+ else
357
+ {
358
+ ++document->level;
359
+ }
666
360
 
667
361
  return RTEST(document->ok);
668
362
  }
@@ -695,6 +389,13 @@ VALUE rb_document_end_tag(VALUE self, VALUE r_name)
695
389
 
696
390
  document->mixed = 1;
697
391
  }
392
+ else
393
+ {
394
+ if (document->level == 0)
395
+ document->current = document->previous;
396
+ else
397
+ --document->level;
398
+ }
698
399
 
699
400
  return RTEST(document->ok);
700
401
  }
@@ -723,16 +424,16 @@ void Init_rnv()
723
424
  * @return [Integer]
724
425
  */
725
426
  rb_define_attr(Error, "col", 1, 0);
427
+
428
+ DataTypeLibrary = rb_define_class_under(RNV, "DataTypeLibrary", rb_cObject);
429
+
726
430
  /*
727
- * error message
728
- * @return [String]
729
- */
730
- rb_define_attr(Error, "message", 1, 0);
731
- /*
732
- * what was expected
733
- * @return [String]
431
+ * document in which library is registered
432
+ * @return [RNV::Document]
734
433
  */
735
- rb_define_attr(Error, "expected", 1, 0);
434
+ rb_define_attr(DataTypeLibrary, "document", 1, 0);
435
+
436
+ rb_define_method(DataTypeLibrary, "push_error", rb_datatype_push_error, 1);
736
437
 
737
438
  Document = rb_define_class_under(RNV, "Document", rb_cObject);
738
439
 
@@ -761,6 +462,12 @@ void Init_rnv()
761
462
  */
762
463
  rb_define_attr(Document, "last_col", 1, 1);
763
464
 
465
+ /*
466
+ * xpath to node, set by SAX handler
467
+ * @return [String]
468
+ */
469
+ rb_define_attr(Document, "xpath", 1, 1);
470
+
764
471
  /*
765
472
  * errors from current document
766
473
  * @return [Array<RNV::Error>]