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