From 66e3fbd8793a434feb19718553f303a43a1a7a86 Mon Sep 17 00:00:00 2001 From: Daniel Baston Date: Tue, 15 Oct 2024 14:27:29 -0400 Subject: [PATCH] gdal_typetraits: remove some boilerplate --- autotest/cpp/test_gdal_typetraits.cpp | 6 + gcore/gdal_typetraits.h | 463 ++++++++++---------------- 2 files changed, 190 insertions(+), 279 deletions(-) diff --git a/autotest/cpp/test_gdal_typetraits.cpp b/autotest/cpp/test_gdal_typetraits.cpp index 90bc1e24566b..8efd2363ee59 100644 --- a/autotest/cpp/test_gdal_typetraits.cpp +++ b/autotest/cpp/test_gdal_typetraits.cpp @@ -21,26 +21,32 @@ TEST_F(test_gdal_typetraits, CXXTypeTraits) 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::ogr_type == OFTInteger); + static_assert(gdal::CXXTypeTraits::gdal_type == GDT_UInt32); static_assert(gdal::CXXTypeTraits::size == 4); EXPECT_EQ(gdal::CXXTypeTraits::GetExtendedDataType() diff --git a/gcore/gdal_typetraits.h b/gcore/gdal_typetraits.h index f7e341f49e7c..affd5bf399e2 100644 --- a/gcore/gdal_typetraits.h +++ b/gcore/gdal_typetraits.h @@ -43,6 +43,89 @@ namespace gdal { +/** 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 + */ +constexpr 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 GDALDataType to the most suitable OGRFieldSubType. + * + * @since 3.11 + */ +constexpr inline OGRFieldSubType +GetOGRFieldSubType(const GDALDataType gdal_type) +{ + switch (gdal_type) + { + case GDT_Byte: + break; + case GDT_Int8: + break; + case GDT_Int16: + return OFSTInt16; + case GDT_Int32: + break; + case GDT_UInt16: + break; + case GDT_UInt32: + break; + case GDT_Int64: + break; + case GDT_UInt64: + break; + case GDT_Float32: + return OFSTFloat32; + case GDT_Float64: + break; + case GDT_CInt16: + break; + case GDT_CInt32: + break; + case GDT_CFloat32: + break; + case GDT_CFloat64: + break; + case GDT_Unknown: + break; + case GDT_TypeCount: + break; + } + return OFSTNone; +} + /** 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. @@ -59,185 +142,112 @@ template struct CXXTypeTraits { }; -//! @cond Doxygen_Suppress -template <> struct CXXTypeTraits +namespace detail { - 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; +template struct CXXTypeTraitsBase +{ + static constexpr GDALDataType gdal_type = GDT_Unknown; + static constexpr size_t size = sizeof(T); + static constexpr OGRFieldType ogr_type = + GetOGRFieldType(CXXTypeTraits::gdal_type); + static constexpr OGRFieldSubType ogr_subtype = + GetOGRFieldSubType(CXXTypeTraits::gdal_type); static inline GDALExtendedDataType GetExtendedDataType() { - return GDALExtendedDataType::Create(GDT_Int8); + return GDALExtendedDataType::Create(CXXTypeTraits::gdal_type); } }; +} // namespace detail -template <> struct CXXTypeTraits +//! @cond Doxygen_Suppress +template <> +struct CXXTypeTraits : public detail::CXXTypeTraitsBase { - 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 constexpr GDALDataType gdal_type = GDT_Int8; +}; - static inline GDALExtendedDataType GetExtendedDataType() - { - return GDALExtendedDataType::Create(GDT_Byte); - } +template <> +struct CXXTypeTraits : public detail::CXXTypeTraitsBase +{ + static constexpr GDALDataType gdal_type = GDT_Byte; }; -template <> struct CXXTypeTraits +template <> +struct CXXTypeTraits : public detail::CXXTypeTraitsBase { 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 +template <> +struct CXXTypeTraits : public detail::CXXTypeTraitsBase { 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 +template <> +struct CXXTypeTraits : public detail::CXXTypeTraitsBase { 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 +template <> +struct CXXTypeTraits : public detail::CXXTypeTraitsBase { 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 +template <> +struct CXXTypeTraits : public detail::CXXTypeTraitsBase { 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 +template <> +struct CXXTypeTraits : public detail::CXXTypeTraitsBase { 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 +template <> +struct CXXTypeTraits : public detail::CXXTypeTraitsBase { 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 +template <> +struct CXXTypeTraits : public detail::CXXTypeTraitsBase { 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> +template <> +struct CXXTypeTraits> + : public detail::CXXTypeTraitsBase> { 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> +template <> +struct CXXTypeTraits> + : public detail::CXXTypeTraitsBase> { 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 +template <> +struct CXXTypeTraits + : public detail::CXXTypeTraitsBase { - 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() { @@ -263,230 +273,125 @@ template struct GDALDataTypeTraits { }; -//! @cond Doxygen_Suppress -template <> struct GDALDataTypeTraits +namespace detail { - typedef int8_t type; - static constexpr size_t size = sizeof(int8_t); - static constexpr OGRFieldType ogr_type = OFTInteger; - static constexpr OGRFieldSubType ogr_subtype = OFSTNone; +template struct GDALDataTypeTraitsBase +{ + + static constexpr size_t size = sizeof(typename GDALDataTypeTraits::type); + static constexpr OGRFieldType ogr_type = GetOGRFieldType(T); + static constexpr OGRFieldSubType ogr_subtype = GetOGRFieldSubType(T); static inline GDALExtendedDataType GetExtendedDataType() { - return GDALExtendedDataType::Create(GDT_Int8); + return GDALExtendedDataType::Create(T); } }; +} // namespace detail -template <> struct GDALDataTypeTraits +//! @cond Doxygen_Suppress +template <> +struct GDALDataTypeTraits + : public detail::GDALDataTypeTraitsBase { - typedef uint8_t type; - static constexpr size_t size = sizeof(uint8_t); - static constexpr OGRFieldType ogr_type = OFTInteger; - static constexpr OGRFieldSubType ogr_subtype = OFSTNone; + typedef int8_t type; +}; - static inline GDALExtendedDataType GetExtendedDataType() - { - return GDALExtendedDataType::Create(GDT_Byte); - } +template <> +struct GDALDataTypeTraits + : public detail::GDALDataTypeTraitsBase +{ + typedef uint8_t type; }; -template <> struct GDALDataTypeTraits +template <> +struct GDALDataTypeTraits + : public detail::GDALDataTypeTraitsBase { 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 +template <> +struct GDALDataTypeTraits + : public detail::GDALDataTypeTraitsBase { 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 +template <> +struct GDALDataTypeTraits + : public detail::GDALDataTypeTraitsBase { 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 +template <> +struct GDALDataTypeTraits + : public detail::GDALDataTypeTraitsBase { 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 +template <> +struct GDALDataTypeTraits + : public detail::GDALDataTypeTraitsBase { 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 +template <> +struct GDALDataTypeTraits + : public detail::GDALDataTypeTraitsBase { 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 +template <> +struct GDALDataTypeTraits + : public detail::GDALDataTypeTraitsBase { 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 +template <> +struct GDALDataTypeTraits + : public detail::GDALDataTypeTraitsBase { 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 +template <> +struct GDALDataTypeTraits + : public detail::GDALDataTypeTraitsBase { // 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 +template <> +struct GDALDataTypeTraits + : public detail::GDALDataTypeTraitsBase { // 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 +template <> +struct GDALDataTypeTraits + : public detail::GDALDataTypeTraitsBase { 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 +template <> +struct GDALDataTypeTraits + : public detail::GDALDataTypeTraitsBase { 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.