ruby_rnv 0.2.4 → 0.3.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: a97a5b35a39aa2ad603660b81b9c13e04375dafbc9f537fec0720357befd53f8
4
- data.tar.gz: 54dff4be913ec5e3e356cb43c5d58a936aa6aa76f38212212a19f3057875f22c
3
+ metadata.gz: 076d290b71d2baddf3f6655f99471138ba7a348ce04ac509f246a92c007d2c27
4
+ data.tar.gz: '014108a35aacd5f4c78804ef9740f40e314b9f28968f038f0746375acc259fff'
5
5
  SHA512:
6
- metadata.gz: bacdd196d95d59883413268ab7dc70d68bd39d4d93876ca156687aceabd7d76cd917a09dbeea4537a3f3c96cbc883bd6f7cd35bf152ac0c421e6e9183f14c2a9
7
- data.tar.gz: c43c097908014a8dc61fedab76ab407012077ec471fdc256aeca28d8261e3c90a4678f50a7b4308aa66efd96c008e1eb2e86f6fafe3ef1418b433b0da74a146c
6
+ metadata.gz: 4e79a6d9727dbf1736df5b972acc8fb609b996ed224cf7346e42269af7777a07be42dad27ce11ae7db2d151be1a5c27d39169301289537d45ec12303aab129e7
7
+ data.tar.gz: a52f9058d874dd8083a892e0aff3ca55f68bae0bbc6f34446b31bf1922ee0d74e14693ab4d2ef6bb2cf270a1f384cf0b9f32fc1dbe764dbb6e4d2bd936ca7b0d
data/ext/rnv/ruby_rnv.c CHANGED
@@ -56,7 +56,7 @@ typedef struct document
56
56
 
57
57
  } document_t;
58
58
 
59
- VALUE RNV;
59
+ VALUE RNV, SchemaNotLoaded, Error, Document;
60
60
 
61
61
  // convert error code to symbol
62
62
  ID errno_to_id(int erno)
@@ -275,7 +275,7 @@ int ruby_verror_handler(rnv_t *rnv, int erno, char *format, va_list ap)
275
275
  // lazyly strip with ruby
276
276
  rb_funcall(error_str, rb_intern("strip!"), 0);
277
277
 
278
- VALUE err_class = rb_const_get(RNV, rb_intern("Error"));
278
+ VALUE err_class = Error;
279
279
  VALUE err_obj = rb_class_new_instance(0, NULL, err_class);
280
280
  rb_iv_set(err_obj, "@document", self);
281
281
  rb_iv_set(err_obj, "@code", error_erno);
@@ -317,61 +317,6 @@ int ruby_verror_handler(rnv_t *rnv, int erno, char *format, va_list ap)
317
317
  rb_ary_push(errors, err_obj);
318
318
  }
319
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;
348
- }
349
-
350
- /*
351
- * @return [String]
352
- */
353
- VALUE rb_error_to_s(VALUE self)
354
- {
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");
359
-
360
- VALUE ret = rb_str_new2("");
361
-
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));
365
-
366
- ret = rb_str_cat2(ret, ": error: ");
367
-
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
320
  void document_free(document_t *document)
376
321
  {
377
322
  // FIXME : introduce *_delete functions
@@ -417,7 +362,8 @@ void document_free(document_t *document)
417
362
 
418
363
  free(document->rnv);
419
364
 
420
- free(document->text);
365
+ if (document->text)
366
+ free(document->text);
421
367
 
422
368
  ruby_xfree(document);
423
369
  }
@@ -450,9 +396,12 @@ VALUE rb_document_init(VALUE self)
450
396
  document->rnv->user_data = (void *)self;
451
397
  document->rnv->verror_handler = &ruby_verror_handler;
452
398
  document->nexp = 16; /* maximum number of candidates to display */
399
+ document->text = NULL;
453
400
 
454
401
  rb_iv_set(self, "@errors", rb_ary_new2(0));
455
402
 
403
+ rb_iv_set(self, "@libraries", rb_hash_new());
404
+
456
405
  return self;
457
406
  }
458
407
 
@@ -550,8 +499,61 @@ static void flush_text(document_t *document)
550
499
  document->text[document->n_txt = 0] = '\0';
551
500
  }
552
501
 
