My Project
attributes.hh
Go to the documentation of this file.
1 /* -*- mia-c++ -*-
2  *
3  * This file is part of MIA - a toolbox for medical image analysis
4  * Copyright (c) Leipzig, Madrid 1999-2017 Gert Wollny
5  *
6  * MIA is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with MIA; if not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #ifndef mia_core_attributes_hh
22 #define mia_core_attributes_hh
23 
24 #include <mia/core/msgstream.hh>
25 #include <mia/core/errormacro.hh>
26 #include <map>
27 #include <memory>
28 #include <string>
29 #include <cstring>
30 #include <vector>
31 #include <iostream>
32 #include <sstream>
33 #include <stdexcept>
34 #include <type_traits>
35 #include <iomanip>
36 #include <boost/any.hpp>
37 #include <boost/ref.hpp>
38 #include <boost/lexical_cast.hpp>
40 
42 
52 {
53 public:
55  virtual ~CAttribute();
56 
58  std::string as_string() const;
59 
64  bool is_equal(const CAttribute& other) const;
65 
72  bool is_less(const CAttribute& other) const;
73 
75  virtual const char *typedescr() const = 0;
76 
78  virtual int type_id() const = 0;
79 private:
80  virtual std::string do_as_string() const = 0;
81 
82  virtual bool do_is_equal(const CAttribute& other) const = 0;
83 
84  virtual bool do_is_less(const CAttribute& other) const = 0;
85 };
86 
87 
88 inline
89 std::ostream& operator << (std::ostream& os, const CAttribute& attr)
90 {
91  os << attr.as_string();
92  return os;
93 };
94 
95 inline bool operator == (const CAttribute& a, const CAttribute& b)
96 {
97  return a.is_equal(b);
98 }
99 
100 
102 typedef std::shared_ptr<CAttribute > PAttribute;
103 
117 template <typename T>
119 {
120 public:
122 
123 
127  TAttribute(typename ::boost::reference_wrapper<T>::type value);
129 
130 
135  operator T()const;
136 
138  virtual const char *typedescr() const;
139 
140  virtual int type_id() const;
141 protected:
143  const T& get_value() const;
144 private:
145  virtual std::string do_as_string() const;
146  virtual bool do_is_equal(const CAttribute& other) const;
147  virtual bool do_is_less(const CAttribute& other) const;
148 
149  T m_value;
150 };
151 
161 template <typename T>
163 {
164  const TAttribute<T>& a = dynamic_cast<const TAttribute<T>&>(attr);
165  return a;
166 }
167 
173 
179 
185 
191 
197 
203 
204 
210 
216 
221 typedef std::map<std::string, PAttribute> CAttributeMap;
222 
223 template <>
225  static const int value = 1000;
226 };
227 
228 
234 
239 typedef std::shared_ptr<CAttributeMap > PAttributeMap;
240 
241 
249 EXPORT_CORE std::ostream& operator << (std::ostream& os, const CAttributeMap& data);
250 
251 
260 {
261 public:
262 
264 
265 
268 
274 
276 
278  CAttributedData& operator =(const CAttributedData& org);
279 
284  const PAttribute get_attribute(const std::string& key) const;
285 
289  CAttributeMap::const_iterator begin_attributes() const;
290 
294  CAttributeMap::const_iterator end_attributes() const;
295 
302  void set_attribute(const std::string& key, PAttribute attr);
303 
304 
310  void set_attributes(CAttributeMap::const_iterator begin, CAttributeMap::const_iterator end);
311 
317  void set_attribute(const std::string& key, const std::string& value);
318 
319 
326  template <typename T>
327  void set_attribute(const std::string& key, const T& value);
328 
334  void set_attribute(const std::string& key, const char *value);
335 
336 
338  const std::string get_attribute_as_string(const std::string& key)const;
339 
340 
348  template <typename T>
349  const T get_attribute_as(const std::string& key)const;
350 
359  template <typename T>
360  const T get_attribute_as(const std::string& key, T default_value)const;
361 
367  void delete_attribute(const std::string& key);
368 
374  bool has_attribute(const std::string& key)const;
375 
377  friend EXPORT_CORE bool operator == (const CAttributedData& a, const CAttributedData& b);
379 
380  void print(std::ostream& os) const
381  {
382  os << *m_attr;
383  }
384 private:
385  PAttributeMap m_attr;
386 };
387 
388 
389 inline std::ostream& operator << (std::ostream& os, const CAttributedData& data)
390 {
391  data.print(os);
392  return os;
393 }
394 
395 
396 
406 
407 
416 {
417 public:
419  virtual ~CAttrTranslator() {};
420 
425  PAttribute from_string(const std::string& value) const;
426 private:
427  virtual PAttribute do_from_string(const std::string& value) const = 0;
428 protected:
430 
435  bool do_register(const std::string& key);
436 };
437 
447 {
448 public:
456  PAttribute to_attr(const std::string& key, const std::string& value) const;
457 
460 private:
461  friend class CAttrTranslator;
470  bool add(const std::string& key, CAttrTranslator *t);
471 
472  typedef std::map<std::string, std::shared_ptr<CAttrTranslator>> CMap;
473  CMap m_translators;
474 };
475 
476 
488 template <typename T>
489 void EXPORT_CORE add_attribute(CAttributeMap& attributes, const std::string& key, T value)
490 {
491  cvdebug() << "add attribute " << key << " of type " << typeid(T).name() << " and value '" << value << "'\n";
492  attributes[key] = PAttribute(new TAttribute<T>(value));
493 }
494 
495 template <>
496 inline void EXPORT_CORE add_attribute(CAttributeMap& attributes, const std::string& key, const char *value)
497 {
498  attributes[key] = CStringAttrTranslatorMap::instance().to_attr(key, value);
499  cvdebug() << "add_attribute '" << key
500  << "' to '" << value << "' of type '"
501  << attributes[key]->typedescr() << "'\n";
502 }
503 
504 
505 
516 template <typename T>
518 {
519 public:
526  static bool register_for(const std::string& key);
527 private:
528  virtual PAttribute do_from_string(const std::string& value) const;
529 };
530 
531 
532 // template implementation
533 
534 template <typename T>
535 TAttribute<T>::TAttribute(typename ::boost::reference_wrapper<T>::type value):
536  m_value(value)
537 {
538 }
539 
540 template <typename T>
542 {
543  return m_value;
544 }
545 
546 template <typename T>
547 const T& TAttribute<T>::get_value() const
548 {
549  return m_value;
550 }
551 
552 template <typename T>
553 const char *TAttribute<T>::typedescr() const
554 {
555  return typeid(T).name();
556 }
557 
558 template <typename T>
560 {
562  "You must provide a type specialization for attribute_type<T>");
564 }
565 
574 template <typename T, bool is_floating>
575 struct __convert_to_string {
576  static std::string apply(const typename ::boost::reference_wrapper<T>::type value)
577  {
578  return boost::lexical_cast<std::string>(value);
579  }
580 };
581 
582 template <typename T>
583 struct __convert_to_string<T, true> {
584  static std::string apply(const typename ::boost::reference_wrapper<T>::type value)
585  {
586  std::stringstream sval;
587  sval << std::setprecision(10) << value;
588  return sval.str();
589  }
590 };
591 
592 
593 template <typename T>
594 struct dispatch_attr_string {
595  static std::string val2string(const typename ::boost::reference_wrapper<T>::type value)
596  {
597  return __convert_to_string<T, std::is_floating_point<T>::value>::apply(value);
598  }
599  static T string2val(const std::string& str)
600  {
601  T v;
602  std::istringstream svalue(str);
603  svalue >> v;
604  return v;
605  }
606 };
607 
608 
609 template <typename T>
610 struct dispatch_attr_string<std::vector<T>> {
611  static std::string val2string(const std::vector<T>& value)
612  {
613  std::stringstream sval;
614  sval << value.size();
615 
616  for (size_t i = 0; i < value.size(); ++i)
617  sval << " "
618  << __convert_to_string<T, std::is_floating_point<T>::value>::apply(value[i]);
619 
620  return sval.str();
621  }
622  static std::vector<T> string2val(const std::string& str)
623  {
624  size_t s;
625  std::istringstream svalue(str);
626  std::vector<T> v;
627  svalue >> s;
628 
629  if (s > v.max_size())
630  throw create_exception<std::runtime_error>("string2val: try to create a vector of size ",
631  s, " but support only size ", v.max_size());
632 
633  v.resize(s);
634 
635  for (size_t i = 0; i < s; ++i)
636  svalue >> v[i];
637 
638  if (svalue.fail()) {
639  std::stringstream msg;
640  msg << "string2val: unable to convert '" << str << "'";
641  throw std::invalid_argument(msg.str());
642  }
643 
644  return v;
645  }
646 };
647 
648 
649 template <>
650 struct dispatch_attr_string<std::vector<bool>> {
651  static std::string val2string(const std::vector<bool>& value)
652  {
653  std::stringstream sval;
654  sval << value.size();
655 
656  for (size_t i = 0; i < value.size(); ++i)
657  sval << " " << value[i];
658 
659  return sval.str();
660  }
661  static std::vector<bool> string2val(const std::string& str)
662  {
663  size_t s;
664  std::istringstream svalue(str);
665  svalue >> s;
666  std::vector<bool> v(s);
667 
668  // Added override for coverity
669  //
670  // Since s is used as the size for the new vector, a large
671  // value will result in a std::bad_alloc exception. This
672  // is not worse than bailing out because s is larger than
673  // an abitrary set boundary that youle be cheked here.
674  //
675  // coverity[tainted_scalar]
676  for (size_t i = 0; i < s; ++i) {
677  bool value;
678  svalue >> value;
679  v[i] = value;
680  }
681 
682  if (svalue.fail()) {
683  std::stringstream msg;
684  msg << "string2val: unable to convert '" << str << "'";
685  throw std::invalid_argument(msg.str());
686  }
687 
688  return v;
689  }
690 };
691 
692 template <>
693 struct dispatch_attr_string<unsigned char> {
694  static std::string val2string(unsigned char value)
695  {
696  std::stringstream sval;
697  sval << (unsigned int)value;
698  return sval.str();
699  }
700  static unsigned char string2val(const std::string& str)
701  {
702  unsigned int v;
703  std::istringstream svalue(str);
704  svalue >> v;
705  return (unsigned char)v;
706  }
707 };
708 
709 template <>
710 struct dispatch_attr_string<signed char> {
711  static std::string val2string(signed char value)
712  {
713  std::stringstream sval;
714  sval << (signed int)value;
715  return sval.str();
716  }
717  static signed char string2val(const std::string& str)
718  {
719  int v;
720  std::istringstream svalue(str);
721  svalue >> v;
722  return (signed char)v;
723  }
724 };
725 
726 template <>
727 struct dispatch_attr_string<std::string> {
728  static std::string val2string(std::string value)
729  {
730  return value;
731  }
732  static std::string string2val(const std::string& str)
733  {
734  return str;
735  }
736 };
737 
738 template <>
739 struct dispatch_attr_string<CAttributeMap> {
740  static std::string val2string(const CAttributeMap& /*value*/)
741  {
742  throw std::invalid_argument("Conversion of a CAttributeMap to a string not implemented");
743  }
744  static CAttributeMap string2val(const std::string& /*str*/)
745  {
746  throw std::invalid_argument("Conversion of a string to a CAttributeMap not implemented");
747  }
748 };
749 
751 
752 template <typename T>
753 void CAttributedData::set_attribute(const std::string& key, const T& value)
754 {
755  add_attribute(*m_attr, key, value);
756 }
757 
758 
759 template <typename T>
760 std::string TAttribute<T>::do_as_string() const
761 {
762  return dispatch_attr_string<T>::val2string(m_value);
763 }
764 
765 template <typename T>
766 bool TAttribute<T>::do_is_equal(const CAttribute& other) const
767 {
768  const TAttribute<T> *o = dynamic_cast<const TAttribute<T> *>(&other);
769 
770  if (!o) {
771  cvdebug() << "TAttribute<T>::do_is_equal:Cast to "
772  << typeid(const TAttribute<T> *).name()
773  << "failed\n";
774  return false;
775  }
776 
777  return m_value == o->m_value;
778 }
779 
780 template <typename T>
781 bool TAttribute<T>::do_is_less(const CAttribute& other) const
782 {
783  const TAttribute<T> *o = dynamic_cast<const TAttribute<T> *>(&other);
784 
785  if (o)
786  return m_value < o->m_value;
787 
788  return strcmp(typedescr(), other.typedescr()) < 0;
789 }
790 
791 template <typename T>
792 const T CAttributedData::get_attribute_as(const std::string& key)const
793 {
794  PAttribute attr = get_attribute(key);
795 
796  if (attr)
797  return dynamic_cast<const TAttribute<T>&>(*attr);
798  else
799  throw create_exception<std::invalid_argument>("CAttributedData: no attribute '", key, "' found");
800 }
801 
802 template <typename T>
803 const T CAttributedData::get_attribute_as(const std::string& key, T default_value)const
804 {
805  PAttribute pattr = get_attribute(key);
806 
807  if (!pattr)
808  return default_value;
809 
810  auto attr = dynamic_cast<const TAttribute<T> *>(pattr.get());
811 
812  if (!attr) {
813  cvwarn() << "Attribute '" << key << "'exists but is not of the expected type, returning default\n";
814  return default_value;
815  }
816 
817  return *attr;
818 }
819 
820 
822 extern template class EXPORT_CORE TAttribute<uint8_t>;
823 extern template class EXPORT_CORE TAttribute<int8_t>;
824 
825 extern template class EXPORT_CORE TAttribute<std::vector<uint8_t>>;
826 extern template class EXPORT_CORE TAttribute<std::vector<int8_t>>;
828 
831 
834 
837 
840 
843 
846 
849 
852 
855 
858 
861 
863 
864 #endif
TTranslator< int64_t > CSLTranslator
Definition: attributes.hh:838
TTranslator< bool > CBitTranslator
Definition: attributes.hh:859
std::ostream & operator<<(std::ostream &os, const CAttribute &attr)
Definition: attributes.hh:89
TTranslator< uint64_t > CULTranslator
Definition: attributes.hh:835
TTranslator< std::vector< uint16_t > > CVUSTranslator
Definition: attributes.hh:848
TTranslator< std::vector< int64_t > > CVSLTranslator
Definition: attributes.hh:839
TTranslator< uint8_t > CUBTranslator
Definition: attributes.hh:853
TTranslator< int8_t > CSBTranslator
Definition: attributes.hh:856
TTranslator< signed int > CSITranslator
Definition: attributes.hh:844
TTranslator< std::vector< int8_t > > CVSBTranslator
Definition: attributes.hh:857
TTranslator< std::vector< double > > CVDoubleTranslator
Definition: attributes.hh:830
NEVER typedef TTranslator< double > CDoubleTranslator
*‍/
Definition: attributes.hh:829
TTranslator< std::vector< uint8_t > > CVUBTranslator
Definition: attributes.hh:854
TTranslator< uint16_t > CUSTranslator
Definition: attributes.hh:847
std::shared_ptr< CAttribute > PAttribute
define the shared pointer wrapped attribute pointer
Definition: attributes.hh:102
TTranslator< std::vector< int32_t > > CVSITranslator
Definition: attributes.hh:845
bool operator==(const CAttribute &a, const CAttribute &b)
Definition: attributes.hh:95
TTranslator< std::vector< bool > > CVBitTranslator
Definition: attributes.hh:860
TTranslator< std::vector< uint32_t > > CVUITranslator
Definition: attributes.hh:842
TTranslator< std::vector< int16_t > > CVSSTranslator
Definition: attributes.hh:851
TTranslator< unsigned int > CUITranslator
Definition: attributes.hh:841
TTranslator< std::vector< float > > CVFloatTranslator
Definition: attributes.hh:833
TTranslator< float > CFloatTranslator
Definition: attributes.hh:832
TTranslator< int16_t > CSSTranslator
Definition: attributes.hh:850
TTranslator< std::vector< uint64_t > > CVULTranslator
Definition: attributes.hh:836
A class to translate an attribute from a string.
Definition: attributes.hh:416
PAttribute from_string(const std::string &value) const
bool do_register(const std::string &key)
virtual ~CAttrTranslator()
The virtual destructor just ensures virtual destruction and silences a warning.
Definition: attributes.hh:419
The class of all attributes of data that is considered to ve meta-data.
Definition: attributes.hh:52
bool is_less(const CAttribute &other) const
bool is_equal(const CAttribute &other) const
virtual int type_id() const =0
std::string as_string() const
returns the value as a atring
virtual ~CAttribute()
virtual destructor since derived classes may define dynamic objetcs
virtual const char * typedescr() const =0
A collection of attributes.
Definition: attributes.hh:260
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
bool has_attribute(const std::string &key) const
CAttributedData(PAttributeMap attr)
void set_attribute(const std::string &key, PAttribute attr)
void set_attribute(const std::string &key, const std::string &value)
void delete_attribute(const std::string &key)
void set_attribute(const std::string &key, const char *value)
CAttributeMap::const_iterator begin_attributes() const
CAttributedData(const CAttributedData &org)
const PAttribute get_attribute(const std::string &key) const
const T get_attribute_as(const std::string &key) const
Definition: attributes.hh:792
CAttributeMap::const_iterator end_attributes() const
void set_attributes(CAttributeMap::const_iterator begin, CAttributeMap::const_iterator end)
void print(std::ostream &os) const
Definition: attributes.hh:380
A singelton class to translate strings to attributes based on keys.
Definition: attributes.hh:447
static CStringAttrTranslatorMap & instance()
PAttribute to_attr(const std::string &key, const std::string &value) const
Class of an attribute that holds data of type T.
Definition: attributes.hh:119
TAttribute(typename ::boost::reference_wrapper< T >::type value)
Definition: attributes.hh:535
virtual const char * typedescr() const
Definition: attributes.hh:553
const T & get_value() const
Definition: attributes.hh:547
virtual int type_id() const
Definition: attributes.hh:559
Generic string vs. attribute translator singleton.
Definition: attributes.hh:518
static bool register_for(const std::string &key)
#define NS_MIA_BEGIN
conveniance define to start the mia namespace
Definition: defines.hh:33
#define EXPORT_CORE
Macro to manage Visual C++ style dllimport/dllexport.
Definition: defines.hh:101
#define NS_MIA_END
conveniance define to end the mia namespace
Definition: defines.hh:36
void EXPORT_CORE add_attribute(CAttributeMap &attributes, const std::string &key, T value)
Definition: attributes.hh:489
std::map< std::string, PAttribute > CAttributeMap
A name:attribute map.
Definition: attributes.hh:221
TAttribute< double > CDoubleAttribute
a double attribute
Definition: attributes.hh:196
TAttribute< std::vector< std::string > > CVStringAttribute
a vector of strings attribute
Definition: attributes.hh:215
std::shared_ptr< CAttributeMap > PAttributeMap
another pointer-usage easy maker
Definition: attributes.hh:239
TAttribute< int > CIntAttribute
an integer attribute
Definition: attributes.hh:172
TAttribute< std::vector< float > > CVFloatAttribute
Definition: attributes.hh:190
TAttribute< std::vector< double > > CVDoubleAttribute
a vector of doubles attribute
Definition: attributes.hh:202
TAttribute< float > CFloatAttribute
a float attribute
Definition: attributes.hh:184
TAttribute< std::string > CStringAttribute
a string attribute
Definition: attributes.hh:209
T EXPORT_CORE get_attribute_as(const CAttribute &attr)
Definition: attributes.hh:162
TAttribute< std::vector< int > > CVIntAttribute
a vector of integers attribute
Definition: attributes.hh:178
TAttribute< CAttributeMap > CAttributeList
providing the possibility to nest attribute lists
Definition: attributes.hh:233
vstream & cvwarn()
send warnings to this stream adapter
Definition: msgstream.hh:321
CDebugSink & cvdebug()
Definition: msgstream.hh:226
static const int attr_unknown
static const int value