ruby_rnv 0.2.3 → 0.4.1

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: ce96c14db6a65519b008b024bdd445baa77d7fd8dc7c4058036069b570137ffc
4
- data.tar.gz: ea3d0f24683bc0534c59ed42780e3f09fec6065fa4d45cb338661000d04e9e4f
3
+ metadata.gz: f815e167e18653e6820b447245834127448b9ac2b72c2f0228baefb40226007d
4
+ data.tar.gz: d192a9e1faa7e62c25caf68fca1beaeb7a77f706a85ecf50175f70c5e4dd45f4
5
5
  SHA512:
6
- metadata.gz: fbf7ae9c188ca229dcc96c468dc5cf5b4cade193d49dd65fdc1ad9e1e7fcf124fb7a536c8b0a8a89a6c80706ab5ca94ff5b8a88bb7fa1d97b8376064e26c00d3
7
- data.tar.gz: e949052b38a2cece1846fbcb4f365112de0f9674c0e55eb10fd5646f19f61e6034796d8923807736e17b7e8ad5e3081d2aecd60899d6cd6921b3863c516956fa
6
+ metadata.gz: 9d53f3238103630b7617fe91850bd4ad930781981cc3d67cd8a5f1d9cfb4ff90d9de6463483e2ee054bce3cbeb19f6407edeb5dd91008b222a464a6bd7ab07d0
7
+ data.tar.gz: 3613bb75f3ef998a5a90af133fcbcc40b51a7bb983149bbcb8bae67e800a72c5a61978f26fb96aed8ec707d2ecbac2a4356fbe457382dbf85277be6638257074
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
 
@@ -489,10 +119,11 @@ 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
-
494
122
  if (document->opened)
123
+ {
124
+ document_load(document);
495
125
  return Qtrue;
126
+ }
496
127
  else
497
128
  return Qfalse;
498
129
  }
@@ -507,27 +138,21 @@ VALUE rb_document_load_file(VALUE self, VALUE r_fn)
507
138
  document_t *document;
508
139
  Data_Get_Struct(self, document_t, document);
509
140
 
510
- switch (TYPE(r_fn))
511
- {
512
- case T_STRING:
513
- document->fn = RSTRING_PTR(r_fn);
514
-
515
- document->opened = rnl_fn(document->rnv,
516
- document->rnc_st,
517
- document->rn_st,
518
- document->rnd_st,
519
- document->fn);
520
- break;
521
- case T_FILE: // TODO
522
- default:
523
- rb_raise(rb_eTypeError, "invalid argument");
524
- break;
525
- }
141
+ Check_Type(r_fn, T_STRING);
526
142
 
527
- document_load(document);
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);
528
150
 
529
151
  if (document->opened)
152
+ {
153
+ document_load(document);
530
154
  return Qtrue;
155
+ }
531
156
  else
532
157
  return Qfalse;
533
158
  }
@@ -547,6 +172,63 @@ VALUE rb_document_valid(VALUE self)
547
172
  return Qfalse;
548
173
  }
549
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
+
550
232
  static void flush_text(document_t *document)
551
233
  {
552
234
  document->ok = rnv_text(document->rnv, document->drv_st, document->rn_st, document->rx_st,
@@ -556,7 +238,7 @@ static void flush_text(document_t *document)
556
238
  }
557
239
 
558
240
  /*
559
- * begin a new document
241
+ * begin parsing a new document
560
242
  * @return [nil]
561
243
  */
562
244
  VALUE rb_document_begin(VALUE self)
@@ -564,11 +246,22 @@ VALUE rb_document_begin(VALUE self)
564
246
  document_t *document;
565
247
  Data_Get_Struct(self, document_t, document);
566
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
+
567
255
  m_free(document->text);
568
256
  document->text = (char *)m_alloc(document->len_txt = LEN_T, sizeof(char));
569
257
 
570
258
  document->ok = document->current = document->previous = document->start;
571
259
 
260
+ document->last_line = 0;
261
+ document->last_col = 0;
262
+
263
+ document->level = 0;
264
+
572
265
  document->text[0] = '\0';
573
266
  document->n_txt = 0;
574
267
  document->mixed = 0;
@@ -579,14 +272,17 @@ VALUE rb_document_begin(VALUE self)
579
272
  /*
580
273
  * to be called by SAX characters handler
581
274
  * @param [String] r_str characters
582
- * @return [Integer]
275
+ * @return [Boolean]
583
276
  */
584
277
  VALUE rb_document_characters(VALUE self, VALUE r_str)
585
278
  {
586
279
  document_t *document;
587
280
  Data_Get_Struct(self, document_t, document);
588
281
 
589
- 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)
590
286
  {
591
287
  Check_Type(r_str, T_STRING);
592
288
  char *s = RSTRING_PTR(r_str);
@@ -607,21 +303,24 @@ VALUE rb_document_characters(VALUE self, VALUE r_str)
607
303
  document->text[document->n_txt] = '\0'; /* '\0' guarantees that the text is bounded, and strto[ld] work for data */
608
304
  }
609
305
 
610
- return INT2NUM(document->ok);
306
+ return RTEST(document->ok);
611
307
  }
612
308
 
613
309
  /*
614
310
  * to be called by SAX start tag handler
615
311
  * @param [String] r_name tag name, must be in the form 'NS_URI:TAG_NAME'
616
- * @param [Array<String>] r_attrs flattened array of tag attributes in the form ['NS_URI:ATTR_NAME','ATTR_VALUE']
617
- * @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]
618
314
  */
