vil_nitf2_typed_array_field.h
Go to the documentation of this file.
1 //:
2 // \file
3 // vil_nitf2: Written by Harry Voorhees (hlv@) and Rob Radtke (rob@) of
4 // Stellar Science Ltd. Co. (stellarscience.com) for
5 // Air Force Research Laboratory, 2005.
6 
7 #ifndef VIL_NITF2_TYPED_ARRAY_FIELD_H
8 #define VIL_NITF2_TYPED_ARRAY_FIELD_H
9 
10 #include <map>
11 #include <iosfwd>
12 #ifdef _MSC_VER
13 # include <vcl_msvc_warnings.h>
14 #endif
15 
16 #include "vil_nitf2_array_field.h"
17 #include "vil_nitf2.h"
18 
20 
21 //: Typed concrete class for array fields.
22 // Stores values and implements I/O of values.
23 //
24 template<class T>
26 {
27  public:
28  // Constructor
30  : vil_nitf2_array_field(field_definition, num_dimensions) {}
31 
32  //:
33  // Set out_value to the scalar value at the specified index vector,
34  // and returns whether specified element was defined.
35  // The length of the index vector must equal num_dimensions(),
36  // and check_index(indexes) must return true to indicate that
37  // the indexes are within bounds. Even so, this method may return
38  // false if the value is undefined at the specified index.
39  // (This is a partial override of overloaded method
40  // vil_nitf2_array_field::value() for my specific type.)
41  bool value(const vil_nitf2_index_vector& indexes, T& out_value) const override ;
42 
43  //: Reads from input stream the scalar value at specified index.
44  // check_index(indexes) must be true, or this will emit an error.
45  // Returns success.
47  const vil_nitf2_index_vector& indexes,
48  int variable_width) override;
49 
50  //: Writes to output stream the scalar value at specified index.
51  // check_index(indexes) must be true, of this will emit an error.
52  // Returns success. Arg variable_width, if non-negative, overrides
53  // formatter's field_width.
55  const vil_nitf2_index_vector& indexes,
56  int variable_width) const override;
57 
58  //: Output in human-readable form.
59  // Implementation provides an example of how to iterate over all elements.
60  std::ostream& output(std::ostream& os) const override;
61 
62  //: Destructor (overridden below for instantiations where T is a pointer)
64 
65  protected:
66  // Helper method for output() method above. Iterates over one
67  // dimension of vector field, recursively printing all defined elements
68  // to output stream.
69  void output_dimension_iterate(std::ostream& os, vil_nitf2_index_vector indexes,
70  bool& output_yet) const;
71 
72  private:
73  // Value (i,j,...) is stored in m_value_map[(i,j,...)], where the
74  // length of the index vector (i,j,...) equals member m_num_dimensions.
75  // A map is used here instead of simple vector for several reasons:
76  // (1) this single class can represent a vector of any dimensionality;
77  // (2) due to conditional and blank nodes, a vector may be sparsely
78  // populated; and (3) a multi-dimensional vector's dimensions may vary.
79  std::map<vil_nitf2_index_vector, T> m_value_map;
80 };
81 
82 //==============================================================================
83 // implementation
84 //==============================================================================
85 
86 #include "vil_nitf2_index_vector.h"
90 
91 template<class T>
93  const vil_nitf2_index_vector& indexes, T& out_value) const
94 {
95  if ((int)indexes.size() != m_num_dimensions) {
96  std::cerr << "vil_nitf2_typed_array_field index vector wrong length\n";
97  return false;
98  }
99  typename std::map<vil_nitf2_index_vector, T>::const_iterator element = m_value_map.find(indexes);
100  if (element != m_value_map.end()) {
101  out_value = element->second;
102  return true;
103  }
104  else return false;
105 }
106 
107 template<class T>
110  int variable_width)
111 {
112  VIL_NITF2_LOG(log_debug) << "Reading " << tag() << indexes << ": ";
113  bool is_blank;
114  if (!check_index(indexes)) {
115  VIL_NITF2_LOG(log_debug) << "invalid index!" << std::endl;
116  return false;
117  }
118  vil_nitf2_field_formatter* formatter = m_definition->formatter;
119  // To do: make this cast safe!
121  // if non-negative variable_width is specified, it overrides the field_width
122  int saved_field_width = typed_formatter->field_width;
123  if (variable_width > 0) {
124  typed_formatter->field_width = variable_width;
125  }
126  T val;
127  bool value_read = typed_formatter->read(input, val, is_blank);
128  typed_formatter->field_width = saved_field_width;
129  if (value_read) {
130  VIL_NITF2_LOG(log_debug) << val << std::endl;
131  m_value_map[indexes] = val;
132  }
133  else if (is_blank && !m_definition->blanks_ok) {
134  VIL_NITF2_LOG(log_debug) << "not specified, but required!" << std::endl;
135  }
136  else if (is_blank) {
137  VIL_NITF2_LOG(log_debug) << "(unspecified)" << std::endl;
138  }
139  else {
140  VIL_NITF2_LOG(log_debug) << "failed!" << std::endl;
141  return false;
142  }
143  return true;
144 }
145 
146 template<class T>
149  int variable_width) const
150 {
151  VIL_NITF2_LOG(log_debug) << "Writing tag " << tag() << indexes << ' ';
152  if (!check_index(indexes)) {
153  VIL_NITF2_LOG(log_debug) << ": invalid index!" << std::endl;
154  return false;
155  }
156  T val;
157  // To do: make this cast safe!
158  vil_nitf2_typed_field_formatter<T>* typed_formatter =
159  (vil_nitf2_typed_field_formatter<T>*)m_definition->formatter;
160  if (variable_width > 0) typed_formatter->field_width = variable_width;
161  bool value_defined = value(indexes, val);
162  if (value_defined) {
163  VIL_NITF2_LOG(log_debug) << std::endl;
164  return typed_formatter->write(output, val);
165  }
166  else {
167  if (!m_definition->blanks_ok) {
168  VIL_NITF2_LOG(log_debug) << ": required value undefined at this index; writing blanks." << std::endl;
169  }
170  return typed_formatter->write_blank(output);
171  }
172 }
173 
174 template<class T>
175 std::ostream& vil_nitf2_typed_array_field<T>::output(std::ostream& os) const
176 {
177  bool output_yet = false;
178  output_dimension_iterate(os, vil_nitf2_index_vector(), output_yet);
179  return os;
180 }
181 
182 template<class T>
184  std::ostream& os, vil_nitf2_index_vector indexes, bool& output_yet) const
185 {
186  if ((int)indexes.size()==m_num_dimensions) {
187  T val;
188  if (value(indexes, val)) {
189  // flag output_yet is simply used to print a separator between
190  // elements within a line.
191  if (output_yet) {
192  os << ", ";
193  }
194  else {
195  output_yet = true;
196  }
197  os << indexes << ' ' << val;
198  }
199  }
200  else {
201  int dim = next_dimension(indexes);
202  for (int i=0; i < dim; ++i) {
203  vil_nitf2_index_vector next_indexes(indexes);
204  next_indexes.push_back(i);
205  output_dimension_iterate(os, next_indexes, output_yet);
206  }
207  os << std::endl;
208  output_yet = false;
209  }
210 }
211 
212 template<class T>
213 std::ostream& operator << (std::ostream& os, const vil_nitf2_typed_array_field<T>& field)
214 {
215  return field->output(os);
216 };
217 
218 // Override destructor when T is a pointer type
219 template<>
221 {
222  for (auto & it : m_value_map)
223  {
224  // vector delete corresponds to new char[] for binary data
225  delete[] (char*) it.second;
226  }
227  m_value_map.clear();
228 }
229 
230 template<>
232 {
233  for (auto & it : m_value_map)
234  {
235  delete it.second;
236  }
237  m_value_map.clear();
238 }
239 
240 template<typename T>
242 {
243  // Nothing to do for POD types
244 }
245 
246 #endif // VIL_NITF2_TYPED_ARRAY_FIELD_H
bool write_vector_element(vil_nitf2_ostream &output, const vil_nitf2_index_vector &indexes, int variable_width) const override
Writes to output stream the scalar value at specified index.
void output_dimension_iterate(std::ostream &os, vil_nitf2_index_vector indexes, bool &output_yet) const
std::ostream & operator<<(std::ostream &os, const vil_nitf2_typed_array_field< T > &field)
bool read_vector_element(vil_nitf2_istream &input, const vil_nitf2_index_vector &indexes, int variable_width) override
Reads from input stream the scalar value at specified index.
#define VIL_NITF2_LOG(LEVEL)
Definition: vil_nitf2.h:63
vil_nitf2_typed_array_field(int num_dimensions, vil_nitf2_field_definition *field_definition)
vil_nitf2: Written by Harry Voorhees (hlv@) and Rob Radtke (rob@) of Stellar Science Ltd.
Stream interface for VIL image loaders.
Definition: vil_stream.h:21
~vil_nitf2_typed_array_field() override
Destructor (overridden below for instantiations where T is a pointer).
bool write_blank(std::ostream &output)
Typed concrete class for array fields.
std::ostream & output(std::ostream &os) const override
Output in human-readable form.
virtual bool read(vil_nitf2_istream &input, T &out_value, bool &out_blank)
std::map< vil_nitf2_index_vector, T > m_value_map
bool value(const vil_nitf2_index_vector &indexes, T &out_value) const override
Set out_value to the scalar value at the specified index vector, and returns whether specified elemen...
Abstract class for array fields, i.e., fields that occur within a repeat loop.
virtual bool write(vil_nitf2_ostream &output, const T &value)
int num_dimensions() const override
Number of dimensions.