From a53f425e38580b8f0bdfbeb8cc58d9a08b236a41 Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Tue, 20 May 2014 22:27:20 -0700 Subject: [PATCH 1/3] Fixes for plFormat on GCC/Clang: - int64_t is a typedef of long on Linux/x86_64 -- don't redefine its specialization - Properly forward-declare the unspecialized variadic template form of _IFormat --- Sources/Plasma/CoreLib/CMakeLists.txt | 17 +++++++++++++---- Sources/Plasma/CoreLib/plFormat.cpp | 4 +++- Sources/Plasma/CoreLib/plFormat.h | 14 ++++++++------ 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/Sources/Plasma/CoreLib/CMakeLists.txt b/Sources/Plasma/CoreLib/CMakeLists.txt index be0bf861..72b41932 100644 --- a/Sources/Plasma/CoreLib/CMakeLists.txt +++ b/Sources/Plasma/CoreLib/CMakeLists.txt @@ -8,17 +8,26 @@ add_definitions(-DPRODUCT_SHORT_NAME="${PRODUCT_SHORT_NAME}") add_definitions(-DPRODUCT_LONG_NAME="${PRODUCT_LONG_NAME}") add_definitions(-DPRODUCT_UUID="${PRODUCT_UUID}") -if(NOT WCHAR_BYTES) - include(CheckTypeSize) +include(CheckTypeSize) +if(NOT WCHAR_BYTES) check_type_size("wchar_t" WCHAR_BYTES) if(NOT WCHAR_BYTES) message(FATAL_ERROR "Could not determine sizeof(wchar_t)") set(WCHAR_BYTES 0) - endif(NOT WCHAR_BYTES) -endif(NOT WCHAR_BYTES) + endif() +endif() add_definitions(-DWCHAR_BYTES=${WCHAR_BYTES}) +if(NOT SIZEOF_LONG) + check_type_size("long" SIZEOF_LONG) + if(NOT SIZEOF_LONG) + message(FATAL_ERROR "Could not determine sizeof(long)") + set(SIZEOF_LONG 0) + endif() +endif() +add_definitions(-DSIZEOF_LONG=${SIZEOF_LONG}) + try_compile(HAVE_CPUID ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR}/cmake/check_cpuid.cpp OUTPUT_VARIABLE OUTPUT) diff --git a/Sources/Plasma/CoreLib/plFormat.cpp b/Sources/Plasma/CoreLib/plFormat.cpp index eee0fd88..01ce94df 100644 --- a/Sources/Plasma/CoreLib/plFormat.cpp +++ b/Sources/Plasma/CoreLib/plFormat.cpp @@ -338,7 +338,7 @@ static plStringBuffer _formatChar(const plFormat_Private::FormatSpec &form #define _PL_FORMAT_IMPL_INT_TYPE(_stype, _utype) \ PL_FORMAT_IMPL(_stype) \ { \ - /* Note: The use of unsigned here is not a typo -- we only format decimal + /* Note: The use of unsigned here is not a typo -- we only format decimal \ values with a sign, so we can convert everything else to unsigned. */ \ switch (format.fDigitClass) { \ case plFormat_Private::kDigitBin: \ @@ -388,7 +388,9 @@ _PL_FORMAT_IMPL_INT_TYPE(signed char, unsigned char) _PL_FORMAT_IMPL_INT_TYPE(short, unsigned short) _PL_FORMAT_IMPL_INT_TYPE(int, unsigned) _PL_FORMAT_IMPL_INT_TYPE(long, unsigned long) +#if (SIZEOF_LONG == 4) _PL_FORMAT_IMPL_INT_TYPE(int64_t, uint64_t) +#endif PL_FORMAT_IMPL(char) { diff --git a/Sources/Plasma/CoreLib/plFormat.h b/Sources/Plasma/CoreLib/plFormat.h index 432ff7b7..bd88429b 100644 --- a/Sources/Plasma/CoreLib/plFormat.h +++ b/Sources/Plasma/CoreLib/plFormat.h @@ -132,6 +132,12 @@ namespace plFormat_Private }; extern FormatSpec _FetchNextFormat(_IFormatDataObject &data); + + template + plString _IFormat(_IFormatDataObject &data, _type, _Args...); + + // End of the chain -- emits the last piece (if any) and builds the final string + plString _IFormat(_IFormatDataObject &data); } /** Declare a formattable type for `plFormat`. @@ -201,8 +207,10 @@ PL_FORMAT_TYPE(int) PL_FORMAT_TYPE(unsigned) PL_FORMAT_TYPE(long) PL_FORMAT_TYPE(unsigned long) +#if (SIZEOF_LONG == 4) PL_FORMAT_TYPE(int64_t) PL_FORMAT_TYPE(uint64_t) +#endif PL_FORMAT_TYPE(const char *) PL_FORMAT_TYPE(const wchar_t *) PL_FORMAT_TYPE(const plString &) @@ -218,10 +226,4 @@ PL_FORMAT_TYPE(const std::wstring &) // To use other formats, don't pass us a bool directly... PL_FORMAT_TYPE(bool) -namespace plFormat_Private -{ - // End of the chain -- emits the last piece (if any) and builds the final string - plString _IFormat(_IFormatDataObject &data); -} - #endif // plFormat_Defined From 7d76cae10f56d76e1c4856c2069a669a9e085ac8 Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Tue, 20 May 2014 23:06:09 -0700 Subject: [PATCH 2/3] Make life simpler. Make life less stupid. Make life work. --- Sources/Plasma/CoreLib/plFormat.h | 40 ++++++++++++++----------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/Sources/Plasma/CoreLib/plFormat.h b/Sources/Plasma/CoreLib/plFormat.h index bd88429b..2c969a24 100644 --- a/Sources/Plasma/CoreLib/plFormat.h +++ b/Sources/Plasma/CoreLib/plFormat.h @@ -133,38 +133,34 @@ namespace plFormat_Private extern FormatSpec _FetchNextFormat(_IFormatDataObject &data); - template - plString _IFormat(_IFormatDataObject &data, _type, _Args...); + template + plString _IFormat(_IFormatDataObject &data, _Type value, _Args... args) + { + plFormat_Private::FormatSpec format = plFormat_Private::_FetchNextFormat(data); + data.fOutput.push_back(_impl_plFormat_DataHandler(format, value)); + return _IFormat(data, args...); + } // End of the chain -- emits the last piece (if any) and builds the final string plString _IFormat(_IFormatDataObject &data); } +template +plString plFormat(const char *fmt_str, _Type value, _Args... args) +{ + plFormat_Private::_IFormatDataObject data; + data.fFormatStr = fmt_str; + plFormat_Private::FormatSpec format = plFormat_Private::_FetchNextFormat(data); + data.fOutput.push_back(_impl_plFormat_DataHandler(format, value)); + return plFormat_Private::_IFormat(data, args...); +} + /** Declare a formattable type for `plFormat`. * \sa PL_FORMAT_IMPL() */ #define PL_FORMAT_TYPE(_type) \ extern plStringBuffer _impl_plFormat_DataHandler( \ - const plFormat_Private::FormatSpec &format, _type value); \ - namespace plFormat_Private \ - { \ - template \ - plString _IFormat(_IFormatDataObject &data, _type value, _Args... args) \ - { \ - plFormat_Private::FormatSpec format = plFormat_Private::_FetchNextFormat(data); \ - data.fOutput.push_back(_impl_plFormat_DataHandler(format, value)); \ - return _IFormat(data, args...); \ - } \ - } \ - template \ - plString plFormat(const char *fmt_str, _type value, _Args... args) \ - { \ - plFormat_Private::_IFormatDataObject data; \ - data.fFormatStr = fmt_str; \ - plFormat_Private::FormatSpec format = plFormat_Private::_FetchNextFormat(data); \ - data.fOutput.push_back(_impl_plFormat_DataHandler(format, value)); \ - return plFormat_Private::_IFormat(data, args...); \ - } + const plFormat_Private::FormatSpec &format, _type value); /** Provide the implementation for a formattable type for `plFormat`. * \sa PL_FORMAT_TYPE(), PL_FORMAT_FORWARD() From d8c376914394e86355e9b24b4bf7e2a3a7372672 Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Wed, 21 May 2014 21:09:56 -0700 Subject: [PATCH 3/3] Fix it for standards-complient compilers (GCC/Clang). Unfortunately, this means that all formatters must be declared in the same place now, as they must be declared BEFORE the template which uses them is declared (not just before it was instantiated, which MSVC allows). --- Sources/Plasma/CoreLib/plFileSystem.h | 4 - Sources/Plasma/CoreLib/plFormat.h | 116 +++++++++++------- .../Plasma/NucleusLib/pnKeyedObject/plUoid.h | 4 - Sources/Plasma/NucleusLib/pnUUID/pnUUID.h | 2 - 4 files changed, 72 insertions(+), 54 deletions(-) diff --git a/Sources/Plasma/CoreLib/plFileSystem.h b/Sources/Plasma/CoreLib/plFileSystem.h index 8fe89b4f..4237f11c 100644 --- a/Sources/Plasma/CoreLib/plFileSystem.h +++ b/Sources/Plasma/CoreLib/plFileSystem.h @@ -227,10 +227,6 @@ inline plFileName operator+(const char *left, const plFileName &right) { return left + right.AsString(); } -// Shortcut for use in plFormat -PL_FORMAT_TYPE(const plFileName &) - - /** Structure to get information about a file by name. * \sa plFileName */ diff --git a/Sources/Plasma/CoreLib/plFormat.h b/Sources/Plasma/CoreLib/plFormat.h index 2c969a24..f2940799 100644 --- a/Sources/Plasma/CoreLib/plFormat.h +++ b/Sources/Plasma/CoreLib/plFormat.h @@ -132,30 +132,11 @@ namespace plFormat_Private }; extern FormatSpec _FetchNextFormat(_IFormatDataObject &data); - - template - plString _IFormat(_IFormatDataObject &data, _Type value, _Args... args) - { - plFormat_Private::FormatSpec format = plFormat_Private::_FetchNextFormat(data); - data.fOutput.push_back(_impl_plFormat_DataHandler(format, value)); - return _IFormat(data, args...); - } - - // End of the chain -- emits the last piece (if any) and builds the final string - plString _IFormat(_IFormatDataObject &data); -} - -template -plString plFormat(const char *fmt_str, _Type value, _Args... args) -{ - plFormat_Private::_IFormatDataObject data; - data.fFormatStr = fmt_str; - plFormat_Private::FormatSpec format = plFormat_Private::_FetchNextFormat(data); - data.fOutput.push_back(_impl_plFormat_DataHandler(format, value)); - return plFormat_Private::_IFormat(data, args...); } /** Declare a formattable type for `plFormat`. + * \note PL_FORMAT_IMPL must only be used in plFormat.h, due to constraints + * on compile-time declaration order imposed by some compilers. * \sa PL_FORMAT_IMPL() */ #define PL_FORMAT_TYPE(_type) \ @@ -193,33 +174,80 @@ plString plFormat(const char *fmt_str, _Type value, _Args... args) #define PL_FORMAT_FORWARD(format, fwd_value) \ _impl_plFormat_DataHandler((format), (fwd_value)) -PL_FORMAT_TYPE(char) -PL_FORMAT_TYPE(wchar_t) -PL_FORMAT_TYPE(signed char) -PL_FORMAT_TYPE(unsigned char) -PL_FORMAT_TYPE(short) -PL_FORMAT_TYPE(unsigned short) -PL_FORMAT_TYPE(int) -PL_FORMAT_TYPE(unsigned) -PL_FORMAT_TYPE(long) -PL_FORMAT_TYPE(unsigned long) +// ==================================== +// BEGIN: Formattable type declarations +// ==================================== + + PL_FORMAT_TYPE(char) + PL_FORMAT_TYPE(wchar_t) + PL_FORMAT_TYPE(signed char) + PL_FORMAT_TYPE(unsigned char) + PL_FORMAT_TYPE(short) + PL_FORMAT_TYPE(unsigned short) + PL_FORMAT_TYPE(int) + PL_FORMAT_TYPE(unsigned) + PL_FORMAT_TYPE(long) + PL_FORMAT_TYPE(unsigned long) #if (SIZEOF_LONG == 4) -PL_FORMAT_TYPE(int64_t) -PL_FORMAT_TYPE(uint64_t) + PL_FORMAT_TYPE(int64_t) + PL_FORMAT_TYPE(uint64_t) #endif -PL_FORMAT_TYPE(const char *) -PL_FORMAT_TYPE(const wchar_t *) -PL_FORMAT_TYPE(const plString &) + PL_FORMAT_TYPE(const char *) + PL_FORMAT_TYPE(const wchar_t *) + PL_FORMAT_TYPE(const plString &) + + // Shortcut for plFileName + PL_FORMAT_TYPE(const class plFileName &) + + // TODO: Remove these when they're no longer needed + PL_FORMAT_TYPE(const std::string &) + PL_FORMAT_TYPE(const std::wstring &) + + // TODO: Implement floating point types (float, double). They're harder + // than the others, so I'll get around to them later >.> + + // Formats as "true" or "false", following normal string formatting rules. + // To use other formats, don't pass us a bool directly... + PL_FORMAT_TYPE(bool) -// TODO: Remove these when they're no longer needed -PL_FORMAT_TYPE(const std::string &) -PL_FORMAT_TYPE(const std::wstring &) + // Formats for plUoid + PL_FORMAT_TYPE(const class plLocation &) + PL_FORMAT_TYPE(const class plUoid &) -// TODO: Implement floating point types (float, double). They're harder -// than the others, so I'll get around to them later >.> + // Format for plUUID + PL_FORMAT_TYPE(const class plUUID &) -// Formats as "true" or "false", following normal string formatting rules. -// To use other formats, don't pass us a bool directly... -PL_FORMAT_TYPE(bool) +// ================================== +// END: Formattable type declarations +// ================================== + +// NOTE: Added in order to work properly in GCC/Clang; all PL_FORMAT_TYPE +// declarations MUST be above this line. +#undef PL_FORMAT_TYPE + +namespace plFormat_Private +{ + // End of the chain -- emits the last piece (if any) and builds the final string + plString _IFormat(_IFormatDataObject &data); + + // Internal plFormat implementation which carries over the pieces formatted so far + template + plString _IFormat(_IFormatDataObject &data, _Type value, _Args... args) + { + plFormat_Private::FormatSpec format = plFormat_Private::_FetchNextFormat(data); + data.fOutput.push_back(_impl_plFormat_DataHandler(format, value)); + return _IFormat(data, args...); + } +} + +template +plString plFormat(const char *fmt_str, _Type value, _Args... args) +{ + plFormat_Private::_IFormatDataObject data; + data.fFormatStr = fmt_str; + plFormat_Private::FormatSpec format = plFormat_Private::_FetchNextFormat(data); + data.fOutput.push_back(_impl_plFormat_DataHandler(format, value)); + return plFormat_Private::_IFormat(data, args...); +} #endif // plFormat_Defined diff --git a/Sources/Plasma/NucleusLib/pnKeyedObject/plUoid.h b/Sources/Plasma/NucleusLib/pnKeyedObject/plUoid.h index 0c1d7255..a8e7fbe7 100644 --- a/Sources/Plasma/NucleusLib/pnKeyedObject/plUoid.h +++ b/Sources/Plasma/NucleusLib/pnKeyedObject/plUoid.h @@ -144,8 +144,6 @@ public: static const plLocation kInvalidLoc; }; -PL_FORMAT_TYPE(const plLocation &) - //// plUoid ////////////////////////////////////////////////////////////////// class plUoid @@ -200,6 +198,4 @@ protected: plLoadMask fLoadMask; }; -PL_FORMAT_TYPE(const plUoid &) - #endif // plUoid_h_inc diff --git a/Sources/Plasma/NucleusLib/pnUUID/pnUUID.h b/Sources/Plasma/NucleusLib/pnUUID/pnUUID.h index d7dce497..e24b50b1 100644 --- a/Sources/Plasma/NucleusLib/pnUUID/pnUUID.h +++ b/Sources/Plasma/NucleusLib/pnUUID/pnUUID.h @@ -96,6 +96,4 @@ public: static plUUID Generate(); }; -PL_FORMAT_TYPE(const plUUID &) - #endif // pnUUID_h_inc