502
+ 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
+ {
504
+ VALUE self = (VALUE)rnv->user_data;
505
+ VALUE libraries = rb_iv_get(self, "@libraries");
506
+ VALUE lib = rb_hash_aref(libraries, INT2FIX(uri));
507
+
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));
510
+
511
+ return RTEST(ret);
512
+ }
513
+
514
+ 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)
515
+ {
516
+ VALUE self = (VALUE)rnv->user_data;
517
+ VALUE libraries = rb_iv_get(self, "@libraries");
518
+ VALUE lib = rb_hash_aref(libraries, INT2FIX(uri));
519
+
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));
522
+
523
+ return RTEST(ret);
524
+ }
525
+
526
+ /*
527
+ * add a new datatype library
528
+ * @see https://www.oasis-open.org/committees/relax-ng/spec-20010811.html#IDA1I1R
529
+ * @param [String] r_ns unique ns URL for this datatype
530
+ * @param [RNV::DataTypeLibrary] r_cb_obj
531
+ * @return [nil]
532
+ */
533
+ VALUE rb_document_add_dtl(VALUE self, VALUE r_ns, VALUE r_cb_obj)
534
+ {
535
+ document_t *document;
536
+ Data_Get_Struct(self, document_t, document);
537
+
538
+ if (document->opened)
539
+ {
540
+ Check_Type(r_ns, T_STRING);
541
+
542
+ char *suri = RSTRING_PTR(r_ns);
543
+
544
+ drv_add_dtl(document->rnv, document->drv_st, document->rn_st, suri, &rb_dtl_equal, &rb_dtl_allows);
545
+
546
+ int uri = document->drv_st->dtl[document->drv_st->n_dtl - 1].uri;
547
+
548
+ VALUE libraries = rb_iv_get(self, "@libraries");
549
+
550
+ rb_hash_aset(libraries, INT2FIX(uri), r_cb_obj);
551
+ }
552
+ return Qnil;
553
+ }
554
+
553
555
  /*
554
- * begin a new document
556
+ * begin parsing a new document
555
557
  * @return [nil]
556
558
  */
557
559
  VALUE rb_document_begin(VALUE self)
@@ -559,6 +561,12 @@ VALUE rb_document_begin(VALUE self)
559
561
  document_t *document;
560
562
  Data_Get_Struct(self, document_t, document);
561
563
 
564
+ if (!document->opened)
565
+ rb_raise(SchemaNotLoaded, "schema was not loaded correctly");
566
+
567
+ // reset errors
568
+ rb_iv_set(self, "@errors", rb_ary_new2(0));
569
+
562
570
  m_free(document->text);
563
571
  document->text = (char *)m_alloc(document->len_txt = LEN_T, sizeof(char));
564
572
 
@@ -574,14 +582,17 @@ VALUE rb_document_begin(VALUE self)
574
582
  /*
575
583
  * to be called by SAX characters handler
576
584
  * @param [String] r_str characters
577
- * @return [Integer]
585
+ * @return [Boolean]
578
586
  */
579
587
  VALUE rb_document_characters(VALUE self, VALUE r_str)
580
588
  {
581
589
  document_t *document;
582
590
  Data_Get_Struct(self, document_t, document);
583
591
 
584
- if (document->opened && document->current != document->rnv->rn_notAllowed)
592
+ if (!document->opened)
593
+ rb_raise(SchemaNotLoaded, "schema was not loaded correctly");
594
+
595
+ if (document->current != document->rnv->rn_notAllowed)
585
596
  {
586
597
  Check_Type(r_str, T_STRING);
587
598
  char *s = RSTRING_PTR(r_str);
@@ -602,21 +613,24 @@ VALUE rb_document_characters(VALUE self, VALUE r_str)
602
613
  document->text[document->n_txt] = '\0'; /* '\0' guarantees that the text is bounded, and strto[ld] work for data */
603
614
  }
604
615
 
605
- return INT2NUM(document->ok);
616
+ return RTEST(document->ok);
606
617
  }
607
618
 
608
619
  /*
609
620
  * to be called by SAX start tag handler
610
621
  * @param [String] r_name tag name, must be in the form 'NS_URI:TAG_NAME'
611
- * @param [Array<String>] r_attrs flattened array of tag attributes in the form ['NS_URI:ATTR_NAME','ATTR_VALUE']
612
- * @return [Integer]
622
+ * @param [Array<Array<String>>] r_attrs flattened array of tag attributes in the form [['NS_URI:ATTR_NAME','ATTR_VALUE']]
623
+ * @return [Boolean]
613
624
  */
