DeveelDB  20151217
complete SQL database system, primarly developed for .NET/Mono frameworks
BlockIndex_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 {
30  public class BlockIndex<T> : BlockIndexBase<T> where T : IComparable<T>, IEquatable<T> {
34  public BlockIndex() {
35  }
36 
38  public BlockIndex(IEnumerable<T> values)
39  : base(values) {
40  }
41 
43  public BlockIndex(IIndex<T> index)
44  : base(index) {
45  }
46 
48  public BlockIndex(IEnumerable<IIndexBlock<T>> blocks)
49  : base(blocks) {
50  }
51 
53  protected override IIndexBlock<T> NewBlock() {
54  return new Block(512);
55  }
56 
57  #region Block
58 
59  protected class Block : IIndexBlock<T> {
60  private int count;
61  private bool changed;
62 
63  protected Block() {
64  }
65 
66  public Block(int blockSize)
67  : this() {
68  BaseArray = new T[blockSize];
69  count = 0;
70  }
71 
72  protected T[] BaseArray { get; set; }
73 
74  protected virtual int ArrayLength {
75  get { return BaseArray.Length; }
76  }
77 
78  public IEnumerator<T> GetEnumerator() {
79  return new Enumerator(this);
80  }
81 
82  IEnumerator IEnumerable.GetEnumerator() {
83  return GetEnumerator();
84  }
85 
87  get { return Next; }
88  set { Next = (Block) value; }
89  }
90 
91  private Block Next { get; set; }
92 
94  get { return Previous; }
95  set { Previous = (Block) value; }
96  }
97 
98  private Block Previous { get; set; }
99 
101  public bool HasChanged {
102  get { return changed; }
103  }
104 
106  public int Count {
107  get { return count; }
108  protected set { count = value; }
109  }
110 
112  public bool IsFull {
113  get { return count >= ArrayLength; }
114  }
115 
117  public bool IsEmpty {
118  get { return count <= 0; }
119  }
120 
122  public virtual T Top {
123  get { return GetArray(true)[count - 1]; }
124  }
125 
127  public virtual T Bottom {
128  get {
129  if (count <= 0)
130  throw new InvalidOperationException("no bottom value.");
131 
132  return GetArray(true)[0];
133  }
134  }
135 
137  public T this[int index] {
138  get { return GetArray(true)[index]; }
139  set {
140  changed = true;
141  GetArray(false)[index] = value;
142  }
143  }
144 
145  protected virtual T[] GetArray(bool readOnly) {
146  if (readOnly) {
147  var newArray = new T[BaseArray.Length];
148  Array.Copy(BaseArray, 0, newArray, 0, BaseArray.Length);
149  return newArray;
150  }
151  return BaseArray;
152  }
153 
154  private static bool IsSmallerOrEqual(T x, T y) {
155  return x.CompareTo(y) <= 0;
156  }
157 
158  private static bool IsGreaterOrEqual(T x, T y) {
159  return x.CompareTo(y) >= 0;
160  }
161 
162  private static bool IsGreater(T x, T y) {
163  return x.CompareTo(y) > 0;
164  }
165 
166  private static bool IsSmaller(T x, T y) {
167  return x.CompareTo(y) < 0;
168  }
169 
171  public bool CanContain(int number) {
172  return count + number + 1 < ArrayLength;
173  }
174 
176  public void Add(T value) {
177  changed = true;
178  var arr = GetArray(false);
179  arr[count] = value;
180  ++count;
181  }
182 
184  public T RemoveAt(int index) {
185  changed = true;
186  var arr = GetArray(false);
187  var val = arr[index];
188  Array.Copy(BaseArray, index + 1, arr, index, (count - index));
189  --count;
190  return val;
191  }
192 
194  public int IndexOf(T value) {
195  var arr = GetArray(true);
196  for (int i = count - 1; i >= 0; --i) {
197  if (arr[i].Equals(value))
198  return i;
199  }
200  return -1;
201  }
202 
204  public int IndexOf(T value, int startIndex) {
205  var arr = GetArray(true);
206  for (int i = startIndex; i < count; ++i) {
207  if (arr[i].Equals(value))
208  return i;
209  }
210  return -1;
211  }
212 
214  public void Insert(T value, int index) {
215  changed = true;
216  var arr = GetArray(false);
217  Array.Copy(BaseArray, index, arr, index + 1, (count - index));
218  ++count;
219  arr[index] = value;
220  }
221 
223  public void MoveTo(IIndexBlock<T> destBlock, int destIndex, int length) {
224  var block = (Block) destBlock;
225 
226  var arr = GetArray(false);
227  var destArr = block.GetArray(false);
228 
229  // Make room in the destination block
230  int destbSize = block.Count;
231  if (destbSize > 0) {
232  Array.Copy(destArr, 0, destArr, length, destbSize);
233  }
234 
235  // Copy from this block into the destination block.
236  Array.Copy(arr, count - length, destArr, 0, length);
237  // Alter size of destination and source block.
238  block.count += length;
239  count -= length;
240  // Mark both blocks as changed
241  changed = true;
242  block.changed = true;
243  }
244 
246  public void CopyTo(IIndexBlock<T> destBlock) {
247  var block = (Block) destBlock;
248  var destArr = block.GetArray(false);
249  Array.Copy(GetArray(true), 0, destArr, 0, count);
250  block.count = count;
251  block.changed = true;
252  }
253 
255  public int CopyTo(T[] destArray, int arrayIndex) {
256  Array.Copy(GetArray(true), 0, destArray, arrayIndex, count);
257  return count;
258  }
259 
261  public void Clear() {
262  changed = true;
263  count = 0;
264  }
265 
267  public int BinarySearch(object key, IIndexComparer<T> comparer) {
268  var arr = GetArray(true);
269  int low = 0;
270  int high = count - 1;
271 
272  while (low <= high) {
273  int mid = (low + high)/2;
274  int cmp = comparer.CompareValue(arr[mid], (DataObject) key);
275 
276  if (cmp < 0)
277  low = mid + 1;
278  else if (cmp > 0)
279  high = mid - 1;
280  else
281  return mid; // key found
282  }
283  return -(low + 1); // key not found.
284  }
285 
287  public int SearchFirst(object key, IIndexComparer<T> comparer) {
288  var arr = GetArray(true);
289  int low = 0;
290  int high = count - 1;
291 
292  while (low <= high) {
293  if (high - low <= 2) {
294  for (int i = low; i <= high; ++i) {
295  int cmp1 = comparer.CompareValue(arr[i], (DataObject) key);
296  if (cmp1 == 0)
297  return i;
298 
299  if (cmp1 > 0)
300  return -(i + 1);
301  }
302 
303  return -(high + 2);
304  }
305 
306  int mid = (low + high)/2;
307  int cmp = comparer.CompareValue(arr[mid], (DataObject) key);
308 
309  if (cmp < 0) {
310  low = mid + 1;
311  } else if (cmp > 0) {
312  high = mid - 1;
313  } else {
314  high = mid;
315  }
316  }
317  return -(low + 1); // key not found.
318 
319  }
320 
322  public int SearchLast(object key, IIndexComparer<T> comparer) {
323  var arr = GetArray(true);
324  int low = 0;
325  int high = count - 1;
326 
327  while (low <= high) {
328 
329  if (high - low <= 2) {
330  for (int i = high; i >= low; --i) {
331  int cmp1 = comparer.CompareValue(arr[i], (DataObject) key);
332  if (cmp1 == 0)
333  return i;
334  if (cmp1 < 0)
335  return -(i + 2);
336  }
337  return -(low + 1);
338  }
339 
340  int mid = (low + high)/2;
341  int cmp = comparer.CompareValue(arr[mid], (DataObject) key);
342 
343  if (cmp < 0) {
344  low = mid + 1;
345  } else if (cmp > 0) {
346  high = mid - 1;
347  } else {
348  low = mid;
349  }
350  }
351  return -(low + 1); // key not found.
352  }
353 
355  public int SearchFirst(T value) {
356  var arr = GetArray(true);
357  int low = 0;
358  int high = count - 1;
359 
360  while (low <= high) {
361 
362  if (high - low <= 2) {
363  for (int i = low; i <= high; ++i) {
364  if (arr[i].Equals(value))
365  return i;
366  if (IsGreater(arr[i], value))
367  return -(i + 1);
368  }
369  return -(high + 2);
370  }
371 
372  int mid = (low + high)/2;
373 
374  if (IsSmaller(arr[mid], value)) {
375  low = mid + 1;
376  } else if (IsGreater(arr[mid], value)) {
377  high = mid - 1;
378  } else {
379  high = mid;
380  }
381  }
382  return -(low + 1); // key not found.
383  }
384 
386  public int SearchLast(T value) {
387  var arr = GetArray(true);
388  int low = 0;
389  int high = count - 1;
390 
391  while (low <= high) {
392 
393  if (high - low <= 2) {
394  for (int i = high; i >= low; --i) {
395  if (arr[i].Equals(value))
396  return i;
397  if (IsSmaller(arr[i], value))
398  return -(i + 2);
399  }
400  return -(low + 1);
401  }
402 
403  int mid = (low + high)/2;
404 
405  if (IsSmaller(arr[mid], value)) {
406  low = mid + 1;
407  } else if (IsGreater(arr[mid], value)) {
408  high = mid - 1;
409  } else {
410  low = mid;
411  }
412  }
413  return -(low + 1); // key not found.
414  }
415 
416  #region Enumerator
417 
418  private class Enumerator : IEnumerator<T> {
419  private readonly Block block;
420  private int index;
421  private T[] array;
422 
423  public Enumerator(Block block) {
424  this.block = block;
425  array = block.GetArray(true);
426  index = -1;
427  }
428 
429  public void Dispose() {
430  }
431 
432  public bool MoveNext() {
433  return ++index < array.Length;
434  }
435 
436  public void Reset() {
437  array = block.GetArray(true);
438  index = -1;
439  }
440 
441  public T Current {
442  get { return array[index]; }
443  }
444 
445  object IEnumerator.Current {
446  get { return Current; }
447  }
448  }
449 
450  #endregion
451  }
452 
453  #endregion
454  }
455 }
static bool IsGreater(T x, T y)
int IndexOf(T value)
summary> Performs an iterative search from the given position to the end of the list in the block...
static bool IsGreaterOrEqual(T x, T y)
A comparer that is used within IIndex to compares two values which are indices to data that is bei...
int IndexOf(T value, int startIndex)
static bool IsSmallerOrEqual(T x, T y)
int SearchFirst(T value)
summary> Assuming a sorted block, finds the last index in the block that equals the given value...
IIndexBlock< T > Next
Gets or sets the next block in the hash.
void Clear()
Clears the block of all elements.
int CopyTo(T[] destArray, int arrayIndex)
BlockIndex()
Constructs an index with no values.
Definition: BlockIndex_T.cs:34
IEnumerator< T > GetEnumerator()
Definition: BlockIndex_T.cs:78
static bool IsSmaller(T x, T y)
void Add(T value)
Adss an int element to the block.
int SearchFirst(object key, IIndexComparer< T > comparer)
summary> Finds the last index in the block that equals the given key. /summary> param name="key"> ...
IIndexBlock< T > Previous
Gets or sets the previous block in the hash.
BlockIndex(IIndex< T > index)
Definition: BlockIndex_T.cs:43
override IIndexBlock< T > NewBlock()
Creates a new IIndexBlock for the given implementation.
Definition: BlockIndex_T.cs:53
virtual T[] GetArray(bool readOnly)
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
void MoveTo(IIndexBlock< T > destBlock, int destIndex, int length)
summary> Copies all the data from this block into the given destination block. /summary> param name="...
BlockIndex(IEnumerable< IIndexBlock< T >> blocks)
Definition: BlockIndex_T.cs:48
void CopyTo(IIndexBlock< T > destBlock)
summary> Copies all the data from this block into the given array. /summary> param name="array">The d...
A block contained in a BlockIndex.
int SearchLast(object key, IIndexComparer< T > comparer)
summary> Assuming a sorted block, finds the first index in the block that equals the given value...
An implementation of an index of values that are stored across an array of blocks.
An implementation of BlockIndexBase that stores all values in blocks that are entirely stored in m...
Definition: BlockIndex_T.cs:30
T RemoveAt(int index)
Removes the element at the given index from the block.
BlockIndex(IEnumerable< T > values)
Definition: BlockIndex_T.cs:38
int BinarySearch(object key, IIndexComparer< T > comparer)
summary> Finds the first index in the block that equals the given key. /summary> param name="key"> ...
void Insert(T value, int index)
Inserts an element to the block at the given index.