database.ha (1613B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 4 use hash::fnv; 5 use strings; 6 7 // A pair of a Media Type and a list of file extensions associated with it. The 8 // extension list does not include the leading '.' character. 9 export type mimetype = struct { 10 mime: str, 11 exts: []str, 12 }; 13 14 // List of media types with statically allocated fields (though the list itself 15 // is dynamically allocated). 16 let static_db: []*mimetype = []; 17 18 // List of media types with heap-allocated fields, used when loading mime types 19 // from the system database. 20 let heap_db: []*mimetype = []; 21 22 def MIME_BUCKETS: size = 256; 23 24 // Hash tables for efficient database lookup by mimetype or extension 25 let mimetable: [MIME_BUCKETS][]*mimetype = [[]...]; 26 let exttable: [MIME_BUCKETS][]*mimetype = [[]...]; 27 28 // Registers a Media Type and its extensions in the internal MIME database. This 29 // function is designed to be used by @init functions for modules which 30 // implement new Media Types. 31 export fn register(mime: *mimetype...) void = { 32 let i = len(static_db); 33 append(static_db, mime...); 34 for (i < len(static_db); i += 1) { 35 hashtable_insert(static_db[i]); 36 }; 37 }; 38 39 fn hashtable_insert(item: *mimetype) void = { 40 const hash = fnv::string(item.mime); 41 let bucket = &mimetable[hash % len(mimetable)]; 42 append(bucket, item); 43 44 for (let ext .. item.exts) { 45 const hash = fnv::string(ext); 46 let bucket = &exttable[hash % len(exttable)]; 47 append(bucket, item); 48 }; 49 }; 50 51 @fini fn fini() void = { 52 for (let m .. heap_db) { 53 free(m.mime); 54 strings::freeall(m.exts); 55 free(m); 56 }; 57 free(heap_db); 58 free(static_db); 59 };