Skip to content

Instantly share code, notes, and snippets.

@dwilliamson
Last active June 3, 2023 23:06
Show Gist options
  • Save dwilliamson/a51b6249af60416cad0bf69520c1ed22 to your computer and use it in GitHub Desktop.
Save dwilliamson/a51b6249af60416cad0bf69520c1ed22 to your computer and use it in GitHub Desktop.
//
// TinyCRT, revamp and TinyWin support by Don Williamson, 2011
// Based on http://www.codeproject.com/KB/library/tlibc.aspx and LIBCTINY by Matt Pietrek
//
#pragma once
#ifdef USE_DEFAULT_CRT
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stdarg.h>
#include <float.h>
#include <cctype>
#define srandom srand
#define snprintf _snprintf
#else
#if defined(__clcpp_parse__) || (TINYCRT_NODLL)
#define TINYCRT_API
#else
#ifdef TINYCRT_IMPL
#define TINYCRT_API __declspec(dllexport)
#else
#define TINYCRT_API __declspec(dllimport)
#endif
#endif
#define NULL 0
#define TCRT_RESTRICT __declspec(restrict)
#define TCRT_NOALIAS __declspec(noalias)
#define TCRT_INTRINSIC(fn) __pragma(intrinsic(fn))
#define TCRT_GLOBAL
#ifdef __clang__
#pragma clang diagnostic ignored "-Winvalid-offsetof"
#define offsetof(type,member) __builtin_offsetof(type, member)
#else
#define offsetof(type,member) ((size_t) &(((type*)0)->member))
#endif
// ------------------------------------------------------------------------------------------------
// Standard types
// ------------------------------------------------------------------------------------------------
// stdint.h
typedef signed __int8 int8_t;
typedef signed __int16 int16_t;
typedef signed __int32 int32_t;
typedef signed __int64 int64_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
// POSIX extensions
typedef unsigned char uchar_t;
typedef unsigned short ushort_t;
typedef unsigned int uint_t;
typedef unsigned long ulong_t;
// Wide types
typedef unsigned short wint_t;
typedef unsigned short wctype_t;
// The size of time_t is "unspecified" by the standard
// GCC defines it like this
typedef long int time_t;
#ifdef _WIN64
typedef unsigned __int64 size_t;
typedef signed __int64 intptr_t;
typedef unsigned __int64 uintptr_t;
typedef __int64 ptrdiff_t;
#else
typedef __w64 unsigned int size_t;
typedef signed int intptr_t;
typedef unsigned int uintptr_t;
typedef __w64 int ptrdiff_t;
#endif
// printf-style macros
#define PRIx8 "x" // uint8_t
#define PRIx16 "x" // uint16_t
#define PRIx32 "x" // uint32_t
#define PRIx64 "llx" // uint64_t
// For isinf that aren't really in C library anyway
#ifndef __cplusplus
typedef unsigned int bool;
#endif
#ifdef __cplusplus
extern "C"
{
#endif
// ------------------------------------------------------------------------------------------------
// C atexit shutdown
// ------------------------------------------------------------------------------------------------
typedef void(__cdecl *_PVFV)();
int __cdecl atexit(_PVFV func);
void exit(int code);
TINYCRT_API char** _get_argv();
// ------------------------------------------------------------------------------------------------
// File handling
// ------------------------------------------------------------------------------------------------
// File and seek constants
#define EOF (-1)
#define SEEK_CUR 1
#define SEEK_END 2
#define SEEK_SET 0
// stdin/stdio/stderr access macros
#ifndef _STDSTREAM_DEFINED
#define stdin (&__iob_func()[0])
#define stdout (&__iob_func()[1])
#define stderr (&__iob_func()[2])
#define _STDSTREAM_DEFINED
#endif
// The standard stdio.h FILE structure
#ifndef _FILE_DEFINED
struct _iobuf {
char *_ptr;
int _cnt;
char *_base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
char *_tmpfname;
};
typedef struct _iobuf FILE;
#define _FILE_DEFINED
#endif
// stdio.h file access functions
TINYCRT_API FILE* __iob_func();
TINYCRT_API FILE* fopen(const char* path, const char* attrs);
TINYCRT_API int fclose(FILE* fp);
TINYCRT_API int feof(FILE* fp);
TINYCRT_API int fprintf(FILE* fp, const char* format, ...);
TINYCRT_API int fseek(FILE* str, long offset, int origin);
TINYCRT_API long ftell(FILE* fp);
TINYCRT_API size_t fread(void* buffer, size_t size, size_t count, FILE* str);
TINYCRT_API size_t fwrite(const void* buffer, size_t size, size_t count, FILE* str);
TINYCRT_API char *fgets(char* str, int n, FILE* s);
TINYCRT_API int fgetc(FILE* s);
TINYCRT_API int fflush(FILE* fp);
// MSVC "safe" alternatives
TINYCRT_API int fopen_s(FILE** fp, const char* path, const char* attrs);
// Environment variable management
TINYCRT_API const char* getenv(const char* name);
TINYCRT_API void putenv(const char* name, const char* value);
// ------------------------------------------------------------------------------------------------
// Maths
// ------------------------------------------------------------------------------------------------
#define RAND_MAX ((1UL << 31) - 1)
#define DBL_DIG 15 /* # of decimal digits of precision */
#define DBL_EPSILON 2.2204460492503131e-016 /* smallest such that 1.0+DBL_EPSILON != 1.0 */
#define DBL_MANT_DIG 53 /* # of bits in mantissa */
#define DBL_MAX 1.7976931348623158e+308 /* max value */
#define DBL_MAX_10_EXP 308 /* max decimal exponent */
#define DBL_MAX_EXP 1024 /* max binary exponent */
#define DBL_MIN 2.2250738585072014e-308 /* min positive value */
#define DBL_MIN_10_EXP (-307) /* min decimal exponent */
#define DBL_MIN_EXP (-1021) /* min binary exponent */
#define DBL_MIN_10_UNIT 1e-307
#define _DBL_RADIX 2 /* exponent radix */
#define _DBL_ROUNDS 1 /* addition rounding: near */
#define FLT_DIG 6 /* # of decimal digits of precision */
#define FLT_EPSILON 1.192092896e-07F /* smallest such that 1.0+FLT_EPSILON != 1.0 */
#define FLT_GUARD 0
#define FLT_MANT_DIG 24 /* # of bits in mantissa */
#define FLT_MAX 3.402823466e+38F /* max value */
#define FLT_MAX_10_EXP 38 /* max decimal exponent */
#define FLT_MAX_EXP 128 /* max binary exponent */
#define FLT_MIN 1.175494351e-38F /* min positive value */
#define FLT_MIN_10_EXP (-37) /* min decimal exponent */
#define FLT_MIN_EXP (-125) /* min binary exponent */
#define FLT_NORMALIZE 0
#define FLT_RADIX 2 /* exponent radix */
#define FLT_ROUNDS 1 /* addition rounding: near */
#define FLT_MIN_10_UNIT 1e-37f
#define MB_LEN_MAX 5 /* max. # bytes in multibyte char */
#define SHRT_MIN (-32768) /* minimum (signed) short value */
#define SHRT_MAX 32767 /* maximum (signed) short value */
#define USHRT_MAX 0xffff /* maximum unsigned short value */
#define INT_MIN (-2147483647 - 1) /* minimum (signed) int value */
#define INT_MAX 2147483647 /* maximum (signed) int value */
#define UINT_MAX 0xffffffff /* maximum unsigned int value */
#define LONG_MIN (-2147483647L - 1) /* minimum (signed) long value */
#define LONG_MAX 2147483647L /* maximum (signed) long value */
#define ULONG_MAX 0xffffffffUL /* maximum unsigned long value */
#define LLONG_MAX 9223372036854775807i64 /* maximum signed long long int value */
#define LLONG_MIN (-9223372036854775807i64 - 1) /* minimum signed long long int value */
#define ULLONG_MAX 0xffffffffffffffffui64 /* maximum unsigned long long int value */
#define I16_MIN SHRT_MIN
#define I16_MAX SHRT_MAX
#define U16_MIN 0
#define U16_MAX USHRT_MAX
#define I32_MIN INT_MIN
#define I32_MAX INT_MAX
#define U32_MIN 0
#define U32_MAX UINT_MAX
TINYCRT_API int abs(int n);
TINYCRT_API long strtol(const char* str, char** endptr, int base);
TINYCRT_API long long strtoll(const char* str, char** endptr, int base);
TINYCRT_API long atol(const char *str);
TINYCRT_API int atoi(const char *str);
TINYCRT_API void srandom(unsigned long seed);
TINYCRT_API unsigned long rand();
TINYCRT_API double frexp(double value, int* eptr);
TINYCRT_API float frexpf(float value, int* eptr);
TINYCRT_API double ldexp(double x, int exp);
TINYCRT_API float ldexpf(float x, int exp);
TINYCRT_API double modf(double value, double* iptr);
TINYCRT_API float modff(float value, float* iptr);
TINYCRT_API double fmod(double x, double y);
TINYCRT_API float fmodf(float x, float y);
TINYCRT_API float floorf(float x);
TINYCRT_API float ceilf(float x);
TINYCRT_API double round(double x);
TINYCRT_API float roundf(float x);
TINYCRT_API double truncate(double x);
TINYCRT_API float truncatef(float x);
TINYCRT_API bool isinf(double value);
TINYCRT_API bool isinff(float value);
TINYCRT_API bool isnan(double value);
TINYCRT_API bool isnanf(float value);
TINYCRT_API double fabs(double val);
TINYCRT_API float fabsf(float val);
TINYCRT_API double sin(double angle);
TINYCRT_API float sinf(float angle);
TINYCRT_API double cos(double angle);
TINYCRT_API float cosf(float angle);
TINYCRT_API double tan(double angle);
TINYCRT_API float tanf(float angle);
TINYCRT_API double asin(double val);
TINYCRT_API float asinf(float val);
TINYCRT_API double acos(double val);
TINYCRT_API float acosf(float val);
TINYCRT_API double atan(double val);
TINYCRT_API float atanf(float val);
TINYCRT_API double atan2(double y, double x);
TINYCRT_API float atan2f(float y, float x);
float powf(float x, float y);
float expf(float x);
float sqrtf(float val);
TINYCRT_API int float_as_int(float f);
TINYCRT_API float int_as_float(int i);
TINYCRT_API uint32_t log2i(uint32_t x);
TINYCRT_API float logEf(float a);
TINYCRT_API float logf(float a, float b);
TINYCRT_API float log2f(float a);
TINYCRT_API float log10f(float a);
TINYCRT_API double cbrt(double val);
TINYCRT_API float cbrtf(float val);
TINYCRT_API int cbrti(int val);
// Visual C bit rotate functions
unsigned int _rotl(unsigned int value, int shift); TCRT_INTRINSIC(_rotl);
unsigned int _rotr(unsigned int value, int shift); TCRT_INTRINSIC(_rotr);
unsigned long _lrotl(unsigned long value, int shift); TCRT_INTRINSIC(_lrotl);
unsigned long _lrotr(unsigned long value, int shift); TCRT_INTRINSIC(_lrotr);
double floor(double x);
double ceil(double x);
double pow(double x, double y); TCRT_INTRINSIC(pow);
double exp(double x); TCRT_INTRINSIC(exp);
double sqrt(double val); TCRT_INTRINSIC(sqrt);
unsigned char _BitScanForward(unsigned long* Index, unsigned long Mask); TCRT_INTRINSIC(_BitScanForward);
__inline unsigned char bsf(unsigned long* Index, unsigned long Mask)
{
return _BitScanForward(Index, Mask);
}
// ------------------------------------------------------------------------------------------------
// Float/string conversion
// ------------------------------------------------------------------------------------------------
char* dtoa_simple(double value, char* dest, int size);
TINYCRT_API double strtod(const char* s00, char** se);
TINYCRT_API char* dtoa(double d, int mode, int ndigits, int* decpt, int* sign, char** rve);
TINYCRT_API void freedtoa(char *s);
// ------------------------------------------------------------------------------------------------
// Memory manipulation
// ------------------------------------------------------------------------------------------------
TINYCRT_API int __cdecl memcmp(const void *b1, const void *b2, size_t n);
TINYCRT_API void * __cdecl memmove(void *dst, const void *src, size_t count);
void* __cdecl memset(void *dst, int val, size_t size); TCRT_INTRINSIC(memset);
void* __cdecl memcpy(void *dst, const void *src, size_t size); TCRT_INTRINSIC(memcpy);
// ------------------------------------------------------------------------------------------------
// Variable argument support
// ------------------------------------------------------------------------------------------------
// Standard vaarg stack pointer
typedef char * va_list;
// Variable argument macros
#define _ADDRESSOF(v) ( &(v) )
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
#define va_start(ap,v) ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_end(ap) ( ap = (va_list)0 )
// Variable argument formatted printing
TINYCRT_API int vsnprintf(char* dest, size_t n, const char* format, va_list args);
TINYCRT_API int vsprintf(char* dest, const char* format, va_list args); // UNSAFE
TINYCRT_API int _snprintf(char* dest, size_t n, const char* fmt, ...);
TINYCRT_API int sprintf_s(char* dest, size_t n, const char* fmt, ...);
TINYCRT_API int sprintf(char* buffer, const char* format, ...); // UNSAFE
TINYCRT_API int vprintf(const char* format, va_list args);
TINYCRT_API int printf(const char* format, ...);
// TODO: Prefix underscore is the MSVC version (snprintf is non-standard). Do the same for the others...
#define snprintf _snprintf
// Unimplemented
__inline int sscanf(const char* src, const char* format, ...)
{
return 0;
}
// ------------------------------------------------------------------------------------------------
// String manipulation
// ------------------------------------------------------------------------------------------------
TINYCRT_API int strcmp(const char *s1, const char *s2);
TINYCRT_API int strcmpi(const char *s1, const char *s2);
TINYCRT_API int stricmp(const char *s1, const char *s2);
TINYCRT_API int _stricmp(const char *s1, const char *s2);
TINYCRT_API int strncmp(const char *s1, const char *s2, size_t n);
TINYCRT_API int strnicmp(const char *s1, const char *s2, size_t n);
TINYCRT_API char* strcpy(char *dest, const char *src);
TINYCRT_API char *strncpy(char *dest, const char *src, size_t n);
TINYCRT_API size_t strlen(const char *str);
TINYCRT_API char *strchr(const char *str, int ch);
TINYCRT_API char *strrchr(const char *str, int ch);
TINYCRT_API char *strcat(char *dst, const char *src);
TINYCRT_API const char *strstr(const char *str, const char *substr);
TINYCRT_API char *_strupr(char *s);
TINYCRT_API char *_strlwr(char *s);
TINYCRT_API int toupper(int c);
TINYCRT_API int tolower(int c);
TINYCRT_API int isspace(int c);
TINYCRT_API int isupper(int c);
TINYCRT_API int islower(int c);
TINYCRT_API int isalpha(int c);
TINYCRT_API int isdigit(int c);
TINYCRT_API int isxdigit(int c);
TINYCRT_API int isalnum(int c);
TINYCRT_API int isprint(int c);
// ------------------------------------------------------------------------------------------------
// Sorting
// ------------------------------------------------------------------------------------------------
TINYCRT_API void qsort(void *a, size_t n, size_t es, int(*cmp)(const void *, const void *));
TINYCRT_API void qsort_r(void *a, size_t n, size_t es, int(*cmp)(void*, const void *, const void *));
// ------------------------------------------------------------------------------------------------
// Assert
// ------------------------------------------------------------------------------------------------
// Expressed as a macro so that the debugger breaks on the line of assertion
#define assert(expression) do { if (!(expression)) { pre_assert(#expression); __debugbreak(); post_assert(); } } while(0)
TINYCRT_API void set_assert_callback(void(*assert_callback)(const char*));
TINYCRT_API void pre_assert(const char* expression_text);
TINYCRT_API void post_assert(void);
TINYCRT_API void assert_fn(int expression);
// Very simple implementation
TINYCRT_API uint64_t time(uint64_t* timer);
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
// min/max/swap unwrapped by std
template <typename TYPE> inline TYPE min(TYPE a, TYPE b) { return a < b ? a : b; }
template <typename TYPE> inline TYPE max(TYPE a, TYPE b) { return a > b ? a : b; }
template <typename TYPE> inline void swap(TYPE& a, TYPE& b)
{
TYPE tmp;
tmp = a;
a = b;
b = tmp;
}
// Typed C++ wrappers around C stdlib functions
inline unsigned int abs(unsigned int val) { return val; }
inline float abs(float val) { return fabsf(val); }
inline double abs(double val) { return fabs(val); }
inline float fabs(float val) { return fabsf(val); }
inline float sin(float val) { return sinf(val); }
inline float cos(float val) { return cosf(val); }
inline float tan(float val) { return tanf(val); }
inline float asin(float val) { return asinf(val); }
inline float acos(float val) { return acosf(val); }
inline float atan(float val) { return atanf(val); }
inline float atan2(float y, float x) { return atan2f(y, x); }
inline int sqrt(int val) { return (int)sqrtf((float)val); }
inline unsigned int sqrt(unsigned int val) { return (unsigned int)sqrtf((float)val); }
inline float sqrt(float val) { return sqrtf(val); }
inline float floor(float val) { return floorf(val); }
inline float ceil(float val) { return ceilf(val); }
inline float pow(float x, float y) { return powf(x, y); }
inline float exp(float x) { return expf(x); }
inline float fmod(float x, float y) { return fmodf(x, y); }
// Custom implementation of C++ Standard Library list initialiser.
namespace std
{
template <typename Type>
class initializer_list
{
public:
#ifdef _MSC_VER
initializer_list(const Type* first, const Type* last)
: m_begin(first)
, m_end(last)
{
}
#else
initializer_list(const Type* first, size_t len)
: m_begin(first)
, m_end(first + len)
{
}
#endif
const Type* begin() const
{
return m_begin;
}
const Type* end() const
{
return m_end;
}
size_t size() const
{
return m_end - m_begin;
}
private:
const Type* m_begin = nullptr;
const Type* m_end = nullptr;
};
}
#endif
#endif // USE_DEFAULT_CRT
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment