include/native/dxapi/dxplatform.h (116 lines of code) (raw):
/*
* Copyright 2021 EPAM Systems, Inc
*
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership. Licensed under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
#pragma once
#ifndef __DX_PLATFORM_H__
#define __DX_PLATFORM_H__
// Determine target CPU endianness
#if defined(__BYTE_ORDER__)
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define DX_PLATFORM_LITTLE_ENDIAN 1
#else
#define DX_PLATFORM_LITTLE_ENDIAN 0
#endif
#elif defined(__ENDIAN_LITTLE__)
#if __ENDIAN_LITTLE__ == 1
#define DX_PLATFORM_LITTLE_ENDIAN 1
#else
#define DX_PLATFORM_LITTLE_ENDIAN 0
#endif
#elif defined(__BIG_ENDIAN__) || defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN) || defined(_ARCH_PPC) || defined(__PPC) || defined(__PPC__)
#define DX_PLATFORM_LITTLE_ENDIAN 0
#else
// LE system by default
#define DX_PLATFORM_LITTLE_ENDIAN 1
#endif
// Determine target operating system
#if defined(_WIN32)
/* Windows platform */
#define DX_PLATFORM_WINDOWS 1
#if (_MANAGED == 1) || (_M_CEE == 1)
// Managed windows environment
#define DX_PLATFORM_MANAGED
#define DX_PLATFORM_WINDOWS_MANAGED
#else
// Native windows environment
#define DX_PLATFORM_NATIVE 1
#define DX_PLATFORM_WINDOWS_NATIVE 1
#endif // (_MANAGED == 1) || (_M_CEE == 1)
#if defined(_MSC_VER) && ( _MSC_VER < 1800)
#define strtoull _strtoui64
#define strtoll _strtoi64
//#define isnan _isnan
#endif
#include <intrin.h>
#else // defined(_WIN32)
#define DX_PLATFORM_UNIX 1
#define DX_PLATFORM_NATIVE 1
#endif
#if !defined(_M_X64) /* || TODO: (more platform arch checks) */
#define DX_PLATFORM_32 1
#else
#define DX_PLATFORM_64 1
// const assert for word size
#endif
#if defined(_MSC_VER)
#ifndef INLINE
#define NOINLINE __declspec(noinline)
#if (_MSC_VER >= 1200)
#define INLINE __forceinline
#else
#define INLINE __inline
#endif /* #if (_MSC_VER >= 1200) */
#endif /* #ifndef INLINE */
#else
#ifndef INLINE
#define INLINE inline __attribute__((always_inline))
#define NOINLINE __attribute__ ((noinline))
#endif
#endif
#if DX_PLATFORM_WINDOWS
#pragma comment (lib, "WS2_32.lib")
#define _bswap64(x) _byteswap_uint64(x)
#define _bswap32(x) _byteswap_ulong(x)
#define _bswap16(x) _byteswap_ushort(x)
#else
// !defined(DX_PLATFORM_WINDOWS)
#define _bswap64(x) __builtin_bswap64(x)
#define _bswap32(x) __builtin_bswap32(x)
#define _bswap16(x) __builtin_bswap16(x)
#include <unistd.h>
#endif
// Any platform
#include <cmath>
#include <stdint.h>
#include <assert.h>
#include <string.h>
#include <string>
#include <vector>
namespace DxApiImpl {
template <typename P, typename Q> static INLINE const P& _as(const Q &x)
{
static_assert(sizeof(P) <= sizeof(Q), "Type sizes must match");
return *(const P *)(const char *)&x;
}
/*
* Byteswap operation
*/
template<typename T> INLINE T _bswap(T x);
template<> INLINE uint8_t _bswap<uint8_t>(uint8_t x) { return x; }
template<> INLINE int8_t _bswap<int8_t>(int8_t x) { return x; }
template<> INLINE uint16_t _bswap<uint16_t>(uint16_t x) { return _bswap16(x); }
template<> INLINE int16_t _bswap<int16_t>(int16_t x) { return (int16_t)_bswap16((uint16_t)x); }
template<> INLINE uint32_t _bswap<uint32_t>(uint32_t x) { return _bswap32(x); }
template<> INLINE int32_t _bswap<int32_t>(int32_t x) { return (int32_t)_bswap32((uint32_t)x); }
template<> INLINE uint64_t _bswap<uint64_t>(uint64_t x) { return _bswap64(x); }
template<> INLINE int64_t _bswap<int64_t>(int64_t x) { return (int64_t)_bswap64((uint64_t)x); }
/*
* Unaligned load/store operations
*/
template<typename T> static INLINE T _load(const void * ptr) { return *(const T *)ptr; }
template<typename T> static INLINE void _store(void * ptr, T x) { *(T *)ptr = x; }
// Move value of type T between possibly overlapping unaligned memory locations
template<typename T> static INLINE void _move(void * dest, const void * src) { _store<T>(dest, _load<T>(src)); }
//template<typename T> static INLINE void _move(void * dest, const void * src) { T tmp = *(const T *)src; *(T *)dest = tmp; }
#if DX_PLATFORM_LITTLE_ENDIAN
template<typename T> static INLINE T _toBE(T x) { return _bswap<T>(x); }
template<typename T> static INLINE T _fromBE(T x) { return _bswap<T>(x); }
template<typename T> static INLINE T _toLE(T x) { return x; } // Does nothing at all
template<typename T> static INLINE T _fromLE(T x) { return x; }
#else
#error "This library only supports Little-Endian systems (for now)"
// While it could be defined for big-endian systems, it is mostly pointless, because known BE systems have poor support for misaligned loads/stores
#endif
template<typename T> static INLINE T _loadBE(const void * ptr) { return _fromBE(_load<T>(ptr)); }
template<typename T> static INLINE void _storeBE(void * ptr, T x) { _store<T>(ptr, _toBE<T>(x)); }
template<typename T> static INLINE T _loadLE(const void * ptr) { return _fromLE(_load<T>(ptr)); }
template<typename T> static INLINE void _storeLE(void * const ptr, T x) { _store<T>(ptr, _toLE<T>(x)); }
template<> INLINE double _loadBE<double>(const void * ptr) { uint64_t tmp = _loadBE<uint64_t>(ptr); return _as<double>(tmp); }
template<> INLINE float _loadBE<float>(const void * ptr) { uint32_t tmp = _loadBE<uint32_t>(ptr); return _as<float>(tmp); }
template<> INLINE void _storeBE<double>(void * ptr, double x) { _storeBE<uint64_t>(ptr, _as<uint64_t>(x)); }
template<> INLINE void _storeBE<float>(void * ptr, float x) { _storeBE<uint32_t>(ptr, _as<uint32_t>(x)); }
} // namespace DxApiImpl
#endif // #if defined(__DX_PLATFORM_H__)
#ifndef _DXAPI
#define _DXAPI
// TODO: For debug only, remove later?
#ifdef _DEBUG
//#include "tickdb/common.h"
#endif
#endif