Line data Source code
1 : #define _OksBuildDll_
2 :
3 : #include "oks/object.hpp"
4 : #include "oks/xml.hpp"
5 : #include "oks/attribute.hpp"
6 : #include "oks/relationship.hpp"
7 : #include "oks/class.hpp"
8 : #include "oks/kernel.hpp"
9 : #include "oks/cstring.hpp"
10 :
11 : #include "oks_utils.hpp"
12 :
13 : #include "logging/Logging.hpp"
14 :
15 : #include <string.h>
16 : #include <stdlib.h>
17 :
18 : #include <string>
19 : #include <sstream>
20 : #include <stdexcept>
21 : #include <limits>
22 :
23 : #include <boost/date_time/posix_time/time_formatters.hpp>
24 : #include <boost/date_time/posix_time/time_parsers.hpp>
25 : #include <boost/date_time/gregorian/gregorian.hpp>
26 :
27 :
28 : namespace dunedaq {
29 36 : ERS_DECLARE_ISSUE(
30 : oks,
31 : DeprecatedFormat,
32 : "the file " << file << " contains OKS time data stored in deprecated format \'" << data << "\'. Please refresh it using an oks application. Support for such format will be removed in a future release.",
33 : ((const char *)file)
34 : ((const char *)data)
35 : )
36 :
37 : namespace oks {
38 : // ugly reinterpret staff to convert date and time to integers
39 :
40 0 : void OksData::SetFast(boost::gregorian::date d)
41 : {
42 0 : data.DATE = d.day_number();
43 0 : }
44 :
45 0 : void OksData::SetFast(boost::posix_time::ptime t)
46 : {
47 0 : data.TIME = *reinterpret_cast<uint64_t*>(&t);
48 0 : }
49 :
50 0 : boost::gregorian::date OksData::date() const noexcept
51 : {
52 0 : return boost::gregorian::date(boost::gregorian::gregorian_calendar::from_day_number(data.DATE));
53 : }
54 :
55 0 : boost::posix_time::ptime OksData::time() const noexcept
56 : {
57 0 : return *reinterpret_cast<boost::posix_time::ptime*>(const_cast<uint64_t*>(&data.TIME));
58 : }
59 :
60 :
61 2104 : inline void free_list(OksData::List& dlist)
62 : {
63 6626 : for(OksData::List::const_iterator i = dlist.begin(); i != dlist.end(); ++i) {
64 4522 : delete *i;
65 : }
66 2104 : dlist.clear();
67 2104 : }
68 :
69 :
70 : static bool
71 0 : operator==(const OksData::List & l1, const OksData::List & l2)
72 : {
73 0 : if(&l1 == &l2) return true;
74 :
75 0 : size_t l1Lenght = l1.size();
76 0 : size_t l2Lenght = l2.size();
77 :
78 0 : if(!l1Lenght && !l2Lenght) return true;
79 0 : if(l1Lenght != l2Lenght) return false;
80 :
81 0 : size_t pos = 0;
82 :
83 0 : auto i1 = l1.begin();
84 0 : auto i2 = l2.begin();
85 :
86 0 : for(;i1 != l1.end(); ++i1, ++i2) {
87 0 : OksData * d1 = *i1;
88 0 : OksData * d2 = *i2;
89 :
90 0 : if( !d1 && !d2 ) return true;
91 0 : if( !d1 || !d2 ) return false;
92 :
93 0 : if(
94 : (
95 0 : (d1->type == d2->type) &&
96 0 : (d1->type == OksData::object_type) &&
97 : (
98 0 : (!d1->data.OBJECT && !d2->data.OBJECT) ||
99 : (
100 0 : (d1->data.OBJECT && d2->data.OBJECT) &&
101 0 : (d1->data.OBJECT->GetClass()->get_name() == d2->data.OBJECT->GetClass()->get_name()) &&
102 0 : (d1->data.OBJECT->GetId() == d2->data.OBJECT->GetId())
103 : )
104 : )
105 0 : ) ||
106 : (
107 0 : (*d1 == *d2)
108 : )
109 : ) {
110 0 : pos++;
111 0 : continue;
112 : }
113 :
114 : return false;
115 : }
116 :
117 : return true;
118 : }
119 :
120 :
121 : bool
122 2589 : OksData::operator==(const OksData& d) const {
123 2589 : return (
124 2589 : (d.type == type) &&
125 : (
126 2589 : ( (type == string_type) && (*d.data.STRING == *data.STRING) ) ||
127 2589 : ( (type == u32_int_type) && (d.data.U32_INT == data.U32_INT) ) ||
128 2589 : ( (type == s32_int_type) && (d.data.S32_INT == data.S32_INT) ) ||
129 2589 : ( (type == u16_int_type) && (d.data.U16_INT == data.U16_INT) ) ||
130 2589 : ( (type == s16_int_type) && (d.data.S16_INT == data.S16_INT) ) ||
131 2589 : ( (type == s8_int_type) && (d.data.S8_INT == data.S8_INT) ) ||
132 2589 : ( (type == u8_int_type) && (d.data.U8_INT == data.U8_INT) ) ||
133 2589 : ( (type == s64_int_type) && (d.data.S64_INT == data.S64_INT) ) ||
134 2589 : ( (type == u64_int_type) && (d.data.U64_INT == data.U64_INT) ) ||
135 2589 : ( (type == float_type) && (d.data.FLOAT == data.FLOAT) ) ||
136 2589 : ( (type == double_type) && (d.data.DOUBLE == data.DOUBLE) ) ||
137 2589 : ( (type == bool_type) && (d.data.BOOL == data.BOOL) ) ||
138 2589 : ( (type == date_type) && (d.data.DATE == data.DATE) ) ||
139 2589 : ( (type == time_type) && (d.data.TIME == data.TIME) ) ||
140 0 : ( (type == object_type) && OksObject::are_equal_fast(d.data.OBJECT, data.OBJECT) ) ||
141 2589 : ( (type == list_type) && (*d.data.LIST == *data.LIST) ) ||
142 2589 : ( (type == uid_type) && (d.data.UID.class_id->get_name() == data.UID.class_id->get_name() && *d.data.UID.object_id == *data.UID.object_id) ) ||
143 2589 : ( (type == uid2_type) && (*d.data.UID2.class_id == *data.UID2.class_id && *d.data.UID2.object_id == *data.UID2.object_id) ) ||
144 2589 : ( (type == enum_type) && (*d.data.ENUMERATION == *data.ENUMERATION) ) ||
145 0 : ( (type == class_type) && (d.data.CLASS->get_name() == data.CLASS->get_name()) )
146 : )
147 2589 : );
148 : }
149 :
150 : bool
151 0 : OksData::operator!=(const OksData& d) const {
152 0 : return ( (d == *this) ? false : true );
153 : }
154 :
155 :
156 : static bool
157 366 : test_comparable(OksData::Type type1, OksData::Type type2)
158 : {
159 366 : const char * fname = "OksData::operator[<|<=|>|>=](const OksData&) const";
160 366 : const char * h3 = "Can't compare ";
161 :
162 366 : if(type1 != type2 && !(OksData::is_object(type1) && OksData::is_object(type2))) {
163 0 : Oks::error_msg(fname) << h3 << "OKS data of different types\n";
164 0 : return false;
165 : }
166 366 : else if(type1 == OksData::list_type) {
167 0 : Oks::error_msg(fname) << h3 << "lists\n";
168 0 : return false;
169 : }
170 :
171 : return true;
172 : }
173 :
174 : const std::string&
175 0 : OksData::__oid() const
176 : {
177 0 : if(type == object_type)
178 0 : return data.OBJECT->uid.object_id;
179 0 : else if(type == uid_type)
180 0 : return *data.UID.object_id;
181 : else
182 0 : return *data.UID2.object_id;
183 : }
184 :
185 : const std::string&
186 0 : OksData::__cn() const
187 : {
188 0 : if(type == object_type)
189 0 : return data.OBJECT->uid.class_id->get_name();
190 0 : else if(type == uid_type)
191 0 : return data.UID.class_id->get_name();
192 : else
193 0 : return *data.UID2.class_id;
194 : }
195 :
196 : #define CMP_OBJ( OP, c1, c2, id1, id2 ) (c1 OP c2) || (!(c2 OP c1) && id1 OP id2)
197 :
198 : #define CMP_DATA( OP ) \
199 : switch(type) { \
200 : case string_type: return (*data.STRING OP *d.data.STRING); \
201 : case u32_int_type: return (data.U32_INT OP d.data.U32_INT); \
202 : case s32_int_type: return (data.S32_INT OP d.data.S32_INT); \
203 : case u16_int_type: return (data.U16_INT OP d.data.U16_INT); \
204 : case s16_int_type: return (data.S16_INT OP d.data.S16_INT); \
205 : case s8_int_type: return (data.S8_INT OP d.data.S8_INT); \
206 : case u8_int_type: return (data.U8_INT OP d.data.U8_INT); \
207 : case s64_int_type: return (data.S64_INT OP d.data.S64_INT); \
208 : case u64_int_type: return (data.U64_INT OP d.data.U64_INT); \
209 : case float_type: return (data.FLOAT OP d.data.FLOAT); \
210 : case double_type: return (data.DOUBLE OP d.data.DOUBLE); \
211 : case bool_type: return (data.BOOL OP d.data.BOOL); \
212 : case date_type: return (data.DATE OP d.data.DATE); \
213 : case time_type: return (data.TIME OP d.data.TIME); \
214 : case enum_type: return (*data.ENUMERATION OP *d.data.ENUMERATION); \
215 : case class_type: return (data.CLASS->get_name() OP d.data.CLASS->get_name()); \
216 : case object_type: \
217 : case uid_type: \
218 : case uid2_type: \
219 : return CMP_OBJ ( OP, __cn(), d.__cn(), __oid(), d.__oid() ); \
220 : default: return false; \
221 : }
222 :
223 :
224 183 : bool OksData::is_le(const OksData &d) const noexcept
225 : {
226 183 : CMP_DATA( <= )
227 : }
228 :
229 183 : bool OksData::is_ge(const OksData &d) const noexcept
230 : {
231 183 : CMP_DATA( >= )
232 : }
233 :
234 0 : bool OksData::is_l(const OksData &d) const noexcept
235 : {
236 0 : CMP_DATA( < )
237 : }
238 :
239 0 : bool OksData::is_g(const OksData &d) const noexcept
240 : {
241 0 : CMP_DATA( > )
242 : }
243 :
244 :
245 : bool
246 183 : OksData::operator<=(const OksData& d) const {
247 183 : if(test_comparable(type, d.type) == false) return false;
248 183 : return is_le(d);
249 : }
250 :
251 :
252 : bool
253 183 : OksData::operator>=(const OksData& d) const {
254 183 : if(test_comparable(type, d.type) == false) return false;
255 183 : return is_ge(d);
256 : }
257 :
258 :
259 : bool
260 0 : OksData::operator>(const OksData& d) const {
261 0 : if(test_comparable(type, d.type) == false) return false;
262 0 : return is_g(d);
263 : }
264 :
265 :
266 : bool
267 0 : OksData::operator<(const OksData& d) const {
268 0 : if(test_comparable(type, d.type) == false) return false;
269 0 : return is_l(d);
270 : }
271 :
272 :
273 : void
274 14204 : OksData::copy(const OksData & d)
275 : {
276 14204 : type = d.type;
277 :
278 14204 : if(type == list_type) {
279 885 : data.LIST = new List();
280 :
281 1004 : for(List::iterator i = d.data.LIST->begin(); i != d.data.LIST->end(); ++i) {
282 119 : OksData *d2 = new OksData();
283 119 : *d2 = *(*i);
284 119 : data.LIST->push_back(d2);
285 : }
286 : }
287 5660 : else if(type == string_type) data.STRING = new OksString(*d.data.STRING);
288 19 : else if(type == object_type) data.OBJECT = d.data.OBJECT; // Don't allow deep copy for objects
289 2954 : else if(type == u32_int_type) data.U32_INT = d.data.U32_INT;
290 100 : else if(type == s32_int_type) data.S32_INT = d.data.S32_INT;
291 421 : else if(type == u16_int_type) data.U16_INT = d.data.U16_INT;
292 5 : else if(type == s16_int_type) data.S16_INT = d.data.S16_INT;
293 0 : else if(type == double_type) data.DOUBLE = d.data.DOUBLE;
294 20 : else if(type == float_type) data.FLOAT = d.data.FLOAT;
295 0 : else if(type == s8_int_type) data.S8_INT = d.data.S8_INT;
296 100 : else if(type == u8_int_type) data.U8_INT = d.data.U8_INT;
297 0 : else if(type == s64_int_type) data.S64_INT = d.data.S64_INT;
298 32 : else if(type == u64_int_type) data.U64_INT = d.data.U64_INT;
299 10 : else if(type == class_type) data.CLASS = d.data.CLASS;
300 : else if(type == uid2_type) {
301 0 : data.UID2.class_id = new OksString(*d.data.UID2.class_id);
302 0 : data.UID2.object_id = new OksString(*d.data.UID2.object_id);
303 : }
304 : else if(type == uid_type) {
305 0 : data.UID.class_id = d.data.UID.class_id;
306 0 : data.UID.object_id = new OksString(*d.data.UID.object_id);
307 : }
308 703 : else if(type == bool_type) data.BOOL = d.data.BOOL;
309 0 : else if(type == date_type) data.DATE = d.data.DATE;
310 0 : else if(type == time_type) data.TIME = d.data.TIME;
311 3295 : else if(type == enum_type) data.ENUMERATION = d.data.ENUMERATION;
312 14204 : }
313 :
314 :
315 : std::ostream&
316 0 : operator<<(std::ostream& s, const OksData & d)
317 : {
318 0 : switch (d.type) {
319 0 : case OksData::list_type: {
320 0 : s << '(';
321 0 : for(OksData::List::iterator i = d.data.LIST->begin(); i != d.data.LIST->end(); ++i) {
322 0 : s << *(*i);
323 0 : if((*i) != d.data.LIST->back()) s << ", ";
324 : }
325 0 : s << ')';
326 0 : break; }
327 :
328 0 : case OksData::string_type:
329 0 : s << '\"' << *(d.data.STRING) << '\"';
330 0 : break;
331 :
332 0 : case OksData::object_type:
333 0 : if(d.data.OBJECT)
334 0 : s << '[' << d.data.OBJECT->GetId() << '@' << d.data.OBJECT->GetClass()->get_name() << ']';
335 : else
336 0 : s << "[NIL]";
337 :
338 : break;
339 :
340 0 : case OksData::uid2_type:
341 0 : s << '#' << '[' << *d.data.UID2.object_id << '@' << *d.data.UID2.class_id << ']';
342 0 : break;
343 :
344 0 : case OksData::uid_type:
345 0 : s << '#' << '[' << *d.data.UID.object_id << '@' << d.data.UID.class_id->get_name() << ']';
346 0 : break;
347 :
348 0 : case OksData::s32_int_type:
349 0 : s << d.data.S32_INT;
350 0 : break;
351 :
352 0 : case OksData::u32_int_type:
353 0 : s << d.data.U32_INT;
354 0 : break;
355 :
356 0 : case OksData::s16_int_type:
357 0 : s << d.data.S16_INT;
358 0 : break;
359 :
360 0 : case OksData::u16_int_type:
361 0 : s << d.data.U16_INT;
362 0 : break;
363 :
364 0 : case OksData::float_type: {
365 0 : std::streamsize p = s.precision();
366 0 : s.precision(std::numeric_limits< float >::digits10);
367 0 : s << d.data.FLOAT;
368 0 : s.precision(p);
369 0 : break; }
370 :
371 0 : case OksData::double_type: {
372 0 : std::streamsize p = s.precision();
373 0 : s.precision(std::numeric_limits< double >::digits10);
374 0 : s << d.data.DOUBLE;
375 0 : s.precision(p);
376 0 : break; }
377 :
378 0 : case OksData::s8_int_type:
379 0 : s << static_cast<int16_t>(d.data.S8_INT);
380 0 : break;
381 :
382 0 : case OksData::u8_int_type:
383 0 : s << static_cast<uint16_t>(d.data.U8_INT);
384 0 : break;
385 :
386 0 : case OksData::s64_int_type:
387 0 : s << d.data.S64_INT;
388 0 : break;
389 :
390 0 : case OksData::u64_int_type:
391 0 : s << d.data.U64_INT;
392 0 : break;
393 :
394 0 : case OksData::bool_type:
395 0 : s << ( (d.data.BOOL == true) ? "true" : "false" );
396 0 : break;
397 :
398 0 : case OksData::date_type:
399 0 : s << boost::gregorian::to_simple_string(d.date());
400 0 : break;
401 :
402 0 : case OksData::time_type:
403 0 : s << boost::posix_time::to_simple_string(d.time());
404 0 : break;
405 :
406 0 : case OksData::enum_type:
407 0 : s << '\"' << *(d.data.ENUMERATION) << '\"';
408 0 : break;
409 :
410 0 : case OksData::class_type:
411 0 : s << '[' << d.data.CLASS->get_name() << ']';
412 0 : break;
413 :
414 0 : case OksData::unknown_type:
415 0 : Oks::error_msg("operator<<(ostream&, const OksData&)")
416 0 : << "Can't put to stream \'OksData::unknown_type\'";
417 0 : break;
418 : }
419 :
420 0 : return s;
421 : }
422 :
423 :
424 : void
425 96335 : OksData::Clear()
426 : {
427 96335 : if(type >= string_type) {
428 30805 : switch(type) {
429 6075 : case list_type:
430 6075 : if(List * dlist = data.LIST) {
431 6075 : if(!dlist->empty()) {
432 2054 : free_list(*dlist);
433 : }
434 6075 : delete dlist;
435 : }
436 : break;
437 :
438 12887 : case string_type:
439 12887 : if(data.STRING) { delete data.STRING; }
440 : break;
441 :
442 0 : case uid2_type:
443 0 : if(data.UID2.object_id) { delete data.UID2.object_id; }
444 0 : if(data.UID2.class_id) { delete data.UID2.class_id; }
445 : break;
446 :
447 3132 : case uid_type:
448 3132 : if(data.UID.object_id) { delete data.UID.object_id; }
449 : break;
450 :
451 : default:
452 : /* Make compiler happy */
453 : break;
454 : }
455 : }
456 :
457 96335 : type = unknown_type;
458 96335 : }
459 :
460 : std::string
461 0 : AttributeRangeError::fill(const OksData * d, const std::string& range)
462 : {
463 0 : std::ostringstream s;
464 0 : s << "value ";
465 0 : if (d->type == OksData::string_type || d->type == OksData::enum_type)
466 0 : s << *d;
467 : else
468 0 : s << '\'' << *d << '\'';
469 0 : s << " is out of range \'" << range << '\'';
470 0 : return s.str();
471 0 : }
472 :
473 : std::string
474 0 : AttributeReadError::fill(const char * value, const char * type, const std::string& reason)
475 : {
476 0 : std::ostringstream s;
477 :
478 0 : if(value) { s << "string \'" << value << '\''; }
479 0 : else { s << "empty string"; }
480 :
481 0 : s << " is not a valid value for \'" << type << "\' type";
482 :
483 0 : if(!reason.empty()) s << ":\n" << reason;
484 :
485 0 : return s.str();
486 0 : }
487 :
488 : std::string
489 0 : AttributeReadError::fill(const char * type, const std::string& reason)
490 : {
491 0 : std::ostringstream s;
492 :
493 0 : s << "the string is not a valid value for \'" << type << "\' type";
494 :
495 0 : if(!reason.empty()) s << ":\n" << reason;
496 :
497 0 : return s.str();
498 0 : }
499 :
500 :
501 : void
502 9074 : OksData::check_range(const OksAttribute * a) const
503 : {
504 9074 : if (a->p_range_obj == nullptr)
505 : return;
506 :
507 1634 : if (type == list_type)
508 : {
509 5 : if (data.LIST)
510 : {
511 10 : for (const auto& i : *data.LIST)
512 : {
513 5 : i->check_range(a);
514 : }
515 : }
516 : }
517 : else
518 : {
519 1629 : if (a->p_range_obj->validate(*this) == false)
520 : {
521 0 : throw AttributeRangeError(this, a->get_range());
522 : }
523 : }
524 : }
525 :
526 : void
527 10810 : OksData::SetNullValue(const OksAttribute * a)
528 : {
529 10810 : switch(type) {
530 0 : case s8_int_type: data.S8_INT = 0; return;
531 191 : case u8_int_type: data.U8_INT = 0; return;
532 561 : case bool_type: data.BOOL = false; return;
533 2854 : case u32_int_type: data.U32_INT = 0L; return;
534 223 : case s32_int_type: data.S32_INT = 0L; return;
535 16 : case s16_int_type: data.S16_INT = 0; return;
536 358 : case u16_int_type: data.U16_INT = 0; return;
537 22 : case s64_int_type: data.S64_INT = (int64_t)(0); return;
538 86 : case u64_int_type: data.U64_INT = (uint64_t)(0); return;
539 65 : case float_type: data.FLOAT = (float)(.0); return;
540 11 : case double_type: data.DOUBLE = (double)(.0); return;
541 5519 : case string_type: data.STRING = new OksString(); return;
542 829 : case enum_type: data.ENUMERATION = &((*(a->p_enumerators))[0]); return; // first value
543 75 : case class_type: data.CLASS = a->p_class; return; // some class
544 0 : case date_type: SetFast(boost::gregorian::day_clock::universal_day()); return;
545 0 : case time_type: SetFast(boost::posix_time::second_clock::universal_time()); return;
546 0 : default: Clear2(); throw AttributeReadError("", "non-attribute-type", "internal OKS error");
547 : }
548 : }
549 :
550 :
551 : void
552 3945 : OksData::SetValue(const char * s, const OksAttribute * a)
553 : {
554 3945 : if(*s == '\0') {
555 0 : SetNullValue(a);
556 : }
557 : else {
558 3945 : switch(type) {
559 0 : case s8_int_type: data.S8_INT = static_cast<int8_t>(strtol(s, 0, 0)); return;
560 221 : case u8_int_type: data.U8_INT = static_cast<uint8_t>(strtoul(s, 0, 0)); return;
561 543 : case bool_type: switch(strlen(s)) {
562 270 : case 4: data.BOOL = (cmp_str4n(s, "true") || cmp_str4n(s, "TRUE") || cmp_str4n(s, "True")); return;
563 25 : case 1: data.BOOL = (*s == 't' || *s == 'T' || *s == '1'); return;
564 253 : default: data.BOOL = false; return;
565 : }
566 2228 : case u32_int_type: data.U32_INT = static_cast<uint32_t>(strtoul(s, 0, 0)); return;
567 223 : case s32_int_type: data.S32_INT = static_cast<int32_t>(strtol(s, 0, 0)); return;
568 16 : case s16_int_type: data.S16_INT = static_cast<int16_t>(strtol(s, 0, 0)); return;
569 385 : case u16_int_type: data.U16_INT = static_cast<uint16_t>(strtoul(s, 0, 0)); return;
570 22 : case s64_int_type: data.S64_INT = static_cast<int64_t>(strtoll(s, 0, 0)); return;
571 88 : case u64_int_type: data.U64_INT = static_cast<uint64_t>(strtoull(s, 0, 0)); return;
572 65 : case float_type: data.FLOAT = strtof(s, 0); return;
573 11 : case double_type: data.DOUBLE = strtod(s, 0); return;
574 :
575 9 : case string_type: data.STRING = new OksString(s); return;
576 1 : case enum_type: try {
577 1 : data.ENUMERATION = a->get_enum_value(s, strlen(s)); return;
578 : }
579 0 : catch(std::exception& ex) {
580 0 : throw AttributeReadError(s, "enum", ex.what());
581 0 : }
582 0 : case date_type: try {
583 0 : if(strchr(s, '-') || strchr(s, '/')) {
584 0 : SetFast(boost::gregorian::from_simple_string(s)); return;
585 : }
586 : else {
587 0 : SetFast(boost::gregorian::from_undelimited_string(s)); return;
588 : }
589 : }
590 0 : catch(std::exception& ex) {
591 0 : throw AttributeReadError(s, "date", ex.what());
592 0 : }
593 0 : case time_type: try {
594 0 : if(strlen(s) == 15 && s[8] == 'T') {
595 0 : SetFast(boost::posix_time::from_iso_string(s)); return;
596 : }
597 : else {
598 0 : SetFast(boost::posix_time::time_from_string(s)); return;
599 : }
600 : }
601 0 : catch(std::exception& ex) {
602 0 : throw AttributeReadError(s, "time", ex.what());
603 0 : }
604 133 : case class_type: if(OksClass * c = a->p_class->get_kernel()->find_class(s)) {
605 133 : data.CLASS = c; return;
606 : }
607 : else {
608 0 : Clear2(); throw AttributeReadError(s, "class", "the value is not a name of valid OKS class");
609 : }
610 0 : default: Clear2(); throw AttributeReadError(s, "non-attribute-type", "internal OKS error");
611 : }
612 : }
613 :
614 : }
615 :
616 :
617 : std::list<std::string>
618 0 : OksAttribute::get_init_values() const
619 : {
620 0 : std::list<std::string> val;
621 :
622 : // check, if the attribute is multi-value
623 0 : if(get_is_multi_values() == true) {
624 0 : OksData d;
625 0 : d.SetValues(get_init_value().c_str(), this);
626 :
627 0 : for(OksData::List::const_iterator i = d.data.LIST->begin(); i != d.data.LIST->end(); ++i) {
628 0 : val.push_back((*i)->str());
629 : }
630 0 : }
631 :
632 0 : return val;
633 0 : }
634 :
635 :
636 : void
637 1597 : OksData::SetValues(const char *s, const OksAttribute *a)
638 : {
639 1597 : if( !a->get_is_multi_values() ) {
640 0 : ReadFrom(s, a->get_data_type(), a);
641 1503 : return;
642 : }
643 :
644 1597 : if(type != list_type) {
645 1525 : Set(new List());
646 : }
647 72 : else if(!data.LIST->empty()) {
648 4 : free_list(*data.LIST);
649 : }
650 :
651 1597 : if( !s ) return;
652 1597 : while( *s == ' ' ) s++;
653 1597 : if( *s == '\0' ) return;
654 :
655 94 : std::string str(s);
656 :
657 263 : while( str.length() ) {
658 169 : while( str.length() && str[0] == ' ') str.erase(0, 1);
659 169 : if( !str.length() ) return;
660 169 : char delimeter = (
661 169 : str[0] == '\"' ? '\"' :
662 : str[0] == '\'' ? '\'' :
663 : str[0] == '`' ? '`' :
664 : ','
665 : );
666 :
667 150 : if(delimeter != ',') str.erase(0, 1);
668 169 : std::string::size_type p = str.find(delimeter);
669 :
670 169 : OksData *d = new OksData();
671 169 : d->type = a->get_data_type();
672 :
673 169 : if(d->type == OksData::string_type) {
674 159 : d->data.STRING = new OksString(str, p);
675 : }
676 10 : else if(d->type == OksData::enum_type) {
677 0 : std::string token(str, 0, p);
678 0 : d->data.ENUMERATION = a->get_enum_value(token); // FIXME, create more efficient using compare(idx, len ,str)
679 0 : }
680 : else {
681 10 : std::string token(str, 0, p);
682 10 : d->SetValue(token.c_str(), a);
683 10 : }
684 :
685 169 : data.LIST->push_back(d);
686 :
687 169 : str.erase(0, p);
688 169 : if(str.length()) {
689 150 : if(delimeter != ',') {
690 150 : p = str.find(',');
691 150 : if( p == std::string::npos )
692 : p = str.length();
693 : else
694 75 : p++;
695 150 : str.erase(0, p);
696 : }
697 : else
698 0 : str.erase(0, 1);
699 : }
700 : }
701 94 : }
702 :
703 :
704 : void
705 0 : OksData::ReadFrom(const OksRelationship *r) noexcept
706 : {
707 0 : if(r->get_high_cardinality_constraint() != OksRelationship::Many) {
708 0 : Set((OksObject *)0);
709 : }
710 : else {
711 0 : Set(new List());
712 : }
713 0 : }
714 :
715 :
716 : void
717 0 : OksXmlInputStream::get_num_token(char __last)
718 : {
719 0 : size_t pos(1);
720 :
721 0 : try {
722 0 : char c = get_first_non_empty();
723 :
724 0 : if(c == __last) {
725 0 : m_cvt_char->m_buf[0] = 0;
726 0 : throw std::runtime_error("empty numeric value");
727 : }
728 :
729 0 : m_cvt_char->m_buf[0] = c;
730 :
731 0 : while(true) {
732 0 : c = get();
733 :
734 0 : if(c == __last) {
735 0 : m_cvt_char->m_buf[pos] = '\0';
736 0 : f->unget();
737 : return;
738 : }
739 0 : else if(c == ' ' || c == '\n' || c == '\r' || c == '\t') {
740 0 : m_cvt_char->m_buf[pos] = '\0';
741 0 : return;
742 : }
743 :
744 0 : m_cvt_char->realloc(pos);
745 0 : m_cvt_char->m_buf[pos++] = c;
746 : }
747 : }
748 0 : catch(std::exception& ex) {
749 0 : m_cvt_char->m_buf[pos] = '\0';
750 0 : throw BadFileData(std::string("failed to read numeric value: ") + ex.what(), line_no, line_pos);
751 0 : }
752 : }
753 :
754 : void
755 0 : OksData::read(const ReadFileParams& read_params, const OksAttribute * a, /*atype,*/ int32_t num)
756 : {
757 0 : if(type != list_type) {
758 0 : Set(new List());
759 : }
760 0 : else if(!data.LIST->empty()) {
761 0 : free_list(*data.LIST);
762 : }
763 :
764 0 : while(num-- > 0) {
765 0 : data.LIST->push_back(new OksData(read_params, a));
766 : }
767 0 : }
768 :
769 :
770 : void
771 0 : OksData::read(const ReadFileParams& read_params, const OksAttribute *a)
772 : {
773 0 : const char * read_value=""; // is used for report in case of exception
774 0 : char * __sanity;
775 0 : OksXmlInputStream& fxs(read_params.s);
776 :
777 0 : try {
778 0 : switch(a->get_data_type()) {
779 0 : case string_type:
780 0 : read_value = "quoted string";
781 0 : {
782 0 : size_t len = fxs.get_quoted();
783 0 : if(type == string_type && data.STRING) {
784 0 : data.STRING->assign(fxs.get_xml_token().m_buf, len);
785 : }
786 : else {
787 0 : Clear();
788 0 : type = string_type;
789 0 : data.STRING = new OksString(fxs.get_xml_token().m_buf, len);
790 : }
791 : }
792 : break;
793 :
794 0 : case s32_int_type:
795 0 : read_value = "signed 32 bits integer";
796 0 : fxs.get_num_token('<');
797 0 : Set(static_cast<int32_t>(strtol(fxs.m_cvt_char->m_buf, &__sanity, 0)));
798 0 : if( __builtin_expect((*__sanity != 0 || errno == ERANGE), 0) ) OksXmlInputStream::__throw_strto("strtol", __sanity, fxs.m_cvt_char->m_buf, fxs.line_no, fxs.line_pos);
799 : break;
800 :
801 0 : case u32_int_type:
802 0 : read_value = "unsigned 32 bits integer";
803 0 : fxs.get_num_token('<');
804 0 : Set(static_cast<uint32_t>(strtoul(fxs.m_cvt_char->m_buf, &__sanity, 0)));
805 0 : if( __builtin_expect((*__sanity != 0 || errno == ERANGE), 0) ) OksXmlInputStream::__throw_strto("strtoul", __sanity, fxs.m_cvt_char->m_buf, fxs.line_no, fxs.line_pos);
806 : break;
807 :
808 0 : case s16_int_type:
809 0 : read_value = "signed 16 bits integer";
810 0 : fxs.get_num_token('<');
811 0 : Set(static_cast<int16_t>(strtol(fxs.m_cvt_char->m_buf, &__sanity, 0)));
812 0 : if( __builtin_expect((*__sanity != 0 || errno == ERANGE), 0) ) OksXmlInputStream::__throw_strto("strtol", __sanity, fxs.m_cvt_char->m_buf, fxs.line_no, fxs.line_pos);
813 : break;
814 :
815 0 : case u16_int_type:
816 0 : read_value = "unsigned 16 bits integer";
817 0 : fxs.get_num_token('<');
818 0 : Set(static_cast<uint16_t>(strtoul(fxs.m_cvt_char->m_buf, &__sanity, 0)));
819 0 : if( __builtin_expect((*__sanity != 0 || errno == ERANGE), 0) ) OksXmlInputStream::__throw_strto("strtoul", __sanity, fxs.m_cvt_char->m_buf, fxs.line_no, fxs.line_pos);
820 : break;
821 :
822 0 : case s8_int_type:
823 0 : read_value = "signed 8 bits integer";
824 0 : fxs.get_num_token('<');
825 0 : Set(static_cast<int8_t>(strtol(fxs.m_cvt_char->m_buf, &__sanity, 0)));
826 0 : if( __builtin_expect((*__sanity != 0 || errno == ERANGE), 0) ) OksXmlInputStream::__throw_strto("strtol", __sanity, fxs.m_cvt_char->m_buf, fxs.line_no, fxs.line_pos);
827 : break;
828 :
829 0 : case u8_int_type:
830 0 : read_value = "unsigned 8 bits integer";
831 0 : fxs.get_num_token('<');
832 0 : Set(static_cast<uint8_t>(strtoul(fxs.m_cvt_char->m_buf, &__sanity, 0)));
833 0 : if( __builtin_expect((*__sanity != 0 || errno == ERANGE), 0) ) OksXmlInputStream::__throw_strto("strtoul", __sanity, fxs.m_cvt_char->m_buf, fxs.line_no, fxs.line_pos);
834 : break;
835 :
836 0 : case s64_int_type:
837 0 : read_value = "signed 64 bits integer";
838 0 : fxs.get_num_token('<');
839 0 : Set(static_cast<int64_t>(strtoll(fxs.m_cvt_char->m_buf, &__sanity, 0)));
840 0 : if( __builtin_expect((*__sanity != 0 || errno == ERANGE), 0) ) OksXmlInputStream::__throw_strto("strtoll", __sanity, fxs.m_cvt_char->m_buf, fxs.line_no, fxs.line_pos);
841 : break;
842 :
843 0 : case u64_int_type:
844 0 : read_value = "unsigned 64 bits integer";
845 0 : fxs.get_num_token('<');
846 0 : Set(static_cast<uint64_t>(strtoull(fxs.m_cvt_char->m_buf, &__sanity, 0)));
847 0 : if( __builtin_expect((*__sanity != 0 || errno == ERANGE), 0) ) OksXmlInputStream::__throw_strto("strtoull", __sanity, fxs.m_cvt_char->m_buf, fxs.line_no, fxs.line_pos);
848 : break;
849 :
850 0 : case float_type:
851 0 : read_value = "float";
852 0 : fxs.get_num_token('<');
853 0 : Set(strtof(fxs.m_cvt_char->m_buf, &__sanity));
854 0 : if( __builtin_expect((*__sanity != 0 || errno == ERANGE), 0) ) OksXmlInputStream::__throw_strto("strtof", __sanity, fxs.m_cvt_char->m_buf, fxs.line_no, fxs.line_pos);
855 : break;
856 :
857 0 : case double_type:
858 0 : read_value = "double";
859 0 : fxs.get_num_token('<');
860 0 : Set(strtod(fxs.m_cvt_char->m_buf, &__sanity));
861 0 : if( __builtin_expect((*__sanity != 0 || errno == ERANGE), 0) ) OksXmlInputStream::__throw_strto("strtod", __sanity, fxs.m_cvt_char->m_buf, fxs.line_no, fxs.line_pos);
862 : break;
863 :
864 0 : case bool_type:
865 0 : read_value = "boolean";
866 0 : fxs.get_num_token('<');
867 0 : Set(static_cast<bool>(strtol(fxs.m_cvt_char->m_buf, &__sanity, 0)));
868 0 : if( __builtin_expect((*__sanity != 0 || errno == ERANGE), 0) ) OksXmlInputStream::__throw_strto("strtol", __sanity, fxs.m_cvt_char->m_buf, fxs.line_no, fxs.line_pos);
869 : break;
870 :
871 0 : case date_type:
872 0 : read_value = "quoted date string";
873 0 : {
874 0 : size_t len = fxs.get_quoted();
875 0 : Set(str2date(fxs.get_xml_token().m_buf, len));
876 : }
877 : break;
878 :
879 0 : case time_type:
880 0 : read_value = "quoted time string";
881 0 : {
882 0 : size_t len = fxs.get_quoted();
883 0 : Set(str2time(fxs.get_xml_token().m_buf, len));
884 : }
885 : break;
886 :
887 0 : case enum_type:
888 0 : read_value = "quoted enum string";
889 0 : {
890 0 : size_t len = fxs.get_quoted();
891 0 : SetE(fxs.get_xml_token().m_buf, len, a);
892 : }
893 : break;
894 :
895 0 : case uid2_type:
896 0 : read_value = "two quoted class-name / object-id strings";
897 0 : Set(new OksString(), new OksString());
898 0 : {
899 0 : size_t len = fxs.get_quoted();
900 0 : data.UID2.class_id->assign(fxs.get_xml_token().m_buf, len);
901 0 : len = fxs.get_quoted();
902 0 : data.UID2.object_id->assign(fxs.get_xml_token().m_buf, len);
903 : }
904 : break;
905 :
906 0 : case class_type:
907 0 : read_value = "quoted class-type string";
908 0 : type = class_type;
909 0 : fxs.get_quoted();
910 0 : SetValue(fxs.get_xml_token().m_buf, a);
911 : break;
912 :
913 0 : default:
914 0 : type = unknown_type;
915 0 : {
916 0 : std::ostringstream s;
917 0 : s << "Unknown attribute type \"" << (int)a->get_data_type() << "\" (line " << fxs.get_line_no() << ", char " << fxs.get_line_pos() << ')';
918 0 : throw std::runtime_error( s.str().c_str() );
919 0 : }
920 : }
921 : }
922 0 : catch (exception & e) {
923 0 : throw FailedRead(read_value, e);
924 0 : }
925 0 : catch (std::exception & e) {
926 0 : throw FailedRead(read_value, e.what());
927 0 : }
928 0 : }
929 :
930 :
931 : void
932 8741 : OksData::read(const OksAttribute *a, const OksXmlValue& value)
933 : {
934 8741 : const char * read_value=""; // is used for report in case of exception
935 8741 : char * __sanity;
936 :
937 8741 : try {
938 8741 : switch(a->get_data_type()) {
939 4235 : case string_type:
940 4235 : {
941 4235 : if(type == string_type && data.STRING) {
942 3727 : data.STRING->assign(value.buf(), value.len());
943 : }
944 : else {
945 508 : Clear();
946 508 : type = string_type;
947 508 : data.STRING = new OksString(value.buf(), value.len());
948 : }
949 : }
950 : break;
951 :
952 100 : case s32_int_type:
953 100 : read_value = "signed 32 bits integer";
954 100 : Set(static_cast<int32_t>(strtol(value.buf(), &__sanity, 0)));
955 100 : if( __builtin_expect((*__sanity != 0 || errno == ERANGE), 0) ) OksXmlInputStream::__throw_strto("strtol", __sanity, value.buf(), value.line_no(), value.line_pos());
956 : break;
957 :
958 2295 : case u32_int_type:
959 2295 : read_value = "unsigned 32 bits integer";
960 2295 : Set(static_cast<uint32_t>(strtoul(value.buf(), &__sanity, 0)));
961 2295 : if( __builtin_expect((*__sanity != 0 || errno == ERANGE), 0) ) OksXmlInputStream::__throw_strto("strtoul", __sanity, value.buf(), value.line_no(), value.line_pos());
962 : break;
963 :
964 14 : case s16_int_type:
965 14 : read_value = "signed 16 bits integer";
966 14 : Set(static_cast<int16_t>(strtol(value.buf(), &__sanity, 0)));
967 14 : if( __builtin_expect((*__sanity != 0 || errno == ERANGE), 0) ) OksXmlInputStream::__throw_strto("strtol", __sanity, value.buf(), value.line_no(), value.line_pos());
968 : break;
969 :
970 653 : case u16_int_type:
971 653 : read_value = "unsigned 16 bits integer";
972 653 : Set(static_cast<uint16_t>(strtoul(value.buf(), &__sanity, 0)));
973 653 : if( __builtin_expect((*__sanity != 0 || errno == ERANGE), 0) ) OksXmlInputStream::__throw_strto("strtoul", __sanity, value.buf(), value.line_no(), value.line_pos());
974 : break;
975 :
976 0 : case s8_int_type:
977 0 : read_value = "signed 8 bits integer";
978 0 : Set(static_cast<int8_t>(strtol(value.buf(), &__sanity, 0)));
979 0 : if( __builtin_expect((*__sanity != 0 || errno == ERANGE), 0) ) OksXmlInputStream::__throw_strto("strtol", __sanity, value.buf(), value.line_no(), value.line_pos());
980 : break;
981 :
982 5 : case u8_int_type:
983 5 : read_value = "unsigned 8 bits integer";
984 5 : Set(static_cast<uint8_t>(strtoul(value.buf(), &__sanity, 0)));
985 5 : if( __builtin_expect((*__sanity != 0 || errno == ERANGE), 0) ) OksXmlInputStream::__throw_strto("strtoul", __sanity, value.buf(), value.line_no(), value.line_pos());
986 : break;
987 :
988 0 : case s64_int_type:
989 0 : read_value = "signed 64 bits integer";
990 0 : Set(static_cast<int64_t>(strtoll(value.buf(), &__sanity, 0)));
991 0 : if( __builtin_expect((*__sanity != 0 || errno == ERANGE), 0) ) OksXmlInputStream::__throw_strto("strtoll", __sanity, value.buf(), value.line_no(), value.line_pos());
992 : break;
993 :
994 5 : case u64_int_type:
995 5 : read_value = "unsigned 64 bits integer";
996 5 : Set(static_cast<uint64_t>(strtoull(value.buf(), &__sanity, 0)));
997 5 : if( __builtin_expect((*__sanity != 0 || errno == ERANGE), 0) ) OksXmlInputStream::__throw_strto("strtoull", __sanity, value.buf(), value.line_no(), value.line_pos());
998 : break;
999 :
1000 20 : case float_type:
1001 20 : read_value = "float";
1002 20 : Set(strtof(value.buf(), &__sanity));
1003 20 : if( __builtin_expect((*__sanity != 0 || errno == ERANGE), 0) ) OksXmlInputStream::__throw_strto("strtof", __sanity, value.buf(), value.line_no(), value.line_pos());
1004 : break;
1005 :
1006 0 : case double_type:
1007 0 : read_value = "double";
1008 0 : Set(strtod(value.buf(), &__sanity));
1009 0 : if( __builtin_expect((*__sanity != 0 || errno == ERANGE), 0) ) OksXmlInputStream::__throw_strto("strtod", __sanity, value.buf(), value.line_no(), value.line_pos());
1010 : break;
1011 :
1012 666 : case bool_type:
1013 666 : read_value = "boolean";
1014 666 : Set(static_cast<bool>(strtol(value.buf(), &__sanity, 0)));
1015 666 : if( __builtin_expect((*__sanity != 0 || errno == ERANGE), 0) ) OksXmlInputStream::__throw_strto("strtol", __sanity, value.buf(), value.line_no(), value.line_pos());
1016 : break;
1017 :
1018 0 : case date_type:
1019 0 : read_value = "quoted date string";
1020 0 : Set(str2date(value.buf(), value.len()));
1021 : break;
1022 :
1023 0 : case time_type:
1024 0 : read_value = "quoted time string";
1025 0 : Set(str2time(value.buf(), value.len()));
1026 : break;
1027 :
1028 690 : case enum_type:
1029 690 : read_value = "quoted enum string";
1030 690 : SetE(value.buf(), value.len(), a);
1031 : break;
1032 :
1033 0 : case uid2_type:
1034 0 : read_value = "two quoted class-name / object-id strings";
1035 0 : {
1036 0 : std::ostringstream s;
1037 0 : s << "Unexpected uid2 type at (line " << value.line_no() << ", char " << value.line_pos() << ')';
1038 0 : throw std::runtime_error( s.str().c_str() );
1039 0 : }
1040 58 : break;
1041 :
1042 58 : case class_type:
1043 58 : read_value = "quoted class-type string";
1044 58 : type = class_type;
1045 58 : SetValue(value.buf(), a);
1046 : break;
1047 :
1048 0 : default:
1049 0 : type = unknown_type;
1050 0 : {
1051 0 : std::ostringstream s;
1052 0 : s << "Unknown attribute type \"" << (int)a->get_data_type() << "\" (line " << value.line_no() << ", char " << value.line_pos() << ')';
1053 0 : throw std::runtime_error( s.str().c_str() );
1054 0 : }
1055 : }
1056 : }
1057 0 : catch (exception & e) {
1058 0 : throw FailedRead(read_value, e);
1059 0 : }
1060 0 : catch (std::exception & e) {
1061 0 : throw FailedRead(read_value, e.what());
1062 0 : }
1063 8741 : }
1064 :
1065 : void
1066 273 : OksData::read(const OksAttribute *a, const ReadFileParams& read_params)
1067 : {
1068 273 : if (type != list_type)
1069 0 : Set(new List());
1070 273 : else if (!data.LIST->empty())
1071 46 : free_list(*data.LIST);
1072 :
1073 1927 : while (true)
1074 1100 : try
1075 : {
1076 1100 : const char * tag_start = read_params.s.get_tag_start();
1077 :
1078 : // check for closing tag
1079 1100 : if (*tag_start == '/' && cmp_str5n(tag_start+1, OksObject::attribute_xml_tag))
1080 : break;
1081 :
1082 827 : if (cmp_str4(tag_start, OksObject::data_xml_tag))
1083 : {
1084 827 : {
1085 827 : OksXmlAttribute attr(read_params.s);
1086 :
1087 827 : if (cmp_str3(attr.name(), OksObject::value_xml_attribute))
1088 : {
1089 827 : OksXmlValue value(read_params.s.get_value(attr.p_value_len));
1090 827 : data.LIST->push_back(new OksData(a, value));
1091 : }
1092 : else
1093 : {
1094 0 : std::ostringstream s;
1095 0 : s << "Unexpected attribute \"" << attr.name() << "\" instead of \"" << OksObject::value_xml_attribute << "\" (line " << read_params.s.get_line_no() << ", char " << read_params.s.get_line_pos() << ')';
1096 0 : throw std::runtime_error(s.str().c_str());
1097 0 : }
1098 : }
1099 827 : {
1100 827 : OksXmlAttribute attr(read_params.s);
1101 :
1102 827 : if (cmp_str1(attr.name(), "/") == false)
1103 : {
1104 0 : std::ostringstream s;
1105 0 : s << "Unexpected tag \"" << attr.name() << "\" instead of close tag (line " << read_params.s.get_line_no() << ", char " << read_params.s.get_line_pos() << ')';
1106 0 : throw std::runtime_error(s.str().c_str());
1107 0 : }
1108 : }
1109 : }
1110 : else
1111 : {
1112 0 : std::ostringstream s;
1113 0 : s << "Unexpected tag \"" << tag_start << "\" (line " << read_params.s.get_line_no() << ", char " << read_params.s.get_line_pos() << ')';
1114 0 : throw std::runtime_error(s.str().c_str());
1115 0 : }
1116 : }
1117 0 : catch (exception & e)
1118 : {
1119 0 : throw FailedRead("multi-value", e);
1120 0 : }
1121 0 : catch (std::exception & e)
1122 : {
1123 0 : throw FailedRead("multi-value", e.what());
1124 827 : }
1125 273 : }
1126 :
1127 : void
1128 0 : OksData::read(const ReadFileParams& read_params, const OksRelationship * r, int32_t num)
1129 : {
1130 0 : if( __builtin_expect((type != list_type), 0) ) {
1131 0 : Set(new List());
1132 : }
1133 0 : else if( __builtin_expect((!data.LIST->empty()), 0) ) {
1134 0 : free_list(*data.LIST);
1135 : }
1136 :
1137 0 : while(num-- > 0) {
1138 0 : OksData * d = new OksData(read_params, r);
1139 :
1140 : // ignore dangling objects saved previously
1141 0 : if( __builtin_expect((d->type == OksData::uid2_type && d->data.UID2.class_id->empty()), 0) ) continue;
1142 :
1143 : // add real object
1144 0 : data.LIST->push_back(d);
1145 : }
1146 0 : }
1147 :
1148 : void
1149 0 : OksData::read(const ReadFileParams& read_params, const OksRelationship * r)
1150 : {
1151 0 : const OksClass * rel_class(r->p_class_type); // class of relationship
1152 0 : OksString * class_id(0); // class-name of read object
1153 0 : const OksClass * c(0); // class of read object
1154 0 : OksXmlInputStream& fxs(read_params.s);
1155 :
1156 0 : try {
1157 :
1158 : // read class name from stream and store it either on 'c' (pointer-to-class) or new OksString
1159 :
1160 0 : size_t len = fxs.get_quoted();
1161 :
1162 0 : if( __builtin_expect((len > 0), 1) ) {
1163 0 : if( __builtin_expect((!read_params.alias_table), 1) ) {
1164 0 : if( __builtin_expect((rel_class != 0), 1) ) {
1165 0 : c = rel_class->get_kernel()->find_class(fxs.get_xml_token().m_buf);
1166 : }
1167 :
1168 0 : if( __builtin_expect((c == 0), 0) ) {
1169 0 : class_id = new OksString(fxs.get_xml_token().m_buf, len);
1170 : }
1171 : }
1172 : else {
1173 0 : const char * class_name_str(fxs.get_xml_token().m_buf);
1174 :
1175 0 : if(class_name_str[0] == '@') {
1176 0 : class_name_str++;
1177 0 : len--;
1178 :
1179 0 : c = ( rel_class ? rel_class->get_kernel()->find_class(class_name_str) : 0 );
1180 :
1181 0 : if(c) {
1182 0 : read_params.alias_table->add_value(0, c);
1183 : }
1184 : else {
1185 0 : read_params.alias_table->add_value(new OksString(class_name_str, len), 0);
1186 : }
1187 : }
1188 : else {
1189 0 : if(rel_class) {
1190 0 : if(const OksAliasTable::Value * value = read_params.alias_table->get(class_name_str)) {
1191 0 : c = (
1192 0 : value->class_ptr
1193 0 : ? value->class_ptr
1194 0 : : rel_class->get_kernel()->find_class(*value->class_name)
1195 : );
1196 : }
1197 : else {
1198 0 : Oks::warning_msg("OksData::read(const ReadFileParams&, const OksRelationship*")
1199 : << " Can't find alias for class \'" << class_name_str << "\'\n"
1200 0 : " Possibly data file has been saved in old format\n";
1201 :
1202 0 : c = rel_class->get_kernel()->find_class(class_name_str);
1203 : }
1204 : }
1205 : }
1206 :
1207 0 : if(!c) {
1208 0 : class_id = new OksString(class_name_str, len);
1209 : }
1210 : }
1211 : }
1212 :
1213 :
1214 : // read object id from stream and try to find OksObject
1215 :
1216 0 : len = fxs.get_quoted();
1217 :
1218 0 : if( __builtin_expect((c == 0), 0) ) {
1219 0 : if(class_id) {
1220 0 : Set(class_id, new OksString(fxs.get_xml_token().m_buf, len));
1221 0 : class_id = 0;
1222 : }
1223 : else {
1224 0 : Set((OksObject *)0);
1225 : }
1226 :
1227 0 : goto final;
1228 : }
1229 :
1230 :
1231 0 : std::string& obj_id((const_cast<ReadFileParams&>(read_params)).tmp); // use temporal string for fast assignment
1232 0 : obj_id.assign(fxs.get_xml_token().m_buf, len);
1233 0 : OksObject * obj = c->get_object(obj_id);
1234 :
1235 0 : if(!obj) {
1236 0 : Set(c, new OksString(obj_id));
1237 0 : goto final;
1238 : }
1239 :
1240 :
1241 : // final checks
1242 :
1243 0 : read_params.owner->OksObject::check_class_type(r, c);
1244 0 : Set(obj);
1245 0 : obj->add_RCR(read_params.owner, r);
1246 : }
1247 0 : catch(exception& ex) {
1248 0 : if(class_id) delete class_id;
1249 0 : throw FailedRead("relationship value", ex);
1250 0 : }
1251 0 : catch (std::exception & ex) {
1252 0 : if(class_id) delete class_id;
1253 0 : throw FailedRead("relationship value", ex.what());
1254 0 : }
1255 :
1256 0 : final:
1257 :
1258 0 : IsConsistent(r, read_params.owner, "WARNING");
1259 :
1260 0 : }
1261 :
1262 :
1263 : void
1264 5402 : OksData::read(const OksRelationship * r, const OksXmlRelValue& value)
1265 : {
1266 5402 : try
1267 : {
1268 5402 : if (__builtin_expect((value.m_class == nullptr), 0))
1269 : {
1270 0 : if (value.m_class_id)
1271 : {
1272 0 : Set(value.m_class_id, new OksString(value.m_value.buf(), value.m_value.len()));
1273 0 : value.m_class_id = nullptr;
1274 : }
1275 : else
1276 : {
1277 0 : Set((OksObject *) nullptr);
1278 : }
1279 :
1280 0 : goto final;
1281 : }
1282 :
1283 5402 : OksObject * obj = value.m_class->get_object(value.m_value.buf());
1284 :
1285 5402 : if (!obj)
1286 : {
1287 3132 : Set(value.m_class, new OksString(value.m_value.buf(), value.m_value.len()));
1288 3131 : goto final;
1289 : }
1290 :
1291 : // final checks
1292 :
1293 2270 : value.m_file_params.owner->OksObject::check_class_type(r, value.m_class);
1294 2270 : Set(obj);
1295 2270 : obj->add_RCR(value.m_file_params.owner, r);
1296 : }
1297 0 : catch (exception& ex)
1298 : {
1299 0 : if (value.m_class_id)
1300 0 : delete value.m_class_id;
1301 0 : throw FailedRead("relationship value", ex);
1302 0 : }
1303 0 : catch (std::exception & ex)
1304 : {
1305 0 : if (value.m_class_id)
1306 0 : delete value.m_class_id;
1307 0 : throw FailedRead("relationship value", ex.what());
1308 0 : }
1309 :
1310 5401 : final:
1311 :
1312 5401 : IsConsistent(r, value.m_file_params.owner, "WARNING");
1313 5399 : }
1314 :
1315 : void
1316 1659 : OksData::read(const OksRelationship *r, const ReadFileParams& read_params)
1317 : {
1318 1659 : if (type != list_type)
1319 0 : Set(new List());
1320 1659 : else if (!data.LIST->empty())
1321 0 : free_list(*data.LIST);
1322 :
1323 5038 : while (true)
1324 5038 : try
1325 : {
1326 5038 : const char * tag_start = read_params.s.get_tag_start();
1327 :
1328 : // check for closing tag
1329 5039 : if (*tag_start == '/' && cmp_str4n(tag_start+1, OksObject::relationship_xml_tag))
1330 : break;
1331 :
1332 3380 : if (cmp_str3(tag_start, OksObject::ref_xml_tag))
1333 : {
1334 3380 : OksXmlRelValue value(read_params);
1335 :
1336 10139 : try {
1337 16898 : while(true) {
1338 10139 : OksXmlAttribute attr(read_params.s);
1339 :
1340 : // check for close of tag
1341 :
1342 10136 : if(cmp_str1(attr.name(), ">") || cmp_str1(attr.name(), "/")) { break; }
1343 :
1344 : // check for known oks-relationship' attributes
1345 :
1346 6758 : else if(cmp_str5(attr.name(), OksObject::class_xml_attribute)) {
1347 3379 : value.m_class = read_params.owner->uid.class_id->get_kernel()->find_class(attr.value());
1348 3379 : if( __builtin_expect((value.m_class == nullptr && attr.value_len() > 0), 0) ) {
1349 0 : value.m_class_id = new OksString(attr.value(), attr.value_len());
1350 : }
1351 : }
1352 3379 : else if(cmp_str2(attr.name(), OksObject::id_xml_attribute)) {
1353 3379 : value.m_value = read_params.s.get_value(attr.p_value_len);
1354 : }
1355 : else
1356 0 : read_params.s.throw_unexpected_attribute(attr.name());
1357 6759 : }
1358 :
1359 3378 : if(value.is_empty() == false)
1360 : {
1361 3378 : OksData * d = new OksData(r, value);
1362 :
1363 : // ignore dangling objects saved previously
1364 3379 : if( __builtin_expect((d->type == OksData::uid2_type && d->data.UID2.class_id->empty()), 0) ) continue;
1365 :
1366 : // add real object
1367 3379 : data.LIST->push_back(d);
1368 : }
1369 : }
1370 0 : catch(exception & e) {
1371 0 : throw FailedRead("multi-value relationship", e);
1372 0 : }
1373 0 : catch (std::exception & e) {
1374 0 : throw FailedRead("multi-value relationship", e.what());
1375 0 : }
1376 : }
1377 : else
1378 : {
1379 0 : std::ostringstream s;
1380 0 : s << "Unexpected tag \"" << tag_start << "\" (line " << read_params.s.get_line_no() << ", char " << read_params.s.get_line_pos() << ')';
1381 0 : throw std::runtime_error(s.str().c_str());
1382 0 : }
1383 : }
1384 0 : catch (exception & e)
1385 : {
1386 0 : throw FailedRead("multi-value", e);
1387 0 : }
1388 0 : catch (std::exception & e)
1389 : {
1390 0 : throw FailedRead("multi-value", e.what());
1391 0 : }
1392 1659 : }
1393 :
1394 :
1395 : //
1396 : // Writes to stream any OKS data except relationship types
1397 : // (i.e. object, uid, uid2)
1398 : //
1399 :
1400 : void
1401 0 : OksData::WriteTo(OksXmlOutputStream& xmls, bool put_number) const
1402 : {
1403 0 : switch (type) {
1404 0 : case list_type: {
1405 0 : if(!data.LIST->empty()) {
1406 0 : if(put_number) xmls.put_value((unsigned long)data.LIST->size());
1407 0 : for(List::iterator i = data.LIST->begin(); i != data.LIST->end(); ++i) {
1408 0 : if(!put_number) {
1409 0 : xmls.put_raw('\n');
1410 0 : xmls.put_raw(' ');
1411 : }
1412 :
1413 0 : xmls.put_raw(' ');
1414 :
1415 0 : (*i)->WriteTo(xmls, put_number);
1416 : }
1417 :
1418 0 : if(!put_number)
1419 : {
1420 0 : xmls.put_raw('\n');
1421 0 : xmls.put_raw(' ');
1422 : }
1423 : }
1424 : else {
1425 0 : if(put_number) xmls.put_raw('0');
1426 : }
1427 :
1428 : break; }
1429 :
1430 0 : case string_type:
1431 0 : xmls.put_quoted(data.STRING->c_str());
1432 0 : break;
1433 :
1434 0 : case s32_int_type:
1435 0 : xmls.put_value(data.S32_INT);
1436 0 : break;
1437 :
1438 0 : case u32_int_type:
1439 0 : xmls.put_value(data.U32_INT);
1440 0 : break;
1441 :
1442 0 : case s16_int_type:
1443 0 : xmls.put_value(data.S16_INT);
1444 0 : break;
1445 :
1446 0 : case u16_int_type:
1447 0 : xmls.put_value(data.U16_INT);
1448 0 : break;
1449 :
1450 0 : case float_type: {
1451 0 : std::ostream& s = xmls.get_stream();
1452 0 : std::streamsize p = s.precision();
1453 0 : s.precision(std::numeric_limits< float >::digits10);
1454 0 : xmls.put_value(data.FLOAT);
1455 0 : s.precision(p);
1456 0 : break; }
1457 :
1458 0 : case double_type: {
1459 0 : std::ostream& s = xmls.get_stream();
1460 0 : std::streamsize p = s.precision();
1461 0 : s.precision(std::numeric_limits< double >::digits10);
1462 0 : xmls.put_value(data.DOUBLE);
1463 0 : s.precision(p);
1464 0 : break; }
1465 :
1466 0 : case s8_int_type:
1467 0 : xmls.put_value(static_cast<int16_t>(data.S8_INT));
1468 0 : break;
1469 :
1470 0 : case u8_int_type:
1471 0 : xmls.put_value(static_cast<uint16_t>(data.U8_INT));
1472 0 : break;
1473 :
1474 0 : case s64_int_type:
1475 0 : xmls.put_value(data.S64_INT);
1476 0 : break;
1477 :
1478 0 : case u64_int_type:
1479 0 : xmls.put_value(data.U64_INT);
1480 0 : break;
1481 :
1482 0 : case bool_type:
1483 0 : xmls.put_value((short)(data.BOOL));
1484 0 : break;
1485 :
1486 0 : case date_type:
1487 0 : xmls.put_quoted(boost::gregorian::to_iso_string(date()).c_str());
1488 0 : break;
1489 :
1490 0 : case time_type:
1491 0 : xmls.put_quoted(boost::posix_time::to_iso_string(time()).c_str());
1492 0 : break;
1493 :
1494 0 : case enum_type:
1495 0 : xmls.put_quoted(data.ENUMERATION->c_str());
1496 0 : break;
1497 :
1498 0 : case class_type:
1499 0 : xmls.put_quoted(data.CLASS->get_name().c_str());
1500 0 : break;
1501 :
1502 0 : case uid2_type:
1503 0 : case uid_type:
1504 0 : case object_type:
1505 0 : case unknown_type:
1506 0 : Oks::error_msg("OksData::WriteTo(OksXmlOutputStream&, bool)")
1507 0 : << "Can't write \'" << (type == unknown_type ? "unknown" : "relationship") << "_type\'\n";
1508 0 : break;
1509 : }
1510 0 : }
1511 :
1512 :
1513 : void
1514 0 : OksData::WriteTo(OksXmlOutputStream& xmls) const
1515 : {
1516 0 : switch (type) {
1517 0 : case string_type:
1518 0 : xmls.put(data.STRING->c_str());
1519 0 : break;
1520 :
1521 0 : case s32_int_type:
1522 0 : xmls.put_value(data.S32_INT);
1523 0 : break;
1524 :
1525 0 : case u32_int_type:
1526 0 : xmls.put_value(data.U32_INT);
1527 0 : break;
1528 :
1529 0 : case s16_int_type:
1530 0 : xmls.put_value(data.S16_INT);
1531 0 : break;
1532 :
1533 0 : case u16_int_type:
1534 0 : xmls.put_value(data.U16_INT);
1535 0 : break;
1536 :
1537 0 : case float_type: {
1538 0 : std::ostream& s = xmls.get_stream();
1539 0 : std::streamsize p = s.precision();
1540 0 : s.precision(std::numeric_limits< float >::digits10);
1541 0 : xmls.put_value(data.FLOAT);
1542 0 : s.precision(p);
1543 0 : break; }
1544 :
1545 0 : case double_type: {
1546 0 : std::ostream& s = xmls.get_stream();
1547 0 : std::streamsize p = s.precision();
1548 0 : s.precision(std::numeric_limits< double >::digits10);
1549 0 : xmls.put_value(data.DOUBLE);
1550 0 : s.precision(p);
1551 0 : break; }
1552 :
1553 0 : case s8_int_type:
1554 0 : xmls.put_value(static_cast<int16_t>(data.S8_INT));
1555 0 : break;
1556 :
1557 0 : case u8_int_type:
1558 0 : xmls.put_value(static_cast<uint16_t>(data.U8_INT));
1559 0 : break;
1560 :
1561 0 : case s64_int_type:
1562 0 : xmls.put_value(data.S64_INT);
1563 0 : break;
1564 :
1565 0 : case u64_int_type:
1566 0 : xmls.put_value(data.U64_INT);
1567 0 : break;
1568 :
1569 0 : case bool_type:
1570 0 : xmls.put_value((short)(data.BOOL));
1571 0 : break;
1572 :
1573 0 : case date_type:
1574 0 : xmls.put(boost::gregorian::to_iso_string(date()).c_str());
1575 0 : break;
1576 :
1577 0 : case time_type:
1578 0 : xmls.put(boost::posix_time::to_iso_string(time()).c_str());
1579 0 : break;
1580 :
1581 0 : case enum_type:
1582 0 : xmls.put(data.ENUMERATION->c_str());
1583 0 : break;
1584 :
1585 0 : case class_type:
1586 0 : xmls.put(data.CLASS->get_name().c_str());
1587 0 : break;
1588 :
1589 0 : case list_type:
1590 0 : throw std::runtime_error("internal error: call OksData::WriteTo() on list");
1591 :
1592 0 : case uid2_type:
1593 0 : case uid_type:
1594 0 : case object_type:
1595 0 : case unknown_type:
1596 0 : Oks::error_msg("OksData::WriteTo(OksXmlOutputStream&, bool)")
1597 0 : << "Can't write \'" << (type == unknown_type ? "unknown" : "relationship") << "_type\'\n";
1598 0 : break;
1599 : }
1600 0 : }
1601 :
1602 :
1603 :
1604 : //
1605 : // Writes to XML stream OKS data relationship types
1606 : //
1607 :
1608 : void
1609 0 : OksData::WriteTo(OksXmlOutputStream& xmls, OksKernel *k, OksAliasTable *alias_table, bool /*test_existance*/, bool put_number) const
1610 : {
1611 0 : const char * fname = "WriteTo(OksXmlOutputStream&, ...)";
1612 :
1613 0 : static std::string emptyName(""); // to save NIL name
1614 :
1615 0 : const std::string * class_name = 0;
1616 0 : const std::string * object_id = 0;
1617 :
1618 0 : switch (type) {
1619 0 : case object_type:
1620 0 : if(data.OBJECT) {
1621 0 : class_name = &data.OBJECT->GetClass()->get_name();
1622 0 : object_id = &data.OBJECT->GetId();
1623 : }
1624 : else
1625 : class_name = object_id = &emptyName;
1626 :
1627 : break;
1628 :
1629 0 : case list_type: {
1630 0 : if(!data.LIST->empty()) {
1631 0 : if(put_number) xmls.put_value((unsigned long)data.LIST->size());
1632 :
1633 0 : for(List::iterator i = data.LIST->begin(); i != data.LIST->end(); ++i) {
1634 0 : if(!put_number) {
1635 0 : xmls.put_raw('\n');
1636 0 : xmls.put_raw(' ');
1637 : }
1638 :
1639 0 : xmls.put_raw(' ');
1640 :
1641 0 : (*i)->WriteTo(xmls, k, alias_table, false, put_number);
1642 : }
1643 :
1644 0 : if(!put_number) {
1645 0 : xmls.put_raw('\n');
1646 0 : xmls.put_raw(' ');
1647 : }
1648 : }
1649 : else {
1650 0 : if(put_number) xmls.put_raw('0');
1651 : }
1652 :
1653 : return; }
1654 :
1655 0 : case uid2_type:
1656 0 : class_name = data.UID2.class_id;
1657 0 : object_id = data.UID2.object_id;
1658 0 : break;
1659 :
1660 0 : case uid_type:
1661 0 : class_name = &data.UID.class_id->get_name();
1662 0 : object_id = data.UID.object_id;
1663 0 : break;
1664 :
1665 0 : default:
1666 0 : Oks::error_msg(fname)
1667 0 : << "Can't write \'" << (type == unknown_type ? "unknown" : "attribute") << "_type\'\n";
1668 0 : return;
1669 : }
1670 :
1671 :
1672 0 : if(!class_name->empty()) {
1673 :
1674 : // if alias table is not defined, store object in extended format
1675 :
1676 0 : if(!alias_table) {
1677 0 : xmls.put_quoted(class_name->c_str());
1678 : }
1679 :
1680 :
1681 : // otherwise store object in compact format
1682 :
1683 : else {
1684 0 : const OksAliasTable::Value *value = alias_table->get(static_cast<const OksString *>(class_name));
1685 :
1686 : // class' alias was already defined
1687 0 : if(value)
1688 0 : xmls.put_quoted(value->class_name->c_str());
1689 :
1690 : //makes new class' alias
1691 : else {
1692 0 : alias_table->add_key(static_cast<OksString *>(const_cast<std::string *>(class_name)));
1693 :
1694 0 : std::string s(*class_name);
1695 0 : s.insert(0, "@"); // add '@' to distinguish alias from class name when load
1696 0 : xmls.put_quoted(s.c_str());
1697 0 : }
1698 : }
1699 :
1700 : }
1701 : else {
1702 0 : xmls.put_quoted("");
1703 : }
1704 :
1705 0 : xmls.put_raw(' ');
1706 0 : xmls.put_quoted(object_id->c_str());
1707 : }
1708 :
1709 : void
1710 0 : OksData::ConvertTo(OksData *to, const OksRelationship *r) const
1711 : {
1712 0 : if(r->get_high_cardinality_constraint() == OksRelationship::Many) {
1713 0 : to->Set(new List());
1714 :
1715 0 : if(type != list_type) {
1716 0 : OksData *item = new OksData();
1717 :
1718 0 : if(type == OksData::object_type) item->Set(data.OBJECT);
1719 0 : else if(type == OksData::uid_type) item->Set(data.UID.class_id, *data.UID.object_id);
1720 0 : else if(type == OksData::uid2_type) item->Set(*data.UID2.class_id, *data.UID2.object_id);
1721 :
1722 0 : to->data.LIST->push_back(item);
1723 :
1724 0 : return;
1725 : }
1726 0 : else if(data.LIST && !data.LIST->empty()){
1727 0 : for(List::iterator i = data.LIST->begin(); i != data.LIST->end(); ++i) {
1728 0 : OksData *item = new OksData();
1729 0 : OksData *dd = *i;
1730 :
1731 0 : if(dd->type == OksData::object_type) item->Set(dd->data.OBJECT);
1732 0 : else if(dd->type == OksData::uid_type) item->Set(dd->data.UID.class_id, *dd->data.UID.object_id);
1733 0 : else if(dd->type == OksData::uid2_type) item->Set(*dd->data.UID2.class_id, *dd->data.UID2.object_id);
1734 :
1735 0 : to->data.LIST->push_back(item);
1736 : }
1737 :
1738 0 : return;
1739 : }
1740 :
1741 : }
1742 : else {
1743 0 : const OksData * from = ((type == list_type) ? data.LIST->front() : this);
1744 :
1745 0 : if(from->type == OksData::object_type) to->Set(from->data.OBJECT);
1746 0 : else if(from->type == OksData::uid_type) to->Set(from->data.UID.class_id, *from->data.UID.object_id);
1747 0 : else if(from->type == OksData::uid2_type) to->Set(*from->data.UID2.class_id, *from->data.UID2.object_id);
1748 : }
1749 : }
1750 :
1751 :
1752 : void
1753 30 : OksData::cvt(OksData *to, const OksAttribute *a) const
1754 : {
1755 30 : if(a->get_is_multi_values()) {
1756 9 : to->Set(new List());
1757 :
1758 9 : if(type != list_type) {
1759 9 : OksData *item = new OksData();
1760 :
1761 9 : std::string cvts = str();
1762 9 : item->ReadFrom(cvts.c_str(), a->get_data_type(), a);
1763 :
1764 9 : to->data.LIST->push_back(item);
1765 :
1766 9 : return;
1767 9 : }
1768 0 : else if(data.LIST && !data.LIST->empty()) {
1769 0 : for(List::iterator i = data.LIST->begin(); i != data.LIST->end(); ++i) {
1770 0 : OksData *item = new OksData();
1771 0 : OksData *dd = *i;
1772 :
1773 0 : std::string cvts = dd->str();
1774 0 : item->ReadFrom(cvts.c_str(), a->get_data_type(), a);
1775 :
1776 0 : to->data.LIST->push_back(item);
1777 0 : }
1778 :
1779 0 : return;
1780 : }
1781 : }
1782 : else {
1783 21 : const OksData * from = ((type == list_type) ? (data.LIST->empty() ? 0 : data.LIST->front() ) : this);
1784 21 : std::string cvts;
1785 21 : if(from) cvts = from->str();
1786 21 : to->ReadFrom(cvts.c_str(), a->get_data_type(), a);
1787 21 : }
1788 : }
1789 :
1790 :
1791 : static std::string
1792 0 : list2str(const OksData::List * l, const OksKernel * k, int base)
1793 : {
1794 0 : std::ostringstream s;
1795 :
1796 0 : s << '(';
1797 :
1798 0 : if(l) {
1799 0 : bool is_first = true;
1800 :
1801 0 : for(OksData::List::const_iterator i = l->begin(); i != l->end(); ++i) {
1802 0 : std::string s2 = (k ? (*i)->str(k) : (*i)->str(base));
1803 :
1804 0 : if(!s2.empty()) {
1805 0 : if(is_first == false) { s << ", "; }
1806 : else { is_first = false; }
1807 0 : s << s2;
1808 : }
1809 0 : }
1810 : }
1811 :
1812 0 : s << ')';
1813 :
1814 0 : return s.str();
1815 0 : }
1816 :
1817 :
1818 :
1819 : // only is used for OksData pointing to objects
1820 :
1821 : std::string
1822 0 : OksData::str(const OksKernel * kernel) const
1823 : {
1824 0 : if(type == list_type) {
1825 0 : return list2str(data.LIST, kernel, 0);
1826 : }
1827 :
1828 0 : std::ostringstream s;
1829 :
1830 0 : switch (type) {
1831 0 : case uid2_type:
1832 0 : s << "#[" << *data.UID2.object_id << '@' << *data.UID2.class_id << ']';
1833 : break;
1834 :
1835 0 : case uid_type:
1836 0 : s << "#[" << *data.UID.object_id << '@' << data.UID.class_id->get_name() << ']';
1837 : break;
1838 :
1839 0 : case object_type:
1840 0 : if(data.OBJECT && !kernel->is_dangling(data.OBJECT) && data.OBJECT->GetClass()->get_name().length()) {
1841 0 : s << '[' << data.OBJECT->GetId() << '@' << data.OBJECT->GetClass()->get_name() << ']';
1842 : }
1843 : break;
1844 :
1845 0 : default:
1846 0 : std::cerr << "ERROR [OksData::str(const OksKernel *)]: wrong use for such data: " << *this << std::endl;
1847 0 : return "";
1848 : }
1849 :
1850 0 : return s.str();
1851 0 : }
1852 :
1853 :
1854 : // is only used for primitive data types
1855 :
1856 : std::string
1857 66 : OksData::str(int base) const
1858 : {
1859 66 : if(type == string_type) { return *data.STRING; }
1860 0 : else if(type == enum_type) { return *data.ENUMERATION; }
1861 0 : else if(type == bool_type) { return (data.BOOL ? "true" : "false"); }
1862 0 : else if(type == list_type) { return list2str(data.LIST, 0, base); }
1863 0 : else if(type == date_type) { return boost::gregorian::to_simple_string(date()); }
1864 0 : else if(type == time_type) { return boost::posix_time::to_simple_string(time()); }
1865 0 : else if(type == class_type) { return data.CLASS->get_name(); }
1866 :
1867 :
1868 20 : std::ostringstream s;
1869 :
1870 20 : if(base) {
1871 0 : s.setf((base == 10 ? std::ios::dec : base == 16 ? std::ios::hex : std::ios::oct), std::ios::basefield );
1872 0 : s.setf(std::ios::showbase);
1873 : }
1874 :
1875 20 : switch (type) {
1876 0 : case s8_int_type:
1877 0 : s << static_cast<int16_t>(data.S8_INT);
1878 : break;
1879 :
1880 0 : case u8_int_type:
1881 0 : s << static_cast<uint16_t>(data.U8_INT);
1882 : break;
1883 :
1884 9 : case s16_int_type:
1885 9 : s << data.S16_INT;
1886 : break;
1887 :
1888 9 : case u16_int_type:
1889 9 : s << data.U16_INT;
1890 : break;
1891 :
1892 2 : case s32_int_type:
1893 2 : s << data.S32_INT;
1894 : break;
1895 :
1896 0 : case u32_int_type:
1897 0 : s << data.U32_INT;
1898 : break;
1899 :
1900 0 : case s64_int_type:
1901 0 : s << data.S64_INT;
1902 : break;
1903 :
1904 0 : case u64_int_type:
1905 0 : s << data.U64_INT;
1906 : break;
1907 :
1908 0 : case float_type:
1909 0 : s.precision(std::numeric_limits< float >::digits10);
1910 0 : s << data.FLOAT;
1911 : break;
1912 :
1913 0 : case double_type:
1914 0 : s.precision(std::numeric_limits< double >::digits10);
1915 0 : s << data.DOUBLE;
1916 : break;
1917 :
1918 0 : default:
1919 0 : std::cerr << "ERROR [OksData::str(int)]: wrong use for such data: " << *this << std::endl;
1920 0 : return "";
1921 : }
1922 :
1923 20 : return s.str();
1924 20 : }
1925 :
1926 :
1927 : bool
1928 5401 : OksData::IsConsistent(const OksRelationship *r, const OksObject *o, const char *msg)
1929 : {
1930 5401 : if(r->get_low_cardinality_constraint() != OksRelationship::Zero) {
1931 3759 : if(
1932 3759 : ( type == OksData::object_type && data.OBJECT == 0 ) ||
1933 7518 : ( type == OksData::uid_type && (!data.UID.object_id || data.UID.object_id->empty() || !data.UID.class_id) ) ||
1934 0 : ( type == OksData::uid2_type && (!data.UID2.object_id || !data.UID2.class_id || data.UID2.object_id->empty() || data.UID2.class_id->empty()) )
1935 : ) {
1936 0 : if(o->GetClass()->get_kernel()->get_silence_mode() != true) {
1937 0 : std::cerr << msg << ": value of \"" << r->get_name() << "\" relationship in object " << o << " must be non-null\n";
1938 : }
1939 0 : return false;
1940 : }
1941 3759 : else if(type == OksData::list_type && data.LIST->empty()) {
1942 0 : if(o->GetClass()->get_kernel()->get_silence_mode() != true) {
1943 0 : std::cerr << msg << ": \"" << r->get_name() << "\" relationship in object " << o << " must contain at least one object\n";
1944 : }
1945 0 : return false;
1946 : }
1947 : }
1948 :
1949 : return true;
1950 : }
1951 :
1952 :
1953 :
1954 : void
1955 0 : OksData::sort(bool ascending)
1956 : {
1957 0 : if (type != list_type || data.LIST->size() < 2)
1958 : return;
1959 :
1960 0 : if (ascending)
1961 0 : data.LIST->sort( []( const OksData* a, const OksData* b ) { return *a < *b; } );
1962 : else
1963 0 : data.LIST->sort( []( const OksData* a, const OksData* b ) { return *a > *b; } );
1964 : }
1965 :
1966 512 : boost::posix_time::ptime str2time(const char * value, size_t len, const char * file_name)
1967 : {
1968 512 : if(len == 15 && value[8] == 'T') {
1969 512 : try {
1970 512 : return boost::posix_time::from_iso_string(value);
1971 : }
1972 0 : catch (std::exception& ex) {
1973 : //throw TimeCvtFailed(value, ex.what());
1974 0 : throw AttributeReadError(value, "time", ex.what());
1975 0 : }
1976 : }
1977 : else {
1978 0 : try {
1979 0 : Time t(value);
1980 0 : std::ostringstream text;
1981 0 : text << std::setfill('0')
1982 0 : << std::setw(4) << t.year()
1983 0 : << std::setw(2) << (t.month() + 1)
1984 0 : << std::setw(2) << t.day()
1985 : << 'T'
1986 0 : << std::setw(2) << t.hour()
1987 0 : << std::setw(2) << t.min()
1988 0 : << std::setw(2) << t.sec();
1989 0 : TLOG_DEBUG( 1 ) << "parse OKS time: " << t << " => " << text.str() ;
1990 :
1991 0 : if(file_name)
1992 0 : ers::warning(DeprecatedFormat(ERS_HERE, file_name, value));
1993 : else
1994 0 : Oks::warning_msg("oks str2time") << "The file is using deprecated OKS time format \"" << value << "\"\nPlease refresh it using an oks application\nSupport for such format will be removed in a future release.\n";
1995 :
1996 0 : return boost::posix_time::from_iso_string(text.str());
1997 0 : }
1998 0 : catch (exception& ex) {
1999 : //throw TimeCvtFailed(value, ex);
2000 0 : throw AttributeReadError(value, "time", ex);
2001 0 : }
2002 0 : catch (std::exception& ex) {
2003 : //throw TimeCvtFailed(value, ex.what());
2004 0 : throw AttributeReadError(value, "time", ex.what());
2005 0 : }
2006 : }
2007 : }
2008 :
2009 0 : boost::gregorian::date str2date(const char * value, size_t len)
2010 : {
2011 0 : if(len == 8 && value[2] != '/' && value[3] != '/') {
2012 0 : try {
2013 0 : return boost::gregorian::from_undelimited_string(value);
2014 : }
2015 0 : catch (std::exception& ex) {
2016 0 : throw AttributeReadError(value, "date", ex.what());
2017 0 : }
2018 : }
2019 : else {
2020 0 : try {
2021 0 : Date t(value);
2022 0 : std::ostringstream text;
2023 0 : text << std::setfill('0')
2024 0 : << std::setw(4) << t.year()
2025 0 : << std::setw(2) << (t.month() + 1)
2026 0 : << std::setw(2) << t.day();
2027 0 : TLOG_DEBUG( 1 ) << "parse OKS date: " << t << " => " << text.str() ;
2028 :
2029 0 : Oks::warning_msg("oks str2date") << "The file is using deprecated OKS date format \"" << value << "\"\nPlease refresh it using an oks application.\nSupport for such format will be removed in a future release.\n";
2030 :
2031 0 : return boost::gregorian::from_undelimited_string(text.str());
2032 0 : }
2033 0 : catch (exception& ex) {
2034 0 : throw AttributeReadError(value, "date", ex);
2035 0 : }
2036 0 : catch (std::exception& ex) {
2037 0 : throw AttributeReadError(value, "date", ex.what());
2038 0 : }
2039 : }
2040 : }
2041 :
2042 : } // namespace oks
2043 : } // namespace dunedaq
|