//------------------------------------------------------------------------------
// emStd1.h
//
// Copyright (C) 2004-2024 Oliver Hamann.
//
// Homepage: http://eaglemode.sourceforge.net/
//
// This program is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License version 3 as published by the
// Free Software Foundation.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License version 3 for
// more details.
//
// You should have received a copy of the GNU General Public License version 3
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------
#ifndef emStd1_h
#define emStd1_h
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <wchar.h>
//==============================================================================
//================================== Version ===================================
//==============================================================================
#define EM_MAJOR_VERSION 0
#define EM_MINOR_VERSION 96
#define EM_MICRO_VERSION 2
#define EM_VERSION_POSTFIX ""
// Version numbers and postfix. Postfix is a string like ".rc1" or "".
const char * emGetVersion();
// Version numbers and postfix as a string.
// The following static variable is built into every object file. Its
// constructor checks whether the object has been compiled with a binary
// compatible version of emCore. If not, emFatalError is called.
class emCompatibilityCheckerClass {
public:
emCompatibilityCheckerClass(int maj, int min, int mic, const char * postfix);
};
static const emCompatibilityCheckerClass emCompatibilityChecker(
EM_MAJOR_VERSION,EM_MINOR_VERSION,EM_MICRO_VERSION,EM_VERSION_POSTFIX
);
//==============================================================================
//===================== Adaptations to compilers and OSes ======================
//==============================================================================
// We do not export variables from Windows DLLs.
#if defined(_WIN32) && !defined(__CYGWIN__)
# ifndef EM_NO_DATA_EXPORT
# define EM_NO_DATA_EXPORT
# endif
#endif
// Get rid of warnings from GCC 3 about the offsetof macro.
// GCC 4 has the option -Wno-invalid-offsetof.
#if defined(__GNUC__) && __GNUC__==3
# ifdef offsetof
# undef offsetof
# define offsetof(TYPE,MEMBER) (((size_t)&((TYPE*)256)->MEMBER)-256)
# endif
#endif
// 'typename' is not supported by every compiler.
// ??? Watcom/OpenWatcom: __WATCOMC__==1100 does not have it, __WATCOMC__==1270
// ??? has it. For other versions I don't know it.
#if defined(__WATCOMC__) && __WATCOMC__<1270
# ifndef typename
# define typename
# endif
#endif
// Imitation of some UNIX functions on Windows
#if defined(_WIN32)
# define strcasecmp stricmp
# define strncasecmp strnicmp
# define snprintf _snprintf
# define vsnprintf _vsnprintf
char * em_asctime_r(const struct tm * ptm, char * buf);
# define asctime_r em_asctime_r
char * em_ctime_r(const time_t * ptime, char * buf);
# define ctime_r em_ctime_r
struct tm * em_gmtime_r(const time_t * ptime, struct tm * buf);
# define gmtime_r em_gmtime_r
struct tm * em_localtime_r(const time_t * ptime, struct tm * buf);
# define localtime_r em_localtime_r
#endif
// Have M_PI
#ifndef M_PI
# define M_PI 3.14159265358979323846
#endif
// Have ssize_t
#if defined(_MSC_VER)
# include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#endif
//==============================================================================
//=================== About RTTI (Run-Time Type Information) ===================
//==============================================================================
#if defined(__WATCOMC__)
# include <typeinfo.h>
inline const char * emRawNameOfTypeInfo(const type_info & t)
{
return t.raw_name();
}
#elif defined(_MSC_VER)
# include <typeinfo>
inline const char * emRawNameOfTypeInfo(const type_info & t)
{
return t.raw_name();
}
#else
# include <typeinfo>
using std::type_info;
inline const char * emRawNameOfTypeInfo(const type_info & t)
{
return t.name();
}
#endif
//==============================================================================
//========================= About function attributes ==========================
//==============================================================================
#if defined(__GNUC__)
# define EM_FUNC_ATTR_PRINTF(pos) __attribute__((format(__printf__,pos,pos+1)))
#else
# define EM_FUNC_ATTR_PRINTF(pos)
#endif
#if defined(__GNUC__)
# define EM_DEPRECATED(decl) decl __attribute__((deprecated))
#elif defined(_MSC_VER)
# define EM_DEPRECATED(decl) __declspec(deprecated) decl
#else
# define EM_DEPRECATED(decl) decl
#endif
//==============================================================================
//========================= Byte order of the machine ==========================
//==============================================================================
// EM_BYTE_ORDER is 1234 (little endian) or 4321 (big endian) or maybe 3412.
#if defined(__FreeBSD__) || defined(ANDROID)
# include <sys/endian.h>
#endif
#if defined(__BYTE_ORDER) &&\
(__BYTE_ORDER==1234 || __BYTE_ORDER==4321 || __BYTE_ORDER==3412)
# define EM_BYTE_ORDER __BYTE_ORDER
#elif defined(_BYTE_ORDER) &&\
(_BYTE_ORDER==1234 || _BYTE_ORDER==4321 || _BYTE_ORDER==3412)
# define EM_BYTE_ORDER _BYTE_ORDER
#elif defined(BYTE_ORDER) &&\
(BYTE_ORDER==1234 || BYTE_ORDER==4321 || BYTE_ORDER==3412)
# define EM_BYTE_ORDER BYTE_ORDER
#elif defined(__i386__) || defined(__i386) || defined(_M_IX86) || \
defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64)
# define EM_BYTE_ORDER 1234
#else
# error "don't know how to define EM_BYTE_ORDER"
#endif
//==============================================================================
//============================= Integer data types =============================
//==============================================================================
typedef signed char emInt8;
typedef unsigned char emUInt8;
typedef emUInt8 emByte;
#if USHRT_MAX == 0xFFFF
typedef signed short emInt16;
typedef unsigned short emUInt16;
#else
typedef signed __int16 emInt16;
typedef unsigned __int16 emUInt16;
#endif
#if UINT_MAX == 0xFFFFFFFFL
typedef signed int emInt32;
typedef unsigned int emUInt32;
#elif ULONG_MAX == 0xFFFFFFFFL
typedef signed long emInt32;
typedef unsigned long emUInt32;
#else
typedef signed __int32 emInt32;
typedef unsigned __int32 emUInt32;
#endif
#if (defined(__GNUC__) || defined(__SUNPRO_CC)) && defined(__WORDSIZE)
# if __WORDSIZE == 64
typedef signed long emInt64;
typedef unsigned long emUInt64;
# else
typedef signed long long emInt64;
typedef unsigned long long emUInt64;
# endif
#else
typedef signed __int64 emInt64;
typedef unsigned __int64 emUInt64;
#endif
#define EM_INT8_MIN ((emInt8)0x80)
#define EM_INT8_MAX ((emInt8)0x7f)
#define EM_UINT8_MAX ((emUInt8)0xff)
#define EM_INT16_MIN ((emInt16)0x8000)
#define EM_INT16_MAX ((emInt16)0x7fff)
#define EM_UINT16_MAX ((emUInt16)0xffff)
#define EM_INT32_MIN ((emInt32)0x80000000)
#define EM_INT32_MAX ((emInt32)0x7fffffff)
#define EM_UINT32_MAX ((emUInt32)0xffffffff)
#define EM_INT64_MIN ((emInt64)((((emUInt64)0x80000000)<<32)))
#define EM_INT64_MAX ((emInt64)(((((emUInt64)0x7fffffff)<<32)|0xffffffff)))
#define EM_UINT64_MAX ((emUInt64)(((((emUInt64)0xffffffff)<<32)|0xffffffff)))
int emStrToInt64(const char * str, int strLen, emInt64 * pVal);
int emStrToUInt64(const char * str, int strLen, emUInt64 * pVal);
// Parse a decimal 64-bit integer. Returns the number of characters
// parsed, or 0 on error.
int emInt64ToStr(char * buf, int bufLen, emInt64 val);
int emUInt64ToStr(char * buf, int bufLen, emUInt64 val);
// Convert a 64-integer to a decimal string. Returns the number of
// characters produced, or 0 if the buffer is too small.
//==============================================================================
//========================== Locale and UTF-8 support ==========================
//==============================================================================
void emInitLocale();
// This must be called once by the main function of the program before
// doing anything else.
//-------------------------- UTF-8 character encoding --------------------------
bool emIsUtf8System();
// Ask whether the character encoding of the current locale is UTF-8.
int emEncodeUtf8Char(char * utf8, int ucs4);
// Encode a UTF-8 string from a single 31-bit Unicode character.
// Arguments:
// utf8 - Buffer for returning the UTF-8 encoded string.
// It is _NOT_ terminated by a null. The buffer must
// have space for at least 6 bytes.
// ucs4 - The Unicode character.
// Returns: Number of bytes written to the buffer (1 - 6).
int emDecodeUtf8Char(int * pUcs4, const char * utf8, int utf8Len=INT_MAX);
// Decode one 31-bit Unicode character from a UTF-8 string.
// Arguments:
// pUcs4 - Pointer for returning the Unicode character. On error,
// utf8[0] is set here. And if the UTF-8 string is empty,
// zero is set.
// utf8 - The UTF-8 string.
// utf8Len - Maximum number of bytes to be read from the UTF-8
// string, if it is not null-terminated.
// Returns:
// On success, the number of bytes read from the UTF-8 string is
// returned (1 - 6). If the UTF-8 string is empty, zero is returned.
// And if the UTF-8 string does not contain a valid and complete code
// sequence, -1 is returned.
//------------------ Character encoding of the current locale ------------------
struct emMBState {
emMBState();
void Clear();
mbstate_t State;
};
#define EM_MB_LEN_MAX (2*MB_LEN_MAX)
// Maximum number of bytes written by emEncodeChar(..).
int emEncodeChar(char * str, int ucs4, emMBState * state=NULL);
// Encode a string from a single 31-bit Unicode character. The type of
// encoding depends on the current locale.
// Arguments:
// str - Buffer for returning the encoded string.
// It is _NOT_ terminated by a null. The buffer must
// have space for at least EM_MB_LEN_MAX bytes.
// ucs4 - The Unicode character.
// state - Input and output of character encoding state or shift state.
// Returns: Number of bytes written to the buffer (1 - EM_MB_LEN_MAX).
int emDecodeChar(int * pUcs4, const char * str, int strLen=INT_MAX,
emMBState * state=NULL);
// Decode one 31-bit Unicode character from a string. The type of
// decoding depends on the current locale.
// Arguments:
// pUcs4 - Pointer for returning the Unicode character. On error,
// str[0] is set here. And if the encoded string is empty,
// zero is set.
// str - The encoded string.
// strLen - Maximum number of bytes to be read from the encoded
// string, if it is not null-terminated.
// state - Input and output of character encoding state or shift state.
// Returns: Number of bytes read from the encoded string (>=0).
int emGetDecodedCharCount(const char * str, int strLen=INT_MAX);
// Get the number of 31-bit Unicode characters which could be decoded
// from a string by calling emDecodeChar(..) repeatedly.
// Arguments:
// str - The encoded string.
// strLen - Maximum number of bytes to be read from the encoded
// string, if it is not null-terminated.
// Returns: Number of characters which could be decoded from the string.
//==============================================================================
//========================= Logs, warnings and errors ==========================
//==============================================================================
void emLog(const char * format, ...) EM_FUNC_ATTR_PRINTF(1);
// Output a debug or warning message. A line break is appended. The
// message is written to stderr, but if under Windows and stderr fails,
// the message is written to a log file named "emCoreBasedAppLog.log" in
// a temp directory (the directory returned by the Win-API function
// GetTempPath).
void emEnableDLog(bool devLogEnabled=true);
bool emIsDLogEnabled();
// Whether messages for development and debugging should be made. This
// is to be modified by the main program only, maybe through a command
// line option. The default is 'false'.
void emDLog(const char * format, ...) EM_FUNC_ATTR_PRINTF(1);
// Like emLog, but the call is ignored if emIsDLogEnabled()==false.
void emWarning(const char * format, ...) EM_FUNC_ATTR_PRINTF(1);
// Like emLog, but "WARNING: " is prepended.
void emFatalError(const char * format, ...) EM_FUNC_ATTR_PRINTF(1);
// Output an error message and exit this process. The message is written
// to stderr (a line break is appended). Optionally it is also shown in
// a GUI message box - see emSetFatalErrorGraphical.
void emSetFatalErrorGraphical(bool graphical);
// Whether to show the fatal error message in a dialog (default: false).
//==============================================================================
//================================ emUncopyable ================================
//==============================================================================
class emUncopyable
// Objects of this class can never be copied.
{
public:
inline emUncopyable() {}
private:
inline emUncopyable(const emUncopyable &) {}
inline emUncopyable & operator = (const emUncopyable &) { return *this; }
};
//==============================================================================
//============================= emUnconstructable ==============================
//==============================================================================
class emUnconstructable
// Objects of this class can never be constructed.
{
public:
static inline void DummyMethod() {}
private:
inline emUnconstructable() {}
};
//==============================================================================
//=============================== emMin & emMax ================================
//==============================================================================
template <class OBJ> inline OBJ emMin(OBJ a, OBJ b) { return a<b ? a : b; }
template <class OBJ> inline OBJ emMax(OBJ a, OBJ b) { return a>b ? a : b; }
// Return the minimum or maximum of two things.
//==============================================================================
//=============================== emStdComparer ================================
//==============================================================================
template <class OBJ> class emStdComparer : public emUnconstructable {
public:
// The following functions can be used as an argument for certain
// functions about sorting and searching (e.g. emSortArray).
static int Compare(const OBJ * a, const OBJ * b, void * context)
{
if (*a<*b) return -1;
if (*a>*b) return 1;
return 0;
}
static int ReverseCompare(const OBJ * a, const OBJ * b, void * context)
{
if (*a<*b) return 1;
if (*a>*b) return -1;
return 0;
}
};
//==============================================================================
//================================ emAlignment =================================
//==============================================================================
enum {
EM_ALIGN_CENTER = 0,
EM_ALIGN_TOP = (1<<0),
EM_ALIGN_BOTTOM = (1<<1),
EM_ALIGN_LEFT = (1<<2),
EM_ALIGN_RIGHT = (1<<3),
EM_ALIGN_TOP_LEFT = EM_ALIGN_TOP | EM_ALIGN_LEFT,
EM_ALIGN_TOP_RIGHT = EM_ALIGN_TOP | EM_ALIGN_RIGHT,
EM_ALIGN_BOTTOM_LEFT = EM_ALIGN_BOTTOM | EM_ALIGN_LEFT,
EM_ALIGN_BOTTOM_RIGHT = EM_ALIGN_BOTTOM | EM_ALIGN_RIGHT
};
typedef emByte emAlignment;
// Data type for the alignment of something within a rectangle.
const char * emAlignmentToString(emAlignment alignment);
emAlignment emStringToAlignment(const char * str);
// Convert an alignment to and from string representation.
//==============================================================================
//============================== Implementations ===============================
//==============================================================================
inline emMBState::emMBState() {
memset(&State,0,sizeof(State));
}
inline void emMBState::Clear() {
memset(&State,0,sizeof(State));
}
#endif