Digest-SHA1

 view release on metacpan or  search on metacpan

SHA1.xs  view on Meta::CPAN

	c2 = *from++;
	*d++ = base64[c1>>2];
	*d++ = base64[((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)];
	if (from == end) {
	    *d++ = base64[(c2 & 0xF) << 2];
	    break;
	}
	c3 = *from++;
	*d++ = base64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)];
	*d++ = base64[c3 & 0x3F];
    }
    *d = '\0';
    return to;
}

/* Formats */
#define F_BIN 0
#define F_HEX 1
#define F_B64 2

static SV* make_mortal_sv(pTHX_ const unsigned char *src, int type)
{
    STRLEN len;
    char result[41];
    char *ret;
    
    switch (type) {
    case F_BIN:
	ret = (char*)src;
	len = 20;
	break;
    case F_HEX:
	ret = hex_20(src, result);
	len = 40;
	break;
    case F_B64:
	ret = base64_20(src, result);
	len = 27;
	break;
    default:
	croak("Bad convertion type (%d)", type);
	break;
    }
    return sv_2mortal(newSVpv(ret,len));
}


/********************************************************************/

typedef PerlIO* InputStream;

MODULE = Digest::SHA1		PACKAGE = Digest::SHA1

PROTOTYPES: DISABLE

void
new(xclass)
	SV* xclass
    PREINIT:
	SHA_INFO* context;
    PPCODE:
	if (!SvROK(xclass)) {
	    STRLEN my_na;
	    char *sclass = SvPV(xclass, my_na);
	    New(55, context, 1, SHA_INFO);
	    ST(0) = sv_newmortal();
	    sv_setref_pv(ST(0), sclass, (void*)context);
	    SvREADONLY_on(SvRV(ST(0)));
	} else {
	    context = get_sha_info(aTHX_ xclass);
	}
	sha_init(context);
	XSRETURN(1);

void
clone(self)
        SV* self
    PREINIT:
        SHA_INFO* cont = get_sha_info(aTHX_ self);
        const char *myname = sv_reftype(SvRV(self),TRUE);
        SHA_INFO* context;
    PPCODE:
        New(55, context, 1, SHA_INFO);
        ST(0) = sv_newmortal();
        sv_setref_pv(ST(0), myname , (void*)context);
        SvREADONLY_on(SvRV(ST(0)));
        memcpy(context,cont,sizeof(SHA_INFO));
        XSRETURN(1);

void
DESTROY(context)
	SHA_INFO* context
    CODE:
        Safefree(context);

void
add(self, ...)
	SV* self
    PREINIT:
	SHA_INFO* context = get_sha_info(aTHX_ self);
	int i;
	unsigned char *data;
	STRLEN len;
    PPCODE:
	for (i = 1; i < items; i++) {
	    data = (unsigned char *)(SvPVbyte(ST(i), len));
	    sha_update(context, data, len);
	}
	XSRETURN(1);  /* self */

void
addfile(self, fh)
	SV* self
	InputStream fh
    PREINIT:
	SHA_INFO* context = get_sha_info(aTHX_ self);
	unsigned char buffer[4096];
	int  n;
    CODE:
        if (fh) {
	    /* Process blocks until EOF or error */
            while ( (n = PerlIO_read(fh, buffer, sizeof(buffer))) > 0) {
		sha_update(context, buffer, n);
	    }
	    if (PerlIO_error(fh)) {
		croak("Reading from filehandle failed");
	    }
        }
        else {
	    croak("No filehandle passed");
        }
 
	XSRETURN(1);  /* self */

void
digest(context)
	SHA_INFO* context
    ALIAS:
	Digest::SHA1::digest    = F_BIN
	Digest::SHA1::hexdigest = F_HEX
	Digest::SHA1::b64digest = F_B64
    PREINIT:
	unsigned char digeststr[20];
    PPCODE:
        sha_final(digeststr, context);
	sha_init(context);  /* In case it is reused */
        ST(0) = make_mortal_sv(aTHX_ digeststr, ix);
        XSRETURN(1);

void
sha1(...)
    ALIAS:
	Digest::SHA1::sha1        = F_BIN
	Digest::SHA1::sha1_hex    = F_HEX
	Digest::SHA1::sha1_base64 = F_B64
    PREINIT:
	SHA_INFO ctx;
	int i;
	unsigned char *data;
        STRLEN len;
	unsigned char digeststr[20];
    PPCODE:
	sha_init(&ctx);

	if (DOWARN) {
            const char *msg = 0;
	    if (items == 1) {
		if (SvROK(ST(0))) {
                    SV* sv = SvRV(ST(0));
		    if (SvOBJECT(sv) && strEQ(HvNAME(SvSTASH(sv)), "Digest::SHA1"))
		        msg = "probably called as method";
		    else
			msg = "called with reference argument";
		}
	    }
	    else if (items > 1) {
		data = (unsigned char *)SvPVbyte(ST(0), len);
		if (len == 12 && memEQ("Digest::SHA1", data, 12)) {
		    msg = "probably called as class method";
		}
	    }
	    if (msg) {
		const char *f = (ix == F_BIN) ? "sha1" :
                                (ix == F_HEX) ? "sha1_hex" : "sha1_base64";
	        warn("&Digest::SHA1::%s function %s", f, msg);
	    }
	}

	for (i = 0; i < items; i++) {
	    data = (unsigned char *)(SvPVbyte(ST(i), len));
	    sha_update(&ctx, data, len);
	}
	sha_final(digeststr, &ctx);
        ST(0) = make_mortal_sv(aTHX_ digeststr, ix);
        XSRETURN(1);

void
sha1_transform(data)
	SV* data
    PREINIT:
        SHA_INFO ctx;
        unsigned char *data_pv;
        unsigned char test[64];
        STRLEN len;
        unsigned char digeststr[20];
    PPCODE:
        sha_init(&ctx);
        
        memset (test, 0, 64);
        data_pv = (unsigned char *)(SvPVbyte(data, len));
        memcpy (test, data_pv, len);
	memcpy ((&ctx)->data, test, 64);
        sha_transform_and_copy(digeststr, &ctx);
        ST(0) = sv_2mortal(newSVpv((char*)digeststr, 20));
        XSRETURN(1);



( run in 2.108 seconds using v1.01-cache-2.11-cpan-71847e10f99 )