attributes.hh
Go to the documentation of this file.
/* -*- mia-c++ -*-
*
* This file is part of MIA - a toolbox for medical image analysis
* Copyright (c) Leipzig, Madrid 1999-2017 Gert Wollny
*
* MIA 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 MIA; if not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef mia_core_attributes_hh
#define mia_core_attributes_hh
#include <mia/core/msgstream.hh>
#include <mia/core/errormacro.hh>
#include <map>
#include <memory>
#include <string>
#include <cstring>
#include <vector>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <type_traits>
#include <iomanip>
#include <boost/any.hpp>
#include <boost/ref.hpp>
#include <boost/lexical_cast.hpp>
#include <mia/core/attributetype.hh>
NS_MIA_BEGIN
class EXPORT_CORE CAttribute
{
public:
virtual ~CAttribute();
std::string as_string() const;
bool is_equal(const CAttribute& other) const;
bool is_less(const CAttribute& other) const;
virtual const char *typedescr() const = 0;
virtual int type_id() const = 0;
private:
virtual std::string do_as_string() const = 0;
virtual bool do_is_equal(const CAttribute& other) const = 0;
virtual bool do_is_less(const CAttribute& other) const = 0;
};
inline
std::ostream& operator << (std::ostream& os, const CAttribute& attr)
{
os << attr.as_string();
return os;
};
inline bool operator == (const CAttribute& a, const CAttribute& b)
{
return a.is_equal(b);
}
typedef std::shared_ptr<CAttribute > PAttribute;
template <typename T>
class EXPORT_CORE TAttribute : public CAttribute
{
public:
TAttribute(typename ::boost::reference_wrapper<T>::type value);
operator T()const;
virtual const char *typedescr() const;
virtual int type_id() const;
protected:
const T& get_value() const;
private:
virtual std::string do_as_string() const;
virtual bool do_is_equal(const CAttribute& other) const;
virtual bool do_is_less(const CAttribute& other) const;
T m_value;
};
template <typename T>
T EXPORT_CORE get_attribute_as(const CAttribute& attr)
{
const TAttribute<T>& a = dynamic_cast<const TAttribute<T>&>(attr);
return a;
}
typedef TAttribute<int> CIntAttribute;
typedef TAttribute<std::vector<int>> CVIntAttribute;
typedef TAttribute<float> CFloatAttribute;
typedef TAttribute<std::vector<float>> CVFloatAttribute;
typedef TAttribute<double> CDoubleAttribute;
typedef TAttribute<std::vector<double>> CVDoubleAttribute;
typedef TAttribute<std::string> CStringAttribute;
typedef TAttribute<std::vector<std::string>> CVStringAttribute;
typedef std::map<std::string, PAttribute> CAttributeMap;
template <>
struct attribute_type<CAttributeMap> : public EAttributeType {
static const int value = 1000;
};
typedef TAttribute<CAttributeMap> CAttributeList;
typedef std::shared_ptr<CAttributeMap > PAttributeMap;
EXPORT_CORE std::ostream& operator << (std::ostream& os, const CAttributeMap& data);
class EXPORT_CORE CAttributedData
{
public:
CAttributedData();
CAttributedData(const CAttributedData& org);
CAttributedData(PAttributeMap attr);
CAttributedData& operator =(const CAttributedData& org);
const PAttribute get_attribute(const std::string& key) const;
CAttributeMap::const_iterator begin_attributes() const;
CAttributeMap::const_iterator end_attributes() const;
void set_attribute(const std::string& key, PAttribute attr);
void set_attributes(CAttributeMap::const_iterator begin, CAttributeMap::const_iterator end);
void set_attribute(const std::string& key, const std::string& value);
template <typename T>
void set_attribute(const std::string& key, const T& value);
void set_attribute(const std::string& key, const char *value);
const std::string get_attribute_as_string(const std::string& key)const;
template <typename T>
const T get_attribute_as(const std::string& key)const;
template <typename T>
const T get_attribute_as(const std::string& key, T default_value)const;
void delete_attribute(const std::string& key);
bool has_attribute(const std::string& key)const;
friend EXPORT_CORE bool operator == (const CAttributedData& a, const CAttributedData& b);
void print(std::ostream& os) const
{
os << *m_attr;
}
private:
PAttributeMap m_attr;
};
inline std::ostream& operator << (std::ostream& os, const CAttributedData& data)
{
data.print(os);
return os;
}
EXPORT_CORE bool operator == (const CAttributeMap& am, const CAttributeMap& bm);
class EXPORT_CORE CAttrTranslator
{
public:
virtual ~CAttrTranslator() {};
PAttribute from_string(const std::string& value) const;
private:
virtual PAttribute do_from_string(const std::string& value) const = 0;
protected:
CAttrTranslator();
bool do_register(const std::string& key);
};
class EXPORT_CORE CStringAttrTranslatorMap
{
public:
PAttribute to_attr(const std::string& key, const std::string& value) const;
static CStringAttrTranslatorMap& instance();
private:
friend class CAttrTranslator;
CStringAttrTranslatorMap();
bool add(const std::string& key, CAttrTranslator *t);
typedef std::map<std::string, std::shared_ptr<CAttrTranslator>> CMap;
CMap m_translators;
};
template <typename T>
void EXPORT_CORE add_attribute(CAttributeMap& attributes, const std::string& key, T value)
{
cvdebug() << "add attribute " << key << " of type " << typeid(T).name() << " and value '" << value << "'\n";
attributes[key] = PAttribute(new TAttribute<T>(value));
}
template <>
inline void EXPORT_CORE add_attribute(CAttributeMap& attributes, const std::string& key, const char *value)
{
attributes[key] = CStringAttrTranslatorMap::instance().to_attr(key, value);
cvdebug() << "add_attribute '" << key
<< "' to '" << value << "' of type '"
<< attributes[key]->typedescr() << "'\n";
}
template <typename T>
class EXPORT_CORE TTranslator: public CAttrTranslator
{
public:
static bool register_for(const std::string& key);
private:
virtual PAttribute do_from_string(const std::string& value) const;
};
// template implementation
template <typename T>
TAttribute<T>::TAttribute(typename ::boost::reference_wrapper<T>::type value):
m_value(value)
{
}
template <typename T>
TAttribute<T>::operator T() const
{
return m_value;
}
template <typename T>
const T& TAttribute<T>::get_value() const
{
return m_value;
}
template <typename T>
const char *TAttribute<T>::typedescr() const
{
return typeid(T).name();
}
template <typename T>
int TAttribute<T>::type_id() const
{
static_assert(attribute_type<T>::value != EAttributeType::attr_unknown,
"You must provide a type specialization for attribute_type<T>");
return attribute_type<T>::value;
}
template <typename T, bool is_floating>
struct __convert_to_string {
static std::string apply(const typename ::boost::reference_wrapper<T>::type value)
{
return boost::lexical_cast<std::string>(value);
}
};
template <typename T>
struct __convert_to_string<T, true> {
static std::string apply(const typename ::boost::reference_wrapper<T>::type value)
{
std::stringstream sval;
sval << std::setprecision(10) << value;
return sval.str();
}
};
template <typename T>
struct dispatch_attr_string {
static std::string val2string(const typename ::boost::reference_wrapper<T>::type value)
{
return __convert_to_string<T, std::is_floating_point<T>::value>::apply(value);
}
static T string2val(const std::string& str)
{
T v;
std::istringstream svalue(str);
svalue >> v;
return v;
}
};
template <typename T>
struct dispatch_attr_string<std::vector<T>> {
static std::string val2string(const std::vector<T>& value)
{
std::stringstream sval;
sval << value.size();
for (size_t i = 0; i < value.size(); ++i)
sval << " "
<< __convert_to_string<T, std::is_floating_point<T>::value>::apply(value[i]);
return sval.str();
}
static std::vector<T> string2val(const std::string& str)
{
size_t s;
std::istringstream svalue(str);
std::vector<T> v;
svalue >> s;
if (s > v.max_size())
throw create_exception<std::runtime_error>("string2val: try to create a vector of size ",
s, " but support only size ", v.max_size());
v.resize(s);
for (size_t i = 0; i < s; ++i)
svalue >> v[i];
if (svalue.fail()) {
std::stringstream msg;
msg << "string2val: unable to convert '" << str << "'";
throw std::invalid_argument(msg.str());
}
return v;
}
};
template <>
struct dispatch_attr_string<std::vector<bool>> {
static std::string val2string(const std::vector<bool>& value)
{
std::stringstream sval;
sval << value.size();
for (size_t i = 0; i < value.size(); ++i)
sval << " " << value[i];
return sval.str();
}
static std::vector<bool> string2val(const std::string& str)
{
size_t s;
std::istringstream svalue(str);
svalue >> s;
std::vector<bool> v(s);
// Added override for coverity
//
// Since s is used as the size for the new vector, a large
// value will result in a std::bad_alloc exception. This
// is not worse than bailing out because s is larger than
// an abitrary set boundary that youle be cheked here.
//
// coverity[tainted_scalar]
for (size_t i = 0; i < s; ++i) {
bool value;
svalue >> value;
v[i] = value;
}
if (svalue.fail()) {
std::stringstream msg;
msg << "string2val: unable to convert '" << str << "'";
throw std::invalid_argument(msg.str());
}
return v;
}
};
template <>
struct dispatch_attr_string<unsigned char> {
static std::string val2string(unsigned char value)
{
std::stringstream sval;
sval << (unsigned int)value;
return sval.str();
}
static unsigned char string2val(const std::string& str)
{
unsigned int v;
std::istringstream svalue(str);
svalue >> v;
return (unsigned char)v;
}
};
template <>
struct dispatch_attr_string<signed char> {
static std::string val2string(signed char value)
{
std::stringstream sval;
sval << (signed int)value;
return sval.str();
}
static signed char string2val(const std::string& str)
{
int v;
std::istringstream svalue(str);
svalue >> v;
return (signed char)v;
}
};
template <>
struct dispatch_attr_string<std::string> {
static std::string val2string(std::string value)
{
return value;
}
static std::string string2val(const std::string& str)
{
return str;
}
};
template <>
struct dispatch_attr_string<CAttributeMap> {
static std::string val2string(const CAttributeMap& /*value*/)
{
throw std::invalid_argument("Conversion of a CAttributeMap to a string not implemented");
}
static CAttributeMap string2val(const std::string& /*str*/)
{
throw std::invalid_argument("Conversion of a string to a CAttributeMap not implemented");
}
};
template <typename T>
void CAttributedData::set_attribute(const std::string& key, const T& value)
{
add_attribute(*m_attr, key, value);
}
template <typename T>
std::string TAttribute<T>::do_as_string() const
{
return dispatch_attr_string<T>::val2string(m_value);
}
template <typename T>
bool TAttribute<T>::do_is_equal(const CAttribute& other) const
{
const TAttribute<T> *o = dynamic_cast<const TAttribute<T> *>(&other);
if (!o) {
cvdebug() << "TAttribute<T>::do_is_equal:Cast to "
<< typeid(const TAttribute<T> *).name()
<< "failed\n";
return false;
}
return m_value == o->m_value;
}
template <typename T>
bool TAttribute<T>::do_is_less(const CAttribute& other) const
{
const TAttribute<T> *o = dynamic_cast<const TAttribute<T> *>(&other);
if (o)
return m_value < o->m_value;
return strcmp(typedescr(), other.typedescr()) < 0;
}
template <typename T>
const T CAttributedData::get_attribute_as(const std::string& key)const
{
PAttribute attr = get_attribute(key);
if (attr)
return dynamic_cast<const TAttribute<T>&>(*attr);
else
throw create_exception<std::invalid_argument>("CAttributedData: no attribute '", key, "' found");
}
template <typename T>
const T CAttributedData::get_attribute_as(const std::string& key, T default_value)const
{
PAttribute pattr = get_attribute(key);
if (!pattr)
return default_value;
auto attr = dynamic_cast<const TAttribute<T> *>(pattr.get());
if (!attr) {
cvwarn() << "Attribute '" << key << "'exists but is not of the expected type, returning default\n";
return default_value;
}
return *attr;
}
extern template class EXPORT_CORE TAttribute<uint8_t>;
extern template class EXPORT_CORE TAttribute<int8_t>;
extern template class EXPORT_CORE TAttribute<std::vector<uint8_t>>;
extern template class EXPORT_CORE TAttribute<std::vector<int8_t>>;
typedef TTranslator<double> CDoubleTranslator;
typedef TTranslator<std::vector<double>> CVDoubleTranslator;
typedef TTranslator<float> CFloatTranslator;
typedef TTranslator<std::vector<float>> CVFloatTranslator;
typedef TTranslator<uint64_t> CULTranslator;
typedef TTranslator<std::vector<uint64_t>> CVULTranslator;
typedef TTranslator<int64_t> CSLTranslator;
typedef TTranslator<std::vector<int64_t>> CVSLTranslator;
typedef TTranslator<unsigned int> CUITranslator;
typedef TTranslator<std::vector<uint32_t>> CVUITranslator;
typedef TTranslator<signed int> CSITranslator;
typedef TTranslator<std::vector<int32_t>> CVSITranslator;
typedef TTranslator<uint16_t> CUSTranslator;
typedef TTranslator<std::vector<uint16_t>> CVUSTranslator;
typedef TTranslator<int16_t> CSSTranslator;
typedef TTranslator<std::vector<int16_t>> CVSSTranslator;
typedef TTranslator<uint8_t> CUBTranslator;
typedef TTranslator<std::vector<uint8_t>> CVUBTranslator;
typedef TTranslator<int8_t> CSBTranslator;
typedef TTranslator<std::vector<int8_t>> CVSBTranslator;
typedef TTranslator<bool> CBitTranslator;
typedef TTranslator<std::vector<bool>> CVBitTranslator;
NS_MIA_END
#endif
CSLTranslator
TTranslator< int64_t > CSLTranslator
Definition attributes.hh:838
CBitTranslator
TTranslator< bool > CBitTranslator
Definition attributes.hh:859
CULTranslator
TTranslator< uint64_t > CULTranslator
Definition attributes.hh:835
CVUSTranslator
TTranslator< std::vector< uint16_t > > CVUSTranslator
Definition attributes.hh:848
CVSLTranslator
TTranslator< std::vector< int64_t > > CVSLTranslator
Definition attributes.hh:839
CUBTranslator
TTranslator< uint8_t > CUBTranslator
Definition attributes.hh:853
CSBTranslator
TTranslator< int8_t > CSBTranslator
Definition attributes.hh:856
CSITranslator
TTranslator< signed int > CSITranslator
Definition attributes.hh:844
CVSBTranslator
TTranslator< std::vector< int8_t > > CVSBTranslator
Definition attributes.hh:857
CVDoubleTranslator
TTranslator< std::vector< double > > CVDoubleTranslator
Definition attributes.hh:830
CDoubleTranslator
NEVER typedef TTranslator< double > CDoubleTranslator
*‍/
Definition attributes.hh:829
CVUBTranslator
TTranslator< std::vector< uint8_t > > CVUBTranslator
Definition attributes.hh:854
CUSTranslator
TTranslator< uint16_t > CUSTranslator
Definition attributes.hh:847
PAttribute
std::shared_ptr< CAttribute > PAttribute
define the shared pointer wrapped attribute pointer
Definition attributes.hh:102
CVSITranslator
TTranslator< std::vector< int32_t > > CVSITranslator
Definition attributes.hh:845
operator==
bool operator==(const CAttribute &a, const CAttribute &b)
Definition attributes.hh:95
CVBitTranslator
TTranslator< std::vector< bool > > CVBitTranslator
Definition attributes.hh:860
CVUITranslator
TTranslator< std::vector< uint32_t > > CVUITranslator
Definition attributes.hh:842
CVSSTranslator
TTranslator< std::vector< int16_t > > CVSSTranslator
Definition attributes.hh:851
CUITranslator
TTranslator< unsigned int > CUITranslator
Definition attributes.hh:841
CVFloatTranslator
TTranslator< std::vector< float > > CVFloatTranslator
Definition attributes.hh:833
operator<<
std::ostream & operator<<(std::ostream &os, const CAttribute &attr)
Definition attributes.hh:89
CFloatTranslator
TTranslator< float > CFloatTranslator
Definition attributes.hh:832
CSSTranslator
TTranslator< int16_t > CSSTranslator
Definition attributes.hh:850
CVULTranslator
TTranslator< std::vector< uint64_t > > CVULTranslator
Definition attributes.hh:836
attributetype.hh
CAttrTranslator::from_string
PAttribute from_string(const std::string &value) const
CAttrTranslator::do_register
bool do_register(const std::string &key)
CAttrTranslator::~CAttrTranslator
virtual ~CAttrTranslator()
The virtual destructor just ensures virtual destruction and silences a warning.
Definition attributes.hh:419
CAttrTranslator::CAttrTranslator
CAttrTranslator()
CAttribute
The class of all attributes of data that is considered to ve meta-data.
Definition attributes.hh:52
CAttribute::is_less
bool is_less(const CAttribute &other) const
CAttribute::is_equal
bool is_equal(const CAttribute &other) const
CAttribute::type_id
virtual int type_id() const =0
CAttribute::as_string
std::string as_string() const
returns the value as a atring
CAttribute::~CAttribute
virtual ~CAttribute()
virtual destructor since derived classes may define dynamic objetcs
CAttribute::typedescr
virtual const char * typedescr() const =0
CAttributedData
A collection of attributes.
Definition attributes.hh:260
CAttributedData::CAttributedData
CAttributedData()
CAttributedData::get_attribute_as_string
const std::string get_attribute_as_string(const std::string &key) const
returns the requested attribute as string, returns an empty string if attribute doesn't exist
CAttributedData::has_attribute
bool has_attribute(const std::string &key) const
CAttributedData::CAttributedData
CAttributedData(PAttributeMap attr)
CAttributedData::set_attribute
void set_attribute(const std::string &key, PAttribute attr)
CAttributedData::set_attribute
void set_attribute(const std::string &key, const std::string &value)
CAttributedData::delete_attribute
void delete_attribute(const std::string &key)
CAttributedData::set_attribute
void set_attribute(const std::string &key, const char *value)
CAttributedData::begin_attributes
CAttributeMap::const_iterator begin_attributes() const
CAttributedData::CAttributedData
CAttributedData(const CAttributedData &org)
CAttributedData::get_attribute
const PAttribute get_attribute(const std::string &key) const
CAttributedData::get_attribute_as
const T get_attribute_as(const std::string &key) const
Definition attributes.hh:792
CAttributedData::end_attributes
CAttributeMap::const_iterator end_attributes() const
CAttributedData::set_attributes
void set_attributes(CAttributeMap::const_iterator begin, CAttributeMap::const_iterator end)
CAttributedData::print
void print(std::ostream &os) const
Definition attributes.hh:380
CStringAttrTranslatorMap::CAttrTranslator
friend class CAttrTranslator
Definition attributes.hh:461
CStringAttrTranslatorMap::instance
static CStringAttrTranslatorMap & instance()
CStringAttrTranslatorMap::to_attr
PAttribute to_attr(const std::string &key, const std::string &value) const
TAttribute
Class of an attribute that holds data of type T.
Definition attributes.hh:119
TAttribute::TAttribute
TAttribute(typename ::boost::reference_wrapper< T >::type value)
Definition attributes.hh:535
TAttribute::typedescr
virtual const char * typedescr() const
Definition attributes.hh:553
TAttribute::get_value
const T & get_value() const
Definition attributes.hh:547
TAttribute::type_id
virtual int type_id() const
Definition attributes.hh:559
TTranslator
Generic string vs. attribute translator singleton.
Definition attributes.hh:518
TTranslator::register_for
static bool register_for(const std::string &key)
NS_MIA_BEGIN
#define NS_MIA_BEGIN
conveniance define to start the mia namespace
Definition defines.hh:33
EXPORT_CORE
#define EXPORT_CORE
Macro to manage Visual C++ style dllimport/dllexport.
Definition defines.hh:101
NS_MIA_END
#define NS_MIA_END
conveniance define to end the mia namespace
Definition defines.hh:36
errormacro.hh
add_attribute
void EXPORT_CORE add_attribute(CAttributeMap &attributes, const std::string &key, T value)
Definition attributes.hh:489
CAttributeMap
std::map< std::string, PAttribute > CAttributeMap
A name:attribute map.
Definition attributes.hh:221
CDoubleAttribute
TAttribute< double > CDoubleAttribute
a double attribute
Definition attributes.hh:196
CVStringAttribute
TAttribute< std::vector< std::string > > CVStringAttribute
a vector of strings attribute
Definition attributes.hh:215
PAttributeMap
std::shared_ptr< CAttributeMap > PAttributeMap
another pointer-usage easy maker
Definition attributes.hh:239
CIntAttribute
TAttribute< int > CIntAttribute
an integer attribute
Definition attributes.hh:172
CVFloatAttribute
TAttribute< std::vector< float > > CVFloatAttribute
Definition attributes.hh:190
CVDoubleAttribute
TAttribute< std::vector< double > > CVDoubleAttribute
a vector of doubles attribute
Definition attributes.hh:202
CFloatAttribute
TAttribute< float > CFloatAttribute
a float attribute
Definition attributes.hh:184
CStringAttribute
TAttribute< std::string > CStringAttribute
a string attribute
Definition attributes.hh:209
get_attribute_as
T EXPORT_CORE get_attribute_as(const CAttribute &attr)
Definition attributes.hh:162
CVIntAttribute
TAttribute< std::vector< int > > CVIntAttribute
a vector of integers attribute
Definition attributes.hh:178
CAttributeList
TAttribute< CAttributeMap > CAttributeList
providing the possibility to nest attribute lists
Definition attributes.hh:233
cvwarn
vstream & cvwarn()
send warnings to this stream adapter
Definition msgstream.hh:321
create_exception
E create_exception(T ...t)
helper template to create exceptions with complex messages
Definition errormacro.hh:80
msgstream.hh
cvdebug
CDebugSink & cvdebug()
Definition msgstream.hh:226
std
Definition gsl_iterator.hh:324
EAttributeType
Definition attributetype.hh:32
EAttributeType::attr_unknown
static const int attr_unknown
Definition attributetype.hh:33
attribute_type< CAttributeMap >::value
static const int value
Definition attributes.hh:225
attribute_type
Definition attributetype.hh:65
attribute_type::value
static const int value
Definition attributetype.hh:66