Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
libvirt
提交
f113c597
L
libvirt
项目概览
openeuler
/
libvirt
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
L
libvirt
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
f113c597
编写于
11月 30, 2005
作者:
D
Daniel Veillard
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
oops, forgot hash.[ch], Daniel
上级
978d57bb
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
531 addition
and
0 deletion
+531
-0
src/hash.c
src/hash.c
+460
-0
src/hash.h
src/hash.h
+71
-0
未找到文件。
src/hash.c
0 → 100644
浏览文件 @
f113c597
/*
* hash.c: chained hash tables
*
* Reference: Your favorite introductory book on algorithms
*
* Copyright (C) 2000 Bjorn Reese and Daniel Veillard.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
* CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
*
* Author: breese@users.sourceforge.net
*/
#define IN_LIBXML
#include <string.h>
#include "hash.h"
#define MAX_HASH_LEN 8
/* #define DEBUG_GROW */
/*
* A single entry in the hash table
*/
typedef
struct
_xenHashEntry
xenHashEntry
;
typedef
xenHashEntry
*
xenHashEntryPtr
;
struct
_xenHashEntry
{
struct
_xenHashEntry
*
next
;
char
*
name
;
void
*
payload
;
int
valid
;
};
/*
* The entire hash table
*/
struct
_xenHashTable
{
struct
_xenHashEntry
*
table
;
int
size
;
int
nbElems
;
};
/*
* xenHashComputeKey:
* Calculate the hash key
*/
static
unsigned
long
xenHashComputeKey
(
xenHashTablePtr
table
,
const
char
*
name
)
{
unsigned
long
value
=
0L
;
char
ch
;
if
(
name
!=
NULL
)
{
value
+=
30
*
(
*
name
);
while
((
ch
=
*
name
++
)
!=
0
)
{
value
=
value
^
((
value
<<
5
)
+
(
value
>>
3
)
+
(
unsigned
long
)
ch
);
}
}
return
(
value
%
table
->
size
);
}
/**
* xenHashCreate:
* @size: the size of the hash table
*
* Create a new xenHashTablePtr.
*
* Returns the newly created object, or NULL if an error occured.
*/
xenHashTablePtr
xenHashCreate
(
int
size
)
{
xenHashTablePtr
table
;
if
(
size
<=
0
)
size
=
256
;
table
=
malloc
(
sizeof
(
xenHashTable
));
if
(
table
)
{
table
->
size
=
size
;
table
->
nbElems
=
0
;
table
->
table
=
malloc
(
size
*
sizeof
(
xenHashEntry
));
if
(
table
->
table
)
{
memset
(
table
->
table
,
0
,
size
*
sizeof
(
xenHashEntry
));
return
(
table
);
}
free
(
table
);
}
return
(
NULL
);
}
/**
* xenHashGrow:
* @table: the hash table
* @size: the new size of the hash table
*
* resize the hash table
*
* Returns 0 in case of success, -1 in case of failure
*/
static
int
xenHashGrow
(
xenHashTablePtr
table
,
int
size
)
{
unsigned
long
key
;
int
oldsize
,
i
;
xenHashEntryPtr
iter
,
next
;
struct
_xenHashEntry
*
oldtable
;
#ifdef DEBUG_GROW
unsigned
long
nbElem
=
0
;
#endif
if
(
table
==
NULL
)
return
(
-
1
);
if
(
size
<
8
)
return
(
-
1
);
if
(
size
>
8
*
2048
)
return
(
-
1
);
oldsize
=
table
->
size
;
oldtable
=
table
->
table
;
if
(
oldtable
==
NULL
)
return
(
-
1
);
table
->
table
=
malloc
(
size
*
sizeof
(
xenHashEntry
));
if
(
table
->
table
==
NULL
)
{
table
->
table
=
oldtable
;
return
(
-
1
);
}
memset
(
table
->
table
,
0
,
size
*
sizeof
(
xenHashEntry
));
table
->
size
=
size
;
/* If the two loops are merged, there would be situations where
a new entry needs to allocated and data copied into it from
the main table. So instead, we run through the array twice, first
copying all the elements in the main array (where we can't get
conflicts) and then the rest, so we only free (and don't allocate)
*/
for
(
i
=
0
;
i
<
oldsize
;
i
++
)
{
if
(
oldtable
[
i
].
valid
==
0
)
continue
;
key
=
xenHashComputeKey
(
table
,
oldtable
[
i
].
name
);
memcpy
(
&
(
table
->
table
[
key
]),
&
(
oldtable
[
i
]),
sizeof
(
xenHashEntry
));
table
->
table
[
key
].
next
=
NULL
;
}
for
(
i
=
0
;
i
<
oldsize
;
i
++
)
{
iter
=
oldtable
[
i
].
next
;
while
(
iter
)
{
next
=
iter
->
next
;
/*
* put back the entry in the new table
*/
key
=
xenHashComputeKey
(
table
,
iter
->
name
);
if
(
table
->
table
[
key
].
valid
==
0
)
{
memcpy
(
&
(
table
->
table
[
key
]),
iter
,
sizeof
(
xenHashEntry
));
table
->
table
[
key
].
next
=
NULL
;
free
(
iter
);
}
else
{
iter
->
next
=
table
->
table
[
key
].
next
;
table
->
table
[
key
].
next
=
iter
;
}
#ifdef DEBUG_GROW
nbElem
++
;
#endif
iter
=
next
;
}
}
free
(
oldtable
);
#ifdef DEBUG_GROW
xmlGenericError
(
xmlGenericErrorContext
,
"xenHashGrow : from %d to %d, %d elems
\n
"
,
oldsize
,
size
,
nbElem
);
#endif
return
(
0
);
}
/**
* xenHashFree:
* @table: the hash table
* @f: the deallocator function for items in the hash
*
* Free the hash @table and its contents. The userdata is
* deallocated with @f if provided.
*/
void
xenHashFree
(
xenHashTablePtr
table
,
xenHashDeallocator
f
)
{
int
i
;
xenHashEntryPtr
iter
;
xenHashEntryPtr
next
;
int
inside_table
=
0
;
int
nbElems
;
if
(
table
==
NULL
)
return
;
if
(
table
->
table
)
{
nbElems
=
table
->
nbElems
;
for
(
i
=
0
;
(
i
<
table
->
size
)
&&
(
nbElems
>
0
);
i
++
)
{
iter
=
&
(
table
->
table
[
i
]);
if
(
iter
->
valid
==
0
)
continue
;
inside_table
=
1
;
while
(
iter
)
{
next
=
iter
->
next
;
if
((
f
!=
NULL
)
&&
(
iter
->
payload
!=
NULL
))
f
(
iter
->
payload
,
iter
->
name
);
if
(
iter
->
name
)
free
(
iter
->
name
);
iter
->
payload
=
NULL
;
if
(
!
inside_table
)
free
(
iter
);
nbElems
--
;
inside_table
=
0
;
iter
=
next
;
}
inside_table
=
0
;
}
free
(
table
->
table
);
}
free
(
table
);
}
/**
* xenHashAddEntry3:
* @table: the hash table
* @name: the name of the userdata
* @userdata: a pointer to the userdata
*
* Add the @userdata to the hash @table. This can later be retrieved
* by using @name. Duplicate entries generate errors.
*
* Returns 0 the addition succeeded and -1 in case of error.
*/
int
xenHashAddEntry
(
xenHashTablePtr
table
,
const
char
*
name
,
void
*
userdata
)
{
unsigned
long
key
,
len
=
0
;
xenHashEntryPtr
entry
;
xenHashEntryPtr
insert
;
if
((
table
==
NULL
)
||
(
name
==
NULL
))
return
(
-
1
);
/*
* Check for duplicate and insertion location.
*/
key
=
xenHashComputeKey
(
table
,
name
);
if
(
table
->
table
[
key
].
valid
==
0
)
{
insert
=
NULL
;
}
else
{
for
(
insert
=
&
(
table
->
table
[
key
]);
insert
->
next
!=
NULL
;
insert
=
insert
->
next
)
{
if
(
!
strcmp
(
insert
->
name
,
name
))
return
(
-
1
);
len
++
;
}
if
(
!
strcmp
(
insert
->
name
,
name
))
return
(
-
1
);
}
if
(
insert
==
NULL
)
{
entry
=
&
(
table
->
table
[
key
]);
}
else
{
entry
=
malloc
(
sizeof
(
xenHashEntry
));
if
(
entry
==
NULL
)
return
(
-
1
);
}
entry
->
name
=
strdup
(
name
);
entry
->
payload
=
userdata
;
entry
->
next
=
NULL
;
entry
->
valid
=
1
;
if
(
insert
!=
NULL
)
insert
->
next
=
entry
;
table
->
nbElems
++
;
if
(
len
>
MAX_HASH_LEN
)
xenHashGrow
(
table
,
MAX_HASH_LEN
*
table
->
size
);
return
(
0
);
}
/**
* xenHashUpdateEntry:
* @table: the hash table
* @name: the name of the userdata
* @userdata: a pointer to the userdata
* @f: the deallocator function for replaced item (if any)
*
* Add the @userdata to the hash @table. This can later be retrieved
* by using @name. Existing entry for this tuple
* will be removed and freed with @f if found.
*
* Returns 0 the addition succeeded and -1 in case of error.
*/
int
xenHashUpdateEntry
(
xenHashTablePtr
table
,
const
char
*
name
,
void
*
userdata
,
xenHashDeallocator
f
)
{
unsigned
long
key
;
xenHashEntryPtr
entry
;
xenHashEntryPtr
insert
;
if
((
table
==
NULL
)
||
name
==
NULL
)
return
(
-
1
);
/*
* Check for duplicate and insertion location.
*/
key
=
xenHashComputeKey
(
table
,
name
);
if
(
table
->
table
[
key
].
valid
==
0
)
{
insert
=
NULL
;
}
else
{
for
(
insert
=
&
(
table
->
table
[
key
]);
insert
->
next
!=
NULL
;
insert
=
insert
->
next
)
{
if
(
!
strcmp
(
insert
->
name
,
name
))
{
if
(
f
)
f
(
insert
->
payload
,
insert
->
name
);
insert
->
payload
=
userdata
;
return
(
0
);
}
}
if
(
!
strcmp
(
insert
->
name
,
name
))
{
if
(
f
)
f
(
insert
->
payload
,
insert
->
name
);
insert
->
payload
=
userdata
;
return
(
0
);
}
}
if
(
insert
==
NULL
)
{
entry
=
&
(
table
->
table
[
key
]);
}
else
{
entry
=
malloc
(
sizeof
(
xenHashEntry
));
if
(
entry
==
NULL
)
return
(
-
1
);
}
entry
->
name
=
strdup
(
name
);
entry
->
payload
=
userdata
;
entry
->
next
=
NULL
;
entry
->
valid
=
1
;
table
->
nbElems
++
;
if
(
insert
!=
NULL
)
{
insert
->
next
=
entry
;
}
return
(
0
);
}
/**
* xenHashLookup:
* @table: the hash table
* @name: the name of the userdata
*
* Find the userdata specified by the (@name, @name2, @name3) tuple.
*
* Returns the a pointer to the userdata
*/
void
*
xenHashLookup
(
xenHashTablePtr
table
,
const
char
*
name
)
{
unsigned
long
key
;
xenHashEntryPtr
entry
;
if
(
table
==
NULL
)
return
(
NULL
);
if
(
name
==
NULL
)
return
(
NULL
);
key
=
xenHashComputeKey
(
table
,
name
);
if
(
table
->
table
[
key
].
valid
==
0
)
return
(
NULL
);
for
(
entry
=
&
(
table
->
table
[
key
]);
entry
!=
NULL
;
entry
=
entry
->
next
)
{
if
(
!
strcmp
(
entry
->
name
,
name
))
return
(
entry
->
payload
);
}
return
(
NULL
);
}
/**
* xenHashSize:
* @table: the hash table
*
* Query the number of elements installed in the hash @table.
*
* Returns the number of elements in the hash table or
* -1 in case of error
*/
int
xenHashSize
(
xenHashTablePtr
table
)
{
if
(
table
==
NULL
)
return
(
-
1
);
return
(
table
->
nbElems
);
}
/**
* xenHashRemoveEntry:
* @table: the hash table
* @name: the name of the userdata
* @f: the deallocator function for removed item (if any)
*
* Find the userdata specified by the @name and remove
* it from the hash @table. Existing userdata for this tuple will be removed
* and freed with @f.
*
* Returns 0 if the removal succeeded and -1 in case of error or not found.
*/
int
xenHashRemoveEntry
(
xenHashTablePtr
table
,
const
char
*
name
,
xenHashDeallocator
f
)
{
unsigned
long
key
;
xenHashEntryPtr
entry
;
xenHashEntryPtr
prev
=
NULL
;
if
(
table
==
NULL
||
name
==
NULL
)
return
(
-
1
);
key
=
xenHashComputeKey
(
table
,
name
);
if
(
table
->
table
[
key
].
valid
==
0
)
{
return
(
-
1
);
}
else
{
for
(
entry
=
&
(
table
->
table
[
key
]);
entry
!=
NULL
;
entry
=
entry
->
next
)
{
if
(
!
strcmp
(
entry
->
name
,
name
))
{
if
((
f
!=
NULL
)
&&
(
entry
->
payload
!=
NULL
))
f
(
entry
->
payload
,
entry
->
name
);
entry
->
payload
=
NULL
;
if
(
entry
->
name
)
free
(
entry
->
name
);
if
(
prev
)
{
prev
->
next
=
entry
->
next
;
free
(
entry
);
}
else
{
if
(
entry
->
next
==
NULL
)
{
entry
->
valid
=
0
;
}
else
{
entry
=
entry
->
next
;
memcpy
(
&
(
table
->
table
[
key
]),
entry
,
sizeof
(
xenHashEntry
));
free
(
entry
);
}
}
table
->
nbElems
--
;
return
(
0
);
}
prev
=
entry
;
}
return
(
-
1
);
}
}
src/hash.h
0 → 100644
浏览文件 @
f113c597
/*
* Summary: Chained hash tables
* Description: This module implements the hash table support used in
* various places in the library.
*
* Copy: See Copyright for the status of this software.
*
* Author: Bjorn Reese <bjorn.reese@systematic.dk>
*/
#ifndef __XEN_HASH_H__
#define __XEN_HASH_H__
#ifdef __cplusplus
extern
"C"
{
#endif
/*
* The hash table.
*/
typedef
struct
_xenHashTable
xenHashTable
;
typedef
xenHashTable
*
xenHashTablePtr
;
/*
* function types:
*/
/**
* xenHashDeallocator:
* @payload: the data in the hash
* @name: the name associated
*
* Callback to free data from a hash.
*/
typedef
void
(
*
xenHashDeallocator
)(
void
*
payload
,
char
*
name
);
/*
* Constructor and destructor.
*/
xenHashTablePtr
xenHashCreate
(
int
size
);
void
xenHashFree
(
xenHashTablePtr
table
,
xenHashDeallocator
f
);
int
xenHashSize
(
xenHashTablePtr
table
);
/*
* Add a new entry to the hash table.
*/
int
xenHashAddEntry
(
xenHashTablePtr
table
,
const
char
*
name
,
void
*
userdata
);
int
xenHashUpdateEntry
(
xenHashTablePtr
table
,
const
char
*
name
,
void
*
userdata
,
xenHashDeallocator
f
);
/*
* Remove an entry from the hash table.
*/
int
xenHashRemoveEntry
(
xenHashTablePtr
table
,
const
char
*
name
,
xenHashDeallocator
f
);
/*
* Retrieve the userdata.
*/
void
*
xenHashLookup
(
xenHashTablePtr
table
,
const
char
*
name
);
#ifdef __cplusplus
}
#endif
#endif
/* ! __XEN_HASH_H__ */
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录