summaryrefslogtreecommitdiff
path: root/src/iterator.h
diff options
context:
space:
mode:
authorVicent Martí <vicent@github.com>2013-03-12 09:23:53 -0700
committerVicent Martí <vicent@github.com>2013-03-12 09:23:53 -0700
commit1ac10aae1da23f4a626d8eecd636402572785426 (patch)
treea315a5ed203ed12807b814b65e825923c536f38b /src/iterator.h
parentb70bf922a1de35722904930c42467e95c889562f (diff)
parent62beacd300a6d3c62943723928f45ef852485e62 (diff)
downloadlibgit2-1ac10aae1da23f4a626d8eecd636402572785426.tar.gz
Merge pull request #1408 from arrbee/refactor-iterators
Refactor iterators
Diffstat (limited to 'src/iterator.h')
-rw-r--r--src/iterator.h153
1 files changed, 73 insertions, 80 deletions
diff --git a/src/iterator.h b/src/iterator.h
index a9bccfca8..4a4e6a9d8 100644
--- a/src/iterator.h
+++ b/src/iterator.h
@@ -12,11 +12,6 @@
#include "vector.h"
#include "buffer.h"
-#define ITERATOR_PREFIXCMP(ITER, STR, PREFIX) \
- (((ITER).flags & GIT_ITERATOR_IGNORE_CASE) != 0 ? \
- git__prefixcmp_icase((STR), (PREFIX)) : \
- git__prefixcmp((STR), (PREFIX)))
-
typedef struct git_iterator git_iterator;
typedef enum {
@@ -24,20 +19,26 @@ typedef enum {
GIT_ITERATOR_TYPE_TREE = 1,
GIT_ITERATOR_TYPE_INDEX = 2,
GIT_ITERATOR_TYPE_WORKDIR = 3,
- GIT_ITERATOR_TYPE_SPOOLANDSORT = 4
} git_iterator_type_t;
typedef enum {
- GIT_ITERATOR_IGNORE_CASE = (1 << 0), /* ignore_case */
- GIT_ITERATOR_DONT_IGNORE_CASE = (1 << 1), /* force ignore_case off */
+ /** ignore case for entry sort order */
+ GIT_ITERATOR_IGNORE_CASE = (1 << 0),
+ /** force case sensitivity for entry sort order */
+ GIT_ITERATOR_DONT_IGNORE_CASE = (1 << 1),
+ /** return tree items in addition to blob items */
+ GIT_ITERATOR_INCLUDE_TREES = (1 << 2),
+ /** don't flatten trees, requiring advance_into (implies INCLUDE_TREES) */
+ GIT_ITERATOR_DONT_AUTOEXPAND = (1 << 3),
} git_iterator_flag_t;
typedef struct {
- int (*current)(git_iterator *, const git_index_entry **);
- int (*at_end)(git_iterator *);
- int (*advance)(git_iterator *, const git_index_entry **);
+ int (*current)(const git_index_entry **, git_iterator *);
+ int (*advance)(const git_index_entry **, git_iterator *);
+ int (*advance_into)(const git_index_entry **, git_iterator *);
int (*seek)(git_iterator *, const char *prefix);
int (*reset)(git_iterator *, const char *start, const char *end);
+ int (*at_end)(git_iterator *);
void (*free)(git_iterator *);
} git_iterator_callbacks;
@@ -52,86 +53,92 @@ struct git_iterator {
};
extern int git_iterator_for_nothing(
- git_iterator **out, git_iterator_flag_t flags);
+ git_iterator **out,
+ git_iterator_flag_t flags,
+ const char *start,
+ const char *end);
/* tree iterators will match the ignore_case value from the index of the
* repository, unless you override with a non-zero flag value
*/
-extern int git_iterator_for_tree_range(
+extern int git_iterator_for_tree(
git_iterator **out,
git_tree *tree,
git_iterator_flag_t flags,
const char *start,
const char *end);
-GIT_INLINE(int) git_iterator_for_tree(git_iterator **out, git_tree *tree)
-{
- return git_iterator_for_tree_range(out, tree, 0, NULL, NULL);
-}
-
/* index iterators will take the ignore_case value from the index; the
* ignore_case flags are not used
*/
-extern int git_iterator_for_index_range(
+extern int git_iterator_for_index(
git_iterator **out,
git_index *index,
git_iterator_flag_t flags,
const char *start,
const char *end);
-GIT_INLINE(int) git_iterator_for_index(git_iterator **out, git_index *index)
-{
- return git_iterator_for_index_range(out, index, 0, NULL, NULL);
-}
-
/* workdir iterators will match the ignore_case value from the index of the
* repository, unless you override with a non-zero flag value
*/
-extern int git_iterator_for_workdir_range(
+extern int git_iterator_for_workdir(
git_iterator **out,
git_repository *repo,
git_iterator_flag_t flags,
const char *start,
const char *end);
-GIT_INLINE(int) git_iterator_for_workdir(git_iterator **out, git_repository *repo)
-{
- return git_iterator_for_workdir_range(out, repo, 0, NULL, NULL);
-}
-
extern void git_iterator_free(git_iterator *iter);
-/* Spool all iterator values, resort with alternative ignore_case value
- * and replace callbacks with spoolandsort alternates.
- */
-extern int git_iterator_spoolandsort_push(git_iterator *iter, bool ignore_case);
-
-/* Restore original callbacks - not required in most circumstances */
-extern void git_iterator_spoolandsort_pop(git_iterator *iter);
-
-/* Entry is not guaranteed to be fully populated. For a tree iterator,
- * we will only populate the mode, oid and path, for example. For a workdir
- * iterator, we will not populate the oid.
+/* Return a git_index_entry structure for the current value the iterator
+ * is looking at or NULL if the iterator is at the end.
+ *
+ * The entry may noy be fully populated. Tree iterators will only have a
+ * value mode, OID, and path. Workdir iterators will not have an OID (but
+ * you can use `git_iterator_current_oid()` to calculate it on demand).
*
* You do not need to free the entry. It is still "owned" by the iterator.
- * Once you call `git_iterator_advance`, then content of the old entry is
- * no longer guaranteed to be valid.
+ * Once you call `git_iterator_advance()` then the old entry is no longer
+ * guaranteed to be valid - it may be freed or just overwritten in place.
*/
GIT_INLINE(int) git_iterator_current(
- git_iterator *iter, const git_index_entry **entry)
+ const git_index_entry **entry, git_iterator *iter)
{
- return iter->cb->current(iter, entry);
+ return iter->cb->current(entry, iter);
}
-GIT_INLINE(int) git_iterator_at_end(git_iterator *iter)
+/**
+ * Advance to the next item for the iterator.
+ *
+ * If GIT_ITERATOR_INCLUDE_TREES is set, this may be a tree item. If
+ * GIT_ITERATOR_DONT_AUTOEXPAND is set, calling this again when on a tree
+ * item will skip over all the items under that tree.
+ */
+GIT_INLINE(int) git_iterator_advance(
+ const git_index_entry **entry, git_iterator *iter)
{
- return iter->cb->at_end(iter);
+ return iter->cb->advance(entry, iter);
}
-GIT_INLINE(int) git_iterator_advance(
- git_iterator *iter, const git_index_entry **entry)
+/**
+ * Iterate into a tree item (when GIT_ITERATOR_DONT_AUTOEXPAND is set).
+ *
+ * git_iterator_advance() steps through all items being iterated over
+ * (either with or without trees, depending on GIT_ITERATOR_INCLUDE_TREES),
+ * but if GIT_ITERATOR_DONT_AUTOEXPAND is set, it will skip to the next
+ * sibling of a tree instead of going to the first child of the tree. In
+ * that case, use this function to advance to the first child of the tree.
+ *
+ * If the current item is not a tree, this is a no-op.
+ *
+ * For working directory iterators only, a tree (i.e. directory) can be
+ * empty. In that case, this function returns GIT_ENOTFOUND and does not
+ * advance. That can't happen for tree and index iterators.
+ */
+GIT_INLINE(int) git_iterator_advance_into(
+ const git_index_entry **entry, git_iterator *iter)
{
- return iter->cb->advance(iter, entry);
+ return iter->cb->advance_into(entry, iter);
}
GIT_INLINE(int) git_iterator_seek(
@@ -146,6 +153,11 @@ GIT_INLINE(int) git_iterator_reset(
return iter->cb->reset(iter, start, end);
}
+GIT_INLINE(int) git_iterator_at_end(git_iterator *iter)
+{
+ return iter->cb->at_end(iter);
+}
+
GIT_INLINE(git_iterator_type_t) git_iterator_type(git_iterator *iter)
{
return iter->type;
@@ -166,47 +178,28 @@ GIT_INLINE(bool) git_iterator_ignore_case(git_iterator *iter)
return ((iter->flags & GIT_ITERATOR_IGNORE_CASE) != 0);
}
+extern int git_iterator_set_ignore_case(git_iterator *iter, bool ignore_case);
+
extern int git_iterator_current_tree_entry(
- git_iterator *iter, const git_tree_entry **tree_entry);
+ const git_tree_entry **entry_out, git_iterator *iter);
extern int git_iterator_current_parent_tree(
- git_iterator *iter, const char *parent_path, const git_tree **tree_ptr);
+ const git_tree **tree_out, git_iterator *iter, const char *parent_path);
-extern int git_iterator_current_is_ignored(git_iterator *iter);
-
-/**
- * Iterate into a workdir directory.
- *
- * Workdir iterators do not automatically descend into directories (so that
- * when comparing two iterator entries you can detect a newly created
- * directory in the workdir). As a result, you may get S_ISDIR items from
- * a workdir iterator. If you wish to iterate over the contents of the
- * directories you encounter, then call this function when you encounter
- * a directory.
- *
- * If there are no files in the directory, this will end up acting like a
- * regular advance and will skip past the directory, so you should be
- * prepared for that case.
- *
- * On non-workdir iterators or if not pointing at a directory, this is a
- * no-op and will not advance the iterator.
- */
-extern int git_iterator_advance_into_directory(
- git_iterator *iter, const git_index_entry **entry);
+extern bool git_iterator_current_is_ignored(git_iterator *iter);
extern int git_iterator_cmp(
git_iterator *iter, const char *path_prefix);
/**
- * Get the full path of the current item from a workdir iterator.
- * This will return NULL for a non-workdir iterator.
+ * Get full path of the current item from a workdir iterator. This will
+ * return NULL for a non-workdir iterator. The git_buf is still owned by
+ * the iterator; this is exposed just for efficiency.
*/
extern int git_iterator_current_workdir_path(
- git_iterator *iter, git_buf **path);
-
-
-extern git_index *git_iterator_index_get_index(git_iterator *iter);
+ git_buf **path, git_iterator *iter);
-extern git_iterator_type_t git_iterator_inner_type(git_iterator *iter);
+/* Return index pointer if index iterator, else NULL */
+extern git_index *git_iterator_get_index(git_iterator *iter);
#endif