📄 hash.c
字号:
/* * hash - one-way hash routines * * Copyright (C) 1999-2006 Landon Curt Noll * * Calc is open software; you can redistribute it and/or modify it under * the terms of the version 2.1 of the GNU Lesser General Public License * as published by the Free Software Foundation. * * Calc 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 Lesser General * Public License for more details. * * A copy of version 2.1 of the GNU Lesser General Public License is * distributed with calc under the filename COPYING-LGPL. You should have * received a copy with calc; if not, write to Free Software Foundation, Inc. * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. * * @(#) $Revision: 29.10 $ * @(#) $Id: hash.c,v 29.10 2006/06/20 10:25:45 chongo Exp $ * @(#) $Source: /usr/local/src/cmd/calc/RCS/hash.c,v $ * * Under source code control: 1995/11/23 05:13:11 * File existed as early as: 1995 * * chongo <was here> /\oo/\ http://www.isthe.com/chongo/ * Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/ */#include <stdio.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include "calc.h"#include "value.h"#include "zrand.h"#include "zrandom.h"#include "hash.h"/* * external hash_setup functions */extern void shs_init_state(HASH*);extern void shs1_init_state(HASH*);extern void MD5_init_state(HASH*);/* * hash_long can deal with BOOL's, int's, FLAGS's and LEN's */#define hash_bool(type, val, state) (hash_long((type), (long)(val), (state)))#define hash_int(type, val, state) (hash_long((type), (long)(val), (state)))#define hash_flag(type, val, state) (hash_long((type), (long)(val), (state)))#define hash_len(type, val, state) (hash_long((type), (long)(val), (state)))/* * hash_setup - setup the hash state for a given hash */static struct hash_setup { int type; /* hash type (see XYZ_HASH_TYPE below) */ void (*init_state)(HASH*); /* initialize a hash state */} htbl[] = { { SHS_HASH_TYPE, shs_init_state }, /* old SHS / SHA */ { SHS1_HASH_TYPE, shs1_init_state }, /* SHS-1 / SHA-1 */ { MD5_HASH_TYPE, MD5_init_state }, /* MD5 */ { -1, NULL } /* must be last */};/* * hash_init - initialize a hash state * * given: * type - hash type (see hash.h) * state - the state to initialize, or NULL to malloc it * * returns: * initialized state */HASH *hash_init(int type, HASH *state){ int i; /* * malloc if needed */ if (state == NULL) { state = (HASH *)malloc(sizeof(HASH)); if (state == NULL) { math_error("hash_init: cannot malloc HASH"); /*NOTREACHED*/ } } /* * clear hash value */ memset((void*)state, 0, sizeof(HASH)); state->bytes = TRUE; /* * search for the hash_setup function */ for (i=0; htbl[i].init_state != NULL; ++i) { /* if we found the state that we were looking for */ if (type == htbl[i].type) { /* initialize state and return */ (htbl[i].init_state)(state); /* firewall - MAX_CHUNKSIZE must be >= chunksize */ if (state->chunksize > MAX_CHUNKSIZE) { math_error( "internal error: MAX_CHUNKSIZE is too small"); /*NOTREACHED*/ } return state; } } /* * no such hash state */ math_error("internal error: hash type not found in htbl[]"); return NULL;}/* * hash_free - free the hash state */voidhash_free(HASH *state){ /* * do nothing if state is NULL */ if (state == NULL) { return; } /* * free main state and return */ free(state); return;}/* * hash_copy - copy a hash state * * given: * state - the state to copy * * returns: * pointer to copy of state */HASH *hash_copy(HASH *state){ HASH *hnew; /* copy of state */ /* * malloc new state */ hnew = (HASH *)malloc(sizeof(HASH)); if (hnew == NULL) { math_error("hash_init: cannot malloc HASH"); /*NOTREACHED*/ } /* * duplicate state */ memcpy((void *)hnew, (void *)state, sizeof(HASH)); return hnew;}/* * hash_cmp - compare hash values * * given: * a first hash state * b second hash state * * returns: * TRUE => hash states are different * FALSE => hash states are the same */inthash_cmp(HASH *a, HASH *b){ /* * firewall and quick check */ if (a == b) { /* pointers to the same object */ return FALSE; } if (a == NULL || b == NULL) { /* one pointer is NULL, so they differ */ return TRUE; } if (a->cmp == NULL || b->cmp == NULL) { /* one cmp function is NULL, so they differ */ return TRUE; } /* * compare hash types */ if (a->hashtype != b->hashtype) { /* different hash types are different */ return TRUE; } /* * perform the hash specific comparison */ return ((a->cmp)(a,b));}/* * hash_print - print the name and value of a hash * * given: * state the hash state to print name and value of */voidhash_print(HASH *state){ /* print the hash */ (state->print)(state); return;}/* * hash_final - finalize the state of a hash and return a ZVALUE * * given: * state the hash state to finalize * * returns: * hash state as a ZVALUE */ZVALUEhash_final(HASH *state){ /* return the finalized the hash value */ return (state->final)(state);}/* * hash_long - note a long value * * given: * type - hash type (see hash.h) * longval - a long value * state - the state to hash * * returns: * the new state * * This function will hash a long value as if it were a 64 bit value. * The input is a long. If a long is smaller than 64 bits, we will * hash a final 32 bits of zeros. * * This function is OK to hash BOOL's, unslogned long's, unsigned int's * signed int's as well as FLAG's and LEN's. */HASH *hash_long(int type, long longval, HASH *state){ long lval[64/LONG_BITS]; /* 64 bits of longs */ /* * initialize if state is NULL */ if (state == NULL) { state = hash_init(type, NULL); } /* * setup for the hash_long */ (state->chkpt)(state); state->bytes = FALSE; /* data to be read as words */ /* * catch the zero numeric value special case */ if (longval == 0) { /* note a zero numeric value and return */ (state->note)(HASH_ZERO(state->base), state); return state; } /* * prep for a long value hash */ (state->note)(state->base, state); /* * hash as if we have a 64 bit value */ memset((char *)lval, 0, sizeof(lval)); lval[0] = longval; (state->update)(state, (USB8 *)lval, sizeof(lval)); /* * all done */ return state;}/* * hash_zvalue - hash a ZVALUE * * given: * type - hash type (see hash.h) * zval - the ZVALUE * state - the state to hash or NULL * * returns: * the new state */HASH *hash_zvalue(int type, ZVALUE zval, HASH *state){#if CALC_BYTE_ORDER == BIG_ENDIAN && BASEB == 16 int full_lim; /* HALFs in whole chunks in zval */ int chunkhalf; /* size of half buffer in HALFs */ int i; int j;#endif#if BASEB == 16 HALF half[MAX_CHUNKSIZE]; /* For endian reversal */#endif /* * initialize if state is NULL */ if (state == NULL) { state = hash_init(type, NULL); } /* * setup for the ZVALUE hash */ (state->chkpt)(state); state->bytes = FALSE; /* data to be read as words */ /* * catch the zero numeric value special case */ if (ziszero(zval)) { /* note a zero numeric value and return */ (state->note)(HASH_ZERO(state->base), state); return state; } /* * prep for a ZVALUE hash */ (state->note)(HASH_ZVALUE(state->base), state); /* note if we have a negative value */ if (zisneg(zval)) { (state->note)(HASH_NEG(state->base), state); }#if CALC_BYTE_ORDER == BIG_ENDIAN && BASEB == 16 /* * hash full chunks * * We need to convert the array of HALFs into canonical architectural * independent form -- 32 bit arrays. Because we have 16 bit values * in Big Endian form, we need to swap 16 bit values so that they * appear as 32 bit Big Endian values. */ chunkhalf = state->chunksize/sizeof(HALF); full_lim = (zval.len / chunkhalf) * chunkhalf; for (i=0; i < full_lim; i += chunkhalf) { /* HALF swap copy a chunk into a data buffer */ for (j=0; j < chunkhalf; j += 2) { half[j] = zval.v[i+j+1]; half[j+1] = zval.v[i+j]; } (state->update)(state, (USB8*) half, state->chunksize); } /* * hash the final partial chunk (if any) * * We need to convert the array of HALFs into canonical architectural * independent form -- 32 bit arrays. Because we have 16 bit values * in Big Endian form, we need to swap 16 bit values so that they * appear as 32 bit Big Endian values. */ if (zval.len > full_lim) { for (j=0; j < zval.len-full_lim-1; j += 2) { half[j] = zval.v[full_lim+j+1]; half[j+1] = zval.v[full_lim+j]; } if (j < zval.len-full_lim) { half[j] = (HALF)0; half[j+1] = zval.v[zval.len-1]; --full_lim; } (state->update)(state, (USB8 *) half, (zval.len-full_lim)*sizeof(HALF)); }#else /* * hash the array of HALFs * * The array of HALFs is equivalent to the canonical architectural * independent form. We either have 32 bit HALFs (in which case * we do not case the byte order) or we have 16 bit HALFs in Little * Endian order (which happens to be laid out in the same order as * 32 bit values). */ (state->update)(state, (USB8 *)zval.v, zval.len*sizeof(HALF));#if BASEB == 16 if (zval.len & 1) { /* padding to complete word */ half[0] = 0; (state->update)(state, (USB8 *) half, 2); }#endif#endif /* * all done */ return state;}/* * hash_number - hash a NUMBER * * given: * type - hash type (see hash.h) * n - the NUMBER * state - the state to hash or NULL * * returns: * the new state */HASH *hash_number(int type, void *n, HASH *state){ NUMBER *number = (NUMBER *)n; /* n as a NUMBER pointer */ BOOL sign; /* sign of the denominator */ /* * initialize if state is NULL */ if (state == NULL) { state = hash_init(type, NULL); } /* * setup for the NUMBER hash */ (state->chkpt)(state); state->bytes = FALSE; /* * process the numerator */ state = hash_zvalue(type, number->num, state); /* * if the NUMBER is not an integer, process the denominator */ if (qisfrac(number)) { /* note the division */ (state->note)(HASH_DIV(state->base), state); /* hash denominator as positive -- just in case */ sign = number->den.sign; number->den.sign = 0; /* hash the denominator */ state = hash_zvalue(type, number->den, state); /* restore the sign */ number->den.sign = sign; } /* * all done */ return state;}/* * hash_complex - hash a COMPLEX * * given: * type - hash type (see hash.h) * c - the COMPLEX * state - the state to hash or NULL * * returns: * the new state */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -