Line data Source code
1 : #define _OksBuildDll_
2 :
3 : #include "oks/index.hpp"
4 : #include "oks/attribute.hpp"
5 : #include "oks/class.hpp"
6 :
7 : namespace dunedaq {
8 : namespace oks {
9 :
10 : size_t
11 0 : OksIndex::get_offset(OksClass *cl, OksAttribute *a)
12 : {
13 0 : OksDataInfo::Map::const_iterator x = cl->p_data_info->find(a->p_name);
14 0 : return (x == cl->p_data_info->end()) ? 0 : x->second->offset;
15 : }
16 :
17 :
18 0 : OksIndex::OksIndex(OksClass *cl, OksAttribute *attr) :
19 : std::multiset<OksObject *, OksObjectSortBy> (get_offset(cl, attr)),
20 0 : c (cl),
21 0 : a (attr)
22 : {
23 0 : const char * fname = "OksIndex::OksIndex(OksClass *, OksAttribute *";
24 :
25 0 : if(!c) {
26 0 : Oks::error_msg(fname) << "Can't build index for NIL class\n";
27 : return;
28 : }
29 :
30 0 : if(c->get_is_abstract()) {
31 0 : Oks::error_msg(fname)
32 0 : << "Can't build index for ABSTRACT class \"" << c->get_name() << "\"\n";
33 : return;
34 : }
35 :
36 0 : if(!a) {
37 0 : Oks::error_msg(fname) << "Can't build index for NIL attribute\n";
38 : return;
39 : }
40 :
41 0 : if(c->find_attribute(a->get_name()) == 0) {
42 0 : Oks::error_msg(fname)
43 0 : << "Can't find attribute \"" << a->p_name << "\" in class \""
44 0 : << c->get_name() << "\" to build index.\n";
45 : return;
46 : }
47 :
48 0 : if(c->p_indices && c->p_indices->find(a) != c->p_indices->end()) {
49 0 : Oks::error_msg(fname)
50 0 : << "Class \"" << c->get_name() << "\" already has index for attribute \""
51 0 : << a->p_name << "\".\n";
52 : return;
53 : }
54 :
55 0 : offset = ((*c->p_data_info)[a->p_name])->offset;
56 :
57 0 : if(!c->p_indices)
58 0 : c->p_indices = new OksIndex::Map();
59 :
60 0 : (*c->p_indices)[a] = this;
61 :
62 0 : if(c->p_objects && !c->p_objects->empty()) {
63 0 : for(OksObject::Map::iterator i = c->p_objects->begin(); i != c->p_objects->end(); ++i)
64 0 : insert((*i).second);
65 : }
66 :
67 0 : std::cout << "Build index for attribute \'" << a->p_name << "\' in class \'" << c->get_name()
68 0 : << "\' for " << size() << " instances\n";
69 :
70 : #ifdef DEBUG_INDICES
71 : for(int j=0; j<entries(); j++) {
72 : OksObject *obj = at(j);
73 :
74 : std::cout << j << ".\tobject id \'" << obj->GetId() << "\' "
75 : << "\tvalue: \'" << obj->data[offset] << "\'\n";
76 : }
77 : #endif
78 0 : }
79 :
80 0 : OksIndex::~OksIndex()
81 : {
82 0 : if(c && a) {
83 0 : c->p_indices->erase(a);
84 :
85 0 : if(c->p_indices->empty()) {
86 0 : delete c->p_indices;
87 0 : c->p_indices = 0;
88 : }
89 : }
90 0 : }
91 :
92 :
93 : OksObject*
94 0 : OksIndex::remove_obj(OksObject *o)
95 : {
96 0 : std::pair<Position, Position> positions = equal_range(o);
97 0 : Position i = positions.first;
98 0 : Position i2 = positions.second;
99 :
100 0 : for(; i != i2; ++i) {
101 0 : if(o == *i) {
102 0 : erase(i);
103 0 : return o;
104 : }
105 : }
106 :
107 : return 0;
108 : }
109 :
110 :
111 : OksObject *
112 0 : OksIndex::FindFirst(OksData *d) const
113 : {
114 0 : OksObject test_o(offset, d);
115 :
116 0 : ConstPosition pos = lower_bound(&test_o);
117 :
118 0 : if(pos != end()) return *pos;
119 :
120 : return 0;
121 0 : }
122 :
123 :
124 : void
125 0 : OksIndex::find_interval(OksData *d, OksQuery::Comparator f, ConstPosition& i1, ConstPosition& i2) const
126 : {
127 0 : i1 = i2 = end();
128 :
129 0 : if(empty()) return;
130 :
131 0 : OksObject test_o(offset, d);
132 :
133 0 : if(f == OksQuery::equal_cmp) {
134 0 : i1 = lower_bound(&test_o);
135 :
136 0 : if(i1 != end()) {
137 0 : if((*i1)->data[offset] == *d) {
138 0 : i2 = upper_bound(&test_o);
139 : }
140 : else {
141 0 : i2 = i1;
142 : }
143 : }
144 : }
145 0 : else if(f == OksQuery::less_or_equal_cmp || f == OksQuery::less_cmp) {
146 0 : i1 = begin();
147 :
148 0 : if(f == OksQuery::less_cmp) {
149 0 : i2 = lower_bound(&test_o);
150 : }
151 : else {
152 0 : i2 = upper_bound(&test_o);
153 : }
154 : }
155 0 : else if(f == OksQuery::greater_or_equal_cmp || f == OksQuery::greater_cmp) {
156 0 : i2 = end();
157 :
158 0 : if(f == OksQuery::greater_cmp) {
159 0 : i1 = upper_bound(&test_o);
160 : }
161 : else {
162 0 : i1 = lower_bound(&test_o);
163 : }
164 : }
165 0 : }
166 :
167 :
168 : OksObject::List *
169 0 : OksIndex::find_all(OksData *d, OksQuery::Comparator f) const
170 : {
171 0 : OksObject::List * olist = 0;
172 :
173 0 : ConstPosition pos1, pos2;
174 :
175 0 : find_interval(d, f, pos1, pos2);
176 :
177 0 : if(pos1 != pos2) {
178 0 : olist = new OksObject::List();
179 0 : for(;pos1 != pos2; ++pos1) olist->push_back(*pos1);
180 : }
181 :
182 0 : return olist;
183 : }
184 :
185 :
186 : OksObject::List *
187 0 : OksIndex::find_all(bool andOperation, OksData *d1, OksQuery::Comparator f1, OksData *d2, OksQuery::Comparator f2) const
188 : {
189 0 : OksObject::List * olist = 0;
190 :
191 0 : ConstPosition a1, b1;
192 :
193 0 : find_interval(d1, f1, a1, b1);
194 :
195 0 : if((andOperation == true) && (a1 == b1)) return 0;
196 :
197 0 : ConstPosition a2, b2;
198 :
199 0 : find_interval(d2, f2, a2, b2);
200 :
201 0 : if(andOperation == true) {
202 0 : if(a2 == b2) return 0;
203 :
204 :
205 : //
206 : // find intersection ([pos1,pos2] or NIL) of [a1,b1] and [a2,b2]
207 : // where begin() <= {a1,b1,a2,b2} <= end())
208 : //
209 : // (note that a1 and a2 are not equal to end() but b1 nad b2 have to be tested)
210 : //
211 :
212 0 : ConstPosition pos1, pos2;
213 :
214 0 : if((*a2)->data[offset] <= (*a1)->data[offset]) {
215 0 : if((b2 != end()) && ((*b2)->data[offset] < (*a1)->data[offset])) return 0;
216 0 : pos1 = a1;
217 : }
218 : else {
219 0 : if((b1 != end()) && (*a2)->data[offset] > (*b1)->data[offset]) return 0;
220 0 : pos1 = a2;
221 : }
222 :
223 0 : if(b2 == end() || b1 == end()) {
224 0 : pos2 = (b2 != end()) ? b2 : b1;
225 : }
226 : else
227 0 : pos2 = ((*b2)->data[offset] <= (*b1)->data[offset]) ? b2 : b1;
228 :
229 0 : olist = new OksObject::List();
230 0 : for(;pos1 != pos2; ++pos1) olist->push_back(*pos1);
231 : }
232 : else {
233 0 : if(a1 != b1 && a2 == b2) {
234 0 : olist = new OksObject::List();
235 0 : for(;a1 != b1; ++a1) olist->push_back(*a1);
236 : }
237 0 : else if(a2 != b2 && a1 == b1) {
238 0 : olist = new OksObject::List();
239 0 : for(;a2 != b2; ++a2) olist->push_back(*a2);
240 : }
241 0 : else if(a1 != b1 && a2 != b2) {
242 0 : olist = new OksObject::List();
243 :
244 :
245 : //
246 : // find union of [a1,b1] and [a2,b2] (i.e. [pos1,pos2] or [a1,b1],[a2,b2])
247 : // where begin() <= {a1,b1,a2,b2} <= end())
248 : //
249 : // (note that a1 and a2 are not equal to end() but b1 nad b2 have to be tested)
250 : //
251 :
252 0 : ConstPosition pos1, pos2;
253 :
254 0 : if((*a2)->data[offset] <= (*a1)->data[offset]) {
255 0 : if(b2 != end() && (*b2)->data[offset] < (*a1)->data[offset]) {
256 0 : for(;a2 != b2; ++a2) olist->push_back(*a2);
257 0 : for(;a1 != b1; ++a1) olist->push_back(*a1);
258 :
259 0 : return olist;
260 : }
261 :
262 0 : pos1 = a2;
263 : }
264 : else {
265 0 : if(b1 != end() && (*a2)->data[offset] > (*b1)->data[offset]) {
266 0 : for(;a1 != b1; ++a1) olist->push_back(*a1);
267 0 : for(;a2 != b2; ++a2) olist->push_back(*a2);
268 :
269 : return olist;
270 : }
271 :
272 0 : pos1 = a1;
273 : }
274 :
275 0 : if(b2 == end() || b1 == end()) {
276 0 : pos2 = (b2 == end()) ? b2 : b1;
277 : }
278 : else
279 0 : pos2 = ((*b2)->data[offset] >= (*b1)->data[offset]) ? b2 : b1;
280 :
281 0 : for(;pos1 != pos2; ++pos1) olist->push_back(*pos1);
282 : }
283 : }
284 :
285 : return olist;
286 : }
287 :
288 : } // namespace oks
289 : } // namespace dunedaq
|