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