vil_nitf2_field_sequence.cxx
Go to the documentation of this file.
1 // vil_nitf2: Written by Harry Voorhees (hlv@) and Rob Radtke (rob@) of
2 // Stellar Science Ltd. Co. (stellarscience.com) for
3 // Air Force Research Laboratory, 2005.
4 
5 #include <utility>
10 #include "vil_nitf2_scalar_field.h"
11 #include "vil_nitf2_array_field.h"
13 
14 #ifdef _MSC_VER
15 # include <vcl_msvc_warnings.h>
16 #endif
17 
20 {
22  for (auto i : fields_vector) {
23  t->children.push_back( i->get_tree() );
24  }
25  return t;
26 }
27 
28 void vil_nitf2_field_sequence::insert_field( const std::string& str, vil_nitf2_field* field )
29 {
30  fields.insert(std::make_pair(str, field));
31  fields_vector.push_back(field);
32 }
33 
36  int num_dimensions)
37 {
38  for (auto node : *field_defs)
39  {
40  if (node && node->is_field_definition()) {
41  vil_nitf2_field_definition* field_def = node->field_definition();
42  vil_nitf2_array_field* field = field_def->formatter->create_array_field(num_dimensions, field_def);
43  if (field) {
44  insert_field(field_def->tag, field);
45  } else {
46  std::cerr << "vil_nitf2_field_sequence:create_array_fields(): Error created required std::vector field "
47  << field_def->tag << "; bailing out.\n";
48  return false;
49  }
50  } else if (node && node->is_repeat_node()) {
51  // recursively create nested vector fields
53  if (!create_array_fields(repeat_node->field_definitions, num_dimensions+1)) {
54  return false;
55  }
56  } else {
57  std::cerr << "vil_nitf2_field_sequence::create_array_fields(): unsupported node type!\n";
58  return false;
59  }
60  }
61  return true;
62 }
63 
65  const vil_nitf2_field_definitions* field_defs,
66  const vil_nitf2_index_vector& index, int repeat_count)
67 {
68  for (auto node : *field_defs)
69  {
70  if (node && node->is_field_definition()) {
71  vil_nitf2_field_definition* field_def = node->field_definition();
72  vil_nitf2_array_field* field = get_field(field_def->tag)->array_field();
73  if (field) {
74  VIL_NITF2_LOG(log_debug) << " (Setting tag " << field_def->tag << " dimension "
75  << index << " to " << repeat_count << ".)" << std::endl;
76  field->set_next_dimension(index, repeat_count);
77  } else {
78  std::cerr << "vil_nitf2_field_sequence:set_array_field_dimension(): array field "
79  << field_def->tag << " not found!\n";
80  }
81  } else if (node && node->is_repeat_node()) {
82  // recursively set dimension vector fields
84  set_array_fields_dimension(repeat_node->field_definitions, index, repeat_count);
85  } else {
86  std::cerr << "vil_nitf2_field_sequence::set_array_fields_dimension(): unsupported node type!\n";
87  }
88  }
89 }
90 
92  const vil_nitf2_field_definitions* field_defs,
93  const vil_nitf2_index_vector& indexes)
94 {
95  if (!field_defs)
96  field_defs = m_field_definitions;
97  if (!field_defs)
98  std::cerr << "vil_nitf2_field_sequence::read() missing field definitions!\n";
99  bool error = false;
100  for (auto node : *field_defs)
101  {
102  if (node && node->is_field_definition())
103  {
104  vil_nitf2_field_definition* field_def = node->field_definition();
105  // The field exists if it is required, or if it is conditional and
106  // the condition is true.
107  bool field_exists;
108  if (field_def->is_required()) {
109  field_exists = true;
110  } else {
111  bool condition;
112  bool conditionValid = (*(field_def->condition_functor))(this, indexes, condition);
113  if (conditionValid) {
114  field_exists = condition;
115  } else {
116  // Cannot evaluate condition; therefore I don't know whether this
117  // field exists and cannot reliably parse the rest of the record
118  std::cerr << "vil_nitf2_field_sequence::read(): Cannot evaluate condition for tag " << field_def->tag << '\n';
119  error = true;
120  break;
121  }
122  }
123  if (field_exists)
124  {
125  // Evaluate its width functor, if any.
126  int variable_width = -1;
127  if (field_def->width_functor != nullptr) {
128  bool computed_width = (*(field_def->width_functor))(this, indexes, variable_width);
129  if (!computed_width) {
130  // Cannot evaluate width functor; therefore I don't know the length
131  // of this field and cannot reliably parse the rest of the record
132  std::cerr << "vil_nitf2_field_sequence::read(): Cannot evaluate width functor for tag " << field_def->tag << '\n';
133  error = true;
134  break;
135  }
136  }
137  if (variable_width == 0) {
138  VIL_NITF2_LOG(log_debug) << "Skipping field " << field_def->tag << ", whose length = 0." << std::endl;
139  }
140  else
141  {
142  // Either there is no width functor, in which case variable_width = -1 and will be ignored,
143  // or there is a width functor, and the resulting positive variable_width will be applied.
144  if (indexes.size()==0) {
145  // read scalar field
146  bool fieldReadError;
147  vil_nitf2_scalar_field* field = vil_nitf2_scalar_field::read(input, field_def, variable_width, &fieldReadError);
148  if (field) {
149  insert_field(field_def->tag, field);
150  }
151  if ( fieldReadError ){
152  error = true;
153  break;
154  }
155 
156  } else {
157  // read vector field element
158  bool read_error = true;
159  vil_nitf2_field_definition* field_def = node->field_definition();
160  if (field_def) {
161  vil_nitf2_array_field* field = get_field(field_def->tag)->array_field();
162  if (field) {
163  if (field->read_vector_element(input, indexes, variable_width)) {
164  read_error = false;
165  }
166  }
167  }
168  if (read_error) {
169  std::cerr << "vil_nitf2_field_sequence::read(): Couldn't find std::vector field!\n";
170  return false;
171  }
172  }
173  }
174  // TO DO: Check that the expected amount of data was read; if not,
175  // try to recover.
176  }
177  }
178  else if (node && node->is_repeat_node())
179  {
181 
182  // Compute how many times it repeats
183  int repeat_count = 0;
184  bool computed_repeat = false;
185  if (repeat_node->repeat_functor != nullptr) {
186  computed_repeat = (*(repeat_node->repeat_functor))(this, indexes, repeat_count);
187  }
188  if (!computed_repeat) {
189  // Cannot evaluate repeat count; therefore I don't know the length
190  // of this field and cannot reliably parse the rest of the record
191  std::cerr << "Cannot evaluate repeat count for repeat node\n";
192  error = true;
193  break;
194  }
195  // On the first call to this method, call create_array_fields to loop
196  // recursively over the field definitions to create all vector fields.
197  // All nested fields need to be defined before any values are read. This is
198  // is so that we can start setting the bounds on outer dimensions of
199  // nested field at the top of each repeat loop.
200  //
201  // For example, for this field sequence:
202  // REPEAT i=1..N
203  // FIELD A(i)
204  // REPEAT j=1..A(i)
205  // FIELD B(i,j)
206  // the following call to create_array_fields sets up fields
207  // A (with 1 dimension) and B (with 2 dimensions).
208  if (indexes.size() == 0) {
209  if (!create_array_fields(repeat_node->field_definitions, 1)) {
210  return false;
211  }
212  }
213  // Loop repeat_count times over fields to read the elements
214  std::string nesting_level_indicator((indexes.size()+1)*2, '-');
215  VIL_NITF2_LOG(log_debug) << nesting_level_indicator
216  << "Repeating fields " << repeat_count << " times:" << std::endl;
217  for (int i=0; i<repeat_count; ++i)
218  {
219  // The first time through the repeat loop, set the dimension
220  // bounds of all fields, including repeated fields. So, for the
221  // example above, during the first call to this method read(),
222  // the invocation of set_fields_bounds() will set:
223  // A.dimension(vector()) = N
224  // B.dimension(vector()) = N
225  // During the recursive calls to read(), the two invocations of
226  // set_field_bounds() will set:
227  // B.dimension(vector(1)) = A(1)
228  // B.dimension(vector(2)) = A(2)
229  // Actually, the indexes are zero-based, but this gives the general
230  // idea.
231  if (i==0) {
232  set_array_fields_dimension(repeat_node->field_definitions, indexes, repeat_count);
233  }
234 
235  // Now call myself recursively to read the vector field elements
236  vil_nitf2_index_vector nested_indexes(indexes);
237  nested_indexes.push_back(i);
238  if (!read(input, repeat_node->field_definitions, nested_indexes)) {
239  return false;
240  }
241  }
242  VIL_NITF2_LOG(log_debug) << nesting_level_indicator << "End repeating fields." << std::endl;
243  }
244  else {
245  std::cerr << "vil_nitf2_tagged_record::read(): unsupported node.\n";
246  }
247  }
248  return !error;
249 }
250 
252  const vil_nitf2_field_definitions* field_defs,
253  vil_nitf2_index_vector indexes)
254 {
255  if (!field_defs)
256  field_defs = m_field_definitions;
257  if (!field_defs)
258  std::cerr << "vil_nitf2_field_sequence::write(): Missing field definitions!\n";
259  for (auto node : *field_defs)
260  {
261  if (node && node->is_field_definition())
262  {
263  vil_nitf2_field_definition* field_def = node->field_definition();
264  if (!field_def) {
265  std::cerr << "vil_nitf2_field_sequence::write(): Missing field definition!\n";
266  return false;
267  }
268  vil_nitf2_field* field = get_field(field_def->tag);
269 
270  // Determine whether the field is required or is a conditional field
271  // whose condition is satisfied
272  bool expected = field_def->is_required();
273  if (!expected) {
274  bool condition;
275  if ((*field_def->condition_functor)(this, indexes, condition)) {
276  expected |= condition;
277  } else {
278  std::cerr << "vil_nitf2_field_sequence::write(): Cound not evaluate condition for field "
279  << field_def->tag << std::endl;
280  // Cannot evaluate condition, therefore I can't tell whether this
281  // field should exist.
282  return false;
283  }
284  }
285  if (field && !expected) {
286  std::cerr << "vil_nitf2_field_sequence::write(): Field " << field_def->tag
287  << " is being ignored because its condition is not satisfied.\n";
288  }
289  else
290  {
291  // Will emit field. Evaluate its width functor, if any.
292  int variable_width = -1;
293  if (field_def->width_functor != nullptr) {
294  bool computed_width = (*(field_def->width_functor))(this, indexes, variable_width);
295  if (!computed_width) {
296  // Cannot evaluate width functor; therefore I don't know the length
297  // of this field and cannot reliably parse the rest of the record
298  std::cerr << "vil_nitf2_field_sequence::write(): Cannot evaluate width functor for tag " << field_def->tag << std::endl;
299  return false;
300  }
301  }
302  if (variable_width == 0) {
303  VIL_NITF2_LOG(log_debug) << "Skipping field " << field_def->tag << ", whose length = 0." << std::endl;
304  } else {
305  // Either there is no width functor, in which case variable_width = -1 and will be ignored,
306  // or there is a width functor, and the resulting positive variable_width will be applied.
307  if (!field && expected) {
308  if (!field_def->blanks_ok) {
309  std::cerr << "vil_nitf2_field_sequence::write(): Field " << field_def->tag
310  << " is unspecified; writing blanks.\n";
311  }
312  if (variable_width > 0)
313  field_def->formatter->field_width = variable_width;
314  field_def->formatter->write_blank(output);
315  } else if (field) {
316  if (field->scalar_field()) {
317  field->scalar_field()->write(output, variable_width);
318  } else {
319  field->array_field()->write_vector_element(output, indexes, variable_width);
320  }
321  }
322  }
323  }
324  }
325  else if (node && node->is_repeat_node())
326  {
328  // Compute how many times it repeats
329  int repeat_count = 0;
330  bool computed_repeat = false;
331  if (repeat_node->repeat_functor != nullptr) {
332  computed_repeat = (*(repeat_node->repeat_functor))(this, indexes, repeat_count);
333  }
334  if (!computed_repeat) {
335  // Cannot evaluate repeat count; therefore I don't know the length
336  // of this field.
337  std::cerr << "vil_nitf2_field_sequence::write(): Cannot evaluate repeat count for repeat node\n";
338  return false;
339  }
340  if (repeat_node->field_definitions) {
341  for (int i=0; i < repeat_count; ++i) {
342  vil_nitf2_index_vector nested_indexes(indexes);
343  nested_indexes.push_back(i);
344  this->write(output, repeat_node->field_definitions, nested_indexes);
345  }
346  }
347  } else {
348  std::cerr << "vil_nitf2_field_sequence::write(): Ignoring unsupported node.\n";
349  }
350  }
351  return true;
352 }
353 
355 {
356  // Delete fields, which I own
357  for (auto & field_map_entry : fields)
358  {
359  vil_nitf2_field* field = field_map_entry.second;
360  delete field;
361  }
362 }
363 
365 {
366  auto field_map_entry = fields.find(tag);
367  if (field_map_entry == fields.end())
368  return nullptr;
369  return field_map_entry->second;
370 }
371 
372 // Who needs templated functions when we have macros!
373 #define NITF_FIELD_SEQ_GET_VALUE(T) \
374 bool vil_nitf2_field_sequence::get_value(std::string tag, T& out_value) const { \
375  vil_nitf2_field* field = get_field(tag); \
376  vil_nitf2_scalar_field* scalar_field = field ? field->scalar_field() : 0; \
377  if (!scalar_field) { \
378  /*std::cerr << "vil_nitf2_field_sequence::get_value(" << tag << "): scalar field not found.\n";*/ \
379  return false; \
380  } \
381  if (!scalar_field->value(out_value)) { \
382  std::cerr << "vil_nitf2_field_sequence::get_value(" << tag << ") called with wrong type.\n"; \
383  return false; \
384  } \
385  return true; \
386 }
387 
392 NITF_FIELD_SEQ_GET_VALUE(std::string)
396 
397 #define NITF_FIELD_SEQ_GET_ARRAY_VALUE(T) \
398 bool vil_nitf2_field_sequence::get_value(std::string tag, \
399  const vil_nitf2_index_vector& indexes, \
400  T& out_value, \
401  bool ignore_extra_indexes) const { \
402  vil_nitf2_field* field = get_field(tag); \
403  if (!field) { \
404  /*std::cerr << "vil_nitf2_field_sequence::get_value(" << tag << ", const vil_nitf2_index_vector&): tag not found.\n"; */\
405  return false; \
406  } \
407  vil_nitf2_index_vector trimmed_indexes(indexes); \
408  if (ignore_extra_indexes && (int)indexes.size() > field->num_dimensions()) { \
409  trimmed_indexes.resize(field->num_dimensions()); \
410  } \
411  if (trimmed_indexes.size()==0) { \
412  return field->scalar_field() && field->scalar_field()->value(out_value); \
413  } else { \
414  return field->array_field()->value(trimmed_indexes, out_value); \
415  } \
416 }
417 
418 NITF_FIELD_SEQ_GET_ARRAY_VALUE(int) // expanded below for debugging
425 
426 // Macro to generate overloads of get_values(), since VXL coding
427 // standards forbid using templated member functions.
428 //
429 #define NITF_FIELD_SEQ_GET_VALUES(T) \
430 bool vil_nitf2_field_sequence::get_values(std::string tag, \
431  const vil_nitf2_index_vector& indexes, \
432  std::vector<T>& out_values, \
433  bool clear_out_values) const \
434 { \
435  vil_nitf2_field* field = get_field(tag); \
436  if (!field) { \
437  /*std::cerr << "vil_nitf2_field_sequence::get_value(" << tag << ", const vil_nitf2_index_vector&): tag not found.\n"; */\
438  return false; \
439  } \
440  if (clear_out_values) { \
441  out_values.clear(); \
442  } \
443  int num_dims = field->num_dimensions(); \
444  if (num_dims == (int)indexes.size()) { \
445  /* get single value */\
446  T value; \
447  if (get_value(tag, indexes, value, false)) { \
448  out_values.push_back(value); \
449  return true; \
450  } else { \
451  return false; \
452  } \
453  } else { \
454  vil_nitf2_array_field* array_field = field->array_field(); \
455  if (!array_field) { \
456  /* indexes is too long */\
457  return false; \
458  } \
459  /* traverse value tree depth-first, collecting values into out_values */\
460  int dimension = array_field->next_dimension(indexes); \
461  for (int index=0; index < dimension; ++index) { \
462  vil_nitf2_index_vector next_indexes = indexes; \
463  next_indexes.push_back(index); \
464  if (!get_values(tag, next_indexes, out_values, false)) { \
465  return false; \
466  } \
467  } \
468  return true; \
469  } \
470 } \
471 \
472 bool vil_nitf2_field_sequence::get_values(std::string tag, std::vector<T>& out_values) const \
473 { \
474  return get_values(tag, vil_nitf2_index_vector(), out_values, true); \
475 }
476 
481 NITF_FIELD_SEQ_GET_VALUES(std::string)
484 
485 #if VXL_HAS_INT_64
486 //if not VXL_HAS_INT_64 isn't defined the vil_nitf2_long is the same as just plain 'int'
487 //and this function will be a duplicate of that get_value
491 #endif
vxl_int_32 vil_nitf2_long
Definition: vil_nitf2.h:26
vil_nitf2_field_functor< int > * width_functor
bool read(vil_nitf2_istream &input, const vil_nitf2_field_definitions *field_defs=nullptr, const vil_nitf2_index_vector &indexes=vil_nitf2_index_vector())
bool create_array_fields(const vil_nitf2_field_definitions *field_defs, int num_dimensions)
vil_nitf2_scalar_field * scalar_field()
void set_array_fields_dimension(const vil_nitf2_field_definitions *field_defs, const vil_nitf2_index_vector &index, int repeat_count)
vil_nitf2_array_field * array_field()
#define VIL_NITF2_LOG(LEVEL)
Definition: vil_nitf2.h:63
#define NITF_FIELD_SEQ_GET_VALUES(T)
#define NITF_FIELD_SEQ_GET_VALUE(T)
bool write(vil_nitf2_ostream &output, int variable_width=-1) const
virtual bool write(vil_nitf2_ostream &, const vil_nitf2_field_definitions *field_defs=nullptr, vil_nitf2_index_vector indexes=vil_nitf2_index_vector())
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
std::vector< vil_nitf2_field * > fields_vector
#define NITF_FIELD_SEQ_GET_ARRAY_VALUE(T)
bool write_blank(std::ostream &output)
vil_nitf2_field * get_field(const std::string &tag) const
virtual vil_nitf2_array_field * create_array_field(int num_dimensions, vil_nitf2_field_definition *)=0
virtual bool read_vector_element(vil_nitf2_istream &input, const vil_nitf2_index_vector &indexes, int variable_width)=0
Reads from input stream the scalar value at specified index.
vil_nitf2_field_definition_repeat_node * repeat_node()
virtual bool write_vector_element(vil_nitf2_ostream &output, const vil_nitf2_index_vector &indexes, int variable_width) const =0
Writes to output stream the scalar value at specified index.
const vil_nitf2_field_definitions * m_field_definitions
std::vector< field_tree * > children
Abstract class for array fields, i.e., fields that occur within a repeat loop.
void insert_field(const std::string &str, vil_nitf2_field *field)
vil_nitf2_field_formatter * formatter
vil_nitf2_field_functor< int > * repeat_functor
void set_next_dimension(const vil_nitf2_index_vector &indexes, int bound)
Given a partial index vector, set the value of the next dimension.
virtual vil_nitf2_field::field_tree * get_tree(vil_nitf2_field::field_tree *tr=nullptr) const
vil_nitf2_field_functor< bool > * condition_functor
vil_nitf2_field_definition * field_definition()
static vil_nitf2_scalar_field * read(vil_nitf2_istream &input, vil_nitf2_field_definition *definition, int variable_width=-1, bool *error=nullptr)