diff --git a/hawk/lib/arr.c b/hawk/lib/arr.c index 10fbf65d..f7ff3163 100644 --- a/hawk/lib/arr.c +++ b/hawk/lib/arr.c @@ -145,13 +145,13 @@ const hawk_arr_style_t* hawk_get_arr_style (hawk_arr_style_kind_t kind) return &style[kind]; } - int hawk_arr_init (hawk_arr_t* arr, hawk_gem_t* gem, hawk_oow_t capa) { HAWK_MEMSET (arr, 0, HAWK_SIZEOF(*arr)); arr->gem = gem; arr->size = 0; + arr->tally = 0; arr->capa = 0; arr->slot = HAWK_NULL; arr->scale = 1; @@ -170,6 +170,8 @@ void hawk_arr_fini (hawk_arr_t* arr) hawk_gem_freemem (arr->gem, arr->slot); arr->slot = HAWK_NULL; arr->capa = 0; + arr->size = 0 ; + arr->tally = 0; } } @@ -217,7 +219,7 @@ hawk_arr_t* hawk_arr_setcapa (hawk_arr_t* arr, hawk_oow_t capa) if (capa == arr->capa) return arr; - if (arr->size > capa) + if (capa < arr->size) { /* to trigger freeers on the items truncated */ hawk_arr_delete (arr, capa, arr->size - capa); @@ -238,6 +240,9 @@ hawk_arr_t* hawk_arr_setcapa (hawk_arr_t* arr, hawk_oow_t capa) } tmp = HAWK_NULL; + + HAWK_ASSERT (arr->size == 0); + HAWK_ASSERT (arr->tally == 0); } arr->slot = tmp; @@ -359,6 +364,7 @@ hawk_oow_t hawk_arr_insert (hawk_arr_t* arr, hawk_oow_t pos, void* dptr, hawk_oo if (pos > arr->size) arr->size = pos + 1; else arr->size++; + arr->tally++; return pos; } @@ -379,6 +385,7 @@ hawk_oow_t hawk_arr_update (hawk_arr_t* arr, hawk_oow_t pos, void* dptr, hawk_oo /* no previous data */ arr->slot[pos] = alloc_slot(arr, dptr, dlen); if (arr->slot[pos] == HAWK_NULL) return HAWK_ARR_NIL; + arr->tally++; } else { @@ -415,20 +422,20 @@ hawk_oow_t hawk_arr_delete (hawk_arr_t* arr, hawk_oow_t index, hawk_oow_t count) for (i = index; i < index + count; i++) { slot_t* c = arr->slot[i]; - - if (c != HAWK_NULL) + if (c) { if (arr->style->freeer) arr->style->freeer (arr, DPTR(c), DLEN(c)); hawk_gem_freemem (arr->gem, c); arr->slot[i] = HAWK_NULL; + arr->tally--; } } for (i = index + count; i < arr->size; i++) { - arr->slot[i-count] = arr->slot[i]; + arr->slot[i - count] = arr->slot[i]; } - arr->slot[arr->size-1] = HAWK_NULL; + arr->slot[arr->size - 1] = HAWK_NULL; arr->size -= count; return count; @@ -446,12 +453,12 @@ hawk_oow_t hawk_arr_uplete (hawk_arr_t* arr, hawk_oow_t index, hawk_oow_t count) for (i = index; i < index + count; i++) { slot_t* c = arr->slot[i]; - - if (c != HAWK_NULL) + if (c) { if (arr->style->freeer) arr->style->freeer (arr, DPTR(c), DLEN(c)); hawk_gem_freemem (arr->gem, c); arr->slot[i] = HAWK_NULL; + arr->tally--; } } @@ -474,6 +481,7 @@ void hawk_arr_clear (hawk_arr_t* arr) } arr->size = 0; + arr->tally = 0; } hawk_oow_t hawk_arr_walk (hawk_arr_t* arr, walker_t walker, void* ctx) @@ -701,6 +709,7 @@ void hawk_arr_deleteheap (hawk_arr_t* arr, hawk_oow_t index) /* empty the last slot */ arr->slot[arr->size] = HAWK_NULL; + arr->tally--; } hawk_oow_t hawk_arr_updateheap (hawk_arr_t* arr, hawk_oow_t index, void* dptr, hawk_oow_t dlen) diff --git a/hawk/lib/fnc.c b/hawk/lib/fnc.c index 7afe03f7..d9ebdb3c 100644 --- a/hawk/lib/fnc.c +++ b/hawk/lib/fnc.c @@ -697,8 +697,8 @@ int hawk_fnc_length (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) len = HAWK_MAP_SIZE(((hawk_val_map_t*)v)->map); break; - case HAWK_VAL_ARR: - len = HAWK_ARR_SIZE(((hawk_val_arr_t*)v)->arr); + case HAWK_VAL_ARR: /* returns the number of set items instead of the last index + 1 */ + len = HAWK_ARR_TALLY(((hawk_val_arr_t*)v)->arr); break; case HAWK_VAL_STR: diff --git a/hawk/lib/hawk-arr.h b/hawk/lib/hawk-arr.h index da0a9944..a9bfe962 100644 --- a/hawk/lib/hawk-arr.h +++ b/hawk/lib/hawk-arr.h @@ -56,8 +56,9 @@ typedef enum hawk_arr_walk_t hawk_arr_walk_t; #define HAWK_ARR_NIL ((hawk_oow_t)-1) -#define HAWK_ARR_SIZE(arr) (*(const hawk_oow_t*)&(arr)->size) -#define HAWK_ARR_CAPA(arr) (*(const hawk_oow_t*)&(arr)->capa) +#define HAWK_ARR_SIZE(arr) ((arr)->size) +#define HAWK_ARR_CAPA(arr) ((arr)->capa) +#define HAWK_ARR_TALLY(arr) ((arr)->tally) #define HAWK_ARR_SLOT(arr,index) ((arr)->slot[index]) #define HAWK_ARR_DPTL(arr,index) ((const hawk_ptl_t*)&(arr)->slot[index]->val) @@ -179,6 +180,7 @@ struct hawk_arr_t hawk_oow_t heap_pos_offset; /* offset in the data element where position * is stored when heap operation is performed. */ hawk_oow_t size; /* number of items */ + hawk_oow_t tally; /* number of items set */ hawk_oow_t capa; /* capacity */ hawk_arr_slot_t** slot; }; diff --git a/hawk/lib/mod-hawk.c b/hawk/lib/mod-hawk.c index 478f5626..403ac19e 100644 --- a/hawk/lib/mod-hawk.c +++ b/hawk/lib/mod-hawk.c @@ -233,6 +233,44 @@ static int fnc_array (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) return 0; } +static int fnc_array_size (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) +{ + hawk_val_t* a0; + hawk_oow_t iv; + + a0 = hawk_rtx_getarg(rtx, 0); + + if (HAWK_RTX_GETVALTYPE(rtx, a0) != HAWK_VAL_ARR) + { + hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_ENOTARR); + return -1; + } + + iv = HAWK_ARR_SIZE(((hawk_val_arr_t*)a0)->arr); + HAWK_ASSERT (iv >= 0 && iv <= HAWK_QUICKINT_MAX); + hawk_rtx_setretval (rtx, hawk_rtx_makeintval(rtx, iv)); + return 0; +} + +static int fnc_array_tally (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) +{ + hawk_val_t* a0; + hawk_oow_t iv; + + a0 = hawk_rtx_getarg(rtx, 0); + + if (HAWK_RTX_GETVALTYPE(rtx, a0) != HAWK_VAL_ARR) + { + hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_ENOTARR); + return -1; + } + + iv = HAWK_ARR_TALLY(((hawk_val_arr_t*)a0)->arr); + HAWK_ASSERT (iv >= 0 && iv <= HAWK_QUICKINT_MAX); + hawk_rtx_setretval (rtx, hawk_rtx_makeintval(rtx, iv)); + return 0; +} + static int fnc_map (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) { hawk_val_t* tmp; @@ -327,6 +365,9 @@ static fnctab_t fnctab[] = { /* keep this table sorted for binary search in query(). */ { HAWK_T("array"), { { 0, A_MAX }, fnc_array, 0 } }, + { HAWK_T("array_size"), { { 1, 1 }, fnc_array_size, 0 } }, + { HAWK_T("array_tally"), { { 1, 1 }, fnc_array_tally, 0 } }, + { HAWK_T("call"), { { 1, A_MAX, HAWK_T("vR") }, fnc_call, 0 } }, { HAWK_T("function_exists"), { { 1, 1, HAWK_NULL }, fnc_function_exists, 0 } }, { HAWK_T("gc"), { { 0, 1, HAWK_NULL }, fnc_gc, 0 } }, diff --git a/hawk/t/h-001.hawk b/hawk/t/h-001.hawk index d0deebe0..a254cf67 100644 --- a/hawk/t/h-001.hawk +++ b/hawk/t/h-001.hawk @@ -94,13 +94,48 @@ function main() ensure (a[0][40], "bye", SCRIPTNAME); call_by_ref_3(a[0][40]); ensure (a[0][40], "hello world", SCRIPTNAME); - ensure (length(a[0]), 41); + ensure (length(a[0]), 2, SCRIPTNAME); + ensure (hawk::array_size(a[0]), 41, SCRIPTNAME); delete a[0][40]; - ensure (length(a[0]), 41); + ensure (length(a[0]), 1, SCRIPTNAME); + ensure (hawk::array_size(a[0]), 41, SCRIPTNAME); ensure (a[0][0], "farewell", SCRIPTNAME); ensure (a[0][40], nil, SCRIPTNAME); - #hawk::splice (a[0], 40, 1); - #ensure (length(a[0]), 40); + #hawk::splice (a[0], 40, 1, SCRIPTNAME); + #ensure (length(a[0]), 40, SCRIPTNAME); + } + + + { + @local a, i; + + a = hawk::array(); + ensure (length(a), 0, SCRIPTNAME); + ensure (hawk::array_size(a), 0, SCRIPTNAME); + + for (i = 0; i < 10; i++) a[i*i]=i; + ensure (length(a), 10, SCRIPTNAME); + ensure (hawk::array_size(a), 82, SCRIPTNAME); + + delete a[0]; + ensure (length(a), 9, SCRIPTNAME); + ensure (hawk::array_size(a), 82, SCRIPTNAME); + + delete a[81]; + ensure (length(a), 8, SCRIPTNAME); + ensure (hawk::array_size(a), 82, SCRIPTNAME); + + delete a[36]; + ensure (length(a), 7, SCRIPTNAME); + ensure (hawk::array_size(a), 82, SCRIPTNAME); + + for (i = 0; i < 10; i++) delete a[i*i]; + ensure (length(a), 0, SCRIPTNAME); + ensure (hawk::array_size(a), 82, SCRIPTNAME); + + delete a; + ensure (length(a), 0, SCRIPTNAME); + ensure (hawk::array_size(a), 0, SCRIPTNAME); } print "SUCCESS"