simdtest.cpp
Go to the documentation of this file.
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 
15 // Since Travis CI installs old Valgrind 3.7.0, which fails with some SSE4.2
16 // The unit tests prefix with SIMD should be skipped by Valgrind test
17 
18 // __SSE2__ and __SSE4_2__ are recognized by gcc, clang, and the Intel compiler.
19 // We use -march=native with gmake to enable -msse2 and -msse4.2, if supported.
20 #if defined(__SSE4_2__)
21 # define RAPIDJSON_SSE42
22 #elif defined(__SSE2__)
23 # define RAPIDJSON_SSE2
24 #elif defined(__ARM_NEON)
25 # define RAPIDJSON_NEON
26 #endif
27 
28 #define RAPIDJSON_NAMESPACE rapidjson_simd
29 
30 #include "unittest.h"
31 
32 #include "rapidjson/reader.h"
33 #include "rapidjson/writer.h"
34 
35 #ifdef __GNUC__
36 RAPIDJSON_DIAG_PUSH
37 RAPIDJSON_DIAG_OFF(effc++)
38 #endif
39 
40 using namespace rapidjson_simd;
41 
42 #ifdef RAPIDJSON_SSE2
43 #define SIMD_SUFFIX(name) name##_SSE2
44 #elif defined(RAPIDJSON_SSE42)
45 #define SIMD_SUFFIX(name) name##_SSE42
46 #elif defined(RAPIDJSON_NEON)
47 #define SIMD_SUFFIX(name) name##_NEON
48 #else
49 #define SIMD_SUFFIX(name) name
50 #endif
51 
52 template <typename StreamType>
54  for (size_t step = 1; step < 32; step++) {
55  char buffer[1025];
56  for (size_t i = 0; i < 1024; i++)
57  buffer[i] = " \t\r\n"[i % 4];
58  for (size_t i = 0; i < 1024; i += step)
59  buffer[i] = 'X';
60  buffer[1024] = '\0';
61 
62  StreamType s(buffer);
63  size_t i = 0;
64  for (;;) {
65  SkipWhitespace(s);
66  if (s.Peek() == '\0')
67  break;
68  EXPECT_EQ(i, s.Tell());
69  EXPECT_EQ('X', s.Take());
70  i += step;
71  }
72  }
73 }
74 
76  TestSkipWhitespace<StringStream>();
77  TestSkipWhitespace<InsituStringStream>();
78 }
79 
80 TEST(SIMD, SIMD_SUFFIX(SkipWhitespace_EncodedMemoryStream)) {
81  for (size_t step = 1; step < 32; step++) {
82  char buffer[1024];
83  for (size_t i = 0; i < 1024; i++)
84  buffer[i] = " \t\r\n"[i % 4];
85  for (size_t i = 0; i < 1024; i += step)
86  buffer[i] = 'X';
87 
88  MemoryStream ms(buffer, 1024);
90  size_t i = 0;
91  for (;;) {
92  SkipWhitespace(s);
93  if (s.Peek() == '\0')
94  break;
95  //EXPECT_EQ(i, s.Tell());
96  EXPECT_EQ('X', s.Take());
97  i += step;
98  }
99  }
100 }
101 
102 struct ScanCopyUnescapedStringHandler : BaseReaderHandler<UTF8<>, ScanCopyUnescapedStringHandler> {
103  bool String(const char* str, size_t length, bool) {
104  memcpy(buffer, str, length + 1);
105  return true;
106  }
107  char buffer[1024 + 5 + 32];
108 };
109 
110 template <unsigned parseFlags, typename StreamType>
112  char buffer[1024 + 5 + 32];
113  char backup[1024 + 5 + 32];
114 
115  // Test "ABCDABCD...\\"
116  for (size_t offset = 0; offset < 32; offset++) {
117  for (size_t step = 0; step < 1024; step++) {
118  char* json = buffer + offset;
119  char *p = json;
120  *p++ = '\"';
121  for (size_t i = 0; i < step; i++)
122  *p++ = "ABCD"[i % 4];
123  *p++ = '\\';
124  *p++ = '\\';
125  *p++ = '\"';
126  *p++ = '\0';
127  strcpy(backup, json); // insitu parsing will overwrite buffer, so need to backup first
128 
129  StreamType s(json);
130  Reader reader;
132  reader.Parse<parseFlags>(s, h);
133  EXPECT_TRUE(memcmp(h.buffer, backup + 1, step) == 0);
134  EXPECT_EQ('\\', h.buffer[step]); // escaped
135  EXPECT_EQ('\0', h.buffer[step + 1]);
136  }
137  }
138 
139  // Test "\\ABCDABCD..."
140  for (size_t offset = 0; offset < 32; offset++) {
141  for (size_t step = 0; step < 1024; step++) {
142  char* json = buffer + offset;
143  char *p = json;
144  *p++ = '\"';
145  *p++ = '\\';
146  *p++ = '\\';
147  for (size_t i = 0; i < step; i++)
148  *p++ = "ABCD"[i % 4];
149  *p++ = '\"';
150  *p++ = '\0';
151  strcpy(backup, json); // insitu parsing will overwrite buffer, so need to backup first
152 
153  StreamType s(json);
154  Reader reader;
156  reader.Parse<parseFlags>(s, h);
157  EXPECT_TRUE(memcmp(h.buffer + 1, backup + 3, step) == 0);
158  EXPECT_EQ('\\', h.buffer[0]); // escaped
159  EXPECT_EQ('\0', h.buffer[step + 1]);
160  }
161  }
162 }
163 
164 TEST(SIMD, SIMD_SUFFIX(ScanCopyUnescapedString)) {
165  TestScanCopyUnescapedString<kParseDefaultFlags, StringStream>();
166  TestScanCopyUnescapedString<kParseInsituFlag, InsituStringStream>();
167 }
168 
169 TEST(SIMD, SIMD_SUFFIX(ScanWriteUnescapedString)) {
170  char buffer[2048 + 1 + 32];
171  for (size_t offset = 0; offset < 32; offset++) {
172  for (size_t step = 0; step < 1024; step++) {
173  char* s = buffer + offset;
174  char* p = s;
175  for (size_t i = 0; i < step; i++)
176  *p++ = "ABCD"[i % 4];
177  char escape = "\0\n\\\""[step % 4];
178  *p++ = escape;
179  for (size_t i = 0; i < step; i++)
180  *p++ = "ABCD"[i % 4];
181 
182  StringBuffer sb;
183  Writer<StringBuffer> writer(sb);
184  writer.String(s, SizeType(step * 2 + 1));
185  const char* q = sb.GetString();
186  EXPECT_EQ('\"', *q++);
187  for (size_t i = 0; i < step; i++)
188  EXPECT_EQ("ABCD"[i % 4], *q++);
189  if (escape == '\0') {
190  EXPECT_EQ('\\', *q++);
191  EXPECT_EQ('u', *q++);
192  EXPECT_EQ('0', *q++);
193  EXPECT_EQ('0', *q++);
194  EXPECT_EQ('0', *q++);
195  EXPECT_EQ('0', *q++);
196  }
197  else if (escape == '\n') {
198  EXPECT_EQ('\\', *q++);
199  EXPECT_EQ('n', *q++);
200  }
201  else if (escape == '\\') {
202  EXPECT_EQ('\\', *q++);
203  EXPECT_EQ('\\', *q++);
204  }
205  else if (escape == '\"') {
206  EXPECT_EQ('\\', *q++);
207  EXPECT_EQ('\"', *q++);
208  }
209  for (size_t i = 0; i < step; i++)
210  EXPECT_EQ("ABCD"[i % 4], *q++);
211  EXPECT_EQ('\"', *q++);
212  EXPECT_EQ('\0', *q++);
213  }
214  }
215 }
216 
217 #ifdef __GNUC__
218 RAPIDJSON_DIAG_POP
219 #endif
TEST(SIMD, SIMD_SUFFIX(SkipWhitespace))
Definition: simdtest.cpp:75
ParseResult Parse(InputStream &is, Handler &handler)
Parse JSON text.
Definition: reader.h:558
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition: rapidjson.h:389
Represents an in-memory input byte stream.
Definition: memorystream.h:40
void TestScanCopyUnescapedString()
Definition: simdtest.cpp:111
bool String(const char *str, size_t length, bool)
Definition: simdtest.cpp:103
JSON writer.
Definition: fwd.h:95
Default implementation of Handler.
Definition: fwd.h:85
const Ch * GetString() const
Definition: stringbuffer.h:73
XmlRpcServer s
bool String(const Ch *str, SizeType length, bool copy=false)
Definition: writer.h:204
void TestSkipWhitespace()
Definition: simdtest.cpp:53
Ch Peek() const
Definition: encodedstream.h:48
static const char json[]
#define SIMD_SUFFIX(name)
Definition: simdtest.cpp:49
StreamType
Input byte stream wrapper with a statically bound encoding.
Definition: encodedstream.h:39
void SkipWhitespace(InputStream &is)
Skip the JSON white spaces in a stream.
Definition: reader.h:266


choreo_rapidjson
Author(s):
autogenerated on Thu Jul 18 2019 03:59:09