zig-skills/references/std-buf-map.md

185 lines
4.4 KiB
Markdown

# std.BufMap / std.BufSet
String-keyed maps and sets that own their strings. Automatically copy and free string keys/values.
## When to Use
- Environment variable storage
- String-to-string mapping with ownership
- Set of unique strings with automatic memory management
- When you don't want to manage string lifetime manually
## BufMap (String -> String)
```zig
const std = @import("std");
var map = std.BufMap.init(allocator);
defer map.deinit(); // frees all stored strings
// Put copies a new key and value. Replacing an existing key retains the stored
// key allocation and copies only the new value.
try map.put("HOME", "/Users/alice");
try map.put("PATH", "/usr/bin");
// Get
if (map.get("HOME")) |home| {
std.debug.print("home: {s}\n", .{home});
}
// Replace through the public ownership-aware operation.
try map.put("PATH", "/new/path");
// Remove (frees both key and value)
map.remove("PATH");
// Count
const n = map.count();
```
## BufMap: Move Ownership
```zig
// putMove takes ownership instead of copying
const key = try allocator.dupe(u8, "MY_KEY");
const value = try allocator.dupe(u8, "my_value");
map.putMove(key, value) catch |err| {
allocator.free(key);
allocator.free(value);
return err;
};
// On success, the map owns both buffers.
```
## BufMap: Iteration
```zig
var it = map.iterator();
while (it.next()) |entry| {
const key = entry.key_ptr.*;
const value = entry.value_ptr.*;
std.debug.print("{s}={s}\n", .{ key, value });
}
```
## BufSet (Set of Strings)
```zig
var set = std.BufSet.init(allocator);
defer set.deinit(); // frees all stored strings
// Insert (copies the string)
try set.insert("apple");
try set.insert("banana");
try set.insert("apple"); // no-op, already exists
// Check membership
if (set.contains("apple")) {
// it's in the set
}
// Remove (frees the string)
set.remove("banana");
// Count
const n = set.count();
```
## BufSet: Iteration
```zig
var it = set.iterator();
while (it.next()) |key| {
std.debug.print("{s}\n", .{key.*});
}
```
## BufSet: Clone
```zig
// Create independent copy
var copy = try set.clone();
defer copy.deinit();
// Clone with different allocator
var arena_copy = try set.cloneWithAllocator(arena.allocator());
// No need to deinit if using arena
```
## Complete Example: Environment Variables
```zig
const std = @import("std");
pub fn main() !void {
var gpa: std.heap.DebugAllocator(.{}) = .init;
defer _ = gpa.deinit();
const alloc = gpa.allocator();
var env = std.BufMap.init(alloc);
defer env.deinit();
// Set some variables
try env.put("APP_NAME", "MyApp");
try env.put("APP_VERSION", "1.0.0");
try env.put("DEBUG", "true");
// Update a value
try env.put("DEBUG", "false"); // replaces, frees old value
// Print all
var it = env.iterator();
while (it.next()) |entry| {
std.debug.print("{s}={s}\n", .{ entry.key_ptr.*, entry.value_ptr.* });
}
// Check and use
if (env.get("DEBUG")) |debug| {
if (std.mem.eql(u8, debug, "true")) {
std.debug.print("Debug mode enabled\n", .{});
}
}
}
```
## Complete Example: Unique Words
```zig
const std = @import("std");
pub fn main() !void {
var gpa: std.heap.DebugAllocator(.{}) = .init;
defer _ = gpa.deinit();
var words = std.BufSet.init(gpa.allocator());
defer words.deinit();
const text = "the quick brown fox jumps over the lazy dog";
var tokens = std.mem.tokenizeScalar(u8, text, ' ');
while (tokens.next()) |word| {
try words.insert(word); // duplicates automatically ignored
}
std.debug.print("Unique words: {}\n", .{words.count()}); // 8
var it = words.iterator();
while (it.next()) |word| {
std.debug.print(" {s}\n", .{word.*});
}
}
```
## Notes
- A new insertion copies both strings. Replacing an existing key retains its
stored key and replaces the owned value.
- `putMove` transfers ownership only on success; on error the caller retains it.
- A slice from `get()` is invalidated by replacing/removing its key or
deinitializing the map.
- A pointer from `getPtr()` is invalidated by resize, removal of that entry, or
deinitialization. Replacing the value updates the existing slot.
- Iteration order is arbitrary; do not rely on insertion order, and do not
modify a `BufMap` or `BufSet` while an iterator is live.
- For non-owning string maps, use `std.StringHashMap`