Git-Raw

 view release on metacpan or  search on metacpan

deps/libgit2/src/libgit2/iterator.c  view on Meta::CPAN


static void empty_iterator_free(git_iterator *i)
{
	GIT_UNUSED(i);
}

typedef struct {
	git_iterator base;
	git_iterator_callbacks cb;
} empty_iterator;

int git_iterator_for_nothing(
	git_iterator **out,
	git_iterator_options *options)
{
	empty_iterator *iter;

	static git_iterator_callbacks callbacks = {
		empty_iterator_noop,
		empty_iterator_noop,
		empty_iterator_noop,
		empty_iterator_advance_over,
		empty_iterator_reset,
		empty_iterator_free
	};

	*out = NULL;

	iter = git__calloc(1, sizeof(empty_iterator));
	GIT_ERROR_CHECK_ALLOC(iter);

	iter->base.type = GIT_ITERATOR_EMPTY;
	iter->base.cb = &callbacks;
	iter->base.flags = options->flags;

	*out = &iter->base;
	return 0;
}

/* Tree iterator */

typedef struct {
	git_tree_entry *tree_entry;
	const char *parent_path;
} tree_iterator_entry;

typedef struct {
	git_tree *tree;

	/* path to this particular frame (folder) */
	git_str path;

	/* a sorted list of the entries for this frame (folder), these are
	 * actually pointers to the iterator's entry pool.
	 */
	git_vector entries;
	tree_iterator_entry *current;

	size_t next_idx;

	/* on case insensitive iterations, we also have an array of other
	 * paths that were case insensitively equal to this one, and their
	 * tree objects.  we have coalesced the tree entries into this frame.
	 * a child `tree_iterator_entry` will contain a pointer to its actual
	 * parent path.
	 */
	git_vector similar_trees;
	git_array_t(git_str) similar_paths;
} tree_iterator_frame;

typedef struct {
	git_iterator base;
	git_tree *root;
	git_array_t(tree_iterator_frame) frames;

	git_index_entry entry;
	git_str entry_path;

	/* a pool of entries to reduce the number of allocations */
	git_pool entry_pool;
} tree_iterator;

GIT_INLINE(tree_iterator_frame *) tree_iterator_parent_frame(
	tree_iterator *iter)
{
	return iter->frames.size > 1 ?
		&iter->frames.ptr[iter->frames.size-2] : NULL;
}

GIT_INLINE(tree_iterator_frame *) tree_iterator_current_frame(
	tree_iterator *iter)
{
	return iter->frames.size ? &iter->frames.ptr[iter->frames.size-1] : NULL;
}

GIT_INLINE(int) tree_entry_cmp(
	const git_tree_entry *a, const git_tree_entry *b, bool icase)
{
	return git_fs_path_cmp(
		a->filename, a->filename_len, a->attr == GIT_FILEMODE_TREE,
		b->filename, b->filename_len, b->attr == GIT_FILEMODE_TREE,
		icase ? git__strncasecmp : git__strncmp);
}

GIT_INLINE(int) tree_iterator_entry_cmp_icase(
	const void *ptr_a, const void *ptr_b)
{
	const tree_iterator_entry *a = (const tree_iterator_entry *)ptr_a;
	const tree_iterator_entry *b = (const tree_iterator_entry *)ptr_b;

	return tree_entry_cmp(a->tree_entry, b->tree_entry, true);
}

static int tree_iterator_entry_sort_icase(const void *ptr_a, const void *ptr_b)
{
	const tree_iterator_entry *a = (const tree_iterator_entry *)ptr_a;
	const tree_iterator_entry *b = (const tree_iterator_entry *)ptr_b;

	int c = tree_entry_cmp(a->tree_entry, b->tree_entry, true);

	/* stabilize the sort order for filenames that are (case insensitively)



( run in 2.856 seconds using v1.01-cache-2.11-cpan-71847e10f99 )