diff --git a/Makefile.djgpp b/Makefile.djgpp
index 76020b1..e348072 100644
--- a/Makefile.djgpp
+++ b/Makefile.djgpp
@@ -33,7 +33,7 @@ INSTALL = install
DEBUG = -g
## CHANGE THIS ##
-TARGET = roo-e
+TARGET = roo_e
SRCDIR = .
OBJDIR = obj
BINDIR = bin
@@ -41,7 +41,7 @@ BINDIR = bin
# CFLAGS, LDFLAGS, CPPFLAGS, PREFIX can be overriden on CLI
CFLAGS := $(DEBUG)
-CFLAGS += -I$(SRCDIR)/shared -I$(SRCDIR)/roo-e/src
+CFLAGS += -I$(SRCDIR)/shared -I$(SRCDIR)/roo_e/src
CPPFLAGS :=
LDFLAGS :=
LDLIBS :=
@@ -78,9 +78,8 @@ ALL_LDLIBS := $(LDLIBS) -lc
# Source, Binaries, Dependencies
-SRC := $(shell find $(SRCDIR)/roo-e -type f -name '*.c')
-SRC += $(shell find $(SRCDIR)/shared -type f -name '*.c')
-SRC += $(shell find $(SRCDIR)/test -type f -name '*.c')
+SRC := $(shell find $(SRCDIR)/roo_e/src -type f -name '*.c')
+SRC += $(shell find $(SRCDIR)/test/src -type f -name '*.c')
OBJ := $(patsubst $(SRCDIR)/%,$(OBJDIR)/%,$(SRC:.c=.o))
DEP := $(OBJ:.o=.d)
BIN := $(BINDIR)/$(TARGET)
diff --git a/build.sh b/build.sh
index 353fde1..427c3ec 100755
--- a/build.sh
+++ b/build.sh
@@ -1,4 +1,4 @@
-#!/bin/bash -e
+#!/bin/bash -ex
#
# Roo/E, the Kangaroo Punch Portable GUI Toolkit
@@ -24,21 +24,21 @@
#
-# This requires DJGPP for Linux in /opt/cross/djgpp
-#
-# See: https://github.com/andrewwutw/build-djgpp
+# This requires Toolchains from:
+# https://skunkworks.kangaroopunch.com/skunkworks/toolchains
[[ -d obj ]] && rm -rf obj
mkdir -p \
- obj/shared/thirdparty/memwatch \
- obj/roo-e/src/platform \
- obj/roo-e/src/gui/widgets \
+ obj/roo_e/src/thirdparty/memwatch \
+ obj/roo_e/src/platform \
+ obj/roo_e/src/gui/widgets \
obj/test/src
-source /opt/cross/djgpp/setenv
+#source <(../toolchains/toolchains.sh use x86 dos)
+source ../toolchains/x-tools/djgpp/setenv
make -f Makefile.djgpp
-[[ -f bin/roo-e ]] && rm bin/roo-e
-[[ -f bin/grx ]] && rm bin/grx
+[[ -f bin/roo_e ]] && rm bin/roo_e
+[[ -f bin/grx ]] && rm bin/grx
diff --git a/font/font.pro b/font/font.pro
deleted file mode 100644
index 6921f3b..0000000
--- a/font/font.pro
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# Kangaroo Punch MultiPlayer Game Server Mark II
-# Copyright (C) 2020-2021 Scott Duensing
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-#
-
-TEMPLATE = app
-CONFIG -= qt
-CONFIG += console
-
-DESTDIR = $$OUT_PWD/bin
-SHARED = $$PWD/../shared
-CLIENT = $$PWD/../client/src
-SYSTEM = $$CLIENT/system
-GUI = $$CLIENT/gui
-
-DEFINES += FONT_DEBUGGING
-
-INCLUDEPATH += \
- $$SHARED \
- $$SHARED/thirdparty \
- $$CLIENT \
- $$SYSTEM \
- $$GUI
-
-HEADERS = \
- $$SHARED/stddclmr.h \
- $$SHARED/thirdparty/memwatch/memwatch.h \
- $$SHARED/thirdparty/stb_image.h
-
-SOURCES = \
- $$SHARED/thirdparty/memwatch/memwatch.c \
- src/main.c
diff --git a/master.pro b/master.pro
deleted file mode 100644
index 78ac7da..0000000
--- a/master.pro
+++ /dev/null
@@ -1,40 +0,0 @@
-#
-# Roo/E, the Kangaroo Punch Portable GUI Toolkit
-# Copyright (C) 2022 Scott Duensing
-#
-# http://kangaroopunch.com
-#
-#
-# This file is part of Roo/E.
-#
-# Roo/E is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Affero General Public License as published by the Free
-# Software Foundation, either version 3 of the License, or (at your option)
-# any later version.
-#
-# Roo/E is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with Roo/E. If not, see .
-#
-
-
-TEMPLATE = subdirs
-CONFIG *= ORDERED
-
-SUBDIRS = \
- roo-e \
- test
-
-OTHER_FILES = \
- .gitattributes \
- .gitignore \
- agpl-3.0.txt \
- LICENSE \
- build.sh \
- Makefile.djgpp \
- test.sh \
- test.conf
diff --git a/roo_e/roo-e.pro b/roo_e/roo-e.pro
deleted file mode 100644
index e38466c..0000000
--- a/roo_e/roo-e.pro
+++ /dev/null
@@ -1,105 +0,0 @@
-#
-# Roo/E, the Kangaroo Punch Portable GUI Toolkit
-# Copyright (C) 2022 Scott Duensing
-#
-# http://kangaroopunch.com
-#
-#
-# This file is part of Roo/E.
-#
-# Roo/E is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Affero General Public License as published by the Free
-# Software Foundation, either version 3 of the License, or (at your option)
-# any later version.
-#
-# Roo/E is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with Roo/E. If not, see .
-#
-
-
-TEMPLATE = lib
-CONFIG -= \
- app_bundle \
- qt
-CONFIG += \
- console \
- c99 \
- staticlib
-
-CONFIG += BACKEND_SDL2
-#CONFIG += BACKEND_DJGPP
-
-SHARED = $$PWD/../shared
-
-DESTDIR = $$OUT_PWD/bin
-
-INCLUDEPATH += \
- $$PWD/src \
- $$SHARED
-
-HEADERS += \
- $$SHARED/macros.h \
- $$SHARED/array.h \
- $$SHARED/memory.h \
- $$SHARED/stddclmr.h \
- $$SHARED/thirdparty/memwatch/memwatch.h \
- $$SHARED/thirdparty/stb_ds.h \
- $$SHARED/log.h \
- $$SHARED/util.h \
- src/gui/font.h \
- src/gui/gui-all.h \
- src/gui/gui.h \
- src/gui/image.h \
- src/gui/surface.h \
- src/gui/widgets/button.h \
- src/gui/widgets/checkbox.h \
- src/gui/widgets/frame.h \
- src/gui/widgets/label.h \
- src/gui/widgets/picture.h \
- src/gui/widgets/radio.h \
- src/gui/widgets/hscroll.h \
- src/gui/widgets/scroll.h \
- src/gui/widgets/vscroll.h \
- src/gui/wmwindow.h \
- src/os.h \
- src/platform/platform.h \
- src/thirdparty/stb_image.h
-
-SOURCES += \
- $$SHARED/array.c \
- $$SHARED/memory.c \
- $$SHARED/thirdparty/memwatch/memwatch.c \
- $$SHARED/log.c \
- $$SHARED/util.c \
- src/gui/font.c \
- src/gui/gui.c \
- src/gui/image.c \
- src/gui/surface.c \
- src/gui/widgets/button.c \
- src/gui/widgets/checkbox.c \
- src/gui/widgets/frame.c \
- src/gui/widgets/label.c \
- src/gui/widgets/picture.c \
- src/gui/widgets/radio.c \
- src/gui/widgets/hscroll.c \
- src/gui/widgets/scroll.c \
- src/gui/widgets/vscroll.c \
- src/gui/wmwindow.c \
- src/platform/djgpp.c \
- src/platform/sdl2.c
-
-BACKEND_SDL2 {
- DEFINES += BACKEND_SDL2
- LIBS += \
- -lSDL2
-}
-
-BACKEND_DJGPP {
- DEFINES += BACKEND_DJGPP
-}
-
diff --git a/roo_e/src/gui/font.c b/roo_e/src/gui/font.c
index 90b3149..eec3af5 100644
--- a/roo_e/src/gui/font.c
+++ b/roo_e/src/gui/font.c
@@ -121,7 +121,10 @@ FontT *fontLoad(char *filename) {
return NULL;
}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-result"
fread(buffer, size, 1, in);
+#pragma GCC diagnostic pop
fclose(in);
font = fontFromRAMLoad(buffer);
diff --git a/roo_e/src/gui/gui.c b/roo_e/src/gui/gui.c
index e20748d..2d1e415 100644
--- a/roo_e/src/gui/gui.c
+++ b/roo_e/src/gui/gui.c
@@ -133,7 +133,10 @@ void guiShutdown(void) {
while (hmlen(_widgetCatalog) > 0) {
if (_widgetCatalog[0].value->unregister) _widgetCatalog[0].value->unregister(NULL);
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-value"
hmdel(_widgetCatalog, _widgetCatalog[0].key);
+#pragma GCC diagnostic pop
}
hmfree(_widgetCatalog);
diff --git a/roo_e/src/gui/surface.c b/roo_e/src/gui/surface.c
index dd8376f..257ad11 100644
--- a/roo_e/src/gui/surface.c
+++ b/roo_e/src/gui/surface.c
@@ -413,12 +413,15 @@ SurfaceT *surfaceLoad(char *filename) {
if (in) {
NEW(SurfaceT, i);
if (!i) return NULL;
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-result"
fread(&i->width, sizeof(uint16_t), 1, in);
fread(&i->height, sizeof(uint16_t), 1, in);
fread(&i->scanline, sizeof(size_t), 1, in);
fread(&i->bytes, sizeof(size_t), 1, in);
i->buffer.bits8 = (uint8_t *)malloc(i->bytes);
fread(i->buffer.bits8, i->bytes, 1, in);
+#pragma GCC diagnostic pop
fclose(in);
}
}
diff --git a/roo_e/src/gui/widgets/checkbox.c b/roo_e/src/gui/widgets/checkbox.c
index 3fd4af8..fec9116 100644
--- a/roo_e/src/gui/widgets/checkbox.c
+++ b/roo_e/src/gui/widgets/checkbox.c
@@ -68,7 +68,7 @@ CheckboxT *checkboxCreate(char *label, uint8_t value, ...) {
memset(c, 0, sizeof(CheckboxT));
c->value = value;
- c->label = labelCreate(LABEL_ALIGN_LEFT, f, label);
+ c->label = labelCreate(LABEL_ALIGN_LEFT, f, label); // Gets attached to widget tree during paint.
if (!c->label) {
DEL(c);
return NULL;
diff --git a/roo_e/src/gui/wmwindow.c b/roo_e/src/gui/wmwindow.c
index cc20eb6..ac513ed 100644
--- a/roo_e/src/gui/wmwindow.c
+++ b/roo_e/src/gui/wmwindow.c
@@ -515,8 +515,6 @@ void windowMove(WindowT *w, uint16_t x, uint16_t y) {
static void windowPaint(struct WidgetS *widget, ...) {
int16_t x = 0;
int16_t y;
- int16_t px;
- int16_t py;
int16_t xi;
int16_t yi;
int16_t xc;
@@ -676,10 +674,6 @@ void wmRender(void) {
DamageListT **damageList = NULL;
DamageListT *damageItem = NULL;
- // ***TODO*** We still calculate the desktop in the damage list below.
- // There's some odd off-by-one when rendering that needs fixed. For now
- // we just draw the desktop and then window contents.
-
// Update all minimized windows.
surfaceSet(__guiBackBuffer);
for (i=0; ireg->paint(widget, WINDOW_PAINT_NORMAL);
}
+ surfaceSet(__guiBackBuffer);
+
// This is global so we can click on them later.
_iconCount = 0;
- // Draw the desktop.
- surfaceSet(__guiBackBuffer);
- surfaceClear(GUI_CYAN);
-
// Do we have windows?
if (arrlen(_windowList) > 0) {
@@ -928,6 +920,12 @@ void wmRender(void) {
}
} while (found == 1);
+ // ***TODO*** Something is off by one somewhere. The last column
+ // and row are not being rendered / blitted.
+ // Hack around it for now.
+ surfaceLineH(0, videoDisplayWidthGet() - 1, videoDisplayHeightGet() - 1, GUI_BLACK);
+ surfaceLineV(videoDisplayWidthGet() - 1, 0, videoDisplayHeightGet() - 1, GUI_BLACK);
+
// Draw the damage list.
i = 1;
for (k=0; krect.x, damageList[k]->rect.y, damageList[k]->rect.x2, damageList[k]->rect.y2, GUI_CYAN);
+ surfaceBoxFilled(damageList[k]->rect.x, damageList[k]->rect.y, damageList[k]->rect.x2 - 1, damageList[k]->rect.y2 - 1, GUI_CYAN);
}
/*
@@ -1003,7 +1001,6 @@ void wmUpdate(EventT *event) {
int16_t x2;
int16_t y2;
uint8_t onResize = 0;
- WidgetT *widget;
WidgetT *widgetOver = NULL;
WindowT *win = NULL;
ClickRawInputT rawEvent = { 0 };
diff --git a/roo_e/src/thirdparty/memwatch/memwatch.c b/roo_e/src/thirdparty/memwatch/memwatch.c
index ae0f6ab..0c36e3a 100644
--- a/roo_e/src/thirdparty/memwatch/memwatch.c
+++ b/roo_e/src/thirdparty/memwatch/memwatch.c
@@ -829,6 +829,8 @@ void* mwUnmark( void *p, const char *file, unsigned line ) {
** Abort/Retry/Ignore handlers
***********************************************************************/
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-result"
static int mwARI( const char *estr ) {
char inbuf[81];
int c;
@@ -843,6 +845,7 @@ static int mwARI( const char *estr ) {
if( c == 'I' || c == 'i' ) return MW_ARI_IGNORE;
return MW_ARI_ABORT;
}
+#pragma GCC diagnostic pop
/* standard ARI handler (exported) */
int mwAriHandler( const char *estr ) {
diff --git a/roo_e/src/thirdparty/stb_ds.h b/roo_e/src/thirdparty/stb_ds.h
index ebd6161..d69a682 100644
--- a/roo_e/src/thirdparty/stb_ds.h
+++ b/roo_e/src/thirdparty/stb_ds.h
@@ -4,11 +4,11 @@
dynamic arrays and hash tables for C (also works in C++).
For a gentle introduction:
- http://nothings.org/stb_ds
+ http://nothings.org/stb_ds
To use this library, do this in *one* C or C++ file:
- #define STB_DS_IMPLEMENTATION
- #include "stb_ds.h"
+ #define STB_DS_IMPLEMENTATION
+ #include "stb_ds.h"
TABLE OF CONTENTS
@@ -25,7 +25,7 @@ COMPILE-TIME OPTIONS
#define STBDS_NO_SHORT_NAMES
- This flag needs to be set globally.
+ This flag needs to be set globally.
By default stb_ds exposes shorter function names that are not qualified
with the "stbds_" prefix. If these names conflict with the names in your
@@ -33,7 +33,7 @@ COMPILE-TIME OPTIONS
#define STBDS_SIPHASH_2_4
- This flag only needs to be set in the file containing #define STB_DS_IMPLEMENTATION.
+ This flag only needs to be set in the file containing #define STB_DS_IMPLEMENTATION.
By default stb_ds.h hashes using a weaker variant of SipHash and a custom hash for
4- and 8-byte keys. On 64-bit platforms, you can define the above flag to force
@@ -44,7 +44,7 @@ COMPILE-TIME OPTIONS
#define STBDS_REALLOC(context,ptr,size) better_realloc
#define STBDS_FREE(context,ptr) better_free
- These defines only need to be set in the file containing #define STB_DS_IMPLEMENTATION.
+ These defines only need to be set in the file containing #define STB_DS_IMPLEMENTATION.
By default stb_ds uses stdlib realloc() and free() for memory management. You can
substitute your own functions instead by defining these symbols. You must either
@@ -53,11 +53,11 @@ COMPILE-TIME OPTIONS
#define STBDS_UNIT_TESTS
- Defines a function stbds_unit_tests() that checks the functioning of the data structures.
+ Defines a function stbds_unit_tests() that checks the functioning of the data structures.
Note that on older versions of gcc (e.g. 5.x.x) you may need to build with '-std=c++0x'
- (or equivalentally '-std=c++11') when using anonymous structures as seen on the web
- page or in STBDS_UNIT_TESTS.
+ (or equivalentally '-std=c++11') when using anonymous structures as seen on the web
+ page or in STBDS_UNIT_TESTS.
LICENSE
@@ -68,7 +68,7 @@ DOCUMENTATION
Dynamic Arrays
- Non-function interface:
+ Non-function interface:
Declare an empty dynamic array of type T
T* foo = NULL;
@@ -293,77 +293,77 @@ DOCUMENTATION
NOTES
* These data structures are realloc'd when they grow, and the macro
- "functions" write to the provided pointer. This means: (a) the pointer
- must be an lvalue, and (b) the pointer to the data structure is not
- stable, and you must maintain it the same as you would a realloc'd
- pointer. For example, if you pass a pointer to a dynamic array to a
- function which updates it, the function must return back the new
- pointer to the caller. This is the price of trying to do this in C.
+ "functions" write to the provided pointer. This means: (a) the pointer
+ must be an lvalue, and (b) the pointer to the data structure is not
+ stable, and you must maintain it the same as you would a realloc'd
+ pointer. For example, if you pass a pointer to a dynamic array to a
+ function which updates it, the function must return back the new
+ pointer to the caller. This is the price of trying to do this in C.
* The following are the only functions that are thread-safe on a single data
- structure, i.e. can be run in multiple threads simultaneously on the same
- data structure
- hmlen shlen
- hmlenu shlenu
- hmget_ts shget_ts
- hmgeti_ts shgeti_ts
- hmgets_ts shgets_ts
+ structure, i.e. can be run in multiple threads simultaneously on the same
+ data structure
+ hmlen shlen
+ hmlenu shlenu
+ hmget_ts shget_ts
+ hmgeti_ts shgeti_ts
+ hmgets_ts shgets_ts
* You iterate over the contents of a dynamic array and a hashmap in exactly
- the same way, using arrlen/hmlen/shlen:
+ the same way, using arrlen/hmlen/shlen:
for (i=0; i < arrlen(foo); ++i)
... foo[i] ...
* All operations except arrins/arrdel are O(1) amortized, but individual
- operations can be slow, so these data structures may not be suitable
- for real time use. Dynamic arrays double in capacity as needed, so
- elements are copied an average of once. Hash tables double/halve
- their size as needed, with appropriate hysteresis to maintain O(1)
- performance.
+ operations can be slow, so these data structures may not be suitable
+ for real time use. Dynamic arrays double in capacity as needed, so
+ elements are copied an average of once. Hash tables double/halve
+ their size as needed, with appropriate hysteresis to maintain O(1)
+ performance.
NOTES - DYNAMIC ARRAY
* If you know how long a dynamic array is going to be in advance, you can avoid
- extra memory allocations by using arrsetlen to allocate it to that length in
- advance and use foo[n] while filling it out, or arrsetcap to allocate the memory
- for that length and use arrput/arrpush as normal.
+ extra memory allocations by using arrsetlen to allocate it to that length in
+ advance and use foo[n] while filling it out, or arrsetcap to allocate the memory
+ for that length and use arrput/arrpush as normal.
* Unlike some other versions of the dynamic array, this version should
- be safe to use with strict-aliasing optimizations.
+ be safe to use with strict-aliasing optimizations.
NOTES - HASH MAP
* For compilers other than GCC and clang (e.g. Visual Studio), for hmput/hmget/hmdel
- and variants, the key must be an lvalue (so the macro can take the address of it).
- Extensions are used that eliminate this requirement if you're using C99 and later
- in GCC or clang, or if you're using C++ in GCC. But note that this can make your
- code less portable.
+ and variants, the key must be an lvalue (so the macro can take the address of it).
+ Extensions are used that eliminate this requirement if you're using C99 and later
+ in GCC or clang, or if you're using C++ in GCC. But note that this can make your
+ code less portable.
* To test for presence of a key in a hashmap, just do 'hmgeti(foo,key) >= 0'.
* The iteration order of your data in the hashmap is determined solely by the
- order of insertions and deletions. In particular, if you never delete, new
- keys are always added at the end of the array. This will be consistent
- across all platforms and versions of the library. However, you should not
- attempt to serialize the internal hash table, as the hash is not consistent
- between different platforms, and may change with future versions of the library.
+ order of insertions and deletions. In particular, if you never delete, new
+ keys are always added at the end of the array. This will be consistent
+ across all platforms and versions of the library. However, you should not
+ attempt to serialize the internal hash table, as the hash is not consistent
+ between different platforms, and may change with future versions of the library.
* Use sh_new_arena() for string hashmaps that you never delete from. Initialize
- with NULL if you're managing the memory for your strings, or your strings are
- never freed (at least until the hashmap is freed). Otherwise, use sh_new_strdup().
- @TODO: make an arena variant that garbage collects the strings with a trivial
- copy collector into a new arena whenever the table shrinks / rebuilds. Since
- current arena recommendation is to only use arena if it never deletes, then
- this can just replace current arena implementation.
+ with NULL if you're managing the memory for your strings, or your strings are
+ never freed (at least until the hashmap is freed). Otherwise, use sh_new_strdup().
+ @TODO: make an arena variant that garbage collects the strings with a trivial
+ copy collector into a new arena whenever the table shrinks / rebuilds. Since
+ current arena recommendation is to only use arena if it never deletes, then
+ this can just replace current arena implementation.
* If adversarial input is a serious concern and you're on a 64-bit platform,
- enable STBDS_SIPHASH_2_4 (see the 'Compile-time options' section), and pass
- a strong random number to stbds_rand_seed.
+ enable STBDS_SIPHASH_2_4 (see the 'Compile-time options' section), and pass
+ a strong random number to stbds_rand_seed.
* The default value for the hash table is stored in foo[-1], so if you
- use code like 'hmget(T,k)->value = 5' you can accidentally overwrite
- the value stored by hmdefault if 'k' is not present.
+ use code like 'hmget(T,k)->value = 5' you can accidentally overwrite
+ the value stored by hmdefault if 'k' is not present.
CREDITS
@@ -373,15 +373,15 @@ CREDITS
github:HeroicKatora -- arraddn() reworking
Bugfixes:
- Andy Durdin
- Shane Liesegang
- Vinh Truong
- Andreas Molzer
- github:hashitaku
- github:srdjanstipic
- Macoy Madson
- Andreas Vennstrom
- Tobias Mansfield-Williams
+ Andy Durdin
+ Shane Liesegang
+ Vinh Truong
+ Andreas Molzer
+ github:hashitaku
+ github:srdjanstipic
+ Macoy Madson
+ Andreas Vennstrom
+ Tobias Mansfield-Williams
*/
#ifdef STBDS_UNIT_TESTS
@@ -768,16 +768,16 @@ void *stbds_arrgrowf(void *a, size_t elemsize, size_t addlen, size_t min_cap)
// compute the minimum capacity needed
if (min_len > min_cap)
- min_cap = min_len;
+ min_cap = min_len;
if (min_cap <= stbds_arrcap(a))
- return a;
+ return a;
// increase needed capacity to guarantee O(1) amortized
if (min_cap < 2 * stbds_arrcap(a))
- min_cap = 2 * stbds_arrcap(a);
+ min_cap = 2 * stbds_arrcap(a);
else if (min_cap < 4)
- min_cap = 4;
+ min_cap = 4;
//if (num_prev < 65536) if (a) prev_allocs[num_prev++] = (int *) ((char *) a+1);
//if (num_prev == 2201)
@@ -786,11 +786,11 @@ void *stbds_arrgrowf(void *a, size_t elemsize, size_t addlen, size_t min_cap)
//if (num_prev < 65536) prev_allocs[num_prev++] = (int *) (char *) b;
b = (char *) b + sizeof(stbds_array_header);
if (a == NULL) {
- stbds_header(b)->length = 0;
- stbds_header(b)->hash_table = 0;
- stbds_header(b)->temp = 0;
+ stbds_header(b)->length = 0;
+ stbds_header(b)->hash_table = 0;
+ stbds_header(b)->temp = 0;
} else {
- STBDS_STATS(++stbds_array_grow);
+ STBDS_STATS(++stbds_array_grow);
}
stbds_header(b)->capacity = min_cap;
@@ -875,8 +875,8 @@ static size_t stbds_log2(size_t slot_count)
{
size_t n=0;
while (slot_count > 1) {
- slot_count >>= 1;
- ++n;
+ slot_count >>= 1;
+ ++n;
}
return n;
}
@@ -915,7 +915,7 @@ static stbds_hash_index *stbds_make_hash_index(size_t slot_count, stbds_hash_ind
t->used_count_shrink_threshold = slot_count* 6/16; // if table is only 6/16th full, shrink
#endif
// Following statistics were measured on a Core i7-6700 @ 4.00Ghz, compiled with clang 7.0.1 -O2
- // Note that the larger tables have high variance as they were run fewer times
+ // Note that the larger tables have high variance as they were run fewer times
// A1 A2 B1 C1
// 0.10ms : 0.10ms : 0.10ms : 0.11ms : 2,000 inserts creating 2K table
// 0.96ms : 0.95ms : 0.97ms : 1.04ms : 20,000 inserts creating 20K table
@@ -930,54 +930,54 @@ static stbds_hash_index *stbds_make_hash_index(size_t slot_count, stbds_hash_ind
// 192.11ms : 194.39ms : 196.38ms : 195.73ms : 500,000 inserts & deletes in 200M table
if (slot_count <= STBDS_BUCKET_LENGTH)
- t->used_count_shrink_threshold = 0;
+ t->used_count_shrink_threshold = 0;
// to avoid infinite loop, we need to guarantee that at least one slot is empty and will terminate probes
STBDS_ASSERT(t->used_count_threshold + t->tombstone_count_threshold < t->slot_count);
STBDS_STATS(++stbds_hash_alloc);
if (ot) {
- t->string = ot->string;
- // reuse old seed so we can reuse old hashes so below "copy out old data" doesn't do any hashing
- t->seed = ot->seed;
+ t->string = ot->string;
+ // reuse old seed so we can reuse old hashes so below "copy out old data" doesn't do any hashing
+ t->seed = ot->seed;
} else {
- size_t a,b,temp;
- memset(&t->string, 0, sizeof(t->string));
- t->seed = stbds_hash_seed;
- // LCG
- // in 32-bit, a = 2147001325 b = 715136305
- // in 64-bit, a = 2862933555777941757 b = 3037000493
- stbds_load_32_or_64(a,temp, 2147001325, 0x27bb2ee6, 0x87b0b0fd);
- stbds_load_32_or_64(b,temp, 715136305, 0, 0xb504f32d);
- stbds_hash_seed = stbds_hash_seed * a + b;
+ size_t a,b,temp;
+ memset(&t->string, 0, sizeof(t->string));
+ t->seed = stbds_hash_seed;
+ // LCG
+ // in 32-bit, a = 2147001325 b = 715136305
+ // in 64-bit, a = 2862933555777941757 b = 3037000493
+ stbds_load_32_or_64(a,temp, 2147001325, 0x27bb2ee6, 0x87b0b0fd);
+ stbds_load_32_or_64(b,temp, 715136305, 0, 0xb504f32d);
+ stbds_hash_seed = stbds_hash_seed * a + b;
}
{
- size_t i,j;
- for (i=0; i < slot_count >> STBDS_BUCKET_SHIFT; ++i) {
- stbds_hash_bucket *b = &t->storage[i];
- for (j=0; j < STBDS_BUCKET_LENGTH; ++j)
- b->hash[j] = STBDS_HASH_EMPTY;
- for (j=0; j < STBDS_BUCKET_LENGTH; ++j)
- b->index[j] = STBDS_INDEX_EMPTY;
- }
+ size_t i,j;
+ for (i=0; i < slot_count >> STBDS_BUCKET_SHIFT; ++i) {
+ stbds_hash_bucket *b = &t->storage[i];
+ for (j=0; j < STBDS_BUCKET_LENGTH; ++j)
+ b->hash[j] = STBDS_HASH_EMPTY;
+ for (j=0; j < STBDS_BUCKET_LENGTH; ++j)
+ b->index[j] = STBDS_INDEX_EMPTY;
+ }
}
// copy out the old data, if any
if (ot) {
- size_t i,j;
- t->used_count = ot->used_count;
- for (i=0; i < ot->slot_count >> STBDS_BUCKET_SHIFT; ++i) {
- stbds_hash_bucket *ob = &ot->storage[i];
- for (j=0; j < STBDS_BUCKET_LENGTH; ++j) {
- if (STBDS_INDEX_IN_USE(ob->index[j])) {
- size_t hash = ob->hash[j];
- size_t pos = stbds_probe_position(hash, t->slot_count, t->slot_count_log2);
- size_t step = STBDS_BUCKET_LENGTH;
- STBDS_STATS(++stbds_rehash_items);
- for (;;) {
- size_t limit,z;
- stbds_hash_bucket *bucket;
- bucket = &t->storage[pos >> STBDS_BUCKET_SHIFT];
- STBDS_STATS(++stbds_rehash_probes);
+ size_t i,j;
+ t->used_count = ot->used_count;
+ for (i=0; i < ot->slot_count >> STBDS_BUCKET_SHIFT; ++i) {
+ stbds_hash_bucket *ob = &ot->storage[i];
+ for (j=0; j < STBDS_BUCKET_LENGTH; ++j) {
+ if (STBDS_INDEX_IN_USE(ob->index[j])) {
+ size_t hash = ob->hash[j];
+ size_t pos = stbds_probe_position(hash, t->slot_count, t->slot_count_log2);
+ size_t step = STBDS_BUCKET_LENGTH;
+ STBDS_STATS(++stbds_rehash_items);
+ for (;;) {
+ size_t limit,z;
+ stbds_hash_bucket *bucket;
+ bucket = &t->storage[pos >> STBDS_BUCKET_SHIFT];
+ STBDS_STATS(++stbds_rehash_probes);
for (z=pos & STBDS_BUCKET_MASK; z < STBDS_BUCKET_LENGTH; ++z) {
if (bucket->hash[z] == 0) {
@@ -1017,7 +1017,7 @@ size_t stbds_hash_string(char *str, size_t seed)
{
size_t hash = seed;
while (*str)
- hash = STBDS_ROTATE_LEFT(hash, 9) + (unsigned char) *str++;
+ hash = STBDS_ROTATE_LEFT(hash, 9) + (unsigned char) *str++;
// Thomas Wang 64-to-32 bit mix function, hopefully also works in 32 bits
hash ^= seed;
@@ -1071,16 +1071,16 @@ static size_t stbds_siphash_bytes(void *p, size_t len, size_t seed)
#endif
#define STBDS_SIPROUND() \
- do { \
- v0 += v1; v1 = STBDS_ROTATE_LEFT(v1, 13); v1 ^= v0; v0 = STBDS_ROTATE_LEFT(v0,STBDS_SIZE_T_BITS/2); \
- v2 += v3; v3 = STBDS_ROTATE_LEFT(v3, 16); v3 ^= v2; \
- v2 += v1; v1 = STBDS_ROTATE_LEFT(v1, 17); v1 ^= v2; v2 = STBDS_ROTATE_LEFT(v2,STBDS_SIZE_T_BITS/2); \
- v0 += v3; v3 = STBDS_ROTATE_LEFT(v3, 21); v3 ^= v0; \
- } while (0)
+ do { \
+ v0 += v1; v1 = STBDS_ROTATE_LEFT(v1, 13); v1 ^= v0; v0 = STBDS_ROTATE_LEFT(v0,STBDS_SIZE_T_BITS/2); \
+ v2 += v3; v3 = STBDS_ROTATE_LEFT(v3, 16); v3 ^= v2; \
+ v2 += v1; v1 = STBDS_ROTATE_LEFT(v1, 17); v1 ^= v2; v2 = STBDS_ROTATE_LEFT(v2,STBDS_SIZE_T_BITS/2); \
+ v0 += v3; v3 = STBDS_ROTATE_LEFT(v3, 21); v3 ^= v0; \
+ } while (0)
for (i=0; i+sizeof(size_t) <= len; i += sizeof(size_t), d += sizeof(size_t)) {
- data = d[0] | (d[1] << 8) | (d[2] << 16) | (d[3] << 24);
- data |= (size_t) (d[4] | (d[5] << 8) | (d[6] << 16) | (d[7] << 24)) << 16 << 16; // discarded if size_t == 4
+ data = d[0] | (d[1] << 8) | (d[2] << 16) | (d[3] << 24);
+ data |= (size_t) (d[4] | (d[5] << 8) | (d[6] << 16) | (d[7] << 24)) << 16 << 16; // discarded if size_t == 4
v3 ^= data;
for (j=0; j < STBDS_SIPHASH_C_ROUNDS; ++j)
@@ -1089,22 +1089,22 @@ static size_t stbds_siphash_bytes(void *p, size_t len, size_t seed)
}
data = len << (STBDS_SIZE_T_BITS-8);
switch (len - i) {
- case 7: data |= ((size_t) d[6] << 24) << 24; // fall through
- case 6: data |= ((size_t) d[5] << 20) << 20; // fall through
- case 5: data |= ((size_t) d[4] << 16) << 16; // fall through
- case 4: data |= (d[3] << 24); // fall through
- case 3: data |= (d[2] << 16); // fall through
- case 2: data |= (d[1] << 8); // fall through
- case 1: data |= d[0]; // fall through
- case 0: break;
+ case 7: data |= ((size_t) d[6] << 24) << 24; // fall through
+ case 6: data |= ((size_t) d[5] << 20) << 20; // fall through
+ case 5: data |= ((size_t) d[4] << 16) << 16; // fall through
+ case 4: data |= (d[3] << 24); // fall through
+ case 3: data |= (d[2] << 16); // fall through
+ case 2: data |= (d[1] << 8); // fall through
+ case 1: data |= d[0]; // fall through
+ case 0: break;
}
v3 ^= data;
for (j=0; j < STBDS_SIPHASH_C_ROUNDS; ++j)
- STBDS_SIPROUND();
+ STBDS_SIPROUND();
v0 ^= data;
v2 ^= 0xff;
for (j=0; j < STBDS_SIPHASH_D_ROUNDS; ++j)
- STBDS_SIPROUND();
+ STBDS_SIPROUND();
#ifdef STBDS_SIPHASH_2_4
return v0^v1^v2^v3;
@@ -1121,77 +1121,77 @@ size_t stbds_hash_bytes(void *p, size_t len, size_t seed)
unsigned char *d = (unsigned char *) p;
if (len == 4) {
- unsigned int hash = d[0] | (d[1] << 8) | (d[2] << 16) | (d[3] << 24);
- #if 0
- // HASH32-A Bob Jenkin's hash function w/o large constants
- hash ^= seed;
- hash -= (hash<<6);
- hash ^= (hash>>17);
- hash -= (hash<<9);
- hash ^= seed;
- hash ^= (hash<<4);
- hash -= (hash<<3);
- hash ^= (hash<<10);
- hash ^= (hash>>15);
- #elif 1
- // HASH32-BB Bob Jenkin's presumably-accidental version of Thomas Wang hash with rotates turned into shifts.
- // Note that converting these back to rotates makes it run a lot slower, presumably due to collisions, so I'm
- // not really sure what's going on.
- hash ^= seed;
- hash = (hash ^ 61) ^ (hash >> 16);
- hash = hash + (hash << 3);
- hash = hash ^ (hash >> 4);
- hash = hash * 0x27d4eb2d;
- hash ^= seed;
- hash = hash ^ (hash >> 15);
- #else // HASH32-C - Murmur3
- hash ^= seed;
- hash *= 0xcc9e2d51;
- hash = (hash << 17) | (hash >> 15);
- hash *= 0x1b873593;
- hash ^= seed;
- hash = (hash << 19) | (hash >> 13);
- hash = hash*5 + 0xe6546b64;
- hash ^= hash >> 16;
- hash *= 0x85ebca6b;
- hash ^= seed;
- hash ^= hash >> 13;
- hash *= 0xc2b2ae35;
- hash ^= hash >> 16;
- #endif
- // Following statistics were measured on a Core i7-6700 @ 4.00Ghz, compiled with clang 7.0.1 -O2
- // Note that the larger tables have high variance as they were run fewer times
- // HASH32-A // HASH32-BB // HASH32-C
- // 0.10ms // 0.10ms // 0.10ms : 2,000 inserts creating 2K table
- // 0.96ms // 0.95ms // 0.99ms : 20,000 inserts creating 20K table
- // 14.69ms // 14.43ms // 14.97ms : 200,000 inserts creating 200K table
- // 199.99ms // 195.36ms // 202.05ms : 2,000,000 inserts creating 2M table
- // 2234.84ms // 2187.74ms // 2240.38ms : 20,000,000 inserts creating 20M table
- // 55.68ms // 53.72ms // 57.31ms : 500,000 inserts & deletes in 2K table
- // 63.43ms // 61.99ms // 65.73ms : 500,000 inserts & deletes in 20K table
- // 80.04ms // 77.96ms // 81.83ms : 500,000 inserts & deletes in 200K table
- // 100.42ms // 97.40ms // 102.39ms : 500,000 inserts & deletes in 2M table
- // 119.71ms // 120.59ms // 121.63ms : 500,000 inserts & deletes in 20M table
- // 185.28ms // 195.15ms // 187.74ms : 500,000 inserts & deletes in 200M table
- // 15.58ms // 14.79ms // 15.52ms : 200,000 inserts creating 200K table with varying key spacing
+ unsigned int hash = d[0] | (d[1] << 8) | (d[2] << 16) | (d[3] << 24);
+ #if 0
+ // HASH32-A Bob Jenkin's hash function w/o large constants
+ hash ^= seed;
+ hash -= (hash<<6);
+ hash ^= (hash>>17);
+ hash -= (hash<<9);
+ hash ^= seed;
+ hash ^= (hash<<4);
+ hash -= (hash<<3);
+ hash ^= (hash<<10);
+ hash ^= (hash>>15);
+ #elif 1
+ // HASH32-BB Bob Jenkin's presumably-accidental version of Thomas Wang hash with rotates turned into shifts.
+ // Note that converting these back to rotates makes it run a lot slower, presumably due to collisions, so I'm
+ // not really sure what's going on.
+ hash ^= seed;
+ hash = (hash ^ 61) ^ (hash >> 16);
+ hash = hash + (hash << 3);
+ hash = hash ^ (hash >> 4);
+ hash = hash * 0x27d4eb2d;
+ hash ^= seed;
+ hash = hash ^ (hash >> 15);
+ #else // HASH32-C - Murmur3
+ hash ^= seed;
+ hash *= 0xcc9e2d51;
+ hash = (hash << 17) | (hash >> 15);
+ hash *= 0x1b873593;
+ hash ^= seed;
+ hash = (hash << 19) | (hash >> 13);
+ hash = hash*5 + 0xe6546b64;
+ hash ^= hash >> 16;
+ hash *= 0x85ebca6b;
+ hash ^= seed;
+ hash ^= hash >> 13;
+ hash *= 0xc2b2ae35;
+ hash ^= hash >> 16;
+ #endif
+ // Following statistics were measured on a Core i7-6700 @ 4.00Ghz, compiled with clang 7.0.1 -O2
+ // Note that the larger tables have high variance as they were run fewer times
+ // HASH32-A // HASH32-BB // HASH32-C
+ // 0.10ms // 0.10ms // 0.10ms : 2,000 inserts creating 2K table
+ // 0.96ms // 0.95ms // 0.99ms : 20,000 inserts creating 20K table
+ // 14.69ms // 14.43ms // 14.97ms : 200,000 inserts creating 200K table
+ // 199.99ms // 195.36ms // 202.05ms : 2,000,000 inserts creating 2M table
+ // 2234.84ms // 2187.74ms // 2240.38ms : 20,000,000 inserts creating 20M table
+ // 55.68ms // 53.72ms // 57.31ms : 500,000 inserts & deletes in 2K table
+ // 63.43ms // 61.99ms // 65.73ms : 500,000 inserts & deletes in 20K table
+ // 80.04ms // 77.96ms // 81.83ms : 500,000 inserts & deletes in 200K table
+ // 100.42ms // 97.40ms // 102.39ms : 500,000 inserts & deletes in 2M table
+ // 119.71ms // 120.59ms // 121.63ms : 500,000 inserts & deletes in 20M table
+ // 185.28ms // 195.15ms // 187.74ms : 500,000 inserts & deletes in 200M table
+ // 15.58ms // 14.79ms // 15.52ms : 200,000 inserts creating 200K table with varying key spacing
- return (((size_t) hash << 16 << 16) | hash) ^ seed;
+ return (((size_t) hash << 16 << 16) | hash) ^ seed;
} else if (len == 8 && sizeof(size_t) == 8) {
- size_t hash = d[0] | (d[1] << 8) | (d[2] << 16) | (d[3] << 24);
- hash |= (size_t) (d[4] | (d[5] << 8) | (d[6] << 16) | (d[7] << 24)) << 16 << 16; // avoid warning if size_t == 4
- hash ^= seed;
- hash = (~hash) + (hash << 21);
- hash ^= STBDS_ROTATE_RIGHT(hash,24);
- hash *= 265;
- hash ^= STBDS_ROTATE_RIGHT(hash,14);
- hash ^= seed;
- hash *= 21;
- hash ^= STBDS_ROTATE_RIGHT(hash,28);
- hash += (hash << 31);
- hash = (~hash) + (hash << 18);
- return hash;
+ size_t hash = d[0] | (d[1] << 8) | (d[2] << 16) | (d[3] << 24);
+ hash |= (size_t) (d[4] | (d[5] << 8) | (d[6] << 16) | (d[7] << 24)) << 16 << 16; // avoid warning if size_t == 4
+ hash ^= seed;
+ hash = (~hash) + (hash << 21);
+ hash ^= STBDS_ROTATE_RIGHT(hash,24);
+ hash *= 265;
+ hash ^= STBDS_ROTATE_RIGHT(hash,14);
+ hash ^= seed;
+ hash *= 21;
+ hash ^= STBDS_ROTATE_RIGHT(hash,28);
+ hash += (hash << 31);
+ hash = (~hash) + (hash << 18);
+ return hash;
} else {
- return stbds_siphash_bytes(p,len,seed);
+ return stbds_siphash_bytes(p,len,seed);
}
#endif
}
@@ -1203,9 +1203,9 @@ size_t stbds_hash_bytes(void *p, size_t len, size_t seed)
static int stbds_is_key_equal(void *a, size_t elemsize, void *key, size_t keysize, size_t keyoffset, int mode, size_t i)
{
if (mode >= STBDS_HM_STRING)
- return 0==strcmp((char *) key, * (char **) ((char *) a + elemsize*i + keyoffset));
+ return 0==strcmp((char *) key, * (char **) ((char *) a + elemsize*i + keyoffset));
else
- return 0==memcmp(key, (char *) a + elemsize*i + keyoffset, keysize);
+ return 0==memcmp(key, (char *) a + elemsize*i + keyoffset, keysize);
}
#define STBDS_HASH_TO_ARR(x,elemsize) ((char*) (x) - (elemsize))
@@ -1217,13 +1217,13 @@ void stbds_hmfree_func(void *a, size_t elemsize)
{
if (a == NULL) return;
if (stbds_hash_table(a) != NULL) {
- if (stbds_hash_table(a)->string.mode == STBDS_SH_STRDUP) {
- size_t i;
- // skip 0th element, which is default
- for (i=1; i < stbds_header(a)->length; ++i)
- STBDS_FREE(NULL, *(char**) ((char *) a + elemsize*i));
- }
- stbds_strreset(&stbds_hash_table(a)->string);
+ if (stbds_hash_table(a)->string.mode == STBDS_SH_STRDUP) {
+ size_t i;
+ // skip 0th element, which is default
+ for (i=1; i < stbds_header(a)->length; ++i)
+ STBDS_FREE(NULL, *(char**) ((char *) a + elemsize*i));
+ }
+ stbds_strreset(&stbds_hash_table(a)->string);
}
STBDS_FREE(NULL, stbds_header(a)->hash_table);
STBDS_FREE(NULL, stbds_header(a));
@@ -1244,8 +1244,8 @@ static ptrdiff_t stbds_hm_find_slot(void *a, size_t elemsize, void *key, size_t
pos = stbds_probe_position(hash, table->slot_count, table->slot_count_log2);
for (;;) {
- STBDS_STATS(++stbds_hash_probes);
- bucket = &table->storage[pos >> STBDS_BUCKET_SHIFT];
+ STBDS_STATS(++stbds_hash_probes);
+ bucket = &table->storage[pos >> STBDS_BUCKET_SHIFT];
// start searching from pos to end of bucket, this should help performance on small hash tables that fit in cache
for (i=pos & STBDS_BUCKET_MASK; i < STBDS_BUCKET_LENGTH; ++i) {
@@ -1282,30 +1282,30 @@ void * stbds_hmget_key_ts(void *a, size_t elemsize, void *key, size_t keysize, p
{
size_t keyoffset = 0;
if (a == NULL) {
- // make it non-empty so we can return a temp
- a = stbds_arrgrowf(0, elemsize, 0, 1);
- stbds_header(a)->length += 1;
- memset(a, 0, elemsize);
- *temp = STBDS_INDEX_EMPTY;
- // adjust a to point after the default element
- return STBDS_ARR_TO_HASH(a,elemsize);
+ // make it non-empty so we can return a temp
+ a = stbds_arrgrowf(0, elemsize, 0, 1);
+ stbds_header(a)->length += 1;
+ memset(a, 0, elemsize);
+ *temp = STBDS_INDEX_EMPTY;
+ // adjust a to point after the default element
+ return STBDS_ARR_TO_HASH(a,elemsize);
} else {
- stbds_hash_index *table;
- void *raw_a = STBDS_HASH_TO_ARR(a,elemsize);
- // adjust a to point to the default element
- table = (stbds_hash_index *) stbds_header(raw_a)->hash_table;
- if (table == 0) {
- *temp = -1;
- } else {
- ptrdiff_t slot = stbds_hm_find_slot(a, elemsize, key, keysize, keyoffset, mode);
- if (slot < 0) {
- *temp = STBDS_INDEX_EMPTY;
- } else {
- stbds_hash_bucket *b = &table->storage[slot >> STBDS_BUCKET_SHIFT];
- *temp = b->index[slot & STBDS_BUCKET_MASK];
- }
- }
- return a;
+ stbds_hash_index *table;
+ void *raw_a = STBDS_HASH_TO_ARR(a,elemsize);
+ // adjust a to point to the default element
+ table = (stbds_hash_index *) stbds_header(raw_a)->hash_table;
+ if (table == 0) {
+ *temp = -1;
+ } else {
+ ptrdiff_t slot = stbds_hm_find_slot(a, elemsize, key, keysize, keyoffset, mode);
+ if (slot < 0) {
+ *temp = STBDS_INDEX_EMPTY;
+ } else {
+ stbds_hash_bucket *b = &table->storage[slot >> STBDS_BUCKET_SHIFT];
+ *temp = b->index[slot & STBDS_BUCKET_MASK];
+ }
+ }
+ return a;
}
}
@@ -1324,10 +1324,10 @@ void * stbds_hmput_default(void *a, size_t elemsize)
// a has a hash table but no entries, because of shmode <- grow
// a has entries <- do nothing
if (a == NULL || stbds_header(STBDS_HASH_TO_ARR(a,elemsize))->length == 0) {
- a = stbds_arrgrowf(a ? STBDS_HASH_TO_ARR(a,elemsize) : NULL, elemsize, 0, 1);
- stbds_header(a)->length += 1;
- memset(a, 0, elemsize);
- a=STBDS_ARR_TO_HASH(a,elemsize);
+ a = stbds_arrgrowf(a ? STBDS_HASH_TO_ARR(a,elemsize) : NULL, elemsize, 0, 1);
+ stbds_header(a)->length += 1;
+ memset(a, 0, elemsize);
+ a=STBDS_ARR_TO_HASH(a,elemsize);
}
return a;
}
@@ -1341,11 +1341,11 @@ void *stbds_hmput_key(void *a, size_t elemsize, void *key, size_t keysize, int m
stbds_hash_index *table;
if (a == NULL) {
- a = stbds_arrgrowf(0, elemsize, 0, 1);
- memset(a, 0, elemsize);
- stbds_header(a)->length += 1;
- // adjust a to point AFTER the default element
- a = STBDS_ARR_TO_HASH(a,elemsize);
+ a = stbds_arrgrowf(0, elemsize, 0, 1);
+ memset(a, 0, elemsize);
+ stbds_header(a)->length += 1;
+ // adjust a to point AFTER the default element
+ a = STBDS_ARR_TO_HASH(a,elemsize);
}
// adjust a to point to the default element
@@ -1355,8 +1355,8 @@ void *stbds_hmput_key(void *a, size_t elemsize, void *key, size_t keysize, int m
table = (stbds_hash_index *) stbds_header(a)->hash_table;
if (table == NULL || table->used_count >= table->used_count_threshold) {
- stbds_hash_index *nt;
- size_t slot_count;
+ stbds_hash_index *nt;
+ size_t slot_count;
slot_count = (table == NULL) ? STBDS_BUCKET_LENGTH : table->slot_count*2;
nt = stbds_make_hash_index(slot_count, table);
@@ -1370,11 +1370,11 @@ void *stbds_hmput_key(void *a, size_t elemsize, void *key, size_t keysize, int m
// we iterate hash table explicitly because we want to track if we saw a tombstone
{
- size_t hash = mode >= STBDS_HM_STRING ? stbds_hash_string((char*)key,table->seed) : stbds_hash_bytes(key, keysize,table->seed);
- size_t step = STBDS_BUCKET_LENGTH;
- size_t pos;
- ptrdiff_t tombstone = -1;
- stbds_hash_bucket *bucket;
+ size_t hash = mode >= STBDS_HM_STRING ? stbds_hash_string((char*)key,table->seed) : stbds_hash_bytes(key, keysize,table->seed);
+ size_t step = STBDS_BUCKET_LENGTH;
+ size_t pos;
+ ptrdiff_t tombstone = -1;
+ stbds_hash_bucket *bucket;
// stored hash values are forbidden from being 0, so we can detect empty slots to early out quickly
if (hash < 2) hash += 2;
@@ -1427,11 +1427,11 @@ void *stbds_hmput_key(void *a, size_t elemsize, void *key, size_t keysize, int m
pos &= (table->slot_count-1);
}
found_empty_slot:
- if (tombstone >= 0) {
- pos = tombstone;
- --table->tombstone_count;
- }
- ++table->used_count;
+ if (tombstone >= 0) {
+ pos = tombstone;
+ --table->tombstone_count;
+ }
+ ++table->used_count;
{
ptrdiff_t i = (ptrdiff_t) stbds_arrlen(a);
@@ -1472,32 +1472,32 @@ void * stbds_shmode_func(size_t elemsize, int mode)
void * stbds_hmdel_key(void *a, size_t elemsize, void *key, size_t keysize, size_t keyoffset, int mode)
{
if (a == NULL) {
- return 0;
+ return 0;
} else {
- stbds_hash_index *table;
- void *raw_a = STBDS_HASH_TO_ARR(a,elemsize);
- table = (stbds_hash_index *) stbds_header(raw_a)->hash_table;
- stbds_temp(raw_a) = 0;
- if (table == 0) {
- return a;
- } else {
- ptrdiff_t slot;
- slot = stbds_hm_find_slot(a, elemsize, key, keysize, keyoffset, mode);
- if (slot < 0)
- return a;
- else {
- stbds_hash_bucket *b = &table->storage[slot >> STBDS_BUCKET_SHIFT];
- int i = slot & STBDS_BUCKET_MASK;
- ptrdiff_t old_index = b->index[i];
- ptrdiff_t final_index = (ptrdiff_t) stbds_arrlen(raw_a)-1-1; // minus one for the raw_a vs a, and minus one for 'last'
- STBDS_ASSERT(slot < (ptrdiff_t) table->slot_count);
- --table->used_count;
- ++table->tombstone_count;
- stbds_temp(raw_a) = 1;
- STBDS_ASSERT(table->used_count >= 0);
- //STBDS_ASSERT(table->tombstone_count < table->slot_count/4);
- b->hash[i] = STBDS_HASH_DELETED;
- b->index[i] = STBDS_INDEX_DELETED;
+ stbds_hash_index *table;
+ void *raw_a = STBDS_HASH_TO_ARR(a,elemsize);
+ table = (stbds_hash_index *) stbds_header(raw_a)->hash_table;
+ stbds_temp(raw_a) = 0;
+ if (table == 0) {
+ return a;
+ } else {
+ ptrdiff_t slot;
+ slot = stbds_hm_find_slot(a, elemsize, key, keysize, keyoffset, mode);
+ if (slot < 0)
+ return a;
+ else {
+ stbds_hash_bucket *b = &table->storage[slot >> STBDS_BUCKET_SHIFT];
+ int i = slot & STBDS_BUCKET_MASK;
+ ptrdiff_t old_index = b->index[i];
+ ptrdiff_t final_index = (ptrdiff_t) stbds_arrlen(raw_a)-1-1; // minus one for the raw_a vs a, and minus one for 'last'
+ STBDS_ASSERT(slot < (ptrdiff_t) table->slot_count);
+ --table->used_count;
+ ++table->tombstone_count;
+ stbds_temp(raw_a) = 1;
+ STBDS_ASSERT(table->used_count >= 0);
+ //STBDS_ASSERT(table->tombstone_count < table->slot_count/4);
+ b->hash[i] = STBDS_HASH_DELETED;
+ b->index[i] = STBDS_INDEX_DELETED;
if (mode == STBDS_HM_STRING && table->string.mode == STBDS_SH_STRDUP)
STBDS_FREE(NULL, *(char**) ((char *) a+elemsize*old_index));
@@ -1559,8 +1559,8 @@ char *stbds_stralloc(stbds_string_arena *a, char *str)
char *p;
size_t len = strlen(str)+1;
if (len > a->remaining) {
- // compute the next blocksize
- size_t blocksize = a->block;
+ // compute the next blocksize
+ size_t blocksize = a->block;
// size is 512, 512, 1024, 1024, 2048, 2048, 4096, 4096, etc., so that
// there are log(SIZE) allocations to free when we destroy the table
@@ -1607,9 +1607,9 @@ void stbds_strreset(stbds_string_arena *a)
stbds_string_block *x,*y;
x = a->storage;
while (x) {
- y = x->next;
- STBDS_FREE(NULL, x);
- x = y;
+ y = x->next;
+ STBDS_FREE(NULL, x);
+ x = y;
}
memset(a, 0, sizeof(*a));
}
@@ -1667,27 +1667,27 @@ void stbds_unit_tests(void)
STBDS_ASSERT(arrlen(arr)==0);
for (i=0; i < 20000; i += 50) {
- for (j=0; j < i; ++j)
- arrpush(arr,j);
- arrfree(arr);
+ for (j=0; j < i; ++j)
+ arrpush(arr,j);
+ arrfree(arr);
}
for (i=0; i < 4; ++i) {
- arrpush(arr,1); arrpush(arr,2); arrpush(arr,3); arrpush(arr,4);
- arrdel(arr,i);
- arrfree(arr);
- arrpush(arr,1); arrpush(arr,2); arrpush(arr,3); arrpush(arr,4);
- arrdelswap(arr,i);
- arrfree(arr);
+ arrpush(arr,1); arrpush(arr,2); arrpush(arr,3); arrpush(arr,4);
+ arrdel(arr,i);
+ arrfree(arr);
+ arrpush(arr,1); arrpush(arr,2); arrpush(arr,3); arrpush(arr,4);
+ arrdelswap(arr,i);
+ arrfree(arr);
}
for (i=0; i < 5; ++i) {
- arrpush(arr,1); arrpush(arr,2); arrpush(arr,3); arrpush(arr,4);
- stbds_arrins(arr,i,5);
- STBDS_ASSERT(arr[i] == 5);
- if (i < 4)
- STBDS_ASSERT(arr[4] == 4);
- arrfree(arr);
+ arrpush(arr,1); arrpush(arr,2); arrpush(arr,3); arrpush(arr,4);
+ stbds_arrins(arr,i,5);
+ STBDS_ASSERT(arr[i] == 5);
+ if (i < 4)
+ STBDS_ASSERT(arr[4] == 4);
+ arrfree(arr);
}
i = 1;
@@ -1696,30 +1696,30 @@ void stbds_unit_tests(void)
STBDS_ASSERT(hmgeti(intmap, i) == -1);
STBDS_ASSERT(hmget (intmap, i) == -2);
for (i=0; i < testsize; i+=2)
- hmput(intmap, i, i*5);
+ hmput(intmap, i, i*5);
for (i=0; i < testsize; i+=1) {
- if (i & 1) STBDS_ASSERT(hmget(intmap, i) == -2 );
- else STBDS_ASSERT(hmget(intmap, i) == i*5);
- if (i & 1) STBDS_ASSERT(hmget_ts(intmap, i, temp) == -2 );
- else STBDS_ASSERT(hmget_ts(intmap, i, temp) == i*5);
+ if (i & 1) STBDS_ASSERT(hmget(intmap, i) == -2 );
+ else STBDS_ASSERT(hmget(intmap, i) == i*5);
+ if (i & 1) STBDS_ASSERT(hmget_ts(intmap, i, temp) == -2 );
+ else STBDS_ASSERT(hmget_ts(intmap, i, temp) == i*5);
}
for (i=0; i < testsize; i+=2)
- hmput(intmap, i, i*3);
+ hmput(intmap, i, i*3);
for (i=0; i < testsize; i+=1)
- if (i & 1) STBDS_ASSERT(hmget(intmap, i) == -2 );
- else STBDS_ASSERT(hmget(intmap, i) == i*3);
+ if (i & 1) STBDS_ASSERT(hmget(intmap, i) == -2 );
+ else STBDS_ASSERT(hmget(intmap, i) == i*3);
for (i=2; i < testsize; i+=4)
- hmdel(intmap, i); // delete half the entries
+ hmdel(intmap, i); // delete half the entries
for (i=0; i < testsize; i+=1)
- if (i & 3) STBDS_ASSERT(hmget(intmap, i) == -2 );
- else STBDS_ASSERT(hmget(intmap, i) == i*3);
+ if (i & 3) STBDS_ASSERT(hmget(intmap, i) == -2 );
+ else STBDS_ASSERT(hmget(intmap, i) == i*3);
for (i=0; i < testsize; i+=1)
- hmdel(intmap, i); // delete the rest of the entries
+ hmdel(intmap, i); // delete the rest of the entries
for (i=0; i < testsize; i+=1)
- STBDS_ASSERT(hmget(intmap, i) == -2 );
+ STBDS_ASSERT(hmget(intmap, i) == -2 );
hmfree(intmap);
for (i=0; i < testsize; i+=2)
- hmput(intmap, i, i*3);
+ hmput(intmap, i, i*3);
hmfree(intmap);
#if defined(__clang__) || defined(__GNUC__)
@@ -1735,117 +1735,117 @@ void stbds_unit_tests(void)
#endif
for (i=0; i < testsize; ++i)
- stralloc(&sa, strkey(i));
+ stralloc(&sa, strkey(i));
strreset(&sa);
{
- s.key = "a", s.value = 1;
- shputs(strmap, s);
- STBDS_ASSERT(*strmap[0].key == 'a');
- STBDS_ASSERT(strmap[0].key == s.key);
- STBDS_ASSERT(strmap[0].value == s.value);
- shfree(strmap);
+ s.key = "a", s.value = 1;
+ shputs(strmap, s);
+ STBDS_ASSERT(*strmap[0].key == 'a');
+ STBDS_ASSERT(strmap[0].key == s.key);
+ STBDS_ASSERT(strmap[0].value == s.value);
+ shfree(strmap);
}
{
- s.key = "a", s.value = 1;
- sh_new_strdup(strmap);
- shputs(strmap, s);
- STBDS_ASSERT(*strmap[0].key == 'a');
- STBDS_ASSERT(strmap[0].key != s.key);
- STBDS_ASSERT(strmap[0].value == s.value);
- shfree(strmap);
+ s.key = "a", s.value = 1;
+ sh_new_strdup(strmap);
+ shputs(strmap, s);
+ STBDS_ASSERT(*strmap[0].key == 'a');
+ STBDS_ASSERT(strmap[0].key != s.key);
+ STBDS_ASSERT(strmap[0].value == s.value);
+ shfree(strmap);
}
{
- s.key = "a", s.value = 1;
- sh_new_arena(strmap);
- shputs(strmap, s);
- STBDS_ASSERT(*strmap[0].key == 'a');
- STBDS_ASSERT(strmap[0].key != s.key);
- STBDS_ASSERT(strmap[0].value == s.value);
- shfree(strmap);
+ s.key = "a", s.value = 1;
+ sh_new_arena(strmap);
+ shputs(strmap, s);
+ STBDS_ASSERT(*strmap[0].key == 'a');
+ STBDS_ASSERT(strmap[0].key != s.key);
+ STBDS_ASSERT(strmap[0].value == s.value);
+ shfree(strmap);
}
for (j=0; j < 2; ++j) {
- STBDS_ASSERT(shgeti(strmap,"foo") == -1);
- if (j == 0)
- sh_new_strdup(strmap);
- else
- sh_new_arena(strmap);
- STBDS_ASSERT(shgeti(strmap,"foo") == -1);
- shdefault(strmap, -2);
- STBDS_ASSERT(shgeti(strmap,"foo") == -1);
- for (i=0; i < testsize; i+=2)
- shput(strmap, strkey(i), i*3);
- for (i=0; i < testsize; i+=1)
- if (i & 1) STBDS_ASSERT(shget(strmap, strkey(i)) == -2 );
- else STBDS_ASSERT(shget(strmap, strkey(i)) == i*3);
- for (i=2; i < testsize; i+=4)
- shdel(strmap, strkey(i)); // delete half the entries
- for (i=0; i < testsize; i+=1)
- if (i & 3) STBDS_ASSERT(shget(strmap, strkey(i)) == -2 );
- else STBDS_ASSERT(shget(strmap, strkey(i)) == i*3);
- for (i=0; i < testsize; i+=1)
- shdel(strmap, strkey(i)); // delete the rest of the entries
- for (i=0; i < testsize; i+=1)
- STBDS_ASSERT(shget(strmap, strkey(i)) == -2 );
- shfree(strmap);
+ STBDS_ASSERT(shgeti(strmap,"foo") == -1);
+ if (j == 0)
+ sh_new_strdup(strmap);
+ else
+ sh_new_arena(strmap);
+ STBDS_ASSERT(shgeti(strmap,"foo") == -1);
+ shdefault(strmap, -2);
+ STBDS_ASSERT(shgeti(strmap,"foo") == -1);
+ for (i=0; i < testsize; i+=2)
+ shput(strmap, strkey(i), i*3);
+ for (i=0; i < testsize; i+=1)
+ if (i & 1) STBDS_ASSERT(shget(strmap, strkey(i)) == -2 );
+ else STBDS_ASSERT(shget(strmap, strkey(i)) == i*3);
+ for (i=2; i < testsize; i+=4)
+ shdel(strmap, strkey(i)); // delete half the entries
+ for (i=0; i < testsize; i+=1)
+ if (i & 3) STBDS_ASSERT(shget(strmap, strkey(i)) == -2 );
+ else STBDS_ASSERT(shget(strmap, strkey(i)) == i*3);
+ for (i=0; i < testsize; i+=1)
+ shdel(strmap, strkey(i)); // delete the rest of the entries
+ for (i=0; i < testsize; i+=1)
+ STBDS_ASSERT(shget(strmap, strkey(i)) == -2 );
+ shfree(strmap);
}
{
- struct { char *key; char value; } *hash = NULL;
- char name[4] = "jen";
- shput(hash, "bob" , 'h');
- shput(hash, "sally" , 'e');
- shput(hash, "fred" , 'l');
- shput(hash, "jen" , 'x');
- shput(hash, "doug" , 'o');
+ struct { char *key; char value; } *hash = NULL;
+ char name[4] = "jen";
+ shput(hash, "bob" , 'h');
+ shput(hash, "sally" , 'e');
+ shput(hash, "fred" , 'l');
+ shput(hash, "jen" , 'x');
+ shput(hash, "doug" , 'o');
shput(hash, name , 'l');
shfree(hash);
}
for (i=0; i < testsize; i += 2) {
- stbds_struct s = { i,i*2,i*3,i*4 };
- hmput(map, s, i*5);
+ stbds_struct s = { i,i*2,i*3,i*4 };
+ hmput(map, s, i*5);
}
for (i=0; i < testsize; i += 1) {
- stbds_struct s = { i,i*2,i*3 ,i*4 };
- stbds_struct t = { i,i*2,i*3+1,i*4 };
- if (i & 1) STBDS_ASSERT(hmget(map, s) == 0);
- else STBDS_ASSERT(hmget(map, s) == i*5);
- if (i & 1) STBDS_ASSERT(hmget_ts(map, s, temp) == 0);
- else STBDS_ASSERT(hmget_ts(map, s, temp) == i*5);
- //STBDS_ASSERT(hmget(map, t.key) == 0);
+ stbds_struct s = { i,i*2,i*3 ,i*4 };
+ stbds_struct t = { i,i*2,i*3+1,i*4 };
+ if (i & 1) STBDS_ASSERT(hmget(map, s) == 0);
+ else STBDS_ASSERT(hmget(map, s) == i*5);
+ if (i & 1) STBDS_ASSERT(hmget_ts(map, s, temp) == 0);
+ else STBDS_ASSERT(hmget_ts(map, s, temp) == i*5);
+ //STBDS_ASSERT(hmget(map, t.key) == 0);
}
for (i=0; i < testsize; i += 2) {
- stbds_struct s = { i,i*2,i*3,i*4 };
- hmputs(map2, s);
+ stbds_struct s = { i,i*2,i*3,i*4 };
+ hmputs(map2, s);
}
hmfree(map);
for (i=0; i < testsize; i += 1) {
- stbds_struct s = { i,i*2,i*3,i*4 };
- stbds_struct t = { i,i*2,i*3+1,i*4 };
- if (i & 1) STBDS_ASSERT(hmgets(map2, s.key).d == 0);
- else STBDS_ASSERT(hmgets(map2, s.key).d == i*4);
- //STBDS_ASSERT(hmgetp(map2, t.key) == 0);
+ stbds_struct s = { i,i*2,i*3,i*4 };
+ stbds_struct t = { i,i*2,i*3+1,i*4 };
+ if (i & 1) STBDS_ASSERT(hmgets(map2, s.key).d == 0);
+ else STBDS_ASSERT(hmgets(map2, s.key).d == i*4);
+ //STBDS_ASSERT(hmgetp(map2, t.key) == 0);
}
hmfree(map2);
for (i=0; i < testsize; i += 2) {
- stbds_struct2 s = { { i,i*2 }, i*3,i*4, i*5 };
- hmputs(map3, s);
+ stbds_struct2 s = { { i,i*2 }, i*3,i*4, i*5 };
+ hmputs(map3, s);
}
for (i=0; i < testsize; i += 1) {
- stbds_struct2 s = { { i,i*2}, i*3, i*4, i*5 };
- stbds_struct2 t = { { i,i*2}, i*3+1, i*4, i*5 };
- if (i & 1) STBDS_ASSERT(hmgets(map3, s.key).d == 0);
- else STBDS_ASSERT(hmgets(map3, s.key).d == i*5);
- //STBDS_ASSERT(hmgetp(map3, t.key) == 0);
+ stbds_struct2 s = { { i,i*2}, i*3, i*4, i*5 };
+ stbds_struct2 t = { { i,i*2}, i*3+1, i*4, i*5 };
+ if (i & 1) STBDS_ASSERT(hmgets(map3, s.key).d == 0);
+ else STBDS_ASSERT(hmgets(map3, s.key).d == i*5);
+ //STBDS_ASSERT(hmgetp(map3, t.key) == 0);
}
#endif
}
diff --git a/test/src/main.c b/test/src/main.c
index 68d8e6b..353cc99 100644
--- a/test/src/main.c
+++ b/test/src/main.c
@@ -52,11 +52,11 @@ int main(int argc, char *argv[]) {
memoryStartup(argv[0]);
logOpenByHandle(memoryLogHandleGet());
- if (guiStartup(800, 600, 16) == SUCCESS) {
+ if (guiStartup(800, 600, 8) == SUCCESS) {
for (i=1; i<4; i++) {
sprintf(title, "Testing %d", i);
- w = windowCreate(i * 50, i * 50, 600, 400, title, WIN_STANDARD, 640, 480);
+ w = windowCreate(i * 50, i * 50, 500, 300, title, WIN_STANDARD, 640, 480);
l = labelCreate(LABEL_ALIGN_LEFT, __guiFontVGA8x16, "Label");
labelColorSet(l, __guiBaseColors[i], GUI_BLACK);
diff --git a/test/test.pro b/test/test.pro
deleted file mode 100644
index c7df217..0000000
--- a/test/test.pro
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# Roo/E, the Kangaroo Punch Portable GUI Toolkit
-# Copyright (C) 2022 Scott Duensing
-#
-# http://kangaroopunch.com
-#
-#
-# This file is part of Roo/E.
-#
-# Roo/E is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Affero General Public License as published by the Free
-# Software Foundation, either version 3 of the License, or (at your option)
-# any later version.
-#
-# Roo/E is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with Roo/E. If not, see .
-#
-
-
-TEMPLATE = app
-CONFIG -= \
- app_bundle \
- qt
-CONFIG += \
- console \
- c99
-
-DESTDIR = $$OUT_PWD/bin
-
-INCLUDEPATH += \
- $$PWD/../roo-e/src \
- $$PWD/../shared \
- $$PWD/src
-
-SOURCES += \
- src/main.c
-
-LIBS += \
- $$PWD/../build-master-debug/roo-e/bin/libroo-e.a \
- -lSDL2