19 using System.Collections.Generic;
21 namespace Deveel.Data.Index {
67 Blocks =
new List<IIndexBlock<T>>(10);
72 foreach (var block
in blocks) {
80 foreach (var value
in values) {
89 var blockIndex = (BlockIndexBase<T>) index;
91 var inBlocks = blockIndex.Blocks;
92 int inBlocksCount = inBlocks.Count;
94 for (
int i = 0; i < inBlocksCount; ++i) {
96 var block = inBlocks[i];
98 var destBlock = InsertBlock(i, NewBlock());
100 block.CopyTo(destBlock);
104 Count = blockIndex.Count;
107 var i = index.GetEnumerator();
108 while (i.MoveNext()) {
114 if (index.IsReadOnly)
118 protected List<IIndexBlock<T>> Blocks {
get;
private set; }
120 public bool IsReadOnly {
get; set; }
122 public int Count {
get;
private set; }
124 public T
this[
int index] {
126 int size = Blocks.Count;
128 for (
int i = 0; i < size; ++i) {
129 var block = Blocks[i];
130 int bsize = block.Count;
131 if (index >= start && index < start + bsize)
132 return block[index - start];
137 throw new ArgumentOutOfRangeException(
"index");
166 Blocks.Insert(index, block);
169 if (index + 1 < Blocks.Count) {
170 var nextBlock = Blocks[index + 1];
171 block.
Next = nextBlock;
172 nextBlock.Previous = block;
179 var prevBlock = Blocks[index - 1];
181 prevBlock.Next = block;
197 if (index + 1 < Blocks.Count) {
198 newNext = Blocks[index + 1];
201 newPrev = Blocks[index - 1];
204 if (newPrev != null) {
205 newPrev.
Next = newNext;
207 if (newNext != null) {
211 var beenRemoved = Blocks[index];
213 OnDeleteBlock(beenRemoved);
224 block.
Insert(value, position);
233 int moveSize = (block.
Count/7) - 1;
239 if (blockIndex < Blocks.Count - 1) {
240 var nextBlock = Blocks[blockIndex + 1];
242 if (nextBlock.CanContain(moveSize)) {
246 moveTo = InsertBlock(blockIndex + 1, NewBlock());
251 moveTo = InsertBlock(blockIndex + 1, NewBlock());
256 block.
MoveTo(moveTo, 0, moveSize);
271 var oldValue = block.
RemoveAt(position);
275 if (block.
IsEmpty && Blocks.Count > 1)
276 RemoveBlock(blockIndex);
295 int high = Blocks.Count - 1;
297 while (low <= high) {
298 int mid = (low + high)/2;
299 var block = Blocks[mid];
332 int high = Blocks.Count - 1;
334 while (low <= high) {
335 if (high - low <= 2) {
336 for (
int i = high; i >= low; --i) {
337 var block1 = Blocks[i];
347 int mid = (low + high)/2;
348 var block = Blocks[mid];
385 int high = Blocks.Count - 1;
387 while (low <= high) {
389 if (high - low <= 2) {
390 for (
int i = low; i <= high; ++i) {
391 var block1 = Blocks[i];
398 return -(high + 1) - 1;
401 int mid = (low + high)/2;
402 var block = Blocks[mid];
422 return x.CompareTo(y) <= 0;
426 return x.CompareTo(y) >= 0;
430 return x.CompareTo(y) > 0;
434 return x.CompareTo(y) < 0;
450 int high = Blocks.Count - 1;
452 while (low <= high) {
454 if (high - low <= 2) {
455 for (
int i = high; i >= low; --i) {
456 var block1 = Blocks[i];
457 if (IsSmallerOrEqual(block1.Bottom, val)) {
458 if (IsGreaterOrEqual(block1.Top, val))
466 int mid = (low + high)/2;
467 var block = Blocks[mid];
470 if (IsGreater(block.Bottom,val)) {
474 else if (IsSmaller(block.Top, val)) {
501 throw new InvalidOperationException(
"Index is read-only.");
506 if (Blocks.Count == 0) {
507 InsertBlock(0, NewBlock());
521 if (array.Length < length || (offset + length) > Count)
522 throw new InvalidOperationException(
"Size mismatch.");
524 foreach (var block
in Blocks) {
525 offset += block.CopyTo(array, offset);
532 int size = Blocks.Count;
534 for (
int i = 0; i < size; ++i) {
535 var block = Blocks[i];
536 int bsize = block.Count;
537 if (index >= start && index <= start + bsize) {
538 InsertIntoBlock(value, i, block, index - start);
544 throw new ArgumentOutOfRangeException(
"index");
547 public void Add(T value) {
550 int size = Blocks.Count;
551 var block = Blocks[size - 1];
552 InsertIntoBlock(value, size - 1, block, block.Count);
558 int size = Blocks.Count;
560 for (
int i = 0; i < size; ++i) {
561 var block = Blocks[i];
562 int bsize = block.Count;
563 if (index >= start && index <= start + bsize) {
564 return RemoveFromBlock(i, block, index - start);
569 throw new ArgumentOutOfRangeException(
"index");
573 int blockIndex = FindLastBlock(value);
580 var block = Blocks[blockIndex];
583 return block.SearchLast(value) >= 0;
589 int blockIndex = FindLastBlock(value);
591 if (blockIndex < 0) {
594 blockIndex = (-(blockIndex + 1)) - 1;
595 if (blockIndex < 0) {
601 var block = Blocks[blockIndex];
604 int i = block.SearchLast(value);
614 InsertIntoBlock(value, blockIndex, block, i);
620 int blockIndex = FindLastBlock(value);
622 if (blockIndex < 0) {
625 blockIndex = (-(blockIndex + 1)) - 1;
626 if (blockIndex < 0) {
632 var block = Blocks[blockIndex];
635 int i = block.SearchLast(value);
644 InsertIntoBlock(value, blockIndex, block, i);
653 int blockIndex = FindLastBlock(value);
655 if (blockIndex < 0) {
658 blockIndex = (-(blockIndex + 1)) - 1;
659 if (blockIndex < 0) {
665 var block = Blocks[blockIndex];
668 int i = block.SearchLast(value);
676 var valRemoved = RemoveFromBlock(blockIndex, block, i);
677 if (!value.Equals(valRemoved))
678 throw new InvalidOperationException(
"Incorrect value removed.");
685 int blockIndex = FindBlockContaining(key, comparer);
692 var block = Blocks[blockIndex];
695 return block.BinarySearch(key, comparer) >= 0;
701 int blockIndex = FindLastBlock(key, comparer);
703 if (blockIndex < 0) {
706 blockIndex = (-(blockIndex + 1)) - 1;
707 if (blockIndex < 0) {
713 var block = Blocks[blockIndex];
716 int i = block.SearchLast(key, comparer);
726 InsertIntoBlock(value, blockIndex, block, i);
733 int origBlockIndex = FindFirstBlock(key, comparer);
734 int blockIndex = origBlockIndex;
735 int lastBlockIndex = Blocks.Count - 1;
739 throw new InvalidOperationException(
"Value (" + key +
") was not found in the list.");
741 var block = Blocks[blockIndex];
742 int i = block.IndexOf(value);
746 if (blockIndex > lastBlockIndex)
747 throw new InvalidOperationException(
"Value (" + key +
") was not found in the list.");
749 block = Blocks[blockIndex];
751 i = block.IndexOf(value);
755 return RemoveFromBlock(blockIndex, block, i);
759 int blockIndex = FindLastBlock(key, comparer);
762 if (blockIndex < 0) {
764 blockIndex = (-(blockIndex + 1));
768 var block = Blocks[blockIndex];
771 sr = block.SearchLast(key, comparer);
775 for (
int i = 0; i < blockIndex; ++i) {
776 var block = Blocks[i];
777 offset += block.Count;
780 return sr >= 0 ? offset + sr : -offset + sr;
784 int blockNum = FindFirstBlock(key, comparer);
789 blockNum = (-(blockNum + 1));
793 var block = Blocks[blockNum];
796 sr = block.SearchFirst(key, comparer);
800 for (
int i = 0; i < blockNum; ++i) {
801 var block = Blocks[i];
802 offset += block.Count;
805 return sr >= 0 ? offset + sr : -offset + sr;
809 return GetEnumerator(0, Count - 1);
813 return new Enumerator(
this, startOffset, endOffset);
816 IEnumerator<T> IEnumerable<T>.GetEnumerator() {
817 return GetEnumerator();
820 IEnumerator IEnumerable.GetEnumerator() {
821 return GetEnumerator();
840 this.startOffset = startOffset;
841 this.endOffset = endOffset;
847 int size = index.Blocks.Count;
849 for (blockIndex = 0; blockIndex < size; ++blockIndex) {
850 var block = index.Blocks[blockIndex];
851 int bsize = block.Count;
852 if (offset < start + bsize) {
853 blockOffset = offset - start;
857 currentBlock = block;
858 currentBlockSize = bsize;
864 throw new IndexOutOfRangeException(
"'index' (" + offset +
") out of bounds.");
873 if (currentOffset < endOffset) {
876 if (++blockOffset >= currentBlockSize) {
878 currentBlock = index.Blocks[blockIndex];
879 currentBlockSize = currentBlock.
Count;
890 currentOffset = startOffset - 1;
892 if (endOffset >= startOffset) {
894 SetupVars(startOffset - 1);
899 get {
return currentBlock[blockOffset]; }
902 object IEnumerator.Current {
903 get {
return Current; }
909 if (blockOffset < 0) {
910 if (blockIndex > 0) {
912 currentBlock = index.Blocks[blockIndex];
913 currentBlockSize = currentBlock.
Count;
914 blockOffset = currentBlock.
Count - 1;
920 if (currentOffset > startOffset) {
929 index.CheckImmutable();
934 int origBlockCount = index.Blocks.Count;
935 index.RemoveFromBlock(blockIndex, currentBlock, blockOffset);
938 if (origBlockCount == index.Blocks.Count) {
944 SetupVars(currentOffset);
void InsertSort(object key, T value, IIndexComparer< T > comparer)
static bool IsGreaterOrEqual(T x, T y)
BlockIndexBase(IEnumerable< T > values)
void Insert(T index, int value)
Inserts an element to the block at the given index.
IIndexBlock< T > currentBlock
T RemoveAt(int index)
Removes the element at the given index from the block.
int SearchFirst(object key, IIndexComparer< T > comparer)
int FindLastBlock(T val)
Uses a binary search algorithm to quickly determine the index of the IIndexBlock within 'blocks' o...
void CopyToArray(T[] array, int offset, int length)
Copies the data from each block into the given int[] array.
Enumerates the elements of an index.
A comparer that is used within IIndex to compares two values which are indices to data that is bei...
IIndexEnumerator< T > GetEnumerator()
IIndexBlock< T > Next
Gets or sets the next block in the hash.
void Insert(int index, T value)
IIndexEnumerator< T > GetEnumerator(int startOffset, int endOffset)
BlockIndexBase(IEnumerable< IIndexBlock< T >> blocks)
T RemoveSort(object key, T value, IIndexComparer< T > comparer)
IIndexBlock< T > Previous
Gets or sets the previous block in the hash.
readonly BlockIndexBase< T > index
bool UniqueInsertSort(T value)
static bool IsSmallerOrEqual(T x, T y)
Represents a dynamic object that encapsulates a defined SqlType and a compatible constant ISqlObject ...
int CompareValue(T index, DataObject value)
Compares a value contained in the underlying index at the given position and the
static bool IsGreater(T x, T y)
bool IsFull
Gets a value indicating if the block is full.
Enumerator(BlockIndexBase< T > index, int startOffset, int endOffset)
void MoveTo(IIndexBlock< T > destBlock, int destIndex, int count)
A block contained in a BlockIndex.
bool IsEmpty
Gets a value indicating if the block is empty.
An interface for querying and accessing an index of primitive integers.
virtual void OnDeleteBlock(IIndexBlock< T > block)
Called when the class decides the given IIndexBlock is no longer needed.
void InsertIntoBlock(T value, int blockIndex, IIndexBlock< T > block, int position)
Inserts a value in the given block position in the list.
An implementation of an index of values that are stored across an array of blocks.
void RemoveBlock(int index)
Removes a block from the given position in the index.
bool Contains(object key, IIndexComparer< T > comparer)
int FindBlockContaining(object key, IIndexComparer< T > comparer)
Uses a binary search algorithm to quickly determine the index of the IIndexBlock within 'blocks' o...
void SetupVars(int offset)
void CheckImmutable()
Checks if the current index is mutable.
int FindLastBlock(object key, IIndexComparer< T > comparer)
Uses a binary search algorithm to quickly determine the index of the IIndexBlock within 'blocks' o...
int FindFirstBlock(object key, IIndexComparer< T > c)
Uses a binary search algorithm to quickly determine the index of the IIndexBlock within 'blocks' o...
BlockIndexBase(IIndex< T > index)
static bool IsSmaller(T x, T y)
int SearchLast(object key, IIndexComparer< T > comparer)
bool MoveBack()
Reverses the direction of the enumerator to the previous element within the list. /summary> returns> ...
T RemoveFromBlock(int blockIndex, IIndexBlock< T > block, int position)
Removes the value from the given position in the specified block.
IIndexBlock< T > InsertBlock(int index, IIndexBlock< T > block)
Inserts a block at the given position in the index.