Skip to content

Commit

Permalink
Merge pull request #785 from casperisfine/typed-data
Browse files Browse the repository at this point in the history
Convert Markdown objects to TypedData API
  • Loading branch information
robin850 authored Jun 1, 2024
2 parents 14d3c28 + 9dcf966 commit 71ed87f
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 24 deletions.
20 changes: 15 additions & 5 deletions ext/redcarpet/rc_markdown.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,17 @@ rb_redcarpet_md__free(void *markdown)
sd_markdown_free((struct sd_markdown *)markdown);
}

static const rb_data_type_t rb_redcarpet_md__type = {
"Redcarpet/md",
{
NULL, // Nothing to mark
rb_redcarpet_md__free,
},
0,
0,
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};

static VALUE rb_redcarpet_md__new(int argc, VALUE *argv, VALUE klass)
{
VALUE rb_markdown, rb_rndr, hash, rndr_options;
Expand All @@ -111,7 +122,7 @@ static VALUE rb_redcarpet_md__new(int argc, VALUE *argv, VALUE klass)
if (rb_obj_is_kind_of(rb_rndr, rb_cRenderHTML_TOC))
extensions |= MKDEXT_FENCED_CODE;

Data_Get_Struct(rb_rndr, struct rb_redcarpet_rndr, rndr);
rndr = rb_redcarpet_rndr_unwrap(rb_rndr);

/* Merge the current options in the @options hash */
if (hash != Qnil) {
Expand All @@ -123,7 +134,7 @@ static VALUE rb_redcarpet_md__new(int argc, VALUE *argv, VALUE klass)
if (!markdown)
rb_raise(rb_eRuntimeError, "Failed to create new Renderer class");

rb_markdown = Data_Wrap_Struct(klass, NULL, rb_redcarpet_md__free, markdown);
rb_markdown = TypedData_Wrap_Struct(klass, &rb_redcarpet_md__type, markdown);
rb_iv_set(rb_markdown, "@renderer", rb_rndr);

return rb_markdown;
Expand All @@ -138,15 +149,14 @@ static VALUE rb_redcarpet_md_render(VALUE self, VALUE text)
Check_Type(text, T_STRING);

rb_rndr = rb_iv_get(self, "@renderer");
Data_Get_Struct(self, struct sd_markdown, markdown);
TypedData_Get_Struct(self, struct sd_markdown, &rb_redcarpet_md__type, markdown);

if (rb_respond_to(rb_rndr, rb_intern("preprocess")))
text = rb_funcall(rb_rndr, rb_intern("preprocess"), 1, text);
if (NIL_P(text))
return Qnil;

struct rb_redcarpet_rndr *renderer;
Data_Get_Struct(rb_rndr, struct rb_redcarpet_rndr, renderer);
struct rb_redcarpet_rndr *renderer = rb_redcarpet_rndr_unwrap(rb_rndr);
renderer->options.active_enc = rb_enc_get(text);

/* initialize buffers */
Expand Down
52 changes: 33 additions & 19 deletions ext/redcarpet/rc_render.c
Original file line number Diff line number Diff line change
Expand Up @@ -299,17 +299,6 @@ cb_link_attribute(VALUE key, VALUE val, VALUE payload)
return 0;
}

static void
rndr_link_attributes(struct buf *ob, const struct buf *url, void *opaque)
{
struct redcarpet_renderopt *opt = opaque;
struct rb_redcarpet_rndr *rndr;

Data_Get_Struct(opt->self, struct rb_redcarpet_rndr, rndr);
Check_Type(opt->link_attributes, T_HASH);
rb_hash_foreach(opt->link_attributes, &cb_link_attribute, (VALUE)ob);
}

static struct sd_callbacks rb_redcarpet_callbacks = {
rndr_blockcode,
rndr_blockquote,
Expand Down Expand Up @@ -388,30 +377,55 @@ static const char *rb_redcarpet_method_names[] = {

static const size_t rb_redcarpet_method_count = sizeof(rb_redcarpet_method_names)/sizeof(char *);

static void rb_redcarpet_rbase_mark(struct rb_redcarpet_rndr *rndr)
static void rb_redcarpet_rbase_mark(void *data)
{
struct rb_redcarpet_rndr *rndr = (struct rb_redcarpet_rndr *)data;
if (rndr->options.link_attributes)
rb_gc_mark(rndr->options.link_attributes);
}

static void rndr_deallocate(void *rndr)
static const rb_data_type_t rb_redcarpet_rndr_type = {
"Redcarpet/rndr",
{
rb_redcarpet_rbase_mark,
RUBY_TYPED_DEFAULT_FREE,
},
0,
0,
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};

struct rb_redcarpet_rndr * rb_redcarpet_rndr_unwrap(VALUE self)
{
xfree(rndr);
struct rb_redcarpet_rndr *rndr;
TypedData_Get_Struct(self, struct rb_redcarpet_rndr, &rb_redcarpet_rndr_type, rndr);
return rndr;
}

static VALUE rb_redcarpet_rbase_alloc(VALUE klass)
{
struct rb_redcarpet_rndr *rndr = ALLOC(struct rb_redcarpet_rndr);
memset(rndr, 0x0, sizeof(struct rb_redcarpet_rndr));
return Data_Wrap_Struct(klass, rb_redcarpet_rbase_mark, rndr_deallocate, rndr);
return TypedData_Wrap_Struct(klass, &rb_redcarpet_rndr_type, rndr);
}

static void
rndr_link_attributes(struct buf *ob, const struct buf *url, void *opaque)
{
struct redcarpet_renderopt *opt = opaque;
struct rb_redcarpet_rndr *rndr;

TypedData_Get_Struct(opt->self, struct rb_redcarpet_rndr, &rb_redcarpet_rndr_type, rndr);
Check_Type(opt->link_attributes, T_HASH);
rb_hash_foreach(opt->link_attributes, &cb_link_attribute, (VALUE)ob);
}

static void rb_redcarpet__overload(VALUE self, VALUE base_class)
{
struct rb_redcarpet_rndr *rndr;
VALUE options_ivar;

Data_Get_Struct(self, struct rb_redcarpet_rndr, rndr);
TypedData_Get_Struct(self, struct rb_redcarpet_rndr, &rb_redcarpet_rndr_type, rndr);
rndr->options.self = self;
rndr->options.base_class = base_class;

Expand Down Expand Up @@ -448,7 +462,7 @@ static VALUE rb_redcarpet_html_init(int argc, VALUE *argv, VALUE self)
unsigned int render_flags = 0;
VALUE hash, link_attr = Qnil;

Data_Get_Struct(self, struct rb_redcarpet_rndr, rndr);
TypedData_Get_Struct(self, struct rb_redcarpet_rndr, &rb_redcarpet_rndr_type, rndr);

if (rb_scan_args(argc, argv, "01", &hash) == 1) {
Check_Type(hash, T_HASH);
Expand Down Expand Up @@ -500,7 +514,7 @@ static VALUE rb_redcarpet_html_init(int argc, VALUE *argv, VALUE self)
rb_redcarpet__overload(self, rb_cRenderHTML);

if (!NIL_P(link_attr)) {
rndr->options.link_attributes = link_attr;
RB_OBJ_WRITE(self, &rndr->options.link_attributes, link_attr);
rndr->options.html.link_attributes = &rndr_link_attributes;
}

Expand All @@ -513,7 +527,7 @@ static VALUE rb_redcarpet_htmltoc_init(int argc, VALUE *argv, VALUE self)
unsigned int render_flags = HTML_TOC;
VALUE hash, nesting_level = Qnil;

Data_Get_Struct(self, struct rb_redcarpet_rndr, rndr);
TypedData_Get_Struct(self, struct rb_redcarpet_rndr, &rb_redcarpet_rndr_type, rndr);

if (rb_scan_args(argc, argv, "01", &hash) == 1) {
Check_Type(hash, T_HASH);
Expand Down
2 changes: 2 additions & 0 deletions ext/redcarpet/redcarpet.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,6 @@ struct rb_redcarpet_rndr {
struct redcarpet_renderopt options;
};

struct rb_redcarpet_rndr * rb_redcarpet_rndr_unwrap(VALUE);

#endif

0 comments on commit 71ed87f

Please sign in to comment.