Skip to content

Commit

Permalink
/prov generic2
Browse files Browse the repository at this point in the history
  • Loading branch information
jeog committed Apr 29, 2016
1 parent 37c9db7 commit eab7fc5
Show file tree
Hide file tree
Showing 8 changed files with 402 additions and 49 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
## project specific
###################
*.tosdb
prov/tmp*

#################
## Eclipse
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ Even if you are not comfortable contributing code, simply reporting bugs or ques
All log files and dumps
- **/prov**
Provisional code that is being worked on outside the main build tree
### Build Notes
- - -
Expand Down
102 changes: 102 additions & 0 deletions prov/generic2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
Copyright (C) 2014 Jonathon Ogden < [email protected] >
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses.
*/

#include "generic2.hpp"

TOSDB_Generic&
TOSDB_Generic::operator=(const TOSDB_Generic& gen)
{
if( *this == gen )
return *this;

if( gen.is_string() )
{
if( this->is_string() )
/* if we're also a string simply assign */
*((std::string*)this->_sub) = *((std::string*)gen._sub);
else
/* otherwise allocate new */
*(std::string**)this->_sub =
new std::string(*((std::string*)gen._sub));
}
else
{
if( this->is_string() )
delete *(std::string**)this->_sub;

memcpy(this->_sub, gen._sub, gen._type_bsz);
}

this->_type_val = gen._type_val;
this->_type_bsz = gen._type_bsz;
return *this;
}

TOSDB_Generic&
TOSDB_Generic::operator=(TOSDB_Generic&& gen)
{
/* not sure if this is optimal or its better to branch(as above) and move
the string object in, allowing gen's destructor to delete
although, this way is a lot cleaner than 2 nested conditionals*/
if(this->_type_val == TYVAL_STRING)
delete *(std::string**)this->_sub;

/* we are stealing the scalar value OR the string pointer */
memcpy(this->_sub, gen._sub, gen._type_bsz);
/* keep gen's carcas from screwing us if it had a string ptr */
memset(gen._sub, 0, 8);
/* and change its type to keep it's destructor from doing the same */
gen._type_val = TYVAL_VOID;

this->_type_val = gen._type_val;
this->_type_bsz = gen._type_bsz;
return *this;
}


std::string
TOSDB_Generic::as_string() const
{
switch(this->_type_val){
case(TYVAL_LONG):
case(TYVAL_LONG_LONG):
return std::to_string(*((long long*)this->_sub));
case(TYVAL_FLOAT):
case(TYVAL_DOUBLE):
return std::to_string(*((double*)this->_sub));
case(TYVAL_STRING):
return *((std::string*)(this->_sub));
default:
return std::string();
};
}

size_t
TOSDB_Generic::size() const
{
switch(this->_type_val){
case(TYVAL_LONG): return sizeof(long);
case(TYVAL_LONG_LONG): return sizeof(long long);
case(TYVAL_FLOAT): return sizeof(float);
case(TYVAL_DOUBLE): return sizeof(double);
case(TYVAL_STRING): return ((std::string*)(this->_sub))->size();
default: return 0;
};
}


277 changes: 277 additions & 0 deletions prov/generic2.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,277 @@
/*
Copyright (C) 2014 Jonathon Ogden < [email protected] >
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses.
*/

#ifndef JO_JO_GENERIC
#define JO_JO_GENERIC

#include <sstream>
#include <string>
#include <iostream>
#include <typeinfo>
#include <math.h>
#include <limits.h>
#include <string.h>


template<typename T> /* forward decl */
inline T
CastGenericFromString(std::string str);


