Skip to content

Commit

Permalink
Merge pull request #2806 from casperisfine/xslt-stylesheet-typed-data
Browse files Browse the repository at this point in the history
Migrate Nokogiri::XSLT::Stylesheet to the TypedData API
  • Loading branch information
flavorjones authored Mar 3, 2023
2 parents 95fb122 + c75c0dc commit 5ec39e6
Showing 1 changed file with 64 additions and 21 deletions.
85 changes: 64 additions & 21 deletions ext/nokogiri/xslt_stylesheet.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,30 @@
VALUE cNokogiriXsltStylesheet ;

static void
mark(nokogiriXsltStylesheetTuple *wrapper)
mark(void *data)
{
nokogiriXsltStylesheetTuple *wrapper = (nokogiriXsltStylesheetTuple *)data;
rb_gc_mark(wrapper->func_instances);
}

static void
dealloc(nokogiriXsltStylesheetTuple *wrapper)
dealloc(void *data)
{
nokogiriXsltStylesheetTuple *wrapper = (nokogiriXsltStylesheetTuple *)data;
xsltStylesheetPtr doc = wrapper->ss;
xsltFreeStylesheet(doc);
ruby_xfree(wrapper);
}

static const rb_data_type_t xslt_stylesheet_type = {
.wrap_struct_name = "Nokogiri::XSLT::Stylesheet",
.function = {
.dmark = mark,
.dfree = dealloc,
},
.flags = RUBY_TYPED_FREE_IMMEDIATELY
};

PRINTFLIKE_DECL(2, 3)
static void
xslt_generic_error_handler(void *ctx, const char *msg, ...)
Expand All @@ -42,8 +53,12 @@ Nokogiri_wrap_xslt_stylesheet(xsltStylesheetPtr ss)
VALUE self;
nokogiriXsltStylesheetTuple *wrapper;

self = Data_Make_Struct(cNokogiriXsltStylesheet, nokogiriXsltStylesheetTuple,
mark, dealloc, wrapper);
self = TypedData_Make_Struct(
cNokogiriXsltStylesheet,
nokogiriXsltStylesheetTuple,
&xslt_stylesheet_type,
wrapper
);

