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 +4 -4
- data/ext/rnv/ruby_rnv.c +106 -82
- data/ext/rnv/src/drv.c +11 -15
- data/ext/rnv/src/drv.h +9 -1
- data/lib/rnv.rb +3 -0
- data/lib/rnv/data_type_library.rb +23 -0
- data/lib/rnv/error.rb +13 -0
- data/lib/rnv/pre_processor.rb +25 -0
- data/lib/rnv/validator.rb +14 -9
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 076d290b71d2baddf3f6655f99471138ba7a348ce04ac509f246a92c007d2c27
|
|
4
|
+
data.tar.gz: '014108a35aacd5f4c78804ef9740f40e314b9f28968f038f0746375acc259fff'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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 =
|
|
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
|
-
|
|
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 [
|
|
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
|
|
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
|
|
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
|
|
612
|
-
* @return [
|
|
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
|
|
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
|
-
|
|
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(
|
|
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
|
|
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 [
|
|
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
|
|
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
|
|
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
|
-
|
|
707
|
+
SchemaNotLoaded = rb_define_class_under(RNV, "SchemaNotLoaded", rb_eStandardError);
|
|
690
708
|
|
|
691
|
-
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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
|
@@ -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
|
|
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.
|
|
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-
|
|
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:
|