]> PatchyGit - patchyircd.git/commitdiff
map: move base functions into the class
authorEgor <egor@patchysicp.xyz>
Sun, 2 Mar 2025 17:32:12 +0000 (19:32 +0200)
committerEgor <egor@patchysicp.xyz>
Sun, 2 Mar 2025 17:32:12 +0000 (19:32 +0200)
src/admin.cpp
src/irc.cpp
src/main.cpp
src/map.cpp
src/map.h
src/net.cpp

index 8257d6d..fcec636 100644 (file)
@@ -14,7 +14,7 @@ static int map_index(lua_State *L)
 {
        map_base *m = *(map_base **)luaL_checkudata(L, 1, "map");
        const char *key = luaL_checkstring(L, 2);
-       void *value = map_get(m, key);
+       void *value = m->_get(key);
        if (!value)
                return 0;
        lua_getiuservalue(L, 1, 1);
@@ -40,22 +40,22 @@ static int map_newindex(lua_State *L)
        const char *key = luaL_checkstring(L, 2);
        luaL_checkany(L, 3);
        if (lua_isnil(L, 3)) {
-               (void)map_set(m, key, 0, 0);
+               (void)m->_set(key, 0, 0);
                return 0;
        }
        lua_getiuservalue(L, 1, 1);
        switch (lua_tointeger(L, -1)) {
        case MAPTYPE_STRINGSET:
-               (void)map_set(m, key, key, 0);
+               (void)m->_set(key, key, 0);
                break;
        case MAPTYPE_CLIENT: {
                void **p = (void **)luaL_checkudata(L, 3, "client");
-               (void)map_set(m, key, *p, 0);
+               (void)m->_set(key, *p, 0);
                break;
        }
        case MAPTYPE_CHANNEL: {
                void **p = (void **)luaL_checkudata(L, 3, "channel");
-               (void)map_set(m, key, *p, 0);
+               (void)m->_set(key, *p, 0);
                break;
        }
        }
@@ -63,15 +63,10 @@ static int map_newindex(lua_State *L)
 }
 static int map_iter_next(lua_State *L)
 {
-       map_iter_t *it = (map_iter_t *)luaL_checkudata(L, 1, "map_iter");
-       lua_getiuservalue(L, 1, 2);
-       const char *key = (const char *)lua_touserdata(L, -1);
-       lua_pop(L, 1);
-       void *value;
-       if (!map_foriter(it, &key, &value))
+       map_base::iter *it = (map_base::iter *)luaL_checkudata(L, 1, "map_iter");
+       auto [key, value] = it->next();
+       if (!value)
                return 0;
-       lua_pushlightuserdata(L, (void *)key);
-       lua_setiuservalue(L, 1, 2);
        lua_getiuservalue(L, 1, 1);
        switch (lua_tointeger(L, -1)) {
        case MAPTYPE_STRINGSET:
@@ -95,14 +90,12 @@ static int map_pairs(lua_State *L)
 {
        map_base *m = *(map_base **)luaL_checkudata(L, 1, "map");
        lua_pushcfunction(L, map_iter_next);
-       map_iter_t *it = (map_iter_t *)lua_newuserdatauv(L, sizeof(map_iter_t), 2);
+       map_base::iter *it = (map_base::iter *)lua_newuserdatauv(L, sizeof(map_base::iter), 1);
        memset(it, 0, sizeof(*it));
        it->root = m;
        luaL_setmetatable(L, "map_iter");
        lua_getiuservalue(L, 1, 1);
        lua_setiuservalue(L, -2, 1);
-       lua_pushlightuserdata(L, 0);
-       lua_setiuservalue(L, -2, 2);
        lua_pushnil(L);
        return 3;
 }
index 290c8e5..ccd4006 100644 (file)
@@ -1568,16 +1568,16 @@ void channel_kill(struct channel *chan)
        free(chan->name);
        free(chan->topic);
        free(chan->topic_who);
-       map_free(&chan->members);
-       map_free(&chan->o);
-       map_free(&chan->v);
-       map_free(&chan->listb);
-       map_free(&chan->liste);
-       map_free(&chan->listI);
-       map_free(&chan->listq);
-       map_free(&chan->listwo);
-       map_free(&chan->listwv);
-       map_free(&chan->invitees);
+       chan->members.clear();
+       chan->o.clear();
+       chan->v.clear();
+       chan->listb.clear();
+       chan->liste.clear();
+       chan->listI.clear();
+       chan->listq.clear();
+       chan->listwo.clear();
+       chan->listwv.clear();
+       chan->invitees.clear();
        free(chan->chankey);
        free(chan);
 }
index 2eb65c4..e5cb301 100644 (file)
@@ -384,9 +384,9 @@ int main(int argc, char *argv[])
        /* free any persistent channels */
        for (auto chan : channel_map.pop_view())
                channel_kill(chan);
-       map_free(&client_map);
-       map_free(&channel_map);
-       map_free(&autojoin);
+       client_map.clear();
+       channel_map.clear();
+       autojoin.clear();
        if (fchanlog)
                fclose(fchanlog);
        return 0;
index b5e0f4a..20ba22e 100644 (file)
@@ -21,68 +21,57 @@ static int ent_find(map_base *root, const char *key, int *found)
        *found = 0;
        return lo;
 }
