LCOV - code coverage report
Current view: top level - pression/compressor/zstd/lib/common - mem.h (source / functions) Hit Total Coverage
Test: Pression Lines: 56 77 72.7 %
Date: 2016-12-06 05:44:58 Functions: 20 23 87.0 %

          Line data    Source code
       1             : /**
       2             :  * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
       3             :  * All rights reserved.
       4             :  *
       5             :  * This source code is licensed under the BSD-style license found in the
       6             :  * LICENSE file in the root directory of this source tree. An additional grant
       7             :  * of patent rights can be found in the PATENTS file in the same directory.
       8             :  */
       9             : 
      10             : #ifndef MEM_H_MODULE
      11             : #define MEM_H_MODULE
      12             : 
      13             : #if defined (__cplusplus)
      14             : extern "C" {
      15             : #endif
      16             : 
      17             : /*-****************************************
      18             : *  Dependencies
      19             : ******************************************/
      20             : #include <stddef.h>     /* size_t, ptrdiff_t */
      21             : #include <string.h>     /* memcpy */
      22             : 
      23             : 
      24             : /*-****************************************
      25             : *  Compiler specifics
      26             : ******************************************/
      27             : #if defined(_MSC_VER)   /* Visual Studio */
      28             : #   include <stdlib.h>  /* _byteswap_ulong */
      29             : #   include <intrin.h>  /* _byteswap_* */
      30             : #endif
      31             : #if defined(__GNUC__)
      32             : #  define MEM_STATIC static __inline __attribute__((unused))
      33             : #elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
      34             : #  define MEM_STATIC static inline
      35             : #elif defined(_MSC_VER)
      36             : #  define MEM_STATIC static __inline
      37             : #else
      38             : #  define MEM_STATIC static  /* this version may generate warnings for unused static functions; disable the relevant warning */
      39             : #endif
      40             : 
      41             : /* code only tested on 32 and 64 bits systems */
      42             : #define MEM_STATIC_ASSERT(c)   { enum { XXH_static_assert = 1/(int)(!!(c)) }; }
      43             : MEM_STATIC void MEM_check(void) { MEM_STATIC_ASSERT((sizeof(size_t)==4) || (sizeof(size_t)==8)); }
      44             : 
      45             : 
      46             : /*-**************************************************************
      47             : *  Basic Types
      48             : *****************************************************************/
      49             : #if  !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
      50             : # include <stdint.h>
      51             :   typedef  uint8_t BYTE;
      52             :   typedef uint16_t U16;
      53             :   typedef  int16_t S16;
      54             :   typedef uint32_t U32;
      55             :   typedef  int32_t S32;
      56             :   typedef uint64_t U64;
      57             :   typedef  int64_t S64;
      58             : #else
      59             :   typedef unsigned char       BYTE;
      60             :   typedef unsigned short      U16;
      61             :   typedef   signed short      S16;
      62             :   typedef unsigned int        U32;
      63             :   typedef   signed int        S32;
      64             :   typedef unsigned long long  U64;
      65             :   typedef   signed long long  S64;
      66             : #endif
      67             : 
      68             : 
      69             : /*-**************************************************************
      70             : *  Memory I/O
      71             : *****************************************************************/
      72             : /* MEM_FORCE_MEMORY_ACCESS :
      73             :  * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.
      74             :  * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.
      75             :  * The below switch allow to select different access method for improved performance.
      76             :  * Method 0 (default) : use `memcpy()`. Safe and portable.
      77             :  * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).
      78             :  *            This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.
      79             :  * Method 2 : direct access. This method is portable but violate C standard.
      80             :  *            It can generate buggy code on targets depending on alignment.
      81             :  *            In some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)
      82             :  * See http://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details.
      83             :  * Prefer these methods in priority order (0 > 1 > 2)
      84             :  */
      85             : #ifndef MEM_FORCE_MEMORY_ACCESS   /* can be defined externally, on command line for example */
      86             : #  if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) )
      87             : #    define MEM_FORCE_MEMORY_ACCESS 2
      88             : #  elif defined(__INTEL_COMPILER) /*|| defined(_MSC_VER)*/ || \
      89             :   (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) ))
      90             : #    define MEM_FORCE_MEMORY_ACCESS 1
      91             : #  endif
      92             : #endif
      93             : 
      94   171323782 : MEM_STATIC unsigned MEM_32bits(void) { return sizeof(size_t)==4; }
      95    98300662 : MEM_STATIC unsigned MEM_64bits(void) { return sizeof(size_t)==8; }
      96             : 
      97   165732980 : MEM_STATIC unsigned MEM_isLittleEndian(void)
      98             : {
      99   165732980 :     const union { U32 u; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental  */
     100   165732980 :     return one.c[0];
     101             : }
     102             : 
     103             : #if defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==2)
     104             : 
     105             : /* violates C standard, by lying on structure alignment.
     106             : Only use if no other choice to achieve best performance on target platform */
     107             : MEM_STATIC U16 MEM_read16(const void* memPtr) { return *(const U16*) memPtr; }
     108             : MEM_STATIC U32 MEM_read32(const void* memPtr) { return *(const U32*) memPtr; }
     109             : MEM_STATIC U64 MEM_read64(const void* memPtr) { return *(const U64*) memPtr; }
     110             : MEM_STATIC U64 MEM_readST(const void* memPtr) { return *(const size_t*) memPtr; }
     111             : 
     112             : MEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }
     113             : MEM_STATIC void MEM_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; }
     114             : MEM_STATIC void MEM_write64(void* memPtr, U64 value) { *(U64*)memPtr = value; }
     115             : 
     116             : #elif defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==1)
     117             : 
     118             : /* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
     119             : /* currently only defined for gcc and icc */
     120             : #if defined(_MSC_VER) || (defined(__INTEL_COMPILER) && defined(WIN32))
     121             :         __pragma( pack(push, 1) )
     122             :     typedef union { U16 u16; U32 u32; U64 u64; size_t st; } unalign;
     123             :     __pragma( pack(pop) )
     124             : #else
     125             :     typedef union { U16 u16; U32 u32; U64 u64; size_t st; } __attribute__((packed)) unalign;
     126             : #endif
     127             : 
     128             : MEM_STATIC U16 MEM_read16(const void* ptr) { return ((const unalign*)ptr)->u16; }
     129             : MEM_STATIC U32 MEM_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
     130             : MEM_STATIC U64 MEM_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }
     131             : MEM_STATIC U64 MEM_readST(const void* ptr) { return ((const unalign*)ptr)->st; }
     132             : 
     133             : MEM_STATIC void MEM_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; }
     134             : MEM_STATIC void MEM_write32(void* memPtr, U32 value) { ((unalign*)memPtr)->u32 = value; }
     135             : MEM_STATIC void MEM_write64(void* memPtr, U64 value) { ((unalign*)memPtr)->u64 = value; }
     136             : 
     137             : #else
     138             : 
     139             : /* default method, safe and standard.
     140             :    can sometimes prove slower */
     141             : 
     142       18684 : MEM_STATIC U16 MEM_read16(const void* memPtr)
     143             : {
     144       18684 :     U16 val; memcpy(&val, memPtr, sizeof(val)); return val;
     145             : }
     146             : 
     147   262785080 : MEM_STATIC U32 MEM_read32(const void* memPtr)
     148             : {
     149   262785080 :     U32 val; memcpy(&val, memPtr, sizeof(val)); return val;
     150             : }
     151             : 
     152   108230878 : MEM_STATIC U64 MEM_read64(const void* memPtr)
     153             : {
     154   108230878 :     U64 val; memcpy(&val, memPtr, sizeof(val)); return val;
     155             : }
     156             : 
     157    33794404 : MEM_STATIC size_t MEM_readST(const void* memPtr)
     158             : {
     159    33794404 :     size_t val; memcpy(&val, memPtr, sizeof(val)); return val;
     160             : }
     161             : 
     162      712244 : MEM_STATIC void MEM_write16(void* memPtr, U16 value)
     163             : {
     164      712244 :     memcpy(memPtr, &value, sizeof(value));
     165      712244 : }
     166             : 
     167        4722 : MEM_STATIC void MEM_write32(void* memPtr, U32 value)
     168             : {
     169        4722 :     memcpy(memPtr, &value, sizeof(value));
     170        4722 : }
     171             : 
     172    46148622 : MEM_STATIC void MEM_write64(void* memPtr, U64 value)
     173             : {
     174    46148622 :     memcpy(memPtr, &value, sizeof(value));
     175    46148622 : }
     176             : 
     177             : #endif /* MEM_FORCE_MEMORY_ACCESS */
     178             : 
     179           0 : MEM_STATIC U32 MEM_swap32(U32 in)
     180             : {
     181             : #if defined(_MSC_VER)     /* Visual Studio */
     182             :     return _byteswap_ulong(in);
     183             : #elif defined (__GNUC__)
     184           0 :     return __builtin_bswap32(in);
     185             : #else
     186             :     return  ((in << 24) & 0xff000000 ) |
     187             :             ((in <<  8) & 0x00ff0000 ) |
     188             :             ((in >>  8) & 0x0000ff00 ) |
     189             :             ((in >> 24) & 0x000000ff );
     190             : #endif
     191             : }
     192             : 
     193           0 : MEM_STATIC U64 MEM_swap64(U64 in)
     194             : {
     195             : #if defined(_MSC_VER)     /* Visual Studio */
     196             :     return _byteswap_uint64(in);
     197             : #elif defined (__GNUC__)
     198           0 :     return __builtin_bswap64(in);
     199             : #else
     200             :     return  ((in << 56) & 0xff00000000000000ULL) |
     201             :             ((in << 40) & 0x00ff000000000000ULL) |
     202             :             ((in << 24) & 0x0000ff0000000000ULL) |
     203             :             ((in << 8)  & 0x000000ff00000000ULL) |
     204             :             ((in >> 8)  & 0x00000000ff000000ULL) |
     205             :             ((in >> 24) & 0x0000000000ff0000ULL) |
     206             :             ((in >> 40) & 0x000000000000ff00ULL) |
     207             :             ((in >> 56) & 0x00000000000000ffULL);
     208             : #endif
     209             : }
     210             : 
     211             : MEM_STATIC size_t MEM_swapST(size_t in)
     212             : {
     213             :     if (MEM_32bits())
     214             :         return (size_t)MEM_swap32((U32)in);
     215             :     else
     216             :         return (size_t)MEM_swap64((U64)in);
     217             : }
     218             : 
     219             : /*=== Little endian r/w ===*/
     220             : 
     221        9376 : MEM_STATIC U16 MEM_readLE16(const void* memPtr)
     222             : {
     223        9376 :     if (MEM_isLittleEndian())
     224        9376 :         return MEM_read16(memPtr);
     225             :     else {
     226           0 :         const BYTE* p = (const BYTE*)memPtr;
     227           0 :         return (U16)(p[0] + (p[1]<<8));
     228             :     }
     229             : }
     230             : 
     231      712244 : MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)
     232             : {
     233      712244 :     if (MEM_isLittleEndian()) {
     234      712244 :         MEM_write16(memPtr, val);
     235             :     } else {
     236           0 :         BYTE* p = (BYTE*)memPtr;
     237           0 :         p[0] = (BYTE)val;
     238           0 :         p[1] = (BYTE)(val>>8);
     239             :     }
     240      712244 : }
     241             : 
     242        3362 : MEM_STATIC U32 MEM_readLE24(const void* memPtr)
     243             : {
     244        3362 :     return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16);
     245             : }
     246             : 
     247        2064 : MEM_STATIC void MEM_writeLE24(void* memPtr, U32 val)
     248             : {
     249        2064 :     MEM_writeLE16(memPtr, (U16)val);
     250        2064 :     ((BYTE*)memPtr)[2] = (BYTE)(val>>16);
     251        2064 : }
     252             : 
     253      131530 : MEM_STATIC U32 MEM_readLE32(const void* memPtr)
     254             : {
     255      131530 :     if (MEM_isLittleEndian())
     256      131530 :         return MEM_read32(memPtr);
     257             :     else
     258           0 :         return MEM_swap32(MEM_read32(memPtr));
     259             : }
     260             : 
     261        4722 : MEM_STATIC void MEM_writeLE32(void* memPtr, U32 val32)
     262             : {
     263        4722 :     if (MEM_isLittleEndian())
     264        4722 :         MEM_write32(memPtr, val32);
     265             :     else
     266           0 :         MEM_write32(memPtr, MEM_swap32(val32));
     267        4722 : }
     268             : 
     269   107611486 : MEM_STATIC U64 MEM_readLE64(const void* memPtr)
     270             : {
     271   107611486 :     if (MEM_isLittleEndian())
     272   107611486 :         return MEM_read64(memPtr);
     273             :     else
     274           0 :         return MEM_swap64(MEM_read64(memPtr));
     275             : }
     276             : 
     277    46148622 : MEM_STATIC void MEM_writeLE64(void* memPtr, U64 val64)
     278             : {
     279    46148622 :     if (MEM_isLittleEndian())
     280    46148622 :         MEM_write64(memPtr, val64);
     281             :     else
     282           0 :         MEM_write64(memPtr, MEM_swap64(val64));
     283    46148622 : }
     284             : 
     285    40295114 : MEM_STATIC size_t MEM_readLEST(const void* memPtr)
     286             : {
     287    40295114 :     if (MEM_32bits())
     288           0 :         return (size_t)MEM_readLE32(memPtr);
     289             :     else
     290    40295114 :         return (size_t)MEM_readLE64(memPtr);
     291             : }
     292             : 
     293    46148622 : MEM_STATIC void MEM_writeLEST(void* memPtr, size_t val)
     294             : {
     295    46148622 :     if (MEM_32bits())
     296           0 :         MEM_writeLE32(memPtr, (U32)val);
     297             :     else
     298    46148622 :         MEM_writeLE64(memPtr, (U64)val);
     299    46148622 : }
     300             : 
     301             : /*=== Big endian r/w ===*/
     302             : 
     303             : MEM_STATIC U32 MEM_readBE32(const void* memPtr)
     304             : {
     305             :     if (MEM_isLittleEndian())
     306             :         return MEM_swap32(MEM_read32(memPtr));
     307             :     else
     308             :         return MEM_read32(memPtr);
     309             : }
     310             : 
     311             : MEM_STATIC void MEM_writeBE32(void* memPtr, U32 val32)
     312             : {
     313             :     if (MEM_isLittleEndian())
     314             :         MEM_write32(memPtr, MEM_swap32(val32));
     315             :     else
     316             :         MEM_write32(memPtr, val32);
     317             : }
     318             : 
     319             : MEM_STATIC U64 MEM_readBE64(const void* memPtr)
     320             : {
     321             :     if (MEM_isLittleEndian())
     322             :         return MEM_swap64(MEM_read64(memPtr));
     323             :     else
     324             :         return MEM_read64(memPtr);
     325             : }
     326             : 
     327             : MEM_STATIC void MEM_writeBE64(void* memPtr, U64 val64)
     328             : {
     329             :     if (MEM_isLittleEndian())
     330             :         MEM_write64(memPtr, MEM_swap64(val64));
     331             :     else
     332             :         MEM_write64(memPtr, val64);
     333             : }
     334             : 
     335             : MEM_STATIC size_t MEM_readBEST(const void* memPtr)
     336             : {
     337             :     if (MEM_32bits())
     338             :         return (size_t)MEM_readBE32(memPtr);
     339             :     else
     340             :         return (size_t)MEM_readBE64(memPtr);
     341             : }
     342             : 
     343             : MEM_STATIC void MEM_writeBEST(void* memPtr, size_t val)
     344             : {
     345             :     if (MEM_32bits())
     346             :         MEM_writeBE32(memPtr, (U32)val);
     347             :     else
     348             :         MEM_writeBE64(memPtr, (U64)val);
     349             : }
     350             : 
     351             : 
     352             : /* function safe only for comparisons */
     353           0 : MEM_STATIC U32 MEM_readMINMATCH(const void* memPtr, U32 length)
     354             : {
     355           0 :     switch (length)
     356             :     {
     357             :     default :
     358           0 :     case 4 : return MEM_read32(memPtr);
     359           0 :     case 3 : if (MEM_isLittleEndian())
     360           0 :                 return MEM_read32(memPtr)<<8;
     361             :              else
     362           0 :                 return MEM_read32(memPtr)>>8;
     363             :     }
     364             : }
     365             : 
     366             : #if defined (__cplusplus)
     367             : }
     368             : #endif
     369             : 
     370             : #endif /* MEM_H_MODULE */

Generated by: LCOV version 1.11