Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

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.\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),
00232             true)
00233      .field("TGT_n_CAT",   "Target Classification Category",
00234             NITF_ENUM(1, vil_nitf2_enum_values()
00235               .value("H", "Helicopter")
00236               .value("T", "Tracked")
00237               .value("U", "Unknown")
00238               .value("W", "Wheeled")),
00239             true))
00240    .field("TEST_NEG_COND", "Test False Condition", NITF_STR_BCSA(14), false,
00241           0, new vil_nitf2_field_value_greater_than<int>("MTI_DP", 5))
00242    .field("TEST_POS_COND", "Test True Condition",  NITF_STR_BCSA(14), false,
00243           0, new vil_nitf2_field_value_greater_than<int>("MTI_DP", 1))
00244    .field("CLASS",  "Security Classification",
00245           NITF_ENUM(1, vil_nitf2_enum_values()
00246             .value("T", "Top Secret")
00247             .value("S", "Secret")
00248             .value("C", "Confindential")
00249             .value("R", "Restricted")
00250             .value("U", "Unclassified")),
00251             true, 0, 0)
00252    .field("CODEW", "Code Words",                  NITF_STR_BCSA(15), false,
00253           0, new vil_nitf2_field_value_one_of<vcl_string>( "CLASS", "T" ) )
00254    .field("CWTEST", "Another Code Word Test",     NITF_STR_BCSA(15), false,
00255           0, new vil_nitf2_field_value_one_of<vcl_string>( "CLASS", "U" ) )
00256    .field("NBANDS", "Number of bands",            NITF_INT(1), false,
00257           0, 0 )
00258    .field("XBANDS", "Large number of bands",      NITF_INT(2), false,
00259           0, new vil_nitf2_field_value_one_of<int>("NBANDS",0))
00260    .repeat(new vil_nitf2_choose_field_value<int>("NBANDS", "XBANDS",
00261              new vil_nitf2_field_value_greater_than<int>("NBANDS", 0)),
00262              vil_nitf2_field_definitions()
00263      .field("BAND_LTR", "Band Description",       NITF_CHAR(), true,
00264             0)
00265    )
00266    .field( "EXP_TEST", "Exponential format test",  NITF_EXP(6,1))
00267    // test nested repeats and functor references to tags within and
00268    // outside repeat loops
00269    .field( "N",   "Test repeat N", NITF_INT(1))
00270    .repeat(new vil_nitf2_field_value<int>("N"), vil_nitf2_field_definitions()
00271      .field("A", "Test repeat A", NITF_INT(1))
00272      .repeat(new vil_nitf2_field_value<int>("N"), vil_nitf2_field_definitions()
00273         .field("S", "Test repeat S", NITF_STR(3))
00274      )
00275      .repeat(new vil_nitf2_field_value<int>("A"), vil_nitf2_field_definitions()
00276        .field("B", "Test repeat B", NITF_STR_BCSA(3))
00277        .repeat(new vil_nitf2_field_value<int>("A"), vil_nitf2_field_definitions()
00278          .field("C", "Test repeat C", NITF_STR_BCSA(4))
00279        )
00280      )
00281    )
00282    // test fixed repeat count
00283    .repeat(4, vil_nitf2_field_definitions()
00284      .field("D", "Test fixed repeat", NITF_INT(1))
00285    )
00286   .end();
00287   // Create a test input vcl_string
00288   vcl_string testFieldsStr =
00289     "02"                     // MTI_DP
00290     "003"                    // MTI_PACKET_ID
00291     //"19990908070605"         // DATIME
00292     "              "         // DATIME
00293     "+89.111111-159.222222"  // ACFT_LOC
00294     "890102.33N0091122.00W"  // ACFT_LOC2
00295     "-60.00"                 // SQUINT_ANGLE
00296     "003"                    // NO_VALID_TARGETS
00297     " "                      // TGT_CAT
00298     "2222" "H"               // TGT_1_SPEED2, TGT_1_CAT2
00299     "    " " "               // TGT_2_SPEED2, TGT_2_CAT2
00300     "4444" "T"               // TGT_3_SPEED2, TGT_3_CAT2
00301     ""                       // TEST_NEG_COND not present
00302     "True Condition"         // TEST_POS_COND
00303     "T"                      // CLASS
00304     "RandomCodeWords"        // CODEW (only present if CLASS=T)
00305     ""                       // CWTEST (not present because CLASS!=U
00306     "0"                      // NBANDS (0, so use XBANDS instead)
00307     "12"                     // XBANDS (present because NBANDS=0)
00308     "abcdefghijkl"           // 12 BAND_LTRs (XBAND=12)
00309     "+1.234567E-8"           // Exponential format test
00310     // test nested repeats
00311     "2"       // N
00312     // for i=0...N-1: i=0
00313     "1"       // A[0]
00314     "S00"     // S[0,0]
00315     "S01"     // S[0,1]
00316     //   for j=0...A[i]-1: j=0
00317     "B00"     // B[0,0]
00318     //     for k=0..A[i]-1: k=0
00319     "C000"    // C[0,0,0]
00320     // i=1:
00321     "2"       // A[1]
00322     "S10"     // S[1,0]
00323     "S11"     // S[1,1]
00324     //   for j=0..A[i]: j=0
00325     "B10"     // B[1,0]
00326     //     for k=0..A[i]
00327     "C100"      // C[1,0,0]
00328     "C101"      // C[1,0,1]
00329     "B11"       // B[1,1]
00330     "C110"      // C[1,1,0]
00331     "C111"      // C[1,1,1]
00332     // test fixed repeat
00333     "7890"
00334   ;
00335   vcl_stringstream test_stream;
00336   test_stream << test_tre_tag; // CETAG
00337   test_stream << vcl_setw(5) << vcl_setfill('0') << testFieldsStr.length(); // CELENGTH
00338   test_stream << testFieldsStr; // rest of fields
00339   vcl_string read_string = test_stream.str();
00340   // Write the test input vcl_string to a vil_stream
00341   vil_stream_core* vs = new vil_stream_core();
00342   vs->write(read_string.c_str(), read_string.length());
00343   vs->seek(0);
00344   vil_stream_section* vss = new vil_stream_section(vs, 0, read_string.length());
00345   // Record from the vil_stream
00346   vil_nitf2_tagged_record* record = vil_nitf2_tagged_record::create(*vss);
00347   if (record)
00348   {
00349     vcl_cerr << *record << vcl_endl;
00350     // Now write the record, and compare the output to the test input
00351     vcl_cerr << "\nOriginal string:\n" << read_string
00352              << "\nWrite() output:\n";
00353     vil_stream_core* vs2 = new vil_stream_core();
00354     record->write(*(vil_stream*)vs2);
00355     vil_streampos bufsize = vs2->file_size();
00356     char* buf = new char[(unsigned int)bufsize + 1];
00357     vs2->seek(0);
00358     vs2->read(buf, bufsize);
00359     buf[bufsize]='\0';
00360     vcl_string write_string = vcl_string(buf);
00361     vcl_cerr << write_string << vcl_endl;
00362     if (read_string != write_string) {
00363       vcl_cerr << "\nWrite failed!\n";
00364       error = true;
00365     }
00366     delete buf;
00367     vcl_cerr << "Testing get_value:\n";
00368     int mti_dp;
00369     if (!record->get_value("MTI_DP", mti_dp) || mti_dp!=2) {
00370       vcl_cerr << "Get value failed!\n";
00371       error = true;
00372     } else {
00373       vcl_cerr << "MTI_DP = " << mti_dp << vcl_endl;
00374     }
00375     int tgt_speed[4];
00376     if (!record->get_value("TGT_n_SPEED", vil_nitf2_index_vector(0), tgt_speed[0])  ||
00377         tgt_speed[0] != 2222 ||
00378         record->get_value("TGT_n_SPEED", vil_nitf2_index_vector(1), tgt_speed[1]) /*should be null*/ ||
00379         !record->get_value("TGT_n_SPEED", vil_nitf2_index_vector(2), tgt_speed[2]) ||
00380         tgt_speed[2] != 4444) {
00381       vcl_cerr << "Get vector value test failed!\n";
00382       error = true;
00383     } else {
00384       vcl_cerr << "TGT_2_SPEED = " << tgt_speed[2] << vcl_endl;
00385     }
00386     int d2;
00387     if (!record->get_value("D", vil_nitf2_index_vector(2), d2) || d2 != 9) {
00388       vcl_cerr << "Get fixed repeat count test failed!\n";
00389       error = true;
00390     }
00391     // fetch C[*]
00392     vcl_cerr << "Testing get_values (all values)...\n";
00393     vcl_vector<vcl_string> c_values;
00394     if (!record->get_values("C", c_values) ||
00395         c_values.size() != 5 ||
00396         c_values[0]!="C000" ||
00397         c_values[1]!="C100" ||
00398         c_values[2]!="C101" ||
00399         c_values[3]!="C110" ||
00400         c_values[4]!="C111") {
00401       vcl_cerr << "failed!\n\n";
00402       error = true;
00403     }
00404     // Fetch A[1,*]
00405     vcl_cerr << "Get values (partial index)...\n";
00406     vil_nitf2_index_vector indexes;
00407     vcl_vector<int> a_values;
00408     indexes.push_back(1);
00409     if (!record->get_values("A", indexes, a_values) ||
00410         a_values.size() != 1 ||
00411         a_values[0] != 2) {
00412       vcl_cerr << "failed!\n\n";
00413       error = true;
00414     }
00415     // Fetch C[1,*]
00416     if (!record->get_values("C", indexes, c_values) ||
00417         c_values.size() != 4 ||
00418         c_values[0]!="C100" ||
00419         c_values[1]!="C101" ||
00420         c_values[2]!="C110" ||
00421         c_values[3]!="C111")
00422     {
00423       vcl_cerr << "failed!\n\n";
00424     }
00425   } else {
00426     vcl_cerr << "Didn't create record!\n";
00427     error = true;
00428   }
00429   // Try output of vector field
00430   vcl_cerr << "Output of vector field C:\n"
00431            << *(record->get_field("C"));
00432   // Clean up test definition and test cleanup
00433   if (!vil_nitf2_tagged_record_definition::undefine(test_tre_tag)) {
00434     vcl_cerr << "Error undefining TRE.\n";
00435     error = true;
00436   }
00437   return !error;
00438 }
00439 
00440 vcl_ostream& vil_nitf2_tagged_record::output(vcl_ostream& os) const
00441 {
00442   os << "CETAG: " << name() << vcl_endl
00443      << "CELEN: " << length() << vcl_endl;
00444   for (vil_nitf2_field_definitions::iterator fieldNode = m_definition->m_field_definitions->begin();
00445        fieldNode != m_definition->m_field_definitions->end(); ++fieldNode)
00446   {
00447     vil_nitf2_field_definition* field_def = (*fieldNode)->field_definition();
00448     // to do: handle other nodes
00449     if (!field_def) break;
00450     vil_nitf2_field* field = get_field(field_def->tag);
00451     os << field_def->tag << ": ";
00452     if (field) {
00453       os << *field << vcl_endl;
00454     } else {
00455       os << "(undefined)" << vcl_endl;
00456     }
00457   }
00458   return os;
00459 }
00460 
00461 bool vil_nitf2_tagged_record::write(vil_nitf2_ostream& output)
00462 {
00463   // To track of how much is written
00464   vil_streampos start = output.tell();
00465   // Write tag and length fields
00466   if (m_tag_field && m_length_field) {
00467     m_tag_field->write(output);
00468     m_length_field->write(output);
00469   } else return false;
00470   // Write data fields
00471   m_field_sequence->write(output);
00472   // Check whether the vcl_right amount was written
00473   vil_streampos end = output.tell();
00474   vil_streampos length_written = end - start;
00475   int expected_length = s_tag_formatter().field_width + s_length_formatter().field_width
00476     + length();
00477   return length_written == expected_length;
00478 }
00479 
00480 vil_nitf2_tagged_record::~vil_nitf2_tagged_record()
00481 {
00482   delete m_field_sequence;
00483 }
00484 
00485 vil_nitf2_field_definition* vil_nitf2_field_sequence::find_field_definition(vcl_string tag)
00486 {
00487   for (vil_nitf2_field_definitions::const_iterator node = m_field_definitions->begin();
00488        node != m_field_definitions->end(); ++node)
00489   {
00490     vil_nitf2_field_definition* field_def = (*node)->field_definition();
00491     // to do: search other nodes
00492     if (!field_def) break;
00493 
00494     if (field_def->tag == tag) {
00495       return field_def;
00496     }
00497   }
00498   // tag definition not found
00499   return 0;
00500 }
00501 
00502 vil_nitf2_field::field_tree* vil_nitf2_tagged_record::get_tree() const
00503 {
00504   //create our tree
00505   //we add the field definitions if the TRE was recognized, or we note that we
00506   //skipped it otherwise
00507   vil_nitf2_field::field_tree* tr;
00508   if ( m_field_sequence ) {
00509     tr = m_field_sequence->get_tree();
00510   } else {
00511     tr = new vil_nitf2_field::field_tree;
00512     vil_nitf2_field::field_tree* skipped_node = new vil_nitf2_field::field_tree;
00513     skipped_node->columns.push_back( "CEDATA" );
00514     skipped_node->columns.push_back( "<skipped unknown TRE>" );
00515     tr->children.push_back( skipped_node );
00516   }
00517 
00518   //add the columns describing the name of the TRE
00519   tr->columns.push_back( name() );
00520   tr->columns.push_back( pretty_name() );
00521   //add the CEL (length) field to the front
00522   vil_nitf2_field::field_tree* first_child = new vil_nitf2_field::field_tree;
00523   first_child->columns.push_back( "CEL" );
00524   first_child->columns.push_back( "Extension Length" );
00525   vcl_stringstream len_stream;
00526   len_stream << length();
00527   first_child->columns.push_back( len_stream.str() );
00528   tr->children.insert( tr->children.begin(), first_child );
00529   return tr;
00530 }
00531 
00532 vcl_ostream& operator << (vcl_ostream& os, const vil_nitf2_tagged_record& record)
00533 {
00534   return record.output(os);
00535 }
00536 
00537 // vil_nitf2_tagged_record_sequence
00538 
00539 vcl_ostream& operator << (vcl_ostream& os, const vil_nitf2_tagged_record_sequence& seq)
00540 {
00541   os << seq.size() << " TRE's:" << vcl_endl;
00542   vil_nitf2_tagged_record_sequence::const_iterator it;
00543   for (it = seq.begin(); it != seq.end(); ++it) {
00544     os << *it << vcl_endl;
00545   }
00546   return os;
00547 }

Generated on Thu Jan 10 14:40:00 2008 for core/vil by  doxygen 1.4.4