1 #ifndef INCLUDED_PCRTYPES 2 # define INCLUDED_PCRTYPES 3 4 #ifndef INCLUDED_CSFTYPES 5 #include "csftypes.h" 6 #define INCLUDED_CSFTYPES 7 #endif 8 9 #ifndef INCLUDED_STRING 10 #include <string> 11 #define INCLUDED_STRING 12 #endif 13 14 /* NOTE that this file is included in the PCRaster gdal driver 15 * it accounts for more compiler issues than we deal with 16 * normally in PCRaster, such as the VC6 compiler. 17 * 64 bit integer typedefs are only defined for the PCRaster 18 * source not for the Gdal driver. 19 * The Gdal PCRaster driver defines USE_IN_GDAL, PCRaster sources 20 * do not. 21 */ 22 23 // memset 24 // use string.h not cstring 25 // VC6 does not have memset in std 26 // better use Ansi-C string.h to be safe 27 #ifndef INCLUDED_C_STRING 28 #include <string.h> 29 #define INCLUDED_C_STRING 30 #endif 31 32 #ifndef USE_IN_GDAL 33 // exclude Gdal driver, only for PCRaster sources 34 35 # ifdef _MSC_VER 36 typedef __int64 PCR_INT8; 37 typedef unsigned __int64 PCR_UINT8; 38 # else 39 // assume gcc FTTB 40 typedef long long PCR_INT8; 41 typedef unsigned long long PCR_UINT8; 42 # endif 43 /* from gcc manual: 44 ISO C99 supports data types for integers that are at least 64 bits wide, Mperror(const char * userString)45 and as an extension GCC supports them in C89 mode and in C++. Simply 46 write long long int for a signed integer, or unsigned long long int for 47 an unsigned integer. To make an integer constant of type long long int, 48 add the suffix `LL' to the integer. To make an integer constant of type 49 unsigned long long int, add the suffix `ULL' to the integer. 50 51 WARNING: macros below are not typesafe, use pcr::isMV and pcr::setMV instead 52 */ 53 #define MV_INT8 ((CSF_IN_GLOBAL_NS PCR_INT8)0x8000000000000000LL) 54 #define MV_UINT8 ((CSF_IN_GLOBAL_NS PCR_UINT8)0xFFFFFFFFFFFFFFFFULL) 55 #define IS_MV_INT8(x) ((*((const CSF_IN_GLOBAL_NS PCR_INT8 *)x)) == MV_INT8) 56 #define IS_MV_UINT8(x) ((*((const CSF_IN_GLOBAL_NS PCR_UINT8 *)x)) == MV_UINT8) 57 #define SET_MV_INT8(x) ( (*((PCR_INT8 *)(x))) = MV_INT8) 58 #define SET_MV_UINT8(x) ( (*((PCR_UINT8 *)(x))) = MV_UINT8) 59 60 #endif 61 62 namespace pcr { 63 /*! 64 \brief Tests if the value v is a missing value. 65 \param v the value to be tested. 66 \return True if value \a v is a missing value. 67 68 The generic isMV(const T& v) is not implemented, only the specializations. 69 70 TODO: Check translation of todo to English. 71 \todo Put all things with a certain type, SMF, set Mv isType in a so-called. 72 Struct trait see cast drama as isMV fog INT2 in BandMapTest::Open2. 73 See numeric_limit discussion in Josuttis. 74 */ 75 template<typename T> static bool isMV(const T& v); 76 /*! 77 \brief Tests if the value pointed to by v is a missing value. 78 \param v Pointer to the value to be tested. 79 \return True if the value pointed to by v is a missing value. 80 */ 81 template<typename T> static bool isMV(T* v) { 82 return isMV(*v); 83 } 84 85 # define PCR_DEF_ISMV(type) \ 86 template<> \ 87 inline bool isMV(const type& v) \ 88 { return v == MV_##type; } 89 PCR_DEF_ISMV(UINT1) 90 PCR_DEF_ISMV(UINT2) 91 PCR_DEF_ISMV(UINT4) 92 PCR_DEF_ISMV(INT1) 93 PCR_DEF_ISMV(INT2) 94 PCR_DEF_ISMV(INT4) 95 # ifndef USE_IN_GDAL 96 template<> 97 inline bool isMV(const PCR_UINT8& v) 98 { return v == MV_UINT8; } 99 template<> 100 inline bool isMV(const PCR_INT8& v) 101 { return v == MV_INT8; } 102 # endif 103 # undef PCR_DEF_ISMV 104 template<> inline bool isMV(const REAL4& v) 105 { return IS_MV_REAL4(&v); } 106 template<> inline bool isMV(const REAL8& v) 107 { return IS_MV_REAL8(&v); } 108 109 template<> inline bool isMV(std::string const& string) 110 { 111 return string.empty(); 112 } 113 114 /*! 115 \brief Sets the value v to a missing value. 116 \param v value to be set. 117 the generic setMV(T& v) is not implemented, only the specializations 118 */ 119 template<typename T> void setMV(T& v); 120 /*! 121 \brief Sets the value pointed to by v to a missing value. 122 \param v Pointer to the value to be set. 123 */ 124 template<typename T> static void setMV(T *v) { 125 setMV(*v); 126 } 127 128 # define PCR_DEF_SETMV(type) \ 129 template<> \ 130 inline void setMV(type& v) \ 131 { v = MV_##type; } 132 PCR_DEF_SETMV(UINT1) 133 PCR_DEF_SETMV(UINT2) 134 PCR_DEF_SETMV(UINT4) 135 PCR_DEF_SETMV(INT1) 136 PCR_DEF_SETMV(INT2) 137 PCR_DEF_SETMV(INT4) 138 # ifndef USE_IN_GDAL 139 template<> 140 inline void setMV(PCR_UINT8& v) 141 { v = MV_UINT8; } 142 template<> 143 inline void setMV(PCR_INT8& v) 144 { v = MV_INT8; } 145 # endif 146 # undef PCR_DEF_SETMV 147 148 template<> 149 inline void setMV(REAL4& v) 150 { 151 # ifndef __i386__ 152 SET_MV_REAL4((&v)); 153 # else 154 // this fixes an optimization problem (release mode), if is v is a single 155 // element variable in function scope (stack-based) 156 // constraint the setting to memory (m) 157 // for correct alignment 158 asm ("movl $-1, %0" : "=m" (v)); 159 # endif 160 } 161 template<> 162 inline void setMV(REAL8& v) 163 { 164 # ifndef __i386__ 165 SET_MV_REAL8((&v)); 166 # else 167 memset(&v,MV_UINT1,sizeof(REAL8)); 168 // constraint the setting to memory (m) 169 // this fixes the same optimization problem, as for REAL4 170 // see com_mvoptest.cc, does not work: ! 171 // int *v2= (int *)&v; 172 // asm ("movl $-1, %[dest]" : [dest] "=m" (v2[0])); 173 // asm ("movl $-1, %[dest]" : [dest] "=m" (v2[1])); 174 # endif 175 } 176 177 template<> 178 inline void setMV(std::string& string) 179 { 180 // VC6 does not have clear 181 // string.clear(); 182 string=""; 183 } 184 185 /*! \brief set array \a v of size \a n to all MV's 186 * the generic setMV(T& v) is implemented, the specializations 187 * are optimizations 188 * \todo 189 * check if stdlib has a 'wordsized' memset 190 * or optimize for I86, for gcc look into include/asm/string 191 */ 192 template<typename T> 193 static void setMV(T *v, size_t n) 194 { 195 for(size_t i=0; i<n; i++) 196 pcr::setMV(v[i]); 197 } 198 199 namespace detail { 200 template<typename T> 201 static void setMVMemSet(T *v, size_t n) { 202 memset(v,MV_UINT1,n*sizeof(T)); 203 } 204 } 205 206 # define PCR_DEF_SETMV_MEMSET(type) \ 207 template<> \ 208 inline void setMV(type* v,size_t n) \ 209 { detail::setMVMemSet(v,n); } 210 PCR_DEF_SETMV_MEMSET(UINT1) 211 PCR_DEF_SETMV_MEMSET(UINT2) 212 PCR_DEF_SETMV_MEMSET(UINT4) 213 # ifndef USE_IN_GDAL 214 PCR_DEF_SETMV_MEMSET(PCR_UINT8) 215 # endif 216 PCR_DEF_SETMV_MEMSET(REAL4) 217 PCR_DEF_SETMV_MEMSET(REAL8) 218 # undef PCR_DEF_SETMV_MEMSET 219 template<> 220 inline void setMV(INT1 *v, size_t n) { 221 memset(v,MV_INT1,n); 222 } 223 224 //! replace a value equal to \a nonStdMV with the standard MV 225 /*! 226 * \todo 227 * the isMV test is only needed for floats, to protect NAN evaluation 228 * what once happened on bcc/win32. Should reevaluate that. 229 */ 230 template<typename T> 231 struct AlterToStdMV { 232 T d_nonStdMV; 233 AlterToStdMV(T nonStdMV): 234 d_nonStdMV(nonStdMV) {} 235 236 void operator()(T& v) { 237 if (!isMV(v) && v == d_nonStdMV) 238 setMV(v); 239 } 240 }; 241 242 //! return the value or the standard missing value if value equal to \a nonStdMV 243 /*! 244 * \todo 245 * the isMV test is only needed for floats, to protect NAN evaluation 246 * what once happened on bcc/win32. Should reevaluate that. 247 */ 248 template<typename T> 249 struct ToStdMV { 250 T d_nonStdMV; 251 T d_mv; 252 ToStdMV(T nonStdMV): 253 d_nonStdMV(nonStdMV) { 254 setMV(d_mv); 255 } 256 257 T operator()(T const& v) { 258 if (!isMV(v) && v == d_nonStdMV) { 259 return d_mv; 260 } 261 return v; 262 } 263 }; 264 265 //! replace the standard MV with a value equal to \a otherMV 266 /*! 267 * \todo 268 * the isMV test is only needed for floats, to protect NAN evaluation 269 * what once happened on bcc/win32. Should reevaluate that. 270 */ 271 template<typename T> 272 struct AlterFromStdMV { 273 T d_otherMV; 274 AlterFromStdMV(T otherMV): 275 d_otherMV(otherMV) {} 276 277 void operator()(T& v) { 278 if (isMV(v)) 279 v = d_otherMV; 280 } 281 }; 282 283 //! return the value or \a otherMV if value equal to standard MV 284 /*! 285 * \todo 286 * the isMV test is only needed for floats, to protect NAN evaluation 287 * what once happened on bcc/win32. Should reevaluate that. 288 */ 289 template<typename T> 290 struct FromStdMV { 291 T d_otherMV; 292 FromStdMV(T otherMV): 293 d_otherMV(otherMV) {} 294 295 T operator()(const T& v) { 296 if (isMV(v)) 297 return d_otherMV; 298 return v; 299 } 300 }; 301 302 } 303 304 305 #endif 306