1 // vil_nitf2: Written by Harry Voorhees (hlv@) and Rob Radtke (rob@) of 2 // Stellar Science Ltd. Co. (stellarscience.com) for 3 // Air Force Research Laboratory, 2005. 4 5 #ifndef VIL_NITF2_FIELD_FUNCTOR_H 6 #define VIL_NITF2_FIELD_FUNCTOR_H 7 8 class vil_nitf2_field; 9 class vil_nitf2_enum_values; 10 class vil_nitf2_index_vector; 11 12 #include <map> 13 #include <string> 14 #include <utility> 15 #include <vector> 16 #include "vil_nitf2_field_sequence.h" 17 #ifdef _MSC_VER 18 # include <vcl_msvc_warnings.h> 19 #endif 20 21 //----------------------------------------------------------------------------- 22 //: 23 // \file 24 // \brief Functors used by NITF classes 25 // 26 // Base class for functors that define a function that takes a 27 // vil_nitf2_field_sequence and attempts to compute an "out" parameter of 28 // type T. The function also returns a bool that specifies whether the 29 // value could be computed. 30 // 31 // These functors are used to evaluate NITF field tags and invariably 32 // call vil_nitf2_field_sequence::get_value(). When calling this method, 33 // please be sure to set the argument ignore_extra_indexes to true. 34 // This will allow the functor to be used within a repeat loop 35 // and reference any preceding tag, inside or outside the repeat loop. 36 // For example, to define a field sequence like this: 37 // FIELD A; 38 // REPEAT i=1..N 39 // FIELD B(i) 40 // FIELD C(i) exists if B(i) > 0 41 // FIELD D(i) exists if A > 0 42 // the same conditional functor can be used in the definitions of fields 43 // C and D by simply providing the name of the appropriate tag. When 44 // the functor is evaluated, the current index (i) is used to fetch the 45 // tag. By calling get_value() with ignore_extra_indexes set to true, 46 // the value of A can be fetched without causing an error. 47 48 template<typename T> 49 class vil_nitf2_field_functor 50 { 51 public: 52 virtual bool operator() (vil_nitf2_field_sequence* record, 53 const vil_nitf2_index_vector& indexes, T& out_value) = 0; 54 virtual ~vil_nitf2_field_functor() = default; 55 56 // Virtual copy method 57 virtual vil_nitf2_field_functor<T>* copy() const = 0; 58 }; 59 60 //: 61 // Functor vil_nitf2_field_value defines a function that sets its out parameter 62 // to a value of a field from a field sequence. The function returns whether 63 // the field was found. The functor is instantiated with the field's tag. 64 // The field sequence is passed to the function. 65 // 66 // You can override any value by specifying an overrideMap. For example, 67 // if 0 was a special value that actually meant 1 but all other values 68 // (2, 3, 4...) actually meant when they were you could get that effect like this: 69 // <code> 70 // std::map< int, int > overrides; 71 // overrides.insert( std::make_pair( 0, 1 ) ); 72 // new vil_nitf2_field_value( "FIELD_NAME", overrides ); 73 // </code> 74 template<typename T> 75 class vil_nitf2_field_value : public vil_nitf2_field_functor<T> 76 { 77 public: vil_nitf2_field_value(std::string tag)78 vil_nitf2_field_value(std::string tag) : tag(std::move(tag)) {} 79 vil_nitf2_field_value(std::string tag,std::map<T,T> overrideMap)80 vil_nitf2_field_value(std::string tag, std::map<T, T> overrideMap ) 81 : tag(std::move(tag)), overrides(std::move( overrideMap )) {} 82 copy()83 vil_nitf2_field_functor<T>* copy() const override { 84 return new vil_nitf2_field_value(tag, overrides); } 85 operator()86 bool operator() (vil_nitf2_field_sequence* record, 87 const vil_nitf2_index_vector& indexes, T& value) override 88 { 89 bool success = record->get_value(tag, indexes, value, true); 90 if ( success ) { 91 //check to see if this value is overridden or not 92 typename std::map<T, T>::const_iterator it = overrides.find( value ); 93 if ( it != overrides.end() ){ 94 //found override, use it 95 value = (*it).second; 96 } 97 } 98 return success; 99 } 100 101 private: 102 std::string tag; 103 std::map<T, T> overrides; 104 }; 105 106 //: 107 // Functor vil_nitf2_multiply_field_values defines a function that sets its out 108 // parameter to the product of the values of two fields. The predicate 109 // returns true iff both fields are found or the arg 'use_zero_if_tag_not_found'; 110 // in the latter case, the out parameter is set to 0. 111 // 112 class vil_nitf2_multiply_field_values : public vil_nitf2_field_functor<int> 113 { 114 public: 115 vil_nitf2_multiply_field_values(std::string tag_1, 116 std::string tag_2, 117 bool use_zero_if_tag_not_found = false) tag_1(std::move (tag_1))118 : tag_1(std::move(tag_1)), 119 tag_2(std::move(tag_2)), 120 use_zero_if_tag_not_found(use_zero_if_tag_not_found) {} 121 copy()122 vil_nitf2_field_functor<int>* copy() const override { 123 return new vil_nitf2_multiply_field_values( 124 tag_1, tag_2, use_zero_if_tag_not_found); 125 } 126 127 bool operator() (vil_nitf2_field_sequence* record, 128 const vil_nitf2_index_vector& indexes, int& value) override; 129 130 private: 131 std::string tag_1; 132 std::string tag_2; 133 bool use_zero_if_tag_not_found; 134 }; 135 136 //: 137 // Functor vil_nitf2_max_field_value_plus_offset_and_threshold defines a 138 // function that sets its out parameter to either the value of a specified 139 // field plus an offset, or a specified minimum value, whichever is greater. 140 // The function returns whether the field was found. 141 // 142 class vil_nitf2_max_field_value_plus_offset_and_threshold : public vil_nitf2_field_functor<int> 143 { 144 public: 145 vil_nitf2_max_field_value_plus_offset_and_threshold( 146 std::string tag, int offset, int min_threshold = 0, int tag_factor = 1 ) tag(std::move (tag))147 : tag(std::move(tag)), offset(offset), min_threshold(min_threshold), tag_factor( tag_factor ) {} 148 copy()149 vil_nitf2_field_functor<int>* copy() const override { 150 return new vil_nitf2_max_field_value_plus_offset_and_threshold( 151 tag, offset, min_threshold, tag_factor); } 152 153 bool operator() (vil_nitf2_field_sequence* record, 154 const vil_nitf2_index_vector& indexes, int& value) override; 155 156 private: 157 std::string tag; 158 int offset; 159 int min_threshold; 160 int tag_factor; 161 }; 162 163 //: 164 // Functor vil_nitf2_field_value_greater_than defines a comparison predicate that 165 // sets its out parameter to true if a specified field from a field 166 // sequence is found and its value is greater than a specified threshold. 167 // The predicate returns whether the field was found. 168 // 169 template<typename T> 170 class vil_nitf2_field_value_greater_than: public vil_nitf2_field_functor<bool> 171 { 172 public: vil_nitf2_field_value_greater_than(std::string tag,T threshold)173 vil_nitf2_field_value_greater_than(std::string tag, T threshold) 174 : tag(std::move(tag)), threshold(threshold) {} 175 copy()176 vil_nitf2_field_functor<bool>* copy() const override { 177 return new vil_nitf2_field_value_greater_than(tag, threshold); } 178 operator()179 bool operator() (vil_nitf2_field_sequence* record, 180 const vil_nitf2_index_vector& indexes, bool& result) override { 181 T value; 182 if (record->get_value(tag, indexes, value, true)) { 183 result = value > threshold; 184 return true; 185 } 186 else { 187 return false; 188 } 189 } 190 private: 191 std::string tag; 192 T threshold; 193 }; 194 195 //: 196 // Functor vil_nitf2_field_specified defines a comparison predicate that sets 197 // its out parameter to true iff the specified field is not blank. 198 // 199 class vil_nitf2_field_specified: public vil_nitf2_field_functor<bool> 200 { 201 public: vil_nitf2_field_specified(std::string tag)202 vil_nitf2_field_specified(std::string tag) : tag(std::move(tag)) {} 203 copy()204 vil_nitf2_field_functor<bool>* copy() const override { 205 return new vil_nitf2_field_specified(tag); } 206 207 bool operator() (vil_nitf2_field_sequence* record, 208 const vil_nitf2_index_vector& indexes, bool& result) override; 209 210 private: 211 std::string tag; 212 }; 213 214 //: 215 // Functor vil_nitf2_field_value_one_of defines a predicate that sets its out 216 // parameter to true iff the value of the specified tag equals one of 217 // the elements of a std::vector of acceptable values. 218 // 219 template<typename T> 220 class vil_nitf2_field_value_one_of: public vil_nitf2_field_functor<bool> 221 { 222 public: 223 /// Constructor to specify a std::vector of acceptable values vil_nitf2_field_value_one_of(std::string tag,std::vector<T> acceptable_values)224 vil_nitf2_field_value_one_of(std::string tag, std::vector<T> acceptable_values) 225 : tag(std::move(tag)), acceptable_values(std::move(acceptable_values)) {} 226 227 /// Constructor to specify only one acceptable value vil_nitf2_field_value_one_of(std::string tag,T acceptable_value)228 vil_nitf2_field_value_one_of(std::string tag, T acceptable_value) 229 : tag(std::move(tag)), acceptable_values(1, acceptable_value) {} 230 copy()231 vil_nitf2_field_functor<bool>* copy() const override { 232 return new vil_nitf2_field_value_one_of(tag, acceptable_values); } 233 operator()234 bool operator() (vil_nitf2_field_sequence* record, 235 const vil_nitf2_index_vector& indexes, bool& result) override 236 { 237 result = false; 238 T val; 239 if (record->get_value(tag, indexes, val, true)) { 240 typename std::vector<T>::iterator it; 241 for (it = acceptable_values.begin(); it != acceptable_values.end(); ++it) { 242 if ((*it) == val) { 243 result = true; 244 break; 245 } 246 } 247 return true; 248 } 249 // Field not defined 250 return false; 251 } 252 253 protected: 254 std::string tag; 255 std::vector<T> acceptable_values; 256 }; 257 258 //: 259 // Functor vil_nitf2_choose_field_value defines a function that sets its out 260 // parameter to a value of one of two fields of a field sequence. The 261 // field chosen is determined by the evaluating the functor passed as 262 // argument 'choose_tag_1_predicate': tag_1 is chosen if it evaluates to true; 263 // tag_2, otherwise. 264 // 265 template<typename T> 266 class vil_nitf2_choose_field_value : public vil_nitf2_field_functor<T> 267 { 268 public: 269 /// Constructor. I take ownership of inDecider. vil_nitf2_choose_field_value(std::string tag_1,std::string tag_2,vil_nitf2_field_functor<bool> * choose_tag_1_predicate)270 vil_nitf2_choose_field_value(std::string tag_1, std::string tag_2, 271 vil_nitf2_field_functor<bool>* choose_tag_1_predicate) 272 : tag_1(std::move(tag_1)), tag_2(std::move(tag_2)), choose_tag_1_predicate(choose_tag_1_predicate) {} 273 copy()274 vil_nitf2_field_functor<T>* copy() const override { 275 return new vil_nitf2_choose_field_value( 276 tag_1, tag_2, choose_tag_1_predicate->copy()); } 277 ~vil_nitf2_choose_field_value()278 ~vil_nitf2_choose_field_value() override { 279 if (choose_tag_1_predicate) delete choose_tag_1_predicate; 280 } 281 operator()282 bool operator() (vil_nitf2_field_sequence* record, 283 const vil_nitf2_index_vector& indexes, T& value) override { 284 bool choose_tag_1; 285 if ((*choose_tag_1_predicate)(record, indexes, choose_tag_1)) { 286 if (choose_tag_1) return record->get_value(tag_1, indexes, value, true); 287 else return record->get_value(tag_2, indexes, value, true); 288 } 289 else return false; 290 } 291 private: 292 std::string tag_1; 293 std::string tag_2; 294 vil_nitf2_field_functor<bool>* choose_tag_1_predicate; 295 }; 296 297 // Functor vil_nitf2_constant_functor defines a function that sets its 298 // output value to a constant that does not depend on the field sequence 299 // passed to it. 300 // 301 template<typename T> 302 class vil_nitf2_constant_functor : public vil_nitf2_field_functor<T> 303 { 304 public: vil_nitf2_constant_functor(T value)305 vil_nitf2_constant_functor(T value) : value_(value) {} 306 copy()307 vil_nitf2_constant_functor* copy() const override { 308 return new vil_nitf2_constant_functor(value_); 309 } 310 311 ~vil_nitf2_constant_functor() override = default; 312 operator()313 bool operator() (vil_nitf2_field_sequence* /*record*/, 314 const vil_nitf2_index_vector& /*indexes*/, T& value) override { 315 value = value_; 316 return true; 317 } 318 319 private: 320 T value_; 321 }; 322 323 #endif // VIL_NITF2_FIELD_FUNCTOR_H 324