源码的下载地址:https://download.csdn.net/download/xiyuan255/12372494
/*
* File name : xy_chash_source.c
*
* Created on : 2019年10月11日14:40:24
* Author : Firmware of xiyuan255
* Version : 2.0
* Language : C
* Copyright : Copyright (C) 2019, xiyuan255 Inc.
*
*/
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <assert.h>
#include "xy_chash_source.h"
#ifndef BITS_PER_BYTE
#define BITS_PER_BYTE ((int) (8 * sizeof(char)))
#endif
#ifndef BITS
#define BITS(type) ((int) (BITS_PER_BYTE * (int) sizeof(type)))
#endif
/**
* 封装整型值
*/
PUBLIC cell_value_t value_integer(long value)
{
cell_value_t v;
memset(&v, 0x00, sizeof(v));
v.valid = 1;
v.type = integer;
v.value.integer = value;
return v;
}
/**
* 封装浮点型值
*/
PUBLIC cell_value_t value_floating(double value)
{
cell_value_t v;
memset(&v, 0x00, sizeof(v));
v.valid = 1;
v.type = floating;
v.value.floating = value;
return v;
}
/**
* 封装字符串型值
*/
PUBLIC cell_value_t value_string(const char *value, int flags)
{
cell_value_t v;
int value_len = 0;
memset(&v, 0x00, sizeof(v));
v.valid = 1;
v.type = string;
if (value && *value && flags & VALUE_ALLOCATE) {
v.allocated = 1;
value_len = strlen(value);
v.value.string = calloc(sizeof(char), value_len);
if (NULL != v.value.string) {
strcpy(v.value.string, value);
}
} else {
v.allocated = 0;
v.value.string = (char*) value;
}
return v;
}
/**
* 封装字节型值
*/
PUBLIC cell_value_t value_bytes(const uint8_t *value, int len)
{
cell_value_t v;
memset(&v, 0x00, sizeof(v));
v.valid = 1;
v.type = bytes;
if (len > 0) {
v.allocated = 1;
v.byteslen = len;
v.value.bytes = calloc(sizeof(char), len);
if (NULL != v.value.bytes) {
memcpy(v.value.bytes, value, len);
}
} else {
v.allocated = 0;
v.byteslen = 0;
v.value.bytes = (uint8_t *)value;
}
return v;
}
/**
* 封装符号型值
*/
PUBLIC cell_value_t value_symbol(const void *value)
{
cell_value_t v;
memset(&v, 0x00, sizeof(v));
v.valid = 1;
v.type = symbol;
v.value.symbol = (void *)value;
return v;
}
/**
* 释放成员动态内存
*/
PUBLIC void value_free(cell_value_t *v)
{
if (v->valid && v->allocated) {
if (string == v->type && NULL != v->value.string) {
free(v->value.string);
} else if (bytes == v->type && NULL != v->value.bytes) {
free(v->value.bytes);
}
}
v->type = undefined;
v->byteslen = 0;
v->valid = 0;
v->allocated = 0;
}
/*
Check if this number is a prime
*/
__STATIC_INLINE int is_prime(int n)
{
int i, max;
assert(n > 0);
max = n / 2;
for (i = 2; i <= max; i++) {
if (n % i == 0) {
return 0;
}
}
return 1;
}
/*
Calculate the largest prime smaller than size.
*/
__STATIC int calc_prime(int size)
{
int count;
assert(size > 0);
for (count = size; count > 0; count--) {
if (is_prime(count)) {
return count;
}
}
return 1;
}
/**
* 计算hash指示值
* 这个称为散列函数,根据不同的key产生散列值。不同的key可能出现相同的散列值,
* 这称为hash碰撞。hash有一个特性,不同的散列值则对应的key一定不同,但相同的
* 散列值可能对应相同的key也可能对应不同的key。
*/
__STATIC int hash_index(HashTable_t *chash, const char *key)
{
unsigned int sum = 0;
int i = 0;
assert(chash && key && *key);
i = 0;
sum = 0;
while (*key) {
sum += (((int) *key++) << i);
i = (i + 7) % (BITS(int) - BITS_PER_BYTE);
}
return sum % chash->size;
}
/*
Close this symbol table. Call a cleanup function to allow the caller to free resources associated with each symbol
table entry.
*/
PUBLIC void c_hash_free(HashTable_t *chash)
{
hash_cell_t *sp, *forw;
int i;
if (NULL == chash) {
return;
}
/*
Free all symbols in the hash table, then the hash table itself.
*/
for (i = 0; i < chash->size; i++) {
for (sp = chash->hash_table[i]; sp; sp = forw) {
forw = sp->ptr_next;
value_free(&sp->key);
value_free(&sp->content);
free((void *)sp);
sp = forw;
}
}
free((void *)chash->hash_table);
free((void *)chash);
}
/**
* 创建hash对象
*/
PUBLIC HashTable_t *c_hash_create(int size)
{
HashTable_t *chash = NULL;
chash = (HashTable_t *)calloc(sizeof(char), sizeof(HashTable_t));
if (NULL == chash) {
return NULL;
}
chash->size = calc_prime(size); /* 求出size之下的最大素数 */
chash->hash_table = (hash_cell_p *)malloc(chash->size * sizeof(hash_cell_p));
if (NULL == chash->hash_table) {
free(chash);
return NULL;
}
memset(chash->hash_table, 0, chash->size * sizeof(hash_cell_p));
return chash;
}
/**
* 向hash对象插入cell_value_t成员
*/
PUBLIC hash_cell_t *c_hash_enter(HashTable_t *chash, const char *key, cell_value_t v, void *arg)
{
hash_cell_t *sp, *last;
int hindex;
char *cp;
assert(chash && key && *key);
last = NULL;
hindex = hash_index(chash, key);
if (NULL != (sp = chash->hash_table[hindex])) {
for (; sp; sp = sp->ptr_next) {
cp = sp->key.value.string;
if (cp[0] == key[0] && 0 == strcmp(cp, key)) {
break;
}
last = sp;
}
if (sp) { // 已经存在则更新
if (sp->content.valid) {
value_free(&sp->content);
}
sp->content = v;
sp->arg = arg;
return sp;
}
sp = (hash_cell_t *)calloc(sizeof(char), sizeof(hash_cell_t));
if (NULL == sp) {
return NULL;
}
sp->key = value_string(key, VALUE_ALLOCATE);
sp->content = v;
sp->ptr_next = (hash_cell_t *)NULL;
sp->arg = arg;
sp->index = hindex;
last->ptr_next = sp;
} else {
if ((sp = (hash_cell_t *)malloc(sizeof(hash_cell_t))) == 0) {
return NULL;
}
chash->hash_table[hindex] = sp;
sp->ptr_next = (hash_cell_t *) NULL;
sp->content = v;
sp->arg = arg;
sp->key = value_string(key, VALUE_ALLOCATE);
sp->index = hindex;
}
return sp;
}
/**
* 删除hash对象中key的成员
*/
PUBLIC int c_hash_delete(HashTable_t *chash, const char *key)
{
hash_cell_t *sp, *last;
int hindex;
char *cp;
assert(chash && key && *key);
last = NULL;
hindex = hash_index(chash, key);
if (NULL != (sp = chash->hash_table[hindex])) {
for ( ; sp; sp = sp->ptr_next) {
cp = sp->key.value.string;
if (cp[0] == key[0] && 0 == strcmp(cp, key)) {
break;
}
last = sp;
}
}
if ((hash_cell_t *)NULL == sp) {
return -1;
}
if (last) {
last->ptr_next = sp->ptr_next;
} else {
chash->hash_table[hindex] = sp->ptr_next;
}
value_free(&sp->key);
value_free(&sp->content);
free((void *)sp);
return 0;
}
/**
* 获取hash对象的第一个成员
*/
PUBLIC hash_cell_p c_hash_first(HashTable_t *chash)
{
int i = 0;
hash_cell_p sp = NULL;
assert(chash);
for (i = 0; i < chash->size; i++) {
if (NULL != (sp = chash->hash_table[i])) {
break;
}
}
return sp;
}
/**
* 获取hash对象的下一成员
*/
PUBLIC hash_cell_p c_hash_next(HashTable_t *chash, hash_cell_p cell)
{
int i = 0;
hash_cell_p sp = NULL;
assert(chash);
if (NULL == cell) {
return c_hash_first(chash);
}
if (NULL != cell->ptr_next) {
return cell->ptr_next;
}
for (i = cell->index + 1; i < chash->size; i++) {
if (NULL != (sp = chash->hash_table[i])) {
return sp;
}
}
return NULL;
}
/**
* 查询hash对象的的key成员
*/
PUBLIC hash_cell_p c_hash_lookup(HashTable_t *chash, const char *key)
{
hash_cell_p sp = NULL;
char *cp;
if (NULL == chash || NULL == key) {
return NULL;
}
for (sp = chash->hash_table[hash_index(chash, key)]; sp; sp = sp->ptr_next) {
cp = sp->key.value.string;
if (cp[0] == key[0] && 0 == strcmp(cp, key)) {
break;
}
}
return sp;
}
/**
* 查询hash对象的的key成员中的整型值
*/
PUBLIC int c_hash_lookup_integer(HashTable_t *chash, const char *key, long *integer)
{
hash_cell_t *kp;
if (NULL == (kp = c_hash_lookup(chash, key))) {
return -1;
}
*integer = kp->content.value.integer;
return 0;
}
/**
* 查询hash对象的的key成员中的浮点型值
*/
PUBLIC int c_hash_lookup_floating(HashTable_t *chash, const char *key, double *floating)
{
hash_cell_t *kp;
if (NULL == (kp = c_hash_lookup(chash, key))) {
return -1;
}
*floating = kp->content.value.floating;
return 0;
}
/**
* 查询hash对象的的key成员中的字符串值
*/
PUBLIC int c_hash_lookup_string(HashTable_t *chash, const char *key, char *string, int len)
{
hash_cell_t *kp;
int slen = 0;
if (NULL == (kp = c_hash_lookup(chash, key))) {
return -1;
}
slen = strlen(kp->content.value.string);
memcpy(string, kp->content.value.string, (slen >= len)? len-1 : slen);
return 0;
}
/**
* 查询hash对象的的key成员中的字节型值
*/
PUBLIC int c_hash_lookup_bytes(HashTable_t *chash, const char *key, uint8_t *bytes, int *iolen)
{
hash_cell_t *kp;
int blen = 0;
if (NULL == (kp = c_hash_lookup(chash, key))) {
return -1;
}
blen = kp->content.byteslen;
memcpy(bytes, kp->content.value.bytes, (blen >= *iolen)? *iolen-1 : blen);
*iolen = blen;
return 0;
}
/**
* 查询hash对象的的key成员中的符号型值
*/
PUBLIC int c_hash_lookup_symbol(HashTable_t *chash, const char *key, void **symbol)
{
hash_cell_t *kp;
if (NULL == (kp = c_hash_lookup(chash, key))) {
return -1;
}
*symbol = kp->content.value.symbol;
return 0;
}