std.mem — Operações de Memória
O módulo std.mem fornece funções fundamentais para trabalhar com memória e slices no Zig. Ele inclui operações de comparação, busca, cópia, preenchimento, alinhamento e a interface Allocator — o mecanismo central de alocação de memória do Zig.
Visão Geral
const std = @import("std");
const mem = std.mem;
O std.mem é um dos módulos mais usados em Zig, pois slices ([]const u8, []u8) são o tipo fundamental para strings e dados binários.
Funções de Comparação
// Compara dois slices para igualdade
pub fn eql(comptime T: type, a: []const T, b: []const T) bool
// Compara com ordenação (retorna .lt, .eq, .gt)
pub fn order(comptime T: type, a: []const T, b: []const T) std.math.Order
// Verifica se slice começa com prefixo
pub fn startsWith(comptime T: type, haystack: []const T, needle: []const T) bool
// Verifica se slice termina com sufixo
pub fn endsWith(comptime T: type, haystack: []const T, needle: []const T) bool
Funções de Busca
// Encontra primeira ocorrência de subsequência
pub fn indexOf(comptime T: type, haystack: []const T, needle: []const T) ?usize
// Encontra última ocorrência
pub fn lastIndexOf(comptime T: type, haystack: []const T, needle: []const T) ?usize
// Encontra primeiro elemento igual a qualquer valor no conjunto
pub fn indexOfAny(comptime T: type, haystack: []const T, needles: []const T) ?usize
// Conta ocorrências de um valor
pub fn count(comptime T: type, haystack: []const T, needle: []const T) usize
// Verifica se contém subsequência
pub fn containsAtLeast(comptime T: type, haystack: []const T, n: usize, needle: []const T) bool
Funções de Manipulação
// Copia memória (src e dst não podem sobrepor)
pub fn copyForwards(comptime T: type, dst: []T, src: []const T) void
// Preenche com um valor
pub fn set(comptime T: type, slice: []T, value: T) void
// Substitui todas as ocorrências
pub fn replace(comptime T: type, input: []const T, needle: []const T, replacement: []const T, output: []T) usize
// Remove prefixo/sufixo
pub fn trimLeft(comptime T: type, slice: []const T, values_to_strip: []const T) []const T
pub fn trimRight(comptime T: type, slice: []const T, values_to_strip: []const T) []const T
pub fn trim(comptime T: type, slice: []const T, values_to_strip: []const T) []const T
Exemplo 1: Comparação e Busca em Strings
const std = @import("std");
const mem = std.mem;
pub fn main() void {
const texto = "Zig é uma linguagem de programação de sistemas";
// Comparação
std.debug.print("Igual: {}\n", .{mem.eql(u8, "Zig", "Zig")}); // true
std.debug.print("Igual: {}\n", .{mem.eql(u8, "Zig", "zig")}); // false
// Busca
if (mem.indexOf(u8, texto, "linguagem")) |pos| {
std.debug.print("'linguagem' encontrada na posição {d}\n", .{pos});
}
// Prefixo e sufixo
std.debug.print("Começa com 'Zig': {}\n", .{mem.startsWith(u8, texto, "Zig")});
std.debug.print("Termina com 'sistemas': {}\n", .{mem.endsWith(u8, texto, "sistemas")});
// Contagem
const contagem = mem.count(u8, texto, "de");
std.debug.print("Ocorrências de 'de': {d}\n", .{contagem});
}
Exemplo 2: Manipulação de Slices
const std = @import("std");
const mem = std.mem;
pub fn main() void {
// Trim
const bruto = " Olá, mundo! ";
const limpo = mem.trim(u8, bruto, " ");
std.debug.print("Trim: '{s}'\n", .{limpo}); // 'Olá, mundo!'
const apenas_esquerda = mem.trimLeft(u8, bruto, " ");
std.debug.print("TrimLeft: '{s}'\n", .{apenas_esquerda}); // 'Olá, mundo! '
// Substituição
var buf: [100]u8 = undefined;
const entrada = "foo-bar-baz";
const substituicoes = mem.replace(u8, entrada, "-", "_", &buf);
std.debug.print("Substituição: '{s}' ({d} trocas)\n", .{
buf[0..entrada.len],
substituicoes,
}); // 'foo_bar_baz' (2 trocas)
// Preenchimento
var dados: [10]u8 = undefined;
mem.set(u8, &dados, 0xFF);
std.debug.print("Preenchido: ", .{});
for (dados) |byte| {
std.debug.print("{x:0>2} ", .{byte});
}
std.debug.print("\n", .{});
}
Exemplo 3: Funções de Alinhamento
const std = @import("std");
const mem = std.mem;
pub fn main() void {
// Alinhamento de valores
std.debug.print("alignForward(13, 8) = {d}\n", .{mem.alignForward(usize, 13, 8)}); // 16
std.debug.print("alignBackward(13, 8) = {d}\n", .{mem.alignBackward(usize, 13, 8)}); // 8
std.debug.print("isAligned(16, 8) = {}\n", .{mem.isAligned(16, 8)}); // true
std.debug.print("isAligned(13, 8) = {}\n", .{mem.isAligned(13, 8)}); // false
// Conversão de slices
const bytes = [_]u8{ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 };
const inteiros = mem.bytesAsSlice(u32, &bytes);
std.debug.print("Inteiros: {d}, {d}\n", .{ inteiros[0], inteiros[1] }); // 1, 2 (little-endian)
}
Padrões Comuns
Comparação de Strings
Em Zig, strings são []const u8. Use mem.eql para comparar:
fn ehComando(entrada: []const u8, comando: []const u8) bool {
return mem.eql(u8, entrada, comando);
}
Busca case-insensitive
fn indexOfInsensitive(haystack: []const u8, needle: []const u8) ?usize {
if (needle.len > haystack.len) return null;
for (0..haystack.len - needle.len + 1) |i| {
if (std.ascii.eqlIgnoreCase(haystack[i..][0..needle.len], needle)) {
return i;
}
}
return null;
}
Conversão entre Tipos de Slice
// []u8 para []u32 (requer alinhamento!)
const aligned_bytes = mem.bytesAsSlice(u32, bytes_alinhados);
// []u32 para []u8
const raw_bytes = mem.sliceAsBytes(inteiros);
Módulos Relacionados
- std.mem.Allocator — Interface de alocação
- std.mem.eql — Comparação e busca detalhada
- std.mem.split — Divisão e tokenização
- std.heap — Implementações de alocadores
- std.fmt — Formatação de strings