summaryrefslogtreecommitdiff
path: root/ext/sha1/sha1-ruby.c
blob: 75b382640765b560c4e82815bf86896b3cb241b9 (plain)
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include "ruby.h"
#include "sha1.h"

static VALUE cSHA1;

static VALUE
sha1_update(obj, str)
    VALUE obj;
    struct RString *str;
{
    SHA1_CTX *sha1;

    Check_Type(str, T_STRING);
    Data_Get_Struct(obj, SHA1_CTX, sha1);
    SHA1Update(sha1, str->ptr, str->len);

    return obj;
}

static VALUE
sha1_digest(obj)
    VALUE obj;
{
    SHA1_CTX *sha1, ctx;
    unsigned char digest[20];

    Data_Get_Struct(obj, SHA1_CTX, sha1);
    ctx = *sha1;
    SHA1Final(digest, &ctx);

    return rb_str_new(digest, 20);
}

static VALUE
sha1_hexdigest(obj)
    VALUE obj;
{
    SHA1_CTX *sha1, ctx;
    unsigned char digest[20];
    char buf[33];
    int i;

    Data_Get_Struct(obj, SHA1_CTX, sha1);
    ctx = *sha1;
    SHA1Final(digest, &ctx);

    for (i=0; i<20; i++) {
	sprintf(buf+i*2, "%02x", digest[i]);
    }
    return rb_str_new(buf, 40);
}

static VALUE
sha1_clone(obj)
    VALUE obj;
{
    SHA1_CTX *sha1, *sha1_new;

    Data_Get_Struct(obj, SHA1_CTX, sha1);
    obj = Data_Make_Struct(CLASS_OF(obj), SHA1_CTX, 0, free, sha1_new);
    *sha1_new = *sha1;

    return obj;
}

static VALUE
sha1_init(argc, argv, self)
    int argc;
    VALUE* argv;
    VALUE self;
{
    VALUE arg;

    rb_scan_args(argc, argv, "01", &arg);

    if (!NIL_P(arg)) sha1_update(self, arg);

    return self;
}

static VALUE
sha1_new(argc, argv, class)
    int argc;
    VALUE* argv;
    VALUE class;
{
    VALUE obj;
    SHA1_CTX *sha1;

    obj = Data_Make_Struct(class, SHA1_CTX, 0, free, sha1);
    SHA1Init(sha1);
    rb_obj_call_init(obj, argc, argv);

    return obj;
}

void
Init_sha1()
{
    cSHA1 = rb_define_class("SHA1", rb_cObject);

    rb_define_singleton_method(cSHA1, "new", sha1_new, -1);
    rb_define_singleton_method(cSHA1, "sha1", sha1_new, -1);

    rb_define_method(cSHA1, "update", sha1_update, 1);
    rb_define_method(cSHA1, "initialize", sha1_init, -1);
    rb_define_method(cSHA1, "<<", sha1_update, 1);
    rb_define_method(cSHA1, "digest", sha1_digest, 0);
    rb_define_method(cSHA1, "hexdigest", sha1_hexdigest, 0);
    rb_define_method(cSHA1, "clone",  sha1_clone, 0);
}