MyGUI  3.4.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  return mIndexFace.size();
16  }
17 
18  size_t BiIndexBase::insertItemAt(size_t _index)
19  {
20 #if MYGUI_DEBUG_MODE == 1
21  MYGUI_ASSERT_RANGE_INSERT(_index, mIndexFace.size(), "BiIndexBase::insertItemAt");
22  checkIndexes();
23 #endif
24 
25  if (_index == MyGUI::ITEM_NONE)
26  _index = mIndexFace.size();
27 
28  size_t index;
29 
30  if (_index == mIndexFace.size())
31  {
32  // для вставки айтема
33  index = mIndexFace.size();
34 
35  mIndexFace.push_back(_index);
36  mIndexBack.push_back(_index);
37  }
38  else
39  {
40  // для вставки айтема
41  index = mIndexFace[_index];
42 
43  size_t count = mIndexFace.size();
44  for (size_t pos = 0; pos < count; ++pos)
45  {
46  if (mIndexFace[pos] >= index)
47  mIndexFace[pos]++;
48  }
49  mIndexFace.insert(mIndexFace.begin() + _index, index);
50 
51  count ++;
52  mIndexBack.push_back(0);
53  for (size_t pos = 0; pos < count; ++pos)
54  {
55  mIndexBack[mIndexFace[pos]] = pos;
56  }
57  }
58 
59 #if MYGUI_DEBUG_MODE == 1
60  checkIndexes();
61 #endif
62 
63  return index;
64  }
65 
66  size_t BiIndexBase::removeItemAt(size_t _index)
67  {
68 #if MYGUI_DEBUG_MODE == 1
69  MYGUI_ASSERT_RANGE(_index, mIndexFace.size(), "BiIndexBase::removeItemAt");
70  checkIndexes();
71 #endif
72 
73  // для удаления айтема
74  size_t index = mIndexFace[_index];
75 
76  mIndexFace.erase(mIndexFace.begin() + _index);
77  mIndexBack.pop_back();
78 
79  size_t count = mIndexFace.size();
80  for (size_t pos = 0; pos < count; ++pos)
81  {
82  if (mIndexFace[pos] > index)
83  mIndexFace[pos]--;
84  mIndexBack[mIndexFace[pos]] = pos;
85  }
86 
87 #if MYGUI_DEBUG_MODE == 1
88  checkIndexes();
89 #endif
90 
91  return index;
92  }
93 
95  {
96  mIndexFace.clear();
97  mIndexBack.clear();
98  }
99 
100  // на входе индексы пользователя, на выходе реальные индексы
101  size_t BiIndexBase::convertToBack(size_t _index) const
102  {
103 #if MYGUI_DEBUG_MODE == 1
104  MYGUI_ASSERT_RANGE_AND_NONE(_index, mIndexFace.size(), "BiIndexBase::convertToBack");
105 #endif
106  return _index == ITEM_NONE ? ITEM_NONE : mIndexFace[_index];
107  }
108 
109  // на входе индексы реальные, на выходе, то что видит пользователь
110  size_t BiIndexBase::convertToFace(size_t _index) const
111  {
112 #if MYGUI_DEBUG_MODE == 1
113  MYGUI_ASSERT_RANGE_AND_NONE(_index, mIndexFace.size(), "BiIndexBase::convertToFace");
114 #endif
115  return _index == ITEM_NONE ? ITEM_NONE : mIndexBack[_index];
116  }
117 
118  // меняет местами два индекса, индексы со стороны пользователя
119  void BiIndexBase::swapItemsFaceAt(size_t _index1, size_t _index2)
120  {
121 #if MYGUI_DEBUG_MODE == 1
122  MYGUI_ASSERT_RANGE(_index1, mIndexFace.size(), "BiIndexBase::swapItemsFaceAt");
123  MYGUI_ASSERT_RANGE(_index2, mIndexFace.size(), "BiIndexBase::swapItemsFaceAt");
124 #endif
125 
126  std::swap(mIndexFace[_index1], mIndexFace[_index2]);
127  std::swap(mIndexBack[mIndexFace[_index1]], mIndexBack[mIndexFace[_index2]]);
128  }
129 
130  // меняет местами два индекса, индексы со сторонны данных
131  void BiIndexBase::swapItemsBackAt(size_t _index1, size_t _index2)
132  {
133 #if MYGUI_DEBUG_MODE == 1
134  MYGUI_ASSERT_RANGE(_index1, mIndexFace.size(), "BiIndexBase::swapItemsBackAt");
135  MYGUI_ASSERT_RANGE(_index2, mIndexFace.size(), "BiIndexBase::swapItemsBackAt");
136 #endif
137 
138  std::swap(mIndexBack[_index1], mIndexBack[_index2]);
139  std::swap(mIndexFace[mIndexBack[_index1]], mIndexFace[mIndexBack[_index2]]);
140  }
141 
142 #if MYGUI_DEBUG_MODE == 1
143 
144  void BiIndexBase::checkIndexes()
145  {
146  assert(mIndexFace.size() == mIndexBack.size());
147 
148  // проверяем на уникальность каждого индекса в маппинге
149  std::vector<bool> vec;
150  size_t count = mIndexFace.size();
151 
152  vec.reserve(count);
153  for (size_t pos = 0; pos < count; ++pos)
154  vec.push_back(false);
155 
156  for (size_t pos = 0; pos < count; ++pos)
157  {
158  // максимум
159  size_t index = mIndexBack[pos];
160  if (index >= count)
161  throw new std::exception();
162 
163  // максимум
164  index = mIndexFace[pos];
165  if (index >= count)
166  throw new std::exception();
167 
168  if (vec[index])
169  throw new std::exception();
170  vec[index] = true;
171  }
172 
173  for (size_t pos = 0; pos < count; ++pos)
174  {
175  if (!vec[pos])
176  throw new std::exception();
177  }
178 
179  // проверяем на взаимоссылаемость индексов
180  for (size_t pos = 0; pos < count; ++pos)
181  {
182  size_t index = mIndexFace[pos];
183  if (mIndexBack[index] != pos)
184  throw new std::exception();
185  }
186  }
187 
188 #endif
189 
190 } // namespace MyGUI
#define MYGUI_ASSERT_RANGE_INSERT(index, size, owner)
#define MYGUI_ASSERT_RANGE(index, size, owner)
#define MYGUI_ASSERT_RANGE_AND_NONE(index, size, owner)
void swapItemsBackAt(size_t _index1, size_t _index2)
size_t removeItemAt(size_t _index)
size_t insertItemAt(size_t _index)
size_t convertToBack(size_t _index) const
size_t convertToFace(size_t _index) const
size_t getIndexCount() const
void swapItemsFaceAt(size_t _index1, size_t _index2)
const size_t ITEM_NONE
Definition: MyGUI_Macros.h:17