From b2693a138f31d2dc6e56f883e5ee273642c36b99 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Mon, 30 Sep 2024 14:46:08 +0200 Subject: [PATCH] Add public gdal_typetraits.h header with gdal::CXXTypeTraits and gdal::GDALDataTypeTraits --- autotest/cpp/CMakeLists.txt | 1 + autotest/cpp/test_gdal_typetraits.cpp | 197 ++++++++++ gcore/CMakeLists.txt | 1 + gcore/gdal_typetraits.h | 510 ++++++++++++++++++++++++++ 4 files changed, 709 insertions(+) create mode 100644 autotest/cpp/test_gdal_typetraits.cpp create mode 100644 gcore/gdal_typetraits.h diff --git a/autotest/cpp/CMakeLists.txt b/autotest/cpp/CMakeLists.txt index 74f10ca99290..493f1d59f9bd 100644 --- a/autotest/cpp/CMakeLists.txt +++ b/autotest/cpp/CMakeLists.txt @@ -78,6 +78,7 @@ add_executable( test_gdal_dted.cpp test_gdal_gtiff.cpp test_gdal_pixelfn.cpp + test_gdal_typetraits.cpp test_ogr.cpp test_ogr_organize_polygons.cpp test_ogr_geometry_stealing.cpp diff --git a/autotest/cpp/test_gdal_typetraits.cpp b/autotest/cpp/test_gdal_typetraits.cpp new file mode 100644 index 000000000000..90bc1e24566b --- /dev/null +++ b/autotest/cpp/test_gdal_typetraits.cpp @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: MIT +// Copyright 2024, Even Rouault + +#include "gdal_unit_test.h" + +#include "gdal_typetraits.h" + +#include "gtest_include.h" + +namespace +{ + +struct test_gdal_typetraits : public ::testing::Test +{ +}; + +TEST_F(test_gdal_typetraits, CXXTypeTraits) +{ + static_assert(gdal::CXXTypeTraits::gdal_type == GDT_Int8); + static_assert(gdal::CXXTypeTraits::size == 1); + EXPECT_EQ( + gdal::CXXTypeTraits::GetExtendedDataType().GetNumericDataType(), + GDT_Int8); + static_assert(gdal::CXXTypeTraits::gdal_type == GDT_Byte); + static_assert(gdal::CXXTypeTraits::size == 1); + EXPECT_EQ(gdal::CXXTypeTraits::GetExtendedDataType() + .GetNumericDataType(), + GDT_Byte); + static_assert(gdal::CXXTypeTraits::gdal_type == GDT_Int16); + static_assert(gdal::CXXTypeTraits::size == 2); + EXPECT_EQ(gdal::CXXTypeTraits::GetExtendedDataType() + .GetNumericDataType(), + GDT_Int16); + static_assert(gdal::CXXTypeTraits::gdal_type == GDT_UInt16); + static_assert(gdal::CXXTypeTraits::size == 2); + EXPECT_EQ(gdal::CXXTypeTraits::GetExtendedDataType() + .GetNumericDataType(), + GDT_UInt16); + static_assert(gdal::CXXTypeTraits::gdal_type == GDT_Int32); + static_assert(gdal::CXXTypeTraits::size == 4); + EXPECT_EQ(gdal::CXXTypeTraits::GetExtendedDataType() + .GetNumericDataType(), + GDT_Int32); + static_assert(gdal::CXXTypeTraits::gdal_type == GDT_UInt32); + static_assert(gdal::CXXTypeTraits::size == 4); + EXPECT_EQ(gdal::CXXTypeTraits::GetExtendedDataType() + .GetNumericDataType(), + GDT_UInt32); + static_assert(gdal::CXXTypeTraits::gdal_type == GDT_Int64); + static_assert(gdal::CXXTypeTraits::size == 8); + EXPECT_EQ(gdal::CXXTypeTraits::GetExtendedDataType() + .GetNumericDataType(), + GDT_Int64); + static_assert(gdal::CXXTypeTraits::gdal_type == GDT_UInt64); + static_assert(gdal::CXXTypeTraits::size == 8); + EXPECT_EQ(gdal::CXXTypeTraits::GetExtendedDataType() + .GetNumericDataType(), + GDT_UInt64); + static_assert(gdal::CXXTypeTraits::gdal_type == GDT_Float32); + static_assert(gdal::CXXTypeTraits::size == 4); + EXPECT_EQ( + gdal::CXXTypeTraits::GetExtendedDataType().GetNumericDataType(), + GDT_Float32); + static_assert(gdal::CXXTypeTraits::gdal_type == GDT_Float64); + static_assert(gdal::CXXTypeTraits::size == 8); + EXPECT_EQ( + gdal::CXXTypeTraits::GetExtendedDataType().GetNumericDataType(), + GDT_Float64); + static_assert(gdal::CXXTypeTraits>::gdal_type == + GDT_CFloat32); + static_assert(gdal::CXXTypeTraits>::size == 8); + EXPECT_EQ(gdal::CXXTypeTraits>::GetExtendedDataType() + .GetNumericDataType(), + GDT_CFloat32); + static_assert(gdal::CXXTypeTraits>::gdal_type == + GDT_CFloat64); + static_assert(gdal::CXXTypeTraits>::size == 16); + EXPECT_EQ(gdal::CXXTypeTraits>::GetExtendedDataType() + .GetNumericDataType(), + GDT_CFloat64); + static_assert(gdal::CXXTypeTraits::size == 0); + EXPECT_EQ( + gdal::CXXTypeTraits::GetExtendedDataType().GetClass(), + GEDTC_STRING); +} + +TEST_F(test_gdal_typetraits, GDALDataTypeTraits) +{ + EXPECT_EQ(gdal::GDALDataTypeTraits::GetExtendedDataType() + .GetNumericDataType(), + GDT_Byte); + static_assert( + std::is_same_v::type, uint8_t>); + static_assert(gdal::GDALDataTypeTraits::size == 1); + EXPECT_EQ(gdal::GDALDataTypeTraits::GetExtendedDataType() + .GetNumericDataType(), + GDT_Int8); + static_assert( + std::is_same_v::type, int8_t>); + static_assert(gdal::GDALDataTypeTraits::size == 1); + EXPECT_EQ(gdal::GDALDataTypeTraits::GetExtendedDataType() + .GetNumericDataType(), + GDT_Int16); + static_assert( + std::is_same_v::type, int16_t>); + static_assert(gdal::GDALDataTypeTraits::size == 2); + EXPECT_EQ(gdal::GDALDataTypeTraits::GetExtendedDataType() + .GetNumericDataType(), + GDT_UInt16); + static_assert( + std::is_same_v::type, uint16_t>); + static_assert(gdal::GDALDataTypeTraits::size == 2); + EXPECT_EQ(gdal::GDALDataTypeTraits::GetExtendedDataType() + .GetNumericDataType(), + GDT_Int32); + static_assert( + std::is_same_v::type, int32_t>); + static_assert(gdal::GDALDataTypeTraits::size == 4); + EXPECT_EQ(gdal::GDALDataTypeTraits::GetExtendedDataType() + .GetNumericDataType(), + GDT_UInt32); + static_assert( + std::is_same_v::type, uint32_t>); + static_assert(gdal::GDALDataTypeTraits::size == 4); + EXPECT_EQ(gdal::GDALDataTypeTraits::GetExtendedDataType() + .GetNumericDataType(), + GDT_Int64); + static_assert( + std::is_same_v::type, int64_t>); + static_assert(gdal::GDALDataTypeTraits::size == 8); + EXPECT_EQ(gdal::GDALDataTypeTraits::GetExtendedDataType() + .GetNumericDataType(), + GDT_UInt64); + static_assert( + std::is_same_v::type, uint64_t>); + static_assert(gdal::GDALDataTypeTraits::size == 8); + EXPECT_EQ(gdal::GDALDataTypeTraits::GetExtendedDataType() + .GetNumericDataType(), + GDT_Float32); + static_assert( + std::is_same_v::type, float>); + static_assert(gdal::GDALDataTypeTraits::size == 4); + EXPECT_EQ(gdal::GDALDataTypeTraits::GetExtendedDataType() + .GetNumericDataType(), + GDT_Float64); + static_assert( + std::is_same_v::type, double>); + static_assert(gdal::GDALDataTypeTraits::size == 8); + EXPECT_EQ(gdal::GDALDataTypeTraits::GetExtendedDataType() + .GetNumericDataType(), + GDT_CInt16); + EXPECT_EQ(gdal::GDALDataTypeTraits::GetExtendedDataType() + .GetNumericDataType(), + GDT_CInt32); + EXPECT_EQ(gdal::GDALDataTypeTraits::GetExtendedDataType() + .GetNumericDataType(), + GDT_CFloat32); + static_assert(std::is_same_v::type, + std::complex>); + static_assert(gdal::GDALDataTypeTraits::size == 8); + EXPECT_EQ(gdal::GDALDataTypeTraits::GetExtendedDataType() + .GetNumericDataType(), + GDT_CFloat64); + static_assert(std::is_same_v::type, + std::complex>); + static_assert(gdal::GDALDataTypeTraits::size == 16); +} + +TEST_F(test_gdal_typetraits, GetOGRFieldType) +{ + EXPECT_EQ(gdal::GetOGRFieldType(GDT_Byte), OFTInteger); + EXPECT_EQ(gdal::GetOGRFieldType(GDT_Int8), OFTInteger); + EXPECT_EQ(gdal::GetOGRFieldType(GDT_Int16), OFTInteger); + EXPECT_EQ(gdal::GetOGRFieldType(GDT_Int32), OFTInteger); + EXPECT_EQ(gdal::GetOGRFieldType(GDT_UInt16), OFTInteger); + EXPECT_EQ(gdal::GetOGRFieldType(GDT_UInt32), OFTInteger64); + EXPECT_EQ(gdal::GetOGRFieldType(GDT_Int64), OFTInteger64); + EXPECT_EQ(gdal::GetOGRFieldType(GDT_UInt64), OFTReal); + EXPECT_EQ(gdal::GetOGRFieldType(GDT_Float32), OFTReal); + EXPECT_EQ(gdal::GetOGRFieldType(GDT_Float64), OFTReal); + EXPECT_EQ(gdal::GetOGRFieldType(GDT_CInt16), OFTMaxType); + EXPECT_EQ(gdal::GetOGRFieldType(GDT_CInt32), OFTMaxType); + EXPECT_EQ(gdal::GetOGRFieldType(GDT_CFloat32), OFTMaxType); + EXPECT_EQ(gdal::GetOGRFieldType(GDT_CFloat64), OFTMaxType); + EXPECT_EQ(gdal::GetOGRFieldType(GDT_Unknown), OFTMaxType); + EXPECT_EQ(gdal::GetOGRFieldType(GDT_TypeCount), OFTMaxType); + + EXPECT_EQ(gdal::GetOGRFieldType(GDALExtendedDataType::Create(GDT_Byte)), + OFTInteger); + EXPECT_EQ(gdal::GetOGRFieldType(GDALExtendedDataType::CreateString()), + OFTString); + EXPECT_EQ( + gdal::GetOGRFieldType(GDALExtendedDataType::Create("compound", 0, {})), + OFTMaxType); +} + +} // namespace diff --git a/gcore/CMakeLists.txt b/gcore/CMakeLists.txt index a61970e9e1f5..a4699856b6fb 100644 --- a/gcore/CMakeLists.txt +++ b/gcore/CMakeLists.txt @@ -194,6 +194,7 @@ target_public_header( gdalgeorefpamdataset.h gdal_mdreader.h gdalsubdatasetinfo.h + gdal_typetraits.h ) set(GDAL_DATA_FILES diff --git a/gcore/gdal_typetraits.h b/gcore/gdal_typetraits.h new file mode 100644 index 000000000000..f7e341f49e7c --- /dev/null +++ b/gcore/gdal_typetraits.h @@ -0,0 +1,510 @@ +/****************************************************************************** + * Name: gdal_typetraits.h + * Project: GDAL Core + * Purpose: Type traits for mapping C++ types to and from GDAL/OGR types. + * Author: Robin Princeley, + * + ****************************************************************************** + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ****************************************************************************/ +#if !defined(GDAL_TYPETRAITS_H_INCLUDED) +#define GDAL_TYPETRAITS_H_INCLUDED + +#include "gdal_priv.h" + +// NOTE: below GDAL_ENABLE_FLOAT16 is not guaranteed to be stable and is +// mostly for Esri internal needs for now. Might be revisited if/once RFC 100 +// (https://github.com/OSGeo/gdal/pull/10146) is adopted. +#ifdef GDAL_ENABLE_FLOAT16 +#if defined(__GNUC__) || defined(__clang__) +#define __STDC_WANT_IEC_60559_TYPES_EXT__ +#include // Also brings in _Float16 +#endif +#endif + +#include + +namespace gdal +{ + +/** Trait accepting a C++ type ([u]int[8/16/32/64], float, double, + * std::complex, std::complex or std::string) + * and mapping it to GDALDataType / OGRFieldType. + * + * Each specialization has the following members: + * static constexpr GDALDataType gdal_type; + * static constexpr size_t size; + * static constexpr OGRFieldType ogr_type; + * static constexpr OGRFieldSubType ogr_subtype; + * + * @since 3.11 + */ +template struct CXXTypeTraits +{ +}; + +//! @cond Doxygen_Suppress +template <> struct CXXTypeTraits +{ + static constexpr GDALDataType gdal_type = GDT_Int8; + static constexpr size_t size = sizeof(int8_t); + static constexpr OGRFieldType ogr_type = OFTInteger; + static constexpr OGRFieldSubType ogr_subtype = OFSTNone; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::Create(GDT_Int8); + } +}; + +template <> struct CXXTypeTraits +{ + static constexpr GDALDataType gdal_type = GDT_Byte; + static constexpr size_t size = sizeof(uint8_t); + static constexpr OGRFieldType ogr_type = OFTInteger; + static constexpr OGRFieldSubType ogr_subtype = OFSTNone; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::Create(GDT_Byte); + } +}; + +template <> struct CXXTypeTraits +{ + static constexpr GDALDataType gdal_type = GDT_Int16; + static constexpr size_t size = sizeof(int16_t); + static constexpr OGRFieldType ogr_type = OFTInteger; + static constexpr OGRFieldSubType ogr_subtype = OFSTInt16; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::Create(GDT_Int16); + } +}; + +template <> struct CXXTypeTraits +{ + static constexpr GDALDataType gdal_type = GDT_UInt16; + static constexpr size_t size = sizeof(uint16_t); + static constexpr OGRFieldType ogr_type = OFTInteger; + static constexpr OGRFieldSubType ogr_subtype = OFSTNone; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::Create(GDT_UInt16); + } +}; + +template <> struct CXXTypeTraits +{ + static constexpr GDALDataType gdal_type = GDT_Int32; + static constexpr size_t size = sizeof(int32_t); + static constexpr OGRFieldType ogr_type = OFTInteger; + static constexpr OGRFieldSubType ogr_subtype = OFSTNone; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::Create(GDT_Int32); + } +}; + +template <> struct CXXTypeTraits +{ + static constexpr GDALDataType gdal_type = GDT_UInt32; + static constexpr size_t size = sizeof(uint32_t); + static constexpr OGRFieldType ogr_type = OFTInteger64; + static constexpr OGRFieldSubType ogr_subtype = OFSTNone; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::Create(GDT_UInt32); + } +}; + +template <> struct CXXTypeTraits +{ + static constexpr GDALDataType gdal_type = GDT_Int64; + static constexpr size_t size = sizeof(int64_t); + static constexpr OGRFieldType ogr_type = OFTInteger64; + static constexpr OGRFieldSubType ogr_subtype = OFSTNone; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::Create(GDT_Int64); + } +}; + +template <> struct CXXTypeTraits +{ + static constexpr GDALDataType gdal_type = GDT_UInt64; + static constexpr size_t size = sizeof(uint64_t); + // Mapping to Real is questionable... + static constexpr OGRFieldType ogr_type = OFTReal; + static constexpr OGRFieldSubType ogr_subtype = OFSTNone; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::Create(GDT_UInt64); + } +}; + +template <> struct CXXTypeTraits +{ + static constexpr GDALDataType gdal_type = GDT_Float32; + static constexpr size_t size = sizeof(float); + static constexpr OGRFieldType ogr_type = OFTReal; + static constexpr OGRFieldSubType ogr_subtype = OFSTFloat32; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::Create(GDT_Float32); + } +}; + +template <> struct CXXTypeTraits +{ + static constexpr GDALDataType gdal_type = GDT_Float64; + static constexpr size_t size = sizeof(double); + static constexpr OGRFieldType ogr_type = OFTReal; + static constexpr OGRFieldSubType ogr_subtype = OFSTNone; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::Create(GDT_Float64); + } +}; + +template <> struct CXXTypeTraits> +{ + static constexpr GDALDataType gdal_type = GDT_CFloat32; + static constexpr size_t size = sizeof(float) * 2; + static constexpr OGRFieldType ogr_type = OFTMaxType; + static constexpr OGRFieldSubType ogr_subtype = OFSTNone; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::Create(GDT_CFloat32); + } +}; + +template <> struct CXXTypeTraits> +{ + static constexpr GDALDataType gdal_type = GDT_CFloat64; + static constexpr size_t size = sizeof(double) * 2; + static constexpr OGRFieldType ogr_type = OFTMaxType; + static constexpr OGRFieldSubType ogr_subtype = OFSTNone; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::Create(GDT_CFloat64); + } +}; + +#if defined(GDAL_ENABLE_FLOAT16) && defined(FLT16_MAX) && defined(FLT16_MIN) +template <> struct CXXTypeTraits<_Float16> +{ + static constexpr GDALDataType gdal_type = GDT_Float16; + static constexpr size_t size = sizeof(_Float16); + static constexpr OGRFieldType ogr_type = OFTReal; + static constexpr OGRFieldSubType ogr_subtype = OFSTNone; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::Create(GDT_Float16); + } +}; +#endif + +template <> struct CXXTypeTraits +{ + static constexpr GDALDataType gdal_type = GDT_Unknown; + static constexpr size_t size = 0; + static constexpr OGRFieldType ogr_type = OFTString; + static constexpr OGRFieldSubType ogr_subtype = OFSTNone; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::CreateString(); + } +}; + +//! @endcond + +/** Trait accepting a GDALDataType and mapping it to corresponding C++ type and + * OGRFieldType + * + * Each specialization has the following members: + * typedef T type; (except for GDT_CInt16 and GDT_CInt32) + * static constexpr size_t size; + * static constexpr OGRFieldType ogr_type; + * static constexpr OGRFieldSubType ogr_subtype; + * static inline GDALExtendedDataType GetExtendedDataType(); + * + * @since 3.11 + */ +template struct GDALDataTypeTraits +{ +}; + +//! @cond Doxygen_Suppress +template <> struct GDALDataTypeTraits +{ + typedef int8_t type; + static constexpr size_t size = sizeof(int8_t); + static constexpr OGRFieldType ogr_type = OFTInteger; + static constexpr OGRFieldSubType ogr_subtype = OFSTNone; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::Create(GDT_Int8); + } +}; + +template <> struct GDALDataTypeTraits +{ + typedef uint8_t type; + static constexpr size_t size = sizeof(uint8_t); + static constexpr OGRFieldType ogr_type = OFTInteger; + static constexpr OGRFieldSubType ogr_subtype = OFSTNone; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::Create(GDT_Byte); + } +}; + +template <> struct GDALDataTypeTraits +{ + typedef int16_t type; + static constexpr size_t size = sizeof(int16_t); + static constexpr OGRFieldType ogr_type = OFTInteger; + static constexpr OGRFieldSubType ogr_subtype = OFSTInt16; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::Create(GDT_Int16); + } +}; + +template <> struct GDALDataTypeTraits +{ + typedef uint16_t type; + static constexpr size_t size = sizeof(uint16_t); + static constexpr OGRFieldType ogr_type = OFTInteger; + static constexpr OGRFieldSubType ogr_subtype = OFSTNone; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::Create(GDT_UInt16); + } +}; + +template <> struct GDALDataTypeTraits +{ + typedef int32_t type; + static constexpr size_t size = sizeof(int32_t); + static constexpr OGRFieldType ogr_type = OFTInteger; + static constexpr OGRFieldSubType ogr_subtype = OFSTNone; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::Create(GDT_Int32); + } +}; + +template <> struct GDALDataTypeTraits +{ + typedef uint32_t type; + static constexpr size_t size = sizeof(uint32_t); + static constexpr OGRFieldType ogr_type = OFTInteger64; + static constexpr OGRFieldSubType ogr_subtype = OFSTNone; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::Create(GDT_UInt32); + } +}; + +template <> struct GDALDataTypeTraits +{ + typedef int64_t type; + static constexpr size_t size = sizeof(int64_t); + static constexpr OGRFieldType ogr_type = OFTInteger64; + static constexpr OGRFieldSubType ogr_subtype = OFSTNone; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::Create(GDT_Int64); + } +}; + +template <> struct GDALDataTypeTraits +{ + typedef uint64_t type; + static constexpr size_t size = sizeof(uint64_t); + // Mapping to Real is questionable... + static constexpr OGRFieldType ogr_type = OFTReal; + static constexpr OGRFieldSubType ogr_subtype = OFSTNone; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::Create(GDT_UInt64); + } +}; + +template <> struct GDALDataTypeTraits +{ + typedef float type; + static constexpr size_t size = sizeof(float); + static constexpr OGRFieldType ogr_type = OFTReal; + static constexpr OGRFieldSubType ogr_subtype = OFSTFloat32; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::Create(GDT_Float32); + } +}; + +template <> struct GDALDataTypeTraits +{ + typedef double type; + static constexpr size_t size = sizeof(double); + static constexpr OGRFieldType ogr_type = OFTReal; + static constexpr OGRFieldSubType ogr_subtype = OFSTNone; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::Create(GDT_Float64); + } +}; + +template <> struct GDALDataTypeTraits +{ + // typedef type not available ! + static constexpr size_t size = sizeof(int16_t) * 2; + static constexpr OGRFieldType ogr_type = OFTMaxType; + static constexpr OGRFieldSubType ogr_subtype = OFSTNone; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::Create(GDT_CInt16); + } +}; + +template <> struct GDALDataTypeTraits +{ + // typedef type not available ! + static constexpr size_t size = sizeof(int32_t) * 2; + static constexpr OGRFieldType ogr_type = OFTMaxType; + static constexpr OGRFieldSubType ogr_subtype = OFSTNone; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::Create(GDT_CInt32); + } +}; + +template <> struct GDALDataTypeTraits +{ + typedef std::complex type; + static constexpr size_t size = sizeof(float) * 2; + static constexpr OGRFieldType ogr_type = OFTMaxType; + static constexpr OGRFieldSubType ogr_subtype = OFSTNone; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::Create(GDT_CFloat32); + } +}; + +template <> struct GDALDataTypeTraits +{ + typedef std::complex type; + static constexpr size_t size = sizeof(double) * 2; + static constexpr OGRFieldType ogr_type = OFTMaxType; + static constexpr OGRFieldSubType ogr_subtype = OFSTNone; + + static inline GDALExtendedDataType GetExtendedDataType() + { + return GDALExtendedDataType::Create(GDT_CFloat64); + } +}; + +//! @endcond + +/** Map a GDALDataType to the most suitable OGRFieldType. + * + * Note that GDT_UInt32 is mapped to OFTInteger64 to avoid data losses. + * GDT_UInt64 is mapped to OFTReal, which can be lossy. If values are + * guaranteed to be in [0, INT64_MAX] range, callers might want to use + * OFTInteger64 instead. + * There is no mapping for complex data types. + * + * @since 3.11 + */ +inline OGRFieldType GetOGRFieldType(const GDALDataType gdal_type) +{ + switch (gdal_type) + { + case GDT_Byte: + case GDT_Int8: + case GDT_Int16: + case GDT_Int32: + case GDT_UInt16: + return OFTInteger; + case GDT_UInt32: + case GDT_Int64: + return OFTInteger64; + case GDT_UInt64: // Questionable + case GDT_Float32: + case GDT_Float64: + return OFTReal; + case GDT_CInt16: + case GDT_CInt32: + case GDT_CFloat32: + case GDT_CFloat64: + case GDT_Unknown: + case GDT_TypeCount: + break; + } + return OFTMaxType; +} + +/** Map a GDALExtendedDataType to the most suitable OGRFieldType. + * + * Note that GDT_UInt32 is mapped to OFTInteger64 to avoid data losses. + * GDT_UInt64 is mapped to OFTReal, which can be lossy. If values are + * guaranteed to be in [0, INT64_MAX] range, callers might want to use + * OFTInteger64 instead. + * + * @since 3.11 + */ +inline OGRFieldType GetOGRFieldType(const GDALExtendedDataType &oEDT) +{ + if (oEDT.GetClass() == GEDTC_NUMERIC) + return GetOGRFieldType(oEDT.GetNumericDataType()); + else if (oEDT.GetClass() == GEDTC_STRING) + return OFTString; + return OFTMaxType; +} + +} // namespace gdal + +#endif // GDAL_TYPETRAITS_H_INCLUDED