mirror of
https://git.proxmox.com/git/libgit2
synced 2025-08-12 10:01:10 +00:00
Rename git_khash_str to git_strmap, etc.
This renamed `git_khash_str` to `git_strmap`, `git_hash_oid` to `git_oidmap`, and deletes `git_hashtable` from the tree, plus adds unit tests for `git_strmap`.
This commit is contained in:
parent
01fed0a8f9
commit
c2b670436f
48
src/attr.c
48
src/attr.c
@ -3,7 +3,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
GIT_KHASH_STR__IMPLEMENTATION;
|
GIT__USE_STRMAP;
|
||||||
|
|
||||||
static int collect_attr_files(
|
static int collect_attr_files(
|
||||||
git_repository *repo, const char *path, git_vector *files);
|
git_repository *repo, const char *path, git_vector *files);
|
||||||
@ -126,14 +126,14 @@ int git_attr_foreach(
|
|||||||
git_attr_file *file;
|
git_attr_file *file;
|
||||||
git_attr_rule *rule;
|
git_attr_rule *rule;
|
||||||
git_attr_assignment *assign;
|
git_attr_assignment *assign;
|
||||||
git_khash_str *seen = NULL;
|
git_strmap *seen = NULL;
|
||||||
|
|
||||||
if ((error = git_attr_path__init(
|
if ((error = git_attr_path__init(
|
||||||
&path, pathname, git_repository_workdir(repo))) < 0 ||
|
&path, pathname, git_repository_workdir(repo))) < 0 ||
|
||||||
(error = collect_attr_files(repo, pathname, &files)) < 0)
|
(error = collect_attr_files(repo, pathname, &files)) < 0)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
seen = git_khash_str_alloc();
|
seen = git_strmap_alloc();
|
||||||
GITERR_CHECK_ALLOC(seen);
|
GITERR_CHECK_ALLOC(seen);
|
||||||
|
|
||||||
git_vector_foreach(&files, i, file) {
|
git_vector_foreach(&files, i, file) {
|
||||||
@ -142,10 +142,10 @@ int git_attr_foreach(
|
|||||||
|
|
||||||
git_vector_foreach(&rule->assigns, k, assign) {
|
git_vector_foreach(&rule->assigns, k, assign) {
|
||||||
/* skip if higher priority assignment was already seen */
|
/* skip if higher priority assignment was already seen */
|
||||||
if (git_khash_str_exists(seen, assign->name))
|
if (git_strmap_exists(seen, assign->name))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
git_khash_str_insert(seen, assign->name, assign, error);
|
git_strmap_insert(seen, assign->name, assign, error);
|
||||||
if (error >= 0)
|
if (error >= 0)
|
||||||
error = callback(assign->name, assign->value, payload);
|
error = callback(assign->name, assign->value, payload);
|
||||||
|
|
||||||
@ -156,7 +156,7 @@ int git_attr_foreach(
|
|||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
git_khash_str_free(seen);
|
git_strmap_free(seen);
|
||||||
git_vector_free(&files);
|
git_vector_free(&files);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
@ -200,12 +200,12 @@ int git_attr_add_macro(
|
|||||||
bool git_attr_cache__is_cached(git_repository *repo, const char *path)
|
bool git_attr_cache__is_cached(git_repository *repo, const char *path)
|
||||||
{
|
{
|
||||||
const char *cache_key = path;
|
const char *cache_key = path;
|
||||||
git_khash_str *files = git_repository_attr_cache(repo)->files;
|
git_strmap *files = git_repository_attr_cache(repo)->files;
|
||||||
|
|
||||||
if (repo && git__prefixcmp(cache_key, git_repository_workdir(repo)) == 0)
|
if (repo && git__prefixcmp(cache_key, git_repository_workdir(repo)) == 0)
|
||||||
cache_key += strlen(git_repository_workdir(repo));
|
cache_key += strlen(git_repository_workdir(repo));
|
||||||
|
|
||||||
return git_khash_str_exists(files, cache_key);
|
return git_strmap_exists(files, cache_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_attr_cache__lookup_or_create_file(
|
int git_attr_cache__lookup_or_create_file(
|
||||||
@ -220,9 +220,9 @@ int git_attr_cache__lookup_or_create_file(
|
|||||||
git_attr_file *file = NULL;
|
git_attr_file *file = NULL;
|
||||||
khiter_t pos;
|
khiter_t pos;
|
||||||
|
|
||||||
pos = git_khash_str_lookup_index(cache->files, key);
|
pos = git_strmap_lookup_index(cache->files, key);
|
||||||
if (git_khash_str_valid_index(cache->files, pos)) {
|
if (git_strmap_valid_index(cache->files, pos)) {
|
||||||
*file_ptr = git_khash_str_value_at(cache->files, pos);
|
*file_ptr = git_strmap_value_at(cache->files, pos);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,7 +240,7 @@ int git_attr_cache__lookup_or_create_file(
|
|||||||
error = git_attr_file__set_path(repo, key, file);
|
error = git_attr_file__set_path(repo, key, file);
|
||||||
|
|
||||||
if (!error) {
|
if (!error) {
|
||||||
git_khash_str_insert(cache->files, file->path, file, error);
|
git_strmap_insert(cache->files, file->path, file, error);
|
||||||
if (error > 0)
|
if (error > 0)
|
||||||
error = 0;
|
error = 0;
|
||||||
}
|
}
|
||||||
@ -383,13 +383,13 @@ int git_attr_cache__init(git_repository *repo)
|
|||||||
|
|
||||||
/* allocate hashtable for attribute and ignore file contents */
|
/* allocate hashtable for attribute and ignore file contents */
|
||||||
if (cache->files == NULL) {
|
if (cache->files == NULL) {
|
||||||
cache->files = git_khash_str_alloc();
|
cache->files = git_strmap_alloc();
|
||||||
GITERR_CHECK_ALLOC(cache->files);
|
GITERR_CHECK_ALLOC(cache->files);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate hashtable for attribute macros */
|
/* allocate hashtable for attribute macros */
|
||||||
if (cache->macros == NULL) {
|
if (cache->macros == NULL) {
|
||||||
cache->macros = git_khash_str_alloc();
|
cache->macros = git_strmap_alloc();
|
||||||
GITERR_CHECK_ALLOC(cache->macros);
|
GITERR_CHECK_ALLOC(cache->macros);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,21 +416,21 @@ void git_attr_cache_flush(
|
|||||||
if (cache->files != NULL) {
|
if (cache->files != NULL) {
|
||||||
git_attr_file *file;
|
git_attr_file *file;
|
||||||
|
|
||||||
git_khash_str_foreach_value(cache->files, file, {
|
git_strmap_foreach_value(cache->files, file, {
|
||||||
git_attr_file__free(file);
|
git_attr_file__free(file);
|
||||||
});
|
});
|
||||||
|
|
||||||
git_khash_str_free(cache->files);
|
git_strmap_free(cache->files);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cache->macros != NULL) {
|
if (cache->macros != NULL) {
|
||||||
git_attr_rule *rule;
|
git_attr_rule *rule;
|
||||||
|
|
||||||
git_khash_str_foreach_value(cache->macros, rule, {
|
git_strmap_foreach_value(cache->macros, rule, {
|
||||||
git_attr_rule__free(rule);
|
git_attr_rule__free(rule);
|
||||||
});
|
});
|
||||||
|
|
||||||
git_khash_str_free(cache->macros);
|
git_strmap_free(cache->macros);
|
||||||
}
|
}
|
||||||
|
|
||||||
git_pool_clear(&cache->pool);
|
git_pool_clear(&cache->pool);
|
||||||
@ -440,28 +440,28 @@ void git_attr_cache_flush(
|
|||||||
|
|
||||||
int git_attr_cache__insert_macro(git_repository *repo, git_attr_rule *macro)
|
int git_attr_cache__insert_macro(git_repository *repo, git_attr_rule *macro)
|
||||||
{
|
{
|
||||||
git_khash_str *macros = git_repository_attr_cache(repo)->macros;
|
git_strmap *macros = git_repository_attr_cache(repo)->macros;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
/* TODO: generate warning log if (macro->assigns.length == 0) */
|
/* TODO: generate warning log if (macro->assigns.length == 0) */
|
||||||
if (macro->assigns.length == 0)
|
if (macro->assigns.length == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
git_khash_str_insert(macros, macro->match.pattern, macro, error);
|
git_strmap_insert(macros, macro->match.pattern, macro, error);
|
||||||
return (error < 0) ? -1 : 0;
|
return (error < 0) ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
git_attr_rule *git_attr_cache__lookup_macro(
|
git_attr_rule *git_attr_cache__lookup_macro(
|
||||||
git_repository *repo, const char *name)
|
git_repository *repo, const char *name)
|
||||||
{
|
{
|
||||||
git_khash_str *macros = git_repository_attr_cache(repo)->macros;
|
git_strmap *macros = git_repository_attr_cache(repo)->macros;
|
||||||
khiter_t pos;
|
khiter_t pos;
|
||||||
|
|
||||||
pos = git_khash_str_lookup_index(macros, name);
|
pos = git_strmap_lookup_index(macros, name);
|
||||||
|
|
||||||
if (!git_khash_str_valid_index(macros, pos))
|
if (!git_strmap_valid_index(macros, pos))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return (git_attr_rule *)git_khash_str_value_at(macros, pos);
|
return (git_attr_rule *)git_strmap_value_at(macros, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#define INCLUDE_attr_h__
|
#define INCLUDE_attr_h__
|
||||||
|
|
||||||
#include "attr_file.h"
|
#include "attr_file.h"
|
||||||
#include "khash_str.h"
|
#include "strmap.h"
|
||||||
|
|
||||||
#define GIT_ATTR_CONFIG "core.attributesfile"
|
#define GIT_ATTR_CONFIG "core.attributesfile"
|
||||||
#define GIT_IGNORE_CONFIG "core.excludesfile"
|
#define GIT_IGNORE_CONFIG "core.excludesfile"
|
||||||
@ -16,8 +16,8 @@
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
int initialized;
|
int initialized;
|
||||||
git_pool pool;
|
git_pool pool;
|
||||||
git_khash_str *files; /* hash path to git_attr_file of rules */
|
git_strmap *files; /* hash path to git_attr_file of rules */
|
||||||
git_khash_str *macros; /* hash name to vector<git_attr_assignment> */
|
git_strmap *macros; /* hash name to vector<git_attr_assignment> */
|
||||||
const char *cfg_attr_file; /* cached value of core.attributesfile */
|
const char *cfg_attr_file; /* cached value of core.attributesfile */
|
||||||
const char *cfg_excl_file; /* cached value of core.excludesfile */
|
const char *cfg_excl_file; /* cached value of core.excludesfile */
|
||||||
} git_attr_cache;
|
} git_attr_cache;
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
#include "git2/attr.h"
|
#include "git2/attr.h"
|
||||||
#include "vector.h"
|
#include "vector.h"
|
||||||
#include "hashtable.h"
|
|
||||||
#include "pool.h"
|
#include "pool.h"
|
||||||
|
|
||||||
#define GIT_ATTR_FILE ".gitattributes"
|
#define GIT_ATTR_FILE ".gitattributes"
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "fileops.h"
|
#include "fileops.h"
|
||||||
#include "hashtable.h"
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "git2/config.h"
|
#include "git2/config.h"
|
||||||
#include "vector.h"
|
#include "vector.h"
|
||||||
|
@ -12,13 +12,13 @@
|
|||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "git2/config.h"
|
#include "git2/config.h"
|
||||||
#include "git2/types.h"
|
#include "git2/types.h"
|
||||||
#include "khash_str.h"
|
#include "strmap.h"
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <regex.h>
|
#include <regex.h>
|
||||||
|
|
||||||
GIT_KHASH_STR__IMPLEMENTATION;
|
GIT__USE_STRMAP;
|
||||||
|
|
||||||
typedef struct cvar_t {
|
typedef struct cvar_t {
|
||||||
struct cvar_t *next;
|
struct cvar_t *next;
|
||||||
@ -72,7 +72,7 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
git_config_file parent;
|
git_config_file parent;
|
||||||
|
|
||||||
git_khash_str *values;
|
git_strmap *values;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
git_buf buffer;
|
git_buf buffer;
|
||||||
@ -132,21 +132,21 @@ static int normalize_name(const char *in, char **out)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_vars(git_khash_str *values)
|
static void free_vars(git_strmap *values)
|
||||||
{
|
{
|
||||||
cvar_t *var = NULL;
|
cvar_t *var = NULL;
|
||||||
|
|
||||||
if (values == NULL)
|
if (values == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
git_khash_str_foreach_value(values, var,
|
git_strmap_foreach_value(values, var,
|
||||||
while (var != NULL) {
|
while (var != NULL) {
|
||||||
cvar_t *next = CVAR_LIST_NEXT(var);
|
cvar_t *next = CVAR_LIST_NEXT(var);
|
||||||
cvar_free(var);
|
cvar_free(var);
|
||||||
var = next;
|
var = next;
|
||||||
});
|
});
|
||||||
|
|
||||||
git_khash_str_free(values);
|
git_strmap_free(values);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int config_open(git_config_file *cfg)
|
static int config_open(git_config_file *cfg)
|
||||||
@ -154,7 +154,7 @@ static int config_open(git_config_file *cfg)
|
|||||||
int res;
|
int res;
|
||||||
diskfile_backend *b = (diskfile_backend *)cfg;
|
diskfile_backend *b = (diskfile_backend *)cfg;
|
||||||
|
|
||||||
b->values = git_khash_str_alloc();
|
b->values = git_strmap_alloc();
|
||||||
GITERR_CHECK_ALLOC(b->values);
|
GITERR_CHECK_ALLOC(b->values);
|
||||||
|
|
||||||
git_buf_init(&b->reader.buffer, 0);
|
git_buf_init(&b->reader.buffer, 0);
|
||||||
@ -196,7 +196,7 @@ static int file_foreach(git_config_file *backend, int (*fn)(const char *, const
|
|||||||
if (!b->values)
|
if (!b->values)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
git_khash_str_foreach(b->values, key, var,
|
git_strmap_foreach(b->values, key, var,
|
||||||
do {
|
do {
|
||||||
if (fn(key, var->value, data) < 0)
|
if (fn(key, var->value, data) < 0)
|
||||||
break;
|
break;
|
||||||
@ -223,9 +223,9 @@ static int config_set(git_config_file *cfg, const char *name, const char *value)
|
|||||||
* Try to find it in the existing values and update it if it
|
* Try to find it in the existing values and update it if it
|
||||||
* only has one value.
|
* only has one value.
|
||||||
*/
|
*/
|
||||||
pos = git_khash_str_lookup_index(b->values, key);
|
pos = git_strmap_lookup_index(b->values, key);
|
||||||
if (git_khash_str_valid_index(b->values, pos)) {
|
if (git_strmap_valid_index(b->values, pos)) {
|
||||||
cvar_t *existing = git_khash_str_value_at(b->values, pos);
|
cvar_t *existing = git_strmap_value_at(b->values, pos);
|
||||||
char *tmp = NULL;
|
char *tmp = NULL;
|
||||||
|
|
||||||
git__free(key);
|
git__free(key);
|
||||||
@ -258,7 +258,7 @@ static int config_set(git_config_file *cfg, const char *name, const char *value)
|
|||||||
GITERR_CHECK_ALLOC(var->value);
|
GITERR_CHECK_ALLOC(var->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
git_khash_str_insert2(b->values, key, var, old_var, rval);
|
git_strmap_insert2(b->values, key, var, old_var, rval);
|
||||||
if (rval < 0)
|
if (rval < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (old_var != NULL)
|
if (old_var != NULL)
|
||||||
@ -284,14 +284,14 @@ static int config_get(git_config_file *cfg, const char *name, const char **out)
|
|||||||
if (normalize_name(name, &key) < 0)
|
if (normalize_name(name, &key) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
pos = git_khash_str_lookup_index(b->values, key);
|
pos = git_strmap_lookup_index(b->values, key);
|
||||||
git__free(key);
|
git__free(key);
|
||||||
|
|
||||||
/* no error message; the config system will write one */
|
/* no error message; the config system will write one */
|
||||||
if (!git_khash_str_valid_index(b->values, pos))
|
if (!git_strmap_valid_index(b->values, pos))
|
||||||
return GIT_ENOTFOUND;
|
return GIT_ENOTFOUND;
|
||||||
|
|
||||||
*out = ((cvar_t *)git_khash_str_value_at(b->values, pos))->value;
|
*out = ((cvar_t *)git_strmap_value_at(b->values, pos))->value;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -311,13 +311,13 @@ static int config_get_multivar(
|
|||||||
if (normalize_name(name, &key) < 0)
|
if (normalize_name(name, &key) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
pos = git_khash_str_lookup_index(b->values, key);
|
pos = git_strmap_lookup_index(b->values, key);
|
||||||
git__free(key);
|
git__free(key);
|
||||||
|
|
||||||
if (!git_khash_str_valid_index(b->values, pos))
|
if (!git_strmap_valid_index(b->values, pos))
|
||||||
return GIT_ENOTFOUND;
|
return GIT_ENOTFOUND;
|
||||||
|
|
||||||
var = git_khash_str_value_at(b->values, pos);
|
var = git_strmap_value_at(b->values, pos);
|
||||||
|
|
||||||
if (regex_str != NULL) {
|
if (regex_str != NULL) {
|
||||||
regex_t regex;
|
regex_t regex;
|
||||||
@ -374,13 +374,13 @@ static int config_set_multivar(
|
|||||||
if (normalize_name(name, &key) < 0)
|
if (normalize_name(name, &key) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
pos = git_khash_str_lookup_index(b->values, key);
|
pos = git_strmap_lookup_index(b->values, key);
|
||||||
if (!git_khash_str_valid_index(b->values, pos)) {
|
if (!git_strmap_valid_index(b->values, pos)) {
|
||||||
git__free(key);
|
git__free(key);
|
||||||
return GIT_ENOTFOUND;
|
return GIT_ENOTFOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
var = git_khash_str_value_at(b->values, pos);
|
var = git_strmap_value_at(b->values, pos);
|
||||||
|
|
||||||
result = regcomp(&preg, regexp, REG_EXTENDED);
|
result = regcomp(&preg, regexp, REG_EXTENDED);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
@ -440,20 +440,20 @@ static int config_delete(git_config_file *cfg, const char *name)
|
|||||||
if (normalize_name(name, &key) < 0)
|
if (normalize_name(name, &key) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
pos = git_khash_str_lookup_index(b->values, key);
|
pos = git_strmap_lookup_index(b->values, key);
|
||||||
git__free(key);
|
git__free(key);
|
||||||
|
|
||||||
if (!git_khash_str_valid_index(b->values, pos))
|
if (!git_strmap_valid_index(b->values, pos))
|
||||||
return GIT_ENOTFOUND;
|
return GIT_ENOTFOUND;
|
||||||
|
|
||||||
var = git_khash_str_value_at(b->values, pos);
|
var = git_strmap_value_at(b->values, pos);
|
||||||
|
|
||||||
if (var->next != NULL) {
|
if (var->next != NULL) {
|
||||||
giterr_set(GITERR_CONFIG, "Cannot delete multivar with a single delete");
|
giterr_set(GITERR_CONFIG, "Cannot delete multivar with a single delete");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
git_khash_str_delete_at(b->values, pos);
|
git_strmap_delete_at(b->values, pos);
|
||||||
|
|
||||||
result = config_write(b, var->key, NULL, NULL);
|
result = config_write(b, var->key, NULL, NULL);
|
||||||
|
|
||||||
@ -914,14 +914,14 @@ static int config_parse(diskfile_backend *cfg_file)
|
|||||||
var->value = var_value;
|
var->value = var_value;
|
||||||
|
|
||||||
/* Add or append the new config option */
|
/* Add or append the new config option */
|
||||||
pos = git_khash_str_lookup_index(cfg_file->values, var->key);
|
pos = git_strmap_lookup_index(cfg_file->values, var->key);
|
||||||
if (!git_khash_str_valid_index(cfg_file->values, pos)) {
|
if (!git_strmap_valid_index(cfg_file->values, pos)) {
|
||||||
git_khash_str_insert(cfg_file->values, var->key, var, result);
|
git_strmap_insert(cfg_file->values, var->key, var, result);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
break;
|
break;
|
||||||
result = 0;
|
result = 0;
|
||||||
} else {
|
} else {
|
||||||
existing = git_khash_str_value_at(cfg_file->values, pos);
|
existing = git_strmap_value_at(cfg_file->values, pos);
|
||||||
while (existing->next != NULL) {
|
while (existing->next != NULL) {
|
||||||
existing = existing->next;
|
existing = existing->next;
|
||||||
}
|
}
|
||||||
|
328
src/hashtable.c
328
src/hashtable.c
@ -1,328 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2009-2012 the libgit2 contributors
|
|
||||||
*
|
|
||||||
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
|
||||||
* a Linking Exception. For full terms see the included COPYING file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
#include "repository.h"
|
|
||||||
#include "commit.h"
|
|
||||||
|
|
||||||
#define MAX_LOOPS 5
|
|
||||||
static const double max_load_factor = 0.65;
|
|
||||||
|
|
||||||
static int resize_to(git_hashtable *self, size_t new_size);
|
|
||||||
static int set_size(git_hashtable *self, size_t new_size);
|
|
||||||
static git_hashtable_node *node_with_hash(git_hashtable *self, const void *key, int hash_id);
|
|
||||||
static void node_swap_with(git_hashtable_node *self, git_hashtable_node *other);
|
|
||||||
static int node_insert(git_hashtable *self, git_hashtable_node *new_node);
|
|
||||||
static int insert_nodes(git_hashtable *self, git_hashtable_node *old_nodes, size_t old_size);
|
|
||||||
static void reinsert_stash(git_hashtable *self);
|
|
||||||
|
|
||||||
static int resize_to(git_hashtable *self, size_t new_size)
|
|
||||||
{
|
|
||||||
git_hashtable_node *old_nodes = self->nodes;
|
|
||||||
size_t old_size = self->size;
|
|
||||||
git_hashtable_node old_stash[GIT_HASHTABLE_STASH_SIZE];
|
|
||||||
size_t old_stash_count = self->stash_count;
|
|
||||||
|
|
||||||
self->is_resizing = 1;
|
|
||||||
|
|
||||||
if (old_stash_count > 0)
|
|
||||||
memcpy(old_stash, self->stash,
|
|
||||||
old_stash_count * sizeof(git_hashtable_node));
|
|
||||||
|
|
||||||
do {
|
|
||||||
self->size = new_size;
|
|
||||||
self->size_mask = new_size - 1;
|
|
||||||
self->key_count = 0;
|
|
||||||
self->stash_count = 0;
|
|
||||||
self->nodes = git__calloc(1, sizeof(git_hashtable_node) * self->size);
|
|
||||||
GITERR_CHECK_ALLOC(self->nodes);
|
|
||||||
|
|
||||||
if (insert_nodes(self, old_nodes, old_size) == 0 &&
|
|
||||||
insert_nodes(self, old_stash, old_stash_count) == 0)
|
|
||||||
self->is_resizing = 0;
|
|
||||||
else {
|
|
||||||
new_size *= 2;
|
|
||||||
git__free(self->nodes);
|
|
||||||
}
|
|
||||||
} while (self->is_resizing);
|
|
||||||
|
|
||||||
git__free(old_nodes);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int set_size(git_hashtable *self, size_t new_size)
|
|
||||||
{
|
|
||||||
self->nodes =
|
|
||||||
git__realloc(self->nodes, new_size * sizeof(git_hashtable_node));
|
|
||||||
GITERR_CHECK_ALLOC(self->nodes);
|
|
||||||
|
|
||||||
if (new_size > self->size)
|
|
||||||
memset(&self->nodes[self->size], 0x0,
|
|
||||||
(new_size - self->size) * sizeof(git_hashtable_node));
|
|
||||||
|
|
||||||
self->size = new_size;
|
|
||||||
self->size_mask = new_size - 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
GIT_INLINE(git_hashtable_node *)node_with_hash(
|
|
||||||
git_hashtable *self, const void *key, int hash_id)
|
|
||||||
{
|
|
||||||
size_t pos = self->hash(key, hash_id) & self->size_mask;
|
|
||||||
return git_hashtable_node_at(self->nodes, pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
GIT_INLINE(void) node_swap_with(
|
|
||||||
git_hashtable_node *self, git_hashtable_node *other)
|
|
||||||
{
|
|
||||||
git_hashtable_node tmp = *self;
|
|
||||||
*self = *other;
|
|
||||||
*other = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int node_insert(git_hashtable *self, git_hashtable_node *new_node)
|
|
||||||
{
|
|
||||||
int iteration, hash_id;
|
|
||||||
git_hashtable_node *node;
|
|
||||||
|
|
||||||
for (iteration = 0; iteration < MAX_LOOPS; iteration++) {
|
|
||||||
for (hash_id = 0; hash_id < GIT_HASHTABLE_HASHES; ++hash_id) {
|
|
||||||
node = node_with_hash(self, new_node->key, hash_id);
|
|
||||||
node_swap_with(new_node, node);
|
|
||||||
if (new_node->key == 0x0) {
|
|
||||||
self->key_count++;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Insert into stash if there is space */
|
|
||||||
if (self->stash_count < GIT_HASHTABLE_STASH_SIZE) {
|
|
||||||
node_swap_with(new_node, &self->stash[self->stash_count++]);
|
|
||||||
self->key_count++;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Failed to insert node. Hashtable is currently resizing */
|
|
||||||
assert(!self->is_resizing);
|
|
||||||
|
|
||||||
if (resize_to(self, self->size * 2) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return git_hashtable_insert(self, new_node->key, new_node->value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int insert_nodes(
|
|
||||||
git_hashtable *self, git_hashtable_node *old_nodes, size_t old_size)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
for (i = 0; i < old_size; ++i) {
|
|
||||||
git_hashtable_node *node = git_hashtable_node_at(old_nodes, i);
|
|
||||||
if (node->key && node_insert(self, node) < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void reinsert_stash(git_hashtable *self)
|
|
||||||
{
|
|
||||||
int stash_count;
|
|
||||||
struct git_hashtable_node stash[GIT_HASHTABLE_STASH_SIZE];
|
|
||||||
|
|
||||||
if (self->stash_count <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
memcpy(stash, self->stash, self->stash_count * sizeof(git_hashtable_node));
|
|
||||||
stash_count = self->stash_count;
|
|
||||||
self->stash_count = 0;
|
|
||||||
|
|
||||||
/* the node_insert() calls *cannot* fail because the stash is empty */
|
|
||||||
insert_nodes(self, stash, stash_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
git_hashtable *git_hashtable_alloc(
|
|
||||||
size_t min_size,
|
|
||||||
git_hash_ptr hash,
|
|
||||||
git_hash_keyeq_ptr key_eq)
|
|
||||||
{
|
|
||||||
git_hashtable *table;
|
|
||||||
|
|
||||||
assert(hash && key_eq);
|
|
||||||
|
|
||||||
if ((table = git__malloc(sizeof(*table))) == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
memset(table, 0x0, sizeof(git_hashtable));
|
|
||||||
|
|
||||||
table->hash = hash;
|
|
||||||
table->key_equal = key_eq;
|
|
||||||
|
|
||||||
min_size = git__size_t_powerof2(min_size < 8 ? 8 : min_size);
|
|
||||||
set_size(table, min_size);
|
|
||||||
|
|
||||||
return table;
|
|
||||||
}
|
|
||||||
|
|
||||||
void git_hashtable_clear(git_hashtable *self)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
|
|
||||||
memset(self->nodes, 0x0, sizeof(git_hashtable_node) * self->size);
|
|
||||||
|
|
||||||
self->stash_count = 0;
|
|
||||||
self->key_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void git_hashtable_free(git_hashtable *self)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
|
|
||||||
git__free(self->nodes);
|
|
||||||
git__free(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int git_hashtable_insert2(
|
|
||||||
git_hashtable *self, const void *key, void *value, void **old_value)
|
|
||||||
{
|
|
||||||
int hash_id;
|
|
||||||
git_hashtable_node *node;
|
|
||||||
|
|
||||||
assert(self && self->nodes);
|
|
||||||
|
|
||||||
*old_value = NULL;
|
|
||||||
|
|
||||||
for (hash_id = 0; hash_id < GIT_HASHTABLE_HASHES; ++hash_id) {
|
|
||||||
node = node_with_hash(self, key, hash_id);
|
|
||||||
|
|
||||||
if (!node->key) {
|
|
||||||
node->key = key;
|
|
||||||
node->value = value;
|
|
||||||
self->key_count++;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == node->key || self->key_equal(key, node->key) == 0) {
|
|
||||||
*old_value = node->value;
|
|
||||||
node->key = key;
|
|
||||||
node->value = value;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* no space in table; must do cuckoo dance */
|
|
||||||
{
|
|
||||||
git_hashtable_node x;
|
|
||||||
x.key = key;
|
|
||||||
x.value = value;
|
|
||||||
return node_insert(self, &x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static git_hashtable_node *find_node(git_hashtable *self, const void *key)
|
|
||||||
{
|
|
||||||
int hash_id, count = 0;
|
|
||||||
git_hashtable_node *node;
|
|
||||||
|
|
||||||
for (hash_id = 0; hash_id < GIT_HASHTABLE_HASHES; ++hash_id) {
|
|
||||||
node = node_with_hash(self, key, hash_id);
|
|
||||||
if (node->key) {
|
|
||||||
++count;
|
|
||||||
if (self->key_equal(key, node->key) == 0)
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check stash if not found but all slots were filled */
|
|
||||||
if (count == GIT_HASHTABLE_HASHES) {
|
|
||||||
for (count = 0; count < self->stash_count; ++count)
|
|
||||||
if (self->key_equal(key, self->stash[count].key) == 0)
|
|
||||||
return &self->stash[count];
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void reset_stash(git_hashtable *self, git_hashtable_node *node)
|
|
||||||
{
|
|
||||||
/* if node was in stash, then compact stash */
|
|
||||||
ssize_t offset = node - self->stash;
|
|
||||||
|
|
||||||
if (offset >= 0 && offset < self->stash_count) {
|
|
||||||
if (offset < self->stash_count - 1)
|
|
||||||
memmove(node, node + 1, (self->stash_count - offset) *
|
|
||||||
sizeof(git_hashtable_node));
|
|
||||||
self->stash_count--;
|
|
||||||
}
|
|
||||||
|
|
||||||
reinsert_stash(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *git_hashtable_lookup(git_hashtable *self, const void *key)
|
|
||||||
{
|
|
||||||
git_hashtable_node *node;
|
|
||||||
assert(self && key);
|
|
||||||
node = find_node(self, key);
|
|
||||||
return node ? node->value : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int git_hashtable_remove2(
|
|
||||||
git_hashtable *self, const void *key, void **old_value)
|
|
||||||
{
|
|
||||||
git_hashtable_node *node;
|
|
||||||
|
|
||||||
assert(self && self->nodes);
|
|
||||||
|
|
||||||
node = find_node(self, key);
|
|
||||||
if (node) {
|
|
||||||
*old_value = node->value;
|
|
||||||
|
|
||||||
node->key = NULL;
|
|
||||||
node->value = NULL;
|
|
||||||
self->key_count--;
|
|
||||||
|
|
||||||
reset_stash(self, node);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GIT_ENOTFOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
int git_hashtable_merge(git_hashtable *self, git_hashtable *other)
|
|
||||||
{
|
|
||||||
size_t new_size = git__size_t_powerof2(self->size + other->size);
|
|
||||||
|
|
||||||
if (resize_to(self, new_size) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (insert_nodes(self, other->nodes, other->key_count) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return insert_nodes(self, other->stash, other->stash_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Standard string
|
|
||||||
*/
|
|
||||||
uint32_t git_hash__strhash_cb(const void *key, int hash_id)
|
|
||||||
{
|
|
||||||
static uint32_t hash_seeds[GIT_HASHTABLE_HASHES] = {
|
|
||||||
2147483647,
|
|
||||||
0x5d20bb23,
|
|
||||||
0x7daaab3c
|
|
||||||
};
|
|
||||||
|
|
||||||
size_t key_len = strlen((const char *)key);
|
|
||||||
|
|
||||||
/* won't take hash of strings longer than 2^31 right now */
|
|
||||||
assert(key_len == (size_t)((int)key_len));
|
|
||||||
|
|
||||||
return git__hash(key, (int)key_len, hash_seeds[hash_id]);
|
|
||||||
}
|
|
102
src/hashtable.h
102
src/hashtable.h
@ -1,102 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2009-2012 the libgit2 contributors
|
|
||||||
*
|
|
||||||
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
|
||||||
* a Linking Exception. For full terms see the included COPYING file.
|
|
||||||
*/
|
|
||||||
#ifndef INCLUDE_hashtable_h__
|
|
||||||
#define INCLUDE_hashtable_h__
|
|
||||||
|
|
||||||
#include "git2/common.h"
|
|
||||||
#include "git2/oid.h"
|
|
||||||
#include "git2/odb.h"
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
#define GIT_HASHTABLE_HASHES 3
|
|
||||||
|
|
||||||
typedef uint32_t (*git_hash_ptr)(const void *, int hash_id);
|
|
||||||
typedef int (*git_hash_keyeq_ptr)(const void *key_a, const void *key_b);
|
|
||||||
|
|
||||||
struct git_hashtable_node {
|
|
||||||
const void *key;
|
|
||||||
void *value;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define GIT_HASHTABLE_STASH_SIZE 3
|
|
||||||
|
|
||||||
struct git_hashtable {
|
|
||||||
struct git_hashtable_node *nodes;
|
|
||||||
|
|
||||||
size_t size_mask;
|
|
||||||
size_t size;
|
|
||||||
size_t key_count;
|
|
||||||
|
|
||||||
struct git_hashtable_node stash[GIT_HASHTABLE_STASH_SIZE];
|
|
||||||
int stash_count;
|
|
||||||
|
|
||||||
int is_resizing;
|
|
||||||
|
|
||||||
git_hash_ptr hash;
|
|
||||||
git_hash_keyeq_ptr key_equal;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct git_hashtable_node git_hashtable_node;
|
|
||||||
typedef struct git_hashtable git_hashtable;
|
|
||||||
|
|
||||||
git_hashtable *git_hashtable_alloc(
|
|
||||||
size_t min_size,
|
|
||||||
git_hash_ptr hash,
|
|
||||||
git_hash_keyeq_ptr key_eq);
|
|
||||||
|
|
||||||
void *git_hashtable_lookup(git_hashtable *h, const void *key);
|
|
||||||
int git_hashtable_remove2(git_hashtable *table, const void *key, void **old_value);
|
|
||||||
|
|
||||||
GIT_INLINE(int) git_hashtable_remove(git_hashtable *table, const void *key)
|
|
||||||
{
|
|
||||||
void *_unused;
|
|
||||||
return git_hashtable_remove2(table, key, &_unused);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void git_hashtable_free(git_hashtable *h);
|
|
||||||
void git_hashtable_clear(git_hashtable *h);
|
|
||||||
int git_hashtable_merge(git_hashtable *self, git_hashtable *other);
|
|
||||||
|
|
||||||
int git_hashtable_insert2(git_hashtable *h, const void *key, void *value, void **old_value);
|
|
||||||
|
|
||||||
GIT_INLINE(int) git_hashtable_insert(git_hashtable *h, const void *key, void *value)
|
|
||||||
{
|
|
||||||
void *_unused;
|
|
||||||
return git_hashtable_insert2(h, key, value, &_unused);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define git_hashtable_node_at(nodes, pos) ((git_hashtable_node *)(&nodes[pos]))
|
|
||||||
|
|
||||||
#define GIT_HASHTABLE__FOREACH(self,block) { \
|
|
||||||
size_t _c; \
|
|
||||||
git_hashtable_node *_n = (self)->nodes; \
|
|
||||||
for (_c = (self)->size; _c > 0; _c--, _n++) { \
|
|
||||||
if (!_n->key) continue; block } }
|
|
||||||
|
|
||||||
#define GIT_HASHTABLE_FOREACH(self, pkey, pvalue, code)\
|
|
||||||
GIT_HASHTABLE__FOREACH(self,{(pkey)=_n->key;(pvalue)=_n->value;code;})
|
|
||||||
|
|
||||||
#define GIT_HASHTABLE_FOREACH_KEY(self, pkey, code)\
|
|
||||||
GIT_HASHTABLE__FOREACH(self,{(pkey)=_n->key;code;})
|
|
||||||
|
|
||||||
#define GIT_HASHTABLE_FOREACH_VALUE(self, pvalue, code)\
|
|
||||||
GIT_HASHTABLE__FOREACH(self,{(pvalue)=_n->value;code;})
|
|
||||||
|
|
||||||
#define GIT_HASHTABLE_FOREACH_DELETE() {\
|
|
||||||
_node->key = NULL; _node->value = NULL; _self->key_count--;\
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If you want a hashtable with standard string keys, you can
|
|
||||||
* just pass git_hash__strcmp_cb and git_hash__strhash_cb to
|
|
||||||
* git_hashtable_alloc.
|
|
||||||
*/
|
|
||||||
#define git_hash__strcmp_cb git__strcmp_cb
|
|
||||||
extern uint32_t git_hash__strhash_cb(const void *key, int hash_id);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2012 the libgit2 contributors
|
|
||||||
*
|
|
||||||
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
|
||||||
* a Linking Exception. For full terms see the included COPYING file.
|
|
||||||
*/
|
|
||||||
#ifndef INCLUDE_khash_str_h__
|
|
||||||
#define INCLUDE_khash_str_h__
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
#define kmalloc git__malloc
|
|
||||||
#define kcalloc git__calloc
|
|
||||||
#define krealloc git__realloc
|
|
||||||
#define kfree git__free
|
|
||||||
#include "khash.h"
|
|
||||||
|
|
||||||
__KHASH_TYPE(str, const char *, void *);
|
|
||||||
typedef khash_t(str) git_khash_str;
|
|
||||||
|
|
||||||
#define GIT_KHASH_STR__IMPLEMENTATION \
|
|
||||||
__KHASH_IMPL(str, static inline, const char *, void *, 1, kh_str_hash_func, kh_str_hash_equal)
|
|
||||||
|
|
||||||
#define git_khash_str_alloc() kh_init(str)
|
|
||||||
#define git_khash_str_free(h) kh_destroy(str, h), h = NULL
|
|
||||||
#define git_khash_str_clear(h) kh_clear(str, h)
|
|
||||||
|
|
||||||
#define git_khash_str_num_entries(h) kh_size(h)
|
|
||||||
|
|
||||||
#define git_khash_str_lookup_index(h, k) kh_get(str, h, k)
|
|
||||||
#define git_khash_str_valid_index(h, idx) (idx != kh_end(h))
|
|
||||||
|
|
||||||
#define git_khash_str_exists(h, k) (kh_get(str, h, k) != kh_end(h))
|
|
||||||
|
|
||||||
#define git_khash_str_value_at(h, idx) kh_val(h, idx)
|
|
||||||
#define git_khash_str_set_value_at(h, idx, v) kh_val(h, idx) = v
|
|
||||||
#define git_khash_str_delete_at(h, idx) kh_del(str, h, idx)
|
|
||||||
|
|
||||||
#define git_khash_str_insert(h, key, val, err) do { \
|
|
||||||
khiter_t __pos = kh_put(str, h, key, &err); \
|
|
||||||
if (err >= 0) kh_val(h, __pos) = val; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define git_khash_str_insert2(h, key, val, old, err) do { \
|
|
||||||
khiter_t __pos = kh_put(str, h, key, &err); \
|
|
||||||
if (err >= 0) { \
|
|
||||||
old = (err == 0) ? kh_val(h, __pos) : NULL; \
|
|
||||||
kh_val(h, __pos) = val; \
|
|
||||||
} } while (0)
|
|
||||||
|
|
||||||
#define git_khash_str_foreach kh_foreach
|
|
||||||
#define git_khash_str_foreach_value kh_foreach_value
|
|
||||||
|
|
||||||
#endif
|
|
@ -4,8 +4,8 @@
|
|||||||
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||||
* a Linking Exception. For full terms see the included COPYING file.
|
* a Linking Exception. For full terms see the included COPYING file.
|
||||||
*/
|
*/
|
||||||
#ifndef INCLUDE_khash_oid_h__
|
#ifndef INCLUDE_oidmap_h__
|
||||||
#define INCLUDE_khash_oid_h__
|
#define INCLUDE_oidmap_h__
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "git2/oid.h"
|
#include "git2/oid.h"
|
||||||
@ -17,7 +17,7 @@
|
|||||||
#include "khash.h"
|
#include "khash.h"
|
||||||
|
|
||||||
__KHASH_TYPE(oid, const git_oid *, void *);
|
__KHASH_TYPE(oid, const git_oid *, void *);
|
||||||
typedef khash_t(oid) git_khash_oid;
|
typedef khash_t(oid) git_oidmap;
|
||||||
|
|
||||||
GIT_INLINE(khint_t) hash_git_oid(const git_oid *oid)
|
GIT_INLINE(khint_t) hash_git_oid(const git_oid *oid)
|
||||||
{
|
{
|
||||||
@ -33,10 +33,10 @@ GIT_INLINE(int) hash_git_oid_equal(const git_oid *a, const git_oid *b)
|
|||||||
return (memcmp(a->id, b->id, sizeof(a->id)) == 0);
|
return (memcmp(a->id, b->id, sizeof(a->id)) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define GIT_KHASH_OID__IMPLEMENTATION \
|
#define GIT__USE_OIDMAP \
|
||||||
__KHASH_IMPL(oid, static inline, const git_oid *, void *, 1, hash_git_oid, hash_git_oid_equal)
|
__KHASH_IMPL(oid, static inline, const git_oid *, void *, 1, hash_git_oid, hash_git_oid_equal)
|
||||||
|
|
||||||
#define git_khash_oid_alloc() kh_init(oid)
|
#define git_oidmap_alloc() kh_init(oid)
|
||||||
#define git_khash_oid_free(h) kh_destroy(oid,h), h = NULL
|
#define git_oidmap_free(h) kh_destroy(oid,h), h = NULL
|
||||||
|
|
||||||
#endif
|
#endif
|
46
src/refs.c
46
src/refs.c
@ -15,7 +15,7 @@
|
|||||||
#include <git2/tag.h>
|
#include <git2/tag.h>
|
||||||
#include <git2/object.h>
|
#include <git2/object.h>
|
||||||
|
|
||||||
GIT_KHASH_STR__IMPLEMENTATION;
|
GIT__USE_STRMAP;
|
||||||
|
|
||||||
#define DEFAULT_NESTING_LEVEL 5
|
#define DEFAULT_NESTING_LEVEL 5
|
||||||
#define MAX_NESTING_LEVEL 10
|
#define MAX_NESTING_LEVEL 10
|
||||||
@ -423,7 +423,7 @@ static int packed_load(git_repository *repo)
|
|||||||
|
|
||||||
/* First we make sure we have allocated the hash table */
|
/* First we make sure we have allocated the hash table */
|
||||||
if (ref_cache->packfile == NULL) {
|
if (ref_cache->packfile == NULL) {
|
||||||
ref_cache->packfile = git_khash_str_alloc();
|
ref_cache->packfile = git_strmap_alloc();
|
||||||
GITERR_CHECK_ALLOC(ref_cache->packfile);
|
GITERR_CHECK_ALLOC(ref_cache->packfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -438,7 +438,7 @@ static int packed_load(git_repository *repo)
|
|||||||
* refresh the packed refs.
|
* refresh the packed refs.
|
||||||
*/
|
*/
|
||||||
if (result == GIT_ENOTFOUND) {
|
if (result == GIT_ENOTFOUND) {
|
||||||
git_khash_str_clear(ref_cache->packfile);
|
git_strmap_clear(ref_cache->packfile);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -452,7 +452,7 @@ static int packed_load(git_repository *repo)
|
|||||||
* At this point, we want to refresh the packed refs. We already
|
* At this point, we want to refresh the packed refs. We already
|
||||||
* have the contents in our buffer.
|
* have the contents in our buffer.
|
||||||
*/
|
*/
|
||||||
git_khash_str_clear(ref_cache->packfile);
|
git_strmap_clear(ref_cache->packfile);
|
||||||
|
|
||||||
buffer_start = (const char *)packfile.ptr;
|
buffer_start = (const char *)packfile.ptr;
|
||||||
buffer_end = (const char *)(buffer_start) + packfile.size;
|
buffer_end = (const char *)(buffer_start) + packfile.size;
|
||||||
@ -477,7 +477,7 @@ static int packed_load(git_repository *repo)
|
|||||||
goto parse_failed;
|
goto parse_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
git_khash_str_insert(ref_cache->packfile, ref->name, ref, err);
|
git_strmap_insert(ref_cache->packfile, ref->name, ref, err);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto parse_failed;
|
goto parse_failed;
|
||||||
}
|
}
|
||||||
@ -486,7 +486,7 @@ static int packed_load(git_repository *repo)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
parse_failed:
|
parse_failed:
|
||||||
git_khash_str_free(ref_cache->packfile);
|
git_strmap_free(ref_cache->packfile);
|
||||||
ref_cache->packfile = NULL;
|
ref_cache->packfile = NULL;
|
||||||
git_buf_free(&packfile);
|
git_buf_free(&packfile);
|
||||||
return -1;
|
return -1;
|
||||||
@ -512,7 +512,7 @@ static int _dirent_loose_listall(void *_data, git_buf *full_path)
|
|||||||
|
|
||||||
/* do not add twice a reference that exists already in the packfile */
|
/* do not add twice a reference that exists already in the packfile */
|
||||||
if ((data->list_flags & GIT_REF_PACKED) != 0 &&
|
if ((data->list_flags & GIT_REF_PACKED) != 0 &&
|
||||||
git_khash_str_exists(data->repo->references.packfile, file_path))
|
git_strmap_exists(data->repo->references.packfile, file_path))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (data->list_flags != GIT_REF_LISTALL) {
|
if (data->list_flags != GIT_REF_LISTALL) {
|
||||||
@ -539,7 +539,7 @@ static int _dirent_loose_load(void *data, git_buf *full_path)
|
|||||||
if (loose_lookup_to_packfile(&ref, repository, file_path) < 0)
|
if (loose_lookup_to_packfile(&ref, repository, file_path) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
git_khash_str_insert2(
|
git_strmap_insert2(
|
||||||
repository->references.packfile, ref->name, ref, old_ref, err);
|
repository->references.packfile, ref->name, ref, old_ref, err);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
git__free(ref);
|
git__free(ref);
|
||||||
@ -737,7 +737,7 @@ static int packed_write(git_repository *repo)
|
|||||||
assert(repo && repo->references.packfile);
|
assert(repo && repo->references.packfile);
|
||||||
|
|
||||||
total_refs =
|
total_refs =
|
||||||
(unsigned int)git_khash_str_num_entries(repo->references.packfile);
|
(unsigned int)git_strmap_num_entries(repo->references.packfile);
|
||||||
|
|
||||||
if (git_vector_init(&packing_list, total_refs, packed_sort) < 0)
|
if (git_vector_init(&packing_list, total_refs, packed_sort) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
@ -747,7 +747,7 @@ static int packed_write(git_repository *repo)
|
|||||||
struct packref *reference;
|
struct packref *reference;
|
||||||
|
|
||||||
/* cannot fail: vector already has the right size */
|
/* cannot fail: vector already has the right size */
|
||||||
git_khash_str_foreach_value(repo->references.packfile, reference, {
|
git_strmap_foreach_value(repo->references.packfile, reference, {
|
||||||
git_vector_insert(&packing_list, reference);
|
git_vector_insert(&packing_list, reference);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -873,7 +873,7 @@ static int reference_exists(int *exists, git_repository *repo, const char *ref_n
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (git_path_isfile(ref_path.ptr) == true ||
|
if (git_path_isfile(ref_path.ptr) == true ||
|
||||||
git_khash_str_exists(repo->references.packfile, ref_path.ptr))
|
git_strmap_exists(repo->references.packfile, ref_path.ptr))
|
||||||
{
|
{
|
||||||
*exists = 1;
|
*exists = 1;
|
||||||
} else {
|
} else {
|
||||||
@ -940,7 +940,7 @@ static int reference_can_write(
|
|||||||
static int packed_lookup(git_reference *ref)
|
static int packed_lookup(git_reference *ref)
|
||||||
{
|
{
|
||||||
struct packref *pack_ref = NULL;
|
struct packref *pack_ref = NULL;
|
||||||
git_khash_str *packfile_refs;
|
git_strmap *packfile_refs;
|
||||||
khiter_t pos;
|
khiter_t pos;
|
||||||
|
|
||||||
if (packed_load(ref->owner) < 0)
|
if (packed_load(ref->owner) < 0)
|
||||||
@ -959,13 +959,13 @@ static int packed_lookup(git_reference *ref)
|
|||||||
|
|
||||||
/* Look up on the packfile */
|
/* Look up on the packfile */
|
||||||
packfile_refs = ref->owner->references.packfile;
|
packfile_refs = ref->owner->references.packfile;
|
||||||
pos = git_khash_str_lookup_index(packfile_refs, ref->name);
|
pos = git_strmap_lookup_index(packfile_refs, ref->name);
|
||||||
if (!git_khash_str_valid_index(packfile_refs, pos)) {
|
if (!git_strmap_valid_index(packfile_refs, pos)) {
|
||||||
giterr_set(GITERR_REFERENCE, "Reference '%s' not found", ref->name);
|
giterr_set(GITERR_REFERENCE, "Reference '%s' not found", ref->name);
|
||||||
return GIT_ENOTFOUND;
|
return GIT_ENOTFOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
pack_ref = git_khash_str_value_at(packfile_refs, pos);
|
pack_ref = git_strmap_value_at(packfile_refs, pos);
|
||||||
|
|
||||||
ref->flags = GIT_REF_OID | GIT_REF_PACKED;
|
ref->flags = GIT_REF_OID | GIT_REF_PACKED;
|
||||||
ref->mtime = ref->owner->references.packfile_time;
|
ref->mtime = ref->owner->references.packfile_time;
|
||||||
@ -1011,7 +1011,7 @@ static int reference_delete(git_reference *ref)
|
|||||||
* We need to reload the packfile, remove the reference from the
|
* We need to reload the packfile, remove the reference from the
|
||||||
* packing list, and repack */
|
* packing list, and repack */
|
||||||
if (ref->flags & GIT_REF_PACKED) {
|
if (ref->flags & GIT_REF_PACKED) {
|
||||||
git_khash_str *packfile_refs;
|
git_strmap *packfile_refs;
|
||||||
struct packref *packref;
|
struct packref *packref;
|
||||||
khiter_t pos;
|
khiter_t pos;
|
||||||
|
|
||||||
@ -1020,15 +1020,15 @@ static int reference_delete(git_reference *ref)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
packfile_refs = ref->owner->references.packfile;
|
packfile_refs = ref->owner->references.packfile;
|
||||||
pos = git_khash_str_lookup_index(packfile_refs, ref->name);
|
pos = git_strmap_lookup_index(packfile_refs, ref->name);
|
||||||
if (!git_khash_str_valid_index(packfile_refs, pos)) {
|
if (!git_strmap_valid_index(packfile_refs, pos)) {
|
||||||
giterr_set(GITERR_REFERENCE,
|
giterr_set(GITERR_REFERENCE,
|
||||||
"Reference %s stopped existing in the packfile", ref->name);
|
"Reference %s stopped existing in the packfile", ref->name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
packref = git_khash_str_value_at(packfile_refs, pos);
|
packref = git_strmap_value_at(packfile_refs, pos);
|
||||||
git_khash_str_delete_at(packfile_refs, pos);
|
git_strmap_delete_at(packfile_refs, pos);
|
||||||
|
|
||||||
git__free(packref);
|
git__free(packref);
|
||||||
if (packed_write(ref->owner) < 0)
|
if (packed_write(ref->owner) < 0)
|
||||||
@ -1488,7 +1488,7 @@ int git_reference_foreach(
|
|||||||
if (packed_load(repo) < 0)
|
if (packed_load(repo) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
git_khash_str_foreach(repo->references.packfile, ref_name, ref, {
|
git_strmap_foreach(repo->references.packfile, ref_name, ref, {
|
||||||
if (callback(ref_name, payload) < 0)
|
if (callback(ref_name, payload) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
@ -1555,11 +1555,11 @@ void git_repository__refcache_free(git_refcache *refs)
|
|||||||
if (refs->packfile) {
|
if (refs->packfile) {
|
||||||
struct packref *reference;
|
struct packref *reference;
|
||||||
|
|
||||||
git_khash_str_foreach_value(refs->packfile, reference, {
|
git_strmap_foreach_value(refs->packfile, reference, {
|
||||||
git__free(reference);
|
git__free(reference);
|
||||||
});
|
});
|
||||||
|
|
||||||
git_khash_str_free(refs->packfile);
|
git_strmap_free(refs->packfile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "git2/oid.h"
|
#include "git2/oid.h"
|
||||||
#include "git2/refs.h"
|
#include "git2/refs.h"
|
||||||
#include "khash_str.h"
|
#include "strmap.h"
|
||||||
|
|
||||||
#define GIT_REFS_DIR "refs/"
|
#define GIT_REFS_DIR "refs/"
|
||||||
#define GIT_REFS_HEADS_DIR GIT_REFS_DIR "heads/"
|
#define GIT_REFS_HEADS_DIR GIT_REFS_DIR "heads/"
|
||||||
@ -46,7 +46,7 @@ struct git_reference {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
git_khash_str *packfile;
|
git_strmap *packfile;
|
||||||
time_t packfile_time;
|
time_t packfile_time;
|
||||||
} git_refcache;
|
} git_refcache;
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "odb.h"
|
#include "odb.h"
|
||||||
#include "attr.h"
|
#include "attr.h"
|
||||||
#include "khash_str.h"
|
#include "strmap.h"
|
||||||
|
|
||||||
#define DOT_GIT ".git"
|
#define DOT_GIT ".git"
|
||||||
#define GIT_DIR DOT_GIT "/"
|
#define GIT_DIR DOT_GIT "/"
|
||||||
@ -83,7 +83,7 @@ struct git_repository {
|
|||||||
git_cache objects;
|
git_cache objects;
|
||||||
git_refcache references;
|
git_refcache references;
|
||||||
git_attr_cache attrcache;
|
git_attr_cache attrcache;
|
||||||
git_khash_str *submodules;
|
git_strmap *submodules;
|
||||||
|
|
||||||
char *path_repository;
|
char *path_repository;
|
||||||
char *workdir;
|
char *workdir;
|
||||||
|
@ -10,14 +10,14 @@
|
|||||||
#include "odb.h"
|
#include "odb.h"
|
||||||
#include "pqueue.h"
|
#include "pqueue.h"
|
||||||
#include "pool.h"
|
#include "pool.h"
|
||||||
#include "khash_oid.h"
|
#include "oidmap.h"
|
||||||
|
|
||||||
#include "git2/revwalk.h"
|
#include "git2/revwalk.h"
|
||||||
#include "git2/merge.h"
|
#include "git2/merge.h"
|
||||||
|
|
||||||
#include <regex.h>
|
#include <regex.h>
|
||||||
|
|
||||||
GIT_KHASH_OID__IMPLEMENTATION;
|
GIT__USE_OIDMAP;
|
||||||
|
|
||||||
#define PARENT1 (1 << 0)
|
#define PARENT1 (1 << 0)
|
||||||
#define PARENT2 (1 << 1)
|
#define PARENT2 (1 << 1)
|
||||||
@ -48,7 +48,7 @@ struct git_revwalk {
|
|||||||
git_repository *repo;
|
git_repository *repo;
|
||||||
git_odb *odb;
|
git_odb *odb;
|
||||||
|
|
||||||
git_khash_oid *commits;
|
git_oidmap *commits;
|
||||||
git_pool commit_pool;
|
git_pool commit_pool;
|
||||||
|
|
||||||
commit_list *iterator_topo;
|
commit_list *iterator_topo;
|
||||||
@ -726,7 +726,7 @@ int git_revwalk_new(git_revwalk **revwalk_out, git_repository *repo)
|
|||||||
|
|
||||||
memset(walk, 0x0, sizeof(git_revwalk));
|
memset(walk, 0x0, sizeof(git_revwalk));
|
||||||
|
|
||||||
walk->commits = git_khash_oid_alloc();
|
walk->commits = git_oidmap_alloc();
|
||||||
GITERR_CHECK_ALLOC(walk->commits);
|
GITERR_CHECK_ALLOC(walk->commits);
|
||||||
|
|
||||||
if (git_pqueue_init(&walk->iterator_time, 8, commit_time_cmp) < 0 ||
|
if (git_pqueue_init(&walk->iterator_time, 8, commit_time_cmp) < 0 ||
|
||||||
@ -757,7 +757,7 @@ void git_revwalk_free(git_revwalk *walk)
|
|||||||
git_revwalk_reset(walk);
|
git_revwalk_reset(walk);
|
||||||
git_odb_free(walk->odb);
|
git_odb_free(walk->odb);
|
||||||
|
|
||||||
git_khash_oid_free(walk->commits);
|
git_oidmap_free(walk->commits);
|
||||||
git_pool_clear(&walk->commit_pool);
|
git_pool_clear(&walk->commit_pool);
|
||||||
git_pqueue_free(&walk->iterator_time);
|
git_pqueue_free(&walk->iterator_time);
|
||||||
git_vector_free(&walk->twos);
|
git_vector_free(&walk->twos);
|
||||||
|
54
src/strmap.h
Normal file
54
src/strmap.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2012 the libgit2 contributors
|
||||||
|
*
|
||||||
|
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||||
|
* a Linking Exception. For full terms see the included COPYING file.
|
||||||
|
*/
|
||||||
|
#ifndef INCLUDE_strmap_h__
|
||||||
|
#define INCLUDE_strmap_h__
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#define kmalloc git__malloc
|
||||||
|
#define kcalloc git__calloc
|
||||||
|
#define krealloc git__realloc
|
||||||
|
#define kfree git__free
|
||||||
|
#include "khash.h"
|
||||||
|
|
||||||
|
__KHASH_TYPE(str, const char *, void *);
|
||||||
|
typedef khash_t(str) git_strmap;
|
||||||
|
|
||||||
|
#define GIT__USE_STRMAP \
|
||||||
|
__KHASH_IMPL(str, static inline, const char *, void *, 1, kh_str_hash_func, kh_str_hash_equal)
|
||||||
|
|
||||||
|
#define git_strmap_alloc() kh_init(str)
|
||||||
|
#define git_strmap_free(h) kh_destroy(str, h), h = NULL
|
||||||
|
#define git_strmap_clear(h) kh_clear(str, h)
|
||||||
|
|
||||||
|
#define git_strmap_num_entries(h) kh_size(h)
|
||||||
|
|
||||||
|
#define git_strmap_lookup_index(h, k) kh_get(str, h, k)
|
||||||
|
#define git_strmap_valid_index(h, idx) (idx != kh_end(h))
|
||||||
|
|
||||||
|
#define git_strmap_exists(h, k) (kh_get(str, h, k) != kh_end(h))
|
||||||
|
|
||||||
|
#define git_strmap_value_at(h, idx) kh_val(h, idx)
|
||||||
|
#define git_strmap_set_value_at(h, idx, v) kh_val(h, idx) = v
|
||||||
|
#define git_strmap_delete_at(h, idx) kh_del(str, h, idx)
|
||||||
|
|
||||||
|
#define git_strmap_insert(h, key, val, err) do { \
|
||||||
|
khiter_t __pos = kh_put(str, h, key, &err); \
|
||||||
|
if (err >= 0) kh_val(h, __pos) = val; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define git_strmap_insert2(h, key, val, old, err) do { \
|
||||||
|
khiter_t __pos = kh_put(str, h, key, &err); \
|
||||||
|
if (err >= 0) { \
|
||||||
|
old = (err == 0) ? kh_val(h, __pos) : NULL; \
|
||||||
|
kh_val(h, __pos) = val; \
|
||||||
|
} } while (0)
|
||||||
|
|
||||||
|
#define git_strmap_foreach kh_foreach
|
||||||
|
#define git_strmap_foreach_value kh_foreach_value
|
||||||
|
|
||||||
|
#endif
|
@ -89,17 +89,17 @@ static void submodule_release(git_submodule *sm, int decr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int submodule_from_entry(
|
static int submodule_from_entry(
|
||||||
git_khash_str *smcfg, git_index_entry *entry)
|
git_strmap *smcfg, git_index_entry *entry)
|
||||||
{
|
{
|
||||||
git_submodule *sm;
|
git_submodule *sm;
|
||||||
void *old_sm;
|
void *old_sm;
|
||||||
khiter_t pos;
|
khiter_t pos;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
pos = git_khash_str_lookup_index(smcfg, entry->path);
|
pos = git_strmap_lookup_index(smcfg, entry->path);
|
||||||
|
|
||||||
if (git_khash_str_valid_index(smcfg, pos))
|
if (git_strmap_valid_index(smcfg, pos))
|
||||||
sm = git_khash_str_value_at(smcfg, pos);
|
sm = git_strmap_value_at(smcfg, pos);
|
||||||
else
|
else
|
||||||
sm = submodule_alloc(entry->path);
|
sm = submodule_alloc(entry->path);
|
||||||
|
|
||||||
@ -115,7 +115,7 @@ static int submodule_from_entry(
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
git_khash_str_insert2(smcfg, sm->path, sm, old_sm, error);
|
git_strmap_insert2(smcfg, sm->path, sm, old_sm, error);
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
sm->refcount++;
|
sm->refcount++;
|
||||||
@ -135,7 +135,7 @@ fail:
|
|||||||
static int submodule_from_config(
|
static int submodule_from_config(
|
||||||
const char *key, const char *value, void *data)
|
const char *key, const char *value, void *data)
|
||||||
{
|
{
|
||||||
git_khash_str *smcfg = data;
|
git_strmap *smcfg = data;
|
||||||
const char *namestart;
|
const char *namestart;
|
||||||
const char *property;
|
const char *property;
|
||||||
git_buf name = GIT_BUF_INIT;
|
git_buf name = GIT_BUF_INIT;
|
||||||
@ -158,13 +158,13 @@ static int submodule_from_config(
|
|||||||
if (git_buf_set(&name, namestart, property - namestart - 1) < 0)
|
if (git_buf_set(&name, namestart, property - namestart - 1) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
pos = git_khash_str_lookup_index(smcfg, name.ptr);
|
pos = git_strmap_lookup_index(smcfg, name.ptr);
|
||||||
if (!git_khash_str_valid_index(smcfg, pos) && is_path)
|
if (!git_strmap_valid_index(smcfg, pos) && is_path)
|
||||||
pos = git_khash_str_lookup_index(smcfg, value);
|
pos = git_strmap_lookup_index(smcfg, value);
|
||||||
if (!git_khash_str_valid_index(smcfg, pos))
|
if (!git_strmap_valid_index(smcfg, pos))
|
||||||
sm = submodule_alloc(name.ptr);
|
sm = submodule_alloc(name.ptr);
|
||||||
else
|
else
|
||||||
sm = git_khash_str_value_at(smcfg, pos);
|
sm = git_strmap_value_at(smcfg, pos);
|
||||||
if (!sm)
|
if (!sm)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
@ -172,7 +172,7 @@ static int submodule_from_config(
|
|||||||
assert(sm->path == sm->name);
|
assert(sm->path == sm->name);
|
||||||
sm->name = git_buf_detach(&name);
|
sm->name = git_buf_detach(&name);
|
||||||
|
|
||||||
git_khash_str_insert2(smcfg, sm->name, sm, old_sm, error);
|
git_strmap_insert2(smcfg, sm->name, sm, old_sm, error);
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
sm->refcount++;
|
sm->refcount++;
|
||||||
@ -183,7 +183,7 @@ static int submodule_from_config(
|
|||||||
if (sm->path == NULL)
|
if (sm->path == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
git_khash_str_insert2(smcfg, sm->path, sm, old_sm, error);
|
git_strmap_insert2(smcfg, sm->path, sm, old_sm, error);
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
sm->refcount++;
|
sm->refcount++;
|
||||||
@ -247,7 +247,7 @@ static int load_submodule_config(git_repository *repo)
|
|||||||
git_index *index;
|
git_index *index;
|
||||||
unsigned int i, max_i;
|
unsigned int i, max_i;
|
||||||
git_oid gitmodules_oid;
|
git_oid gitmodules_oid;
|
||||||
git_khash_str *smcfg;
|
git_strmap *smcfg;
|
||||||
struct git_config_file *mods = NULL;
|
struct git_config_file *mods = NULL;
|
||||||
|
|
||||||
if (repo->submodules)
|
if (repo->submodules)
|
||||||
@ -257,7 +257,7 @@ static int load_submodule_config(git_repository *repo)
|
|||||||
* under both its name and its path. These are usually the same, but
|
* under both its name and its path. These are usually the same, but
|
||||||
* that is not guaranteed.
|
* that is not guaranteed.
|
||||||
*/
|
*/
|
||||||
smcfg = git_khash_str_alloc();
|
smcfg = git_strmap_alloc();
|
||||||
GITERR_CHECK_ALLOC(smcfg);
|
GITERR_CHECK_ALLOC(smcfg);
|
||||||
|
|
||||||
/* scan index for gitmodules (and .gitmodules entry) */
|
/* scan index for gitmodules (and .gitmodules entry) */
|
||||||
@ -307,13 +307,13 @@ cleanup:
|
|||||||
if (mods != NULL)
|
if (mods != NULL)
|
||||||
git_config_file_free(mods);
|
git_config_file_free(mods);
|
||||||
if (error)
|
if (error)
|
||||||
git_khash_str_free(smcfg);
|
git_strmap_free(smcfg);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void git_submodule_config_free(git_repository *repo)
|
void git_submodule_config_free(git_repository *repo)
|
||||||
{
|
{
|
||||||
git_khash_str *smcfg = repo->submodules;
|
git_strmap *smcfg = repo->submodules;
|
||||||
git_submodule *sm;
|
git_submodule *sm;
|
||||||
|
|
||||||
repo->submodules = NULL;
|
repo->submodules = NULL;
|
||||||
@ -321,10 +321,10 @@ void git_submodule_config_free(git_repository *repo)
|
|||||||
if (smcfg == NULL)
|
if (smcfg == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
git_khash_str_foreach_value(smcfg, sm, {
|
git_strmap_foreach_value(smcfg, sm, {
|
||||||
submodule_release(sm,1);
|
submodule_release(sm,1);
|
||||||
});
|
});
|
||||||
git_khash_str_free(smcfg);
|
git_strmap_free(smcfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int submodule_cmp(const void *a, const void *b)
|
static int submodule_cmp(const void *a, const void *b)
|
||||||
@ -345,7 +345,7 @@ int git_submodule_foreach(
|
|||||||
if ((error = load_submodule_config(repo)) < 0)
|
if ((error = load_submodule_config(repo)) < 0)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
git_khash_str_foreach_value(repo->submodules, sm, {
|
git_strmap_foreach_value(repo->submodules, sm, {
|
||||||
/* usually the following will not come into play */
|
/* usually the following will not come into play */
|
||||||
if (sm->refcount > 1) {
|
if (sm->refcount > 1) {
|
||||||
if (git_vector_bsearch(&seen, sm) != GIT_ENOTFOUND)
|
if (git_vector_bsearch(&seen, sm) != GIT_ENOTFOUND)
|
||||||
@ -373,12 +373,12 @@ int git_submodule_lookup(
|
|||||||
if (load_submodule_config(repo) < 0)
|
if (load_submodule_config(repo) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
pos = git_khash_str_lookup_index(repo->submodules, name);
|
pos = git_strmap_lookup_index(repo->submodules, name);
|
||||||
if (!git_khash_str_valid_index(repo->submodules, pos))
|
if (!git_strmap_valid_index(repo->submodules, pos))
|
||||||
return GIT_ENOTFOUND;
|
return GIT_ENOTFOUND;
|
||||||
|
|
||||||
if (sm_ptr)
|
if (sm_ptr)
|
||||||
*sm_ptr = git_khash_str_value_at(repo->submodules, pos);
|
*sm_ptr = git_strmap_value_at(repo->submodules, pos);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
102
tests-clar/core/strmap.c
Normal file
102
tests-clar/core/strmap.c
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
#include "clar_libgit2.h"
|
||||||
|
#include "strmap.h"
|
||||||
|
|
||||||
|
GIT__USE_STRMAP;
|
||||||
|
|
||||||
|
void test_core_strmap__0(void)
|
||||||
|
{
|
||||||
|
git_strmap *table = git_strmap_alloc();
|
||||||
|
cl_assert(table != NULL);
|
||||||
|
cl_assert(git_strmap_num_entries(table) == 0);
|
||||||
|
git_strmap_free(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void insert_strings(git_strmap *table, int count)
|
||||||
|
{
|
||||||
|
int i, j, over, err;
|
||||||
|
char *str;
|
||||||
|
|
||||||
|
for (i = 0; i < count; ++i) {
|
||||||
|
str = malloc(10);
|
||||||
|
for (j = 0; j < 10; ++j)
|
||||||
|
str[j] = 'a' + (i % 26);
|
||||||
|
str[9] = '\0';
|
||||||
|
|
||||||
|
/* if > 26, then encode larger value in first letters */
|
||||||
|
for (j = 0, over = i / 26; over > 0; j++, over = over / 26)
|
||||||
|
str[j] = 'A' + (over % 26);
|
||||||
|
|
||||||
|
git_strmap_insert(table, str, str, err);
|
||||||
|
cl_assert(err >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
cl_assert((int)git_strmap_num_entries(table) == count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_core_strmap__1(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *str;
|
||||||
|
git_strmap *table = git_strmap_alloc();
|
||||||
|
cl_assert(table != NULL);
|
||||||
|
|
||||||
|
insert_strings(table, 20);
|
||||||
|
|
||||||
|
cl_assert(git_strmap_exists(table, "aaaaaaaaa"));
|
||||||
|
cl_assert(git_strmap_exists(table, "ggggggggg"));
|
||||||
|
cl_assert(!git_strmap_exists(table, "aaaaaaaab"));
|
||||||
|
cl_assert(!git_strmap_exists(table, "abcdefghi"));
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
git_strmap_foreach_value(table, str, { i++; free(str); });
|
||||||
|
cl_assert(i == 20);
|
||||||
|
|
||||||
|
git_strmap_free(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_core_strmap__2(void)
|
||||||
|
{
|
||||||
|
khiter_t pos;
|
||||||
|
int i;
|
||||||
|
char *str;
|
||||||
|
git_strmap *table = git_strmap_alloc();
|
||||||
|
cl_assert(table != NULL);
|
||||||
|
|
||||||
|
insert_strings(table, 20);
|
||||||
|
|
||||||
|
cl_assert(git_strmap_exists(table, "aaaaaaaaa"));
|
||||||
|
cl_assert(git_strmap_exists(table, "ggggggggg"));
|
||||||
|
cl_assert(!git_strmap_exists(table, "aaaaaaaab"));
|
||||||
|
cl_assert(!git_strmap_exists(table, "abcdefghi"));
|
||||||
|
|
||||||
|
cl_assert(git_strmap_exists(table, "bbbbbbbbb"));
|
||||||
|
pos = git_strmap_lookup_index(table, "bbbbbbbbb");
|
||||||
|
cl_assert(git_strmap_valid_index(table, pos));
|
||||||
|
cl_assert_equal_s(git_strmap_value_at(table, pos), "bbbbbbbbb");
|
||||||
|
free(git_strmap_value_at(table, pos));
|
||||||
|
git_strmap_delete_at(table, pos);
|
||||||
|
|
||||||
|
cl_assert(!git_strmap_exists(table, "bbbbbbbbb"));
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
git_strmap_foreach_value(table, str, { i++; free(str); });
|
||||||
|
cl_assert(i == 19);
|
||||||
|
|
||||||
|
git_strmap_free(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_core_strmap__3(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *str;
|
||||||
|
git_strmap *table = git_strmap_alloc();
|
||||||
|
cl_assert(table != NULL);
|
||||||
|
|
||||||
|
insert_strings(table, 10000);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
git_strmap_foreach_value(table, str, { i++; free(str); });
|
||||||
|
cl_assert(i == 10000);
|
||||||
|
|
||||||
|
git_strmap_free(table);
|
||||||
|
}
|
@ -1,189 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License, version 2,
|
|
||||||
* as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* In addition to the permissions in the GNU General Public License,
|
|
||||||
* the authors give you unlimited permission to link the compiled
|
|
||||||
* version of this file into combinations with other programs,
|
|
||||||
* and to distribute those combinations without any restriction
|
|
||||||
* coming from the use of this file. (The General Public License
|
|
||||||
* restrictions do apply in other respects; for example, they cover
|
|
||||||
* modification of the file, and distribution when not linked into
|
|
||||||
* a combined executable.)
|
|
||||||
*
|
|
||||||
* This file 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
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
|
||||||
* Boston, MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
#include "test_lib.h"
|
|
||||||
#include "test_helpers.h"
|
|
||||||
|
|
||||||
#include "hashtable.h"
|
|
||||||
#include "hash.h"
|
|
||||||
|
|
||||||
typedef struct _aux_object {
|
|
||||||
int __bulk;
|
|
||||||
git_oid id;
|
|
||||||
int visited;
|
|
||||||
} table_item;
|
|
||||||
|
|
||||||
static uint32_t hash_func(const void *key, int hash_id)
|
|
||||||
{
|
|
||||||
uint32_t r;
|
|
||||||
const git_oid *id = key;
|
|
||||||
|
|
||||||
memcpy(&r, id->id + (hash_id * sizeof(uint32_t)), sizeof(r));
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int hash_cmpkey(const void *a, const void *b)
|
|
||||||
{
|
|
||||||
return git_oid_cmp(a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
BEGIN_TEST(table0, "create a new hashtable")
|
|
||||||
|
|
||||||
git_hashtable *table = NULL;
|
|
||||||
|
|
||||||
table = git_hashtable_alloc(55, hash_func, hash_cmpkey);
|
|
||||||
must_be_true(table != NULL);
|
|
||||||
must_be_true(table->size_mask + 1 == 64);
|
|
||||||
|
|
||||||
git_hashtable_free(table);
|
|
||||||
|
|
||||||
END_TEST
|
|
||||||
|
|
||||||
BEGIN_TEST(table1, "fill the hashtable with random entries")
|
|
||||||
|
|
||||||
const int objects_n = 32;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
table_item *objects;
|
|
||||||
git_hashtable *table = NULL;
|
|
||||||
|
|
||||||
table = git_hashtable_alloc(objects_n * 2, hash_func, hash_cmpkey);
|
|
||||||
must_be_true(table != NULL);
|
|
||||||
|
|
||||||
objects = git__malloc(objects_n * sizeof(table_item));
|
|
||||||
memset(objects, 0x0, objects_n * sizeof(table_item));
|
|
||||||
|
|
||||||
/* populate the hash table */
|
|
||||||
for (i = 0; i < objects_n; ++i) {
|
|
||||||
git_hash_buf(&(objects[i].id), &i, sizeof(int));
|
|
||||||
must_pass(git_hashtable_insert(table, &(objects[i].id), &(objects[i])));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* make sure all the inserted objects can be found */
|
|
||||||
for (i = 0; i < objects_n; ++i) {
|
|
||||||
git_oid id;
|
|
||||||
table_item *ob;
|
|
||||||
|
|
||||||
git_hash_buf(&id, &i, sizeof(int));
|
|
||||||
ob = (table_item *)git_hashtable_lookup(table, &id);
|
|
||||||
|
|
||||||
must_be_true(ob != NULL);
|
|
||||||
must_be_true(ob == &(objects[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* make sure we cannot find inexisting objects */
|
|
||||||
for (i = 0; i < 50; ++i) {
|
|
||||||
int hash_id;
|
|
||||||
git_oid id;
|
|
||||||
|
|
||||||
hash_id = (rand() % 50000) + objects_n;
|
|
||||||
git_hash_buf(&id, &hash_id, sizeof(int));
|
|
||||||
must_be_true(git_hashtable_lookup(table, &id) == NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
git_hashtable_free(table);
|
|
||||||
git__free(objects);
|
|
||||||
|
|
||||||
END_TEST
|
|
||||||
|
|
||||||
|
|
||||||
BEGIN_TEST(table2, "make sure the table resizes automatically")
|
|
||||||
|
|
||||||
const int objects_n = 64;
|
|
||||||
int i;
|
|
||||||
size_t old_size;
|
|
||||||
table_item *objects;
|
|
||||||
git_hashtable *table = NULL;
|
|
||||||
|
|
||||||
table = git_hashtable_alloc(objects_n, hash_func, hash_cmpkey);
|
|
||||||
must_be_true(table != NULL);
|
|
||||||
|
|
||||||
objects = git__malloc(objects_n * sizeof(table_item));
|
|
||||||
memset(objects, 0x0, objects_n * sizeof(table_item));
|
|
||||||
|
|
||||||
old_size = table->size_mask + 1;
|
|
||||||
|
|
||||||
/* populate the hash table -- should be automatically resized */
|
|
||||||
for (i = 0; i < objects_n; ++i) {
|
|
||||||
git_hash_buf(&(objects[i].id), &i, sizeof(int));
|
|
||||||
must_pass(git_hashtable_insert(table, &(objects[i].id), &(objects[i])));
|
|
||||||
}
|
|
||||||
|
|
||||||
must_be_true(table->size_mask > old_size);
|
|
||||||
|
|
||||||
/* make sure all the inserted objects can be found */
|
|
||||||
for (i = 0; i < objects_n; ++i) {
|
|
||||||
git_oid id;
|
|
||||||
table_item *ob;
|
|
||||||
|
|
||||||
git_hash_buf(&id, &i, sizeof(int));
|
|
||||||
ob = (table_item *)git_hashtable_lookup(table, &id);
|
|
||||||
|
|
||||||
must_be_true(ob != NULL);
|
|
||||||
must_be_true(ob == &(objects[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
git_hashtable_free(table);
|
|
||||||
git__free(objects);
|
|
||||||
|
|
||||||
END_TEST
|
|
||||||
|
|
||||||
BEGIN_TEST(tableit0, "iterate through all the contents of the table")
|
|
||||||
|
|
||||||
const int objects_n = 32;
|
|
||||||
int i;
|
|
||||||
table_item *objects, *ob;
|
|
||||||
|
|
||||||
git_hashtable *table = NULL;
|
|
||||||
|
|
||||||
table = git_hashtable_alloc(objects_n * 2, hash_func, hash_cmpkey);
|
|
||||||
must_be_true(table != NULL);
|
|
||||||
|
|
||||||
objects = git__malloc(objects_n * sizeof(table_item));
|
|
||||||
memset(objects, 0x0, objects_n * sizeof(table_item));
|
|
||||||
|
|
||||||
/* populate the hash table */
|
|
||||||
for (i = 0; i < objects_n; ++i) {
|
|
||||||
git_hash_buf(&(objects[i].id), &i, sizeof(int));
|
|
||||||
must_pass(git_hashtable_insert(table, &(objects[i].id), &(objects[i])));
|
|
||||||
}
|
|
||||||
|
|
||||||
GIT_HASHTABLE_FOREACH_VALUE(table, ob, ob->visited = 1);
|
|
||||||
|
|
||||||
/* make sure all nodes have been visited */
|
|
||||||
for (i = 0; i < objects_n; ++i)
|
|
||||||
must_be_true(objects[i].visited);
|
|
||||||
|
|
||||||
git_hashtable_free(table);
|
|
||||||
git__free(objects);
|
|
||||||
END_TEST
|
|
||||||
|
|
||||||
|
|
||||||
BEGIN_SUITE(hashtable)
|
|
||||||
ADD_TEST(table0);
|
|
||||||
ADD_TEST(table1);
|
|
||||||
ADD_TEST(table2);
|
|
||||||
ADD_TEST(tableit0);
|
|
||||||
END_SUITE
|
|
||||||
|
|
@ -37,7 +37,6 @@ DECLARE_SUITE(objwrite);
|
|||||||
DECLARE_SUITE(commit);
|
DECLARE_SUITE(commit);
|
||||||
DECLARE_SUITE(revwalk);
|
DECLARE_SUITE(revwalk);
|
||||||
DECLARE_SUITE(index);
|
DECLARE_SUITE(index);
|
||||||
DECLARE_SUITE(hashtable);
|
|
||||||
DECLARE_SUITE(tag);
|
DECLARE_SUITE(tag);
|
||||||
DECLARE_SUITE(tree);
|
DECLARE_SUITE(tree);
|
||||||
DECLARE_SUITE(refs);
|
DECLARE_SUITE(refs);
|
||||||
@ -53,7 +52,6 @@ static libgit2_suite suite_methods[]= {
|
|||||||
SUITE_NAME(commit),
|
SUITE_NAME(commit),
|
||||||
SUITE_NAME(revwalk),
|
SUITE_NAME(revwalk),
|
||||||
SUITE_NAME(index),
|
SUITE_NAME(index),
|
||||||
SUITE_NAME(hashtable),
|
|
||||||
SUITE_NAME(tag),
|
SUITE_NAME(tag),
|
||||||
SUITE_NAME(tree),
|
SUITE_NAME(tree),
|
||||||
SUITE_NAME(refs),
|
SUITE_NAME(refs),
|
||||||
|
Loading…
Reference in New Issue
Block a user