File Coverage

snappy/csnappy_internal_userspace.h
Criterion Covered Total %
statement 2 2 100.0
branch n/a
condition n/a
subroutine n/a
pod n/a
total 2 2 100.0


line stmt bran cond sub pod time code
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 by
33             Zeev Tarantov
34              
35             File modified for Sereal by
36             Steffen Mueller
37             Yves Orton
38              
39             */
40              
41             #ifndef CSNAPPY_INTERNAL_USERSPACE_H_
42             #define CSNAPPY_INTERNAL_USERSPACE_H_
43              
44             /*note the original version of this file checked for MS version, but MS will *never* support
45             * anything but C89, so the version check is bogus. */
46             #if defined(_MSC_VER)
47             typedef unsigned __int8 uint8_t;
48             typedef unsigned __int16 uint16_t;
49             typedef unsigned __int32 uint32_t;
50             typedef unsigned __int64 uint64_t;
51             typedef __int32 int32_t; /* Sereal specific change, see csnappy_decompress.c(271) : error C2065: 'int32_t' : undeclared identifier */
52             /* the following define is Sereal specific, as MS C89 compilers do not know about "inline" */
53             #define inline __inline
54             #ifdef _M_X64
55             # define __x86_64__
56             # define __x86_64
57             # define __amd64__
58             # define __amd64
59             #endif
60             #ifdef _M_IX86
61             # define __i386__
62             # define __i386
63             # define i386
64             # define _X86_
65             #endif
66             #ifdef _M_IA64
67             # define __ia64__
68             # define __ia64
69             # define __IA64__
70             # define __itanium__
71             #endif
72              
73             #else
74              
75             #if defined(__SUNPRO_C) || defined(_AIX)
76             # include
77             #else
78             # include
79             #endif
80              
81             #endif
82              
83             #ifdef _GNU_SOURCE
84             #define min(x, y) (__extension__ ({ \
85             typeof(x) _min1 = (x); \
86             typeof(y) _min2 = (y); \
87             (void) (&_min1 == &_min2); \
88             _min1 < _min2 ? _min1 : _min2; }))
89             #else
90             #define min(x, y) (((x) < (y)) ? (x) : (y))
91             #endif
92              
93             /* Static prediction hints. */
94             #ifndef __GNUC__
95             #define __builtin_expect(a,b) a
96             #endif
97             #define likely(x) __builtin_expect(!!(x), 1)
98             #define unlikely(x) __builtin_expect(!!(x), 0)
99              
100              
101             #ifdef DEBUG
102             #include
103             #define DCHECK(cond) assert(cond)
104             #else
105             #define DCHECK(cond)
106             #endif
107              
108             #include "csnappy_compat.h"
109              
110             /*
111             Uses code from http://code.google.com/p/exfat/source/browse/trunk/libexfat/byteorder.h
112             with 3-clause BSD license instead of GPL, with permission from:
113             Andrew Nayenko
114             Albert Lee
115             */
116             #if defined(_MSC_VER)
117              
118             #include
119             #define bswap_16(x) _byteswap_ushort(x)
120             #define bswap_32(x) _byteswap_ulong(x)
121             #define bswap_64(x) _byteswap_uint64(x)
122             #define __BIG_ENDIAN 4321
123             #define __LITTLE_ENDIAN 1234
124             #define __BYTE_ORDER LITTLE_ENDIAN
125              
126             #elif defined(_AIX)
127              
128             #include
129             #define __LITTLE_ENDIAN LITTLE_ENDIAN
130             #define __BIG_ENDIAN BIG_ENDIAN
131             #define __BYTE_ORDER __BIG_ENDIAN
132              
133             #elif defined(__APPLE__)
134              
135             #include
136             #include
137             #define bswap_16(x) OSSwapInt16(x)
138             #define bswap_32(x) OSSwapInt32(x)
139             #define bswap_64(x) OSSwapInt64(x)
140             #define __BYTE_ORDER BYTE_ORDER
141             #define __LITTLE_ENDIAN LITTLE_ENDIAN
142             #define __BIG_ENDIAN BIG_ENDIAN
143              
144             #elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__)
145              
146             #include
147             #define bswap_16(x) bswap16(x)
148             #define bswap_32(x) bswap32(x)
149             #define bswap_64(x) bswap64(x)
150             #define __BYTE_ORDER _BYTE_ORDER
151             #define __LITTLE_ENDIAN _LITTLE_ENDIAN
152             #define __BIG_ENDIAN _BIG_ENDIAN
153              
154             #elif defined(__OpenBSD__)
155              
156             #include
157             #define bswap_16(x) swap16(x)
158             #define bswap_32(x) swap32(x)
159             #define bswap_64(x) swap64(x)
160             #define __BYTE_ORDER _BYTE_ORDER
161             #define __LITTLE_ENDIAN _LITTLE_ENDIAN
162             #define __BIG_ENDIAN _BIG_ENDIAN
163              
164             #elif defined(__MINGW32__)
165             #include
166             #define __BYTE_ORDER BYTE_ORDER
167             #define __LITTLE_ENDIAN LITTLE_ENDIAN
168             #define __BIG_ENDIAN BIG_ENDIAN
169              
170              
171             #elif defined(__sun)
172              
173             #include
174             #define bswap_16(x) BSWAP_16(x)
175             #define bswap_32(x) BSWAP_32(x)
176             #define bswap_64(x) BSWAP_64(x)
177             #define __LITTLE_ENDIAN 1234
178             #define __BIG_ENDIAN 4321
179             #ifdef _LITTLE_ENDIAN
180             #define __BYTE_ORDER __LITTLE_ENDIAN
181             #else
182             #define __BYTE_ORDER __BIG_ENDIAN
183             #endif
184              
185             #elif defined(__hpux)
186              
187             #ifdef __LP64__
188             #define __LITTLE_ENDIAN 12345678
189             #define __BIG_ENDIAN 87654321
190             #define int64_t long
191             #else
192             #define __LITTLE_ENDIAN 1234
193             #define __BIG_ENDIAN 4321
194             #define int64_t long long
195             #endif
196              
197             #define __BYTE_ORDER __BIG_ENDIAN /* HP-UX always */
198             #define int32_t int
199             #define int16_t short
200              
201             #define __SNAPPY_STRICT_ALIGN
202              
203             #elif defined(__s390x__) || defined(__zarch__) || defined(__SYSC_ZARCH__)
204              
205             #ifndef __BIG_ENDIAN
206             #define __BIG_ENDIAN 87654321
207             #endif
208             #ifndef __LITTLE_ENDIAN
209             #define __LITTLE_ENDIAN 12345678
210             #endif
211             #ifndef __BYTE_ORDER
212             #define __BYTE_ORDER __BIG_ENDIAN
213             #endif
214              
215             #define __SNAPPY_STRICT_ALIGN
216              
217             #elif defined(__GNUC__) || defined(__ANDROID__) || defined(__CYGWIN__)
218              
219             #include
220             #include
221              
222             #endif
223              
224             #ifndef bswap_16
225             #define bswap_16(x) \
226             (((uint16_t)(x) & 0xFF00) >> 8 | \
227             ((uint16_t)(x) & 0x00FF) << 8)
228             #endif
229              
230             #ifndef bswap_32
231             #define bswap_32(x) \
232             (((uint32_t)(x) & 0xFF000000) >> 24 | \
233             ((uint32_t)(x) & 0x00FF0000) >> 8 | \
234             ((uint32_t)(x) & 0x0000FF00) << 8 | \
235             ((uint32_t)(x) & 0x000000FF) << 24)
236             #endif
237              
238             #ifndef bswap_64
239             #define bswap_64(x) \
240             (((uint64_t)(x) & 0xFF00000000000000) >> 56 | \
241             ((uint64_t)(x) & 0x00FF000000000000) >> 40 | \
242             ((uint64_t)(x) & 0x0000FF0000000000) >> 24 | \
243             ((uint64_t)(x) & 0x000000FF00000000) >> 8 | \
244             ((uint64_t)(x) & 0x00000000FF000000) << 8 | \
245             ((uint64_t)(x) & 0x0000000000FF0000) << 24 | \
246             ((uint64_t)(x) & 0x000000000000FF00) << 40 | \
247             ((uint64_t)(x) & 0x00000000000000FF) << 56)
248             #endif
249              
250              
251             /* Potentially unaligned loads and stores. */
252              
253             #if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__)
254             #if defined(__GNUC__)
255             typedef uint16_t my_uint16_t __attribute__((aligned(1)));
256             typedef uint32_t my_uint32_t __attribute__((aligned(1)));
257             typedef uint64_t my_uint64_t __attribute__((aligned(1)));
258             #else
259             typedef uint16_t my_uint16_t;
260             typedef uint32_t my_uint32_t;
261             typedef uint64_t my_uint64_t;
262             #endif
263              
264             #define UNALIGNED_LOAD16(_p) (*(const my_uint16_t*)(_p))
265             #define UNALIGNED_LOAD32(_p) (*(const my_uint32_t*)(_p))
266             #define UNALIGNED_LOAD64(_p) (*(const my_uint64_t*)(_p))
267              
268             #define UNALIGNED_STORE16(_p, _val) (*(my_uint16_t*)(_p) = (_val))
269             #define UNALIGNED_STORE32(_p, _val) (*(my_uint32_t*)(_p) = (_val))
270             #define UNALIGNED_STORE64(_p, _val) (*(my_uint64_t*)(_p) = (_val))
271              
272             #elif defined(__arm__) && \
273             !defined(__ARM_ARCH_4__) && \
274             !defined(__ARM_ARCH_4T__) && /* http://wiki.debian.org/ArmEabiPort#Choice_of_minimum_CPU */ \
275             !defined(__MARM_ARMV4__) && \
276             !defined(_ARMV4I_) && \
277             !defined(__ARM_ARCH_5__) && \
278             !defined(__ARM_ARCH_5T__) && \
279             !defined(__ARM_ARCH_5E__) && \
280             !defined(__ARM_ARCH_5TE__) && \
281             !defined(__ARM_ARCH_5TEJ__) && \
282             !defined(__MARM_ARMV5__)
283              
284             #define UNALIGNED_LOAD16(_p) (*(const uint16_t*)(_p))
285             #define UNALIGNED_LOAD32(_p) (*(const uint32_t*)(_p))
286             #define UNALIGNED_STORE16(_p, _val) (*(uint16_t*)(_p) = (_val))
287             #define UNALIGNED_STORE32(_p, _val) (*(uint32_t*)(_p) = (_val))
288              
289             #pragma pack(1)
290             struct una_u64 { uint64_t x; };
291             #pragma pack()
292              
293             static INLINE uint64_t UNALIGNED_LOAD64(const void *p)
294             {
295             const struct una_u64 *ptr = (const struct una_u64 *)p;
296             return ptr->x;
297             }
298              
299             static INLINE void UNALIGNED_STORE64(void *p, uint64_t v)
300             {
301             struct una_u64 *ptr = (struct una_u64 *)p;
302             ptr->x = v;
303             }
304              
305             #elif defined(__SNAPPY_STRICT_ALIGN) || defined(__sparc) || defined(__sparc__) /* strict architectures */
306              
307             /* For these platforms, there really are no unaligned loads/stores.
308             * Read/write everything as uint8_t. Smart compilers might recognize
309             * these patterns and generate something smart. */
310              
311             /* Possible future enhancement: see if the ptr is evenly divisible
312             * (as uintNN_t) by 2/4/8, and if so, do the cast-as-uintNN_t-ptr-
313             * and-deref-as-uintNN_t. Balancing act: adding the branch
314             * will slow things down, while reading/writing aligned might speed
315             * things up. */
316              
317             #if __BYTE_ORDER == __BIG_ENDIAN
318              
319             static INLINE uint16_t UNALIGNED_LOAD16(const void *p)
320             {
321             return
322             (uint16_t)(((uint8_t*)p)[0]) << 8 |
323             (uint16_t)(((uint8_t*)p)[1]);
324             }
325              
326             static INLINE uint32_t UNALIGNED_LOAD32(const void *p)
327             {
328             return
329             (uint32_t)(((uint8_t*)p)[0]) << 24 |
330             (uint32_t)(((uint8_t*)p)[1]) << 16 |
331             (uint32_t)(((uint8_t*)p)[2]) << 8 |
332             (uint32_t)(((uint8_t*)p)[3]);
333             }
334              
335             static INLINE uint64_t UNALIGNED_LOAD64(const void *p)
336             {
337             return
338             (uint64_t)((uint8_t*)p)[0] << 56 |
339             (uint64_t)((uint8_t*)p)[1] << 48 |
340             (uint64_t)((uint8_t*)p)[2] << 40 |
341             (uint64_t)((uint8_t*)p)[3] << 32 |
342             (uint64_t)((uint8_t*)p)[4] << 24 |
343             (uint64_t)((uint8_t*)p)[5] << 16 |
344             (uint64_t)((uint8_t*)p)[5] << 8 |
345             (uint64_t)((uint8_t*)p)[7];
346             }
347              
348             static INLINE void UNALIGNED_STORE16(void *p, uint16_t v)
349             {
350             uint8_t* s = (uint8_t*)p;
351             s[0] = (v & 0xFF00) >> 8;
352             s[1] = (v & 0x00FF);
353             }
354              
355             static INLINE void UNALIGNED_STORE32(void *p, uint32_t v)
356             {
357             uint8_t* s = (uint8_t*)p;
358             s[0] = (v & 0xFF000000) >> 24;
359             s[1] = (v & 0x00FF0000) >> 16;
360             s[2] = (v & 0x0000FF00) >> 8;
361             s[3] = (v & 0x000000FF);
362             }
363              
364             static INLINE void UNALIGNED_STORE64(void *p, uint64_t v)
365             {
366             uint8_t* s = (uint8_t*)p;
367             s[0] = (v & 0xFF00000000000000) >> 56;
368             s[1] = (v & 0x00FF000000000000) >> 48;
369             s[2] = (v & 0x0000FF0000000000) >> 40;
370             s[3] = (v & 0x000000FF00000000) >> 32;
371             s[4] = (v & 0x00000000FF000000) >> 24;
372             s[5] = (v & 0x0000000000FF0000) >> 16;
373             s[6] = (v & 0x000000000000FF00) >> 8;
374             s[7] = (v & 0x00000000000000FF);
375             }
376              
377             #endif /* #if __BYTE_ORDER == __BIG_ENDIAN */
378              
379             #if __BYTE_ORDER == __LITTLE_ENDIAN
380              
381             static INLINE uint16_t UNALIGNED_LOAD16(const void *p)
382             {
383             return
384             (uint16_t)(((uint8_t*)p)[1]) << 8) |
385             (uint16_t)(((uint8_t*)p)[0]);
386             }
387              
388             static INLINE uint32_t UNALIGNED_LOAD32(const void *p)
389             {
390             return
391             (uint32_t)(((uint8_t*)p)[3]) << 24 |
392             (uint32_t)(((uint8_t*)p)[2]) << 16 |
393             (uint32_t)(((uint8_t*)p)[1]) << 8 |
394             (uint32_t)(((uint8_t*)p)[0]);
395             }
396              
397             static INLINE uint64_t UNALIGNED_LOAD64(const void *p)
398             {
399             return
400             (uint64_t)(((uint8_t*)p)[7]) << 56 |
401             (uint64_t)(((uint8_t*)p)[6]) << 48 |
402             (uint64_t)(((uint8_t*)p)[5]) << 40 |
403             (uint64_t)(((uint8_t*)p)[4]) << 32 |
404             (uint64_t)(((uint8_t*)p)[3]) << 24 |
405             (uint64_t)(((uint8_t*)p)[2]) << 16 |
406             (uint64_t)(((uint8_t*)p)[1]) << 8 |
407             (uint64_t)(((uint8_t*)p)[0]);
408             }
409              
410             static INLINE void UNALIGNED_STORE16(void *p, uint16_t v)
411             {
412             uint8_t* s = (uint8_t*)p;
413             s[1] = (v & 0xFF00) >> 8;
414             s[0] = (v & 0x00FF);
415             }
416              
417             static INLINE void UNALIGNED_STORE32(void *p, uint32_t v)
418             {
419             uint8_t* s = (uint8_t*)p;
420             s[3] = (v & 0xFF000000) >> 24;
421             s[2] = (v & 0x00FF0000) >> 16;
422             s[1] = (v & 0x0000FF00) >> 8;
423             s[0] = (v & 0x000000FF);
424             }
425              
426             static INLINE void UNALIGNED_STORE64(void *p, uint64_t v)
427             {
428             uint8_t* s = (uint8_t*)p;
429             s[7] = (v & 0xFF00000000000000) >> 56;
430             s[6] = (v & 0x00FF000000000000) >> 48;
431             s[5] = (v & 0x0000FF0000000000) >> 40;
432             s[4] = (v & 0x000000FF00000000) >> 32;
433             s[3] = (v & 0x00000000FF000000) >> 24;
434             s[2] = (v & 0x0000000000FF0000) >> 16;
435             s[1] = (v & 0x000000000000FF00) >> 8;
436             s[0] = (v & 0x00000000000000FF);
437             }
438              
439             #endif /* #if __BYTE_ORDER == __LITTLE_ENDIAN */
440              
441             #else /* !(x86 || powerpc) && !(arm && !(old arm architectures)) */
442              
443             /* pragma pack is available in gcc (though originally apparently by
444             * Microsoft) and in some other compilers (probably inspired by either
445             * the two big ones), but there is no good portable way to detect
446             * whether it's supported. The bad news: on platforms where it's not
447             * supported (unsupported pragmas are ignored) but which do require
448             * strict alignment, the below pragma pack trickery will fail.
449             * Therefore this option is the last and the default, and the platforms
450             * requiring strict alignment are detected earlier. */
451              
452             #pragma pack(1)
453             struct una_u16 { uint16_t x; };
454             struct una_u32 { uint32_t x; };
455             struct una_u64 { uint64_t x; };
456             #pragma pack()
457              
458             static INLINE uint16_t UNALIGNED_LOAD16(const void *p)
459             {
460             const struct una_u16 *ptr = (const struct una_u16 *)p;
461             return ptr->x;
462             }
463              
464             static INLINE uint32_t UNALIGNED_LOAD32(const void *p)
465             {
466             const struct una_u32 *ptr = (const struct una_u32 *)p;
467             return ptr->x;
468             }
469              
470             static INLINE uint64_t UNALIGNED_LOAD64(const void *p)
471             {
472             const struct una_u64 *ptr = (const struct una_u64 *)p;
473             return ptr->x;
474             }
475              
476             static INLINE void UNALIGNED_STORE16(void *p, uint16_t v)
477             {
478             struct una_u16 *ptr = (struct una_u16 *)p;
479             ptr->x = v;
480             }
481              
482             static INLINE void UNALIGNED_STORE32(void *p, uint32_t v)
483             {
484             struct una_u32 *ptr = (struct una_u32 *)p;
485             ptr->x = v;
486             }
487              
488             static INLINE void UNALIGNED_STORE64(void *p, uint64_t v)
489             {
490             struct una_u64 *ptr = (struct una_u64 *)p;
491             ptr->x = v;
492             }
493              
494             #endif /* defining UNALIGNED_LOADNN and UNALIGNED_STORENN */
495              
496              
497             #if __BYTE_ORDER == __LITTLE_ENDIAN
498             #define get_unaligned_le32(p) UNALIGNED_LOAD32(p)
499             #define put_unaligned_le16(v, p) UNALIGNED_STORE16(p, v)
500             #elif __BYTE_ORDER == __BIG_ENDIAN
501             static INLINE uint32_t get_unaligned_le32(const void *p)
502             {
503             return bswap_32(UNALIGNED_LOAD32(p));
504             }
505             static INLINE void put_unaligned_le16(uint16_t val, void *p)
506             {
507             UNALIGNED_STORE16(p, bswap_16(val));
508             }
509             #else
510             static INLINE uint32_t get_unaligned_le32(const void *p)
511             {
512             const uint8_t *b = (const uint8_t *)p;
513             return b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
514             }
515             static INLINE void put_unaligned_le16(uint16_t val, void *p)
516             {
517             uint8_t *b = (uint8_t *)p;
518             b[0] = val & 255;
519             b[1] = val >> 8;
520             }
521             #endif
522              
523              
524             #if defined(HAVE_BUILTIN_CTZ)
525              
526             static INLINE int FindLSBSetNonZero(uint32_t n)
527             {
528             return __builtin_ctz(n);
529             }
530              
531 76895           static INLINE int FindLSBSetNonZero64(uint64_t n)
532             {
533 76895           return __builtin_ctzll(n);
534             }
535              
536             #else /* Portable versions. */
537              
538             static INLINE int FindLSBSetNonZero(uint32_t n)
539             {
540             int rc = 31, i, shift;
541             uint32_t x;
542             for (i = 4, shift = 1 << 4; i >= 0; --i) {
543             x = n << shift;
544             if (x != 0) {
545             n = x;
546             rc -= shift;
547             }
548             shift >>= 1;
549             }
550             return rc;
551             }
552              
553             /* FindLSBSetNonZero64() is defined in terms of FindLSBSetNonZero(). */
554             static INLINE int FindLSBSetNonZero64(uint64_t n)
555             {
556             const uint32_t bottombits = (uint32_t)n;
557             if (bottombits == 0) {
558             /* Bottom bits are zero, so scan in top bits */
559             return 32 + FindLSBSetNonZero((uint32_t)(n >> 32));
560             } else {
561             return FindLSBSetNonZero(bottombits);
562             }
563             }
564              
565             #endif /* End portable versions. */
566              
567             #endif /* CSNAPPY_INTERNAL_USERSPACE_H_ */