bioformats  5.1.3
MetadataMap.h
1 /*
2  * #%L
3  * OME-BIOFORMATS C++ library for image IO.
4  * Copyright © 2006 - 2015 Open Microscopy Environment:
5  * - Massachusetts Institute of Technology
6  * - National Institutes of Health
7  * - University of Dundee
8  * - Board of Regents of the University of Wisconsin-Madison
9  * - Glencoe Software, Inc.
10  * %%
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions are met:
13  *
14  * 1. Redistributions of source code must retain the above copyright notice,
15  * this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright notice,
17  * this list of conditions and the following disclaimer in the documentation
18  * and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  * The views and conclusions contained in the software and documentation are
33  * those of the authors and should not be interpreted as representing official
34  * policies, either expressed or implied, of any organization.
35  * #L%
36  */
37 
38 #ifndef OME_BIOFORMATS_METADATAMAP_H
39 #define OME_BIOFORMATS_METADATAMAP_H
40 
41 #include <algorithm>
42 #include <cmath>
43 #include <iomanip>
44 #include <map>
45 #include <ostream>
46 #include <sstream>
47 #include <string>
48 #include <vector>
49 
50 #include <ome/compat/cstdint.h>
51 #include <ome/common/variant.h>
52 
53 namespace ome
54 {
55  namespace bioformats
56  {
57 
80  {
81  private:
82  /*
83  * The following series of typedefs may appear a little
84  * complicated, and perhaps unnecessary, but they do have a
85  * purpose. They exist to work around pre-C++11 compiler
86  * limitations (lack of variadic templates), primarily a limit
87  * to the maximum number of types which may be used with
88  * boost::variant. To exceed this limit (minimum guaranteed is
89  * 10), boost::mpl sequences are used to define the variant
90  * types. These also have length limits, so the type list is
91  * built up by defining separate type sequences, then
92  * concatenating them, and transforming them to provide list
93  * variants. Note that none of this is code per se; it's all
94  * compile-time template expansion which evaluates to a list of
95  * permitted types.
96  */
97 
99  typedef boost::mpl::vector<std::string,
101 
103  typedef boost::mpl::vector<uint8_t,
104  uint16_t,
105  uint32_t,
106  uint64_t,
107  int8_t,
108  int16_t,
109  int32_t,
110  int64_t> integer_types;
111 
113  typedef boost::mpl::vector<float,
114  double,
115  long double> float_types;
116 
118  typedef boost::mpl::joint_view<integer_types,
119  float_types>::type numeric_types_view;
120 
122  typedef boost::mpl::joint_view<non_numeric_types,
123  numeric_types_view>::type basic_types_view;
124 
126  template<typename T>
127  struct make_vector
128  {
130  typedef std::vector<T> type;
131  };
132 
134  typedef boost::mpl::transform_view<basic_types_view, make_vector<boost::mpl::_1> >::type list_types_view;
135 
137  typedef boost::mpl::joint_view<basic_types_view, list_types_view> all_types_view;
138 
140  typedef boost::mpl::vector<> empty_types;
141 
143  typedef boost::mpl::insert_range<empty_types, boost::mpl::end<empty_types>::type, all_types_view>::type discriminated_types;
144 
145  public:
147  typedef std::string key_type;
148 
150  typedef boost::make_variant_over<discriminated_types>::type value_type;
151 
153  typedef std::map<key_type, value_type> map_type;
154 
156  typedef map_type::size_type size_type;
157 
159  typedef map_type::iterator iterator;
160 
162  typedef map_type::const_iterator const_iterator;
163 
165  typedef map_type::reverse_iterator reverse_iterator;
166 
168  typedef map_type::const_reverse_iterator const_reverse_iterator;
169 
170  private:
173 
174  public:
177  {}
178 
181  {}
182 
192  void
193  set(const key_type& key,
194  const value_type& value)
195  {
196  iterator i = find(key);
197  if (i != end())
198  erase(i);
199  map_type::value_type newvalue(key, value);
200  insert(newvalue);
201  }
202 
212  template <typename T>
213  void
214  set(const key_type& key,
215  const T& value)
216  {
217  value_type v = value;
218  set(key, v);
219  }
220 
231  template <typename T>
232  void
233  append(const key_type& key,
234  const T& value)
235  {
236  typedef typename std::vector<T> list_type;
237 
238  try
239  {
240  list_type& list(get<list_type>(key));
241  list.push_back(value);
242  }
243  catch (boost::bad_get& e)
244  {
245  list_type new_list;
246  new_list.push_back(value);
247  set(key, new_list);
248  }
249  }
250 
260  bool
261  get(const key_type& key,
262  value_type& value) const
263  {
264  const_iterator i = find(key);
265  if (i == end())
266  return false;
267 
268  value = i->second;
269  return true;
270  }
271 
283  template <typename T>
284  bool
285  get(const key_type& key,
286  T& value) const
287  {
288  try
289  {
290  value = get<T>(key);
291  return true;
292  }
293  catch (boost::bad_get& e)
294  {
295  return false;
296  }
297  }
298 
310  template <typename T>
311  T&
312  get(const key_type& key)
313  {
314  return boost::get<T>(get<value_type>(key));
315  }
316 
328  template <typename T>
329  const T&
330  get(const key_type& key) const
331  {
332  return boost::get<T>(get<value_type>(key));
333  }
334 
341  iterator
342  find(const key_type& key)
343  {
344  return discriminating_map.find(key);
345  }
346 
353  const_iterator
354  find(const key_type& key) const
355  {
356  return discriminating_map.find(key);
357  }
358 
372  std::pair<iterator, bool>
373  insert(map_type::value_type& value)
374  {
375  return discriminating_map.insert(value);
376  }
377 
383  void
384  erase(const key_type& key)
385  {
386  discriminating_map.erase(key);
387  }
388 
394  void
395  erase(iterator pos)
396  {
397  discriminating_map.erase(pos);
398  }
399 
400  private:
402  struct getkey
403  {
410  template <typename T>
411  typename T::first_type operator()(T pair) const
412  {
413  return pair.first;
414  }
415  };
416 
417  public:
427  std::vector<key_type>
428  keys() const
429  {
430  std::vector<key_type> ret;
431  std::transform(begin(), end(), std::back_inserter(ret), getkey());
432  std::sort(ret.begin(), ret.end());
433 
434  return ret;
435  }
436 
444  void
446  const std::string& prefix)
447  {
448  for (const_iterator i = map.begin();
449  i != map.end();
450  ++i)
451  {
452  map_type::value_type v(prefix + i->first, i->second);
453  insert(v);
454  }
455  }
456 
467  flatten() const;
468 
474  map_type&
475  map()
476  {
477  return discriminating_map;
478  }
479 
485  const map_type&
486  map() const
487  {
488  return discriminating_map;
489  }
490 
496  iterator
498  {
499  return discriminating_map.begin();
500  }
501 
507  const_iterator
508  begin() const
509  {
510  return discriminating_map.begin();
511  }
512 
518  iterator
519  end()
520  {
521  return discriminating_map.end();
522  }
523 
529  const_iterator
530  end() const
531  {
532  return discriminating_map.end();
533  }
534 
540  reverse_iterator
542  {
543  return discriminating_map.rbegin();
544  }
545 
551  const_reverse_iterator
552  rbegin() const
553  {
554  return discriminating_map.rbegin();
555  }
556 
562  reverse_iterator
564  {
565  return discriminating_map.rend();
566  }
567 
573  const_reverse_iterator
574  rend() const
575  {
576  return discriminating_map.rend();
577  }
578 
589  value_type&
590  operator[] (const key_type& key)
591  {
592  return discriminating_map[key];
593  }
594 
601  bool
602  operator == (const MetadataMap& rhs) const
603  {
604  return discriminating_map == rhs.discriminating_map;
605  }
606 
613  bool
614  operator != (const MetadataMap& rhs) const
615  {
616  return discriminating_map != rhs.discriminating_map;
617  }
618 
625  bool
626  operator < (const MetadataMap& rhs) const
627  {
628  return discriminating_map < rhs.discriminating_map;
629  }
630 
638  bool
639  operator <= (const MetadataMap& rhs) const
640  {
641  return discriminating_map <= rhs.discriminating_map;
642  }
643 
650  bool
651  operator > (const MetadataMap& rhs) const
652  {
653  return discriminating_map > rhs.discriminating_map;
654  }
655 
663  bool
664  operator >= (const MetadataMap& rhs) const
665  {
666  return discriminating_map >= rhs.discriminating_map;
667  }
668 
677  size_type
678  size() const
679  {
680  return discriminating_map.size();
681  }
682 
688  bool
689  empty() const
690  {
691  return discriminating_map.empty();
692  }
693 
699  void
701  {
702  return discriminating_map.clear();
703  }
704  };
705 
706  namespace detail
707  {
708 
712  struct MetadataMapValueTypeOStreamVisitor : public boost::static_visitor<>
713  {
715  std::ostream& os;
716 
723  os(os)
724  {}
725 
733  template <typename T>
734  void
735  operator() (const std::vector<T> & c) const
736  {
737  for (typename std::vector<T>::const_iterator i = c.begin();
738  i != c.end();
739  ++i)
740  {
741  os << *i;
742  if (i + 1 != c.end())
743  os << ", ";
744  }
745  }
746 
752  template <typename T>
753  void
754  operator() (const T& v) const
755  {
756  os << v;
757  }
758  };
759 
763  struct MetadataMapOStreamVisitor : public boost::static_visitor<>
764  {
766  std::ostream& os;
769 
776  MetadataMapOStreamVisitor(std::ostream& os,
777  const MetadataMap::key_type& key):
778  os(os),
779  key(key)
780  {}
781 
792  template <typename T>
793  void
794  operator() (const std::vector<T> & c) const
795  {
796  typename std::vector<T>::size_type idx = 1;
797  // Determine the optimal padding based on the maximum digit count.
798  int sf = static_cast<int>(std::log10(static_cast<float>(c.size()))) + 1;
799  for (typename std::vector<T>::const_iterator i = c.begin();
800  i != c.end();
801  ++i, ++idx)
802  {
803  os << key << " #" << std::setw(sf) << std::setfill('0') << std::right << idx << " = " << *i << '\n';
804  }
805  }
806 
815  template <typename T>
816  void
817  operator() (const T& v) const
818  {
819  os << key << " = " << v << '\n';
820  }
821  };
822 
826  struct MetadataMapFlattenVisitor : public boost::static_visitor<>
827  {
832 
840  const MetadataMap::key_type& key):
841  map(map),
842  key(key)
843  {}
844 
855  template <typename T>
856  void
857  operator() (const std::vector<T> & c) const
858  {
859  typename std::vector<T>::size_type idx = 1;
860  // Determine the optimal padding based on the maximum digit count.
861  int sf = static_cast<int>(std::log10(static_cast<float>(c.size()))) + 1;
862  for (typename std::vector<T>::const_iterator i = c.begin();
863  i != c.end();
864  ++i, ++idx)
865  {
866  std::ostringstream os;
867  os << key << " #" << std::setw(sf) << std::setfill('0') << std::right << idx;
868  map.set(os.str(), *i);
869  }
870  }
871 
880  template <typename T>
881  void
882  operator() (const T& v) const
883  {
884  map.set(key, v);
885  }
886  };
887 
888  }
889 
901  template<>
903  MetadataMap::get<MetadataMap::value_type>(const key_type& key)
904  {
905  map_type::iterator i = discriminating_map.find(key);
906  if (i == discriminating_map.end())
907  throw boost::bad_get();
908 
909  return i->second;
910  }
911 
923  template<>
924  inline const MetadataMap::value_type&
925  MetadataMap::get<MetadataMap::value_type>(const key_type& key) const
926  {
927  map_type::const_iterator i = discriminating_map.find(key);
928  if (i == discriminating_map.end())
929  throw boost::bad_get();
930 
931  return i->second;
932  }
933 
934  inline
935  MetadataMap
937  {
938  MetadataMap newmap;
940  i != discriminating_map.end();
941  ++i)
942  {
943  boost::apply_visitor(detail::MetadataMapFlattenVisitor(newmap, i->first), i->second);
944  }
945  return newmap;
946  }
947 
948  }
949 }
950 
951 namespace std
952 {
953 
961  template<class charT, class traits>
962  inline basic_ostream<charT,traits>&
963  operator<< (basic_ostream<charT,traits>& os,
964  const ::ome::bioformats::MetadataMap::value_type& vt)
965  {
966  boost::apply_visitor(::ome::bioformats::detail::MetadataMapValueTypeOStreamVisitor(os), vt);
967  return os;
968  }
969 
977  template<class charT, class traits>
978  inline basic_ostream<charT,traits>&
979  operator<< (basic_ostream<charT,traits>& os,
980  const ::ome::bioformats::MetadataMap& map)
981  {
982  for (::ome::bioformats::MetadataMap::const_iterator i = map.begin();
983  i != map.end();
984  ++i)
985  {
986  boost::apply_visitor(::ome::bioformats::detail::MetadataMapOStreamVisitor(os, i->first), i->second);
987  }
988  return os;
989  }
990 
991 }
992 
993 #endif // OME_BIOFORMATS_METADATAMAP_H
994 
995 /*
996  * Local Variables:
997  * mode:C++
998  * End:
999  */
const_reverse_iterator rbegin() const
Get a constant reverse iterator to the end of the map.
Definition: MetadataMap.h:552
boost::mpl::vector< float, double, long double > float_types
Storable floating-point types.
Definition: MetadataMap.h:115
map_type::const_iterator const_iterator
Constant iterator.
Definition: MetadataMap.h:162
bool operator!=(const MetadataMap &rhs) const
Compare maps for non-equality.
Definition: MetadataMap.h:614
void operator()(const std::vector< T > &c) const
Output a vector value of arbitrary type.
Definition: MetadataMap.h:735
map_type discriminating_map
Key-value mapping.
Definition: MetadataMap.h:172
Functor to get a map key.
Definition: MetadataMap.h:402
std::vector< T > type
The result type.
Definition: MetadataMap.h:130
boost::mpl::transform_view< basic_types_view, make_vector< boost::mpl::_1 > >::type list_types_view
Aggregate view of all storable list types.
Definition: MetadataMap.h:134
std::vector< key_type > keys() const
Get a list of keys in the map.
Definition: MetadataMap.h:428
map_type::size_type size_type
Size type.
Definition: MetadataMap.h:156
Visitor template for output of MetadataMap values to an ostream.
Definition: MetadataMap.h:763
Metadata key-value map using a restricted set of value types.
Definition: MetadataMap.h:79
MetadataMap & map
The map in which to set the flattened elements.
Definition: MetadataMap.h:829
const_iterator find(const key_type &key) const
Find a key in the map.
Definition: MetadataMap.h:354
map_type::reverse_iterator reverse_iterator
Reverse iterator.
Definition: MetadataMap.h:165
STL namespace.
MetadataMap()
Constructor.
Definition: MetadataMap.h:176
T::first_type operator()(T pair) const
Get key from pair.
Definition: MetadataMap.h:411
boost::mpl::vector< uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t > integer_types
Storable integer types.
Definition: MetadataMap.h:110
map_type & map()
Get the underlying map.
Definition: MetadataMap.h:475
const MetadataMap::key_type & key
The key of the value being flattened.
Definition: MetadataMap.h:831
bool operator>=(const MetadataMap &rhs) const
Check if map is greater than or equal to another map.
Definition: MetadataMap.h:664
value_type & operator[](const key_type &key)
Get or set a value by key index.
Definition: MetadataMap.h:590
size_type size() const
Get the size of the map.
Definition: MetadataMap.h:678
iterator begin()
Get an iterator to the beginning of the map.
Definition: MetadataMap.h:497
void append(const key_type &key, const T &value)
Append a value to a vector.
Definition: MetadataMap.h:233
const_reverse_iterator rend() const
Get a constant reverse iterator to the beginning of the map.
Definition: MetadataMap.h:574
MetadataMapOStreamVisitor(std::ostream &os, const MetadataMap::key_type &key)
Constructor.
Definition: MetadataMap.h:776
std::pair< iterator, bool > insert(map_type::value_type &value)
Insert a value into the map.
Definition: MetadataMap.h:373
void merge(const MetadataMap &map, const std::string &prefix)
Merge a separate map into this map.
Definition: MetadataMap.h:445
boost::make_variant_over< discriminated_types >::type value_type
Value type, allowing assignment of all storable types.
Definition: MetadataMap.h:150
Variant type limit workaround.
boost::mpl::joint_view< non_numeric_types, numeric_types_view >::type basic_types_view
Aggregate view of all storable simple types.
Definition: MetadataMap.h:123
Convert T into a std::vector.
Definition: MetadataMap.h:127
Open Microscopy Environment C++ implementation.
Definition: CoreMetadata.cpp:40
std::string key_type
Key type.
Definition: MetadataMap.h:147
const map_type & map() const
Get the underlying map.
Definition: MetadataMap.h:486
void operator()(const std::vector< T > &c) const
Output a vector value of arbitrary type.
Definition: MetadataMap.h:794
boost::mpl::joint_view< integer_types, float_types >::type numeric_types_view
Aggregate view of all numeric types.
Definition: MetadataMap.h:119
const_iterator end() const
Get a constant iterator to the end of the map.
Definition: MetadataMap.h:530
bool operator<=(const MetadataMap &rhs) const
Check if map is less than or equal to another map.
Definition: MetadataMap.h:639
boost::mpl::joint_view< basic_types_view, list_types_view > all_types_view
Aggregate view of all storable types.
Definition: MetadataMap.h:137
bool operator<(const MetadataMap &rhs) const
Check if map is less than another map.
Definition: MetadataMap.h:626
reverse_iterator rend()
Get a reverse iterator to the beginning of the map.
Definition: MetadataMap.h:563
MetadataMap flatten() const
Create a flattened map.
Definition: MetadataMap.h:936
void erase(const key_type &key)
Erase a key from the map by name.
Definition: MetadataMap.h:384
bool empty() const
Check if the map is empty.
Definition: MetadataMap.h:689
boost::mpl::insert_range< empty_types, boost::mpl::end< empty_types >::type, all_types_view >::type discriminated_types
List of discriminated types used by boost::variant.
Definition: MetadataMap.h:143
Visitor template for output of MetadataMap values to an ostream.
Definition: MetadataMap.h:712
void erase(iterator pos)
Erase a key from the map by an iterator position.
Definition: MetadataMap.h:395
map_type::const_reverse_iterator const_reverse_iterator
Constant reverse iterator.
Definition: MetadataMap.h:168
iterator find(const key_type &key)
Find a key in the map.
Definition: MetadataMap.h:342
iterator end()
Get an iterator to the end of the map.
Definition: MetadataMap.h:519
map_type::iterator iterator
Iterator.
Definition: MetadataMap.h:159
const MetadataMap::key_type & key
The key of the value being output.
Definition: MetadataMap.h:768
Standard integer types.
MetadataMapValueTypeOStreamVisitor(std::ostream &os)
Constructor.
Definition: MetadataMap.h:722
const_iterator begin() const
Get a constant iterator to the beginning of the map.
Definition: MetadataMap.h:508
~MetadataMap()
Destructor.
Definition: MetadataMap.h:180
reverse_iterator rbegin()
Get a reverse iterator to the end of the map.
Definition: MetadataMap.h:541
Visitor template for flattening of MetadataMap vector values.
Definition: MetadataMap.h:826
bool operator>(const MetadataMap &rhs) const
Check if map is greater than another map.
Definition: MetadataMap.h:651
MetadataMapFlattenVisitor(MetadataMap &map, const MetadataMap::key_type &key)
Constructor.
Definition: MetadataMap.h:839
boost::mpl::vector< std::string, bool > non_numeric_types
Storable non-numeric types.
Definition: MetadataMap.h:100
void clear()
Clear the map.
Definition: MetadataMap.h:700
void set(const key_type &key, const value_type &value)
Add a key-value pair to the map.
Definition: MetadataMap.h:193
std::ostream & os
The stream to output to.
Definition: MetadataMap.h:766
boost::mpl::vector empty_types
Empty vector placeholder.
Definition: MetadataMap.h:140
void set(const key_type &key, const T &value)
Add a key-value pair to the map.
Definition: MetadataMap.h:214
std::ostream & os
The stream to output to.
Definition: MetadataMap.h:715
void operator()(const std::vector< T > &c) const
Output a vector value of arbitrary type.
Definition: MetadataMap.h:857
std::map< key_type, value_type > map_type
std::string to discriminated type mapping.
Definition: MetadataMap.h:153
bool operator==(const MetadataMap &rhs) const
Compare maps for equality.
Definition: MetadataMap.h:602