nano-safe-gem 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. checksums.yaml +7 -0
  2. data/nano-safe-gem.gemspec +12 -0
  3. data/oj-3.17.3/CHANGELOG.md +1506 -0
  4. data/oj-3.17.3/LICENSE +21 -0
  5. data/oj-3.17.3/README.md +103 -0
  6. data/oj-3.17.3/RELEASE_NOTES.md +61 -0
  7. data/oj-3.17.3/ext/oj/buf.h +85 -0
  8. data/oj-3.17.3/ext/oj/cache.c +329 -0
  9. data/oj-3.17.3/ext/oj/cache.h +22 -0
  10. data/oj-3.17.3/ext/oj/cache8.c +105 -0
  11. data/oj-3.17.3/ext/oj/cache8.h +21 -0
  12. data/oj-3.17.3/ext/oj/circarray.c +64 -0
  13. data/oj-3.17.3/ext/oj/circarray.h +22 -0
  14. data/oj-3.17.3/ext/oj/code.c +214 -0
  15. data/oj-3.17.3/ext/oj/code.h +40 -0
  16. data/oj-3.17.3/ext/oj/compat.c +239 -0
  17. data/oj-3.17.3/ext/oj/custom.c +1079 -0
  18. data/oj-3.17.3/ext/oj/debug.c +126 -0
  19. data/oj-3.17.3/ext/oj/dump.c +1765 -0
  20. data/oj-3.17.3/ext/oj/dump.h +112 -0
  21. data/oj-3.17.3/ext/oj/dump_compat.c +902 -0
  22. data/oj-3.17.3/ext/oj/dump_leaf.c +162 -0
  23. data/oj-3.17.3/ext/oj/dump_object.c +715 -0
  24. data/oj-3.17.3/ext/oj/dump_strict.c +404 -0
  25. data/oj-3.17.3/ext/oj/encode.h +16 -0
  26. data/oj-3.17.3/ext/oj/encoder.c +43 -0
  27. data/oj-3.17.3/ext/oj/err.c +57 -0
  28. data/oj-3.17.3/ext/oj/err.h +67 -0
  29. data/oj-3.17.3/ext/oj/extconf.rb +72 -0
  30. data/oj-3.17.3/ext/oj/fast.c +1730 -0
  31. data/oj-3.17.3/ext/oj/intern.c +313 -0
  32. data/oj-3.17.3/ext/oj/intern.h +22 -0
  33. data/oj-3.17.3/ext/oj/mem.c +318 -0
  34. data/oj-3.17.3/ext/oj/mem.h +53 -0
  35. data/oj-3.17.3/ext/oj/mimic_json.c +922 -0
  36. data/oj-3.17.3/ext/oj/object.c +726 -0
  37. data/oj-3.17.3/ext/oj/odd.c +245 -0
  38. data/oj-3.17.3/ext/oj/odd.h +43 -0
  39. data/oj-3.17.3/ext/oj/oj.c +2332 -0
  40. data/oj-3.17.3/ext/oj/oj.h +405 -0
  41. data/oj-3.17.3/ext/oj/parse.c +1367 -0
  42. data/oj-3.17.3/ext/oj/parse.h +113 -0
  43. data/oj-3.17.3/ext/oj/parser.c +1676 -0
  44. data/oj-3.17.3/ext/oj/parser.h +103 -0
  45. data/oj-3.17.3/ext/oj/rails.c +1480 -0
  46. data/oj-3.17.3/ext/oj/rails.h +18 -0
  47. data/oj-3.17.3/ext/oj/reader.c +220 -0
  48. data/oj-3.17.3/ext/oj/reader.h +137 -0
  49. data/oj-3.17.3/ext/oj/resolve.c +80 -0
  50. data/oj-3.17.3/ext/oj/resolve.h +12 -0
  51. data/oj-3.17.3/ext/oj/rxclass.c +144 -0
  52. data/oj-3.17.3/ext/oj/rxclass.h +26 -0
  53. data/oj-3.17.3/ext/oj/safe.c +230 -0
  54. data/oj-3.17.3/ext/oj/safe.h +79 -0
  55. data/oj-3.17.3/ext/oj/saj.c +677 -0
  56. data/oj-3.17.3/ext/oj/saj2.c +584 -0
  57. data/oj-3.17.3/ext/oj/saj2.h +23 -0
  58. data/oj-3.17.3/ext/oj/scp.c +185 -0
  59. data/oj-3.17.3/ext/oj/simd.h +219 -0
  60. data/oj-3.17.3/ext/oj/sparse.c +943 -0
  61. data/oj-3.17.3/ext/oj/stream_writer.c +329 -0
  62. data/oj-3.17.3/ext/oj/strict.c +187 -0
  63. data/oj-3.17.3/ext/oj/string_writer.c +517 -0
  64. data/oj-3.17.3/ext/oj/trace.c +72 -0
  65. data/oj-3.17.3/ext/oj/trace.h +55 -0
  66. data/oj-3.17.3/ext/oj/usual.c +1231 -0
  67. data/oj-3.17.3/ext/oj/usual.h +69 -0
  68. data/oj-3.17.3/ext/oj/util.c +136 -0
  69. data/oj-3.17.3/ext/oj/util.h +20 -0
  70. data/oj-3.17.3/ext/oj/val_stack.c +101 -0
  71. data/oj-3.17.3/ext/oj/val_stack.h +151 -0
  72. data/oj-3.17.3/ext/oj/validate.c +46 -0
  73. data/oj-3.17.3/ext/oj/wab.c +586 -0
  74. data/oj-3.17.3/lib/oj/active_support_helper.rb +39 -0
  75. data/oj-3.17.3/lib/oj/bag.rb +95 -0
  76. data/oj-3.17.3/lib/oj/easy_hash.rb +52 -0
  77. data/oj-3.17.3/lib/oj/error.rb +21 -0
  78. data/oj-3.17.3/lib/oj/json.rb +188 -0
  79. data/oj-3.17.3/lib/oj/mimic.rb +301 -0
  80. data/oj-3.17.3/lib/oj/saj.rb +80 -0
  81. data/oj-3.17.3/lib/oj/schandler.rb +143 -0
  82. data/oj-3.17.3/lib/oj/state.rb +135 -0
  83. data/oj-3.17.3/lib/oj/version.rb +4 -0
  84. data/oj-3.17.3/lib/oj.rb +15 -0
  85. data/oj-3.17.3/pages/Advanced.md +22 -0
  86. data/oj-3.17.3/pages/Compatibility.md +25 -0
  87. data/oj-3.17.3/pages/Custom.md +23 -0
  88. data/oj-3.17.3/pages/Encoding.md +65 -0
  89. data/oj-3.17.3/pages/InstallOptions.md +20 -0
  90. data/oj-3.17.3/pages/JsonGem.md +94 -0
  91. data/oj-3.17.3/pages/Modes.md +161 -0
  92. data/oj-3.17.3/pages/Options.md +337 -0
  93. data/oj-3.17.3/pages/Parser.md +309 -0
  94. data/oj-3.17.3/pages/Rails.md +167 -0
  95. data/oj-3.17.3/pages/Security.md +20 -0
  96. data/oj-3.17.3/pages/WAB.md +13 -0
  97. metadata +136 -0
