Browse Source

Got dictionary into a useful state

I also fixed a memory leak and made it easier to run quick tests.
windows-imgui
Macoy Madson 7 months ago
parent
commit
c1a8153f5a
  1. 173
      src/Dictionary.cake
  2. 1
      src/DynamicArray.cake
  3. 39
      test/src/GameLibTests.cake

173
src/Dictionary.cake

@ -6,45 +6,144 @@
(import &comptime-only "STB.cake")
(use-stb-ds clone-stb-headers-dictionary)
;;
;; Hash table with string keys
;;
;; Automatically allocate each string key to a string arena
(def-c-function-alias strdict-use-key-arena sh_new_arena)
;; Automatically strdup and free string keys
(def-c-function-alias strdict-use-key-strdup sh_new_strdup)
(def-c-function-alias strdict-length shlen)
;; (dict (* <your Key Value type>) &return size_t)
(def-c-function-alias strdict-free shfree)
;; (dict (* <your Key Value type>))
;; These are used for the following functions:
;; - strdict-ptr-or-default-at
;; - strdict-struct-at
;; - strdict-value-at
(def-c-function-alias strdict-set-not-found-default shdefaults)
;; (dict (* <your Key Value type>) item <your Key Value type>
;; &return <your Key Value type>)
(def-c-function-alias strdict-set-not-found-default-value shdefault)
;; (dict (* <your Key Value type>) value <your Value type>
;; &return <your Value type>)
;; Setting
(def-c-function-alias strdict-set-key-value shput)
;; (dict (* <your Key Value type>) key (* char) value <your Value type>
;; &return <your Value type>)
;; Requires a key field
(def-c-function-alias strdict-set-struct shputs)
;; (dict (* <your Key Value type>) item <your Key Value type> &return <your Key Value type>)
;; Getting
(def-c-function-alias strdict-ptr-at shgetp_null)
;; (dict (* <your Key Value type>) key (* (const char)) &return (* <your Key Value type>))
(def-c-function-alias strdict-ptr-or-default-at shgetp)
;; (dict (* <your Key Value type>) key (* (const char)) &return (* <your Key Value type>))
(def-c-function-alias strdict-index-at shgeti)
;; (dict (* <your Key Value type>) key (* (const char)) &return ptrdiff_t)
(def-c-function-alias strdict-struct-at shgets)
;; (dict (* <your Key Value type>) key (* (const char)) &return <your Key Value type>)
(def-c-function-alias strdict-value-at shget)
;; (dict (* <your Key Value type>) &return <your value type>)
(comptime-cond
('auto-test
(c-import "stdio.h")
(defun test--dictionary (&return int)
(defstruct dictionary-entry
key (* char)
value (* (const char)))
(var my-dictionary (* dictionary-entry) null)
(sh_new_arena my-dictionary)
;; TODO Memory leak
;; (var my-entry dictionary-entry (array (strdup "cakelisp") "a programming language"))
;; (shputs my-dictionary my-entry)
(shput my-dictionary "cakelisp" "a programming language")
(shput my-dictionary "gamelib" "a helpful library")
(var keys ([] (* (const char))) (array "cakelisp" "gamelib"))
(each-in-array keys i
(var returned-entry-copy (* (const char)) (shget my-dictionary (at i keys)))
(unless returned-entry-copy
(fprintf stderr "Expected to get string back. Length: %ld\n" (shlen my-dictionary))
(return 1))
(fprintf stderr "what is %s? %s\n" (at i keys) returned-entry-copy)
(var entry-index ptrdiff_t (shgeti my-dictionary (at i keys)))
(unless (>= entry-index 0)
(fprintf stderr "Expected to get entry index back\n")
(return 1))
(fprintf stderr "Element is at %d (%p). Key = %s\n" (type-cast entry-index int)
(addr (at entry-index my-dictionary))
(field (at entry-index my-dictionary) key))
(var returned-entry (* dictionary-entry) (shgetp my-dictionary (at i keys)))
(unless (and returned-entry (path returned-entry > key) (path returned-entry > value))
(fprintf stderr "Expected to get valid entry back, got %p (array[-1] = %p). Length: %ld\n"
returned-entry (addr (at -1 my-dictionary)) (shlen my-dictionary))
(return 1))
(fprintf stderr "what is %s (%p)? %s\n"
(path returned-entry > key) (path returned-entry > key)
(path returned-entry > value)))
(shfree my-dictionary)
(scope ;; Simple key value entries
(defstruct dictionary-entry
key (* char)
value (* (const char)))
(var my-dictionary (* dictionary-entry) null)
(strdict-use-key-arena my-dictionary)
(strdict-set-key-value my-dictionary "cakelisp" "a programming language")
(strdict-set-key-value my-dictionary "gamelib" "a helpful library")
(var keys ([] (* (const char))) (array "cakelisp" "gamelib"))
(each-in-array keys i
(var returned-entry-copy (* (const char)) (strdict-value-at my-dictionary (at i keys)))
(unless returned-entry-copy
(fprintf stderr "Expected to get string back. Length: %ld\n"
(strdict-length my-dictionary))
(return 1))
(fprintf stderr "what is %s? %s\n" (at i keys) returned-entry-copy)
(var entry-index ptrdiff_t (strdict-index-at my-dictionary (at i keys)))
(unless (>= entry-index 0)
(fprintf stderr "Expected to get entry index back\n")
(return 1))
(fprintf stderr "Element is at %d (%p). Key = %s\n" (type-cast entry-index int)
(addr (at entry-index my-dictionary))
(field (at entry-index my-dictionary) key))
(var returned-entry (* dictionary-entry) (strdict-ptr-or-default-at my-dictionary (at i keys)))
(unless (and returned-entry (path returned-entry > key) (path returned-entry > value))
(fprintf stderr "Expected to get valid entry back, got %p (array[-1] = %p). Length: %ld\n"
returned-entry (addr (at -1 my-dictionary)) (strdict-length my-dictionary))
(return 1))
(fprintf stderr "what is %s (%p)? %s\n"
(path returned-entry > key) (path returned-entry > key)
(path returned-entry > value)))
(strdict-free my-dictionary))
(scope ;; Arbitrary fields dictionary
(defstruct complex-dictionary-entry
key (* char)
thing-category (* (const char))
thing-description (* (const char)))
(var my-dictionary (* complex-dictionary-entry) null)
(strdict-use-key-arena my-dictionary)
(var items ([] complex-dictionary-entry)
(array
(array (strdup "cakelisp") "programming language" "cakelisp is a programming language")
(array (strdup "gamelib") "library" "gamelib is a library for making games")))
(each-in-array items i
(strdict-set-struct my-dictionary (at i items)))
(unless (= (array-size items) (strdict-length my-dictionary))
(fprintf stderr "Expected size %d, got %d"
(type-cast (array-size items) int)
(type-cast (strdict-length my-dictionary) int))
(return 1))
(each-in-array items i
(var returned-entry (* complex-dictionary-entry)
(strdict-ptr-or-default-at my-dictionary (field (at i items) key)))
(unless (and returned-entry
(path returned-entry > key)
(path returned-entry > thing-category)
(path returned-entry > thing-description))
(fprintf stderr "Expected to get valid entry back, got %p (array[-1] = %p). Length: %ld\n"
returned-entry (addr (at -1 my-dictionary)) (strdict-length my-dictionary))
(return 1))
(fprintf stderr "What is %s? (%s) %s\n"
(path returned-entry > key)
(path returned-entry > thing-category)
(path returned-entry > thing-description)))
(scope
(var returned-entry (* complex-dictionary-entry)
(strdict-ptr-or-default-at my-dictionary "bad value"))
(fprintf stderr "Expected to get default (not found) entry back, got %p (array[-1] = %p).
Length: %ld\n"
returned-entry (addr (at -1 my-dictionary)) (strdict-length my-dictionary)))
(scope
(var returned-entry (* complex-dictionary-entry)
(strdict-ptr-at my-dictionary "bad value"))
(when returned-entry
(fprintf stderr "Expected to get null back, got %p (array[-1] = %p). Length: %ld\n"
returned-entry (addr (at -1 my-dictionary)) (strdict-length my-dictionary))))
(each-in-array items i
(free (type-cast (field (at i items) key) (* void))))
(strdict-free my-dictionary))
(return 0))))