619
315
  VALUE rb_document_start_tag(VALUE self, VALUE r_name, VALUE r_attrs)
620
316
  {
621
317
  document_t *document;
622
318
  Data_Get_Struct(self, document_t, document);
623
319
 
624
- 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)
625
324
  {
626
325
  int i;
627
326
  char *name;
@@ -631,20 +330,22 @@ VALUE rb_document_start_tag(VALUE self, VALUE r_name, VALUE r_attrs)
631
330
  name = RSTRING_PTR(r_name);
632
331
 
633
332
  Check_Type(r_attrs, T_ARRAY);
634
- 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);
635
337
 
636
338
  attrs = malloc(sizeof(char *) * (attrs_len + 1));
637
339
 
638
340
  for (i = 0; i < attrs_len; i++)
639
341
  {
640
- attrs[i] = RSTRING_PTR(rb_ary_entry(r_attrs, i));
342
+ attrs[i] = RSTRING_PTR(rb_ary_entry(r_flat_attrs, i));
641
343
  }
642
344
  attrs[attrs_len] = 0; // zero terminated
643
345
 
644
346
  document->mixed = 1;
645
347
 
646
348
  flush_text(document);
647
- //printf("RNV START %d/%d %s %d\n", current, previous, name, attrs_len);
648
349
  document->ok = rnv_start_tag(document->rnv, document->drv_st, document->rn_st, document->rx_st,
649
350
  &document->current, &document->previous, (char *)name, (char **)attrs) &&
650
351
  document->ok;
@@ -652,21 +353,28 @@ VALUE rb_document_start_tag(VALUE self, VALUE r_name, VALUE r_attrs)
652
353
  document->mixed = 0;
653
354
  free(attrs);
654
355
  }
356
+ else
357
+ {
358
+ ++document->level;
359
+ }
655
360
 
656
- return INT2NUM(document->ok);
361
+ return RTEST(document->ok);
657
362
  }
658
363
 
659
364
  /*
660
365
  * to be called by SAX end tag handler
661
366
  * @param [String] r_name tag name, must be in the form 'NS_URI:TAG_NAME'
662
- * @return [Integer]
367
+ * @return [Boolean]
663
368
  */
664
369
  VALUE rb_document_end_tag(VALUE self, VALUE r_name)
665
370
  {
666
371
  document_t *document;
667
372
  Data_Get_Struct(self, document_t, document);
668
373
 
669
- 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)
670
378
  {
671
379
  char *name;
672
380
 
@@ -675,15 +383,21 @@ VALUE rb_document_end_tag(VALUE self, VALUE r_name)
675
383
 
676
384
  flush_text(document);
677
385
 
678
- //printf("RNV END %d/%d %s\n", current, previous, name);
679
386
  document->ok = rnv_end_tag(document->rnv, document->drv_st, document->rn_st,
680
387
  &document->current, &document->previous, (char *)name) &&
681
388
  document->ok;
682
389
 
683
390
  document->mixed = 1;
684
391
  }
392
+ else
393
+ {
394
+ if (document->level == 0)
395
+ document->current = document->previous;
396
+ else
397
+ --document->level;
398
+ }
685
399
 
686
- return INT2NUM(document->ok);
400
+ return RTEST(document->ok);
687
401
  }
688
402
 
689
403
  // The initialization method for this module
@@ -691,21 +405,15 @@ void Init_rnv()
691
405
  {
692
406
  RNV = rb_define_module("RNV");
693
407
 
694
- VALUE Error = rb_define_class_under(RNV, "Error", rb_cObject);
408
+ SchemaNotLoaded = rb_define_class_under(RNV, "SchemaNotLoaded", rb_eStandardError);
695
409
 
696
- rb_define_method(Error, "inspect", rb_error_inspect, 0);
697
- rb_define_method(Error, "to_s", rb_error_to_s, 0);
410
+ Error = rb_define_class_under(RNV, "Error", rb_cObject);
698
411
 
699
412
  /*
700
413
  * error symbol code
701
414
  * @return [Symbol]
702
415
  */
703
416
  rb_define_attr(Error, "code", 1, 0);
704
- /*
705
- * error message
706
- * @return [String]
707
- */
708
- rb_define_attr(Error, "message", 1, 0);
709
417
  /*
710
418
  * error line
711
419
  * @return [Integer]
@@ -717,7 +425,17 @@ void Init_rnv()
717
425
  */
718
426
  rb_define_attr(Error, "col", 1, 0);
719
427
 
720
- 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);
721
439
 
722
440
  rb_define_alloc_func(Document, rb_document_alloc);
723
441
  rb_define_method(Document, "initialize", rb_document_init, 0);
@@ -726,6 +444,8 @@ void Init_rnv()
726
444
  rb_define_method(Document, "load_string", rb_document_load_string, 1);
727
445
  rb_define_method(Document, "valid?", rb_document_valid, 0);
728
446
 
447
+ rb_define_method(Document, "add_datatype_library", rb_document_add_dtl, 2);
448
+
729
449
  rb_define_method(Document, "start_document", rb_document_begin, 0);
730
450
  rb_define_method(Document, "start_tag", rb_document_start_tag, 2);
731
451
  rb_define_method(Document, "characters", rb_document_characters, 1);