ruby_rnv 0.2.1 → 0.3.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 +4 -4
- data/ext/rnv/ruby_rnv.c +131 -104
- 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 +16 -9
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d336dc0c4dae28d9aa530925a9d322cc2a46598d77dc179da6785e47250fe552
|
4
|
+
data.tar.gz: 4e04b15b29ba46fad249f180b923def4cb69e04a041788022769a80ae4a0fb64
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8578ad4848314ed6f152bdd39e8824ad95b705ff6c6d32c150b8491564a0a78997455627903f1c8d00f43f581178c0c1dbb75c2e1ca4358f47ad1e962e98eac9
|
7
|
+
data.tar.gz: 6b3a9ad08b327a3931a3c944a43ecbb48dbcdf6f1a99dceb0c1e5935916254a2e88d45f7d7e26f6b9a374e39355c7e2f69d39777b4b7e5bf3fa0f6b44cbf877c
|
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
|
|
@@ -470,7 +419,7 @@ static void document_load(document_t *document)
|
|
470
419
|
/*
|
471
420
|
* load schema from a buffer
|
472
421
|
* @param [String] r_str buffer
|
473
|
-
* @return [
|
422
|
+
* @return [Boolean]
|
474
423
|
*/
|
475
424
|
VALUE rb_document_load_string(VALUE self, VALUE r_str)
|
476
425
|
{
|
@@ -489,40 +438,42 @@ VALUE rb_document_load_string(VALUE self, VALUE r_str)
|
|
489
438
|
document->fn,
|
490
439
|
RSTRING_PTR(r_str), RSTRING_LEN(r_str));
|
491
440
|
|
492
|
-
|
493
|
-
|
441
|
+
if (document->opened)
|
442
|
+
{
|
443
|
+
document_load(document);
|
444
|
+
return Qtrue;
|
445
|
+
}
|
446
|
+
else
|
447
|
+
return Qfalse;
|
494
448
|
}
|
495
449
|
|
496
450
|
/*
|
497
451
|
* load schema from a file
|
498
452
|
* @param [String] r_fn filename
|
499
|
-
* @return [
|
453
|
+
* @return [Boolean]
|
500
454
|
*/
|
501
455
|
VALUE rb_document_load_file(VALUE self, VALUE r_fn)
|
502
456
|
{
|
503
457
|
document_t *document;
|
504
458
|
Data_Get_Struct(self, document_t, document);
|
505
459
|
|
506
|
-
|
507
|
-
{
|
508
|
-
case T_STRING:
|
509
|
-
document->fn = RSTRING_PTR(r_fn);
|
460
|
+
Check_Type(r_fn, T_STRING);
|
510
461
|
|
511
|
-
|
512
|
-
document->rnc_st,
|
513
|
-
document->rn_st,
|
514
|
-
document->rnd_st,
|
515
|
-
document->fn);
|
462
|
+
document->fn = RSTRING_PTR(r_fn);
|
516
463
|
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
}
|
464
|
+
document->opened = rnl_fn(document->rnv,
|
465
|
+
document->rnc_st,
|
466
|
+
document->rn_st,
|
467
|
+
document->rnd_st,
|
468
|
+
document->fn);
|
523
469
|
|
524
|
-
|
525
|
-
|
470
|
+
if (document->opened)
|
471
|
+
{
|
472
|
+
document_load(document);
|
473
|
+
return Qtrue;
|
474
|
+
}
|
475
|
+
else
|
476
|
+
return Qfalse;
|
526
477
|
}
|
527
478
|
|
528
479
|
/*
|
@@ -548,8 +499,61 @@ static void flush_text(document_t *document)
|
|
548
499
|
document->text[document->n_txt = 0] = '\0';
|
549
500
|
}
|
550
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
|
+
|
551
526
|
/*
|
552
|
-
*
|
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
|
+
|
555
|
+
/*
|
556
|
+
* begin parsing a new document
|
553
557
|
* @return [nil]
|
554
558
|
*/
|
555
559
|
VALUE rb_document_begin(VALUE self)
|
@@ -557,6 +561,12 @@ VALUE rb_document_begin(VALUE self)
|
|
557
561
|
document_t *document;
|
558
562
|
Data_Get_Struct(self, document_t, document);
|
559
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
|
+
|
560
570
|
m_free(document->text);
|
561
571
|
document->text = (char *)m_alloc(document->len_txt = LEN_T, sizeof(char));
|
562
572
|
|
@@ -572,14 +582,17 @@ VALUE rb_document_begin(VALUE self)
|
|
572
582
|
/*
|
573
583
|
* to be called by SAX characters handler
|
574
584
|
* @param [String] r_str characters
|
575
|
-
* @return [
|
585
|
+
* @return [Boolean]
|
576
586
|
*/
|
577
587
|
VALUE rb_document_characters(VALUE self, VALUE r_str)
|
578
588
|
{
|
579
589
|
document_t *document;
|
580
590
|
Data_Get_Struct(self, document_t, document);
|
581
591
|
|
582
|
-
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)
|
583
596
|
{
|
584
597
|
Check_Type(r_str, T_STRING);
|
585
598
|
char *s = RSTRING_PTR(r_str);
|
@@ -600,22 +613,26 @@ VALUE rb_document_characters(VALUE self, VALUE r_str)
|
|
600
613
|
document->text[document->n_txt] = '\0'; /* '\0' guarantees that the text is bounded, and strto[ld] work for data */
|
601
614
|
}
|
602
615
|
|
603
|
-
return
|
616
|
+
return RTEST(document->ok);
|
604
617
|
}
|
605
618
|
|
606
619
|
/*
|
607
620
|
* to be called by SAX start tag handler
|
608
621
|
* @param [String] r_name tag name, must be in the form 'NS_URI:TAG_NAME'
|
609
|
-
* @param [Array<String
|
610
|
-
* @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]
|
611
624
|
*/
|
612
625
|
VALUE rb_document_start_tag(VALUE self, VALUE r_name, VALUE r_attrs)
|
613
626
|
{
|
614
627
|
document_t *document;
|
615
628
|
Data_Get_Struct(self, document_t, document);
|
616
629
|
|
617
|
-
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)
|
618
634
|
{
|
635
|
+
int i;
|
619
636
|
char *name;
|
620
637
|
char **attrs;
|
621
638
|
|
@@ -623,20 +640,22 @@ VALUE rb_document_start_tag(VALUE self, VALUE r_name, VALUE r_attrs)
|
|
623
640
|
name = RSTRING_PTR(r_name);
|
624
641
|
|
625
642
|
Check_Type(r_attrs, T_ARRAY);
|
626
|
-
|
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);
|
627
647
|
|
628
648
|
attrs = malloc(sizeof(char *) * (attrs_len + 1));
|
629
649
|
|
630
|
-
for (
|
650
|
+
for (i = 0; i < attrs_len; i++)
|
631
651
|
{
|
632
|
-
attrs[i] = RSTRING_PTR(rb_ary_entry(
|
652
|
+
attrs[i] = RSTRING_PTR(rb_ary_entry(r_flat_attrs, i));
|
633
653
|
}
|
634
654
|
attrs[attrs_len] = 0; // zero terminated
|
635
655
|
|
636
656
|
document->mixed = 1;
|
637
657
|
|
638
658
|
flush_text(document);
|
639
|
-
//printf("RNV START %d/%d %s %d\n", current, previous, name, attrs_len);
|
640
659
|
document->ok = rnv_start_tag(document->rnv, document->drv_st, document->rn_st, document->rx_st,
|
641
660
|
&document->current, &document->previous, (char *)name, (char **)attrs) &&
|
642
661
|
document->ok;
|
@@ -645,20 +664,23 @@ VALUE rb_document_start_tag(VALUE self, VALUE r_name, VALUE r_attrs)
|
|
645
664
|
free(attrs);
|
646
665
|
}
|
647
666
|
|
648
|
-
return
|
667
|
+
return RTEST(document->ok);
|
649
668
|
}
|
650
669
|
|
651
670
|
/*
|
652
671
|
* to be called by SAX end tag handler
|
653
672
|
* @param [String] r_name tag name, must be in the form 'NS_URI:TAG_NAME'
|
654
|
-
* @return [
|
673
|
+
* @return [Boolean]
|
655
674
|
*/
|
656
675
|
VALUE rb_document_end_tag(VALUE self, VALUE r_name)
|
657
676
|
{
|
658
677
|
document_t *document;
|
659
678
|
Data_Get_Struct(self, document_t, document);
|
660
679
|
|
661
|
-
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)
|
662
684
|
{
|
663
685
|
char *name;
|
664
686
|
|
@@ -667,7 +689,6 @@ VALUE rb_document_end_tag(VALUE self, VALUE r_name)
|
|
667
689
|
|
668
690
|
flush_text(document);
|
669
691
|
|
670
|
-
//printf("RNV END %d/%d %s\n", current, previous, name);
|
671
692
|
document->ok = rnv_end_tag(document->rnv, document->drv_st, document->rn_st,
|
672
693
|
&document->current, &document->previous, (char *)name) &&
|
673
694
|
document->ok;
|
@@ -675,7 +696,7 @@ VALUE rb_document_end_tag(VALUE self, VALUE r_name)
|
|
675
696
|
document->mixed = 1;
|
676
697
|
}
|
677
698
|
|
678
|
-
return
|
699
|
+
return RTEST(document->ok);
|
679
700
|
}
|
680
701
|
|
681
702
|
// The initialization method for this module
|
@@ -683,21 +704,15 @@ void Init_rnv()
|
|
683
704
|
{
|
684
705
|
RNV = rb_define_module("RNV");
|
685
706
|
|
686
|
-
|
707
|
+
SchemaNotLoaded = rb_define_class_under(RNV, "SchemaNotLoaded", rb_eStandardError);
|
687
708
|
|
688
|
-
|
689
|
-
rb_define_method(Error, "to_s", rb_error_to_s, 0);
|
709
|
+
Error = rb_define_class_under(RNV, "Error", rb_cObject);
|
690
710
|
|
691
711
|
/*
|
692
712
|
* error symbol code
|
693
713
|
* @return [Symbol]
|
694
714
|
*/
|
695
715
|
rb_define_attr(Error, "code", 1, 0);
|
696
|
-
/*
|
697
|
-
* error message
|
698
|
-
* @return [String]
|
699
|
-
*/
|
700
|
-
rb_define_attr(Error, "message", 1, 0);
|
701
716
|
/*
|
702
717
|
* error line
|
703
718
|
* @return [Integer]
|
@@ -708,8 +723,18 @@ void Init_rnv()
|
|
708
723
|
* @return [Integer]
|
709
724
|
*/
|
710
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);
|
711
736
|
|
712
|
-
|
737
|
+
Document = rb_define_class_under(RNV, "Document", rb_cObject);
|
713
738
|
|
714
739
|
rb_define_alloc_func(Document, rb_document_alloc);
|
715
740
|
rb_define_method(Document, "initialize", rb_document_init, 0);
|
@@ -718,6 +743,8 @@ void Init_rnv()
|
|
718
743
|
rb_define_method(Document, "load_string", rb_document_load_string, 1);
|
719
744
|
rb_define_method(Document, "valid?", rb_document_valid, 0);
|
720
745
|
|
746
|
+
rb_define_method(Document, "add_datatype_library", rb_document_add_dtl, 2);
|
747
|
+
|
721
748
|
rb_define_method(Document, "start_document", rb_document_begin, 0);
|
722
749
|
rb_define_method(Document, "start_tag", rb_document_start_tag, 2);
|
723
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.text(str))
|
35
36
|
end
|
36
37
|
|
37
38
|
private
|
@@ -57,25 +58,29 @@ 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|
|
83
|
+
ctx.replace_entities = true
|
79
84
|
rnv_doc.ctx = ctx
|
80
85
|
end
|
81
86
|
|
@@ -84,16 +89,18 @@ module RNV
|
|
84
89
|
|
85
90
|
# parse and validate file
|
86
91
|
# @param [String, File] xml XML file to parse
|
92
|
+
# @param [RNV::PreProcessor] pre_processor an optional pre-processor for tag and attributes data
|
87
93
|
# @return [Boolean] true if valid
|
88
|
-
def parse_file(xml)
|
89
|
-
@document.errors = [] # reset errors
|
94
|
+
def parse_file(xml, pre_processor = PreProcessor.new)
|
90
95
|
@document.start_document
|
91
96
|
rnv_doc = NokogiriSaxDocument.new(@document)
|
97
|
+
rnv_doc.pre_processor = pre_processor
|
92
98
|
|
93
99
|
file = xml.is_a?(File) ? xml : File.open(xml)
|
94
100
|
|
95
101
|
parser = Nokogiri::XML::SAX::Parser.new(rnv_doc)
|
96
102
|
parser.parse(file) do |ctx|
|
103
|
+
ctx.replace_entities = true
|
97
104
|
rnv_doc.ctx = ctx
|
98
105
|
end
|
99
106
|
|
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.1
|
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,8 +147,11 @@ 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
|
-
homepage:
|
154
|
+
homepage: https://github.com/immateriel/ruby_rnv
|
152
155
|
licenses:
|
153
156
|
- MIT
|
154
157
|
metadata: {}
|
@@ -170,5 +173,5 @@ requirements: []
|
|
170
173
|
rubygems_version: 3.0.8
|
171
174
|
signing_key:
|
172
175
|
specification_version: 4
|
173
|
-
summary: RelaxNG compact syntax validator
|
176
|
+
summary: RelaxNG compact syntax validator for Ruby
|
174
177
|
test_files: []
|