core/vil/file_formats/vil_nitf2_tagged_record.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_TAGGED_RECORD_H
00006 #define VIL_NITF2_TAGGED_RECORD_H
00007 
00008 #include <vcl_list.h>
00009 #include <vcl_vector.h>
00010 // not used? #include <vcl_map.h>
00011 // not used? #include <vcl_set.h>
00012 #include <vcl_iostream.h>
00013 // not used? #include <vcl_sstream.h>
00014 #include <vcl_string.h>
00015 // not used? #include <vcl_istream.h>
00016 #include <vcl_ostream.h>
00017 
00018 #include "vil_nitf2_field_functor.h"
00019 #include "vil_nitf2_field.h"
00020 
00021 // Forward declarations
00022 class vil_nitf2_field_formatter;
00023 class vil_nitf2_tagged_record;
00024 class vil_nitf2_tagged_record_definition;
00025 class vil_nitf2_integer_formatter;
00026 class vil_nitf2_string_formatter;
00027 class vil_nitf2_index_vector;
00028 class vil_nitf2_scalar_field;
00029 
00030 // Overview of NITF tagged record code
00031 //
00032 // This code is used to define and read National Imagery Transmission
00033 // Format (NITF) tagged record extensions (TREs), also known as
00034 // controlled extensions. It is intended to eventually support
00035 // writing and verifying TREs also.
00036 //
00037 // A TRE is stored as a sequence of ASCII fields, each of a vcl_fixed length,
00038 // that are appended together without any tag names or delimiters. Some
00039 // fields' existence depends on the values of previous fields; other
00040 // fields are repeated by a value of a previous field. The TRE definition
00041 // code allows the programmer to specify such conditions, and the NITF
00042 // file reader evaluates such conditions as it parses the file.
00043 //
00044 // The classes that represent TRE definitions were designed so that a
00045 // programmer can succinctly define a TRE in a format similar to the
00046 // tables that appear in the NITF documentation. This was felt to be
00047 // important goal to help reduce errors, since NITF TREs can contain
00048 // hundred of fields, and many users will need to define their own TRE's
00049 // depending on their application and environment.
00050 //
00051 // Here an example that implements part of the definition of TRE "MTIRPB"
00052 // from NIMA STDI-0002 version 2.1:
00053 //
00054 // vil_nitf2_tagged_record_definition::define("MTIRPB", fields()
00055 //
00056 //   .field("MTI_DP",           "Destination Point",   NITF_INT(2))
00057 //   .field("DATIME",           "Scan Date & Time",    NITF_DAT(14))
00058 //   .field("ACFT_LOC",         "Aircraft Position",   NITF_LOC(21))
00059 //   .field("SQUINT_ANGLE",     "Squint Angle",        NITF_DBL(6, 2, true),  true)
00060 //   .field("NO_VALID_TARGETS", "Number of Targets",   NITF_INT(3))
00061 //
00062 //   .repeat("NO_VALID_TARGETS", fields()
00063 //
00064 //     .field("TGT_n_SPEED",    "Target Ground Speed", NITF_INT(4),  true)
00065 //     .field("TGT_n_CAT",      "Target Classification Category",
00066 //            NITF_ENUM(1, vil_nitf2_enum_values()
00067 //              .value("H", "Helicopter")
00068 //              .value("T", "Tracked")
00069 //              .value("U", "Unknown")
00070 //              .value("W", "Wheeled")),
00071 //             true))
00072 //
00073 //   .field("TEST_POS_COND",    "Test True Condition", NITF_STR_BCSA(14),  false,
00074 //          NitfGreaterThan<int>("MTI_DP", 1))
00075 //   .end();
00076 //
00077 // A TaggedRecordDefintion consists of the TRE's name (here, "MTIRPB")
00078 // and an ordered list of FieldDefinitions. Each field definition is
00079 // specified by these arguments to method "field" above: tag,
00080 // pretty_name, format; followed by optional arguments: value_optional,
00081 // repeat_count, condition, units, description.
00082 //
00083 // In this example the first field is a two-digit integer; the second a
00084 // is a date-time structure, specified to 14 "digits" precision
00085 // (YYYYMMDDHHMMSS); the next field is a location specified as 21
00086 // characters, stored either as a latitude-longitude pair of decimal
00087 // degrees or deg/min/sec/hemisphere (depending on the TRE, various
00088 // formats are allowed, sometimes with variable precision). The next
00089 // field, SQUINT_ANGLE, is a vcl_fixed-point decimal number stored using 6
00090 // characters, including 2 decimal places and a sign. The "true"
00091 // following the empty "units" argument indicates that field
00092 // SQUINT_ANGLE's value is optional, i.e., the field may be blank. Unless
00093 // a value is defined as optional, the parser will issue a warning in
00094 // such cases (although it will continue parsing the rest of the TRE if
00095 // possible).
00096 //
00097 // The next field, NO_VALID_TARGETS, is an integer field. This is followed
00098 // by a repeating integer field, TGT_n_SPEED; the last argument of its
00099 // definition indicates that TGT_n_SPEED is repeated by the value of field
00100 // NO_VALID_TARGETS. The code here represents TGT_n_SPEED as a single field
00101 // whose value is a vcl_vector of integer pointers.  The reason for using
00102 // pointers is in case some of the field values are blank; for such entries,
00103 // the corresponding vcl_vector element is null.
00104 //
00105 // The next field, TGT_n_CAT, is a repeating enumerated string field, whose
00106 // valid values are "H", "T", "U", "W", and blank.
00107 //
00108 // The final field, TEST_POS_COND, is a conditional field. It exists if
00109 // and only if its condition is satisfied; in this case, if the value of
00110 // field MTI_DP is greater than 1. Conditional fields along with
00111 // repeating fields therefore cause instances of a TRE to vary in length.
00112 //
00113 // That summarizes how TRE's are defined. Some possible extensions in the
00114 // future include value range checks and the ability to specify which formats
00115 // among a set of alternatives (such as geolocation) are allowed.
00116 //
00117 // When a TRE is defined, it is added to a dictionary of known TREs that
00118 // is used to read (and eventually to write) NITF files. As a NITF file
00119 // is read in, at the start of a TRE the tag and length of the TRE are read.
00120 // If the tag is recognized, its data is parsed into field using tag
00121 // definition, creating a TaggedRecord. If not, the tag's data is skipped
00122 // over (according to its declared length) and the next tag is processed.
00123 //
00124 // Values of NITF fields are passed back to the application as built-in
00125 // types and as NITF structure types. Built-in types include integer,
00126 // double (used to represent all vcl_fixed-point decimal fields), string, and
00127 // character. NITF structure types include date_time and Location.
00128 //
00129 // Here is an overview of the class hierarchy:
00130 //
00131 //   vil_nitf2_tagged_record_definition: defines a TRE, consisting of a name and a
00132 //   list of vil_nitf2_field_definition.
00133 //
00134 //   vil_nitf2_field_definition: defines a field; includes a vil_nitf2_field_formatter.
00135 //
00136 //   vil_nitf2_field_formatter and its derived classes vil_nitf2_typed_field_formatter<T>:
00137 //   define the type and format of a field; used to read and write a field.
00138 //
00139 //   vil_nitf2_tagged_record: an instance of a tagged record. Points to a
00140 //   TaggedRecordDefinition and owns a list of vil_nitf2_field.
00141 //
00142 //   vil_nitf2_field: an instance of a field. Contains a pointer to a
00143 //   vil_nitf2_field_definition. See derived classes for its value.
00144 //
00145 //   vil_nitf2_typed_scalar_field<T>: derived from vil_nitf2_field to represent a scalar
00146 //   value of type T (where T=integer, double, vcl_string, char,
00147 //   vil_nitf2_date_time, or vil_nitf2_location*)
00148 //
00149 //   vil_nitf2_typed_array_field<T*>: derived from vil_nitf2_field to represent a
00150 //   repeating field of type T.
00151 //
00152 //   vil_nitf2_field_functor<T>: A function object base class used to derive
00153 //   functions that compute values of tags from a TRE for the purpose
00154 //   of representing conditions and repeat counts.
00155 
00156 //-----------------------------------------------------------------------------
00157 // vil_nitf2_tagged_record is an instance of a single NITF tagged record extension,
00158 // consisting of a list of vil_nitf2_fields, as read from (or to be written to) a
00159 // NITF file.
00160 //
00161 class vil_nitf2_tagged_record
00162 {
00163  public:
00164   // Return record identifier
00165   vcl_string name() const;
00166   vcl_string pretty_name() const;
00167 
00168   // Return record length in bytes
00169   int length() const { return m_length; }
00170 
00171   //bool validate(vil_nitf2_ostream& = vcl_cerr);
00172 
00173   // Attempts to read a NITF tagged record from input stream
00174   static vil_nitf2_tagged_record* create(vil_nitf2_istream& input);
00175 
00176   // Attempts to write a NITF tagged record to the input stream
00177   virtual bool write(vil_nitf2_ostream&);
00178 
00179   // Implements operator <<
00180   vcl_ostream& output(vcl_ostream&) const;
00181 
00182   // Sets out_value to the value of the integer-value field specified by tag.
00183   // Returns 0 if such a field is not found.
00184   bool get_value(vcl_string tag, int& out_value) const;
00185   bool get_value(vcl_string tag, double& out_value) const;
00186   bool get_value(vcl_string tag, char& out_value) const;
00187   bool get_value(vcl_string tag, void*& out_value) const;
00188   bool get_value(vcl_string tag, vcl_string& out_value) const;
00189   bool get_value(vcl_string tag, vil_nitf2_location*& out_value) const;
00190   bool get_value(vcl_string tag, vil_nitf2_date_time& out_value) const;
00191 #if VXL_HAS_INT_64
00192   bool get_value(vcl_string tag, vil_nitf2_long& out_value) const;
00193 #endif //VXL_HAS_INT_64
00194 
00195   //bool get_value(vcl_string tag, int i, int& out_value) const;
00196   //bool get_value(vcl_string tag, int i, double& out_value) const;
00197   //bool get_value(vcl_string tag, int i, char& out_value) const;
00198   //bool get_value(vcl_string tag, int i, void*& out_value) const;
00199   //bool get_value(vcl_string tag, int i, vcl_string& out_value) const;
00200   //bool get_value(vcl_string tag, int i, vil_nitf2_location*& out_value) const;
00201   //bool get_value(vcl_string tag, int i, vil_nitf2_date_time& out_value) const;
00202 #if VXL_HAS_INT_64
00203   //bool get_value(vcl_string tag, int i, vil_nitf2_long& out_value) const;
00204 #endif //VXL_HAS_INT_64
00205 
00206   bool get_value(vcl_string tag, const vil_nitf2_index_vector& indexes, int& out_value) const;
00207   bool get_value(vcl_string tag, const vil_nitf2_index_vector& indexes, double& out_value) const;
00208   bool get_value(vcl_string tag, const vil_nitf2_index_vector& indexes, char& out_value) const;
00209   bool get_value(vcl_string tag, const vil_nitf2_index_vector& indexes, void*& out_value) const;
00210   bool get_value(vcl_string tag, const vil_nitf2_index_vector& indexes, vcl_string& out_value) const;
00211   bool get_value(vcl_string tag, const vil_nitf2_index_vector& indexes, vil_nitf2_location*& out_value) const;
00212   bool get_value(vcl_string tag, const vil_nitf2_index_vector& indexes, vil_nitf2_date_time& out_value) const;
00213 #if VXL_HAS_INT_64
00214     bool get_value(vcl_string tag, const vil_nitf2_index_vector& indexes, vil_nitf2_long& out_value) const;
00215 #endif //VXL_HAS_INT_64
00216 
00217   // Sets out_value to a flattened list of the values of the array field element
00218   // specified by tag and index. If index is the empty vector, then out_values
00219   // hold all instances of the field. If index partially specifies value instances,
00220   // the out_values hold all instances of the field selected by the partial index.
00221   // Appends to, instead of clearing, out_values if clear_out_values is false.
00222   // Returns 0 if such a field is not found or is of the wrong type.
00223   bool get_values(vcl_string tag, const vil_nitf2_index_vector& indexes,
00224                   vcl_vector<int>& out_values, bool clear_out_values = true) const;
00225   bool get_values(vcl_string tag, const vil_nitf2_index_vector& indexes,
00226                   vcl_vector<double>& out_values, bool clear_out_values = true) const;
00227   bool get_values(vcl_string tag, const vil_nitf2_index_vector& indexes,
00228                   vcl_vector<char>& out_values, bool clear_out_values = true) const;
00229   bool get_values(vcl_string tag, const vil_nitf2_index_vector& indexes,
00230                   vcl_vector<void*>& out_values, bool clear_out_values = true) const;
00231   bool get_values(vcl_string tag, const vil_nitf2_index_vector& indexes,
00232                   vcl_vector<vcl_string>& out_values, bool clear_out_values = true) const;
00233   bool get_values(vcl_string tag, const vil_nitf2_index_vector& indexes,
00234                   vcl_vector<vil_nitf2_location*>& out_values, bool clear_out_values = true) const;
00235   bool get_values(vcl_string tag, const vil_nitf2_index_vector& indexes,
00236                   vcl_vector<vil_nitf2_date_time>& out_values, bool clear_out_values = true) const;
00237 #if VXL_HAS_INT_64
00238   bool get_values(vcl_string tag, const vil_nitf2_index_vector& indexes,
00239                   vcl_vector<vil_nitf2_long>& out_values, bool clear_out_values = true) const;
00240 #endif
00241 
00242   // Convenience overload of preceding methods, that set out_values to all
00243   // instances of array field element.
00244   bool get_values(vcl_string tag, vcl_vector<int>& out_values) const;
00245   bool get_values(vcl_string tag, vcl_vector<double>& out_values) const;
00246   bool get_values(vcl_string tag, vcl_vector<char>& out_values) const;
00247   bool get_values(vcl_string tag, vcl_vector<void*>& out_values) const;
00248   bool get_values(vcl_string tag, vcl_vector<vcl_string>& out_values) const;
00249   bool get_values(vcl_string tag, vcl_vector<vil_nitf2_location*>& out_values) const;
00250   bool get_values(vcl_string tag, vcl_vector<vil_nitf2_date_time>& out_values) const;
00251 #if VXL_HAS_INT_64
00252   bool get_values(vcl_string tag, vcl_vector<vil_nitf2_long>& out_values) const;
00253 #endif
00254 
00255   virtual vil_nitf2_field::field_tree* get_tree() const;
00256 
00257   // Sets the value of the integer-valued field specified by tag to value.
00258   // Not yet implemented.
00259   //bool set_value(vcl_string tag, int value) {
00260   //  return m_field_sequence->set_value(tag, value); }
00261 
00262   // Returns a field with specified tag, or 0 if not found.
00263   vil_nitf2_field* get_field(vcl_string tag) const {
00264     return m_field_sequence->get_field(tag); }
00265 
00266   // Removes a field with specified tag, returning whether successful.
00267   // Use this method to "undefine" an existing field.
00268   // Not yet implemented.
00269   //bool remove_field(vcl_string tag) {
00270   //  return m_field_sequence->remove_field(tag); }
00271 
00272   // Test method. Prints results. Returns true if no errors.
00273   static bool test();
00274 
00275   // Destructor
00276   virtual ~vil_nitf2_tagged_record();
00277 
00278  private:
00279   // Default constructor
00280   vil_nitf2_tagged_record();
00281 
00282   // Reads tagged record members from input stream
00283   bool read(vil_nitf2_istream& input);
00284 
00285   // Static variables
00286   static vil_nitf2_field_definition & s_length_definition();
00287   static vil_nitf2_field_definition & s_tag_definition();
00288   static vil_nitf2_integer_formatter & s_length_formatter();
00289   static vil_nitf2_string_formatter & s_tag_formatter();
00290 
00291   // Member variables
00292   vil_nitf2_scalar_field* m_length_field;
00293   vil_nitf2_scalar_field* m_tag_field;
00294   int m_length;
00295   vil_nitf2_tagged_record_definition* m_definition;
00296   vil_nitf2_field_sequence* m_field_sequence;
00297 };
00298 
00299 vcl_ostream& operator << (vcl_ostream& os, const vil_nitf2_tagged_record& record);
00300 
00301 //-----------------------------------------------------------------------------
00302 // A sequence of tagged records, as read from a NITF file header or image
00303 // subheader extended data field.
00304 
00305 class vil_nitf2_tagged_record_sequence : public vcl_list<vil_nitf2_tagged_record*>
00306 {
00307  public:
00308   // Constructor
00309   vil_nitf2_tagged_record_sequence() : vcl_list<vil_nitf2_tagged_record*>() {}
00310 
00311   // Destructor
00312   virtual ~vil_nitf2_tagged_record_sequence() {}
00313 };
00314 
00315 vcl_ostream& operator << (vcl_ostream& os, const vil_nitf2_tagged_record_sequence& seq);
00316 
00317 #endif // VIL_NITF2_TAGGED_RECORD_H