DEFINITIONS
This source file includes following functions.
- get_digest_base_metadata
- rb_digest_base_alloc
- rb_digest_base_s_digest
- rb_digest_base_s_hexdigest
- rb_digest_base_become
- rb_digest_base_update
- rb_digest_base_init
- rb_digest_base_digest
- rb_digest_base_hexdigest
- rb_digest_base_equal
- Init_digest
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 #include "digest.h"
35
36 static VALUE mDigest, cDigest_Base;
37 static ID id_metadata;
38
39
40
41
42
43 static algo_t *
44 get_digest_base_metadata(klass)
45 VALUE klass;
46 {
47 VALUE obj;
48 algo_t *algo;
49
50 if (rb_cvar_defined(klass, id_metadata) == Qfalse) {
51 rb_notimplement();
52 }
53
54 obj = rb_cvar_get(klass, id_metadata);
55
56 Data_Get_Struct(obj, algo_t, algo);
57
58 return algo;
59 }
60
61 static VALUE
62 rb_digest_base_alloc(klass)
63 VALUE klass;
64 {
65 algo_t *algo;
66 VALUE obj;
67 void *pctx;
68
69 if (klass == cDigest_Base) {
70 rb_raise(rb_eNotImpError, "Digest::Base is an abstract class");
71 }
72
73 algo = get_digest_base_metadata(klass);
74
75 pctx = xmalloc(algo->ctx_size);
76 algo->init_func(pctx);
77
78 obj = Data_Wrap_Struct(klass, 0, free, pctx);
79
80 return obj;
81 }
82
83 static VALUE
84 rb_digest_base_s_digest(klass, str)
85 VALUE klass;
86 VALUE str;
87 {
88 algo_t *algo;
89 void *pctx;
90 size_t len;
91 unsigned char *digest;
92 VALUE obj = rb_digest_base_alloc(klass);
93
94 algo = get_digest_base_metadata(klass);
95 Data_Get_Struct(obj, void, pctx);
96
97 StringValue(str);
98 algo->update_func(pctx, RSTRING(str)->ptr, RSTRING(str)->len);
99
100 len = algo->digest_len;
101
102 digest = xmalloc(len);
103 algo->final_func(digest, pctx);
104
105 obj = rb_str_new(digest, len);
106
107 free(digest);
108 free(pctx);
109
110 return obj;
111 }
112
113 static VALUE
114 rb_digest_base_s_hexdigest(klass, str)
115 VALUE klass;
116 VALUE str;
117 {
118 algo_t *algo;
119 void *pctx;
120 size_t len;
121 unsigned char *hexdigest;
122 VALUE obj = rb_digest_base_alloc(klass);
123
124 StringValue(str);
125 algo = get_digest_base_metadata(klass);
126
127 pctx = xmalloc(algo->ctx_size);
128 algo->init_func(pctx);
129 algo->update_func(pctx, RSTRING(str)->ptr, RSTRING(str)->len);
130
131 len = algo->digest_len * 2;
132
133 hexdigest = xmalloc(len + 1);
134 algo->end_func(pctx, hexdigest);
135
136 obj = rb_str_new(hexdigest, len);
137
138 free(hexdigest);
139 free(pctx);
140
141 return obj;
142 }
143
144 static VALUE
145 rb_digest_base_become(copy, obj)
146 VALUE copy, obj;
147 {
148 algo_t *algo;
149 void *pctx1, *pctx2;
150
151 if (copy == obj) return copy;
152 rb_check_frozen(copy);
153 algo = get_digest_base_metadata(CLASS_OF(copy));
154 if (algo != get_digest_base_metadata(CLASS_OF(obj))) {
155 rb_raise(rb_eTypeError, "wrong argument class");
156 }
157 Data_Get_Struct(obj, void, pctx1);
158 Data_Get_Struct(copy, void, pctx2);
159 memcpy(pctx2, pctx1, algo->ctx_size);
160
161 return copy;
162 }
163
164 static VALUE
165 rb_digest_base_update(self, str)
166 VALUE self, str;
167 {
168 algo_t *algo;
169 void *pctx;
170
171 StringValue(str);
172 algo = get_digest_base_metadata(CLASS_OF(self));
173 Data_Get_Struct(self, void, pctx);
174
175 algo->update_func(pctx, RSTRING(str)->ptr, RSTRING(str)->len);
176
177 return self;
178 }
179
180 static VALUE
181 rb_digest_base_init(argc, argv, self)
182 int argc;
183 VALUE* argv;
184 VALUE self;
185 {
186 VALUE arg;
187
188 rb_scan_args(argc, argv, "01", &arg);
189
190 if (!NIL_P(arg)) rb_digest_base_update(self, arg);
191
192 return self;
193 }
194
195 static VALUE
196 rb_digest_base_digest(self)
197 VALUE self;
198 {
199 algo_t *algo;
200 void *pctx1, *pctx2;
201 unsigned char *digest;
202 size_t len;
203 VALUE str;
204
205 algo = get_digest_base_metadata(CLASS_OF(self));
206 Data_Get_Struct(self, void, pctx1);
207
208 len = algo->ctx_size;
209
210 pctx2 = xmalloc(len);
211 memcpy(pctx2, pctx1, len);
212
213 len = algo->digest_len;
214
215 digest = xmalloc(len);
216 algo->final_func(digest, pctx2);
217
218 str = rb_str_new(digest, len);
219
220 free(digest);
221 free(pctx2);
222
223 return str;
224 }
225
226 static VALUE
227 rb_digest_base_hexdigest(self)
228 VALUE self;
229 {
230 algo_t *algo;
231 void *pctx1, *pctx2;
232 unsigned char *hexdigest;
233 size_t len;
234 VALUE str;
235
236 algo = get_digest_base_metadata(CLASS_OF(self));
237 Data_Get_Struct(self, void, pctx1);
238
239 len = algo->ctx_size;
240
241 pctx2 = xmalloc(len);
242 memcpy(pctx2, pctx1, len);
243
244 len = algo->digest_len * 2;
245
246 hexdigest = xmalloc(len + 1);
247 algo->end_func(pctx2, hexdigest);
248
249 str = rb_str_new(hexdigest, len);
250
251 free(hexdigest);
252 free(pctx2);
253
254 return str;
255 }
256
257 static VALUE
258 rb_digest_base_equal(self, other)
259 VALUE self, other;
260 {
261 algo_t *algo;
262 VALUE klass;
263 VALUE str1, str2;
264
265 klass = CLASS_OF(self);
266 algo = get_digest_base_metadata(klass);
267
268 if (CLASS_OF(other) == klass) {
269 void *pctx1, *pctx2;
270
271 Data_Get_Struct(self, void, pctx1);
272 Data_Get_Struct(other, void, pctx2);
273
274 return algo->equal_func(pctx1, pctx2) ? Qtrue : Qfalse;
275 }
276
277 StringValue(other);
278 str2 = other;
279
280 if (RSTRING(str2)->len == algo->digest_len)
281 str1 = rb_digest_base_digest(self);
282 else
283 str1 = rb_digest_base_hexdigest(self);
284
285 if (RSTRING(str1)->len == RSTRING(str2)->len
286 && rb_str_cmp(str1, str2) == 0)
287 return Qtrue;
288
289 return Qfalse;
290 }
291
292
293
294
295
296 void
297 Init_digest()
298 {
299 mDigest = rb_define_module("Digest");
300
301 cDigest_Base = rb_define_class_under(mDigest, "Base", rb_cObject);
302
303 rb_define_singleton_method(cDigest_Base, "allocate", rb_digest_base_alloc, 0);
304 rb_define_singleton_method(cDigest_Base, "digest", rb_digest_base_s_digest, 1);
305 rb_define_singleton_method(cDigest_Base, "hexdigest", rb_digest_base_s_hexdigest, 1);
306
307 rb_define_method(cDigest_Base, "initialize", rb_digest_base_init, -1);
308 rb_define_method(cDigest_Base, "become", rb_digest_base_become, 1);
309 rb_define_method(cDigest_Base, "update", rb_digest_base_update, 1);
310 rb_define_method(cDigest_Base, "<<", rb_digest_base_update, 1);
311 rb_define_method(cDigest_Base, "digest", rb_digest_base_digest, 0);
312 rb_define_method(cDigest_Base, "hexdigest", rb_digest_base_hexdigest, 0);
313 rb_define_method(cDigest_Base, "to_s", rb_digest_base_hexdigest, 0);
314 rb_define_method(cDigest_Base, "==", rb_digest_base_equal, 1);
315
316 id_metadata = rb_intern("metadata");
317 }