| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2020-04-16 03:42:30 +00:00
										 |  |  |     Copyright (c) 2006-2020 Chung, Hyung-Hwan. All rights reserved. | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Redistribution and use in source and binary forms, with or without | 
					
						
							|  |  |  |     modification, are permitted provided that the following conditions | 
					
						
							|  |  |  |     are met: | 
					
						
							|  |  |  |     1. Redistributions of source code must retain the above copyright | 
					
						
							|  |  |  |        notice, this list of conditions and the following disclaimer. | 
					
						
							|  |  |  |     2. Redistributions in binary form must reproduce the above copyright | 
					
						
							|  |  |  |        notice, this list of conditions and the following disclaimer in the | 
					
						
							|  |  |  |        documentation and/or other materials provided with the distribution. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR | 
					
						
							|  |  |  |     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 
					
						
							|  |  |  |     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 
					
						
							|  |  |  |     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 
					
						
							|  |  |  |     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 
					
						
							|  |  |  |     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
					
						
							|  |  |  |     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
					
						
							|  |  |  |     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
					
						
							|  |  |  |     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 
					
						
							|  |  |  |     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <hawk-arr.h>
 | 
					
						
							|  |  |  | #include "hawk-prv.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define slot_t   hawk_arr_slot_t
 | 
					
						
							|  |  |  | #define copier_t hawk_arr_copier_t
 | 
					
						
							|  |  |  | #define freeer_t hawk_arr_freeer_t
 | 
					
						
							|  |  |  | #define comper_t hawk_arr_comper_t
 | 
					
						
							|  |  |  | #define sizer_t  hawk_arr_sizer_t
 | 
					
						
							|  |  |  | #define keeper_t hawk_arr_keeper_t
 | 
					
						
							|  |  |  | #define walker_t hawk_arr_walker_t
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define TOB(arr,len) ((len)*(arr)->scale)
 | 
					
						
							|  |  |  | #define DPTR(slot)   ((slot)->val.ptr)
 | 
					
						
							|  |  |  | #define DLEN(slot)   ((slot)->val.len)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* the default comparator is not proper for number comparision.
 | 
					
						
							|  |  |  |  * the first different byte decides whice side is greater */ | 
					
						
							| 
									
										
										
										
											2020-04-24 06:49:19 +00:00
										 |  |  | int hawk_arr_dflcomp (hawk_arr_t* arr, const void* dptr1, hawk_oow_t dlen1, const void* dptr2, hawk_oow_t dlen2) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	if (dlen1 == dlen2) return HAWK_MEMCMP(dptr1, dptr2, TOB(arr,dlen1)); | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int n; | 
					
						
							|  |  |  | 	hawk_oow_t min; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	min = (dlen1 < dlen2)? dlen1: dlen2; | 
					
						
							|  |  |  | 	n = HAWK_MEMCMP(dptr1, dptr2, TOB(arr,min)); | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	if (n == 0 && dlen1 != dlen2) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		n = (dlen1 > dlen2)? 1: -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return n; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static HAWK_INLINE slot_t* alloc_slot (hawk_arr_t* arr, void* dptr, hawk_oow_t dlen) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	slot_t* n; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-24 06:49:19 +00:00
										 |  |  | 	if (arr->style->copier == HAWK_ARR_COPIER_SIMPLE) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-12-16 15:09:58 +00:00
										 |  |  | 		n = (slot_t*)hawk_gem_allocmem(arr->gem, HAWK_SIZEOF(slot_t)); | 
					
						
							| 
									
										
										
										
											2020-03-03 12:00:13 +00:00
										 |  |  | 		if (HAWK_UNLIKELY(!n)) return HAWK_NULL; | 
					
						
							| 
									
										
										
										
											2020-04-24 06:49:19 +00:00
										 |  |  | 		DPTR(n) = dptr; /* store the pointer */ | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-04-24 06:49:19 +00:00
										 |  |  | 	else if (arr->style->copier == HAWK_ARR_COPIER_INLINE) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-12-16 15:09:58 +00:00
										 |  |  | 		n = (slot_t*)hawk_gem_allocmem(arr->gem, HAWK_SIZEOF(slot_t) + TOB(arr,dlen)); | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		if (HAWK_UNLIKELY(!n)) return HAWK_NULL; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-24 06:49:19 +00:00
										 |  |  | 		HAWK_MEMCPY (n + 1, dptr, TOB(arr,dlen)); /* copy data contents */ | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		DPTR(n) = n + 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-12-16 15:09:58 +00:00
										 |  |  | 		n = (slot_t*)hawk_gem_allocmem(arr->gem, HAWK_SIZEOF(slot_t)); | 
					
						
							| 
									
										
										
										
											2020-03-03 12:00:13 +00:00
										 |  |  | 		if (HAWK_UNLIKELY(!n)) return HAWK_NULL; | 
					
						
							| 
									
										
										
										
											2020-04-24 06:49:19 +00:00
										 |  |  | 		DPTR(n) = arr->style->copier(arr, dptr, dlen); /* call the custom copier */ | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		if (HAWK_UNLIKELY(!DPTR(n))) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2025-07-06 16:29:52 +09:00
										 |  |  | 			hawk_gem_freemem(arr->gem, n); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			return HAWK_NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	DLEN(n) = dlen; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return n; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-16 15:09:58 +00:00
										 |  |  | hawk_arr_t* hawk_arr_open (hawk_gem_t* gem, hawk_oow_t xtnsize, hawk_oow_t capa) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	hawk_arr_t* arr; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-16 15:09:58 +00:00
										 |  |  | 	arr = (hawk_arr_t*)hawk_gem_allocmem(gem, HAWK_SIZEOF(hawk_arr_t) + xtnsize); | 
					
						
							| 
									
										
										
										
											2020-03-03 12:00:13 +00:00
										 |  |  | 	if (HAWK_UNLIKELY(!arr)) return HAWK_NULL; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-16 15:09:58 +00:00
										 |  |  | 	if (hawk_arr_init(arr, gem, capa) <= -1) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-12-16 15:09:58 +00:00
										 |  |  | 		hawk_gem_freemem (gem, arr); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		return HAWK_NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HAWK_MEMSET (arr + 1, 0, xtnsize); | 
					
						
							|  |  |  | 	return arr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hawk_arr_close (hawk_arr_t* arr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hawk_arr_fini (arr); | 
					
						
							| 
									
										
										
										
											2025-07-06 16:29:52 +09:00
										 |  |  | 	hawk_gem_freemem(arr->gem, arr); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-24 06:49:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-16 15:09:58 +00:00
										 |  |  | int hawk_arr_init (hawk_arr_t* arr, hawk_gem_t* gem, hawk_oow_t capa) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-10-01 13:55:02 +09:00
										 |  |  | 	HAWK_MEMSET(arr, 0, HAWK_SIZEOF(*arr)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-16 15:09:58 +00:00
										 |  |  | 	arr->gem = gem; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	arr->size = 0; | 
					
						
							| 
									
										
										
										
											2020-04-29 13:03:02 +00:00
										 |  |  | 	arr->tally = 0; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	arr->capa = 0; | 
					
						
							|  |  |  | 	arr->slot = HAWK_NULL; | 
					
						
							|  |  |  | 	arr->scale = 1; | 
					
						
							|  |  |  | 	arr->heap_pos_offset = HAWK_ARR_NIL; | 
					
						
							| 
									
										
										
										
											2020-04-24 06:49:19 +00:00
										 |  |  | 	arr->style = &style[0]; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return (hawk_arr_setcapa(arr, capa) == HAWK_NULL)? -1: 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hawk_arr_fini (hawk_arr_t* arr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hawk_arr_clear (arr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (arr->slot) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2025-07-06 16:29:52 +09:00
										 |  |  | 		hawk_gem_freemem(arr->gem, arr->slot); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		arr->slot = HAWK_NULL; | 
					
						
							|  |  |  | 		arr->capa = 0; | 
					
						
							| 
									
										
										
										
											2020-04-29 13:03:02 +00:00
										 |  |  | 		arr->size = 0 ; | 
					
						
							|  |  |  | 		arr->tally = 0; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int hawk_arr_getscale (hawk_arr_t* arr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return arr->scale; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hawk_arr_setscale (hawk_arr_t* arr, int scale) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	/* The scale should be larger than 0 and less than or equal to the
 | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	 * maximum value that the hawk_uint8_t type can hold */ | 
					
						
							| 
									
										
										
										
											2019-12-21 16:59:00 +00:00
										 |  |  | 	HAWK_ASSERT (scale > 0 && scale <= HAWK_TYPE_MAX(hawk_uint8_t)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (scale <= 0) scale = 1; | 
					
						
							|  |  |  | 	if (scale > HAWK_TYPE_MAX(hawk_uint8_t)) scale = HAWK_TYPE_MAX(hawk_uint8_t); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	arr->scale = scale; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-24 06:49:19 +00:00
										 |  |  | const hawk_arr_style_t* hawk_arr_getstyle (hawk_arr_t* arr) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-05-04 07:21:13 +00:00
										 |  |  | 	return arr->style; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-24 06:49:19 +00:00
										 |  |  | void hawk_arr_setstyle (hawk_arr_t* arr, const hawk_arr_style_t* style) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-04-24 06:49:19 +00:00
										 |  |  | 	HAWK_ASSERT (style != HAWK_NULL); | 
					
						
							|  |  |  | 	arr->style = style; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | hawk_oow_t hawk_arr_getsize (hawk_arr_t* arr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return arr->size; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | hawk_oow_t hawk_arr_getcapa (hawk_arr_t* arr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return arr->capa; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | hawk_arr_t* hawk_arr_setcapa (hawk_arr_t* arr, hawk_oow_t capa) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	void* tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (capa == arr->capa) return arr; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-29 13:03:02 +00:00
										 |  |  | 	if (capa < arr->size) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		/* to trigger freeers on the items truncated */ | 
					
						
							| 
									
										
										
										
											2025-07-06 16:29:52 +09:00
										 |  |  | 		hawk_arr_delete(arr, capa, arr->size - capa); | 
					
						
							|  |  |  | 		HAWK_ASSERT(arr->size <= capa); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	if (capa > 0) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-12-16 15:09:58 +00:00
										 |  |  | 		tmp = (slot_t**)hawk_gem_reallocmem(arr->gem, arr->slot, HAWK_SIZEOF(*arr->slot) * capa); | 
					
						
							| 
									
										
										
										
											2020-03-03 12:00:13 +00:00
										 |  |  | 		if (HAWK_UNLIKELY(!tmp)) return HAWK_NULL; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		if (arr->slot) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2025-07-06 16:29:52 +09:00
										 |  |  | 			hawk_arr_clear(arr); | 
					
						
							|  |  |  | 			hawk_gem_freemem(arr->gem, arr->slot); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		tmp = HAWK_NULL; | 
					
						
							| 
									
										
										
										
											2020-04-29 13:03:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		HAWK_ASSERT (arr->size == 0); | 
					
						
							|  |  |  | 		HAWK_ASSERT (arr->tally == 0); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	arr->slot = tmp; | 
					
						
							|  |  |  | 	arr->capa = capa; | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	return arr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | hawk_oow_t hawk_arr_search (hawk_arr_t* arr, hawk_oow_t pos, const void* dptr, hawk_oow_t dlen) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hawk_oow_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	for (i = pos; i < arr->size; i++) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		if (arr->slot[i] == HAWK_NULL) continue; | 
					
						
							| 
									
										
										
										
											2020-04-24 06:49:19 +00:00
										 |  |  | 		if (arr->style->comper(arr, DPTR(arr->slot[i]), DLEN(arr->slot[i]), dptr, dlen) == 0) return i; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-16 15:09:58 +00:00
										 |  |  | 	hawk_gem_seterrnum (arr->gem, HAWK_NULL, HAWK_ENOENT); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	return HAWK_ARR_NIL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | hawk_oow_t hawk_arr_rsearch (hawk_arr_t* arr, hawk_oow_t pos, const void* dptr, hawk_oow_t dlen) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hawk_oow_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (arr->size > 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (pos >= arr->size) pos = arr->size - 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		for (i = pos + 1; i-- > 0; ) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			if (arr->slot[i] == HAWK_NULL) continue; | 
					
						
							| 
									
										
										
										
											2020-04-24 06:49:19 +00:00
										 |  |  | 			if (arr->style->comper(arr, DPTR(arr->slot[i]), DLEN(arr->slot[i]), dptr, dlen) == 0) return i; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-16 15:09:58 +00:00
										 |  |  | 	hawk_gem_seterrnum (arr->gem, HAWK_NULL, HAWK_ENOENT); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	return HAWK_ARR_NIL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | hawk_oow_t hawk_arr_upsert (hawk_arr_t* arr, hawk_oow_t pos, void* dptr, hawk_oow_t dlen) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2025-10-01 13:55:02 +09:00
										 |  |  | 	if (pos < arr->size) return hawk_arr_update(arr, pos, dptr, dlen); | 
					
						
							| 
									
										
										
										
											2019-12-16 15:09:58 +00:00
										 |  |  | 	return hawk_arr_insert(arr, pos, dptr, dlen); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | hawk_oow_t hawk_arr_insert (hawk_arr_t* arr, hawk_oow_t pos, void* dptr, hawk_oow_t dlen) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hawk_oow_t i; | 
					
						
							|  |  |  | 	slot_t* slot; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* allocate the slot first */ | 
					
						
							| 
									
										
										
										
											2020-04-24 06:49:19 +00:00
										 |  |  | 	slot = alloc_slot(arr, dptr, dlen); | 
					
						
							|  |  |  | 	if (HAWK_UNLIKELY(!slot)) return HAWK_ARR_NIL; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	/* do resizeing if necessary.
 | 
					
						
							|  |  |  | 	 * resizing is performed after slot allocation because that way, it | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	 * doesn't modify arr on any errors */ | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	if (pos >= arr->capa || arr->size >= arr->capa) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		hawk_oow_t capa, mincapa; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* get the minimum capacity needed */ | 
					
						
							|  |  |  | 		mincapa = (pos >= arr->size)? (pos + 1): (arr->size + 1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-24 06:49:19 +00:00
										 |  |  | 		if (arr->style->sizer) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2020-04-24 06:49:19 +00:00
										 |  |  | 			capa = arr->style->sizer(arr, mincapa); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 			if (arr->capa <= 0) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2019-12-21 16:59:00 +00:00
										 |  |  | 				HAWK_ASSERT (arr->size <= 0); | 
					
						
							| 
									
										
										
										
											2019-12-16 15:09:58 +00:00
										 |  |  | 				capa = HAWK_ALIGN_POW2(pos + 1, 64); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 			else | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				hawk_oow_t bound = (pos >= arr->size)? pos: arr->size; | 
					
						
							| 
									
										
										
										
											2019-12-16 15:09:58 +00:00
										 |  |  | 				capa = HAWK_ALIGN_POW2(bound + 1, 64); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 				do { capa = arr->capa * 2; } while (capa <= bound); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-12-16 15:09:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		do | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-12-16 15:09:58 +00:00
										 |  |  | 			if (hawk_arr_setcapa(arr, capa) != HAWK_NULL) break; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if (capa <= mincapa) | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2025-07-06 16:29:52 +09:00
										 |  |  | 				if (arr->style->freeer) arr->style->freeer(arr, DPTR(slot), DLEN(slot)); | 
					
						
							|  |  |  | 				hawk_gem_freemem(arr->gem, slot); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 				return HAWK_ARR_NIL; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			capa--; /* let it retry after lowering the capacity */ | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		while (1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-16 15:09:58 +00:00
										 |  |  | 		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 */ | 
					
						
							| 
									
										
										
										
											2025-07-06 16:29:52 +09:00
										 |  |  | 			if (arr->style->freeer) arr->style->freeer(arr, DPTR(slot), DLEN(slot)); | 
					
						
							|  |  |  | 			hawk_gem_freemem(arr->gem, slot); | 
					
						
							| 
									
										
										
										
											2019-12-16 15:09:58 +00:00
										 |  |  | 			hawk_gem_seterrnum (arr->gem, HAWK_NULL, HAWK_EBUFFULL); | 
					
						
							|  |  |  | 			return HAWK_ARR_NIL; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* fill in the gap with HAWK_NULL */ | 
					
						
							|  |  |  | 	for (i = arr->size; i < pos; i++) arr->slot[i] = HAWK_NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* shift values to the next cell */ | 
					
						
							|  |  |  | 	for (i = arr->size; i > pos; i--) arr->slot[i] = arr->slot[i-1]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*  set the value */ | 
					
						
							|  |  |  | 	arr->slot[pos] = slot; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (pos > arr->size) arr->size = pos + 1; | 
					
						
							|  |  |  | 	else arr->size++; | 
					
						
							| 
									
										
										
										
											2020-04-29 13:03:02 +00:00
										 |  |  | 	arr->tally++; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return pos; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | hawk_oow_t hawk_arr_update (hawk_arr_t* arr, hawk_oow_t pos, void* dptr, hawk_oow_t dlen) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	slot_t* c; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	if (pos >= arr->size) | 
					
						
							| 
									
										
										
										
											2019-12-16 15:09:58 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		hawk_gem_seterrnum (arr->gem, HAWK_NULL, HAWK_EINVAL); | 
					
						
							|  |  |  | 		return HAWK_ARR_NIL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	c = arr->slot[pos]; | 
					
						
							|  |  |  | 	if (c == HAWK_NULL) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/* no previous data */ | 
					
						
							| 
									
										
										
										
											2019-12-16 15:09:58 +00:00
										 |  |  | 		arr->slot[pos] = alloc_slot(arr, dptr, dlen); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		if (arr->slot[pos] == HAWK_NULL) return HAWK_ARR_NIL; | 
					
						
							| 
									
										
										
										
											2020-04-29 13:03:02 +00:00
										 |  |  | 		arr->tally++; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (dptr == DPTR(c) && dlen == DLEN(c)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			/* updated to the same data */ | 
					
						
							| 
									
										
										
										
											2025-10-01 13:55:02 +09:00
										 |  |  | 			if (arr->style->keeper) arr->style->keeper(arr, dptr, dlen); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			/* updated to different data */ | 
					
						
							| 
									
										
										
										
											2019-12-16 15:09:58 +00:00
										 |  |  | 			slot_t* slot = alloc_slot(arr, dptr, dlen); | 
					
						
							| 
									
										
										
										
											2020-04-24 06:49:19 +00:00
										 |  |  | 			if (HAWK_UNLIKELY(!slot)) return HAWK_ARR_NIL; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-06 16:29:52 +09:00
										 |  |  | 			if (arr->style->freeer) arr->style->freeer(arr, DPTR(c), DLEN(c)); | 
					
						
							|  |  |  | 			hawk_gem_freemem(arr->gem, c); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			arr->slot[pos] = slot; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return pos; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | hawk_oow_t hawk_arr_delete (hawk_arr_t* arr, hawk_oow_t index, hawk_oow_t count) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hawk_oow_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (index >= arr->size) return 0; | 
					
						
							|  |  |  | 	if (count > arr->size - index) count = arr->size - index; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	i = index; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = index; i < index + count; i++) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		slot_t* c = arr->slot[i]; | 
					
						
							| 
									
										
										
										
											2020-04-29 13:03:02 +00:00
										 |  |  | 		if (c) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2025-07-06 16:29:52 +09:00
										 |  |  | 			if (arr->style->freeer) arr->style->freeer(arr, DPTR(c), DLEN(c)); | 
					
						
							|  |  |  | 			hawk_gem_freemem(arr->gem, c); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			arr->slot[i] = HAWK_NULL; | 
					
						
							| 
									
										
										
										
											2020-04-29 13:03:02 +00:00
										 |  |  | 			arr->tally--; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = index + count; i < arr->size; i++) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-04-29 13:03:02 +00:00
										 |  |  | 		arr->slot[i - count] = arr->slot[i]; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-04-29 13:03:02 +00:00
										 |  |  | 	arr->slot[arr->size - 1] = HAWK_NULL; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	arr->size -= count; | 
					
						
							|  |  |  | 	return count; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | hawk_oow_t hawk_arr_uplete (hawk_arr_t* arr, hawk_oow_t index, hawk_oow_t count) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hawk_oow_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (index >= arr->size) return 0; | 
					
						
							|  |  |  | 	if (count > arr->size - index) count = arr->size - index; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	i = index; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = index; i < index + count; i++) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		slot_t* c = arr->slot[i]; | 
					
						
							| 
									
										
										
										
											2020-04-29 13:03:02 +00:00
										 |  |  | 		if (c) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2025-07-06 16:29:52 +09:00
										 |  |  | 			if (arr->style->freeer) arr->style->freeer(arr, DPTR(c), DLEN(c)); | 
					
						
							|  |  |  | 			hawk_gem_freemem(arr->gem, c); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			arr->slot[i] = HAWK_NULL; | 
					
						
							| 
									
										
										
										
											2020-04-29 13:03:02 +00:00
										 |  |  | 			arr->tally--; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return count; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hawk_arr_clear (hawk_arr_t* arr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hawk_oow_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	for (i = 0; i < arr->size; i++) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		slot_t* c = arr->slot[i]; | 
					
						
							|  |  |  | 		if (c != HAWK_NULL) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2025-07-06 16:29:52 +09:00
										 |  |  | 			if (arr->style->freeer) arr->style->freeer(arr, DPTR(c), DLEN(c)); | 
					
						
							|  |  |  | 			hawk_gem_freemem(arr->gem, c); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			arr->slot[i] = HAWK_NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	arr->size = 0; | 
					
						
							| 
									
										
										
										
											2020-04-29 13:03:02 +00:00
										 |  |  | 	arr->tally = 0; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | hawk_oow_t hawk_arr_walk (hawk_arr_t* arr, walker_t walker, void* ctx) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hawk_arr_walk_t w = HAWK_ARR_WALK_FORWARD; | 
					
						
							|  |  |  | 	hawk_oow_t i = 0, nwalks = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (arr->size <= 0) return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	while (1) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-04-24 15:52:08 +00:00
										 |  |  | 		if (arr->slot[i]) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2020-04-24 15:52:08 +00:00
										 |  |  | 			w = walker(arr, i, ctx); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			nwalks++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (w == HAWK_ARR_WALK_STOP) break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		if (w == HAWK_ARR_WALK_FORWARD) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			i++; | 
					
						
							|  |  |  | 			if (i >= arr->size) break; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		if (w == HAWK_ARR_WALK_BACKWARD) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			if (i <= 0) break; | 
					
						
							|  |  |  | 			i--; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nwalks; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | hawk_oow_t hawk_arr_rwalk (hawk_arr_t* arr, walker_t walker, void* ctx) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hawk_arr_walk_t w = HAWK_ARR_WALK_BACKWARD; | 
					
						
							|  |  |  | 	hawk_oow_t i, nwalks = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (arr->size <= 0) return 0; | 
					
						
							|  |  |  | 	i = arr->size - 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 	while (1) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2025-10-01 13:55:02 +09:00
										 |  |  | 		if (arr->slot[i]) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2025-10-01 13:55:02 +09:00
										 |  |  | 			w = walker(arr, i, ctx); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			nwalks++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (w == HAWK_ARR_WALK_STOP) break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		if (w == HAWK_ARR_WALK_FORWARD) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			i++; | 
					
						
							|  |  |  | 			if (i >= arr->size) break; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 		if (w == HAWK_ARR_WALK_BACKWARD) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			if (i <= 0) break; | 
					
						
							|  |  |  | 			i--; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nwalks; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | hawk_oow_t hawk_arr_pushstack (hawk_arr_t* arr, void* dptr, hawk_oow_t dlen) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2025-10-01 13:55:02 +09:00
										 |  |  | 	return hawk_arr_insert(arr, arr->size, dptr, dlen); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hawk_arr_popstack (hawk_arr_t* arr) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2025-10-01 13:55:02 +09:00
										 |  |  | 	HAWK_ASSERT(arr->size > 0); | 
					
						
							|  |  |  | 	hawk_arr_delete(arr, arr->size - 1, 1); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define HEAP_PARENT(x) (((x)-1) / 2)
 | 
					
						
							|  |  |  | #define HEAP_LEFT(x)   ((x)*2 + 1)
 | 
					
						
							|  |  |  | #define HEAP_RIGHT(x)  ((x)*2 + 2)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define HEAP_UPDATE_POS(arr, index) \
 | 
					
						
							|  |  |  | 	do { \ | 
					
						
							|  |  |  | 		if (arr->heap_pos_offset != HAWK_ARR_NIL) \ | 
					
						
							|  |  |  | 			*(hawk_oow_t*)((hawk_uint8_t*)DPTR(arr->slot[index]) + arr->heap_pos_offset) = index; \ | 
					
						
							|  |  |  | 	} while(0) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-09 04:34:21 +00:00
										 |  |  | static hawk_oow_t sift_up (hawk_arr_t* arr, hawk_oow_t index) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	hawk_oow_t parent; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (index > 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		int n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		parent = HEAP_PARENT(index); | 
					
						
							| 
									
										
										
										
											2020-04-24 06:49:19 +00:00
										 |  |  | 		n = arr->style->comper(arr, DPTR(arr->slot[index]), DLEN(arr->slot[index]), DPTR(arr->slot[parent]), DLEN(arr->slot[parent])); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		if (n > 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			slot_t* tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			tmp = arr->slot[index]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			while (1) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				arr->slot[index] = arr->slot[parent]; | 
					
						
							| 
									
										
										
										
											2025-10-01 13:55:02 +09:00
										 |  |  | 				HEAP_UPDATE_POS(arr, index); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				index = parent; | 
					
						
							|  |  |  | 				parent = HEAP_PARENT(parent); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if (index <= 0) break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-24 06:49:19 +00:00
										 |  |  | 				n = arr->style->comper(arr, DPTR(tmp), DLEN(tmp), DPTR(arr->slot[parent]), DLEN(arr->slot[parent])); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 				if (n <= 0) break; | 
					
						
							| 
									
										
										
										
											2024-05-02 22:47:30 +09:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			arr->slot[index] = tmp; | 
					
						
							| 
									
										
										
										
											2025-10-01 13:55:02 +09:00
										 |  |  | 			HEAP_UPDATE_POS(arr, index); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return index; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-09 04:34:21 +00:00
										 |  |  | static hawk_oow_t sift_down (hawk_arr_t* arr, hawk_oow_t index) | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	hawk_oow_t base; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	base = arr->size / 2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (index < base) /* at least 1 child is under the 'index' position */ | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		slot_t* tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		tmp = arr->slot[index]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		do | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hawk_oow_t left, right, child; | 
					
						
							|  |  |  | 			int n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			left= HEAP_LEFT(index); | 
					
						
							|  |  |  | 			right = HEAP_RIGHT(index); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (right < arr->size) | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2020-04-24 06:49:19 +00:00
										 |  |  | 				n = arr->style->comper(arr, | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 					DPTR(arr->slot[right]), DLEN(arr->slot[right]), | 
					
						
							|  |  |  | 					DPTR(arr->slot[left]), DLEN(arr->slot[left])); | 
					
						
							|  |  |  | 				child = (n > 0)? right: left; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				child = left; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-24 06:49:19 +00:00
										 |  |  | 			n = arr->style->comper(arr, DPTR(tmp), DLEN(tmp), DPTR(arr->slot[child]), DLEN(arr->slot[child])); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			if (n > 0) break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			arr->slot[index] = arr->slot[child]; | 
					
						
							| 
									
										
										
										
											2025-10-01 13:55:02 +09:00
										 |  |  | 			HEAP_UPDATE_POS(arr, index); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 			index = child; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		while (index < base); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		arr->slot[index] = tmp; | 
					
						
							| 
									
										
										
										
											2025-10-01 13:55:02 +09:00
										 |  |  | 		HEAP_UPDATE_POS(arr, index); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return index; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | hawk_oow_t hawk_arr_pushheap (hawk_arr_t* arr, void* dptr, hawk_oow_t dlen) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hawk_oow_t index; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* add a value at the back of the array  */ | 
					
						
							|  |  |  | 	index = arr->size; | 
					
						
							| 
									
										
										
										
											2019-12-16 15:09:58 +00:00
										 |  |  | 	if (hawk_arr_insert(arr, index, dptr, dlen) == HAWK_ARR_NIL) return HAWK_ARR_NIL; | 
					
						
							| 
									
										
										
										
											2025-10-01 13:55:02 +09:00
										 |  |  | 	HEAP_UPDATE_POS(arr, index); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-21 16:59:00 +00:00
										 |  |  | 	HAWK_ASSERT (arr->size == index + 1); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* move the item upto the top if it's greater than the parent items */ | 
					
						
							| 
									
										
										
										
											2025-10-01 13:55:02 +09:00
										 |  |  | 	sift_up(arr, index); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	return arr->size; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hawk_arr_popheap (hawk_arr_t* arr) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-12-21 16:59:00 +00:00
										 |  |  | 	HAWK_ASSERT (arr->size > 0); | 
					
						
							| 
									
										
										
										
											2025-10-01 13:55:02 +09:00
										 |  |  | 	hawk_arr_deleteheap(arr, 0); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hawk_arr_deleteheap (hawk_arr_t* arr, hawk_oow_t index) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	slot_t* tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-21 16:59:00 +00:00
										 |  |  | 	HAWK_ASSERT (arr->size > 0); | 
					
						
							|  |  |  | 	HAWK_ASSERT (index < arr->size); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* remember the item to destroy */ | 
					
						
							|  |  |  | 	tmp = arr->slot[index]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	arr->size = arr->size - 1; | 
					
						
							|  |  |  | 	if (arr->size > 0 && index != arr->size) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		int n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* move the last item to the deleting position */ | 
					
						
							|  |  |  | 		arr->slot[index] = arr->slot[arr->size]; | 
					
						
							| 
									
										
										
										
											2025-10-01 13:55:02 +09:00
										 |  |  | 		HEAP_UPDATE_POS(arr, index); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* move it up if the last item is greater than the item to be deleted,
 | 
					
						
							|  |  |  | 		 * move it down otherwise. */ | 
					
						
							| 
									
										
										
										
											2020-04-24 06:49:19 +00:00
										 |  |  | 		n = arr->style->comper(arr, DPTR(arr->slot[index]), DLEN(arr->slot[index]), DPTR(tmp), DLEN(tmp)); | 
					
						
							| 
									
										
										
										
											2025-10-01 13:55:02 +09:00
										 |  |  | 		if (n > 0) sift_up(arr, index); | 
					
						
							|  |  |  | 		else if (n < 0) sift_down(arr, index); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* destroy the actual item */ | 
					
						
							| 
									
										
										
										
											2025-07-06 16:29:52 +09:00
										 |  |  | 	if (arr->style->freeer) arr->style->freeer(arr, DPTR(tmp), DLEN(tmp)); | 
					
						
							|  |  |  | 	hawk_gem_freemem(arr->gem, tmp); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* empty the last slot */ | 
					
						
							|  |  |  | 	arr->slot[arr->size] = HAWK_NULL; | 
					
						
							| 
									
										
										
										
											2020-04-29 13:03:02 +00:00
										 |  |  | 	arr->tally--; | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | hawk_oow_t hawk_arr_updateheap (hawk_arr_t* arr, hawk_oow_t index, void* dptr, hawk_oow_t dlen) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	slot_t* tmp; | 
					
						
							|  |  |  | 	int n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tmp = arr->slot[index]; | 
					
						
							| 
									
										
										
										
											2019-12-21 16:59:00 +00:00
										 |  |  | 	HAWK_ASSERT (tmp != HAWK_NULL); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-24 06:49:19 +00:00
										 |  |  | 	n = arr->style->comper(arr, dptr, dlen, DPTR(tmp), DLEN(tmp)); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	if (n) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (hawk_arr_update(arr, index, dptr, dlen) == HAWK_ARR_NIL) return HAWK_ARR_NIL; | 
					
						
							| 
									
										
										
										
											2025-10-01 13:55:02 +09:00
										 |  |  | 		HEAP_UPDATE_POS(arr, index); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-10-01 13:55:02 +09:00
										 |  |  | 		if (n > 0) sift_up(arr, index); | 
					
						
							|  |  |  | 		else sift_down(arr, index); | 
					
						
							| 
									
										
										
										
											2019-12-13 04:29:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return index; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | hawk_oow_t hawk_arr_getheapposoffset (hawk_arr_t* arr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return arr->heap_pos_offset; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hawk_arr_setheapposoffset (hawk_arr_t* arr, hawk_oow_t offset) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	arr->heap_pos_offset = offset; | 
					
						
							|  |  |  | } |