core/vil/file_formats/vil_nitf2_typed_field_formatter.cxx
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 #include "vil_nitf2_typed_field_formatter.h"
00006 
00007 #include <vcl_algorithm.h>
00008 #include <vcl_iomanip.h>
00009 #include <vcl_iostream.h>
00010 #include <vcl_utility.h>
00011 #include <vcl_compiler.h> //for VCL_WIN32
00012 
00013 #include <vcl_cerrno.h>
00014 
00015 //==============================================================================
00016 // Class vil_nitf2_date_time_formatter
00017 
00018 vil_nitf2_date_time_formatter::vil_nitf2_date_time_formatter(int field_width)
00019   : vil_nitf2_typed_field_formatter<vil_nitf2_date_time>(vil_nitf2::type_date_time, field_width)
00020 {}
00021 
00022 vil_nitf2_field_formatter* vil_nitf2_date_time_formatter::copy() const
00023 {
00024   return new vil_nitf2_date_time_formatter(field_width);
00025 }
00026 
00027 bool vil_nitf2_date_time_formatter::read_vcl_stream(vcl_istream& input, vil_nitf2_date_time& out_value, bool& out_blank)
00028 {
00029   return out_value.read(input, field_width, out_blank);
00030 }
00031 
00032 bool vil_nitf2_date_time_formatter::write_vcl_stream(vcl_ostream& output, const vil_nitf2_date_time& value)
00033 {
00034   return value.write(output, field_width);
00035 }
00036 
00037 //==============================================================================
00038 // Class vil_nitf2_location_formatter
00039 
00040 vil_nitf2_location_formatter::vil_nitf2_location_formatter(int field_width)
00041   : vil_nitf2_typed_field_formatter<vil_nitf2_location*>(vil_nitf2::type_location, field_width)
00042 {}
00043 
00044 vil_nitf2_field_formatter* vil_nitf2_location_formatter::copy() const
00045 {
00046   return new vil_nitf2_location_formatter(field_width);
00047 }
00048 
00049 bool vil_nitf2_location_formatter::read_vcl_stream(vcl_istream& input,
00050                                                    vil_nitf2_location*& out_value,
00051                                                    bool& out_blank)
00052 {
00053   vcl_streampos tag_start_pos = input.tellg();
00054   vil_nitf2_location* location = new vil_nitf2_location_degrees(deg_precision(field_width));
00055   if (location->read(input, field_width, out_blank)) {
00056     out_value = location;
00057     return true;
00058   } else {
00059     delete location;
00060     input.seekg(tag_start_pos);
00061     location = new vil_nitf2_location_dmsh(sec_precision(field_width));
00062     if (location->read(input, field_width, out_blank)) {
00063       out_value = location;
00064       return true;
00065     } else {
00066       delete location;
00067       out_value = 0;
00068       return false;
00069     }
00070   }
00071 }
00072 
00073 bool vil_nitf2_location_formatter::write_vcl_stream(vcl_ostream& output, vil_nitf2_location*const& value)
00074 {
00075   return value->write(output, field_width);
00076 }
00077 
00078 //==============================================================================
00079 // Class vil_nitf2_integer_formatter
00080 
00081 vil_nitf2_integer_formatter::vil_nitf2_integer_formatter(int field_width, bool show_sign )
00082   : vil_nitf2_typed_field_formatter<int>(vil_nitf2::type_int, field_width),
00083       show_sign(show_sign)
00084 {
00085   //Assuming that int is 32 bits, then it can't represent a value higher than
00086   // (10^32)/2 ... that is 2147483648.
00087   //assert( field_width < 10 );
00088 }
00089 
00090 vil_nitf2_field_formatter* vil_nitf2_integer_formatter::copy() const
00091 {
00092   return new vil_nitf2_integer_formatter(field_width, show_sign);
00093 }
00094 
00095 bool
00096 vil_nitf2_integer_formatter::read_vcl_stream(vcl_istream& input,
00097                                              int& out_value, bool& out_blank)
00098 {
00099   char* cstr;
00100   if (!read_c_str(input, field_width, cstr, out_blank)) {
00101     delete[] cstr;
00102     return false;
00103   }
00104   char* endp;
00105   errno = 0;
00106   out_value = (int)strtol(cstr, &endp, 10);
00107   bool sign_ok = check_sign(cstr, show_sign);
00108   bool retVal = (endp-cstr)==field_width // processed all chars
00109          && errno==0              // with no errors
00110          && sign_ok;              // sign shown as expected
00111   delete[] cstr;
00112   return retVal;
00113 }
00114 
00115 bool vil_nitf2_integer_formatter::write_vcl_stream(vcl_ostream& output, const int& value)
00116 {
00117   output << vcl_setw(field_width) << vcl_right << vcl_setfill('0');
00118   if (show_sign) {
00119     output << vcl_showpos;
00120   } else {
00121     output << vcl_noshowpos;
00122   }
00123   output << value;
00124   return !output.fail();
00125 }
00126 
00127 //==============================================================================
00128 // Class vil_nitf2_long_long_formatter
00129 
00130 vil_nitf2_long_long_formatter::
00131 vil_nitf2_long_long_formatter(int field_width, bool show_sign)
00132   : vil_nitf2_typed_field_formatter<vil_nitf2_long>(vil_nitf2::type_long_long, field_width),
00133     show_sign(show_sign)
00134 {}
00135 
00136 vil_nitf2_field_formatter* vil_nitf2_long_long_formatter::copy() const
00137 {
00138   return new vil_nitf2_long_long_formatter(field_width, show_sign);
00139 }
00140 
00141 bool vil_nitf2_long_long_formatter::
00142 read_vcl_stream(vcl_istream& input, vil_nitf2_long& out_value, bool& out_blank)
00143 {
00144   char* cstr;
00145   if (!read_c_str(input, field_width, cstr, out_blank)) {
00146     delete[] cstr;
00147     return false;
00148   }
00149   bool conversion_ok;
00150   char* endp;
00151   errno = 0;
00152 
00153 #if VXL_HAS_INT_64
00154 
00155 #if defined VCL_VC
00156   out_value = _strtoi64(cstr, &endp, 10);
00157   conversion_ok = (endp-cstr)==field_width;   // processed all chars
00158 #elif defined VCL_BORLAND
00159   out_value = _atoi64( cstr );
00160   conversion_ok = true;                       //no error checking available
00161 #else
00162   out_value = ::strtoll(cstr, &endp, 10);     // in Standard C Library
00163   conversion_ok = (endp-cstr)==field_width;   // processed all chars
00164 #endif
00165 
00166 #else //VXL_HAS_INT_64
00167   out_value = strtol(cstr, &endp, 10);
00168   conversion_ok = (endp-cstr)==field_width;   // processed all chars
00169 #endif //VXL_HAS_INT_64
00170 
00171   bool sign_ok = check_sign(cstr, show_sign);
00172   delete[] cstr;
00173   return conversion_ok
00174          && errno==0              // with no errors
00175          && sign_ok;              // sign shown as expected
00176 }
00177 
00178 bool vil_nitf2_long_long_formatter::write_vcl_stream(vcl_ostream& output, const vil_nitf2_long& value)
00179 {
00180   output << vcl_setw(field_width) << vcl_right << vcl_setfill('0');
00181   if (show_sign) {
00182     output << vcl_showpos;
00183   } else {
00184     output << vcl_noshowpos;
00185   }
00186   output << value;
00187   return !output.fail();
00188 }
00189 
00190 //==============================================================================
00191 // Class vil_nitf2_double_formatter
00192 
00193 vil_nitf2_double_formatter::
00194 vil_nitf2_double_formatter(int field_width, int precision, bool show_sign)
00195   : vil_nitf2_typed_field_formatter<double>(vil_nitf2::type_double, field_width),
00196     precision(precision),
00197     show_sign(show_sign)
00198 {}
00199 
00200 vil_nitf2_field_formatter* vil_nitf2_double_formatter::copy() const
00201 {
00202   return new vil_nitf2_double_formatter(field_width, precision, show_sign);
00203 }
00204 
00205 bool vil_nitf2_double_formatter::read_vcl_stream(vcl_istream& input,
00206                                                  double& out_value, bool& out_blank)
00207 {
00208   char* cstr;
00209   if (!read_c_str(input, field_width, cstr, out_blank)) {
00210     delete[] cstr;
00211     return false;
00212   }
00213   char* endp;
00214   errno=0;
00215   out_value = strtod(cstr, &endp);
00216   bool sign_ok = check_sign(cstr, show_sign);
00217   bool decimal_ok = cstr[(field_width-precision)-1]=='.';
00218   bool retVal =
00219     (endp-cstr)==field_width  // processed all chars
00220      && errno==0              // with no errors
00221      && decimal_ok            // decimal point in right place
00222      && sign_ok;              // sign shown as expected
00223   delete[] cstr;
00224   return retVal;
00225 }
00226 
00227 bool vil_nitf2_double_formatter::write_vcl_stream(vcl_ostream& output, const double& value)
00228 {
00229   output << vcl_setw(field_width) << vcl_fixed;
00230   if (show_sign) {
00231     output << vcl_showpos;
00232   } else {
00233     output << vcl_noshowpos;
00234   }
00235   output << vcl_internal << vcl_setfill('0') << vcl_setprecision(precision)
00236          << value;
00237   return !output.fail();
00238 }
00239 
00240 //==============================================================================
00241 // Class vil_nitf2_exponential_formatter
00242 
00243 vil_nitf2_exponential_formatter::
00244 vil_nitf2_exponential_formatter(int mantissa_width, int exponent_width)
00245   : vil_nitf2_typed_field_formatter<double>(vil_nitf2::type_double,
00246                                             mantissa_width + exponent_width + 5),
00247     mantissa_width(mantissa_width),
00248     exponent_width(exponent_width)
00249 {}
00250 
00251 vil_nitf2_field_formatter* vil_nitf2_exponential_formatter::copy() const
00252 {
00253   return new vil_nitf2_exponential_formatter(mantissa_width, exponent_width);
00254 }
00255 
00256 bool vil_nitf2_exponential_formatter::read_vcl_stream(vcl_istream& input,
00257                                                       double& out_value, bool& out_blank)
00258 {
00259   char* cstr;
00260   if (!read_c_str(input, field_width, cstr, out_blank)) {
00261     delete[] cstr;
00262     return false;
00263   }
00264   char* endp;
00265   errno=0;
00266   out_value = strtod(cstr, &endp);
00267   // Check locations of non-digits in format: +d.dddddE+dd
00268   const char base_sign = cstr[0];
00269   const bool base_sign_ok = base_sign=='+' || base_sign=='-';
00270   const bool decimal_ok = cstr[2]=='.';
00271   const char e_ok = cstr[3+mantissa_width]=='E';
00272   const char exp_sign = cstr[4+mantissa_width];
00273   const bool exp_sign_ok = exp_sign=='+' || exp_sign=='-';
00274   bool retVal =
00275     (endp-cstr)==field_width   // processed all chars
00276      && errno==0               // read a number with no errors
00277      && base_sign_ok           // base sign in right place
00278      && decimal_ok             // decimal point in right place
00279      && e_ok                   // 'E' in right place
00280      && exp_sign_ok;           // exponent sign in right place
00281   delete[] cstr;
00282   return retVal;
00283 }
00284 
00285 bool vil_nitf2_exponential_formatter::write_vcl_stream(vcl_ostream& output,
00286                                                        const double& value)
00287 {
00288   // Can't control the width of exponent (it's 3) so write it to a buffer first
00289   vcl_ostringstream buffer;
00290   buffer << vcl_setw(field_width) << vcl_scientific
00291          << vcl_showpos << vcl_uppercase
00292          << vcl_internal << vcl_setfill('0') << vcl_setprecision(mantissa_width)
00293          << value;
00294   vcl_string buffer_string = buffer.str();
00295   unsigned int length = (unsigned int)(buffer_string.length());
00296   // Write everything up to the exponent sign
00297   output << buffer_string.substr(0,length-3);
00298   // Write exponent digits, padding or unpadding them to desired width
00299   output << vcl_setw(exponent_width) << vcl_setfill('0')
00300          << buffer_string.substr(length-vcl_min(3,exponent_width), vcl_min(3,exponent_width));
00301   return !output.fail();
00302 }
00303 
00304 //==============================================================================
00305 // Class vil_nitf2_binary_formatter
00306 
00307 vil_nitf2_binary_formatter::vil_nitf2_binary_formatter(int width_bytes)
00308   : vil_nitf2_typed_field_formatter<void*>(vil_nitf2::type_binary, width_bytes)
00309 {}
00310 
00311 vil_nitf2_field_formatter* vil_nitf2_binary_formatter::copy() const
00312 {
00313   return new vil_nitf2_binary_formatter(field_width);
00314 }
00315 
00316 bool vil_nitf2_binary_formatter::read(vil_stream& input, void*& out_value,
00317                                       bool& out_blank)
00318 {
00319   out_value = (void*)(new char[field_width]);
00320   out_blank = false; //no such thing as 'blank' binary data
00321   return input.read( out_value, field_width ) == field_width;
00322 }
00323 
00324 bool vil_nitf2_binary_formatter::write(vil_nitf2_ostream& output, void*const& value)
00325 {
00326   return output.write( value, field_width ) == field_width;
00327 }
00328 
00329 //==============================================================================
00330 // Class vil_nitf2_char_formatter
00331 
00332 vil_nitf2_char_formatter::vil_nitf2_char_formatter()
00333   : vil_nitf2_typed_field_formatter<char>(vil_nitf2::type_char, 1)
00334 {}
00335 
00336 vil_nitf2_field_formatter* vil_nitf2_char_formatter::copy() const
00337 {
00338   return new vil_nitf2_char_formatter();
00339 }
00340 
00341 bool vil_nitf2_char_formatter::read_vcl_stream(vcl_istream& input, char& out_value, bool& out_blank)
00342 {
00343   input.get(out_value);
00344   //int numRead = input.read(&out_value, 1);
00345   out_blank = (out_value == ' ');
00346   return !input.fail();
00347   //return numRead == 1;
00348 }
00349 
00350 bool vil_nitf2_char_formatter::write_vcl_stream(vcl_ostream& output, const char& value)
00351 {
00352   output << value;
00353   return !output.fail();
00354 }
00355 
00356 //==============================================================================
00357 // Class vil_nitf2_string_formatter
00358 
00359 vil_nitf2_string_formatter::
00360 vil_nitf2_string_formatter(int field_width, enum_char_set char_set)
00361   : vil_nitf2_typed_field_formatter<vcl_string>(vil_nitf2::type_string, field_width),
00362     char_set(char_set)
00363 {}
00364 
00365 vil_nitf2_field_formatter* vil_nitf2_string_formatter::copy() const
00366 {
00367   return new vil_nitf2_string_formatter(field_width, char_set);
00368 }
00369 
00370 bool vil_nitf2_string_formatter::read_vcl_stream(vcl_istream& input,
00371                                                  vcl_string& out_value,
00372                                                  bool& out_blank)
00373 {
00374   char* cstr;
00375   if (!read_c_str(input, field_width, cstr, out_blank)) {
00376     delete[] cstr;
00377     return false;
00378   }
00379   vcl_string str = vcl_string(cstr);
00380   delete[] cstr;
00381   vcl_string::size_type end_pos = str.find_last_not_of(" ")+1;
00382   if (end_pos == vcl_string::npos) {
00383     out_value = str;
00384   } else {
00385     out_value = str.substr(0, end_pos);
00386   }
00387   return is_valid(out_value);
00388 }
00389 
00390 bool vil_nitf2_string_formatter::write_vcl_stream(vcl_ostream& output, const vcl_string& value)
00391 {
00392   output << vcl_setw(field_width) << vcl_left << vcl_setfill(' ') << value;
00393   return !output.fail();
00394 }
00395 
00396 bool vil_nitf2_string_formatter::is_valid(vcl_string /*value*/) const
00397 {
00398   // to do: check char set
00399   return true;
00400 }
00401 
00402 //==============================================================================
00403 // Class vil_nitf2_enum_string_formatter
00404 
00405 vil_nitf2_enum_string_formatter::
00406 vil_nitf2_enum_string_formatter(int field_width, const vil_nitf2_enum_values& value_map)
00407   : vil_nitf2_string_formatter(field_width), value_map(value_map)
00408 {
00409   //field_type = Nitf::Enum;
00410   validate_value_map();
00411 }
00412 
00413 vil_nitf2_field_formatter* vil_nitf2_enum_string_formatter::copy() const
00414 {
00415   return new vil_nitf2_enum_string_formatter(field_width, value_map);
00416 }
00417 
00418 void vil_nitf2_enum_string_formatter::validate_value_map()
00419 {
00420   for (vil_nitf2_enum_values::iterator entry = value_map.begin();
00421        entry != value_map.end(); ++entry)
00422   {
00423     vcl_string token = entry->first;
00424     if (int(token.length()) > field_width) {
00425       vcl_cerr << "vil_nitf2_enum_values: WARNING: Ignoring token "
00426                << token << "; length exceeds declared field width.\n";
00427       // Should probably remove it so that is_valid() doesn't match it.
00428       // On the other hand, this class will never read a token of this
00429       // length, so don't worry about it.
00430     }
00431   }
00432 }
00433 
00434 bool vil_nitf2_enum_string_formatter::is_valid_value(vcl_string token) const
00435 {
00436   return value_map.find(token) != value_map.end();
00437 }
00438 
00439 //==============================================================================
00440 // Class vil_nitf2_enum_values
00441 
00442 vil_nitf2_enum_values& vil_nitf2_enum_values::value(vcl_string token, vcl_string pretty_name)
00443 {
00444   if (!insert(vcl_make_pair(token, pretty_name)).second) {
00445     vcl_cerr << "vil_nitf2_enum_values: WARNING: Ignoring definition "
00446              << token << "; token already defined for this enumeration.\n";
00447   }
00448   return *this;
00449 }
00450 
00451 //==============================================================================
00452 // Class vil_nitf2_tre_sequence_formatter
00453 
00454 #include "vil_nitf2_tagged_record.h"
00455 
00456 vil_nitf2_tagged_record_sequence_formatter::vil_nitf2_tagged_record_sequence_formatter()
00457   : vil_nitf2_typed_field_formatter<vil_nitf2_tagged_record_sequence>(
00458       vil_nitf2::type_tagged_record_sequence, 1 /* ignored */)
00459 {}
00460 
00461 vil_nitf2_field_formatter*
00462 vil_nitf2_tagged_record_sequence_formatter::copy() const
00463 {
00464   return new vil_nitf2_tagged_record_sequence_formatter();
00465 }
00466 
00467 bool vil_nitf2_tagged_record_sequence_formatter::
00468 read( vil_nitf2_istream& input,
00469       vil_nitf2_tagged_record_sequence& out_value, bool& out_blank )
00470 {
00471   if (field_width <= 0) return false;
00472   vil_streampos current = input.tell();
00473   vil_streampos end = current + field_width;
00474   bool error_reading_tre = false;
00475   out_value.clear();
00476   while (input.tell() < end && !error_reading_tre) {
00477     vil_nitf2_tagged_record* record = vil_nitf2_tagged_record::create(input);
00478     if (record) {
00479       out_value.push_back(record); // out_value assumes ownership of record
00480     }
00481     error_reading_tre &= !record;
00482   }
00483   if (input.tell() != end) { // TO DO: what does end equal at EOF?
00484     VIL_NITF2_LOG(log_info) << "\nSeeking to end of TRE sequence field.\n";
00485     input.seek(end);
00486     if (input.tell() != end) {
00487       vcl_cerr << "\nSeek to end of TRE sequence field failed.\n";
00488       error_reading_tre = true;
00489     }
00490   }
00491   out_blank = false;
00492   return !error_reading_tre;
00493 }
00494 
00495 bool vil_nitf2_tagged_record_sequence_formatter::
00496 write(vil_nitf2_ostream& /*output*/, vil_nitf2_tagged_record_sequence& /*value*/ )
00497 {
00498   return false;
00499 }