-void *map_get(map_base *root, const char *key)
+void *map_base::_get(const char *key)
 {
        int found;
-       int i = ent_find(root, key, &found);
-       return found ? root->ptr[i].value : 0;
+       int i = ent_find(this, key, &found);
+       return found ? ptr[i].value : 0;
 }
-int map_set(map_base *root, const char *key, const void *value, void **oldvalue)
+int map_base::_set(const char *key, const void *value, void **oldvalue)
 {
        int found;
-       int i = ent_find(root, key, &found);
+       int i = ent_find(this, key, &found);
        if (found) {
                if (oldvalue)
-                       *oldvalue = root->ptr[i].value;
+                       *oldvalue = ptr[i].value;
                if (!value) {
-                       free(root->ptr[i].key);
-                       memmove(root->ptr+i, root->ptr+i+1, sizeof(struct map_value)*(root->len-(i+1)));
-                       root->len--;
+                       free(ptr[i].key);
+                       memmove(ptr+i, ptr+i+1, sizeof(struct map_value)*(len-(i+1)));
+                       len--;
                } else {
-                       root->ptr[i].value = (void *)value;
+                       ptr[i].value = (void *)value;
                }
        } else {
                if (oldvalue)
                        *oldvalue = 0;
                if (value) {
-                       if (root->len == root->cap) {
-                               int ncap = root->cap ? root->cap*2 : 2;
-                               struct map_value *nptr = (struct map_value *)realloc(root->ptr, sizeof(struct map_value)*ncap);
+                       if (len == cap) {
+                               int ncap = cap ? cap*2 : 2;
+                               struct map_value *nptr = (struct map_value *)realloc(ptr, sizeof(struct map_value)*ncap);
                                if (!nptr)
                                        return -1;
-                               root->ptr = nptr;
-                               root->cap = ncap;
+                               ptr = nptr;
+                               cap = ncap;
                        }
                        int slen = strlen(key)+1;
                        char *nkey = (char *)malloc(slen);
                        if (!nkey)
                                return -1;
                        memcpy(nkey, key, slen);
-                       memmove(root->ptr+i+1, root->ptr+i, sizeof(struct map_value)*(root->len-i));
-                       root->len++;
-                       root->ptr[i].key = nkey;
-                       root->ptr[i].value = (void *)value;
+                       memmove(ptr+i+1, ptr+i, sizeof(struct map_value)*(len-i));
+                       len++;
+                       ptr[i].key = nkey;
+                       ptr[i].value = (void *)value;
                }
        }
        return 0;
 }
-void map_free(map_base *root)
+void map_base::clear()
 {
-       while (root->len) {
-               free(root->ptr[--root->len].key);
+       while (len) {
+               free(ptr[--len].key);
        }
-       free(root->ptr);
-       root->ptr = 0;
-       root->len = root->cap = 0;
-}
-int map_foriter(map_iter_t *it, const char **outkey, void *outvalue)
-{
-       if (it->index == it->root->len)
-               return 0;
-       if (outkey)
-               *outkey = it->root->ptr[it->index].key;
-       if (outvalue)
-               *(void **)outvalue = it->root->ptr[it->index].value;
-       it->index++;
-       return 1;
+       free(ptr);
+       ptr = 0;
+       len = cap = 0;
 }
index 475311e..07b272a 100644 (file)
--- a/src/map.h
+++ b/src/map.h
@@ -1,29 +1,8 @@
 #ifndef MAP_H_
 #define MAP_H_
-#include <stddef.h>
-#if defined(__has_c_attribute)
-#    if __has_c_attribute(nodiscard)
-#        define NODISCARD [[nodiscard]]
-#    else
-#        define NODISCARD
-#    endif
-#else
-#    define NODISCARD
-#endif
-
-/* all complexity is in terms of n = number of elements */
-struct map_value {
-       char *key;
-       void *value;
-};
-struct map_base {
-       struct map_value *ptr;
-       size_t len, cap;
-};
-typedef struct map_iter {
-       map_base *root;
-       size_t index;
-} map_iter_t;
+#include <stdlib.h>
+#include <utility>
+#include <iterator>
 
 /* A map abstract data type with following properties:
  * - keys are lexicographically-sorted unique NUL-terminated strings
@@ -35,37 +14,40 @@ typedef struct map_iter {
  * A map is created by allocating and zero-initializing an object of type
  * map_t. All map functions take a pointer to map_t.
  */
-
-/* Return the associated value for a given key.
- * Dynarr complexity: O(log n) */
-void *map_get(map_base *root, const char *key);
-/* Associate a new value with a given key.
- * Returns 0 on success, -1 on allocation error.
- * If oldvalue is not NULL, it receives the old value of key.
- * No allocation failures on value = NULL.
- * Dynarr complexity: O(n) */
-NODISCARD int map_set(map_base *root, const char *key, const void *value, void **oldvalue);
-/* Removes all keys from the map and frees any associated memory.
- * The map_t is reset to zero-initialized state and can be used again.
- * Dynarr complexity: O(n) */
-void map_free(map_base *root);
-
-/* Iterate over a map.
- *
- * Do not modify the map while iterating.
- * Don't modify *outkey or what it points to, and don't rely on it's lifetime
- * being longer than one iteration.
- * outvalue is actually a void**, but for implicit casting reasons it's void*.
- * Both outkey and outvalue can be specified as NULL.
- * Returns 0 on end of iteration, 1 otherwise.
- */
-NODISCARD int map_foriter(map_iter_t *f, const char **outkey, void *outvalue);
-
-#include <utility>
-#include <iterator>
-#include <stdlib.h>
-struct client_data;
-struct channel;
+struct map_value {
+       char *key;
+       void *value;
+};
+struct map_base {
+       struct map_value *ptr;
+       size_t len, cap;
+       /* Return the associated value for a given key.
+        * Dynarr complexity: O(log n) */
+       void *_get(const char *key);
+       /* Associate a new value with a given key.
+        * Returns 0 on success, -1 on allocation error.
+        * If oldvalue is not NULL, it receives the old value of key.
+        * No allocation failures on value = NULL.
+        * Dynarr complexity: O(n) */
+       [[nodiscard]] int _set(const char *key, const void *value, void **oldvalue);
+       /* Removes all keys from the map and frees any associated memory.
+        * The map_t is reset to zero-initialized state and can be used again.
+        * Dynarr complexity: O(n) */
+       void clear();
+       /* Iterate over a map.
+        * Do not modify the map while iterating.
+        */
+       struct iter {
+               map_base *root;
+               size_t index;
+               auto next() {
+                       map_value kv{0, 0};
+                       if (index < root->len)
+                               kv = root->ptr[index++];
+                       return std::make_pair(kv.key, kv.value);
+               }
+       };
+};
 
 template<typename T, typename V>
 struct map_base2 : map_base {
@@ -96,9 +78,6 @@ struct map_base2 : map_base {
        auto pop_view() {
                return reverse{*this};
        }
-       void clear() {
-               map_free(this);
-       }
        size_t size() {
                return len;
        }
@@ -111,31 +90,33 @@ protected:
        }
 public:
        bool has(V v) {
-               return !!map_get(this, T::to_key(v));
+               return !!_get(T::to_key(v));
        }
        bool add(V v) {
                void *old;
-               if (map_set(this, T::to_key(v), v, &old) == -1)
+               if (_set(T::to_key(v), v, &old) == -1)
                        abort();
                return !old;
        }
        bool remove(V v) {
                void *old;
-               (void)map_set(this, T::to_key(v), 0, &old);
+               (void)_set(T::to_key(v), 0, &old);
                return !!old;
        }
 
        V get(const char *k) {
-               return (V)map_get(this, k);
+               return (V)_get(k);
        }
 };
 
+struct client_data;
 struct clientmap : map_base2<clientmap, struct client_data *> {
        void rename(struct client_data *v, const char *newk) {
-               if (remove(v) && map_set(this, newk, v, 0) == -1)
+               if (remove(v) && _set(newk, v, 0) == -1)
                        abort();
        }
 };
+struct channel;
 struct channelmap : map_base2<channelmap, struct channel *> {
 };
 struct stringset : map_base2<stringset, const char *> {
index f0ab00b..135a91d 100644 (file)
@@ -78,9 +78,9 @@ void killConnection(struct client_data *cl, int byChoice)
                for (auto chan : cl->invites)
                        chan->invitees.remove(cl);
        }
-       map_free(&cl->channels);
-       map_free(&cl->invites);
-       map_free(&cl->monitor);
+       cl->channels.clear();
+       cl->invites.clear();
+       cl->monitor.clear();
        killConnectionPart2(cl);
 }
 void killConnectionPart2(struct client_data *cl)