/** * Enter into the current subtree. * <para /> * If the current entry is a subtree this method arranges for its children * to be returned before the next sibling following the subtree is returned. * * @throws MissingObjectException * a subtree was found, but the subtree object does not exist in * this repository. The repository may be missing objects. * @throws IncorrectObjectTypeException * a subtree was found, and the subtree id does not denote a * tree, but instead names some other non-tree type of object. * The repository may have data corruption. * @throws CorruptObjectException * the contents of a tree did not appear to be a tree. The * repository may have data corruption. * @throws IOException * a loose object or pack file could not be Read. */ public void enterSubtree() { AbstractTreeIterator ch = CurrentHead; var tmp = new AbstractTreeIterator[_trees.Length]; for (int i = 0; i < _trees.Length; i++) { AbstractTreeIterator treeIterator = _trees[i]; AbstractTreeIterator newIterator; if (treeIterator.Matches == ch && !treeIterator.eof() && FileMode.Tree == treeIterator.EntryFileMode) { newIterator = treeIterator.createSubtreeIterator(_db, _idBuffer, _cursor); } else { newIterator = treeIterator.createEmptyTreeIterator(); } tmp[i] = newIterator; } _depth++; _advance = false; Array.Copy(tmp, 0, _trees, 0, _trees.Length); }
/// <summary> /// Obtain the tree iterator for the current entry. /// <para /> /// Entering into (or exiting out of) a subtree causes the current tree /// iterator instance to be changed for the nth tree. This allows the tree /// iterators to manage only one list of items, with the diving handled by /// recursive trees. /// </summary> /// <typeparam name="T">type of the tree iterator expected by the caller.</typeparam> /// <param name="nth">tree to obtain the current iterator of.</param> /// <param name="clazz">type of the tree iterator expected by the caller.</param> /// <returns> /// The current iterator of the requested type; null if the tree /// has no entry to match the current path. /// </returns> public T getTree <T>(int nth, Type clazz) // [henon] was Class<T> clazz where T : AbstractTreeIterator { AbstractTreeIterator t = _trees[nth]; return(t.Matches == _currentHead ? (T)t : null); }
/// <summary> /// Compare the path of this current entry to another iterator's entry. /// </summary> /// <param name="treeIterator"> /// The other iterator to compare the path against. /// </param> /// <param name="treeIteratorMode"> /// The other iterator <see cref="FileMode"/> bits. /// </param> /// <returns> /// return -1 if this entry sorts first; 0 if the entries are equal; 1 if /// <paramref name="treeIterator"/>'s entry sorts first. /// </returns> public int pathCompare(AbstractTreeIterator treeIterator, int treeIteratorMode) { byte[] a = Path; byte[] b = treeIterator.Path; int aLen = PathLen; int bLen = treeIterator.PathLen; // Its common when we are a subtree for both parents to match; // when this happens everything in _path[0..cPos] is known to // be equal and does not require evaluation again. // int cPos = AlreadyMatch(this, treeIterator); for (; cPos < aLen && cPos < bLen; cPos++) { int cmp = (a[cPos] & 0xff) - (b[cPos] & 0xff); if (cmp != 0) { return(cmp); } } if (cPos < aLen) { return((a[cPos] & 0xff) - LastPathChar(treeIteratorMode)); } if (cPos < bLen) { return(LastPathChar(Mode) - (b[cPos] & 0xff)); } return(LastPathChar(Mode) - LastPathChar(treeIteratorMode)); }
/** * Reset this walker to run over a single existing tree. * * @param id * the tree we need to parse. The walker will execute over this * single tree if the reset is successful. * @throws MissingObjectException * the given tree object does not exist in this repository. * @throws IncorrectObjectTypeException * the given object id does not denote a tree, but instead names * some other non-tree type of object. Note that commits are not * trees, even if they are sometimes called a "tree-ish". * @throws CorruptObjectException * the object claimed to be a tree, but its contents did not * appear to be a tree. The repository may have data corruption. * @throws IOException * a loose object or pack file could not be Read. */ public void reset(AnyObjectId id) { if (_trees.Length == 1) { AbstractTreeIterator iterator = _trees[0]; while (iterator.Parent != null) { iterator = iterator.Parent; } CanonicalTreeParser oParse = (iterator as CanonicalTreeParser); if (oParse != null) { iterator.Matches = null; iterator.MatchShift = 0; oParse.reset(_db, id, _cursor); _trees[0] = iterator; } else { _trees[0] = ParserFor(id); } } else { _trees = new AbstractTreeIterator[] { ParserFor(id) }; } _advance = false; _depth = 0; }
/** * Get the current entry's name within its parent tree. * <para /> * This method is not very efficient and is primarily meant for debugging * and output generation. Applications should try to avoid calling it, * and if invoked do so only once per interesting entry, where the name is * absolutely required for correct function. * * @return name of the current entry within the parent tree (or directory). * The name never includes a '/'. */ public string getNameString() { AbstractTreeIterator t = _currentHead; int off = t.PathOffset; int end = t.PathLen; return(RawParseUtils.decode(Constants.CHARSET, t.Path, off, end)); }
/// <summary> /// Compare the path of this current entry to another iterator's entry. /// </summary> /// <param name="treeIterator"> /// The other iterator to compare the path against. /// </param> /// <returns> /// return -1 if this entry sorts first; 0 if the entries are equal; 1 if /// <paramref name="treeIterator"/>'s entry sorts first. /// </returns> public int pathCompare(AbstractTreeIterator treeIterator) { if (treeIterator == null) { throw new ArgumentNullException("treeIterator"); } return(pathCompare(treeIterator, treeIterator.Mode)); }
/// <summary> /// Check if the current entry of both iterators has the same id. /// <para /> /// This method is faster than <see cref="getEntryObjectId()"/>as it does not /// require copying the bytes out of the buffers. A direct <see cref="idBuffer"/> /// compare operation is performed. /// </summary> /// <param name="otherIterator">the other iterator to test against.</param> /// <returns> /// true if both iterators have the same object id; false otherwise. /// </returns> public virtual bool idEqual(AbstractTreeIterator otherIterator) { if (otherIterator == null) { throw new ArgumentNullException("otherIterator"); } return(ObjectId.Equals(idBuffer(), idOffset(), otherIterator.idBuffer(), otherIterator.idOffset())); }
public static string pathOf(AbstractTreeIterator t) { if (t == null) { throw new ArgumentNullException("t"); } return(RawParseUtils.decode(Constants.CHARSET, t.Path, 0, t.PathLen)); }
/** * Get the current entry's complete path as a UTF-8 byte array. * * @return complete path of the current entry, from the root of the * repository. If the current entry is in a subtree there will be at * least one '/' in the returned string. */ public byte[] getRawPath() { AbstractTreeIterator treeIterator = CurrentHead; int newPathLen = treeIterator.PathLen; var rawPath = new byte[newPathLen]; Array.Copy(treeIterator.Path, 0, rawPath, 0, newPathLen); return(rawPath); }
/** * Advance this walker to the next relevant entry. * * @return true if there is an entry available; false if all entries have * been walked and the walk of this set of tree iterators is over. * @throws MissingObjectException * {@link #isRecursive()} was enabled, a subtree was found, but * the subtree object does not exist in this repository. The * repository may be missing objects. * @throws IncorrectObjectTypeException * {@link #isRecursive()} was enabled, a subtree was found, and * the subtree id does not denote a tree, but instead names some * other non-tree type of object. The repository may have data * corruption. * @throws CorruptObjectException * the contents of a tree did not appear to be a tree. The * repository may have data corruption. * @throws IOException * a loose object or pack file could not be Read. */ public bool next() { try { if (_advance) { _advance = false; _postChildren = false; popEntriesEqual(); } while (true) { AbstractTreeIterator t = min(); if (t.eof()) { if (_depth > 0) { ExitSubtree(); if (PostOrderTraversal) { _advance = true; _postChildren = true; return(true); } popEntriesEqual(); continue; } return(false); } _currentHead = t; if (!_filter.include(this)) { skipEntriesEqual(); continue; } if (Recursive && FileMode.Tree == t.EntryFileMode) { enterSubtree(); continue; } _advance = true; return(true); } } catch (StopWalkException) { foreach (AbstractTreeIterator t in _trees) { t.stopWalk(); } return(false); } }
/// <summary> /// Set path buffer capacity to the specified size /// </summary> /// <param name="capacity">the new size</param> /// <param name="length">the amount of bytes to copy</param> private void SetPathCapacity(int capacity, int length) { var oldPath = Path; var newPath = new byte[capacity]; Array.Copy(oldPath, 0, newPath, 0, length); for (AbstractTreeIterator p = this; p != null && p.Path == oldPath; p = p._parent) { p.Path = newPath; } }
/** * Obtain the ObjectId for the current entry. * <para /> * Every tree supplies an object id, even if the tree does not contain the * current entry. In the latter case {@link ObjectId#zeroId()} is supplied. * <para /> * Applications should try to use {@link #idEqual(int, int)} when possible * as it avoids conversion overheads. * * @param out * buffer to copy the object id into. * @param nth * tree to obtain the object identifier from. * @see #idEqual(int, int) */ public void getObjectId(MutableObjectId @out, int nth) { AbstractTreeIterator t = _trees[nth]; if (t.Matches == _currentHead) { t.getEntryObjectId(@out); } else { @out.Clear(); } }
/** * Add an already created tree iterator for walking. * <para /> * The position of this tree is returned to the caller, in case the caller * has lost track of the order they added the trees into the walker. * <para /> * The tree which the iterator operates on must have the same root as * existing trees in the walk. * * @param parentIterator * an iterator to walk over. The iterator should be new, with no * parent, and should still be positioned before the first entry. * The tree which the iterator operates on must have the same root * as other trees in the walk. * * @return position of this tree within the walker. * @throws CorruptObjectException * the iterator was unable to obtain its first entry, due to * possible data corruption within the backing data store. */ public int addTree(AbstractTreeIterator parentIterator) { int n = _trees.Length; var newTrees = new AbstractTreeIterator[n + 1]; Array.Copy(_trees, 0, newTrees, 0, n); newTrees[n] = parentIterator; parentIterator.Matches = null; parentIterator.MatchShift = 0; _trees = newTrees; return(n); }
public virtual void popEntriesEqual() { AbstractTreeIterator ch = _currentHead; for (int i = 0; i < _trees.Length; i++) { AbstractTreeIterator t = _trees[i]; if (t.Matches == ch) { t.next(1); t.Matches = null; } } }
/// <summary> /// Create an iterator for a subtree of an existing iterator. /// </summary> /// <param name="p">parent tree iterator.</param> protected AbstractTreeIterator(AbstractTreeIterator p) { _parent = p; Path = p.Path; PathOffset = p.PathLen + 1; try { Path[PathOffset - 1] = (byte)'/'; } catch (IndexOutOfRangeException) { growPath(p.PathLen); Path[PathOffset - 1] = (byte)'/'; } }
public virtual void skipEntriesEqual() { AbstractTreeIterator ch = _currentHead; for (int i = 0; i < _trees.Length; i++) { AbstractTreeIterator t = _trees[i]; if (t.Matches != ch) { continue; } t.skip(); t.Matches = null; } }
/** * Add an already created tree iterator for walking. * <para /> * The position of this tree is returned to the caller, in case the caller * has lost track of the order they added the trees into the walker. * <para /> * The tree which the iterator operates on must have the same root as * existing trees in the walk. * * @param parentIterator * an iterator to walk over. The iterator should be new, with no * parent, and should still be positioned before the first entry. * The tree which the iterator operates on must have the same root * as other trees in the walk. * * @return position of this tree within the walker. * @throws CorruptObjectException * the iterator was unable to obtain its first entry, due to * possible data corruption within the backing data store. */ public int addTree(AbstractTreeIterator parentIterator) { if (parentIterator == null) { throw new ArgumentNullException("parentIterator"); } int n = _trees.Length; var newTrees = new AbstractTreeIterator[n + 1]; Array.Copy(_trees, 0, newTrees, 0, n); newTrees[n] = parentIterator; parentIterator.Matches = null; parentIterator.MatchShift = 0; _trees = newTrees; return(n); }
/** * Test if the supplied path matches (being suffix of) the current entry's * path. * <para /> * This method tests that the supplied path is exactly equal to the current * entry, or is relative to one of entry's parent directories. It is faster * to use this method then to use {@link #getPathString()} to first Create * a String object, then test <code>endsWith</code> or some other type of * string match function. * * @param p * path buffer to test. * @param pLen * number of bytes from <code>buf</code> to test. * @return true if p is suffix of the current path; * false if otherwise */ public bool isPathSuffix(byte[] p, int pLen) { AbstractTreeIterator t = _currentHead; byte[] c = t.Path; int cLen = t.PathLen; int ci; for (ci = 1; ci < cLen && ci < pLen; ci++) { if (c[cLen - ci] != p[pLen - ci]) { return(false); } } return(true); }
/// <summary> /// Create an iterator for a subtree of an existing iterator. /// </summary> /// <param name="p">parent tree iterator.</param> protected AbstractTreeIterator(AbstractTreeIterator p) { if (p == null) { throw new ArgumentNullException("p"); } _parent = p; Path = p.Path; PathOffset = p.PathLen + 1; try { Path[PathOffset - 1] = (byte)'/'; } catch (IndexOutOfRangeException) { growPath(p.PathLen); Path[PathOffset - 1] = (byte)'/'; } }
/** * Test if the supplied path matches the current entry's path. * <para /> * This method tests that the supplied path is exactly equal to the current * entry, or is one of its parent directories. It is faster to use this * method then to use {@link #getPathString()} to first Create a string * object, then test <code>startsWith</code> or some other type of string * match function. * * @param p * path buffer to test. Callers should ensure the path does not * end with '/' prior to invocation. * @param pLen * number of bytes from <code>buf</code> to test. * @return < 0 if p is before the current path; 0 if p matches the current * path; 1 if the current path is past p and p will never match * again on this tree walk. */ public int isPathPrefix(byte[] p, int pLen) { if (p == null) { throw new ArgumentNullException("p"); } AbstractTreeIterator t = _currentHead; byte[] c = t.Path; int cLen = t.PathLen; int ci; for (ci = 0; ci < cLen && ci < pLen; ci++) { int cValue = (c[ci] & 0xff) - (p[ci] & 0xff); if (cValue != 0) { return(cValue); } } if (ci < cLen) { // Ran out of pattern but we still had current data. // If c[ci] == '/' then pattern matches the subtree. // Otherwise we cannot be certain so we return -1. // return(c[ci] == '/' ? 0 : -1); } if (ci < pLen) { // Ran out of current, but we still have pattern data. // If p[ci] == '/' then pattern matches this subtree, // otherwise we cannot be certain so we return -1. // return(p[ci] == '/' ? 0 : -1); } // Both strings are identical. // return(0); }
/// <summary> /// Create a new iterator with no parent and a prefix. /// /// The prefix path supplied is inserted in front of all paths generated by /// this iterator. It is intended to be used when an iterator is being /// created for a subsection of an overall repository and needs to be /// combined with other iterators that are created to run over the entire /// repository namespace. /// </summary> /// <param name="prefix"> /// position of this iterator in the repository tree. The value /// may be null or the empty array to indicate the prefix is the /// root of the repository. A trailing slash ('/') is /// automatically appended if the prefix does not end in '/'. /// </param> protected AbstractTreeIterator(byte[] prefix) { _parent = null; if (prefix != null && prefix.Length > 0) { PathLen = prefix.Length; Path = new byte[Math.Max(DEFAULT_PATH_SIZE, PathLen + 1)]; Array.Copy(prefix, 0, Path, 0, PathLen); if (Path[PathLen - 1] != (byte)'/') { Path[PathLen++] = (byte)'/'; } PathOffset = PathLen; } else { Path = new byte[DEFAULT_PATH_SIZE]; PathOffset = 0; } }
private static int AlreadyMatch(AbstractTreeIterator a, AbstractTreeIterator b) { while (true) { AbstractTreeIterator ap = a._parent; AbstractTreeIterator bp = b._parent; if (ap == null || bp == null) { return(0); } if (ap.Matches == bp.Matches) { return(a.PathOffset); } a = ap; b = bp; } }
/** * Compare two tree's current ObjectId values for equality. * * @param nthA * first tree to compare the object id from. * @param nthB * second tree to compare the object id from. * @return result of * <code>getObjectId(nthA).Equals(getObjectId(nthB))</code>. * @see #getObjectId(int) */ public bool idEqual(int nthA, int nthB) { AbstractTreeIterator ch = _currentHead; AbstractTreeIterator a = _trees[nthA]; AbstractTreeIterator b = _trees[nthB]; if (a.Matches == ch && b.Matches == ch) { return(a.idEqual(b)); } if (a.Matches != ch && b.Matches != ch) { // If neither tree matches the current path node then neither // tree has this entry. In such case the ObjectId is zero(), // and zero() is always equal to zero(). // return(true); } return(false); }
/** * Test if the supplied path matches (being suffix of) the current entry's * path. * <para /> * This method tests that the supplied path is exactly equal to the current * entry, or is relative to one of entry's parent directories. It is faster * to use this method then to use {@link #getPathString()} to first Create * a String object, then test <code>endsWith</code> or some other type of * string match function. * * @param p * path buffer to test. * @param pLen * number of bytes from <code>buf</code> to test. * @return true if p is suffix of the current path; * false if otherwise */ public bool isPathSuffix(byte[] p, int pLen) { if (p == null) { throw new ArgumentNullException("p"); } AbstractTreeIterator t = _currentHead; byte[] c = t.Path; int cLen = t.PathLen; int ci; for (ci = 1; ci < cLen && ci < pLen; ci++) { if (c[cLen - ci] != p[pLen - ci]) { return(false); } } return(true); }
public virtual AbstractTreeIterator min() { int i = 0; AbstractTreeIterator minRef = _trees[i]; while (minRef.eof() && ++i < _trees.Length) { minRef = _trees[i]; } if (minRef.eof()) { return(minRef); } minRef.Matches = minRef; while (++i < _trees.Length) { AbstractTreeIterator t = _trees[i]; if (t.eof()) { continue; } int cmp = t.pathCompare(minRef); if (cmp < 0) { t.Matches = t; minRef = t; } else if (cmp == 0) { t.Matches = minRef; } } return(minRef); }
private void ExitSubtree() { _depth--; for (int i = 0; i < _trees.Length; i++) { _trees[i] = _trees[i].Parent; } AbstractTreeIterator minRef = null; foreach (AbstractTreeIterator t in _trees) { if (t.Matches != t) { continue; } if (minRef == null || t.pathCompare(minRef) < 0) { minRef = t; } } _currentHead = minRef; }
/// <summary> /// Check if the current entry of both iterators has the same id. /// <para /> /// This method is faster than <see cref="getEntryObjectId()"/>as it does not /// require copying the bytes out of the buffers. A direct <see cref="idBuffer"/> /// compare operation is performed. /// </summary> /// <param name="otherIterator">the other iterator to test against.</param> /// <returns> /// true if both iterators have the same object id; false otherwise. /// </returns> public virtual bool idEqual(AbstractTreeIterator otherIterator) { if (otherIterator == null) throw new ArgumentNullException ("otherIterator"); return ObjectId.Equals(idBuffer(), idOffset(), otherIterator.idBuffer(), otherIterator.idOffset()); }
/// <summary> /// Create an iterator for a subtree of an existing iterator. /// </summary> /// <param name="p">parent tree iterator.</param> protected AbstractTreeIterator(AbstractTreeIterator p) { _parent = p; Path = p.Path; PathOffset = p.PathLen + 1; try { Path[PathOffset - 1] = (byte)'/'; } catch (IndexOutOfRangeException) { growPath(p.PathLen); Path[PathOffset - 1] = (byte)'/'; } }
/// <summary> /// Check if the current entry of both iterators has the same id. /// <para /> /// This method is faster than <see cref="getEntryObjectId()"/>as it does not /// require copying the bytes out of the buffers. A direct <see cref="idBuffer"/> /// compare operation is performed. /// </summary> /// <param name="otherIterator">the other iterator to test against.</param> /// <returns> /// true if both iterators have the same object id; false otherwise. /// </returns> public virtual bool idEqual(AbstractTreeIterator otherIterator) { return ObjectId.Equals(idBuffer(), idOffset(), otherIterator.idBuffer(), otherIterator.idOffset()); }
/// <summary> /// Create an iterator for a subtree of an existing iterator. /// The caller is responsible for setting up the path of the child iterator. /// </summary> /// <param name="p">parent tree iterator.</param> /// <param name="childPath"> /// Path array to be used by the child iterator. This path must /// contain the path from the top of the walk to the first child /// and must end with a '/'. /// </param> /// <param name="childPathOffset"> /// position within <code>childPath</code> where the child can /// insert its data. The value at /// <code>childPath[childPathOffset-1]</code> must be '/'. /// </param> protected AbstractTreeIterator(AbstractTreeIterator p, byte[] childPath, int childPathOffset) { _parent = p; Path = childPath; PathOffset = childPathOffset; }
private static string NameOf(AbstractTreeIterator i) { return RawParseUtils.decode(Constants.CHARSET, i.Path, 0, i.PathLen); }
/// <summary> /// Compare the path of this current entry to another iterator's entry. /// </summary> /// <param name="treeIterator"> /// The other iterator to compare the path against. /// </param> /// <returns> /// return -1 if this entry sorts first; 0 if the entries are equal; 1 if /// <paramref name="treeIterator"/>'s entry sorts first. /// </returns> public int pathCompare(AbstractTreeIterator treeIterator) { return pathCompare(treeIterator, treeIterator.Mode); }
/// <summary> /// Create a new iterator with no parent. /// </summary> protected AbstractTreeIterator() { _parent = null; Path = new byte[DEFAULT_PATH_SIZE]; PathOffset = 0; }
private CanonicalTreeParser(AbstractTreeIterator p) : base(p) { }
/// <summary> /// Compare the path of this current entry to another iterator's entry. /// </summary> /// <param name="treeIterator"> /// The other iterator to compare the path against. /// </param> /// <param name="treeIteratorMode"> /// The other iterator <see cref="FileMode"/> bits. /// </param> /// <returns> /// return -1 if this entry sorts first; 0 if the entries are equal; 1 if /// <paramref name="treeIterator"/>'s entry sorts first. /// </returns> public int pathCompare(AbstractTreeIterator treeIterator, int treeIteratorMode) { if (treeIterator == null) throw new ArgumentNullException ("treeIterator"); byte[] a = Path; byte[] b = treeIterator.Path; int aLen = PathLen; int bLen = treeIterator.PathLen; // Its common when we are a subtree for both parents to match; // when this happens everything in _path[0..cPos] is known to // be equal and does not require evaluation again. // int cPos = AlreadyMatch(this, treeIterator); for (; cPos < aLen && cPos < bLen; cPos++) { int cmp = (a[cPos] & 0xff) - (b[cPos] & 0xff); if (cmp != 0) { return cmp; } } if (cPos < aLen) { return (a[cPos] & 0xff) - LastPathChar(treeIteratorMode); } if (cPos < bLen) { return LastPathChar(Mode) - (b[cPos] & 0xff); } return LastPathChar(Mode) - LastPathChar(treeIteratorMode); }
private static int AlreadyMatch(AbstractTreeIterator a, AbstractTreeIterator b) { while (true) { AbstractTreeIterator ap = a._parent; AbstractTreeIterator bp = b._parent; if (ap == null || bp == null) { return 0; } if (ap.Matches == bp.Matches) { return a.PathOffset; } a = ap; b = bp; } }
/// <summary> /// Check if the current entry of both iterators has the same id. /// <para /> /// This method is faster than <see cref="getEntryObjectId()"/>as it does not /// require copying the bytes out of the buffers. A direct <see cref="idBuffer"/> /// compare operation is performed. /// </summary> /// <param name="otherIterator">the other iterator to test against.</param> /// <returns> /// true if both iterators have the same object id; false otherwise. /// </returns> public virtual bool idEqual(AbstractTreeIterator otherIterator) { return(ObjectId.Equals(idBuffer(), idOffset(), otherIterator.idBuffer(), otherIterator.idOffset())); }
private CanonicalTreeParser(AbstractTreeIterator p) : base(p) { }
/// <summary> /// Create an iterator for a subtree of an existing iterator. /// The caller is responsible for setting up the path of the child iterator. /// </summary> /// <param name="p">parent tree iterator.</param> /// <param name="childPath"> /// Path array to be used by the child iterator. This path must /// contain the path from the top of the walk to the first child /// and must end with a '/'. /// </param> /// <param name="childPathOffset"> /// position within <code>childPath</code> where the child can /// insert its data. The value at /// <code>childPath[childPathOffset-1]</code> must be '/'. /// </param> protected AbstractTreeIterator(AbstractTreeIterator p, byte[] childPath, int childPathOffset) { _parent = p; Path = childPath; PathOffset = childPathOffset; }
/// <summary> /// Create an iterator for a subtree of an existing iterator. /// </summary> /// <param name="p">parent tree iterator.</param> protected AbstractTreeIterator(AbstractTreeIterator p) { if (p == null) throw new ArgumentNullException ("p"); _parent = p; Path = p.Path; PathOffset = p.PathLen + 1; try { Path[PathOffset - 1] = (byte)'/'; } catch (IndexOutOfRangeException) { growPath(p.PathLen); Path[PathOffset - 1] = (byte)'/'; } }
/// <summary> /// Create a new iterator with no parent and a prefix. /// /// The prefix path supplied is inserted in front of all paths generated by /// this iterator. It is intended to be used when an iterator is being /// created for a subsection of an overall repository and needs to be /// combined with other iterators that are created to run over the entire /// repository namespace. /// </summary> /// <param name="prefix"> /// position of this iterator in the repository tree. The value /// may be null or the empty array to indicate the prefix is the /// root of the repository. A trailing slash ('/') is /// automatically appended if the prefix does not end in '/'. /// </param> protected AbstractTreeIterator(byte[] prefix) { _parent = null; if (prefix != null && prefix.Length > 0) { PathLen = prefix.Length; Path = new byte[Math.Max(DEFAULT_PATH_SIZE, PathLen + 1)]; Array.Copy(prefix, 0, Path, 0, PathLen); if (Path[PathLen - 1] != (byte)'/') { Path[PathLen++] = (byte)'/'; } PathOffset = PathLen; } else { Path = new byte[DEFAULT_PATH_SIZE]; PathOffset = 0; } }
/// <summary> /// Create a new iterator with no parent. /// </summary> protected AbstractTreeIterator() { _parent = null; Path = new byte[DEFAULT_PATH_SIZE]; PathOffset = 0; }
/// <summary> /// Compare the path of this current entry to another iterator's entry. /// </summary> /// <param name="treeIterator"> /// The other iterator to compare the path against. /// </param> /// <returns> /// return -1 if this entry sorts first; 0 if the entries are equal; 1 if /// <paramref name="treeIterator"/>'s entry sorts first. /// </returns> public int pathCompare(AbstractTreeIterator treeIterator) { if (treeIterator == null) throw new ArgumentNullException ("treeIterator"); return pathCompare(treeIterator, treeIterator.Mode); }