core/vil/file_formats/vil_nitf2_array_field.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_array_field.h"
00006 #include "vil_nitf2_field_definition.h"
00007 #include "vil_nitf2_index_vector.h"
00008 
00009 #include <vcl_cstddef.h> // for size_t
00010 #include <vcl_sstream.h>
00011 #include <vcl_cstdlib.h>
00012 #include <vil/vil_stream_core.h>
00013 
00014 int vil_nitf2_array_field::num_dimensions() const
00015 {
00016   return m_num_dimensions;
00017 }
00018 
00019 int vil_nitf2_array_field::
00020 next_dimension(const vil_nitf2_index_vector& index) const
00021 {
00022   vcl_map<vil_nitf2_index_vector,int>::const_iterator dimension_bounds_entry = m_dimensions_map.find(index);
00023   if (dimension_bounds_entry != m_dimensions_map.end()) {
00024     return dimension_bounds_entry->second;
00025   } else {
00026     return 0;
00027   }
00028 }
00029 
00030 void vil_nitf2_array_field::
00031 set_next_dimension(const vil_nitf2_index_vector& index, int bound)
00032 {
00033   if ((int)index.size() >= m_num_dimensions) {
00034     vcl_cerr << "vil_nitf2_array_field::set_next_dimension"
00035              << index << ": invalid partial index!\n";
00036     return;
00037   }
00038   if (next_dimension(index) > 0) {
00039     vcl_cerr << "vil_nitf2_array_field::set_next_dimension"
00040              << index << ": bound previously set!\n";
00041   }
00042   m_dimensions_map[index] = bound;
00043 }
00044 
00045 bool vil_nitf2_array_field::
00046 check_index(const vil_nitf2_index_vector& indexes) const
00047 {
00048   if ((int)indexes.size() != m_num_dimensions) {
00049     vcl_cerr << "index length does not match value dimensions!\n";
00050     return false;
00051   }
00052   // Remove the last element from index and look it up in the dimensions map.
00053   // Then check if the removed element is less than the returned dimension bound.
00054   // If no dimension bound is found, then one of the other index values is
00055   // invalid.
00056   vil_nitf2_index_vector dimension_index;
00057   for (int dim=0; dim < m_num_dimensions-1; ++dim) {
00058     dimension_index.push_back(indexes[dim]);
00059   }
00060   int dimension_bound = next_dimension(dimension_index);
00061   int last_index = indexes[indexes.size()-1];
00062   if (last_index < dimension_bound) {
00063     return true;
00064   } else {
00065     vcl_cerr << "Tag " << tag() << indexes << ": index out of bounds!\n";
00066     return false;
00067   }
00068 }
00069 
00070 vcl_string int_to_string( int i )
00071 {
00072   vcl_stringstream s;
00073   s << i;
00074   return s.str();
00075 }
00076 
00077 vcl_string index_string( const vil_nitf2_index_vector& indices )
00078 {
00079   vcl_string ret_val = "";
00080   for ( unsigned int i = 0 ; i < indices.size() ; i++ ){
00081     ret_val += "[" + int_to_string( indices[i] ) + "]";
00082   }
00083   return ret_val;
00084 }
00085 
00086 vcl_string vil_nitf2_array_field::get_value_string(const vil_nitf2_index_vector& in_indices) const
00087 {
00088   vil_stream_core* str = new vil_stream_core;
00089   write_vector_element( *str, in_indices, -1 );
00090   vil_streampos num_to_read = str->tell();
00091   str->seek( 0 );
00092   char* buffer;
00093   buffer = (char*)vcl_malloc( (vcl_size_t) num_to_read+1 );
00094   str->read( (void*)buffer, num_to_read );
00095   buffer[(vcl_size_t) num_to_read] = 0;
00096   return vcl_string( buffer );
00097 }
00098 
00099 void vil_nitf2_array_field::do_dimension( const vil_nitf2_index_vector& in_indices,
00100                                           vil_nitf2_field::field_tree* inTree ) const
00101 {
00102   int dim = next_dimension( in_indices );
00103   for ( int i = 0 ; i < dim ; i++ )
00104   {
00105     //this is the index list we're dealing with in this loop
00106     vil_nitf2_index_vector curr_indices = in_indices;
00107     curr_indices.push_back( i );
00108     //create our tree node and add it to inTree's child list
00109     vil_nitf2_field::field_tree* tr = new vil_nitf2_field::field_tree;
00110     vcl_string tag_str = tag();
00111     vcl_string index_str = index_string( curr_indices );
00112     vcl_string p_name;
00113     if ( index_str == "" ) p_name = pretty_name();
00114     else p_name = "";
00115     tr->columns.push_back( tag_str + index_str );
00116     tr->columns.push_back( p_name );
00117     if( check_index( curr_indices ) ) {
00118       tr->columns.push_back( get_value_string( curr_indices ) );
00119     }
00120     inTree->children.push_back( tr );
00121     //recursive call
00122     do_dimension( curr_indices, tr );
00123   }
00124 }
00125 
00126 vil_nitf2_field::field_tree* vil_nitf2_array_field::get_tree() const
00127 {
00128   field_tree* tr = vil_nitf2_field::get_tree();
00129   do_dimension( vil_nitf2_index_vector(), tr );
00130   return tr;
00131 }