ruby-oci8 1.0.2

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.
Files changed (71) hide show
  1. data/ChangeLog +569 -0
  2. data/Makefile +51 -0
  3. data/NEWS +322 -0
  4. data/README +415 -0
  5. data/VERSION +1 -0
  6. data/dist-files +70 -0
  7. data/doc/api.en.html +527 -0
  8. data/doc/api.en.rd +554 -0
  9. data/doc/api.ja.html +525 -0
  10. data/doc/api.ja.rd +557 -0
  11. data/doc/manual.css +35 -0
  12. data/ext/oci8/MANIFEST +22 -0
  13. data/ext/oci8/attr.c +415 -0
  14. data/ext/oci8/bind.c +194 -0
  15. data/ext/oci8/const.c +165 -0
  16. data/ext/oci8/define.c +53 -0
  17. data/ext/oci8/describe.c +81 -0
  18. data/ext/oci8/descriptor.c +39 -0
  19. data/ext/oci8/env.c +276 -0
  20. data/ext/oci8/error.c +234 -0
  21. data/ext/oci8/extconf.rb +118 -0
  22. data/ext/oci8/handle.c +262 -0
  23. data/ext/oci8/lob.c +386 -0
  24. data/ext/oci8/oci8.c +137 -0
  25. data/ext/oci8/oci8.h +345 -0
  26. data/ext/oci8/ocinumber.c +117 -0
  27. data/ext/oci8/oraconf.rb +1026 -0
  28. data/ext/oci8/oradate.c +426 -0
  29. data/ext/oci8/oranumber.c +445 -0
  30. data/ext/oci8/param.c +37 -0
  31. data/ext/oci8/post-config.rb +5 -0
  32. data/ext/oci8/server.c +182 -0
  33. data/ext/oci8/session.c +99 -0
  34. data/ext/oci8/stmt.c +624 -0
  35. data/ext/oci8/svcctx.c +229 -0
  36. data/lib/DBD/OCI8/OCI8.rb +549 -0
  37. data/lib/oci8.rb.in +1605 -0
  38. data/metaconfig +142 -0
  39. data/pre-distclean.rb +7 -0
  40. data/ruby-oci8.gemspec +54 -0
  41. data/ruby-oci8.spec +62 -0
  42. data/setup.rb +1331 -0
  43. data/support/README +4 -0
  44. data/support/runit/assert.rb +281 -0
  45. data/support/runit/cui/testrunner.rb +101 -0
  46. data/support/runit/error.rb +4 -0
  47. data/support/runit/method_mappable.rb +20 -0
  48. data/support/runit/robserver.rb +25 -0
  49. data/support/runit/setuppable.rb +15 -0
  50. data/support/runit/teardownable.rb +16 -0
  51. data/support/runit/testcase.rb +113 -0
  52. data/support/runit/testfailure.rb +25 -0
  53. data/support/runit/testresult.rb +121 -0
  54. data/support/runit/testsuite.rb +43 -0
  55. data/support/runit/version.rb +3 -0
  56. data/test/README +4 -0
  57. data/test/config.rb +129 -0
  58. data/test/test_all.rb +43 -0
  59. data/test/test_bind_raw.rb +53 -0
  60. data/test/test_bind_time.rb +191 -0
  61. data/test/test_break.rb +81 -0
  62. data/test/test_clob.rb +101 -0
  63. data/test/test_connstr.rb +80 -0
  64. data/test/test_dbi.rb +317 -0
  65. data/test/test_dbi_clob.rb +56 -0
  66. data/test/test_describe.rb +137 -0
  67. data/test/test_metadata.rb +243 -0
  68. data/test/test_oci8.rb +273 -0
  69. data/test/test_oradate.rb +263 -0
  70. data/test/test_oranumber.rb +149 -0
  71. metadata +118 -0
@@ -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
+ }