LCOV - code coverage report
Current view: top level - src/sl3 - value.cpp (source / functions) Coverage Total Hit
Test: coverage.info.cleaned Lines: 98.3 % 421 414
Test Date: 2024-12-09 18:45:33 Functions: 100.0 % 41 41
Branches: 73.3 % 375 275

             Branch data     Line data    Source code
       1                 :             : /******************************************************************************
       2                 :             :  ------------- Copyright (c) 2009-2023 H a r a l d  A c h i t z ---------------
       3                 :             :  ---------- < h a r a l d dot a c h i t z at g m a i l dot c o m > ------------
       4                 :             :  ---- This Source Code Form is subject to the terms of the Mozilla Public -----
       5                 :             :  ---- License, v. 2.0. If a copy of the MPL was not distributed with this -----
       6                 :             :  ---------- file, You can obtain one at http://mozilla.org/MPL/2.0/. ----------
       7                 :             :  ******************************************************************************/
       8                 :             : 
       9                 :             : #include <sl3/error.hpp>
      10                 :             : #include <sl3/value.hpp>
      11                 :             : 
      12                 :             : #include <algorithm>
      13                 :             : #include <climits>
      14                 :             : #include <cmath>
      15                 :             : #include <iomanip>
      16                 :             : #include <limits>
      17                 :             : #include <ostream>
      18                 :             : #include <type_traits>
      19                 :             : 
      20                 :             : #include "utils.hpp"
      21                 :             : 
      22                 :             : namespace sl3
      23                 :             : {
      24                 :             :   namespace
      25                 :             :   {
      26                 :             :     // not in coverage, only used in never reachable case/if branches
      27                 :             :     void
      28                 :             :     raiseErrUnexpected (const std::string& msg) // LCOV_EXCL_LINE
      29                 :             :     {
      30                 :             :       throw ErrUnexpected (msg); // LCOV_EXCL_LINE
      31                 :             :     }
      32                 :             : 
      33                 :             :     template <class T>
      34                 :             :     typename std::enable_if<!std::numeric_limits<T>::is_integer, bool>::type
      35                 :          19 :     almost_equal (T x, T y, int ulp)
      36                 :             :     {
      37                 :             :       using std::numeric_limits;
      38                 :             :       // the machine epsilon has to be scaled to the magnitude of the values
      39                 :             :       // used
      40                 :             :       // and multiplied by the desired precision in ULPs (units in the last
      41                 :             :       // place)
      42                 :          19 :       return std::abs (x - y)
      43                 :          19 :                  < numeric_limits<T>::epsilon () * std::abs (x + y) * ulp
      44                 :             :              // unless the result is subnormal
      45   [ -  +  -  - ]:          19 :              || std::abs (x - y) < numeric_limits<T>::min ();
      46                 :             :     }
      47                 :             : 
      48                 :             :     template <typename InT, typename OutT>
      49                 :             :     // requires std::is_integral<OutT>::value
      50                 :             :     // requires is_floating_point<InT>::value
      51                 :             :     inline OutT
      52                 :          10 :     losslessConvert1 (InT in)
      53                 :             :     {
      54                 :          10 :       InT converted = std::trunc (in);
      55         [ +  + ]:          10 :       if (in - converted != 0.0)
      56         [ +  - ]:           7 :         throw ErrTypeMisMatch{"Conversion loses fraction"};
      57                 :             : 
      58                 :             :       using limit = std::numeric_limits<OutT>;
      59                 :             :       // if (converted < limit::min () || converted > limit::max ())
      60         [ +  - ]:           3 :       if (is_less (converted, limit::min ())
      61   [ +  -  +  -  :           3 :           || is_greater (converted, limit::max ()))
             +  +  +  + ]
      62         [ +  - ]:           2 :         throw ErrOutOfRange{"Converted value to big"};
      63                 :             : 
      64                 :           1 :       return static_cast<OutT> (converted);
      65                 :             :     }
      66                 :             : 
      67                 :             :     template <typename InT, typename OutT>
      68                 :             :     // requires std::is_integral<OutT>::value
      69                 :             :     // requires is_floating_point<InT>::value
      70                 :             :     inline OutT
      71                 :             :     losslessConvert2 (InT in)
      72                 :             :     {
      73                 :             :       InT converted{0.0};
      74                 :             :       InT fraction = std::modf (in, &converted);
      75                 :             : 
      76                 :             :       if (fraction != 0.0)
      77                 :             :         throw ErrOutOfRange{"Conversion loses fraction"};
      78                 :             : 
      79                 :             :       using limit = std::numeric_limits<OutT>;
      80                 :             :       if (converted < limit::min () || converted > limit::max ())
      81                 :             :         throw ErrOutOfRange{"Converted value to big"};
      82                 :             : 
      83                 :             :       return static_cast<OutT> (converted);
      84                 :             :     }
      85                 :             : 
      86                 :             :   } //--------------------------------------------------------------------------
      87                 :             : 
      88                 :         384 :   Value::Value () noexcept
      89                 :         384 :   : _type{Type::Null}
      90                 :             :   {
      91                 :         384 :   }
      92                 :             : 
      93                 :          37 :   Value::Value (int val) noexcept
      94                 :          37 :   : _type{Type::Int}
      95                 :             :   {
      96                 :          37 :     _store.intval = val;
      97                 :          37 :   }
      98                 :             : 
      99                 :           1 :   Value::Value (int64_t val) noexcept
     100                 :           1 :   : _type{Type::Int}
     101                 :             :   {
     102                 :           1 :     _store.intval = val;
     103                 :           1 :   }
     104                 :             : 
     105                 :          21 :   Value::Value (std::string val) noexcept
     106                 :          21 :   : _type{Type::Text}
     107                 :             :   {
     108                 :          21 :     new (&_store.textval) std::string (std::move (val));
     109                 :          21 :   }
     110                 :             : 
     111                 :          19 :   Value::Value (const char* val)
     112                 :          19 :   : _type{Type::Text}
     113                 :             :   {
     114   [ +  -  -  - ]:          38 :     new (&_store.textval) std::string (val);
     115                 :          19 :   }
     116                 :             : 
     117                 :          35 :   Value::Value (double val) noexcept
     118                 :          35 :   : _type{Type::Real}
     119                 :             :   {
     120                 :          35 :     _store.realval = val;
     121                 :          35 :   }
     122                 :             : 
     123                 :          36 :   Value::Value (Blob val) noexcept
     124                 :          36 :   : _type{Type::Blob}
     125                 :             :   {
     126                 :          36 :     new (&_store.blobval) Blob (std::move (val));
     127                 :          36 :   }
     128                 :             : 
     129                 :        1333 :   Value::~Value () noexcept
     130                 :             :   {
     131         [ +  + ]:        1333 :     if (_type == Type::Text)
     132                 :             :       {
     133                 :         202 :         _store.textval.~basic_string<std::string::value_type> ();
     134                 :             :       }
     135         [ +  + ]:        1131 :     else if (_type == Type::Blob)
     136                 :             :       {
     137                 :         101 :         _store.blobval.~vector<Blob::value_type> ();
     138                 :             :       }
     139                 :        1333 :   }
     140                 :             : 
     141                 :         409 :   Value::Value (const Value& other) noexcept
     142                 :         409 :   : _type{other._type}
     143                 :             :   {
     144   [ +  +  +  +  :         409 :     switch (_type)
                   +  - ]
     145                 :             :       {
     146                 :          86 :       case Type::Null:
     147                 :          86 :         break;
     148                 :             : 
     149                 :         124 :       case Type::Int:
     150                 :         124 :         _store.intval = other._store.intval;
     151                 :         124 :         break;
     152                 :             : 
     153                 :          69 :       case Type::Real:
     154                 :          69 :         _store.realval = other._store.realval;
     155                 :          69 :         break;
     156                 :             : 
     157                 :          74 :       case Type::Text:
     158                 :          74 :         new (&_store.textval) std::string (other._store.textval);
     159                 :          74 :         break;
     160                 :             : 
     161                 :          56 :       case Type::Blob:
     162                 :          56 :         new (&_store.blobval) Blob (other._store.blobval);
     163                 :          56 :         break;
     164                 :             : 
     165                 :           0 :       default:
     166                 :             :         raiseErrUnexpected ("never reach"); // LCOV_EXCL_LINE
     167                 :             :       }
     168                 :         409 :   }
     169                 :             : 
     170                 :         391 :   Value::Value (Value&& other) noexcept
     171                 :         391 :   : _type (other._type)
     172                 :             :   {
     173                 :             :     // gcc 5.3, only release, will complain if uninitialized
     174                 :         391 :     _store.intval = 0;
     175                 :             : 
     176   [ +  +  +  +  :         391 :     switch (_type)
                +  -  - ]
     177                 :             :       {
     178                 :          33 :       case Type::Null:
     179                 :          33 :         break;
     180                 :             : 
     181                 :         151 :       case Type::Int:
     182                 :         151 :         _store.intval = std::move (other._store.intval);
     183                 :         151 :         break;
     184                 :             : 
     185                 :          54 :       case Type::Real:
     186                 :          54 :         _store.realval = std::move (other._store.realval);
     187                 :          54 :         break;
     188                 :             : 
     189                 :         128 :       case Type::Text:
     190                 :         128 :         new (&_store.textval) std::string (std::move (other._store.textval));
     191                 :         128 :         other._store.textval.~basic_string ();
     192                 :         128 :         break;
     193                 :             : 
     194                 :          25 :       case Type::Blob:
     195                 :          25 :         new (&_store.blobval) Blob (std::move (other._store.blobval));
     196                 :          25 :         other._store.blobval.~vector ();
     197                 :          25 :         break;
     198                 :             : 
     199                 :           0 :       case Type::Variant:
     200                 :             :         raiseErrUnexpected ("never reach"); // LCOV_EXCL_LINE
     201                 :             :         break;                              // LCOV_EXCL_LINE
     202                 :             :       }
     203                 :             : 
     204                 :             :     // important, set other to null so that clear does not trial to clear
     205                 :         391 :     other._type = Type::Null;
     206                 :         391 :   }
     207                 :             : 
     208                 :             :   Value&
     209                 :         107 :   Value::operator= (const Value& other)
     210                 :             :   {
     211         [ +  + ]:         107 :     if (_type == Type::Text)
     212                 :             :       {
     213         [ +  + ]:          15 :         if (other._type == Type::Text)
     214                 :             :           {
     215                 :           5 :             _store.textval = other._store.textval;
     216                 :           5 :             return *this;
     217                 :             :           }
     218                 :             : 
     219                 :          10 :         _store.textval.~basic_string<std::string::value_type> ();
     220                 :             :       }
     221         [ +  + ]:          92 :     else if (_type == Type::Blob)
     222                 :             :       {
     223         [ +  + ]:          12 :         if (other._type == Type::Blob)
     224                 :             :           {
     225                 :           1 :             _store.blobval = other._store.blobval;
     226                 :           1 :             return *this;
     227                 :             :           }
     228                 :          11 :         _store.blobval.~vector<Blob::value_type> ();
     229                 :             :       }
     230                 :             : 
     231                 :         101 :     _type = other._type;
     232                 :             : 
     233   [ +  +  +  +  :         101 :     switch (_type)
                +  -  - ]
     234                 :             :       {
     235                 :          14 :       case Type::Null:
     236                 :          14 :         break;
     237                 :             : 
     238                 :          29 :       case Type::Int:
     239                 :          29 :         _store.intval = other._store.intval;
     240                 :          29 :         break;
     241                 :             : 
     242                 :          23 :       case Type::Real:
     243                 :          23 :         _store.realval = other._store.realval;
     244                 :          23 :         break;
     245                 :             : 
     246                 :          21 :       case Type::Text:
     247   [ +  -  -  - ]:          21 :         new (&_store.textval) std::string (other._store.textval);
     248                 :          21 :         break;
     249                 :             : 
     250                 :          14 :       case Type::Blob:
     251   [ +  -  -  - ]:          14 :         new (&_store.blobval) Blob (other._store.blobval);
     252                 :          14 :         break;
     253                 :             : 
     254                 :           0 :       case Type::Variant:
     255                 :             :         raiseErrUnexpected ("never reach"); // LCOV_EXCL_LINE
     256                 :             :         break;                              // LCOV_EXCL_LINE
     257                 :             :       }
     258                 :             : 
     259                 :         101 :     return *this;
     260                 :             :   }
     261                 :             : 
     262                 :             :   Value&
     263                 :          62 :   Value::operator= (Value&& other)
     264                 :             :   {
     265         [ +  + ]:          62 :     if (_type == Type::Text)
     266                 :             :       {
     267         [ +  + ]:          12 :         if (other._type == Type::Text)
     268                 :             :           {
     269                 :           1 :             _store.textval = std::move (other._store.textval);
     270                 :           1 :             other.setNull ();
     271                 :           1 :             return *this;
     272                 :             :           }
     273                 :             : 
     274                 :          11 :         _store.textval.~basic_string<std::string::value_type> ();
     275                 :             :       }
     276         [ +  + ]:          50 :     else if (_type == Type::Blob)
     277                 :             :       {
     278         [ +  + ]:          11 :         if (other._type == Type::Blob)
     279                 :             :           {
     280                 :           1 :             _store.blobval = std::move (other._store.blobval);
     281                 :           1 :             other.setNull ();
     282                 :           1 :             return *this;
     283                 :             :           }
     284                 :             : 
     285                 :          10 :         _store.blobval.~vector<Blob::value_type> ();
     286                 :             :       }
     287                 :             : 
     288                 :          60 :     _type = other._type;
     289                 :             : 
     290   [ +  +  +  +  :          60 :     switch (_type)
                +  -  - ]
     291                 :             :       {
     292                 :          12 :       case Type::Null:
     293                 :          12 :         break;
     294                 :             : 
     295                 :          18 :       case Type::Int:
     296                 :          18 :         _store.intval = std::move (other._store.intval);
     297                 :          18 :         break;
     298                 :             : 
     299                 :          10 :       case Type::Real:
     300                 :          10 :         _store.realval = std::move (other._store.realval);
     301                 :          10 :         break;
     302                 :             : 
     303                 :          11 :       case Type::Text:
     304                 :          11 :         new (&_store.textval) std::string (std::move (other._store.textval));
     305                 :          11 :         other._store.textval.~basic_string ();
     306                 :          11 :         break;
     307                 :             : 
     308                 :           9 :       case Type::Blob:
     309                 :           9 :         new (&_store.blobval) Blob (std::move (other._store.blobval));
     310                 :           9 :         other._store.blobval.~vector ();
     311                 :           9 :         break;
     312                 :             : 
     313                 :           0 :       case Type::Variant:
     314                 :             :         raiseErrUnexpected ("never reach"); // LCOV_EXCL_LINE
     315                 :             :         break;                              // LCOV_EXCL_LINE
     316                 :             :       }
     317                 :             : 
     318                 :             :     // important, set other to null so that clear does not trial to clear
     319                 :          60 :     other._type = Type::Null;
     320                 :             : 
     321                 :          60 :     return *this;
     322                 :             :   }
     323                 :             : 
     324                 :             :   Value&
     325                 :          57 :   Value::operator= (int val)
     326                 :             :   {
     327         [ +  + ]:          57 :     if (_type == Type::Text)
     328                 :             :       {
     329                 :           1 :         _store.textval.~basic_string<std::string::value_type> ();
     330                 :             :       }
     331         [ +  + ]:          56 :     else if (_type == Type::Blob)
     332                 :             :       {
     333                 :           1 :         _store.blobval.~vector<Blob::value_type> ();
     334                 :             :       }
     335                 :          57 :     _store.intval = val;
     336                 :          57 :     _type         = Type::Int;
     337                 :          57 :     return *this;
     338                 :             :   }
     339                 :             : 
     340                 :             :   Value&
     341                 :          75 :   Value::operator= (const int64_t& val)
     342                 :             :   {
     343         [ +  + ]:          75 :     if (_type == Type::Text)
     344                 :             :       {
     345                 :           1 :         _store.textval.~basic_string<std::string::value_type> ();
     346                 :             :       }
     347         [ +  + ]:          74 :     else if (_type == Type::Blob)
     348                 :             :       {
     349                 :           1 :         _store.blobval.~vector<Blob::value_type> ();
     350                 :             :       }
     351                 :          75 :     _store.intval = val;
     352                 :          75 :     _type         = Type::Int;
     353                 :          75 :     return *this;
     354                 :             :   }
     355                 :             : 
     356                 :             :   Value&
     357                 :          62 :   Value::operator= (const double& val)
     358                 :             :   {
     359         [ +  + ]:          62 :     if (_type == Type::Text)
     360                 :             :       {
     361                 :           1 :         _store.textval.~basic_string<std::string::value_type> ();
     362                 :             :       }
     363         [ +  + ]:          61 :     else if (_type == Type::Blob)
     364                 :             :       {
     365                 :           1 :         _store.blobval.~vector<Blob::value_type> ();
     366                 :             :       }
     367                 :          62 :     _store.realval = val;
     368                 :          62 :     _type          = Type::Real;
     369                 :          62 :     return *this;
     370                 :             :   }
     371                 :             : 
     372                 :             :   Value&
     373                 :          97 :   Value::operator= (const std::string& val)
     374                 :             :   {
     375         [ +  + ]:          97 :     if (_type == Type::Text)
     376                 :             :       {
     377                 :           1 :         _store.textval = val;
     378                 :           1 :         return *this;
     379                 :             :       }
     380         [ +  + ]:          96 :     else if (_type == Type::Blob)
     381                 :             :       {
     382                 :           1 :         _store.blobval.~vector<Blob::value_type> ();
     383                 :             :       }
     384                 :             : 
     385   [ +  -  -  - ]:          96 :     new (&_store.textval) std::string (val);
     386                 :          96 :     _type = Type::Text;
     387                 :          96 :     return *this;
     388                 :             :   }
     389                 :             : 
     390                 :             :   Value&
     391                 :          23 :   Value::operator= (const Blob& val)
     392                 :             :   {
     393         [ +  + ]:          23 :     if (_type == Type::Text)
     394                 :             :       {
     395                 :           2 :         _store.textval.~basic_string<std::string::value_type> ();
     396                 :             :       }
     397         [ +  + ]:          21 :     else if (_type == Type::Blob)
     398                 :             :       {
     399                 :           1 :         _store.blobval = val;
     400                 :           1 :         return *this;
     401                 :             :       }
     402   [ +  -  -  - ]:          22 :     new (&_store.blobval) Blob (val);
     403                 :          22 :     _type = Type::Blob;
     404                 :          22 :     return *this;
     405                 :             :   }
     406                 :             : 
     407                 :           7 :   Value::operator int () const
     408                 :             :   {
     409         [ +  + ]:           7 :     if (isNull ())
     410         [ +  - ]:           1 :       throw ErrNullValueAccess ();
     411         [ +  + ]:           6 :     else if (_type == Type::Real)
     412                 :           3 :       return losslessConvert1<double, int> (_store.realval);
     413         [ +  + ]:           3 :     else if (_type != Type::Int)
     414         [ +  - ]:           2 :       throw ErrTypeMisMatch ("Implicit conversion: " + typeName (_type)
     415   [ +  -  +  -  :           3 :                              + " to int64_t");
                   +  - ]
     416                 :             : 
     417                 :             :     using limit = std::numeric_limits<int>;
     418                 :             : 
     419   [ +  -  +  +  :           2 :     if (_store.intval < limit::min () || _store.intval > limit::max ())
                   +  + ]
     420         [ +  - ]:           1 :       throw ErrOutOfRange ("Implicit conversion int64_t to int, value to big");
     421                 :             : 
     422                 :           1 :     return static_cast<int> (_store.intval);
     423                 :             :   }
     424                 :             : 
     425                 :          42 :   Value::operator int64_t () const
     426                 :             :   {
     427         [ +  + ]:          42 :     if (isNull ())
     428         [ +  - ]:           1 :       throw ErrNullValueAccess ();
     429         [ +  + ]:          41 :     else if (_type == Type::Real)
     430                 :           7 :       return losslessConvert1<double, int64_t> (_store.realval);
     431         [ +  + ]:          34 :     else if (_type != Type::Int)
     432         [ +  - ]:          24 :       throw ErrTypeMisMatch ("Implicit conversion: " + typeName (_type)
     433   [ +  -  +  -  :          36 :                              + " to int64_t");
                   +  - ]
     434                 :             : 
     435                 :          22 :     return _store.intval;
     436                 :             :   }
     437                 :             : 
     438                 :          20 :   Value::operator double () const
     439                 :             :   {
     440         [ +  + ]:          20 :     if (isNull ())
     441                 :             :       {
     442         [ +  - ]:           1 :         throw ErrNullValueAccess ();
     443                 :             :       }
     444         [ +  + ]:          19 :     else if (_type == Type::Int)
     445                 :             :       {
     446                 :             :         //        using limit = std::numeric_limits<double>;
     447                 :             :         //        if (_store.intval < limit::min () || _store.intval >
     448                 :             :         //        limit::max ())
     449                 :             :         //          throw Not possible  :- );
     450                 :             : 
     451                 :           1 :         return static_cast<double> (_store.intval);
     452                 :             :       }
     453         [ +  + ]:          18 :     else if (_type != Type::Real)
     454                 :             :       {
     455         [ +  - ]:          24 :         throw ErrTypeMisMatch (typeName (_type)
     456   [ +  -  +  -  :          36 :                                + " != " + typeName (Type::Real));
             +  -  +  - ]
     457                 :             :       }
     458                 :             : 
     459                 :           6 :     return _store.realval;
     460                 :             :   }
     461                 :             : 
     462                 :          30 :   Value::operator const std::string& () const
     463                 :             :   {
     464         [ +  + ]:          30 :     if (isNull ())
     465         [ +  - ]:           1 :       throw ErrNullValueAccess ();
     466         [ +  + ]:          29 :     else if (_type != Type::Text)
     467         [ +  - ]:          46 :       throw ErrTypeMisMatch (typeName (_type)
     468   [ +  -  +  -  :          69 :                              + " != " + typeName (Type::Text));
             +  -  +  - ]
     469                 :             : 
     470                 :           6 :     return _store.textval;
     471                 :             :   }
     472                 :             : 
     473                 :          30 :   Value::operator const Blob& () const
     474                 :             :   {
     475         [ +  + ]:          30 :     if (isNull ())
     476         [ +  - ]:           1 :       throw ErrNullValueAccess ();
     477         [ +  + ]:          29 :     else if (_type != Type::Blob)
     478         [ +  - ]:          46 :       throw ErrTypeMisMatch (typeName (_type)
     479   [ +  -  +  -  :          69 :                              + " != " + typeName (Type::Blob));
             +  -  +  - ]
     480                 :             : 
     481                 :           6 :     return _store.blobval;
     482                 :             :   }
     483                 :             : 
     484                 :             :   const int64_t&
     485                 :         109 :   Value::int64 () const
     486                 :             :   {
     487         [ +  + ]:         109 :     if (isNull ())
     488         [ +  - ]:           3 :       throw ErrNullValueAccess ();
     489                 :             : 
     490                 :         106 :     const auto wanted = Type::Int;
     491         [ +  + ]:         106 :     if (_type != wanted)
     492   [ +  -  +  -  :          30 :       throw ErrTypeMisMatch (typeName (_type) + " != " + typeName (wanted));
          +  -  +  -  +  
                      - ]
     493                 :             : 
     494                 :          76 :     return _store.intval;
     495                 :             :   }
     496                 :             : 
     497                 :             :   const double&
     498                 :          53 :   Value::real () const
     499                 :             :   {
     500         [ +  + ]:          53 :     if (isNull ())
     501         [ +  - ]:           3 :       throw ErrNullValueAccess ();
     502                 :             : 
     503                 :          50 :     const auto wanted = Type::Real;
     504         [ +  + ]:          50 :     if (_type != wanted)
     505   [ +  -  +  -  :          16 :       throw ErrTypeMisMatch (typeName (_type) + " != " + typeName (wanted));
          +  -  +  -  +  
                      - ]
     506                 :             : 
     507                 :          34 :     return _store.realval;
     508                 :             :   }
     509                 :             : 
     510                 :             :   const std::string&
     511                 :          94 :   Value::text () const
     512                 :             :   {
     513         [ +  + ]:          94 :     if (isNull ())
     514         [ +  - ]:           3 :       throw ErrNullValueAccess ();
     515                 :             : 
     516                 :          91 :     const auto wanted = Type::Text;
     517         [ +  + ]:          91 :     if (_type != wanted)
     518   [ +  -  +  -  :          28 :       throw ErrTypeMisMatch (typeName (_type) + " != " + typeName (wanted));
          +  -  +  -  +  
                      - ]
     519                 :             : 
     520                 :          63 :     return _store.textval;
     521                 :             :   }
     522                 :             : 
     523                 :             :   const Blob&
     524                 :          60 :   Value::blob () const
     525                 :             :   {
     526         [ +  + ]:          60 :     if (isNull ())
     527         [ +  - ]:           3 :       throw ErrNullValueAccess ();
     528                 :             : 
     529                 :          57 :     const auto wanted = Type::Blob;
     530         [ +  + ]:          57 :     if (_type != wanted)
     531   [ +  -  +  -  :          27 :       throw ErrTypeMisMatch (typeName (_type) + " != " + typeName (wanted));
          +  -  +  -  +  
                      - ]
     532                 :             : 
     533                 :          30 :     return _store.blobval;
     534                 :             :   }
     535                 :             : 
     536                 :             :   std::string
     537                 :           5 :   Value::ejectText ()
     538                 :             :   {
     539         [ +  + ]:           5 :     if (_type == Type::Null)
     540                 :             :       {
     541         [ +  - ]:           3 :         throw ErrNullValueAccess ();
     542                 :             :       }
     543         [ +  + ]:           2 :     else if (_type != Type::Text)
     544                 :             :       {
     545         [ +  - ]:           2 :         throw ErrTypeMisMatch (typeName (_type)
     546   [ +  -  +  -  :           3 :                                + " != " + typeName (Type::Text));
             +  -  +  - ]
     547                 :             :       }
     548                 :           1 :     auto tmp = std::move (_store.textval);
     549                 :             :     // setNull (); // does not works,
     550                 :             :     // gcc reports some obscure error in release build
     551                 :             :     // therefore we do it manually
     552                 :           1 :     _store.textval.~basic_string<std::string::value_type> ();
     553                 :           1 :     _type = Type::Null;
     554                 :           1 :     return tmp;
     555                 :             :   }
     556                 :             : 
     557                 :             :   Blob
     558                 :           5 :   Value::ejectBlob ()
     559                 :             :   {
     560         [ +  + ]:           5 :     if (_type == Type::Null)
     561                 :             :       {
     562         [ +  - ]:           3 :         throw ErrNullValueAccess ();
     563                 :             :       }
     564         [ +  + ]:           2 :     else if (_type != Type::Blob)
     565                 :             :       {
     566         [ +  - ]:           2 :         throw ErrTypeMisMatch (typeName (_type)
     567   [ +  -  +  -  :           3 :                                + " != " + typeName (Type::Blob));
             +  -  +  - ]
     568                 :             :       }
     569                 :             : 
     570                 :           1 :     auto tmp = std::move (_store.blobval);
     571                 :             :     // setNull (); // does not works,
     572                 :             :     // gcc reports some obscure error in release build
     573                 :             :     // therefore we do it manually
     574                 :           1 :     _store.blobval.~vector<Blob::value_type> ();
     575                 :           1 :     _type = Type::Null;
     576                 :           1 :     return tmp;
     577                 :             :   }
     578                 :             : 
     579                 :             :   void
     580                 :           3 :   Value::setNull () noexcept
     581                 :             :   {
     582         [ +  + ]:           3 :     if (_type == Type::Text)
     583                 :             :       {
     584                 :           2 :         _store.textval.~basic_string<std::string::value_type> ();
     585                 :             :       }
     586         [ +  - ]:           1 :     else if (_type == Type::Blob)
     587                 :             :       {
     588                 :           1 :         _store.blobval.~vector<Blob::value_type> ();
     589                 :             :       }
     590                 :           3 :     _type = Type::Null;
     591                 :           3 :   }
     592                 :             : 
     593                 :             :   bool
     594                 :         723 :   Value::isNull () const noexcept
     595                 :             :   {
     596                 :         723 :     return _type == Type::Null;
     597                 :             :   }
     598                 :             : 
     599                 :             :   Type
     600                 :        1128 :   Value::getType () const noexcept
     601                 :             :   {
     602                 :        1128 :     return _type;
     603                 :             :   }
     604                 :             : 
     605                 :             :   std::ostream&
     606                 :          23 :   operator<< (std::ostream& stm, const sl3::Value& v)
     607                 :             :   {
     608   [ +  +  +  +  :          23 :     switch (v.getType ())
                   +  - ]
     609                 :             :       {
     610                 :           2 :       case Type::Null:
     611                 :           2 :         stm << "<NULL>";
     612                 :           2 :         break;
     613                 :             : 
     614                 :           6 :       case Type::Int:
     615                 :           6 :         stm << v._store.intval;
     616                 :           6 :         break;
     617                 :             : 
     618                 :           6 :       case Type::Real:
     619                 :           6 :         stm << v._store.realval;
     620                 :           6 :         break;
     621                 :             : 
     622                 :           7 :       case Type::Text:
     623                 :           7 :         stm << v._store.textval;
     624                 :           7 :         break;
     625                 :             : 
     626                 :           2 :       case Type::Blob:
     627                 :           2 :         stm << "<BLOB>";
     628                 :           2 :         break;
     629                 :             : 
     630                 :           0 :       default:
     631                 :             :         stm << "unknown storage type !!"; // LCOV_EXCL_LINE
     632                 :             :         break;                            // LCOV_EXCL_LINE
     633                 :             :       }
     634                 :             : 
     635                 :          23 :     return stm;
     636                 :             :   }
     637                 :             : 
     638                 :             :   bool
     639                 :         113 :   value_type_eq (const Value& a, const Value& b) noexcept
     640                 :             :   {
     641         [ +  + ]:         113 :     if (a.getType () != b.getType ())
     642                 :          21 :       return false;
     643                 :             : 
     644                 :          92 :     bool retval = false;
     645                 :             : 
     646   [ +  +  +  +  :          92 :     switch (a.getType ())
                   +  - ]
     647                 :             :       {
     648                 :          16 :       case Type::Null:
     649                 :          16 :         retval = b.isNull ();
     650                 :          16 :         break;
     651                 :             : 
     652                 :          22 :       case Type::Int:
     653                 :          22 :         retval = a._store.intval == b._store.intval;
     654                 :             : 
     655                 :          22 :         break;
     656                 :             : 
     657                 :          19 :       case Type::Real:
     658                 :          19 :         retval = almost_equal (a._store.realval, b._store.realval, 2);
     659                 :          19 :         break;
     660                 :             : 
     661                 :          18 :       case Type::Text:
     662                 :          18 :         retval = a._store.textval == b._store.textval;
     663                 :          18 :         break;
     664                 :             : 
     665                 :          17 :       case Type::Blob:
     666                 :          17 :         retval = a._store.blobval == b._store.blobval;
     667                 :          17 :         break;
     668                 :             : 
     669                 :           0 :       default:
     670                 :             :         break; // LCOV_EXCL_LINE
     671                 :             :       }
     672                 :             : 
     673                 :          92 :     return retval;
     674                 :             :   }
     675                 :             : 
     676                 :             :   bool
     677                 :          38 :   value_type_lt (const Value& a, const Value& b) noexcept
     678                 :             :   {
     679         [ +  + ]:          38 :     if (b.isNull ())
     680                 :           4 :       return false;
     681                 :             : 
     682         [ +  + ]:          34 :     if (a.isNull ())
     683                 :           4 :       return true;
     684                 :             : 
     685         [ +  + ]:          30 :     if (a.getType () == Type::Int)
     686                 :             :       {
     687         [ +  + ]:          11 :         if (b.getType () == Type::Int)
     688                 :           6 :           return a._store.intval < b._store.intval;
     689                 :             : 
     690         [ +  + ]:           5 :         if (b.getType () == Type::Real)
     691                 :           3 :           return is_less_equal (a._store.intval, b._store.realval);
     692                 :             :         // respect type, int type smaller if equal to real value
     693                 :             : 
     694                 :           2 :         return true;
     695                 :             :       }
     696                 :             : 
     697         [ +  + ]:          19 :     if (a.getType () == Type::Real)
     698                 :             :       {
     699         [ +  + ]:           7 :         if (b.getType () == Type::Int)
     700                 :           2 :           return is_less (a._store.realval, b._store.intval);
     701                 :             :         // respect type, int type smaller if equal to real value
     702                 :             : 
     703         [ +  + ]:           5 :         if (b.getType () == Type::Real)
     704                 :           3 :           return a._store.realval < b._store.realval;
     705                 :             : 
     706                 :           2 :         return true;
     707                 :             :       }
     708                 :             : 
     709         [ +  + ]:          12 :     if (a.getType () == Type::Text)
     710                 :             :       {
     711         [ +  + ]:           6 :         if (b.getType () == Type::Text)
     712                 :           3 :           return a._store.textval < b._store.textval;
     713                 :             : 
     714                 :             :         // only blob types are bigger
     715                 :           3 :         return b.getType () == Type::Blob;
     716                 :             :       }
     717                 :             : 
     718                 :             :     // ASSERT_EXCEPT(a.getType () == Type::Blob, ErrUnexpected) ;
     719                 :             : 
     720                 :             :     // this is blob
     721         [ +  + ]:           6 :     if (b.getType () != Type::Blob)
     722                 :           3 :       return false;
     723                 :             : 
     724                 :             :     // we are both bolb
     725                 :           3 :     return a._store.blobval < b._store.blobval;
     726                 :             :   }
     727                 :             : 
     728                 :             :   void
     729                 :           1 :   Value::swap (Value& other) noexcept
     730                 :             :   {
     731                 :           1 :     Value t{std::move (other)};
     732                 :             :     // should be auto t{...} but 4.8.2 does not like it
     733                 :           1 :     other = std::move (*this);
     734                 :           1 :     *this = std::move (t);
     735                 :           1 :   }
     736                 :             : 
     737                 :             :   void
     738                 :           1 :   swap (Value& a, Value& b) noexcept
     739                 :             :   {
     740                 :           1 :     a.swap (b);
     741                 :           1 :   }
     742                 :             : 
     743                 :             :   bool
     744                 :          30 :   value_eq (const Value& a, const Value& b) noexcept
     745                 :             :   {
     746                 :          30 :     bool retval = false;
     747                 :             : 
     748   [ +  +  +  +  :          30 :     switch (a.getType ())
                   +  - ]
     749                 :             :       {
     750                 :           5 :       case Type::Null:
     751                 :           5 :         retval = b.isNull ();
     752                 :           5 :         break;
     753                 :             : 
     754                 :           9 :       case Type::Int:
     755         [ +  + ]:           9 :         if (b._type == Type::Int)
     756                 :           3 :           retval = a._store.intval == b._store.intval;
     757         [ +  + ]:           6 :         else if (b._type == Type::Real)
     758                 :           3 :           retval = is_equal (a._store.intval, b._store.realval);
     759                 :             : 
     760                 :           9 :         break;
     761                 :             : 
     762                 :           6 :       case Type::Real:
     763         [ +  + ]:           6 :         if (b._type == Type::Int)
     764                 :           1 :           retval = is_equal (a._store.realval, b._store.intval);
     765         [ +  + ]:           5 :         else if (b._type == Type::Real)
     766                 :           2 :           retval = a._store.realval == b._store.realval;
     767                 :             : 
     768                 :           6 :         break;
     769                 :             : 
     770                 :           5 :       case Type::Text:
     771         [ +  + ]:           5 :         if (b._type == Type::Text)
     772                 :           1 :           retval = a._store.textval == b._store.textval;
     773                 :           5 :         break;
     774                 :             : 
     775                 :           5 :       case Type::Blob:
     776         [ +  + ]:           5 :         if (b._type == Type::Blob)
     777                 :           1 :           retval = a._store.blobval == b._store.blobval;
     778                 :           5 :         break;
     779                 :             : 
     780                 :           0 :       default:
     781                 :             :         break; // LCOV_EXCL_LINE
     782                 :             :       }
     783                 :             : 
     784                 :          30 :     return retval;
     785                 :             :   }
     786                 :             : 
     787                 :             :   bool
     788                 :          51 :   value_lt (const Value& a, const Value& b) noexcept
     789                 :             :   {
     790         [ +  + ]:          51 :     if (b.isNull ())
     791                 :           4 :       return false;
     792                 :             : 
     793         [ +  + ]:          47 :     if (a.isNull ())
     794                 :           4 :       return true;
     795                 :             : 
     796         [ +  + ]:          43 :     if (a.getType () == Type::Int)
     797                 :             :       {
     798         [ +  + ]:          23 :         if (b.getType () == Type::Int)
     799                 :          18 :           return a._store.intval < b._store.intval;
     800                 :             : 
     801         [ +  + ]:           5 :         if (b.getType () == Type::Real)
     802                 :           3 :           return is_less (a._store.intval, b._store.realval);
     803                 :             : 
     804                 :           2 :         return true;
     805                 :             :       }
     806                 :             : 
     807         [ +  + ]:          20 :     if (a.getType () == Type::Real)
     808                 :             :       {
     809         [ +  + ]:           7 :         if (b.getType () == Type::Int)
     810                 :           2 :           return is_less (a._store.realval, b._store.intval);
     811                 :             : 
     812         [ +  + ]:           5 :         if (b.getType () == Type::Real)
     813                 :           3 :           return a._store.realval < b._store.realval;
     814                 :             : 
     815                 :           2 :         return true;
     816                 :             :       }
     817                 :             : 
     818         [ +  + ]:          13 :     if (a.getType () == Type::Text)
     819                 :             :       {
     820         [ +  + ]:           7 :         if (b.getType () == Type::Text)
     821                 :           4 :           return a._store.textval < b._store.textval;
     822                 :             : 
     823         [ +  + ]:           3 :         if (b.getType () == Type::Blob)
     824                 :           1 :           return true;
     825                 :             :         else
     826                 :           2 :           return false;
     827                 :             :       }
     828                 :             : 
     829                 :             :     // TODO assert a.getType () == Type::Blob
     830                 :             : 
     831                 :             :     // this is blob
     832         [ +  + ]:           6 :     if (b.getType () != Type::Blob)
     833                 :           3 :       return false;
     834                 :             : 
     835                 :             :     // we are both bolb
     836                 :           3 :     return a._store.blobval < b._store.blobval;
     837                 :             :   }
     838                 :             : 
     839                 :             : } // ns
        

Generated by: LCOV version 2.0-1