ruby-oci8 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +569 -0
- data/Makefile +51 -0
- data/NEWS +322 -0
- data/README +415 -0
- data/VERSION +1 -0
- data/dist-files +70 -0
- data/doc/api.en.html +527 -0
- data/doc/api.en.rd +554 -0
- data/doc/api.ja.html +525 -0
- data/doc/api.ja.rd +557 -0
- data/doc/manual.css +35 -0
- data/ext/oci8/MANIFEST +22 -0
- data/ext/oci8/attr.c +415 -0
- data/ext/oci8/bind.c +194 -0
- data/ext/oci8/const.c +165 -0
- data/ext/oci8/define.c +53 -0
- data/ext/oci8/describe.c +81 -0
- data/ext/oci8/descriptor.c +39 -0
- data/ext/oci8/env.c +276 -0
- data/ext/oci8/error.c +234 -0
- data/ext/oci8/extconf.rb +118 -0
- data/ext/oci8/handle.c +262 -0
- data/ext/oci8/lob.c +386 -0
- data/ext/oci8/oci8.c +137 -0
- data/ext/oci8/oci8.h +345 -0
- data/ext/oci8/ocinumber.c +117 -0
- data/ext/oci8/oraconf.rb +1026 -0
- data/ext/oci8/oradate.c +426 -0
- data/ext/oci8/oranumber.c +445 -0
- data/ext/oci8/param.c +37 -0
- data/ext/oci8/post-config.rb +5 -0
- data/ext/oci8/server.c +182 -0
- data/ext/oci8/session.c +99 -0
- data/ext/oci8/stmt.c +624 -0
- data/ext/oci8/svcctx.c +229 -0
- data/lib/DBD/OCI8/OCI8.rb +549 -0
- data/lib/oci8.rb.in +1605 -0
- data/metaconfig +142 -0
- data/pre-distclean.rb +7 -0
- data/ruby-oci8.gemspec +54 -0
- data/ruby-oci8.spec +62 -0
- data/setup.rb +1331 -0
- data/support/README +4 -0
- data/support/runit/assert.rb +281 -0
- data/support/runit/cui/testrunner.rb +101 -0
- data/support/runit/error.rb +4 -0
- data/support/runit/method_mappable.rb +20 -0
- data/support/runit/robserver.rb +25 -0
- data/support/runit/setuppable.rb +15 -0
- data/support/runit/teardownable.rb +16 -0
- data/support/runit/testcase.rb +113 -0
- data/support/runit/testfailure.rb +25 -0
- data/support/runit/testresult.rb +121 -0
- data/support/runit/testsuite.rb +43 -0
- data/support/runit/version.rb +3 -0
- data/test/README +4 -0
- data/test/config.rb +129 -0
- data/test/test_all.rb +43 -0
- data/test/test_bind_raw.rb +53 -0
- data/test/test_bind_time.rb +191 -0
- data/test/test_break.rb +81 -0
- data/test/test_clob.rb +101 -0
- data/test/test_connstr.rb +80 -0
- data/test/test_dbi.rb +317 -0
- data/test/test_dbi_clob.rb +56 -0
- data/test/test_describe.rb +137 -0
- data/test/test_metadata.rb +243 -0
- data/test/test_oci8.rb +273 -0
- data/test/test_oradate.rb +263 -0
- data/test/test_oranumber.rb +149 -0
- metadata +118 -0
data/ext/oci8/oradate.c
ADDED
@@ -0,0 +1,426 @@
|
|
1
|
+
/*
|
2
|
+
oradate.c - part of ruby-oci8
|
3
|
+
|
4
|
+
Copyright (C) 2002 KUBO Takehiro <kubo@jiubao.org>
|
5
|
+
|
6
|
+
=begin
|
7
|
+
== OraDate
|
8
|
+
date and time between 4712 B.C. and 9999 A.D.
|
9
|
+
=end
|
10
|
+
*/
|
11
|
+
#include "oci8.h"
|
12
|
+
#include <time.h>
|
13
|
+
|
14
|
+
#define Set_year(od, y) (od)->century = y / 100 + 100, (od)->year = y % 100 + 100
|
15
|
+
#define Set_month(od, m) (od)->month = m
|
16
|
+
#define Set_day(od, d) (od)->day = d
|
17
|
+
#define Set_hour(od, h) (od)->hour = h + 1
|
18
|
+
#define Set_minute(od, m) (od)->minute = m + 1
|
19
|
+
#define Set_second(od, s) (od)->second = s + 1
|
20
|
+
|
21
|
+
#define Get_year(od) (((od)->century - 100) * 100 + ((od)->year - 100))
|
22
|
+
#define Get_month(od) ((od)->month)
|
23
|
+
#define Get_day(od) ((od)->day)
|
24
|
+
#define Get_hour(od) ((od)->hour - 1)
|
25
|
+
#define Get_minute(od) ((od)->minute - 1)
|
26
|
+
#define Get_second(od) ((od)->second - 1)
|
27
|
+
|
28
|
+
#define Check_year(year) \
|
29
|
+
if (year < -4712 || 9999 < year) \
|
30
|
+
rb_raise(rb_eRangeError, "Out of range for year %d (expect -4712 .. 9999)", year)
|
31
|
+
#define Check_month(month) \
|
32
|
+
if (month < 1 || 12 < month) \
|
33
|
+
rb_raise(rb_eRangeError, "Out of range for month %d (expect 1 .. 12)", month)
|
34
|
+
#define Check_day(day) \
|
35
|
+
if (day < 1 || 31 < day) \
|
36
|
+
rb_raise(rb_eRangeError, "Out of range for day %d (expect 1 .. 31)", day)
|
37
|
+
#define Check_hour(hour) \
|
38
|
+
if (hour < 0 || 23 < hour) \
|
39
|
+
rb_raise(rb_eRangeError, "Out of range for hour %d (expect 0 .. 24)", hour)
|
40
|
+
#define Check_minute(min) \
|
41
|
+
if (min < 0 || 59 < min) \
|
42
|
+
rb_raise(rb_eRangeError, "Out of range for minute %d (expect 0 .. 59)", min)
|
43
|
+
#define Check_second(sec) \
|
44
|
+
if (sec < 0 || 59 < sec) \
|
45
|
+
rb_raise(rb_eRangeError, "Out of range for second %d (expect 0 .. 59)", sec)
|
46
|
+
|
47
|
+
|
48
|
+
static VALUE ora_date_s_allocate(VALUE klass)
|
49
|
+
{
|
50
|
+
ora_date_t *od;
|
51
|
+
return Data_Make_Struct(klass, ora_date_t, NULL, xfree, od);
|
52
|
+
}
|
53
|
+
|
54
|
+
#ifndef HAVE_RB_DEFINE_ALLOC_FUNC
|
55
|
+
/* ruby 1.6 */
|
56
|
+
static VALUE ora_date_s_new(int argc, VALUE *argv, VALUE klass)
|
57
|
+
{
|
58
|
+
VALUE obj = ora_date_s_allocate(klass);
|
59
|
+
rb_obj_call_init(obj, argc, argv);
|
60
|
+
return obj;
|
61
|
+
}
|
62
|
+
#endif
|
63
|
+
|
64
|
+
/*
|
65
|
+
=begin
|
66
|
+
--- OraDate.new([year [, month [, day [, hour [, min [,sec]]]]]])
|
67
|
+
=end
|
68
|
+
*/
|
69
|
+
static VALUE ora_date_initialize(int argc, VALUE *argv, VALUE self)
|
70
|
+
{
|
71
|
+
VALUE vyear, vmonth, vday, vhour, vmin, vsec;
|
72
|
+
ora_date_t *od;
|
73
|
+
int year, month, day, hour, min, sec;
|
74
|
+
|
75
|
+
rb_scan_args(argc, argv, "06", &vyear, &vmonth, &vday, &vhour, &vmin, &vsec);
|
76
|
+
/* set year */
|
77
|
+
if (argc > 0) {
|
78
|
+
year = NUM2INT(vyear);
|
79
|
+
Check_year(year);
|
80
|
+
} else {
|
81
|
+
year = 1;
|
82
|
+
}
|
83
|
+
/* set month */
|
84
|
+
if (argc > 1) {
|
85
|
+
month = NUM2INT(vmonth);
|
86
|
+
Check_month(month);
|
87
|
+
} else {
|
88
|
+
month = 1;
|
89
|
+
}
|
90
|
+
/* set day */
|
91
|
+
if (argc > 2) {
|
92
|
+
day = NUM2INT(vday);
|
93
|
+
Check_day(day);
|
94
|
+
} else {
|
95
|
+
day = 1;
|
96
|
+
}
|
97
|
+
/* set hour */
|
98
|
+
if (argc > 3) {
|
99
|
+
hour = NUM2INT(vhour);
|
100
|
+
Check_hour(hour);
|
101
|
+
} else {
|
102
|
+
hour = 0;
|
103
|
+
}
|
104
|
+
/* set minute */
|
105
|
+
if (argc > 4) {
|
106
|
+
min = NUM2INT(vmin);
|
107
|
+
Check_minute(min);
|
108
|
+
} else {
|
109
|
+
min = 0;
|
110
|
+
}
|
111
|
+
/* set second */
|
112
|
+
if (argc > 5) {
|
113
|
+
sec = NUM2INT(vsec);
|
114
|
+
Check_second(sec);
|
115
|
+
} else {
|
116
|
+
sec = 0;
|
117
|
+
}
|
118
|
+
|
119
|
+
Data_Get_Struct(self, ora_date_t, od);
|
120
|
+
oci8_set_ora_date(od, year, month, day, hour, min, sec);
|
121
|
+
return Qnil;
|
122
|
+
}
|
123
|
+
|
124
|
+
static VALUE ora_date_initialize_copy(VALUE lhs, VALUE rhs)
|
125
|
+
{
|
126
|
+
ora_date_t *l, *r;
|
127
|
+
|
128
|
+
#ifdef HAVE_RB_DEFINE_ALLOC_FUNC
|
129
|
+
/* ruby 1.8 */
|
130
|
+
rb_obj_init_copy(lhs, rhs);
|
131
|
+
#endif
|
132
|
+
Data_Get_Struct(lhs, ora_date_t, l);
|
133
|
+
Data_Get_Struct(rhs, ora_date_t, r);
|
134
|
+
memcpy(l, r, sizeof(ora_date_t));
|
135
|
+
return lhs;
|
136
|
+
}
|
137
|
+
|
138
|
+
#ifndef HAVE_RB_DEFINE_ALLOC_FUNC
|
139
|
+
/* ruby 1.6 */
|
140
|
+
static VALUE ora_date_clone(VALUE self)
|
141
|
+
{
|
142
|
+
VALUE obj = ora_date_s_allocate(CLASS_OF(self));
|
143
|
+
return ora_date_initialize_copy(obj, self);
|
144
|
+
}
|
145
|
+
#endif
|
146
|
+
|
147
|
+
/*
|
148
|
+
=begin
|
149
|
+
--- OraDate.now()
|
150
|
+
=end
|
151
|
+
*/
|
152
|
+
static VALUE ora_date_s_now(int argc, VALUE *argv)
|
153
|
+
{
|
154
|
+
ora_date_t *od;
|
155
|
+
VALUE obj;
|
156
|
+
int year, month, day, hour, min, sec;
|
157
|
+
time_t tm;
|
158
|
+
struct tm *tp;
|
159
|
+
|
160
|
+
tm = time(0);
|
161
|
+
tp = localtime(&tm);
|
162
|
+
year = tp->tm_year + 1900;
|
163
|
+
month = tp->tm_mon + 1;
|
164
|
+
day = tp->tm_mday;
|
165
|
+
hour = tp->tm_hour;
|
166
|
+
min = tp->tm_min;
|
167
|
+
sec = tp->tm_sec;
|
168
|
+
|
169
|
+
obj = Data_Make_Struct(cOraDate, ora_date_t, NULL, xfree, od);
|
170
|
+
oci8_set_ora_date(od, year, month, day, hour, min, sec);
|
171
|
+
return obj;
|
172
|
+
}
|
173
|
+
|
174
|
+
/*
|
175
|
+
=begin
|
176
|
+
--- OraDate#to_s()
|
177
|
+
=end
|
178
|
+
*/
|
179
|
+
static VALUE ora_date_to_s(VALUE self)
|
180
|
+
{
|
181
|
+
ora_date_t *od;
|
182
|
+
char buf[30];
|
183
|
+
|
184
|
+
Data_Get_Struct(self, ora_date_t, od);
|
185
|
+
sprintf(buf, "%04d/%02d/%02d %02d:%02d:%02d", Get_year(od), Get_month(od),
|
186
|
+
Get_day(od), Get_hour(od), Get_minute(od), Get_second(od));
|
187
|
+
return rb_str_new2(buf);
|
188
|
+
}
|
189
|
+
|
190
|
+
/*
|
191
|
+
=begin
|
192
|
+
--- OraDate#to_a()
|
193
|
+
=end
|
194
|
+
*/
|
195
|
+
static VALUE ora_date_to_a(VALUE self)
|
196
|
+
{
|
197
|
+
ora_date_t *od;
|
198
|
+
VALUE ary[6];
|
199
|
+
|
200
|
+
Data_Get_Struct(self, ora_date_t, od);
|
201
|
+
ary[0] = INT2FIX(Get_year(od));
|
202
|
+
ary[1] = INT2FIX(Get_month(od));
|
203
|
+
ary[2] = INT2FIX(Get_day(od));
|
204
|
+
ary[3] = INT2FIX(Get_hour(od));
|
205
|
+
ary[4] = INT2FIX(Get_minute(od));
|
206
|
+
ary[5] = INT2FIX(Get_second(od));
|
207
|
+
return rb_ary_new4(6, ary);
|
208
|
+
}
|
209
|
+
|
210
|
+
#define DEFINE_GETTER_FUNC(where) \
|
211
|
+
static VALUE ora_date_##where(VALUE self) \
|
212
|
+
{ \
|
213
|
+
ora_date_t *od; \
|
214
|
+
\
|
215
|
+
Data_Get_Struct(self, ora_date_t, od); \
|
216
|
+
return INT2FIX(Get_##where(od)); \
|
217
|
+
}
|
218
|
+
|
219
|
+
#define DEFINE_SETTER_FUNC(where) \
|
220
|
+
static VALUE ora_date_set_##where(VALUE self, VALUE val) \
|
221
|
+
{ \
|
222
|
+
ora_date_t *od; \
|
223
|
+
int v; \
|
224
|
+
\
|
225
|
+
v = NUM2INT(val); \
|
226
|
+
Check_##where(v); \
|
227
|
+
Data_Get_Struct(self, ora_date_t, od); \
|
228
|
+
Set_##where(od, v); \
|
229
|
+
return self; \
|
230
|
+
}
|
231
|
+
|
232
|
+
/*
|
233
|
+
=begin
|
234
|
+
--- OraDate#year
|
235
|
+
=end
|
236
|
+
*/
|
237
|
+
DEFINE_GETTER_FUNC(year)
|
238
|
+
DEFINE_SETTER_FUNC(year)
|
239
|
+
|
240
|
+
/*
|
241
|
+
=begin
|
242
|
+
--- OraDate#month
|
243
|
+
=end
|
244
|
+
*/
|
245
|
+
DEFINE_GETTER_FUNC(month)
|
246
|
+
DEFINE_SETTER_FUNC(month)
|
247
|
+
|
248
|
+
/*
|
249
|
+
=begin
|
250
|
+
--- OraDate#day
|
251
|
+
=end
|
252
|
+
*/
|
253
|
+
DEFINE_GETTER_FUNC(day)
|
254
|
+
DEFINE_SETTER_FUNC(day)
|
255
|
+
|
256
|
+
/*
|
257
|
+
=begin
|
258
|
+
--- OraDate#hour
|
259
|
+
=end
|
260
|
+
*/
|
261
|
+
DEFINE_GETTER_FUNC(hour)
|
262
|
+
DEFINE_SETTER_FUNC(hour)
|
263
|
+
|
264
|
+
/*
|
265
|
+
=begin
|
266
|
+
--- OraDate#minute
|
267
|
+
=end
|
268
|
+
*/
|
269
|
+
DEFINE_GETTER_FUNC(minute)
|
270
|
+
DEFINE_SETTER_FUNC(minute)
|
271
|
+
|
272
|
+
/*
|
273
|
+
=begin
|
274
|
+
--- OraDate#second
|
275
|
+
=end
|
276
|
+
*/
|
277
|
+
DEFINE_GETTER_FUNC(second)
|
278
|
+
DEFINE_SETTER_FUNC(second)
|
279
|
+
|
280
|
+
/*
|
281
|
+
=begin
|
282
|
+
--- OraDate#trunc()
|
283
|
+
=end
|
284
|
+
*/
|
285
|
+
static VALUE ora_date_trunc(VALUE self)
|
286
|
+
{
|
287
|
+
ora_date_t *od;
|
288
|
+
|
289
|
+
Data_Get_Struct(self, ora_date_t, od);
|
290
|
+
od->hour = 1;
|
291
|
+
od->minute = 1;
|
292
|
+
od->second = 1;
|
293
|
+
return self;
|
294
|
+
}
|
295
|
+
|
296
|
+
static VALUE ora_date_hash(VALUE self)
|
297
|
+
{
|
298
|
+
ora_date_t *od;
|
299
|
+
unsigned int v;
|
300
|
+
|
301
|
+
Data_Get_Struct(self, ora_date_t, od);
|
302
|
+
v = (od->century << 8)
|
303
|
+
+ (od->year << 15)
|
304
|
+
+ (od->month << 22)
|
305
|
+
+ (od->day << 26)
|
306
|
+
+ (od->hour << 12)
|
307
|
+
+ (od->minute << 6)
|
308
|
+
+ (od->second << 0);
|
309
|
+
return INT2FIX(v);
|
310
|
+
}
|
311
|
+
|
312
|
+
/*
|
313
|
+
=begin
|
314
|
+
--- OraDate#<=>(other)
|
315
|
+
=end
|
316
|
+
*/
|
317
|
+
static VALUE ora_date_cmp(VALUE self, VALUE val)
|
318
|
+
{
|
319
|
+
ora_date_t *od1, *od2;
|
320
|
+
Data_Get_Struct(self, ora_date_t, od1);
|
321
|
+
Data_Get_Struct(val, ora_date_t, od2);
|
322
|
+
if (od1->century < od2->century) return INT2FIX(-1);
|
323
|
+
if (od1->century > od2->century) return INT2FIX(1);
|
324
|
+
if (od1->year < od2->year) return INT2FIX(-1);
|
325
|
+
if (od1->year > od2->year) return INT2FIX(1);
|
326
|
+
if (od1->month < od2->month) return INT2FIX(-1);
|
327
|
+
if (od1->month > od2->month) return INT2FIX(1);
|
328
|
+
if (od1->day < od2->day) return INT2FIX(-1);
|
329
|
+
if (od1->day > od2->day) return INT2FIX(1);
|
330
|
+
if (od1->hour < od2->hour) return INT2FIX(-1);
|
331
|
+
if (od1->hour > od2->hour) return INT2FIX(1);
|
332
|
+
if (od1->minute < od2->minute) return INT2FIX(-1);
|
333
|
+
if (od1->minute > od2->minute) return INT2FIX(1);
|
334
|
+
if (od1->second < od2->second) return INT2FIX(-1);
|
335
|
+
if (od1->second > od2->second) return INT2FIX(1);
|
336
|
+
return INT2FIX(0);
|
337
|
+
}
|
338
|
+
|
339
|
+
static VALUE ora_date_dump(int argc, VALUE *argv, VALUE self)
|
340
|
+
{
|
341
|
+
ora_date_t *od;
|
342
|
+
Data_Get_Struct(self, ora_date_t, od);
|
343
|
+
return rb_str_new((const char*)od, sizeof(ora_date_t));
|
344
|
+
}
|
345
|
+
|
346
|
+
static VALUE ora_date_s_load(VALUE klass, VALUE str)
|
347
|
+
{
|
348
|
+
ora_date_t *od;
|
349
|
+
VALUE obj;
|
350
|
+
|
351
|
+
Check_Type(str, T_STRING);
|
352
|
+
if (RSTRING_LEN(str) != sizeof(ora_date_t)) {
|
353
|
+
rb_raise(rb_eTypeError, "marshaled OraDate format differ");
|
354
|
+
}
|
355
|
+
obj = Data_Make_Struct(cOraDate, ora_date_t, NULL, xfree, od);
|
356
|
+
memcpy(od, RSTRING_PTR(str), sizeof(ora_date_t));
|
357
|
+
return obj;
|
358
|
+
}
|
359
|
+
|
360
|
+
void Init_ora_date(void)
|
361
|
+
{
|
362
|
+
#ifdef HAVE_RB_DEFINE_ALLOC_FUNC
|
363
|
+
/* ruby 1.8 */
|
364
|
+
rb_define_alloc_func(cOraDate, RUBY_METHOD_FUNC(ora_date_s_allocate));
|
365
|
+
rb_define_method(cOraDate, "initialize", ora_date_initialize, -1);
|
366
|
+
rb_define_method(cOraDate, "initialize_copy", ora_date_initialize_copy, 1);
|
367
|
+
#else
|
368
|
+
/* ruby 1.6 */
|
369
|
+
rb_define_singleton_method(cOraDate, "new", ora_date_s_new, -1);
|
370
|
+
rb_define_method(cOraDate, "initialize", ora_date_initialize, -1);
|
371
|
+
rb_define_method(cOraDate, "clone", ora_date_clone, 0);
|
372
|
+
rb_define_method(cOraDate, "dup", ora_date_clone, 0);
|
373
|
+
#endif
|
374
|
+
|
375
|
+
rb_define_singleton_method(cOraDate, "now", ora_date_s_now, 0);
|
376
|
+
rb_define_method(cOraDate, "to_s", ora_date_to_s, 0);
|
377
|
+
rb_define_method(cOraDate, "to_a", ora_date_to_a, 0);
|
378
|
+
|
379
|
+
rb_define_method(cOraDate, "year", ora_date_year, 0);
|
380
|
+
rb_define_method(cOraDate, "year=", ora_date_set_year, 1);
|
381
|
+
|
382
|
+
rb_define_method(cOraDate, "month", ora_date_month, 0);
|
383
|
+
rb_define_method(cOraDate, "month=", ora_date_set_month, 1);
|
384
|
+
|
385
|
+
rb_define_method(cOraDate, "day", ora_date_day, 0);
|
386
|
+
rb_define_method(cOraDate, "day=", ora_date_set_day, 1);
|
387
|
+
|
388
|
+
rb_define_method(cOraDate, "hour", ora_date_hour, 0);
|
389
|
+
rb_define_method(cOraDate, "hour=", ora_date_set_hour, 1);
|
390
|
+
|
391
|
+
rb_define_method(cOraDate, "minute", ora_date_minute, 0);
|
392
|
+
rb_define_method(cOraDate, "minute=", ora_date_set_minute, 1);
|
393
|
+
|
394
|
+
rb_define_method(cOraDate, "second", ora_date_second, 0);
|
395
|
+
rb_define_method(cOraDate, "second=", ora_date_set_second, 1);
|
396
|
+
|
397
|
+
rb_define_method(cOraDate, "trunc", ora_date_trunc, 0);
|
398
|
+
|
399
|
+
rb_define_method(cOraDate, "<=>", ora_date_cmp, 1);
|
400
|
+
rb_include_module(cOraDate, rb_mComparable);
|
401
|
+
|
402
|
+
rb_define_method(cOraDate, "hash", ora_date_hash, 0);
|
403
|
+
|
404
|
+
rb_define_method(cOraDate, "_dump", ora_date_dump, -1);
|
405
|
+
rb_define_singleton_method(cOraDate, "_load", ora_date_s_load, 1);
|
406
|
+
}
|
407
|
+
|
408
|
+
void oci8_set_ora_date(ora_date_t *od, int year, int month, int day, int hour, int minute, int second)
|
409
|
+
{
|
410
|
+
Set_year(od, year);
|
411
|
+
Set_month(od, month);
|
412
|
+
Set_day(od, day);
|
413
|
+
Set_hour(od, hour);
|
414
|
+
Set_minute(od, minute);
|
415
|
+
Set_second(od, second);
|
416
|
+
}
|
417
|
+
|
418
|
+
void oci8_get_ora_date(ora_date_t *od, int *year, int *month, int *day, int *hour, int *minute, int *second)
|
419
|
+
{
|
420
|
+
*year = Get_year(od);
|
421
|
+
*month = Get_month(od);
|
422
|
+
*day = Get_day(od);
|
423
|
+
*hour = Get_hour(od);
|
424
|
+
*minute = Get_minute(od);
|
425
|
+
*second = Get_second(od);
|
426
|
+
}
|
@@ -0,0 +1,445 @@
|
|
1
|
+
/*
|
2
|
+
oranumber.c - part of ruby-oci8
|
3
|
+
|
4
|
+
Copyright (C) 2002 KUBO Takehiro <kubo@jiubao.org>
|
5
|
+
|
6
|
+
=begin
|
7
|
+
== OraNumber
|
8
|
+
This is not a numeric class, so algebra operations and setter methods
|
9
|
+
are not permitted, but a place to hold fetched date from Oracle server.
|
10
|
+
|
11
|
+
In fact as matter, this is a test class to check the algorithm to
|
12
|
+
convert Oracle internal number format to Ruby's number, which is internally used by,
|
13
|
+
for example, ((<OCIStmt#attrGet|OCIHandle#attrGet>))(((<OCI_ATTR_MIN>))).
|
14
|
+
=end
|
15
|
+
*/
|
16
|
+
#include "oci8.h"
|
17
|
+
#include "math.h"
|
18
|
+
|
19
|
+
#define Get_Sign(on) ((on)->exponent & 0x80)
|
20
|
+
#define Get_Exp_Part(on) ((on)->exponent & 0x7F)
|
21
|
+
#define Get_Exponent(on) (Get_Sign(on) ? (Get_Exp_Part(on) - 65) : (~(Get_Exp_Part(on)) + 63))
|
22
|
+
#define Get_Mantissa_At(on, i) (Get_Sign(on) ? (on)->mantissa[i] - 1 : 101 - (on)->mantissa[i])
|
23
|
+
|
24
|
+
static int ora_number_from_str(ora_vnumber_t *ovn, unsigned char *buf, size_t len);
|
25
|
+
|
26
|
+
static ora_vnumber_t *get_ora_number(VALUE self)
|
27
|
+
{
|
28
|
+
ora_vnumber_t *ovn;
|
29
|
+
Data_Get_Struct(self, ora_vnumber_t, ovn);
|
30
|
+
return ovn;
|
31
|
+
}
|
32
|
+
|
33
|
+
static VALUE ora_number_s_allocate(VALUE klass)
|
34
|
+
{
|
35
|
+
ora_vnumber_t *ovn;
|
36
|
+
return Data_Make_Struct(klass, ora_vnumber_t, NULL, xfree, ovn);
|
37
|
+
}
|
38
|
+
|
39
|
+
#ifndef HAVE_RB_DEFINE_ALLOC_FUNC
|
40
|
+
/* ruby 1.6 */
|
41
|
+
static VALUE ora_number_s_new(int argc, VALUE *argv, VALUE klass)
|
42
|
+
{
|
43
|
+
VALUE obj = ora_number_s_allocate(klass);
|
44
|
+
rb_obj_call_init(obj, argc, argv);
|
45
|
+
return obj;
|
46
|
+
}
|
47
|
+
#endif
|
48
|
+
|
49
|
+
/*
|
50
|
+
=begin
|
51
|
+
--- OraNumber.new()
|
52
|
+
=end
|
53
|
+
*/
|
54
|
+
static VALUE ora_number_initialize(int argc, VALUE *argv, VALUE self)
|
55
|
+
{
|
56
|
+
ora_vnumber_t *ovn = get_ora_number(self);
|
57
|
+
volatile VALUE arg;
|
58
|
+
|
59
|
+
rb_scan_args(argc, argv, "01", &arg);
|
60
|
+
ovn->size = 1;
|
61
|
+
ovn->num.exponent = 0x80;
|
62
|
+
memset(ovn->num.mantissa, 0, sizeof(ovn->num.mantissa));
|
63
|
+
if (argc == 1) {
|
64
|
+
if (TYPE(arg) != T_STRING) {
|
65
|
+
arg = rb_obj_as_string(arg);
|
66
|
+
}
|
67
|
+
if (ora_number_from_str(ovn, RSTRING_ORATEXT(arg), RSTRING_LEN(arg)) != 0) {
|
68
|
+
rb_raise(rb_eArgError, "could not convert '%s' to OraNumber", RSTRING_PTR(arg));
|
69
|
+
}
|
70
|
+
}
|
71
|
+
return Qnil;
|
72
|
+
}
|
73
|
+
|
74
|
+
static VALUE ora_number_initialize_copy(VALUE lhs, VALUE rhs)
|
75
|
+
{
|
76
|
+
ora_vnumber_t *l, *r;
|
77
|
+
|
78
|
+
#ifdef HAVE_RB_DEFINE_ALLOC_FUNC
|
79
|
+
/* ruby 1.8 */
|
80
|
+
rb_obj_init_copy(lhs, rhs);
|
81
|
+
#endif
|
82
|
+
Data_Get_Struct(lhs, ora_vnumber_t, l);
|
83
|
+
Data_Get_Struct(rhs, ora_vnumber_t, r);
|
84
|
+
memcpy(l, r, sizeof(ora_vnumber_t));
|
85
|
+
return lhs;
|
86
|
+
}
|
87
|
+
|
88
|
+
static VALUE ora_number_clone(VALUE self)
|
89
|
+
{
|
90
|
+
VALUE obj = ora_number_s_allocate(CLASS_OF(self));
|
91
|
+
return ora_number_initialize_copy(obj, self);
|
92
|
+
}
|
93
|
+
|
94
|
+
/*
|
95
|
+
=begin
|
96
|
+
--- OraNumber#to_i()
|
97
|
+
=end
|
98
|
+
*/
|
99
|
+
static VALUE ora_number_to_i(VALUE self)
|
100
|
+
{
|
101
|
+
ora_vnumber_t *ovn = get_ora_number(self);
|
102
|
+
unsigned char buf[ORA_NUMBER_BUF_SIZE];
|
103
|
+
|
104
|
+
ora_number_to_str(buf, NULL, &(ovn->num), ovn->size);
|
105
|
+
return rb_cstr2inum(TO_CHARPTR(buf), 10);
|
106
|
+
}
|
107
|
+
|
108
|
+
/*
|
109
|
+
=begin
|
110
|
+
--- OraNumber#to_f()
|
111
|
+
=end
|
112
|
+
*/
|
113
|
+
static VALUE ora_number_to_f(VALUE self)
|
114
|
+
{
|
115
|
+
ora_vnumber_t *ovn = get_ora_number(self);
|
116
|
+
unsigned char buf[ORA_NUMBER_BUF_SIZE];
|
117
|
+
|
118
|
+
ora_number_to_str(buf, NULL, &(ovn->num), ovn->size);
|
119
|
+
return rb_float_new(rb_cstr_to_dbl(TO_CHARPTR(buf), Qfalse));
|
120
|
+
}
|
121
|
+
|
122
|
+
/*
|
123
|
+
=begin
|
124
|
+
--- OraNumber#to_s()
|
125
|
+
=end
|
126
|
+
*/
|
127
|
+
static VALUE ora_number_to_s(VALUE self)
|
128
|
+
{
|
129
|
+
ora_vnumber_t *ovn = get_ora_number(self);
|
130
|
+
unsigned char buf[ORA_NUMBER_BUF_SIZE];
|
131
|
+
size_t len;
|
132
|
+
|
133
|
+
ora_number_to_str(buf, &len, &(ovn->num), ovn->size);
|
134
|
+
return rb_str_new(TO_CHARPTR(buf), len);
|
135
|
+
}
|
136
|
+
|
137
|
+
static VALUE ora_number_uminus(VALUE self)
|
138
|
+
{
|
139
|
+
ora_vnumber_t *ovn = get_ora_number(self);
|
140
|
+
VALUE obj;
|
141
|
+
int i;
|
142
|
+
|
143
|
+
if (ovn->num.exponent == 0x80)
|
144
|
+
return self;
|
145
|
+
obj = ora_number_clone(self);
|
146
|
+
ovn = get_ora_number(obj);
|
147
|
+
ovn->num.exponent = ~(ovn->num.exponent);
|
148
|
+
for (i = 0;i < ovn->size - 1;i++)
|
149
|
+
ovn->num.mantissa[i] = 102 - ovn->num.mantissa[i];
|
150
|
+
if (Get_Sign(&(ovn->num))) {
|
151
|
+
if (ovn->size != 21 || ovn->num.mantissa[19] == 0x00) {
|
152
|
+
ovn->size--;
|
153
|
+
}
|
154
|
+
} else {
|
155
|
+
if (ovn->size != 21) {
|
156
|
+
ovn->num.mantissa[ovn->size - 1] = 102;
|
157
|
+
ovn->size++;
|
158
|
+
}
|
159
|
+
}
|
160
|
+
return obj;
|
161
|
+
}
|
162
|
+
|
163
|
+
static VALUE ora_number_dump(int argc, VALUE *argv, VALUE self)
|
164
|
+
{
|
165
|
+
ora_vnumber_t *ovn = get_ora_number(self);
|
166
|
+
unsigned char i;
|
167
|
+
for (i = ovn->size - 1; i < 20; i++) {
|
168
|
+
ovn->num.mantissa[i] = 0;
|
169
|
+
}
|
170
|
+
return rb_str_new((const char*)ovn, sizeof(ora_vnumber_t));
|
171
|
+
}
|
172
|
+
|
173
|
+
static VALUE ora_number_s_load(VALUE klass, VALUE str)
|
174
|
+
{
|
175
|
+
ora_vnumber_t *ovn;
|
176
|
+
VALUE obj;
|
177
|
+
|
178
|
+
Check_Type(str, T_STRING);
|
179
|
+
if (RSTRING_LEN(str) != sizeof(ora_vnumber_t)) {
|
180
|
+
rb_raise(rb_eTypeError, "marshaled OraNumber format differ");
|
181
|
+
}
|
182
|
+
obj = ora_number_s_allocate(klass);
|
183
|
+
ovn = get_ora_number(obj);
|
184
|
+
memcpy(ovn, RSTRING_PTR(str), sizeof(ora_vnumber_t));
|
185
|
+
return obj;
|
186
|
+
}
|
187
|
+
|
188
|
+
void Init_ora_number(void)
|
189
|
+
{
|
190
|
+
#ifdef HAVE_RB_DEFINE_ALLOC_FUNC
|
191
|
+
/* ruby 1.8 */
|
192
|
+
rb_define_alloc_func(cOraNumber, RUBY_METHOD_FUNC(ora_number_s_allocate));
|
193
|
+
rb_define_method(cOraNumber, "initialize", ora_number_initialize, -1);
|
194
|
+
rb_define_method(cOraNumber, "initialize_copy", ora_number_initialize_copy, 1);
|
195
|
+
#else
|
196
|
+
/* ruby 1.6 */
|
197
|
+
rb_define_singleton_method(cOraNumber, "new", ora_number_s_new, -1);
|
198
|
+
rb_define_method(cOraNumber, "initialize", ora_number_initialize, -1);
|
199
|
+
rb_define_method(cOraNumber, "clone", ora_number_clone, 0);
|
200
|
+
rb_define_method(cOraNumber, "dup", ora_number_clone, 0);
|
201
|
+
#endif
|
202
|
+
|
203
|
+
rb_define_method(cOraNumber, "to_i", ora_number_to_i, 0);
|
204
|
+
rb_define_method(cOraNumber, "to_f", ora_number_to_f, 0);
|
205
|
+
rb_define_method(cOraNumber, "to_s", ora_number_to_s, 0);
|
206
|
+
rb_define_method(cOraNumber, "-@", ora_number_uminus, 0);
|
207
|
+
|
208
|
+
rb_define_method(cOraNumber, "_dump", ora_number_dump, -1);
|
209
|
+
rb_define_singleton_method(cOraNumber, "_load", ora_number_s_load, 1);
|
210
|
+
}
|
211
|
+
|
212
|
+
void ora_number_to_str(unsigned char *buf, size_t *lenp, ora_number_t *on, unsigned char size)
|
213
|
+
{
|
214
|
+
int exponent;
|
215
|
+
int len = 0;
|
216
|
+
int mentissa_size;
|
217
|
+
int i, j;
|
218
|
+
|
219
|
+
if (on->exponent == 0x80) {
|
220
|
+
buf[0] = '0';
|
221
|
+
buf[1] = '\0';
|
222
|
+
if (lenp != NULL)
|
223
|
+
*lenp = 1;
|
224
|
+
return;
|
225
|
+
}
|
226
|
+
|
227
|
+
if (Get_Sign(on)) {
|
228
|
+
mentissa_size = size - 1;
|
229
|
+
} else {
|
230
|
+
if (size == 21 && on->mantissa[19] != 102)
|
231
|
+
mentissa_size = 20;
|
232
|
+
else
|
233
|
+
mentissa_size = size - 2;
|
234
|
+
buf[len++] = '-';
|
235
|
+
}
|
236
|
+
exponent = Get_Exponent(on);
|
237
|
+
if (exponent < 0) {
|
238
|
+
buf[len++] = '0';
|
239
|
+
buf[len++] = '.';
|
240
|
+
for (i = exponent * 2;i < -2;i++)
|
241
|
+
buf[len++] = '0';
|
242
|
+
for (i = 0;i < mentissa_size;i++) {
|
243
|
+
j = Get_Mantissa_At(on, i);
|
244
|
+
buf[len++] = j / 10 + '0';
|
245
|
+
if (i != mentissa_size - 1 || j % 10 != 0)
|
246
|
+
buf[len++] = j % 10 + '0';
|
247
|
+
}
|
248
|
+
} else {
|
249
|
+
for (i = 0;i < mentissa_size;i++) {
|
250
|
+
j = Get_Mantissa_At(on, i);
|
251
|
+
if (i == exponent + 1) {
|
252
|
+
buf[len++] = '.';
|
253
|
+
}
|
254
|
+
if (i != 0 || j / 10 != 0)
|
255
|
+
buf[len++] = j / 10 + '0';
|
256
|
+
if ((i < exponent + 1) /* integer part */
|
257
|
+
|| (i != mentissa_size - 1 || j % 10 != 0) /* decimal fraction */)
|
258
|
+
buf[len++] = j % 10 + '0';
|
259
|
+
}
|
260
|
+
for (;i <= exponent;i++) {
|
261
|
+
buf[len++] = '0';
|
262
|
+
buf[len++] = '0';
|
263
|
+
}
|
264
|
+
}
|
265
|
+
buf[len] = '\0';
|
266
|
+
if (lenp != NULL)
|
267
|
+
*lenp = len;
|
268
|
+
}
|
269
|
+
|
270
|
+
static int ora_number_from_str(ora_vnumber_t *ovn, unsigned char *buf, size_t len)
|
271
|
+
{
|
272
|
+
unsigned char work[80];
|
273
|
+
int sign = 1;
|
274
|
+
int state = 0;
|
275
|
+
int i, j;
|
276
|
+
int iidx; /* index of integer part */
|
277
|
+
int fidx; /* index of fraction part */
|
278
|
+
unsigned char *p;
|
279
|
+
int mantissa_size;
|
280
|
+
int exponent;
|
281
|
+
|
282
|
+
if (len > ORA_NUMBER_BUF_SIZE) {
|
283
|
+
return 1;
|
284
|
+
}
|
285
|
+
/* [ \t]*(+|-)[0-9]*(.[0-9]*) */
|
286
|
+
for (i = iidx = fidx = 0; i < len; i++) {
|
287
|
+
unsigned char uc = buf[i];
|
288
|
+
switch (state) {
|
289
|
+
case 0:
|
290
|
+
/* [ \t]*(+|-)[0-9]*(.[0-9]*) */
|
291
|
+
/* ^ */
|
292
|
+
switch (uc) {
|
293
|
+
case ' ':
|
294
|
+
case '\t':
|
295
|
+
/* [ \t]*(+|-)[0-9]*(.[0-9]*) */
|
296
|
+
/* ^ */
|
297
|
+
break;
|
298
|
+
case '-':
|
299
|
+
sign = -1;
|
300
|
+
state = 1;
|
301
|
+
/* [ \t]*(+|-)[0-9]*(.[0-9]*) */
|
302
|
+
/* ^ */
|
303
|
+
break;
|
304
|
+
case '+':
|
305
|
+
case '0':
|
306
|
+
state = 1;
|
307
|
+
/* [ \t]*(+|-)[0-9]*(.[0-9]*) */
|
308
|
+
/* ^ */
|
309
|
+
break;
|
310
|
+
case '1':
|
311
|
+
case '2':
|
312
|
+
case '3':
|
313
|
+
case '4':
|
314
|
+
case '5':
|
315
|
+
case '6':
|
316
|
+
case '7':
|
317
|
+
case '8':
|
318
|
+
case '9':
|
319
|
+
work[iidx++] = uc - '0';
|
320
|
+
state = 1;
|
321
|
+
/* [ \t]*(+|-)[0-9]*(.[0-9]*) */
|
322
|
+
/* ^ */
|
323
|
+
break;
|
324
|
+
case '.':
|
325
|
+
state = 2;
|
326
|
+
/* [ \t]*(+|-)[0-9]*(.[0-9]*) */
|
327
|
+
/* ^ */
|
328
|
+
break;
|
329
|
+
default:
|
330
|
+
return 1;
|
331
|
+
}
|
332
|
+
break;
|
333
|
+
case 1:
|
334
|
+
/* [ \t]*(+|-)[0-9]*(.[0-9]*) */
|
335
|
+
/* ^ */
|
336
|
+
switch (uc) {
|
337
|
+
case '0':
|
338
|
+
case '1':
|
339
|
+
case '2':
|
340
|
+
case '3':
|
341
|
+
case '4':
|
342
|
+
case '5':
|
343
|
+
case '6':
|
344
|
+
case '7':
|
345
|
+
case '8':
|
346
|
+
case '9':
|
347
|
+
if (iidx > sizeof(work))
|
348
|
+
return 1;
|
349
|
+
work[iidx++] = uc - '0';
|
350
|
+
/* [ \t]*(+|-)[0-9]*(.[0-9]*) */
|
351
|
+
/* ^ */
|
352
|
+
break;
|
353
|
+
case '.':
|
354
|
+
state = 2;
|
355
|
+
/* [ \t]*(+|-)[0-9]*(.[0-9]*) */
|
356
|
+
/* ^ */
|
357
|
+
break;
|
358
|
+
default:
|
359
|
+
return 1;
|
360
|
+
}
|
361
|
+
break;
|
362
|
+
case 2:
|
363
|
+
/* [ \t]*(+|-)[0-9]*(.[0-9]*) */
|
364
|
+
/* ^ */
|
365
|
+
switch (uc) {
|
366
|
+
case '0':
|
367
|
+
case '1':
|
368
|
+
case '2':
|
369
|
+
case '3':
|
370
|
+
case '4':
|
371
|
+
case '5':
|
372
|
+
case '6':
|
373
|
+
case '7':
|
374
|
+
case '8':
|
375
|
+
case '9':
|
376
|
+
if (iidx + fidx > sizeof(work))
|
377
|
+
return 1;
|
378
|
+
work[iidx + fidx++] = uc - '0';
|
379
|
+
/* [ \t]*(+|-)[0-9]*(.[0-9]*) */
|
380
|
+
/* ^ */
|
381
|
+
break;
|
382
|
+
default:
|
383
|
+
return 1;
|
384
|
+
}
|
385
|
+
break;
|
386
|
+
}
|
387
|
+
}
|
388
|
+
/* convert to 100-base number */
|
389
|
+
if (iidx & 1) {
|
390
|
+
i = j = 1;
|
391
|
+
} else {
|
392
|
+
i = j = 0;
|
393
|
+
}
|
394
|
+
if (fidx & 1) {
|
395
|
+
if (iidx + fidx > sizeof(work))
|
396
|
+
return 1;
|
397
|
+
work[iidx + fidx++] = 0;
|
398
|
+
}
|
399
|
+
while (i < iidx + fidx) {
|
400
|
+
work[j++] = work[i] * 10 + work[i + 1];
|
401
|
+
i += 2;
|
402
|
+
}
|
403
|
+
iidx = (iidx + 1) >> 1;
|
404
|
+
fidx >>= 1;
|
405
|
+
/* ... */
|
406
|
+
p = work;
|
407
|
+
mantissa_size = iidx + fidx;
|
408
|
+
exponent = (int)iidx - 1;
|
409
|
+
/* delete leading zeros */
|
410
|
+
while (mantissa_size > 0 && p[0] == 0) {
|
411
|
+
mantissa_size--;
|
412
|
+
exponent--;
|
413
|
+
p++;
|
414
|
+
}
|
415
|
+
/* delete trailing zeros */
|
416
|
+
while (mantissa_size > 0 && p[mantissa_size - 1] == 0) {
|
417
|
+
mantissa_size--;
|
418
|
+
}
|
419
|
+
/* check size */
|
420
|
+
if (mantissa_size > sizeof(ovn->num.mantissa))
|
421
|
+
return 1;
|
422
|
+
if (mantissa_size == 0) {
|
423
|
+
ovn->size = 1;
|
424
|
+
ovn->num.exponent = 0x80;
|
425
|
+
return 0;
|
426
|
+
}
|
427
|
+
if (sign > 0) {
|
428
|
+
ovn->size = mantissa_size + 1;
|
429
|
+
ovn->num.exponent = 0x80 + exponent + 65;
|
430
|
+
for (i = 0; i < mantissa_size; i++) {
|
431
|
+
ovn->num.mantissa[i] = p[i] + 1;
|
432
|
+
}
|
433
|
+
} else {
|
434
|
+
ovn->size = mantissa_size + 1;
|
435
|
+
ovn->num.exponent = 62 - exponent;
|
436
|
+
for (i = 0; i < mantissa_size; i++) {
|
437
|
+
ovn->num.mantissa[i] = 101 - p[i];
|
438
|
+
}
|
439
|
+
if (mantissa_size < 20) {
|
440
|
+
ovn->size++;
|
441
|
+
ovn->num.mantissa[i] = 102;
|
442
|
+
}
|
443
|
+
}
|
444
|
+
return 0;
|
445
|
+
}
|