/*
 * name-hash.c
 *
 * Hashing names in the index state
 *
 * Copyright (C) 2008 Linus Torvalds
 */
#define NO_THE_INDEX_COMPATIBILITY_MACROS
#include "cache.h"

/*
 * This removes bit 5 if bit 6 is set.
 *
 * That will make US-ASCII characters hash to their upper-case
 * equivalent. We could easily do this one whole word at a time,
 * but that's for future worries.
 */
static inline unsigned char icase_hash(unsigned char c)
{
	return c & ~((c & 0x40) >> 1);
}

static unsigned int hash_name(const char *name, int namelen)
{
	unsigned int hash = 0x123;

	while (namelen--) {
		unsigned char c = *name++;
		c = icase_hash(c);
		hash = hash*101 + c;
	}
	return hash;
}

struct dir_entry {
	struct dir_entry *next;
	struct dir_entry *parent;
	struct cache_entry *ce;
	int nr;
	unsigned int namelen;
};

static struct dir_entry *find_dir_entry(struct index_state *istate,
		const char *name, unsigned int namelen)
{
	unsigned int hash = hash_name(name, namelen);
	struct dir_entry *dir;

	for (dir = lookup_hash(hash, &istate->dir_hash); dir; dir = dir->next)
		if (dir->namelen == namelen &&
		    !strncasecmp(dir->ce->name, name, namelen))
			return dir;
	return NULL;
}

static struct dir_entry *hash_dir_entry(struct index_state *istate,
		struct cache_entry *ce, int namelen)
{
	/*
	 * Throw each directory component in the hash for quick lookup
	 * during a git status. Directory components are stored with their
	 * closing slash.  Despite submodules being a directory, they never
	 * reach this point, because they are stored without a closing slash
	 * in index_state.name_hash (as ordinary cache_entries).
	 *
	 * Note that the cache_entry stored with the dir_entry merely
	 * supplies the name of the directory (up to dir_entry.namelen). We
	 * track the number of 'active' files in a directory in dir_entry.nr,
	 * so we can tell if the directory is still relevant, e.g. for git
	 * status. However, if cache_entries are removed, we cannot pinpoint
	 * an exact cache_entry that's still active. It is very possible that
	 * multiple dir_entries point to the same cache_entry.
	 */
	struct dir_entry *dir;

	/* get length of parent directory */
	while (namelen > 0 && !is_dir_sep(ce->name[namelen - 1]))
		namelen--;
	if (namelen <= 0)
		return NULL;

	/* lookup existing entry for that directory */
	dir = find_dir_entry(istate, ce->name, namelen);
	if (!dir) {
		/* not found, create it and add to hash table */
		void **pdir;
		unsigned int hash = hash_name(ce->name, namelen);

		dir = xcalloc(1, sizeof(struct dir_entry));
		dir->namelen = namelen;
		dir->ce = ce;

		pdir = insert_hash(hash, dir, &istate->dir_hash);
		if (pdir) {
			dir->next = *pdir;
			*pdir = dir;
		}

		/* recursively add missing parent directories */
		dir->parent = hash_dir_entry(istate, ce, namelen - 1);
	}
	return dir;
}

static void add_dir_entry(struct index_state *istate, struct cache_entry *ce)
{
	/* Add reference to the directory entry (and parents if 0). */
	struct dir_entry *dir = hash_dir_entry(istate, ce, ce_namelen(ce));
	while (dir && !(dir->nr++))
		dir = dir->parent;
}

static void remove_dir_entry(struct index_state *istate, struct cache_entry *ce)
{
	/*
	 * Release reference to the directory entry (and parents if 0).
	 *
	 * Note: we do not remove / free the entry because there's no
	 * hash.[ch]::remove_hash and dir->next may point to other entries
	 * that are still valid, so we must not free the memory.
	 */
	struct dir_entry *dir = hash_dir_entry(istate, ce, ce_namelen(ce));
	while (dir && dir->nr && !(--dir->nr))
		dir = dir->parent;
}

static void hash_index_entry(struct index_state *istate, struct cache_entry *ce)
{
	void **pos;
	unsigned int hash;

	if (ce->ce_flags & CE_HASHED)
		return;
	ce->ce_flags |= CE_HASHED;
	ce->next = NULL;
	hash = hash_name(ce->name, ce_namelen(ce));
	pos = insert_hash(hash, ce, &istate->name_hash);
	if (pos) {
		ce->next = *pos;
		*pos = ce;
	}

	if (ignore_case && !(ce->ce_flags & CE_UNHASHED))
		add_dir_entry(istate, ce);
}

