ray 0.0.0.pre1 → 0.0.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. data/.gitignore +15 -0
  2. data/.gitmodules +3 -0
  3. data/Rakefile +148 -5
  4. data/VERSION +1 -1
  5. data/ext/event.c +535 -0
  6. data/ext/extconf.rb +7 -1
  7. data/ext/image.c +110 -18
  8. data/ext/joystick.c +145 -0
  9. data/ext/ray.c +288 -35
  10. data/ext/ray.h +54 -2
  11. data/lib/ray/config.rb +84 -0
  12. data/lib/ray/dsl.rb +19 -0
  13. data/lib/ray/dsl/converter.rb +65 -0
  14. data/lib/ray/dsl/event.rb +52 -0
  15. data/lib/ray/dsl/event_raiser.rb +21 -0
  16. data/lib/ray/dsl/event_runner.rb +39 -0
  17. data/lib/ray/dsl/event_translator.rb +38 -0
  18. data/lib/ray/dsl/handler.rb +71 -0
  19. data/lib/ray/dsl/listener.rb +30 -0
  20. data/lib/ray/dsl/matcher.rb +60 -0
  21. data/lib/ray/dsl/type.rb +58 -0
  22. data/lib/ray/game.rb +107 -0
  23. data/lib/ray/helper.rb +17 -0
  24. data/lib/ray/image.rb +11 -0
  25. data/lib/ray/ray.rb +8 -0
  26. data/lib/ray/scene.rb +102 -0
  27. data/psp/SDL_psp_main.c +84 -0
  28. data/psp/bigdecimal/README +60 -0
  29. data/psp/bigdecimal/bigdecimal.c +4697 -0
  30. data/psp/bigdecimal/bigdecimal.h +216 -0
  31. data/psp/bigdecimal/lib/bigdecimal/jacobian.rb +85 -0
  32. data/psp/bigdecimal/lib/bigdecimal/ludcmp.rb +84 -0
  33. data/psp/bigdecimal/lib/bigdecimal/math.rb +235 -0
  34. data/psp/bigdecimal/lib/bigdecimal/newton.rb +77 -0
  35. data/psp/bigdecimal/lib/bigdecimal/util.rb +65 -0
  36. data/psp/digest/bubblebabble/bubblebabble.c +142 -0
  37. data/psp/digest/defs.h +20 -0
  38. data/psp/digest/digest.c +643 -0
  39. data/psp/digest/digest.h +32 -0
  40. data/psp/digest/lib/digest.rb +50 -0
  41. data/psp/digest/lib/md5.rb +27 -0
  42. data/psp/digest/lib/sha1.rb +27 -0
  43. data/psp/digest/md5/md5.c +420 -0
  44. data/psp/digest/md5/md5.h +80 -0
  45. data/psp/digest/md5/md5init.c +40 -0
  46. data/psp/digest/rmd160/rmd160.c +457 -0
  47. data/psp/digest/rmd160/rmd160.h +56 -0
  48. data/psp/digest/rmd160/rmd160init.c +40 -0
  49. data/psp/digest/sha1/sha1.c +269 -0
  50. data/psp/digest/sha1/sha1.h +39 -0
  51. data/psp/digest/sha1/sha1init.c +40 -0
  52. data/psp/digest/sha2/lib/sha2.rb +73 -0
  53. data/psp/digest/sha2/sha2.c +919 -0
  54. data/psp/digest/sha2/sha2.h +109 -0
  55. data/psp/digest/sha2/sha2init.c +52 -0
  56. data/psp/enumerator/enumerator.c +298 -0
  57. data/psp/etc/etc.c +559 -0
  58. data/psp/ext.c +285 -0
  59. data/psp/fcntl/fcntl.c +187 -0
  60. data/psp/lib/rbconfig.rb +178 -0
  61. data/psp/nkf/lib/kconv.rb +367 -0
  62. data/psp/nkf/nkf-utf8/config.h +88 -0
  63. data/psp/nkf/nkf-utf8/nkf.c +6040 -0
  64. data/psp/nkf/nkf-utf8/utf8tbl.c +8500 -0
  65. data/psp/nkf/nkf-utf8/utf8tbl.h +34 -0
  66. data/psp/nkf/nkf.c +654 -0
  67. data/psp/socket/addrinfo.h +173 -0
  68. data/psp/socket/getaddrinfo.c +676 -0
  69. data/psp/socket/getnameinfo.c +270 -0
  70. data/psp/socket/pspsocket.c +71 -0
  71. data/psp/socket/pspsocket.h +28 -0
  72. data/psp/socket/socket.c +4662 -0
  73. data/psp/socket/sockport.h +76 -0
  74. data/psp/stringio/stringio.c +1306 -0
  75. data/psp/strscan/strscan.c +1320 -0
  76. data/psp/syck/bytecode.c +1166 -0
  77. data/psp/syck/emitter.c +1242 -0
  78. data/psp/syck/gram.c +1894 -0
  79. data/psp/syck/gram.h +79 -0
  80. data/psp/syck/handler.c +174 -0
  81. data/psp/syck/implicit.c +2990 -0
  82. data/psp/syck/node.c +408 -0
  83. data/psp/syck/rubyext.c +2367 -0
  84. data/psp/syck/syck.c +504 -0
  85. data/psp/syck/syck.h +456 -0
  86. data/psp/syck/token.c +2725 -0
  87. data/psp/syck/yaml2byte.c +257 -0
  88. data/psp/syck/yamlbyte.h +170 -0
  89. data/psp/thread/thread.c +1175 -0
  90. data/psp/zlib/zlib.c +3547 -0
  91. data/script.rb +10 -0
  92. data/spec/ray/config_spec.rb +90 -0
  93. data/spec/ray/conversion_spec.rb +43 -0
  94. data/spec/ray/event_spec.rb +191 -0
  95. data/spec/ray/image_spec.rb +43 -1
  96. data/spec/ray/joystick_spec.rb +17 -0
  97. data/spec/ray/matcher_spec.rb +73 -0
  98. data/spec/ray/ray_spec.rb +72 -1
  99. data/spec/ray/type_spec.rb +17 -0
  100. data/spec/res/aqua.bmp +0 -0
  101. data/spec/res/aqua.png +0 -0
  102. data/spec/res/not_a_jpeg.jpeg +0 -0
  103. data/spec_runner.rb +4 -0
  104. metadata +101 -9
  105. data/ext/Makefile +0 -189
  106. data/ext/ray +0 -0
  107. data/ext/ray.bundle +0 -0
  108. data/ext/ray_ext.bundle +0 -0
  109. data/ext/ray_ext.so +0 -0
  110. data/ext/test.rb +0 -21
