@@ -171,7 +171,7 @@ static struct digest {
171
171
/*
172
172
// checksum: native [
173
173
// {Computes a checksum, CRC, hash, or HMAC.}
174
- // data [binary! string!] {If string, it will be UTF8 encoded}
174
+ // data [binary! string! file! ] {If string, it will be UTF8 encoded}
175
175
// method [word!] {One of `system/catalog/checksums` and HASH}
176
176
// /with {Extra value for HMAC key or hash table size; not compatible with TCP/CRC24/CRC32/ADLER32 methods.}
177
177
// spec [any-string! binary! integer!] {String or binary for MD5/SHA* HMAC key, integer for hash table size.}
@@ -180,29 +180,50 @@ static struct digest {
180
180
// ]
181
181
***********************************************************************/
182
182
{
183
- REBVAL * arg = D_ARG (ARG_CHECKSUM_DATA );
184
- REBINT sym = VAL_WORD_CANON (D_ARG (ARG_CHECKSUM_METHOD ));
185
- REBVAL * spec = D_ARG (ARG_CHECKSUM_SPEC );
183
+ REBVAL * data = D_ARG (ARG_CHECKSUM_DATA );
184
+ REBVAL * method = D_ARG (ARG_CHECKSUM_METHOD );
185
+ REBVAL * spec = D_ARG (ARG_CHECKSUM_SPEC );
186
+ REBINT sym ;
186
187
REBINT sum ;
187
188
REBINT i = 0 ;
188
189
REBCNT j ;
189
190
REBSER * digest , * ser ;
190
191
REBCNT len , keylen ;
191
- REBYTE * data ;
192
+ REBYTE * bin ;
192
193
REBYTE * keycp ;
193
194
194
195
195
- len = Partial1 (arg , D_ARG (ARG_CHECKSUM_LENGTH ));
196
+ len = Partial1 (data , D_ARG (ARG_CHECKSUM_LENGTH ));
197
+ sym = VAL_WORD_CANON (method );
196
198
197
- if (IS_STRING (arg )) {
198
- ser = Encode_UTF8_Value (arg , len , 0 );
199
- data = SERIES_DATA (ser );
199
+ if (IS_BINARY (data )) {
200
+ bin = VAL_BIN_DATA (data );
201
+ }
202
+ else if (IS_STRING (data )) {
203
+ ser = Encode_UTF8_Value (data , len , 0 );
204
+ bin = SERIES_DATA (ser );
200
205
len = SERIES_LEN (ser ) - 1 ;
201
206
}
202
207
else {
203
- data = VAL_BIN_DATA (arg );
208
+ // Dispatch file to file-checksum function...
209
+ REBVAL * func = Find_Word_Value (Lib_Context , SYM_FILE_CHECKSUM );
210
+ if (func && IS_FUNCTION (func ) && sym > SYM_CRC32 && sym <= SYM_RIPEMD160 ) {
211
+ // Build block to evaluate: [file-checksum data method]
212
+ // Where method must be converted to lit-word first...
213
+ VAL_TYPE (method ) = REB_LIT_WORD ;
214
+ REBSER * code = Make_Block (3 );
215
+ BLK_HEAD (code )[0 ] = * func ;
216
+ BLK_HEAD (code )[1 ] = * data ;
217
+ BLK_HEAD (code )[2 ] = * method ;
218
+ SERIES_TAIL (code ) = 3 ; // It is important to mark the tail of the block!
219
+ Do_Next (code , 0 , 0 );
220
+ * DS_RETURN = * DS_TOP ;
221
+ return R_RET ;
222
+ }
223
+ // in case that file-checksum is not a function or is used not yet implemented method...
224
+ Trap0 (RE_FEATURE_NA );
204
225
}
205
-
226
+
206
227
if (sym > SYM_CRC32 && sym <= SYM_RIPEMD160 ) {
207
228
// O: could be optimized using index computed from `sym`
208
229
// find matching digest:
@@ -251,7 +272,7 @@ static struct digest {
251
272
252
273
digests [i ].init (ctx );
253
274
digests [i ].update (ctx ,ipad ,blocklen );
254
- digests [i ].update (ctx , data , len );
275
+ digests [i ].update (ctx , bin , len );
255
276
digests [i ].final (ctx , tmpdigest );
256
277
digests [i ].init (ctx );
257
278
digests [i ].update (ctx ,opad ,blocklen );
@@ -261,7 +282,7 @@ static struct digest {
261
282
Free_Mem (ctx , digests [i ].ctxsize ());
262
283
263
284
} else {
264
- digests [i ].digest (data , len , BIN_HEAD (digest ));
285
+ digests [i ].digest (bin , len , BIN_HEAD (digest ));
265
286
}
266
287
267
288
SERIES_TAIL (digest ) = digests [i ].len ;
@@ -278,20 +299,20 @@ static struct digest {
278
299
Trap0 (RE_BAD_REFINES );
279
300
280
301
if (sym == SYM_CRC32 || sym == SYM_ADLER32 ) {
281
- i = (sym == SYM_CRC32 ) ? CRC32 (data , len ) : z_adler32_z (0x00000001L , data , len );
302
+ i = (sym == SYM_CRC32 ) ? CRC32 (bin , len ) : z_adler32_z (0x00000001L , bin , len );
282
303
}
283
304
else if (sym == SYM_HASH ) { // /hash
284
305
if (!D_REF (ARG_CHECKSUM_WITH )) Trap0 (RE_MISSING_ARG );
285
306
if (!IS_INTEGER (spec )) Trap1 (RE_BAD_REFINE , D_ARG (ARG_CHECKSUM_SPEC ));
286
307
sum = VAL_INT32 (spec ); // size of the hash table
287
308
if (sum <= 1 ) sum = 1 ;
288
- i = Hash_String (data , len ) % sum ;
309
+ i = Hash_String (bin , len ) % sum ;
289
310
}
290
311
else if (sym == SYM_CRC24 ) {
291
- i = Compute_CRC24 (data , len );
312
+ i = Compute_CRC24 (bin , len );
292
313
}
293
314
else if (sym == SYM_TCP ) {
294
- i = Compute_IPC (data , len );
315
+ i = Compute_IPC (bin , len );
295
316
}
296
317
else {
297
318
Trap_Arg (D_ARG (ARG_CHECKSUM_METHOD ));
0 commit comments