Commit d653946c authored by Aleksey Kravchenko's avatar Aleksey Kravchenko

Imported Upstream version 1.2.10

parent fceb5fb5
RHash License
Copyright (c) 2005-2011 Aleksey Kravchenko <rhash.admin@gmail.com>
Copyright (c) 2005-2012 Aleksey Kravchenko <rhash.admin@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
......
Mon Apr 09 2011 Aleksey
Tue Dec 25 2012 Aleksey
* === Version 1.2.10 ===
Mon Nov 5 2012 Aleksey
* Bugfix: incorrect GOST hash for ("\FF" x 64) on non-x86 CPU
Mon Oct 8 2012 Aleksey
* Shortcut -k for --check-embedded
Thu Sep 27 2012 Aleksey
* Bugfix: non-zero exit code if some files were not found
* improved Ctrl-C processing
Sat Aug 4 2012 Aleksey
* Bugfix: path issue with verification of hash files
Mon Jun 25 2012 Aleksey
* Bugfix: different BTIH were generated for the same file
Sun May 13 2012 Aleksey
* BugFix: python crashed on ia64
Tue Apr 17 2012 Aleksey
* PHP bindings for librhash
Sat Apr 14 2012 Aleksey
* === Version 1.2.9 ===
Fri Apr 13 2012 Aleksey, Sergey Basalaev
* translations: de, en_AU, es, gl, it
Sun Apr 08 2012 Aleksey
* Bugfix: handling UNC filenames on Windows
* option --bt-batch for batch torrents
......
This diff is collapsed.
......@@ -29,14 +29,14 @@ for a long-term storing or transferring.
Features:
* Small and easy to learn interface.
* Hi-level and Low-level API.
* Allows calculating of several hash functions simultaniously.
* Allows calculating of several hash functions simultaneously.
* Portability: the library works on Linux, *BSD and Windows.
=== Links ===
* Project Home Page: http://rhash.sourceforge.net/
* Oficial Releases: http://sf.net/projects/rhash/files/rhash/
* Official Releases: http://sf.net/projects/rhash/files/rhash/
* RHash hash functions descriptions http://rhash.anz.ru/hashes.php
* The table of the hash functions supported by RHash
......@@ -55,7 +55,7 @@ The latest source code can be obtained from Git repository by command:
=== Notes on RHash License ===
The RHash program and LibRHash library are distributed under RHash License,
see the COPYING file for details. In particluar, the program, the library
see the COPYING file for details. In particular, the program, the library
and source code can be used free of charge under the MIT, BSD, GPL,
commercial or freeware license without additional restrictions. In the case
the OSI-approved license is required the MIT license should be used.
MAKE = make
RUBY = ruby
PYTHON = python
PERL = /usr/bin/perl
DESTDIR =
PREFIX = /usr/local
PERL_OPTIMIZE = -O2 -g -Wall
VERSION = $(shell sed -ne 's/^version=\(.*\)/\1/p' version.properties)
FILES = Makefile version.properties
BINDINGS = java mono perl python ruby
ARCHIVE_GZIP = rhash-bindings-$(VERSION)-src.tar.gz
COPYDIR = rhash-bindings-$(VERSION)
CP = cp -l --parents
all: configure build test
clean: distclean
configure: $(patsubst %, configure-%, $(filter perl ruby, $(BINDINGS)))
build: $(patsubst %, build-%, $(BINDINGS))
test: $(patsubst %, test-%, $(BINDINGS))
install: $(patsubst %, install-%, $(filter perl ruby, $(BINDINGS)))
configure-perl:
cd perl && perl Makefile.PL INSTALLDIRS=vendor
configure-ruby:
$(RUBY) -C ruby extconf.rb
build-java:
$(MAKE) -C java/
build-perl:
$(MAKE) -C perl OPTIMIZE="$(PERL_OPTIMIZE)"
build-python:
# not required
build-ruby:
$(MAKE) -C ruby
build-mono:
$(MAKE) -C mono
test-java:
$(MAKE) -C java test
test-perl:
$(MAKE) -C perl test
test-ruby:
$(RUBY) -C ruby test_rhash.rb
test-mono:
$(MAKE) -C mono test
test-python:
$(PYTHON) python/test_rhash.py
install-ruby:
$(MAKE) -C ruby install DESTDIR=$(DESTDIR) sitedir=$(DESTDIR)/usr/lib/ruby
install-perl:
$(MAKE) -C perl install DESTDIR=$(DESTDIR)
# $(MAKE) -C perl install DESTDIR=$(DESTDIR) PREFIX=$(PREFIX) SITEPREFIX=$(PREFIX)
copy-dist:
mkdir -p $(COPYDIR)
find java ruby python -type f -regex '.*\(\.\([hc]\|java\|py\|rb\|txt\)\|Makefile\)' -exec $(CP) '{}' $(COPYDIR)/ \;
find perl -type f -regex '.*\(\.\(t\|PL\|pm\|xs\)\|MANIFEST\|typemap\)' -exec $(CP) '{}' "$(COPYDIR)/" \;
find mono -type f -regex '.*\(\.\([hc]\|cs\|xml\|txt\|snk\|sln\|csproj\)\|Makefile\)' -exec $(CP) '{}' "$(COPYDIR)/" \;
$(CP) $(FILES) "$(COPYDIR)/"
gzip: distclean
rm -rf "$(COPYDIR)" $(ARCHIVE_GZIP)
make copy-dist
tar -czf $(ARCHIVE_GZIP) "$(COPYDIR)"
rm -rf "$(COPYDIR)"
distclean:
$(MAKE) -C java distclean
$(MAKE) -C mono clean
[ ! -f ruby/Makefile ] || $(MAKE) -C ruby distclean
[ ! -f perl/Makefile ] || $(MAKE) -C perl distclean
rm -f python/*.pyc
#!/usr/bin/make -f
# This file is a part of Java Bindings for Librhash
# Copyright (c) 2011-2012, Sergey Basalaev <sbasalaev@gmail.com>
# Librhash is (c) 2011-2012, Aleksey Kravchenko <rhash.admin@gmail.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so.
#
# This 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. Use it at your own risk!
MAKE = make
JAVA = java
JAVAC = javac
JAVADOC = javadoc
JAVAH = javah
JAR = jar
JUNIT_CLASSPATH = /usr/share/java/junit4.jar
VERSION = $(shell sed -ne 's/^version=\(.*\)/\1/p' ../version.properties)
JAVASRC_DIR = src
CSRC_DIR = native
DEST_DIR = dist
CLASSES_DIR = classes
JAVADOC_DIR = javadoc
TEST_DIR = test
JAVADOC_API_URL = http://download.oracle.com/javase/6/docs/api/
JARFILE = $(DEST_DIR)/rhash-$(VERSION).jar
all: jar jar-symlink jni javadoc
jar: compile-classes
mkdir -p $(DEST_DIR)
$(JAR) cf $(JARFILE) -C $(CLASSES_DIR) org/
jar-symlink:
mkdir -p $(DEST_DIR)
ln -fs rhash-$(VERSION).jar $(DEST_DIR)/rhash.jar
compile-classes:
mkdir -p $(CLASSES_DIR)
$(JAVAC) -d $(CLASSES_DIR) -sourcepath $(JAVASRC_DIR) `find ${JAVASRC_DIR} -name '*.java'`
update-header: compile-classes
$(JAVAH) -o $(CSRC_DIR)/bindings.h -classpath $(CLASSES_DIR) org.sf.rhash.Bindings
jni:
$(MAKE) -C $(CSRC_DIR)
mkdir -p $(DEST_DIR)
cp $(CSRC_DIR)/*rhash-jni* $(DEST_DIR)
javadoc: clean-javadoc
$(JAVADOC) -windowtitle 'RHash' \
-sourcepath src \
-subpackages org \
-d $(JAVADOC_DIR) \
-link $(JAVADOC_API_URL)
test: jar jni
$(JAVAC) -classpath $(JARFILE):$(JUNIT_CLASSPATH) $(TEST_DIR)/RHashTest.java
$(JAVA) -classpath $(TEST_DIR):$(JARFILE):$(JUNIT_CLASSPATH) -Djava.library.path=$(DEST_DIR) junit.textui.TestRunner RHashTest
clean: clean-javadoc clean-jni clean-classes clean-test
clean-javadoc:
rm -rf $(JAVADOC_DIR)
clean-classes:
rm -rf $(CLASSES_DIR)
clean-jni:
$(MAKE) -C $(CSRC_DIR) clean
clean-test:
rm -f $(TEST_DIR)/*.class
distclean: clean
rm -rf $(DEST_DIR)
.PHONY: jar jni javadoc clean clean-javadoc distclean
#!/usr/bin/make -f
# This file is a part of Java Bindings for Librhash
# Copyright (c) 2011-2012, Sergey Basalaev <sbasalaev@gmail.com>
# Librhash is (c) 2011-2012, Aleksey Kravchenko <rhash.admin@gmail.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so.
#
# This 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. Use it at your own risk!
CC = gcc
CFLAGS = -g -O2
LIBRHASH_INC =
LIBRHASH_LD =
LDFLAGS = -lrhash $(LIBRHASH_LD)
ALLCFLAGS = $(CFLAGS) $(LIBRHASH_INC) -fPIC
#Platform dependent
JNI_INCLUDES = /usr/lib/jvm/default-java/include
LIB_PREFIX = lib
LIB_SUFFIX = .so
OBJECTS = bindings.o digest.o
LIBRARY = $(LIB_PREFIX)rhash-jni$(LIB_SUFFIX)
all: $(LIBRARY)
bindings.o: bindings.c bindings.h
$(CC) $(ALLCFLAGS) -I$(JNI_INCLUDES) -c $< -o $@
digest.o: digest.c digest.h
$(CC) $(ALLCFLAGS) -c $< -o $@
$(LIBRARY): $(OBJECTS)
$(CC) -shared -o $@ $(OBJECTS) $(LDFLAGS)
clean:
rm -f *.o $(LIBRARY)
/*
* This file is a part of Java Bindings for Librhash
* Copyright (c) 2011-2012, Sergey Basalaev <sbasalaev@gmail.com>
* Librhash is (c) 2011-2012, Aleksey Kravchenko <rhash.admin@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so.
*
* This 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. Use it at your own risk!
*/
#include <rhash/rhash.h>
#include <stdlib.h>
#ifdef __GNUC__
#include <stdint.h>
#define TO_RHASH(a) ((rhash)(intptr_t)(a))
#define TO_DIGEST(a) ((Digest)(intptr_t)(a))
#define TO_JLONG(a) ((jlong)(intptr_t)(a))
#else
#define TO_RHASH(a) ((rhash)(a))
#define TO_DIGEST(a) ((Digest)(a))
#define TO_JLONG(a) ((jlong)(a))
#endif /* __GNUC__ */
#include "bindings.h"
#include "digest.h"
/*
* Class: org_sf_rhash_Bindings
* Method: rhash_library_init
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_org_sf_rhash_Bindings_rhash_1library_1init
(JNIEnv *env, jclass clz) {
rhash_library_init();
}
/*
* Class: org_sf_rhash_Bindings
* Method: rhash_count
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_org_sf_rhash_Bindings_rhash_1count
(JNIEnv *env, jclass clz) {
return rhash_count();
}
/*
* Class: org_sf_rhash_Bindings
* Method: rhash_msg
* Signature: (I[BII)J
*/
JNIEXPORT jlong JNICALL Java_org_sf_rhash_Bindings_rhash_1msg
(JNIEnv *env, jclass clz, jint hash_id, jbyteArray buf, jint ofs, jint len) {
// reading data
void* msg = malloc(len);
(*env)->GetByteArrayRegion(env, buf, ofs, len, msg);
// creating and populating Digest
Digest obj = malloc(sizeof(DigestStruct));
obj->hash_len = rhash_get_digest_size(hash_id);
obj->hash_data = calloc(obj->hash_len, sizeof(unsigned char));
rhash_msg(hash_id, msg, len, obj->hash_data);
//cleaning
free(msg);
//returning
return TO_JLONG(obj);
}
/*
* Class: org_sf_rhash_Bindings
* Method: rhash_print_bytes
* Signature: (JI)[B
*/
JNIEXPORT jbyteArray JNICALL Java_org_sf_rhash_Bindings_rhash_1print_1bytes
(JNIEnv *env, jclass clz, jlong ptr, jint flags) {
Digest obj = TO_DIGEST(ptr);
char output[130];
int len = rhash_print_bytes(output, obj->hash_data, obj->hash_len, flags);
jbyteArray arr = (*env)->NewByteArray(env, len);
(*env)->SetByteArrayRegion(env, arr, 0, len, output);
return arr;
}
/*
* Class: org_sf_rhash_Bindings
* Method: rhash_print_magnet
* Signature: (JLjava/lang/String;I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_sf_rhash_Bindings_rhash_1print_1magnet
(JNIEnv *env, jclass clz, jlong context, jstring filepath, jint flags) {
const char* fpath = (filepath != NULL) ?
(*env)->GetStringUTFChars(env, filepath, NULL) : NULL;
size_t len = rhash_print_magnet(NULL, fpath, TO_RHASH(context), flags, RHPR_FILESIZE);
char *buf = (char*)malloc(len);
rhash_print_magnet(buf, fpath, TO_RHASH(context), flags, RHPR_FILESIZE);
if (filepath != NULL) {
(*env)->ReleaseStringUTFChars(env, filepath, fpath);
}
jstring str = (*env)->NewStringUTF(env, buf);
free(buf);
return str;
}
/*
* Class: org_sf_rhash_Bindings
* Method: rhash_is_base32
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL Java_org_sf_rhash_Bindings_rhash_1is_1base32
(JNIEnv *env, jclass clz, jint hash_id) {
return rhash_is_base32(hash_id);
}
/*
* Class: org_sf_rhash_Bindings
* Method: rhash_get_digest_size
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_org_sf_rhash_Bindings_rhash_1get_1digest_1size
(JNIEnv *env, jclass clz, jint hash_id) {
return rhash_get_digest_size(hash_id);
}
/*
* Class: org_sf_rhash_Bindings
* Method: rhash_init
* Signature: (I)J
*/
JNIEXPORT jlong JNICALL Java_org_sf_rhash_Bindings_rhash_1init
(JNIEnv *env, jclass clz, jint hash_flags) {
rhash ctx = rhash_init(hash_flags);
rhash_set_autofinal(ctx, 0);
return TO_JLONG(ctx);
}
/*
* Class: org_sf_rhash_Bindings
* Method: rhash_update
* Signature: (J[BII)V
*/
JNIEXPORT void JNICALL Java_org_sf_rhash_Bindings_rhash_1update
(JNIEnv *env, jclass clz, jlong context, jbyteArray data, jint ofs, jint len) {
void* msg = malloc(len);
(*env)->GetByteArrayRegion(env, data, ofs, len, msg);
rhash_update(TO_RHASH(context), msg, len);
free(msg);
}
/*
* Class: org_sf_rhash_Bindings
* Method: rhash_final
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_org_sf_rhash_Bindings_rhash_1final
(JNIEnv *env, jclass clz, jlong context) {
rhash_final(TO_RHASH(context), NULL);
}
/*
* Class: org_sf_rhash_Bindings
* Method: rhash_reset
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_org_sf_rhash_Bindings_rhash_1reset
(JNIEnv *env, jclass clz, jlong context) {
rhash_reset(TO_RHASH(context));
}
/*
* Class: org_sf_rhash_Bindings
* Method: rhash_print
* Signature: (JI)J
*/
JNIEXPORT jlong JNICALL Java_org_sf_rhash_Bindings_rhash_1print
(JNIEnv *env, jclass clz, jlong context, jint hash_id) {
Digest obj = malloc(sizeof(DigestStruct));
obj->hash_len = rhash_get_digest_size(hash_id);
obj->hash_data = calloc(obj->hash_len, sizeof(unsigned char));
rhash_print(obj->hash_data, TO_RHASH(context), hash_id, RHPR_RAW);
return TO_JLONG(obj);
}
/*
* Class: org_sf_rhash_Bindings
* Method: rhash_free
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_org_sf_rhash_Bindings_rhash_1free
(JNIEnv *env, jclass clz, jlong context) {
rhash_free(TO_RHASH(context));
}
/*
* Class: org_sf_rhash_Bindings
* Method: compareDigests
* Signature: (JJ)Z
*/
JNIEXPORT jboolean JNICALL Java_org_sf_rhash_Bindings_compareDigests
(JNIEnv *env, jclass clz, jlong ptr1, jlong ptr2) {
return compareDigests(TO_DIGEST(ptr1), TO_DIGEST(ptr2));
}
/*
* Class: org_sf_rhash_Bindings
* Method: hashcodeForDigest
* Signature: (J)I
*/
JNIEXPORT jint JNICALL Java_org_sf_rhash_Bindings_hashcodeForDigest
(JNIEnv *env, jclass clz, jlong ptr) {
return hashcodeForDigest(TO_DIGEST(ptr));
}
/*
* Class: org_sf_rhash_Bindings
* Method: freeDigest
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_org_sf_rhash_Bindings_freeDigest
(JNIEnv *env, jclass clz, jlong ptr) {
freeDigest(TO_DIGEST(ptr));
}
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_sf_rhash_Bindings */
#ifndef _Included_org_sf_rhash_Bindings
#define _Included_org_sf_rhash_Bindings
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: org_sf_rhash_Bindings
* Method: rhash_library_init
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_org_sf_rhash_Bindings_rhash_1library_1init
(JNIEnv *, jclass);
/*
* Class: org_sf_rhash_Bindings
* Method: rhash_count
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_org_sf_rhash_Bindings_rhash_1count
(JNIEnv *, jclass);
/*
* Class: org_sf_rhash_Bindings
* Method: rhash_msg
* Signature: (I[BII)J
*/
JNIEXPORT jlong JNICALL Java_org_sf_rhash_Bindings_rhash_1msg
(JNIEnv *, jclass, jint, jbyteArray, jint, jint);
/*
* Class: org_sf_rhash_Bindings
* Method: rhash_print_bytes
* Signature: (JI)[B
*/
JNIEXPORT jbyteArray JNICALL Java_org_sf_rhash_Bindings_rhash_1print_1bytes
(JNIEnv *, jclass, jlong, jint);
/*
* Class: org_sf_rhash_Bindings
* Method: rhash_print_magnet
* Signature: (JLjava/lang/String;I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_sf_rhash_Bindings_rhash_1print_1magnet
(JNIEnv *, jclass, jlong, jstring, jint);
/*
* Class: org_sf_rhash_Bindings
* Method: rhash_is_base32
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL Java_org_sf_rhash_Bindings_rhash_1is_1base32
(JNIEnv *, jclass, jint);
/*
* Class: org_sf_rhash_Bindings
* Method: rhash_get_digest_size
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_org_sf_rhash_Bindings_rhash_1get_1digest_1size
(JNIEnv *, jclass, jint);
/*
* Class: org_sf_rhash_Bindings
* Method: rhash_init
* Signature: (I)J
*/
JNIEXPORT jlong JNICALL Java_org_sf_rhash_Bindings_rhash_1init
(JNIEnv *, jclass, jint);
/*
* Class: org_sf_rhash_Bindings
* Method: rhash_update
* Signature: (J[BII)V
*/
JNIEXPORT void JNICALL Java_org_sf_rhash_Bindings_rhash_1update
(JNIEnv *, jclass, jlong, jbyteArray, jint, jint);
/*
* Class: org_sf_rhash_Bindings
* Method: rhash_final
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_org_sf_rhash_Bindings_rhash_1final
(JNIEnv *, jclass, jlong);
/*
* Class: org_sf_rhash_Bindings
* Method: rhash_reset
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_org_sf_rhash_Bindings_rhash_1reset
(JNIEnv *, jclass, jlong);
/*
* Class: org_sf_rhash_Bindings
* Method: rhash_print
* Signature: (JI)J
*/
JNIEXPORT jlong JNICALL Java_org_sf_rhash_Bindings_rhash_1print
(JNIEnv *, jclass, jlong, jint);
/*
* Class: org_sf_rhash_Bindings
* Method: rhash_free
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_org_sf_rhash_Bindings_rhash_1free
(JNIEnv *, jclass, jlong);
/*
* Class: org_sf_rhash_Bindings
* Method: compareDigests
* Signature: (JJ)Z
*/
JNIEXPORT jboolean JNICALL Java_org_sf_rhash_Bindings_compareDigests
(JNIEnv *, jclass, jlong, jlong);
/*
* Class: org_sf_rhash_Bindings
* Method: hashcodeForDigest
* Signature: (J)I
*/
JNIEXPORT jint JNICALL Java_org_sf_rhash_Bindings_hashcodeForDigest
(JNIEnv *, jclass, jlong);
/*
* Class: org_sf_rhash_Bindings
* Method: freeDigest
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_org_sf_rhash_Bindings_freeDigest
(JNIEnv *, jclass, jlong);
#ifdef __cplusplus
}
#endif
#endif
/*
* This file is a part of Java Bindings for Librhash
* Copyright (c) 2011-2012, Sergey Basalaev <sbasalaev@gmail.com>
* Librhash is (c) 2011-2012, Aleksey Kravchenko <rhash.admin@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so.
*
* This 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. Use it at your own risk!
*/
#include <stdlib.h>
#include <string.h>
#include "digest.h"
void freeDigest(Digest obj) {
free(obj->hash_data);
free(obj);
}
int compareDigests(Digest o1, Digest o2) {
if (o1->hash_len != o2->hash_len) return 0;
return memcmp(o1->hash_data, o2->hash_data, o1->hash_len) == 0;
}
int hashcodeForDigest(Digest obj) {
int hash = 123321, i;
for (i = 0; i < obj->hash_len; i++) {
switch (i % 3) {
case 0: hash ^= obj->hash_data[i];
case 1: hash ^= obj->hash_data[i] << 8;
case 2: hash ^= obj->hash_data[i] << 16;
case 3: hash ^= obj->hash_data[i] << 24;
}
}