LCOV - code coverage report
Current view: top level - oks/src - data.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 28.3 % 1284 364
Test Date: 2026-10-11 15:05:20 Functions: 35.9 % 64 23

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

Generated by: LCOV version 2.0-1