| ... | @@ -9,23 +9,26 @@ const Wyhash = std.hash.Wyhash; | ... | @@ -9,23 +9,26 @@ const Wyhash = std.hash.Wyhash; |
| 9 | const Allocator = mem.Allocator; | 9 | const Allocator = mem.Allocator; |
| 10 | const hash_map = @This(); | 10 | const hash_map = @This(); |
| 11 | | 11 | |
| 12 | /// An ArrayHashMap with default hash and equal functions. | 12 | /// An `ArrayHashMap` with default hash and equal functions. |
| 13 | /// See AutoContext for a description of the hash and equal implementations. | 13 | /// |
| | 14 | /// See `AutoContext` for a description of the hash and equal implementations. |
| 14 | pub fn AutoArrayHashMap(comptime K: type, comptime V: type) type { | 15 | pub fn AutoArrayHashMap(comptime K: type, comptime V: type) type { |
| 15 | return ArrayHashMap(K, V, AutoContext(K), !autoEqlIsCheap(K)); | 16 | return ArrayHashMap(K, V, AutoContext(K), !autoEqlIsCheap(K)); |
| 16 | } | 17 | } |
| 17 | | 18 | |
| 18 | /// An ArrayHashMapUnmanaged with default hash and equal functions. | 19 | /// An `ArrayHashMapUnmanaged` with default hash and equal functions. |
| 19 | /// See AutoContext for a description of the hash and equal implementations. | 20 | /// |
| | 21 | /// See `AutoContext` for a description of the hash and equal implementations. |
| 20 | pub fn AutoArrayHashMapUnmanaged(comptime K: type, comptime V: type) type { | 22 | pub fn AutoArrayHashMapUnmanaged(comptime K: type, comptime V: type) type { |
| 21 | return ArrayHashMapUnmanaged(K, V, AutoContext(K), !autoEqlIsCheap(K)); | 23 | return ArrayHashMapUnmanaged(K, V, AutoContext(K), !autoEqlIsCheap(K)); |
| 22 | } | 24 | } |
| 23 | | 25 | |
| 24 | /// Builtin hashmap for strings as keys. | 26 | /// An `ArrayHashMap` with strings as keys. |
| 25 | pub fn StringArrayHashMap(comptime V: type) type { | 27 | pub fn StringArrayHashMap(comptime V: type) type { |
| 26 | return ArrayHashMap([]const u8, V, StringContext, true); | 28 | return ArrayHashMap([]const u8, V, StringContext, true); |
| 27 | } | 29 | } |
| 28 | | 30 | |
| | 31 | /// An `ArrayHashMapUnmanaged` with strings as keys. |
| 29 | pub fn StringArrayHashMapUnmanaged(comptime V: type) type { | 32 | pub fn StringArrayHashMapUnmanaged(comptime V: type) type { |
| 30 | return ArrayHashMapUnmanaged([]const u8, V, StringContext, true); | 33 | return ArrayHashMapUnmanaged([]const u8, V, StringContext, true); |
| 31 | } | 34 | } |
| ... | @@ -50,29 +53,33 @@ pub fn hashString(s: []const u8) u32 { | ... | @@ -50,29 +53,33 @@ pub fn hashString(s: []const u8) u32 { |
| 50 | return @as(u32, @truncate(std.hash.Wyhash.hash(0, s))); | 53 | return @as(u32, @truncate(std.hash.Wyhash.hash(0, s))); |
| 51 | } | 54 | } |
| 52 | | 55 | |
| 53 | /// Insertion order is preserved. | 56 | /// A hash table of keys and values, each stored sequentially. |
| 54 | /// Deletions perform a "swap removal" on the entries list. | 57 | /// |
| | 58 | /// Insertion order is preserved. In general, this data structure supports the same |
| | 59 | /// operations as `std.ArrayList`. |
| | 60 | /// |
| | 61 | /// Deletion operations: |
| | 62 | /// * `swapRemove` - O(1) |
| | 63 | /// * `orderedRemove` - O(N) |
| | 64 | /// |
| 55 | /// Modifying the hash map while iterating is allowed, however, one must understand | 65 | /// Modifying the hash map while iterating is allowed, however, one must understand |
| 56 | /// the (well defined) behavior when mixing insertions and deletions with iteration. | 66 | /// the (well defined) behavior when mixing insertions and deletions with iteration. |
| 57 | /// For a hash map that can be initialized directly that does not store an Allocator | 67 | /// |
| 58 | /// field, see `ArrayHashMapUnmanaged`. | 68 | /// See `ArrayHashMapUnmanaged` for a variant of this data structure that accepts an |
| 59 | /// When `store_hash` is `false`, this data structure is biased towards cheap `eql` | 69 | /// `Allocator` as a parameter when needed rather than storing it. |
| 60 | /// functions. It does not store each item's hash in the table. Setting `store_hash` | | |
| 61 | /// to `true` incurs slightly more memory cost by storing each key's hash in the table | | |
| 62 | /// but only has to call `eql` for hash collisions. | | |
| 63 | /// If typical operations (except iteration over entries) need to be faster, prefer | | |
| 64 | /// the alternative `std.HashMap`. | | |
| 65 | /// Context must be a struct type with two member functions: | | |
| 66 | /// hash(self, K) u32 | | |
| 67 | /// eql(self, K, K, usize) bool | | |
| 68 | /// Adapted variants of many functions are provided. These variants | | |
| 69 | /// take a pseudo key instead of a key. Their context must have the functions: | | |
| 70 | /// hash(self, PseudoKey) u32 | | |
| 71 | /// eql(self, PseudoKey, K, usize) bool | | |
| 72 | pub fn ArrayHashMap( | 70 | pub fn ArrayHashMap( |
| 73 | comptime K: type, | 71 | comptime K: type, |
| 74 | comptime V: type, | 72 | comptime V: type, |
| | 73 | /// A namespace that provides these two functions: |
| | 74 | /// * `pub fn hash(self, K) u32` |
| | 75 | /// * `pub fn eql(self, K, K) bool` |
| | 76 | /// |
| 75 | comptime Context: type, | 77 | comptime Context: type, |
| | 78 | /// When `false`, this data structure is biased towards cheap `eql` |
| | 79 | /// functions and avoids storing each key's hash in the table. Setting |
| | 80 | /// `store_hash` to `true` incurs more memory cost but limits `eql` to |
| | 81 | /// being called only once per insertion/deletion (provided there are no |
| | 82 | /// hash collisions). |
| 76 | comptime store_hash: bool, | 83 | comptime store_hash: bool, |
| 77 | ) type { | 84 | ) type { |
| 78 | return struct { | 85 | return struct { |
| ... | @@ -472,34 +479,40 @@ pub fn ArrayHashMap( | ... | @@ -472,34 +479,40 @@ pub fn ArrayHashMap( |
| 472 | }; | 479 | }; |
| 473 | } | 480 | } |
| 474 | | 481 | |
| 475 | /// General purpose hash table. | 482 | /// A hash table of keys and values, each stored sequentially. |
| 476 | /// Insertion order is preserved. | 483 | /// |
| 477 | /// Deletions perform a "swap removal" on the entries list. | 484 | /// Insertion order is preserved. In general, this data structure supports the same |
| | 485 | /// operations as `std.ArrayListUnmanaged`. |
| | 486 | /// |
| | 487 | /// Deletion operations: |
| | 488 | /// * `swapRemove` - O(1) |
| | 489 | /// * `orderedRemove` - O(N) |
| | 490 | /// |
| 478 | /// Modifying the hash map while iterating is allowed, however, one must understand | 491 | /// Modifying the hash map while iterating is allowed, however, one must understand |
| 479 | /// the (well defined) behavior when mixing insertions and deletions with iteration. | 492 | /// the (well defined) behavior when mixing insertions and deletions with iteration. |
| 480 | /// This type does not store an Allocator field - the Allocator must be passed in | 493 | /// |
| | 494 | /// This type does not store an `Allocator` field - the `Allocator` must be passed in |
| 481 | /// with each function call that requires it. See `ArrayHashMap` for a type that stores | 495 | /// with each function call that requires it. See `ArrayHashMap` for a type that stores |
| 482 | /// an Allocator field for convenience. | 496 | /// an `Allocator` field for convenience. |
| | 497 | /// |
| 483 | /// Can be initialized directly using the default field values. | 498 | /// Can be initialized directly using the default field values. |
| | 499 | /// |
| 484 | /// This type is designed to have low overhead for small numbers of entries. When | 500 | /// This type is designed to have low overhead for small numbers of entries. When |
| 485 | /// `store_hash` is `false` and the number of entries in the map is less than 9, | 501 | /// `store_hash` is `false` and the number of entries in the map is less than 9, |
| 486 | /// the overhead cost of using `ArrayHashMapUnmanaged` rather than `std.ArrayList` is | 502 | /// the overhead cost of using `ArrayHashMapUnmanaged` rather than `std.ArrayList` is |
| 487 | /// only a single pointer-sized integer. | 503 | /// only a single pointer-sized integer. |
| 488 | /// When `store_hash` is `false`, this data structure is biased towards cheap `eql` | | |
| 489 | /// functions. It does not store each item's hash in the table. Setting `store_hash` | | |
| 490 | /// to `true` incurs slightly more memory cost by storing each key's hash in the table | | |
| 491 | /// but guarantees only one call to `eql` per insertion/deletion. | | |
| 492 | /// Context must be a struct type with two member functions: | | |
| 493 | /// hash(self, K) u32 | | |
| 494 | /// eql(self, K, K) bool | | |
| 495 | /// Adapted variants of many functions are provided. These variants | | |
| 496 | /// take a pseudo key instead of a key. Their context must have the functions: | | |
| 497 | /// hash(self, PseudoKey) u32 | | |
| 498 | /// eql(self, PseudoKey, K) bool | | |
| 499 | pub fn ArrayHashMapUnmanaged( | 504 | pub fn ArrayHashMapUnmanaged( |
| 500 | comptime K: type, | 505 | comptime K: type, |
| 501 | comptime V: type, | 506 | comptime V: type, |
| | 507 | /// A namespace that provides these two functions: |
| | 508 | /// * `pub fn hash(self, K) u32` |
| | 509 | /// * `pub fn eql(self, K, K) bool` |
| 502 | comptime Context: type, | 510 | comptime Context: type, |
| | 511 | /// When `false`, this data structure is biased towards cheap `eql` |
| | 512 | /// functions and avoids storing each key's hash in the table. Setting |
| | 513 | /// `store_hash` to `true` incurs more memory cost but limits `eql` to |
| | 514 | /// being called only once per insertion/deletion (provided there are no |
| | 515 | /// hash collisions). |
| 503 | comptime store_hash: bool, | 516 | comptime store_hash: bool, |
| 504 | ) type { | 517 | ) type { |
| 505 | return struct { | 518 | return struct { |