00001 //: 00002 // \file 00003 // vil_nitf2: Written by Harry Voorhees (hlv@) and Rob Radtke (rob@) of 00004 // Stellar Science Ltd. Co. (stellarscience.com) for 00005 // Air Force Research Laboratory, 2005. 00006 00007 #ifndef VIL_NITF2_ARRAY_FIELD_H 00008 #define VIL_NITF2_ARRAY_FIELD_H 00009 00010 #include <vcl_map.h> 00011 #include <vcl_string.h> 00012 #include "vil_nitf2_field.h" 00013 #include "vil_nitf2_index_vector.h" 00014 00015 class vil_nitf2_field_definition; 00016 class vil_nitf2_location; 00017 class vil_nitf2_date_time; 00018 00019 //: Abstract class for array fields, i.e., fields that occur within a repeat loop. 00020 // Since repeat loops can be nested, this field can be multi-dimensional. 00021 // Its row dimensions don't even need to be same. One instance of this 00022 // class "collects" all the values associated with a tag, even though they 00023 // may be interleaved among other values in the NITF file. This class 00024 // provides dimensional information and implements methods common to the 00025 // type-specific subclasses. 00026 00027 class vil_nitf2_array_field : public vil_nitf2_field 00028 { 00029 public: 00030 // Constructor 00031 vil_nitf2_array_field(vil_nitf2_field_definition* definition, int num_dimensions) 00032 : vil_nitf2_field(definition), m_num_dimensions(num_dimensions) {} 00033 00034 // Destructor 00035 virtual ~vil_nitf2_array_field() {} 00036 00037 //: Number of dimensions. 00038 // \returns this vector's number of dimensions, which equals 00039 // its "repeat" nesting level. 00040 int num_dimensions() const; 00041 00042 //: Given a partial index vector, set the value of the next dimension. 00043 // Length of indexes must be less than num_dimensions(). See comment 00044 // for member m_dimensions_map, below; indexes is its key. For example, 00045 // if indexes is empty, the first dimension is set. 00046 void set_next_dimension(const vil_nitf2_index_vector& indexes, int bound); 00047 00048 //: Given a partial index vector, return value of next dimension (or zero if none). 00049 // Length of indexes must be less than num_dimensions(). See comment 00050 // for member m_dimensions_map, below; indexes is its key. For 00051 // example, if indexes is empty, the first dimension is retrieved. 00052 int next_dimension(const vil_nitf2_index_vector& indexes) const; 00053 00054 //: Compares index vector against value dimensions. 00055 bool check_index(const vil_nitf2_index_vector& indexes) const; 00056 00057 //: Reads from input stream the scalar value at specified index. 00058 // check_index(indexes) must be true, or this will emit an error. 00059 // \returns success. 00060 virtual bool read_vector_element(vil_nitf2_istream& input, 00061 const vil_nitf2_index_vector& indexes, 00062 int variable_width) = 0; 00063 00064 //: Writes to output stream the scalar value at specified index. 00065 // check_index(indexes) must be true, of this will emit an error. 00066 // Returns success. Arg variable_width, if non-negative, overrides 00067 // formatter's field_width. 00068 virtual bool write_vector_element(vil_nitf2_ostream& output, 00069 const vil_nitf2_index_vector& indexes, 00070 int variable_width) const = 0; 00071 00072 virtual field_tree* get_tree() const; 00073 00074 //: 00075 // Sets out_value to the value of the element selected by specified 00076 // index vector, which must satisfy check_index(). Returns true iff the 00077 // value is defined. Note that this may return false because the value 00078 // is unspecified (i.e., blank), even if the index is valid. 00079 // 00080 // Subclasses overload the appropriate method to set out parameter and 00081 // return true. The implementation here return false. These methods are 00082 // defined here for the convenience of my callers, so they don't have to 00083 // downcast to the specific field type. 00084 #if VXL_HAS_INT_64 00085 virtual bool value(const vil_nitf2_index_vector&, vil_nitf2_long& ) const { return false; } 00086 #endif 00087 virtual bool value(const vil_nitf2_index_vector&, int& ) const { return false; } 00088 virtual bool value(const vil_nitf2_index_vector&, double& ) const { return false; } 00089 virtual bool value(const vil_nitf2_index_vector&, char& ) const { return false; } 00090 virtual bool value(const vil_nitf2_index_vector&, void*& ) const { return false; } 00091 virtual bool value(const vil_nitf2_index_vector&, vcl_string& ) const { return false; } 00092 virtual bool value(const vil_nitf2_index_vector&, vil_nitf2_location*& ) const { return false; } 00093 virtual bool value(const vil_nitf2_index_vector&, vil_nitf2_date_time& ) const { return false; } 00094 00095 protected: 00096 void do_dimension( const vil_nitf2_index_vector& index, 00097 vil_nitf2_field::field_tree* tr ) const; 00098 vcl_string get_value_string(const vil_nitf2_index_vector& in_indices) const; 00099 00100 00101 //: Dimensionality of vector field 00102 int m_num_dimensions; 00103 00104 //: 00105 // Because a repeating field's dimension can depend on the value of 00106 // another repeating field, slices of a multi-dimensional vector field 00107 // can have varying dimensions (for an example test case, see method 00108 // vil_nitf2_tagged_record::test()). Dimensions are therefore stored 00109 // here as follows: 00110 // - m_dimensions_map[vector()] holds the first dimension; 00111 // - m_dimensions_map[vector(i)] holds the second dimension of 00112 // row i of a 2-or-more-dimensional vector; 00113 // - m_dimensions_map[vector(i,j)] holds the third dimension of 00114 // plane (i,j) of a 3-or-more-dimensional vector; 00115 // and so on, according dimensionality of the field. 00116 vcl_map<vil_nitf2_index_vector, int> m_dimensions_map; 00117 }; 00118 00119 #endif // VIL_NITF2_ARRAY_FIELD_H