static void lazy_init_name_hash(struct index_state *istate)
{
	int nr;

	if (istate->name_hash_initialized)
		return;
	if (istate->cache_nr)
		preallocate_hash(&istate->name_hash, istate->cache_nr);
	for (nr = 0; nr < istate->cache_nr; nr++)
		hash_index_entry(istate, istate->cache[nr]);
	istate->name_hash_initialized = 1;
}

void add_name_hash(struct index_state *istate, struct cache_entry *ce)
{
	/* if already hashed, add reference to directory entries */
	if (ignore_case && (ce->ce_flags & CE_STATE_MASK) == CE_STATE_MASK)
		add_dir_entry(istate, ce);

	ce->ce_flags &= ~CE_UNHASHED;
	if (istate->name_hash_initialized)
		hash_index_entry(istate, ce);
}

/*
 * We don't actually *remove* it, we can just mark it invalid so that
 * we won't find it in lookups.
 *
 * Not only would we have to search the lists (simple enough), but
 * we'd also have to rehash other hash buckets in case this makes the
 * hash bucket empty (common). So it's much better to just mark
 * it.
 */
void remove_name_hash(struct index_state *istate, struct cache_entry *ce)
{
	/* if already hashed, release reference to directory entries */
	if (ignore_case && (ce->ce_flags & CE_STATE_MASK) == CE_HASHED)
		remove_dir_entry(istate, ce);

	ce->ce_flags |= CE_UNHASHED;
}

static int slow_same_name(const char *name1, int len1, const char *name2, int len2)
{
	if (len1 != len2)
		return 0;

	while (len1) {
		unsigned char c1 = *name1++;
		unsigned char c2 = *name2++;
		len1--;
		if (c1 != c2) {
			c1 = toupper(c1);
			c2 = toupper(c2);
			if (c1 != c2)
				return 0;
		}
	}
	return 1;
}

static int same_name(const struct cache_entry *ce, const char *name, int namelen, int icase)
{
	int len = ce_namelen(ce);

	/*
	 * Always do exact compare, even if we want a case-ignoring comparison;
	 * we do the quick exact one first, because it will be the common case.
	 */
	if (len == namelen && !cache_name_compare(name, namelen, ce->name, len))
		return 1;

	if (!icase)
		return 0;

	return slow_same_name(name, namelen, ce->name, len);
}

struct cache_entry *index_name_exists(struct index_state *istate, const char *name, int namelen, int icase)
{
	unsigned int hash = hash_name(name, namelen);
	struct cache_entry *ce;

	lazy_init_name_hash(istate);
	ce = lookup_hash(hash, &istate->name_hash);

	while (ce) {
		if (!(ce->ce_flags & CE_UNHASHED)) {
			if (same_name(ce, name, namelen, icase))
				return ce;
		}
		ce = ce->next;
	}

	/*
	 * When looking for a directory (trailing '/'), it might be a
	 * submodule or a directory. Despite submodules being directories,
	 * they are stored in the name hash without a closing slash.
	 * When ignore_case is 1, directories are stored in a separate hash
	 * table *with* their closing slash.
	 *
	 * The side effect of this storage technique is we have need to
	 * lookup the directory in a separate hash table, and if not found
	 * remove the slash from name and perform the lookup again without
	 * the slash.  If a match is made, S_ISGITLINK(ce->mode) will be
	 * true.
	 */
	if (icase && name[namelen - 1] == '/') {
		struct dir_entry *dir = find_dir_entry(istate, name, namelen);
		if (dir && dir->nr)
			return dir->ce;

		ce = index_name_exists(istate, name, namelen - 1, icase);
		if (ce && S_ISGITLINK(ce->ce_mode))
			return ce;
	}
	return NULL;
}

static int free_dir_entry(void *entry, void *unused)
{
	struct dir_entry *dir = entry;
	while (dir) {
		struct dir_entry *next = dir->next;
		free(dir);
		dir = next;
	}
	return 0;
}

void free_name_hash(struct index_state *istate)
{
	if (!istate->name_hash_initialized)
		return;
	istate->name_hash_initialized = 0;
	if (ignore_case)
		/* free directory entries */
		for_each_hash(&istate->dir_hash, free_dir_entry, NULL);

	free_hash(&istate->name_hash);
	free_hash(&istate->dir_hash);
}
