ruby_rnv 0.2.2 → 0.4.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: 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);