ruby_rnv 0.2.4 → 0.3.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: 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: