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