forked from LeenkxTeam/LNXSDK
292 lines
8.1 KiB
C
292 lines
8.1 KiB
C
/*
|
|
* Copyright (C)2005-2016 Haxe Foundation
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
#include <hl.h>
|
|
#ifdef HL_VCC
|
|
# pragma warning(disable:4034) // sizeof(void) == 0
|
|
#endif
|
|
|
|
#define H_SIZE_INIT 3
|
|
|
|
// successive primes that double every time
|
|
static int H_PRIMES[] = {
|
|
7,17,37,79,163,331,673,1361,2729,5471,10949,21911,43853,87613,175229,350459,700919,1401857,2803727,5607457,11214943,22429903,44859823,89719661,179424673,373587883,776531401,1611623773
|
|
};
|
|
|
|
// ----- FREE LIST ---------------------------------
|
|
|
|
typedef struct {
|
|
int pos;
|
|
int count;
|
|
} hl_free_bucket;
|
|
|
|
typedef struct {
|
|
hl_free_bucket *buckets;
|
|
int head;
|
|
int nbuckets;
|
|
} hl_free_list;
|
|
|
|
static void hl_freelist_resize( hl_free_list *f, int newsize ) {
|
|
hl_free_bucket *buckets = (hl_free_bucket*)hl_gc_alloc_noptr(sizeof(hl_free_bucket)*newsize);
|
|
memcpy(buckets,f->buckets,f->head * sizeof(hl_free_bucket));
|
|
f->buckets = buckets;
|
|
f->nbuckets = newsize;
|
|
}
|
|
|
|
static void hl_freelist_init( hl_free_list *f ) {
|
|
memset(f,0,sizeof(hl_free_list));
|
|
}
|
|
|
|
static void hl_freelist_add_range( hl_free_list *f, int pos, int count ) {
|
|
hl_free_bucket *b = f->buckets;
|
|
hl_free_bucket *prev = NULL;
|
|
if( !b ) {
|
|
// special handling for countinuous space
|
|
if( f->nbuckets == 0 ) {
|
|
f->head = pos;
|
|
f->nbuckets = count;
|
|
return;
|
|
} else if( f->head + f->nbuckets == pos ) {
|
|
f->nbuckets += count;
|
|
return;
|
|
} else if( pos + count == f->head ) {
|
|
f->head -= count;
|
|
f->nbuckets += count;
|
|
return;
|
|
} else {
|
|
int cur_pos = f->head, cur_count = f->nbuckets;
|
|
f->head = 0;
|
|
f->nbuckets = 0;
|
|
hl_freelist_resize(f,2);
|
|
if( cur_count ) hl_freelist_add_range(f,cur_pos,cur_count);
|
|
b = f->buckets;
|
|
}
|
|
}
|
|
while( b < f->buckets + f->head ) {
|
|
if( b->pos > pos ) break;
|
|
prev = b;
|
|
b++;
|
|
}
|
|
if( b < f->buckets + f->head && b->pos == pos + count ) {
|
|
b->pos -= count;
|
|
b->count += count;
|
|
// merge
|
|
if( prev && prev->pos + prev->count == b->pos ) {
|
|
prev->count += b->count;
|
|
memmove(b,b+1,((f->buckets + f->head) - (b+1)) * sizeof(hl_free_bucket));
|
|
f->head--;
|
|
}
|
|
return;
|
|
}
|
|
if( prev && prev->pos + prev->count == pos ) {
|
|
prev->count += count;
|
|
return;
|
|
}
|
|
// insert
|
|
if( f->head == f->nbuckets ) {
|
|
int pos = (int)(b - f->buckets);
|
|
hl_freelist_resize(f,((f->nbuckets * 3) + 1) >> 1);
|
|
b = f->buckets + pos;
|
|
}
|
|
memmove(b+1,b,((f->buckets + f->head) - b) * sizeof(hl_free_bucket));
|
|
b->pos = pos;
|
|
b->count = count;
|
|
f->head++;
|
|
}
|
|
|
|
static void hl_freelist_add( hl_free_list *f, int pos ) {
|
|
hl_freelist_add_range(f,pos,1);
|
|
}
|
|
|
|
static int hl_freelist_get( hl_free_list *f ) {
|
|
hl_free_bucket *b;
|
|
int p;
|
|
if( !f->buckets ) {
|
|
if( f->nbuckets == 0 ) return -1;
|
|
f->nbuckets--;
|
|
return f->head++;
|
|
}
|
|
if( f->head == 0 )
|
|
return -1;
|
|
b = f->buckets + f->head - 1;
|
|
b->count--;
|
|
p = b->pos + b->count;
|
|
if( b->count == 0 ) {
|
|
f->head--;
|
|
if( f->head < (f->nbuckets>>1) )
|
|
hl_freelist_resize(f,f->nbuckets>>1);
|
|
}
|
|
return p;
|
|
}
|
|
|
|
// ----- INT MAP ---------------------------------
|
|
|
|
typedef struct {
|
|
int key;
|
|
} hl_hi_entry;
|
|
|
|
typedef struct {
|
|
vdynamic *value;
|
|
} hl_hi_value;
|
|
|
|
#define hlt_key hlt_i32
|
|
#define hl_hifilter(key) key
|
|
#define hl_hihash(h) ((unsigned)(h))
|
|
#define _MKEY_TYPE int
|
|
#define _MNAME(n) hl_hi##n
|
|
#define _MMATCH(c) m->entries[c].key == key
|
|
#define _MKEY(m,c) m->entries[c].key
|
|
#define _MSET(c) m->entries[c].key = key
|
|
#define _MERASE(c)
|
|
|
|
#include "maps.h"
|
|
|
|
|
|
// ----- INT64 MAP ---------------------------------
|
|
|
|
typedef struct {
|
|
int64 key;
|
|
} hl_hi64_entry;
|
|
|
|
typedef struct {
|
|
vdynamic *value;
|
|
} hl_hi64_value;
|
|
|
|
#define hlt_key hlt_i64
|
|
#define hl_hi64filter(key) key
|
|
#define hl_hi64hash(h) (((unsigned int)h) ^ ((unsigned int)(h>>32)))
|
|
#define _MKEY_TYPE int64
|
|
#define _MNAME(n) hl_hi64##n
|
|
#define _MMATCH(c) m->entries[c].key == key
|
|
#define _MKEY(m,c) m->entries[c].key
|
|
#define _MSET(c) m->entries[c].key = key
|
|
#define _MERASE(c)
|
|
|
|
#include "maps.h"
|
|
|
|
// ----- BYTES MAP ---------------------------------
|
|
|
|
typedef struct {
|
|
unsigned int hash;
|
|
} hl_hb_entry;
|
|
|
|
typedef struct {
|
|
uchar *key;
|
|
vdynamic *value;
|
|
} hl_hb_value;
|
|
|
|
#define hlt_key hlt_bytes
|
|
#define hl_hbfilter(key) key
|
|
#define hl_hbhash(key) ((unsigned)hl_hash_gen(key,false))
|
|
#define _MKEY_TYPE uchar*
|
|
#define _MNAME(n) hl_hb##n
|
|
#define _MMATCH(c) m->entries[c].hash == hash && ucmp(m->values[c].key,key) == 0
|
|
#define _MKEY(m,c) m->values[c].key
|
|
#define _MSET(c) m->entries[c].hash = hash; m->values[c].key = key
|
|
#define _MERASE(c) m->values[c].key = NULL
|
|
|
|
#include "maps.h"
|
|
|
|
// ----- OBJECT MAP ---------------------------------
|
|
|
|
typedef void hl_ho_entry;
|
|
|
|
typedef struct {
|
|
vdynamic *key;
|
|
vdynamic *value;
|
|
} hl_ho_value;
|
|
|
|
static vdynamic *hl_hofilter( vdynamic *key ) {
|
|
if( key )
|
|
switch( key->t->kind ) {
|
|
// erase virtual (prevent mismatch once virtualized)
|
|
case HVIRTUAL:
|
|
key = hl_virtual_make_value((vvirtual*)key);
|
|
break;
|
|
// store real pointer instead of dynamic wrapper
|
|
case HBYTES:
|
|
case HTYPE:
|
|
case HABSTRACT:
|
|
case HREF:
|
|
case HENUM:
|
|
key = (vdynamic*)key->v.ptr;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return key;
|
|
}
|
|
|
|
#define hlt_key hlt_dyn
|
|
#define hl_hohash(key) ((unsigned int)(int_val)(key))
|
|
#define _MKEY_TYPE vdynamic*
|
|
#define _MNAME(n) hl_ho##n
|
|
#define _MMATCH(c) m->values[c].key == key
|
|
#define _MKEY(m,c) m->values[c].key
|
|
#define _MSET(c) m->values[c].key = key
|
|
#define _MERASE(c) m->values[c].key = NULL
|
|
|
|
#include "maps.h"
|
|
|
|
#define _IMAP _ABSTRACT(hl_int_map)
|
|
DEFINE_PRIM( _IMAP, hialloc, _NO_ARG );
|
|
DEFINE_PRIM( _VOID, hiset, _IMAP _I32 _DYN );
|
|
DEFINE_PRIM( _BOOL, hiexists, _IMAP _I32 );
|
|
DEFINE_PRIM( _DYN, higet, _IMAP _I32 );
|
|
DEFINE_PRIM( _BOOL, hiremove, _IMAP _I32 );
|
|
DEFINE_PRIM( _ARR, hikeys, _IMAP );
|
|
DEFINE_PRIM( _ARR, hivalues, _IMAP );
|
|
DEFINE_PRIM( _VOID, hiclear, _IMAP );
|
|
DEFINE_PRIM( _I32, hisize, _IMAP );
|
|
|
|
#define _I64MAP _ABSTRACT(hl_int64_map)
|
|
DEFINE_PRIM( _I64MAP, hi64alloc, _NO_ARG );
|
|
DEFINE_PRIM( _VOID, hi64set, _I64MAP _I64 _DYN );
|
|
DEFINE_PRIM( _BOOL, hi64exists, _I64MAP _I64 );
|
|
DEFINE_PRIM( _DYN, hi64get, _I64MAP _I64 );
|
|
DEFINE_PRIM( _BOOL, hi64remove, _I64MAP _I64 );
|
|
DEFINE_PRIM( _ARR, hi64keys, _I64MAP );
|
|
DEFINE_PRIM( _ARR, hi64values, _I64MAP );
|
|
DEFINE_PRIM( _VOID, hi64clear, _I64MAP );
|
|
DEFINE_PRIM( _I32, hi64size, _I64MAP );
|
|
|
|
#define _BMAP _ABSTRACT(hl_bytes_map)
|
|
DEFINE_PRIM( _BMAP, hballoc, _NO_ARG );
|
|
DEFINE_PRIM( _VOID, hbset, _BMAP _BYTES _DYN );
|
|
DEFINE_PRIM( _BOOL, hbexists, _BMAP _BYTES );
|
|
DEFINE_PRIM( _DYN, hbget, _BMAP _BYTES );
|
|
DEFINE_PRIM( _BOOL, hbremove, _BMAP _BYTES );
|
|
DEFINE_PRIM( _ARR, hbkeys, _BMAP );
|
|
DEFINE_PRIM( _ARR, hbvalues, _BMAP );
|
|
DEFINE_PRIM( _VOID, hbclear, _BMAP );
|
|
DEFINE_PRIM( _I32, hbsize, _BMAP );
|
|
|
|
#define _OMAP _ABSTRACT(hl_obj_map)
|
|
DEFINE_PRIM( _OMAP, hoalloc, _NO_ARG );
|
|
DEFINE_PRIM( _VOID, hoset, _OMAP _DYN _DYN );
|
|
DEFINE_PRIM( _BOOL, hoexists, _OMAP _DYN );
|
|
DEFINE_PRIM( _DYN, hoget, _OMAP _DYN );
|
|
DEFINE_PRIM( _BOOL, horemove, _OMAP _DYN );
|
|
DEFINE_PRIM( _ARR, hokeys, _OMAP );
|
|
DEFINE_PRIM( _ARR, hovalues, _OMAP );
|
|
DEFINE_PRIM( _VOID, hoclear, _OMAP );
|
|
DEFINE_PRIM( _I32, hosize, _OMAP );
|