core/vil/file_formats/vil_nitf2_typed_field_formatter.h
Go to the documentation of this file.
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_TYPED_FIELD_FORMATTER_H
00006 #define VIL_NITF2_TYPED_FIELD_FORMATTER_H
00007 
00008 #include "vil_nitf2_field_formatter.h"
00009 #include "vil_nitf2_tagged_record.h"
00010 
00011 #include <vcl_cassert.h>
00012 #include <vcl_iosfwd.h>
00013 #include <vcl_string.h>
00014 #include <vcl_sstream.h>
00015 
00016 // All subclasses of NITF field formatter derive from this template
00017 // The template handles both scalars and vectors of type T.
00018 //
00019 template<typename T>
00020 class vil_nitf2_typed_field_formatter : public vil_nitf2_field_formatter
00021 {
00022  public:
00023   // Constructor
00024   vil_nitf2_typed_field_formatter(vil_nitf2::enum_field_type field_type, int field_width)
00025     : vil_nitf2_field_formatter(field_type, field_width) {}
00026 
00027   // Destructor
00028   virtual ~vil_nitf2_typed_field_formatter() {}
00029 
00030   // Returns a vcl_vector field of specified dimensionality.
00031   vil_nitf2_array_field* create_array_field(
00032     int num_dimensions, vil_nitf2_field_definition* field_definition);
00033 
00034   // Returns a new field, read from stream.
00035   virtual vil_nitf2_scalar_field* read_field(vil_nitf2_istream& input, bool& out_blank);
00036 
00037   // Writes scalar field to the specified stream.
00038   virtual bool write_field(vil_nitf2_ostream& output, const vil_nitf2_scalar_field* field);
00039 
00040   // Attempts to read one instance of field from vil_nitf2_istream into value.
00041   // Returns whether value is valid. Sets out_blank to indicate whether the
00042   // input read consisted entirely of blanks (in which case false is the
00043   // return value). The default implementation converts to a vcl_stringstream
00044   // and calls read(vcl_istream&). Subclasses either need to overload
00045   // this method or read(vil_nitf2_istream&).
00046   virtual bool read(vil_nitf2_istream& input, T& out_value, bool& out_blank);
00047 
00048   // Same as above, but reads value from a vcl_istream (which, unlike a
00049   // vil_nitf2_istream, supports formatted I/O).
00050   virtual bool read_vcl_stream(vcl_istream& input, T& out_value, bool& out_blank);
00051 
00052   // Write value to a vil_nitf2_ostream.  Return success. The default
00053   // implementation calls write(vcl_ostream&). Subclasses need to either
00054   // overload this method or define write(vcl_ostream&).  Returns success.
00055   virtual bool write(vil_nitf2_ostream& output, const T& value);
00056 
00057   // Same as above, but writes value to a vcl_ostream (which, unlike
00058   // vil_nitf2_ostream, supports formatted I/O).
00059   virtual bool write_vcl_stream(vcl_ostream& output, const T& value);
00060 };
00061 
00062 //=============================================================================
00063 // vil_nitf2_typed_field_formatter implementation
00064 //=============================================================================
00065 
00066 #include "vil_nitf2_typed_scalar_field.h"
00067 #include "vil_nitf2_typed_array_field.h"
00068 #include "vil_nitf2_index_vector.h"
00069 
00070 template<typename T>
00071 vil_nitf2_array_field* vil_nitf2_typed_field_formatter<T>::create_array_field(
00072   int num_dimensions, vil_nitf2_field_definition* field_definition)
00073 {
00074   return new vil_nitf2_typed_array_field<T>(num_dimensions, field_definition);
00075 }
00076 
00077 template<typename T>
00078 vil_nitf2_scalar_field* vil_nitf2_typed_field_formatter<T>::read_field(
00079   vil_nitf2_istream& input, bool& out_blank)
00080 {
00081   T value;
00082   if (read( input, value, out_blank )) {
00083     return new vil_nitf2_typed_scalar_field<T>(value, 0);
00084   }
00085   return 0;
00086 }
00087 
00088 template<typename T>
00089 bool vil_nitf2_typed_field_formatter<T>::write_field(
00090   vil_nitf2_ostream& output, const vil_nitf2_scalar_field* field)
00091 {
00092   if (field) {
00093     T val;
00094     if (field->value(val)) {
00095       return write(output, val);
00096     }
00097   }
00098   return false;
00099 }
00100 
00101 template<typename T>
00102 bool vil_nitf2_typed_field_formatter<T>::read(
00103   vil_nitf2_istream& input, T& out_value, bool& out_blank)
00104 {
00105   //hackery for non-binary data (convert to string and create a stringstream from it)
00106   vcl_string str = vil_nitf2_field_formatter::read_string(input, field_width);
00107   vcl_stringstream s(str);
00108   return read_vcl_stream( s, out_value, out_blank );
00109 }
00110 
00111 template<typename T>
00112 bool vil_nitf2_typed_field_formatter<T>::read_vcl_stream(
00113   vcl_istream& /* input */, T& /* out_value */, bool& /* out_blank */)
00114 {
00115   assert(0);
00116   return false;
00117 }
00118 
00119 template<typename T>
00120 bool vil_nitf2_typed_field_formatter<T>::write_vcl_stream(
00121   vcl_ostream& /* output */, const T& /* value */)
00122 {
00123   assert( 0 );
00124   return false;
00125 }
00126 
00127 template<typename T>
00128 bool vil_nitf2_typed_field_formatter<T>::write(
00129   vil_nitf2_ostream& output, const T& value)
00130 {
00131   vcl_stringstream strstr;
00132   write_vcl_stream(strstr, value);
00133   vcl_string str = strstr.str();
00134   output.write(str.c_str(), str.length());
00135   return output.ok();
00136 }
00137 
00138 //=============================================================================
00139 // vil_nitf2_type_field_formatter subclasses
00140 //=============================================================================
00141 
00142 // Reads and writes an integer field, with or without sign.
00143 //
00144 class vil_nitf2_integer_formatter : public vil_nitf2_typed_field_formatter<int>
00145 {
00146  public:
00147   vil_nitf2_integer_formatter(int field_width, bool show_sign = false);
00148 
00149   vil_nitf2_field_formatter* copy() const;
00150 
00151   // partially overridden read/write methods
00152   using vil_nitf2_typed_field_formatter<int>::read;
00153   using vil_nitf2_typed_field_formatter<int>::write;
00154   virtual bool read_vcl_stream(vcl_istream& input, int& out_value, bool& out_blank);
00155   virtual bool write_vcl_stream(vcl_ostream& output, const int& value);
00156 
00157   bool show_sign;
00158 };
00159 
00160 class vil_nitf2_long_long_formatter : public vil_nitf2_typed_field_formatter<vil_nitf2_long>
00161 {
00162  public:
00163   vil_nitf2_long_long_formatter(int field_width, bool show_sign = false);
00164 
00165   vil_nitf2_field_formatter* copy() const;
00166 
00167   // partially overridden read/write methods
00168   using vil_nitf2_typed_field_formatter<vil_nitf2_long>::read;
00169   using vil_nitf2_typed_field_formatter<vil_nitf2_long>::write;
00170   virtual bool read_vcl_stream(vcl_istream& input, vil_nitf2_long& out_value, bool& out_blank);
00171   virtual bool write_vcl_stream(vcl_ostream& output, const vil_nitf2_long& value);
00172 
00173   bool show_sign;
00174 };
00175 
00176 // Reads and writes a fixed point field, with or without sign, and with
00177 // specified precision.
00178 //
00179 class vil_nitf2_double_formatter : public vil_nitf2_typed_field_formatter<double>
00180 {
00181  public:
00182   vil_nitf2_double_formatter(int field_width, int precision, bool show_sign);
00183 
00184   vil_nitf2_field_formatter* copy() const;
00185 
00186   // partially overridden read/write methods
00187   using vil_nitf2_typed_field_formatter<double>::read;
00188   using vil_nitf2_typed_field_formatter<double>::write;
00189   virtual bool read_vcl_stream(vcl_istream& input, double& out_value, bool& out_blank);
00190   virtual bool write_vcl_stream(vcl_ostream& output, const double& value);
00191 
00192   int precision;
00193   bool show_sign;
00194 };
00195 
00196 // Reads and writes a floating point field in exponential format: sign, digit,
00197 // decimal point, mantissa digits, 'E', sign, exponent digits;
00198 // e.g., "+3.1416E+00", which has mantissa width 4 and exponent width 2.
00199 //
00200 class vil_nitf2_exponential_formatter : public vil_nitf2_typed_field_formatter<double>
00201 {
00202  public:
00203   vil_nitf2_exponential_formatter(int mantissa_width, int exponent_width);
00204 
00205   vil_nitf2_field_formatter* copy() const;
00206 
00207   // partially overridden read/write methods
00208   using vil_nitf2_typed_field_formatter<double>::read;
00209   using vil_nitf2_typed_field_formatter<double>::write;
00210   virtual bool read_vcl_stream(vcl_istream& input, double& out_value, bool& out_blank);
00211   virtual bool write_vcl_stream(vcl_ostream& output, const double& value);
00212 
00213   int mantissa_width;
00214   int exponent_width;
00215 };
00216 
00217 // Reads and writes a character field. (I know this seems like overkill,
00218 // but it's part of an inheritance hierarchy.)
00219 //
00220 class vil_nitf2_char_formatter : public vil_nitf2_typed_field_formatter<char>
00221 {
00222  public:
00223   vil_nitf2_char_formatter();
00224 
00225   vil_nitf2_field_formatter* copy() const;
00226 
00227   // partially overridden read/write methods
00228   using vil_nitf2_typed_field_formatter<char>::read;
00229   using vil_nitf2_typed_field_formatter<char>::write;
00230   virtual bool read_vcl_stream(vcl_istream& input, char& out_value, bool& out_blank);
00231   virtual bool write_vcl_stream(vcl_ostream& output, const char& value);
00232 };
00233 
00234 // Reads and writes a binary data field
00235 //
00236 class vil_nitf2_binary_formatter : public vil_nitf2_typed_field_formatter<void*>
00237 {
00238  public:
00239   vil_nitf2_binary_formatter(int width_bytes);
00240 
00241   vil_nitf2_field_formatter* copy() const;
00242 
00243   // partially overridden read/write methods
00244   using vil_nitf2_typed_field_formatter<void*>::read_vcl_stream;
00245   using vil_nitf2_typed_field_formatter<void*>::write_vcl_stream;
00246 
00247   // Overload read() instead of read_vcl_stream() to read binary data without
00248   // converting to string, because zero data would prematurely null-terminate
00249   // the stringstream.
00250   virtual bool read( vil_nitf2_istream& input, void*& out_value, bool& out_blank );
00251 
00252   /// Overload to write() instead of write_vcl_stream() to write binary data
00253   // (see preceding comment).
00254   virtual bool write(vil_nitf2_ostream& output, void*const& value);
00255 };
00256 
00257 // Reads and writes a vcl_string field.
00258 //
00259 class vil_nitf2_string_formatter : public vil_nitf2_typed_field_formatter<vcl_string>
00260 {
00261  public:
00262   // Character sets
00263   enum enum_char_set { ECS, ECSA, BCS, BCSA };
00264 
00265   // Constructor
00266   vil_nitf2_string_formatter(int field_width, enum_char_set char_set = ECS);
00267 
00268   vil_nitf2_field_formatter* copy() const;
00269 
00270   // Destructor
00271   virtual ~vil_nitf2_string_formatter() {}
00272 
00273   // partially overridden read/write methods
00274   using vil_nitf2_typed_field_formatter<vcl_string>::read;
00275   using vil_nitf2_typed_field_formatter<vcl_string>::write;
00276   virtual bool read_vcl_stream(vcl_istream& input, vcl_string& out_value, bool& out_blank );
00277   virtual bool write_vcl_stream(vcl_ostream& output, const vcl_string& value);
00278 
00279   virtual bool is_valid(vcl_string value) const;
00280 
00281   // Member variable
00282   enum_char_set char_set;
00283 };
00284 
00285 // Helper class for vil_nitf2_enum_string_formatter. Represents a vcl_string enumeration.
00286 //
00287 class vil_nitf2_enum_values : public vcl_map<vcl_string, vcl_string>
00288 {
00289  public:
00290   vil_nitf2_enum_values& value(vcl_string token, vcl_string pretty_name = "");
00291 };
00292 
00293 // Reads and writes an enumerated vcl_string field.
00294 // To Do: Reimplement this to represent its value using a new class
00295 // NitfEnum_value, that outputs its pretty_name by default.
00296 //
00297 class vil_nitf2_enum_string_formatter : public vil_nitf2_string_formatter
00298 {
00299  public:
00300   // Constructor
00301   vil_nitf2_enum_string_formatter(int field_width, const vil_nitf2_enum_values&);
00302 
00303   vil_nitf2_field_formatter* copy() const;
00304 
00305   // Is specified value valid?
00306   bool is_valid_value(vcl_string value) const;
00307 
00308  private:
00309   void validate_value_map();
00310   vil_nitf2_enum_values value_map;
00311 };
00312 
00313 // Reads and write a date/time field.
00314 //
00315 class vil_nitf2_date_time_formatter : public vil_nitf2_typed_field_formatter<vil_nitf2_date_time>
00316 {
00317  public:
00318   // Constructor
00319   vil_nitf2_date_time_formatter(int field_width);
00320 
00321   vil_nitf2_field_formatter* copy() const;
00322 
00323   // partially overridden read/write methods
00324   using vil_nitf2_typed_field_formatter<vil_nitf2_date_time>::read;
00325   using vil_nitf2_typed_field_formatter<vil_nitf2_date_time>::write;
00326   virtual bool read_vcl_stream(vcl_istream& input, vil_nitf2_date_time& out_value, bool& out_blank);
00327   virtual bool write_vcl_stream(vcl_ostream& output, const vil_nitf2_date_time& value);
00328 };
00329 
00330 // Reads and writes a location field.
00331 //
00332 class vil_nitf2_location_formatter : public vil_nitf2_typed_field_formatter<vil_nitf2_location*>
00333 {
00334  public:
00335   // Constructor
00336   vil_nitf2_location_formatter(int field_width);
00337 
00338   vil_nitf2_field_formatter* copy() const;
00339 
00340   // partially overridden read/write methods
00341   using vil_nitf2_typed_field_formatter<vil_nitf2_location*>::read;
00342   using vil_nitf2_typed_field_formatter<vil_nitf2_location*>::write;
00343   virtual bool read_vcl_stream(vcl_istream& input, vil_nitf2_location*& out_value, bool& out_blank);
00344   virtual bool write_vcl_stream(vcl_ostream& output, vil_nitf2_location*const& value);
00345 
00346   // Converts overall field width to seconds precision for DMSH formatted
00347   // field, ddmmss.sssHdddmmss.sssH
00348   static int sec_precision(int field_width) { return (field_width-17)/2; }
00349 
00350   // Converts overall field width to degrees precision for degrees formatted
00351   // field, +dd.ddd+ddd.ddd
00352   static int deg_precision(int field_width) { return (field_width-9)/2; }
00353 };
00354 
00355 // Reads and writes a TRE sequence field
00356 //
00357 class vil_nitf2_tagged_record_sequence_formatter :
00358   public vil_nitf2_typed_field_formatter<vil_nitf2_tagged_record_sequence>
00359 {
00360  public:
00361   // Constructor
00362   vil_nitf2_tagged_record_sequence_formatter();
00363 
00364   vil_nitf2_field_formatter* copy() const;
00365 
00366   // partially overridden read/write methods
00367   using vil_nitf2_typed_field_formatter<vil_nitf2_tagged_record_sequence>::read_vcl_stream;
00368   using vil_nitf2_typed_field_formatter<vil_nitf2_tagged_record_sequence>::write_vcl_stream;
00369 
00370   // Overload read() instead of read_vcl_stream() to read binary data without
00371   // converting to string, because zero data would prematurely null-terminate
00372   // the stringstream.
00373   virtual bool read( vil_nitf2_istream& input, vil_nitf2_tagged_record_sequence& out_value, bool& out_blank );
00374 
00375   /// Overload to write() instead of write_vcl_stream() to write binary data
00376   // (see preceding comment).
00377   virtual bool write(vil_nitf2_ostream& output, vil_nitf2_tagged_record_sequence& value);
00378 };
00379 
00380 #endif // VIL_NITF2_TYPED_FIELD_FORMATTER_H