DeveelDB  20151217
complete SQL database system, primarly developed for .NET/Mono frameworks
BlockIndexBase_T.cs
Go to the documentation of this file.
1 //
2 // Copyright 2010-2015 Deveel
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 using System;
18 using System.Collections;
19 using System.Collections.Generic;
20 
21 namespace Deveel.Data.Index {
63  public abstract class BlockIndexBase<T> : IIndex<T> where T : IComparable<T>, IEquatable<T> {
64  protected BlockIndexBase() {
65  Count = 0;
66  IsReadOnly = false;
67  Blocks = new List<IIndexBlock<T>>(10);
68  }
69 
70  protected BlockIndexBase(IEnumerable<IIndexBlock<T>> blocks)
71  : this() {
72  foreach (var block in blocks) {
73  Blocks.Add(block);
74  Count += block.Count;
75  }
76  }
77 
78  protected BlockIndexBase(IEnumerable<T> values)
79  : this() {
80  foreach (var value in values) {
81  Add(value);
82  }
83  }
84 
85  protected BlockIndexBase(IIndex<T> index)
86  : this() {
87  if (index is BlockIndexBase<T>) {
88  // Optimization for when the input list is a BlockIntegerList
89  var blockIndex = (BlockIndexBase<T>) index;
90 
91  var inBlocks = blockIndex.Blocks;
92  int inBlocksCount = inBlocks.Count;
93  // For each block in 'blockIndex'
94  for (int i = 0; i < inBlocksCount; ++i) {
95  // get the block.
96  var block = inBlocks[i];
97  // Insert a new block in this object.
98  var destBlock = InsertBlock(i, NewBlock());
99  // Copy the contents of the source block to the new destination block.
100  block.CopyTo(destBlock);
101  }
102 
103  // Set the size of the list
104  Count = blockIndex.Count; //count;
105  } else {
106  // The case when IIntegerList type is not known
107  var i = index.GetEnumerator();
108  while (i.MoveNext()) {
109  Add(i.Current);
110  }
111  }
112 
113  // If the given list is immutable then set this list to immutable
114  if (index.IsReadOnly)
115  IsReadOnly = true;
116  }
117 
118  protected List<IIndexBlock<T>> Blocks { get; private set; }
119 
120  public bool IsReadOnly { get; set; }
121 
122  public int Count { get; private set; }
123 
124  public T this[int index] {
125  get {
126  int size = Blocks.Count;
127  int start = 0;
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];
133 
134  start += bsize;
135  }
136 
137  throw new ArgumentOutOfRangeException("index");
138  }
139  }
140 
145  protected abstract IIndexBlock<T> NewBlock();
146 
155  protected virtual void OnDeleteBlock(IIndexBlock<T> block) {
156  }
157 
158 
165  private IIndexBlock<T> InsertBlock(int index, IIndexBlock<T> block) {
166  Blocks.Insert(index, block);
167 
168  // Point to next in the list.
169  if (index + 1 < Blocks.Count) {
170  var nextBlock = Blocks[index + 1];
171  block.Next = nextBlock;
172  nextBlock.Previous = block;
173  } else {
174  block.Next = null;
175  }
176 
177  // Point to previous in the list.
178  if (index > 0) {
179  var prevBlock = Blocks[index - 1];
180  block.Previous = prevBlock;
181  prevBlock.Next = block;
182  } else {
183  block.Previous = null;
184  }
185 
186  return block;
187  }
188 
193  private void RemoveBlock(int index) {
194  // Alter linked list pointers.
195  IIndexBlock<T> newPrev = null;
196  IIndexBlock<T> newNext = null;
197  if (index + 1 < Blocks.Count) {
198  newNext = Blocks[index + 1];
199  }
200  if (index > 0) {
201  newPrev = Blocks[index - 1];
202  }
203 
204  if (newPrev != null) {
205  newPrev.Next = newNext;
206  }
207  if (newNext != null) {
208  newNext.Previous = newPrev;
209  }
210 
211  var beenRemoved = Blocks[index];
212  Blocks.RemoveAt(index);
213  OnDeleteBlock(beenRemoved);
214  }
215 
223  private void InsertIntoBlock(T value, int blockIndex, IIndexBlock<T> block, int position) {
224  block.Insert(value, position);
225 
226  ++Count;
227  // Is the block full?
228  if (block.IsFull) {
229  // We need to move half of the data out of this block into either the
230  // next block or create a new block to store it.
231 
232  // The size that we going to zap out of this block.
233  int moveSize = (block.Count/7) - 1;
234 
235  // The block to move half the data from this block.
236  IIndexBlock<T> moveTo;
237 
238  // Is there a next block?
239  if (blockIndex < Blocks.Count - 1) {
240  var nextBlock = Blocks[blockIndex + 1];
241  // Yes, can this block contain half the values from this block?
242  if (nextBlock.CanContain(moveSize)) {
243  moveTo = nextBlock;
244  } else {
245  // Can't contain so insert a new block.
246  moveTo = InsertBlock(blockIndex + 1, NewBlock());
247  }
248 
249  } else {
250  // No next block so create a new block
251  moveTo = InsertBlock(blockIndex + 1, NewBlock());
252  }
253 
254  // 'moveTo' should be set to the block we are to use to move half the
255  // data from this block.
256  block.MoveTo(moveTo, 0, moveSize);
257  }
258  }
259 
270  private T RemoveFromBlock(int blockIndex, IIndexBlock<T> block, int position) {
271  var oldValue = block.RemoveAt(position);
272  --Count;
273  // If we have emptied out this block, then we should remove it from the
274  // list.
275  if (block.IsEmpty && Blocks.Count > 1)
276  RemoveBlock(blockIndex);
277 
278  return oldValue;
279  }
280 
290  private int FindBlockContaining(object key, IIndexComparer<T> comparer) {
291  if (Count == 0)
292  return -1;
293 
294  int low = 0;
295  int high = Blocks.Count - 1;
296 
297  while (low <= high) {
298  int mid = (low + high)/2;
299  var block = Blocks[mid];
300 
301  // Is what we are searching for lower than the bottom value?
302  if (comparer.CompareValue(block.Bottom, (DataObject) key) > 0) {
303  high = mid - 1;
304  }
305  // No, then is it greater than the highest value?
306  else if (comparer.CompareValue(block.Top, (DataObject) key) < 0) {
307  low = mid + 1;
308  }
309  // Must be inside this block then!
310  else {
311  return mid;
312  }
313  }
314 
315  return -(low + 1); // key not found.
316  }
317 
327  private int FindLastBlock(object key, IIndexComparer<T> comparer) {
328  if (Count == 0)
329  return -1;
330 
331  int low = 0;
332  int high = Blocks.Count - 1;
333 
334  while (low <= high) {
335  if (high - low <= 2) {
336  for (int i = high; i >= low; --i) {
337  var block1 = Blocks[i];
338  if (comparer.CompareValue(block1.Bottom, (DataObject) key) <= 0) {
339  if (comparer.CompareValue(block1.Top, (DataObject) key) >= 0)
340  return i;
341  return -(i + 1) - 1;
342  }
343  }
344  return -(low + 1);
345  }
346 
347  int mid = (low + high)/2;
348  var block = Blocks[mid];
349 
350  // Is what we are searching for lower than the bottom value?
351  if (comparer.CompareValue(block.Bottom, (DataObject) key) > 0) {
352  high = mid - 1;
353  }
354  // No, then is it greater than the highest value?
355  else if (comparer.CompareValue(block.Top, (DataObject) key) < 0) {
356  low = mid + 1;
357  }
358  // Equal, so highest must be someplace between mid and high.
359  else {
360  low = mid;
361  if (low == high) {
362  return low;
363  }
364  }
365  }
366 
367  return -(low + 1); // key not found.
368  }
369 
379  private int FindFirstBlock(object key, IIndexComparer<T> c) {
380  if (Count == 0) {
381  return -1;
382  }
383 
384  int low = 0;
385  int high = Blocks.Count - 1;
386 
387  while (low <= high) {
388 
389  if (high - low <= 2) {
390  for (int i = low; i <= high; ++i) {
391  var block1 = Blocks[i];
392  if (c.CompareValue(block1.Top, (DataObject) key) >= 0) {
393  if (c.CompareValue(block1.Bottom, (DataObject) key) <= 0)
394  return i;
395  return -(i + 1);
396  }
397  }
398  return -(high + 1) - 1;
399  }
400 
401  int mid = (low + high)/2;
402  var block = Blocks[mid];
403 
404  // Is what we are searching for lower than the bottom value?
405  if (c.CompareValue(block.Bottom, (DataObject) key) > 0) {
406  high = mid - 1;
407  }
408  // No, then is it greater than the highest value?
409  else if (c.CompareValue(block.Top, (DataObject) key) < 0) {
410  low = mid + 1;
411  }
412  // Equal, so highest must be someplace between mid and high.
413  else {
414  high = mid;
415  }
416  }
417 
418  return -(low + 1); // key not found.
419  }
420 
421  private static bool IsSmallerOrEqual(T x, T y) {
422  return x.CompareTo(y) <= 0;
423  }
424 
425  private static bool IsGreaterOrEqual(T x, T y) {
426  return x.CompareTo(y) >= 0;
427  }
428 
429  private static bool IsGreater(T x, T y) {
430  return x.CompareTo(y) > 0;
431  }
432 
433  private static bool IsSmaller(T x, T y) {
434  return x.CompareTo(y) < 0;
435  }
436 
444  private int FindLastBlock(T val) {
445  if (Count == 0) {
446  return -1;
447  }
448 
449  int low = 0;
450  int high = Blocks.Count - 1;
451 
452  while (low <= high) {
453 
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))
459  return i;
460  return -(i + 1) - 1;
461  }
462  }
463  return -(low + 1);
464  }
465 
466  int mid = (low + high)/2;
467  var block = Blocks[mid];
468 
469  // Is what we are searching for lower than the bottom value?
470  if (IsGreater(block.Bottom,val)) {
471  high = mid - 1;
472  }
473  // No, then is it greater than the highest value?
474  else if (IsSmaller(block.Top, val)) {
475  low = mid + 1;
476  }
477  // Equal, so highest must be someplace between mid and high.
478  else {
479  low = mid;
480  if (low == high) {
481  return low;
482  }
483  }
484  }
485 
486  return -(low + 1); // key not found.
487  }
488 
499  private void CheckImmutable() {
500  if (IsReadOnly)
501  throw new InvalidOperationException("Index is read-only.");
502 
503  // HACK: We have a side effect of checking whether the list is immutable.
504  // If the block list doesn't contain any entries we add one here. This
505  // hack reduces the memory requirements.
506  if (Blocks.Count == 0) {
507  InsertBlock(0, NewBlock());
508  }
509  }
510 
520  internal void CopyToArray(T[] array, int offset, int length) {
521  if (array.Length < length || (offset + length) > Count)
522  throw new InvalidOperationException("Size mismatch.");
523 
524  foreach (var block in Blocks) {
525  offset += block.CopyTo(array, offset);
526  }
527  }
528 
529  public void Insert(int index, T value) {
530  CheckImmutable();
531 
532  int size = Blocks.Count;
533  int start = 0;
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);
539  return;
540  }
541  start += bsize;
542  }
543 
544  throw new ArgumentOutOfRangeException("index");
545  }
546 
547  public void Add(T value) {
548  CheckImmutable();
549 
550  int size = Blocks.Count;
551  var block = Blocks[size - 1];
552  InsertIntoBlock(value, size - 1, block, block.Count);
553  }
554 
555  public T RemoveAt(int index) {
556  CheckImmutable();
557 
558  int size = Blocks.Count;
559  int start = 0;
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);
565  }
566  start += bsize;
567  }
568 
569  throw new ArgumentOutOfRangeException("index");
570  }
571 
572  public bool Contains(T value) {
573  int blockIndex = FindLastBlock(value);
574 
575  if (blockIndex < 0)
576  // We didn't find in the list, so return false.
577  return false;
578 
579  // We got a block, so find out if it's in the block or not.
580  var block = Blocks[blockIndex];
581 
582  // Find, if not there then return false.
583  return block.SearchLast(value) >= 0;
584  }
585 
586  public void InsertSort(T value) {
587  CheckImmutable();
588 
589  int blockIndex = FindLastBlock(value);
590 
591  if (blockIndex < 0) {
592  // Not found a block,
593  // The block to insert the value,
594  blockIndex = (-(blockIndex + 1)) - 1;
595  if (blockIndex < 0) {
596  blockIndex = 0;
597  }
598  }
599 
600  // We got a block, so find out if it's in the block or not.
601  var block = Blocks[blockIndex];
602 
603  // The point to insert in the block,
604  int i = block.SearchLast(value);
605  if (i < 0) {
606  i = -(i + 1);
607  } else {
608  i = i + 1;
609  // NOTE: A block can never become totally full so it's always okay to
610  // skip one ahead.
611  }
612 
613  // Insert value into the block,
614  InsertIntoBlock(value, blockIndex, block, i);
615  }
616 
617  public bool UniqueInsertSort(T value) {
618  CheckImmutable();
619 
620  int blockIndex = FindLastBlock(value);
621 
622  if (blockIndex < 0) {
623  // Not found a block,
624  // The block to insert the value,
625  blockIndex = (-(blockIndex + 1)) - 1;
626  if (blockIndex < 0) {
627  blockIndex = 0;
628  }
629  }
630 
631  // We got a block, so find out if it's in the block or not.
632  var block = Blocks[blockIndex];
633 
634  // The point to insert in the block,
635  int i = block.SearchLast(value);
636  if (i < 0) {
637  i = -(i + 1);
638  } else {
639  // This means we found the value in the given block, so return false.
640  return false;
641  }
642 
643  // Insert value into the block,
644  InsertIntoBlock(value, blockIndex, block, i);
645 
646  // Value inserted so return true.
647  return true;
648  }
649 
650  public bool RemoveSort(T value) {
651  CheckImmutable();
652 
653  int blockIndex = FindLastBlock(value);
654 
655  if (blockIndex < 0) {
656  // Not found a block,
657  // The block to remove the value,
658  blockIndex = (-(blockIndex + 1)) - 1;
659  if (blockIndex < 0) {
660  blockIndex = 0;
661  }
662  }
663 
664  // We got a block, so find out if it's in the block or not.
665  var block = Blocks[blockIndex];
666 
667  // The point to remove the block,
668  int i = block.SearchLast(value);
669  if (i < 0) {
670  // This means we can't found the value in the given block, so return
671  // false.
672  return false;
673  }
674 
675  // Remove value into the block,
676  var valRemoved = RemoveFromBlock(blockIndex, block, i);
677  if (!value.Equals(valRemoved))
678  throw new InvalidOperationException("Incorrect value removed.");
679 
680  // Value removed so return true.
681  return true;
682  }
683 
684  public bool Contains(object key, IIndexComparer<T> comparer) {
685  int blockIndex = FindBlockContaining(key, comparer);
686 
687  if (blockIndex < 0)
688  // We didn't find in the list, so return false.
689  return false;
690 
691  // We got a block, so find out if it's in the block or not.
692  var block = Blocks[blockIndex];
693 
694  // Find, if not there then return false.
695  return block.BinarySearch(key, comparer) >= 0;
696  }
697 
698  public void InsertSort(object key, T value, IIndexComparer<T> comparer) {
699  CheckImmutable();
700 
701  int blockIndex = FindLastBlock(key, comparer);
702 
703  if (blockIndex < 0) {
704  // Not found a block,
705  // The block to insert the value,
706  blockIndex = (-(blockIndex + 1)) - 1;
707  if (blockIndex < 0) {
708  blockIndex = 0;
709  }
710  }
711 
712  // We got a block, so find out if it's in the block or not.
713  var block = Blocks[blockIndex];
714 
715  // The point to insert in the block,
716  int i = block.SearchLast(key, comparer);
717  if (i < 0) {
718  i = -(i + 1);
719  } else {
720  i = i + 1;
721  // NOTE: A block can never become totally full so it's always okay to
722  // skip one ahead.
723  }
724 
725  // Insert value into the block,
726  InsertIntoBlock(value, blockIndex, block, i);
727  }
728 
729  public T RemoveSort(object key, T value, IIndexComparer<T> comparer) {
730  CheckImmutable();
731 
732  // Find the range of blocks that the value is in.
733  int origBlockIndex = FindFirstBlock(key, comparer);
734  int blockIndex = origBlockIndex;
735  int lastBlockIndex = Blocks.Count - 1;
736 
737  if (blockIndex < 0)
738  // Not found in a block,
739  throw new InvalidOperationException("Value (" + key + ") was not found in the list.");
740 
741  var block = Blocks[blockIndex];
742  int i = block.IndexOf(value);
743  while (i == -1) {
744  // If not found, go to next block
745  ++blockIndex;
746  if (blockIndex > lastBlockIndex)
747  throw new InvalidOperationException("Value (" + key + ") was not found in the list.");
748 
749  block = Blocks[blockIndex];
750  // Try and find the value within this block
751  i = block.IndexOf(value);
752  }
753 
754  // Remove value from the block,
755  return RemoveFromBlock(blockIndex, block, i);
756  }
757 
758  public int SearchLast(object key, IIndexComparer<T> comparer) {
759  int blockIndex = FindLastBlock(key, comparer);
760  int sr;
761 
762  if (blockIndex < 0) {
763  // Guarenteed not found in any blocks so return start of insert block
764  blockIndex = (-(blockIndex + 1)); // - 1;
765  sr = -1;
766  } else {
767  // We got a block, so find out if it's in the block or not.
768  var block = Blocks[blockIndex];
769 
770  // Try and find it in the block,
771  sr = block.SearchLast(key, comparer);
772  }
773 
774  int offset = 0;
775  for (int i = 0; i < blockIndex; ++i) {
776  var block = Blocks[i];
777  offset += block.Count;
778  }
779 
780  return sr >= 0 ? offset + sr : -offset + sr;
781  }
782 
783  public int SearchFirst(object key, IIndexComparer<T> comparer) {
784  int blockNum = FindFirstBlock(key, comparer);
785  int sr;
786 
787  if (blockNum < 0) {
788  // Guarenteed not found in any blocks so return start of insert block
789  blockNum = (-(blockNum + 1)); // - 1;
790  sr = -1;
791  } else {
792  // We got a block, so find out if it's in the block or not.
793  var block = Blocks[blockNum];
794 
795  // Try and find it in the block,
796  sr = block.SearchFirst(key, comparer);
797  }
798 
799  int offset = 0;
800  for (int i = 0; i < blockNum; ++i) {
801  var block = Blocks[i];
802  offset += block.Count;
803  }
804 
805  return sr >= 0 ? offset + sr : -offset + sr;
806  }
807 
809  return GetEnumerator(0, Count - 1);
810  }
811 
812  public IIndexEnumerator<T> GetEnumerator(int startOffset, int endOffset) {
813  return new Enumerator(this, startOffset, endOffset);
814  }
815 
816  IEnumerator<T> IEnumerable<T>.GetEnumerator() {
817  return GetEnumerator();
818  }
819 
820  IEnumerator IEnumerable.GetEnumerator() {
821  return GetEnumerator();
822  }
823 
824  #region Enumerator
825 
827  private readonly BlockIndexBase<T> index;
828  private readonly int startOffset;
829  private int endOffset;
830 
832  private int currentBlockSize;
833  private int blockIndex;
834  private int blockOffset;
835 
836  private int currentOffset;
837 
838  public Enumerator(BlockIndexBase<T> index, int startOffset, int endOffset) {
839  this.index = index;
840  this.startOffset = startOffset;
841  this.endOffset = endOffset;
842 
843  Reset();
844  }
845 
846  private void SetupVars(int offset) {
847  int size = index.Blocks.Count;
848  int start = 0;
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;
854  if (blockOffset < 0)
855  blockOffset = -1;
856 
857  currentBlock = block;
858  currentBlockSize = bsize;
859  return;
860  }
861  start += bsize;
862  }
863 
864  throw new IndexOutOfRangeException("'index' (" + offset + ") out of bounds.");
865  }
866 
867 
868 
869  public void Dispose() {
870  }
871 
872  public bool MoveNext() {
873  if (currentOffset < endOffset) {
874  ++currentOffset;
875 
876  if (++blockOffset >= currentBlockSize) {
877  ++blockIndex;
878  currentBlock = index.Blocks[blockIndex];
879  currentBlockSize = currentBlock.Count;
880  blockOffset = 0;
881  }
882 
883  return true;
884  }
885 
886  return false;
887  }
888 
889  public void Reset() {
890  currentOffset = startOffset - 1;
891 
892  if (endOffset >= startOffset) {
893  // Setup variables to 1 before the start
894  SetupVars(startOffset - 1);
895  }
896  }
897 
898  public T Current {
899  get { return currentBlock[blockOffset]; }
900  }
901 
902  object IEnumerator.Current {
903  get { return Current; }
904  }
905 
906  private void WalkBack() {
907  --blockOffset;
908  --currentOffset;
909  if (blockOffset < 0) {
910  if (blockIndex > 0) {
911  --blockIndex;
912  currentBlock = index.Blocks[blockIndex];
913  currentBlockSize = currentBlock.Count;
914  blockOffset = currentBlock.Count - 1;
915  }
916  }
917  }
918 
919  public bool MoveBack() {
920  if (currentOffset > startOffset) {
921  WalkBack();
922  return true;
923  }
924 
925  return false;
926  }
927 
928  public void Remove() {
929  index.CheckImmutable();
930 
931  // NOT ELEGANT: We check 'blocks' size to determine if the value
932  // deletion caused blocks to be removed. If it did, we set up the
933  // internal variables afresh with a call to 'setupVars'.
934  int origBlockCount = index.Blocks.Count;
935  index.RemoveFromBlock(blockIndex, currentBlock, blockOffset);
936 
937  // Did the number of blocks in the list change?
938  if (origBlockCount == index.Blocks.Count) {
939  // HACK: Evaluate the current cached block size
940  --currentBlockSize;
941  WalkBack();
942  } else {
943  --currentOffset;
944  SetupVars(currentOffset);
945  }
946  --endOffset;
947  }
948  }
949 
950  #endregion
951  }
952 }
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.
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.
static bool IsSmallerOrEqual(T x, T y)
Represents a dynamic object that encapsulates a defined SqlType and a compatible constant ISqlObject ...
Definition: DataObject.cs:35
int CompareValue(T index, DataObject value)
Compares a value contained in the underlying index at the given position and the
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.
Definition: IIndex.cs:37
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 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...
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.