@@ -0,0 +1,185 @@
1
+ // Copyright (c) 2012 Peter Ohler. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file in the project root for license details.
3
+
4
+ #include <math.h>
5
+ #include <stdio.h>
6
+ #include <stdlib.h>
7
+ #include <string.h>
8
+ #include <sys/types.h>
9
+ #include <unistd.h>
10
+
11
+ #include "encode.h"
12
+ #include "intern.h"
13
+ #include "oj.h"
14
+ #include "parse.h"
15
+
16
+ static VALUE noop_start(ParseInfo pi) {
17
+ return Qnil;
18
+ }
19
+
20
+ static void noop_end(ParseInfo pi) {
21
+ }
22
+
23
+ static void noop_add_value(ParseInfo pi, VALUE val) {
24
+ }
25
+
26
+ static void noop_add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
27
+ }
28
+
29
+ static void noop_add_num(ParseInfo pi, NumInfo ni) {
30
+ }
31
+
32
+ static VALUE noop_hash_key(ParseInfo pi, const char *key, size_t klen) {
33
+ return Qundef;
34
+ }
35
+
36
+ static void noop_hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *orig) {
37
+ }
38
+
39
+ static void noop_hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
40
+ }
41
+
42
+ static void noop_hash_set_value(ParseInfo pi, Val kval, VALUE value) {
43
+ }
44
+
45
+ static void noop_array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
46
+ }
47
+
48
+ static void noop_array_append_num(ParseInfo pi, NumInfo ni) {
49
+ }
50
+
51
+ static void noop_array_append_value(ParseInfo pi, VALUE value) {
52
+ }
53
+
54
+ static void add_value(ParseInfo pi, VALUE val) {
55
+ rb_funcall(pi->handler, oj_add_value_id, 1, val);
56
+ }
57
+
58
+ static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
59
+ volatile VALUE rstr = rb_utf8_str_new(str, len);
60
+
61
+ rb_funcall(pi->handler, oj_add_value_id, 1, rstr);
62
+ }
63
+
64
+ static void add_num(ParseInfo pi, NumInfo ni) {
65
+ rb_funcall(pi->handler, oj_add_value_id, 1, oj_num_as_value(ni));
66
+ }
67
+
68
+ static VALUE start_hash(ParseInfo pi) {
69
+ return rb_funcall(pi->handler, oj_hash_start_id, 0);
70
+ }
71
+
72
+ static void end_hash(ParseInfo pi) {
73
+ rb_funcall(pi->handler, oj_hash_end_id, 0);
74
+ }
75
+
76
+ static VALUE start_array(ParseInfo pi) {
77
+ return rb_funcall(pi->handler, oj_array_start_id, 0);
78
+ }
79
+
80
+ static void end_array(ParseInfo pi) {
81
+ rb_funcall(pi->handler, oj_array_end_id, 0);
82
+ }
83
+
84
+ static VALUE hash_key(ParseInfo pi, const char *key, size_t klen) {
85
+ return rb_funcall(pi->handler, oj_hash_key_id, 1, rb_str_new(key, klen));
86
+ }
87
+
88
+ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *orig) {
89
+ volatile VALUE rstr = rb_utf8_str_new(str, len);
90
+
91
+ rb_funcall(pi->handler, oj_hash_set_id, 3, stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, kval), rstr);
92
+ }
93
+
94
+ static void hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
95
+ rb_funcall(pi->handler,
96
+ oj_hash_set_id,
97
+ 3,
98
+ stack_peek(&pi->stack)->val,
99
+ oj_calc_hash_key(pi, kval),
100
+ oj_num_as_value(ni));
101
+ }
102
+
103
+ static void hash_set_value(ParseInfo pi, Val kval, VALUE value) {
104
+ rb_funcall(pi->handler, oj_hash_set_id, 3, stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, kval), value);
105
+ }
106
+
107
+ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
108
+ volatile VALUE rstr = rb_utf8_str_new(str, len);
109
+
110
+ rb_funcall(pi->handler, oj_array_append_id, 2, stack_peek(&pi->stack)->val, rstr);
111
+ }
112
+
113
+ static void array_append_num(ParseInfo pi, NumInfo ni) {
114
+ rb_funcall(pi->handler, oj_array_append_id, 2, stack_peek(&pi->stack)->val, oj_num_as_value(ni));
115
+ }
116
+
117
+ static void array_append_value(ParseInfo pi, VALUE value) {
118
+ rb_funcall(pi->handler, oj_array_append_id, 2, stack_peek(&pi->stack)->val, value);
119
+ }
120
+
121
+ VALUE
122
+ oj_sc_parse(int argc, VALUE *argv, VALUE self) {
123
+ struct _parseInfo pi;
124
+ VALUE input = argv[1];
125
+
126
+ parse_info_init(&pi);
127
+ pi.err_class = Qnil;
128
+ pi.max_depth = 0;
129
+ pi.options = oj_default_options;
130
+ if (3 == argc) {
131
+ oj_parse_options(argv[2], &pi.options);
132
+ }
133
+ if (rb_block_given_p()) {
134
+ pi.proc = Qnil;
135
+ } else {
136
+ pi.proc = Qundef;
137
+ }
138
+ pi.handler = *argv;
139
+
140
+ pi.start_hash = rb_respond_to(pi.handler, oj_hash_start_id) ? start_hash : noop_start;
141
+ pi.end_hash = rb_respond_to(pi.handler, oj_hash_end_id) ? end_hash : noop_end;
142
+ pi.hash_key = rb_respond_to(pi.handler, oj_hash_key_id) ? hash_key : noop_hash_key;
143
+ pi.start_array = rb_respond_to(pi.handler, oj_array_start_id) ? start_array : noop_start;
144
+ pi.end_array = rb_respond_to(pi.handler, oj_array_end_id) ? end_array : noop_end;
145
+ if (rb_respond_to(pi.handler, oj_hash_set_id)) {
146
+ pi.hash_set_value = hash_set_value;
147
+ pi.hash_set_cstr = hash_set_cstr;
148
+ pi.hash_set_num = hash_set_num;
149
+ pi.expect_value = 1;
150
+ } else {
151
+ pi.hash_set_value = noop_hash_set_value;
152
+ pi.hash_set_cstr = noop_hash_set_cstr;
153
+ pi.hash_set_num = noop_hash_set_num;
154
+ pi.expect_value = 0;
155
+ }
156
+ if (rb_respond_to(pi.handler, oj_array_append_id)) {
157
+ pi.array_append_value = array_append_value;
158
+ pi.array_append_cstr = array_append_cstr;
159
+ pi.array_append_num = array_append_num;
160
+ pi.expect_value = 1;
161
+ } else {
162
+ pi.array_append_value = noop_array_append_value;
163
+ pi.array_append_cstr = noop_array_append_cstr;
164
+ pi.array_append_num = noop_array_append_num;
165
+ pi.expect_value = 0;
166
+ }
167
+ if (rb_respond_to(pi.handler, oj_add_value_id)) {
168
+ pi.add_cstr = add_cstr;
169
+ pi.add_num = add_num;
170
+ pi.add_value = add_value;
171
+ pi.expect_value = 1;
172
+ } else {
173
+ pi.add_cstr = noop_add_cstr;
174
+ pi.add_num = noop_add_num;
175
+ pi.add_value = noop_add_value;
176
+ pi.expect_value = 0;
177
+ }
178
+ pi.has_callbacks = true;
179
+
180
+ if (T_STRING == rb_type(input)) {
181
+ return oj_pi_parse(argc - 1, argv + 1, &pi, 0, 0, 1);
182
+ } else {
183
+ return oj_pi_sparse(argc - 1, argv + 1, &pi, 0);
184
+ }
185
+ }
@@ -0,0 +1,219 @@
1
+ #ifndef OJ_SIMD_H
2
+ #define OJ_SIMD_H
3
+
4
+ // SIMD architecture detection and configuration
5
+ // This header provides unified SIMD support across different CPU architectures
6
+ // with cross-platform runtime detection (Windows/Linux/Mac)
7
+
8
+ // SIMD implementation enum - used for runtime selection
9
+ typedef enum _simd_implementation { SIMD_NONE, SIMD_NEON, SIMD_SSE2, SIMD_SSE42 } SIMD_Implementation;
10
+
11
+ // Define in oj.c.
12
+ extern SIMD_Implementation SIMD_Impl;
13
+
14
+ // Runtime CPU detection function (implemented in oj.c)
15
+ SIMD_Implementation oj_get_simd_implementation(void);
16
+
17
+ // =============================================================================
18
+ // Compiler compatibility macros
19
+ // =============================================================================
20
+
21
+ // Branch prediction hints
22
+ #if defined(__GNUC__) || defined(__clang__)
23
+ #define OJ_LIKELY(x) __builtin_expect(!!(x), 1)
24
+ #define OJ_UNLIKELY(x) __builtin_expect(!!(x), 0)
25
+ #else
26
+ #define OJ_LIKELY(x) (x)
27
+ #define OJ_UNLIKELY(x) (x)
28
+ #endif
29
+
30
+ // Prefetch hints
31
+ #if defined(__GNUC__) || defined(__clang__)
32
+ #define OJ_PREFETCH(addr) __builtin_prefetch(addr, 0, 0)
33
+ #elif defined(_MSC_VER)
34
+ #include <intrin.h>
35
+ #define OJ_PREFETCH(addr) _mm_prefetch((const char *)(addr), _MM_HINT_T0)
36
+ #else
37
+ #define OJ_PREFETCH(addr) ((void)0)
38
+ #endif
39
+
40
+ // Count trailing zeros (for SSE2 mask scanning)
41
+ #if defined(__GNUC__) || defined(__clang__)
42
+ #define OJ_CTZ(x) __builtin_ctz(x)
43
+ #define OJ_CTZ64(x) __builtin_ctzll(x)
44
+ #elif defined(_MSC_VER)
45
+ #include <intrin.h>
46
+ static __inline int oj_ctz_msvc(unsigned int x) {
47
+ unsigned long index;
48
+ if (0 == x) {
49
+ return 32;
50
+ }
51
+ _BitScanForward(&index, x);
52
+ return (int)index;
53
+ }
54
+ static __inline int oj_ctz64_msvc(uint64_t x) {
55
+ unsigned long index;
56
+ if (_BitScanForward64(&index, x)) {
57
+ return (int)index;
58
+ }
59
+ return 64;
60
+ }
61
+ #define OJ_CTZ(x) oj_ctz_msvc(x)
62
+ #define OJ_CTZ64(x) oj_ctz64_msvc(x)
63
+ #else
64
+ // Fallback: naive implementation
65
+ static inline int oj_ctz_fallback(unsigned int x) {
66
+ int count = 0;
67
+ while ((x & 1) == 0 && count < 32) {
68
+ x >>= 1;
69
+ count++;
70
+ }
71
+ return count;
72
+ }
73
+
74
+ static inline int oj_ctz64_fallback(uint64_t x) {
75
+ int count = 0;
76
+ while ((x & 1) == 0 && count < 64) {
77
+ x >>= 1;
78
+ count++;
79
+ }
80
+ return count;
81
+ }
82
+ #define OJ_CTZ(x) oj_ctz_fallback(x)
83
+ #define OJ_CTZ64(x) oj_ctz64_fallback(x)
84
+ #endif
85
+
86
+ // =============================================================================
87
+ // x86/x86_64 SIMD detection
88
+ // =============================================================================
89
+ #if defined(__x86_64__) || defined(__i386__) || defined(_M_IX86) || defined(_M_X64)
90
+ #define HAVE_SIMD_X86 1
91
+
92
+ // Include appropriate SIMD headers
93
+ #if defined(_MSC_VER)
94
+ // MSVC: use intrin.h for all intrinsics
95
+ #include <intrin.h>
96
+ #define HAVE_SIMD_SSE4_2 1
97
+ #define HAVE_SIMD_SSE2 1
98
+ #elif defined(__GNUC__) || defined(__clang__)
99
+ // GCC/Clang: check for header availability and include them
100
+ // We include headers but use target attributes to enable instructions per-function
101
+ // Include cpuid.h for __get_cpuid fallback when __builtin_cpu_supports is unavailable
102
+ #if __has_include(<cpuid.h>)
103
+ #include <cpuid.h>
104
+ #endif
105
+ #if defined(__SSE4_2__) || defined(__SSE2__)
106
+ // If any SSE is enabled globally, x86intrin.h should be available
107
+ #include <x86intrin.h>
108
+ #define HAVE_SIMD_SSE4_2 1
109
+ #define HAVE_SIMD_SSE2 1
110
+ #else
111
+ // Try to include headers anyway for target attribute functions
112
+ #if __has_include(<x86intrin.h>)
113
+ #include <x86intrin.h>
114
+ #define HAVE_SIMD_SSE4_2 1
115
+ #define HAVE_SIMD_SSE2 1
116
+ #elif __has_include(<nmmintrin.h>)
117
+ #include <nmmintrin.h>
118
+ #define HAVE_SIMD_SSE4_2 1
119
+ #define HAVE_SIMD_SSE2 1
120
+ #elif __has_include(<emmintrin.h>)
121
+ #include <emmintrin.h>
122
+ #define HAVE_SIMD_SSE2 1
123
+ #endif
124
+ #endif
125
+ #endif
126
+
127
+ // Target attribute macros for function-level SIMD enabling
128
+ #if defined(__clang__) || defined(__GNUC__)
129
+ #define OJ_TARGET_SSE42 __attribute__((target("sse4.2")))
130
+ #define OJ_TARGET_SSE2 __attribute__((target("sse2")))
131
+ #else
132
+ // MSVC doesn't need target attributes - intrinsics are always available
133
+ #define OJ_TARGET_SSE42
134
+ #define OJ_TARGET_SSE2
135
+ #endif
136
+
137
+ #endif // x86/x86_64
138
+
139
+ // =============================================================================
140
+ // ARM NEON detection
141
+ // =============================================================================
142
+ #if defined(__ARM_NEON) || defined(__ARM_NEON__) || defined(__aarch64__) || defined(_M_ARM64)
143
+ #define HAVE_SIMD_NEON 1
144
+ #define SIMD_MINIMUM_THRESHOLD 6
145
+ #include <arm_neon.h>
146
+ #endif
147
+
148
+ // =============================================================================
149
+ // SIMD type string for debugging/logging
150
+ // =============================================================================
151
+ #if defined(HAVE_SIMD_SSE4_2) || defined(HAVE_SIMD_SSE2)
152
+ #define HAVE_SIMD_STRING_SCAN 1
153
+ #define SIMD_TYPE "x86 (runtime detected)"
154
+ #elif defined(HAVE_SIMD_NEON)
155
+ #define HAVE_SIMD_STRING_SCAN 1
156
+ #define SIMD_TYPE "NEON"
157
+ #else
158
+ #define SIMD_TYPE "none"
159
+ #endif
160
+
161
+ #if defined(HAVE_SIMD_SSE4_2)
162
+
163
+ #define SIMD_MINIMUM_THRESHOLD 6
164
+
165
+ extern void initialize_sse42(void);
166
+
167
+ static inline OJ_TARGET_SSE42 __m128i vector_lookup_sse42(__m128i input, __m128i *lookup_table, int tab_size) {
168
+ // Extract high 4 bits to determine which 16-byte chunk (0-15)
169
+ __m128i hi_index = _mm_and_si128(_mm_srli_epi32(input, 4), _mm_set1_epi8(0x0F));
170
+
171
+ // Extract low 4 bits for index within the chunk (0-15)
172
+ __m128i low_index = _mm_and_si128(input, _mm_set1_epi8(0x0F));
173
+
174
+ // Perform lookups in all 16 tables
175
+ __m128i results[16];
176
+ for (int i = 0; i < tab_size; i++) {
177
+ results[i] = _mm_shuffle_epi8(lookup_table[i], low_index);
178
+ }
179
+
180
+ // Create masks for each chunk and blend results
181
+ __m128i final_result = _mm_setzero_si128();
182
+
183
+ for (int i = 0; i < tab_size; i++) {
184
+ __m128i mask = _mm_cmpeq_epi8(hi_index, _mm_set1_epi8(i));
185
+ __m128i masked_result = _mm_and_si128(mask, results[i]);
186
+ final_result = _mm_or_si128(final_result, masked_result);
187
+ }
188
+
189
+ return final_result;
190
+ }
191
+
192
+ #endif
193
+
194
+ #ifndef __has_builtin
195
+ #define __has_builtin(x) 0
196
+ #endif
197
+
198
+ #if __has_builtin(__builtin_memcpy)
199
+ #define HAVE_FAST_MEMCPY 1
200
+
201
+ inline static void fast_memcpy16(void *dest, const void *src, size_t n) {
202
+ char *d = (char *)dest;
203
+ char *s = (char *)src;
204
+ if (n >= 8) {
205
+ __builtin_memcpy(d, s, 8);
206
+ __builtin_memcpy(d + n - 8, s + n - 8, 8);
207
+ } else if (n >= 4) {
208
+ __builtin_memcpy(d, s, 4);
209
+ __builtin_memcpy(d + n - 4, s + n - 4, 4);
210
+ } else if (n >= 2) {
211
+ __builtin_memcpy(d, s, 2);
212
+ __builtin_memcpy(d + n - 2, s + n - 2, 2);
213
+ } else if (n >= 1) {
214
+ *d = *s;
215
+ }
216
+ }
217
+ #endif
218
+
219
+ #endif /* OJ_SIMD_H */