@zigc/lib 0.16.0-dev.3144 → 0.16.0-dev.3153
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/compiler/reduce.zig +5 -1
- package/compiler/std-docs.zig +8 -1
- package/package.json +1 -1
- package/std/Build/Step/CheckObject.zig +3 -3
- package/std/Build/Step/ConfigHeader.zig +34 -32
- package/std/Build/Step/Run.zig +3 -3
- package/std/Build/Step/TranslateC.zig +0 -6
- package/std/Build/Step.zig +6 -13
- package/std/Build/WebServer.zig +8 -1
- package/std/Build.zig +14 -14
- package/std/Io/Threaded.zig +1 -1
- package/std/Io/Uring.zig +1 -1
- package/std/array_hash_map.zig +96 -555
- package/std/c.zig +17 -17
- package/std/json/Stringify.zig +3 -3
- package/std/json/dynamic.zig +4 -4
- package/std/os/emscripten.zig +1 -1
- package/std/os/linux.zig +2 -2
- package/std/process/Child.zig +1 -1
- package/std/std.zig +7 -6
- package/std/zig/AstGen.zig +3 -3
- package/std/zig/system.zig +18 -4
package/std/array_hash_map.zig
CHANGED
|
@@ -12,27 +12,15 @@ const hash_map = @This();
|
|
|
12
12
|
/// An `ArrayHashMap` with default hash and equal functions.
|
|
13
13
|
///
|
|
14
14
|
/// See `AutoContext` for a description of the hash and equal implementations.
|
|
15
|
-
pub fn
|
|
15
|
+
pub fn Auto(comptime K: type, comptime V: type) type {
|
|
16
16
|
return ArrayHashMap(K, V, AutoContext(K), !autoEqlIsCheap(K));
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
/// An `ArrayHashMapUnmanaged` with default hash and equal functions.
|
|
20
|
-
///
|
|
21
|
-
/// See `AutoContext` for a description of the hash and equal implementations.
|
|
22
|
-
pub fn AutoArrayHashMapUnmanaged(comptime K: type, comptime V: type) type {
|
|
23
|
-
return ArrayHashMapUnmanaged(K, V, AutoContext(K), !autoEqlIsCheap(K));
|
|
24
|
-
}
|
|
25
|
-
|
|
26
19
|
/// An `ArrayHashMap` with strings as keys.
|
|
27
|
-
pub fn
|
|
20
|
+
pub fn String(comptime V: type) type {
|
|
28
21
|
return ArrayHashMap([]const u8, V, StringContext, true);
|
|
29
22
|
}
|
|
30
23
|
|
|
31
|
-
/// An `ArrayHashMapUnmanaged` with strings as keys.
|
|
32
|
-
pub fn StringArrayHashMapUnmanaged(comptime V: type) type {
|
|
33
|
-
return ArrayHashMapUnmanaged([]const u8, V, StringContext, true);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
24
|
pub const StringContext = struct {
|
|
37
25
|
pub fn hash(self: @This(), s: []const u8) u32 {
|
|
38
26
|
_ = self;
|
|
@@ -53,454 +41,8 @@ pub fn hashString(s: []const u8) u32 {
|
|
|
53
41
|
return @truncate(std.hash.Wyhash.hash(0, s));
|
|
54
42
|
}
|
|
55
43
|
|
|
56
|
-
/// Deprecated
|
|
57
|
-
|
|
58
|
-
/// allocator). After Zig 0.14.0 is released, `ArrayHashMapWithAllocator` will
|
|
59
|
-
/// be removed and `ArrayHashMapUnmanaged` will be a deprecated alias. After
|
|
60
|
-
/// Zig 0.15.0 is released, the deprecated alias `ArrayHashMapUnmanaged` will
|
|
61
|
-
/// be removed.
|
|
62
|
-
pub const ArrayHashMap = ArrayHashMapWithAllocator;
|
|
63
|
-
|
|
64
|
-
/// A hash table of keys and values, each stored sequentially.
|
|
65
|
-
///
|
|
66
|
-
/// Insertion order is preserved. In general, this data structure supports the same
|
|
67
|
-
/// operations as `std.ArrayList`.
|
|
68
|
-
///
|
|
69
|
-
/// Deletion operations:
|
|
70
|
-
/// * `swapRemove` - O(1)
|
|
71
|
-
/// * `orderedRemove` - O(N)
|
|
72
|
-
///
|
|
73
|
-
/// Modifying the hash map while iterating is allowed, however, one must understand
|
|
74
|
-
/// the (well defined) behavior when mixing insertions and deletions with iteration.
|
|
75
|
-
///
|
|
76
|
-
/// See `ArrayHashMapUnmanaged` for a variant of this data structure that accepts an
|
|
77
|
-
/// `Allocator` as a parameter when needed rather than storing it.
|
|
78
|
-
pub fn ArrayHashMapWithAllocator(
|
|
79
|
-
comptime K: type,
|
|
80
|
-
comptime V: type,
|
|
81
|
-
/// A namespace that provides these two functions:
|
|
82
|
-
/// * `pub fn hash(self, K) u32`
|
|
83
|
-
/// * `pub fn eql(self, K, K, usize) bool`
|
|
84
|
-
///
|
|
85
|
-
/// The final `usize` in the `eql` function represents the index of the key
|
|
86
|
-
/// that's already inside the map.
|
|
87
|
-
comptime Context: type,
|
|
88
|
-
/// When `false`, this data structure is biased towards cheap `eql`
|
|
89
|
-
/// functions and avoids storing each key's hash in the table. Setting
|
|
90
|
-
/// `store_hash` to `true` incurs more memory cost but limits `eql` to
|
|
91
|
-
/// being called only once per insertion/deletion (provided there are no
|
|
92
|
-
/// hash collisions).
|
|
93
|
-
comptime store_hash: bool,
|
|
94
|
-
) type {
|
|
95
|
-
return struct {
|
|
96
|
-
unmanaged: Unmanaged,
|
|
97
|
-
allocator: Allocator,
|
|
98
|
-
ctx: Context,
|
|
99
|
-
|
|
100
|
-
/// The ArrayHashMapUnmanaged type using the same settings as this managed map.
|
|
101
|
-
pub const Unmanaged = ArrayHashMapUnmanaged(K, V, Context, store_hash);
|
|
102
|
-
|
|
103
|
-
/// Pointers to a key and value in the backing store of this map.
|
|
104
|
-
/// Modifying the key is allowed only if it does not change the hash.
|
|
105
|
-
/// Modifying the value is allowed.
|
|
106
|
-
/// Entry pointers become invalid whenever this ArrayHashMap is modified,
|
|
107
|
-
/// unless `ensureTotalCapacity`/`ensureUnusedCapacity` was previously used.
|
|
108
|
-
pub const Entry = Unmanaged.Entry;
|
|
109
|
-
|
|
110
|
-
/// A KV pair which has been copied out of the backing store
|
|
111
|
-
pub const KV = Unmanaged.KV;
|
|
112
|
-
|
|
113
|
-
/// The Data type used for the MultiArrayList backing this map
|
|
114
|
-
pub const Data = Unmanaged.Data;
|
|
115
|
-
/// The MultiArrayList type backing this map
|
|
116
|
-
pub const DataList = Unmanaged.DataList;
|
|
117
|
-
|
|
118
|
-
/// The stored hash type, either u32 or void.
|
|
119
|
-
pub const Hash = Unmanaged.Hash;
|
|
120
|
-
|
|
121
|
-
/// getOrPut variants return this structure, with pointers
|
|
122
|
-
/// to the backing store and a flag to indicate whether an
|
|
123
|
-
/// existing entry was found.
|
|
124
|
-
/// Modifying the key is allowed only if it does not change the hash.
|
|
125
|
-
/// Modifying the value is allowed.
|
|
126
|
-
/// Entry pointers become invalid whenever this ArrayHashMap is modified,
|
|
127
|
-
/// unless `ensureTotalCapacity`/`ensureUnusedCapacity` was previously used.
|
|
128
|
-
pub const GetOrPutResult = Unmanaged.GetOrPutResult;
|
|
129
|
-
|
|
130
|
-
/// An Iterator over Entry pointers.
|
|
131
|
-
pub const Iterator = Unmanaged.Iterator;
|
|
132
|
-
|
|
133
|
-
const Self = @This();
|
|
134
|
-
|
|
135
|
-
/// Create an ArrayHashMap instance which will use a specified allocator.
|
|
136
|
-
pub fn init(allocator: Allocator) Self {
|
|
137
|
-
if (@sizeOf(Context) != 0)
|
|
138
|
-
@compileError("Cannot infer context " ++ @typeName(Context) ++ ", call initContext instead.");
|
|
139
|
-
return initContext(allocator, undefined);
|
|
140
|
-
}
|
|
141
|
-
pub fn initContext(allocator: Allocator, ctx: Context) Self {
|
|
142
|
-
return .{
|
|
143
|
-
.unmanaged = .empty,
|
|
144
|
-
.allocator = allocator,
|
|
145
|
-
.ctx = ctx,
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/// Frees the backing allocation and leaves the map in an undefined state.
|
|
150
|
-
/// Note that this does not free keys or values. You must take care of that
|
|
151
|
-
/// before calling this function, if it is needed.
|
|
152
|
-
pub fn deinit(self: *Self) void {
|
|
153
|
-
self.unmanaged.deinit(self.allocator);
|
|
154
|
-
self.* = undefined;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/// Puts the hash map into a state where any method call that would
|
|
158
|
-
/// cause an existing key or value pointer to become invalidated will
|
|
159
|
-
/// instead trigger an assertion.
|
|
160
|
-
///
|
|
161
|
-
/// An additional call to `lockPointers` in such state also triggers an
|
|
162
|
-
/// assertion.
|
|
163
|
-
///
|
|
164
|
-
/// `unlockPointers` returns the hash map to the previous state.
|
|
165
|
-
pub fn lockPointers(self: *Self) void {
|
|
166
|
-
self.unmanaged.lockPointers();
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/// Undoes a call to `lockPointers`.
|
|
170
|
-
pub fn unlockPointers(self: *Self) void {
|
|
171
|
-
self.unmanaged.unlockPointers();
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/// Clears the map but retains the backing allocation for future use.
|
|
175
|
-
pub fn clearRetainingCapacity(self: *Self) void {
|
|
176
|
-
return self.unmanaged.clearRetainingCapacity();
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/// Clears the map and releases the backing allocation
|
|
180
|
-
pub fn clearAndFree(self: *Self) void {
|
|
181
|
-
return self.unmanaged.clearAndFree(self.allocator);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/// Returns the number of KV pairs stored in this map.
|
|
185
|
-
pub fn count(self: Self) usize {
|
|
186
|
-
return self.unmanaged.count();
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
/// Returns the backing array of keys in this map. Modifying the map may
|
|
190
|
-
/// invalidate this array. Modifying this array in a way that changes
|
|
191
|
-
/// key hashes or key equality puts the map into an unusable state until
|
|
192
|
-
/// `reIndex` is called.
|
|
193
|
-
pub fn keys(self: Self) []K {
|
|
194
|
-
return self.unmanaged.keys();
|
|
195
|
-
}
|
|
196
|
-
/// Returns the backing array of values in this map. Modifying the map
|
|
197
|
-
/// may invalidate this array. It is permitted to modify the values in
|
|
198
|
-
/// this array.
|
|
199
|
-
pub fn values(self: Self) []V {
|
|
200
|
-
return self.unmanaged.values();
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/// Returns an iterator over the pairs in this map.
|
|
204
|
-
/// Modifying the map may invalidate this iterator.
|
|
205
|
-
pub fn iterator(self: *const Self) Iterator {
|
|
206
|
-
return self.unmanaged.iterator();
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/// If key exists this function cannot fail.
|
|
210
|
-
/// If there is an existing item with `key`, then the result
|
|
211
|
-
/// `Entry` pointer points to it, and found_existing is true.
|
|
212
|
-
/// Otherwise, puts a new item with undefined value, and
|
|
213
|
-
/// the `Entry` pointer points to it. Caller should then initialize
|
|
214
|
-
/// the value (but not the key).
|
|
215
|
-
pub fn getOrPut(self: *Self, key: K) !GetOrPutResult {
|
|
216
|
-
return self.unmanaged.getOrPutContext(self.allocator, key, self.ctx);
|
|
217
|
-
}
|
|
218
|
-
pub fn getOrPutAdapted(self: *Self, key: anytype, ctx: anytype) !GetOrPutResult {
|
|
219
|
-
return self.unmanaged.getOrPutContextAdapted(self.allocator, key, ctx, self.ctx);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/// If there is an existing item with `key`, then the result
|
|
223
|
-
/// `Entry` pointer points to it, and found_existing is true.
|
|
224
|
-
/// Otherwise, puts a new item with undefined value, and
|
|
225
|
-
/// the `Entry` pointer points to it. Caller should then initialize
|
|
226
|
-
/// the value (but not the key).
|
|
227
|
-
/// If a new entry needs to be stored, this function asserts there
|
|
228
|
-
/// is enough capacity to store it.
|
|
229
|
-
pub fn getOrPutAssumeCapacity(self: *Self, key: K) GetOrPutResult {
|
|
230
|
-
return self.unmanaged.getOrPutAssumeCapacityContext(key, self.ctx);
|
|
231
|
-
}
|
|
232
|
-
pub fn getOrPutAssumeCapacityAdapted(self: *Self, key: anytype, ctx: anytype) GetOrPutResult {
|
|
233
|
-
return self.unmanaged.getOrPutAssumeCapacityAdapted(key, ctx);
|
|
234
|
-
}
|
|
235
|
-
pub fn getOrPutValue(self: *Self, key: K, value: V) !GetOrPutResult {
|
|
236
|
-
return self.unmanaged.getOrPutValueContext(self.allocator, key, value, self.ctx);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
/// Increases capacity, guaranteeing that insertions up until the
|
|
240
|
-
/// `expected_count` will not cause an allocation, and therefore cannot fail.
|
|
241
|
-
pub fn ensureTotalCapacity(self: *Self, new_capacity: usize) !void {
|
|
242
|
-
return self.unmanaged.ensureTotalCapacityContext(self.allocator, new_capacity, self.ctx);
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/// Increases capacity, guaranteeing that insertions up until
|
|
246
|
-
/// `additional_count` **more** items will not cause an allocation, and
|
|
247
|
-
/// therefore cannot fail.
|
|
248
|
-
pub fn ensureUnusedCapacity(self: *Self, additional_count: usize) !void {
|
|
249
|
-
return self.unmanaged.ensureUnusedCapacityContext(self.allocator, additional_count, self.ctx);
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
/// Returns the number of total elements which may be present before it is
|
|
253
|
-
/// no longer guaranteed that no allocations will be performed.
|
|
254
|
-
pub fn capacity(self: Self) usize {
|
|
255
|
-
return self.unmanaged.capacity();
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
/// Clobbers any existing data. To detect if a put would clobber
|
|
259
|
-
/// existing data, see `getOrPut`.
|
|
260
|
-
pub fn put(self: *Self, key: K, value: V) !void {
|
|
261
|
-
return self.unmanaged.putContext(self.allocator, key, value, self.ctx);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
/// Inserts a key-value pair into the hash map, asserting that no previous
|
|
265
|
-
/// entry with the same key is already present
|
|
266
|
-
pub fn putNoClobber(self: *Self, key: K, value: V) !void {
|
|
267
|
-
return self.unmanaged.putNoClobberContext(self.allocator, key, value, self.ctx);
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
/// Asserts there is enough capacity to store the new key-value pair.
|
|
271
|
-
/// Clobbers any existing data. To detect if a put would clobber
|
|
272
|
-
/// existing data, see `getOrPutAssumeCapacity`.
|
|
273
|
-
pub fn putAssumeCapacity(self: *Self, key: K, value: V) void {
|
|
274
|
-
return self.unmanaged.putAssumeCapacityContext(key, value, self.ctx);
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
/// Asserts there is enough capacity to store the new key-value pair.
|
|
278
|
-
/// Asserts that it does not clobber any existing data.
|
|
279
|
-
/// To detect if a put would clobber existing data, see `getOrPutAssumeCapacity`.
|
|
280
|
-
pub fn putAssumeCapacityNoClobber(self: *Self, key: K, value: V) void {
|
|
281
|
-
return self.unmanaged.putAssumeCapacityNoClobberContext(key, value, self.ctx);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
/// Inserts a new `Entry` into the hash map, returning the previous one, if any.
|
|
285
|
-
pub fn fetchPut(self: *Self, key: K, value: V) !?KV {
|
|
286
|
-
return self.unmanaged.fetchPutContext(self.allocator, key, value, self.ctx);
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
/// Inserts a new `Entry` into the hash map, returning the previous one, if any.
|
|
290
|
-
/// If insertion happuns, asserts there is enough capacity without allocating.
|
|
291
|
-
pub fn fetchPutAssumeCapacity(self: *Self, key: K, value: V) ?KV {
|
|
292
|
-
return self.unmanaged.fetchPutAssumeCapacityContext(key, value, self.ctx);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
/// Finds pointers to the key and value storage associated with a key.
|
|
296
|
-
pub fn getEntry(self: Self, key: K) ?Entry {
|
|
297
|
-
return self.unmanaged.getEntryContext(key, self.ctx);
|
|
298
|
-
}
|
|
299
|
-
pub fn getEntryAdapted(self: Self, key: anytype, ctx: anytype) ?Entry {
|
|
300
|
-
return self.unmanaged.getEntryAdapted(key, ctx);
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
/// Finds the index in the `entries` array where a key is stored
|
|
304
|
-
pub fn getIndex(self: Self, key: K) ?usize {
|
|
305
|
-
return self.unmanaged.getIndexContext(key, self.ctx);
|
|
306
|
-
}
|
|
307
|
-
pub fn getIndexAdapted(self: Self, key: anytype, ctx: anytype) ?usize {
|
|
308
|
-
return self.unmanaged.getIndexAdapted(key, ctx);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
/// Find the value associated with a key
|
|
312
|
-
pub fn get(self: Self, key: K) ?V {
|
|
313
|
-
return self.unmanaged.getContext(key, self.ctx);
|
|
314
|
-
}
|
|
315
|
-
pub fn getAdapted(self: Self, key: anytype, ctx: anytype) ?V {
|
|
316
|
-
return self.unmanaged.getAdapted(key, ctx);
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
/// Find a pointer to the value associated with a key
|
|
320
|
-
pub fn getPtr(self: Self, key: K) ?*V {
|
|
321
|
-
return self.unmanaged.getPtrContext(key, self.ctx);
|
|
322
|
-
}
|
|
323
|
-
pub fn getPtrAdapted(self: Self, key: anytype, ctx: anytype) ?*V {
|
|
324
|
-
return self.unmanaged.getPtrAdapted(key, ctx);
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
/// Find the actual key associated with an adapted key
|
|
328
|
-
pub fn getKey(self: Self, key: K) ?K {
|
|
329
|
-
return self.unmanaged.getKeyContext(key, self.ctx);
|
|
330
|
-
}
|
|
331
|
-
pub fn getKeyAdapted(self: Self, key: anytype, ctx: anytype) ?K {
|
|
332
|
-
return self.unmanaged.getKeyAdapted(key, ctx);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
/// Find a pointer to the actual key associated with an adapted key
|
|
336
|
-
pub fn getKeyPtr(self: Self, key: K) ?*K {
|
|
337
|
-
return self.unmanaged.getKeyPtrContext(key, self.ctx);
|
|
338
|
-
}
|
|
339
|
-
pub fn getKeyPtrAdapted(self: Self, key: anytype, ctx: anytype) ?*K {
|
|
340
|
-
return self.unmanaged.getKeyPtrAdapted(key, ctx);
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
/// Check whether a key is stored in the map
|
|
344
|
-
pub fn contains(self: Self, key: K) bool {
|
|
345
|
-
return self.unmanaged.containsContext(key, self.ctx);
|
|
346
|
-
}
|
|
347
|
-
pub fn containsAdapted(self: Self, key: anytype, ctx: anytype) bool {
|
|
348
|
-
return self.unmanaged.containsAdapted(key, ctx);
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
/// If there is an `Entry` with a matching key, it is deleted from
|
|
352
|
-
/// the hash map, and then returned from this function. The entry is
|
|
353
|
-
/// removed from the underlying array by swapping it with the last
|
|
354
|
-
/// element.
|
|
355
|
-
pub fn fetchSwapRemove(self: *Self, key: K) ?KV {
|
|
356
|
-
return self.unmanaged.fetchSwapRemoveContext(key, self.ctx);
|
|
357
|
-
}
|
|
358
|
-
pub fn fetchSwapRemoveAdapted(self: *Self, key: anytype, ctx: anytype) ?KV {
|
|
359
|
-
return self.unmanaged.fetchSwapRemoveContextAdapted(key, ctx, self.ctx);
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
/// If there is an `Entry` with a matching key, it is deleted from
|
|
363
|
-
/// the hash map, and then returned from this function. The entry is
|
|
364
|
-
/// removed from the underlying array by shifting all elements forward
|
|
365
|
-
/// thereby maintaining the current ordering.
|
|
366
|
-
pub fn fetchOrderedRemove(self: *Self, key: K) ?KV {
|
|
367
|
-
return self.unmanaged.fetchOrderedRemoveContext(key, self.ctx);
|
|
368
|
-
}
|
|
369
|
-
pub fn fetchOrderedRemoveAdapted(self: *Self, key: anytype, ctx: anytype) ?KV {
|
|
370
|
-
return self.unmanaged.fetchOrderedRemoveContextAdapted(key, ctx, self.ctx);
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
/// If there is an `Entry` with a matching key, it is deleted from
|
|
374
|
-
/// the hash map. The entry is removed from the underlying array
|
|
375
|
-
/// by swapping it with the last element. Returns true if an entry
|
|
376
|
-
/// was removed, false otherwise.
|
|
377
|
-
pub fn swapRemove(self: *Self, key: K) bool {
|
|
378
|
-
return self.unmanaged.swapRemoveContext(key, self.ctx);
|
|
379
|
-
}
|
|
380
|
-
pub fn swapRemoveAdapted(self: *Self, key: anytype, ctx: anytype) bool {
|
|
381
|
-
return self.unmanaged.swapRemoveContextAdapted(key, ctx, self.ctx);
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
/// If there is an `Entry` with a matching key, it is deleted from
|
|
385
|
-
/// the hash map. The entry is removed from the underlying array
|
|
386
|
-
/// by shifting all elements forward, thereby maintaining the
|
|
387
|
-
/// current ordering. Returns true if an entry was removed, false otherwise.
|
|
388
|
-
pub fn orderedRemove(self: *Self, key: K) bool {
|
|
389
|
-
return self.unmanaged.orderedRemoveContext(key, self.ctx);
|
|
390
|
-
}
|
|
391
|
-
pub fn orderedRemoveAdapted(self: *Self, key: anytype, ctx: anytype) bool {
|
|
392
|
-
return self.unmanaged.orderedRemoveContextAdapted(key, ctx, self.ctx);
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
/// Deletes the item at the specified index in `entries` from
|
|
396
|
-
/// the hash map. The entry is removed from the underlying array
|
|
397
|
-
/// by swapping it with the last element.
|
|
398
|
-
pub fn swapRemoveAt(self: *Self, index: usize) void {
|
|
399
|
-
self.unmanaged.swapRemoveAtContext(index, self.ctx);
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
/// Deletes the item at the specified index in `entries` from
|
|
403
|
-
/// the hash map. The entry is removed from the underlying array
|
|
404
|
-
/// by shifting all elements forward, thereby maintaining the
|
|
405
|
-
/// current ordering.
|
|
406
|
-
pub fn orderedRemoveAt(self: *Self, index: usize) void {
|
|
407
|
-
self.unmanaged.orderedRemoveAtContext(index, self.ctx);
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
/// Create a copy of the hash map which can be modified separately.
|
|
411
|
-
/// The copy uses the same context and allocator as this instance.
|
|
412
|
-
pub fn clone(self: Self) !Self {
|
|
413
|
-
var other = try self.unmanaged.cloneContext(self.allocator, self.ctx);
|
|
414
|
-
return other.promoteContext(self.allocator, self.ctx);
|
|
415
|
-
}
|
|
416
|
-
/// Create a copy of the hash map which can be modified separately.
|
|
417
|
-
/// The copy uses the same context as this instance, but the specified
|
|
418
|
-
/// allocator.
|
|
419
|
-
pub fn cloneWithAllocator(self: Self, allocator: Allocator) !Self {
|
|
420
|
-
var other = try self.unmanaged.cloneContext(allocator, self.ctx);
|
|
421
|
-
return other.promoteContext(allocator, self.ctx);
|
|
422
|
-
}
|
|
423
|
-
/// Create a copy of the hash map which can be modified separately.
|
|
424
|
-
/// The copy uses the same allocator as this instance, but the
|
|
425
|
-
/// specified context.
|
|
426
|
-
pub fn cloneWithContext(self: Self, ctx: anytype) !ArrayHashMap(K, V, @TypeOf(ctx), store_hash) {
|
|
427
|
-
var other = try self.unmanaged.cloneContext(self.allocator, ctx);
|
|
428
|
-
return other.promoteContext(self.allocator, ctx);
|
|
429
|
-
}
|
|
430
|
-
/// Create a copy of the hash map which can be modified separately.
|
|
431
|
-
/// The copy uses the specified allocator and context.
|
|
432
|
-
pub fn cloneWithAllocatorAndContext(self: Self, allocator: Allocator, ctx: anytype) !ArrayHashMap(K, V, @TypeOf(ctx), store_hash) {
|
|
433
|
-
var other = try self.unmanaged.cloneContext(allocator, ctx);
|
|
434
|
-
return other.promoteContext(allocator, ctx);
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
/// Set the map to an empty state, making deinitialization a no-op, and
|
|
438
|
-
/// returning a copy of the original.
|
|
439
|
-
pub fn move(self: *Self) Self {
|
|
440
|
-
self.unmanaged.pointer_stability.assertUnlocked();
|
|
441
|
-
const result = self.*;
|
|
442
|
-
self.unmanaged = .empty;
|
|
443
|
-
return result;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
/// Recomputes stored hashes and rebuilds the key indexes. If the
|
|
447
|
-
/// underlying keys have been modified directly, call this method to
|
|
448
|
-
/// recompute the denormalized metadata necessary for the operation of
|
|
449
|
-
/// the methods of this map that lookup entries by key.
|
|
450
|
-
///
|
|
451
|
-
/// One use case for this is directly calling `entries.resize()` to grow
|
|
452
|
-
/// the underlying storage, and then setting the `keys` and `values`
|
|
453
|
-
/// directly without going through the methods of this map.
|
|
454
|
-
///
|
|
455
|
-
/// The time complexity of this operation is O(n).
|
|
456
|
-
pub fn reIndex(self: *Self) !void {
|
|
457
|
-
return self.unmanaged.reIndexContext(self.allocator, self.ctx);
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
/// Sorts the entries and then rebuilds the index.
|
|
461
|
-
/// `sort_ctx` must have this method:
|
|
462
|
-
/// `fn lessThan(ctx: @TypeOf(ctx), a_index: usize, b_index: usize) bool`
|
|
463
|
-
/// Uses a stable sorting algorithm.
|
|
464
|
-
pub fn sort(self: *Self, sort_ctx: anytype) void {
|
|
465
|
-
return self.unmanaged.sortContext(sort_ctx, self.ctx);
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
/// Sorts the entries and then rebuilds the index.
|
|
469
|
-
/// `sort_ctx` must have this method:
|
|
470
|
-
/// `fn lessThan(ctx: @TypeOf(ctx), a_index: usize, b_index: usize) bool`
|
|
471
|
-
/// Uses an unstable sorting algorithm.
|
|
472
|
-
pub fn sortUnstable(self: *Self, sort_ctx: anytype) void {
|
|
473
|
-
return self.unmanaged.sortUnstableContext(sort_ctx, self.ctx);
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
/// Shrinks the underlying `Entry` array to `new_len` elements and
|
|
477
|
-
/// discards any associated index entries. Keeps capacity the same.
|
|
478
|
-
///
|
|
479
|
-
/// Asserts the discarded entries remain initialized and capable of
|
|
480
|
-
/// performing hash and equality checks. Any deinitialization of
|
|
481
|
-
/// discarded entries must take place *after* calling this function.
|
|
482
|
-
pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void {
|
|
483
|
-
return self.unmanaged.shrinkRetainingCapacityContext(new_len, self.ctx);
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
/// Shrinks the underlying `Entry` array to `new_len` elements and
|
|
487
|
-
/// discards any associated index entries. Reduces allocated capacity.
|
|
488
|
-
///
|
|
489
|
-
/// Asserts the discarded entries remain initialized and capable of
|
|
490
|
-
/// performing hash and equality checks. It is a bug to call this
|
|
491
|
-
/// function if the discarded entries require deinitialization. For
|
|
492
|
-
/// that use case, `shrinkRetainingCapacity` can be used instead.
|
|
493
|
-
pub fn shrinkAndFree(self: *Self, new_len: usize) void {
|
|
494
|
-
return self.unmanaged.shrinkAndFreeContext(self.allocator, new_len, self.ctx);
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
/// Removes the last inserted `Entry` in the hash map and returns it if count is nonzero.
|
|
498
|
-
/// Otherwise returns null.
|
|
499
|
-
pub fn pop(self: *Self) ?KV {
|
|
500
|
-
return self.unmanaged.popContext(self.ctx);
|
|
501
|
-
}
|
|
502
|
-
};
|
|
503
|
-
}
|
|
44
|
+
/// Deprecated; use `Custom`.
|
|
45
|
+
pub const ArrayHashMap = Custom;
|
|
504
46
|
|
|
505
47
|
/// A hash table of keys and values, each stored sequentially.
|
|
506
48
|
///
|
|
@@ -522,11 +64,11 @@ pub fn ArrayHashMapWithAllocator(
|
|
|
522
64
|
///
|
|
523
65
|
/// This type is designed to have low overhead for small numbers of entries. When
|
|
524
66
|
/// `store_hash` is `false` and the number of entries in the map is less than 9,
|
|
525
|
-
/// the overhead cost of using `
|
|
67
|
+
/// the overhead cost of using `ArrayHashMap` rather than `std.ArrayList` is
|
|
526
68
|
/// only a single pointer-sized integer.
|
|
527
69
|
///
|
|
528
70
|
/// Default initialization of this struct is deprecated; use `.empty` instead.
|
|
529
|
-
pub fn
|
|
71
|
+
pub fn Custom(
|
|
530
72
|
comptime K: type,
|
|
531
73
|
comptime V: type,
|
|
532
74
|
/// A namespace that provides these two functions:
|
|
@@ -605,9 +147,6 @@ pub fn ArrayHashMapUnmanaged(
|
|
|
605
147
|
index: usize,
|
|
606
148
|
};
|
|
607
149
|
|
|
608
|
-
/// The ArrayHashMap type using the same settings as this managed map.
|
|
609
|
-
pub const Managed = ArrayHashMap(K, V, Context, store_hash);
|
|
610
|
-
|
|
611
150
|
/// Some functions require a context only if hashes are not stored.
|
|
612
151
|
/// To keep the api simple, this type is only used internally.
|
|
613
152
|
const ByIndexContext = if (store_hash) void else Context;
|
|
@@ -626,21 +165,6 @@ pub fn ArrayHashMapUnmanaged(
|
|
|
626
165
|
|
|
627
166
|
const Oom = Allocator.Error;
|
|
628
167
|
|
|
629
|
-
/// Convert from an unmanaged map to a managed map. After calling this,
|
|
630
|
-
/// the promoted map should no longer be used.
|
|
631
|
-
pub fn promote(self: Self, gpa: Allocator) Managed {
|
|
632
|
-
if (@sizeOf(Context) != 0)
|
|
633
|
-
@compileError("Cannot infer context " ++ @typeName(Context) ++ ", call promoteContext instead.");
|
|
634
|
-
return self.promoteContext(gpa, undefined);
|
|
635
|
-
}
|
|
636
|
-
pub fn promoteContext(self: Self, gpa: Allocator, ctx: Context) Managed {
|
|
637
|
-
return .{
|
|
638
|
-
.unmanaged = self,
|
|
639
|
-
.allocator = gpa,
|
|
640
|
-
.ctx = ctx,
|
|
641
|
-
};
|
|
642
|
-
}
|
|
643
|
-
|
|
644
168
|
pub fn init(gpa: Allocator, key_list: []const K, value_list: []const V) Oom!Self {
|
|
645
169
|
var self: Self = .{};
|
|
646
170
|
errdefer self.deinit(gpa);
|
|
@@ -2189,35 +1713,37 @@ const IndexHeader = struct {
|
|
|
2189
1713
|
};
|
|
2190
1714
|
|
|
2191
1715
|
test "basic hash map usage" {
|
|
2192
|
-
|
|
2193
|
-
defer map.deinit();
|
|
1716
|
+
const gpa = testing.allocator;
|
|
2194
1717
|
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
try testing.expect((try map.fetchPut(
|
|
1718
|
+
var map: Auto(i32, i32) = .empty;
|
|
1719
|
+
defer map.deinit(gpa);
|
|
1720
|
+
|
|
1721
|
+
try testing.expect((try map.fetchPut(gpa, 1, 11)) == null);
|
|
1722
|
+
try testing.expect((try map.fetchPut(gpa, 2, 22)) == null);
|
|
1723
|
+
try testing.expect((try map.fetchPut(gpa, 3, 33)) == null);
|
|
1724
|
+
try testing.expect((try map.fetchPut(gpa, 4, 44)) == null);
|
|
2199
1725
|
|
|
2200
|
-
try map.putNoClobber(5, 55);
|
|
2201
|
-
try testing.expect((try map.fetchPut(5, 66)).?.value == 55);
|
|
2202
|
-
try testing.expect((try map.fetchPut(5, 55)).?.value == 66);
|
|
1726
|
+
try map.putNoClobber(gpa, 5, 55);
|
|
1727
|
+
try testing.expect((try map.fetchPut(gpa, 5, 66)).?.value == 55);
|
|
1728
|
+
try testing.expect((try map.fetchPut(gpa, 5, 55)).?.value == 66);
|
|
2203
1729
|
|
|
2204
|
-
const gop1 = try map.getOrPut(5);
|
|
1730
|
+
const gop1 = try map.getOrPut(gpa, 5);
|
|
2205
1731
|
try testing.expect(gop1.found_existing == true);
|
|
2206
1732
|
try testing.expect(gop1.value_ptr.* == 55);
|
|
2207
1733
|
try testing.expect(gop1.index == 4);
|
|
2208
1734
|
gop1.value_ptr.* = 77;
|
|
2209
1735
|
try testing.expect(map.getEntry(5).?.value_ptr.* == 77);
|
|
2210
1736
|
|
|
2211
|
-
const gop2 = try map.getOrPut(99);
|
|
1737
|
+
const gop2 = try map.getOrPut(gpa, 99);
|
|
2212
1738
|
try testing.expect(gop2.found_existing == false);
|
|
2213
1739
|
try testing.expect(gop2.index == 5);
|
|
2214
1740
|
gop2.value_ptr.* = 42;
|
|
2215
1741
|
try testing.expect(map.getEntry(99).?.value_ptr.* == 42);
|
|
2216
1742
|
|
|
2217
|
-
const gop3 = try map.getOrPutValue(5, 5);
|
|
1743
|
+
const gop3 = try map.getOrPutValue(gpa, 5, 5);
|
|
2218
1744
|
try testing.expect(gop3.value_ptr.* == 77);
|
|
2219
1745
|
|
|
2220
|
-
const gop4 = try map.getOrPutValue(100, 41);
|
|
1746
|
+
const gop4 = try map.getOrPutValue(gpa, 100, 41);
|
|
2221
1747
|
try testing.expect(gop4.value_ptr.* == 41);
|
|
2222
1748
|
|
|
2223
1749
|
try testing.expect(map.contains(2));
|
|
@@ -2234,7 +1760,7 @@ test "basic hash map usage" {
|
|
|
2234
1760
|
|
|
2235
1761
|
// Since we've used `swapRemove` above, the index of this entry should remain unchanged.
|
|
2236
1762
|
try testing.expect(map.getIndex(100).? == 1);
|
|
2237
|
-
const gop5 = try map.getOrPut(5);
|
|
1763
|
+
const gop5 = try map.getOrPut(gpa, 5);
|
|
2238
1764
|
try testing.expect(gop5.found_existing == true);
|
|
2239
1765
|
try testing.expect(gop5.value_ptr.* == 77);
|
|
2240
1766
|
try testing.expect(gop5.index == 4);
|
|
@@ -2247,7 +1773,7 @@ test "basic hash map usage" {
|
|
|
2247
1773
|
try testing.expect(map.orderedRemove(100) == false);
|
|
2248
1774
|
try testing.expect(map.getEntry(100) == null);
|
|
2249
1775
|
try testing.expect(map.get(100) == null);
|
|
2250
|
-
const gop6 = try map.getOrPut(5);
|
|
1776
|
+
const gop6 = try map.getOrPut(gpa, 5);
|
|
2251
1777
|
try testing.expect(gop6.found_existing == true);
|
|
2252
1778
|
try testing.expect(gop6.value_ptr.* == 77);
|
|
2253
1779
|
try testing.expect(gop6.index == 3);
|
|
@@ -2256,15 +1782,17 @@ test "basic hash map usage" {
|
|
|
2256
1782
|
}
|
|
2257
1783
|
|
|
2258
1784
|
test "iterator hash map" {
|
|
2259
|
-
|
|
2260
|
-
|
|
1785
|
+
const gpa = testing.allocator;
|
|
1786
|
+
|
|
1787
|
+
var reset_map: Auto(i32, i32) = .empty;
|
|
1788
|
+
defer reset_map.deinit(gpa);
|
|
2261
1789
|
|
|
2262
1790
|
// test ensureTotalCapacity with a 0 parameter
|
|
2263
|
-
try reset_map.ensureTotalCapacity(0);
|
|
1791
|
+
try reset_map.ensureTotalCapacity(gpa, 0);
|
|
2264
1792
|
|
|
2265
|
-
try reset_map.putNoClobber(0, 11);
|
|
2266
|
-
try reset_map.putNoClobber(1, 22);
|
|
2267
|
-
try reset_map.putNoClobber(2, 33);
|
|
1793
|
+
try reset_map.putNoClobber(gpa, 0, 11);
|
|
1794
|
+
try reset_map.putNoClobber(gpa, 1, 22);
|
|
1795
|
+
try reset_map.putNoClobber(gpa, 2, 33);
|
|
2268
1796
|
|
|
2269
1797
|
const keys = [_]i32{
|
|
2270
1798
|
0, 2, 1,
|
|
@@ -2312,10 +1840,12 @@ test "iterator hash map" {
|
|
|
2312
1840
|
}
|
|
2313
1841
|
|
|
2314
1842
|
test "ensure capacity" {
|
|
2315
|
-
|
|
2316
|
-
defer map.deinit();
|
|
1843
|
+
const gpa = testing.allocator;
|
|
2317
1844
|
|
|
2318
|
-
|
|
1845
|
+
var map: Auto(i32, i32) = .empty;
|
|
1846
|
+
defer map.deinit(gpa);
|
|
1847
|
+
|
|
1848
|
+
try map.ensureTotalCapacity(gpa, 20);
|
|
2319
1849
|
const initial_capacity = map.capacity();
|
|
2320
1850
|
try testing.expect(initial_capacity >= 20);
|
|
2321
1851
|
var i: i32 = 0;
|
|
@@ -2329,23 +1859,25 @@ test "ensure capacity" {
|
|
|
2329
1859
|
test "ensure capacity leak" {
|
|
2330
1860
|
try testing.checkAllAllocationFailures(std.testing.allocator, struct {
|
|
2331
1861
|
pub fn f(allocator: Allocator) !void {
|
|
2332
|
-
var map
|
|
2333
|
-
defer map.deinit();
|
|
1862
|
+
var map: Auto(i32, i32) = .empty;
|
|
1863
|
+
defer map.deinit(allocator);
|
|
2334
1864
|
|
|
2335
1865
|
var i: i32 = 0;
|
|
2336
1866
|
// put more than `linear_scan_max` in so index_header gets allocated.
|
|
2337
|
-
while (i <= 20) : (i += 1) try map.put(i, i);
|
|
1867
|
+
while (i <= 20) : (i += 1) try map.put(allocator, i, i);
|
|
2338
1868
|
}
|
|
2339
1869
|
}.f, .{});
|
|
2340
1870
|
}
|
|
2341
1871
|
|
|
2342
1872
|
test "big map" {
|
|
2343
|
-
|
|
2344
|
-
|
|
1873
|
+
const gpa = testing.allocator;
|
|
1874
|
+
|
|
1875
|
+
var map: Auto(i32, i32) = .empty;
|
|
1876
|
+
defer map.deinit(gpa);
|
|
2345
1877
|
|
|
2346
1878
|
var i: i32 = 0;
|
|
2347
1879
|
while (i < 8) : (i += 1) {
|
|
2348
|
-
try map.put(i, i + 10);
|
|
1880
|
+
try map.put(gpa, i, i + 10);
|
|
2349
1881
|
}
|
|
2350
1882
|
|
|
2351
1883
|
i = 0;
|
|
@@ -2358,7 +1890,7 @@ test "big map" {
|
|
|
2358
1890
|
|
|
2359
1891
|
i = 4;
|
|
2360
1892
|
while (i < 12) : (i += 1) {
|
|
2361
|
-
try map.put(i, i + 12);
|
|
1893
|
+
try map.put(gpa, i, i + 12);
|
|
2362
1894
|
}
|
|
2363
1895
|
|
|
2364
1896
|
i = 0;
|
|
@@ -2393,17 +1925,19 @@ test "big map" {
|
|
|
2393
1925
|
}
|
|
2394
1926
|
|
|
2395
1927
|
test "clone" {
|
|
2396
|
-
|
|
2397
|
-
|
|
1928
|
+
const gpa = testing.allocator;
|
|
1929
|
+
|
|
1930
|
+
var original: Auto(i32, i32) = .empty;
|
|
1931
|
+
defer original.deinit(gpa);
|
|
2398
1932
|
|
|
2399
1933
|
// put more than `linear_scan_max` so we can test that the index header is properly cloned
|
|
2400
1934
|
var i: u8 = 0;
|
|
2401
1935
|
while (i < 10) : (i += 1) {
|
|
2402
|
-
try original.putNoClobber(i, i * 10);
|
|
1936
|
+
try original.putNoClobber(gpa, i, i * 10);
|
|
2403
1937
|
}
|
|
2404
1938
|
|
|
2405
|
-
var copy = try original.clone();
|
|
2406
|
-
defer copy.deinit();
|
|
1939
|
+
var copy = try original.clone(gpa);
|
|
1940
|
+
defer copy.deinit(gpa);
|
|
2407
1941
|
|
|
2408
1942
|
i = 0;
|
|
2409
1943
|
while (i < 10) : (i += 1) {
|
|
@@ -2419,16 +1953,18 @@ test "clone" {
|
|
|
2419
1953
|
}
|
|
2420
1954
|
|
|
2421
1955
|
test "shrink" {
|
|
2422
|
-
|
|
2423
|
-
|
|
1956
|
+
const gpa = testing.allocator;
|
|
1957
|
+
|
|
1958
|
+
var map: Auto(i32, i32) = .empty;
|
|
1959
|
+
defer map.deinit(gpa);
|
|
2424
1960
|
|
|
2425
1961
|
// This test is more interesting if we insert enough entries to allocate the index header.
|
|
2426
1962
|
const num_entries = 200;
|
|
2427
1963
|
var i: i32 = 0;
|
|
2428
1964
|
while (i < num_entries) : (i += 1)
|
|
2429
|
-
try testing.expect((try map.fetchPut(i, i * 10)) == null);
|
|
1965
|
+
try testing.expect((try map.fetchPut(gpa, i, i * 10)) == null);
|
|
2430
1966
|
|
|
2431
|
-
try testing.expect(map.
|
|
1967
|
+
try testing.expect(map.index_header != null);
|
|
2432
1968
|
try testing.expect(map.count() == num_entries);
|
|
2433
1969
|
|
|
2434
1970
|
// Test `shrinkRetainingCapacity`.
|
|
@@ -2437,7 +1973,7 @@ test "shrink" {
|
|
|
2437
1973
|
try testing.expect(map.capacity() >= num_entries);
|
|
2438
1974
|
i = 0;
|
|
2439
1975
|
while (i < num_entries) : (i += 1) {
|
|
2440
|
-
const gop = try map.getOrPut(i);
|
|
1976
|
+
const gop = try map.getOrPut(gpa, i);
|
|
2441
1977
|
if (i < 17) {
|
|
2442
1978
|
try testing.expect(gop.found_existing == true);
|
|
2443
1979
|
try testing.expect(gop.value_ptr.* == i * 10);
|
|
@@ -2445,12 +1981,12 @@ test "shrink" {
|
|
|
2445
1981
|
}
|
|
2446
1982
|
|
|
2447
1983
|
// Test `shrinkAndFree`.
|
|
2448
|
-
map.shrinkAndFree(15);
|
|
1984
|
+
map.shrinkAndFree(gpa, 15);
|
|
2449
1985
|
try testing.expect(map.count() == 15);
|
|
2450
1986
|
try testing.expect(map.capacity() == 15);
|
|
2451
1987
|
i = 0;
|
|
2452
1988
|
while (i < num_entries) : (i += 1) {
|
|
2453
|
-
const gop = try map.getOrPut(i);
|
|
1989
|
+
const gop = try map.getOrPut(gpa, i);
|
|
2454
1990
|
if (i < 15) {
|
|
2455
1991
|
try testing.expect(gop.found_existing == true);
|
|
2456
1992
|
try testing.expect(gop.value_ptr.* == i * 10);
|
|
@@ -2459,15 +1995,17 @@ test "shrink" {
|
|
|
2459
1995
|
}
|
|
2460
1996
|
|
|
2461
1997
|
test "pop()" {
|
|
2462
|
-
|
|
2463
|
-
|
|
1998
|
+
const gpa = testing.allocator;
|
|
1999
|
+
|
|
2000
|
+
var map: Auto(i32, i32) = .empty;
|
|
2001
|
+
defer map.deinit(gpa);
|
|
2464
2002
|
|
|
2465
2003
|
// Insert just enough entries so that the map expands. Afterwards,
|
|
2466
2004
|
// pop all entries out of the map.
|
|
2467
2005
|
|
|
2468
2006
|
var i: i32 = 0;
|
|
2469
2007
|
while (i < 9) : (i += 1) {
|
|
2470
|
-
try testing.expect((try map.fetchPut(i, i)) == null);
|
|
2008
|
+
try testing.expect((try map.fetchPut(gpa, i, i)) == null);
|
|
2471
2009
|
}
|
|
2472
2010
|
|
|
2473
2011
|
while (map.pop()) |pop| {
|
|
@@ -2479,31 +2017,33 @@ test "pop()" {
|
|
|
2479
2017
|
}
|
|
2480
2018
|
|
|
2481
2019
|
test "reIndex" {
|
|
2482
|
-
|
|
2483
|
-
|
|
2020
|
+
const gpa = testing.allocator;
|
|
2021
|
+
|
|
2022
|
+
var map: Custom(i32, i32, AutoContext(i32), true) = .empty;
|
|
2023
|
+
defer map.deinit(gpa);
|
|
2484
2024
|
|
|
2485
2025
|
// Populate via the API.
|
|
2486
2026
|
const num_indexed_entries = 200;
|
|
2487
2027
|
var i: i32 = 0;
|
|
2488
2028
|
while (i < num_indexed_entries) : (i += 1)
|
|
2489
|
-
try testing.expect((try map.fetchPut(i, i * 10)) == null);
|
|
2029
|
+
try testing.expect((try map.fetchPut(gpa, i, i * 10)) == null);
|
|
2490
2030
|
|
|
2491
2031
|
// Make sure we allocated an index header.
|
|
2492
|
-
try testing.expect(map.
|
|
2032
|
+
try testing.expect(map.index_header != null);
|
|
2493
2033
|
|
|
2494
2034
|
// Now write to the arrays directly.
|
|
2495
2035
|
const num_unindexed_entries = 20;
|
|
2496
|
-
try map.
|
|
2036
|
+
try map.entries.resize(std.testing.allocator, num_indexed_entries + num_unindexed_entries);
|
|
2497
2037
|
for (map.keys()[num_indexed_entries..], map.values()[num_indexed_entries..], num_indexed_entries..) |*key, *value, j| {
|
|
2498
2038
|
key.* = @intCast(j);
|
|
2499
2039
|
value.* = @intCast(j * 10);
|
|
2500
2040
|
}
|
|
2501
2041
|
|
|
2502
2042
|
// After reindexing, we should see everything.
|
|
2503
|
-
try map.reIndex();
|
|
2043
|
+
try map.reIndex(gpa);
|
|
2504
2044
|
i = 0;
|
|
2505
2045
|
while (i < num_indexed_entries + num_unindexed_entries) : (i += 1) {
|
|
2506
|
-
const gop = try map.getOrPut(i);
|
|
2046
|
+
const gop = try map.getOrPut(gpa, i);
|
|
2507
2047
|
try testing.expect(gop.found_existing == true);
|
|
2508
2048
|
try testing.expect(gop.value_ptr.* == i * 10);
|
|
2509
2049
|
try testing.expect(gop.index == i);
|
|
@@ -2511,23 +2051,20 @@ test "reIndex" {
|
|
|
2511
2051
|
}
|
|
2512
2052
|
|
|
2513
2053
|
test "auto store_hash" {
|
|
2514
|
-
const HasCheapEql =
|
|
2515
|
-
const HasExpensiveEql =
|
|
2054
|
+
const HasCheapEql = Auto(i32, i32);
|
|
2055
|
+
const HasExpensiveEql = Auto([32]i32, i32);
|
|
2516
2056
|
try testing.expect(@FieldType(HasCheapEql.Data, "hash") == void);
|
|
2517
2057
|
try testing.expect(@FieldType(HasExpensiveEql.Data, "hash") != void);
|
|
2518
|
-
|
|
2519
|
-
const HasCheapEqlUn = AutoArrayHashMapUnmanaged(i32, i32);
|
|
2520
|
-
const HasExpensiveEqlUn = AutoArrayHashMapUnmanaged([32]i32, i32);
|
|
2521
|
-
try testing.expect(@FieldType(HasCheapEqlUn.Data, "hash") == void);
|
|
2522
|
-
try testing.expect(@FieldType(HasExpensiveEqlUn.Data, "hash") != void);
|
|
2523
2058
|
}
|
|
2524
2059
|
|
|
2525
2060
|
test "sort" {
|
|
2526
|
-
|
|
2527
|
-
|
|
2061
|
+
const gpa = testing.allocator;
|
|
2062
|
+
|
|
2063
|
+
var map: Auto(i32, i32) = .empty;
|
|
2064
|
+
defer map.deinit(gpa);
|
|
2528
2065
|
|
|
2529
2066
|
for ([_]i32{ 8, 3, 12, 10, 2, 4, 9, 5, 6, 13, 14, 15, 16, 1, 11, 17, 7 }) |x| {
|
|
2530
|
-
try map.put(x, x * 3);
|
|
2067
|
+
try map.put(gpa, x, x * 3);
|
|
2531
2068
|
}
|
|
2532
2069
|
|
|
2533
2070
|
const C = struct {
|
|
@@ -2549,15 +2086,17 @@ test "sort" {
|
|
|
2549
2086
|
}
|
|
2550
2087
|
|
|
2551
2088
|
test "0 sized key" {
|
|
2552
|
-
|
|
2553
|
-
|
|
2089
|
+
const gpa = testing.allocator;
|
|
2090
|
+
|
|
2091
|
+
var map: Auto(u0, i32) = .empty;
|
|
2092
|
+
defer map.deinit(gpa);
|
|
2554
2093
|
|
|
2555
2094
|
try testing.expectEqual(map.get(0), null);
|
|
2556
2095
|
|
|
2557
|
-
try map.put(0, 5);
|
|
2096
|
+
try map.put(gpa, 0, 5);
|
|
2558
2097
|
try testing.expectEqual(map.get(0), 5);
|
|
2559
2098
|
|
|
2560
|
-
try map.put(0, 10);
|
|
2099
|
+
try map.put(gpa, 0, 10);
|
|
2561
2100
|
try testing.expectEqual(map.get(0), 10);
|
|
2562
2101
|
|
|
2563
2102
|
try testing.expectEqual(map.swapRemove(0), true);
|
|
@@ -2565,12 +2104,14 @@ test "0 sized key" {
|
|
|
2565
2104
|
}
|
|
2566
2105
|
|
|
2567
2106
|
test "0 sized key and 0 sized value" {
|
|
2568
|
-
|
|
2569
|
-
|
|
2107
|
+
const gpa = testing.allocator;
|
|
2108
|
+
|
|
2109
|
+
var map: Auto(u0, u0) = .empty;
|
|
2110
|
+
defer map.deinit(gpa);
|
|
2570
2111
|
|
|
2571
2112
|
try testing.expectEqual(map.get(0), null);
|
|
2572
2113
|
|
|
2573
|
-
try map.put(0, 0);
|
|
2114
|
+
try map.put(gpa, 0, 0);
|
|
2574
2115
|
try testing.expectEqual(map.get(0), 0);
|
|
2575
2116
|
|
|
2576
2117
|
try testing.expectEqual(map.swapRemove(0), true);
|
|
@@ -2580,7 +2121,7 @@ test "0 sized key and 0 sized value" {
|
|
|
2580
2121
|
test "setKey storehash true" {
|
|
2581
2122
|
const gpa = std.testing.allocator;
|
|
2582
2123
|
|
|
2583
|
-
var map:
|
|
2124
|
+
var map: ArrayHashMap(i32, i32, AutoContext(i32), true) = .empty;
|
|
2584
2125
|
defer map.deinit(gpa);
|
|
2585
2126
|
|
|
2586
2127
|
try map.put(gpa, 12, 34);
|
|
@@ -2596,7 +2137,7 @@ test "setKey storehash true" {
|
|
|
2596
2137
|
test "setKey storehash false" {
|
|
2597
2138
|
const gpa = std.testing.allocator;
|
|
2598
2139
|
|
|
2599
|
-
var map:
|
|
2140
|
+
var map: ArrayHashMap(i32, i32, AutoContext(i32), false) = .empty;
|
|
2600
2141
|
defer map.deinit(gpa);
|
|
2601
2142
|
|
|
2602
2143
|
try map.put(gpa, 12, 34);
|
|
@@ -2691,7 +2232,7 @@ pub fn getAutoHashStratFn(comptime K: type, comptime Context: type, comptime str
|
|
|
2691
2232
|
test "orderedRemoveAtMany" {
|
|
2692
2233
|
const gpa = testing.allocator;
|
|
2693
2234
|
|
|
2694
|
-
var map:
|
|
2235
|
+
var map: Auto(usize, void) = .empty;
|
|
2695
2236
|
defer map.deinit(gpa);
|
|
2696
2237
|
|
|
2697
2238
|
for (0..10) |n| {
|