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 : #include "cpl_float.h" 31 : 32 : #include <complex> 33 : 34 : namespace gdal 35 : { 36 : 37 : /** Trait accepting a C++ type ([u]int[8/16/32/64], float, double, 38 : * std::complex<float>, std::complex<double> or std::string) 39 : * and mapping it to GDALDataType / OGRFieldType. 40 : * 41 : * Each specialization has the following members: 42 : * static constexpr GDALDataType gdal_type; 43 : * static constexpr size_t size; 44 : * static constexpr OGRFieldType ogr_type; 45 : * static constexpr OGRFieldSubType ogr_subtype; 46 : * 47 : * @since 3.11 48 : */ 49 : template <typename T> struct CXXTypeTraits 50 : { 51 : }; 52 : 53 : //! @cond Doxygen_Suppress 54 : template <> struct CXXTypeTraits<int8_t> 55 : { 56 : static constexpr GDALDataType gdal_type = GDT_Int8; 57 : static constexpr size_t size = sizeof(int8_t); 58 : static constexpr OGRFieldType ogr_type = OFTInteger; 59 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 60 : 61 1 : static inline GDALExtendedDataType GetExtendedDataType() 62 : { 63 1 : return GDALExtendedDataType::Create(GDT_Int8); 64 : } 65 : }; 66 : 67 : template <> struct CXXTypeTraits<uint8_t> 68 : { 69 : static constexpr GDALDataType gdal_type = GDT_Byte; 70 : static constexpr size_t size = sizeof(uint8_t); 71 : static constexpr OGRFieldType ogr_type = OFTInteger; 72 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 73 : 74 1 : static inline GDALExtendedDataType GetExtendedDataType() 75 : { 76 1 : return GDALExtendedDataType::Create(GDT_Byte); 77 : } 78 : }; 79 : 80 : template <> struct CXXTypeTraits<int16_t> 81 : { 82 : static constexpr GDALDataType gdal_type = GDT_Int16; 83 : static constexpr size_t size = sizeof(int16_t); 84 : static constexpr OGRFieldType ogr_type = OFTInteger; 85 : static constexpr OGRFieldSubType ogr_subtype = OFSTInt16; 86 : 87 1 : static inline GDALExtendedDataType GetExtendedDataType() 88 : { 89 1 : return GDALExtendedDataType::Create(GDT_Int16); 90 : } 91 : }; 92 : 93 : template <> struct CXXTypeTraits<uint16_t> 94 : { 95 : static constexpr GDALDataType gdal_type = GDT_UInt16; 96 : static constexpr size_t size = sizeof(uint16_t); 97 : static constexpr OGRFieldType ogr_type = OFTInteger; 98 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 99 : 100 1 : static inline GDALExtendedDataType GetExtendedDataType() 101 : { 102 1 : return GDALExtendedDataType::Create(GDT_UInt16); 103 : } 104 : }; 105 : 106 : template <> struct CXXTypeTraits<int32_t> 107 : { 108 : static constexpr GDALDataType gdal_type = GDT_Int32; 109 : static constexpr size_t size = sizeof(int32_t); 110 : static constexpr OGRFieldType ogr_type = OFTInteger; 111 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 112 : 113 1 : static inline GDALExtendedDataType GetExtendedDataType() 114 : { 115 1 : return GDALExtendedDataType::Create(GDT_Int32); 116 : } 117 : }; 118 : 119 : template <> struct CXXTypeTraits<uint32_t> 120 : { 121 : static constexpr GDALDataType gdal_type = GDT_UInt32; 122 : static constexpr size_t size = sizeof(uint32_t); 123 : static constexpr OGRFieldType ogr_type = OFTInteger64; 124 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 125 : 126 1 : static inline GDALExtendedDataType GetExtendedDataType() 127 : { 128 1 : return GDALExtendedDataType::Create(GDT_UInt32); 129 : } 130 : }; 131 : 132 : template <> struct CXXTypeTraits<int64_t> 133 : { 134 : static constexpr GDALDataType gdal_type = GDT_Int64; 135 : static constexpr size_t size = sizeof(int64_t); 136 : static constexpr OGRFieldType ogr_type = OFTInteger64; 137 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 138 : 139 1 : static inline GDALExtendedDataType GetExtendedDataType() 140 : { 141 1 : return GDALExtendedDataType::Create(GDT_Int64); 142 : } 143 : }; 144 : 145 : template <> struct CXXTypeTraits<uint64_t> 146 : { 147 : static constexpr GDALDataType gdal_type = GDT_UInt64; 148 : static constexpr size_t size = sizeof(uint64_t); 149 : // Mapping to Real is questionable... 150 : static constexpr OGRFieldType ogr_type = OFTReal; 151 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 152 : 153 1 : static inline GDALExtendedDataType GetExtendedDataType() 154 : { 155 1 : return GDALExtendedDataType::Create(GDT_UInt64); 156 : } 157 : }; 158 : 159 : template <> struct CXXTypeTraits<GFloat16> 160 : { 161 : static constexpr GDALDataType gdal_type = GDT_Float16; 162 : static constexpr size_t size = sizeof(GFloat16); 163 : static constexpr OGRFieldType ogr_type = OFTReal; 164 : // We could introduce OFSTFloat16 165 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 166 : 167 : static inline GDALExtendedDataType GetExtendedDataType() 168 : { 169 : return GDALExtendedDataType::Create(GDT_Float16); 170 : } 171 : }; 172 : 173 : template <> struct CXXTypeTraits<float> 174 : { 175 : static constexpr GDALDataType gdal_type = GDT_Float32; 176 : static constexpr size_t size = sizeof(float); 177 : static constexpr OGRFieldType ogr_type = OFTReal; 178 : static constexpr OGRFieldSubType ogr_subtype = OFSTFloat32; 179 : 180 1 : static inline GDALExtendedDataType GetExtendedDataType() 181 : { 182 1 : return GDALExtendedDataType::Create(GDT_Float32); 183 : } 184 : }; 185 : 186 : template <> struct CXXTypeTraits<double> 187 : { 188 : static constexpr GDALDataType gdal_type = GDT_Float64; 189 : static constexpr size_t size = sizeof(double); 190 : static constexpr OGRFieldType ogr_type = OFTReal; 191 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 192 : 193 1 : static inline GDALExtendedDataType GetExtendedDataType() 194 : { 195 1 : return GDALExtendedDataType::Create(GDT_Float64); 196 : } 197 : }; 198 : 199 : template <> struct CXXTypeTraits<std::complex<GFloat16>> 200 : { 201 : static constexpr GDALDataType gdal_type = GDT_CFloat16; 202 : static constexpr size_t size = sizeof(GFloat16) * 2; 203 : static constexpr OGRFieldType ogr_type = OFTMaxType; 204 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 205 : 206 : static inline GDALExtendedDataType GetExtendedDataType() 207 : { 208 : return GDALExtendedDataType::Create(GDT_CFloat16); 209 : } 210 : }; 211 : 212 : template <> struct CXXTypeTraits<std::complex<float>> 213 : { 214 : static constexpr GDALDataType gdal_type = GDT_CFloat32; 215 : static constexpr size_t size = sizeof(float) * 2; 216 : static constexpr OGRFieldType ogr_type = OFTMaxType; 217 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 218 : 219 1 : static inline GDALExtendedDataType GetExtendedDataType() 220 : { 221 1 : return GDALExtendedDataType::Create(GDT_CFloat32); 222 : } 223 : }; 224 : 225 : template <> struct CXXTypeTraits<std::complex<double>> 226 : { 227 : static constexpr GDALDataType gdal_type = GDT_CFloat64; 228 : static constexpr size_t size = sizeof(double) * 2; 229 : static constexpr OGRFieldType ogr_type = OFTMaxType; 230 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 231 : 232 1 : static inline GDALExtendedDataType GetExtendedDataType() 233 : { 234 1 : return GDALExtendedDataType::Create(GDT_CFloat64); 235 : } 236 : }; 237 : 238 : template <> struct CXXTypeTraits<std::string> 239 : { 240 : static constexpr GDALDataType gdal_type = GDT_Unknown; 241 : static constexpr size_t size = 0; 242 : static constexpr OGRFieldType ogr_type = OFTString; 243 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 244 : 245 1 : static inline GDALExtendedDataType GetExtendedDataType() 246 : { 247 1 : return GDALExtendedDataType::CreateString(); 248 : } 249 : }; 250 : 251 : //! @endcond 252 : 253 : /** Trait accepting a GDALDataType and mapping it to corresponding C++ type and 254 : * OGRFieldType 255 : * 256 : * Each specialization has the following members: 257 : * typedef T type; (except for GDT_CInt16 and GDT_CInt32) 258 : * static constexpr size_t size; 259 : * static constexpr OGRFieldType ogr_type; 260 : * static constexpr OGRFieldSubType ogr_subtype; 261 : * static inline GDALExtendedDataType GetExtendedDataType(); 262 : * 263 : * @since 3.11 264 : */ 265 : template <GDALDataType T> struct GDALDataTypeTraits 266 : { 267 : }; 268 : 269 : //! @cond Doxygen_Suppress 270 : template <> struct GDALDataTypeTraits<GDT_Int8> 271 : { 272 : typedef int8_t type; 273 : static constexpr size_t size = sizeof(int8_t); 274 : static constexpr OGRFieldType ogr_type = OFTInteger; 275 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 276 : 277 1 : static inline GDALExtendedDataType GetExtendedDataType() 278 : { 279 1 : return GDALExtendedDataType::Create(GDT_Int8); 280 : } 281 : }; 282 : 283 : template <> struct GDALDataTypeTraits<GDT_Byte> 284 : { 285 : typedef uint8_t type; 286 : static constexpr size_t size = sizeof(uint8_t); 287 : static constexpr OGRFieldType ogr_type = OFTInteger; 288 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 289 : 290 1 : static inline GDALExtendedDataType GetExtendedDataType() 291 : { 292 1 : return GDALExtendedDataType::Create(GDT_Byte); 293 : } 294 : }; 295 : 296 : template <> struct GDALDataTypeTraits<GDT_Int16> 297 : { 298 : typedef int16_t type; 299 : static constexpr size_t size = sizeof(int16_t); 300 : static constexpr OGRFieldType ogr_type = OFTInteger; 301 : static constexpr OGRFieldSubType ogr_subtype = OFSTInt16; 302 : 303 1 : static inline GDALExtendedDataType GetExtendedDataType() 304 : { 305 1 : return GDALExtendedDataType::Create(GDT_Int16); 306 : } 307 : }; 308 : 309 : template <> struct GDALDataTypeTraits<GDT_UInt16> 310 : { 311 : typedef uint16_t type; 312 : static constexpr size_t size = sizeof(uint16_t); 313 : static constexpr OGRFieldType ogr_type = OFTInteger; 314 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 315 : 316 1 : static inline GDALExtendedDataType GetExtendedDataType() 317 : { 318 1 : return GDALExtendedDataType::Create(GDT_UInt16); 319 : } 320 : }; 321 : 322 : template <> struct GDALDataTypeTraits<GDT_Int32> 323 : { 324 : typedef int32_t type; 325 : static constexpr size_t size = sizeof(int32_t); 326 : static constexpr OGRFieldType ogr_type = OFTInteger; 327 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 328 : 329 1 : static inline GDALExtendedDataType GetExtendedDataType() 330 : { 331 1 : return GDALExtendedDataType::Create(GDT_Int32); 332 : } 333 : }; 334 : 335 : template <> struct GDALDataTypeTraits<GDT_UInt32> 336 : { 337 : typedef uint32_t type; 338 : static constexpr size_t size = sizeof(uint32_t); 339 : static constexpr OGRFieldType ogr_type = OFTInteger64; 340 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 341 : 342 1 : static inline GDALExtendedDataType GetExtendedDataType() 343 : { 344 1 : return GDALExtendedDataType::Create(GDT_UInt32); 345 : } 346 : }; 347 : 348 : template <> struct GDALDataTypeTraits<GDT_Int64> 349 : { 350 : typedef int64_t type; 351 : static constexpr size_t size = sizeof(int64_t); 352 : static constexpr OGRFieldType ogr_type = OFTInteger64; 353 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 354 : 355 1 : static inline GDALExtendedDataType GetExtendedDataType() 356 : { 357 1 : return GDALExtendedDataType::Create(GDT_Int64); 358 : } 359 : }; 360 : 361 : template <> struct GDALDataTypeTraits<GDT_UInt64> 362 : { 363 : typedef uint64_t type; 364 : static constexpr size_t size = sizeof(uint64_t); 365 : // Mapping to Real is questionable... 366 : static constexpr OGRFieldType ogr_type = OFTReal; 367 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 368 : 369 1 : static inline GDALExtendedDataType GetExtendedDataType() 370 : { 371 1 : return GDALExtendedDataType::Create(GDT_UInt64); 372 : } 373 : }; 374 : 375 : template <> struct GDALDataTypeTraits<GDT_Float32> 376 : { 377 : typedef float type; 378 : static constexpr size_t size = sizeof(float); 379 : static constexpr OGRFieldType ogr_type = OFTReal; 380 : static constexpr OGRFieldSubType ogr_subtype = OFSTFloat32; 381 : 382 1 : static inline GDALExtendedDataType GetExtendedDataType() 383 : { 384 1 : return GDALExtendedDataType::Create(GDT_Float32); 385 : } 386 : }; 387 : 388 : template <> struct GDALDataTypeTraits<GDT_Float64> 389 : { 390 : typedef double type; 391 : static constexpr size_t size = sizeof(double); 392 : static constexpr OGRFieldType ogr_type = OFTReal; 393 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 394 : 395 1 : static inline GDALExtendedDataType GetExtendedDataType() 396 : { 397 1 : return GDALExtendedDataType::Create(GDT_Float64); 398 : } 399 : }; 400 : 401 : template <> struct GDALDataTypeTraits<GDT_CInt16> 402 : { 403 : // typedef type not available ! 404 : static constexpr size_t size = sizeof(int16_t) * 2; 405 : static constexpr OGRFieldType ogr_type = OFTMaxType; 406 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 407 : 408 1 : static inline GDALExtendedDataType GetExtendedDataType() 409 : { 410 1 : return GDALExtendedDataType::Create(GDT_CInt16); 411 : } 412 : }; 413 : 414 : template <> struct GDALDataTypeTraits<GDT_CInt32> 415 : { 416 : // typedef type not available ! 417 : static constexpr size_t size = sizeof(int32_t) * 2; 418 : static constexpr OGRFieldType ogr_type = OFTMaxType; 419 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 420 : 421 1 : static inline GDALExtendedDataType GetExtendedDataType() 422 : { 423 1 : return GDALExtendedDataType::Create(GDT_CInt32); 424 : } 425 : }; 426 : 427 : template <> struct GDALDataTypeTraits<GDT_CFloat32> 428 : { 429 : typedef std::complex<float> type; 430 : static constexpr size_t size = sizeof(float) * 2; 431 : static constexpr OGRFieldType ogr_type = OFTMaxType; 432 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 433 : 434 1 : static inline GDALExtendedDataType GetExtendedDataType() 435 : { 436 1 : return GDALExtendedDataType::Create(GDT_CFloat32); 437 : } 438 : }; 439 : 440 : template <> struct GDALDataTypeTraits<GDT_CFloat64> 441 : { 442 : typedef std::complex<double> type; 443 : static constexpr size_t size = sizeof(double) * 2; 444 : static constexpr OGRFieldType ogr_type = OFTMaxType; 445 : static constexpr OGRFieldSubType ogr_subtype = OFSTNone; 446 : 447 1 : static inline GDALExtendedDataType GetExtendedDataType() 448 : { 449 1 : return GDALExtendedDataType::Create(GDT_CFloat64); 450 : } 451 : }; 452 : 453 : //! @endcond 454 : 455 : /** Map a GDALDataType to the most suitable OGRFieldType. 456 : * 457 : * Note that GDT_UInt32 is mapped to OFTInteger64 to avoid data losses. 458 : * GDT_UInt64 is mapped to OFTReal, which can be lossy. If values are 459 : * guaranteed to be in [0, INT64_MAX] range, callers might want to use 460 : * OFTInteger64 instead. 461 : * There is no mapping for complex data types. 462 : * 463 : * @since 3.11 464 : */ 465 18 : inline OGRFieldType GetOGRFieldType(const GDALDataType gdal_type) 466 : { 467 18 : switch (gdal_type) 468 : { 469 6 : case GDT_Byte: 470 : case GDT_Int8: 471 : case GDT_Int16: 472 : case GDT_Int32: 473 : case GDT_UInt16: 474 6 : return OFTInteger; 475 2 : case GDT_UInt32: 476 : case GDT_Int64: 477 2 : return OFTInteger64; 478 3 : case GDT_UInt64: // Questionable 479 : case GDT_Float16: 480 : case GDT_Float32: 481 : case GDT_Float64: 482 3 : return OFTReal; 483 7 : case GDT_CInt16: 484 : case GDT_CInt32: 485 : case GDT_CFloat16: 486 : case GDT_CFloat32: 487 : case GDT_CFloat64: 488 : case GDT_Unknown: 489 : case GDT_TypeCount: 490 7 : break; 491 : } 492 7 : return OFTMaxType; 493 : } 494 : 495 : /** Map a GDALExtendedDataType to the most suitable OGRFieldType. 496 : * 497 : * Note that GDT_UInt32 is mapped to OFTInteger64 to avoid data losses. 498 : * GDT_UInt64 is mapped to OFTReal, which can be lossy. If values are 499 : * guaranteed to be in [0, INT64_MAX] range, callers might want to use 500 : * OFTInteger64 instead. 501 : * 502 : * @since 3.11 503 : */ 504 3 : inline OGRFieldType GetOGRFieldType(const GDALExtendedDataType &oEDT) 505 : { 506 3 : if (oEDT.GetClass() == GEDTC_NUMERIC) 507 2 : return GetOGRFieldType(oEDT.GetNumericDataType()); 508 1 : else if (oEDT.GetClass() == GEDTC_STRING) 509 1 : return OFTString; 510 0 : return OFTMaxType; 511 : } 512 : 513 : } // namespace gdal 514 : 515 : #endif // GDAL_TYPETRAITS_H_INCLUDED