diff --git a/Source/EbsdLib/Core/EbsdLibConstants.h b/Source/EbsdLib/Core/EbsdLibConstants.h index 76ceb1e..94f3aa6 100644 --- a/Source/EbsdLib/Core/EbsdLibConstants.h +++ b/Source/EbsdLib/Core/EbsdLibConstants.h @@ -38,6 +38,9 @@ #include #include +#include "EbsdLib/Core/StringLiteral.hpp" + + /** * @file EbsdConstants.h * @brief This file contains many constants that are generic to the EBSD library @@ -47,7 +50,7 @@ namespace EbsdLib using Rgb = uint32_t; inline constexpr Rgb RGB_MASK = 0x00ffffff; // masks RGB values -inline const std::string PathSep("|"); +inline constexpr StringLiteral PathSep = "|"; inline constexpr uint8_t Unchecked = 0; inline constexpr uint8_t PartiallyChecked = 1; inline constexpr uint8_t Checked = 2; @@ -64,28 +67,28 @@ enum InfoStringFormat namespace StringConstants { -inline const std::string Statistics("Statistics"); -inline const std::string StatsData("StatsData"); -inline const std::string StatsType("StatsType"); -inline const std::string GBCD("GBCD"); +inline constexpr StringLiteral Statistics = "Statistics"; +inline constexpr StringLiteral StatsData = "StatsData"; +inline constexpr StringLiteral StatsType = "StatsType"; +inline constexpr StringLiteral GBCD = "GBCD"; } // namespace StringConstants namespace NumericTypes { namespace Names { -inline const std::string Int8("signed int 8 bit"); -inline const std::string UInt8("unsigned int 8 bit"); -inline const std::string Int16("signed int 16 bit"); -inline const std::string UInt16("unsigned int 16 bit"); -inline const std::string Int32("signed int 32 bit"); -inline const std::string UInt32("unsigned int 32 bit"); -inline const std::string Int64("signed int 64 bit"); -inline const std::string UInt64("unsigned int 64 bit"); -inline const std::string Float("Float 32 bit"); -inline const std::string Double("Double 64 bit"); -inline const std::string Bool("Bool"); -inline const std::string SizeT("size_t"); +inline constexpr StringLiteral Int8 = "signed int 8 bit"; +inline constexpr StringLiteral UInt8 = "unsigned int 8 bit"; +inline constexpr StringLiteral Int16 = "signed int 16 bit"; +inline constexpr StringLiteral UInt16 = "unsigned int 16 bit"; +inline constexpr StringLiteral Int32 = "signed int 32 bit"; +inline constexpr StringLiteral UInt32 = "unsigned int 32 bit"; +inline constexpr StringLiteral Int64 = "signed int 64 bit"; +inline constexpr StringLiteral UInt64 = "unsigned int 64 bit"; +inline constexpr StringLiteral Float = "Float 32 bit"; +inline constexpr StringLiteral Double = "Double 64 bit"; +inline constexpr StringLiteral Bool = "Bool"; +inline constexpr StringLiteral SizeT = "size_t"; } // namespace Names enum class Type : int32_t @@ -105,9 +108,9 @@ enum class Type : int32_t UnknownNumType }; -inline const std::string SupportedTypeList(NumericTypes::Names::Int8 + ", " + NumericTypes::Names::UInt8 + ", " + NumericTypes::Names::Int16 + ", " + NumericTypes::Names::UInt16 + ", " + - NumericTypes::Names::Int32 + ", " + NumericTypes::Names::UInt32 + ", " + NumericTypes::Names::Int64 + ", " + NumericTypes::Names::UInt64 + ", " + - NumericTypes::Names::Float + ", " + NumericTypes::Names::Double + ", " + NumericTypes::Names::Bool + ", " + NumericTypes::Names::SizeT); +inline std::string SupportedTypeList(NumericTypes::Names::Int8.str() + ", " + NumericTypes::Names::UInt8.str() + ", " + NumericTypes::Names::Int16.str() + ", " + NumericTypes::Names::UInt16.str() + ", " + + NumericTypes::Names::Int32.str() + ", " + NumericTypes::Names::UInt32.str() + ", " + NumericTypes::Names::Int64.str() + ", " + NumericTypes::Names::UInt64.str() + ", " + + NumericTypes::Names::Float.str() + ", " + NumericTypes::Names::Double.str() + ", " + NumericTypes::Names::Bool.str() + ", " + NumericTypes::Names::SizeT.str() ); } // namespace NumericTypes /** @brief RefFrameZDir defined for the Stacking order of images into a 3D Volume */ @@ -120,35 +123,35 @@ inline constexpr uint32_t UnknownRefFrameZDirection = 2; namespace H5Ebsd { -inline const std::string Manufacturer("Manufacturer"); -inline const std::string Header("Header"); -inline const std::string Phases("Phases"); -inline const std::string Phase("Phase"); -inline const std::string Data("Data"); -inline const std::string Index("Index"); - -inline const std::string ZStartIndex("ZStartIndex"); -inline const std::string ZEndIndex("ZEndIndex"); -inline const std::string ZResolution("Z Resolution"); -inline const std::string StackingOrder("Stacking Order"); -inline const std::string SampleTransformationAngle("SampleTransformationAngle"); -inline const std::string SampleTransformationAxis("SampleTransformationAxis"); -inline const std::string EulerTransformationAngle("EulerTransformationAngle"); -inline const std::string EulerTransformationAxis("EulerTransformationAxis"); +inline constexpr StringLiteral Manufacturer = "Manufacturer"; +inline constexpr StringLiteral Header = "Header"; +inline constexpr StringLiteral Phases = "Phases"; +inline constexpr StringLiteral Phase = "Phase"; +inline constexpr StringLiteral Data = "Data"; +inline constexpr StringLiteral Index = "Index"; + +inline constexpr StringLiteral ZStartIndex = "ZStartIndex"; +inline constexpr StringLiteral ZEndIndex = "ZEndIndex"; +inline constexpr StringLiteral ZResolution = "Z Resolution"; +inline constexpr StringLiteral StackingOrder = "Stacking Order"; +inline constexpr StringLiteral SampleTransformationAngle = "SampleTransformationAngle"; +inline constexpr StringLiteral SampleTransformationAxis = "SampleTransformationAxis"; +inline constexpr StringLiteral EulerTransformationAngle = "EulerTransformationAngle"; +inline constexpr StringLiteral EulerTransformationAxis = "EulerTransformationAxis"; // Each Manufacturer has their own naming scheme for these variables but for // DREAM.3D we are going to settle on using these names for consistency -inline const std::string XResolution("X Resolution"); -inline const std::string YResolution("Y Resolution"); +inline constexpr StringLiteral XResolution = "X Resolution"; +inline constexpr StringLiteral YResolution = "Y Resolution"; // We store the Maximum number of X and Y Points for the given volume. This // allows us to store slices that have different XY voxel dimensions. -inline const std::string XPoints("Max X Points"); -inline const std::string YPoints("Max Y Points"); +inline constexpr StringLiteral XPoints = "Max X Points"; +inline constexpr StringLiteral YPoints = "Max Y Points"; -inline const std::string FileVersionStr("FileVersion"); +inline constexpr StringLiteral FileVersionStr = "FileVersion"; inline constexpr uint32_t FileVersion = 5; -inline const std::string EbsdLibVersionStr("EbsdLibVersion"); +inline constexpr StringLiteral EbsdLibVersionStr = "EbsdLibVersion"; } // namespace H5Ebsd using EnumType = int32_t; @@ -167,8 +170,8 @@ enum class OEM : EnumType namespace CellData { -inline const std::string EulerAngles("EulerAngles"); -inline const std::string Phases("Phases"); +inline constexpr StringLiteral EulerAngles = "EulerAngles"; +inline constexpr StringLiteral Phases = "Phases"; } // namespace CellData enum EbsdToSampleCoordinateMapping @@ -181,9 +184,9 @@ enum EbsdToSampleCoordinateMapping namespace StackingOrder { -inline const std::string LowToHigh("Low To High"); -inline const std::string HighToLow("High To Low"); -inline const std::string UnknownStackingOrder("Unknown Stacking Order"); +inline constexpr StringLiteral LowToHigh = "Low To High"; +inline constexpr StringLiteral HighToLow = "High To Low"; +inline constexpr StringLiteral UnknownStackingOrder = "Unknown Stacking Order"; namespace Utils { @@ -241,9 +244,9 @@ inline constexpr uint32_t UnknownCrystalStructure = 999; //!< UnknownCrystalStru namespace BravaisLattice { -inline const std::string Unknown("Unknown"); -inline const std::string Cubic("Cubic"); -inline const std::string Hexagonal("Hexagonal"); +inline constexpr StringLiteral Unknown = "Unknown"; +inline constexpr StringLiteral Cubic = "Cubic"; +inline constexpr StringLiteral Hexagonal = "Hexagonal"; } // namespace BravaisLattice namespace AngleRepresentation @@ -292,3 +295,4 @@ inline constexpr double BP[6] = {0.0, 1.0, 0.5773502691896260, 0.414213562373095 namespace LPs = LambertParametersType; } // namespace EbsdLib + diff --git a/Source/EbsdLib/Core/SourceList.cmake b/Source/EbsdLib/Core/SourceList.cmake index 49c73f9..b06ccda 100644 --- a/Source/EbsdLib/Core/SourceList.cmake +++ b/Source/EbsdLib/Core/SourceList.cmake @@ -12,6 +12,7 @@ set(EbsdLib_${DIR_NAME}_HDRS ${EbsdLibProj_SOURCE_DIR}/Source/EbsdLib/${DIR_NAME}/OrientationRepresentation.h ${EbsdLibProj_SOURCE_DIR}/Source/EbsdLib/${DIR_NAME}/OrientationTransformation.hpp ${EbsdLibProj_SOURCE_DIR}/Source/EbsdLib/${DIR_NAME}/Quaternion.hpp + ${EbsdLibProj_SOURCE_DIR}/Source/EbsdLib/${DIR_NAME}/StringLiteral.hpp ) set(EbsdLib_${DIR_NAME}_SRCS diff --git a/Source/EbsdLib/Core/StringLiteral.hpp b/Source/EbsdLib/Core/StringLiteral.hpp new file mode 100644 index 0000000..a62e92b --- /dev/null +++ b/Source/EbsdLib/Core/StringLiteral.hpp @@ -0,0 +1,250 @@ +#pragma once + + +#include +#include +#include + +// #include +// #include + +namespace EbsdLib +{ +namespace detail +{ +/** + * @brief Returns true if the given character array is null-terminated. + * @tparam T + * @param string + * @return + */ +template +constexpr bool HasNullTerminator(const T (&string)[Size]) noexcept +{ + return string[Size - 1] == static_cast('\0'); +} +} // namespace detail + +/** + * @brief BasicStringLiteral is meant to be a safe container for a string literal allowing for easy access to its size/length. + * This class should always contain a pointer to a static compile time null-terminated string literal. + * Typical usage will be for static string constants. At this time the constructors allow non string literals to be passed in. + * This is undesired behavior, but there is no way to overcome this in C++17 without using character parameter packs which come with their own issues. + * Example: + * @code + * static constexpr StringLiteral k_Foo = "foo"; + * @endcode + * @tparam T Character type + */ +template +class BasicStringLiteral +{ +public: + BasicStringLiteral() = delete; + + /** + * @brief Constructor that accepts a string literal of fixed size. Should be made consteval in C++20. + * Requires string to be null-terminated. + * @param string + * @return + */ + template + constexpr BasicStringLiteral(const T (&string)[Size]) + : m_String(string) + , m_Size(Size) + { + if(!detail::HasNullTerminator(string)) + { + throw std::runtime_error("BasicStringLiteral must be null-terminated"); + } + } + + ~BasicStringLiteral() noexcept = default; + + BasicStringLiteral(const BasicStringLiteral&) noexcept = default; + BasicStringLiteral(BasicStringLiteral&&) noexcept = default; + + BasicStringLiteral& operator=(const BasicStringLiteral&) noexcept = default; + BasicStringLiteral& operator=(BasicStringLiteral&&) noexcept = default; + + /** + * @brief Returns the c-string pointer. + * @return const T* + */ + constexpr const T* c_str() const noexcept + { + return m_String; + } + + /** + * @brief Returns the size of the string literal not including the null terminator. + * @return size_t + */ + constexpr size_t size() const noexcept + { + return m_Size - 1; + } + + /** + * @brief Returns a view of string literal not including the null terminator. + * @return std::basic_string_view + */ + constexpr std::basic_string_view view() const + { + return std::basic_string_view(m_String, size()); + } + + /** + * @brief Returns a view of string literal including the null terminator. + * @return std::basic_string_view + */ + constexpr std::basic_string_view c_view() const + { + return std::basic_string_view(m_String, m_Size); + } + + /** + * @brief Returns a null-terminated heap allocated string. + * @return std::basic_string + */ + std::basic_string str() const + { + return std::basic_string(m_String, size()); + } + + /** + * @brief Implicit conversion to std::basic_string + */ + operator std::basic_string() const + { + return str(); + } + + /** + * @brief Implicit conversion to std::basic_string_view + */ + operator std::basic_string_view() const + { + return view(); + } + +private: + const T* m_String; + size_t m_Size; +}; + +template +bool operator==(const std::basic_string& lhs, BasicStringLiteral rhs) +{ + return lhs == rhs.view(); +} + +template +bool operator==(BasicStringLiteral lhs, const std::basic_string& rhs) +{ + return rhs == lhs; +} + +template +bool operator!=(const std::basic_string& lhs, BasicStringLiteral rhs) +{ + return lhs != rhs.view(); +} + +template +bool operator!=(BasicStringLiteral lhs, const std::basic_string& rhs) +{ + return rhs != lhs; +} + +template +bool operator<(const std::basic_string& lhs, BasicStringLiteral rhs) +{ + return lhs < rhs.view(); +} + +template +bool operator<(BasicStringLiteral lhs, const std::basic_string& rhs) +{ + return lhs.view() < rhs; +} + +template +bool operator>(const std::basic_string& lhs, BasicStringLiteral rhs) +{ + return lhs > rhs.view(); +} + +template +bool operator>(BasicStringLiteral lhs, const std::basic_string& rhs) +{ + return lhs.view() > rhs; +} + +template +bool operator<=(const std::basic_string& lhs, BasicStringLiteral rhs) +{ + return lhs <= rhs.view(); +} + +template +bool operator<=(BasicStringLiteral lhs, const std::basic_string& rhs) +{ + return lhs.view() <= rhs; +} + +template +bool operator>=(const std::basic_string& lhs, BasicStringLiteral rhs) +{ + return lhs >= rhs.view(); +} + +template +bool operator>=(BasicStringLiteral lhs, const std::basic_string& rhs) +{ + return lhs.view() >= rhs; +} + +using StringLiteral = BasicStringLiteral; +using WStringLiteral = BasicStringLiteral; +using String16Literal = BasicStringLiteral; +using String32Literal = BasicStringLiteral; +} // namespace nx::core + +#if 0 +template +struct fmt::formatter> +{ + static constexpr const CharT* GetFormatString() + { + if constexpr(std::is_same_v) + { + return "{}"; + } + if constexpr(std::is_same_v) + { + return L"{}"; + } + if constexpr(std::is_same_v) + { + return u"{}"; + } + if constexpr(std::is_same_v) + { + return U"{}"; + } + } + + constexpr typename basic_format_parse_context::iterator parse(basic_format_parse_context& ctx) + { + return ctx.begin(); + } + + typename buffer_context::iterator format(const nx::core::BasicStringLiteral& p, buffer_context& ctx) const + { + static constexpr const CharT* formatStr = GetFormatString(); + + return fmt::format_to(ctx.out(), formatStr, p.view()); + } +}; +#endif diff --git a/Source/EbsdLib/IO/H5EbsdVolumeInfo.cpp b/Source/EbsdLib/IO/H5EbsdVolumeInfo.cpp index 89ddede..551d554 100644 --- a/Source/EbsdLib/IO/H5EbsdVolumeInfo.cpp +++ b/Source/EbsdLib/IO/H5EbsdVolumeInfo.cpp @@ -48,20 +48,20 @@ #include "EbsdLib/Utilities/EbsdStringUtils.hpp" #define EBSD_VOLREADER_READ_HEADER(fileId, path, var) \ - err = H5Lite::readScalarDataset(fileId, path, var); \ + err = H5Lite::readScalarDataset(fileId, path.c_str(), var); \ if(err < 0) \ { \ - std::cout << "H5EbsdVolumeInfo Error: Could not load header value for " << path; \ + std::cout << "H5EbsdVolumeInfo Error: Could not load header value for " << path.str(); \ err = H5Utilities::closeFile(fileId); \ return err; \ } #define EBSD_VOLREADER_READ_VECTOR3_HEADER(fileId, path, var, type) \ { \ - err = H5Lite::readPointerDataset(fileId, path, var.data()); \ + err = H5Lite::readPointerDataset(fileId, path.c_str(), var.data()); \ if(err < 0) \ { \ - std::cout << "H5EbsdVolumeInfo Error: Could not load header (as vector) for " << path; \ + std::cout << "H5EbsdVolumeInfo Error: Could not load header (as vector) for " << path.str(); \ err = H5Utilities::closeFile(fileId); \ return err; \ } \ @@ -178,7 +178,7 @@ int H5EbsdVolumeInfo::readVolumeInfo() err = H5Lite::readStringDataset(fileId, EbsdLib::H5Ebsd::Manufacturer, data); if(err < 0) { - std::cout << "H5EbsdVolumeInfo Error: Could not load header value for " << EbsdLib::H5Ebsd::Manufacturer << std::endl; + std::cout << "H5EbsdVolumeInfo Error: Could not load header value for " << EbsdLib::H5Ebsd::Manufacturer.str() << std::endl; err = H5Utilities::closeFile(fileId); return err; } diff --git a/Source/EbsdLib/LaueOps/CubicLowOps.cpp b/Source/EbsdLib/LaueOps/CubicLowOps.cpp index 42589de..a128bf8 100644 --- a/Source/EbsdLib/LaueOps/CubicLowOps.cpp +++ b/Source/EbsdLib/LaueOps/CubicLowOps.cpp @@ -50,6 +50,7 @@ #ifdef EbsdLib_USE_PARALLEL_ALGORITHMS #include #include +#include #endif namespace CubicLow diff --git a/Source/EbsdLib/LaueOps/CubicOps.cpp b/Source/EbsdLib/LaueOps/CubicOps.cpp index 0de82ab..a7e36bd 100644 --- a/Source/EbsdLib/LaueOps/CubicOps.cpp +++ b/Source/EbsdLib/LaueOps/CubicOps.cpp @@ -50,6 +50,7 @@ #ifdef EbsdLib_USE_PARALLEL_ALGORITHMS #include #include +#include #endif namespace CubicHigh diff --git a/Source/EbsdLib/LaueOps/HexagonalLowOps.cpp b/Source/EbsdLib/LaueOps/HexagonalLowOps.cpp index a25a961..cb037a6 100644 --- a/Source/EbsdLib/LaueOps/HexagonalLowOps.cpp +++ b/Source/EbsdLib/LaueOps/HexagonalLowOps.cpp @@ -50,6 +50,7 @@ #ifdef EbsdLib_USE_PARALLEL_ALGORITHMS #include #include +#include #endif namespace HexagonalLow diff --git a/Source/EbsdLib/LaueOps/HexagonalOps.cpp b/Source/EbsdLib/LaueOps/HexagonalOps.cpp index 7af4604..90b69db 100644 --- a/Source/EbsdLib/LaueOps/HexagonalOps.cpp +++ b/Source/EbsdLib/LaueOps/HexagonalOps.cpp @@ -52,6 +52,7 @@ #ifdef EbsdLib_USE_PARALLEL_ALGORITHMS #include #include +#include #endif namespace HexagonalHigh diff --git a/Source/EbsdLib/LaueOps/MonoclinicOps.cpp b/Source/EbsdLib/LaueOps/MonoclinicOps.cpp index bdc452d..b1b4a08 100644 --- a/Source/EbsdLib/LaueOps/MonoclinicOps.cpp +++ b/Source/EbsdLib/LaueOps/MonoclinicOps.cpp @@ -49,6 +49,7 @@ #ifdef EbsdLib_USE_PARALLEL_ALGORITHMS #include #include +#include #endif namespace Monoclinic diff --git a/Source/EbsdLib/LaueOps/OrthoRhombicOps.cpp b/Source/EbsdLib/LaueOps/OrthoRhombicOps.cpp index 7d78fad..4973a84 100644 --- a/Source/EbsdLib/LaueOps/OrthoRhombicOps.cpp +++ b/Source/EbsdLib/LaueOps/OrthoRhombicOps.cpp @@ -49,6 +49,7 @@ #ifdef EbsdLib_USE_PARALLEL_ALGORITHMS #include #include +#include #endif #define EBSD_LIB_GENERATE_ENTIRE_CIRCLE diff --git a/Source/EbsdLib/LaueOps/TetragonalLowOps.cpp b/Source/EbsdLib/LaueOps/TetragonalLowOps.cpp index 66ddb8f..c6471c8 100644 --- a/Source/EbsdLib/LaueOps/TetragonalLowOps.cpp +++ b/Source/EbsdLib/LaueOps/TetragonalLowOps.cpp @@ -49,6 +49,7 @@ #ifdef EbsdLib_USE_PARALLEL_ALGORITHMS #include #include +#include #endif namespace TetragonalLow diff --git a/Source/EbsdLib/LaueOps/TetragonalOps.cpp b/Source/EbsdLib/LaueOps/TetragonalOps.cpp index 2c36495..cdae564 100644 --- a/Source/EbsdLib/LaueOps/TetragonalOps.cpp +++ b/Source/EbsdLib/LaueOps/TetragonalOps.cpp @@ -50,6 +50,7 @@ #ifdef EbsdLib_USE_PARALLEL_ALGORITHMS #include #include +#include #endif namespace TetragonalHigh diff --git a/Source/EbsdLib/LaueOps/TrigonalLowOps.cpp b/Source/EbsdLib/LaueOps/TrigonalLowOps.cpp index 1feaa70..1ac0c11 100644 --- a/Source/EbsdLib/LaueOps/TrigonalLowOps.cpp +++ b/Source/EbsdLib/LaueOps/TrigonalLowOps.cpp @@ -49,6 +49,7 @@ #ifdef EbsdLib_USE_PARALLEL_ALGORITHMS #include #include +#include #endif #include diff --git a/Source/EbsdLib/LaueOps/TrigonalOps.cpp b/Source/EbsdLib/LaueOps/TrigonalOps.cpp index 1c71a35..38598fb 100644 --- a/Source/EbsdLib/LaueOps/TrigonalOps.cpp +++ b/Source/EbsdLib/LaueOps/TrigonalOps.cpp @@ -50,6 +50,7 @@ #ifdef EbsdLib_USE_PARALLEL_ALGORITHMS #include #include +#include #endif namespace TrigonalHigh