Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change all T_DATA objects to typed data #349

Merged
merged 9 commits into from
Aug 30, 2020
5 changes: 5 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ matrix:
env:
- "PGVERSION=12"

- rvm: truffleruby-head
env:
- "PGVERSION=12"

- name: gem-windows
rvm: "2.7"
before_install:
Expand All @@ -43,6 +47,7 @@ matrix:
- rake gem:windows:x86-mingw32
allow_failures:
- rvm: ruby-head
- rvm: truffleruby-head
fast_finish: true

before_install:
Expand Down
1 change: 1 addition & 0 deletions ext/extconf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
have_func 'PQresultMemorySize' # since PostgreSQL-12
have_func 'timegm'
have_func 'rb_gc_adjust_memory_usage' # since ruby-2.4
have_func 'rb_gc_mark_movable' # since ruby-2.7

# unistd.h confilicts with ruby/win32.h when cross compiling for win32 and ruby 1.9.1
have_header 'unistd.h'
Expand Down
15 changes: 14 additions & 1 deletion ext/pg.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,15 @@ typedef long suseconds_t;
#define RARRAY_AREF(a, i) (RARRAY_PTR(a)[i])
#endif

#ifdef HAVE_RB_GC_MARK_MOVABLE
#define pg_compact_callback(x) ((void (*)(void*))(x))
#define pg_gc_location(x) x = rb_gc_location(x)
#else
#define rb_gc_mark_movable(x) rb_gc_mark(x)
#define pg_compact_callback(x) {(x)}
#define pg_gc_location(x) UNUSED(x)
#endif

#define PG_ENC_IDX_BITS 28

/* The data behind each PG::Connection object */
Expand Down Expand Up @@ -220,6 +229,8 @@ typedef struct {
} convs[0];
} t_tmbc;

extern const rb_data_type_t pg_typemap_type;
extern const rb_data_type_t pg_coder_type;

#include "gvl_wrappers.h"

Expand Down Expand Up @@ -304,7 +315,7 @@ VALUE pg_obj_to_i _(( VALUE ));
VALUE pg_tmbc_allocate _(( void ));
void pg_coder_init_encoder _(( VALUE ));
void pg_coder_init_decoder _(( VALUE ));
void pg_coder_mark _(( t_pg_coder * ));
void pg_coder_compact _(( t_pg_coder * ));
char *pg_rb_str_ensure_capa _(( VALUE, long, char *, char ** ));

#define PG_RB_STR_ENSURE_CAPA( str, expand_len, curr_ptr, end_ptr ) \
Expand All @@ -324,6 +335,8 @@ int pg_typemap_fit_to_copy_get _(( VALUE ));
VALUE pg_typemap_result_value _(( t_typemap *, VALUE, int, int ));
t_pg_coder *pg_typemap_typecast_query_param _(( t_typemap *, VALUE, int ));
VALUE pg_typemap_typecast_copy_get _(( t_typemap *, VALUE, int, int, int ));
void pg_typemap_mark _(( t_typemap * ));
void pg_typemap_compact _(( t_typemap * ));

