Skip to content
This repository has been archived by the owner on Aug 26, 2023. It is now read-only.

Commit

Permalink
Wrap ParseArgs in a Ruby object
Browse files Browse the repository at this point in the history
The functions passed to `rb_ensure` should be `VALUE`s. It's probably
the case that Ruby is going to pass these directly without ever
examining them, but maybe not.

This wraps the `ParseArgs` pointer as a Ruby object (of class `Data`
which is what the documentation seems to suggest rather than class
`Object`, but `Data` is also deprecated so who knows?).

This fixes several compilation warnings about mismatched types.
  • Loading branch information
stevecheckoway committed Nov 21, 2020
1 parent 55d7b96 commit a624096
Showing 1 changed file with 36 additions and 8 deletions.
44 changes: 36 additions & 8 deletions ext/nokogumbo/nokogumbo.c
Original file line number Diff line number Diff line change
Expand Up @@ -480,15 +480,38 @@ typedef struct {
xmlDocPtr doc;
} ParseArgs;

static VALUE parse_cleanup(ParseArgs *args) {
static void parse_args_mark(void *parse_args) {
ParseArgs *args = parse_args;
rb_gc_mark_maybe(args->input);
rb_gc_mark_maybe(args->url_or_frag);
}

// Wrap a ParseArgs pointer. The underlying ParseArgs must outlive the
// wrapper.
static VALUE wrap_parse_args(ParseArgs *args) {
return Data_Wrap_Struct(rb_cData, parse_args_mark, RUBY_NEVER_FREE, args);
}

// Returnsd the underlying ParseArgs wrapped by wrap_parse_args.
static ParseArgs *unwrap_parse_args(VALUE obj) {
ParseArgs *args;
Data_Get_Struct(obj, ParseArgs, args);
return args;
}

static VALUE parse_cleanup(VALUE parse_args) {
ParseArgs *args = unwrap_parse_args(parse_args);
gumbo_destroy_output(args->output);
// Make sure garbage collection doesn't mark the objects as being live based
// on references from the ParseArgs. This may be unnecessary.
args->input = Qnil;
args->url_or_frag = Qnil;
if (args->doc != NIL)
xmlFreeDoc(args->doc);
return Qnil;
}


static VALUE parse_continue(ParseArgs *args);
static VALUE parse_continue(VALUE parse_args);

// Parse a string using gumbo_parse into a Nokogiri document
static VALUE parse(VALUE self, VALUE input, VALUE url, VALUE max_attributes, VALUE max_errors, VALUE max_depth) {
Expand All @@ -504,10 +527,13 @@ static VALUE parse(VALUE self, VALUE input, VALUE url, VALUE max_attributes, VAL
.url_or_frag = url,
.doc = NIL,
};
return rb_ensure(parse_continue, (VALUE)&args, parse_cleanup, (VALUE)&args);
VALUE parse_args = wrap_parse_args(&args);

return rb_ensure(parse_continue, parse_args, parse_cleanup, parse_args);
}

static VALUE parse_continue(ParseArgs *args) {
static VALUE parse_continue(VALUE parse_args) {
ParseArgs *args = unwrap_parse_args(parse_args);
GumboOutput *output = args->output;
xmlDocPtr doc;
if (output->document->v.document.has_doctype) {
Expand Down Expand Up @@ -565,7 +591,7 @@ static xmlNodePtr extract_xml_node(VALUE node) {
#endif
}

static VALUE fragment_continue(ParseArgs *args);
static VALUE fragment_continue(VALUE parse_args);

static VALUE fragment (
VALUE self,
Expand Down Expand Up @@ -696,11 +722,13 @@ static VALUE fragment (
.url_or_frag = doc_fragment,
.doc = (xmlDocPtr)extract_xml_node(doc),
};
rb_ensure(fragment_continue, (VALUE)&args, parse_cleanup, (VALUE)&args);
VALUE parse_args = wrap_parse_args(&args);
rb_ensure(fragment_continue, parse_args, parse_cleanup, parse_args);
return Qnil;
}

static VALUE fragment_continue(ParseArgs *args) {
static VALUE fragment_continue(VALUE parse_args) {
ParseArgs *args = unwrap_parse_args(parse_args);
GumboOutput *output = args->output;
VALUE doc_fragment = args->url_or_frag;
xmlDocPtr xml_doc = args->doc;
Expand Down

0 comments on commit a624096

Please sign in to comment.