xref: /netbsd-src/external/bsd/zstd/dist/lib/common/mem.h (revision 3117ece4fc4a4ca4489ba793710b60b0d26bab6c)
1*3117ece4Schristos /*
2*3117ece4Schristos  * Copyright (c) Meta Platforms, Inc. and affiliates.
3*3117ece4Schristos  * All rights reserved.
4*3117ece4Schristos  *
5*3117ece4Schristos  * This source code is licensed under both the BSD-style license (found in the
6*3117ece4Schristos  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7*3117ece4Schristos  * in the COPYING file in the root directory of this source tree).
8*3117ece4Schristos  * You may select, at your option, one of the above-listed licenses.
9*3117ece4Schristos  */
10*3117ece4Schristos 
11*3117ece4Schristos #ifndef MEM_H_MODULE
12*3117ece4Schristos #define MEM_H_MODULE
13*3117ece4Schristos 
14*3117ece4Schristos #if defined (__cplusplus)
15*3117ece4Schristos extern "C" {
16*3117ece4Schristos #endif
17*3117ece4Schristos 
18*3117ece4Schristos /*-****************************************
19*3117ece4Schristos *  Dependencies
20*3117ece4Schristos ******************************************/
21*3117ece4Schristos #include <stddef.h>  /* size_t, ptrdiff_t */
22*3117ece4Schristos #include "compiler.h"  /* __has_builtin */
23*3117ece4Schristos #include "debug.h"  /* DEBUG_STATIC_ASSERT */
24*3117ece4Schristos #include "zstd_deps.h"  /* ZSTD_memcpy */
25*3117ece4Schristos 
26*3117ece4Schristos 
27*3117ece4Schristos /*-****************************************
28*3117ece4Schristos *  Compiler specifics
29*3117ece4Schristos ******************************************/
30*3117ece4Schristos #if defined(_MSC_VER)   /* Visual Studio */
31*3117ece4Schristos #   include <stdlib.h>  /* _byteswap_ulong */
32*3117ece4Schristos #   include <intrin.h>  /* _byteswap_* */
33*3117ece4Schristos #endif
34*3117ece4Schristos 
35*3117ece4Schristos /*-**************************************************************
36*3117ece4Schristos *  Basic Types
37*3117ece4Schristos *****************************************************************/
38*3117ece4Schristos #if  !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
39*3117ece4Schristos #  if defined(_AIX)
40*3117ece4Schristos #    include <inttypes.h>
41*3117ece4Schristos #  else
42*3117ece4Schristos #    include <stdint.h> /* intptr_t */
43*3117ece4Schristos #  endif
44*3117ece4Schristos   typedef   uint8_t BYTE;
45*3117ece4Schristos   typedef   uint8_t U8;
46*3117ece4Schristos   typedef    int8_t S8;
47*3117ece4Schristos   typedef  uint16_t U16;
48*3117ece4Schristos   typedef   int16_t S16;
49*3117ece4Schristos   typedef  uint32_t U32;
50*3117ece4Schristos   typedef   int32_t S32;
51*3117ece4Schristos   typedef  uint64_t U64;
52*3117ece4Schristos   typedef   int64_t S64;
53*3117ece4Schristos #else
54*3117ece4Schristos # include <limits.h>
55*3117ece4Schristos #if CHAR_BIT != 8
56*3117ece4Schristos #  error "this implementation requires char to be exactly 8-bit type"
57*3117ece4Schristos #endif
58*3117ece4Schristos   typedef unsigned char      BYTE;
59*3117ece4Schristos   typedef unsigned char      U8;
60*3117ece4Schristos   typedef   signed char      S8;
61*3117ece4Schristos #if USHRT_MAX != 65535
62*3117ece4Schristos #  error "this implementation requires short to be exactly 16-bit type"
63*3117ece4Schristos #endif
64*3117ece4Schristos   typedef unsigned short      U16;
65*3117ece4Schristos   typedef   signed short      S16;
66*3117ece4Schristos #if UINT_MAX != 4294967295
67*3117ece4Schristos #  error "this implementation requires int to be exactly 32-bit type"
68*3117ece4Schristos #endif
69*3117ece4Schristos   typedef unsigned int        U32;
70*3117ece4Schristos   typedef   signed int        S32;
71*3117ece4Schristos /* note : there are no limits defined for long long type in C90.
72*3117ece4Schristos  * limits exist in C99, however, in such case, <stdint.h> is preferred */
73*3117ece4Schristos   typedef unsigned long long  U64;
74*3117ece4Schristos   typedef   signed long long  S64;
75*3117ece4Schristos #endif
76*3117ece4Schristos 
77*3117ece4Schristos 
78*3117ece4Schristos /*-**************************************************************
79*3117ece4Schristos *  Memory I/O API
80*3117ece4Schristos *****************************************************************/
81*3117ece4Schristos /*=== Static platform detection ===*/
82*3117ece4Schristos MEM_STATIC unsigned MEM_32bits(void);
83*3117ece4Schristos MEM_STATIC unsigned MEM_64bits(void);
84*3117ece4Schristos MEM_STATIC unsigned MEM_isLittleEndian(void);
85*3117ece4Schristos 
86*3117ece4Schristos /*=== Native unaligned read/write ===*/
87*3117ece4Schristos MEM_STATIC U16 MEM_read16(const void* memPtr);
88*3117ece4Schristos MEM_STATIC U32 MEM_read32(const void* memPtr);
89*3117ece4Schristos MEM_STATIC U64 MEM_read64(const void* memPtr);
90*3117ece4Schristos MEM_STATIC size_t MEM_readST(const void* memPtr);
91*3117ece4Schristos 
92*3117ece4Schristos MEM_STATIC void MEM_write16(void* memPtr, U16 value);
93*3117ece4Schristos MEM_STATIC void MEM_write32(void* memPtr, U32 value);
94*3117ece4Schristos MEM_STATIC void MEM_write64(void* memPtr, U64 value);
95*3117ece4Schristos 
96*3117ece4Schristos /*=== Little endian unaligned read/write ===*/
97*3117ece4Schristos MEM_STATIC U16 MEM_readLE16(const void* memPtr);
98*3117ece4Schristos MEM_STATIC U32 MEM_readLE24(const void* memPtr);
99*3117ece4Schristos MEM_STATIC U32 MEM_readLE32(const void* memPtr);
100*3117ece4Schristos MEM_STATIC U64 MEM_readLE64(const void* memPtr);
101*3117ece4Schristos MEM_STATIC size_t MEM_readLEST(const void* memPtr);
102*3117ece4Schristos 
103*3117ece4Schristos MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val);
104*3117ece4Schristos MEM_STATIC void MEM_writeLE24(void* memPtr, U32 val);
105*3117ece4Schristos MEM_STATIC void MEM_writeLE32(void* memPtr, U32 val32);
106*3117ece4Schristos MEM_STATIC void MEM_writeLE64(void* memPtr, U64 val64);
107*3117ece4Schristos MEM_STATIC void MEM_writeLEST(void* memPtr, size_t val);
108*3117ece4Schristos 
109*3117ece4Schristos /*=== Big endian unaligned read/write ===*/
110*3117ece4Schristos MEM_STATIC U32 MEM_readBE32(const void* memPtr);
111*3117ece4Schristos MEM_STATIC U64 MEM_readBE64(const void* memPtr);
112*3117ece4Schristos MEM_STATIC size_t MEM_readBEST(const void* memPtr);
113*3117ece4Schristos 
114*3117ece4Schristos MEM_STATIC void MEM_writeBE32(void* memPtr, U32 val32);
115*3117ece4Schristos MEM_STATIC void MEM_writeBE64(void* memPtr, U64 val64);
116*3117ece4Schristos MEM_STATIC void MEM_writeBEST(void* memPtr, size_t val);
117*3117ece4Schristos 
118*3117ece4Schristos /*=== Byteswap ===*/
119*3117ece4Schristos MEM_STATIC U32 MEM_swap32(U32 in);
120*3117ece4Schristos MEM_STATIC U64 MEM_swap64(U64 in);
121*3117ece4Schristos MEM_STATIC size_t MEM_swapST(size_t in);
122*3117ece4Schristos 
123*3117ece4Schristos 
124*3117ece4Schristos /*-**************************************************************
125*3117ece4Schristos *  Memory I/O Implementation
126*3117ece4Schristos *****************************************************************/
127*3117ece4Schristos /* MEM_FORCE_MEMORY_ACCESS : For accessing unaligned memory:
128*3117ece4Schristos  * Method 0 : always use `memcpy()`. Safe and portable.
129*3117ece4Schristos  * Method 1 : Use compiler extension to set unaligned access.
130*3117ece4Schristos  * Method 2 : direct access. This method is portable but violate C standard.
131*3117ece4Schristos  *            It can generate buggy code on targets depending on alignment.
132*3117ece4Schristos  * Default  : method 1 if supported, else method 0
133*3117ece4Schristos  */
134*3117ece4Schristos #ifndef MEM_FORCE_MEMORY_ACCESS   /* can be defined externally, on command line for example */
135*3117ece4Schristos #  ifdef __GNUC__
136*3117ece4Schristos #    define MEM_FORCE_MEMORY_ACCESS 1
137*3117ece4Schristos #  endif
138*3117ece4Schristos #endif
139*3117ece4Schristos 
140*3117ece4Schristos MEM_STATIC unsigned MEM_32bits(void) { return sizeof(size_t)==4; }
141*3117ece4Schristos MEM_STATIC unsigned MEM_64bits(void) { return sizeof(size_t)==8; }
142*3117ece4Schristos 
143*3117ece4Schristos MEM_STATIC unsigned MEM_isLittleEndian(void)
144*3117ece4Schristos {
145*3117ece4Schristos #if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
146*3117ece4Schristos     return 1;
147*3117ece4Schristos #elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
148*3117ece4Schristos     return 0;
149*3117ece4Schristos #elif defined(__clang__) && __LITTLE_ENDIAN__
150*3117ece4Schristos     return 1;
151*3117ece4Schristos #elif defined(__clang__) && __BIG_ENDIAN__
152*3117ece4Schristos     return 0;
153*3117ece4Schristos #elif defined(_MSC_VER) && (_M_AMD64 || _M_IX86)
154*3117ece4Schristos     return 1;
155*3117ece4Schristos #elif defined(__DMC__) && defined(_M_IX86)
156*3117ece4Schristos     return 1;
157*3117ece4Schristos #else
158*3117ece4Schristos     const union { U32 u; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental  */
159*3117ece4Schristos     return one.c[0];
160*3117ece4Schristos #endif
161*3117ece4Schristos }
162*3117ece4Schristos 
163*3117ece4Schristos #if defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==2)
164*3117ece4Schristos 
165*3117ece4Schristos /* violates C standard, by lying on structure alignment.
166*3117ece4Schristos Only use if no other choice to achieve best performance on target platform */
167*3117ece4Schristos MEM_STATIC U16 MEM_read16(const void* memPtr) { return *(const U16*) memPtr; }
168*3117ece4Schristos MEM_STATIC U32 MEM_read32(const void* memPtr) { return *(const U32*) memPtr; }
169*3117ece4Schristos MEM_STATIC U64 MEM_read64(const void* memPtr) { return *(const U64*) memPtr; }
170*3117ece4Schristos MEM_STATIC size_t MEM_readST(const void* memPtr) { return *(const size_t*) memPtr; }
171*3117ece4Schristos 
172*3117ece4Schristos MEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }
173*3117ece4Schristos MEM_STATIC void MEM_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; }
174*3117ece4Schristos MEM_STATIC void MEM_write64(void* memPtr, U64 value) { *(U64*)memPtr = value; }
175*3117ece4Schristos 
176*3117ece4Schristos #elif defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==1)
177*3117ece4Schristos 
178*3117ece4Schristos typedef __attribute__((aligned(1))) U16 unalign16;
179*3117ece4Schristos typedef __attribute__((aligned(1))) U32 unalign32;
180*3117ece4Schristos typedef __attribute__((aligned(1))) U64 unalign64;
181*3117ece4Schristos typedef __attribute__((aligned(1))) size_t unalignArch;
182*3117ece4Schristos 
183*3117ece4Schristos MEM_STATIC U16 MEM_read16(const void* ptr) { return *(const unalign16*)ptr; }
184*3117ece4Schristos MEM_STATIC U32 MEM_read32(const void* ptr) { return *(const unalign32*)ptr; }
185*3117ece4Schristos MEM_STATIC U64 MEM_read64(const void* ptr) { return *(const unalign64*)ptr; }
186*3117ece4Schristos MEM_STATIC size_t MEM_readST(const void* ptr) { return *(const unalignArch*)ptr; }
187*3117ece4Schristos 
188*3117ece4Schristos MEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(unalign16*)memPtr = value; }
189*3117ece4Schristos MEM_STATIC void MEM_write32(void* memPtr, U32 value) { *(unalign32*)memPtr = value; }
190*3117ece4Schristos MEM_STATIC void MEM_write64(void* memPtr, U64 value) { *(unalign64*)memPtr = value; }
191*3117ece4Schristos 
192*3117ece4Schristos #else
193*3117ece4Schristos 
194*3117ece4Schristos /* default method, safe and standard.
195*3117ece4Schristos    can sometimes prove slower */
196*3117ece4Schristos 
197*3117ece4Schristos MEM_STATIC U16 MEM_read16(const void* memPtr)
198*3117ece4Schristos {
199*3117ece4Schristos     U16 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val;
200*3117ece4Schristos }
201*3117ece4Schristos 
202*3117ece4Schristos MEM_STATIC U32 MEM_read32(const void* memPtr)
203*3117ece4Schristos {
204*3117ece4Schristos     U32 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val;
205*3117ece4Schristos }
206*3117ece4Schristos 
207*3117ece4Schristos MEM_STATIC U64 MEM_read64(const void* memPtr)
208*3117ece4Schristos {
209*3117ece4Schristos     U64 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val;
210*3117ece4Schristos }
211*3117ece4Schristos 
212*3117ece4Schristos MEM_STATIC size_t MEM_readST(const void* memPtr)
213*3117ece4Schristos {
214*3117ece4Schristos     size_t val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val;
215*3117ece4Schristos }
216*3117ece4Schristos 
217*3117ece4Schristos MEM_STATIC void MEM_write16(void* memPtr, U16 value)
218*3117ece4Schristos {
219*3117ece4Schristos     ZSTD_memcpy(memPtr, &value, sizeof(value));
220*3117ece4Schristos }
221*3117ece4Schristos 
222*3117ece4Schristos MEM_STATIC void MEM_write32(void* memPtr, U32 value)
223*3117ece4Schristos {
224*3117ece4Schristos     ZSTD_memcpy(memPtr, &value, sizeof(value));
225*3117ece4Schristos }
226*3117ece4Schristos 
227*3117ece4Schristos MEM_STATIC void MEM_write64(void* memPtr, U64 value)
228*3117ece4Schristos {
229*3117ece4Schristos     ZSTD_memcpy(memPtr, &value, sizeof(value));
230*3117ece4Schristos }
231*3117ece4Schristos 
232*3117ece4Schristos #endif /* MEM_FORCE_MEMORY_ACCESS */
233*3117ece4Schristos 
234*3117ece4Schristos MEM_STATIC U32 MEM_swap32_fallback(U32 in)
235*3117ece4Schristos {
236*3117ece4Schristos     return  ((in << 24) & 0xff000000 ) |
237*3117ece4Schristos             ((in <<  8) & 0x00ff0000 ) |
238*3117ece4Schristos             ((in >>  8) & 0x0000ff00 ) |
239*3117ece4Schristos             ((in >> 24) & 0x000000ff );
240*3117ece4Schristos }
241*3117ece4Schristos 
242*3117ece4Schristos MEM_STATIC U32 MEM_swap32(U32 in)
243*3117ece4Schristos {
244*3117ece4Schristos #if defined(_MSC_VER)     /* Visual Studio */
245*3117ece4Schristos     return _byteswap_ulong(in);
246*3117ece4Schristos #elif (defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) \
247*3117ece4Schristos   || (defined(__clang__) && __has_builtin(__builtin_bswap32))
248*3117ece4Schristos     return __builtin_bswap32(in);
249*3117ece4Schristos #else
250*3117ece4Schristos     return MEM_swap32_fallback(in);
251*3117ece4Schristos #endif
252*3117ece4Schristos }
253*3117ece4Schristos 
254*3117ece4Schristos MEM_STATIC U64 MEM_swap64_fallback(U64 in)
255*3117ece4Schristos {
256*3117ece4Schristos      return  ((in << 56) & 0xff00000000000000ULL) |
257*3117ece4Schristos             ((in << 40) & 0x00ff000000000000ULL) |
258*3117ece4Schristos             ((in << 24) & 0x0000ff0000000000ULL) |
259*3117ece4Schristos             ((in << 8)  & 0x000000ff00000000ULL) |
260*3117ece4Schristos             ((in >> 8)  & 0x00000000ff000000ULL) |
261*3117ece4Schristos             ((in >> 24) & 0x0000000000ff0000ULL) |
262*3117ece4Schristos             ((in >> 40) & 0x000000000000ff00ULL) |
263*3117ece4Schristos             ((in >> 56) & 0x00000000000000ffULL);
264*3117ece4Schristos }
265*3117ece4Schristos 
266*3117ece4Schristos MEM_STATIC U64 MEM_swap64(U64 in)
267*3117ece4Schristos {
268*3117ece4Schristos #if defined(_MSC_VER)     /* Visual Studio */
269*3117ece4Schristos     return _byteswap_uint64(in);
270*3117ece4Schristos #elif (defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) \
271*3117ece4Schristos   || (defined(__clang__) && __has_builtin(__builtin_bswap64))
272*3117ece4Schristos     return __builtin_bswap64(in);
273*3117ece4Schristos #else
274*3117ece4Schristos     return MEM_swap64_fallback(in);
275*3117ece4Schristos #endif
276*3117ece4Schristos }
277*3117ece4Schristos 
278*3117ece4Schristos MEM_STATIC size_t MEM_swapST(size_t in)
279*3117ece4Schristos {
280*3117ece4Schristos     if (MEM_32bits())
281*3117ece4Schristos         return (size_t)MEM_swap32((U32)in);
282*3117ece4Schristos     else
283*3117ece4Schristos         return (size_t)MEM_swap64((U64)in);
284*3117ece4Schristos }
285*3117ece4Schristos 
286*3117ece4Schristos /*=== Little endian r/w ===*/
287*3117ece4Schristos 
288*3117ece4Schristos MEM_STATIC U16 MEM_readLE16(const void* memPtr)
289*3117ece4Schristos {
290*3117ece4Schristos     if (MEM_isLittleEndian())
291*3117ece4Schristos         return MEM_read16(memPtr);
292*3117ece4Schristos     else {
293*3117ece4Schristos         const BYTE* p = (const BYTE*)memPtr;
294*3117ece4Schristos         return (U16)(p[0] + (p[1]<<8));
295*3117ece4Schristos     }
296*3117ece4Schristos }
297*3117ece4Schristos 
298*3117ece4Schristos MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)
299*3117ece4Schristos {
300*3117ece4Schristos     if (MEM_isLittleEndian()) {
301*3117ece4Schristos         MEM_write16(memPtr, val);
302*3117ece4Schristos     } else {
303*3117ece4Schristos         BYTE* p = (BYTE*)memPtr;
304*3117ece4Schristos         p[0] = (BYTE)val;
305*3117ece4Schristos         p[1] = (BYTE)(val>>8);
306*3117ece4Schristos     }
307*3117ece4Schristos }
308*3117ece4Schristos 
309*3117ece4Schristos MEM_STATIC U32 MEM_readLE24(const void* memPtr)
310*3117ece4Schristos {
311*3117ece4Schristos     return (U32)MEM_readLE16(memPtr) + ((U32)(((const BYTE*)memPtr)[2]) << 16);
312*3117ece4Schristos }
313*3117ece4Schristos 
314*3117ece4Schristos MEM_STATIC void MEM_writeLE24(void* memPtr, U32 val)
315*3117ece4Schristos {
316*3117ece4Schristos     MEM_writeLE16(memPtr, (U16)val);
317*3117ece4Schristos     ((BYTE*)memPtr)[2] = (BYTE)(val>>16);
318*3117ece4Schristos }
319*3117ece4Schristos 
320*3117ece4Schristos MEM_STATIC U32 MEM_readLE32(const void* memPtr)
321*3117ece4Schristos {
322*3117ece4Schristos     if (MEM_isLittleEndian())
323*3117ece4Schristos         return MEM_read32(memPtr);
324*3117ece4Schristos     else
325*3117ece4Schristos         return MEM_swap32(MEM_read32(memPtr));
326*3117ece4Schristos }
327*3117ece4Schristos 
328*3117ece4Schristos MEM_STATIC void MEM_writeLE32(void* memPtr, U32 val32)
329*3117ece4Schristos {
330*3117ece4Schristos     if (MEM_isLittleEndian())
331*3117ece4Schristos         MEM_write32(memPtr, val32);
332*3117ece4Schristos     else
333*3117ece4Schristos         MEM_write32(memPtr, MEM_swap32(val32));
334*3117ece4Schristos }
335*3117ece4Schristos 
336*3117ece4Schristos MEM_STATIC U64 MEM_readLE64(const void* memPtr)
337*3117ece4Schristos {
338*3117ece4Schristos     if (MEM_isLittleEndian())
339*3117ece4Schristos         return MEM_read64(memPtr);
340*3117ece4Schristos     else
341*3117ece4Schristos         return MEM_swap64(MEM_read64(memPtr));
342*3117ece4Schristos }
343*3117ece4Schristos 
344*3117ece4Schristos MEM_STATIC void MEM_writeLE64(void* memPtr, U64 val64)
345*3117ece4Schristos {
346*3117ece4Schristos     if (MEM_isLittleEndian())
347*3117ece4Schristos         MEM_write64(memPtr, val64);
348*3117ece4Schristos     else
349*3117ece4Schristos         MEM_write64(memPtr, MEM_swap64(val64));
350*3117ece4Schristos }
351*3117ece4Schristos 
352*3117ece4Schristos MEM_STATIC size_t MEM_readLEST(const void* memPtr)
353*3117ece4Schristos {
354*3117ece4Schristos     if (MEM_32bits())
355*3117ece4Schristos         return (size_t)MEM_readLE32(memPtr);
356*3117ece4Schristos     else
357*3117ece4Schristos         return (size_t)MEM_readLE64(memPtr);
358*3117ece4Schristos }
359*3117ece4Schristos 
360*3117ece4Schristos MEM_STATIC void MEM_writeLEST(void* memPtr, size_t val)
361*3117ece4Schristos {
362*3117ece4Schristos     if (MEM_32bits())
363*3117ece4Schristos         MEM_writeLE32(memPtr, (U32)val);
364*3117ece4Schristos     else
365*3117ece4Schristos         MEM_writeLE64(memPtr, (U64)val);
366*3117ece4Schristos }
367*3117ece4Schristos 
368*3117ece4Schristos /*=== Big endian r/w ===*/
369*3117ece4Schristos 
370*3117ece4Schristos MEM_STATIC U32 MEM_readBE32(const void* memPtr)
371*3117ece4Schristos {
372*3117ece4Schristos     if (MEM_isLittleEndian())
373*3117ece4Schristos         return MEM_swap32(MEM_read32(memPtr));
374*3117ece4Schristos     else
375*3117ece4Schristos         return MEM_read32(memPtr);
376*3117ece4Schristos }
377*3117ece4Schristos 
378*3117ece4Schristos MEM_STATIC void MEM_writeBE32(void* memPtr, U32 val32)
379*3117ece4Schristos {
380*3117ece4Schristos     if (MEM_isLittleEndian())
381*3117ece4Schristos         MEM_write32(memPtr, MEM_swap32(val32));
382*3117ece4Schristos     else
383*3117ece4Schristos         MEM_write32(memPtr, val32);
384*3117ece4Schristos }
385*3117ece4Schristos 
386*3117ece4Schristos MEM_STATIC U64 MEM_readBE64(const void* memPtr)
387*3117ece4Schristos {
388*3117ece4Schristos     if (MEM_isLittleEndian())
389*3117ece4Schristos         return MEM_swap64(MEM_read64(memPtr));
390*3117ece4Schristos     else
391*3117ece4Schristos         return MEM_read64(memPtr);
392*3117ece4Schristos }
393*3117ece4Schristos 
394*3117ece4Schristos MEM_STATIC void MEM_writeBE64(void* memPtr, U64 val64)
395*3117ece4Schristos {
396*3117ece4Schristos     if (MEM_isLittleEndian())
397*3117ece4Schristos         MEM_write64(memPtr, MEM_swap64(val64));
398*3117ece4Schristos     else
399*3117ece4Schristos         MEM_write64(memPtr, val64);
400*3117ece4Schristos }
401*3117ece4Schristos 
402*3117ece4Schristos MEM_STATIC size_t MEM_readBEST(const void* memPtr)
403*3117ece4Schristos {
404*3117ece4Schristos     if (MEM_32bits())
405*3117ece4Schristos         return (size_t)MEM_readBE32(memPtr);
406*3117ece4Schristos     else
407*3117ece4Schristos         return (size_t)MEM_readBE64(memPtr);
408*3117ece4Schristos }
409*3117ece4Schristos 
410*3117ece4Schristos MEM_STATIC void MEM_writeBEST(void* memPtr, size_t val)
411*3117ece4Schristos {
412*3117ece4Schristos     if (MEM_32bits())
413*3117ece4Schristos         MEM_writeBE32(memPtr, (U32)val);
414*3117ece4Schristos     else
415*3117ece4Schristos         MEM_writeBE64(memPtr, (U64)val);
416*3117ece4Schristos }
417*3117ece4Schristos 
418*3117ece4Schristos /* code only tested on 32 and 64 bits systems */
419*3117ece4Schristos MEM_STATIC void MEM_check(void) { DEBUG_STATIC_ASSERT((sizeof(size_t)==4) || (sizeof(size_t)==8)); }
420*3117ece4Schristos 
421*3117ece4Schristos 
422*3117ece4Schristos #if defined (__cplusplus)
423*3117ece4Schristos }
424*3117ece4Schristos #endif
425*3117ece4Schristos 
426*3117ece4Schristos #endif /* MEM_H_MODULE */
427