1
1
s-lang/modules/chksum-module.c

256 строки
5.4 KiB
C

/*
Copyright (C) 2014-2017,2018 John E. Davis
This file is part of the S-Lang Library.
The S-Lang Library is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The S-Lang Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA.
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <slang.h>
#include "chksum.h"
SLANG_MODULE(chksum);
static int Chksum_Type_Id = 0;
typedef struct
{
SLFUTURE_CONST char *name;
SLChksum_Type *(*create)(char *);
}
Chksum_Def_Type;
typedef struct
{
char *name;
unsigned int numrefs;
SLChksum_Type *c;
}
Chksum_Object_Type;
static Chksum_Def_Type Chksum_Table[] =
{
{"md5", _pSLchksum_md5_new},
{"sha1", _pSLchksum_sha1_new},
{NULL, NULL}
};
static Chksum_Def_Type *lookup_chksum (char *name)
{
Chksum_Def_Type *t = Chksum_Table;
while (t->name != NULL)
{
if (0 == strcmp (t->name, name))
return t;
t++;
}
SLang_verror (SL_RunTime_Error, "Unsupported/Unknown checksum method `%s'", name);
return NULL;
}
static int chksum_push (Chksum_Object_Type *obj)
{
obj->numrefs++;
if (0 == SLclass_push_ptr_obj (Chksum_Type_Id, (VOID_STAR)obj))
return 0;
obj->numrefs--;
return -1;
}
static void chksum_free (Chksum_Object_Type *obj)
{
if (obj == NULL)
return;
if (obj->numrefs > 1)
{
obj->numrefs--;
return;
}
if (obj->c != NULL)
(void) obj->c->close (obj->c, NULL);
SLfree ((char *)obj);
}
static void chksum_new (char *name)
{
Chksum_Def_Type *t;
Chksum_Object_Type *obj;
t = lookup_chksum (name);
if (t == NULL)
return;
obj = (Chksum_Object_Type *)SLmalloc (sizeof (Chksum_Object_Type));
if (obj == NULL)
return;
memset ((char *)obj, 0, sizeof(SLChksum_Type));
obj->numrefs = 1;
if (NULL == (obj->c = t->create (name)))
{
SLfree ((char *)obj);
return;
}
(void) chksum_push (obj);
chksum_free (obj);
}
/* s is assumed to be at least 2*len+1 bytes. */
static void hexify_string (unsigned char *s, unsigned int len)
{
unsigned char *s0, *s1;
s0 = s + len;
s1 = s0 + len;
*s1-- = 0;
while (s0 > s)
{
unsigned char ch;
unsigned char buf[3];
s0--;
ch = *s0;
sprintf ((char *)buf, "%02x", ch);
*s1-- = buf[1];
*s1-- = buf[0];
}
}
static void chksum_close (Chksum_Object_Type *obj)
{
unsigned char *digest;
unsigned int digest_len;
SLChksum_Type *c;
if (NULL == (c = obj->c))
{
(void) SLang_push_null ();
return;
}
digest_len = c->digest_len;
if (NULL == (digest = (unsigned char *)SLmalloc(2*digest_len+1)))
return;
if (-1 == c->close (c, digest))
{
SLfree ((char *)digest);
return;
}
obj->c = NULL;
hexify_string (digest, digest_len);
(void) SLang_push_malloced_string ((char *)digest);
}
static void chksum_accumulate (Chksum_Object_Type *obj, SLang_BString_Type *b)
{
SLChksum_Type *c;
SLstrlen_Type len;
unsigned char *s;
if (NULL == (c = obj->c))
{
SLang_verror (SL_InvalidParm_Error, "Checksum object is invalid");
return;
}
if (NULL == (s = SLbstring_get_pointer (b, &len)))
return;
(void) c->accumulate (c, s, len);
}
#define DUMMY_CHKSUM_TYPE ((unsigned int)-1)
static SLang_Intrin_Fun_Type Intrinsics [] =
{
MAKE_INTRINSIC_1 ("_chksum_new", chksum_new, SLANG_VOID_TYPE, SLANG_STRING_TYPE),
MAKE_INTRINSIC_2 ("_chksum_accumulate", chksum_accumulate, SLANG_VOID_TYPE, DUMMY_CHKSUM_TYPE, SLANG_BSTRING_TYPE),
MAKE_INTRINSIC_1 ("_chksum_close", chksum_close, SLANG_VOID_TYPE, DUMMY_CHKSUM_TYPE),
SLANG_END_INTRIN_FUN_TABLE
};
static void destroy_chksum_type (SLtype type, VOID_STAR ptr)
{
(void) type;
chksum_free (*(Chksum_Object_Type **)ptr);
}
static int push_chksum_type (SLtype type, VOID_STAR ptr)
{
(void) type;
return chksum_push (*(Chksum_Object_Type **)ptr);
}
static int register_chksum_type (void)
{
SLang_Class_Type *cl;
if (Chksum_Type_Id != 0)
return 0;
if (NULL == (cl = SLclass_allocate_class ("Chksum_Type")))
return -1;
if (-1 == SLclass_set_destroy_function (cl, destroy_chksum_type))
return -1;
if (-1 == SLclass_set_push_function (cl, push_chksum_type))
return -1;
/* By registering as SLANG_VOID_TYPE, slang will dynamically allocate a
* type.
*/
if (-1 == SLclass_register_class (cl, SLANG_VOID_TYPE, sizeof (Chksum_Object_Type *), SLANG_CLASS_TYPE_PTR))
return -1;
Chksum_Type_Id = SLclass_get_class_id (cl);
if (-1 == SLclass_patch_intrin_fun_table1 (Intrinsics, DUMMY_CHKSUM_TYPE, Chksum_Type_Id))
return -1;
return 0;
}
int init_chksum_module_ns (char *ns_name)
{
SLang_NameSpace_Type *ns;
ns = SLns_create_namespace (ns_name);
if (ns == NULL)
return -1;
if (-1 == register_chksum_type ())
return -1;
if (-1 == SLns_add_intrin_fun_table (ns, Intrinsics, NULL))
return -1;
return 0;
}
void deinit_chksum_module (void)
{
}