ruby_rnv 0.3.0 → 0.5.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: 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>]