MyGUI  3.2.1
MyGUI_BiIndexBase.cpp
Go to the documentation of this file.
1 /*
2  * This source file is part of MyGUI. For the latest info, see http://mygui.info/
3  * Distributed under the MIT License
4  * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT)
5  */
6 
7 #include "MyGUI_Precompiled.h"
8 #include "MyGUI_BiIndexBase.h"
9 
10 namespace MyGUI
11 {
12 
14  {
15  }
16 
18  {
19  }
20 
22  {
23  return mIndexFace.size();
24  }
25 
26  size_t BiIndexBase::insertItemAt(size_t _index)
27  {
28 #if MYGUI_DEBUG_MODE == 1
29  MYGUI_ASSERT_RANGE_INSERT(_index, mIndexFace.size(), "BiIndexBase::insertItemAt");
30  checkIndexes();
31 #endif
32 
33  if (_index == MyGUI::ITEM_NONE)
34  _index = mIndexFace.size();
35 
36  size_t index;
37 
38  if (_index == mIndexFace.size())
39  {
40  // для вставки айтема
41  index = mIndexFace.size();
42 
43  mIndexFace.push_back(_index);
44  mIndexBack.push_back(_index);
45  }
46  else
47  {
48  // для вставки айтема
49  index = mIndexFace[_index];
50 
51  size_t count = mIndexFace.size();
52  for (size_t pos = 0; pos < count; ++pos)
53  {
54  if (mIndexFace[pos] >= index)
55  mIndexFace[pos]++;
56  }
57  mIndexFace.insert(mIndexFace.begin() + _index, index);
58 
59  count ++;
60  mIndexBack.push_back(0);
61  for (size_t pos = 0; pos < count; ++pos)
62  {
63  mIndexBack[mIndexFace[pos]] = pos;
64  }
65  }
66 
67 #if MYGUI_DEBUG_MODE == 1
68  checkIndexes();
69 #endif
70 
71  return index;
72  }
73 
74  size_t BiIndexBase::removeItemAt(size_t _index)
75  {
76 #if MYGUI_DEBUG_MODE == 1
77  MYGUI_ASSERT_RANGE(_index, mIndexFace.size(), "BiIndexBase::removeItemAt");
78  checkIndexes();
79 #endif
80 
81  // для удаления айтема
82  size_t index = mIndexFace[_index];
83 
84  mIndexFace.erase(mIndexFace.begin() + _index);
85  mIndexBack.pop_back();
86 
87  size_t count = mIndexFace.size();
88  for (size_t pos = 0; pos < count; ++pos)
89  {
90  if (mIndexFace[pos] > index)
91  mIndexFace[pos]--;
92  mIndexBack[mIndexFace[pos]] = pos;
93  }
94 
95 #if MYGUI_DEBUG_MODE == 1
96  checkIndexes();
97 #endif
98 
99  return index;
100  }
101 
103  {
104  mIndexFace.clear();
105  mIndexBack.clear();
106  }
107 
108  // на входе индексы пользователя, на выходе реальные индексы
109  size_t BiIndexBase::convertToBack(size_t _index) const
110  {
111 #if MYGUI_DEBUG_MODE == 1
112  MYGUI_ASSERT_RANGE_AND_NONE(_index, mIndexFace.size(), "BiIndexBase::convertToBack");
113 #endif
114  return _index == ITEM_NONE ? ITEM_NONE : mIndexFace[_index];
115  }
116 
117  // на входе индексы реальные, на выходе, то что видит пользователь
118  size_t BiIndexBase::convertToFace(size_t _index) const
119  {
120 #if MYGUI_DEBUG_MODE == 1
121  MYGUI_ASSERT_RANGE_AND_NONE(_index, mIndexFace.size(), "BiIndexBase::convertToFace");
122 #endif
123  return _index == ITEM_NONE ? ITEM_NONE : mIndexBack[_index];
124  }
125 
126  // меняет местами два индекса, индексы со стороны пользователя
127  void BiIndexBase::swapItemsFaceAt(size_t _index1, size_t _index2)
128  {
129 #if MYGUI_DEBUG_MODE == 1
130  MYGUI_ASSERT_RANGE(_index1, mIndexFace.size(), "BiIndexBase::swapItemsFaceAt");
131  MYGUI_ASSERT_RANGE(_index2, mIndexFace.size(), "BiIndexBase::swapItemsFaceAt");
132 #endif
133 
134  std::swap(mIndexFace[_index1], mIndexFace[_index2]);
135  std::swap(mIndexBack[mIndexFace[_index1]], mIndexBack[mIndexFace[_index2]]);
136  }
137 
138  // меняет местами два индекса, индексы со сторонны данных
139  void BiIndexBase::swapItemsBackAt(size_t _index1, size_t _index2)
140  {
141 #if MYGUI_DEBUG_MODE == 1
142  MYGUI_ASSERT_RANGE(_index1, mIndexFace.size(), "BiIndexBase::swapItemsBackAt");
143  MYGUI_ASSERT_RANGE(_index2, mIndexFace.size(), "BiIndexBase::swapItemsBackAt");
144 #endif
145 
146  std::swap(mIndexBack[_index1], mIndexBack[_index2]);
147  std::swap(mIndexFace[mIndexBack[_index1]], mIndexFace[mIndexBack[_index2]]);
148  }
149 
150 #if MYGUI_DEBUG_MODE == 1
151 
152  void BiIndexBase::checkIndexes()
153  {
154  assert(mIndexFace.size() == mIndexBack.size());
155 
156  // проверяем на уникальность каждого индекса в маппинге
157  std::vector<bool> vec;
158  size_t count = mIndexFace.size();
159 
160  vec.reserve(count);
161  for (size_t pos = 0; pos < count; ++pos)
162  vec.push_back(false);
163 
164  for (size_t pos = 0; pos < count; ++pos)
165  {
166  // максимум
167  size_t index = mIndexBack[pos];
168  if (index >= count)
169  throw new std::exception();
170 
171  // максимум
172  index = mIndexFace[pos];
173  if (index >= count)
174  throw new std::exception();
175 
176  if (vec[index])
177  throw new std::exception();
178  vec[index] = true;
179  }
180 
181  for (size_t pos = 0; pos < count; ++pos)
182  {
183  if (!vec[pos])
184  throw new std::exception();
185  }
186 
187  // проверяем на взаимоссылаемость индексов
188  for (size_t pos = 0; pos < count; ++pos)
189  {
190  size_t index = mIndexFace[pos];
191  if (mIndexBack[index] != pos)
192  throw new std::exception();
193  }
194  }
195 
196 #endif
197 
198 } // namespace MyGUI