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
10namespace 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