mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-03-18 01:51:49 +01:00
First import of dmd-2.065-b1 (7088593).
The CPP mangling is not integrated yet.
This commit is contained in:
@@ -1,499 +0,0 @@
|
||||
|
||||
|
||||
// Copyright (c) 2000-2011 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>
|
||||
|
||||
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include "rmem.h"
|
||||
#include "gc/gc.h"
|
||||
//#include "printf.h"
|
||||
|
||||
/* This implementation of the storage allocator uses the Digital Mars gc.
|
||||
*/
|
||||
|
||||
Mem mem;
|
||||
|
||||
//static int nuncollectable;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void gc_init();
|
||||
GC *gc_get();
|
||||
}
|
||||
|
||||
void Mem::init()
|
||||
{
|
||||
gc_init();
|
||||
}
|
||||
|
||||
char *Mem::strdup(const char *s)
|
||||
{
|
||||
return gc_get()->strdup(s);
|
||||
}
|
||||
|
||||
void *Mem::malloc(size_t size)
|
||||
{
|
||||
if (gc) // if cached allocator
|
||||
{
|
||||
// PRINTF("Using cached gc for size %d, file = '%s', line = %d\n", size, GC::file, GC::line);
|
||||
// GC::file = NULL;
|
||||
// GC::line = 0;
|
||||
return ((GC *)gc)->malloc(size);
|
||||
}
|
||||
if (this == &mem) // don't cache global mem
|
||||
{
|
||||
// PRINTF("Using global gc for size %d, file = '%s', line = %d\n", size, GC::file, GC::line);
|
||||
// GC::file = NULL;
|
||||
// GC::line = 0;
|
||||
return gc_get()->malloc(size);
|
||||
}
|
||||
// PRINTF("Generating cached gc for size %d, file = '%s', line = %d\n", size, GC::file, GC::line);
|
||||
gc = gc_get();
|
||||
return gc->malloc(size);
|
||||
}
|
||||
|
||||
void *Mem::malloc_uncollectable(size_t size)
|
||||
{ void *p;
|
||||
|
||||
p = ::malloc(size);
|
||||
if (!p)
|
||||
error();
|
||||
addroots((char *)p, (char *)p + size);
|
||||
|
||||
#if 0
|
||||
++nuncollectable;
|
||||
WPRINTF(L"malloc_uncollectable(%u) = %x, n=%d\n", size, p, nuncollectable);
|
||||
#endif
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void *Mem::calloc(size_t size, size_t n)
|
||||
{
|
||||
return gc_get()->calloc(size, n);
|
||||
}
|
||||
|
||||
void *Mem::realloc(void *p, size_t size)
|
||||
{
|
||||
return gc_get()->realloc(p, size);
|
||||
}
|
||||
|
||||
void Mem::free(void *p)
|
||||
{
|
||||
gc_get()->free(p);
|
||||
}
|
||||
|
||||
void Mem::free_uncollectable(void *p)
|
||||
{
|
||||
if (p)
|
||||
{ removeroots((char *)p);
|
||||
::free(p);
|
||||
|
||||
#if 0
|
||||
--nuncollectable;
|
||||
WPRINTF(L"free_uncollectable(%x) n=%d\n", p, nuncollectable);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
gc_get()->fullcollect();
|
||||
|
||||
GCStats stats;
|
||||
|
||||
getStats(&stats);
|
||||
WPRINTF(L"poolsize = %x, usedsize = %x, freelistsize = %x\n",
|
||||
stats.poolsize, stats.usedsize, stats.freelistsize);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void *Mem::mallocdup(void *o, size_t size)
|
||||
{
|
||||
return gc_get()->mallocdup(o, size);
|
||||
}
|
||||
|
||||
void Mem::check(void *p)
|
||||
{
|
||||
if (gc)
|
||||
gc->check(p);
|
||||
else
|
||||
gc_get()->check(p);
|
||||
}
|
||||
|
||||
void Mem::error()
|
||||
{
|
||||
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun
|
||||
assert(0);
|
||||
#endif
|
||||
printf("Error: out of memory\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void Mem::fullcollect()
|
||||
{
|
||||
gc_get()->fullcollect();
|
||||
|
||||
#if 0
|
||||
{
|
||||
GCStats stats;
|
||||
|
||||
gc_get()->getStats(&stats);
|
||||
WPRINTF(L"Thread %x ", Thread::getId());
|
||||
WPRINTF(L"poolsize=x%x, usedsize=x%x, freelistsize=x%x, freeblocks=%d, pageblocks=%d\n",
|
||||
stats.poolsize, stats.usedsize, stats.freelistsize, stats.freeblocks, stats.pageblocks);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void Mem::fullcollectNoStack()
|
||||
{
|
||||
gc_get()->fullcollectNoStack();
|
||||
|
||||
#if 0
|
||||
{
|
||||
GCStats stats;
|
||||
|
||||
gc_get()->getStats(&stats);
|
||||
WPRINTF(L"Thread %x ", Thread::getId());
|
||||
WPRINTF(L"poolsize=x%x, usedsize=x%x, freelistsize=x%x, freeblocks=%d, pageblocks=%d\n",
|
||||
stats.poolsize, stats.usedsize, stats.freelistsize, stats.freeblocks, stats.pageblocks);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void Mem::mark(void *pointer)
|
||||
{
|
||||
(void) pointer; // for VC /W4 compatibility
|
||||
}
|
||||
|
||||
|
||||
void Mem::addroots(char* pStart, char* pEnd)
|
||||
{
|
||||
gc_get()->addRange(pStart, pEnd);
|
||||
}
|
||||
|
||||
|
||||
void Mem::removeroots(char* pStart)
|
||||
{
|
||||
gc_get()->removeRange(pStart);
|
||||
}
|
||||
|
||||
|
||||
void Mem::setFinalizer(void* pObj, FINALIZERPROC pFn, void* pClientData)
|
||||
{
|
||||
(void)pClientData;
|
||||
gc_get()->setFinalizer(pObj, pFn);
|
||||
}
|
||||
|
||||
|
||||
void Mem::setStackBottom(void *stackbottom)
|
||||
{
|
||||
gc_get()->setStackBottom(stackbottom);
|
||||
}
|
||||
|
||||
|
||||
GC *Mem::getThreadGC()
|
||||
{
|
||||
return gc_get();
|
||||
}
|
||||
|
||||
|
||||
/* =================================================== */
|
||||
|
||||
#if 1
|
||||
void * operator new(size_t m_size)
|
||||
{
|
||||
//PRINTF("Call to global operator new(%d), file = '%s', line = %d\n", m_size, GC::file ? GC::file : "(null)", GC::line);
|
||||
GC::file = NULL;
|
||||
GC::line = 0;
|
||||
return mem.malloc(m_size);
|
||||
}
|
||||
|
||||
void operator delete(void *p)
|
||||
{
|
||||
//WPRINTF(L"Call to global operator delete\n");
|
||||
mem.free(p);
|
||||
}
|
||||
|
||||
void* operator new[](size_t size)
|
||||
{
|
||||
return operator new(size);
|
||||
}
|
||||
|
||||
void operator delete[](void *pv)
|
||||
{
|
||||
operator delete(pv);
|
||||
}
|
||||
#endif
|
||||
|
||||
void * Mem::operator new(size_t m_size)
|
||||
{ void *p;
|
||||
|
||||
p = gc_get()->malloc(m_size);
|
||||
//printf("Mem::operator new(%d) = %p\n", m_size, p);
|
||||
if (!p)
|
||||
mem.error();
|
||||
return p;
|
||||
}
|
||||
|
||||
void * Mem::operator new(size_t m_size, Mem *mem)
|
||||
{ void *p;
|
||||
|
||||
p = mem->malloc(m_size);
|
||||
//printf("Mem::operator new(%d) = %p\n", m_size, p);
|
||||
if (!p)
|
||||
::mem.error();
|
||||
return p;
|
||||
}
|
||||
|
||||
void * Mem::operator new(size_t m_size, GC *gc)
|
||||
{ void *p;
|
||||
|
||||
// if (!gc)
|
||||
// WPRINTF(L"gc is NULL\n");
|
||||
p = gc->malloc(m_size);
|
||||
//printf("Mem::operator new(%d) = %p\n", m_size, p);
|
||||
if (!p)
|
||||
::mem.error();
|
||||
return p;
|
||||
}
|
||||
|
||||
void Mem::operator delete(void *p)
|
||||
{
|
||||
// printf("Mem::operator delete(%p)\n", p);
|
||||
gc_get()->free(p);
|
||||
}
|
||||
|
||||
/* ============================================================ */
|
||||
|
||||
/* The following section of code exists to find the right
|
||||
* garbage collector for this thread. There is one independent instance
|
||||
* of the collector per thread.
|
||||
*/
|
||||
|
||||
/* ===================== linux ================================ */
|
||||
|
||||
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#define LOG 0 // log thread creation / destruction
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
// Key identifying the thread-specific data
|
||||
static pthread_key_t gc_key;
|
||||
|
||||
/* "Once" variable ensuring that the key for gc_alloc will be allocated
|
||||
* exactly once.
|
||||
*/
|
||||
static pthread_once_t gc_alloc_key_once = PTHREAD_ONCE_INIT;
|
||||
|
||||
/* Forward functions */
|
||||
static void gc_alloc_key();
|
||||
static void gc_alloc_destroy_gc(void * accu);
|
||||
|
||||
|
||||
void gc_init()
|
||||
{
|
||||
#if LOG
|
||||
WPRINTF(L"Thread %lx: gc_init()\n", pthread_self());
|
||||
#endif
|
||||
pthread_once(&gc_alloc_key_once, gc_alloc_key);
|
||||
#if LOG
|
||||
WPRINTF(L"Thread %lx: gc_init() return\n", pthread_self());
|
||||
#endif
|
||||
}
|
||||
|
||||
GC *gc_get()
|
||||
{
|
||||
GC *gc;
|
||||
|
||||
// Get the thread-specific data associated with the key
|
||||
gc = (GC *) pthread_getspecific(gc_key);
|
||||
|
||||
// It's initially NULL, meaning that we must allocate the buffer first.
|
||||
if (gc == NULL)
|
||||
{
|
||||
GC_LOG();
|
||||
gc = new GC();
|
||||
gc->init();
|
||||
|
||||
// Store the buffer pointer in the thread-specific data.
|
||||
pthread_setspecific(gc_key, (void *) gc);
|
||||
#if LOG
|
||||
WPRINTF(L"Thread %lx: allocating gc at %x\n", pthread_self(), gc);
|
||||
#endif
|
||||
}
|
||||
return gc;
|
||||
}
|
||||
|
||||
// Function to allocate the key for gc_alloc thread-specific data.
|
||||
|
||||
static void gc_alloc_key()
|
||||
{
|
||||
pthread_key_create(&gc_key, gc_alloc_destroy_gc);
|
||||
#if LOG
|
||||
WPRINTF(L"Thread %lx: allocated gc key %d\n", pthread_self(), gc_key);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Function to free the buffer when the thread exits.
|
||||
// Called only when the thread-specific data is not NULL.
|
||||
|
||||
static void gc_alloc_destroy_gc(void *gc)
|
||||
{
|
||||
#if LOG
|
||||
WPRINTF(L"Thread %x: freeing gc at %x\n", pthread_self(), gc);
|
||||
#endif
|
||||
delete (GC *)gc;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ===================== win32 ================================ */
|
||||
|
||||
#if !defined(linux) && defined(_WIN32)
|
||||
|
||||
#if 1 // single threaded version
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
static GC *gc;
|
||||
|
||||
void gc_init()
|
||||
{
|
||||
if (!gc)
|
||||
{ gc = (GC *)::malloc(sizeof(GC));
|
||||
gc->init();
|
||||
}
|
||||
}
|
||||
|
||||
GC *gc_get()
|
||||
{
|
||||
return gc;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#else // multi threaded version
|
||||
|
||||
#include "mutex.h"
|
||||
#include "thread.h"
|
||||
|
||||
/* This is the win32 version. It suffers from the bug that
|
||||
* when the thread exits the data structure is not cleared,
|
||||
* but the memory pool it points to is free'd.
|
||||
* Thus, if a new thread comes along with the same thread id,
|
||||
* the data will look initialized, but will point to garbage.
|
||||
*
|
||||
* What needs to happen is when a thread exits, the associated
|
||||
* GC_context data struct is cleared.
|
||||
*/
|
||||
|
||||
struct GC_context
|
||||
{
|
||||
ThreadId threadid; // identifier of current thread
|
||||
GC *gc;
|
||||
};
|
||||
|
||||
Mutex gc_mutex;
|
||||
|
||||
static GC_context array[64];
|
||||
|
||||
// Array of pointers to GC_context objects, one per threadid
|
||||
GC_context *gccontext = array;
|
||||
unsigned gccontext_allocdim = 64;
|
||||
unsigned gccontext_dim;
|
||||
|
||||
ThreadId gc_cache_ti;
|
||||
GC_context *gc_cache_cc;
|
||||
|
||||
extern "C" void gc_init()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
extern "C" GC *gc_get()
|
||||
{
|
||||
/* This works by creating an array of GC_context's, one
|
||||
* for each thread. We match up by thread id.
|
||||
*/
|
||||
|
||||
ThreadId ti;
|
||||
GC_context *cc;
|
||||
|
||||
//PRINTF("gc_get()\n");
|
||||
|
||||
ti = Thread::getId();
|
||||
gc_mutex.acquire();
|
||||
|
||||
// Used cached version if we can
|
||||
if (ti == gc_cache_ti)
|
||||
{
|
||||
cc = gc_cache_cc;
|
||||
//exception(L"getGC_context(): cache x%x", ti);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This does a linear search through gccontext[].
|
||||
// A hash table might be faster if there are more
|
||||
// than a dozen threads.
|
||||
GC_context *ccp;
|
||||
GC_context *ccptop = &gccontext[gccontext_dim];
|
||||
for (ccp = gccontext; ccp < ccptop; ccp++)
|
||||
{
|
||||
cc = ccp;
|
||||
if (cc->threadid == ti)
|
||||
{
|
||||
WPRINTF(L"getGC_context(): existing x%x", ti);
|
||||
goto Lret;
|
||||
}
|
||||
}
|
||||
|
||||
// Do not allocate with garbage collector, as this must reside
|
||||
// global to all threads.
|
||||
|
||||
assert(gccontext_dim < gccontext_allocdim);
|
||||
cc = ccp;
|
||||
memset(cc, 0, sizeof(*cc));
|
||||
cc->threadid = ti;
|
||||
cc->gc = new GC();
|
||||
cc->gc->init();
|
||||
|
||||
gccontext_dim++;
|
||||
WPRINTF(L"getGC_context(): new x%x\n", ti);
|
||||
|
||||
Lret:
|
||||
// Cache for next time
|
||||
gc_cache_ti = ti;
|
||||
gc_cache_cc = cc;
|
||||
}
|
||||
|
||||
gc_mutex.release();
|
||||
return cc->gc;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
@@ -520,6 +520,16 @@ int ld_type(longdouble x)
|
||||
|
||||
size_t ld_sprint(char* str, int fmt, longdouble x)
|
||||
{
|
||||
// ensure dmc compatible strings for nan and inf
|
||||
switch(ld_type(x))
|
||||
{
|
||||
case LD_TYPE_QNAN:
|
||||
case LD_TYPE_SNAN:
|
||||
return sprintf(str, "nan");
|
||||
case LD_TYPE_INFINITE:
|
||||
return sprintf(str, x.sign ? "-inf" : "inf");
|
||||
}
|
||||
|
||||
// fmt is 'a','A','f' or 'g'
|
||||
if(fmt != 'a' && fmt != 'A')
|
||||
{
|
||||
@@ -537,16 +547,8 @@ size_t ld_sprint(char* str, int fmt, longdouble x)
|
||||
unsigned short exp = x.exponent;
|
||||
unsigned long long mantissa = x.mantissa;
|
||||
|
||||
switch(ld_type(x))
|
||||
{
|
||||
case LD_TYPE_ZERO:
|
||||
if(ld_type(x) == LD_TYPE_ZERO)
|
||||
return sprintf(str, "0x0.0L");
|
||||
case LD_TYPE_QNAN:
|
||||
case LD_TYPE_SNAN:
|
||||
return sprintf(str, "NAN");
|
||||
case LD_TYPE_INFINITE:
|
||||
return sprintf(str, x.sign ? "-INF" : "INF");
|
||||
}
|
||||
|
||||
size_t len = 0;
|
||||
if(x.sign)
|
||||
|
||||
@@ -763,7 +763,7 @@ int Port::isInfinity(double r)
|
||||
|
||||
longdouble Port::fmodl(longdouble x, longdouble y)
|
||||
{
|
||||
#if __FreeBSD__ || __OpenBSD__
|
||||
#if __FreeBSD__ && __FreeBSD_version < 800000 || __OpenBSD__
|
||||
return ::fmod(x, y); // hack for now, fix later
|
||||
#else
|
||||
return ::fmodl(x, y);
|
||||
|
||||
@@ -18,10 +18,6 @@
|
||||
|
||||
Mem mem;
|
||||
|
||||
void Mem::init()
|
||||
{
|
||||
}
|
||||
|
||||
char *Mem::strdup(const char *s)
|
||||
{
|
||||
char *p;
|
||||
@@ -118,24 +114,6 @@ void Mem::error()
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void Mem::fullcollect()
|
||||
{
|
||||
}
|
||||
|
||||
void Mem::mark(void *pointer)
|
||||
{
|
||||
(void) pointer; // necessary for VC /W4
|
||||
}
|
||||
|
||||
void Mem::setStackBottom(void *bottom)
|
||||
{
|
||||
}
|
||||
|
||||
void Mem::addroots(char* pStart, char* pEnd)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* =================================================== */
|
||||
|
||||
#if defined(__has_feature)
|
||||
|
||||
@@ -15,44 +15,17 @@
|
||||
#endif
|
||||
#include <stddef.h> // for size_t
|
||||
|
||||
typedef void (*FINALIZERPROC)(void* pObj, void* pClientData);
|
||||
|
||||
struct GC; // thread specific allocator
|
||||
|
||||
struct Mem
|
||||
{
|
||||
GC *gc; // pointer to our thread specific allocator
|
||||
Mem() { gc = NULL; }
|
||||
|
||||
void init();
|
||||
|
||||
// Derive from Mem to get these storage allocators instead of global new/delete
|
||||
void * operator new(size_t m_size);
|
||||
void * operator new(size_t m_size, Mem *mem);
|
||||
void * operator new(size_t m_size, GC *gc);
|
||||
void operator delete(void *p);
|
||||
|
||||
void * operator new[](size_t m_size);
|
||||
void operator delete[](void *p);
|
||||
Mem() { }
|
||||
|
||||
char *strdup(const char *s);
|
||||
void *malloc(size_t size);
|
||||
void *malloc_uncollectable(size_t size);
|
||||
void *calloc(size_t size, size_t n);
|
||||
void *realloc(void *p, size_t size);
|
||||
void free(void *p);
|
||||
void free_uncollectable(void *p);
|
||||
void *mallocdup(void *o, size_t size);
|
||||
void error();
|
||||
void check(void *p); // validate pointer
|
||||
void fullcollect(); // do full garbage collection
|
||||
void fullcollectNoStack(); // do full garbage collection, no scan stack
|
||||
void mark(void *pointer);
|
||||
void addroots(char* pStart, char* pEnd);
|
||||
void removeroots(char* pStart);
|
||||
void setFinalizer(void* pObj, FINALIZERPROC pFn, void* pClientData);
|
||||
void setStackBottom(void *bottom);
|
||||
GC *getThreadGC(); // get apartment allocator for this thread
|
||||
};
|
||||
|
||||
extern Mem mem;
|
||||
|
||||
263
dmd2/root/root.c
263
dmd2/root/root.c
@@ -103,11 +103,6 @@ bool RootObject::equals(RootObject *o)
|
||||
return o == this;
|
||||
}
|
||||
|
||||
hash_t RootObject::hashCode()
|
||||
{
|
||||
return (hash_t) this;
|
||||
}
|
||||
|
||||
int RootObject::compare(RootObject *obj)
|
||||
{
|
||||
return this - obj;
|
||||
@@ -133,104 +128,10 @@ void RootObject::toBuffer(OutBuffer *b)
|
||||
b->writestring("Object");
|
||||
}
|
||||
|
||||
void RootObject::mark()
|
||||
{
|
||||
}
|
||||
|
||||
/****************************** String ********************************/
|
||||
|
||||
String::String(const char *str)
|
||||
: str(mem.strdup(str))
|
||||
{
|
||||
}
|
||||
|
||||
String::~String()
|
||||
{
|
||||
mem.free((void *)str);
|
||||
}
|
||||
|
||||
void String::mark()
|
||||
{
|
||||
mem.mark((void *)str);
|
||||
}
|
||||
|
||||
hash_t String::calcHash(const char *str, size_t len)
|
||||
{
|
||||
hash_t hash = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
switch (len)
|
||||
{
|
||||
case 0:
|
||||
return hash;
|
||||
|
||||
case 1:
|
||||
hash *= 37;
|
||||
hash += *(uint8_t *)str;
|
||||
return hash;
|
||||
|
||||
case 2:
|
||||
hash *= 37;
|
||||
hash += *(uint16_t *)str;
|
||||
return hash;
|
||||
|
||||
case 3:
|
||||
hash *= 37;
|
||||
hash += (*(uint16_t *)str << 8) +
|
||||
((uint8_t *)str)[2];
|
||||
return hash;
|
||||
|
||||
default:
|
||||
hash *= 37;
|
||||
hash += *(uint32_t *)str;
|
||||
str += 4;
|
||||
len -= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hash_t String::calcHash(const char *str)
|
||||
{
|
||||
return calcHash(str, strlen(str));
|
||||
}
|
||||
|
||||
hash_t String::hashCode()
|
||||
{
|
||||
return calcHash(str, strlen(str));
|
||||
}
|
||||
|
||||
size_t String::len()
|
||||
{
|
||||
return strlen(str);
|
||||
}
|
||||
|
||||
bool String::equals(RootObject *obj)
|
||||
{
|
||||
return strcmp(str,((String *)obj)->str) == 0;
|
||||
}
|
||||
|
||||
int String::compare(RootObject *obj)
|
||||
{
|
||||
return strcmp(str,((String *)obj)->str);
|
||||
}
|
||||
|
||||
char *String::toChars()
|
||||
{
|
||||
return (char *)str; // toChars() should really be const
|
||||
}
|
||||
|
||||
void String::print()
|
||||
{
|
||||
printf("String '%s'\n",str);
|
||||
}
|
||||
|
||||
|
||||
/****************************** FileName ********************************/
|
||||
|
||||
FileName::FileName(const char *str)
|
||||
: String(str)
|
||||
: str(mem.strdup(str))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -339,51 +240,6 @@ Strings *FileName::splitPath(const char *path)
|
||||
return array;
|
||||
}
|
||||
|
||||
hash_t FileName::hashCode()
|
||||
{
|
||||
#if _WIN32
|
||||
// We need a different hashCode because it must be case-insensitive
|
||||
size_t len = strlen(str);
|
||||
hash_t hash = 0;
|
||||
utf8_t *s = (utf8_t *)str;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
switch (len)
|
||||
{
|
||||
case 0:
|
||||
return hash;
|
||||
|
||||
case 1:
|
||||
hash *= 37;
|
||||
hash += *(uint8_t *)s | 0x20;
|
||||
return hash;
|
||||
|
||||
case 2:
|
||||
hash *= 37;
|
||||
hash += *(uint16_t *)s | 0x2020;
|
||||
return hash;
|
||||
|
||||
case 3:
|
||||
hash *= 37;
|
||||
hash += ((*(uint16_t *)s << 8) +
|
||||
((uint8_t *)s)[2]) | 0x202020;
|
||||
break;
|
||||
|
||||
default:
|
||||
hash *= 37;
|
||||
hash += *(uint32_t *)s | 0x20202020;
|
||||
s += 4;
|
||||
len -= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
// darwin HFS is case insensitive, though...
|
||||
return String::hashCode();
|
||||
#endif
|
||||
}
|
||||
|
||||
int FileName::compare(RootObject *obj)
|
||||
{
|
||||
return compare(str, ((FileName *)obj)->str);
|
||||
@@ -941,6 +797,11 @@ void FileName::free(const char *str)
|
||||
mem.free((void *)str);
|
||||
}
|
||||
|
||||
char *FileName::toChars()
|
||||
{
|
||||
return (char *)str; // toChars() should really be const
|
||||
}
|
||||
|
||||
|
||||
/****************************** File ********************************/
|
||||
|
||||
@@ -969,7 +830,7 @@ File::~File()
|
||||
if (ref == 0)
|
||||
mem.free(buffer);
|
||||
#if _WIN32
|
||||
else if (ref == 2)
|
||||
if (ref == 2)
|
||||
UnmapViewOfFile(buffer);
|
||||
#endif
|
||||
}
|
||||
@@ -977,13 +838,6 @@ File::~File()
|
||||
mem.free(touchtime);
|
||||
}
|
||||
|
||||
void File::mark()
|
||||
{
|
||||
mem.mark(buffer);
|
||||
mem.mark(touchtime);
|
||||
mem.mark(name);
|
||||
}
|
||||
|
||||
/*************************************
|
||||
*/
|
||||
|
||||
@@ -1394,9 +1248,9 @@ Files *File::match(FileName *n)
|
||||
char *fn;
|
||||
File *f;
|
||||
|
||||
fn = (char *)mem.malloc(name - c + strlen(fileinfo.cFileName) + 1);
|
||||
fn = (char *)mem.malloc(name - c + strlen(&fileinfo.cFileName[0]) + 1);
|
||||
memcpy(fn, c, name - c);
|
||||
strcpy(fn + (name - c), fileinfo.cFileName);
|
||||
strcpy(fn + (name - c), &fileinfo.cFileName[0]);
|
||||
f = new File(fn);
|
||||
f->touchtime = mem.malloc(sizeof(WIN32_FIND_DATAA));
|
||||
memcpy(f->touchtime, &fileinfo, sizeof(fileinfo));
|
||||
@@ -1490,11 +1344,6 @@ char *OutBuffer::extractData()
|
||||
return p;
|
||||
}
|
||||
|
||||
void OutBuffer::mark()
|
||||
{
|
||||
mem.mark(data);
|
||||
}
|
||||
|
||||
void OutBuffer::reserve(size_t nbytes)
|
||||
{
|
||||
//printf("OutBuffer::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes);
|
||||
@@ -1861,97 +1710,3 @@ char *OutBuffer::toChars()
|
||||
writeByte(0);
|
||||
return (char *)data;
|
||||
}
|
||||
|
||||
// TODO: Remove (only used by disabled GC)
|
||||
/********************************* Bits ****************************/
|
||||
|
||||
Bits::Bits()
|
||||
{
|
||||
data = NULL;
|
||||
bitdim = 0;
|
||||
allocdim = 0;
|
||||
}
|
||||
|
||||
Bits::~Bits()
|
||||
{
|
||||
mem.free(data);
|
||||
}
|
||||
|
||||
void Bits::mark()
|
||||
{
|
||||
mem.mark(data);
|
||||
}
|
||||
|
||||
void Bits::resize(unsigned bitdim)
|
||||
{
|
||||
unsigned allocdim;
|
||||
unsigned mask;
|
||||
|
||||
allocdim = (bitdim + 31) / 32;
|
||||
data = (unsigned *)mem.realloc(data, allocdim * sizeof(data[0]));
|
||||
if (this->allocdim < allocdim)
|
||||
memset(data + this->allocdim, 0, (allocdim - this->allocdim) * sizeof(data[0]));
|
||||
|
||||
// Clear other bits in last word
|
||||
mask = (1 << (bitdim & 31)) - 1;
|
||||
if (mask)
|
||||
data[allocdim - 1] &= ~mask;
|
||||
|
||||
this->bitdim = bitdim;
|
||||
this->allocdim = allocdim;
|
||||
}
|
||||
|
||||
void Bits::set(unsigned bitnum)
|
||||
{
|
||||
data[bitnum / 32] |= 1 << (bitnum & 31);
|
||||
}
|
||||
|
||||
void Bits::clear(unsigned bitnum)
|
||||
{
|
||||
data[bitnum / 32] &= ~(1 << (bitnum & 31));
|
||||
}
|
||||
|
||||
int Bits::test(unsigned bitnum)
|
||||
{
|
||||
return data[bitnum / 32] & (1 << (bitnum & 31));
|
||||
}
|
||||
|
||||
void Bits::set()
|
||||
{ unsigned mask;
|
||||
|
||||
memset(data, ~0, allocdim * sizeof(data[0]));
|
||||
|
||||
// Clear other bits in last word
|
||||
mask = (1 << (bitdim & 31)) - 1;
|
||||
if (mask)
|
||||
data[allocdim - 1] &= mask;
|
||||
}
|
||||
|
||||
void Bits::clear()
|
||||
{
|
||||
memset(data, 0, allocdim * sizeof(data[0]));
|
||||
}
|
||||
|
||||
void Bits::copy(Bits *from)
|
||||
{
|
||||
assert(bitdim == from->bitdim);
|
||||
memcpy(data, from->data, allocdim * sizeof(data[0]));
|
||||
}
|
||||
|
||||
Bits *Bits::clone()
|
||||
{
|
||||
Bits *b;
|
||||
|
||||
b = new Bits();
|
||||
b->resize(bitdim);
|
||||
b->copy(this);
|
||||
return b;
|
||||
}
|
||||
|
||||
void Bits::sub(Bits *b)
|
||||
{
|
||||
unsigned u;
|
||||
|
||||
for (u = 0; u < allocdim; u++)
|
||||
data[u] &= ~b->data[u];
|
||||
}
|
||||
|
||||
@@ -31,8 +31,8 @@ struct OutBuffer;
|
||||
|
||||
// Can't include arraytypes.h here, need to declare these directly.
|
||||
template <typename TYPE> struct Array;
|
||||
typedef Array<class File> Files;
|
||||
typedef Array<char> Strings;
|
||||
typedef Array<struct File> Files;
|
||||
typedef Array<const char> Strings;
|
||||
|
||||
|
||||
class RootObject
|
||||
@@ -43,11 +43,6 @@ public:
|
||||
|
||||
virtual bool equals(RootObject *o);
|
||||
|
||||
/**
|
||||
* Returns a hash code, useful for things like building hash tables of Objects.
|
||||
*/
|
||||
virtual hash_t hashCode();
|
||||
|
||||
/**
|
||||
* Return <0, ==0, or >0 if this is less than, equal to, or greater than obj.
|
||||
* Useful for sorting Objects.
|
||||
@@ -67,38 +62,13 @@ public:
|
||||
* defined by the library user. For Object, the return value is 0.
|
||||
*/
|
||||
virtual int dyncast();
|
||||
|
||||
/**
|
||||
* Marks pointers for garbage collector by calling mem.mark() for all pointers into heap.
|
||||
*/
|
||||
/*virtual*/ // not used, disable for now
|
||||
void mark();
|
||||
};
|
||||
|
||||
class String : public RootObject
|
||||
{
|
||||
public:
|
||||
const char *str; // the string itself
|
||||
|
||||
String(const char *str);
|
||||
~String();
|
||||
|
||||
static hash_t calcHash(const char *str, size_t len);
|
||||
static hash_t calcHash(const char *str);
|
||||
hash_t hashCode();
|
||||
size_t len();
|
||||
bool equals(RootObject *obj);
|
||||
int compare(RootObject *obj);
|
||||
char *toChars();
|
||||
void print();
|
||||
void mark();
|
||||
};
|
||||
|
||||
class FileName : public String
|
||||
struct FileName
|
||||
{
|
||||
public:
|
||||
const char *str;
|
||||
FileName(const char *str);
|
||||
hash_t hashCode();
|
||||
bool equals(RootObject *obj);
|
||||
static int equals(const char *name1, const char *name2);
|
||||
int compare(RootObject *obj);
|
||||
@@ -129,9 +99,10 @@ public:
|
||||
static const char *canonicalName(const char *name);
|
||||
|
||||
static void free(const char *str);
|
||||
char *toChars();
|
||||
};
|
||||
|
||||
class File : public RootObject
|
||||
struct File
|
||||
{
|
||||
public:
|
||||
int ref; // != 0 if this is a reference to someone else's buffer
|
||||
@@ -145,8 +116,6 @@ public:
|
||||
File(const FileName *);
|
||||
~File();
|
||||
|
||||
void mark();
|
||||
|
||||
char *toChars();
|
||||
|
||||
/* Read file, return !=0 if error
|
||||
@@ -250,7 +219,6 @@ struct OutBuffer
|
||||
OutBuffer();
|
||||
~OutBuffer();
|
||||
char *extractData();
|
||||
void mark();
|
||||
|
||||
void reserve(size_t nbytes);
|
||||
void setsize(size_t size);
|
||||
@@ -308,13 +276,6 @@ struct Array
|
||||
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 *));
|
||||
@@ -522,30 +483,4 @@ struct Array
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Remove (only used by disabled GC)
|
||||
class Bits : public RootObject
|
||||
{
|
||||
public:
|
||||
unsigned bitdim;
|
||||
unsigned allocdim;
|
||||
unsigned *data;
|
||||
|
||||
Bits();
|
||||
~Bits();
|
||||
void mark();
|
||||
|
||||
void resize(unsigned bitdim);
|
||||
|
||||
void set(unsigned bitnum);
|
||||
void clear(unsigned bitnum);
|
||||
int test(unsigned bitnum);
|
||||
|
||||
void set();
|
||||
void clear();
|
||||
void copy(Bits *from);
|
||||
Bits *clone();
|
||||
|
||||
void sub(Bits *b);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -203,7 +203,8 @@ void *spellerX(const char *seed, size_t seedlen, fp_speller_t fp, void *fparg,
|
||||
void *speller(const char *seed, fp_speller_t fp, void *fparg, const char *charset)
|
||||
{
|
||||
size_t seedlen = strlen(seed);
|
||||
for (int distance = 0; distance < 2; distance++)
|
||||
size_t maxdist = seedlen < 3 ? seedlen - 1 : 2;
|
||||
for (int distance = 0; distance < maxdist; distance++)
|
||||
{ void *p = spellerX(seed, seedlen, fp, fparg, charset, distance);
|
||||
if (p)
|
||||
return p;
|
||||
|
||||
Reference in New Issue
Block a user