core/vil/file_formats/vil_nitf2_tagged_record.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_tagged_record.h"
00006 
00007 #include <vcl_sstream.h>
00008 #include <vcl_iomanip.h>
00009 #include <vcl_iostream.h>
00010 #include <vcl_string.h>
00011 
00012 #include <vil/vil_stream_core.h>
00013 #include <vil/vil_stream_section.h>
00014 
00015 #include "vil_nitf2_tagged_record_definition.h"
00016 #include "vil_nitf2_field_definition.h"
00017 #include "vil_nitf2_field_sequence.h"
00018 #include "vil_nitf2_index_vector.h"
00019 #include "vil_nitf2_typed_field_formatter.h"
00020 #include "vil_nitf2_scalar_field.h"
00021 
00022 vil_nitf2_field_definition& vil_nitf2_tagged_record::s_length_definition()
00023 {
00024   static vil_nitf2_field_definition length_definition(
00025     "CEL", "Extension Length", new vil_nitf2_integer_formatter(5));
00026   return length_definition;
00027 }
00028 
00029 vil_nitf2_field_definition& vil_nitf2_tagged_record::s_tag_definition()
00030 {
00031   static vil_nitf2_field_definition tag_definition (
00032     "CETAG", "Extension Tag", new vil_nitf2_string_formatter(6));
00033   return tag_definition;
00034 }
00035 
00036 vil_nitf2_integer_formatter& vil_nitf2_tagged_record::s_length_formatter()
00037 {
00038   static vil_nitf2_integer_formatter length_formatter(5);
00039   return length_formatter;
00040 }
00041 
00042 vil_nitf2_string_formatter& vil_nitf2_tagged_record::s_tag_formatter()
00043 {
00044   static vil_nitf2_string_formatter tag_formatter(6);
00045   return tag_formatter;
00046 }
00047 
00048 vcl_string vil_nitf2_tagged_record::name() const
00049 {
00050   vcl_string cetag;
00051   if ( m_tag_field->value(cetag) ) return cetag;
00052   else                             return "<Unknown>";
00053 }
00054 
00055 vcl_string vil_nitf2_tagged_record::pretty_name() const
00056 {
00057   if ( m_definition ) return m_definition->m_pretty_name;
00058   else                return "<unknown>";
00059 }
00060 
00061 vil_nitf2_tagged_record* vil_nitf2_tagged_record::create(vil_nitf2_istream& input)
00062 {
00063   vil_nitf2_tagged_record* record = new vil_nitf2_tagged_record();
00064   if (record->read(input)) {
00065     return record;
00066   } else {
00067     delete record;
00068     return 0;
00069   }
00070 }
00071 
00072 bool vil_nitf2_tagged_record::read(vil_nitf2_istream& input)
00073 {
00074   // Read TRE tag
00075   m_tag_field = vil_nitf2_scalar_field::read(input, &s_tag_definition());
00076   if (!m_tag_field) {
00077     vcl_cerr << "Error reading extension tag at offset " << input.tell() << ".\n";
00078     // Can't continue reading file
00079     return false;
00080   }
00081   vcl_string cetag;
00082   m_tag_field->value(cetag);
00083 
00084   // Read TRE data length
00085   m_length_field = vil_nitf2_scalar_field::read(input, &s_length_definition());
00086   if (!m_length_field) {
00087     vcl_cerr << "Error reading extension length for tag " << cetag << ".\n";
00088     // Can't continue reading file
00089     return false;
00090   }
00091   m_length_field->value(m_length);
00092 
00093   // See if this record is defined ...
00094   vil_nitf2_tagged_record_definition* record_definition =
00095     vil_nitf2_tagged_record_definition::find(cetag);
00096 
00097   // ... if not, skip ahead to next record ...
00098   if (record_definition == 0) {
00099     VIL_NITF2_LOG(log_info) << "Skipping unknown record " << cetag << ".\n";
00100     // Return whether I've found end of record
00101     //input.seekg(ceLength, vcl_ios::cur);
00102     input.seek(input.tell()+m_length);
00103     return input.ok();
00104   }
00105   // ... otherwise, populate this record's fields.
00106   // First save the position to check later that we read entire record
00107   vil_streampos record_data_start_pos = input.tell();
00108   m_definition = record_definition;
00109   m_field_sequence = new vil_nitf2_field_sequence(record_definition->field_definitions());
00110   m_field_sequence->read(input);
00111 
00112   // Check that the expected amount of data was read
00113   vil_streampos expected_pos = record_data_start_pos;
00114   expected_pos += m_length;
00115   if (input.tell() != expected_pos) {
00116     vcl_cerr << "vil_nitf2_tagged_record::read(): Read " << input.tell() - record_data_start_pos
00117              << " bytes instead of " << m_length << " as expected in "<<cetag<<".\n";
00118     // Attempt to reposition input stream to end of record; return whether
00119     // successful
00120     input.seek(expected_pos);
00121     return input.ok();
00122   }
00123   // At end of record, as expected
00124   return true;
00125 }
00126 
00127 bool vil_nitf2_tagged_record::get_value(vcl_string tag, int& out_value) const
00128 { return m_field_sequence->get_value(tag, out_value); }
00129 
00130 bool vil_nitf2_tagged_record::get_value(vcl_string tag, double& out_value) const
00131 { return m_field_sequence->get_value(tag, out_value); }
00132 
00133 bool vil_nitf2_tagged_record::get_value(vcl_string tag, char& out_value) const
00134 { return m_field_sequence->get_value(tag, out_value); }
00135 bool vil_nitf2_tagged_record::get_value(vcl_string tag, void*& out_value) const
00136 { return m_field_sequence->get_value(tag, out_value); }
00137 
00138 bool vil_nitf2_tagged_record::get_value(vcl_string tag, vcl_string& out_value) const
00139 { return m_field_sequence->get_value(tag, out_value); }
00140 
00141 bool vil_nitf2_tagged_record::get_value(vcl_string tag, vil_nitf2_location*& out_value) const
00142 { return m_field_sequence->get_value(tag, out_value); }
00143 
00144 bool vil_nitf2_tagged_record::get_value(vcl_string tag, vil_nitf2_date_time& out_value) const
00145 { return m_field_sequence->get_value(tag, out_value); }
00146 
00147 #if VXL_HAS_INT_64
00148 // if not VXL_HAS_INT_64 isn't defined the vil_nitf2_long is the same as just plain 'int'
00149 // and this function will be a duplicate of that get_value
00150 bool vil_nitf2_tagged_record::get_value(vcl_string tag, vil_nitf2_long& out_value) const
00151 { return m_field_sequence->get_value(tag, out_value); }
00152 #endif
00153 
00154 bool vil_nitf2_tagged_record::get_value(vcl_string tag, const vil_nitf2_index_vector& indexes, int& out_value) const
00155 { return m_field_sequence->get_value(tag, indexes, out_value); }
00156 
00157 bool vil_nitf2_tagged_record::get_value(vcl_string tag, const vil_nitf2_index_vector& indexes, double& out_value) const
00158 { return m_field_sequence->get_value(tag, indexes, out_value); }
00159 
00160 bool vil_nitf2_tagged_record::get_value(vcl_string tag, const vil_nitf2_index_vector& indexes, char& out_value) const
00161 { return m_field_sequence->get_value(tag, indexes, out_value); }
00162 
00163 bool vil_nitf2_tagged_record::get_value(vcl_string tag, const vil_nitf2_index_vector& indexes, void*& out_value) const
00164 { return m_field_sequence->get_value(tag, indexes, out_value); }
00165 
00166 bool vil_nitf2_tagged_record::get_value(vcl_string tag, const vil_nitf2_index_vector& indexes, vcl_string& out_value) const
00167 { return m_field_sequence->get_value(tag, indexes, out_value); }
00168 
00169 bool vil_nitf2_tagged_record::get_value(vcl_string tag, const vil_nitf2_index_vector& indexes, vil_nitf2_location*& out_value) const
00170 { return m_field_sequence->get_value(tag, indexes, out_value); }
00171 
00172 bool vil_nitf2_tagged_record::get_value(vcl_string tag, const vil_nitf2_index_vector& indexes, vil_nitf2_date_time& out_value) const
00173 { return m_field_sequence->get_value(tag, indexes, out_value); }
00174 
00175 #if VXL_HAS_INT_64
00176 // if not VXL_HAS_INT_64 isn't defined the vil_nitf2_long is the same as just plain 'int'
00177 // and this function will be a duplicate of that get_value
00178 bool vil_nitf2_tagged_record::get_value(vcl_string tag, const vil_nitf2_index_vector& indexes, vil_nitf2_long& out_value) const
00179 { return m_field_sequence->get_value(tag, indexes, out_value); }
00180 #endif
00181 
00182 // Macro to define both overloads of get_values()
00183 #define VIL_NITF2_TAGGED_RECORD_GET_VALUES(T) \
00184 bool vil_nitf2_tagged_record::get_values(vcl_string tag, const vil_nitf2_index_vector& indexes, \
00185                                          vcl_vector<T>& out_values, bool clear_out_values) const \
00186 { return m_field_sequence->get_values(tag, indexes, out_values, clear_out_values); } \
00187 bool vil_nitf2_tagged_record::get_values(vcl_string tag, vcl_vector<T>& out_values) const \
00188 { return m_field_sequence->get_values(tag, out_values); }
00189 
00190 VIL_NITF2_TAGGED_RECORD_GET_VALUES(int);
00191 VIL_NITF2_TAGGED_RECORD_GET_VALUES(double);
00192 VIL_NITF2_TAGGED_RECORD_GET_VALUES(char);
00193 VIL_NITF2_TAGGED_RECORD_GET_VALUES(void*);
00194 VIL_NITF2_TAGGED_RECORD_GET_VALUES(vcl_string);
00195 VIL_NITF2_TAGGED_RECORD_GET_VALUES(vil_nitf2_location*);
00196 VIL_NITF2_TAGGED_RECORD_GET_VALUES(vil_nitf2_date_time);
00197 #if VXL_HAS_INT_64
00198   VIL_NITF2_TAGGED_RECORD_GET_VALUES(vil_nitf2_long);
00199 #endif
00200 
00201 
00202 vil_nitf2_tagged_record::vil_nitf2_tagged_record()
00203   : m_length_field(0), m_tag_field(0), m_length(0), m_definition(0), m_field_sequence(0)
00204 {}
00205 
00206 // TO DO: rewrite this method a sequence of unit tests!
00207 //
00208 bool vil_nitf2_tagged_record::test()
00209 {
00210   bool error = false;
00211   const char* test_tre_tag = "@TEST@";
00212   // Example Tagged Record Extension definition
00213   vil_nitf2_tagged_record_definition::define(test_tre_tag, "Test Definition" )
00214    .field("MTI_DP",           "Destination Point",     NITF_INT(2))
00215    .field("MTI_PACKET_ID",    "MTI Packed ID Number",  NITF_INT(3))
00216    .field("DATIME",           "Scan Date & Time",      NITF_DAT(14), true)
00217    .field("ACFT_LOC",         "Aircraft Position",     NITF_LOC(21))
00218    .field("ACFT_LOC2",        "Aircraft Position 2",   NITF_LOC(21))
00219    .field("SQUINT_ANGLE",     "Squint Angle",          NITF_DBL(6, 2, true), true)
00220    .field("NO_VALID_TARGETS", "Number of Targets",     NITF_INT(3))
00221    .field("TGT_CAT",        "Target Classification Category",
00222           NITF_ENUM(1, vil_nitf2_enum_values()
00223             .value("H", "Helicopter")
00224             .value("T", "Tracked")
00225             .value("U", "Unknown")
00226             .value("W", "Wheeled")
00227             .value("TOO LONG", "Too long value test")
00228             .value("T", "Duplicate value test")))
00229    .repeat(new vil_nitf2_field_value<int>("NO_VALID_TARGETS"),
00230            vil_nitf2_field_definitions()
00231            .field("TGT_n_SPEED", "Target Estimated Ground Speed", NITF_INT(4), true)
00232            .field("TGT_n_CAT",   "Target Classification Category",
00233                   NITF_ENUM(1, vil_nitf2_enum_values()
00234                             .value("H", "Helicopter")
00235                             .value("T", "Tracked")
00236                             .value("U", "Unknown")
00237                             .value("W", "Wheeled")),
00238                   true))
00239    .field("TEST_NEG_COND", "Test False Condition", NITF_STR_BCSA(14), false,
00240           0, new vil_nitf2_field_value_greater_than<int>("MTI_DP", 5))
00241    .field("TEST_POS_COND", "Test True Condition",  NITF_STR_BCSA(14), false,
00242           0, new vil_nitf2_field_value_greater_than<int>("MTI_DP", 1))
00243    .field("CLASS",  "Security Classification",
00244           NITF_ENUM(1, vil_nitf2_enum_values()
00245             .value("T", "Top Secret")
00246             .value("S", "Secret")
00247             .value("C", "Confindential")
00248             .value("R", "Restricted")
00249             .value("U", "Unclassified")),
00250             true, 0, 0)
00251    .field("CODEW", "Code Words",                  NITF_STR_BCSA(15), false,
00252           0, new vil_nitf2_field_value_one_of<vcl_string>( "CLASS", "T" ) )
00253    .field("CWTEST", "Another Code Word Test",     NITF_STR_BCSA(15), false,
00254           0, new vil_nitf2_field_value_one_of<vcl_string>( "CLASS", "U" ) )
00255    .field("NBANDS", "Number of bands",            NITF_INT(1), false,
00256           0, 0 )
00257    .field("XBANDS", "Large number of bands",      NITF_INT(2), false,
00258           0, new vil_nitf2_field_value_one_of<int>("NBANDS",0))
00259    .repeat(new vil_nitf2_choose_field_value<int>("NBANDS", "XBANDS",
00260              new vil_nitf2_field_value_greater_than<int>("NBANDS", 0)),
00261              vil_nitf2_field_definitions()
00262      .field("BAND_LTR", "Band Description",       NITF_CHAR(), true,
00263             0)
00264    )
00265    .field( "EXP_TEST", "Exponential format test",  NITF_EXP(6,1))
00266    // test nested repeats and functor references to tags within and
00267    // outside repeat loops
00268    .field( "N",   "Test repeat N", NITF_INT(1))
00269    .repeat(new vil_nitf2_field_value<int>("N"), vil_nitf2_field_definitions()
00270            .field("A", "Test repeat A", NITF_INT(1))
00271            .repeat(new vil_nitf2_field_value<int>("N"), vil_nitf2_field_definitions()
00272                    .field("S", "Test repeat S", NITF_STR(3)))
00273            .repeat(new vil_nitf2_field_value<int>("A"), vil_nitf2_field_definitions()
00274                    .field("B", "Test repeat B", NITF_STR_BCSA(3))
00275                    .repeat(new vil_nitf2_field_value<int>("A"), vil_nitf2_field_definitions()
00276                            .field("C", "Test repeat C", NITF_STR_BCSA(4)))))
00277    // test fixed repeat count
00278    .repeat(4, vil_nitf2_field_definitions()
00279            .field("D", "Test fixed repeat", NITF_INT(1))
00280    )
00281   .end();
00282   // Create a test input vcl_string
00283   vcl_string testFieldsStr =
00284     "02"                     // MTI_DP
00285     "003"                    // MTI_PACKET_ID
00286   //"19990908070605"         // DATIME
00287     "              "         // DATIME
00288     "+89.111111-159.222222"  // ACFT_LOC
00289     "890102.33N0091122.00W"  // ACFT_LOC2
00290     "-60.00"                 // SQUINT_ANGLE
00291     "003"                    // NO_VALID_TARGETS
00292     " "                      // TGT_CAT
00293     "2222" "H"               // TGT_1_SPEED2, TGT_1_CAT2
00294     "    " " "               // TGT_2_SPEED2, TGT_2_CAT2
00295     "4444" "T"               // TGT_3_SPEED2, TGT_3_CAT2
00296     ""                       // TEST_NEG_COND not present
00297     "True Condition"         // TEST_POS_COND
00298     "T"                      // CLASS
00299     "RandomCodeWords"        // CODEW (only present if CLASS=T)
00300     ""                       // CWTEST (not present because CLASS!=U
00301     "0"                      // NBANDS (0, so use XBANDS instead)
00302     "12"                     // XBANDS (present because NBANDS=0)
00303     "abcdefghijkl"           // 12 BAND_LTRs (XBAND=12)
00304     "+1.234567E-8"           // Exponential format test
00305     // test nested repeats
00306     "2"       // N
00307     // for i=0...N-1: i=0
00308     "1"       // A[0]
00309     "S00"     // S[0,0]
00310     "S01"     // S[0,1]
00311     //   for j=0...A[i]-1: j=0
00312     "B00"     // B[0,0]
00313     //     for k=0..A[i]-1: k=0
00314     "C000"    // C[0,0,0]
00315     // i=1:
00316     "2"       // A[1]
00317     "S10"     // S[1,0]
00318     "S11"     // S[1,1]
00319     //   for j=0..A[i]: j=0
00320     "B10"     // B[1,0]
00321     //     for k=0..A[i]
00322     "C100"      // C[1,0,0]
00323     "C101"      // C[1,0,1]
00324     "B11"       // B[1,1]
00325     "C110"      // C[1,1,0]
00326     "C111"      // C[1,1,1]
00327     // test fixed repeat
00328     "7890"
00329   ;
00330   vcl_stringstream test_stream;
00331   test_stream << test_tre_tag; // CETAG
00332   test_stream << vcl_setw(5) << vcl_setfill('0') << testFieldsStr.length(); // CELENGTH
00333   test_stream << testFieldsStr; // rest of fields
00334   vcl_string read_string = test_stream.str();
00335   // Write the test input vcl_string to a vil_stream
00336   vil_stream_core* vs = new vil_stream_core();
00337   vs->write(read_string.c_str(), read_string.length());
00338   vs->seek(0);
00339   vil_stream_section* vss = new vil_stream_section(vs, 0, read_string.length());
00340   // Record from the vil_stream
00341   vil_nitf2_tagged_record* record = vil_nitf2_tagged_record::create(*vss);
00342   if (record)
00343   {
00344     vcl_cerr << *record << vcl_endl;
00345     // Now write the record, and compare the output to the test input
00346     vcl_cerr << "\nOriginal string:\n" << read_string
00347              << "\nWrite() output:\n";
00348     vil_stream_core* vs2 = new vil_stream_core();
00349     record->write(*(vil_stream*)vs2);
00350     vil_streampos bufsize = vs2->file_size();
00351     char* buf = new char[(unsigned int)bufsize + 1];
00352     vs2->seek(0);
00353     vs2->read(buf, bufsize);
00354     buf[bufsize]='\0';
00355     vcl_string write_string = vcl_string(buf);
00356     vcl_cerr << write_string << vcl_endl;
00357     if (read_string != write_string) {
00358       vcl_cerr << "\nWrite failed!\n";
00359       error = true;
00360     }
00361     delete buf;
00362     vcl_cerr << "Testing get_value:\n";
00363     int mti_dp;
00364     if (!record->get_value("MTI_DP", mti_dp) || mti_dp!=2) {
00365       vcl_cerr << "Get value failed!\n";
00366       error = true;
00367     } else {
00368       vcl_cerr << "MTI_DP = " << mti_dp << vcl_endl;
00369     }
00370     int tgt_speed[4];
00371     if (!record->get_value("TGT_n_SPEED", vil_nitf2_index_vector(0), tgt_speed[0])  ||
00372         tgt_speed[0] != 2222 ||
00373         record->get_value("TGT_n_SPEED", vil_nitf2_index_vector(1), tgt_speed[1]) /*should be null*/ ||
00374         !record->get_value("TGT_n_SPEED", vil_nitf2_index_vector(2), tgt_speed[2]) ||
00375         tgt_speed[2] != 4444) {
00376       vcl_cerr << "Get vector value test failed!\n";
00377       error = true;
00378     } else {
00379       vcl_cerr << "TGT_2_SPEED = " << tgt_speed[2] << vcl_endl;
00380     }
00381     int d2;
00382     if (!record->get_value("D", vil_nitf2_index_vector(2), d2) || d2 != 9) {
00383       vcl_cerr << "Get fixed repeat count test failed!\n";
00384       error = true;
00385     }
00386     // fetch C[*]
00387     vcl_cerr << "Testing get_values (all values)...\n";
00388     vcl_vector<vcl_string> c_values;
00389     if (!record->get_values("C", c_values) ||
00390         c_values.size() != 5 ||
00391         c_values[0]!="C000" ||
00392         c_values[1]!="C100" ||
00393         c_values[2]!="C101" ||
00394         c_values[3]!="C110" ||
00395         c_values[4]!="C111") {
00396       vcl_cerr << "failed!\n\n";
00397       error = true;
00398     }
00399     // Fetch A[1,*]
00400     vcl_cerr << "Get values (partial index)...\n";
00401     vil_nitf2_index_vector indexes;
00402     vcl_vector<int> a_values;
00403     indexes.push_back(1);
00404     if (!record->get_values("A", indexes, a_values) ||
00405         a_values.size() != 1 ||
00406         a_values[0] != 2) {
00407       vcl_cerr << "failed!\n\n";
00408       error = true;
00409     }
00410     // Fetch C[1,*]
00411     if (!record->get_values("C", indexes, c_values) ||
00412         c_values.size() != 4 ||
00413         c_values[0]!="C100" ||
00414         c_values[1]!="C101" ||
00415         c_values[2]!="C110" ||
00416         c_values[3]!="C111")
00417     {
00418       vcl_cerr << "failed!\n\n";
00419     }
00420   } else {
00421     vcl_cerr << "Didn't create record!\n";
00422     error = true;
00423   }
00424   // Try output of vector field
00425   vcl_cerr << "Output of vector field C:\n"
00426            << *(record->get_field("C"));
00427   // Clean up test definition and test cleanup
00428   if (!vil_nitf2_tagged_record_definition::undefine(test_tre_tag)) {
00429     vcl_cerr << "Error undefining TRE.\n";
00430     error = true;
00431   }
00432   return !error;
00433 }
00434 
00435 vcl_ostream& vil_nitf2_tagged_record::output(vcl_ostream& os) const
00436 {
00437   os << "CETAG: " << name() << vcl_endl
00438      << "CELEN: " << length() << vcl_endl;
00439   for (vil_nitf2_field_definitions::iterator fieldNode = m_definition->m_field_definitions->begin();
00440        fieldNode != m_definition->m_field_definitions->end(); ++fieldNode)
00441   {
00442     vil_nitf2_field_definition* field_def = (*fieldNode)->field_definition();
00443     // to do: handle other nodes
00444     if (!field_def) break;
00445     vil_nitf2_field* field = get_field(field_def->tag);
00446     os << field_def->tag << ": ";
00447     if (field) {
00448       os << *field << vcl_endl;
00449     } else {
00450       os << "(undefined)" << vcl_endl;
00451     }
00452   }
00453   return os;
00454 }
00455 
00456 bool vil_nitf2_tagged_record::write(vil_nitf2_ostream& output)
00457 {
00458   // To track of how much is written
00459   vil_streampos start = output.tell();
00460   // Write tag and length fields
00461   if (m_tag_field && m_length_field) {
00462     m_tag_field->write(output);
00463     m_length_field->write(output);
00464   } else return false;
00465   // Write data fields
00466   m_field_sequence->write(output);
00467   // Check whether the vcl_right amount was written
00468   vil_streampos end = output.tell();
00469   vil_streampos length_written = end - start;
00470   int expected_length = s_tag_formatter().field_width + s_length_formatter().field_width
00471     + length();
00472   return length_written == expected_length;
00473 }
00474 
00475 vil_nitf2_tagged_record::~vil_nitf2_tagged_record()
00476 {
00477   delete m_field_sequence;
00478 }
00479 
00480 vil_nitf2_field_definition* vil_nitf2_field_sequence::find_field_definition(vcl_string tag)
00481 {
00482   for (vil_nitf2_field_definitions::const_iterator node = m_field_definitions->begin();
00483        node != m_field_definitions->end(); ++node)
00484   {
00485     vil_nitf2_field_definition* field_def = (*node)->field_definition();
00486     // to do: search other nodes
00487     if (!field_def) break;
00488 
00489     if (field_def->tag == tag) {
00490       return field_def;
00491     }
00492   }
00493   // tag definition not found
00494   return 0;
00495 }
00496 
00497 vil_nitf2_field::field_tree* vil_nitf2_tagged_record::get_tree() const
00498 {
00499   //create our tree
00500   //we add the field definitions if the TRE was recognized, or we note that we
00501   //skipped it otherwise
00502   vil_nitf2_field::field_tree* tr;
00503   if ( m_field_sequence ) {
00504     tr = m_field_sequence->get_tree();
00505   } else {
00506     tr = new vil_nitf2_field::field_tree;
00507     vil_nitf2_field::field_tree* skipped_node = new vil_nitf2_field::field_tree;
00508     skipped_node->columns.push_back( "CEDATA" );
00509     skipped_node->columns.push_back( "<skipped unknown TRE>" );
00510     tr->children.push_back( skipped_node );
00511   }
00512 
00513   //add the columns describing the name of the TRE
00514   tr->columns.push_back( name() );
00515   tr->columns.push_back( pretty_name() );
00516   //add the CEL (length) field to the front
00517   vil_nitf2_field::field_tree* first_child = new vil_nitf2_field::field_tree;
00518   first_child->columns.push_back( "CEL" );
00519   first_child->columns.push_back( "Extension Length" );
00520   vcl_stringstream len_stream;
00521   len_stream << length();
00522   first_child->columns.push_back( len_stream.str() );
00523   tr->children.insert( tr->children.begin(), first_child );
00524   return tr;
00525 }
00526 
00527 vcl_ostream& operator << (vcl_ostream& os, const vil_nitf2_tagged_record& record)
00528 {
00529   return record.output(os);
00530 }
00531 
00532 // vil_nitf2_tagged_record_sequence
00533 
00534 vcl_ostream& operator << (vcl_ostream& os, const vil_nitf2_tagged_record_sequence& seq)
00535 {
00536   os << seq.size() << " TRE's:" << vcl_endl;
00537   vil_nitf2_tagged_record_sequence::const_iterator it;
00538   for (it = seq.begin(); it != seq.end(); ++it) {
00539     os << *it << vcl_endl;
00540   }
00541   return os;
00542 }

Generated on Sat Nov 22 05:07:52 2008 for core/vil by  doxygen 1.5.1