/
ruby_xml_dtd.c
155 lines (131 loc) · 4.28 KB
/
ruby_xml_dtd.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include "libxml.h"
#include "ruby_xml_dtd.h"
VALUE cXMLDtd;
void
ruby_xml_dtd_free(ruby_xml_dtd *rxdtd) {
if (rxdtd->dtd != NULL) {
xmlFreeDtd(rxdtd->dtd);
rxdtd->dtd = NULL;
}
free(rxdtd);
}
static void
ruby_xml_dtd_mark(ruby_xml_dtd *rxdtd) {
return;
//if (rxdtd == NULL) return;
//if (!NIL_P(rxd->xmlver)) rb_gc_mark(rxd->xmlver);
}
VALUE
ruby_xml_dtd_initialize(int argc, VALUE *argv, VALUE class) {
ruby_xml_dtd *rxdtd;
VALUE external, system, dtd_string;
xmlParserInputBufferPtr buffer;
xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
xmlChar *new_string;
// 1 argument -- string --> parsujeme jako dtd
// 2 argumenty -- public, system --> bude se hledat
switch (argc) {
case 2:
rb_scan_args(argc, argv, "20", &external, &system);
Check_Type(external, T_STRING);
Check_Type(system, T_STRING);
rxdtd = ALLOC(ruby_xml_dtd);
rxdtd->dtd = xmlParseDTD( (const xmlChar*)STR2CSTR(external),
(const xmlChar*)STR2CSTR(system) );
if (rxdtd->dtd == NULL) {
free(rxdtd);
return(Qfalse);
}
xmlSetTreeDoc( (xmlNodePtr)rxdtd->dtd, NULL );
return( Data_Wrap_Struct(cXMLDtd, ruby_xml_dtd_mark, ruby_xml_dtd_free, rxdtd) );
break;
/*
SV *
new(CLASS, external, system)
char * CLASS
char * external
char * system
ALIAS:
parse_uri = 1
PREINIT:
xmlDtdPtr dtd = NULL;
CODE:
LibXML_error = sv_2mortal(newSVpv("", 0));
dtd = xmlParseDTD((const xmlChar*)external, (const xmlChar*)system);
if ( dtd == NULL ) {
XSRETURN_UNDEF;
}
xmlSetTreeDoc((xmlNodePtr)dtd, NULL);
RETVAL = PmmNodeToSv( (xmlNodePtr) dtd, NULL );
OUTPUT:
RETVAL
*/
case 1:
rb_scan_args(argc, argv, "10", &dtd_string);
buffer = xmlAllocParserInputBuffer(enc);
//if ( !buffer) return Qnil
new_string = xmlStrdup((const xmlChar*)STR2CSTR(dtd_string));
xmlParserInputBufferPush(buffer, xmlStrlen(new_string), (const char*)new_string);
rxdtd = ALLOC(ruby_xml_dtd);
rxdtd->dtd = xmlIOParseDTD(NULL, buffer, enc);
// NOTE: For some reason freeing this InputBuffer causes a segfault!
// xmlFreeParserInputBuffer(buffer);
xmlFree(new_string);
return( Data_Wrap_Struct(cXMLDtd, ruby_xml_dtd_mark, ruby_xml_dtd_free, rxdtd) );
break;
/*
SV * parse_string(CLASS, str, ...)
char * CLASS
char * str
PREINIT:
STRLEN n_a;
xmlDtdPtr res;
SV * encoding_sv;
xmlParserInputBufferPtr buffer;
xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
xmlChar * new_string;
STRLEN len;
CODE:
LibXML_init_error();
if (items > 2) {
encoding_sv = ST(2);
if (items > 3) {
croak("parse_string: too many parameters");
}
// warn("getting encoding...\n");
enc = xmlParseCharEncoding(SvPV(encoding_sv, n_a));
if (enc == XML_CHAR_ENCODING_ERROR) {
croak("Parse of encoding %s failed: %s", SvPV(encoding_sv, n_a), SvPV(LibXML_error, n_a));
}
}
buffer = xmlAllocParserInputBuffer(enc);
// buffer = xmlParserInputBufferCreateMem(str, xmlStrlen(str), enc);
if ( !buffer)
croak("cant create buffer!\n" );
new_string = xmlStrdup((const xmlChar*)str);
xmlParserInputBufferPush(buffer, xmlStrlen(new_string), (const char*)new_string);
res = xmlIOParseDTD(NULL, buffer, enc);
// NOTE: For some reason freeing this InputBuffer causes a segfault!
// xmlFreeParserInputBuffer(buffer);
xmlFree(new_string);
sv_2mortal( LibXML_error );
LibXML_croak_error();
if (res == NULL) {
croak("no DTD parsed!");
}
RETVAL = PmmNodeToSv((xmlNodePtr)res, NULL);
OUTPUT:
RETVAL
*/
default:
rb_raise(rb_eArgError, "wrong number of arguments (need 1 or 2)");
}
//docobj = ruby_xml_document_new2(cXMLDocument, xmlver);
return Qnil;
}
void
ruby_init_xml_dtd(void) {
cXMLDtd = rb_define_class_under(mXML, "Dtd", rb_cObject);
rb_define_singleton_method(cXMLDtd, "new", ruby_xml_dtd_initialize, -1);
//rb_define_method(cXMLDocument, "xinclude", ruby_xml_document_xinclude, 0);
}