Line data Source code
1 : /****************************************************************************** 2 : * Name: gdal_typetraits.h 3 : * Project: GDAL Core 4 : * Purpose: Type traits for mapping C++ types to and from GDAL/OGR types. 5 : * Author: Robin Princeley, <rprinceley at esri dot com> 6 : * 7 : ****************************************************************************** 8 : * Permission is hereby granted, free of charge, to any person obtaining a 9 : * copy of this software and associated documentation files (the "Software"), 10 : * to deal in the Software without restriction, including without limitation 11 : * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12 : * and/or sell copies of the Software, and to permit persons to whom the 13 : * Software is furnished to do so, subject to the following conditions: 14 : * 15 : * The above copyright notice and this permission notice shall be included 16 : * in all copies or substantial portions of the Software. 17 : * 18 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24 : * DEALINGS IN THE SOFTWARE. 25 : ****************************************************************************/ 26 : #if !defined(GDAL_TYPETRAITS_H_INCLUDED) 27 : #define GDAL_TYPETRAITS_H_INCLUDED 28 : 29 : #include "gdal_priv.h" 30 : 31 : // NOTE: below GDAL_ENABLE_FLOAT16 is not guaranteed to be stable and is 32 : // mostly for Esri internal needs for now. Might be revisited if/once RFC 100 33 : // (https://github.com/OSGeo/gdal/pull/10146) is adopted. 34 : #ifdef GDAL_ENABLE_FLOAT16 35 : #if defined(__GNUC__) || defined(__clang__) 36 : #define __STDC_WANT_IEC_60559_TYPES_EXT__ 37 : #include <float.h> // Also brings in _Float16 38 : #endif 39 : #endif 40 : 41 : #include <complex> 42 : 43 : namespace gdal 44 : { 45 : 46 : /** Trait accepting a C++ type ([u]int[8/16/32/64], float, double, 47 : * std::complex<float>, std::complex<double> or std::string) 48 : * and mapping it to GDALDataType / OGRFieldType. 49 : * 50 : * Each specialization has the following members: 51 : * static constexpr GDALDataType gdal_type; 52 : * static constexpr size_t size; 53 : * static constexpr OGRFieldType ogr_type; 54 : * static constexpr OGRFieldSubType ogr_subtype; 55 : * 56 : * @since 3.11 57 : */ 58 : template <typename T> struct CXXTypeTraits 59 : { 60 : }; 61 : 62 : //! @cond Doxygen_Suppress 63 : template <> struct CXXTypeTraits<int8_t> 64 : { 65 : static constexpr GDALDataType gdal_type = GDT_Int8; 66 : static constexpr size_t size = sizeof(int8_t); 67 : static constexpr OGRFieldType ogr_type = OFTInteger; 68 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 69 : 70 1 : static inline GDALExtendedDataType GetExtendedDataType() 71 : { 72 1 : return GDALExtendedDataType::Create(GDT_Int8); 73 : } 74 : }; 75 : 76 : template <> struct CXXTypeTraits<uint8_t> 77 : { 78 : static constexpr GDALDataType gdal_type = GDT_Byte; 79 : static constexpr size_t size = sizeof(uint8_t); 80 : static constexpr OGRFieldType ogr_type = OFTInteger; 81 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 82 : 83 1 : static inline GDALExtendedDataType GetExtendedDataType() 84 : { 85 1 : return GDALExtendedDataType::Create(GDT_Byte); 86 : } 87 : }; 88 : 89 : template <> struct CXXTypeTraits<int16_t> 90 : { 91 : static constexpr GDALDataType gdal_type = GDT_Int16; 92 : static constexpr size_t size = sizeof(int16_t); 93 : static constexpr OGRFieldType ogr_type = OFTInteger; 94 : static constexpr OGRFieldSubType ogr_subtype = OFSTInt16; 95 : 96 1 : static inline GDALExtendedDataType GetExtendedDataType() 97 : { 98 1 : return GDALExtendedDataType::Create(GDT_Int16); 99 : } 100 : }; 101 : 102 : template <> struct CXXTypeTraits<uint16_t> 103 : { 104 : static constexpr GDALDataType gdal_type = GDT_UInt16; 105 : static constexpr size_t size = sizeof(uint16_t); 106 : static constexpr OGRFieldType ogr_type = OFTInteger; 107 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 108 : 109 1 : static inline GDALExtendedDataType GetExtendedDataType() 110 : { 111 1 : return GDALExtendedDataType::Create(GDT_UInt16); 112 : } 113 : }; 114 : 115 : template <> struct CXXTypeTraits<int32_t> 116 : { 117 : static constexpr GDALDataType gdal_type = GDT_Int32; 118 : static constexpr size_t size = sizeof(int32_t); 119 : static constexpr OGRFieldType ogr_type = OFTInteger; 120 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 121 : 122 1 : static inline GDALExtendedDataType GetExtendedDataType() 123 : { 124 1 : return GDALExtendedDataType::Create(GDT_Int32); 125 : } 126 : }; 127 : 128 : template <> struct CXXTypeTraits<uint32_t> 129 : { 130 : static constexpr GDALDataType gdal_type = GDT_UInt32; 131 : static constexpr size_t size = sizeof(uint32_t); 132 : static constexpr OGRFieldType ogr_type = OFTInteger64; 133 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 134 : 135 1 : static inline GDALExtendedDataType GetExtendedDataType() 136 : { 137 1 : return GDALExtendedDataType::Create(GDT_UInt32); 138 : } 139 : }; 140 : 141 : template <> struct CXXTypeTraits<int64_t> 142 : { 143 : static constexpr GDALDataType gdal_type = GDT_Int64; 144 : static constexpr size_t size = sizeof(int64_t); 145 : static constexpr OGRFieldType ogr_type = OFTInteger64; 146 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 147 : 148 1 : static inline GDALExtendedDataType GetExtendedDataType() 149 : { 150 1 : return GDALExtendedDataType::Create(GDT_Int64); 151 : } 152 : }; 153 : 154 : template <> struct CXXTypeTraits<uint64_t> 155 : { 156 : static constexpr GDALDataType gdal_type = GDT_UInt64; 157 : static constexpr size_t size = sizeof(uint64_t); 158 : // Mapping to Real is questionable... 159 : static constexpr OGRFieldType ogr_type = OFTReal; 160 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 161 : 162 1 : static inline GDALExtendedDataType GetExtendedDataType() 163 : { 164 1 : return GDALExtendedDataType::Create(GDT_UInt64); 165 : } 166 : }; 167 : 168 : template <> struct CXXTypeTraits<float> 169 : { 170 : static constexpr GDALDataType gdal_type = GDT_Float32; 171 : static constexpr size_t size = sizeof(float); 172 : static constexpr OGRFieldType ogr_type = OFTReal; 173 : static constexpr OGRFieldSubType ogr_subtype = OFSTFloat32; 174 : 175 1 : static inline GDALExtendedDataType GetExtendedDataType() 176 : { 177 1 : return GDALExtendedDataType::Create(GDT_Float32); 178 : } 179 : }; 180 : 181 : template <> struct CXXTypeTraits<double> 182 : { 183 : static constexpr GDALDataType gdal_type = GDT_Float64; 184 : static constexpr size_t size = sizeof(double); 185 : static constexpr OGRFieldType ogr_type = OFTReal; 186 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 187 : 188 1 : static inline GDALExtendedDataType GetExtendedDataType() 189 : { 190 1 : return GDALExtendedDataType::Create(GDT_Float64); 191 : } 192 : }; 193 : 194 : template <> struct CXXTypeTraits<std::complex<float>> 195 : { 196 : static constexpr GDALDataType gdal_type = GDT_CFloat32; 197 : static constexpr size_t size = sizeof(float) * 2; 198 : static constexpr OGRFieldType ogr_type = OFTMaxType; 199 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 200 : 201 1 : static inline GDALExtendedDataType GetExtendedDataType() 202 : { 203 1 : return GDALExtendedDataType::Create(GDT_CFloat32); 204 : } 205 : }; 206 : 207 : template <> struct CXXTypeTraits<std::complex<double>> 208 : { 209 : static constexpr GDALDataType gdal_type = GDT_CFloat64; 210 : static constexpr size_t size = sizeof(double) * 2; 211 : static constexpr OGRFieldType ogr_type = OFTMaxType; 212 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 213 : 214 1 : static inline GDALExtendedDataType GetExtendedDataType() 215 : { 216 1 : return GDALExtendedDataType::Create(GDT_CFloat64); 217 : } 218 : }; 219 : 220 : #if defined(GDAL_ENABLE_FLOAT16) && defined(FLT16_MAX) && defined(FLT16_MIN) 221 : template <> struct CXXTypeTraits<_Float16> 222 : { 223 : static constexpr GDALDataType gdal_type = GDT_Float16; 224 : static constexpr size_t size = sizeof(_Float16); 225 : static constexpr OGRFieldType ogr_type = OFTReal; 226 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 227 : 228 : static inline GDALExtendedDataType GetExtendedDataType() 229 : { 230 : return GDALExtendedDataType::Create(GDT_Float16); 231 : } 232 : }; 233 : #endif 234 : 235 : template <> struct CXXTypeTraits<std::string> 236 : { 237 : static constexpr GDALDataType gdal_type = GDT_Unknown; 238 : static constexpr size_t size = 0; 239 : static constexpr OGRFieldType ogr_type = OFTString; 240 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 241 : 242 1 : static inline GDALExtendedDataType GetExtendedDataType() 243 : { 244 1 : return GDALExtendedDataType::CreateString(); 245 : } 246 : }; 247 : 248 : //! @endcond 249 : 250 : /** Trait accepting a GDALDataType and mapping it to corresponding C++ type and 251 : * OGRFieldType 252 : * 253 : * Each specialization has the following members: 254 : * typedef T type; (except for GDT_CInt16 and GDT_CInt32) 255 : * static constexpr size_t size; 256 : * static constexpr OGRFieldType ogr_type; 257 : * static constexpr OGRFieldSubType ogr_subtype; 258 : * static inline GDALExtendedDataType GetExtendedDataType(); 259 : * 260 : * @since 3.11 261 : */ 262 : template <GDALDataType T> struct GDALDataTypeTraits 263 : { 264 : }; 265 : 266 : //! @cond Doxygen_Suppress 267 : template <> struct GDALDataTypeTraits<GDT_Int8> 268 : { 269 : typedef int8_t type; 270 : static constexpr size_t size = sizeof(int8_t); 271 : static constexpr OGRFieldType ogr_type = OFTInteger; 272 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 273 : 274 1 : static inline GDALExtendedDataType GetExtendedDataType() 275 : { 276 1 : return GDALExtendedDataType::Create(GDT_Int8); 277 : } 278 : }; 279 : 280 : template <> struct GDALDataTypeTraits<GDT_Byte> 281 : { 282 : typedef uint8_t type; 283 : static constexpr size_t size = sizeof(uint8_t); 284 : static constexpr OGRFieldType ogr_type = OFTInteger; 285 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 286 : 287 1 : static inline GDALExtendedDataType GetExtendedDataType() 288 : { 289 1 : return GDALExtendedDataType::Create(GDT_Byte); 290 : } 291 : }; 292 : 293 : template <> struct GDALDataTypeTraits<GDT_Int16> 294 : { 295 : typedef int16_t type; 296 : static constexpr size_t size = sizeof(int16_t); 297 : static constexpr OGRFieldType ogr_type = OFTInteger; 298 : static constexpr OGRFieldSubType ogr_subtype = OFSTInt16; 299 : 300 1 : static inline GDALExtendedDataType GetExtendedDataType() 301 : { 302 1 : return GDALExtendedDataType::Create(GDT_Int16); 303 : } 304 : }; 305 : 306 : template <> struct GDALDataTypeTraits<GDT_UInt16> 307 : { 308 : typedef uint16_t type; 309 : static constexpr size_t size = sizeof(uint16_t); 310 : static constexpr OGRFieldType ogr_type = OFTInteger; 311 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 312 : 313 1 : static inline GDALExtendedDataType GetExtendedDataType() 314 : { 315 1 : return GDALExtendedDataType::Create(GDT_UInt16); 316 : } 317 : }; 318 : 319 : template <> struct GDALDataTypeTraits<GDT_Int32> 320 : { 321 : typedef int32_t type; 322 : static constexpr size_t size = sizeof(int32_t); 323 : static constexpr OGRFieldType ogr_type = OFTInteger; 324 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 325 : 326 1 : static inline GDALExtendedDataType GetExtendedDataType() 327 : { 328 1 : return GDALExtendedDataType::Create(GDT_Int32); 329 : } 330 : }; 331 : 332 : template <> struct GDALDataTypeTraits<GDT_UInt32> 333 : { 334 : typedef uint32_t type; 335 : static constexpr size_t size = sizeof(uint32_t); 336 : static constexpr OGRFieldType ogr_type = OFTInteger64; 337 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 338 : 339 1 : static inline GDALExtendedDataType GetExtendedDataType() 340 : { 341 1 : return GDALExtendedDataType::Create(GDT_UInt32); 342 : } 343 : }; 344 : 345 : template <> struct GDALDataTypeTraits<GDT_Int64> 346 : { 347 : typedef int64_t type; 348 : static constexpr size_t size = sizeof(int64_t); 349 : static constexpr OGRFieldType ogr_type = OFTInteger64; 350 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 351 : 352 1 : static inline GDALExtendedDataType GetExtendedDataType() 353 : { 354 1 : return GDALExtendedDataType::Create(GDT_Int64); 355 : } 356 : }; 357 : 358 : template <> struct GDALDataTypeTraits<GDT_UInt64> 359 : { 360 : typedef uint64_t type; 361 : static constexpr size_t size = sizeof(uint64_t); 362 : // Mapping to Real is questionable... 363 : static constexpr OGRFieldType ogr_type = OFTReal; 364 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 365 : 366 1 : static inline GDALExtendedDataType GetExtendedDataType() 367 : { 368 1 : return GDALExtendedDataType::Create(GDT_UInt64); 369 : } 370 : }; 371 : 372 : template <> struct GDALDataTypeTraits<GDT_Float32> 373 : { 374 : typedef float type; 375 : static constexpr size_t size = sizeof(float); 376 : static constexpr OGRFieldType ogr_type = OFTReal; 377 : static constexpr OGRFieldSubType ogr_subtype = OFSTFloat32; 378 : 379 1 : static inline GDALExtendedDataType GetExtendedDataType() 380 : { 381 1 : return GDALExtendedDataType::Create(GDT_Float32); 382 : } 383 : }; 384 : 385 : template <> struct GDALDataTypeTraits<GDT_Float64> 386 : { 387 : typedef double type; 388 : static constexpr size_t size = sizeof(double); 389 : static constexpr OGRFieldType ogr_type = OFTReal; 390 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 391 : 392 1 : static inline GDALExtendedDataType GetExtendedDataType() 393 : { 394 1 : return GDALExtendedDataType::Create(GDT_Float64); 395 : } 396 : }; 397 : 398 : template <> struct GDALDataTypeTraits<GDT_CInt16> 399 : { 400 : // typedef type not available ! 401 : static constexpr size_t size = sizeof(int16_t) * 2; 402 : static constexpr OGRFieldType ogr_type = OFTMaxType; 403 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 404 : 405 1 : static inline GDALExtendedDataType GetExtendedDataType() 406 : { 407 1 : return GDALExtendedDataType::Create(GDT_CInt16); 408 : } 409 : }; 410 : 411 : template <> struct GDALDataTypeTraits<GDT_CInt32> 412 : { 413 : // typedef type not available ! 414 : static constexpr size_t size = sizeof(int32_t) * 2; 415 : static constexpr OGRFieldType ogr_type = OFTMaxType; 416 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 417 : 418 1 : static inline GDALExtendedDataType GetExtendedDataType() 419 : { 420 1 : return GDALExtendedDataType::Create(GDT_CInt32); 421 : } 422 : }; 423 : 424 : template <> struct GDALDataTypeTraits<GDT_CFloat32> 425 : { 426 : typedef std::complex<float> type; 427 : static constexpr size_t size = sizeof(float) * 2; 428 : static constexpr OGRFieldType ogr_type = OFTMaxType; 429 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 430 : 431 1 : static inline GDALExtendedDataType GetExtendedDataType() 432 : { 433 1 : return GDALExtendedDataType::Create(GDT_CFloat32); 434 : } 435 : }; 436 : 437 : template <> struct GDALDataTypeTraits<GDT_CFloat64> 438 : { 439 : typedef std::complex<double> type; 440 : static constexpr size_t size = sizeof(double) * 2; 441 : static constexpr OGRFieldType ogr_type = OFTMaxType; 442 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 443 : 444 1 : static inline GDALExtendedDataType GetExtendedDataType() 445 : { 446 1 : return GDALExtendedDataType::Create(GDT_CFloat64); 447 : } 448 : }; 449 : 450 : //! @endcond 451 : 452 : /** Map a GDALDataType to the most suitable OGRFieldType. 453 : * 454 : * Note that GDT_UInt32 is mapped to OFTInteger64 to avoid data losses. 455 : * GDT_UInt64 is mapped to OFTReal, which can be lossy. If values are 456 : * guaranteed to be in [0, INT64_MAX] range, callers might want to use 457 : * OFTInteger64 instead. 458 : * There is no mapping for complex data types. 459 : * 460 : * @since 3.11 461 : */ 462 18 : inline OGRFieldType GetOGRFieldType(const GDALDataType gdal_type) 463 : { 464 18 : switch (gdal_type) 465 : { 466 6 : case GDT_Byte: 467 : case GDT_Int8: 468 : case GDT_Int16: 469 : case GDT_Int32: 470 : case GDT_UInt16: 471 6 : return OFTInteger; 472 2 : case GDT_UInt32: 473 : case GDT_Int64: 474 2 : return OFTInteger64; 475 3 : case GDT_UInt64: // Questionable 476 : case GDT_Float32: 477 : case GDT_Float64: 478 3 : return OFTReal; 479 7 : case GDT_CInt16: 480 : case GDT_CInt32: 481 : case GDT_CFloat32: 482 : case GDT_CFloat64: 483 : case GDT_Unknown: 484 : case GDT_TypeCount: 485 7 : break; 486 : } 487 7 : return OFTMaxType; 488 : } 489 : 490 : /** Map a GDALExtendedDataType to the most suitable OGRFieldType. 491 : * 492 : * Note that GDT_UInt32 is mapped to OFTInteger64 to avoid data losses. 493 : * GDT_UInt64 is mapped to OFTReal, which can be lossy. If values are 494 : * guaranteed to be in [0, INT64_MAX] range, callers might want to use 495 : * OFTInteger64 instead. 496 : * 497 : * @since 3.11 498 : */ 499 3 : inline OGRFieldType GetOGRFieldType(const GDALExtendedDataType &oEDT) 500 : { 501 3 : if (oEDT.GetClass() == GEDTC_NUMERIC) 502 2 : return GetOGRFieldType(oEDT.GetNumericDataType()); 503 1 : else if (oEDT.GetClass() == GEDTC_STRING) 504 1 : return OFTString; 505 0 : return OFTMaxType; 506 : } 507 : 508 : } // namespace gdal 509 : 510 : #endif // GDAL_TYPETRAITS_H_INCLUDED