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