diff --git a/include/rapidjson/internal/strfunc.h b/include/rapidjson/internal/strfunc.h index de41d8f..226439a 100644 --- a/include/rapidjson/internal/strfunc.h +++ b/include/rapidjson/internal/strfunc.h @@ -16,6 +16,7 @@ #define RAPIDJSON_INTERNAL_STRFUNC_H_ #include "../stream.h" +#include RAPIDJSON_NAMESPACE_BEGIN namespace internal { @@ -34,6 +35,16 @@ inline SizeType StrLen(const Ch* s) { return SizeType(p - s); } +template <> +inline SizeType StrLen(const char* s) { + return SizeType(std::strlen(s)); +} + +template <> +inline SizeType StrLen(const wchar_t* s) { + return SizeType(std::wcslen(s)); +} + //! Returns number of code points in a encoded string. template bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) { diff --git a/include/rapidjson/prettywriter.h b/include/rapidjson/prettywriter.h index b68b687..a9d0f02 100644 --- a/include/rapidjson/prettywriter.h +++ b/include/rapidjson/prettywriter.h @@ -107,7 +107,8 @@ public: return Base::WriteString(str, length); } - bool String(const Ch* str, SizeType length, bool copy = false) { + template + RAPIDJSON_ENABLEIF_RETURN((internal::IsSame), (bool)) String(const T* str, SizeType length, bool copy = false) { RAPIDJSON_ASSERT(str != 0); (void)copy; PrettyPrefix(kStringType); @@ -126,7 +127,8 @@ public: return Base::WriteStartObject(); } - bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } + template + RAPIDJSON_ENABLEIF_RETURN((internal::IsSame), (bool)) Key(const T* str, SizeType length, bool copy = false) { return String(str, length, copy); } #if RAPIDJSON_HAS_STDSTRING bool Key(const std::basic_string& str) { @@ -184,8 +186,22 @@ public: //@{ //! Simpler but slower overload. - bool String(const Ch* str) { return String(str, internal::StrLen(str)); } - bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } + template + RAPIDJSON_ENABLEIF_RETURN((internal::IsSame), (bool)) String(const T* const& str) { return String(str, internal::StrLen(str)); } + template + RAPIDJSON_ENABLEIF_RETURN((internal::IsSame), (bool)) Key(const T* const& str) { return Key(str, internal::StrLen(str)); } + + //! The compiler can give us the length of quoted strings for free. + template + RAPIDJSON_ENABLEIF_RETURN((internal::IsSame), (bool)) String(const T (&str)[N]) { + RAPIDJSON_ASSERT(str[N-1] == '\0'); // you must pass in a null-terminated string (quoted constant strings are always null-terminated) + return String(str, N-1); + } + template + RAPIDJSON_ENABLEIF_RETURN((internal::IsSame), (bool)) Key(const T (&str)[N]) { + RAPIDJSON_ASSERT(str[N-1] == '\0'); // you must pass in a null-terminated string (quoted constant strings are always null-terminated) + return Key(str, N-1); + } //@} diff --git a/include/rapidjson/writer.h b/include/rapidjson/writer.h index 43ec5dc..7a0af39 100644 --- a/include/rapidjson/writer.h +++ b/include/rapidjson/writer.h @@ -16,6 +16,7 @@ #define RAPIDJSON_WRITER_H_ #include "stream.h" +#include "internal/meta.h" #include "internal/stack.h" #include "internal/strfunc.h" #include "internal/dtoa.h" @@ -198,7 +199,8 @@ public: return EndValue(WriteString(str, length)); } - bool String(const Ch* str, SizeType length, bool copy = false) { + template + RAPIDJSON_ENABLEIF_RETURN((internal::IsSame), (bool)) String(const T* str, SizeType length, bool copy = false) { RAPIDJSON_ASSERT(str != 0); (void)copy; Prefix(kStringType); @@ -217,7 +219,8 @@ public: return WriteStartObject(); } - bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } + template + RAPIDJSON_ENABLEIF_RETURN((internal::IsSame), (bool)) Key(const T* str, SizeType length, bool copy = false) { return String(str, length, copy); } bool EndObject(SizeType memberCount = 0) { (void)memberCount; @@ -247,8 +250,22 @@ public: //@{ //! Simpler but slower overload. - bool String(const Ch* str) { return String(str, internal::StrLen(str)); } - bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } + template + RAPIDJSON_ENABLEIF_RETURN((internal::IsSame), (bool)) String(const T* const& str) { return String(str, internal::StrLen(str)); } + template + RAPIDJSON_ENABLEIF_RETURN((internal::IsSame), (bool)) Key(const T* const& str) { return Key(str, internal::StrLen(str)); } + + //! The compiler can give us the length of quoted strings for free. + template + RAPIDJSON_ENABLEIF_RETURN((internal::IsSame), (bool)) String(const T (&str)[N]) { + RAPIDJSON_ASSERT(str[N-1] == '\0'); // you must pass in a null-terminated string (quoted constant strings are always null-terminated) + return String(str, N-1); + } + template + RAPIDJSON_ENABLEIF_RETURN((internal::IsSame), (bool)) Key(const T (&str)[N]) { + RAPIDJSON_ASSERT(str[N-1] == '\0'); // you must pass in a null-terminated string (quoted constant strings are always null-terminated) + return Key(str, N-1); + } //@} diff --git a/test/unittest/CMakeLists.txt b/test/unittest/CMakeLists.txt index 4e29765..fdf0ad0 100644 --- a/test/unittest/CMakeLists.txt +++ b/test/unittest/CMakeLists.txt @@ -79,7 +79,7 @@ add_test(NAME unittest if(NOT MSVC) # Not running SIMD.* unit test cases for Valgrind add_test(NAME valgrind_unittest - COMMAND valgrind --leak-check=full --error-exitcode=1 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittest --gtest_filter=-SIMD.* + COMMAND valgrind --suppressions=${CMAKE_SOURCE_DIR}/test/valgrind.supp --leak-check=full --error-exitcode=1 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittest --gtest_filter=-SIMD.* WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) if(CMAKE_BUILD_TYPE STREQUAL "Debug") diff --git a/test/valgrind.supp b/test/valgrind.supp new file mode 100644 index 0000000..1fed18b --- /dev/null +++ b/test/valgrind.supp @@ -0,0 +1,17 @@ +{ + Suppress wcslen valgrind report 1 + Memcheck:Cond + fun:__wcslen_sse2 +} + +{ + Suppress wcslen valgrind report 2 + Memcheck:Addr8 + fun:__wcslen_sse2 +} + +{ + Suppress wcslen valgrind report 3 + Memcheck:Value8 + fun:__wcslen_sse2 +}