Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
ObjectMap.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 //
4 // ----------------------------------------------------------------------
5 // Gold Parser engine.
6 // See more details on http://www.devincook.com/goldparser/
7 //
8 // Original code is written in VB by Devin Cook (GOLDParser@DevinCook.com)
9 //
10 // This translation is done by Vladimir Morozov (vmoroz@hotmail.com)
11 //
12 // The translation is based on the other engine translations:
13 // Delphi engine by Alexandre Rai (riccio@gmx.at)
14 // C# engine by Marcus Klimstra (klimstra@home.nl)
15 // ----------------------------------------------------------------------
16 #region Using directives
17 
18 using System;
19 
20 #endregion
21 
22 namespace GoldParser
23 {
24  /// <summary>
25  /// Maps integer values used for transition vectors to objects.
26  /// </summary>
27  internal class ObjectMap
28  {
29  #region Fields
30 
31  private bool m_readonly;
32  private MapProvider m_mapProvider;
33 
34  private const int MAXINDEX = 255;
35  private const int GROWTH = 32;
36  private const int MINSIZE = 32;
37  private const int MAXARRAYCOUNT = 12;
38 
39  private const int INVALIDKEY = Int32.MaxValue;
40 
41  #endregion
42 
43  #region Constructors
44 
45  /// <summary>
46  /// Creates new instance of <see cref="ObjectMap"/> class.
47  /// </summary>
48  public ObjectMap()
49  {
50  m_mapProvider = new SortedMapProvider(MINSIZE);
51  }
52 
53  #endregion
54 
55  #region Public members.
56 
57  /// <summary>
58  /// Gets number of entries in the map.
59  /// </summary>
60  public int Count
61  {
62  get { return m_mapProvider.m_count; }
63  }
64 
65  /// <summary>
66  /// Gets or sets read only flag.
67  /// </summary>
68  public bool ReadOnly
69  {
70  get { return m_readonly; }
71  set
72  {
73  if (m_readonly != value)
74  {
75  SetMapProvider(value);
76  m_readonly = value;
77  }
78  }
79  }
80 
81  /// <summary>
82  /// Gets or sets value by key.
83  /// </summary>
84  public object this[int key]
85  {
86  get { return m_mapProvider[key]; }
87  set { m_mapProvider.Add(key, value); }
88  }
89 
90  /// <summary>
91  /// Returns key by index.
92  /// </summary>
93  /// <param name="index">Zero based index of the requested key.</param>
94  /// <returns>Returns key for the given index.</returns>
95  public int GetKey(int index)
96  {
97  return m_mapProvider.GetEntry(index).Key;
98  }
99 
100  /// <summary>
101  /// Removes entry by its key.
102  /// </summary>
103  /// <param name="key"></param>
104  public void Remove(int key)
105  {
106  m_mapProvider.Remove(key);
107  }
108 
109  /// <summary>
110  /// Adds a new key and value pair.
111  /// If key exists then value is applied to existing key.
112  /// </summary>
113  /// <param name="key">New key to add.</param>
114  /// <param name="value">Value for the key.</param>
115  public void Add(int key, object value)
116  {
117  m_mapProvider.Add(key, value);
118  }
119 
120  #endregion
121 
122  #region Private members
123 
124  private void SetMapProvider(bool readOnly)
125  {
126  int count = m_mapProvider.m_count;
127  MapProvider provider = m_mapProvider;
128  if (readOnly)
129  {
130  SortedMapProvider pr = m_mapProvider as SortedMapProvider;
131  if (pr.m_lastKey <= MAXINDEX)
132  {
133  provider = new IndexMapProvider();
134  }
135  else if (count <= MAXARRAYCOUNT)
136  {
137  provider = new ArrayMapProvider(m_mapProvider.m_count);
138  }
139  }
140  else
141  {
142  if (! (provider is SortedMapProvider))
143  {
144  provider = new SortedMapProvider(m_mapProvider.m_count);
145  }
146  }
147  if (provider != m_mapProvider)
148  {
149  for (int i = 0; i < count; i++)
150  {
151  Entry entry = m_mapProvider.GetEntry(i);
152  provider.Add(entry.Key, entry.Value);
153  }
154  m_mapProvider = provider;
155  }
156  }
157 
158  #endregion
159 
160  #region Entry struct definition
161 
162  private struct Entry
163  {
164  internal int Key;
165  internal object Value;
166 
167  internal Entry(int key, object value)
168  {
169  Key = key;
170  Value = value;
171  }
172  }
173 
174  #endregion
175 
176  private abstract class MapProvider
177  {
178  internal int m_count; // Entry count in the collection.
179 
180  internal abstract object this[int key]
181  {
182  get;
183  }
184 
185  internal abstract Entry GetEntry(int index);
186 
187  internal abstract void Add(int key, object value);
188 
189  internal virtual void Remove(int key)
190  {
191  throw new InvalidOperationException();
192  }
193  }
194 
195  private class SortedMapProvider : MapProvider
196  {
197  internal Entry[] m_entries; // Array of entries.
198 
199  internal int m_lastKey; // Bigest key number.
200 
201  internal SortedMapProvider(int capacity)
202  {
203  m_entries = new Entry[capacity];
204  }
205 
206  internal override object this[int key]
207  {
208  get
209  {
210  int minIndex = 0;
211  int maxIndex = m_count - 1;
212  if (maxIndex >= 0 && key <= m_lastKey)
213  {
214  do
215  {
216  int midIndex = (maxIndex + minIndex) / 2;
217  if (key <= m_entries[midIndex].Key)
218  {
219  maxIndex = midIndex;
220  }
221  else
222  {
223  minIndex = midIndex + 1;
224  }
225  } while (minIndex < maxIndex);
226  if (key == m_entries[minIndex].Key)
227  {
228  return m_entries[minIndex].Value;
229  }
230  }
231  return null;
232  }
233  }
234 
235  internal override Entry GetEntry(int index)
236  {
237  return m_entries[index];
238  }
239 
240  internal override void Add(int key, object value)
241  {
242  bool found;
243  int index = FindInsertIndex(key, out found);
244  if (found)
245  {
246  m_entries[index].Value = value;
247  return;
248  }
249  if (m_count >= m_entries.Length)
250  {
251  Entry[] entries = new Entry[m_entries.Length + GROWTH];
252  Array.Copy(m_entries, 0, entries, 0, m_entries.Length);
253  m_entries = entries;
254  }
255  if (index < m_count)
256  {
257  Array.Copy(m_entries, index, m_entries, index + 1, m_count - index);
258  }
259  else
260  {
261  m_lastKey = key;
262  }
263  m_entries[index].Key = key;
264  m_entries[index].Value = value;
265  m_count++;
266  }
267 
268  internal override void Remove(int key)
269  {
270  int index = FindIndex(key);
271  if (index >= 0)
272  {
273  int tailSize = (m_count - 1) - index;
274  if (tailSize > 0)
275  {
276  Array.Copy(m_entries, index + 1, m_entries, index, tailSize);
277  }
278  else if (m_count > 1)
279  {
280  m_lastKey = m_entries[m_count - 2].Key;
281  }
282  else
283  {
284  m_lastKey = INVALIDKEY;
285  }
286  m_count--;
287  m_entries[m_count].Key = INVALIDKEY;
288  m_entries[m_count].Value = null;
289  }
290  }
291 
292  private int FindIndex(int key)
293  {
294  int minIndex = 0;
295  if (m_count > 0 && key <= m_lastKey)
296  {
297  int maxIndex = m_count - 1;
298  do
299  {
300  int midIndex = (maxIndex + minIndex) / 2;
301  if (key <= m_entries[midIndex].Key)
302  {
303  maxIndex = midIndex;
304  }
305  else
306  {
307  minIndex = midIndex + 1;
308  }
309  } while (minIndex < maxIndex);
310  if (key == m_entries[minIndex].Key)
311  {
312  return minIndex;
313  }
314  }
315  return -1;
316  }
317 
318  private int FindInsertIndex(int key, out bool found)
319  {
320  int minIndex = 0;
321  if (m_count > 0 && key <= m_lastKey)
322  {
323  int maxIndex = m_count - 1;
324  do
325  {
326  int midIndex = (maxIndex + minIndex) / 2;
327  if (key <= m_entries[midIndex].Key)
328  {
329  maxIndex = midIndex;
330  }
331  else
332  {
333  minIndex = midIndex + 1;
334  }
335  } while (minIndex < maxIndex);
336  found = (key == m_entries[minIndex].Key);
337  return minIndex;
338  }
339  found = false;
340  return m_count;
341  }
342  }
343 
344  private class IndexMapProvider : MapProvider
345  {
346  private object[] m_array; // Array of entries.
347 
348  internal IndexMapProvider()
349  {
350  m_array = new object[MAXINDEX + 1];
351  for (int i = m_array.Length; --i >= 0; )
352  {
353  m_array[i] = Unassigned.Value;
354  }
355  }
356 
357  internal override object this[int key]
358  {
359  get
360  {
361  if (key >= m_array.Length || key < 0)
362  {
363  return null;
364  }
365  return m_array[key];
366  }
367  }
368 
369  internal override Entry GetEntry(int index)
370  {
371  int idx = -1;
372  for (int i = 0; i < m_array.Length; i++)
373  {
374  object value = m_array[i];
375  if (value != Unassigned.Value)
376  {
377  idx++;
378  }
379  if (idx == index)
380  {
381  return new Entry(i, value);
382  }
383  }
384  return new Entry();
385  }
386 
387  internal override void Add(int key, object value)
388  {
389  m_array[key] = value;
390  m_count++;
391  }
392  }
393 
394  private class ArrayMapProvider : MapProvider
395  {
396  private Entry[] m_entries; // Array of entries.
397 
398  internal ArrayMapProvider(int capacity)
399  {
400  m_entries = new Entry[capacity];
401  }
402 
403  internal override object this[int key]
404  {
405  get
406  {
407  for (int i = m_count; --i >= 0;)
408  {
409  Entry entry = m_entries[i];
410  int entryKey = entry.Key;
411  if (entryKey > key)
412  {
413  continue;
414  }
415  else if (entryKey == key)
416  {
417  return entry.Value;
418  }
419  else if (entryKey < key)
420  {
421  return null;
422  }
423  }
424  return null;
425  }
426  }
427 
428  internal override Entry GetEntry(int index)
429  {
430  return m_entries[index];
431  }
432 
433  internal override void Add(int key, object value)
434  {
435  m_entries[m_count].Key = key;
436  m_entries[m_count].Value = value;
437  m_count++;
438  }
439  }
440 
441  private class Unassigned
442  {
443  internal static Unassigned Value = new Unassigned();
444  }
445  }
446 }
Only valid for a property that will be used only as a "read only" property.
_In_ size_t count
Definition: DirectXTexP.h:174
The remove mixin to remove a mixin from current mixins.