614
625
  VALUE rb_document_start_tag(VALUE self, VALUE r_name, VALUE r_attrs)
615
626
  {
616
627
  document_t *document;
617
628
  Data_Get_Struct(self, document_t, document);
618
629
 
619
- if (document->opened && document->current != document->rnv->rn_notAllowed)
630
+ if (!document->opened)
631
+ rb_raise(SchemaNotLoaded, "schema was not loaded correctly");
632
+
633
+ if (document->current != document->rnv->rn_notAllowed)
620
634
  {
621
635
  int i;
622
636
  char *name;
@@ -626,20 +640,22 @@ VALUE rb_document_start_tag(VALUE self, VALUE r_name, VALUE r_attrs)
626
640
  name = RSTRING_PTR(r_name);
627
641
 
628
642
  Check_Type(r_attrs, T_ARRAY);
629
- unsigned int attrs_len = RARRAY_LEN(r_attrs);
643
+
644
+ // lazyly flatten with ruby
645
+ VALUE r_flat_attrs = rb_funcall(r_attrs, rb_intern("flatten"), 0);
646
+ unsigned int attrs_len = RARRAY_LEN(r_flat_attrs);
630
647
 
631
648
  attrs = malloc(sizeof(char *) * (attrs_len + 1));
632
649
 
633
650
  for (i = 0; i < attrs_len; i++)
634
651
  {
635
- attrs[i] = RSTRING_PTR(rb_ary_entry(r_attrs, i));
652
+ attrs[i] = RSTRING_PTR(rb_ary_entry(r_flat_attrs, i));
636
653
  }
637
654
  attrs[attrs_len] = 0; // zero terminated
638
655
 
639
656
  document->mixed = 1;
640
657
 
641
658
  flush_text(document);
642
- //printf("RNV START %d/%d %s %d\n", current, previous, name, attrs_len);
643
659
  document->ok = rnv_start_tag(document->rnv, document->drv_st, document->rn_st, document->rx_st,
644
660
  &document->current, &document->previous, (char *)name, (char **)attrs) &&
645
661
  document->ok;
@@ -648,20 +664,23 @@ VALUE rb_document_start_tag(VALUE self, VALUE r_name, VALUE r_attrs)
648
664
  free(attrs);
649
665
  }
650
666
 
651
- return INT2NUM(document->ok);
667
+ return RTEST(document->ok);
652
668
  }
653
669
 
654
670
  /*
655
671
  * to be called by SAX end tag handler
656
672
  * @param [String] r_name tag name, must be in the form 'NS_URI:TAG_NAME'
657
- * @return [Integer]
673
+ * @return [Boolean]
658
674
  */
659
675
  VALUE rb_document_end_tag(VALUE self, VALUE r_name)
660
676
  {
661
677
  document_t *document;
662
678
  Data_Get_Struct(self, document_t, document);
663
679
 
664
- if (document->opened && document->current != document->rnv->rn_notAllowed)
680
+ if (!document->opened)
681
+ rb_raise(SchemaNotLoaded, "schema was not loaded correctly");
682
+
683
+ if (document->current != document->rnv->rn_notAllowed)
665
684
  {
666
685
  char *name;
667
686
 
@@ -670,7 +689,6 @@ VALUE rb_document_end_tag(VALUE self, VALUE r_name)
670
689
 
671
690
  flush_text(document);
672
691
 
673
- //printf("RNV END %d/%d %s\n", current, previous, name);
674
692
  document->ok = rnv_end_tag(document->rnv, document->drv_st, document->rn_st,
675
693
  &document->current, &document->previous, (char *)name) &&
676
694
  document->ok;
@@ -678,7 +696,7 @@ VALUE rb_document_end_tag(VALUE self, VALUE r_name)
678
696
  document->mixed = 1;
679
697
  }
680
698
 
681
- return INT2NUM(document->ok);
699
+ return RTEST(document->ok);
682
700
  }
683
701
 
684
702
  // The initialization method for this module
