IndexMap.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /* Copyright 2010-present MongoDB Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. using System.Collections.Generic;
  16. namespace MongoDB.Driver.Support
  17. {
  18. internal abstract class IndexMap
  19. {
  20. // private static fields
  21. private static readonly IndexMap __identityMap = new RangeBased(0, 0, int.MaxValue);
  22. // public static properties
  23. public static IndexMap IdentityMap
  24. {
  25. get { return __identityMap; }
  26. }
  27. // public properties
  28. public abstract bool IsIdentityMap { get; }
  29. // public methods
  30. public abstract IndexMap Add(int index, int originalIndex);
  31. public abstract int Map(int index);
  32. // nested classes
  33. public class RangeBased : IndexMap
  34. {
  35. // private fields
  36. private int _index;
  37. private int _originalIndex;
  38. private int _count;
  39. // constructors
  40. public RangeBased()
  41. {
  42. }
  43. public RangeBased(int index, int originalIndex, int count)
  44. {
  45. _index = index;
  46. _originalIndex = originalIndex;
  47. _count = count;
  48. }
  49. // public properties
  50. public override bool IsIdentityMap
  51. {
  52. get { return _index == _originalIndex; }
  53. }
  54. // public methods
  55. public override IndexMap Add(int index, int originalIndex)
  56. {
  57. if (_count == 0)
  58. {
  59. _index = index;
  60. _originalIndex = originalIndex;
  61. _count = 1;
  62. return this;
  63. }
  64. else if (index == _index + _count && originalIndex == _originalIndex + _count)
  65. {
  66. _count += 1;
  67. return this;
  68. }
  69. else
  70. {
  71. var dictionaryMap = new DictionaryBased(_index, _originalIndex, _count);
  72. dictionaryMap.Add(index, originalIndex);
  73. return dictionaryMap;
  74. }
  75. }
  76. public override int Map(int index)
  77. {
  78. var offset = index - _index;
  79. if (offset < 0 || offset >= _count)
  80. {
  81. throw new KeyNotFoundException();
  82. }
  83. return _originalIndex + offset;
  84. }
  85. }
  86. public class DictionaryBased : IndexMap
  87. {
  88. // private fields
  89. private readonly Dictionary<int, int> _dictionary = new Dictionary<int, int>();
  90. // constructors
  91. public DictionaryBased()
  92. {
  93. }
  94. public DictionaryBased(int index, int originalIndex, int count)
  95. {
  96. var limit = index + count;
  97. for (int i = index, o = originalIndex; i < limit; i++, o++)
  98. {
  99. _dictionary.Add(i, o);
  100. }
  101. }
  102. // public properties
  103. public override bool IsIdentityMap
  104. {
  105. get { return false; }
  106. }
  107. // public methods
  108. public override IndexMap Add(int index, int originalIndex)
  109. {
  110. _dictionary.Add(index, originalIndex);
  111. return this;
  112. }
  113. public override int Map(int index)
  114. {
  115. return _dictionary[index];
  116. }
  117. }
  118. }
  119. }