LCOV - code coverage report
Current view: top level - oks/src - data.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 25.8 % 1176 303
Test Date: 2025-12-21 13:07:08 Functions: 34.4 % 64 22

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

Generated by: LCOV version 2.0-1