ome-files 0.2.2

MetadataMap.h
1 /*
2 * #%L
3 * OME-FILES 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_FILES_METADATAMAP_H
39 #define OME_FILES_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 files
56 {
57
79 class MetadataMap
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,
100 bool> non_numeric_types;
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::insert_range<boost::mpl::vector0<>, boost::mpl::end<boost::mpl::vector0<> >::type, all_types_view>::type discriminated_types;
141
142 public:
144 typedef std::string key_type;
145
147 typedef boost::make_variant_over<discriminated_types>::type value_type;
148
150 typedef std::map<key_type, value_type> map_type;
151
153 typedef map_type::size_type size_type;
154
156 typedef map_type::iterator iterator;
157
159 typedef map_type::const_iterator const_iterator;
160
162 typedef map_type::reverse_iterator reverse_iterator;
163
165 typedef map_type::const_reverse_iterator const_reverse_iterator;
166
167 private:
169 map_type discriminating_map;
170
171 public:
173 MetadataMap()
174 {}
175
177 ~MetadataMap()
178 {}
179
189 void
190 set(const key_type& key,
191 const value_type& value)
192 {
193 iterator i = find(key);
194 if (i != end())
195 erase(i);
196 map_type::value_type newvalue(key, value);
197 insert(newvalue);
198 }
199
209 template <typename T>
210 void
211 set(const key_type& key,
212 const T& value)
213 {
214 value_type v = value;
215 set(key, v);
216 }
217
228 template <typename T>
229 void
230 append(const key_type& key,
231 const T& value)
232 {
233 typedef typename std::vector<T> list_type;
234
235 try
236 {
237 list_type& list(get<list_type>(key));
238 list.push_back(value);
239 }
240 catch (const boost::bad_get&)
241 {
242 list_type new_list;
243 new_list.push_back(value);
244 set(key, new_list);
245 }
246 }
247
257 bool
258 get(const key_type& key,
259 value_type& value) const
260 {
261 const_iterator i = find(key);
262 if (i == end())
263 return false;
264
265 value = i->second;
266 return true;
267 }
268
280 template <typename T>
281 bool
282 get(const key_type& key,
283 T& value) const
284 {
285 try
286 {
287 value = get<T>(key);
288 return true;
289 }
290 catch (const boost::bad_get&)
291 {
292 return false;
293 }
294 }
295
307 template <typename T>
308 T&
309 get(const key_type& key)
310 {
311 return boost::get<T>(get<value_type>(key));
312 }
313
325 template <typename T>
326 const T&
327 get(const key_type& key) const
328 {
329 return boost::get<T>(get<value_type>(key));
330 }
331
338 iterator
339 find(const key_type& key)
340 {
341 return discriminating_map.find(key);
342 }
343
350 const_iterator
351 find(const key_type& key) const
352 {
353 return discriminating_map.find(key);
354 }
355
369 std::pair<iterator, bool>
370 insert(map_type::value_type& value)
371 {
372 return discriminating_map.insert(value);
373 }
374
380 void
381 erase(const key_type& key)
382 {
383 discriminating_map.erase(key);
384 }
385
391 void
392 erase(iterator pos)
393 {
394 discriminating_map.erase(pos);
395 }
396
397 private:
399 struct getkey
400 {
407 template <typename T>
408 typename T::first_type operator()(T pair) const
409 {
410 return pair.first;
411 }
412 };
413
414 public:
424 std::vector<key_type>
425 keys() const
426 {
427 std::vector<key_type> ret;
428 std::transform(begin(), end(), std::back_inserter(ret), getkey());
429 std::sort(ret.begin(), ret.end());
430
431 return ret;
432 }
433
441 void
442 merge(const MetadataMap& map,
443 const std::string& prefix)
444 {
445 for (const_iterator i = map.begin();
446 i != map.end();
447 ++i)
448 {
449 map_type::value_type v(prefix + i->first, i->second);
450 insert(v);
451 }
452 }
453
463 MetadataMap
464 flatten() const;
465
471 map_type&
472 map()
473 {
474 return discriminating_map;
475 }
476
482 const map_type&
483 map() const
484 {
485 return discriminating_map;
486 }
487
493 iterator
494 begin()
495 {
496 return discriminating_map.begin();
497 }
498
504 const_iterator
505 begin() const
506 {
507 return discriminating_map.begin();
508 }
509
515 iterator
516 end()
517 {
518 return discriminating_map.end();
519 }
520
526 const_iterator
527 end() const
528 {
529 return discriminating_map.end();
530 }
531
537 reverse_iterator
538 rbegin()
539 {
540 return discriminating_map.rbegin();
541 }
542
548 const_reverse_iterator
549 rbegin() const
550 {
551 return discriminating_map.rbegin();
552 }
553
559 reverse_iterator
560 rend()
561 {
562 return discriminating_map.rend();
563 }
564
570 const_reverse_iterator
571 rend() const
572 {
573 return discriminating_map.rend();
574 }
575
586 value_type&
587 operator[] (const key_type& key)
588 {
589 return discriminating_map[key];
590 }
591
598 bool
599 operator == (const MetadataMap& rhs) const
600 {
601 return discriminating_map == rhs.discriminating_map;
602 }
603
610 bool
611 operator != (const MetadataMap& rhs) const
612 {
613 return discriminating_map != rhs.discriminating_map;
614 }
615
622 bool
623 operator < (const MetadataMap& rhs) const
624 {
625 return discriminating_map < rhs.discriminating_map;
626 }
627
635 bool
636 operator <= (const MetadataMap& rhs) const
637 {
638 return discriminating_map <= rhs.discriminating_map;
639 }
640
647 bool
648 operator > (const MetadataMap& rhs) const
649 {
650 return discriminating_map > rhs.discriminating_map;
651 }
652
660 bool
661 operator >= (const MetadataMap& rhs) const
662 {
663 return discriminating_map >= rhs.discriminating_map;
664 }
665
674 size_type
675 size() const
676 {
677 return discriminating_map.size();
678 }
679
685 bool
686 empty() const
687 {
688 return discriminating_map.empty();
689 }
690
696 void
697 clear()
698 {
699 return discriminating_map.clear();
700 }
701 };
702
703 namespace detail
704 {
705
709 struct MetadataMapValueTypeOStreamVisitor : public boost::static_visitor<>
710 {
712 std::ostream& os;
713
719 MetadataMapValueTypeOStreamVisitor(std::ostream& os):
720 os(os)
721 {}
722
730 template <typename T>
731 void
732 operator() (const std::vector<T> & c) const
733 {
734 for (typename std::vector<T>::const_iterator i = c.begin();
735 i != c.end();
736 ++i)
737 {
738 os << *i;
739 if (i + 1 != c.end())
740 os << ", ";
741 }
742 }
743
749 template <typename T>
750 void
751 operator() (const T& v) const
752 {
753 os << v;
754 }
755 };
756
760 struct MetadataMapOStreamVisitor : public boost::static_visitor<>
761 {
763 std::ostream& os;
765 const MetadataMap::key_type& key;
766
773 MetadataMapOStreamVisitor(std::ostream& os,
774 const MetadataMap::key_type& key):
775 os(os),
776 key(key)
777 {}
778
789 template <typename T>
790 void
791 operator() (const std::vector<T> & c) const
792 {
793 typename std::vector<T>::size_type idx = 1;
794 // Determine the optimal padding based on the maximum digit count.
795 int sf = static_cast<int>(std::log10(static_cast<float>(c.size()))) + 1;
796 for (typename std::vector<T>::const_iterator i = c.begin();
797 i != c.end();
798 ++i, ++idx)
799 {
800 os << key << " #" << std::setw(sf) << std::setfill('0') << std::right << idx << " = " << *i << '\n';
801 }
802 }
803
812 template <typename T>
813 void
814 operator() (const T& v) const
815 {
816 os << key << " = " << v << '\n';
817 }
818 };
819
823 struct MetadataMapFlattenVisitor : public boost::static_visitor<>
824 {
826 MetadataMap& map;
828 const MetadataMap::key_type& key;
829
836 MetadataMapFlattenVisitor(MetadataMap& map,
837 const MetadataMap::key_type& key):
838 map(map),
839 key(key)
840 {}
841
852 template <typename T>
853 void
854 operator() (const std::vector<T> & c) const
855 {
856 typename std::vector<T>::size_type idx = 1;
857 // Determine the optimal padding based on the maximum digit count.
858 int sf = static_cast<int>(std::log10(static_cast<float>(c.size()))) + 1;
859 for (typename std::vector<T>::const_iterator i = c.begin();
860 i != c.end();
861 ++i, ++idx)
862 {
863 std::ostringstream os;
864 os << key << " #" << std::setw(sf) << std::setfill('0') << std::right << idx;
865 map.set(os.str(), *i);
866 }
867 }
868
877 template <typename T>
878 void
879 operator() (const T& v) const
880 {
881 map.set(key, v);
882 }
883 };
884
885 }
886
898 template<>
899 inline MetadataMap::value_type&
900 MetadataMap::get<MetadataMap::value_type>(const key_type& key)
901 {
902 map_type::iterator i = discriminating_map.find(key);
903 if (i == discriminating_map.end())
904 throw boost::bad_get();
905
906 return i->second;
907 }
908
920 template<>
921 inline const MetadataMap::value_type&
922 MetadataMap::get<MetadataMap::value_type>(const key_type& key) const
923 {
924 map_type::const_iterator i = discriminating_map.find(key);
925 if (i == discriminating_map.end())
926 throw boost::bad_get();
927
928 return i->second;
929 }
930
931 inline
932 MetadataMap
933 MetadataMap::flatten() const
934 {
935 MetadataMap newmap;
936 for (MetadataMap::const_iterator i = discriminating_map.begin();
937 i != discriminating_map.end();
938 ++i)
939 {
940 boost::apply_visitor(detail::MetadataMapFlattenVisitor(newmap, i->first), i->second);
941 }
942 return newmap;
943 }
944
945 }
946 }
947
948 namespace std
949 {
950
958 template<class charT, class traits>
959 inline basic_ostream<charT,traits>&
960 operator<< (basic_ostream<charT,traits>& os,
961 const ::ome::files::MetadataMap::value_type& vt)
962 {
963 boost::apply_visitor(::ome::files::detail::MetadataMapValueTypeOStreamVisitor(os), vt);
964 return os;
965 }
966
974 template<class charT, class traits>
975 inline basic_ostream<charT,traits>&
976 operator<< (basic_ostream<charT,traits>& os,
977 const ::ome::files::MetadataMap& map)
978 {
979 for (::ome::files::MetadataMap::const_iterator i = map.begin();
980 i != map.end();
981 ++i)
982 {
983 boost::apply_visitor(::ome::files::detail::MetadataMapOStreamVisitor(os, i->first), i->second);
984 }
985 return os;
986 }
987
988 }
989
990 #endif // OME_FILES_METADATAMAP_H
991
992 /*
993 * Local Variables:
994 * mode:C++
995 * End:
996 */
variant.h
ome::files::detail::MetadataMapFlattenVisitor::key
const MetadataMap::key_type & key
The key of the value being flattened.
Definition: MetadataMap.h:828
ome::files::MetadataMap::clear
void clear()
Clear the map.
Definition: MetadataMap.h:697
ome::files::MetadataMap::list_types_view
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
ome::files::MetadataMap::reverse_iterator
map_type::reverse_iterator reverse_iterator
Reverse iterator.
Definition: MetadataMap.h:162
ome::files::detail::MetadataMapOStreamVisitor
Visitor template for output of MetadataMap values to an ostream.
Definition: MetadataMap.h:760
ome::files::MetadataMap::all_types_view
boost::mpl::joint_view< basic_types_view, list_types_view > all_types_view
Aggregate view of all storable types.
Definition: MetadataMap.h:137
ome::files::MetadataMap::map
map_type & map()
Get the underlying map.
Definition: MetadataMap.h:472
ome::files::MetadataMap::rend
reverse_iterator rend()
Get a reverse iterator to the beginning of the map.
Definition: MetadataMap.h:560
ome::files::MetadataMap::operator<=
bool operator<=(const MetadataMap &rhs) const
Check if map is less than or equal to another map.
Definition: MetadataMap.h:636
ome::files::MetadataMap::non_numeric_types
boost::mpl::vector< std::string, bool > non_numeric_types
Storable non-numeric types.
Definition: MetadataMap.h:100
ome::files::MetadataMap::getkey
Functor to get a map key.
Definition: MetadataMap.h:399
ome::files::MetadataMap::operator==
bool operator==(const MetadataMap &rhs) const
Compare maps for equality.
Definition: MetadataMap.h:599
ome::files::MetadataMap::value_type
boost::make_variant_over< discriminated_types >::type value_type
Value type, allowing assignment of all storable types.
Definition: MetadataMap.h:147
ome::files::detail::MetadataMapValueTypeOStreamVisitor::MetadataMapValueTypeOStreamVisitor
MetadataMapValueTypeOStreamVisitor(std::ostream &os)
Constructor.
Definition: MetadataMap.h:719
ome::files::MetadataMap::discriminated_types
boost::mpl::insert_range< boost::mpl::vector0<>, boost::mpl::end< boost::mpl::vector0<> >::type, all_types_view >::type discriminated_types
List of discriminated types used by boost::variant.
Definition: MetadataMap.h:140
ome::files::MetadataMap::erase
void erase(iterator pos)
Erase a key from the map by an iterator position.
Definition: MetadataMap.h:392
std
STL namespace.
ome::files::MetadataMap::begin
const_iterator begin() const
Get a constant iterator to the beginning of the map.
Definition: MetadataMap.h:505
ome::files::MetadataMap::insert
std::pair< iterator, bool > insert(map_type::value_type &value)
Insert a value into the map.
Definition: MetadataMap.h:370
ome::files::detail::MetadataMapFlattenVisitor::map
MetadataMap & map
The map in which to set the flattened elements.
Definition: MetadataMap.h:826
ome::files::MetadataMap
Metadata key-value map using a restricted set of value types.
Definition: MetadataMap.h:79
ome::files::MetadataMap::discriminating_map
map_type discriminating_map
Key-value mapping.
Definition: MetadataMap.h:169
ome::files::MetadataMap::begin
iterator begin()
Get an iterator to the beginning of the map.
Definition: MetadataMap.h:494
ome::files::MetadataMap::make_vector::type
std::vector< T > type
The result type.
Definition: MetadataMap.h:130
ome::files::MetadataMap::keys
std::vector< key_type > keys() const
Get a list of keys in the map.
Definition: MetadataMap.h:425
ome::files::MetadataMap::find
iterator find(const key_type &key)
Find a key in the map.
Definition: MetadataMap.h:339
ome::files::MetadataMap::operator>
bool operator>(const MetadataMap &rhs) const
Check if map is greater than another map.
Definition: MetadataMap.h:648
ome::files::MetadataMap::MetadataMap
MetadataMap()
Constructor.
Definition: MetadataMap.h:173
ome::files::detail::MetadataMapFlattenVisitor
Visitor template for flattening of MetadataMap vector values.
Definition: MetadataMap.h:823
ome::files::detail::MetadataMapValueTypeOStreamVisitor
Visitor template for output of MetadataMap values to an ostream.
Definition: MetadataMap.h:709
ome::files::detail::MetadataMapOStreamVisitor::MetadataMapOStreamVisitor
MetadataMapOStreamVisitor(std::ostream &os, const MetadataMap::key_type &key)
Constructor.
Definition: MetadataMap.h:773
ome
Open Microscopy Environment C++.
ome::files::MetadataMap::end
const_iterator end() const
Get a constant iterator to the end of the map.
Definition: MetadataMap.h:527
ome::files::MetadataMap::~MetadataMap
~MetadataMap()
Destructor.
Definition: MetadataMap.h:177
ome::files::MetadataMap::key_type
std::string key_type
Key type.
Definition: MetadataMap.h:144
ome::files::MetadataMap::operator[]
value_type & operator[](const key_type &key)
Get or set a value by key index.
Definition: MetadataMap.h:587
ome::files::MetadataMap::rend
const_reverse_iterator rend() const
Get a constant reverse iterator to the beginning of the map.
Definition: MetadataMap.h:571
ome::files::MetadataMap::operator>=
bool operator>=(const MetadataMap &rhs) const
Check if map is greater than or equal to another map.
Definition: MetadataMap.h:661
ome::files::MetadataMap::const_iterator
map_type::const_iterator const_iterator
Constant iterator.
Definition: MetadataMap.h:159
ome::files::MetadataMap::rbegin
reverse_iterator rbegin()
Get a reverse iterator to the end of the map.
Definition: MetadataMap.h:538
ome::files::MetadataMap::basic_types_view
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
ome::files::detail::MetadataMapOStreamVisitor::key
const MetadataMap::key_type & key
The key of the value being output.
Definition: MetadataMap.h:765
ome::files::MetadataMap::integer_types
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
ome::files::MetadataMap::rbegin
const_reverse_iterator rbegin() const
Get a constant reverse iterator to the end of the map.
Definition: MetadataMap.h:549
ome::files::MetadataMap::find
const_iterator find(const key_type &key) const
Find a key in the map.
Definition: MetadataMap.h:351
ome::files::MetadataMap::empty
bool empty() const
Check if the map is empty.
Definition: MetadataMap.h:686
cstdint.h
ome::files::MetadataMap::operator<
bool operator<(const MetadataMap &rhs) const
Check if map is less than another map.
Definition: MetadataMap.h:623
ome::files::MetadataMap::const_reverse_iterator
map_type::const_reverse_iterator const_reverse_iterator
Constant reverse iterator.
Definition: MetadataMap.h:165
ome::files::MetadataMap::merge
void merge(const MetadataMap &map, const std::string &prefix)
Merge a separate map into this map.
Definition: MetadataMap.h:442
ome::files::detail::MetadataMapOStreamVisitor::os
std::ostream & os
The stream to output to.
Definition: MetadataMap.h:763
ome::files::MetadataMap::erase
void erase(const key_type &key)
Erase a key from the map by name.
Definition: MetadataMap.h:381
ome::files::MetadataMap::getkey::operator()
T::first_type operator()(T pair) const
Get key from pair.
Definition: MetadataMap.h:408
ome::files::MetadataMap::float_types
boost::mpl::vector< float, double, long double > float_types
Storable floating-point types.
Definition: MetadataMap.h:115
ome::files::MetadataMap::map_type
std::map< key_type, value_type > map_type
std::string to discriminated type mapping.
Definition: MetadataMap.h:150
ome::files::MetadataMap::operator!=
bool operator!=(const MetadataMap &rhs) const
Compare maps for non-equality.
Definition: MetadataMap.h:611
ome::files::MetadataMap::map
const map_type & map() const
Get the underlying map.
Definition: MetadataMap.h:483
ome::files::MetadataMap::make_vector
Convert T into a std::vector<T>.
Definition: MetadataMap.h:127
ome::files::MetadataMap::flatten
MetadataMap flatten() const
Create a flattened map.
Definition: MetadataMap.h:933
ome::files::MetadataMap::numeric_types_view
boost::mpl::joint_view< integer_types, float_types >::type numeric_types_view
Aggregate view of all numeric types.
Definition: MetadataMap.h:119
ome::files::detail::MetadataMapFlattenVisitor::MetadataMapFlattenVisitor
MetadataMapFlattenVisitor(MetadataMap &map, const MetadataMap::key_type &key)
Constructor.
Definition: MetadataMap.h:836
ome::files::MetadataMap::append
void append(const key_type &key, const T &value)
Append a value to a vector.
Definition: MetadataMap.h:230
ome::files::MetadataMap::end
iterator end()
Get an iterator to the end of the map.
Definition: MetadataMap.h:516
ome::files::MetadataMap::size_type
map_type::size_type size_type
Size type.
Definition: MetadataMap.h:153
ome::files::MetadataMap::size
size_type size() const
Get the size of the map.
Definition: MetadataMap.h:675
ome::files::MetadataMap::iterator
map_type::iterator iterator
Iterator.
Definition: MetadataMap.h:156
ome::files::MetadataMap::set
void set(const key_type &key, const value_type &value)
Add a key-value pair to the map.
Definition: MetadataMap.h:190
ome::files::detail::MetadataMapValueTypeOStreamVisitor::os
std::ostream & os
The stream to output to.
Definition: MetadataMap.h:712