diff --git a/hawk/lib/arr.c b/hawk/lib/arr.c index 16117c61..665d7a1e 100644 --- a/hawk/lib/arr.c +++ b/hawk/lib/arr.c @@ -42,9 +42,7 @@ /* the default comparator is not proper for number comparision. * the first different byte decides whice side is greater */ -static int default_comparator (hawk_arr_t* arr, - const void* dptr1, hawk_oow_t dlen1, - const void* dptr2, hawk_oow_t dlen2) +int hawk_arr_dflcomp (hawk_arr_t* arr, const void* dptr1, hawk_oow_t dlen1, const void* dptr2, hawk_oow_t dlen2) { /* if (dlen1 == dlen2) return HAWK_MEMCMP(dptr1, dptr2, TOB(arr,dlen1)); @@ -68,26 +66,26 @@ static HAWK_INLINE slot_t* alloc_slot (hawk_arr_t* arr, void* dptr, hawk_oow_t d { slot_t* n; - if (arr->copier == HAWK_ARR_COPIER_SIMPLE) + if (arr->style->copier == HAWK_ARR_COPIER_SIMPLE) { n = (slot_t*)hawk_gem_allocmem(arr->gem, HAWK_SIZEOF(slot_t)); if (HAWK_UNLIKELY(!n)) return HAWK_NULL; - DPTR(n) = dptr; + DPTR(n) = dptr; /* store the pointer */ } - else if (arr->copier == HAWK_ARR_COPIER_INLINE) + else if (arr->style->copier == HAWK_ARR_COPIER_INLINE) { n = (slot_t*)hawk_gem_allocmem(arr->gem, HAWK_SIZEOF(slot_t) + TOB(arr,dlen)); - if (HAWK_UNLIKELY(!n)) return HAWK_NULL; + if (HAWK_UNLIKELY(!n)) return HAWK_NULL; - HAWK_MEMCPY (n + 1, dptr, TOB(arr,dlen)); + HAWK_MEMCPY (n + 1, dptr, TOB(arr,dlen)); /* copy data contents */ DPTR(n) = n + 1; } else { n = (slot_t*)hawk_gem_allocmem(arr->gem, HAWK_SIZEOF(slot_t)); if (HAWK_UNLIKELY(!n)) return HAWK_NULL; - DPTR(n) = arr->copier(arr, dptr, dlen); - if (DPTR(n) == HAWK_NULL) + DPTR(n) = arr->style->copier(arr, dptr, dlen); /* call the custom copier */ + if (HAWK_UNLIKELY(!DPTR(n))) { hawk_gem_freemem (arr->gem, n); return HAWK_NULL; @@ -122,6 +120,32 @@ void hawk_arr_close (hawk_arr_t* arr) hawk_gem_freemem (arr->gem, arr); } + +static hawk_arr_style_t style[] = +{ + { + HAWK_ARR_COPIER_DEFAULT, + HAWK_ARR_FREEER_DEFAULT, + HAWK_ARR_COMPER_DEFAULT, + HAWK_ARR_KEEPER_DEFAULT, + HAWK_ARR_SIZER_DEFAULT + }, + + { + HAWK_ARR_COPIER_INLINE, + HAWK_ARR_FREEER_DEFAULT, + HAWK_ARR_COMPER_DEFAULT, + HAWK_ARR_KEEPER_DEFAULT, + HAWK_ARR_SIZER_DEFAULT + } +}; + +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)); @@ -132,9 +156,7 @@ int hawk_arr_init (hawk_arr_t* arr, hawk_gem_t* gem, hawk_oow_t capa) arr->slot = HAWK_NULL; arr->scale = 1; arr->heap_pos_offset = HAWK_ARR_NIL; - - arr->copier = HAWK_ARR_COPIER_SIMPLE; - arr->comper = default_comparator; + arr->style = &style[0]; return (hawk_arr_setcapa(arr, capa) == HAWK_NULL)? -1: 0; } @@ -168,56 +190,15 @@ void hawk_arr_setscale (hawk_arr_t* arr, int scale) arr->scale = scale; } -copier_t hawk_arr_getcopier (hawk_arr_t* arr) +const hawk_arr_style_t* hawk_arr_getstyle (hawk_arr_t* arr) { - return arr->copier; + return &arr->style; } -void hawk_arr_setcopier (hawk_arr_t* arr, copier_t copier) +void hawk_arr_setstyle (hawk_arr_t* arr, const hawk_arr_style_t* style) { - if (copier == HAWK_NULL) copier = HAWK_ARR_COPIER_SIMPLE; - arr->copier = copier; -} - -freeer_t hawk_arr_getfreeer (hawk_arr_t* arr) -{ - return arr->freeer; -} - -void hawk_arr_setfreeer (hawk_arr_t* arr, freeer_t freeer) -{ - arr->freeer = freeer; -} - -comper_t hawk_arr_getcomper (hawk_arr_t* arr) -{ - return arr->comper; -} - -void hawk_arr_setcomper (hawk_arr_t* arr, comper_t comper) -{ - if (comper == HAWK_NULL) comper = default_comparator; - arr->comper = comper; -} - -keeper_t hawk_arr_getkeeper (hawk_arr_t* arr) -{ - return arr->keeper; -} - -void hawk_arr_setkeeper (hawk_arr_t* arr, keeper_t keeper) -{ - arr->keeper = keeper; -} - -sizer_t hawk_arr_getsizer (hawk_arr_t* arr) -{ - return arr->sizer; -} - -void hawk_arr_setsizer (hawk_arr_t* arr, sizer_t sizer) -{ - arr->sizer = sizer; + HAWK_ASSERT (style != HAWK_NULL); + arr->style = style; } hawk_oow_t hawk_arr_getsize (hawk_arr_t* arr) @@ -272,7 +253,7 @@ hawk_oow_t hawk_arr_search (hawk_arr_t* arr, hawk_oow_t pos, const void* dptr, h for (i = pos; i < arr->size; i++) { if (arr->slot[i] == HAWK_NULL) continue; - if (arr->comper(arr, DPTR(arr->slot[i]), DLEN(arr->slot[i]), dptr, dlen) == 0) return i; + if (arr->style->comper(arr, DPTR(arr->slot[i]), DLEN(arr->slot[i]), dptr, dlen) == 0) return i; } hawk_gem_seterrnum (arr->gem, HAWK_NULL, HAWK_ENOENT); @@ -290,7 +271,7 @@ hawk_oow_t hawk_arr_rsearch (hawk_arr_t* arr, hawk_oow_t pos, const void* dptr, for (i = pos + 1; i-- > 0; ) { if (arr->slot[i] == HAWK_NULL) continue; - if (arr->comper (arr, DPTR(arr->slot[i]), DLEN(arr->slot[i]), dptr, dlen) == 0) return i; + if (arr->style->comper(arr, DPTR(arr->slot[i]), DLEN(arr->slot[i]), dptr, dlen) == 0) return i; } } @@ -310,8 +291,8 @@ hawk_oow_t hawk_arr_insert (hawk_arr_t* arr, hawk_oow_t pos, void* dptr, hawk_oo slot_t* slot; /* allocate the slot first */ - slot = alloc_slot (arr, dptr, dlen); - if (slot == HAWK_NULL) return HAWK_ARR_NIL; + slot = alloc_slot(arr, dptr, dlen); + if (HAWK_UNLIKELY(!slot)) return HAWK_ARR_NIL; /* do resizeing if necessary. * resizing is performed after slot allocation because that way, it @@ -323,9 +304,9 @@ hawk_oow_t hawk_arr_insert (hawk_arr_t* arr, hawk_oow_t pos, void* dptr, hawk_oo /* get the minimum capacity needed */ mincapa = (pos >= arr->size)? (pos + 1): (arr->size + 1); - if (arr->sizer) + if (arr->style->sizer) { - capa = arr->sizer(arr, mincapa); + capa = arr->style->sizer(arr, mincapa); } else { @@ -348,7 +329,7 @@ hawk_oow_t hawk_arr_insert (hawk_arr_t* arr, hawk_oow_t pos, void* dptr, hawk_oo if (capa <= mincapa) { - if (arr->freeer) arr->freeer (arr, DPTR(slot), DLEN(slot)); + if (arr->style->freeer) arr->style->freeer (arr, DPTR(slot), DLEN(slot)); hawk_gem_freemem (arr->gem, slot); return HAWK_ARR_NIL; } @@ -360,7 +341,7 @@ hawk_oow_t hawk_arr_insert (hawk_arr_t* arr, hawk_oow_t pos, void* dptr, hawk_oo if (pos >= arr->capa || arr->size >= arr->capa) /* can happen if the sizer() callback isn't good enough */ { /* the buffer is not still enough after resizing */ - if (arr->freeer) arr->freeer (arr, DPTR(slot), DLEN(slot)); + if (arr->style->freeer) arr->style->freeer (arr, DPTR(slot), DLEN(slot)); hawk_gem_freemem (arr->gem, slot); hawk_gem_seterrnum (arr->gem, HAWK_NULL, HAWK_EBUFFULL); return HAWK_ARR_NIL; @@ -404,15 +385,15 @@ hawk_oow_t hawk_arr_update (hawk_arr_t* arr, hawk_oow_t pos, void* dptr, hawk_oo if (dptr == DPTR(c) && dlen == DLEN(c)) { /* updated to the same data */ - if (arr->keeper) arr->keeper (arr, dptr, dlen); + if (arr->style->keeper) arr->style->keeper (arr, dptr, dlen); } else { /* updated to different data */ slot_t* slot = alloc_slot(arr, dptr, dlen); - if (slot == HAWK_NULL) return HAWK_ARR_NIL; + if (HAWK_UNLIKELY(!slot)) return HAWK_ARR_NIL; - if (arr->freeer) arr->freeer (arr, DPTR(c), DLEN(c)); + if (arr->style->freeer) arr->style->freeer (arr, DPTR(c), DLEN(c)); hawk_gem_freemem (arr->gem, c); arr->slot[pos] = slot; @@ -437,7 +418,7 @@ hawk_oow_t hawk_arr_delete (hawk_arr_t* arr, hawk_oow_t index, hawk_oow_t count) if (c != HAWK_NULL) { - if (arr->freeer) arr->freeer (arr, DPTR(c), DLEN(c)); + if (arr->style->freeer) arr->style->freeer (arr, DPTR(c), DLEN(c)); hawk_gem_freemem (arr->gem, c); arr->slot[i] = HAWK_NULL; } @@ -468,7 +449,7 @@ hawk_oow_t hawk_arr_uplete (hawk_arr_t* arr, hawk_oow_t index, hawk_oow_t count) if (c != HAWK_NULL) { - if (arr->freeer) arr->freeer (arr, DPTR(c), DLEN(c)); + if (arr->style->freeer) arr->style->freeer (arr, DPTR(c), DLEN(c)); hawk_gem_freemem (arr->gem, c); arr->slot[i] = HAWK_NULL; } @@ -486,7 +467,7 @@ void hawk_arr_clear (hawk_arr_t* arr) slot_t* c = arr->slot[i]; if (c != HAWK_NULL) { - if (arr->freeer) arr->freeer (arr, DPTR(c), DLEN(c)); + if (arr->style->freeer) arr->style->freeer (arr, DPTR(c), DLEN(c)); hawk_gem_freemem (arr->gem, c); arr->slot[i] = HAWK_NULL; } @@ -590,9 +571,7 @@ static hawk_oow_t sift_up (hawk_arr_t* arr, hawk_oow_t index) int n; parent = HEAP_PARENT(index); - n = arr->comper (arr, - DPTR(arr->slot[index]), DLEN(arr->slot[index]), - DPTR(arr->slot[parent]), DLEN(arr->slot[parent])); + n = arr->style->comper(arr, DPTR(arr->slot[index]), DLEN(arr->slot[index]), DPTR(arr->slot[parent]), DLEN(arr->slot[parent])); if (n > 0) { slot_t* tmp; @@ -609,9 +588,7 @@ static hawk_oow_t sift_up (hawk_arr_t* arr, hawk_oow_t index) if (index <= 0) break; - n = arr->comper (arr, - DPTR(tmp), DLEN(tmp), - DPTR(arr->slot[parent]), DLEN(arr->slot[parent])); + n = arr->style->comper(arr, DPTR(tmp), DLEN(tmp), DPTR(arr->slot[parent]), DLEN(arr->slot[parent])); if (n <= 0) break; } @@ -644,7 +621,7 @@ static hawk_oow_t sift_down (hawk_arr_t* arr, hawk_oow_t index) if (right < arr->size) { - n = arr->comper (arr, + n = arr->style->comper(arr, DPTR(arr->slot[right]), DLEN(arr->slot[right]), DPTR(arr->slot[left]), DLEN(arr->slot[left])); child = (n > 0)? right: left; @@ -654,9 +631,7 @@ static hawk_oow_t sift_down (hawk_arr_t* arr, hawk_oow_t index) child = left; } - n = arr->comper (arr, - DPTR(tmp), DLEN(tmp), - DPTR(arr->slot[child]), DLEN(arr->slot[child])); + n = arr->style->comper(arr, DPTR(tmp), DLEN(tmp), DPTR(arr->slot[child]), DLEN(arr->slot[child])); if (n > 0) break; arr->slot[index] = arr->slot[child]; @@ -715,15 +690,13 @@ void hawk_arr_deleteheap (hawk_arr_t* arr, hawk_oow_t index) /* move it up if the last item is greater than the item to be deleted, * move it down otherwise. */ - n = arr->comper (arr, - DPTR(arr->slot[index]), DLEN(arr->slot[index]), - DPTR(tmp), DLEN(tmp)); + n = arr->style->comper(arr, DPTR(arr->slot[index]), DLEN(arr->slot[index]), DPTR(tmp), DLEN(tmp)); if (n > 0) sift_up (arr, index); else if (n < 0) sift_down (arr, index); } /* destroy the actual item */ - if (arr->freeer) arr->freeer (arr, DPTR(tmp), DLEN(tmp)); + if (arr->style->freeer) arr->style->freeer (arr, DPTR(tmp), DLEN(tmp)); hawk_gem_freemem (arr->gem, tmp); /* empty the last slot */ @@ -738,7 +711,7 @@ hawk_oow_t hawk_arr_updateheap (hawk_arr_t* arr, hawk_oow_t index, void* dptr, h tmp = arr->slot[index]; HAWK_ASSERT (tmp != HAWK_NULL); - n = arr->comper(arr, dptr, dlen, DPTR(tmp), DLEN(tmp)); + n = arr->style->comper(arr, dptr, dlen, DPTR(tmp), DLEN(tmp)); if (n) { if (hawk_arr_update(arr, index, dptr, dlen) == HAWK_ARR_NIL) return HAWK_ARR_NIL; diff --git a/hawk/lib/dir.c b/hawk/lib/dir.c index cb28958d..3cba6eb6 100644 --- a/hawk/lib/dir.c +++ b/hawk/lib/dir.c @@ -125,6 +125,15 @@ static int compare_dirent (hawk_arr_t* arr, const void* dptr1, hawk_oow_t dlen1, int hawk_dir_init (hawk_dir_t* dir, hawk_gem_t* gem, const hawk_ooch_t* path, int flags) { + static hawk_arr_style_t stab_style = + { + HAWK_ARR_COPIER_INLINE, + HAWK_ARR_FREEER_DEFAULT, + compare_dirent, + HAWK_ARR_KEEPER_DEFAULT, + HAWK_ARR_SIZER_DEFAULT + }; + int n; int path_flags; @@ -159,11 +168,11 @@ int hawk_dir_init (hawk_dir_t* dir, hawk_gem_t* gem, const hawk_ooch_t* path, in if (dir->flags & HAWK_DIR_SORT) { dir->stab = hawk_arr_open(gem, 0, 128); - if (dir->stab == HAWK_NULL) goto oops_3; + if (HAWK_UNLIKELY(!dir->stab)) goto oops_3; /*hawk_arr_setscale (dir->stab, 1);*/ - hawk_arr_setcopier (dir->stab, HAWK_ARR_COPIER_INLINE); - hawk_arr_setcomper (dir->stab, compare_dirent); + hawk_arr_setstyle (dir->stab, &stab_style); + if (read_ahead_and_sort(dir, path) <= -1) goto oops_4; } diff --git a/hawk/lib/fnc.c b/hawk/lib/fnc.c index 2e97af01..92633a3c 100644 --- a/hawk/lib/fnc.c +++ b/hawk/lib/fnc.c @@ -33,6 +33,7 @@ static int fnc_typename (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi); static int fnc_gcrefs (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi); static int fnc_isnil (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi); static int fnc_ismap (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi); +static int fnc_isarr (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi); static int fnc_asort (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi); static int fnc_asorti (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi); @@ -58,6 +59,7 @@ static hawk_fnc_t sysfnctab[] = /* type info/conversion */ { {HAWK_T("int"), 3}, 0, { {1, 1, HAWK_NULL}, fnc_int, 0 }, HAWK_NULL}, + { {HAWK_T("isarray"), 7}, 0, { {1, 1, HAWK_NULL}, fnc_isarr, 0 }, HAWK_NULL}, { {HAWK_T("isnil"), 5}, 0, { {1, 1, HAWK_NULL}, fnc_isnil, 0 }, HAWK_NULL}, { {HAWK_T("ismap"), 5}, 0, { {1, 1, HAWK_NULL}, fnc_ismap, 0 }, HAWK_NULL}, { {HAWK_T("typename"), 8}, 0, { {1, 1, HAWK_NULL}, fnc_typename, 0 }, HAWK_NULL}, @@ -1774,7 +1776,21 @@ static int fnc_ismap (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) a0 = hawk_rtx_getarg(rtx, 0); r = hawk_rtx_makeintval(rtx, HAWK_RTX_GETVALTYPE(rtx, a0) == HAWK_VAL_MAP); - if (r == HAWK_NULL) return -1; + if (HAWK_UNLIKELY(!r)) return -1; + + hawk_rtx_setretval (rtx, r); + return 0; +} + +static int fnc_isarr (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) +{ + hawk_val_t* a0; + hawk_val_t* r; + + a0 = hawk_rtx_getarg(rtx, 0); + + r = hawk_rtx_makeintval(rtx, HAWK_RTX_GETVALTYPE(rtx, a0) == HAWK_VAL_ARR); + if (HAWK_UNLIKELY(!r)) return -1; hawk_rtx_setretval (rtx, r); return 0; diff --git a/hawk/lib/hawk-arr.h b/hawk/lib/hawk-arr.h index db8e4861..71799a60 100644 --- a/hawk/lib/hawk-arr.h +++ b/hawk/lib/hawk-arr.h @@ -48,6 +48,12 @@ typedef enum hawk_arr_walk_t hawk_arr_walk_t; #define HAWK_ARR_COPIER_SIMPLE ((hawk_arr_copier_t)1) #define HAWK_ARR_COPIER_INLINE ((hawk_arr_copier_t)2) +#define HAWK_ARR_COPIER_DEFAULT (HAWK_ARR_COPIER_SIMPLE) +#define HAWK_ARR_FREEER_DEFAULT (HAWK_NULL) +#define HAWK_ARR_COMPER_DEFAULT (hawk_arr_dflcomp) +#define HAWK_ARR_KEEPER_DEFAULT (HAWK_NULL) +#define HAWK_ARR_SIZER_DEFAULT (HAWK_NULL) + #define HAWK_ARR_NIL ((hawk_oow_t)-1) #define HAWK_ARR_SIZE(arr) (*(const hawk_oow_t*)&(arr)->size) @@ -64,17 +70,16 @@ typedef enum hawk_arr_walk_t hawk_arr_walk_t; * define how the data to add can be maintained in the array. A dynamic * array not specified with any copiers stores the data pointer and * the data length into a slot. A special copier HAWK_ARR_COPIER_INLINE copies - * the contents of the data a user provided into the slot. You can use the - * hawk_arr_setcopier() function to change the copier. - * + * the contents of the data a user provided into the slot. + * * A copier should return the pointer to the copied data. If it fails to copy * data, it may return HAWK_NULL. You need to set a proper freeer to free up * memory allocated for copy. */ typedef void* (*hawk_arr_copier_t) ( hawk_arr_t* arr /**< array */, - void* dptr /**< pointer to data to copy */, - hawk_oow_t dlen /**< length of data to copy */ + void* dptr /**< pointer to data to copy */, + hawk_oow_t dlen /**< length of data to copy */ ); /** @@ -82,8 +87,8 @@ typedef void* (*hawk_arr_copier_t) ( */ typedef void (*hawk_arr_freeer_t) ( hawk_arr_t* arr /**< array */, - void* dptr /**< pointer to data to free */, - hawk_oow_t dlen /**< length of data to free */ + void* dptr /**< pointer to data to free */, + hawk_oow_t dlen /**< length of data to free */ ); /** @@ -103,10 +108,10 @@ typedef void (*hawk_arr_freeer_t) ( */ typedef int (*hawk_arr_comper_t) ( hawk_arr_t* arr /* array */, - const void* dptr1 /* data pointer */, - hawk_oow_t dlen1 /* data length */, - const void* dptr2 /* data pointer */, - hawk_oow_t dlen2 /* data length */ + const void* dptr1 /* data pointer */, + hawk_oow_t dlen1 /* data length */, + const void* dptr2 /* data pointer */, + hawk_oow_t dlen2 /* data length */ ); /** @@ -117,8 +122,8 @@ typedef int (*hawk_arr_comper_t) ( */ typedef void (*hawk_arr_keeper_t) ( hawk_arr_t* arr /**< array */, - void* vptr /**< pointer to a value */, - hawk_oow_t vlen /**< length of a value */ + void* vptr /**< pointer to a value */, + hawk_oow_t vlen /**< length of a value */ ); /** @@ -127,13 +132,40 @@ typedef void (*hawk_arr_keeper_t) ( */ typedef hawk_oow_t (*hawk_arr_sizer_t) ( hawk_arr_t* arr, /**< array */ - hawk_oow_t hint /**< sizing hint */ + hawk_oow_t hint /**< sizing hint */ ); + +typedef struct hawk_arr_style_t hawk_arr_style_t; + +struct hawk_arr_style_t +{ + hawk_arr_copier_t copier; /* data copier */ + hawk_arr_freeer_t freeer; /* data freeer */ + hawk_arr_comper_t comper; /* data comparator */ + hawk_arr_keeper_t keeper; /* data keeper */ + hawk_arr_sizer_t sizer; /* size calculator */ +}; + +/** + * The hawk_arr_style_kind_t type defines the type of predefined + * callback set for pair manipulation. + */ +enum hawk_arr_style_kind_t +{ + /** store element pointers */ + HAWK_ARR_STYLE_DEFAULT, + /** copy elements */ + HAWK_ARR_STYLE_INLINE_COPIER +}; + +typedef enum hawk_arr_style_kind_t hawk_arr_style_kind_t; + + typedef hawk_arr_walk_t (*hawk_arr_walker_t) ( hawk_arr_t* arr /* array */, - hawk_oow_t index /* index to the visited slot */, - void* ctx /* user-defined context */ + hawk_oow_t index /* index to the visited slot */, + void* ctx /* user-defined context */ ); /** @@ -142,11 +174,7 @@ typedef hawk_arr_walk_t (*hawk_arr_walker_t) ( struct hawk_arr_t { hawk_gem_t* gem; - hawk_arr_copier_t copier; /* data copier */ - hawk_arr_freeer_t freeer; /* data freeer */ - hawk_arr_comper_t comper; /* data comparator */ - hawk_arr_keeper_t keeper; /* data keeper */ - hawk_arr_sizer_t sizer; /* size calculator */ + const hawk_arr_style_t* style; hawk_uint8_t scale; /* scale factor */ hawk_oow_t heap_pos_offset; /* offset in the data element where position * is stored when heap operation is performed. */ @@ -167,6 +195,14 @@ struct hawk_arr_slot_t extern "C" { #endif +/** + * The hawk_get_arr_style() functions returns a predefined callback set for + * pair manipulation. + */ +HAWK_EXPORT const hawk_arr_style_t* hawk_get_arr_style ( + hawk_arr_style_kind_t kind +); + /** * The hawk_arr_open() function creates a linear dynamic array. */ @@ -228,65 +264,14 @@ HAWK_EXPORT hawk_arr_copier_t hawk_arr_getcopier ( hawk_arr_t* arr /* array */ ); -/** - * The hawk_arr_setcopier() specifies how to clone an element. The special - * copier #HAWK_ARR_COPIER_INLINE copies the data inline to the internal slot. - * No freeer is invoked when the slot is freeed. You may set the copier to - * #HAWK_ARR_COPIER_SIMPLE to perform no special operation when the data - * pointer is stored. - */ -HAWK_EXPORT void hawk_arr_setcopier ( - hawk_arr_t* arr /** arr */, - hawk_arr_copier_t copier /** element copier */ + +HAWK_EXPORT void hawk_arr_setstyle ( + hawk_arr_t* arr, + const hawk_arr_style_t* style ); -/** - * The hawk_arr_getfreeer() function returns a custom element destroyer. - */ -HAWK_EXPORT hawk_arr_freeer_t hawk_arr_getfreeer ( - hawk_arr_t* arr /**< arr */ -); - -/** - * The hawk_arr_setfreeer() function specifies how to destroy an element. - * The @a freeer is called when a slot containing the element is destroyed. - */ -HAWK_EXPORT void hawk_arr_setfreeer ( - hawk_arr_t* arr /**< arr */, - hawk_arr_freeer_t freeer /**< element freeer */ -); - -HAWK_EXPORT hawk_arr_comper_t hawk_arr_getcomper ( - hawk_arr_t* arr /**< arr */ -); - -/** - * The hawk_arr_setcomper() function specifies how to compare two elements - * for equality test. The comparator @a comper must return 0 if two elements - * compared are equal, 1 if the first element is greater than the - * second, -1 if the second element is greater than the first. - */ -HAWK_EXPORT void hawk_arr_setcomper ( - hawk_arr_t* arr /**< arr */, - hawk_arr_comper_t comper /**< comparator */ -); - -HAWK_EXPORT hawk_arr_keeper_t hawk_arr_getkeeper ( - hawk_arr_t* arr -); - -HAWK_EXPORT void hawk_arr_setkeeper ( - hawk_arr_t* arr, - hawk_arr_keeper_t keeper -); - -HAWK_EXPORT hawk_arr_sizer_t hawk_arr_getsizer ( - hawk_arr_t* arr -); - -HAWK_EXPORT void hawk_arr_setsizer ( - hawk_arr_t* arr, - hawk_arr_sizer_t sizer +HAWK_EXPORT const hawk_arr_style_t* hawk_arr_getstyle ( + hawk_arr_t* arr ); HAWK_EXPORT hawk_oow_t hawk_arr_getsize ( @@ -475,6 +460,19 @@ HAWK_EXPORT void hawk_arr_setheapposoffset ( hawk_oow_t offset ); + + +/** + * The hawk_arr_dflcomp() function is the default comparator + */ +HAWK_EXPORT int hawk_arr_dflcomp ( + hawk_arr_t* arr, + const void* dptr1, + hawk_oow_t dlen1, + const void* dptr2, + hawk_oow_t dlen2 +); + #if defined(__cplusplus) } #endif diff --git a/hawk/lib/hawk.c b/hawk/lib/hawk.c index 445495cb..5bc6be85 100644 --- a/hawk/lib/hawk.c +++ b/hawk/lib/hawk.c @@ -233,15 +233,15 @@ int hawk_init (hawk_t* hawk, hawk_mmgr_t* mmgr, hawk_cmgr_t* cmgr, const hawk_pr *(hawk_t**)(hawk->parse.gbls + 1) = hawk; hawk_arr_setscale (hawk->parse.gbls, HAWK_SIZEOF(hawk_ooch_t)); - hawk_arr_setcopier (hawk->parse.gbls, HAWK_ARR_COPIER_INLINE); + hawk_arr_setstyle (hawk->parse.gbls, hawk_get_arr_style(HAWK_ARR_STYLE_INLINE_COPIER)); *(hawk_t**)(hawk->parse.lcls + 1) = hawk; hawk_arr_setscale (hawk->parse.lcls, HAWK_SIZEOF(hawk_ooch_t)); - hawk_arr_setcopier (hawk->parse.lcls, HAWK_ARR_COPIER_INLINE); + hawk_arr_setstyle (hawk->parse.lcls, hawk_get_arr_style(HAWK_ARR_STYLE_INLINE_COPIER)); *(hawk_t**)(hawk->parse.params + 1) = hawk; hawk_arr_setscale (hawk->parse.params, HAWK_SIZEOF(hawk_ooch_t)); - hawk_arr_setcopier (hawk->parse.params, HAWK_ARR_COPIER_INLINE); + hawk_arr_setstyle (hawk->parse.params, hawk_get_arr_style(HAWK_ARR_STYLE_INLINE_COPIER)); *(hawk_t**)(hawk->fnc.user + 1) = hawk; hawk_htb_setstyle (hawk->fnc.user, &fncusercbs); diff --git a/hawk/lib/hawk.h b/hawk/lib/hawk.h index c0a74320..84476fbe 100644 --- a/hawk/lib/hawk.h +++ b/hawk/lib/hawk.h @@ -36,6 +36,7 @@ #include /* for rtx->named */ #define HAWK_MAP_IS_RBT #include +#include #include /** \file @@ -272,6 +273,22 @@ struct hawk_val_map_t }; typedef struct hawk_val_map_t hawk_val_map_t; +/** + * The hawk_val_arr_t type defines a arr type. The type field is + * #HAWK_VAL_MAP. + */ +struct hawk_val_arr_t +{ + HAWK_VAL_HDR; + + /* TODO: make val_arr to array if the indices used are all + * integers switch to arr dynamically once the + * non-integral index is seen. + */ + hawk_arr_t* arr; +}; +typedef struct hawk_val_arr_t hawk_val_arr_t; + /** * The hawk_val_ref_t type defines a reference type that is used * internally only. The type field is #HAWK_VAL_REF. @@ -1371,9 +1388,10 @@ enum hawk_val_type_t HAWK_VAL_MBS = 4, /**< byte array */ HAWK_VAL_FUN = 5, /**< function pointer */ HAWK_VAL_MAP = 6, /**< map */ + HAWK_VAL_ARR = 7, /**< array */ - HAWK_VAL_REX = 7, /**< regular expression */ - HAWK_VAL_REF = 8 /**< reference to other types */ + HAWK_VAL_REX = 8, /**< regular expression */ + HAWK_VAL_REF = 9 /**< reference to other types */ }; typedef enum hawk_val_type_t hawk_val_type_t; @@ -2867,8 +2885,9 @@ HAWK_EXPORT hawk_val_t* hawk_rtx_makerexval ( * The hawk_rtx_makemapval() function creates an empty array value. * \return value on success, #HAWK_NULL on failure */ -HAWK_EXPORT hawk_val_t* hawk_rtx_makearrayval ( - hawk_rtx_t* rtx +HAWK_EXPORT hawk_val_t* hawk_rtx_makearrval ( + hawk_rtx_t* rtx, + hawk_oow_t init_capa ); /** diff --git a/hawk/lib/mod-hawk.c b/hawk/lib/mod-hawk.c index 5b5d2e62..e55a51fe 100644 --- a/hawk/lib/mod-hawk.c +++ b/hawk/lib/mod-hawk.c @@ -217,7 +217,7 @@ static int fnc_array (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) { hawk_val_t* tmp; - tmp = hawk_rtx_makearrayval(rtx); + tmp = hawk_rtx_makearrval(rtx, 0); if (HAWK_UNLIKELY(!tmp)) return -1; /* hard failure */ /* TODO: take arguments and put them to the map */ diff --git a/hawk/lib/mod-sys.c b/hawk/lib/mod-sys.c index 32b5dea1..a2dff070 100644 --- a/hawk/lib/mod-sys.c +++ b/hawk/lib/mod-sys.c @@ -1610,12 +1610,12 @@ static int fnc_fchmod (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) /* ------------------------------------------------------------------------ */ /* - d = sys::opendir("/etc", sys::DIR_SORT); - if (d >= 0) - { - while (sys::readdir(d,a) > 0) print a; - sys::closedir(d); - } + d = sys::opendir("/etc", sys::DIR_SORT); + if (d >= 0) + { + while (sys::readdir(d,a) > 0) print a; + sys::closedir(d); + } ################################################# diff --git a/hawk/lib/val.c b/hawk/lib/val.c index f6f40cab..13cbed86 100644 --- a/hawk/lib/val.c +++ b/hawk/lib/val.c @@ -891,11 +891,103 @@ hawk_val_t* hawk_rtx_makerexval (hawk_rtx_t* rtx, const hawk_oocs_t* str, hawk_t /* --------------------------------------------------------------------- */ -hawk_val_t* hawk_rtx_makearrayval (hawk_rtx_t* rtx) +static void free_arrayval (hawk_arr_t* arr, void* dptr, hawk_oow_t dlen) { -/* TODO: */ - hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_ENOIMPL); - return HAWK_NULL; + hawk_rtx_t* rtx = *(hawk_rtx_t**)hawk_arr_getxtn(arr); + hawk_val_t* v = (hawk_val_t*)dptr; + +#if defined(DEBUG_VAL) + hawk_logfmt (hawk_rtx_gethawk(rtx), HAWK_LOG_STDERR, HAWK_T("refdown in arr free - [%O]\n"), v); +#endif + +#if defined(HAWK_ENABLE_GC) + if (HAWK_VTR_IS_POINTER(v) && v->v_gc && hawk_val_to_gch(v)->gc_refs == GCH_UNREACHABLE) + { + /* do nothing if the element is unreachable. + * this behavior pairs up with gc_free_unreachables() to + * achieve safe disposal of a value */ + return; + } +#endif + + hawk_rtx_refdownval (rtx, v); +} + +static void same_arrayval (hawk_arr_t* map, void* dptr, hawk_oow_t dlen) +{ + hawk_rtx_t* run = *(hawk_rtx_t**)hawk_arr_getxtn(map); +#if defined(DEBUG_VAL) + hawk_logfmt (hawk_rtx_gethawk(rtx), HAWK_LOG_STDERR, HAWK_T("refdown nofree in map free - [%O]\n"), dptr); +#endif + hawk_rtx_refdownval_nofree (run, dptr); +} + + +hawk_val_t* hawk_rtx_makearrval (hawk_rtx_t* rtx, hawk_oow_t init_capa) +{ + static hawk_arr_style_t style = + { + /* the key is copied inline into a pair and is freed when the pair + * is destroyed. not setting copier for a value means that the pointer + * to the data allocated somewhere else is remembered in a pair. but + * freeing the actual value is handled by free_arrval and same_arrval */ + + HAWK_ARR_COPIER_DEFAULT, + free_arrayval, + HAWK_ARR_COMPER_DEFAULT, + same_arrayval, + HAWK_ARR_SIZER_DEFAULT + }; +#if defined(HAWK_ENABLE_GC) + int retried = 0; +#endif + hawk_val_arr_t* val; + +#if defined(HAWK_ENABLE_GC) +retry: + val = (hawk_val_arr_t*)gc_calloc_val(rtx, HAWK_SIZEOF(hawk_val_arr_t) + HAWK_SIZEOF(hawk_arr_t) + HAWK_SIZEOF(rtx)); +#else + val = (hawk_val_arr_t*)hawk_rtx_callocmem(rtx, HAWK_SIZEOF(hawk_val_arr_t) + HAWK_SIZEOF(hawk_arr_t) + HAWK_SIZEOF(rtx)); +#endif + if (HAWK_UNLIKELY(!val)) return HAWK_NULL; + + val->v_type = HAWK_VAL_ARR; + val->v_refs = 0; + val->v_static = 0; + val->nstr = 0; + val->v_gc = 0; + val->arr = (hawk_arr_t*)(val + 1); + + if (init_capa <= 0) init_capa = 64; /* TODO: what is the best initial value? */ + if (HAWK_UNLIKELY(hawk_arr_init(val->arr, hawk_rtx_getgem(rtx), init_capa) <= -1)) + { +#if defined(HAWK_ENABLE_GC) + gc_free_val (rtx, (hawk_val_t*)val); + if (HAWK_LIKELY(!retried)) + { + /* this arr involves non-gc allocatinon, which happens outside gc_calloc_val(). + * reattempt to allocate after full gc like gc_calloc_val() */ + hawk_rtx_gc (rtx, HAWK_COUNTOF(rtx->gc.g) - 1); + retried = 1; + goto retry; + } +#else + hawk_rtx_freemem (rtx, val); +#endif + return HAWK_NULL; + } + *(hawk_rtx_t**)hawk_arr_getxtn(val->arr) = rtx; + hawk_arr_setstyle (val->arr, &style); + +#if defined(HAWK_ENABLE_GC) + gc_chain_val (&rtx->gc.g[0], (hawk_val_t*)val); + val->v_gc = 1; + #if defined(DEBUG_GC) + hawk_logbfmt (hawk_rtx_gethawk(rtx), HAWK_LOG_STDERR, "[GC] MADE GCH %p VAL %p\n", hawk_val_to_gch(val), val); + #endif +#endif + + return (hawk_val_t*)val; } /* --------------------------------------------------------------------- */ @@ -981,7 +1073,7 @@ retry: if (HAWK_LIKELY(!retried)) { /* this map involves non-gc allocatinon, which happens outside gc_calloc_val(). - * reattempt to allocate after full gc like gc_calloc_val() */ + * reattempt to allocate after full gc like gc_calloc_val() */ hawk_rtx_gc (rtx, HAWK_COUNTOF(rtx->gc.g) - 1); retried = 1; goto retry;