예제 #1
0
        public ContainerEntry NearestIndexedContainer(long position)
        {
            // We want the first container which ends after the position and starts before it.

            // All containers ending before position can't contain it.
            // Find the first container ending after position.
            int indexAfter = IndexOfFirstEndingAfter(position);

            // If position was after the last container end, return empty
            if (indexAfter >= _index.Count)
            {
                return(ContainerEntry.Empty);
            }

            // Find the first ancestor of the container which starts before position
            ContainerEntry candidate = this[indexAfter];

            while (candidate.StartByteOffset > position)
            {
                candidate = Parent(candidate);
            }

            // Since all ancestors of indexed containers are indexed, this must be the closest indexed ancestor.
            return(candidate);
        }
예제 #2
0
        public void Skip()
        {
            // If this container is indexed, skip by seeking
            if (_containerIndex != null)
            {
                ContainerEntry entry = _containerIndex.NearestIndexedContainer(BytesRead);

                if (entry.StartByteOffset == BytesRead)
                {
                    _reader.Seek(entry.EndByteOffset, SeekOrigin.Begin);
                    return;
                }
            }

            // Record depth
            long start = BytesRead;
            int  depth = _currentDepth;

            // Read one token
            Read();

            // If it wasn't a container, we're done
            if (depth == _currentDepth)
            {
                return;
            }

            SkipRest();
            long lengthSkipped = BytesRead - start;
        }
예제 #3
0
 public ContainerEntry Parent(ContainerEntry entry)
 {
     if (entry.ParentIndex < 0 || entry.ParentIndex >= _index.Count)
     {
         return(ContainerEntry.Empty);
     }
     return(_index[entry.ParentIndex]);
 }
예제 #4
0
        public int Depth(ContainerEntry entry)
        {
            int depth = 0;

            ContainerEntry ancestor = entry;

            while (ancestor.Index != -1)
            {
                depth++;
                ancestor = Parent(ancestor);
            }

            return(depth);
        }
예제 #5
0
        public void End(long containerEndOffset)
        {
            ContainerEntry entry = new ContainerEntry(_currentStack.Pop(), containerEndOffset, _index.Count);
            int            depth = _currentStack.Count;

            // Index this container if it's long enough, it's far enough away from the last indexed container, or if we indexed a descendant of it
            if (entry.ByteLength >= ContainerLengthCutoff ||
                containerEndOffset - _lastIndexedEnd >= ContainerLengthCutoff ||
                _mustIndexDepth == depth)
            {
                _index.Add(entry);
                _lastIndexedEnd = containerEndOffset;
                _mustIndexDepth = depth - 1;
            }
        }
예제 #6
0
        public void Read(BionReader reader)
        {
            _index.Clear();
            reader.Read(BionToken.StartArray);

            // Read the Container Index
            long lastEndPosition = 0;

            while (reader.Read())
            {
                if (reader.TokenType != BionToken.Integer)
                {
                    break;
                }
                long endPosition = lastEndPosition + reader.CurrentInteger();

                reader.Read(BionToken.Integer);
                long byteLength = reader.CurrentInteger();

                _index.Add(new ContainerEntry(endPosition - byteLength, endPosition, _index.Count));
                lastEndPosition = endPosition;
            }

            // Reconstruct the hierarchy
            for (int i = _index.Count - 2; i >= 0; --i)
            {
                ContainerEntry current = _index[i];

                // Find the parent - the first container which starts before this one
                int parentIndex = i + 1;
                while (parentIndex != -1)
                {
                    if (_index[parentIndex].StartByteOffset < current.StartByteOffset)
                    {
                        current.ParentIndex = parentIndex;
                        _index[i]           = current;
                        break;
                    }

                    parentIndex = _index[parentIndex].ParentIndex;
                }
            }

            // Size exact
            _index.Capacity = _index.Count;
        }
예제 #7
0
        public ContainerEntry AncestorAtDepth(ContainerEntry entry, int depth)
        {
            int entryDepth = Depth(entry);

            if (entryDepth < depth)
            {
                return(ContainerEntry.Empty);
            }

            int            currentDepth = entryDepth;
            ContainerEntry ancestor     = entry;

            while (currentDepth != depth)
            {
                ancestor = Parent(ancestor);
                currentDepth--;
            }

            return(ancestor);
        }