/src/spotify-json/src/detail/escape_sse42.cpp
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2015-2016 Spotify AB |
3 | | * |
4 | | * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
5 | | * use this file except in compliance with the License. You may obtain a copy of |
6 | | * the License at |
7 | | * |
8 | | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | | * |
10 | | * Unless required by applicable law or agreed to in writing, software |
11 | | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
12 | | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
13 | | * License for the specific language governing permissions and limitations under |
14 | | * the License. |
15 | | */ |
16 | | |
17 | | #include <spotify/json/detail/escape.hpp> |
18 | | |
19 | | #if defined(json_arch_x86_sse42) |
20 | | |
21 | | #include <nmmintrin.h> |
22 | | |
23 | | #include "escape_common.hpp" |
24 | | |
25 | | namespace spotify { |
26 | | namespace json { |
27 | | namespace detail { |
28 | | |
29 | 0 | json_force_inline void write_escaped_16_sse42(char *&out, const __m128i chunk) { |
30 | 0 | write_escaped_c(out, _mm_extract_epi8(chunk, 0)); |
31 | 0 | write_escaped_c(out, _mm_extract_epi8(chunk, 1)); |
32 | 0 | write_escaped_c(out, _mm_extract_epi8(chunk, 2)); |
33 | 0 | write_escaped_c(out, _mm_extract_epi8(chunk, 3)); |
34 | 0 | write_escaped_c(out, _mm_extract_epi8(chunk, 4)); |
35 | 0 | write_escaped_c(out, _mm_extract_epi8(chunk, 5)); |
36 | 0 | write_escaped_c(out, _mm_extract_epi8(chunk, 6)); |
37 | 0 | write_escaped_c(out, _mm_extract_epi8(chunk, 7)); |
38 | 0 | write_escaped_c(out, _mm_extract_epi8(chunk, 8)); |
39 | 0 | write_escaped_c(out, _mm_extract_epi8(chunk, 9)); |
40 | 0 | write_escaped_c(out, _mm_extract_epi8(chunk, 10)); |
41 | 0 | write_escaped_c(out, _mm_extract_epi8(chunk, 11)); |
42 | 0 | write_escaped_c(out, _mm_extract_epi8(chunk, 12)); |
43 | 0 | write_escaped_c(out, _mm_extract_epi8(chunk, 13)); |
44 | 0 | write_escaped_c(out, _mm_extract_epi8(chunk, 14)); |
45 | 0 | write_escaped_c(out, _mm_extract_epi8(chunk, 15)); |
46 | 0 | } |
47 | | |
48 | | void write_escaped_sse42( |
49 | | encode_context &context, |
50 | | const char *begin, |
51 | 2.29k | const char *end) { |
52 | 2.29k | const auto buf = context.reserve(6 * (end - begin)); // 6 is the length of \u00xx |
53 | 2.29k | auto out = buf; |
54 | | |
55 | 2.29k | const __m128i ranges = _mm_setr_epi8( |
56 | 2.29k | 0x00, 0x1F, // null byte & control characters |
57 | 2.29k | 0x22, 0x22, // double quotation mark |
58 | 2.29k | 0x5C, 0x5C, // reverse solidus (backslash) |
59 | 2.29k | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
60 | 2.29k | ); |
61 | | |
62 | 2.29k | if (json_unaligned_2(begin) && (end - begin) >= 1) { write_escaped_1(out, begin); } |
63 | 2.29k | if (json_unaligned_4(begin) && (end - begin) >= 2) { write_escaped_2(out, begin); } |
64 | 2.29k | if (json_unaligned_8(begin) && (end - begin) >= 4) { write_escaped_4(out, begin); } |
65 | 2.29k | if (json_unaligned_16(begin) && (end - begin) >= 8) { write_escaped_8(out, begin); } |
66 | | |
67 | 2.29k | for (; end - begin >= 16; begin += 16) { |
68 | 0 | const __m128i chunk = _mm_load_si128(reinterpret_cast<const __m128i *>(begin)); |
69 | 0 | const unsigned has_character_in_ranges = _mm_cmpestrc(ranges, 6, chunk, 16, _SIDD_CMP_RANGES); |
70 | 0 | if (json_likely(!has_character_in_ranges)) { |
71 | 0 | _mm_storeu_si128(reinterpret_cast<__m128i *>(out), chunk); |
72 | 0 | out += 16; |
73 | 0 | } else { |
74 | 0 | write_escaped_16_sse42(out, chunk); |
75 | 0 | } |
76 | 0 | } |
77 | | |
78 | 2.29k | if ((end - begin) >= 8) { write_escaped_8(out, begin); } |
79 | 2.29k | if ((end - begin) >= 4) { write_escaped_4(out, begin); } |
80 | 2.29k | if ((end - begin) >= 2) { write_escaped_2(out, begin); } |
81 | 2.29k | if ((end - begin) >= 1) { write_escaped_1(out, begin); } |
82 | | |
83 | 2.29k | context.advance(out - buf); |
84 | 2.29k | } |
85 | | |
86 | | } // namespace detail |
87 | | } // namespace json |
88 | | } // namespace spotify |
89 | | |
90 | | #endif // defined(json_arch_x86_sse42) |