PGconn *pg_get_pgconn _(( VALUE ));
t_pg_connection *pg_get_connection _(( VALUE ));
Expand Down
92 changes: 65 additions & 27 deletions ext/pg_coder.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ pg_coder_allocate( VALUE klass )
void
pg_coder_init_encoder( VALUE self )
{
t_pg_coder *this = DATA_PTR( self );
t_pg_coder *this = RTYPEDDATA_DATA( self );
VALUE klass = rb_class_of(self);
if( rb_const_defined( klass, s_id_CFUNC ) ){
VALUE cfunc = rb_const_get( klass, s_id_CFUNC );
this->enc_func = DATA_PTR(cfunc);
this->enc_func = RTYPEDDATA_DATA(cfunc);
} else {
this->enc_func = NULL;
}
Expand All @@ -45,12 +45,12 @@ pg_coder_init_encoder( VALUE self )
void
pg_coder_init_decoder( VALUE self )
{
t_pg_coder *this = DATA_PTR( self );
t_pg_coder *this = RTYPEDDATA_DATA( self );
VALUE klass = rb_class_of(self);
this->enc_func = NULL;
if( rb_const_defined( klass, s_id_CFUNC ) ){
VALUE cfunc = rb_const_get( klass, s_id_CFUNC );
this->dec_func = DATA_PTR(cfunc);
this->dec_func = RTYPEDDATA_DATA(cfunc);
} else {
this->dec_func = NULL;
}
Expand All @@ -62,31 +62,57 @@ pg_coder_init_decoder( VALUE self )
}

void
pg_coder_mark(t_pg_coder *this)
pg_coder_compact(t_pg_coder *this)
{
rb_gc_mark(this->coder_obj);
pg_gc_location(this->coder_obj);
}

static void
pg_composite_coder_mark(t_pg_composite_coder *this)
pg_composite_coder_compact(t_pg_composite_coder *this)
{
pg_coder_mark(&this->comp);
pg_coder_compact(&this->comp);
}

const rb_data_type_t pg_coder_type = {
"PG::Coder",
{
(void (*)(void*))NULL,
(void (*)(void*))-1,
(size_t (*)(const void *))NULL,
pg_compact_callback(pg_coder_compact),
},
0,
0,
RUBY_TYPED_FREE_IMMEDIATELY,
};

static VALUE
pg_simple_encoder_allocate( VALUE klass )
{
t_pg_coder *this;
VALUE self = Data_Make_Struct( klass, t_pg_coder, pg_coder_mark, -1, this );
VALUE self = TypedData_Make_Struct( klass, t_pg_coder, &pg_coder_type, this );
pg_coder_init_encoder( self );
return self;
}

static const rb_data_type_t pg_composite_coder_type = {
"PG::CompositeCoder",
{
(void (*)(void*))NULL,
(void (*)(void*))-1,
(size_t (*)(const void *))NULL,
pg_compact_callback(pg_composite_coder_compact),
},
&pg_coder_type,
0,
RUBY_TYPED_FREE_IMMEDIATELY,
};

static VALUE
pg_composite_encoder_allocate( VALUE klass )
{
t_pg_composite_coder *this;
VALUE self = Data_Make_Struct( klass, t_pg_composite_coder, pg_composite_coder_mark, -1, this );
VALUE self = TypedData_Make_Struct( klass, t_pg_composite_coder, &pg_composite_coder_type, this );
pg_coder_init_encoder( self );
this->elem = NULL;
this->needs_quotation = 1;
Expand All @@ -99,7 +125,7 @@ static VALUE
pg_simple_decoder_allocate( VALUE klass )
{
t_pg_coder *this;
VALUE self = Data_Make_Struct( klass, t_pg_coder, pg_coder_mark, -1, this );
VALUE self = TypedData_Make_Struct( klass, t_pg_coder, &pg_coder_type, this );
pg_coder_init_decoder( self );
return self;
}
Expand All @@ -108,7 +134,7 @@ static VALUE
pg_composite_decoder_allocate( VALUE klass )
{
t_pg_composite_coder *this;
VALUE self = Data_Make_Struct( klass, t_pg_composite_coder, pg_composite_coder_mark, -1, this );
VALUE self = TypedData_Make_Struct( klass, t_pg_composite_coder, &pg_composite_coder_type, this );
pg_coder_init_decoder( self );
this->elem = NULL;
this->needs_quotation = 1;
Expand All @@ -135,7 +161,7 @@ pg_coder_encode(int argc, VALUE *argv, VALUE self)
VALUE value;
int len, len2;
int enc_idx;
t_pg_coder *this = DATA_PTR(self);
t_pg_coder *this = RTYPEDDATA_DATA(self);

if(argc < 1 || argc > 2){
rb_raise(rb_eArgError, "wrong number of arguments (%i for 1..2)", argc);
Expand Down Expand Up @@ -192,7 +218,7 @@ pg_coder_decode(int argc, VALUE *argv, VALUE self)
int tuple = -1;
int field = -1;
VALUE res;
t_pg_coder *this = DATA_PTR(self);
t_pg_coder *this = RTYPEDDATA_DATA(self);

if(argc < 1 || argc > 3){
rb_raise(rb_eArgError, "wrong number of arguments (%i for 1..3)", argc);
Expand Down Expand Up @@ -230,7 +256,7 @@ pg_coder_decode(int argc, VALUE *argv, VALUE self)
static VALUE
pg_coder_oid_set(VALUE self, VALUE oid)
{
t_pg_coder *this = DATA_PTR(self);
t_pg_coder *this = RTYPEDDATA_DATA(self);
this->oid = NUM2UINT(oid);
return oid;
}
Expand All @@ -245,7 +271,7 @@ pg_coder_oid_set(VALUE self, VALUE oid)
static VALUE
pg_coder_oid_get(VALUE self)
{
t_pg_coder *this = DATA_PTR(self);
t_pg_coder *this = RTYPEDDATA_DATA(self);
return UINT2NUM(this->oid);
}

Expand All @@ -261,7 +287,7 @@ pg_coder_oid_get(VALUE self)
static VALUE
pg_coder_format_set(VALUE self, VALUE format)
{
t_pg_coder *this = DATA_PTR(self);
t_pg_coder *this = RTYPEDDATA_DATA(self);
this->format = NUM2INT(format);
return format;
}
Expand All @@ -276,7 +302,7 @@ pg_coder_format_set(VALUE self, VALUE format)
static VALUE
pg_coder_format_get(VALUE self)
{
t_pg_coder *this = DATA_PTR(self);
t_pg_coder *this = RTYPEDDATA_DATA(self);
return INT2NUM(this->format);
}

Expand All @@ -292,7 +318,7 @@ pg_coder_format_get(VALUE self)
static VALUE
pg_coder_flags_set(VALUE self, VALUE flags)
{
t_pg_coder *this = DATA_PTR(self);
t_pg_coder *this = RTYPEDDATA_DATA(self);
this->flags = NUM2INT(flags);
return flags;
}
Expand All @@ -306,7 +332,7 @@ pg_coder_flags_set(VALUE self, VALUE flags)
static VALUE
pg_coder_flags_get(VALUE self)
{
t_pg_coder *this = DATA_PTR(self);
t_pg_coder *this = RTYPEDDATA_DATA(self);
return INT2NUM(this->flags);
}

Expand All @@ -323,7 +349,7 @@ pg_coder_flags_get(VALUE self)
static VALUE
pg_coder_needs_quotation_set(VALUE self, VALUE needs_quotation)
{
t_pg_composite_coder *this = DATA_PTR(self);
t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
this->needs_quotation = RTEST(needs_quotation);
return needs_quotation;
}
Expand All @@ -338,7 +364,7 @@ pg_coder_needs_quotation_set(VALUE self, VALUE needs_quotation)
static VALUE
pg_coder_needs_quotation_get(VALUE self)
{
t_pg_composite_coder *this = DATA_PTR(self);
t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
return this->needs_quotation ? Qtrue : Qfalse;
}

Expand All @@ -353,7 +379,7 @@ pg_coder_needs_quotation_get(VALUE self)
static VALUE
pg_coder_delimiter_set(VALUE self, VALUE delimiter)
{
t_pg_composite_coder *this = DATA_PTR(self);
t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
StringValue(delimiter);
if(RSTRING_LEN(delimiter) != 1)
rb_raise( rb_eArgError, "delimiter size must be one byte");
Expand All @@ -370,7 +396,7 @@ pg_coder_delimiter_set(VALUE self, VALUE delimiter)
static VALUE
pg_coder_delimiter_get(VALUE self)
{
t_pg_composite_coder *this = DATA_PTR(self);
t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
return rb_str_new(&this->delimiter, 1);
}

Expand All @@ -386,12 +412,12 @@ pg_coder_delimiter_get(VALUE self)
static VALUE
pg_coder_elements_type_set(VALUE self, VALUE elem_type)
{
t_pg_composite_coder *this = DATA_PTR( self );
t_pg_composite_coder *this = RTYPEDDATA_DATA( self );

if ( NIL_P(elem_type) ){
this->elem = NULL;
} else if ( rb_obj_is_kind_of(elem_type, rb_cPG_Coder) ){
this->elem = DATA_PTR( elem_type );
this->elem = RTYPEDDATA_DATA( elem_type );
} else {
rb_raise( rb_eTypeError, "wrong elements type %s (expected some kind of PG::Coder)",
rb_obj_classname( elem_type ) );
Expand All @@ -401,10 +427,22 @@ pg_coder_elements_type_set(VALUE self, VALUE elem_type)
return elem_type;
}

static const rb_data_type_t pg_coder_cfunc_type = {
"PG::Coder::CFUNC",
{
(void (*)(void*))NULL,
(void (*)(void*))NULL,
(size_t (*)(const void *))NULL,
},
0,
0,
RUBY_TYPED_FREE_IMMEDIATELY,
};

void
pg_define_coder( const char *name, void *func, VALUE base_klass, VALUE nsp )
{
VALUE cfunc_obj = Data_Wrap_Struct( rb_cObject, NULL, NULL, func );
VALUE cfunc_obj = TypedData_Wrap_Struct( rb_cObject, &pg_coder_cfunc_type, func );
VALUE coder_klass = rb_define_class_under( nsp, name, base_klass );
if( nsp==rb_mPG_BinaryEncoder || nsp==rb_mPG_BinaryDecoder )
rb_include_module( coder_klass, rb_mPG_BinaryFormatting );
Expand Down
Loading