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>
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{
53public:
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;
79private:
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
88inline
89std::ostream& operator << (std::ostream& os, const CAttribute& attr)
90{
91 os << attr.as_string();
92 return os;
93};
94
95inline bool operator == (const CAttribute& a, const CAttribute& b)
96{
97 return a.is_equal(b);
98}
99
100
102typedef std::shared_ptr<CAttribute > PAttribute;
103
117template <typename T>
119{
120public:
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;
141protected:
143 const T& get_value() const;
144private:
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
161template <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
221typedef std::map<std::string, PAttribute> CAttributeMap;
222
223template <>
225 static const int value = 1000;
226};
227
228
234
239typedef std::shared_ptr<CAttributeMap > PAttributeMap;
240
241
249EXPORT_CORE std::ostream& operator << (std::ostream& os, const CAttributeMap& data);
250
251
260{
261public:
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 }
384private:
385 PAttributeMap m_attr;
386};
387
388
389inline std::ostream& operator << (std::ostream& os, const CAttributedData& data)
390{
391 data.print(os);
392 return os;
393}
394
395
396
406
407
416{
417public:
419 virtual ~CAttrTranslator() {};
420
425 PAttribute from_string(const std::string& value) const;
426private:
427 virtual PAttribute do_from_string(const std::string& value) const = 0;
428protected:
430
435 bool do_register(const std::string& key);
436};
437
447{
448public:
456 PAttribute to_attr(const std::string& key, const std::string& value) const;
457
460private:
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
488template <typename T>
489void 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
495template <>
496inline 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
516template <typename T>
518{
519public:
526 static bool register_for(const std::string& key);
527private:
528 virtual PAttribute do_from_string(const std::string& value) const;
529};
530
531
532// template implementation
533
534template <typename T>
535TAttribute<T>::TAttribute(typename ::boost::reference_wrapper<T>::type value):
536 m_value(value)
537{
538}
539
540template <typename T>
542{
543 return m_value;
544}
545
546template <typename T>
548{
549 return m_value;
550}
551
552template <typename T>
553const char *TAttribute<T>::typedescr() const
554{
555 return typeid(T).name();
556}
557
558template <typename T>
560{
562 "You must provide a type specialization for attribute_type<T>");
564}
565
574template <typename T, bool is_floating>
575struct __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
582template <typename T>
583struct __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
593template <typename T>
594struct 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
609template <typename T>
610struct 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
649template <>
650struct 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
692template <>
693struct 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
709template <>
710struct 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
726template <>
727struct 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
738template <>
739struct 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
752template <typename T>
753void CAttributedData::set_attribute(const std::string& key, const T& value)
754{
755 add_attribute(*m_attr, key, value);
756}
757
758
759template <typename T>
760std::string TAttribute<T>::do_as_string() const
761{
762 return dispatch_attr_string<T>::val2string(m_value);
763}
764
765template <typename T>
766bool 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
780template <typename T>
781bool 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
791template <typename T>
792const 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
802template <typename T>
803const 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
822extern template class EXPORT_CORE TAttribute<uint8_t>;
823extern template class EXPORT_CORE TAttribute<int8_t>;
824
825extern template class EXPORT_CORE TAttribute<std::vector<uint8_t>>;
826extern 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
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
std::ostream & operator<<(std::ostream &os, const CAttribute &attr)
Definition: attributes.hh:89
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