class TOSDB_Generic{
static const int TYVAL_VOID = 0;
static const int TYVAL_LONG = 1;
static const int TYVAL_LONG_LONG = 2;
static const int TYVAL_FLOAT = 3;
static const int TYVAL_DOUBLE = 4;
static const int TYVAL_STRING = 5;

static const int STR_MAX = UCHAR_MAX - 1;

/* raw mem holding our 'object' */
uint8_t _sub[8];

/* the type of our 'object' */
unsigned char _type_val;

/* have some space from alignment so we'll cache the size (of the
implementations internal representation, NOT the actual size of the type) */
unsigned char _type_bsz;

template< typename T >
T
_val_switch() const
{
try{
switch(this->_type_val){
case TYVAL_LONG:
case TYVAL_LONG_LONG:
return (T)(*(long long*)(this->_sub));
case TYVAL_FLOAT:
case TYVAL_DOUBLE:
return (T)(*(double*)(this->_sub));
case TYVAL_STRING:
return (T)CastGenericFromString<T>(*(std::string*)(this->_sub));
default: throw;
}
}catch(...){
std::ostringstream s;
s << "error casting generic to < " << typeid(T).name() << " >";
#ifdef __GNUC__
throw std::bad_cast();
#else
throw std::bad_cast(s.str().c_str());
#endif
}
}

public:
template<typename T>
struct Type_Check {
static const bool
value = std::is_same<T, float>::value
|| std::is_same<T, long>::value
|| std::is_same<T, double>::value
|| std::is_same<T, long long>::value
|| std::is_same<T, std::string>::value;
};

explicit TOSDB_Generic(long val)
:
_type_val( TYVAL_LONG ),
_type_bsz( sizeof(long long) )
{

*((long long*)this->_sub) = val;
}

explicit TOSDB_Generic(long long val)
:
_type_val( TYVAL_LONG_LONG ),
_type_bsz( sizeof(long long) )
{

*((long long*)this->_sub) = val;
}

explicit TOSDB_Generic(float val)
:
_type_val( TYVAL_FLOAT ),
_type_bsz( sizeof(double) )
{

*((double*)this->_sub) = val;
}

explicit TOSDB_Generic(double val)
:
_type_val( TYVAL_DOUBLE ),
_type_bsz( sizeof(double) )
{

*((double*)this->_sub) = val;
}

explicit TOSDB_Generic(std::string str)
: /* ! must be able to delete (std::string*)_sub at ANY TIME !*/
_type_val( TYVAL_STRING ),
_type_bsz( sizeof(std::string*) )
{ /* let string do all the heavy lifting */
*((std::string**)(this->_sub)) = new std::string(str.substr(0,STR_MAX));
}

TOSDB_Generic(TOSDB_Generic&& gen)
:
_type_val( gen._type_val ),
_type_bsz( gen._type_bsz )
{
/* we are stealing the scalar value OR the string pointer */
memcpy(this->_sub, gen._sub, gen._type_bsz);
/* keep gen's carcas from screwing us if it had a string ptr */
memset(gen._sub, 0, 8);
/* and change its type to keep it's destructor from doing the same */
gen._type_val = TYVAL_VOID;
}

TOSDB_Generic(const TOSDB_Generic& gen)
:
_type_val( gen._type_val ),
_type_bsz( gen._type_bsz )
{
if(gen._type_val == TYVAL_STRING)
*(std::string**)this->_sub =
new std::string(*((std::string*)gen._sub));
else
memcpy(this->_sub, gen._sub, gen._type_bsz);
}

TOSDB_Generic&
operator=(const TOSDB_Generic& gen);

TOSDB_Generic&
operator=(TOSDB_Generic&& gen);

~TOSDB_Generic()
{
if(this->_type_val == TYVAL_STRING)
delete *(std::string**)(this->_sub);
}

inline bool
operator==(const TOSDB_Generic& gen) const
{
return ( (this->_type_val == gen._type_val)
&& (this->as_string() == gen.as_string()) );
}

inline bool
operator!=(const TOSDB_Generic& gen) const
{
return !(this->operator==(gen));
}

size_t
size() const;

inline bool
is_float() const { return (this->_type_val == TYVAL_FLOAT); }

inline bool
is_double() const { return (this->_type_val == TYVAL_DOUBLE); }

inline bool
is_long() const { return (this->_type_val == TYVAL_LONG); }

inline bool
is_long_long() const { return (this->_type_val == TYVAL_LONG_LONG); }

inline bool
is_string() const { return (this->_type_val == TYVAL_STRING); }

inline bool
is_floating_point() const
{
return (this->_type_val == TYVAL_FLOAT || this->_type_val == TYVAL_DOUBLE);
}

inline bool
is_integer() const
{
return (this->_type_val == TYVAL_LONG || this->_type_val == TYVAL_LONG_LONG);
}

inline long
as_long() const { return this->_val_switch<long>(); }

inline long long
as_long_long() const { return this->_val_switch<long long>(); }

inline float
as_float() const { return this->_val_switch<float>(); }

inline double
as_double() const { return this->_val_switch<double>(); }

std::string
as_string() const;

inline operator
long() const { return this->_val_switch<long>(); }

inline operator
long long() const { return this->_val_switch<long long>(); }

inline operator
float() const { return this->_val_switch<float>(); }

inline operator
double() const { return this->_val_switch<double>(); }

inline operator
std::string() const { return this->as_string(); }
};


template<typename T>
inline T
CastGenericFromString(std::string str)
{
static_assert(TOSDB_Generic::Type_Check<T>::value,
"don't know how to cast to this type");
}

template<>
inline long long
CastGenericFromString<long long>(std::string str) { return std::stoll(str); }

template<>
inline long
CastGenericFromString<long>(std::string str) { return std::stol(str); }

template<>
inline double
CastGenericFromString<double>(std::string str) { return std::stod(str); }

template<>
inline float
CastGenericFromString<float>(std::string str) { return std::stof(str); }

template<>
inline std::string
CastGenericFromString<std::string>(std::string str) { return str; }

#endif
Loading

0 comments on commit eab7fc5

Please sign in to comment.