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