mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-03-13 15:41:50 +01:00
First merge of 2.064 beta.
This corresponds to DMD commit a913ce4bc59a94a022a27e390fc841f4aededffb. Doesn't build Phobos yet.
This commit is contained in:
committed by
Kai Nacke
parent
c400d180d2
commit
cb341586e3
@@ -14,20 +14,17 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "aav.h"
|
||||
|
||||
static const size_t prime_list[] = {
|
||||
31UL,
|
||||
97UL, 389UL,
|
||||
1543UL, 6151UL,
|
||||
24593UL, 98317UL,
|
||||
393241UL, 1572869UL,
|
||||
6291469UL, 25165843UL,
|
||||
100663319UL, 402653189UL,
|
||||
1610612741UL, 4294967291UL,
|
||||
};
|
||||
|
||||
inline size_t hash(size_t a)
|
||||
{
|
||||
a ^= (a >> 20) ^ (a >> 12);
|
||||
return a ^ (a >> 7) ^ (a >> 4);
|
||||
}
|
||||
|
||||
struct aaA
|
||||
{
|
||||
@@ -42,9 +39,9 @@ struct AA
|
||||
size_t b_length;
|
||||
size_t nodes; // total number of aaA nodes
|
||||
aaA* binit[4]; // initial value of b[]
|
||||
};
|
||||
|
||||
static const AA bbinit = { NULL, };
|
||||
aaA aafirst; // a lot of these AA's have only one entry
|
||||
};
|
||||
|
||||
/****************************************************
|
||||
* Determine number of entries in associative array.
|
||||
@@ -67,16 +64,20 @@ Value* _aaGet(AA** paa, Key key)
|
||||
|
||||
if (!*paa)
|
||||
{ AA *a = new AA();
|
||||
*a = bbinit;
|
||||
a->b = a->binit;
|
||||
a->b_length = sizeof(a->binit) / sizeof(a->binit[0]);
|
||||
a->nodes = 0;
|
||||
a->binit[0] = NULL;
|
||||
a->binit[1] = NULL;
|
||||
a->binit[2] = NULL;
|
||||
a->binit[3] = NULL;
|
||||
*paa = a;
|
||||
assert((*paa)->b_length == 4);
|
||||
}
|
||||
//printf("paa = %p, *paa = %p\n", paa, *paa);
|
||||
|
||||
assert((*paa)->b_length);
|
||||
size_t i = (size_t)key % (*paa)->b_length;
|
||||
size_t i = hash((size_t)key) & ((*paa)->b_length - 1);
|
||||
aaA** pe = &(*paa)->b[i];
|
||||
aaA *e;
|
||||
while ((e = *pe) != NULL)
|
||||
@@ -88,15 +89,17 @@ Value* _aaGet(AA** paa, Key key)
|
||||
|
||||
// Not found, create new elem
|
||||
//printf("create new one\n");
|
||||
e = new aaA();
|
||||
|
||||
size_t nodes = ++(*paa)->nodes;
|
||||
e = (nodes != 1) ? new aaA() : &(*paa)->aafirst;
|
||||
//e = new aaA();
|
||||
e->next = NULL;
|
||||
e->key = key;
|
||||
e->value = NULL;
|
||||
*pe = e;
|
||||
|
||||
size_t nodes = ++(*paa)->nodes;
|
||||
//printf("length = %d, nodes = %d\n", paa.a.b.length, nodes);
|
||||
if (nodes > (*paa)->b_length * 4)
|
||||
//printf("length = %d, nodes = %d\n", (*paa)->b_length, nodes);
|
||||
if (nodes > (*paa)->b_length * 2)
|
||||
{
|
||||
//printf("rehash\n");
|
||||
_aaRehash(paa);
|
||||
@@ -114,14 +117,11 @@ Value* _aaGet(AA** paa, Key key)
|
||||
Value _aaGetRvalue(AA* aa, Key key)
|
||||
{
|
||||
//printf("_aaGetRvalue(key = %p)\n", key);
|
||||
if (!aa)
|
||||
return NULL;
|
||||
|
||||
size_t len = aa->b_length;
|
||||
|
||||
if (len)
|
||||
if (aa)
|
||||
{
|
||||
size_t i = (size_t)key % len;
|
||||
size_t i;
|
||||
size_t len = aa->b_length;
|
||||
i = hash((size_t)key) & (len-1);
|
||||
aaA* e = aa->b[i];
|
||||
while (e)
|
||||
{
|
||||
@@ -143,39 +143,33 @@ void _aaRehash(AA** paa)
|
||||
//printf("Rehash\n");
|
||||
if (*paa)
|
||||
{
|
||||
AA newb = bbinit;
|
||||
AA *aa = *paa;
|
||||
size_t len = _aaLen(*paa);
|
||||
if (len)
|
||||
{ size_t i;
|
||||
|
||||
for (i = 0; i < sizeof(prime_list)/sizeof(prime_list[0]) - 1; i++)
|
||||
{
|
||||
if (len <= prime_list[i])
|
||||
break;
|
||||
}
|
||||
len = prime_list[i];
|
||||
newb.b = new aaA*[len];
|
||||
memset(newb.b, 0, len * sizeof(aaA*));
|
||||
newb.b_length = len;
|
||||
if (aa)
|
||||
{
|
||||
size_t len = aa->b_length;
|
||||
if (len == 4)
|
||||
len = 32;
|
||||
else
|
||||
len *= 4;
|
||||
aaA** newb = new aaA*[len];
|
||||
memset(newb, 0, len * sizeof(aaA*));
|
||||
|
||||
for (size_t k = 0; k < aa->b_length; k++)
|
||||
{ aaA *e = aa->b[k];
|
||||
while (e)
|
||||
{ aaA* enext = e->next;
|
||||
size_t j = (size_t)e->key % len;
|
||||
e->next = newb.b[j];
|
||||
newb.b[j] = e;
|
||||
size_t j = hash((size_t)e->key) & (len-1);
|
||||
e->next = newb[j];
|
||||
newb[j] = e;
|
||||
e = enext;
|
||||
}
|
||||
}
|
||||
if (aa->b != aa->binit)
|
||||
delete[] aa->b;
|
||||
|
||||
newb.nodes = aa->nodes;
|
||||
aa->b = newb;
|
||||
aa->b_length = len;
|
||||
}
|
||||
|
||||
**paa = newb;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,222 +0,0 @@
|
||||
|
||||
// Copyright (c) 1999-2013 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "port.h"
|
||||
#include "root.h"
|
||||
#include "rmem.h"
|
||||
|
||||
|
||||
/********************************* Array ****************************/
|
||||
|
||||
Array::Array()
|
||||
{
|
||||
data = SMALLARRAYCAP ? &smallarray[0] : NULL;
|
||||
dim = 0;
|
||||
allocdim = SMALLARRAYCAP;
|
||||
}
|
||||
|
||||
Array::~Array()
|
||||
{
|
||||
if (data != &smallarray[0])
|
||||
mem.free(data);
|
||||
}
|
||||
|
||||
void Array::mark()
|
||||
{
|
||||
mem.mark(data);
|
||||
for (size_t u = 0; u < dim; u++)
|
||||
mem.mark(data[u]); // BUG: what if arrays of Object's?
|
||||
}
|
||||
|
||||
void Array::reserve(size_t nentries)
|
||||
{
|
||||
//printf("Array::reserve: dim = %d, allocdim = %d, nentries = %d\n", (int)dim, (int)allocdim, (int)nentries);
|
||||
if (allocdim - dim < nentries)
|
||||
{
|
||||
if (allocdim == 0)
|
||||
{ // Not properly initialized, someone memset it to zero
|
||||
if (nentries <= SMALLARRAYCAP)
|
||||
{ allocdim = SMALLARRAYCAP;
|
||||
data = SMALLARRAYCAP ? &smallarray[0] : NULL;
|
||||
}
|
||||
else
|
||||
{ allocdim = nentries;
|
||||
data = (void **)mem.malloc(allocdim * sizeof(*data));
|
||||
}
|
||||
}
|
||||
else if (allocdim == SMALLARRAYCAP)
|
||||
{
|
||||
allocdim = dim + nentries;
|
||||
data = (void **)mem.malloc(allocdim * sizeof(*data));
|
||||
memcpy(data, &smallarray[0], dim * sizeof(*data));
|
||||
}
|
||||
else
|
||||
{ allocdim = dim + nentries;
|
||||
data = (void **)mem.realloc(data, allocdim * sizeof(*data));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Array::setDim(size_t newdim)
|
||||
{
|
||||
if (dim < newdim)
|
||||
{
|
||||
reserve(newdim - dim);
|
||||
}
|
||||
dim = newdim;
|
||||
}
|
||||
|
||||
void Array::fixDim()
|
||||
{
|
||||
if (dim != allocdim)
|
||||
{
|
||||
if (allocdim >= SMALLARRAYCAP)
|
||||
{
|
||||
if (dim <= SMALLARRAYCAP)
|
||||
{
|
||||
memcpy(&smallarray[0], data, dim * sizeof(*data));
|
||||
mem.free(data);
|
||||
}
|
||||
else
|
||||
data = (void **)mem.realloc(data, dim * sizeof(*data));
|
||||
}
|
||||
allocdim = dim;
|
||||
}
|
||||
}
|
||||
|
||||
void Array::push(void *ptr)
|
||||
{
|
||||
reserve(1);
|
||||
data[dim++] = ptr;
|
||||
}
|
||||
|
||||
void *Array::pop()
|
||||
{
|
||||
return data[--dim];
|
||||
}
|
||||
|
||||
void Array::shift(void *ptr)
|
||||
{
|
||||
reserve(1);
|
||||
memmove(data + 1, data, dim * sizeof(*data));
|
||||
data[0] = ptr;
|
||||
dim++;
|
||||
}
|
||||
|
||||
void Array::insert(size_t index, void *ptr)
|
||||
{
|
||||
reserve(1);
|
||||
memmove(data + index + 1, data + index, (dim - index) * sizeof(*data));
|
||||
data[index] = ptr;
|
||||
dim++;
|
||||
}
|
||||
|
||||
|
||||
void Array::insert(size_t index, Array *a)
|
||||
{
|
||||
if (a)
|
||||
{
|
||||
size_t d = a->dim;
|
||||
reserve(d);
|
||||
if (dim != index)
|
||||
memmove(data + index + d, data + index, (dim - index) * sizeof(*data));
|
||||
memcpy(data + index, a->data, d * sizeof(*data));
|
||||
dim += d;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************
|
||||
* Append array a to this array.
|
||||
*/
|
||||
|
||||
void Array::append(Array *a)
|
||||
{
|
||||
insert(dim, a);
|
||||
}
|
||||
|
||||
void Array::remove(size_t i)
|
||||
{
|
||||
if (dim - i - 1)
|
||||
memmove(data + i, data + i + 1, (dim - i - 1) * sizeof(data[0]));
|
||||
dim--;
|
||||
}
|
||||
|
||||
char *Array::toChars()
|
||||
{
|
||||
char **buf = (char **)malloc(dim * sizeof(char *));
|
||||
assert(buf);
|
||||
size_t len = 2;
|
||||
for (size_t u = 0; u < dim; u++)
|
||||
{
|
||||
buf[u] = ((Object *)data[u])->toChars();
|
||||
len += strlen(buf[u]) + 1;
|
||||
}
|
||||
char *str = (char *)mem.malloc(len);
|
||||
|
||||
str[0] = '[';
|
||||
char *p = str + 1;
|
||||
for (size_t u = 0; u < dim; u++)
|
||||
{
|
||||
if (u)
|
||||
*p++ = ',';
|
||||
len = strlen(buf[u]);
|
||||
memcpy(p,buf[u],len);
|
||||
p += len;
|
||||
}
|
||||
*p++ = ']';
|
||||
*p = 0;
|
||||
free(buf);
|
||||
return str;
|
||||
}
|
||||
|
||||
void Array::zero()
|
||||
{
|
||||
memset(data,0,dim * sizeof(data[0]));
|
||||
}
|
||||
|
||||
void *Array::tos()
|
||||
{
|
||||
return dim ? data[dim - 1] : NULL;
|
||||
}
|
||||
|
||||
int
|
||||
#if _WIN32
|
||||
__cdecl
|
||||
#endif
|
||||
Array_sort_compare(const void *x, const void *y)
|
||||
{
|
||||
Object *ox = *(Object **)x;
|
||||
Object *oy = *(Object **)y;
|
||||
|
||||
return ox->compare(oy);
|
||||
}
|
||||
|
||||
void Array::sort()
|
||||
{
|
||||
if (dim)
|
||||
{
|
||||
qsort(data, dim, sizeof(Object *), Array_sort_compare);
|
||||
}
|
||||
}
|
||||
|
||||
Array *Array::copy()
|
||||
{
|
||||
Array *a = new Array();
|
||||
|
||||
a->setDim(dim);
|
||||
memcpy(a->data, data, dim * sizeof(void *));
|
||||
return a;
|
||||
}
|
||||
|
||||
@@ -481,9 +481,9 @@ FM1: // We don't use fprem1 because for some inexplicable
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
longdouble ld_qnan = { 0x8000000000000000ULL, 0x7fff, 0 };
|
||||
longdouble ld_snan = { 0x0000000000000001ULL, 0x7fff, 0 };
|
||||
longdouble ld_inf = { 0x0000000000000000ULL, 0x7fff, 0 };
|
||||
longdouble ld_qnan = { 0xC000000000000000ULL, 0x7fff, 0 };
|
||||
longdouble ld_snan = { 0xC000000000000001ULL, 0x7fff, 0 };
|
||||
longdouble ld_inf = { 0x8000000000000000ULL, 0x7fff, 0 };
|
||||
|
||||
longdouble ld_zero = { 0, 0, 0 };
|
||||
longdouble ld_one = { 0x8000000000000000ULL, 0x3fff, 0 };
|
||||
|
||||
@@ -13,19 +13,7 @@
|
||||
#ifndef __LONG_DOUBLE_H__
|
||||
#define __LONG_DOUBLE_H__
|
||||
|
||||
#if IN_GCC
|
||||
#include "d-gcc-real.h"
|
||||
typedef real_t longdouble;
|
||||
|
||||
template<typename T> longdouble ldouble(T x) { return (longdouble) x; }
|
||||
inline size_t ld_sprint(char* str, int fmt, longdouble x)
|
||||
{
|
||||
if(fmt == 'a' || fmt == 'A')
|
||||
return x.formatHex(buffer, 46); // don't know the size here, but 46 is the max
|
||||
return x.format(buffer, 46);
|
||||
}
|
||||
|
||||
#elif !_MSC_VER // has native 10 byte doubles
|
||||
#if !_MSC_VER // has native 10 byte doubles
|
||||
#include <stdio.h>
|
||||
typedef long double longdouble;
|
||||
typedef volatile long double volatile_longdouble;
|
||||
@@ -143,8 +131,18 @@ inline longdouble ldouble(unsigned long long mantissa, int exp, int sign = 0)
|
||||
d.sign = sign;
|
||||
return d;
|
||||
}
|
||||
template<typename T> inline longdouble ldouble(T x) { longdouble d; d.set(x); return d; }
|
||||
//template<typename T> inline longdouble ldouble(volatile T x) { longdouble d; d.set(x); return d; }
|
||||
|
||||
// codegen bug in VS2010/VS2012, if the set() function not inlined
|
||||
// (this passed on stack, but expected in ECX; RVO?)
|
||||
#if _MSC_VER >= 1600
|
||||
#define LDOUBLE_INLINE __declspec(noinline)
|
||||
#else
|
||||
#define LDOUBLE_INLINE inline
|
||||
#endif
|
||||
|
||||
template<typename T> LDOUBLE_INLINE longdouble ldouble(T x) { longdouble d; d.set(x); return d; }
|
||||
|
||||
#undef LDOUBLE_INLINE
|
||||
|
||||
longdouble operator+(longdouble ld1, longdouble ld2);
|
||||
longdouble operator-(longdouble ld1, longdouble ld2);
|
||||
@@ -200,6 +198,7 @@ longdouble tanl (longdouble ld);
|
||||
|
||||
longdouble fmodl(longdouble x, longdouble y);
|
||||
longdouble ldexpl(longdouble ldval, int exp); // see strtold
|
||||
longdouble strtold(const char *p,char **endp);
|
||||
|
||||
inline longdouble fabs (longdouble ld) { return fabsl(ld); }
|
||||
inline longdouble sqrt (longdouble ld) { return sqrtl(ld); }
|
||||
@@ -236,38 +235,6 @@ extern longdouble ld_inf;
|
||||
extern longdouble ld_qnan;
|
||||
extern longdouble ld_snan;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// CLASS numeric_limits<longdouble>
|
||||
template<> class _CRTIMP2_PURE std::numeric_limits<longdouble>
|
||||
: public _Num_float_base
|
||||
{ // limits for type long double
|
||||
public:
|
||||
typedef longdouble _Ty;
|
||||
|
||||
static _Ty (__CRTDECL min)() _THROW0() { return LDBL_MIN; }
|
||||
static _Ty (__CRTDECL max)() _THROW0() { return LDBL_MAX; }
|
||||
static _Ty __CRTDECL epsilon() _THROW0() { return LDBL_EPSILON; }
|
||||
static _Ty __CRTDECL round_error() _THROW0() { return ldouble(0.5); }
|
||||
static _Ty __CRTDECL denorm_min() _THROW0() { return ldouble(0x0000000000000001ULL, 1); }
|
||||
static _Ty __CRTDECL infinity() _THROW0() { return ld_inf; }
|
||||
static _Ty __CRTDECL quiet_NaN() _THROW0() { return ld_qnan; }
|
||||
static _Ty __CRTDECL signaling_NaN() _THROW0() { return ld_snan; }
|
||||
|
||||
_STCONS(int, digits, LDBL_MANT_DIG);
|
||||
_STCONS(int, digits10, LDBL_DIG);
|
||||
_STCONS(int, max_exponent, (int)LDBL_MAX_EXP);
|
||||
_STCONS(int, max_exponent10, (int)LDBL_MAX_10_EXP);
|
||||
_STCONS(int, min_exponent, (int)LDBL_MIN_EXP);
|
||||
_STCONS(int, min_exponent10, (int)LDBL_MIN_10_EXP);
|
||||
};
|
||||
|
||||
//_STCONSDEF(numeric_limits<longdouble>, int, digits)
|
||||
//_STCONSDEF(numeric_limits<longdouble>, int, digits10)
|
||||
//_STCONSDEF(numeric_limits<longdouble>, int, max_exponent)
|
||||
//_STCONSDEF(numeric_limits<longdouble>, int, max_exponent10)
|
||||
//_STCONSDEF(numeric_limits<longdouble>, int, min_exponent)
|
||||
//_STCONSDEF(numeric_limits<longdouble>, int, min_exponent10)
|
||||
|
||||
size_t ld_sprint(char* str, int fmt, longdouble x);
|
||||
|
||||
#endif // !_MSC_VER
|
||||
|
||||
666
dmd2/root/port.c
666
dmd2/root/port.c
@@ -16,11 +16,33 @@
|
||||
#include <wchar.h>
|
||||
|
||||
double Port::nan = NAN;
|
||||
longdouble Port::ldbl_nan = NAN;
|
||||
longdouble Port::snan;
|
||||
|
||||
double Port::infinity = INFINITY;
|
||||
longdouble Port::ldbl_infinity = INFINITY;
|
||||
|
||||
double Port::dbl_max = DBL_MAX;
|
||||
double Port::dbl_min = DBL_MIN;
|
||||
longdouble Port::ldbl_max = LDBL_MAX;
|
||||
|
||||
struct PortInitializer
|
||||
{
|
||||
PortInitializer();
|
||||
};
|
||||
|
||||
static PortInitializer portinitializer;
|
||||
|
||||
PortInitializer::PortInitializer()
|
||||
{
|
||||
union
|
||||
{ unsigned int ui[4];
|
||||
longdouble ld;
|
||||
} snan = {{ 0, 0xA0000000, 0x7FFF, 0 }};
|
||||
|
||||
Port::snan = snan.ld;
|
||||
}
|
||||
|
||||
int Port::isNan(double r)
|
||||
{
|
||||
return ::isnan(r);
|
||||
@@ -47,68 +69,22 @@ int Port::isSignallingNan(longdouble r)
|
||||
return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
|
||||
}
|
||||
|
||||
int Port::isFinite(double r)
|
||||
{
|
||||
return ::isfinite(r);
|
||||
}
|
||||
|
||||
int Port::isInfinity(double r)
|
||||
{
|
||||
return (::fpclassify(r) == FP_INFINITE);
|
||||
}
|
||||
|
||||
int Port::Signbit(double r)
|
||||
{
|
||||
return ::signbit(r);
|
||||
}
|
||||
|
||||
double Port::floor(double d)
|
||||
{
|
||||
return ::floor(d);
|
||||
}
|
||||
|
||||
double Port::pow(double x, double y)
|
||||
{
|
||||
return ::pow(x, y);
|
||||
}
|
||||
|
||||
longdouble Port::fmodl(longdouble x, longdouble y)
|
||||
{
|
||||
return ::fmodl(x, y);
|
||||
}
|
||||
|
||||
unsigned long long Port::strtoull(const char *p, char **pend, int base)
|
||||
int Port::fequal(longdouble x, longdouble y)
|
||||
{
|
||||
return ::strtoull(p, pend, base);
|
||||
}
|
||||
|
||||
char *Port::ull_to_string(char *buffer, ulonglong ull)
|
||||
{
|
||||
sprintf(buffer, "%llu", ull);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
|
||||
{
|
||||
swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
double Port::ull_to_double(ulonglong ull)
|
||||
{
|
||||
return (double) ull;
|
||||
}
|
||||
|
||||
const char *Port::list_separator()
|
||||
{
|
||||
// LOCALE_SLIST for Windows
|
||||
return ",";
|
||||
}
|
||||
|
||||
const wchar_t *Port::wlist_separator()
|
||||
{
|
||||
// LOCALE_SLIST for Windows
|
||||
return L",";
|
||||
/* In some cases, the REALPAD bytes get garbage in them,
|
||||
* so be sure and ignore them.
|
||||
*/
|
||||
return memcmp(&x, &y, 10) == 0;
|
||||
}
|
||||
|
||||
char *Port::strupr(char *s)
|
||||
@@ -126,6 +102,36 @@ int Port::stricmp(const char *s1, const char *s2)
|
||||
return ::stricmp(s1, s2);
|
||||
}
|
||||
|
||||
|
||||
extern "C" const char * __cdecl __locale_decpoint;
|
||||
|
||||
float Port::strtof(const char *buffer, char **endp)
|
||||
{
|
||||
const char *save = __locale_decpoint;
|
||||
__locale_decpoint = ".";
|
||||
float result = ::strtof(buffer, endp);
|
||||
__locale_decpoint = save;
|
||||
return result;
|
||||
}
|
||||
|
||||
double Port::strtod(const char *buffer, char **endp)
|
||||
{
|
||||
const char *save = __locale_decpoint;
|
||||
__locale_decpoint = ".";
|
||||
double result = ::strtod(buffer, endp);
|
||||
__locale_decpoint = save;
|
||||
return result;
|
||||
}
|
||||
|
||||
longdouble Port::strtold(const char *buffer, char **endp)
|
||||
{
|
||||
const char *save = __locale_decpoint;
|
||||
__locale_decpoint = ".";
|
||||
longdouble result = ::strtold(buffer, endp);
|
||||
__locale_decpoint = save;
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if _MSC_VER
|
||||
@@ -134,7 +140,7 @@ int Port::stricmp(const char *s1, const char *s2)
|
||||
#pragma warning (disable : 4514)
|
||||
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#include <float.h> // for _isnan
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
@@ -143,13 +149,12 @@ int Port::stricmp(const char *s1, const char *s2)
|
||||
#include <stdlib.h>
|
||||
#include <limits> // for std::numeric_limits
|
||||
|
||||
static unsigned long nanarray[2]= { 0xFFFFFFFF, 0x7FFFFFFF };
|
||||
//static unsigned long nanarray[2] = {0,0x7FF80000 };
|
||||
double Port::nan = (*(double *)nanarray);
|
||||
double Port::nan;
|
||||
longdouble Port::ldbl_nan;
|
||||
longdouble Port::snan;
|
||||
|
||||
//static unsigned long infinityarray[2] = {0,0x7FF00000 };
|
||||
static double zero = 0;
|
||||
double Port::infinity = 1 / zero;
|
||||
double Port::infinity;
|
||||
longdouble Port::ldbl_infinity;
|
||||
|
||||
double Port::dbl_max = DBL_MAX;
|
||||
double Port::dbl_min = DBL_MIN;
|
||||
@@ -164,7 +169,16 @@ static PortInitializer portinitializer;
|
||||
|
||||
PortInitializer::PortInitializer()
|
||||
{
|
||||
union {
|
||||
unsigned long ul[2];
|
||||
double d;
|
||||
} nan = {{ 0, 0x7FF80000 }};
|
||||
|
||||
Port::nan = nan.d;
|
||||
Port::ldbl_nan = ld_qnan;
|
||||
Port::snan = ld_snan;
|
||||
Port::infinity = std::numeric_limits<double>::infinity();
|
||||
Port::ldbl_infinity = ld_inf;
|
||||
}
|
||||
|
||||
int Port::isNan(double r)
|
||||
@@ -192,145 +206,22 @@ int Port::isSignallingNan(longdouble r)
|
||||
return isSignallingNan((double) r);
|
||||
}
|
||||
|
||||
int Port::isFinite(double r)
|
||||
{
|
||||
return ::_finite(r);
|
||||
}
|
||||
|
||||
int Port::isInfinity(double r)
|
||||
{
|
||||
return (::_fpclass(r) & (_FPCLASS_NINF | _FPCLASS_PINF));
|
||||
}
|
||||
|
||||
int Port::Signbit(double r)
|
||||
{
|
||||
return (long)(((long *)&(r))[1] & 0x80000000);
|
||||
}
|
||||
|
||||
double Port::floor(double d)
|
||||
{
|
||||
return ::floor(d);
|
||||
}
|
||||
|
||||
double Port::pow(double x, double y)
|
||||
{
|
||||
if (y == 0)
|
||||
return 1; // even if x is NAN
|
||||
return ::pow(x, y);
|
||||
}
|
||||
|
||||
longdouble Port::fmodl(longdouble x, longdouble y)
|
||||
{
|
||||
return ::fmodl(x, y);
|
||||
}
|
||||
|
||||
unsigned _int64 Port::strtoull(const char *p, char **pend, int base)
|
||||
int Port::fequal(longdouble x, longdouble y)
|
||||
{
|
||||
unsigned _int64 number = 0;
|
||||
int c;
|
||||
int error;
|
||||
#ifndef ULLONG_MAX
|
||||
#define ULLONG_MAX ((unsigned _int64)~0I64)
|
||||
#endif
|
||||
|
||||
while (isspace((unsigned char)*p)) /* skip leading white space */
|
||||
p++;
|
||||
if (*p == '+')
|
||||
p++;
|
||||
switch (base)
|
||||
{ case 0:
|
||||
base = 10; /* assume decimal base */
|
||||
if (*p == '0')
|
||||
{ base = 8; /* could be octal */
|
||||
p++;
|
||||
switch (*p)
|
||||
{ case 'x':
|
||||
case 'X':
|
||||
base = 16; /* hex */
|
||||
p++;
|
||||
break;
|
||||
#if BINARY
|
||||
case 'b':
|
||||
case 'B':
|
||||
base = 2; /* binary */
|
||||
p++;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 16: /* skip over '0x' and '0X' */
|
||||
if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
|
||||
p += 2;
|
||||
break;
|
||||
#if BINARY
|
||||
case 2: /* skip over '0b' and '0B' */
|
||||
if (*p == '0' && (p[1] == 'b' || p[1] == 'B'))
|
||||
p += 2;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
error = 0;
|
||||
for (;;)
|
||||
{ c = *p;
|
||||
if (isdigit(c))
|
||||
c -= '0';
|
||||
else if (isalpha(c))
|
||||
c = (c & ~0x20) - ('A' - 10);
|
||||
else /* unrecognized character */
|
||||
break;
|
||||
if (c >= base) /* not in number base */
|
||||
break;
|
||||
if ((ULLONG_MAX - c) / base < number)
|
||||
error = 1;
|
||||
number = number * base + c;
|
||||
p++;
|
||||
}
|
||||
if (pend)
|
||||
*pend = (char *)p;
|
||||
if (error)
|
||||
{ number = ULLONG_MAX;
|
||||
errno = ERANGE;
|
||||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
char *Port::ull_to_string(char *buffer, ulonglong ull)
|
||||
{
|
||||
_ui64toa(ull, buffer, 10);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
|
||||
{
|
||||
_ui64tow(ull, buffer, 10);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
double Port::ull_to_double(ulonglong ull)
|
||||
{ double d;
|
||||
|
||||
if ((__int64) ull < 0)
|
||||
{
|
||||
// MSVC doesn't implement the conversion
|
||||
d = (double) (__int64)(ull - 0x8000000000000000i64);
|
||||
d += (double)(signed __int64)(0x7FFFFFFFFFFFFFFFi64) + 1.0;
|
||||
}
|
||||
else
|
||||
d = (double)(__int64)ull;
|
||||
return d;
|
||||
}
|
||||
|
||||
const char *Port::list_separator()
|
||||
{
|
||||
// LOCALE_SLIST for Windows
|
||||
return ",";
|
||||
}
|
||||
|
||||
const wchar_t *Port::wlist_separator()
|
||||
{
|
||||
// LOCALE_SLIST for Windows
|
||||
return L",";
|
||||
/* In some cases, the REALPAD bytes get garbage in them,
|
||||
* so be sure and ignore them.
|
||||
*/
|
||||
return memcmp(&x, &y, 10) == 0;
|
||||
}
|
||||
|
||||
char *Port::strupr(char *s)
|
||||
@@ -348,6 +239,197 @@ int Port::stricmp(const char *s1, const char *s2)
|
||||
return ::stricmp(s1, s2);
|
||||
}
|
||||
|
||||
float Port::strtof(const char *p, char **endp)
|
||||
{
|
||||
return static_cast<float>(::strtod(p, endp));
|
||||
}
|
||||
|
||||
double Port::strtod(const char *p, char **endp)
|
||||
{
|
||||
return ::strtod(p, endp);
|
||||
}
|
||||
|
||||
// See backend/strtold.c.
|
||||
longdouble Port::strtold(const char *p, char **endp)
|
||||
{
|
||||
return ::strtold(p, endp);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if __MINGW32__
|
||||
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <wchar.h>
|
||||
#include <float.h>
|
||||
#include <assert.h>
|
||||
|
||||
double Port::nan;
|
||||
longdouble Port::ldbl_nan;
|
||||
longdouble Port::snan;
|
||||
|
||||
static double zero = 0;
|
||||
double Port::infinity = 1 / zero;
|
||||
longdouble Port::ldbl_infinity = 1 / zero;
|
||||
|
||||
double Port::dbl_max = 1.7976931348623157e308;
|
||||
double Port::dbl_min = 5e-324;
|
||||
longdouble Port::ldbl_max = LDBL_MAX;
|
||||
|
||||
struct PortInitializer
|
||||
{
|
||||
PortInitializer();
|
||||
};
|
||||
|
||||
static PortInitializer portinitializer;
|
||||
|
||||
PortInitializer::PortInitializer()
|
||||
{
|
||||
union
|
||||
{ unsigned int ui[2];
|
||||
double d;
|
||||
} nan = {{ 0, 0x7FF80000 }};
|
||||
|
||||
Port::nan = nan.d;
|
||||
assert(!signbit(Port::nan));
|
||||
|
||||
union
|
||||
{ unsigned int ui[4];
|
||||
longdouble ld;
|
||||
} ldbl_nan = {{ 0, 0xC0000000, 0x7FFF, 0}};
|
||||
|
||||
Port::ldbl_nan = ldbl_nan.ld;
|
||||
assert(!signbit(Port::ldbl_nan));
|
||||
|
||||
union
|
||||
{ unsigned int ui[4];
|
||||
longdouble ld;
|
||||
} snan = {{ 0, 0xA0000000, 0x7FFF, 0 }};
|
||||
|
||||
Port::snan = snan.ld;
|
||||
}
|
||||
|
||||
int Port::isNan(double r)
|
||||
{
|
||||
return isnan(r);
|
||||
}
|
||||
|
||||
int Port::isNan(longdouble r)
|
||||
{
|
||||
return isnan(r);
|
||||
}
|
||||
|
||||
int Port::isSignallingNan(double r)
|
||||
{
|
||||
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
||||
* its significand, which is bit 51 of 0..63 for 64 bit doubles.
|
||||
*/
|
||||
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
|
||||
}
|
||||
|
||||
int Port::isSignallingNan(longdouble r)
|
||||
{
|
||||
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
||||
* its significand, which is bit 62 of 0..79 for 80 bit reals.
|
||||
*/
|
||||
return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
|
||||
}
|
||||
|
||||
int Port::isInfinity(double r)
|
||||
{
|
||||
return isinf(r);
|
||||
}
|
||||
|
||||
longdouble Port::fmodl(longdouble x, longdouble y)
|
||||
{
|
||||
return ::fmodl(x, y);
|
||||
}
|
||||
|
||||
int Port::fequal(longdouble x, longdouble y)
|
||||
{
|
||||
/* In some cases, the REALPAD bytes get garbage in them,
|
||||
* so be sure and ignore them.
|
||||
*/
|
||||
return memcmp(&x, &y, 10) == 0;
|
||||
}
|
||||
|
||||
char *Port::strupr(char *s)
|
||||
{
|
||||
char *t = s;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
*s = toupper(*s);
|
||||
s++;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
int Port::memicmp(const char *s1, const char *s2, int n)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{ char c1 = s1[i];
|
||||
char c2 = s2[i];
|
||||
|
||||
result = c1 - c2;
|
||||
if (result)
|
||||
{
|
||||
result = toupper(c1) - toupper(c2);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int Port::stricmp(const char *s1, const char *s2)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
for (;;)
|
||||
{ char c1 = *s1;
|
||||
char c2 = *s2;
|
||||
|
||||
result = c1 - c2;
|
||||
if (result)
|
||||
{
|
||||
result = toupper(c1) - toupper(c2);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
if (!c1)
|
||||
break;
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
float Port::strtof(const char *p, char **endp)
|
||||
{
|
||||
return ::strtof(p, endp);
|
||||
}
|
||||
|
||||
double Port::strtod(const char *p, char **endp)
|
||||
{
|
||||
return ::strtod(p, endp);
|
||||
}
|
||||
|
||||
longdouble Port::strtold(const char *p, char **endp)
|
||||
{
|
||||
return ::__mingw_strtold(p, endp);
|
||||
}
|
||||
|
||||
// See vcbuild/strtold.c.
|
||||
longdouble strtold(const char *p, char **endp);
|
||||
|
||||
@@ -557,14 +639,20 @@ longdouble Port::strtold(const char *p, char **endp)
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <wchar.h>
|
||||
#include <float.h>
|
||||
#include <assert.h>
|
||||
|
||||
double Port::nan;
|
||||
longdouble Port::ldbl_nan;
|
||||
longdouble Port::snan;
|
||||
|
||||
static double zero = 0;
|
||||
double Port::nan = copysign(NAN, 1.0);
|
||||
double Port::infinity = 1 / zero;
|
||||
longdouble Port::ldbl_infinity = 1 / zero;
|
||||
|
||||
double Port::dbl_max = 1.7976931348623157e308;
|
||||
double Port::dbl_min = 5e-324;
|
||||
longdouble Port::ldbl_max = LDBL_MAX;
|
||||
@@ -578,8 +666,29 @@ static PortInitializer portinitializer;
|
||||
|
||||
PortInitializer::PortInitializer()
|
||||
{
|
||||
union
|
||||
{ unsigned int ui[2];
|
||||
double d;
|
||||
} nan = {{ 0, 0x7FF80000 }};
|
||||
|
||||
Port::nan = nan.d;
|
||||
assert(!signbit(Port::nan));
|
||||
|
||||
union
|
||||
{ unsigned int ui[4];
|
||||
longdouble ld;
|
||||
} ldbl_nan = {{ 0, 0xC0000000, 0x7FFF, 0}};
|
||||
|
||||
Port::ldbl_nan = ldbl_nan.ld;
|
||||
assert(!signbit(Port::ldbl_nan));
|
||||
|
||||
union
|
||||
{ unsigned int ui[4];
|
||||
longdouble ld;
|
||||
} snan = {{ 0, 0xA0000000, 0x7FFF, 0 }};
|
||||
|
||||
Port::snan = snan.ld;
|
||||
|
||||
#if __FreeBSD__ && __i386__
|
||||
// LDBL_MAX comes out as infinity. Fix.
|
||||
static unsigned char x[sizeof(longdouble)] =
|
||||
@@ -640,14 +749,6 @@ int Port::isSignallingNan(longdouble r)
|
||||
return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
|
||||
}
|
||||
|
||||
#undef isfinite
|
||||
int Port::isFinite(double r)
|
||||
{
|
||||
return ::finite(r);
|
||||
}
|
||||
|
||||
#if !defined __HAIKU__
|
||||
#endif
|
||||
int Port::isInfinity(double r)
|
||||
{
|
||||
#if __APPLE__
|
||||
@@ -660,24 +761,6 @@ int Port::isInfinity(double r)
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef signbit
|
||||
int Port::Signbit(double r)
|
||||
{
|
||||
union { double d; long long ll; } u;
|
||||
u.d = r;
|
||||
return u.ll < 0;
|
||||
}
|
||||
|
||||
double Port::floor(double d)
|
||||
{
|
||||
return ::floor(d);
|
||||
}
|
||||
|
||||
double Port::pow(double x, double y)
|
||||
{
|
||||
return ::pow(x, y);
|
||||
}
|
||||
|
||||
longdouble Port::fmodl(longdouble x, longdouble y)
|
||||
{
|
||||
#if __FreeBSD__ || __OpenBSD__
|
||||
@@ -687,40 +770,12 @@ longdouble Port::fmodl(longdouble x, longdouble y)
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned long long Port::strtoull(const char *p, char **pend, int base)
|
||||
int Port::fequal(longdouble x, longdouble y)
|
||||
{
|
||||
return ::strtoull(p, pend, base);
|
||||
}
|
||||
|
||||
char *Port::ull_to_string(char *buffer, ulonglong ull)
|
||||
{
|
||||
sprintf(buffer, "%llu", ull);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
|
||||
{
|
||||
#if __OpenBSD__
|
||||
assert(0);
|
||||
#else
|
||||
swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
|
||||
#endif
|
||||
return buffer;
|
||||
}
|
||||
|
||||
double Port::ull_to_double(ulonglong ull)
|
||||
{
|
||||
return (double) ull;
|
||||
}
|
||||
|
||||
const char *Port::list_separator()
|
||||
{
|
||||
return ",";
|
||||
}
|
||||
|
||||
const wchar_t *Port::wlist_separator()
|
||||
{
|
||||
return L",";
|
||||
/* In some cases, the REALPAD bytes get garbage in them,
|
||||
* so be sure and ignore them.
|
||||
*/
|
||||
return memcmp(&x, &y, 10) == 0;
|
||||
}
|
||||
|
||||
char *Port::strupr(char *s)
|
||||
@@ -778,6 +833,16 @@ int Port::stricmp(const char *s1, const char *s2)
|
||||
return result;
|
||||
}
|
||||
|
||||
float Port::strtof(const char *p, char **endp)
|
||||
{
|
||||
return ::strtof(p, endp);
|
||||
}
|
||||
|
||||
double Port::strtod(const char *p, char **endp)
|
||||
{
|
||||
return ::strtod(p, endp);
|
||||
}
|
||||
|
||||
longdouble Port::strtold(const char *p, char **endp)
|
||||
{
|
||||
return ::strtold(p, endp);
|
||||
@@ -794,14 +859,20 @@ longdouble Port::strtold(const char *p, char **endp)
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <wchar.h>
|
||||
#include <float.h>
|
||||
#include <ieeefp.h>
|
||||
|
||||
double Port::nan;
|
||||
longdouble Port::ldbl_nan;
|
||||
longdouble Port::snan;
|
||||
|
||||
static double zero = 0;
|
||||
double Port::nan = NAN;
|
||||
double Port::infinity = 1 / zero;
|
||||
longdouble Port::ldbl_infinity = 1 / zero;
|
||||
|
||||
double Port::dbl_max = 1.7976931348623157e308;
|
||||
double Port::dbl_min = 5e-324;
|
||||
longdouble Port::ldbl_max = LDBL_MAX;
|
||||
@@ -815,14 +886,28 @@ static PortInitializer portinitializer;
|
||||
|
||||
PortInitializer::PortInitializer()
|
||||
{
|
||||
// gcc nan's have the sign bit set by default, so turn it off
|
||||
// Need the volatile to prevent gcc from doing incorrect
|
||||
// constant folding.
|
||||
volatile longdouble foo;
|
||||
foo = NAN;
|
||||
if (signbit(foo)) // signbit sometimes, not always, set
|
||||
foo = -foo; // turn off sign bit
|
||||
Port::nan = foo;
|
||||
union
|
||||
{ unsigned int ui[2];
|
||||
double d;
|
||||
} nan = {{ 0, 0x7FF80000 }};
|
||||
|
||||
Port::nan = nan.d;
|
||||
assert(!signbit(Port::nan));
|
||||
|
||||
union
|
||||
{ unsigned int ui[4];
|
||||
longdouble ld;
|
||||
} ldbl_nan = {{ 0, 0xC0000000, 0x7FFF, 0}};
|
||||
|
||||
Port::ldbl_nan = ldbl_nan.ld;
|
||||
assert(!signbit(Port::ldbl_nan));
|
||||
|
||||
union
|
||||
{ unsigned int ui[4];
|
||||
longdouble ld;
|
||||
} snan = {{ 0, 0xA0000000, 0x7FFF, 0 }};
|
||||
|
||||
Port::snan = snan.ld;
|
||||
}
|
||||
|
||||
int Port::isNan(double r)
|
||||
@@ -851,68 +936,22 @@ int Port::isSignallingNan(longdouble r)
|
||||
return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
|
||||
}
|
||||
|
||||
#undef isfinite
|
||||
int Port::isFinite(double r)
|
||||
{
|
||||
return finite(r);
|
||||
}
|
||||
|
||||
int Port::isInfinity(double r)
|
||||
{
|
||||
return isinf(r);
|
||||
}
|
||||
|
||||
#undef signbit
|
||||
int Port::Signbit(double r)
|
||||
{
|
||||
return (long)(((long *)&r)[1] & 0x80000000);
|
||||
}
|
||||
|
||||
double Port::floor(double d)
|
||||
{
|
||||
return ::floor(d);
|
||||
}
|
||||
|
||||
double Port::pow(double x, double y)
|
||||
{
|
||||
return ::pow(x, y);
|
||||
}
|
||||
|
||||
longdouble Port::fmodl(longdouble x, longdouble y)
|
||||
{
|
||||
return ::fmodl(x, y);
|
||||
}
|
||||
|
||||
unsigned long long Port::strtoull(const char *p, char **pend, int base)
|
||||
int Port::fequal(longdouble x, longdouble y)
|
||||
{
|
||||
return ::strtoull(p, pend, base);
|
||||
}
|
||||
|
||||
char *Port::ull_to_string(char *buffer, ulonglong ull)
|
||||
{
|
||||
sprintf(buffer, "%llu", ull);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
|
||||
{
|
||||
swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
double Port::ull_to_double(ulonglong ull)
|
||||
{
|
||||
return (double) ull;
|
||||
}
|
||||
|
||||
const char *Port::list_separator()
|
||||
{
|
||||
return ",";
|
||||
}
|
||||
|
||||
const wchar_t *Port::wlist_separator()
|
||||
{
|
||||
return L",";
|
||||
/* In some cases, the REALPAD bytes get garbage in them,
|
||||
* so be sure and ignore them.
|
||||
*/
|
||||
return memcmp(&x, &y, 10) == 0;
|
||||
}
|
||||
|
||||
char *Port::strupr(char *s)
|
||||
@@ -928,6 +967,21 @@ char *Port::strupr(char *s)
|
||||
return t;
|
||||
}
|
||||
|
||||
float Port::strtof(const char *p, char **endp)
|
||||
{
|
||||
return ::strtof(p, endp);
|
||||
}
|
||||
|
||||
double Port::strtod(const char *p, char **endp)
|
||||
{
|
||||
return ::strtod(p, endp);
|
||||
}
|
||||
|
||||
longdouble Port::strtold(const char *p, char **endp)
|
||||
{
|
||||
return ::strtold(p, endp);
|
||||
}
|
||||
|
||||
longdouble Port::strtold(const char *p, char **endp)
|
||||
{
|
||||
return ::strtold(p, endp);
|
||||
|
||||
@@ -13,15 +13,13 @@
|
||||
#if defined(IN_LLVM) && (LDC_LLVM_VER >= 303)
|
||||
#include "llvm/Config/config.h"
|
||||
#endif
|
||||
#include <stdlib.h> // for alloca
|
||||
#include <stdint.h>
|
||||
|
||||
#include "longdouble.h"
|
||||
|
||||
#if _MSC_VER
|
||||
#include <float.h> // for _isnan
|
||||
#include <malloc.h> // for alloca
|
||||
#define strtof strtod
|
||||
#define isnan _isnan
|
||||
|
||||
#include <alloca.h>
|
||||
typedef __int64 longlong;
|
||||
typedef unsigned __int64 ulonglong;
|
||||
#else
|
||||
@@ -29,12 +27,17 @@ typedef long long longlong;
|
||||
typedef unsigned long long ulonglong;
|
||||
#endif
|
||||
|
||||
typedef double d_time;
|
||||
typedef unsigned char utf8_t;
|
||||
|
||||
struct Port
|
||||
{
|
||||
static double nan;
|
||||
static longdouble ldbl_nan;
|
||||
static longdouble snan;
|
||||
|
||||
static double infinity;
|
||||
static longdouble ldbl_infinity;
|
||||
|
||||
static double dbl_max;
|
||||
static double dbl_min;
|
||||
static longdouble ldbl_max;
|
||||
@@ -45,32 +48,18 @@ struct Port
|
||||
static int isSignallingNan(double);
|
||||
static int isSignallingNan(longdouble);
|
||||
|
||||
static int isFinite(double);
|
||||
static int isInfinity(double);
|
||||
static int Signbit(double);
|
||||
|
||||
static double floor(double);
|
||||
static double pow(double x, double y);
|
||||
|
||||
static longdouble fmodl(longdouble x, longdouble y);
|
||||
|
||||
static ulonglong strtoull(const char *p, char **pend, int base);
|
||||
|
||||
static char *ull_to_string(char *buffer, ulonglong ull);
|
||||
static wchar_t *ull_to_string(wchar_t *buffer, ulonglong ull);
|
||||
|
||||
// Convert ulonglong to double
|
||||
static double ull_to_double(ulonglong ull);
|
||||
|
||||
// Get locale-dependent list separator
|
||||
static const char *list_separator();
|
||||
static const wchar_t *wlist_separator();
|
||||
static int fequal(longdouble x, longdouble y);
|
||||
|
||||
static char *strupr(char *);
|
||||
|
||||
static int memicmp(const char *s1, const char *s2, int n);
|
||||
static int stricmp(const char *s1, const char *s2);
|
||||
|
||||
static float strtof(const char *p, char **endp);
|
||||
static double strtod(const char *p, char **endp);
|
||||
static longdouble strtold(const char *p, char **endp);
|
||||
};
|
||||
|
||||
|
||||
@@ -11,11 +11,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun
|
||||
#include "../root/rmem.h"
|
||||
#else
|
||||
#include "rmem.h"
|
||||
#endif
|
||||
|
||||
/* This implementation of the storage allocator uses the standard C allocation package.
|
||||
*/
|
||||
@@ -142,6 +138,61 @@ void Mem::addroots(char* pStart, char* pEnd)
|
||||
|
||||
/* =================================================== */
|
||||
|
||||
#if 1
|
||||
|
||||
/* Allocate, but never release
|
||||
*/
|
||||
|
||||
// Allocate a little less than 64kB because the C runtime adds some overhead that
|
||||
// causes the actual memory block to be larger than 64kB otherwise. E.g. the dmc
|
||||
// runtime rounds the size up to 128kB, but the remaining space in the chunk is less
|
||||
// than 64kB, so it cannot be used by another chunk.
|
||||
#define CHUNK_SIZE (4096 * 16 - 64)
|
||||
|
||||
static size_t heapleft = 0;
|
||||
static void *heapp;
|
||||
|
||||
void * operator new(size_t m_size)
|
||||
{
|
||||
// 16 byte alignment is better (and sometimes needed) for doubles
|
||||
m_size = (m_size + 15) & ~15;
|
||||
|
||||
// The layout of the code is selected so the most common case is straight through
|
||||
if (m_size <= heapleft)
|
||||
{
|
||||
L1:
|
||||
heapleft -= m_size;
|
||||
void *p = heapp;
|
||||
heapp = (void *)((char *)heapp + m_size);
|
||||
return p;
|
||||
}
|
||||
|
||||
if (m_size > CHUNK_SIZE)
|
||||
{
|
||||
void *p = malloc(m_size);
|
||||
if (p)
|
||||
return p;
|
||||
printf("Error: out of memory\n");
|
||||
exit(EXIT_FAILURE);
|
||||
return p;
|
||||
}
|
||||
|
||||
heapleft = CHUNK_SIZE;
|
||||
heapp = malloc(CHUNK_SIZE);
|
||||
if (!heapp)
|
||||
{
|
||||
printf("Error: out of memory\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
goto L1;
|
||||
}
|
||||
|
||||
void operator delete(void *p)
|
||||
{
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void * operator new(size_t m_size)
|
||||
{
|
||||
void *p = malloc(m_size);
|
||||
@@ -157,4 +208,4 @@ void operator delete(void *p)
|
||||
free(p);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -98,42 +98,42 @@ void warning(const char *format, ...)
|
||||
|
||||
/****************************** Object ********************************/
|
||||
|
||||
int Object::equals(Object *o)
|
||||
bool RootObject::equals(RootObject *o)
|
||||
{
|
||||
return o == this;
|
||||
}
|
||||
|
||||
hash_t Object::hashCode()
|
||||
hash_t RootObject::hashCode()
|
||||
{
|
||||
return (hash_t) this;
|
||||
}
|
||||
|
||||
int Object::compare(Object *obj)
|
||||
int RootObject::compare(RootObject *obj)
|
||||
{
|
||||
return this - obj;
|
||||
}
|
||||
|
||||
void Object::print()
|
||||
void RootObject::print()
|
||||
{
|
||||
printf("%s %p\n", toChars(), this);
|
||||
}
|
||||
|
||||
char *Object::toChars()
|
||||
char *RootObject::toChars()
|
||||
{
|
||||
return (char *)"Object";
|
||||
}
|
||||
|
||||
int Object::dyncast()
|
||||
int RootObject::dyncast()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Object::toBuffer(OutBuffer *b)
|
||||
void RootObject::toBuffer(OutBuffer *b)
|
||||
{
|
||||
b->writestring("Object");
|
||||
}
|
||||
|
||||
void Object::mark()
|
||||
void RootObject::mark()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -206,12 +206,12 @@ size_t String::len()
|
||||
return strlen(str);
|
||||
}
|
||||
|
||||
int String::equals(Object *obj)
|
||||
bool String::equals(RootObject *obj)
|
||||
{
|
||||
return strcmp(str,((String *)obj)->str) == 0;
|
||||
}
|
||||
|
||||
int String::compare(Object *obj)
|
||||
int String::compare(RootObject *obj)
|
||||
{
|
||||
return strcmp(str,((String *)obj)->str);
|
||||
}
|
||||
@@ -279,7 +279,7 @@ Strings *FileName::splitPath(const char *path)
|
||||
do
|
||||
{ char instring = 0;
|
||||
|
||||
while (isspace((unsigned char)*p)) // skip leading whitespace
|
||||
while (isspace((utf8_t)*p)) // skip leading whitespace
|
||||
p++;
|
||||
buf.reserve(strlen(p) + 1); // guess size of path
|
||||
for (; ; p++)
|
||||
@@ -345,7 +345,7 @@ hash_t FileName::hashCode()
|
||||
// We need a different hashCode because it must be case-insensitive
|
||||
size_t len = strlen(str);
|
||||
hash_t hash = 0;
|
||||
unsigned char *s = (unsigned char *)str;
|
||||
utf8_t *s = (utf8_t *)str;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
@@ -384,7 +384,7 @@ hash_t FileName::hashCode()
|
||||
#endif
|
||||
}
|
||||
|
||||
int FileName::compare(Object *obj)
|
||||
int FileName::compare(RootObject *obj)
|
||||
{
|
||||
return compare(str, ((FileName *)obj)->str);
|
||||
}
|
||||
@@ -398,7 +398,7 @@ int FileName::compare(const char *name1, const char *name2)
|
||||
#endif
|
||||
}
|
||||
|
||||
int FileName::equals(Object *obj)
|
||||
bool FileName::equals(RootObject *obj)
|
||||
{
|
||||
return compare(obj) == 0;
|
||||
}
|
||||
@@ -696,7 +696,7 @@ const char *FileName::searchPath(Strings *path, const char *name, int cwd)
|
||||
|
||||
for (size_t i = 0; i < path->dim; i++)
|
||||
{
|
||||
const char *p = path->tdata()[i];
|
||||
const char *p = (*path)[i];
|
||||
const char *n = combine(p, name);
|
||||
|
||||
if (exists(n))
|
||||
@@ -756,7 +756,7 @@ const char *FileName::safeSearchPath(Strings *path, const char *name)
|
||||
for (size_t i = 0; i < path->dim; i++)
|
||||
{
|
||||
const char *cname = NULL;
|
||||
const char *cpath = canonicalName(path->tdata()[i]);
|
||||
const char *cpath = canonicalName((*path)[i]);
|
||||
//printf("FileName::safeSearchPath(): name=%s; path=%s; cpath=%s\n",
|
||||
// name, (char *)path->data[i], cpath);
|
||||
if (cpath == NULL)
|
||||
@@ -829,7 +829,8 @@ void FileName::ensurePathExists(const char *path)
|
||||
{
|
||||
#if _WIN32
|
||||
size_t len = strlen(path);
|
||||
if (len > 2 && p[-1] == ':' && path + 2 == p)
|
||||
if ((len > 2 && p[-1] == ':' && strcmp(path + 2, p) == 0) ||
|
||||
len == strlen(p))
|
||||
{ mem.free((void *)p);
|
||||
return;
|
||||
}
|
||||
@@ -838,19 +839,20 @@ void FileName::ensurePathExists(const char *path)
|
||||
mem.free((void *)p);
|
||||
}
|
||||
#if _WIN32
|
||||
if (path[strlen(path) - 1] != '\\')
|
||||
#endif
|
||||
#if POSIX
|
||||
if (path[strlen(path) - 1] != '\\')
|
||||
char sep = '\\';
|
||||
#elif POSIX
|
||||
char sep = '/';
|
||||
#endif
|
||||
if (path[strlen(path) - 1] != sep)
|
||||
{
|
||||
//printf("mkdir(%s)\n", path);
|
||||
#if _WIN32
|
||||
if (_mkdir(path))
|
||||
int r = _mkdir(path);
|
||||
#endif
|
||||
#if POSIX
|
||||
if (mkdir(path, 0777))
|
||||
int r = mkdir(path, 0777);
|
||||
#endif
|
||||
if (r)
|
||||
{
|
||||
/* Don't error out if another instance of dmd just created
|
||||
* this directory
|
||||
@@ -1017,7 +1019,7 @@ int File::read()
|
||||
goto err2;
|
||||
}
|
||||
size = buf.st_size;
|
||||
buffer = (unsigned char *) ::malloc(size + 2);
|
||||
buffer = (utf8_t *) ::malloc(size + 2);
|
||||
if (!buffer)
|
||||
{
|
||||
printf("\tmalloc error, errno = %d\n",errno);
|
||||
@@ -1075,7 +1077,7 @@ err1:
|
||||
ref = 0;
|
||||
|
||||
size = GetFileSize(h,NULL);
|
||||
buffer = (unsigned char *) ::malloc(size + 2);
|
||||
buffer = (utf8_t *) ::malloc(size + 2);
|
||||
if (!buffer)
|
||||
goto err2;
|
||||
|
||||
@@ -1151,7 +1153,7 @@ int File::mmread()
|
||||
if (!ref)
|
||||
mem.free(buffer);
|
||||
ref = 2;
|
||||
buffer = (unsigned char *)MapViewOfFileEx(hFileMap, FILE_MAP_READ,0,0,size,NULL);
|
||||
buffer = (utf8_t *)MapViewOfFileEx(hFileMap, FILE_MAP_READ,0,0,size,NULL);
|
||||
if (CloseHandle(hFileMap) != TRUE)
|
||||
goto Lerr;
|
||||
if (buffer == NULL) // mapping view failed
|
||||
@@ -1359,7 +1361,7 @@ int File::exists()
|
||||
void File::remove()
|
||||
{
|
||||
#if POSIX
|
||||
::remove(this->name->toChars());
|
||||
int dummy = ::remove(this->name->toChars());
|
||||
#elif _WIN32
|
||||
DeleteFileA(this->name->toChars());
|
||||
#else
|
||||
@@ -1469,7 +1471,7 @@ OutBuffer::OutBuffer()
|
||||
|
||||
doindent = 0;
|
||||
level = 0;
|
||||
linehead = 1;
|
||||
notlinehead = 0;
|
||||
}
|
||||
|
||||
OutBuffer::~OutBuffer()
|
||||
@@ -1499,7 +1501,8 @@ void OutBuffer::reserve(size_t nbytes)
|
||||
if (size - offset < nbytes)
|
||||
{
|
||||
size = (offset + nbytes) * 2;
|
||||
data = (unsigned char *)mem.realloc(data, size);
|
||||
size = (size + 15) & ~15;
|
||||
data = (utf8_t *)mem.realloc(data, size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1515,7 +1518,7 @@ void OutBuffer::setsize(size_t size)
|
||||
|
||||
void OutBuffer::write(const void *data, size_t nbytes)
|
||||
{
|
||||
if (doindent && linehead)
|
||||
if (doindent && !notlinehead)
|
||||
{
|
||||
if (level)
|
||||
{
|
||||
@@ -1526,14 +1529,14 @@ void OutBuffer::write(const void *data, size_t nbytes)
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
linehead = 0;
|
||||
notlinehead = 1;
|
||||
}
|
||||
reserve(nbytes);
|
||||
memcpy(this->data + offset, data, nbytes);
|
||||
offset += nbytes;
|
||||
}
|
||||
|
||||
void OutBuffer::writebstring(unsigned char *string)
|
||||
void OutBuffer::writebstring(utf8_t *string)
|
||||
{
|
||||
write(string,*string + 1);
|
||||
}
|
||||
@@ -1560,12 +1563,12 @@ void OutBuffer::writenl()
|
||||
writeByte('\n');
|
||||
#endif
|
||||
if (doindent)
|
||||
linehead = 1;
|
||||
notlinehead = 0;
|
||||
}
|
||||
|
||||
void OutBuffer::writeByte(unsigned b)
|
||||
{
|
||||
if (doindent && linehead
|
||||
if (doindent && !notlinehead
|
||||
&& b != '\n')
|
||||
{
|
||||
if (level)
|
||||
@@ -1577,7 +1580,7 @@ void OutBuffer::writeByte(unsigned b)
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
linehead = 0;
|
||||
notlinehead = 1;
|
||||
}
|
||||
reserve(1);
|
||||
this->data[offset] = (unsigned char)b;
|
||||
@@ -1655,12 +1658,13 @@ void OutBuffer::writewchar(unsigned w)
|
||||
|
||||
void OutBuffer::writeword(unsigned w)
|
||||
{
|
||||
if (doindent && linehead
|
||||
#if _WIN32
|
||||
&& w != 0x0A0D)
|
||||
unsigned newline = 0x0A0D;
|
||||
#else
|
||||
&& w != '\n')
|
||||
unsigned newline = '\n';
|
||||
#endif
|
||||
if (doindent && !notlinehead
|
||||
&& w != newline)
|
||||
{
|
||||
if (level)
|
||||
{
|
||||
@@ -1671,7 +1675,7 @@ void OutBuffer::writeword(unsigned w)
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
linehead = 0;
|
||||
notlinehead = 1;
|
||||
}
|
||||
reserve(2);
|
||||
*(unsigned short *)(this->data + offset) = (unsigned short)w;
|
||||
@@ -1698,12 +1702,12 @@ void OutBuffer::writeUTF16(unsigned w)
|
||||
|
||||
void OutBuffer::write4(unsigned w)
|
||||
{
|
||||
if (doindent && linehead
|
||||
#if _WIN32
|
||||
&& w != 0x000A000D)
|
||||
bool notnewline = w != 0x000A000D;
|
||||
#else
|
||||
)
|
||||
bool notnewline = true;
|
||||
#endif
|
||||
if (doindent && !notlinehead && notnewline)
|
||||
{
|
||||
if (level)
|
||||
{
|
||||
@@ -1714,7 +1718,7 @@ void OutBuffer::write4(unsigned w)
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
linehead = 0;
|
||||
notlinehead = 1;
|
||||
}
|
||||
reserve(4);
|
||||
*(unsigned *)(this->data + offset) = w;
|
||||
@@ -1730,7 +1734,7 @@ void OutBuffer::write(OutBuffer *buf)
|
||||
}
|
||||
}
|
||||
|
||||
void OutBuffer::write(Object *obj)
|
||||
void OutBuffer::write(RootObject *obj)
|
||||
{
|
||||
if (obj)
|
||||
{
|
||||
|
||||
272
dmd2/root/root.h
272
dmd2/root/root.h
@@ -12,10 +12,10 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#ifdef DEBUG
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#endif
|
||||
#include "port.h"
|
||||
#include "rmem.h"
|
||||
|
||||
#if __DMC__
|
||||
#pragma once
|
||||
@@ -30,17 +30,18 @@ typedef size_t hash_t;
|
||||
struct OutBuffer;
|
||||
|
||||
// Can't include arraytypes.h here, need to declare these directly.
|
||||
template <typename TYPE> struct ArrayBase;
|
||||
typedef ArrayBase<struct File> Files;
|
||||
typedef ArrayBase<char> Strings;
|
||||
template <typename TYPE> struct Array;
|
||||
typedef Array<class File> Files;
|
||||
typedef Array<char> Strings;
|
||||
|
||||
|
||||
struct Object
|
||||
class RootObject
|
||||
{
|
||||
Object() { }
|
||||
virtual ~Object() { }
|
||||
public:
|
||||
RootObject() { }
|
||||
virtual ~RootObject() { }
|
||||
|
||||
virtual int equals(Object *o);
|
||||
virtual bool equals(RootObject *o);
|
||||
|
||||
/**
|
||||
* Returns a hash code, useful for things like building hash tables of Objects.
|
||||
@@ -51,7 +52,7 @@ struct Object
|
||||
* Return <0, ==0, or >0 if this is less than, equal to, or greater than obj.
|
||||
* Useful for sorting Objects.
|
||||
*/
|
||||
virtual int compare(Object *obj);
|
||||
virtual int compare(RootObject *obj);
|
||||
|
||||
/**
|
||||
* Pretty-print an Object. Useful for debugging the old-fashioned way.
|
||||
@@ -74,8 +75,9 @@ struct Object
|
||||
void mark();
|
||||
};
|
||||
|
||||
struct String : Object
|
||||
class String : public RootObject
|
||||
{
|
||||
public:
|
||||
const char *str; // the string itself
|
||||
|
||||
String(const char *str);
|
||||
@@ -85,20 +87,21 @@ struct String : Object
|
||||
static hash_t calcHash(const char *str);
|
||||
hash_t hashCode();
|
||||
size_t len();
|
||||
int equals(Object *obj);
|
||||
int compare(Object *obj);
|
||||
bool equals(RootObject *obj);
|
||||
int compare(RootObject *obj);
|
||||
char *toChars();
|
||||
void print();
|
||||
void mark();
|
||||
};
|
||||
|
||||
struct FileName : String
|
||||
class FileName : public String
|
||||
{
|
||||
public:
|
||||
FileName(const char *str);
|
||||
hash_t hashCode();
|
||||
int equals(Object *obj);
|
||||
bool equals(RootObject *obj);
|
||||
static int equals(const char *name1, const char *name2);
|
||||
int compare(Object *obj);
|
||||
int compare(RootObject *obj);
|
||||
static int compare(const char *name1, const char *name2);
|
||||
static int absolute(const char *name);
|
||||
static const char *ext(const char *);
|
||||
@@ -128,8 +131,9 @@ struct FileName : String
|
||||
static void free(const char *str);
|
||||
};
|
||||
|
||||
struct File : Object
|
||||
class File : public RootObject
|
||||
{
|
||||
public:
|
||||
int ref; // != 0 if this is a reference to someone else's buffer
|
||||
unsigned char *buffer; // data for our file
|
||||
size_t len; // amount of data in buffer[]
|
||||
@@ -233,13 +237,15 @@ struct File : Object
|
||||
void remove(); // delete file
|
||||
};
|
||||
|
||||
struct OutBuffer : Object
|
||||
struct OutBuffer
|
||||
{
|
||||
unsigned char *data;
|
||||
size_t offset;
|
||||
size_t size;
|
||||
|
||||
int doindent, level, linehead;
|
||||
int doindent;
|
||||
int level;
|
||||
int notlinehead;
|
||||
|
||||
OutBuffer();
|
||||
~OutBuffer();
|
||||
@@ -263,7 +269,7 @@ struct OutBuffer : Object
|
||||
void writeUTF16(unsigned w);
|
||||
void write4(unsigned w);
|
||||
void write(OutBuffer *buf);
|
||||
void write(Object *obj);
|
||||
void write(RootObject *obj);
|
||||
void fill0(size_t nbytes);
|
||||
void align(size_t size);
|
||||
void vprintf(const char *format, va_list args);
|
||||
@@ -277,45 +283,178 @@ struct OutBuffer : Object
|
||||
char *extractString();
|
||||
};
|
||||
|
||||
template <typename TYPE>
|
||||
struct Array
|
||||
{
|
||||
size_t dim;
|
||||
void **data;
|
||||
TYPE **data;
|
||||
|
||||
private:
|
||||
size_t allocdim;
|
||||
#define SMALLARRAYCAP 1
|
||||
void *smallarray[SMALLARRAYCAP]; // inline storage for small arrays
|
||||
TYPE *smallarray[SMALLARRAYCAP]; // inline storage for small arrays
|
||||
|
||||
public:
|
||||
Array();
|
||||
~Array();
|
||||
//Array(const Array&);
|
||||
void mark();
|
||||
char *toChars();
|
||||
Array()
|
||||
{
|
||||
data = SMALLARRAYCAP ? &smallarray[0] : NULL;
|
||||
dim = 0;
|
||||
allocdim = SMALLARRAYCAP;
|
||||
}
|
||||
|
||||
void reserve(size_t nentries);
|
||||
void setDim(size_t newdim);
|
||||
void fixDim();
|
||||
void push(void *ptr);
|
||||
void *pop();
|
||||
void shift(void *ptr);
|
||||
void insert(size_t index, void *ptr);
|
||||
void insert(size_t index, Array *a);
|
||||
void append(Array *a);
|
||||
void remove(size_t i);
|
||||
void zero();
|
||||
void *tos();
|
||||
void sort();
|
||||
Array *copy();
|
||||
};
|
||||
~Array()
|
||||
{
|
||||
if (data != &smallarray[0])
|
||||
mem.free(data);
|
||||
}
|
||||
|
||||
void mark()
|
||||
{
|
||||
mem.mark(data);
|
||||
for (size_t u = 0; u < dim; u++)
|
||||
mem.mark(data[u]); // BUG: what if arrays of Object's?
|
||||
}
|
||||
|
||||
char *toChars()
|
||||
{
|
||||
char **buf = (char **)malloc(dim * sizeof(char *));
|
||||
assert(buf);
|
||||
size_t len = 2;
|
||||
for (size_t u = 0; u < dim; u++)
|
||||
{
|
||||
buf[u] = ((RootObject *)data[u])->toChars();
|
||||
len += strlen(buf[u]) + 1;
|
||||
}
|
||||
char *str = (char *)mem.malloc(len);
|
||||
|
||||
str[0] = '[';
|
||||
char *p = str + 1;
|
||||
for (size_t u = 0; u < dim; u++)
|
||||
{
|
||||
if (u)
|
||||
*p++ = ',';
|
||||
len = strlen(buf[u]);
|
||||
memcpy(p,buf[u],len);
|
||||
p += len;
|
||||
}
|
||||
*p++ = ']';
|
||||
*p = 0;
|
||||
free(buf);
|
||||
return str;
|
||||
}
|
||||
|
||||
void reserve(size_t nentries)
|
||||
{
|
||||
//printf("Array::reserve: dim = %d, allocdim = %d, nentries = %d\n", (int)dim, (int)allocdim, (int)nentries);
|
||||
if (allocdim - dim < nentries)
|
||||
{
|
||||
if (allocdim == 0)
|
||||
{ // Not properly initialized, someone memset it to zero
|
||||
if (nentries <= SMALLARRAYCAP)
|
||||
{ allocdim = SMALLARRAYCAP;
|
||||
data = SMALLARRAYCAP ? &smallarray[0] : NULL;
|
||||
}
|
||||
else
|
||||
{ allocdim = nentries;
|
||||
data = (TYPE **)mem.malloc(allocdim * sizeof(*data));
|
||||
}
|
||||
}
|
||||
else if (allocdim == SMALLARRAYCAP)
|
||||
{
|
||||
allocdim = dim + nentries;
|
||||
data = (TYPE **)mem.malloc(allocdim * sizeof(*data));
|
||||
memcpy(data, &smallarray[0], dim * sizeof(*data));
|
||||
}
|
||||
else
|
||||
{ allocdim = dim + nentries;
|
||||
data = (TYPE **)mem.realloc(data, allocdim * sizeof(*data));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setDim(size_t newdim)
|
||||
{
|
||||
if (dim < newdim)
|
||||
{
|
||||
reserve(newdim - dim);
|
||||
}
|
||||
dim = newdim;
|
||||
}
|
||||
|
||||
void fixDim()
|
||||
{
|
||||
if (dim != allocdim)
|
||||
{
|
||||
if (allocdim >= SMALLARRAYCAP)
|
||||
{
|
||||
if (dim <= SMALLARRAYCAP)
|
||||
{
|
||||
memcpy(&smallarray[0], data, dim * sizeof(*data));
|
||||
mem.free(data);
|
||||
}
|
||||
else
|
||||
data = (TYPE **)mem.realloc(data, dim * sizeof(*data));
|
||||
}
|
||||
allocdim = dim;
|
||||
}
|
||||
}
|
||||
|
||||
TYPE *pop()
|
||||
{
|
||||
return data[--dim];
|
||||
}
|
||||
|
||||
void shift(TYPE *ptr)
|
||||
{
|
||||
reserve(1);
|
||||
memmove(data + 1, data, dim * sizeof(*data));
|
||||
data[0] = ptr;
|
||||
dim++;
|
||||
}
|
||||
|
||||
void remove(size_t i)
|
||||
{
|
||||
if (dim - i - 1)
|
||||
memmove(data + i, data + i + 1, (dim - i - 1) * sizeof(data[0]));
|
||||
dim--;
|
||||
}
|
||||
|
||||
void zero()
|
||||
{
|
||||
memset(data,0,dim * sizeof(data[0]));
|
||||
}
|
||||
|
||||
TYPE *tos()
|
||||
{
|
||||
return dim ? data[dim - 1] : NULL;
|
||||
}
|
||||
|
||||
void sort()
|
||||
{
|
||||
struct ArraySort
|
||||
{
|
||||
static int
|
||||
#if _WIN32
|
||||
__cdecl
|
||||
#endif
|
||||
Array_sort_compare(const void *x, const void *y)
|
||||
{
|
||||
RootObject *ox = *(RootObject **)x;
|
||||
RootObject *oy = *(RootObject **)y;
|
||||
|
||||
return ox->compare(oy);
|
||||
}
|
||||
};
|
||||
|
||||
if (dim)
|
||||
{
|
||||
qsort(data, dim, sizeof(RootObject *), &ArraySort::Array_sort_compare);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TYPE>
|
||||
struct ArrayBase : Array
|
||||
{
|
||||
TYPE **tdata()
|
||||
{
|
||||
return (TYPE **)data;
|
||||
return data;
|
||||
}
|
||||
|
||||
TYPE*& operator[] (size_t index)
|
||||
@@ -323,36 +462,52 @@ struct ArrayBase : Array
|
||||
#ifdef DEBUG
|
||||
assert(index < dim);
|
||||
#endif
|
||||
return ((TYPE **)data)[index];
|
||||
return data[index];
|
||||
}
|
||||
|
||||
void insert(size_t index, TYPE *v)
|
||||
{
|
||||
Array::insert(index, (void *)v);
|
||||
reserve(1);
|
||||
memmove(data + index + 1, data + index, (dim - index) * sizeof(*data));
|
||||
data[index] = v;
|
||||
dim++;
|
||||
}
|
||||
|
||||
void insert(size_t index, ArrayBase *a)
|
||||
void insert(size_t index, Array *a)
|
||||
{
|
||||
Array::insert(index, (Array *)a);
|
||||
if (a)
|
||||
{
|
||||
size_t d = a->dim;
|
||||
reserve(d);
|
||||
if (dim != index)
|
||||
memmove(data + index + d, data + index, (dim - index) * sizeof(*data));
|
||||
memcpy(data + index, a->data, d * sizeof(*data));
|
||||
dim += d;
|
||||
}
|
||||
}
|
||||
|
||||
void append(ArrayBase *a)
|
||||
void append(Array *a)
|
||||
{
|
||||
Array::append((Array *)a);
|
||||
insert(dim, a);
|
||||
}
|
||||
|
||||
void push(TYPE *a)
|
||||
{
|
||||
Array::push((void *)a);
|
||||
reserve(1);
|
||||
data[dim++] = a;
|
||||
}
|
||||
|
||||
ArrayBase *copy()
|
||||
Array *copy()
|
||||
{
|
||||
return (ArrayBase *)Array::copy();
|
||||
Array *a = new Array();
|
||||
|
||||
a->setDim(dim);
|
||||
memcpy(a->data, data, dim * sizeof(*data));
|
||||
return a;
|
||||
}
|
||||
|
||||
typedef int (*ArrayBase_apply_ft_t)(TYPE *, void *);
|
||||
int apply(ArrayBase_apply_ft_t fp, void *param)
|
||||
typedef int (*Array_apply_ft_t)(TYPE *, void *);
|
||||
int apply(Array_apply_ft_t fp, void *param)
|
||||
{
|
||||
for (size_t i = 0; i < dim; i++)
|
||||
{ TYPE *e = (*this)[i];
|
||||
@@ -368,8 +523,9 @@ struct ArrayBase : Array
|
||||
};
|
||||
|
||||
// TODO: Remove (only used by disabled GC)
|
||||
struct Bits : Object
|
||||
class Bits : public RootObject
|
||||
{
|
||||
public:
|
||||
unsigned bitdim;
|
||||
unsigned allocdim;
|
||||
unsigned *data;
|
||||
|
||||
Reference in New Issue
Block a user