ss->_private = (void *)self;
wrapper->ss = ss;
Expand Down Expand Up @@ -91,7 +106,7 @@ parse_stylesheet_doc(VALUE klass, VALUE xmldocobj)
* Serialize +document+ to an xml string.
*/
static VALUE
serialize(VALUE self, VALUE xmlobj)
rb_xslt_stylesheet_serialize(VALUE self, VALUE xmlobj)
{
xmlDocPtr xml ;
nokogiriXsltStylesheetTuple *wrapper;
Expand All @@ -100,7 +115,12 @@ serialize(VALUE self, VALUE xmlobj)
VALUE rval ;

Data_Get_Struct(xmlobj, xmlDoc, xml);
Data_Get_Struct(self, nokogiriXsltStylesheetTuple, wrapper);
TypedData_Get_Struct(
self,
nokogiriXsltStylesheetTuple,
&xslt_stylesheet_type,
wrapper
);
xsltSaveResultToString(&doc_ptr, &doc_len, xml, wrapper->ss);
rval = NOKOGIRI_STR_NEW(doc_ptr, doc_len);
xmlFree(doc_ptr);
Expand Down Expand Up @@ -221,7 +241,7 @@ serialize(VALUE self, VALUE xmlobj)
* See: Nokogiri::XSLT.quote_params
*/
static VALUE
transform(int argc, VALUE *argv, VALUE self)
rb_xslt_stylesheet_transform(int argc, VALUE *argv, VALUE self)
{
VALUE xmldoc, paramobj, errstr, exception ;
xmlDocPtr xml ;
Expand All @@ -246,7 +266,7 @@ transform(int argc, VALUE *argv, VALUE self)
Check_Type(paramobj, T_ARRAY);

Data_Get_Struct(xmldoc, xmlDoc, xml);
Data_Get_Struct(self, nokogiriXsltStylesheetTuple, wrapper);
TypedData_Get_Struct(self, nokogiriXsltStylesheetTuple, &xslt_stylesheet_type, wrapper);

param_len = RARRAY_LEN(paramobj);
params = ruby_xcalloc((size_t)param_len + 1, sizeof(char *));
Expand Down Expand Up @@ -290,7 +310,12 @@ method_caller(xmlXPathParserContextPtr ctxt, int nargs)
handler = (VALUE)xsltGetExtData(transform, functionURI);
function_name = (const char *)(ctxt->context->function);

Nokogiri_marshal_xpath_funcall_and_return_values(ctxt, nargs, handler, (const char *)function_name);
Nokogiri_marshal_xpath_funcall_and_return_values(
ctxt,
nargs,
handler,
(const char *)function_name
);
}

static void *
Expand All @@ -306,12 +331,20 @@ initFunc(xsltTransformContextPtr ctxt, const xmlChar *uri)

for (i = 0; i < RARRAY_LEN(methods); i++) {
VALUE method_name = rb_obj_as_string(rb_ary_entry(methods, i));
xsltRegisterExtFunction(ctxt,
(unsigned char *)StringValueCStr(method_name), uri, method_caller);
xsltRegisterExtFunction(
ctxt,
(unsigned char *)StringValueCStr(method_name),
uri,
method_caller
);
}

Data_Get_Struct((VALUE)ctxt->style->_private, nokogiriXsltStylesheetTuple,
wrapper);
TypedData_Get_Struct(
(VALUE)ctxt->style->_private,
nokogiriXsltStylesheetTuple,
&xslt_stylesheet_type,
wrapper
);
inst = rb_class_new_instance(0, NULL, obj);
rb_ary_push(wrapper->func_instances, inst);

Expand All @@ -324,8 +357,12 @@ shutdownFunc(xsltTransformContextPtr ctxt,
{
nokogiriXsltStylesheetTuple *wrapper;

Data_Get_Struct((VALUE)ctxt->style->_private, nokogiriXsltStylesheetTuple,
wrapper);
TypedData_Get_Struct(
(VALUE)ctxt->style->_private,
nokogiriXsltStylesheetTuple,
&xslt_stylesheet_type,
wrapper
);

rb_ary_clear(wrapper->func_instances);
}
Expand All @@ -337,27 +374,33 @@ shutdownFunc(xsltTransformContextPtr ctxt,
* Register a class that implements custom XSLT transformation functions.
*/
static VALUE
registr(VALUE self, VALUE uri, VALUE obj)
rb_xslt_stylesheet_s_register(VALUE self, VALUE uri, VALUE obj)
{
VALUE modules = rb_iv_get(self, "@modules");
if (NIL_P(modules)) { rb_raise(rb_eRuntimeError, "wtf! @modules isn't set"); }
if (NIL_P(modules)) {
rb_raise(rb_eRuntimeError, "internal error: @modules not set");
}

rb_hash_aset(modules, uri, obj);
xsltRegisterExtModule((unsigned char *)StringValueCStr(uri), initFunc, shutdownFunc);
xsltRegisterExtModule(
(unsigned char *)StringValueCStr(uri),
initFunc,
shutdownFunc
);
return self;
}

void
noko_init_xslt_stylesheet(void)
{
rb_define_singleton_method(mNokogiriXslt, "register", registr, 2);
rb_define_singleton_method(mNokogiriXslt, "register", rb_xslt_stylesheet_s_register, 2);
rb_iv_set(mNokogiriXslt, "@modules", rb_hash_new());

cNokogiriXsltStylesheet = rb_define_class_under(mNokogiriXslt, "Stylesheet", rb_cObject);

rb_undef_alloc_func(cNokogiriXsltStylesheet);

rb_define_singleton_method(cNokogiriXsltStylesheet, "parse_stylesheet_doc", parse_stylesheet_doc, 1);
rb_define_method(cNokogiriXsltStylesheet, "serialize", serialize, 1);
rb_define_method(cNokogiriXsltStylesheet, "transform", transform, -1);
rb_define_method(cNokogiriXsltStylesheet, "serialize", rb_xslt_stylesheet_serialize, 1);
rb_define_method(cNokogiriXsltStylesheet, "transform", rb_xslt_stylesheet_transform, -1);
}

0 comments on commit 5ec39e6

Please sign in to comment.