core/vil/file_formats/vil_nitf2_typed_array_field.h
Go to the documentation of this file.
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_TYPED_ARRAY_FIELD_H
00008 #define VIL_NITF2_TYPED_ARRAY_FIELD_H
00009 
00010 #include <vcl_map.h>
00011 #include <vcl_iosfwd.h>
00012 
00013 #include "vil_nitf2_array_field.h"
00014 #include "vil_nitf2.h"
00015 
00016 class vil_nitf2_index_vector;
00017 
00018 //: Typed concrete class for array fields.
00019 // Stores values and implements I/O of values.
00020 //
00021 template<class T>
00022 class vil_nitf2_typed_array_field : public vil_nitf2_array_field
00023 {
00024  public:
00025   // Constructor
00026   vil_nitf2_typed_array_field(int num_dimensions, vil_nitf2_field_definition* field_definition)
00027     : vil_nitf2_array_field(field_definition, num_dimensions) {}
00028 
00029   //:
00030   // Set out_value to the scalar value at the specified index vector,
00031   // and returns whether specified element was defined.
00032   // The length of the index vector must equal num_dimensions(),
00033   // and check_index(indexes) must return true to indicate that
00034   // the indexes are within bounds. Even so, this method may return
00035   // false if the value is undefined at the specified index.
00036   // (This is a partial override of overloaded method
00037   // vil_nitf2_array_field::value() for my specific type.)
00038   bool value(const vil_nitf2_index_vector& indexes, T& out_value) const;
00039 
00040   //: Reads from input stream the scalar value at specified index.
00041   // check_index(indexes) must be true, or this will emit an error.
00042   // Returns success.
00043   bool read_vector_element(vil_nitf2_istream& input,
00044                            const vil_nitf2_index_vector& indexes,
00045                            int variable_width);
00046 
00047   //: Writes to output stream the scalar value at specified index.
00048   // check_index(indexes) must be true, of this will emit an error.
00049   // Returns success. Arg variable_width, if non-negative, overrides
00050   // formatter's field_width.
00051   bool write_vector_element(vil_nitf2_ostream& output,
00052                             const vil_nitf2_index_vector& indexes,
00053                             int variable_width) const;
00054 
00055   //: Output in human-readable form.
00056   // Implementation provides an example of how to iterate over all elements.
00057   virtual vcl_ostream& output(vcl_ostream& os) const;
00058 
00059   //: Destructor (overridden below for instantiations where T is a pointer)
00060   ~vil_nitf2_typed_array_field() {}
00061 
00062  protected:
00063   // Helper method for output() method above. Iterates over one
00064   // dimension of vector field, recursively printing all defined elements
00065   // to output stream.
00066   void output_dimension_iterate(vcl_ostream& os, vil_nitf2_index_vector indexes,
00067                                 bool& output_yet) const;
00068 
00069  private:
00070   // Value (i,j,...) is stored in m_value_map[(i,j,...)], where the
00071   // length of the index vector (i,j,...) equals member m_num_dimensions.
00072   // A map is used here instead of simple vector for several reasons:
00073   // (1) this single class can represent a vector of any dimensionality;
00074   // (2) due to conditional and blank nodes, a vector may be sparsely
00075   // populated; and (3) a multi-dimensional vector's dimensions may vary.
00076   vcl_map<vil_nitf2_index_vector, T> m_value_map;
00077 };
00078 
00079 //==============================================================================
00080 // implementation
00081 //==============================================================================
00082 
00083 #include "vil_nitf2_index_vector.h"
00084 #include "vil_nitf2_field_formatter.h"
00085 #include "vil_nitf2_typed_field_formatter.h"
00086 #include "vil_nitf2_field_definition.h"
00087 
00088 template<class T>
00089 bool vil_nitf2_typed_array_field<T>::value(
00090   const vil_nitf2_index_vector& indexes, T& out_value) const
00091 {
00092   if ((int)indexes.size() != m_num_dimensions) {
00093     vcl_cerr << "vil_nitf2_typed_array_field index vector wrong length\n";
00094     return false;
00095   }
00096   typename vcl_map<vil_nitf2_index_vector, T>::const_iterator element = m_value_map.find(indexes);
00097   if (element != m_value_map.end()) {
00098     out_value = element->second;
00099     return true;
00100   }
00101   else return false;
00102 }
00103 
00104 template<class T>
00105 bool vil_nitf2_typed_array_field<T>::
00106 read_vector_element(vil_nitf2_istream& input, const vil_nitf2_index_vector& indexes,
00107                     int variable_width)
00108 {
00109   VIL_NITF2_LOG(log_debug) << "Reading " << tag() << indexes << ": ";
00110   bool is_blank;
00111   if (!check_index(indexes)) {
00112     VIL_NITF2_LOG(log_debug) << "invalid index!" << vcl_endl;
00113     return false;
00114   }
00115   vil_nitf2_field_formatter* formatter = m_definition->formatter;
00116   // To do: make this cast safe!
00117   vil_nitf2_typed_field_formatter<T>* typed_formatter = (vil_nitf2_typed_field_formatter<T>*)formatter;
00118   // if non-negative variable_width is specified, it overrides the field_width
00119   int saved_field_width = typed_formatter->field_width;
00120   if (variable_width > 0) {
00121     typed_formatter->field_width = variable_width;
00122   }
00123   T val;
00124   bool value_read = typed_formatter->read(input, val, is_blank);
00125   typed_formatter->field_width = saved_field_width;
00126   if (value_read) {
00127     VIL_NITF2_LOG(log_debug) << val << vcl_endl;
00128     m_value_map[indexes] = val;
00129   }
00130   else if (is_blank && !m_definition->blanks_ok) {
00131     VIL_NITF2_LOG(log_debug) << "not specified, but required!" << vcl_endl;
00132   }
00133   else if (is_blank) {
00134     VIL_NITF2_LOG(log_debug) << "(unspecified)" << vcl_endl;
00135   }
00136   else {
00137     VIL_NITF2_LOG(log_debug) << "failed!" << vcl_endl;
00138     return false;
00139   }
00140   return true;
00141 }
00142 
00143 template<class T>
00144 bool vil_nitf2_typed_array_field<T>::
00145 write_vector_element(vil_nitf2_ostream& output, const vil_nitf2_index_vector& indexes,
00146                      int variable_width) const
00147 {
00148   VIL_NITF2_LOG(log_debug) << "Writing tag " << tag() << indexes << ' ';
00149   if (!check_index(indexes)) {
00150     VIL_NITF2_LOG(log_debug) << ": invalid index!" << vcl_endl;
00151     return false;
00152   }
00153   T val;
00154   // To do: make this cast safe!
00155   vil_nitf2_typed_field_formatter<T>* typed_formatter =
00156     (vil_nitf2_typed_field_formatter<T>*)m_definition->formatter;
00157   if (variable_width > 0) typed_formatter->field_width = variable_width;
00158   bool value_defined = value(indexes, val);
00159   if (value_defined) {
00160     VIL_NITF2_LOG(log_debug) << vcl_endl;
00161     return typed_formatter->write(output, val);
00162   }
00163   else {
00164     if (!m_definition->blanks_ok) {
00165       VIL_NITF2_LOG(log_debug) << ": required value undefined at this index; writing blanks." << vcl_endl;
00166     }
00167     return typed_formatter->write_blank(output);
00168   }
00169 }
00170 
00171 template<class T>
00172 vcl_ostream& vil_nitf2_typed_array_field<T>::output(vcl_ostream& os) const
00173 {
00174   bool output_yet = false;
00175   output_dimension_iterate(os, vil_nitf2_index_vector(), output_yet);
00176   return os;
00177 }
00178 
00179 template<class T>
00180 void vil_nitf2_typed_array_field<T>::output_dimension_iterate(
00181   vcl_ostream& os, vil_nitf2_index_vector indexes, bool& output_yet) const
00182 {
00183   if ((int)indexes.size()==m_num_dimensions) {
00184     T val;
00185     if (value(indexes, val)) {
00186       // flag output_yet is simply used to print a separator between
00187       // elements within a line.
00188       if (output_yet) {
00189         os << ", ";
00190       }
00191       else {
00192         output_yet = true;
00193       }
00194       os << indexes << ' ' << val;
00195     }
00196   }
00197   else {
00198     int dim = next_dimension(indexes);
00199     for (int i=0; i < dim; ++i) {
00200       vil_nitf2_index_vector next_indexes(indexes);
00201       next_indexes.push_back(i);
00202       output_dimension_iterate(os, next_indexes, output_yet);
00203     }
00204     os << vcl_endl;
00205     output_yet = false;
00206   }
00207 }
00208 
00209 template<class T>
00210 vcl_ostream& operator << (vcl_ostream& os, const vil_nitf2_typed_array_field<T>& field)
00211 {
00212   return field->output(os);
00213 };
00214 
00215 // Override destructor when T is a pointer type
00216 template<>
00217 inline vil_nitf2_typed_array_field<void*>::~vil_nitf2_typed_array_field()
00218 {
00219   for (vcl_map<vil_nitf2_index_vector, void*>::iterator it = m_value_map.begin();
00220        it != m_value_map.end(); ++it)
00221   {
00222     // vector delete corresponds to new char[] for binary data
00223     delete[] (char*) it->second;
00224   }
00225   m_value_map.clear();
00226 }
00227 
00228 template<>
00229 inline vil_nitf2_typed_array_field<vil_nitf2_location*>::~vil_nitf2_typed_array_field()
00230 {
00231   for (vcl_map<vil_nitf2_index_vector, vil_nitf2_location*>::iterator it = m_value_map.begin();
00232        it != m_value_map.end(); ++it)
00233   {
00234     delete it->second;
00235   }
00236   m_value_map.clear();
00237 }
00238 
00239 #endif // VIL_NITF2_TYPED_ARRAY_FIELD_H