MyGUI  3.2.0
MyGUI_BiIndexBase.cpp
Go to the documentation of this file.
1 
6 /*
7  This file is part of MyGUI.
8 
9  MyGUI is free software: you can redistribute it and/or modify
10  it under the terms of the GNU Lesser General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  (at your option) any later version.
13 
14  MyGUI is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU Lesser General Public License for more details.
18 
19  You should have received a copy of the GNU Lesser General Public License
20  along with MyGUI. If not, see <http://www.gnu.org/licenses/>.
21 */
22 #include "MyGUI_Precompiled.h"
23 #include "MyGUI_BiIndexBase.h"
24 
25 namespace MyGUI
26 {
27 
29  {
30  }
31 
33  {
34  }
35 
37  {
38  return mIndexFace.size();
39  }
40 
41  size_t BiIndexBase::insertItemAt(size_t _index)
42  {
43  #if MYGUI_DEBUG_MODE == 1
44  MYGUI_ASSERT_RANGE_INSERT(_index, mIndexFace.size(), "BiIndexBase::insertItemAt");
45  checkIndexes();
46  #endif
47 
48  if (_index == MyGUI::ITEM_NONE)
49  _index = mIndexFace.size();
50 
51  size_t index;
52 
53  if (_index == mIndexFace.size())
54  {
55  // для вставки айтема
56  index = mIndexFace.size();
57 
58  mIndexFace.push_back(_index);
59  mIndexBack.push_back(_index);
60  }
61  else
62  {
63  // для вставки айтема
64  index = mIndexFace[_index];
65 
66  size_t count = mIndexFace.size();
67  for (size_t pos = 0; pos < count; ++pos)
68  {
69  if (mIndexFace[pos] >= index)
70  mIndexFace[pos]++;
71  }
72  mIndexFace.insert(mIndexFace.begin() + _index, index);
73 
74  count ++;
75  mIndexBack.push_back(0);
76  for (size_t pos = 0; pos < count; ++pos)
77  {
78  mIndexBack[mIndexFace[pos]] = pos;
79  }
80  }
81 
82  #if MYGUI_DEBUG_MODE == 1
83  checkIndexes();
84  #endif
85 
86  return index;
87  }
88 
89  size_t BiIndexBase::removeItemAt(size_t _index)
90  {
91  #if MYGUI_DEBUG_MODE == 1
92  MYGUI_ASSERT_RANGE(_index, mIndexFace.size(), "BiIndexBase::removeItemAt");
93  checkIndexes();
94  #endif
95 
96  // для удаления айтема
97  size_t index = mIndexFace[_index];
98 
99  mIndexFace.erase(mIndexFace.begin() + _index);
100  mIndexBack.pop_back();
101 
102  size_t count = mIndexFace.size();
103  for (size_t pos = 0; pos < count; ++pos)
104  {
105  if (mIndexFace[pos] > index)
106  mIndexFace[pos]--;
107  mIndexBack[mIndexFace[pos]] = pos;
108  }
109 
110  #if MYGUI_DEBUG_MODE == 1
111  checkIndexes();
112  #endif
113 
114  return index;
115  }
116 
118  {
119  mIndexFace.clear();
120  mIndexBack.clear();
121  }
122 
123  // на входе индексы пользователя, на выходе реальные индексы
124  size_t BiIndexBase::convertToBack(size_t _index) const
125  {
126  #if MYGUI_DEBUG_MODE == 1
127  MYGUI_ASSERT_RANGE_AND_NONE(_index, mIndexFace.size(), "BiIndexBase::convertToBack");
128  #endif
129  return _index == ITEM_NONE ? ITEM_NONE : mIndexFace[_index];
130  }
131 
132  // на входе индексы реальные, на выходе, то что видит пользователь
133  size_t BiIndexBase::convertToFace(size_t _index) const
134  {
135  #if MYGUI_DEBUG_MODE == 1
136  MYGUI_ASSERT_RANGE_AND_NONE(_index, mIndexFace.size(), "BiIndexBase::convertToFace");
137  #endif
138  return _index == ITEM_NONE ? ITEM_NONE : mIndexBack[_index];
139  }
140 
141  // меняет местами два индекса, индексы со стороны пользователя
142  void BiIndexBase::swapItemsFaceAt(size_t _index1, size_t _index2)
143  {
144  #if MYGUI_DEBUG_MODE == 1
145  MYGUI_ASSERT_RANGE(_index1, mIndexFace.size(), "BiIndexBase::swapItemsFaceAt");
146  MYGUI_ASSERT_RANGE(_index2, mIndexFace.size(), "BiIndexBase::swapItemsFaceAt");
147  #endif
148 
149  std::swap(mIndexFace[_index1], mIndexFace[_index2]);
150  std::swap(mIndexBack[mIndexFace[_index1]], mIndexBack[mIndexFace[_index2]]);
151  }
152 
153  // меняет местами два индекса, индексы со сторонны данных
154  void BiIndexBase::swapItemsBackAt(size_t _index1, size_t _index2)
155  {
156  #if MYGUI_DEBUG_MODE == 1
157  MYGUI_ASSERT_RANGE(_index1, mIndexFace.size(), "BiIndexBase::swapItemsBackAt");
158  MYGUI_ASSERT_RANGE(_index2, mIndexFace.size(), "BiIndexBase::swapItemsBackAt");
159  #endif
160 
161  std::swap(mIndexBack[_index1], mIndexBack[_index2]);
162  std::swap(mIndexFace[mIndexBack[_index1]], mIndexFace[mIndexBack[_index2]]);
163  }
164 
165 #if MYGUI_DEBUG_MODE == 1
166 
167  void BiIndexBase::checkIndexes()
168  {
169  assert(mIndexFace.size() == mIndexBack.size());
170 
171  // проверяем на уникальность каждого индекса в маппинге
172  std::vector<bool> vec;
173  size_t count = mIndexFace.size();
174 
175  vec.reserve(count);
176  for (size_t pos = 0; pos < count; ++pos)
177  vec.push_back(false);
178 
179  for (size_t pos = 0; pos < count; ++pos)
180  {
181  // максимум
182  size_t index = mIndexBack[pos];
183  if (index >= count)
184  throw new std::exception();
185 
186  // максимум
187  index = mIndexFace[pos];
188  if (index >= count)
189  throw new std::exception();
190 
191  if (vec[index])
192  throw new std::exception();
193  vec[index] = true;
194  }
195 
196  for (size_t pos = 0; pos < count; ++pos)
197  {
198  if (!vec[pos])
199  throw new std::exception();
200  }
201 
202  // проверяем на взаимоссылаемость индексов
203  for (size_t pos = 0; pos < count; ++pos)
204  {
205  size_t index = mIndexFace[pos];
206  if (mIndexBack[index] != pos)
207  throw new std::exception();
208  }
209  }
210 
211 #endif
212 
213 } // namespace MyGUI
size_t removeItemAt(size_t _index)
size_t convertToFace(size_t _index) const
void swapItemsBackAt(size_t _index1, size_t _index2)
const size_t ITEM_NONE
Definition: MyGUI_Macros.h:32
size_t insertItemAt(size_t _index)
size_t getIndexCount() const
#define MYGUI_ASSERT_RANGE_AND_NONE(index, size, owner)
#define MYGUI_ASSERT_RANGE(index, size, owner)
void swapItemsFaceAt(size_t _index1, size_t _index2)
size_t convertToBack(size_t _index) const
#define MYGUI_ASSERT_RANGE_INSERT(index, size, owner)