simdtest.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // Tencent is pleased to support the open source community by making RapidJSON available.
  2. //
  3. // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
  4. //
  5. // Licensed under the MIT License (the "License"); you may not use this file except
  6. // in compliance with the License. You may obtain a copy of the License at
  7. //
  8. // http://opensource.org/licenses/MIT
  9. //
  10. // Unless required by applicable law or agreed to in writing, software distributed
  11. // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  12. // CONDITIONS OF ANY KIND, either express or implied. See the License for the
  13. // specific language governing permissions and limitations under the License.
  14. // Since Travis CI installs old Valgrind 3.7.0, which fails with some SSE4.2
  15. // The unit tests prefix with SIMD should be skipped by Valgrind test
  16. // __SSE2__ and __SSE4_2__ are recognized by gcc, clang, and the Intel compiler.
  17. // We use -march=native with gmake to enable -msse2 and -msse4.2, if supported.
  18. #if defined(__SSE4_2__)
  19. # define RAPIDJSON_SSE42
  20. #elif defined(__SSE2__)
  21. # define RAPIDJSON_SSE2
  22. #endif
  23. #define RAPIDJSON_NAMESPACE rapidjson_simd
  24. #include "unittest.h"
  25. #include "rapidjson/reader.h"
  26. #ifdef __GNUC__
  27. RAPIDJSON_DIAG_PUSH
  28. RAPIDJSON_DIAG_OFF(effc++)
  29. #endif
  30. using namespace rapidjson_simd;
  31. #ifdef RAPIDJSON_SSE2
  32. #define SIMD_SUFFIX(name) name##_SSE2
  33. #elif defined(RAPIDJSON_SSE42)
  34. #define SIMD_SUFFIX(name) name##_SSE42
  35. #else
  36. #define SIMD_SUFFIX(name) name
  37. #endif
  38. template <typename StreamType>
  39. void TestSkipWhitespace() {
  40. for (size_t step = 1; step < 32; step++) {
  41. char buffer[1025];
  42. for (size_t i = 0; i < 1024; i++)
  43. buffer[i] = " \t\r\n"[i % 4];
  44. for (size_t i = 0; i < 1024; i += step)
  45. buffer[i] = 'X';
  46. buffer[1024] = '\0';
  47. StreamType s(buffer);
  48. size_t i = 0;
  49. for (;;) {
  50. SkipWhitespace(s);
  51. if (s.Peek() == '\0')
  52. break;
  53. EXPECT_EQ(i, s.Tell());
  54. EXPECT_EQ('X', s.Take());
  55. i += step;
  56. }
  57. }
  58. }
  59. TEST(SIMD, SIMD_SUFFIX(SkipWhitespace)) {
  60. TestSkipWhitespace<StringStream>();
  61. TestSkipWhitespace<InsituStringStream>();
  62. }
  63. struct ScanCopyUnescapedStringHandler : BaseReaderHandler<UTF8<>, ScanCopyUnescapedStringHandler> {
  64. bool String(const char* str, size_t length, bool) {
  65. memcpy(buffer, str, length + 1);
  66. return true;
  67. }
  68. char buffer[1024 + 5];
  69. };
  70. template <unsigned parseFlags, typename StreamType>
  71. void TestScanCopyUnescapedString() {
  72. for (size_t step = 0; step < 1024; step++) {
  73. char json[1024 + 5];
  74. char *p = json;
  75. *p ++= '\"';
  76. for (size_t i = 0; i < step; i++)
  77. *p++= "ABCD"[i % 4];
  78. *p++ = '\\';
  79. *p++ = '\\';
  80. *p++ = '\"';
  81. *p++ = '\0';
  82. StreamType s(json);
  83. Reader reader;
  84. ScanCopyUnescapedStringHandler h;
  85. reader.Parse<parseFlags>(s, h);
  86. EXPECT_TRUE(memcmp(h.buffer, json + 1, step) == 0);
  87. EXPECT_EQ('\\', h.buffer[step]); // escaped
  88. EXPECT_EQ('\0', h.buffer[step + 1]);
  89. }
  90. }
  91. TEST(SIMD, SIMD_SUFFIX(ScanCopyUnescapedString)) {
  92. TestScanCopyUnescapedString<kParseDefaultFlags, StringStream>();
  93. TestScanCopyUnescapedString<kParseInsituFlag, InsituStringStream>();
  94. }
  95. #ifdef __GNUC__
  96. RAPIDJSON_DIAG_POP
  97. #endif