@@ -686,21 +704,15 @@ void Init_rnv()
686
704
  {
687
705
  RNV = rb_define_module("RNV");
688
706
 
689
- VALUE Error = rb_define_class_under(RNV, "Error", rb_cObject);
707
+ SchemaNotLoaded = rb_define_class_under(RNV, "SchemaNotLoaded", rb_eStandardError);
690
708
 
691
- rb_define_method(Error, "inspect", rb_error_inspect, 0);
692
- rb_define_method(Error, "to_s", rb_error_to_s, 0);
709
+ Error = rb_define_class_under(RNV, "Error", rb_cObject);
693
710
 
694
711
  /*
695
712
  * error symbol code
696
713
  * @return [Symbol]
697
714
  */
698
715
  rb_define_attr(Error, "code", 1, 0);
699
- /*
700
- * error message
701
- * @return [String]
702
- */
703
- rb_define_attr(Error, "message", 1, 0);
704
716
  /*
705
717
  * error line
706
718
  * @return [Integer]
@@ -711,8 +723,18 @@ void Init_rnv()
711
723
  * @return [Integer]
712
724
  */
713
725
  rb_define_attr(Error, "col", 1, 0);
726
+ /*
727
+ * error message
728
+ * @return [String]
729
+ */
730
+ rb_define_attr(Error, "message", 1, 0);
731
+ /*
732
+ * what was expected
733
+ * @return [String]
734
+ */
735
+ rb_define_attr(Error, "expected", 1, 0);
714
736
 
715
- VALUE Document = rb_define_class_under(RNV, "Document", rb_cObject);
737
+ Document = rb_define_class_under(RNV, "Document", rb_cObject);
716
738
 
717
739
  rb_define_alloc_func(Document, rb_document_alloc);
718
740
  rb_define_method(Document, "initialize", rb_document_init, 0);
@@ -721,6 +743,8 @@ void Init_rnv()
721
743
  rb_define_method(Document, "load_string", rb_document_load_string, 1);
722
744
  rb_define_method(Document, "valid?", rb_document_valid, 0);
723
745
 
746
+ rb_define_method(Document, "add_datatype_library", rb_document_add_dtl, 2);
747
+
724
748
  rb_define_method(Document, "start_document", rb_document_begin, 0);
725
749
  rb_define_method(Document, "start_tag", rb_document_start_tag, 2);
726
750
  rb_define_method(Document, "characters", rb_document_characters, 1);
data/ext/rnv/src/drv.c CHANGED
@@ -13,12 +13,6 @@
13
13
  #include "er.h"
14
14
  #include "drv.h"
15
15
 
16
- struct dtl {
17
- int uri;
18
- int (*equal)(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, char *typ,char *val,char *s,int n);
19
- int (*allows)(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, char *typ,char *ps,char *s,int n);
20
- };
21
-
22
16
  #define LEN_DTL DRV_LEN_DTL
23
17
  #define LEN_M DRV_LEN_M
24
18
  #define PRIME_M DRV_PRIME_M
@@ -112,10 +106,10 @@ static void accept_m(rnv_t *rnv, drv_st_t *drv_st) {
112
106
  if(drv_st->i_m==drv_st->len_m) drv_st->memo=(int(*)[M_SIZE])m_stretch(drv_st->memo,drv_st->len_m=2*drv_st->i_m,drv_st->i_m,sizeof(int[M_SIZE]));
113
107
  }
114
108
 
115
- static int fallback_equal(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, char *typ,char *val,char *s,int n) {return 1;}
116
- static int fallback_allows(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, char *typ,char *ps,char *s,int n) {return 1;}
109
+ static int fallback_equal(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, int uri, char *typ,char *val,char *s,int n) {return 1;}
110
+ static int fallback_allows(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, int uri, char *typ,char *ps,char *s,int n) {return 1;}
117
111
 
118
- static int builtin_equal(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, char *typ,char *val,char *s,int n) {
112
+ static int builtin_equal(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, int uri, char *typ,char *val,char *s,int n) {
119
113
  int dt=rn_newDatatype(rnv, rn_st, 0,typ-rnv->rn_string);
120
114
  if(dt==rnv->rn_dt_string) return s_cmpn(val,s,n)==0;
121
115
  else if(dt==rnv->rn_dt_token) return s_tokcmpn(val,s,n)==0;
@@ -123,7 +117,7 @@ static int builtin_equal(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, char *typ,c
123
117
  return 0;
124
118
  }
125
119
 
126
- static int builtin_allows(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, char *typ,char *ps,char *s,int n) {return 1;}
120
+ static int builtin_allows(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, int uri, char *typ,char *ps,char *s,int n) {return 1;}
127
121
 
128
122
  static void windup(rnv_t *rnv, drv_st_t *drv_st, rn_st_t *rn_st);
129
123
 
@@ -140,11 +134,11 @@ void drv_init(rnv_t *rnv, drv_st_t *drv_st, rn_st_t *rn_st, rx_st_t *rx_st) {
140
134
  windup(rnv, drv_st, rn_st);
141
135
  }
142
136
 
143
- static int emb_xsd_allows(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, char *typ,char *ps,char *s,int n) {
137
+ static int emb_xsd_allows(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, int uri, char *typ,char *ps,char *s,int n) {
144
138
  return xsd_allows(rx_st, typ,ps,s,n);
145
139
  }
146
140
 
147
- static int emb_xsd_equal(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, char *typ,char *val,char *s,int n) {
141
+ static int emb_xsd_equal(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, int uri, char *typ,char *val,char *s,int n) {
148
142
  return xsd_equal(rx_st, typ,val,s,n);
149
143
  }
150
144
 
@@ -160,7 +154,9 @@ void drv_clear(rnv_t *rnv, drv_st_t *drv_st, rn_st_t *rn_st) {
160
154
  windup(rnv, drv_st, rn_st);
161
155
  }
162
156
 
163
- void drv_add_dtl(rnv_t *rnv, drv_st_t *drv_st, rn_st_t *rn_st, char *suri,int (*equal)(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, char *typ,char *val,char *s,int n),int (*allows)(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, char *typ,char *ps,char *s,int n)) {
157
+ void drv_add_dtl(rnv_t *rnv, drv_st_t *drv_st, rn_st_t *rn_st, char *suri,
158
+ int (*equal)(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, int uri, char *typ,char *val,char *s,int n),
159
+ int (*allows)(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, int uri, char *typ,char *ps,char *s,int n)) {
164
160
  if(drv_st->n_dtl==drv_st->len_dtl) drv_st->dtl=(struct dtl *)m_stretch(drv_st->dtl,drv_st->len_dtl=drv_st->n_dtl*2,drv_st->n_dtl,sizeof(struct dtl));
165
161
  drv_st->dtl[drv_st->n_dtl].uri=rn_newString(rnv, rn_st, suri);
166
162
  drv_st->dtl[drv_st->n_dtl].equal=equal;
@@ -381,13 +377,13 @@ static int text(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, drv_st_t *drv_st, in
381
377
  ret=rn_nullable(list(rnv, rn_st, rx_st, drv_st, p1,s,n))?rnv->rn_empty:rnv->rn_notAllowed;
382
378
  break;
383
379
  case RN_P_DATA: rn_Data(p,dt,ps); rn_Datatype(dt,lib,typ);
384
- ret=getdtl(rnv, drv_st, lib)->allows(rnv,rn_st,rx_st,rnv->rn_string+typ,rnv->rn_string+ps,s,n)?rnv->rn_empty:rnv->rn_notAllowed;
380
+ ret=getdtl(rnv, drv_st, lib)->allows(rnv,rn_st,rx_st, lib, rnv->rn_string+typ,rnv->rn_string+ps,s,n)?rnv->rn_empty:rnv->rn_notAllowed;
385
381
  break;
386
382
  case RN_P_DATA_EXCEPT: rn_DataExcept(p,p1,p2);
387
383
  ret=text(rnv, rn_st, rx_st, drv_st, p1,s,n)==rnv->rn_empty&&!rn_nullable(text(rnv, rn_st, rx_st, drv_st, p2,s,n))?rnv->rn_empty:rnv->rn_notAllowed;
388
384
  break;
389
385
  case RN_P_VALUE: rn_Value(p,dt,val); rn_Datatype(dt,lib,typ);
390
- ret=getdtl(rnv, drv_st, lib)->equal(rnv,rn_st,rx_st, rnv->rn_string+typ,rnv->rn_string+val,s,n)?rnv->rn_empty:rnv->rn_notAllowed;
386
+ ret=getdtl(rnv, drv_st, lib)->equal(rnv,rn_st,rx_st, lib, rnv->rn_string+typ,rnv->rn_string+val,s,n)?rnv->rn_empty:rnv->rn_notAllowed;
391
387
  break;
392
388
  default: assert(0);
393
389
  }
data/ext/rnv/src/drv.h CHANGED
@@ -9,13 +9,21 @@
9
9
 
10
10
  #define DRV_ER_NODTL 0
11
11
 
12
+ struct dtl {
13
+ int uri;
14
+ int (*equal)(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, int uri, char *typ,char *val,char *s,int n);
15
+ int (*allows)(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, int uri, char *typ,char *ps,char *s,int n);
16
+ };
17
+
12
18
  extern void drv_default_verror_handler(rnv_t *rnv, int erno,va_list ap);
13
19
 
14
20
  extern void drv_init(rnv_t *rnv, drv_st_t *drv_st, rn_st_t *rn_st, rx_st_t *rx_st);
15
21
  extern void drv_clear(rnv_t *rnv, drv_st_t *drv_st, rn_st_t *rn_st);
16
22
 
17
23
  /* Expat passes character data unterminated. Hence functions that can deal with cdata expect the length of the data */
18
- extern void drv_add_dtl(rnv_t *rnv, drv_st_t *drv_st, rn_st_t *rn_st, char *suri,int (*equal)(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, char *typ,char *val,char *s,int n),int (*allows)(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, char *typ,char *ps,char *s,int n));
24
+ extern void drv_add_dtl(rnv_t *rnv, drv_st_t *drv_st, rn_st_t *rn_st, char *suri,
25
+ int (*equal)(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, int uri, char *typ,char *val,char *s,int n),
26
+ int (*allows)(rnv_t *rnv, rn_st_t *rn_st, rx_st_t *rx_st, int uri, char *typ,char *ps,char *s,int n));
19
27
 
20
28
  extern int drv_start_tag_open(rnv_t *rnv, drv_st_t *drv_st, rn_st_t *rn_st, int p,char *suri,char *sname);
21
29
  extern int drv_start_tag_open_recover(rnv_t *rnv, drv_st_t *drv_st, rn_st_t *rn_st, int p,char *suri,char *sname);
data/lib/rnv.rb CHANGED
@@ -1,2 +1,5 @@
1
1
  require 'rnv/rnv'
2
+ require 'rnv/error'
2
3
  require 'rnv/validator'
4
+ require 'rnv/data_type_library'
5
+ require 'rnv/pre_processor'
@@ -0,0 +1,23 @@
1
+ module RNV
2
+ # Datatype library callback object
3
+ # @see https://www.oasis-open.org/committees/relax-ng/spec-20010811.html#IDA1I1R
4
+ class DataTypeLibrary
5
+ # @param [String] typ
6
+ # @param [String] val
7
+ # @param [String] s
8
+ # @param [Integer] n
9
+ # @return [Boolean]
10
+ def equal(typ, val, s, n)
11
+ true
12
+ end
13
+
14
+ # @param [String] typ
15
+ # @param [String] ps
16
+ # @param [String] s
17
+ # @param [Integer] n
18
+ # @return [Boolean]
19
+ def allows(typ, ps, s, n)
20
+ true
21
+ end
22
+ end
23
+ end
data/lib/rnv/error.rb ADDED
@@ -0,0 +1,13 @@
1
+ module RNV
2
+ class Error
3
+ # @return [String]
4
+ def to_s
5
+ "#{@line}:#{@col}:error: #{@message}\n#{@expected}"
6
+ end
7
+
8
+ # @return [String]
9
+ def inspect
10
+ "#<RNV::Error code: :#{@code}, message: '#{@message}', expected: '#{@expected} line: #{@line}, column: #{@col}>"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,25 @@
1
+ module RNV
2
+ # Object to modify data before validation (eg: HTML5 data-* attributes)
3
+ class PreProcessor
4
+ # replace attributes before validate
5
+ # @param [Array<Array<String>>] attrs
6
+ # @return [Array<Array<String>>]
7
+ def attributes(attrs)
8
+ attrs
9
+ end
10
+
11
+ # replace tag name before validate
12
+ # @param [String] tag
13
+ # @return [String]
14
+ def tag(tag)
15
+ tag
16
+ end
17
+
18
+ # replace content text before validate
19
+ # @param [String] txt
20
+ # @return [String]
21
+ def text(txt)
22
+ txt
23
+ end
24
+ end
25
+ end
data/lib/rnv/validator.rb CHANGED
@@ -1,11 +1,12 @@
1
1
  require 'nokogiri'
2
2
  require 'rnv/rnv'
3
+ require 'rnv/pre_processor'
3
4
 
4
5
  module RNV
5
6
  # @!visibility private
6
7
  class NokogiriSaxDocument < Nokogiri::XML::SAX::Document
7
8
  # @return [Nokogiri::XML::SAX::ParserContext]
8
- attr_accessor :ctx
9
+ attr_accessor :ctx, :pre_processor
9
10
  # @param [RNV::Document] document
10
11
  def initialize(document)
11
12
  @document = document
@@ -15,23 +16,23 @@ module RNV
15
16
  update_line_col
16
17
  tag_attrs = attrs.map { |attr| [attr.uri ? "#{attr.uri}:#{attr.localname}" : attr.localname, attr.value] }
17
18
  tag_name = uri ? "#{uri}:#{name}" : name
18
- @document.start_tag(tag_name, tag_attrs.flatten)
19
+ @document.start_tag(@pre_processor.tag(tag_name), @pre_processor.attributes(tag_attrs))
19
20
  end
20
21
 
21
22
  def end_element_namespace(name, prefix = nil, uri = nil)
22
23
  update_line_col
23
24
  tag_name = uri ? "#{uri}:#{name}" : name
24
- @document.end_tag(tag_name)
25
+ @document.end_tag(@pre_processor.tag(tag_name))
25
26
  end
26
27
 
27
28
  def characters str
28
29
  update_line_col
29
- @document.characters(str)
30
+ @document.characters(@pre_processor.text(str))
30
31
  end
31
32
 
32
33
  def cdata_block str
33
34
  update_line_col
34
- @document.characters(str)
35
+ @document.characters(@pre_processor.(str))
35
36
  end
36
37
 
37
38
  private
@@ -57,22 +58,25 @@ module RNV
57
58
  end
58
59
 
59
60
  # @param [String] str RNC schema buffer
61
+ # @return [Boolean] true if schema loaded successfuly
60
62
  def load_schema_from_string(str)
61
63
  @document.load_string(str)
62
64
  end
63
65
 
64
66
  # @param [String] file RNC schema filename
67
+ # @return [Boolean] true if schema loaded successfuly
65
68
  def load_schema_from_file(file)
66
69
  @document.load_file(file)
67
70
  end
68
71
 
69
72
  # parse and validate buffer
70
73
  # @param [String] str XML buffer to parse
74
+ # @param [RNV::PreProcessor] pre_processor an optional pre-processor for tag and attributes data
71
75
  # @return [Boolean] true if valid
72
- def parse_string(str)
73
- @document.errors = [] # reset errors
76
+ def parse_string(str, pre_processor = PreProcessor.new)
74
77
  @document.start_document
75
78
  rnv_doc = NokogiriSaxDocument.new(@document)
79
+ rnv_doc.pre_processor = pre_processor
76
80
 
77
81
  parser = Nokogiri::XML::SAX::Parser.new(rnv_doc)
78
82
  parser.parse_memory(str) do |ctx|
@@ -85,11 +89,12 @@ module RNV
85
89
 
86
90
  # parse and validate file
87
91
  # @param [String, File] xml XML file to parse
92
+ # @param [RNV::PreProcessor] pre_processor an optional pre-processor for tag and attributes data
88
93
  # @return [Boolean] true if valid
89
- def parse_file(xml)
90
- @document.errors = [] # reset errors
94
+ def parse_file(xml, pre_processor = PreProcessor.new)
91
95
  @document.start_document
92
96
  rnv_doc = NokogiriSaxDocument.new(@document)
97
+ rnv_doc.pre_processor = pre_processor
93
98
 
94
99
  file = xml.is_a?(File) ? xml : File.open(xml)
95
100
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_rnv
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julien Boulnois
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-08 00:00:00.000000000 Z
11
+ date: 2021-04-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -147,6 +147,9 @@ files:
147
147
  - ext/rnv/src/xsd_tm.c
148
148
  - ext/rnv/src/xsd_tm.h
149
149
  - lib/rnv.rb
150
+ - lib/rnv/data_type_library.rb
151
+ - lib/rnv/error.rb
152
+ - lib/rnv/pre_processor.rb
150
153
  - lib/rnv/validator.rb
151
154
  homepage: https://github.com/immateriel/ruby_rnv
152
155
  licenses: