globegit-postgresql-plruby 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. data/Changes +121 -0
  2. data/README.markdown +155 -0
  3. data/Rakefile +48 -0
  4. data/docs/plruby.rb +1931 -0
  5. data/ex_trans.sql +33 -0
  6. data/extconf.rb +267 -0
  7. data/plruby.html +1454 -0
  8. data/plruby.rd +1571 -0
  9. data/postgresql-plruby.gemspec +56 -0
  10. data/src/conversions.h +5 -0
  11. data/src/conversions/basic/conversions.h +25 -0
  12. data/src/conversions/basic/extconf.rb +8 -0
  13. data/src/conversions/basic/plruby_basic.c +357 -0
  14. data/src/conversions/bitstring/bitstring.sql +75 -0
  15. data/src/conversions/bitstring/conversions.h +15 -0
  16. data/src/conversions/bitstring/extconf.rb +8 -0
  17. data/src/conversions/bitstring/plruby_bitstring.c +579 -0
  18. data/src/conversions/convcommon.h +129 -0
  19. data/src/conversions/datetime/conversions.h +13 -0
  20. data/src/conversions/datetime/extconf.rb +8 -0
  21. data/src/conversions/datetime/plruby_datetime.c +269 -0
  22. data/src/conversions/geometry/conversions.h +37 -0
  23. data/src/conversions/geometry/extconf.rb +8 -0
  24. data/src/conversions/geometry/geometry.sql +196 -0
  25. data/src/conversions/geometry/plruby_geometry.c +2494 -0
  26. data/src/conversions/network/conversions.h +21 -0
  27. data/src/conversions/network/extconf.rb +8 -0
  28. data/src/conversions/network/network.sql +63 -0
  29. data/src/conversions/network/plruby_network.c +537 -0
  30. data/src/package.h +20 -0
  31. data/src/plpl.c +1708 -0
  32. data/src/plplan.c +893 -0
  33. data/src/plruby.c +1676 -0
  34. data/src/plruby.h +324 -0
  35. data/src/pltrans.c +388 -0
  36. data/test/conv_bitstring/b.rb +45 -0
  37. data/test/conv_bitstring/runtest +26 -0
  38. data/test/conv_bitstring/test.expected.73 +148 -0
  39. data/test/conv_bitstring/test.expected.74 +148 -0
  40. data/test/conv_bitstring/test.expected.80 +148 -0
  41. data/test/conv_bitstring/test.expected.81 +148 -0
  42. data/test/conv_bitstring/test.expected.82 +148 -0
  43. data/test/conv_bitstring/test.expected.83 +148 -0
  44. data/test/conv_bitstring/test.expected.84 +148 -0
  45. data/test/conv_bitstring/test.out +148 -0
  46. data/test/conv_bitstring/test_mklang.sql +8 -0
  47. data/test/conv_bitstring/test_queries.sql +63 -0
  48. data/test/conv_bitstring/test_queries.sql.in +63 -0
  49. data/test/conv_geometry/b.rb +45 -0
  50. data/test/conv_geometry/runtest +26 -0
  51. data/test/conv_geometry/test.expected.73 +265 -0
  52. data/test/conv_geometry/test.expected.74 +265 -0
  53. data/test/conv_geometry/test.expected.80 +265 -0
  54. data/test/conv_geometry/test.expected.81 +265 -0
  55. data/test/conv_geometry/test.expected.82 +265 -0
  56. data/test/conv_geometry/test.expected.83 +265 -0
  57. data/test/conv_geometry/test.expected.84 +265 -0
  58. data/test/conv_geometry/test.out +265 -0
  59. data/test/conv_geometry/test_mklang.sql +8 -0
  60. data/test/conv_geometry/test_queries.sql +194 -0
  61. data/test/conv_geometry/test_queries.sql.in +194 -0
  62. data/test/conv_network/b.rb +45 -0
  63. data/test/conv_network/runtest +26 -0
  64. data/test/conv_network/test.expected.73 +213 -0
  65. data/test/conv_network/test.expected.74 +237 -0
  66. data/test/conv_network/test.expected.80 +237 -0
  67. data/test/conv_network/test.expected.81 +237 -0
  68. data/test/conv_network/test.expected.82 +237 -0
  69. data/test/conv_network/test.expected.83 +237 -0
  70. data/test/conv_network/test.expected.84 +237 -0
  71. data/test/conv_network/test.out +237 -0
  72. data/test/conv_network/test_mklang.sql +8 -0
  73. data/test/conv_network/test_queries.sql +60 -0
  74. data/test/conv_network/test_queries.sql.in +60 -0
  75. data/test/plp/b.rb +34 -0
  76. data/test/plp/runtest +29 -0
  77. data/test/plp/test.expected.73 +472 -0
  78. data/test/plp/test.expected.74 +472 -0
  79. data/test/plp/test.expected.75 +472 -0
  80. data/test/plp/test.expected.80 +472 -0
  81. data/test/plp/test.expected.81 +472 -0
  82. data/test/plp/test.expected.82 +472 -0
  83. data/test/plp/test.expected.83 +472 -0
  84. data/test/plp/test.expected.84 +472 -0
  85. data/test/plp/test.out +472 -0
  86. data/test/plp/test_mklang.sql +8 -0
  87. data/test/plp/test_queries.sql +273 -0
  88. data/test/plp/test_setup.sql +931 -0
  89. data/test/plp/test_setup.sql.in +931 -0
  90. data/test/plt/b.rb +34 -0
  91. data/test/plt/runtest +29 -0
  92. data/test/plt/test.expected.73 +178 -0
  93. data/test/plt/test.expected.74 +178 -0
  94. data/test/plt/test.expected.75 +178 -0
  95. data/test/plt/test.expected.80 +178 -0
  96. data/test/plt/test.expected.81 +178 -0
  97. data/test/plt/test.expected.82 +178 -0
  98. data/test/plt/test.expected.83 +164 -0
  99. data/test/plt/test.expected.84 +168 -0
  100. data/test/plt/test.out +168 -0
  101. data/test/plt/test_mklang.sql +8 -0
  102. data/test/plt/test_queries.sql +72 -0
  103. data/test/plt/test_setup.sql +252 -0
  104. data/test/plt/test_setup.sql.in +252 -0
  105. data/test/range/b.rb +45 -0
  106. data/test/range/runtest +26 -0
  107. data/test/range/test.expected.73 +396 -0
  108. data/test/range/test.expected.73.in +396 -0
  109. data/test/range/test.expected.74 +396 -0
  110. data/test/range/test.expected.74.in +396 -0
  111. data/test/range/test.expected.75 +396 -0
  112. data/test/range/test.expected.75.in +396 -0
  113. data/test/range/test.expected.80 +396 -0
  114. data/test/range/test.expected.81 +397 -0
  115. data/test/range/test.expected.82 +397 -0
  116. data/test/range/test.expected.83 +397 -0
  117. data/test/range/test.expected.84 +399 -0
  118. data/test/range/test.out +399 -0
  119. data/test/range/test_mklang.sql +8 -0
  120. data/test/range/test_queries.sql +249 -0
  121. data/test/range/test_queries.sql.in +249 -0
  122. 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,8 @@
1
+ require 'mkmf'
2
+
3
+ if CONFIG["LIBRUBYARG"] == "$(LIBRUBYARG_SHARED)" &&
4
+ !enable_config("plruby-shared")
5
+ $LIBRUBYARG = ""
6
+ end
7
+ have_library('ruby18', 'ruby_init')
8
+ create_makefile('plruby/plruby_bitstring')
@@ -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
+ }