-------------------------------------------------------------------------------
-src/third_party/hashtable*.[hc]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-This code comes from http://www.cl.cam.ac.uk/~cwc22/hashtable/ with the
-following license:
-
--------------------------------------------------------------------------------
- Copyright (c) 2002, 2004, Christopher Clark
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
- * Neither the name of the original author; nor the names of any
- contributors may be used to endorse or promote products derived from this
- software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
-
-
m4/ax_cxx_compile_stdcxx.m4
~~~~~~~~~~~~~~~~~~~~~~~~~~~
third_party_sources = \
src/third_party/format.cpp \
src/third_party/getopt_long.c \
- src/third_party/hashtable.c \
- src/third_party/hashtable_itr.c \
src/third_party/xxhash.c
extra_sources = @extra_sources@
base_sources = $(non_third_party_sources) $(generated_sources) $(third_party_sources) $(extra_sources)
third_party_headers = \
src/third_party/catch.hpp \
src/third_party/getopt_long.h \
- src/third_party/hashtable.h \
- src/third_party/hashtable_itr.h \
- src/third_party/hashtable_private.h \
src/third_party/minitrace.h \
src/third_party/xxhash.h
headers = $(non_third_party_headers) $(third_party_headers)
#include "result.hpp"
#include "unify.hpp"
-#include "third_party/hashtable.h"
-#include "third_party/hashtable_itr.h"
-
// Global variables used by other compilation units.
extern char* primary_config_path;
extern char* secondary_config_path;
// Files included by the preprocessor and their hashes. Key: file path. Value:
// struct digest.
-static struct hashtable* included_files = NULL;
+static std::unordered_map<std::string, digest> g_included_files;
// Uses absolute path for some include files.
static bool has_absolute_include_headers = false;
}
// This function hashes an include file and stores the path and hash in the
-// global included_files variable. If the include file is a PCH, cpp_hash is
+// global g_included_files variable. If the include file is a PCH, cpp_hash is
// also updated. Takes over ownership of path.
static void
remember_include_file(char* path,
goto out;
}
- if (hashtable_search(included_files, path)) {
+ if (g_included_files.find(path) != g_included_files.end()) {
// Already known include file.
goto out;
}
}
}
- auto d = static_cast<digest*>(x_malloc(sizeof(digest)));
- hash_result_as_bytes(fhash, d);
- hashtable_insert(included_files, path, d);
- path = NULL; // Ownership transferred to included_files.
+ digest d;
+ hash_result_as_bytes(fhash, &d);
+ g_included_files.emplace(path, d);
+ path = NULL;
if (depend_mode_hash) {
hash_delimiter(depend_mode_hash, "include");
char digest[DIGEST_STRING_BUFFER_SIZE];
- digest_as_string(d, digest);
+ digest_as_string(&d, digest);
hash_string(depend_mode_hash, digest);
}
}
static void
print_included_files(FILE* fp)
{
- struct hashtable_itr* iter = hashtable_iterator(included_files);
- do {
- char* path = static_cast<char*>(hashtable_iterator_key(iter));
- fprintf(fp, "%s\n", path);
- } while (hashtable_iterator_advance(iter));
+ for (const auto& item : g_included_files) {
+ fprintf(fp, "%s\n", item.first.c_str());
+ }
}
// Make a relative path from current working directory to path if path is under
}
}
-static void
-init_included_files_table(void)
-{
- // (This function may be called multiple times if several -arch options are
- // used.)
- if (!included_files) {
- included_files = create_hashtable(1000, hash_from_string, strings_equal);
- }
-}
-
// This function reads and hashes a file. While doing this, it also does these
// things:
//
// - Makes include file paths for which the base directory is a prefix relative
// when computing the hash sum.
// - Stores the paths and hashes of included files in the global variable
-// included_files.
+// g_included_files.
static bool
process_preprocessed_file(struct hash* hash, const char* path, bool pump)
{
free(p);
}
- init_included_files_table();
-
char* cwd = gnu_getcwd();
// Bytes between p and q are pending to be hashed.
return NULL;
}
- init_included_files_table();
-
char buf[10000];
while (fgets(buf, sizeof(buf), f) && !ferror(f)) {
char* saveptr;
static void
update_manifest_file(void)
{
- if (!g_config.direct_mode() || !included_files || g_config.read_only()
+ if (!g_config.direct_mode() || g_config.read_only()
|| g_config.read_only_direct()) {
return;
}
MTR_BEGIN("manifest", "manifest_put");
cc_log("Adding result name to %s", manifest_path);
- if (manifest_put(manifest_path, cached_result_name, included_files)) {
+ if (manifest_put(manifest_path, cached_result_name, g_included_files)) {
if (x_stat(manifest_path, &st) == 0) {
stats_update_size(
manifest_stats_file, file_size(&st) - old_size, old_size == 0 ? 1 : 0);
free(ignore_headers);
ignore_headers = NULL;
ignore_headers_len = 0;
- if (included_files) {
- hashtable_destroy(included_files, 1);
- included_files = NULL;
- }
+ g_included_files.clear();
has_absolute_include_headers = false;
generating_debuginfo = false;
generating_debuginfo_level_3 = false;
if (!g_config.depend_mode()) {
// Find the hash using the preprocessed output. Also updates
- // included_files.
+ // g_included_files.
struct hash* cpp_hash = hash_copy(common_hash);
init_hash_debug(
cpp_hash, output_obj, 'p', "PREPROCESSOR MODE", debug_text_file);
#include "third_party/xxhash.h"
-unsigned
-hash_from_string(void* str)
-{
- return XXH64(str, strlen((const char*)str), 0);
-}
-
unsigned
hash_from_int(int i)
{
return XXH64(&i, sizeof(int), 0);
}
-int
-strings_equal(void* str1, void* str2)
-{
- return str_eq((const char*)str1, (const char*)str2);
-}
-
// Search for the strings "__DATE__" and "__TIME__" in str.
//
// Returns a bitmask with HASH_SOURCE_CODE_FOUND_DATE and
#include <inttypes.h>
-unsigned hash_from_string(void* str);
unsigned hash_from_int(int i);
-int strings_equal(void* str1, void* str2);
#define HASH_SOURCE_CODE_OK 0
#define HASH_SOURCE_CODE_ERROR 1
#include "hashutil.hpp"
#include "int_bytes_conversion.hpp"
-#include "third_party/hashtable_itr.h"
#include "third_party/xxhash.h"
// Manifest data format
static const uint32_t MAX_MANIFEST_ENTRIES = 100;
static const uint32_t MAX_MANIFEST_FILE_INFO_ENTRIES = 10000;
-#define ccache_static_assert(e) \
- do { \
- enum { ccache_static_assert__ = 1 / (e) }; \
- } while (false)
+namespace {
struct file
{
char* path; // NUL-terminated
};
-struct file_info
+struct FileInfo
{
// Index to n_files.
uint32_t index;
int64_t ctime;
};
+bool
+operator==(const FileInfo& lhs, const FileInfo& rhs)
+{
+ return lhs.index == rhs.index && digests_equal(&lhs.digest, &rhs.digest)
+ && lhs.fsize == rhs.fsize && lhs.mtime == rhs.mtime
+ && lhs.ctime == rhs.ctime;
+}
+
+} // namespace
+
+namespace std {
+
+template<> struct hash<FileInfo>
+{
+ size_t
+ operator()(const FileInfo& file_info) const
+ {
+ static_assert(sizeof(FileInfo) == 48, "unexpected size"); // No padding.
+ return XXH64(&file_info, sizeof(file_info), 0);
+ }
+};
+
+} // namespace std
+
struct result
{
// Number of entries in file_info_indexes.
// Information about referenced include files.
uint32_t n_file_infos;
- struct file_info* file_infos;
+ struct FileInfo* file_infos;
// Result names plus references to include file infos.
uint32_t n_results;
int64_t ctime;
};
-static unsigned int
-hash_from_file_info(void* key)
-{
- ccache_static_assert(sizeof(struct file_info) == 48); // No padding.
- return XXH64(key, sizeof(struct file_info), 0);
-}
-
-static int
-file_infos_equal(void* key1, void* key2)
-{
- struct file_info* fi1 = (struct file_info*)key1;
- struct file_info* fi2 = (struct file_info*)key2;
- return fi1->index == fi2->index && digests_equal(&fi1->digest, &fi2->digest)
- && fi1->fsize == fi2->fsize && fi1->mtime == fi2->mtime
- && fi1->ctime == fi2->ctime;
-}
-
static void
free_manifest(struct manifest* mf)
{
READ_UINT32(mf->n_file_infos);
mf->file_infos =
- static_cast<file_info*>(x_calloc(mf->n_file_infos, sizeof(file_info)));
+ static_cast<FileInfo*>(x_calloc(mf->n_file_infos, sizeof(FileInfo)));
for (uint32_t i = 0; i < mf->n_file_infos; i++) {
READ_UINT32(mf->file_infos[i].index);
READ_BYTES(mf->file_infos[i].digest.bytes, DIGEST_SIZE);
verify_result(const Config& config,
struct manifest* mf,
struct result* result,
- struct hashtable* stated_files,
- struct hashtable* hashed_files)
+ std::unordered_map<std::string, file_stats>* stated_files,
+ std::unordered_map<std::string, digest>* hashed_files)
{
for (uint32_t i = 0; i < result->n_file_info_indexes; i++) {
- struct file_info* fi = &mf->file_infos[result->file_info_indexes[i]];
+ struct FileInfo* fi = &mf->file_infos[result->file_info_indexes[i]];
char* path = mf->files[fi->index].path;
- auto st = static_cast<file_stats*>(hashtable_search(stated_files, path));
- if (!st) {
+ auto stated_files_iter = stated_files->find(path);
+ if (stated_files_iter == stated_files->end()) {
struct stat file_stat;
if (x_stat(path, &file_stat) != 0) {
return false;
}
- st = static_cast<file_stats*>(x_malloc(sizeof(file_stats)));
- st->size = file_stat.st_size;
- st->mtime = file_stat.st_mtime;
- st->ctime = file_stat.st_ctime;
- hashtable_insert(stated_files, x_strdup(path), st);
+ file_stats st;
+ st.size = file_stat.st_size;
+ st.mtime = file_stat.st_mtime;
+ st.ctime = file_stat.st_ctime;
+ stated_files_iter = stated_files->emplace(path, st).first;
}
+ const file_stats& fs = stated_files_iter->second;
- if (fi->fsize != st->size) {
+ if (fi->fsize != fs.size) {
return false;
}
// and will error out if that header is later used without rebuilding.
if ((guessed_compiler == GUESSED_CLANG
|| guessed_compiler == GUESSED_UNKNOWN)
- && output_is_precompiled_header && fi->mtime != st->mtime) {
+ && output_is_precompiled_header && fi->mtime != fs.mtime) {
cc_log("Precompiled header includes %s, which has a new mtime", path);
return false;
}
if (config.sloppiness() & SLOPPY_FILE_STAT_MATCHES) {
if (!(config.sloppiness() & SLOPPY_FILE_STAT_MATCHES_CTIME)) {
- if (fi->mtime == st->mtime && fi->ctime == st->ctime) {
+ if (fi->mtime == fs.mtime && fi->ctime == fs.ctime) {
cc_log("mtime/ctime hit for %s", path);
continue;
} else {
cc_log("mtime/ctime miss for %s", path);
}
} else {
- if (fi->mtime == st->mtime) {
+ if (fi->mtime == fs.mtime) {
cc_log("mtime hit for %s", path);
continue;
} else {
}
}
- auto actual = static_cast<digest*>(hashtable_search(hashed_files, path));
- if (!actual) {
+ auto hashed_files_iter = hashed_files->find(path);
+ if (hashed_files_iter == hashed_files->end()) {
struct hash* hash = hash_init();
int ret = hash_source_code_file(config, hash, path);
if (ret & HASH_SOURCE_CODE_ERROR) {
return false;
}
- actual = static_cast<digest*>(malloc(sizeof(digest)));
- hash_result_as_bytes(hash, actual);
- hashtable_insert(hashed_files, x_strdup(path), actual);
+ digest actual;
+ hash_result_as_bytes(hash, &actual);
hash_free(hash);
+ hashed_files_iter = hashed_files->emplace(path, actual).first;
}
- if (!digests_equal(&fi->digest, actual)) {
+
+ if (!digests_equal(&fi->digest, &hashed_files_iter->second)) {
return false;
}
}
return true;
}
-static struct hashtable*
-create_file_index_map(struct file* files, uint32_t len)
+static void
+create_file_index_map(
+ struct file* files,
+ uint32_t len,
+ std::unordered_map<std::string, uint32_t /*index*/>* mf_files)
{
- struct hashtable* h = create_hashtable(1000, hash_from_string, strings_equal);
for (uint32_t i = 0; i < len; i++) {
- auto index = static_cast<uint32_t*>(x_malloc(sizeof(uint32_t)));
- *index = i;
- hashtable_insert(h, x_strdup(files[i].path), index);
+ mf_files->emplace(files[i].path, i);
}
- return h;
}
-static struct hashtable*
-create_file_info_index_map(struct file_info* infos, uint32_t len)
+static void
+create_file_info_index_map(
+ struct FileInfo* infos,
+ uint32_t len,
+ std::unordered_map<FileInfo, uint32_t /*index*/>* mf_file_infos)
{
- struct hashtable* h =
- create_hashtable(1000, hash_from_file_info, file_infos_equal);
for (uint32_t i = 0; i < len; i++) {
- auto fi = static_cast<file_info*>(x_malloc(sizeof(file_info)));
- *fi = infos[i];
- uint32_t* index = static_cast<uint32_t*>(x_malloc(sizeof(uint32_t)));
- *index = i;
- hashtable_insert(h, fi, index);
+ mf_file_infos->emplace(infos[i], i);
}
- return h;
}
static uint32_t
-get_include_file_index(struct manifest* mf,
- char* path,
- struct hashtable* mf_files)
+get_include_file_index(
+ struct manifest* mf,
+ const std::string& path,
+ const std::unordered_map<std::string, uint32_t>& mf_files)
{
- uint32_t* index = static_cast<uint32_t*>(hashtable_search(mf_files, path));
- if (index) {
- return *index;
+ auto it = mf_files.find(path);
+ if (it != mf_files.end()) {
+ return it->second;
}
uint32_t n = mf->n_files;
mf->files = static_cast<file*>(x_realloc(mf->files, (n + 1) * sizeof(file)));
mf->n_files++;
- mf->files[n].path_len = strlen(path);
- mf->files[n].path = x_strdup(path);
+ mf->files[n].path_len = path.size();
+ mf->files[n].path = x_strdup(path.c_str());
return n;
}
static uint32_t
get_file_info_index(struct manifest* mf,
- char* path,
- struct digest* digest,
- struct hashtable* mf_files,
- struct hashtable* mf_file_infos)
+ const std::string& path,
+ const digest& digest,
+ const std::unordered_map<std::string, uint32_t>& mf_files,
+ const std::unordered_map<FileInfo, uint32_t>& mf_file_infos)
{
- struct file_info fi;
+ struct FileInfo fi;
fi.index = get_include_file_index(mf, path, mf_files);
- fi.digest = *digest;
+ fi.digest = digest;
// file_stat.st_{m,c}time has a resolution of 1 second, so we can cache the
// file's mtime and ctime only if they're at least one second older than
// MAX(mtime, ctime).
struct stat file_stat;
- if (stat(path, &file_stat) != -1) {
+ if (stat(path.c_str(), &file_stat) != -1) {
if (time_of_compilation
> std::max(file_stat.st_mtime, file_stat.st_ctime)) {
fi.mtime = file_stat.st_mtime;
fi.fsize = 0;
}
- auto fi_index = static_cast<uint32_t*>(hashtable_search(mf_file_infos, &fi));
- if (fi_index) {
- return *fi_index;
+ auto it = mf_file_infos.find(fi);
+ if (it != mf_file_infos.end()) {
+ return it->second;
}
uint32_t n = mf->n_file_infos;
- mf->file_infos = static_cast<file_info*>(
- x_realloc(mf->file_infos, (n + 1) * sizeof(file_info)));
+ mf->file_infos = static_cast<FileInfo*>(
+ x_realloc(mf->file_infos, (n + 1) * sizeof(FileInfo)));
mf->n_file_infos++;
mf->file_infos[n] = fi;
return n;
}
static void
-add_file_info_indexes(uint32_t* indexes,
- uint32_t size,
- struct manifest* mf,
- struct hashtable* included_files)
+add_file_info_indexes(
+ uint32_t* indexes,
+ uint32_t size,
+ struct manifest* mf,
+ const std::unordered_map<std::string, digest>& included_files)
{
if (size == 0) {
return;
}
- // path --> index
- struct hashtable* mf_files = create_file_index_map(mf->files, mf->n_files);
- // struct file_info --> index
- struct hashtable* mf_file_infos =
- create_file_info_index_map(mf->file_infos, mf->n_file_infos);
- struct hashtable_itr* iter = hashtable_iterator(included_files);
+ std::unordered_map<std::string, uint32_t /*index*/> mf_files;
+ create_file_index_map(mf->files, mf->n_files, &mf_files);
+
+ std::unordered_map<FileInfo, uint32_t /*index*/> mf_file_infos;
+ create_file_info_index_map(mf->file_infos, mf->n_file_infos, &mf_file_infos);
+
uint32_t i = 0;
- do {
- auto path = static_cast<char*>(hashtable_iterator_key(iter));
- auto digest = static_cast<struct digest*>(hashtable_iterator_value(iter));
+ for (const auto& item : included_files) {
+ const auto& path = item.first;
+ const auto& digest = item.second;
indexes[i] = get_file_info_index(mf, path, digest, mf_files, mf_file_infos);
i++;
- } while (hashtable_iterator_advance(iter));
+ }
assert(i == size);
-
- hashtable_destroy(mf_file_infos, 1);
- hashtable_destroy(mf_files, 1);
}
static void
add_result_entry(struct manifest* mf,
struct digest* result_digest,
- struct hashtable* included_files)
+ const std::unordered_map<std::string, digest>& included_files)
{
uint32_t n_results = mf->n_results;
mf->results = static_cast<result*>(
mf->n_results++;
struct result* result = &mf->results[n_results];
- uint32_t n_fii = hashtable_count(included_files);
+ uint32_t n_fii = included_files.size();
result->n_file_info_indexes = n_fii;
result->file_info_indexes =
static_cast<uint32_t*>(x_malloc(n_fii * sizeof(uint32_t)));
return NULL;
}
- // path --> struct digest
- struct hashtable* hashed_files =
- create_hashtable(1000, hash_from_string, strings_equal);
- // path --> struct file_stats
- struct hashtable* stated_files =
- create_hashtable(1000, hash_from_string, strings_equal);
+ std::unordered_map<std::string, file_stats> stated_files;
+ std::unordered_map<std::string, digest> hashed_files;
// Check newest result first since it's a bit more likely to match.
struct digest* name = NULL;
for (uint32_t i = mf->n_results; i > 0; i--) {
if (verify_result(
- config, mf, &mf->results[i - 1], stated_files, hashed_files)) {
+ config, mf, &mf->results[i - 1], &stated_files, &hashed_files)) {
name = static_cast<digest*>(x_malloc(sizeof(digest)));
*name = mf->results[i - 1].name;
goto out;
}
out:
- if (hashed_files) {
- hashtable_destroy(hashed_files, 1);
- }
- if (stated_files) {
- hashtable_destroy(stated_files, 1);
- }
free_manifest(mf);
if (name) {
// Update modification timestamp to save files from LRU cleanup.
bool
manifest_put(const char* manifest_path,
struct digest* result_name,
- struct hashtable* included_files)
+ const std::unordered_map<std::string, digest>& included_files)
{
// We don't bother to acquire a lock when writing the manifest to disk. A
// race between two processes will only result in one lost entry, which is
free_manifest(mf);
mf = create_empty_manifest();
} else if (mf->n_file_infos > MAX_MANIFEST_FILE_INFO_ENTRIES) {
- // Rarely, file_info entries can grow large in pathological cases where
+ // Rarely, FileInfo entries can grow large in pathological cases where
// many included files change, but the main file does not. This also puts
- // an upper bound on the number of file_info entries.
- cc_log("More than %u file_info entries in manifest file; discarding",
+ // an upper bound on the number of FileInfo entries.
+ cc_log("More than %u FileInfo entries in manifest file; discarding",
MAX_MANIFEST_FILE_INFO_ENTRIES);
free_manifest(mf);
mf = create_empty_manifest();
#include "Config.hpp"
#include "hashutil.hpp"
-#include "third_party/hashtable.h"
-
extern const char MANIFEST_MAGIC[4];
#define MANIFEST_VERSION 2
struct digest* manifest_get(const Config& config, const char* manifest_path);
-bool manifest_put(const char* manifest_path,
- struct digest* result_digest,
- struct hashtable* included_files);
+bool
+manifest_put(const char* manifest_path,
+ struct digest* result_digest,
+ const std::unordered_map<std::string, digest>& included_files);
bool manifest_dump(const char* manifest_path, FILE* stream);
+++ /dev/null
-/*
- Copyright (c) 2002, 2004, Christopher Clark
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
- * Neither the name of the original author; nor the names of any
- contributors may be used to endorse or promote products derived from this
- software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include "hashtable.h"
-#define HASHTABLE_INDEXFOR
-#include "hashtable_private.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-
-extern const unsigned int prime_table_length;
-extern const float max_load_factor;
-
-/*
-Credit for primes table: Aaron Krowne
- http://br.endernet.org/~akrowne/
- http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
-*/
-static const unsigned int primes[] = {
-53, 97, 193, 389,
-769, 1543, 3079, 6151,
-12289, 24593, 49157, 98317,
-196613, 393241, 786433, 1572869,
-3145739, 6291469, 12582917, 25165843,
-50331653, 100663319, 201326611, 402653189,
-805306457, 1610612741
-};
-const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0]);
-const float max_load_factor = 0.65f;
-
-/*****************************************************************************/
-struct hashtable *
-create_hashtable(unsigned int minsize,
- unsigned int (*hashf) (void*),
- int (*eqf) (void*,void*))
-{
- struct hashtable *h;
- unsigned int pindex, size = primes[0];
- /* Check requested hashtable isn't too large */
- if (minsize > (1u << 30)) return NULL;
- /* Enforce size as prime */
- for (pindex=0; pindex < prime_table_length; pindex++) {
- if (primes[pindex] > minsize) { size = primes[pindex]; break; }
- }
- h = (struct hashtable *)malloc(sizeof(struct hashtable));
- if (NULL == h) return NULL; /*oom*/
- h->table = (struct entry **)malloc(sizeof(struct entry*) * size);
- if (NULL == h->table) { free(h); return NULL; } /*oom*/
- memset(h->table, 0, size * sizeof(struct entry *));
- h->tablelength = size;
- h->primeindex = pindex;
- h->entrycount = 0;
- h->hashfn = hashf;
- h->eqfn = eqf;
- double loadlimit_float = ceil((double)size * (double)max_load_factor);
- h->loadlimit = (unsigned int)loadlimit_float;
- return h;
-}
-
-/*****************************************************************************/
-unsigned int
-hash(struct hashtable *h, void *k)
-{
- /* Aim to protect against poor hash functions by adding logic here
- * - logic taken from java 1.4 hashtable source */
- unsigned int i = h->hashfn(k);
- i += ~(i << 9);
- i ^= ((i >> 14) | (i << 18)); /* >>> */
- i += (i << 4);
- i ^= ((i >> 10) | (i << 22)); /* >>> */
- return i;
-}
-
-/*****************************************************************************/
-static int
-hashtable_expand(struct hashtable *h)
-{
- /* Double the size of the table to accommodate more entries */
- struct entry **newtable;
- struct entry *e;
- unsigned int newsize, i, index;
- /* Check we're not hitting max capacity */
- if (h->primeindex == (prime_table_length - 1)) return 0;
- newsize = primes[++(h->primeindex)];
-
- newtable = (struct entry **)malloc(sizeof(struct entry*) * newsize);
- if (NULL != newtable)
- {
- memset(newtable, 0, newsize * sizeof(struct entry *));
- /* This algorithm is not 'stable'. ie. it reverses the list
- * when it transfers entries between the tables */
- for (i = 0; i < h->tablelength; i++) {
- while (NULL != (e = h->table[i])) {
- h->table[i] = e->next;
- index = indexFor(newsize,e->h);
- e->next = newtable[index];
- newtable[index] = e;
- }
- }
- free(h->table);
- h->table = newtable;
- }
- /* Plan B: realloc instead */
- else
- {
- struct entry **pE;
- newtable = (struct entry **)
- realloc(h->table, newsize * sizeof(struct entry *));
- if (NULL == newtable) { (h->primeindex)--; return 0; }
- h->table = newtable;
- memset(newtable[h->tablelength], 0, newsize - h->tablelength);
- for (i = 0; i < h->tablelength; i++) {
- for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) {
- index = indexFor(newsize,e->h);
- if (index == i)
- {
- pE = &(e->next);
- }
- else
- {
- *pE = e->next;
- e->next = newtable[index];
- newtable[index] = e;
- }
- }
- }
- }
- h->tablelength = newsize;
- double loadlimit_float = ceil((double)newsize* (double)max_load_factor);
- h->loadlimit = (unsigned int) loadlimit_float;
- return -1;
-}
-
-/*****************************************************************************/
-unsigned int
-hashtable_count(struct hashtable *h)
-{
- return h->entrycount;
-}
-
-/*****************************************************************************/
-int
-hashtable_insert(struct hashtable *h, void *k, void *v)
-{
- /* This method allows duplicate keys - but they shouldn't be used */
- unsigned int index;
- struct entry *e;
- if (++(h->entrycount) > h->loadlimit)
- {
- /* Ignore the return value. If expand fails, we should
- * still try cramming just this value into the existing table
- * -- we may not have memory for a larger table, but one more
- * element may be ok. Next time we insert, we'll try expanding again.*/
- hashtable_expand(h);
- }
- e = (struct entry *)malloc(sizeof(struct entry));
- if (NULL == e) { --(h->entrycount); return 0; } /*oom*/
- e->h = hash(h,k);
- index = indexFor(h->tablelength,e->h);
- e->k = k;
- e->v = v;
- e->next = h->table[index];
- h->table[index] = e;
- return -1;
-}
-
-/*****************************************************************************/
-void * /* returns value associated with key */
-hashtable_search(struct hashtable *h, void *k)
-{
- struct entry *e;
- unsigned int hashvalue, index;
- hashvalue = hash(h,k);
- index = indexFor(h->tablelength,hashvalue);
- e = h->table[index];
- while (NULL != e)
- {
- /* Check hash value to short circuit heavier comparison */
- if ((hashvalue == e->h) && (h->eqfn(k, e->k))) return e->v;
- e = e->next;
- }
- return NULL;
-}
-
-/*****************************************************************************/
-void * /* returns value associated with key */
-hashtable_remove(struct hashtable *h, void *k)
-{
- /* TODO: consider compacting the table when the load factor drops enough,
- * or provide a 'compact' method. */
-
- struct entry *e;
- struct entry **pE;
- void *v;
- unsigned int hashvalue, index;
-
- hashvalue = hash(h,k);
- index = indexFor(h->tablelength,hash(h,k));
- pE = &(h->table[index]);
- e = *pE;
- while (NULL != e)
- {
- /* Check hash value to short circuit heavier comparison */
- if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
- {
- *pE = e->next;
- h->entrycount--;
- v = e->v;
- freekey(e->k);
- free(e);
- return v;
- }
- pE = &(e->next);
- e = e->next;
- }
- return NULL;
-}
-
-/*****************************************************************************/
-/* destroy */
-void
-hashtable_destroy(struct hashtable *h, int free_values)
-{
- unsigned int i;
- struct entry *e, *f;
- struct entry **table = h->table;
- if (free_values)
- {
- for (i = 0; i < h->tablelength; i++)
- {
- e = table[i];
- while (NULL != e)
- { f = e; e = e->next; freekey(f->k); free(f->v); free(f); }
- }
- }
- else
- {
- for (i = 0; i < h->tablelength; i++)
- {
- e = table[i];
- while (NULL != e)
- { f = e; e = e->next; freekey(f->k); free(f); }
- }
- }
- free(h->table);
- free(h);
-}
-
-/*
- * Copyright (c) 2002, Christopher Clark
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of the original author; nor the names of any contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
+++ /dev/null
-/*
- Copyright (c) 2002, 2004, Christopher Clark
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
- * Neither the name of the original author; nor the names of any
- contributors may be used to endorse or promote products derived from this
- software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef HASHTABLE_CWC22_H
-#define HASHTABLE_CWC22_H
-
-#include "config.h"
-
-#if defined (__cplusplus)
-extern "C" {
-#endif
-
-struct hashtable;
-
-/* Example of use:
- *
- * struct hashtable *h;
- * struct some_key *k;
- * struct some_value *v;
- *
- * static unsigned int hash_from_key_fn( void *k );
- * static int keys_equal_fn ( void *key1, void *key2 );
- *
- * h = create_hashtable(16, hash_from_key_fn, keys_equal_fn);
- * k = (struct some_key *) malloc(sizeof(struct some_key));
- * v = (struct some_value *) malloc(sizeof(struct some_value));
- *
- * (initialise k and v to suitable values)
- *
- * if (! hashtable_insert(h,k,v) )
- * { exit(-1); }
- *
- * if (NULL == (found = hashtable_search(h,k) ))
- * { printf("not found!"); }
- *
- * if (NULL == (found = hashtable_remove(h,k) ))
- * { printf("Not found\n"); }
- *
- */
-
-/* Macros may be used to define type-safe(r) hashtable access functions, with
- * methods specialized to take known key and value types as parameters.
- *
- * Example:
- *
- * Insert this at the start of your file:
- *
- * DEFINE_HASHTABLE_INSERT(insert_some, struct some_key, struct some_value);
- * DEFINE_HASHTABLE_SEARCH(search_some, struct some_key, struct some_value);
- * DEFINE_HASHTABLE_REMOVE(remove_some, struct some_key, struct some_value);
- *
- * This defines the functions 'insert_some', 'search_some' and 'remove_some'.
- * These operate just like hashtable_insert etc., with the same parameters,
- * but their function signatures have 'struct some_key *' rather than
- * 'void *', and hence can generate compile time errors if your program is
- * supplying incorrect data as a key (and similarly for value).
- *
- * Note that the hash and key equality functions passed to create_hashtable
- * still take 'void *' parameters instead of 'some key *'. This shouldn't be
- * a difficult issue as they're only defined and passed once, and the other
- * functions will ensure that only valid keys are supplied to them.
- *
- * The cost for this checking is increased code size and runtime overhead
- * - if performance is important, it may be worth switching back to the
- * unsafe methods once your program has been debugged with the safe methods.
- * This just requires switching to some simple alternative defines - eg:
- * #define insert_some hashtable_insert
- *
- */
-
-/*****************************************************************************
- * create_hashtable
-
- * @name create_hashtable
- * @param minsize minimum initial size of hashtable
- * @param hashfunction function for hashing keys
- * @param key_eq_fn function for determining key equality
- * @return newly created hashtable or NULL on failure
- */
-
-struct hashtable *
-create_hashtable(unsigned int minsize,
- unsigned int (*hashfunction) (void*),
- int (*key_eq_fn) (void*,void*));
-
-/*****************************************************************************
- * hashtable_insert
-
- * @name hashtable_insert
- * @param h the hashtable to insert into
- * @param k the key - hashtable claims ownership and will free on removal
- * @param v the value - does not claim ownership
- * @return non-zero for successful insertion
- *
- * This function will cause the table to expand if the insertion would take
- * the ratio of entries to table size over the maximum load factor.
- *
- * This function does not check for repeated insertions with a duplicate key.
- * The value returned when using a duplicate key is undefined -- when
- * the hashtable changes size, the order of retrieval of duplicate key
- * entries is reversed.
- * If in doubt, remove before insert.
- */
-
-int
-hashtable_insert(struct hashtable *h, void *k, void *v);
-
-#define DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \
-int fnname (struct hashtable *h, keytype *k, valuetype *v) \
-{ \
- return hashtable_insert(h,k,v); \
-}
-
-/*****************************************************************************
- * hashtable_search
-
- * @name hashtable_search
- * @param h the hashtable to search
- * @param k the key to search for - does not claim ownership
- * @return the value associated with the key, or NULL if none found
- */
-
-void *
-hashtable_search(struct hashtable *h, void *k);
-
-#define DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \
-valuetype * fnname (struct hashtable *h, keytype *k) \
-{ \
- return (valuetype *) (hashtable_search(h,k)); \
-}
-
-/*****************************************************************************
- * hashtable_remove
-
- * @name hashtable_remove
- * @param h the hashtable to remove the item from
- * @param k the key to search for - does not claim ownership
- * @return the value associated with the key, or NULL if none found
- */
-
-void * /* returns value */
-hashtable_remove(struct hashtable *h, void *k);
-
-#define DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \
-valuetype * fnname (struct hashtable *h, keytype *k) \
-{ \
- return (valuetype *) (hashtable_remove(h,k)); \
-}
-
-
-/*****************************************************************************
- * hashtable_count
-
- * @name hashtable_count
- * @param h the hashtable
- * @return the number of items stored in the hashtable
- */
-unsigned int
-hashtable_count(struct hashtable *h);
-
-
-/*****************************************************************************
- * hashtable_destroy
-
- * @name hashtable_destroy
- * @param h the hashtable
- * @param free_values whether to call 'free' on the remaining values
- */
-
-void
-hashtable_destroy(struct hashtable *h, int free_values);
-
-#if defined (__cplusplus)
-}
-#endif
-
-#endif /* HASHTABLE_CWC22_H */
-
-/*
- * Copyright (c) 2002, Christopher Clark
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of the original author; nor the names of any contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
+++ /dev/null
-/* Copyright (C) 2002, 2004 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
-
-#include "hashtable.h"
-#define HASHTABLE_INDEXFOR
-#include "hashtable_private.h"
-#include "hashtable_itr.h"
-#include <stdlib.h> /* defines NULL */
-
-/*****************************************************************************/
-/* hashtable_iterator - iterator constructor */
-
-struct hashtable_itr *
-hashtable_iterator(struct hashtable *h)
-{
- unsigned int i, tablelength;
- struct hashtable_itr *itr = (struct hashtable_itr *)
- malloc(sizeof(struct hashtable_itr));
- if (NULL == itr) return NULL;
- itr->h = h;
- itr->e = NULL;
- itr->parent = NULL;
- tablelength = h->tablelength;
- itr->index = tablelength;
- if (0 == h->entrycount) return itr;
-
- for (i = 0; i < tablelength; i++)
- {
- if (NULL != h->table[i])
- {
- itr->e = h->table[i];
- itr->index = i;
- break;
- }
- }
- return itr;
-}
-
-/*****************************************************************************/
-/* key - return the key of the (key,value) pair at the current position */
-/* value - return the value of the (key,value) pair at the current position */
-
-void *
-hashtable_iterator_key(struct hashtable_itr *i)
-{ return i->e->k; }
-
-void *
-hashtable_iterator_value(struct hashtable_itr *i)
-{ return i->e->v; }
-
-/*****************************************************************************/
-/* advance - advance the iterator to the next element
- * returns zero if advanced to end of table */
-
-int
-hashtable_iterator_advance(struct hashtable_itr *itr)
-{
- unsigned int j,tablelength;
- struct entry **table;
- struct entry *next;
- if (NULL == itr->e) return 0; /* stupidity check */
-
- next = itr->e->next;
- if (NULL != next)
- {
- itr->parent = itr->e;
- itr->e = next;
- return -1;
- }
- tablelength = itr->h->tablelength;
- itr->parent = NULL;
- if (tablelength <= (j = ++(itr->index)))
- {
- itr->e = NULL;
- return 0;
- }
- table = itr->h->table;
- while (NULL == (next = table[j]))
- {
- if (++j >= tablelength)
- {
- itr->index = tablelength;
- itr->e = NULL;
- return 0;
- }
- }
- itr->index = j;
- itr->e = next;
- return -1;
-}
-
-/*****************************************************************************/
-/* remove - remove the entry at the current iterator position
- * and advance the iterator, if there is a successive
- * element.
- * If you want the value, read it before you remove:
- * beware memory leaks if you don't.
- * Returns zero if end of iteration. */
-
-int
-hashtable_iterator_remove(struct hashtable_itr *itr)
-{
- struct entry *remember_e, *remember_parent;
- int ret;
-
- /* Do the removal */
- if (NULL == (itr->parent))
- {
- /* element is head of a chain */
- itr->h->table[itr->index] = itr->e->next;
- } else {
- /* element is mid-chain */
- itr->parent->next = itr->e->next;
- }
- /* itr->e is now outside the hashtable */
- remember_e = itr->e;
- itr->h->entrycount--;
- freekey(remember_e->k);
-
- /* Advance the iterator, correcting the parent */
- remember_parent = itr->parent;
- ret = hashtable_iterator_advance(itr);
- if (itr->parent == remember_e) { itr->parent = remember_parent; }
- free(remember_e);
- return ret;
-}
-
-/*****************************************************************************/
-int /* returns zero if not found */
-hashtable_iterator_search(struct hashtable_itr *itr,
- struct hashtable *h, void *k)
-{
- struct entry *e, *parent;
- unsigned int hashvalue, index;
-
- hashvalue = hash(h,k);
- index = indexFor(h->tablelength,hashvalue);
-
- e = h->table[index];
- parent = NULL;
- while (NULL != e)
- {
- /* Check hash value to short circuit heavier comparison */
- if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
- {
- itr->index = index;
- itr->e = e;
- itr->parent = parent;
- itr->h = h;
- return -1;
- }
- parent = e;
- e = e->next;
- }
- return 0;
-}
-
-
-/*
- * Copyright (c) 2002, 2004, Christopher Clark
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of the original author; nor the names of any contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
+++ /dev/null
-/* Copyright (C) 2002, 2004 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
-
-#ifndef HASHTABLE_ITR_CWC22_H
-#define HASHTABLE_ITR_CWC22_H
-#include "hashtable.h"
-#include "hashtable_private.h" /* needed to enable inlining */
-
-#if defined (__cplusplus)
-extern "C" {
-#endif
-
-/*****************************************************************************/
-/* This struct is only concrete here to allow the inlining of two of the
- * accessor functions. */
-struct hashtable_itr
-{
- struct hashtable *h;
- struct entry *e;
- struct entry *parent;
- unsigned int index;
-};
-
-
-/*****************************************************************************/
-/* hashtable_iterator
- */
-
-struct hashtable_itr *
-hashtable_iterator(struct hashtable *h);
-
-/*****************************************************************************/
-/* hashtable_iterator_key
- * - return the value of the (key,value) pair at the current position */
-
-#ifdef HAVE_EXTERN_INLINE
-extern inline void *
-hashtable_iterator_key(struct hashtable_itr *i)
-{
- return i->e->k;
-}
-#else
-void *
-hashtable_iterator_key(struct hashtable_itr *i);
-#endif
-
-/*****************************************************************************/
-/* value - return the value of the (key,value) pair at the current position */
-
-#ifdef HAVE_EXTERN_INLINE
-extern inline void *
-hashtable_iterator_value(struct hashtable_itr *i)
-{
- return i->e->v;
-}
-#else
-void *
-hashtable_iterator_value(struct hashtable_itr *i);
-#endif
-
-/*****************************************************************************/
-/* advance - advance the iterator to the next element
- * returns zero if advanced to end of table */
-
-int
-hashtable_iterator_advance(struct hashtable_itr *itr);
-
-/*****************************************************************************/
-/* remove - remove current element and advance the iterator to the next element
- * NB: if you need the value to free it, read it before
- * removing. ie: beware memory leaks!
- * returns zero if advanced to end of table */
-
-int
-hashtable_iterator_remove(struct hashtable_itr *itr);
-
-/*****************************************************************************/
-/* search - overwrite the supplied iterator, to point to the entry
- * matching the supplied key.
- h points to the hashtable to be searched.
- * returns zero if not found. */
-int
-hashtable_iterator_search(struct hashtable_itr *itr,
- struct hashtable *h, void *k);
-
-#define DEFINE_HASHTABLE_ITERATOR_SEARCH(fnname, keytype) \
-int fnname (struct hashtable_itr *i, struct hashtable *h, keytype *k) \
-{ \
- return (hashtable_iterator_search(i,h,k)); \
-}
-
-#if defined (__cplusplus)
-}
-#endif
-
-#endif /* HASHTABLE_ITR_CWC22_H */
-
-/*
- * Copyright (c) 2002, 2004, Christopher Clark
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of the original author; nor the names of any contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
+++ /dev/null
-/* Copyright (C) 2002, 2004 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
-
-#ifndef HASHTABLE_PRIVATE_CWC22_H
-#define HASHTABLE_PRIVATE_CWC22_H
-
-#include "hashtable.h"
-
-#if defined (__cplusplus)
-extern "C" {
-#endif
-
-/*****************************************************************************/
-struct entry
-{
- void *k, *v;
- unsigned int h;
- struct entry *next;
-};
-
-struct hashtable {
- unsigned int tablelength;
- struct entry **table;
- unsigned int entrycount;
- unsigned int loadlimit;
- unsigned int primeindex;
- unsigned int (*hashfn) (void *k);
- int (*eqfn) (void *k1, void *k2);
-};
-
-/*****************************************************************************/
-unsigned int
-hash(struct hashtable *h, void *k);
-
-/*****************************************************************************/
-#ifdef HASHTABLE_INDEXFOR
-/* indexFor */
-static inline unsigned int
-indexFor(unsigned int tablelength, unsigned int hashvalue) {
- return (hashvalue % tablelength);
-}
-
-/* Only works if tablelength == 2^N */
-/*static inline unsigned int
-indexFor(unsigned int tablelength, unsigned int hashvalue)
-{
- return (hashvalue & (tablelength - 1u));
-}
-*/
-#endif
-
-/*****************************************************************************/
-#define freekey(X) free(X)
-/*define freekey(X) ; */
-
-
-/*****************************************************************************/
-
-#if defined (__cplusplus)
-}
-#endif
-
-#endif /* HASHTABLE_PRIVATE_CWC22_H */
-
-/*
- * Copyright (c) 2002, Christopher Clark
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of the original author; nor the names of any contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/