1
src/DynamicArray.cake

@ -217,6 +217,7 @@
(var my-uninitialized-string dynstring null)
(dynstring-concat (addr my-uninitialized-string) "/")
(dynarray-free my-uninitialized-string)
(dynarray-free my-string)
(dynarray-free my-quick-string)
(return 0))))

39
test/src/GameLibTests.cake

@ -37,24 +37,35 @@
(true
"src/Config_Linux.cake")))
(gamelib-run-test
"Auto Test"
(array platform-config
"../src/AutoTest.cake" "../src/SDL.cake" "../src/Math.cake"
"../src/Aubio.cake" "../src/ImGui.cake" "../src/Dictionary.cake"
"../src/DynamicArray.cake"))
;; (var test-minimal bool true)
(var test-minimal bool false)
(gamelib-run-test "Ogre" (array platform-config "src/OgreApp.cake"))
(gamelib-run-test "SDL Ogre" (array platform-config "src/SDLOgreApp.cake"))
(if test-minimal
(gamelib-run-test
"Auto Test (data structures only)"
(array platform-config
"../src/AutoTest.cake" "../src/Dictionary.cake"
"../src/DynamicArray.cake"))
(gamelib-build "Vocal Game (hot reload)"
(array platform-config "src/MakeHotReload.cake" "src/VocalGame.cake"))
(scope ;; Test everything, which requires user input and takes a while
(gamelib-run-test
"Auto Test"
(array platform-config
"../src/AutoTest.cake" "../src/SDL.cake" "../src/Math.cake"
"../src/Aubio.cake" "../src/ImGui.cake" "../src/Dictionary.cake"
"../src/DynamicArray.cake"))
(gamelib-run-test "Hot-loader"
(array platform-config "src/Loader.cake"))
(gamelib-run-test "Ogre" (array platform-config "src/OgreApp.cake"))
(gamelib-run-test "SDL Ogre" (array platform-config "src/SDLOgreApp.cake"))
(gamelib-run-test "Vocal Game (no reload)"
(array platform-config "src/NoHotReload.cake" "src/VocalGame.cake"))
(gamelib-build "Vocal Game (hot reload)"
(array platform-config "src/MakeHotReload.cake" "src/VocalGame.cake"))
(gamelib-run-test "Hot-loader"
(array platform-config "src/Loader.cake"))
(gamelib-run-test "Vocal Game (no reload)"
(array platform-config "src/NoHotReload.cake" "src/VocalGame.cake"))))
(Log "\nGameLibTests: All tests succeeded!\n")
(return true))

Loading…
Cancel
Save