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