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 }