]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/lib/map.qh
#pragma once
[xonotic/xonotic-data.pk3dir.git] / qcsrc / lib / map.qh
1 #pragma once
2
3 #include "int.qh"
4
5 // Databases (hash tables)
6 const int DB_BUCKETS = 8192;
7 void db_save(int db, string filename)
8 {
9         int fh = fopen(filename, FILE_WRITE);
10         if (fh < 0)
11         {
12                 LOG_WARNINGF("^1Can't write DB to %s\n", filename);
13                 return;
14         }
15         fputs(fh, strcat(ftos(DB_BUCKETS), "\n"));
16         for (int i = 0, n = buf_getsize(db); i < n; ++i)
17                 fputs(fh, strcat(bufstr_get(db, i), "\n"));
18         fclose(fh);
19 }
20
21 typedef int HashMap;
22
23 int db_create()
24 {
25         return buf_create();
26 }
27 #define HM_NEW(this) (this = db_create())
28
29 void db_put(int db, string key, string value);
30
31 int db_load(string filename)
32 {
33         int db = buf_create();
34         if (db < 0) return -1;
35         int fh = fopen(filename, FILE_READ);
36         if (fh < 0) return db;
37         string l = fgets(fh);
38         if (stoi(l) == DB_BUCKETS)
39         {
40                 for (int i = 0; (l = fgets(fh)); ++i)
41                 {
42                         if (l != "") bufstr_set(db, i, l);
43                 }
44         }
45         else
46         {
47                 // different count of buckets, or a dump?
48                 // need to reorganize the database then (SLOW)
49                 //
50                 // note: we also parse the first line (l) in case the DB file is
51                 // missing the bucket count
52                 do
53                 {
54                         int n = tokenizebyseparator(l, "\\");
55                         for (int j = 2; j < n; j += 2)
56                                 db_put(db, argv(j - 1), uri_unescape(argv(j)));
57                 }
58                 while ((l = fgets(fh)));
59         }
60         fclose(fh);
61         return db;
62 }
63
64 void db_dump(int db, string filename)
65 {
66         int fh = fopen(filename, FILE_WRITE);
67         if (fh < 0) LOG_FATALF("Can't dump DB to %s\n");
68         fputs(fh, "0\n");
69         for (int i = 0, n = buf_getsize(db); i < n; ++i)
70         {
71                 int m = tokenizebyseparator(bufstr_get(db, i), "\\");
72                 for (int j = 2; j < m; j += 2)
73                         fputs(fh, strcat("\\", argv(j - 1), "\\", argv(j), "\n"));
74         }
75         fclose(fh);
76 }
77
78 void db_close(int db)
79 {
80         buf_del(db);
81 }
82 #define HM_DELETE(this) db_close(this)
83
84 string db_get(int db, string key)
85 {
86         int h = crc16(false, key) % DB_BUCKETS;
87         return uri_unescape(infoget(bufstr_get(db, h), key));
88 }
89 #define HM_gets(this, k) db_get(this, k)
90
91 #define db_remove(db, key) db_put(db, key, "")
92
93 void db_put(int db, string key, string value)
94 {
95         int h = crc16(false, key) % DB_BUCKETS;
96         bufstr_set(db, h, infoadd(bufstr_get(db, h), key, uri_escape(value)));
97 }
98 #define HM_sets(this, key, val) db_put(this, key, val)
99
100 void db_test()
101 {
102         LOG_INFO("LOAD...\n");
103         int db = db_load("foo.db");
104         LOG_INFO("LOADED. FILL...\n");
105         for (int i = 0; i < DB_BUCKETS; ++i)
106                 db_put(db, ftos(random()), "X");
107         LOG_INFO("FILLED. SAVE...\n");
108         db_save(db, "foo.db");
109         LOG_INFO("SAVED. CLOSE...\n");
110         db_close(db);
111         LOG_INFO("CLOSED.\n");
112 }