]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/lib/map.qh
#pragma once
[xonotic/xonotic-data.pk3dir.git] / qcsrc / lib / map.qh
diff --git a/qcsrc/lib/map.qh b/qcsrc/lib/map.qh
new file mode 100644 (file)
index 0000000..0ff16e1
--- /dev/null
@@ -0,0 +1,112 @@
+#pragma once
+
+#include "int.qh"
+
+// Databases (hash tables)
+const int DB_BUCKETS = 8192;
+void db_save(int db, string filename)
+{
+       int fh = fopen(filename, FILE_WRITE);
+       if (fh < 0)
+       {
+               LOG_WARNINGF("^1Can't write DB to %s\n", filename);
+               return;
+       }
+       fputs(fh, strcat(ftos(DB_BUCKETS), "\n"));
+       for (int i = 0, n = buf_getsize(db); i < n; ++i)
+               fputs(fh, strcat(bufstr_get(db, i), "\n"));
+       fclose(fh);
+}
+
+typedef int HashMap;
+
+int db_create()
+{
+       return buf_create();
+}
+#define HM_NEW(this) (this = db_create())
+
+void db_put(int db, string key, string value);
+
+int db_load(string filename)
+{
+       int db = buf_create();
+       if (db < 0) return -1;
+       int fh = fopen(filename, FILE_READ);
+       if (fh < 0) return db;
+       string l = fgets(fh);
+       if (stoi(l) == DB_BUCKETS)
+       {
+               for (int i = 0; (l = fgets(fh)); ++i)
+               {
+                       if (l != "") bufstr_set(db, i, l);
+               }
+       }
+       else
+       {
+               // different count of buckets, or a dump?
+               // need to reorganize the database then (SLOW)
+               //
+               // note: we also parse the first line (l) in case the DB file is
+               // missing the bucket count
+               do
+               {
+                       int n = tokenizebyseparator(l, "\\");
+                       for (int j = 2; j < n; j += 2)
+                               db_put(db, argv(j - 1), uri_unescape(argv(j)));
+               }
+               while ((l = fgets(fh)));
+       }
+       fclose(fh);
+       return db;
+}
+
+void db_dump(int db, string filename)
+{
+       int fh = fopen(filename, FILE_WRITE);
+       if (fh < 0) LOG_FATALF("Can't dump DB to %s\n");
+       fputs(fh, "0\n");
+       for (int i = 0, n = buf_getsize(db); i < n; ++i)
+       {
+               int m = tokenizebyseparator(bufstr_get(db, i), "\\");
+               for (int j = 2; j < m; j += 2)
+                       fputs(fh, strcat("\\", argv(j - 1), "\\", argv(j), "\n"));
+       }
+       fclose(fh);
+}
+
+void db_close(int db)
+{
+       buf_del(db);
+}
+#define HM_DELETE(this) db_close(this)
+
+string db_get(int db, string key)
+{
+       int h = crc16(false, key) % DB_BUCKETS;
+       return uri_unescape(infoget(bufstr_get(db, h), key));
+}
+#define HM_gets(this, k) db_get(this, k)
+
+#define db_remove(db, key) db_put(db, key, "")
+
+void db_put(int db, string key, string value)
+{
+       int h = crc16(false, key) % DB_BUCKETS;
+       bufstr_set(db, h, infoadd(bufstr_get(db, h), key, uri_escape(value)));
+}
+#define HM_sets(this, key, val) db_put(this, key, val)
+
+void db_test()
+{
+       LOG_INFO("LOAD...\n");
+       int db = db_load("foo.db");
+       LOG_INFO("LOADED. FILL...\n");
+       for (int i = 0; i < DB_BUCKETS; ++i)
+               db_put(db, ftos(random()), "X");
+       LOG_INFO("FILLED. SAVE...\n");
+       db_save(db, "foo.db");
+       LOG_INFO("SAVED. CLOSE...\n");
+       db_close(db);
+       LOG_INFO("CLOSED.\n");
+}