globegit-postgresql-plruby 0.5.4
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.
- data/Changes +121 -0
- data/README.markdown +155 -0
- data/Rakefile +48 -0
- data/docs/plruby.rb +1931 -0
- data/ex_trans.sql +33 -0
- data/extconf.rb +267 -0
- data/plruby.html +1454 -0
- data/plruby.rd +1571 -0
- data/postgresql-plruby.gemspec +56 -0
- data/src/conversions.h +5 -0
- data/src/conversions/basic/conversions.h +25 -0
- data/src/conversions/basic/extconf.rb +8 -0
- data/src/conversions/basic/plruby_basic.c +357 -0
- data/src/conversions/bitstring/bitstring.sql +75 -0
- data/src/conversions/bitstring/conversions.h +15 -0
- data/src/conversions/bitstring/extconf.rb +8 -0
- data/src/conversions/bitstring/plruby_bitstring.c +579 -0
- data/src/conversions/convcommon.h +129 -0
- data/src/conversions/datetime/conversions.h +13 -0
- data/src/conversions/datetime/extconf.rb +8 -0
- data/src/conversions/datetime/plruby_datetime.c +269 -0
- data/src/conversions/geometry/conversions.h +37 -0
- data/src/conversions/geometry/extconf.rb +8 -0
- data/src/conversions/geometry/geometry.sql +196 -0
- data/src/conversions/geometry/plruby_geometry.c +2494 -0
- data/src/conversions/network/conversions.h +21 -0
- data/src/conversions/network/extconf.rb +8 -0
- data/src/conversions/network/network.sql +63 -0
- data/src/conversions/network/plruby_network.c +537 -0
- data/src/package.h +20 -0
- data/src/plpl.c +1708 -0
- data/src/plplan.c +893 -0
- data/src/plruby.c +1676 -0
- data/src/plruby.h +324 -0
- data/src/pltrans.c +388 -0
- data/test/conv_bitstring/b.rb +45 -0
- data/test/conv_bitstring/runtest +26 -0
- data/test/conv_bitstring/test.expected.73 +148 -0
- data/test/conv_bitstring/test.expected.74 +148 -0
- data/test/conv_bitstring/test.expected.80 +148 -0
- data/test/conv_bitstring/test.expected.81 +148 -0
- data/test/conv_bitstring/test.expected.82 +148 -0
- data/test/conv_bitstring/test.expected.83 +148 -0
- data/test/conv_bitstring/test.expected.84 +148 -0
- data/test/conv_bitstring/test.out +148 -0
- data/test/conv_bitstring/test_mklang.sql +8 -0
- data/test/conv_bitstring/test_queries.sql +63 -0
- data/test/conv_bitstring/test_queries.sql.in +63 -0
- data/test/conv_geometry/b.rb +45 -0
- data/test/conv_geometry/runtest +26 -0
- data/test/conv_geometry/test.expected.73 +265 -0
- data/test/conv_geometry/test.expected.74 +265 -0
- data/test/conv_geometry/test.expected.80 +265 -0
- data/test/conv_geometry/test.expected.81 +265 -0
- data/test/conv_geometry/test.expected.82 +265 -0
- data/test/conv_geometry/test.expected.83 +265 -0
- data/test/conv_geometry/test.expected.84 +265 -0
- data/test/conv_geometry/test.out +265 -0
- data/test/conv_geometry/test_mklang.sql +8 -0
- data/test/conv_geometry/test_queries.sql +194 -0
- data/test/conv_geometry/test_queries.sql.in +194 -0
- data/test/conv_network/b.rb +45 -0
- data/test/conv_network/runtest +26 -0
- data/test/conv_network/test.expected.73 +213 -0
- data/test/conv_network/test.expected.74 +237 -0
- data/test/conv_network/test.expected.80 +237 -0
- data/test/conv_network/test.expected.81 +237 -0
- data/test/conv_network/test.expected.82 +237 -0
- data/test/conv_network/test.expected.83 +237 -0
- data/test/conv_network/test.expected.84 +237 -0
- data/test/conv_network/test.out +237 -0
- data/test/conv_network/test_mklang.sql +8 -0
- data/test/conv_network/test_queries.sql +60 -0
- data/test/conv_network/test_queries.sql.in +60 -0
- data/test/plp/b.rb +34 -0
- data/test/plp/runtest +29 -0
- data/test/plp/test.expected.73 +472 -0
- data/test/plp/test.expected.74 +472 -0
- data/test/plp/test.expected.75 +472 -0
- data/test/plp/test.expected.80 +472 -0
- data/test/plp/test.expected.81 +472 -0
- data/test/plp/test.expected.82 +472 -0
- data/test/plp/test.expected.83 +472 -0
- data/test/plp/test.expected.84 +472 -0
- data/test/plp/test.out +472 -0
- data/test/plp/test_mklang.sql +8 -0
- data/test/plp/test_queries.sql +273 -0
- data/test/plp/test_setup.sql +931 -0
- data/test/plp/test_setup.sql.in +931 -0
- data/test/plt/b.rb +34 -0
- data/test/plt/runtest +29 -0
- data/test/plt/test.expected.73 +178 -0
- data/test/plt/test.expected.74 +178 -0
- data/test/plt/test.expected.75 +178 -0
- data/test/plt/test.expected.80 +178 -0
- data/test/plt/test.expected.81 +178 -0
- data/test/plt/test.expected.82 +178 -0
- data/test/plt/test.expected.83 +164 -0
- data/test/plt/test.expected.84 +168 -0
- data/test/plt/test.out +168 -0
- data/test/plt/test_mklang.sql +8 -0
- data/test/plt/test_queries.sql +72 -0
- data/test/plt/test_setup.sql +252 -0
- data/test/plt/test_setup.sql.in +252 -0
- data/test/range/b.rb +45 -0
- data/test/range/runtest +26 -0
- data/test/range/test.expected.73 +396 -0
- data/test/range/test.expected.73.in +396 -0
- data/test/range/test.expected.74 +396 -0
- data/test/range/test.expected.74.in +396 -0
- data/test/range/test.expected.75 +396 -0
- data/test/range/test.expected.75.in +396 -0
- data/test/range/test.expected.80 +396 -0
- data/test/range/test.expected.81 +397 -0
- data/test/range/test.expected.82 +397 -0
- data/test/range/test.expected.83 +397 -0
- data/test/range/test.expected.84 +399 -0
- data/test/range/test.out +399 -0
- data/test/range/test_mklang.sql +8 -0
- data/test/range/test_queries.sql +249 -0
- data/test/range/test_queries.sql.in +249 -0
- metadata +207 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
drop table bit_op cascade;
|
|
2
|
+
|
|
3
|
+
create table bit_op (
|
|
4
|
+
b0 bit(8), b1 bit(8), band bit(8), bor bit(8),
|
|
5
|
+
bxor bit(8), bnot0 bit(8), bnot1 bit(8)
|
|
6
|
+
);
|
|
7
|
+
|
|
8
|
+
create function bt(integer, integer) returns bit_op as '
|
|
9
|
+
b0 = BitString.new(args[0], 8)
|
|
10
|
+
b1 = BitString.new(args[1], 8)
|
|
11
|
+
[b0, b1, b0 & b1, b0 | b1, b0 ^ b1, ~b0, ~b1]
|
|
12
|
+
' language 'plruby';
|
|
13
|
+
|
|
14
|
+
select * from bt(12, 24);
|
|
15
|
+
select * from bt(12, 32);
|
|
16
|
+
select * from bt(15, 278);
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
drop function be(integer);
|
|
20
|
+
|
|
21
|
+
create function be(integer) returns setof integer as '
|
|
22
|
+
BitString.new(args[0], 8).each {|i| yield i}
|
|
23
|
+
' language 'plruby';
|
|
24
|
+
|
|
25
|
+
select * from be(12);
|
|
26
|
+
select * from be(257);
|
|
27
|
+
|
|
28
|
+
drop function bx(integer, integer);
|
|
29
|
+
|
|
30
|
+
create function bx(integer, integer) returns bit varying as '
|
|
31
|
+
BitString.new(*args)
|
|
32
|
+
' language 'plruby';
|
|
33
|
+
|
|
34
|
+
select bx(12, 6);
|
|
35
|
+
select bx(12, 8);
|
|
36
|
+
|
|
37
|
+
drop table bit_sht cascade;
|
|
38
|
+
|
|
39
|
+
create table bit_sht (
|
|
40
|
+
b0 bit(8), shft int, bl bit(8), br bit(8), bs text, bi integer,
|
|
41
|
+
sz integer, osz integer
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
create function bs(integer, integer) returns bit_sht as '
|
|
45
|
+
b0 = BitString.new(args[0], 8)
|
|
46
|
+
[b0, args[1], b0 << args[1], b0 >> args[1], b0.to_s, b0.to_i,
|
|
47
|
+
b0.size, b0.octet_size]
|
|
48
|
+
' language 'plruby';
|
|
49
|
+
|
|
50
|
+
select * from bs(12, 2);
|
|
51
|
+
select * from bs(277, -3);
|
|
52
|
+
|
|
53
|
+
drop function ext(text, integer);
|
|
54
|
+
|
|
55
|
+
create function ext(text, integer) returns integer as '
|
|
56
|
+
b0 = BitString.new(args[0])
|
|
57
|
+
b0[args[1]]
|
|
58
|
+
' language 'plruby';
|
|
59
|
+
|
|
60
|
+
select ext('011110', 0);
|
|
61
|
+
select ext('011110', -1);
|
|
62
|
+
select ext('011110', 1);
|
|
63
|
+
select ext('011110', 4);
|
|
64
|
+
|
|
65
|
+
drop function ext2(text, integer, integer);
|
|
66
|
+
|
|
67
|
+
create function ext2(text, integer, integer) returns bit varying(8) as '
|
|
68
|
+
b0 = BitString.new(args[0])
|
|
69
|
+
b0[args[1], args[2]]
|
|
70
|
+
' language 'plruby';
|
|
71
|
+
|
|
72
|
+
select ext2('0111101', 0, 2);
|
|
73
|
+
select ext2('0111101', -1, 3);
|
|
74
|
+
select ext2('0111101', 1, 2);
|
|
75
|
+
select ext2('0111101', 4, 1);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
VALUE tmp;
|
|
3
|
+
|
|
4
|
+
#if RUBY_CAN_USE_AUTOLOAD
|
|
5
|
+
rb_funcall(rb_mKernel, rb_intern("autoload"), 2, rb_str_new2("BitString"),
|
|
6
|
+
rb_str_new2("plruby/plruby_bitstring"));
|
|
7
|
+
tmp = INT2NUM(rb_intern("BitString"));
|
|
8
|
+
rb_hash_aset(plruby_conversions, INT2NUM(BITOID), tmp);
|
|
9
|
+
rb_hash_aset(plruby_conversions, INT2NUM(VARBITOID), tmp);
|
|
10
|
+
#else
|
|
11
|
+
tmp = plruby_define_void_class("BitString", "plruby/plruby_bitstring");
|
|
12
|
+
rb_hash_aset(plruby_classes, INT2NUM(BITOID), tmp);
|
|
13
|
+
rb_hash_aset(plruby_classes, INT2NUM(VARBITOID), tmp);
|
|
14
|
+
#endif
|
|
15
|
+
}
|
|
@@ -0,0 +1,579 @@
|
|
|
1
|
+
#include "convcommon.h"
|
|
2
|
+
#include "utils/varbit.h"
|
|
3
|
+
|
|
4
|
+
static void pl_bit_mark(VarBit *p) {}
|
|
5
|
+
|
|
6
|
+
static VALUE
|
|
7
|
+
pl_bit_s_alloc(VALUE obj)
|
|
8
|
+
{
|
|
9
|
+
VarBit *inst;
|
|
10
|
+
|
|
11
|
+
inst = (VarBit *)ALLOC_N(char, VARBITTOTALLEN(0));
|
|
12
|
+
#ifdef SET_VARSIZE
|
|
13
|
+
SET_VARSIZE(inst, VARBITTOTALLEN(0));
|
|
14
|
+
#else
|
|
15
|
+
VARATT_SIZEP(inst) = VARBITTOTALLEN(0);
|
|
16
|
+
#endif
|
|
17
|
+
VARBITLEN(inst) = 0;
|
|
18
|
+
return Data_Wrap_Struct(obj, pl_bit_mark, free, inst);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static VALUE
|
|
22
|
+
pl_bit_init_copy(VALUE copy, VALUE orig)
|
|
23
|
+
{
|
|
24
|
+
VarBit *t0, *t1;
|
|
25
|
+
int s0, s1;
|
|
26
|
+
|
|
27
|
+
if (copy == orig) return copy;
|
|
28
|
+
if (TYPE(orig) != T_DATA ||
|
|
29
|
+
RDATA(orig)->dmark != (RUBY_DATA_FUNC)pl_bit_mark) {
|
|
30
|
+
rb_raise(rb_eTypeError, "wrong argument type to clone");
|
|
31
|
+
}
|
|
32
|
+
Data_Get_Struct(orig, VarBit, t0);
|
|
33
|
+
Data_Get_Struct(copy, VarBit, t1);
|
|
34
|
+
s0 = VARSIZE(t0);
|
|
35
|
+
s1 = VARSIZE(t1);
|
|
36
|
+
if (s0 != s1) {
|
|
37
|
+
free(t1);
|
|
38
|
+
DATA_PTR(copy) = 0;
|
|
39
|
+
t1 = (VarBit *)ALLOC_N(char, s0);
|
|
40
|
+
DATA_PTR(copy) = t1;
|
|
41
|
+
}
|
|
42
|
+
memcpy(t1, t0, s0);
|
|
43
|
+
return copy;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
static VALUE
|
|
47
|
+
pl_bit_s_datum(VALUE obj, VALUE a)
|
|
48
|
+
{
|
|
49
|
+
VarBit *ip0, *ip1;
|
|
50
|
+
Oid typoid;
|
|
51
|
+
VALUE res;
|
|
52
|
+
|
|
53
|
+
ip0 = (VarBit *)plruby_datum_get(a, &typoid);
|
|
54
|
+
if (typoid != BITOID && typoid != VARBITOID) {
|
|
55
|
+
rb_raise(rb_eArgError, "unknown OID type %d", typoid);
|
|
56
|
+
}
|
|
57
|
+
ip1 = (VarBit *)ALLOC_N(char, VARSIZE(ip0));
|
|
58
|
+
memcpy(ip1, ip0, VARSIZE(ip0));
|
|
59
|
+
res = Data_Wrap_Struct(obj, pl_bit_mark, free, ip1);
|
|
60
|
+
OBJ_TAINT(res);
|
|
61
|
+
return res;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
static VALUE
|
|
65
|
+
pl_bit_to_datum(VALUE obj, VALUE a)
|
|
66
|
+
{
|
|
67
|
+
VarBit *ip0, *ip1;
|
|
68
|
+
int length;
|
|
69
|
+
Oid typoid;
|
|
70
|
+
|
|
71
|
+
typoid = plruby_datum_oid(a, &length);
|
|
72
|
+
switch (typoid) {
|
|
73
|
+
case BITOID:
|
|
74
|
+
case VARBITOID:
|
|
75
|
+
Data_Get_Struct(obj, VarBit, ip0);
|
|
76
|
+
ip1 = (VarBit *)PLRUBY_DFC3(bit, ip0, Int32GetDatum(length), true);
|
|
77
|
+
break;
|
|
78
|
+
default:
|
|
79
|
+
/* a faire */
|
|
80
|
+
return Qnil;
|
|
81
|
+
}
|
|
82
|
+
return plruby_datum_set(a, (Datum)ip1);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
PL_MLOADVAR(pl_bit_mload, varbit_recv, VarBit, VARSIZE);
|
|
86
|
+
PL_MDUMP(pl_bit_mdump, varbit_send);
|
|
87
|
+
|
|
88
|
+
static VALUE
|
|
89
|
+
pl_bit_init(int argc, VALUE *argv, VALUE obj)
|
|
90
|
+
{
|
|
91
|
+
VarBit *inst;
|
|
92
|
+
VALUE a, b;
|
|
93
|
+
void *v = 0;
|
|
94
|
+
int length = -1;
|
|
95
|
+
int taint = 0;
|
|
96
|
+
|
|
97
|
+
if (rb_scan_args(argc, argv, "11", &a, &b) == 2) {
|
|
98
|
+
length = NUM2INT(b);
|
|
99
|
+
}
|
|
100
|
+
taint = OBJ_TAINTED(a);
|
|
101
|
+
if (rb_respond_to(a, rb_intern("to_int"))) {
|
|
102
|
+
a = rb_funcall2(a, rb_intern("to_int"), 0, 0);
|
|
103
|
+
#if PG_PL_VERSION >= 75
|
|
104
|
+
v = (void *)PLRUBY_DFC2(bitfromint4, Int32GetDatum(NUM2LONG(a)),
|
|
105
|
+
Int32GetDatum(length));
|
|
106
|
+
#else
|
|
107
|
+
v = (void *)PLRUBY_DFC1(bitfromint4, Int32GetDatum(NUM2LONG(a)));
|
|
108
|
+
if (length > 0) {
|
|
109
|
+
void *v1;
|
|
110
|
+
|
|
111
|
+
int ll = DatumGetInt32(PLRUBY_DFC1(bitlength, v));
|
|
112
|
+
if (length != ll) {
|
|
113
|
+
if (length < ll) {
|
|
114
|
+
v1 = (void *)PLRUBY_DFC2(bitshiftleft, v,
|
|
115
|
+
Int32GetDatum(ll - length));
|
|
116
|
+
pfree(v);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
v1 = v;
|
|
120
|
+
}
|
|
121
|
+
v = (void *)PLRUBY_DFC3(bit, v1, Int32GetDatum(length), true);
|
|
122
|
+
pfree(v1);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
#endif
|
|
126
|
+
}
|
|
127
|
+
if (!v) {
|
|
128
|
+
a = plruby_to_s(a);
|
|
129
|
+
v = (void *)PLRUBY_DFC3(bit_in, RSTRING_PTR(a), ObjectIdGetDatum(0),
|
|
130
|
+
Int32GetDatum(length));
|
|
131
|
+
}
|
|
132
|
+
Data_Get_Struct(obj, VarBit, inst);
|
|
133
|
+
free(inst);
|
|
134
|
+
inst = (VarBit *)ALLOC_N(char, VARSIZE(v));
|
|
135
|
+
CPY_FREE(inst, v, VARSIZE(v));
|
|
136
|
+
RDATA(obj)->data = inst;
|
|
137
|
+
if (taint) OBJ_TAINT(obj);
|
|
138
|
+
return obj;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
static VALUE
|
|
142
|
+
pl_bit_cmp(VALUE a, VALUE b)
|
|
143
|
+
{
|
|
144
|
+
VarBit *inst0, *inst1;
|
|
145
|
+
int result;
|
|
146
|
+
|
|
147
|
+
if (!rb_obj_is_kind_of(b, rb_obj_class(a))) {
|
|
148
|
+
return Qnil;
|
|
149
|
+
}
|
|
150
|
+
Data_Get_Struct(a, VarBit, inst0);
|
|
151
|
+
Data_Get_Struct(b, VarBit, inst1);
|
|
152
|
+
result = DatumGetInt32(PLRUBY_DFC2(bitcmp, inst0, inst1));
|
|
153
|
+
return INT2FIX(result);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
static VALUE
|
|
157
|
+
pl_bit_to_s(VALUE obj)
|
|
158
|
+
{
|
|
159
|
+
VarBit *src;
|
|
160
|
+
char *str;
|
|
161
|
+
VALUE res;
|
|
162
|
+
|
|
163
|
+
Data_Get_Struct(obj, VarBit, src);
|
|
164
|
+
str = (char *)PLRUBY_DFC1(bit_out, src);
|
|
165
|
+
if (OBJ_TAINTED(obj)) {
|
|
166
|
+
res = rb_tainted_str_new2(str);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
res = rb_str_new2(str);
|
|
170
|
+
}
|
|
171
|
+
pfree(str);
|
|
172
|
+
return res;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
#define BIT_OPERATOR(name_, function_) \
|
|
176
|
+
static VALUE \
|
|
177
|
+
name_(VALUE obj, VALUE a) \
|
|
178
|
+
{ \
|
|
179
|
+
VarBit *v0, *v1, *vp, *vr; \
|
|
180
|
+
VALUE res; \
|
|
181
|
+
\
|
|
182
|
+
if (TYPE(a) != T_DATA || \
|
|
183
|
+
RDATA(a)->dmark != (RUBY_DATA_FUNC)pl_bit_mark) { \
|
|
184
|
+
rb_raise(rb_eArgError, "invalid argument for %s", \
|
|
185
|
+
rb_id2name(rb_frame_last_func())); \
|
|
186
|
+
} \
|
|
187
|
+
Data_Get_Struct(obj, VarBit, v0); \
|
|
188
|
+
Data_Get_Struct(a, VarBit, v1); \
|
|
189
|
+
vp = (VarBit *)PLRUBY_DFC2(function_, v0, v1); \
|
|
190
|
+
vr = (VarBit *)ALLOC_N(char, VARSIZE(vp)); \
|
|
191
|
+
CPY_FREE(vr, vp, VARSIZE(vp)); \
|
|
192
|
+
res = Data_Wrap_Struct(rb_class_of(obj), pl_bit_mark, free, vr); \
|
|
193
|
+
if (OBJ_TAINTED(obj) || OBJ_TAINTED(a)) OBJ_TAINT(res); \
|
|
194
|
+
return res; \
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
BIT_OPERATOR(pl_bit_add, bitcat);
|
|
198
|
+
BIT_OPERATOR(pl_bit_and, bitand);
|
|
199
|
+
BIT_OPERATOR(pl_bit_or, bitor);
|
|
200
|
+
BIT_OPERATOR(pl_bit_xor, bitxor);
|
|
201
|
+
|
|
202
|
+
static VALUE
|
|
203
|
+
pl_bit_push(VALUE obj, VALUE a)
|
|
204
|
+
{
|
|
205
|
+
VarBit *v0, *v1, *vp;
|
|
206
|
+
|
|
207
|
+
if (TYPE(a) != T_DATA ||
|
|
208
|
+
RDATA(a)->dmark != (RUBY_DATA_FUNC)pl_bit_mark) {
|
|
209
|
+
rb_raise(rb_eArgError, "invalid argument for %s",
|
|
210
|
+
rb_id2name(rb_frame_last_func()));
|
|
211
|
+
}
|
|
212
|
+
Data_Get_Struct(obj, VarBit, v0);
|
|
213
|
+
Data_Get_Struct(a, VarBit, v1);
|
|
214
|
+
vp = (VarBit *)PLRUBY_DFC2(bitcat, v0, v1);
|
|
215
|
+
free(v0);
|
|
216
|
+
v0 = (VarBit *)ALLOC_N(char, VARSIZE(vp));
|
|
217
|
+
CPY_FREE(v0, vp, VARSIZE(vp));
|
|
218
|
+
DATA_PTR(obj) = v0;
|
|
219
|
+
return obj;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
static VALUE
|
|
223
|
+
pl_bit_not(VALUE obj)
|
|
224
|
+
{
|
|
225
|
+
VarBit *v0, *vp, *vr;
|
|
226
|
+
VALUE res;
|
|
227
|
+
|
|
228
|
+
Data_Get_Struct(obj, VarBit, v0);
|
|
229
|
+
vp = (VarBit *)PLRUBY_DFC1(bitnot, v0);
|
|
230
|
+
vr = (VarBit *)ALLOC_N(char, VARSIZE(vp));
|
|
231
|
+
CPY_FREE(vr, vp, VARSIZE(vp));
|
|
232
|
+
res = Data_Wrap_Struct(rb_class_of(obj), pl_bit_mark, free, vr);
|
|
233
|
+
if (OBJ_TAINTED(obj)) OBJ_TAINT(res);
|
|
234
|
+
return res;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
#define SHIFT_OPERATOR(name_, function_) \
|
|
238
|
+
static VALUE \
|
|
239
|
+
name_(VALUE obj, VALUE a) \
|
|
240
|
+
{ \
|
|
241
|
+
VarBit *v0, *vp, *vr; \
|
|
242
|
+
VALUE res; \
|
|
243
|
+
\
|
|
244
|
+
Data_Get_Struct(obj, VarBit, v0); \
|
|
245
|
+
a = rb_Integer(a); \
|
|
246
|
+
vp = (VarBit *)PLRUBY_DFC2(function_, v0, Int32GetDatum(NUM2INT(a)));\
|
|
247
|
+
vr = (VarBit *)ALLOC_N(char, VARSIZE(vp)); \
|
|
248
|
+
CPY_FREE(vr, vp, VARSIZE(vp)); \
|
|
249
|
+
res = Data_Wrap_Struct(rb_class_of(obj), pl_bit_mark, free, vr); \
|
|
250
|
+
if (OBJ_TAINTED(obj) || OBJ_TAINTED(a)) OBJ_TAINT(res); \
|
|
251
|
+
return res; \
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
SHIFT_OPERATOR(pl_bit_left_shift, bitshiftleft);
|
|
255
|
+
SHIFT_OPERATOR(pl_bit_right_shift, bitshiftright);
|
|
256
|
+
|
|
257
|
+
static VALUE
|
|
258
|
+
pl_bit_length(VALUE obj)
|
|
259
|
+
{
|
|
260
|
+
VarBit *v;
|
|
261
|
+
int l;
|
|
262
|
+
|
|
263
|
+
Data_Get_Struct(obj, VarBit, v);
|
|
264
|
+
l = DatumGetInt32(PLRUBY_DFC1(bitlength, v));
|
|
265
|
+
return INT2NUM(l);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
static VALUE
|
|
269
|
+
pl_bit_octet_length(VALUE obj)
|
|
270
|
+
{
|
|
271
|
+
VarBit *v;
|
|
272
|
+
int l;
|
|
273
|
+
|
|
274
|
+
Data_Get_Struct(obj, VarBit, v);
|
|
275
|
+
l = DatumGetInt32(PLRUBY_DFC1(bitoctetlength, v));
|
|
276
|
+
return INT2NUM(l);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
static VALUE
|
|
280
|
+
pl_bit_to_i(VALUE obj)
|
|
281
|
+
{
|
|
282
|
+
VarBit *v;
|
|
283
|
+
int l;
|
|
284
|
+
|
|
285
|
+
Data_Get_Struct(obj, VarBit, v);
|
|
286
|
+
l = DatumGetInt32(PLRUBY_DFC1(bittoint4, v));
|
|
287
|
+
return INT2NUM(l);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/* This is varbit_out() from utils/adt/varbit.c */
|
|
291
|
+
|
|
292
|
+
#ifndef IS_HIGHBIT_SET
|
|
293
|
+
#define IS_HIGHBIT_SET(x) ((x) & BITHIGH)
|
|
294
|
+
#endif
|
|
295
|
+
|
|
296
|
+
static VALUE
|
|
297
|
+
pl_bit_each(VALUE obj)
|
|
298
|
+
{
|
|
299
|
+
VarBit *s;
|
|
300
|
+
VALUE i1, i0;
|
|
301
|
+
bits8 *sp, x;
|
|
302
|
+
int i, k, len;
|
|
303
|
+
|
|
304
|
+
i1 = INT2FIX(1);
|
|
305
|
+
i0 = INT2FIX(0);
|
|
306
|
+
Data_Get_Struct(obj, VarBit, s);
|
|
307
|
+
len = VARBITLEN(s);
|
|
308
|
+
sp = VARBITS(s);
|
|
309
|
+
for (i = 0; i < len - BITS_PER_BYTE; i += BITS_PER_BYTE, sp++) {
|
|
310
|
+
x = *sp;
|
|
311
|
+
for (k = 0; k < BITS_PER_BYTE; k++) {
|
|
312
|
+
if (IS_HIGHBIT_SET(x)) {
|
|
313
|
+
rb_yield(i1);
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
rb_yield(i0);
|
|
317
|
+
}
|
|
318
|
+
x <<= 1;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
x = *sp;
|
|
322
|
+
for (k = i; k < len; k++){
|
|
323
|
+
if (IS_HIGHBIT_SET(x)) {
|
|
324
|
+
rb_yield(i1);
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
rb_yield(i0);
|
|
328
|
+
}
|
|
329
|
+
x <<= 1;
|
|
330
|
+
}
|
|
331
|
+
return Qnil;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
static VALUE
|
|
335
|
+
pl_bit_index(VALUE obj, VALUE a)
|
|
336
|
+
{
|
|
337
|
+
VarBit *v0, *v1;
|
|
338
|
+
int i;
|
|
339
|
+
|
|
340
|
+
if (TYPE(a) != T_DATA ||
|
|
341
|
+
RDATA(a)->dmark != (RUBY_DATA_FUNC)pl_bit_mark) {
|
|
342
|
+
rb_raise(rb_eArgError, "invalid argument for %s",
|
|
343
|
+
rb_id2name(rb_frame_last_func()));
|
|
344
|
+
}
|
|
345
|
+
Data_Get_Struct(obj, VarBit, v0);
|
|
346
|
+
Data_Get_Struct(a, VarBit, v1);
|
|
347
|
+
i = DatumGetInt32(PLRUBY_DFC2(bitposition, v0, v1));
|
|
348
|
+
i -= 1;
|
|
349
|
+
if (i < 0) return Qnil;
|
|
350
|
+
return INT2NUM(i);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
static VALUE
|
|
354
|
+
pl_bit_include(VALUE obj, VALUE a)
|
|
355
|
+
{
|
|
356
|
+
if (NIL_P(pl_bit_index(obj, a))) {
|
|
357
|
+
return Qfalse;
|
|
358
|
+
}
|
|
359
|
+
return Qtrue;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
extern long rb_reg_search();
|
|
363
|
+
|
|
364
|
+
static VALUE
|
|
365
|
+
pl_bit_subpat(VALUE obj, VALUE a, int nth)
|
|
366
|
+
{
|
|
367
|
+
VALUE res;
|
|
368
|
+
|
|
369
|
+
obj = pl_bit_to_s(obj);
|
|
370
|
+
if (rb_reg_search(a, obj, 0, 0) >= 0) {
|
|
371
|
+
res = rb_reg_nth_match(nth, rb_backref_get());
|
|
372
|
+
return rb_funcall(rb_obj_class(obj), rb_intern("new"), 1, res);
|
|
373
|
+
}
|
|
374
|
+
return Qnil;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
static VALUE
|
|
378
|
+
pl_bit_substr(VALUE obj, long beg, long len)
|
|
379
|
+
{
|
|
380
|
+
VarBit *v, *v0, *v1;
|
|
381
|
+
long ll;
|
|
382
|
+
VALUE res;
|
|
383
|
+
|
|
384
|
+
Data_Get_Struct(obj, VarBit, v);
|
|
385
|
+
ll = DatumGetInt32(PLRUBY_DFC1(bitlength, v));
|
|
386
|
+
if (len < 0) return Qnil;
|
|
387
|
+
if (beg > ll) return Qnil;
|
|
388
|
+
if (beg < 0) {
|
|
389
|
+
beg += ll;
|
|
390
|
+
if (beg < 0) return Qnil;
|
|
391
|
+
}
|
|
392
|
+
if (beg + len > ll) {
|
|
393
|
+
len = ll - beg;
|
|
394
|
+
}
|
|
395
|
+
if (len < 0) {
|
|
396
|
+
len = 0;
|
|
397
|
+
}
|
|
398
|
+
if (len == 0) {
|
|
399
|
+
res = rb_funcall2(rb_obj_class(obj), rb_intern("allocate"), 0, 0);
|
|
400
|
+
if (OBJ_TAINTED(obj)) OBJ_TAINT(res);
|
|
401
|
+
return res;
|
|
402
|
+
}
|
|
403
|
+
v0 = (VarBit *)PLRUBY_DFC3(bitsubstr, v, Int32GetDatum(beg + 1),
|
|
404
|
+
Int32GetDatum(len));
|
|
405
|
+
v1 = (VarBit *)ALLOC_N(char, VARSIZE(v0));
|
|
406
|
+
CPY_FREE(v1, v0, VARSIZE(v0));
|
|
407
|
+
res = Data_Wrap_Struct(rb_obj_class(obj), pl_bit_mark, free, v1);
|
|
408
|
+
if (OBJ_TAINTED(obj)) OBJ_TAINT(res);
|
|
409
|
+
return res;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
static VALUE
|
|
413
|
+
pl_bit_aref(VALUE obj, VALUE a)
|
|
414
|
+
{
|
|
415
|
+
VarBit *v, *v0, *v1;
|
|
416
|
+
long l, idx;
|
|
417
|
+
bits8 *sp, x;
|
|
418
|
+
VALUE res;
|
|
419
|
+
|
|
420
|
+
Data_Get_Struct(obj, VarBit, v);
|
|
421
|
+
l = DatumGetInt32(PLRUBY_DFC1(bitlength, v));
|
|
422
|
+
|
|
423
|
+
switch (TYPE(a)) {
|
|
424
|
+
case T_FIXNUM:
|
|
425
|
+
idx = FIX2LONG(a);
|
|
426
|
+
|
|
427
|
+
num_index:
|
|
428
|
+
if (idx < 0) {
|
|
429
|
+
idx = l + idx;
|
|
430
|
+
}
|
|
431
|
+
if (idx < 0 || l <= idx) {
|
|
432
|
+
return Qnil;
|
|
433
|
+
}
|
|
434
|
+
sp = VARBITS(v);
|
|
435
|
+
sp += (idx / BITS_PER_BYTE);
|
|
436
|
+
x = *sp <<= (idx % BITS_PER_BYTE);
|
|
437
|
+
if (IS_HIGHBIT_SET(x)) return INT2FIX(1);
|
|
438
|
+
return INT2FIX(0);
|
|
439
|
+
|
|
440
|
+
case T_REGEXP:
|
|
441
|
+
return pl_bit_subpat(obj, a, 0);
|
|
442
|
+
|
|
443
|
+
case T_STRING:
|
|
444
|
+
a = plruby_to_s(a);
|
|
445
|
+
v0 = (void *)PLRUBY_DFC3(bit_in, RSTRING_PTR(a),
|
|
446
|
+
ObjectIdGetDatum(0), Int32GetDatum(-1));
|
|
447
|
+
if (DatumGetInt32(PLRUBY_DFC2(bitposition, v, v0)) > 0) {
|
|
448
|
+
v1 = (VarBit *)ALLOC_N(char, VARSIZE(v0));
|
|
449
|
+
CPY_FREE(v1, v0, VARSIZE(v0));
|
|
450
|
+
res = Data_Wrap_Struct(CLASS_OF(obj), pl_bit_mark, free, v1);
|
|
451
|
+
if (OBJ_TAINTED(obj) || OBJ_TAINTED(a)) OBJ_TAINT(res);
|
|
452
|
+
return res;
|
|
453
|
+
}
|
|
454
|
+
pfree(v0);
|
|
455
|
+
return Qnil;
|
|
456
|
+
|
|
457
|
+
case T_DATA:
|
|
458
|
+
if (RDATA(a)->dmark != (RUBY_DATA_FUNC)pl_bit_mark) {
|
|
459
|
+
rb_raise(rb_eArgError, "expected a BitString object");
|
|
460
|
+
}
|
|
461
|
+
Data_Get_Struct(a, VarBit, v0);
|
|
462
|
+
if (DatumGetInt32(PLRUBY_DFC2(bitposition, v, v0)) > 0) {
|
|
463
|
+
return rb_funcall2(a, rb_intern("dup"), 0, 0);
|
|
464
|
+
}
|
|
465
|
+
return Qnil;
|
|
466
|
+
|
|
467
|
+
default:
|
|
468
|
+
{
|
|
469
|
+
long beg, len;
|
|
470
|
+
|
|
471
|
+
switch (rb_range_beg_len(a, &beg, &len, l, 0)) {
|
|
472
|
+
case Qfalse:
|
|
473
|
+
break;
|
|
474
|
+
case Qnil:
|
|
475
|
+
return Qnil;
|
|
476
|
+
default:
|
|
477
|
+
return pl_bit_substr(obj, beg, len);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
idx = NUM2LONG(a);
|
|
481
|
+
goto num_index;
|
|
482
|
+
}
|
|
483
|
+
return Qnil;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
static VALUE
|
|
487
|
+
pl_bit_aref_m(int argc, VALUE *argv, VALUE obj)
|
|
488
|
+
{
|
|
489
|
+
if (argc == 2) {
|
|
490
|
+
if (TYPE(argv[0]) == T_REGEXP) {
|
|
491
|
+
return pl_bit_subpat(obj, argv[0], NUM2INT(argv[1]));
|
|
492
|
+
}
|
|
493
|
+
return pl_bit_substr(obj, NUM2LONG(argv[0]), NUM2LONG(argv[1]));
|
|
494
|
+
}
|
|
495
|
+
if (argc != 1) {
|
|
496
|
+
rb_raise(rb_eArgError, "wrong number of arguments(%d for 1)", argc);
|
|
497
|
+
}
|
|
498
|
+
return pl_bit_aref(obj, argv[0]);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
static VALUE
|
|
502
|
+
pl_bit_aset(int argc, VALUE *argv, VALUE obj)
|
|
503
|
+
{
|
|
504
|
+
VALUE res;
|
|
505
|
+
int i;
|
|
506
|
+
void *v;
|
|
507
|
+
VarBit *inst;
|
|
508
|
+
|
|
509
|
+
for (i = 0; i < argc; ++i) {
|
|
510
|
+
if (TYPE(argv[i]) == T_DATA &&
|
|
511
|
+
RDATA(argv[i])->dmark == (RUBY_DATA_FUNC)pl_bit_mark) {
|
|
512
|
+
argv[i] = pl_bit_to_s(argv[i]);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
res = rb_funcall2(pl_bit_to_s(obj), rb_intern("[]="), argc, argv);
|
|
516
|
+
if (NIL_P(res)) return res;
|
|
517
|
+
res = plruby_to_s(res);
|
|
518
|
+
v = (void *)PLRUBY_DFC3(bit_in, RSTRING_PTR(res), ObjectIdGetDatum(0),
|
|
519
|
+
Int32GetDatum(-1));
|
|
520
|
+
Data_Get_Struct(obj, VarBit, inst);
|
|
521
|
+
free(inst);
|
|
522
|
+
inst = (VarBit *)ALLOC_N(char, VARSIZE(v));
|
|
523
|
+
CPY_FREE(inst, v, VARSIZE(v));
|
|
524
|
+
RDATA(obj)->data = inst;
|
|
525
|
+
return obj;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
void Init_plruby_bitstring()
|
|
529
|
+
{
|
|
530
|
+
VALUE pl_cBit;
|
|
531
|
+
|
|
532
|
+
pl_cBit = rb_define_class("BitString", rb_cObject);
|
|
533
|
+
rb_include_module(pl_cBit, rb_mComparable);
|
|
534
|
+
rb_include_module(pl_cBit, rb_mEnumerable);
|
|
535
|
+
rb_undef_method(CLASS_OF(pl_cBit), "method_missing");
|
|
536
|
+
#if HAVE_RB_DEFINE_ALLOC_FUNC
|
|
537
|
+
rb_define_alloc_func(pl_cBit, pl_bit_s_alloc);
|
|
538
|
+
#else
|
|
539
|
+
rb_define_singleton_method(pl_cBit, "allocate", pl_bit_s_alloc, 0);
|
|
540
|
+
#endif
|
|
541
|
+
rb_define_singleton_method(pl_cBit, "new", plruby_s_new, -1);
|
|
542
|
+
rb_define_singleton_method(pl_cBit, "from_string", plruby_s_new, -1);
|
|
543
|
+
rb_define_singleton_method(pl_cBit, "from_datum", pl_bit_s_datum, 1);
|
|
544
|
+
rb_define_method(pl_cBit, "to_datum", pl_bit_to_datum, 1);
|
|
545
|
+
rb_define_method(pl_cBit, "initialize", pl_bit_init, -1);
|
|
546
|
+
#ifndef HAVE_RB_INITIALIZE_COPY
|
|
547
|
+
rb_define_method(pl_cBit, "clone", plruby_clone, 0);
|
|
548
|
+
#endif
|
|
549
|
+
rb_define_method(pl_cBit, "initialize_copy", pl_bit_init_copy, 1);
|
|
550
|
+
#if PG_PL_VERSION >= 74
|
|
551
|
+
rb_define_method(pl_cBit, "marshal_load", pl_bit_mload, 1);
|
|
552
|
+
rb_define_method(pl_cBit, "marshal_dump", pl_bit_mdump, -1);
|
|
553
|
+
#ifndef RUBY_CAN_USE_MARSHAL_LOAD
|
|
554
|
+
rb_define_singleton_method(pl_cBit, "_load", plruby_s_load, 1);
|
|
555
|
+
rb_define_alias(pl_cBit, "_dump", "marshal_dump");
|
|
556
|
+
#endif
|
|
557
|
+
#endif
|
|
558
|
+
rb_define_method(pl_cBit, "<=>", pl_bit_cmp, 1);
|
|
559
|
+
rb_define_method(pl_cBit, "each", pl_bit_each, 0);
|
|
560
|
+
rb_define_method(pl_cBit, "+", pl_bit_add, 1);
|
|
561
|
+
rb_define_method(pl_cBit, "concat", pl_bit_push, 1);
|
|
562
|
+
rb_define_method(pl_cBit, "push", pl_bit_push, 1);
|
|
563
|
+
rb_define_method(pl_cBit, "index", pl_bit_index, 1);
|
|
564
|
+
rb_define_method(pl_cBit, "include?", pl_bit_include, 1);
|
|
565
|
+
rb_define_method(pl_cBit, "&", pl_bit_and, 1);
|
|
566
|
+
rb_define_method(pl_cBit, "|", pl_bit_or, 1);
|
|
567
|
+
rb_define_method(pl_cBit, "^", pl_bit_xor, 1);
|
|
568
|
+
rb_define_method(pl_cBit, "~", pl_bit_not, 0);
|
|
569
|
+
rb_define_method(pl_cBit, "<<", pl_bit_left_shift, 1);
|
|
570
|
+
rb_define_method(pl_cBit, ">>", pl_bit_right_shift, 1);
|
|
571
|
+
rb_define_method(pl_cBit, "[]", pl_bit_aref_m, -1);
|
|
572
|
+
rb_define_method(pl_cBit, "[]=", pl_bit_aset, -1);
|
|
573
|
+
rb_define_method(pl_cBit, "length", pl_bit_length, 0);
|
|
574
|
+
rb_define_method(pl_cBit, "size", pl_bit_length, 0);
|
|
575
|
+
rb_define_method(pl_cBit, "octet_length", pl_bit_octet_length, 0);
|
|
576
|
+
rb_define_method(pl_cBit, "octet_size", pl_bit_octet_length, 0);
|
|
577
|
+
rb_define_method(pl_cBit, "to_s", pl_bit_to_s, 0);
|
|
578
|
+
rb_define_method(pl_cBit, "to_i", pl_bit_to_i, 0);
|
|
579
|
+
}
|