sereal 0.0.2

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.
@@ -0,0 +1,414 @@
1
+ /*
2
+ Copyright 2011, Google Inc.
3
+ All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are
7
+ met:
8
+
9
+ * Redistributions of source code must retain the above copyright
10
+ notice, this list of conditions and the following disclaimer.
11
+ * Redistributions in binary form must reproduce the above
12
+ copyright notice, this list of conditions and the following disclaimer
13
+ in the documentation and/or other materials provided with the
14
+ distribution.
15
+ * Neither the name of Google Inc. nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ File modified for the Linux Kernel by
32
+ Zeev Tarantov <zeev.tarantov@gmail.com>
33
+ */
34
+
35
+ #include "csnappy_internal.h"
36
+ #ifdef __KERNEL__
37
+ #include <linux/kernel.h>
38
+ #include <linux/module.h>
39
+ #endif
40
+ #include "csnappy.h"
41
+
42
+ int
43
+ csnappy_get_uncompressed_length(
44
+ const char *src,
45
+ uint32_t src_len,
46
+ uint32_t *result)
47
+ {
48
+ const char *src_base = src;
49
+ uint32_t shift = 0;
50
+ uint8_t c;
51
+ /* Length is encoded in 1..5 bytes */
52
+ *result = 0;
53
+ for (;;) {
54
+ if (shift >= 32)
55
+ goto err_out;
56
+ if (src_len == 0)
57
+ goto err_out;
58
+ c = *(const uint8_t *)src++;
59
+ src_len -= 1;
60
+ *result |= (uint32_t)(c & 0x7f) << shift;
61
+ if (c < 128)
62
+ break;
63
+ shift += 7;
64
+ }
65
+ return src - src_base;
66
+ err_out:
67
+ return CSNAPPY_E_HEADER_BAD;
68
+ }
69
+ #if defined(__KERNEL__) && !defined(STATIC)
70
+ EXPORT_SYMBOL(csnappy_get_uncompressed_length);
71
+ #endif
72
+
73
+ #if defined(__arm__) && !(ARCH_ARM_HAVE_UNALIGNED)
74
+ int csnappy_decompress_noheader(
75
+ const char *src_,
76
+ uint32_t src_remaining,
77
+ char *dst,
78
+ uint32_t *dst_len)
79
+ {
80
+ const uint8_t * src = (const uint8_t *)src_;
81
+ const uint8_t * const src_end = src + src_remaining;
82
+ char * const dst_base = dst;
83
+ char * const dst_end = dst + *dst_len;
84
+ while (src < src_end) {
85
+ uint32_t opcode = *src++;
86
+ uint32_t length = (opcode >> 2) + 1;
87
+ const uint8_t *copy_src;
88
+ if (likely((opcode & 3) == 0)) {
89
+ if (unlikely(length > 60)) {
90
+ uint32_t extra_bytes = length - 60;
91
+ int shift, max_shift;
92
+ if (unlikely(src + extra_bytes > src_end))
93
+ return CSNAPPY_E_DATA_MALFORMED;
94
+ length = 0;
95
+ for (shift = 0, max_shift = extra_bytes*8;
96
+ shift < max_shift;
97
+ shift += 8)
98
+ length |= *src++ << shift;
99
+ ++length;
100
+ }
101
+ if (unlikely(src + length > src_end))
102
+ return CSNAPPY_E_DATA_MALFORMED;
103
+ copy_src = src;
104
+ src += length;
105
+ } else {
106
+ uint32_t offset;
107
+ if (likely((opcode & 3) == 1)) {
108
+ if (unlikely(src + 1 > src_end))
109
+ return CSNAPPY_E_DATA_MALFORMED;
110
+ length = ((length - 1) & 7) + 4;
111
+ offset = ((opcode >> 5) << 8) + *src++;
112
+ } else if (likely((opcode & 3) == 2)) {
113
+ if (unlikely(src + 2 > src_end))
114
+ return CSNAPPY_E_DATA_MALFORMED;
115
+ offset = src[0] | (src[1] << 8);
116
+ src += 2;
117
+ } else {
118
+ if (unlikely(src + 4 > src_end))
119
+ return CSNAPPY_E_DATA_MALFORMED;
120
+ offset = src[0] | (src[1] << 8) |
121
+ (src[2] << 16) | (src[3] << 24);
122
+ src += 4;
123
+ }
124
+ if (unlikely(!offset || (offset > dst - dst_base)))
125
+ return CSNAPPY_E_DATA_MALFORMED;
126
+ copy_src = (const uint8_t *)dst - offset;
127
+ }
128
+ if (unlikely(dst + length > dst_end))
129
+ return CSNAPPY_E_OUTPUT_OVERRUN;
130
+ do *dst++ = *copy_src++; while (--length);
131
+ }
132
+ *dst_len = dst - dst_base;
133
+ return CSNAPPY_E_OK;
134
+ }
135
+ #else /* !(arm with no unaligned access) */
136
+ /*
137
+ * Data stored per entry in lookup table:
138
+ * Range Bits-used Description
139
+ * ------------------------------------
140
+ * 1..64 0..7 Literal/copy length encoded in opcode byte
141
+ * 0..7 8..10 Copy offset encoded in opcode byte / 256
142
+ * 0..4 11..13 Extra bytes after opcode
143
+ *
144
+ * We use eight bits for the length even though 7 would have sufficed
145
+ * because of efficiency reasons:
146
+ * (1) Extracting a byte is faster than a bit-field
147
+ * (2) It properly aligns copy offset so we do not need a <<8
148
+ */
149
+ static const uint16_t char_table[256] = {
150
+ 0x0001, 0x0804, 0x1001, 0x2001, 0x0002, 0x0805, 0x1002, 0x2002,
151
+ 0x0003, 0x0806, 0x1003, 0x2003, 0x0004, 0x0807, 0x1004, 0x2004,
152
+ 0x0005, 0x0808, 0x1005, 0x2005, 0x0006, 0x0809, 0x1006, 0x2006,
153
+ 0x0007, 0x080a, 0x1007, 0x2007, 0x0008, 0x080b, 0x1008, 0x2008,
154
+ 0x0009, 0x0904, 0x1009, 0x2009, 0x000a, 0x0905, 0x100a, 0x200a,
155
+ 0x000b, 0x0906, 0x100b, 0x200b, 0x000c, 0x0907, 0x100c, 0x200c,
156
+ 0x000d, 0x0908, 0x100d, 0x200d, 0x000e, 0x0909, 0x100e, 0x200e,
157
+ 0x000f, 0x090a, 0x100f, 0x200f, 0x0010, 0x090b, 0x1010, 0x2010,
158
+ 0x0011, 0x0a04, 0x1011, 0x2011, 0x0012, 0x0a05, 0x1012, 0x2012,
159
+ 0x0013, 0x0a06, 0x1013, 0x2013, 0x0014, 0x0a07, 0x1014, 0x2014,
160
+ 0x0015, 0x0a08, 0x1015, 0x2015, 0x0016, 0x0a09, 0x1016, 0x2016,
161
+ 0x0017, 0x0a0a, 0x1017, 0x2017, 0x0018, 0x0a0b, 0x1018, 0x2018,
162
+ 0x0019, 0x0b04, 0x1019, 0x2019, 0x001a, 0x0b05, 0x101a, 0x201a,
163
+ 0x001b, 0x0b06, 0x101b, 0x201b, 0x001c, 0x0b07, 0x101c, 0x201c,
164
+ 0x001d, 0x0b08, 0x101d, 0x201d, 0x001e, 0x0b09, 0x101e, 0x201e,
165
+ 0x001f, 0x0b0a, 0x101f, 0x201f, 0x0020, 0x0b0b, 0x1020, 0x2020,
166
+ 0x0021, 0x0c04, 0x1021, 0x2021, 0x0022, 0x0c05, 0x1022, 0x2022,
167
+ 0x0023, 0x0c06, 0x1023, 0x2023, 0x0024, 0x0c07, 0x1024, 0x2024,
168
+ 0x0025, 0x0c08, 0x1025, 0x2025, 0x0026, 0x0c09, 0x1026, 0x2026,
169
+ 0x0027, 0x0c0a, 0x1027, 0x2027, 0x0028, 0x0c0b, 0x1028, 0x2028,
170
+ 0x0029, 0x0d04, 0x1029, 0x2029, 0x002a, 0x0d05, 0x102a, 0x202a,
171
+ 0x002b, 0x0d06, 0x102b, 0x202b, 0x002c, 0x0d07, 0x102c, 0x202c,
172
+ 0x002d, 0x0d08, 0x102d, 0x202d, 0x002e, 0x0d09, 0x102e, 0x202e,
173
+ 0x002f, 0x0d0a, 0x102f, 0x202f, 0x0030, 0x0d0b, 0x1030, 0x2030,
174
+ 0x0031, 0x0e04, 0x1031, 0x2031, 0x0032, 0x0e05, 0x1032, 0x2032,
175
+ 0x0033, 0x0e06, 0x1033, 0x2033, 0x0034, 0x0e07, 0x1034, 0x2034,
176
+ 0x0035, 0x0e08, 0x1035, 0x2035, 0x0036, 0x0e09, 0x1036, 0x2036,
177
+ 0x0037, 0x0e0a, 0x1037, 0x2037, 0x0038, 0x0e0b, 0x1038, 0x2038,
178
+ 0x0039, 0x0f04, 0x1039, 0x2039, 0x003a, 0x0f05, 0x103a, 0x203a,
179
+ 0x003b, 0x0f06, 0x103b, 0x203b, 0x003c, 0x0f07, 0x103c, 0x203c,
180
+ 0x0801, 0x0f08, 0x103d, 0x203d, 0x1001, 0x0f09, 0x103e, 0x203e,
181
+ 0x1801, 0x0f0a, 0x103f, 0x203f, 0x2001, 0x0f0b, 0x1040, 0x2040
182
+ };
183
+
184
+ /*
185
+ * Copy "len" bytes from "src" to "op", one byte at a time. Used for
186
+ * handling COPY operations where the input and output regions may
187
+ * overlap. For example, suppose:
188
+ * src == "ab"
189
+ * op == src + 2
190
+ * len == 20
191
+ * After IncrementalCopy(src, op, len), the result will have
192
+ * eleven copies of "ab"
193
+ * ababababababababababab
194
+ * Note that this does not match the semantics of either memcpy()
195
+ * or memmove().
196
+ */
197
+ static inline void IncrementalCopy(const char *src, char *op, int len)
198
+ {
199
+ DCHECK_GT(len, 0);
200
+ do {
201
+ *op++ = *src++;
202
+ } while (--len > 0);
203
+ }
204
+
205
+ /*
206
+ * Equivalent to IncrementalCopy except that it can write up to ten extra
207
+ * bytes after the end of the copy, and that it is faster.
208
+ *
209
+ * The main part of this loop is a simple copy of eight bytes at a time until
210
+ * we've copied (at least) the requested amount of bytes. However, if op and
211
+ * src are less than eight bytes apart (indicating a repeating pattern of
212
+ * length < 8), we first need to expand the pattern in order to get the correct
213
+ * results. For instance, if the buffer looks like this, with the eight-byte
214
+ * <src> and <op> patterns marked as intervals:
215
+ *
216
+ * abxxxxxxxxxxxx
217
+ * [------] src
218
+ * [------] op
219
+ *
220
+ * a single eight-byte copy from <src> to <op> will repeat the pattern once,
221
+ * after which we can move <op> two bytes without moving <src>:
222
+ *
223
+ * ababxxxxxxxxxx
224
+ * [------] src
225
+ * [------] op
226
+ *
227
+ * and repeat the exercise until the two no longer overlap.
228
+ *
229
+ * This allows us to do very well in the special case of one single byte
230
+ * repeated many times, without taking a big hit for more general cases.
231
+ *
232
+ * The worst case of extra writing past the end of the match occurs when
233
+ * op - src == 1 and len == 1; the last copy will read from byte positions
234
+ * [0..7] and write to [4..11], whereas it was only supposed to write to
235
+ * position 1. Thus, ten excess bytes.
236
+ */
237
+ static const int kMaxIncrementCopyOverflow = 10;
238
+ static inline void IncrementalCopyFastPath(const char *src, char *op, int len)
239
+ {
240
+ while (op - src < 8) {
241
+ UnalignedCopy64(src, op);
242
+ len -= op - src;
243
+ op += op - src;
244
+ }
245
+ while (len > 0) {
246
+ UnalignedCopy64(src, op);
247
+ src += 8;
248
+ op += 8;
249
+ len -= 8;
250
+ }
251
+ }
252
+
253
+
254
+ /* A type that writes to a flat array. */
255
+ struct SnappyArrayWriter {
256
+ char *base;
257
+ char *op;
258
+ char *op_limit;
259
+ };
260
+
261
+ static inline int
262
+ SAW__AppendFastPath(struct SnappyArrayWriter *this,
263
+ const char *ip, uint32_t len)
264
+ {
265
+ char *op = this->op;
266
+ const int space_left = this->op_limit - op;
267
+ if (likely(space_left >= 16)) {
268
+ UnalignedCopy64(ip, op);
269
+ UnalignedCopy64(ip + 8, op + 8);
270
+ } else {
271
+ if (unlikely(space_left < (int32_t)len))
272
+ return CSNAPPY_E_OUTPUT_OVERRUN;
273
+ memcpy(op, ip, len);
274
+ }
275
+ this->op = op + len;
276
+ return CSNAPPY_E_OK;
277
+ }
278
+
279
+ static inline int
280
+ SAW__Append(struct SnappyArrayWriter *this,
281
+ const char *ip, uint32_t len)
282
+ {
283
+ char *op = this->op;
284
+ const int space_left = this->op_limit - op;
285
+ if (unlikely(space_left < (int32_t)len))
286
+ return CSNAPPY_E_OUTPUT_OVERRUN;
287
+ memcpy(op, ip, len);
288
+ this->op = op + len;
289
+ return CSNAPPY_E_OK;
290
+ }
291
+
292
+ static inline int
293
+ SAW__AppendFromSelf(struct SnappyArrayWriter *this,
294
+ uint32_t offset, uint32_t len)
295
+ {
296
+ char *op = this->op;
297
+ const int space_left = this->op_limit - op;
298
+ /* -1u catches offset==0 */
299
+ if (op - this->base <= offset - 1u)
300
+ return CSNAPPY_E_DATA_MALFORMED;
301
+ /* Fast path, used for the majority (70-80%) of dynamic invocations. */
302
+ if (len <= 16 && offset >= 8 && space_left >= 16) {
303
+ UnalignedCopy64(op - offset, op);
304
+ UnalignedCopy64(op - offset + 8, op + 8);
305
+ } else if (space_left >= (int32_t)(len + kMaxIncrementCopyOverflow)) {
306
+ IncrementalCopyFastPath(op - offset, op, len);
307
+ } else {
308
+ if (space_left < (int32_t)len)
309
+ return CSNAPPY_E_OUTPUT_OVERRUN;
310
+ IncrementalCopy(op - offset, op, len);
311
+ }
312
+ this->op = op + len;
313
+ return CSNAPPY_E_OK;
314
+ }
315
+
316
+ int
317
+ csnappy_decompress_noheader(
318
+ const char *src,
319
+ uint32_t src_remaining,
320
+ char *dst,
321
+ uint32_t *dst_len)
322
+ {
323
+ struct SnappyArrayWriter writer;
324
+ const char *end_minus5 = src + src_remaining - 5;
325
+ uint32_t length, trailer, opword, extra_bytes;
326
+ int ret, available;
327
+ uint8_t opcode;
328
+ char scratch[5];
329
+ writer.op = writer.base = dst;
330
+ writer.op_limit = writer.op + *dst_len;
331
+ #define LOOP_COND() \
332
+ if (unlikely(src >= end_minus5)) { \
333
+ available = end_minus5 + 5 - src; \
334
+ if (unlikely(available <= 0)) \
335
+ goto out; \
336
+ memmove(scratch, src, available); \
337
+ src = scratch; \
338
+ end_minus5 = scratch + available - 5; \
339
+ }
340
+
341
+ LOOP_COND();
342
+ for (;;) {
343
+ opcode = *(const uint8_t *)src++;
344
+ if (opcode & 0x3) {
345
+ opword = char_table[opcode];
346
+ extra_bytes = opword >> 11;
347
+ trailer = get_unaligned_le(src, extra_bytes);
348
+ length = opword & 0xff;
349
+ src += extra_bytes;
350
+ trailer += opword & 0x700;
351
+ ret = SAW__AppendFromSelf(&writer, trailer, length);
352
+ if (ret < 0)
353
+ return ret;
354
+ LOOP_COND();
355
+ } else {
356
+ length = (opcode >> 2) + 1;
357
+ available = end_minus5 + 5 - src;
358
+ if (length <= 16 && available >= 16) {
359
+ if ((ret = SAW__AppendFastPath(&writer, src, length)) < 0)
360
+ return ret;
361
+ src += length;
362
+ LOOP_COND();
363
+ continue;
364
+ }
365
+ if (unlikely(length > 60)) {
366
+ extra_bytes = length - 60;
367
+ length = get_unaligned_le(src, extra_bytes) + 1;
368
+ src += extra_bytes;
369
+ available = end_minus5 + 5 - src;
370
+ }
371
+ if (unlikely(available < (int32_t)length))
372
+ return CSNAPPY_E_DATA_MALFORMED;
373
+ ret = SAW__Append(&writer, src, length);
374
+ if (ret < 0)
375
+ return ret;
376
+ src += length;
377
+ LOOP_COND();
378
+ }
379
+ }
380
+ #undef LOOP_COND
381
+ out:
382
+ *dst_len = writer.op - writer.base;
383
+ return CSNAPPY_E_OK;
384
+ }
385
+ #endif /* optimized for unaligned arch */
386
+
387
+ #if defined(__KERNEL__) && !defined(STATIC)
388
+ EXPORT_SYMBOL(csnappy_decompress_noheader);
389
+ #endif
390
+
391
+ int
392
+ csnappy_decompress(
393
+ const char *src,
394
+ uint32_t src_len,
395
+ char *dst,
396
+ uint32_t dst_len)
397
+ {
398
+ int n;
399
+ uint32_t olen = 0;
400
+ /* Read uncompressed length from the front of the compressed input */
401
+ n = csnappy_get_uncompressed_length(src, src_len, &olen);
402
+ if (unlikely(n < CSNAPPY_E_OK))
403
+ return n;
404
+ /* Protect against possible DoS attack */
405
+ if (unlikely(olen > dst_len))
406
+ return CSNAPPY_E_OUTPUT_INSUF;
407
+ return csnappy_decompress_noheader(src + n, src_len - n, dst, &olen);
408
+ }
409
+ #if defined(__KERNEL__) && !defined(STATIC)
410
+ EXPORT_SYMBOL(csnappy_decompress);
411
+
412
+ MODULE_LICENSE("BSD");
413
+ MODULE_DESCRIPTION("Snappy Decompressor");
414
+ #endif
@@ -0,0 +1,147 @@
1
+ /*
2
+ Copyright 2011 Google Inc. All Rights Reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are
6
+ met:
7
+
8
+ * Redistributions of source code must retain the above copyright
9
+ notice, this list of conditions and the following disclaimer.
10
+ * Redistributions in binary form must reproduce the above
11
+ copyright notice, this list of conditions and the following disclaimer
12
+ in the documentation and/or other materials provided with the
13
+ distribution.
14
+ * Neither the name of Google Inc. nor the names of its
15
+ contributors may be used to endorse or promote products derived from
16
+ this software without specific prior written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+
30
+ Various stubs for the open-source version of Snappy.
31
+
32
+ File modified for the Linux Kernel by
33
+ Zeev Tarantov <zeev.tarantov@gmail.com>
34
+ */
35
+
36
+ #ifndef CSNAPPY_INTERNAL_H_
37
+ #define CSNAPPY_INTERNAL_H_
38
+
39
+ #ifndef __KERNEL__
40
+ #include "csnappy_internal_userspace.h"
41
+ #include <string.h>
42
+ #else
43
+
44
+ #include <linux/types.h>
45
+ #include <linux/string.h>
46
+ #include <linux/compiler.h>
47
+ #include <asm/byteorder.h>
48
+ #include <asm/unaligned.h>
49
+
50
+ #if (defined(__LITTLE_ENDIAN) && defined(__BIG_ENDIAN)) || \
51
+ (!defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN))
52
+ #error either __LITTLE_ENDIAN or __BIG_ENDIAN must be defined
53
+ #endif
54
+ #if defined(__LITTLE_ENDIAN)
55
+ #define __BYTE_ORDER __LITTLE_ENDIAN
56
+ #else
57
+ #define __BYTE_ORDER __BIG_ENDIAN
58
+ #endif
59
+
60
+ #ifdef DEBUG
61
+ #define DCHECK(cond) if (!(cond)) \
62
+ printk(KERN_DEBUG "assert failed @ %s:%i\n", \
63
+ __FILE__, __LINE__)
64
+ #else
65
+ #define DCHECK(cond)
66
+ #endif
67
+
68
+ #define UNALIGNED_LOAD16(_p) get_unaligned((const uint16_t *)(_p))
69
+ #define UNALIGNED_LOAD32(_p) get_unaligned((const uint32_t *)(_p))
70
+ #define UNALIGNED_LOAD64(_p) get_unaligned((const uint64_t *)(_p))
71
+ #define UNALIGNED_STORE16(_p, _val) put_unaligned((_val), (uint16_t *)(_p))
72
+ #define UNALIGNED_STORE32(_p, _val) put_unaligned((_val), (uint32_t *)(_p))
73
+ #define UNALIGNED_STORE64(_p, _val) put_unaligned((_val), (uint64_t *)(_p))
74
+
75
+ #define FindLSBSetNonZero(n) __builtin_ctz(n)
76
+ #define FindLSBSetNonZero64(n) __builtin_ctzll(n)
77
+
78
+ #endif /* __KERNEL__ */
79
+
80
+ #define ARCH_ARM_HAVE_UNALIGNED \
81
+ defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) || defined(__ARMV6__) || \
82
+ defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__)
83
+
84
+ static inline void UnalignedCopy64(const void *src, void *dst) {
85
+ #if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || ARCH_ARM_HAVE_UNALIGNED
86
+ if ((sizeof(void *) == 8) || (sizeof(long) == 8)) {
87
+ UNALIGNED_STORE64(dst, UNALIGNED_LOAD64(src));
88
+ } else {
89
+ /* This can be more efficient than UNALIGNED_LOAD64 + UNALIGNED_STORE64
90
+ on some platforms, in particular ARM. */
91
+ const uint8_t *src_bytep = (const uint8_t *)src;
92
+ uint8_t *dst_bytep = (uint8_t *)dst;
93
+
94
+ UNALIGNED_STORE32(dst_bytep, UNALIGNED_LOAD32(src_bytep));
95
+ UNALIGNED_STORE32(dst_bytep + 4, UNALIGNED_LOAD32(src_bytep + 4));
96
+ }
97
+ #else
98
+ const uint8_t *src_bytep = (const uint8_t *)src;
99
+ uint8_t *dst_bytep = (uint8_t *)dst;
100
+ dst_bytep[0] = src_bytep[0];
101
+ dst_bytep[1] = src_bytep[1];
102
+ dst_bytep[2] = src_bytep[2];
103
+ dst_bytep[3] = src_bytep[3];
104
+ dst_bytep[4] = src_bytep[4];
105
+ dst_bytep[5] = src_bytep[5];
106
+ dst_bytep[6] = src_bytep[6];
107
+ dst_bytep[7] = src_bytep[7];
108
+ #endif
109
+ }
110
+
111
+ #if defined(__arm__)
112
+ #if ARCH_ARM_HAVE_UNALIGNED
113
+ static inline uint32_t get_unaligned_le(const void *p, uint32_t n)
114
+ {
115
+ uint32_t wordmask = (1U << (8 * n)) - 1;
116
+ return get_unaligned_le32(p) & wordmask;
117
+ }
118
+ #else
119
+ extern uint32_t get_unaligned_le_armv5(const void *p, uint32_t n);
120
+ #define get_unaligned_le get_unaligned_le_armv5
121
+ #endif
122
+ #else
123
+ static inline uint32_t get_unaligned_le(const void *p, uint32_t n)
124
+ {
125
+ /* Mapping from i in range [0,4] to a mask to extract the bottom 8*i bits */
126
+ static const uint32_t wordmask[] = {
127
+ 0u, 0xffu, 0xffffu, 0xffffffu, 0xffffffffu
128
+ };
129
+ return get_unaligned_le32(p) & wordmask[n];
130
+ }
131
+ #endif
132
+
133
+ #define DCHECK_EQ(a, b) DCHECK(((a) == (b)))
134
+ #define DCHECK_NE(a, b) DCHECK(((a) != (b)))
135
+ #define DCHECK_GT(a, b) DCHECK(((a) > (b)))
136
+ #define DCHECK_GE(a, b) DCHECK(((a) >= (b)))
137
+ #define DCHECK_LT(a, b) DCHECK(((a) < (b)))
138
+ #define DCHECK_LE(a, b) DCHECK(((a) <= (b)))
139
+
140
+ enum {
141
+ LITERAL = 0,
142
+ COPY_1_BYTE_OFFSET = 1, /* 3 bit length + 3 bits of offset in opcode */
143
+ COPY_2_BYTE_OFFSET = 2,
144
+ COPY_4_BYTE_OFFSET = 3
145
+ };
146
+
147
+ #endif /* CSNAPPY_INTERNAL_H_ */