hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

database.ha (1687B)


      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 i = 0z; i < len(item.exts); i += 1) {
     45 		const hash = fnv::string(item.exts[i]);
     46 		let bucket = &exttable[hash % len(exttable)];
     47 		append(bucket, item);
     48 	};
     49 };
     50 
     51 @fini fn fini() void = {
     52 	for (let i = 0z; i < len(heap_db); i += 1) {
     53 		free(heap_db[i].mime);
     54 		strings::freeall(heap_db[i].exts);
     55 		free(heap_db[i]);
     56 	};
     57 	free(heap_db);
     58 	free(static_db);
     59 };