pg 1.4.4 → 1.5.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/Gemfile +6 -0
- data/{History.rdoc → History.md} +303 -151
- data/README.ja.md +300 -0
- data/README.md +286 -0
- data/Rakefile +16 -4
- data/Rakefile.cross +15 -14
- data/certs/kanis@comcard.de.pem +20 -0
- data/certs/larskanis-2023.pem +24 -0
- data/certs/larskanis-2024.pem +24 -0
- data/ext/errorcodes.def +8 -5
- data/ext/errorcodes.txt +3 -5
- data/ext/extconf.rb +7 -0
- data/ext/pg.c +15 -30
- data/ext/pg.h +10 -6
- data/ext/pg_binary_decoder.c +81 -0
- data/ext/pg_binary_encoder.c +224 -0
- data/ext/pg_coder.c +16 -7
- data/ext/pg_connection.c +220 -82
- data/ext/pg_copy_coder.c +315 -22
- data/ext/pg_record_coder.c +11 -10
- data/ext/pg_result.c +93 -19
- data/ext/pg_text_decoder.c +31 -10
- data/ext/pg_text_encoder.c +38 -19
- data/ext/pg_tuple.c +34 -31
- data/ext/pg_type_map.c +3 -2
- data/ext/pg_type_map_all_strings.c +2 -2
- data/ext/pg_type_map_by_class.c +5 -3
- data/ext/pg_type_map_by_column.c +7 -3
- data/ext/pg_type_map_by_oid.c +7 -4
- data/ext/pg_type_map_in_ruby.c +5 -2
- data/lib/pg/basic_type_map_based_on_result.rb +21 -1
- data/lib/pg/basic_type_map_for_queries.rb +19 -10
- data/lib/pg/basic_type_map_for_results.rb +26 -3
- data/lib/pg/basic_type_registry.rb +44 -34
- data/lib/pg/binary_decoder/date.rb +9 -0
- data/lib/pg/binary_decoder/timestamp.rb +26 -0
- data/lib/pg/binary_encoder/timestamp.rb +20 -0
- data/lib/pg/coder.rb +15 -13
- data/lib/pg/connection.rb +158 -64
- data/lib/pg/exceptions.rb +13 -0
- data/lib/pg/text_decoder/date.rb +21 -0
- data/lib/pg/text_decoder/inet.rb +9 -0
- data/lib/pg/text_decoder/json.rb +17 -0
- data/lib/pg/text_decoder/numeric.rb +9 -0
- data/lib/pg/text_decoder/timestamp.rb +30 -0
- data/lib/pg/text_encoder/date.rb +13 -0
- data/lib/pg/text_encoder/inet.rb +31 -0
- data/lib/pg/text_encoder/json.rb +17 -0
- data/lib/pg/text_encoder/numeric.rb +9 -0
- data/lib/pg/text_encoder/timestamp.rb +24 -0
- data/lib/pg/version.rb +1 -1
- data/lib/pg.rb +65 -15
- data/pg.gemspec +7 -3
- data/rakelib/task_extension.rb +1 -1
- data.tar.gz.sig +2 -4
- metadata +104 -46
- metadata.gz.sig +0 -0
- data/.appveyor.yml +0 -36
- data/.gems +0 -6
- data/.gemtest +0 -0
- data/.github/workflows/binary-gems.yml +0 -86
- data/.github/workflows/source-gem.yml +0 -131
- data/.gitignore +0 -13
- data/.hgsigs +0 -34
- data/.hgtags +0 -41
- data/.irbrc +0 -23
- data/.pryrc +0 -23
- data/.tm_properties +0 -21
- data/.travis.yml +0 -49
- data/README.ja.rdoc +0 -13
- data/README.rdoc +0 -233
- data/lib/pg/binary_decoder.rb +0 -23
- data/lib/pg/constants.rb +0 -12
- data/lib/pg/text_decoder.rb +0 -46
- data/lib/pg/text_encoder.rb +0 -59
data/ext/pg_binary_encoder.c
CHANGED
@@ -11,6 +11,9 @@
|
|
11
11
|
#endif
|
12
12
|
|
13
13
|
VALUE rb_mPG_BinaryEncoder;
|
14
|
+
static ID s_id_year;
|
15
|
+
static ID s_id_month;
|
16
|
+
static ID s_id_day;
|
14
17
|
|
15
18
|
|
16
19
|
/*
|
@@ -93,6 +96,215 @@ pg_bin_enc_int8(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, i
|
|
93
96
|
return 8;
|
94
97
|
}
|
95
98
|
|
99
|
+
/*
|
100
|
+
* Document-class: PG::BinaryEncoder::Float4 < PG::SimpleEncoder
|
101
|
+
*
|
102
|
+
* This is the binary encoder class for the PostgreSQL +float4+ type.
|
103
|
+
*
|
104
|
+
*/
|
105
|
+
static int
|
106
|
+
pg_bin_enc_float4(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
107
|
+
{
|
108
|
+
union {
|
109
|
+
float f;
|
110
|
+
int32_t i;
|
111
|
+
} swap4;
|
112
|
+
|
113
|
+
if(out){
|
114
|
+
swap4.f = NUM2DBL(*intermediate);
|
115
|
+
write_nbo32(swap4.i, out);
|
116
|
+
}else{
|
117
|
+
*intermediate = value;
|
118
|
+
}
|
119
|
+
return 4;
|
120
|
+
}
|
121
|
+
|
122
|
+
/*
|
123
|
+
* Document-class: PG::BinaryEncoder::Float8 < PG::SimpleEncoder
|
124
|
+
*
|
125
|
+
* This is the binary encoder class for the PostgreSQL +float8+ type.
|
126
|
+
*
|
127
|
+
*/
|
128
|
+
static int
|
129
|
+
pg_bin_enc_float8(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
130
|
+
{
|
131
|
+
union {
|
132
|
+
double f;
|
133
|
+
int64_t i;
|
134
|
+
} swap8;
|
135
|
+
|
136
|
+
if(out){
|
137
|
+
swap8.f = NUM2DBL(*intermediate);
|
138
|
+
write_nbo64(swap8.i, out);
|
139
|
+
}else{
|
140
|
+
*intermediate = value;
|
141
|
+
}
|
142
|
+
return 8;
|
143
|
+
}
|
144
|
+
|
145
|
+
#define PG_INT32_MIN (-0x7FFFFFFF-1)
|
146
|
+
#define PG_INT32_MAX (0x7FFFFFFF)
|
147
|
+
#define PG_INT64_MIN (-0x7FFFFFFFFFFFFFFFL - 1)
|
148
|
+
#define PG_INT64_MAX 0x7FFFFFFFFFFFFFFFL
|
149
|
+
|
150
|
+
/*
|
151
|
+
* Document-class: PG::BinaryEncoder::Timestamp < PG::SimpleEncoder
|
152
|
+
*
|
153
|
+
* This is a encoder class for conversion of Ruby Time objects to PostgreSQL binary timestamps.
|
154
|
+
*
|
155
|
+
* The following flags can be used to specify timezone interpretation:
|
156
|
+
* * +PG::Coder::TIMESTAMP_DB_UTC+ : Send timestamp as UTC time (default)
|
157
|
+
* * +PG::Coder::TIMESTAMP_DB_LOCAL+ : Send timestamp as local time (slower)
|
158
|
+
*
|
159
|
+
* Example:
|
160
|
+
* enco = PG::BinaryEncoder::Timestamp.new(flags: PG::Coder::TIMESTAMP_DB_UTC)
|
161
|
+
* enco.encode(Time.utc(2000, 1, 1)) # => "\x00\x00\x00\x00\x00\x00\x00\x00"
|
162
|
+
*
|
163
|
+
* String values are expected to contain a binary data with a length of 8 byte.
|
164
|
+
*
|
165
|
+
*/
|
166
|
+
static int
|
167
|
+
pg_bin_enc_timestamp(t_pg_coder *this, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
168
|
+
{
|
169
|
+
if(out){
|
170
|
+
int64_t timestamp;
|
171
|
+
struct timespec ts;
|
172
|
+
|
173
|
+
/* second call -> write data to *out */
|
174
|
+
switch(TYPE(*intermediate)){
|
175
|
+
case T_STRING:
|
176
|
+
return pg_coder_enc_to_s(this, value, out, intermediate, enc_idx);
|
177
|
+
case T_TRUE:
|
178
|
+
write_nbo64(PG_INT64_MAX, out);
|
179
|
+
return 8;
|
180
|
+
case T_FALSE:
|
181
|
+
write_nbo64(PG_INT64_MIN, out);
|
182
|
+
return 8;
|
183
|
+
}
|
184
|
+
|
185
|
+
ts = rb_time_timespec(*intermediate);
|
186
|
+
/* PostgreSQL's timestamp is based on year 2000 and Ruby's time is based on 1970.
|
187
|
+
* Adjust the 30 years difference. */
|
188
|
+
timestamp = ((int64_t)ts.tv_sec - 10957L * 24L * 3600L) * 1000000 + ((int64_t)ts.tv_nsec / 1000);
|
189
|
+
|
190
|
+
if( this->flags & PG_CODER_TIMESTAMP_DB_LOCAL ) {
|
191
|
+
/* send as local time */
|
192
|
+
timestamp += NUM2LL(rb_funcall(*intermediate, rb_intern("utc_offset"), 0)) * 1000000;
|
193
|
+
}
|
194
|
+
|
195
|
+
write_nbo64(timestamp, out);
|
196
|
+
}else{
|
197
|
+
/* first call -> determine the required length */
|
198
|
+
if(TYPE(value) == T_STRING){
|
199
|
+
char *pstr = RSTRING_PTR(value);
|
200
|
+
if(RSTRING_LEN(value) >= 1){
|
201
|
+
switch(pstr[0]) {
|
202
|
+
case 'I':
|
203
|
+
case 'i':
|
204
|
+
*intermediate = Qtrue;
|
205
|
+
return 8;
|
206
|
+
case '-':
|
207
|
+
if (RSTRING_LEN(value) >= 2 && (pstr[1] == 'I' || pstr[1] == 'i')) {
|
208
|
+
*intermediate = Qfalse;
|
209
|
+
return 8;
|
210
|
+
}
|
211
|
+
}
|
212
|
+
}
|
213
|
+
|
214
|
+
return pg_coder_enc_to_s(this, value, out, intermediate, enc_idx);
|
215
|
+
}
|
216
|
+
|
217
|
+
if( this->flags & PG_CODER_TIMESTAMP_DB_LOCAL ) {
|
218
|
+
/* make a local time, so that utc_offset is set */
|
219
|
+
value = rb_funcall(value, rb_intern("getlocal"), 0);
|
220
|
+
}
|
221
|
+
*intermediate = value;
|
222
|
+
}
|
223
|
+
return 8;
|
224
|
+
}
|
225
|
+
|
226
|
+
#define POSTGRES_EPOCH_JDATE 2451545 /* == date2j(2000, 1, 1) */
|
227
|
+
int
|
228
|
+
date2j(int year, int month, int day)
|
229
|
+
{
|
230
|
+
int julian;
|
231
|
+
int century;
|
232
|
+
|
233
|
+
if (month > 2)
|
234
|
+
{
|
235
|
+
month += 1;
|
236
|
+
year += 4800;
|
237
|
+
}
|
238
|
+
else
|
239
|
+
{
|
240
|
+
month += 13;
|
241
|
+
year += 4799;
|
242
|
+
}
|
243
|
+
|
244
|
+
century = year / 100;
|
245
|
+
julian = year * 365 - 32167;
|
246
|
+
julian += year / 4 - century + century / 4;
|
247
|
+
julian += 7834 * month / 256 + day;
|
248
|
+
|
249
|
+
return julian;
|
250
|
+
} /* date2j() */
|
251
|
+
|
252
|
+
/*
|
253
|
+
* Document-class: PG::BinaryEncoder::Date < PG::SimpleEncoder
|
254
|
+
*
|
255
|
+
* This is a encoder class for conversion of Ruby Date objects to PostgreSQL binary date.
|
256
|
+
*
|
257
|
+
* String values are expected to contain a binary data with a length of 4 byte.
|
258
|
+
*
|
259
|
+
*/
|
260
|
+
static int
|
261
|
+
pg_bin_enc_date(t_pg_coder *this, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
262
|
+
{
|
263
|
+
if(out){
|
264
|
+
/* second call -> write data to *out */
|
265
|
+
switch(TYPE(*intermediate)){
|
266
|
+
case T_STRING:
|
267
|
+
return pg_coder_enc_to_s(this, value, out, intermediate, enc_idx);
|
268
|
+
case T_TRUE:
|
269
|
+
write_nbo32(PG_INT32_MAX, out);
|
270
|
+
return 4;
|
271
|
+
case T_FALSE:
|
272
|
+
write_nbo32(PG_INT32_MIN, out);
|
273
|
+
return 4;
|
274
|
+
}
|
275
|
+
|
276
|
+
VALUE year = rb_funcall(value, s_id_year, 0);
|
277
|
+
VALUE month = rb_funcall(value, s_id_month, 0);
|
278
|
+
VALUE day = rb_funcall(value, s_id_day, 0);
|
279
|
+
int jday = date2j(NUM2INT(year), NUM2INT(month), NUM2INT(day)) - POSTGRES_EPOCH_JDATE;
|
280
|
+
write_nbo32(jday, out);
|
281
|
+
|
282
|
+
}else{
|
283
|
+
/* first call -> determine the required length */
|
284
|
+
if(TYPE(value) == T_STRING){
|
285
|
+
char *pstr = RSTRING_PTR(value);
|
286
|
+
if(RSTRING_LEN(value) >= 1){
|
287
|
+
switch(pstr[0]) {
|
288
|
+
case 'I':
|
289
|
+
case 'i':
|
290
|
+
*intermediate = Qtrue;
|
291
|
+
return 4;
|
292
|
+
case '-':
|
293
|
+
if (RSTRING_LEN(value) >= 2 && (pstr[1] == 'I' || pstr[1] == 'i')) {
|
294
|
+
*intermediate = Qfalse;
|
295
|
+
return 4;
|
296
|
+
}
|
297
|
+
}
|
298
|
+
}
|
299
|
+
|
300
|
+
return pg_coder_enc_to_s(this, value, out, intermediate, enc_idx);
|
301
|
+
}
|
302
|
+
|
303
|
+
*intermediate = value;
|
304
|
+
}
|
305
|
+
return 4;
|
306
|
+
}
|
307
|
+
|
96
308
|
/*
|
97
309
|
* Document-class: PG::BinaryEncoder::FromBase64 < PG::CompositeEncoder
|
98
310
|
*
|
@@ -141,6 +353,10 @@ pg_bin_enc_from_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermed
|
|
141
353
|
void
|
142
354
|
init_pg_binary_encoder(void)
|
143
355
|
{
|
356
|
+
s_id_year = rb_intern("year");
|
357
|
+
s_id_month = rb_intern("month");
|
358
|
+
s_id_day = rb_intern("day");
|
359
|
+
|
144
360
|
/* This module encapsulates all encoder classes with binary output format */
|
145
361
|
rb_mPG_BinaryEncoder = rb_define_module_under( rb_mPG, "BinaryEncoder" );
|
146
362
|
|
@@ -153,10 +369,18 @@ init_pg_binary_encoder(void)
|
|
153
369
|
pg_define_coder( "Int4", pg_bin_enc_int4, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
154
370
|
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Int8", rb_cPG_SimpleEncoder ); */
|
155
371
|
pg_define_coder( "Int8", pg_bin_enc_int8, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
372
|
+
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Float4", rb_cPG_SimpleEncoder ); */
|
373
|
+
pg_define_coder( "Float4", pg_bin_enc_float4, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
374
|
+
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Float8", rb_cPG_SimpleEncoder ); */
|
375
|
+
pg_define_coder( "Float8", pg_bin_enc_float8, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
156
376
|
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "String", rb_cPG_SimpleEncoder ); */
|
157
377
|
pg_define_coder( "String", pg_coder_enc_to_s, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
158
378
|
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Bytea", rb_cPG_SimpleEncoder ); */
|
159
379
|
pg_define_coder( "Bytea", pg_coder_enc_to_s, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
380
|
+
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Timestamp", rb_cPG_SimpleEncoder ); */
|
381
|
+
pg_define_coder( "Timestamp", pg_bin_enc_timestamp, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
382
|
+
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Date", rb_cPG_SimpleEncoder ); */
|
383
|
+
pg_define_coder( "Date", pg_bin_enc_date, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
160
384
|
|
161
385
|
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "FromBase64", rb_cPG_CompositeEncoder ); */
|
162
386
|
pg_define_coder( "FromBase64", pg_bin_enc_from_base64, rb_cPG_CompositeEncoder, rb_mPG_BinaryEncoder );
|
data/ext/pg_coder.c
CHANGED
@@ -35,7 +35,7 @@ pg_coder_init_encoder( VALUE self )
|
|
35
35
|
this->enc_func = NULL;
|
36
36
|
}
|
37
37
|
this->dec_func = NULL;
|
38
|
-
this->coder_obj
|
38
|
+
RB_OBJ_WRITE(self, &this->coder_obj, self);
|
39
39
|
this->oid = 0;
|
40
40
|
this->format = 0;
|
41
41
|
this->flags = 0;
|
@@ -54,7 +54,7 @@ pg_coder_init_decoder( VALUE self )
|
|
54
54
|
} else {
|
55
55
|
this->dec_func = NULL;
|
56
56
|
}
|
57
|
-
this->coder_obj
|
57
|
+
RB_OBJ_WRITE(self, &this->coder_obj, self);
|
58
58
|
this->oid = 0;
|
59
59
|
this->format = 0;
|
60
60
|
this->flags = 0;
|
@@ -99,7 +99,9 @@ const rb_data_type_t pg_coder_type = {
|
|
99
99
|
},
|
100
100
|
0,
|
101
101
|
0,
|
102
|
-
|
102
|
+
// IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
|
103
|
+
// macro to update VALUE references, as to trigger write barriers.
|
104
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
|
103
105
|
};
|
104
106
|
|
105
107
|
static VALUE
|
@@ -121,7 +123,7 @@ static const rb_data_type_t pg_composite_coder_type = {
|
|
121
123
|
},
|
122
124
|
&pg_coder_type,
|
123
125
|
0,
|
124
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
126
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
|
125
127
|
};
|
126
128
|
|
127
129
|
static VALUE
|
@@ -273,6 +275,7 @@ static VALUE
|
|
273
275
|
pg_coder_oid_set(VALUE self, VALUE oid)
|
274
276
|
{
|
275
277
|
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
278
|
+
rb_check_frozen(self);
|
276
279
|
this->oid = NUM2UINT(oid);
|
277
280
|
return oid;
|
278
281
|
}
|
@@ -304,6 +307,7 @@ static VALUE
|
|
304
307
|
pg_coder_format_set(VALUE self, VALUE format)
|
305
308
|
{
|
306
309
|
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
310
|
+
rb_check_frozen(self);
|
307
311
|
this->format = NUM2INT(format);
|
308
312
|
return format;
|
309
313
|
}
|
@@ -335,6 +339,7 @@ static VALUE
|
|
335
339
|
pg_coder_flags_set(VALUE self, VALUE flags)
|
336
340
|
{
|
337
341
|
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
342
|
+
rb_check_frozen(self);
|
338
343
|
this->flags = NUM2INT(flags);
|
339
344
|
return flags;
|
340
345
|
}
|
@@ -366,6 +371,7 @@ static VALUE
|
|
366
371
|
pg_coder_needs_quotation_set(VALUE self, VALUE needs_quotation)
|
367
372
|
{
|
368
373
|
t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
|
374
|
+
rb_check_frozen(self);
|
369
375
|
this->needs_quotation = RTEST(needs_quotation);
|
370
376
|
return needs_quotation;
|
371
377
|
}
|
@@ -396,6 +402,7 @@ static VALUE
|
|
396
402
|
pg_coder_delimiter_set(VALUE self, VALUE delimiter)
|
397
403
|
{
|
398
404
|
t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
|
405
|
+
rb_check_frozen(self);
|
399
406
|
StringValue(delimiter);
|
400
407
|
if(RSTRING_LEN(delimiter) != 1)
|
401
408
|
rb_raise( rb_eArgError, "delimiter size must be one byte");
|
@@ -430,6 +437,7 @@ pg_coder_elements_type_set(VALUE self, VALUE elem_type)
|
|
430
437
|
{
|
431
438
|
t_pg_composite_coder *this = RTYPEDDATA_DATA( self );
|
432
439
|
|
440
|
+
rb_check_frozen(self);
|
433
441
|
if ( NIL_P(elem_type) ){
|
434
442
|
this->elem = NULL;
|
435
443
|
} else if ( rb_obj_is_kind_of(elem_type, rb_cPG_Coder) ){
|
@@ -452,10 +460,10 @@ static const rb_data_type_t pg_coder_cfunc_type = {
|
|
452
460
|
},
|
453
461
|
0,
|
454
462
|
0,
|
455
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
463
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
|
456
464
|
};
|
457
465
|
|
458
|
-
|
466
|
+
VALUE
|
459
467
|
pg_define_coder( const char *name, void *func, VALUE base_klass, VALUE nsp )
|
460
468
|
{
|
461
469
|
VALUE cfunc_obj = TypedData_Wrap_Struct( rb_cObject, &pg_coder_cfunc_type, func );
|
@@ -468,9 +476,10 @@ pg_define_coder( const char *name, void *func, VALUE base_klass, VALUE nsp )
|
|
468
476
|
if( nsp==rb_mPG_BinaryDecoder || nsp==rb_mPG_TextDecoder )
|
469
477
|
rb_define_method( coder_klass, "decode", pg_coder_decode, -1 );
|
470
478
|
|
471
|
-
rb_define_const( coder_klass, "CFUNC", cfunc_obj );
|
479
|
+
rb_define_const( coder_klass, "CFUNC", rb_obj_freeze(cfunc_obj) );
|
472
480
|
|
473
481
|
RB_GC_GUARD(cfunc_obj);
|
482
|
+
return coder_klass;
|
474
483
|
}
|
475
484
|
|
476
485
|
|