@@ -0,0 +1,77 @@
1
+ #
2
+ # newton.rb
3
+ #
4
+ # Solves the nonlinear algebraic equation system f = 0 by Newton's method.
5
+ # This program is not dependent on BigDecimal.
6
+ #
7
+ # To call:
8
+ # n = nlsolve(f,x)
9
+ # where n is the number of iterations required,
10
+ # x is the initial value vector
11
+ # f is an Object which is used to compute the values of the equations to be solved.
12
+ # It must provide the following methods:
13
+ #
14
+ # f.values(x):: returns the values of all functions at x
15
+ #
16
+ # f.zero:: returns 0.0
17
+ # f.one:: returns 1.0
18
+ # f.two:: returns 1.0
19
+ # f.ten:: returns 10.0
20
+ #
21
+ # f.eps:: returns the convergence criterion (epsilon value) used to determine whether two values are considered equal. If |a-b| < epsilon, the two values are considered equal.
22
+ #
23
+ # On exit, x is the solution vector.
24
+ #
25
+ require "bigdecimal/ludcmp"
26
+ require "bigdecimal/jacobian"
27
+
28
+ module Newton
29
+ include LUSolve
30
+ include Jacobian
31
+
32
+ def norm(fv,zero=0.0)
33
+ s = zero
34
+ n = fv.size
35
+ for i in 0...n do
36
+ s += fv[i]*fv[i]
37
+ end
38
+ s
39
+ end
40
+
41
+ def nlsolve(f,x)
42
+ nRetry = 0
43
+ n = x.size
44
+
45
+ f0 = f.values(x)
46
+ zero = f.zero
47
+ one = f.one
48
+ two = f.two
49
+ p5 = one/two
50
+ d = norm(f0,zero)
51
+ minfact = f.ten*f.ten*f.ten
52
+ minfact = one/minfact
53
+ e = f.eps
54
+ while d >= e do
55
+ nRetry += 1
56
+ # Not yet converged. => Compute Jacobian matrix
57
+ dfdx = jacobian(f,f0,x)
58
+ # Solve dfdx*dx = -f0 to estimate dx
59
+ dx = lusolve(dfdx,f0,ludecomp(dfdx,n,zero,one),zero)
60
+ fact = two
61
+ xs = x.dup
62
+ begin
63
+ fact *= p5
64
+ if fact < minfact then
65
+ raise "Failed to reduce function values."
66
+ end
67
+ for i in 0...n do
68
+ x[i] = xs[i] - dx[i]*fact
69
+ end
70
+ f0 = f.values(x)
71
+ dn = norm(f0,zero)
72
+ end while(dn>=d)
73
+ d = dn
74
+ end
75
+ nRetry
76
+ end
77
+ end
@@ -0,0 +1,65 @@
1
+ #
2
+ # BigDecimal utility library.
3
+ #
4
+ # To use these functions, require 'bigdecimal/util'
5
+ #
6
+ # The following methods are provided to convert other types to BigDecimals:
7
+ #
8
+ # String#to_d -> BigDecimal
9
+ # Float#to_d -> BigDecimal
10
+ # Rational#to_d -> BigDecimal
11
+ #
12
+ # The following method is provided to convert BigDecimals to other types:
13
+ #
14
+ # BigDecimal#to_r -> Rational
15
+ #
16
+ # ----------------------------------------------------------------------
17
+ #
18
+ class Float < Numeric
19
+ def to_d
20
+ BigDecimal(self.to_s)
21
+ end
22
+ end
23
+
24
+ class String
25
+ def to_d
26
+ BigDecimal(self)
27
+ end
28
+ end
29
+
30
+ class BigDecimal < Numeric
31
+ # Converts a BigDecimal to a String of the form "nnnnnn.mmm".
32
+ # This method is deprecated; use BigDecimal#to_s("F") instead.
33
+ def to_digits
34
+ if self.nan? || self.infinite? || self.zero?
35
+ self.to_s
36
+ else
37
+ i = self.to_i.to_s
38
+ s,f,y,z = self.frac.split
39
+ i + "." + ("0"*(-z)) + f
40
+ end
41
+ end
42
+
43
+ # Converts a BigDecimal to a Rational.
44
+ def to_r
45
+ sign,digits,base,power = self.split
46
+ numerator = sign*digits.to_i
47
+ denomi_power = power - digits.size # base is always 10
48
+ if denomi_power < 0
49
+ Rational(numerator,base ** (-denomi_power))
50
+ else
51
+ Rational(numerator * (base ** denomi_power),1)
52
+ end
53
+ end
54
+ end
55
+
56
+ class Rational < Numeric
57
+ # Converts a Rational to a BigDecimal
58
+ def to_d(nFig=0)
59
+ num = self.numerator.to_s
60
+ if nFig<=0
61
+ nFig = BigDecimal.double_fig*2+1
62
+ end
63
+ BigDecimal.new(num).div(self.denominator,nFig)
64
+ end
65
+ end
@@ -0,0 +1,142 @@
1
+ /************************************************
2
+
3
+ bubblebabble.c - BubbleBabble encoding support
4
+
5
+ $Author: shyouhei $
6
+ created at: Fri Oct 13 18:31:42 JST 2006
7
+
8
+ Copyright (C) 2006 Akinori MUSHA
9
+
10
+ $Id: bubblebabble.c 11708 2007-02-12 23:01:19Z shyouhei $
11
+
12
+ ************************************************/
13
+
14
+ #include <ruby/ruby.h>
15
+ #include "../digest.h"
16
+
17
+ static ID id_digest;
18
+
19
+ static VALUE
20
+ bubblebabble_str_new(VALUE str_digest)
21
+ {
22
+ char *digest;
23
+ size_t digest_len;
24
+ VALUE str;
25
+ char *p;
26
+ int i, j, seed = 1;
27
+ static const char vowels[] = {
28
+ 'a', 'e', 'i', 'o', 'u', 'y'
29
+ };
30
+ static const char consonants[] = {
31
+ 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', 'n',
32
+ 'p', 'r', 's', 't', 'v', 'z', 'x'
33
+ };
34
+
35
+ StringValue(str_digest);
36
+ digest = RSTRING_PTR(str_digest);
37
+ digest_len = RSTRING_LEN(str_digest);
38
+
39
+ if ((LONG_MAX - 2) / 3 < (digest_len | 1)) {
40
+ rb_raise(rb_eRuntimeError, "digest string too long");
41
+ }
42
+
43
+ str = rb_str_new(0, (digest_len | 1) * 3 + 2);
44
+ p = RSTRING_PTR(str);
45
+
46
+ i = j = 0;
47
+ p[j++] = 'x';
48
+
49
+ for (;;) {
50
+ unsigned char byte1, byte2;
51
+
52
+ if (i >= digest_len) {
53
+ p[j++] = vowels[seed % 6];
54
+ p[j++] = consonants[16];
55
+ p[j++] = vowels[seed / 6];
56
+ break;
57
+ }
58
+
59
+ byte1 = digest[i++];
60
+ p[j++] = vowels[(((byte1 >> 6) & 3) + seed) % 6];
61
+ p[j++] = consonants[(byte1 >> 2) & 15];
62
+ p[j++] = vowels[((byte1 & 3) + (seed / 6)) % 6];
63
+
64
+ if (i >= digest_len) {
65
+ break;
66
+ }
67
+
68
+ byte2 = digest[i++];
69
+ p[j++] = consonants[(byte2 >> 4) & 15];
70
+ p[j++] = '-';
71
+ p[j++] = consonants[byte2 & 15];
72
+
73
+ seed = (seed * 5 + byte1 * 7 + byte2) % 36;
74
+ }
75
+
76
+ p[j] = 'x';
77
+
78
+ return str;
79
+ }
80
+
81
+ /*
82
+ * call-seq:
83
+ * Digest.bubblebabble(string) -> bubblebabble_string
84
+ *
85
+ * Returns a BubbleBabble encoded version of a given _string_.
86
+ */
87
+ static VALUE
88
+ rb_digest_s_bubblebabble(VALUE klass, VALUE str)
89
+ {
90
+ return bubblebabble_str_new(str);
91
+ }
92
+
93
+ /*
94
+ * call-seq:
95
+ * Digest::Class.bubblebabble(string, ...) -> hash_string
96
+ *
97
+ * Returns the BubbleBabble encoded hash value of a given _string_.
98
+ */
99
+ static VALUE
100
+ rb_digest_class_s_bubblebabble(int argc, VALUE *argv, VALUE klass)
101
+ {
102
+ return bubblebabble_str_new(rb_funcall2(klass, id_digest, argc, argv));
103
+ }
104
+
105
+ /*
106
+ * call-seq:
107
+ * digest_obj.bubblebabble -> hash_string
108
+ *
109
+ * Returns the resulting hash value in a Bubblebabble encoded form.
110
+ */
111
+ static VALUE
112
+ rb_digest_instance_bubblebabble(VALUE self)
113
+ {
114
+ return bubblebabble_str_new(rb_funcall(self, id_digest, 0));
115
+ }
116
+
117
+ /*
118
+ * This module adds some methods to Digest classes to perform
119
+ * BubbleBabble encoding.
120
+ */
121
+ void
122
+ Init_bubblebabble(void)
123
+ {
124
+ VALUE mDigest, mDigest_Instance, cDigest_Class;
125
+
126
+ // rb_require("digest"); (Commenting this avoids strange errors)
127
+
128
+ mDigest = rb_path2class("Digest");
129
+ mDigest_Instance = rb_path2class("Digest::Instance");
130
+ cDigest_Class = rb_path2class("Digest::Class");
131
+
132
+ /* Digest::bubblebabble() */
133
+ rb_define_module_function(mDigest, "bubblebabble", rb_digest_s_bubblebabble, 1);
134
+
135
+ /* Digest::Class::bubblebabble() */
136
+ rb_define_singleton_method(cDigest_Class, "bubblebabble", rb_digest_class_s_bubblebabble, -1);
137
+
138
+ /* Digest::Instance#bubblebabble() */
139
+ rb_define_method(mDigest_Instance, "bubblebabble", rb_digest_instance_bubblebabble, 0);
140
+
141
+ id_digest = rb_intern("digest");
142
+ }
data/psp/digest/defs.h ADDED
@@ -0,0 +1,20 @@
1
+ /* -*- C -*-
2
+ * $Id: defs.h 11708 2007-02-12 23:01:19Z shyouhei $
3
+ */
4
+
5
+ #ifndef DEFS_H
6
+ #define DEFS_H
7
+
8
+ #include <ruby/ruby.h>
9
+ #include <sys/types.h>
10
+
11
+ #include <sys/cdefs.h>
12
+
13
+ #if !defined(__BEGIN_DECLS)
14
+ # define __BEGIN_DECLS
15
+ # define __END_DECLS
16
+ #endif
17
+
18
+ #include <inttypes.h>
19
+
20
+ #endif /* DEFS_H */
@@ -0,0 +1,643 @@
1
+ /************************************************
2
+
3
+ digest.c -
4
+
5
+ $Author: knu $
6
+ created at: Fri May 25 08:57:27 JST 2001
7
+
8
+ Copyright (C) 1995-2001 Yukihiro Matsumoto
9
+ Copyright (C) 2001-2006 Akinori MUSHA
10
+
11
+ $RoughId: digest.c,v 1.16 2001/07/13 15:38:27 knu Exp $
12
+ $Id: digest.c 11950 2007-02-28 18:42:47Z knu $
13
+
14
+ ************************************************/
15
+
16
+ #include "digest.h"
17
+
18
+ static VALUE rb_mDigest;
19
+ static VALUE rb_mDigest_Instance;
20
+ static VALUE rb_cDigest_Class;
21
+ static VALUE rb_cDigest_Base;
22
+
23
+ static ID id_reset, id_update, id_finish, id_digest, id_hexdigest, id_digest_length;
24
+ static ID id_metadata;
25
+
26
+ RUBY_EXTERN void Init_digest_base(void);
27
+
28
+ /*
29
+ * Document-module: Digest
30
+ *
31
+ * This module provides a framework for message digest libraries.
32
+ */
33
+
34
+ static VALUE
35
+ hexencode_str_new(VALUE str_digest)
36
+ {
37
+ char *digest;
38
+ size_t digest_len;
39
+ int i;
40
+ VALUE str;
41
+ char *p;
42
+ static const char hex[] = {
43
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
44
+ 'a', 'b', 'c', 'd', 'e', 'f'
45
+ };
46
+
47
+ StringValue(str_digest);
48
+ digest = RSTRING_PTR(str_digest);
49
+ digest_len = RSTRING_LEN(str_digest);
50
+
51
+ if (LONG_MAX / 2 < digest_len) {
52
+ rb_raise(rb_eRuntimeError, "digest string too long");
53
+ }
54
+
55
+ str = rb_str_new(0, digest_len * 2);
56
+
57
+ for (i = 0, p = RSTRING_PTR(str); i < digest_len; i++) {
58
+ unsigned char byte = digest[i];
59
+
60
+ p[i + i] = hex[byte >> 4];
61
+ p[i + i + 1] = hex[byte & 0x0f];
62
+ }
63
+
64
+ return str;
65
+ }
66
+
67
+ /*
68
+ * call-seq:
69
+ * Digest.hexencode(string) -> hexencoded_string
70
+ *
71
+ * Generates a hex-encoded version of a given _string_.
72
+ */
73
+ static VALUE
74
+ rb_digest_s_hexencode(VALUE klass, VALUE str)
75
+ {
76
+ return hexencode_str_new(str);
77
+ }
78
+
79
+ /*
80
+ * Document-module: Digest::Instance
81
+ *
82
+ * This module provides instance methods for a digest implementation
83
+ * object to calculate message digest values.
84
+ */
85
+
86
+ /*
87
+ * call-seq:
88
+ * digest_obj.update(string) -> digest_obj
89
+ * digest_obj << string -> digest_obj
90
+ *
91
+ * Updates the digest using a given _string_ and returns self.
92
+ *
93
+ * The update() method and the left-shift operator are overridden by
94
+ * each implementation subclass. (One should be an alias for the
95
+ * other)
96
+ */
97
+ static VALUE
98
+ rb_digest_instance_update(VALUE self, VALUE str)
99
+ {
100
+ rb_raise(rb_eRuntimeError, "%s does not implement update()", rb_inspect(self));
101
+ }
102
+
103
+ /*
104
+ * call-seq:
105
+ * digest_obj.instance_eval { finish } -> digest_obj
106
+ *
107
+ * Finishes the digest and returns the resulting hash value.
108
+ *
109
+ * This method is overridden by each implementation subclass and often
110
+ * made private, because some of those subclasses may leave internal
111
+ * data uninitialized. Do not call this method from outside. Use
112
+ * #digest!() instead, which ensures that internal data be reset for
113
+ * security reasons.
114
+ */
115
+ static VALUE
116
+ rb_digest_instance_finish(VALUE self)
117
+ {
118
+ rb_raise(rb_eRuntimeError, "%s does not implement finish()", rb_inspect(self));
119
+ }
120
+
121
+ /*
122
+ * call-seq:
123
+ * digest_obj.reset -> digest_obj
124
+ *
125
+ * Resets the digest to the initial state and returns self.
126
+ *
127
+ * This method is overridden by each implementation subclass.
128
+ */
129
+ static VALUE
130
+ rb_digest_instance_reset(VALUE self)
131
+ {
132
+ rb_raise(rb_eRuntimeError, "%s does not implement reset()", rb_inspect(self));
133
+ }
134
+
135
+ /*
136
+ * call-seq:
137
+ * digest_obj.new -> another_digest_obj
138
+ *
139
+ * Returns a new, initialized copy of the digest object. Equivalent
140
+ * to digest_obj.clone().reset().
141
+ */
142
+ static VALUE
143
+ rb_digest_instance_new(VALUE self)
144
+ {
145
+ VALUE clone = rb_obj_clone(self);
146
+ rb_funcall(clone, id_reset, 0);
147
+ return clone;
148
+ }
149
+
150
+ /*
151
+ * call-seq:
152
+ * digest_obj.digest -> string
153
+ * digest_obj.digest(string) -> string
154
+ *
155
+ * If none is given, returns the resulting hash value of the digest,
156
+ * keeping the digest's state.
157
+ *
158
+ * If a _string_ is given, returns the hash value for the given
159
+ * _string_, resetting the digest to the initial state before and
160
+ * after the process.
161
+ */
162
+ static VALUE
163
+ rb_digest_instance_digest(int argc, VALUE *argv, VALUE self)
164
+ {
165
+ VALUE str, value;
166
+
167
+ if (rb_scan_args(argc, argv, "01", &str) > 0) {
168
+ rb_funcall(self, id_reset, 0);
169
+ rb_funcall(self, id_update, 1, str);
170
+ value = rb_funcall(self, id_finish, 0);
171
+ rb_funcall(self, id_reset, 0);
172
+ } else {
173
+ VALUE clone = rb_obj_clone(self);
174
+
175
+ value = rb_funcall(clone, id_finish, 0);
176
+ rb_funcall(clone, id_reset, 0);
177
+ }
178
+
179
+ return value;
180
+ }
181
+
182
+ /*
183
+ * call-seq:
184
+ * digest_obj.digest! -> string
185
+ *
186
+ * Returns the resulting hash value and resets the digest to the
187
+ * initial state.
188
+ */
189
+ static VALUE
190
+ rb_digest_instance_digest_bang(VALUE self)
191
+ {
192
+ VALUE value = rb_funcall(self, id_finish, 0);
193
+ rb_funcall(self, id_reset, 0);
194
+
195
+ return value;
196
+ }
197
+
198
+ /*
199
+ * call-seq:
200
+ * digest_obj.hexdigest -> string
201
+ * digest_obj.hexdigest(string) -> string
202
+ *
203
+ * If none is given, returns the resulting hash value of the digest in
204
+ * a hex-encoded form, keeping the digest's state.
205
+ *
206
+ * If a _string_ is given, returns the hash value for the given
207
+ * _string_ in a hex-encoded form, resetting the digest to the initial
208
+ * state before and after the process.
209
+ */
210
+ static VALUE
211
+ rb_digest_instance_hexdigest(int argc, VALUE *argv, VALUE self)
212
+ {
213
+ VALUE str, value;
214
+
215
+ if (rb_scan_args(argc, argv, "01", &str) > 0) {
216
+ rb_funcall(self, id_reset, 0);
217
+ rb_funcall(self, id_update, 1, str);
218
+ value = rb_funcall(self, id_finish, 0);
219
+ rb_funcall(self, id_reset, 0);
220
+ } else {
221
+ VALUE clone = rb_obj_clone(self);
222
+
223
+ value = rb_funcall(clone, id_finish, 0);
224
+ rb_funcall(clone, id_reset, 0);
225
+ }
226
+
227
+ return hexencode_str_new(value);
228
+ }
229
+
230
+ /*
231
+ * call-seq:
232
+ * digest_obj.hexdigest! -> string
233
+ *
234
+ * Returns the resulting hash value and resets the digest to the
235
+ * initial state.
236
+ */
237
+ static VALUE
238
+ rb_digest_instance_hexdigest_bang(VALUE self)
239
+ {
240
+ VALUE value = rb_funcall(self, id_finish, 0);
241
+ rb_funcall(self, id_reset, 0);
242
+
243
+ return hexencode_str_new(value);
244
+ }
245
+
246
+ /*
247
+ * call-seq:
248
+ * digest_obj.to_s -> string
249
+ *
250
+ * Returns digest_obj.hexdigest().
251
+ */
252
+ static VALUE
253
+ rb_digest_instance_to_s(VALUE self)
254
+ {
255
+ return rb_funcall(self, id_hexdigest, 0);
256
+ }
257
+
258
+ /*
259
+ * call-seq:
260
+ * digest_obj.inspect -> string
261
+ *
262
+ * Creates a printable version of the digest object.
263
+ */
264
+ static VALUE
265
+ rb_digest_instance_inspect(VALUE self)
266
+ {
267
+ VALUE str;
268
+ size_t digest_len = 32; /* about this size at least */
269
+ char *cname;
270
+
271
+ cname = rb_obj_classname(self);
272
+
273
+ /* #<Digest::ClassName: xxxxx...xxxx> */
274
+ str = rb_str_buf_new(2 + strlen(cname) + 2 + digest_len * 2 + 1);
275
+ rb_str_buf_cat2(str, "#<");
276
+ rb_str_buf_cat2(str, cname);
277
+ rb_str_buf_cat2(str, ": ");
278
+ rb_str_buf_append(str, rb_digest_instance_hexdigest(0, 0, self));
279
+ rb_str_buf_cat2(str, ">");
280
+ return str;
281
+ }
282
+
283
+ /*
284
+ * call-seq:
285
+ * digest_obj == another_digest_obj -> boolean
286
+ * digest_obj == string -> boolean
287
+ *
288
+ * If a string is given, checks whether it is equal to the hex-encoded
289
+ * hash value of the digest object. If another digest instance is
290
+ * given, checks whether they have the same hash value. Otherwise
291
+ * returns false.
292
+ */
293
+ static VALUE
294
+ rb_digest_instance_equal(VALUE self, VALUE other)
295
+ {
296
+ VALUE str1, str2;
297
+
298
+ if (rb_obj_is_kind_of(other, rb_mDigest_Instance) == Qtrue) {
299
+ str1 = rb_digest_instance_digest(0, 0, self);
300
+ str2 = rb_digest_instance_digest(0, 0, other);
301
+ } else {
302
+ str1 = rb_digest_instance_to_s(self);
303
+ str2 = other;
304
+ }
305
+
306
+ /* never blindly assume that subclass methods return strings */
307
+ StringValue(str1);
308
+ StringValue(str2);
309
+
310
+ if (RSTRING_LEN(str1) == RSTRING_LEN(str2) &&
311
+ rb_str_cmp(str1, str2) == 0) {
312
+ return Qtrue;
313
+ }
314
+ return Qfalse;
315
+ }
316
+
317
+ /*
318
+ * call-seq:
319
+ * digest_obj.digest_length -> integer
320
+ *
321
+ * Returns the length of the hash value of the digest.
322
+ *
323
+ * This method should be overridden by each implementation subclass.
324
+ * If not, digest_obj.digest().length() is returned.
325
+ */
326
+ static VALUE
327
+ rb_digest_instance_digest_length(VALUE self)
328
+ {
329
+ /* subclasses really should redefine this method */
330
+ VALUE digest = rb_digest_instance_digest(0, 0, self);
331
+
332
+ /* never blindly assume that #digest() returns a string */
333
+ StringValue(digest);
334
+ return INT2NUM(RSTRING_LEN(digest));
335
+ }
336
+
337
+ /*
338
+ * call-seq:
339
+ * digest_obj.length -> integer
340
+ * digest_obj.size -> integer
341
+ *
342
+ * Returns digest_obj.digest_length().
343
+ */
344
+ static VALUE
345
+ rb_digest_instance_length(VALUE self)
346
+ {
347
+ return rb_funcall(self, id_digest_length, 0);
348
+ }
349
+
350
+ /*
351
+ * call-seq:
352
+ * digest_obj.block_length -> integer
353
+ *
354
+ * Returns the block length of the digest.
355
+ *
356
+ * This method is overridden by each implementation subclass.
357
+ */
358
+ static VALUE
359
+ rb_digest_instance_block_length(VALUE self)
360
+ {
361
+ rb_raise(rb_eRuntimeError, "%s does not implement block_length()", rb_inspect(self));
362
+ }
363
+
364
+ /*
365
+ * Document-class: Digest::Class
366
+ *
367
+ * This module stands as a base class for digest implementation
368
+ * classes.
369
+ */
370
+
371
+ /*
372
+ * call-seq:
373
+ * Digest::Class.digest(string, *parameters) -> hash_string
374
+ *
375
+ * Returns the hash value of a given _string_. This is equivalent to
376
+ * Digest::Class.new(*parameters).digest(string), where extra
377
+ * _parameters_, if any, are passed through to the constructor and the
378
+ * _string_ is passed to #digest().
379
+ */
380
+ static VALUE
381
+ rb_digest_class_s_digest(int argc, VALUE *argv, VALUE klass)
382
+ {
383
+ VALUE str;
384
+ void *pctx;
385
+ volatile VALUE obj;
386
+
387
+ if (argc < 1) {
388
+ rb_raise(rb_eArgError, "no data given");
389
+ }
390
+
391
+ str = *argv++;
392
+ argc--;
393
+
394
+ StringValue(str);
395
+
396
+ obj = rb_obj_alloc(klass);
397
+ rb_obj_call_init(obj, argc, argv);
398
+
399
+ return rb_funcall(obj, id_digest, 1, str);
400
+ }
401
+
402
+ /*
403
+ * call-seq:
404
+ * Digest::Class.hexdigest(string[, ...]) -> hash_string
405
+ *
406
+ * Returns the hex-encoded hash value of a given _string_. This is
407
+ * almost equivalent to
408
+ * Digest.hexencode(Digest::Class.new(*parameters).digest(string)).
409
+ */
410
+ static VALUE
411
+ rb_digest_class_s_hexdigest(int argc, VALUE *argv, VALUE klass)
412
+ {
413
+ return hexencode_str_new(rb_funcall2(klass, id_digest, argc, argv));
414
+ }
415
+
416
+ /*
417
+ * Document-class: Digest::Base
418
+ *
419
+ * This abstract class provides a common interface to message digest
420
+ * implementation classes written in C.
421
+ */
422
+
423
+ static rb_digest_metadata_t *
424
+ get_digest_base_metadata(VALUE klass)
425
+ {
426
+ VALUE p;
427
+ VALUE obj;
428
+ rb_digest_metadata_t *algo;
429
+
430
+ for (p = klass; p; p = RCLASS(p)->super) {
431
+ if (rb_ivar_defined(p, id_metadata)) {
432
+ obj = rb_ivar_get(p, id_metadata);
433
+ break;
434
+ }
435
+ }
436
+
437
+ if (!p)
438
+ rb_raise(rb_eRuntimeError, "Digest::Base cannot be directly inherited in Ruby");
439
+
440
+ Data_Get_Struct(obj, rb_digest_metadata_t, algo);
441
+
442
+ switch (algo->api_version) {
443
+ case 2:
444
+ break;
445
+
446
+ /*
447
+ * put conversion here if possible when API is updated
448
+ */
449
+
450
+ default:
451
+ rb_raise(rb_eRuntimeError, "Incompatible digest API version");
452
+ }
453
+
454
+ return algo;
455
+ }
456
+
457
+ static VALUE
458
+ rb_digest_base_alloc(VALUE klass)
459
+ {
460
+ rb_digest_metadata_t *algo;
461
+ VALUE obj;
462
+ void *pctx;
463
+
464
+ if (klass == rb_cDigest_Base) {
465
+ rb_raise(rb_eNotImpError, "Digest::Base is an abstract class");
466
+ }
467
+
468
+ algo = get_digest_base_metadata(klass);
469
+
470
+ pctx = xmalloc(algo->ctx_size);
471
+ algo->init_func(pctx);
472
+
473
+ obj = Data_Wrap_Struct(klass, 0, free, pctx);
474
+
475
+ return obj;
476
+ }
477
+
478
+ /* :nodoc: */
479
+ static VALUE
480
+ rb_digest_base_copy(VALUE copy, VALUE obj)
481
+ {
482
+ rb_digest_metadata_t *algo;
483
+ void *pctx1, *pctx2;
484
+
485
+ if (copy == obj) return copy;
486
+
487
+ rb_check_frozen(copy);
488
+
489
+ algo = get_digest_base_metadata(rb_obj_class(copy));
490
+
491
+ Data_Get_Struct(obj, void, pctx1);
492
+ Data_Get_Struct(copy, void, pctx2);
493
+ memcpy(pctx2, pctx1, algo->ctx_size);
494
+
495
+ return copy;
496
+ }
497
+
498
+ /* :nodoc: */
499
+ static VALUE
500
+ rb_digest_base_reset(VALUE self)
501
+ {
502
+ rb_digest_metadata_t *algo;
503
+ void *pctx;
504
+
505
+ algo = get_digest_base_metadata(rb_obj_class(self));
506
+
507
+ Data_Get_Struct(self, void, pctx);
508
+
509
+ algo->init_func(pctx);
510
+
511
+ return self;
512
+ }
513
+
514
+ /* :nodoc: */
515
+ static VALUE
516
+ rb_digest_base_update(VALUE self, VALUE str)
517
+ {
518
+ rb_digest_metadata_t *algo;
519
+ void *pctx;
520
+
521
+ algo = get_digest_base_metadata(rb_obj_class(self));
522
+
523
+ Data_Get_Struct(self, void, pctx);
524
+
525
+ StringValue(str);
526
+ algo->update_func(pctx, (unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str));
527
+
528
+ return self;
529
+ }
530
+
531
+ /* :nodoc: */
532
+ static VALUE
533
+ rb_digest_base_finish(VALUE self)
534
+ {
535
+ rb_digest_metadata_t *algo;
536
+ void *pctx;
537
+ VALUE str;
538
+
539
+ algo = get_digest_base_metadata(rb_obj_class(self));
540
+
541
+ Data_Get_Struct(self, void, pctx);
542
+
543
+ str = rb_str_new(0, algo->digest_len);
544
+ algo->finish_func(pctx, (unsigned char *)RSTRING_PTR(str));
545
+
546
+ /* avoid potential coredump caused by use of a finished context */
547
+ algo->init_func(pctx);
548
+
549
+ return str;
550
+ }
551
+
552
+ /* :nodoc: */
553
+ static VALUE
554
+ rb_digest_base_digest_length(VALUE self)
555
+ {
556
+ rb_digest_metadata_t *algo;
557
+
558
+ algo = get_digest_base_metadata(rb_obj_class(self));
559
+
560
+ return INT2NUM(algo->digest_len);
561
+ }
562
+
563
+ /* :nodoc: */
564
+ static VALUE
565
+ rb_digest_base_block_length(VALUE self)
566
+ {
567
+ rb_digest_metadata_t *algo;
568
+
569
+ algo = get_digest_base_metadata(rb_obj_class(self));
570
+
571
+ return INT2NUM(algo->block_len);
572
+ }
573
+
574
+ void
575
+ Init_digest(void)
576
+ {
577
+ id_reset = rb_intern("reset");
578
+ id_update = rb_intern("update");
579
+ id_finish = rb_intern("finish");
580
+ id_digest = rb_intern("digest");
581
+ id_hexdigest = rb_intern("hexdigest");
582
+ id_digest_length = rb_intern("digest_length");
583
+
584
+ /*
585
+ * module Digest
586
+ */
587
+ rb_mDigest = rb_define_module("Digest");
588
+
589
+ /* module functions */
590
+ rb_define_module_function(rb_mDigest, "hexencode", rb_digest_s_hexencode, 1);
591
+
592
+ /*
593
+ * module Digest::Instance
594
+ */
595
+ rb_mDigest_Instance = rb_define_module_under(rb_mDigest, "Instance");
596
+
597
+ /* instance methods that should be overridden */
598
+ rb_define_method(rb_mDigest_Instance, "update", rb_digest_instance_update, 1);
599
+ rb_define_method(rb_mDigest_Instance, "<<", rb_digest_instance_update, 1);
600
+ rb_define_private_method(rb_mDigest_Instance, "finish", rb_digest_instance_finish, 0);
601
+ rb_define_method(rb_mDigest_Instance, "reset", rb_digest_instance_reset, 0);
602
+ rb_define_method(rb_mDigest_Instance, "digest_length", rb_digest_instance_digest_length, 0);
603
+ rb_define_method(rb_mDigest_Instance, "block_length", rb_digest_instance_block_length, 0);
604
+
605
+ /* instance methods that may be overridden */
606
+ rb_define_method(rb_mDigest_Instance, "==", rb_digest_instance_equal, 1);
607
+ rb_define_method(rb_mDigest_Instance, "inspect", rb_digest_instance_inspect, 0);
608
+
609
+ /* instance methods that need not usually be overridden */
610
+ rb_define_method(rb_mDigest_Instance, "new", rb_digest_instance_new, 0);
611
+ rb_define_method(rb_mDigest_Instance, "digest", rb_digest_instance_digest, -1);
612
+ rb_define_method(rb_mDigest_Instance, "digest!", rb_digest_instance_digest_bang, 0);
613
+ rb_define_method(rb_mDigest_Instance, "hexdigest", rb_digest_instance_hexdigest, -1);
614
+ rb_define_method(rb_mDigest_Instance, "hexdigest!", rb_digest_instance_hexdigest_bang, 0);
615
+ rb_define_method(rb_mDigest_Instance, "to_s", rb_digest_instance_to_s, 0);
616
+ rb_define_method(rb_mDigest_Instance, "length", rb_digest_instance_length, 0);
617
+ rb_define_method(rb_mDigest_Instance, "size", rb_digest_instance_length, 0);
618
+
619
+ /*
620
+ * class Digest::Class
621
+ */
622
+ rb_cDigest_Class = rb_define_class_under(rb_mDigest, "Class", rb_cObject);
623
+ rb_include_module(rb_cDigest_Class, rb_mDigest_Instance);
624
+
625
+ /* class methods */
626
+ rb_define_singleton_method(rb_cDigest_Class, "digest", rb_digest_class_s_digest, -1);
627
+ rb_define_singleton_method(rb_cDigest_Class, "hexdigest", rb_digest_class_s_hexdigest, -1);
628
+
629
+ id_metadata = rb_intern("metadata");
630
+
631
+ /* class Digest::Base < Digest::Class */
632
+ rb_cDigest_Base = rb_define_class_under(rb_mDigest, "Base", rb_cDigest_Class);
633
+
634
+ rb_define_alloc_func(rb_cDigest_Base, rb_digest_base_alloc);
635
+
636
+ rb_define_method(rb_cDigest_Base, "initialize_copy", rb_digest_base_copy, 1);
637
+ rb_define_method(rb_cDigest_Base, "reset", rb_digest_base_reset, 0);
638
+ rb_define_method(rb_cDigest_Base, "update", rb_digest_base_update, 1);
639
+ rb_define_method(rb_cDigest_Base, "<<", rb_digest_base_update, 1);
640
+ rb_define_private_method(rb_cDigest_Base, "finish", rb_digest_base_finish, 0);
641
+ rb_define_method(rb_cDigest_Base, "digest_length", rb_digest_base_digest_length, 0);
642
+ rb_define_method(rb_cDigest_Base, "block_length", rb_digest_base_block_length, 0);
643
+ }