ruby_rnv 0.2.1 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|