tiny.xkb.compose
Defined in tiny.xkb.
API (92)
Actions
Public operations.
Capacity.deriveIterator.nextOptions.parserOptionsOptions.pathOptionsScratchCapacity.deriveScratchStorage.acquireScratchStorage.activateScratchStorage.auxiliaryPathScratchStorage.deinitScratchStorage.fileLineScratchStorage.filePathScratchStorage.initScratchStorage.lineLimitScratchStorage.registryLineScratchStorage.resetScratchStorage.statusState.feedState.initState.resetState.statusState.symbolState.writeUtf8Storage.acquireStorage.activateStorage.deinitStorage.initStorage.insertStorage.publishStorage.resetStorage.statusTable.iteratorTable.resultTable.transitionTable.viewView.resultView.transitioncompileexpandIncludehomePathloadlocalePathparseparseOpenedFilexdgPath
Types and contracts
Public types and contracts.
CapacityDiagnosticDiagnosticCodeDiagnosticFnEntryExhaustionFeedResultIteratorLimitsLoadErrorOptionsParseErrorParserOptionsPathOptionsResultScratchCapacityScratchExhaustionScratchLimitsScratchStatusScratchStorageScratchStorage.AcquireErrorScratchStorage.CapacityScratchStorage.ExhaustionScratchStorage.InitErrorScratchStorage.LimitsStateStatusStorageStorage.AcquireErrorStorage.CapacityStorage.ExhaustionStorage.InitErrorStorage.LimitsStorageStatusTableTextErrorView
Values and defaults
Public values and defaults.
ScratchStorage.claimStorage.claimdefault_scratch_limitsdefault_system_directorymax_file_bytesmax_include_depthmax_nodesmax_output_bytesmax_path_bytesmax_registry_bytesmax_sequence_length
Source
Source: lib/xkb/src/compose/capacity.zig:17
pub const Capacity = struct { limits: Limits, node_count: usize, node_offset: usize, node_bytes: usize, edge_count: usize, edge_offset: usize, edge_bytes: usize, text_offset: usize, storage_bytes: usize, pub fn derive(limits: Limits) DeriveError!Capacity { if (limits.sequence_symbols >= table.max_nodes) { return error.SequenceSymbolLimitExceeded; } if (limits.text_bytes > std.math.maxInt(u32)) return error.TextByteLimitExceeded; const node_count = try added(limits.sequence_symbols, 1); const nodes = try placed(table.Node, 0, node_count); const edges = try placed(table.Edge, nodes.end, limits.sequence_symbols); const text_offset = edges.end; return .{ .limits = limits, .node_count = node_count, .node_offset = nodes.start, .node_bytes = nodes.bytes, .edge_count = limits.sequence_symbols, .edge_offset = edges.start, .edge_bytes = edges.bytes, .text_offset = text_offset, .storage_bytes = try added(text_offset, limits.text_bytes), }; }};Source: lib/xkb/src/compose/capacity.zig:6
pub const Limits = struct { sequence_symbols: usize, text_bytes: usize,};Source: lib/xkb/src/compose/load.zig:7
pub const Options = struct { locale: []const u8, home: ?[]const u8 = null, xcompose_file: ?[]const u8 = null, xdg_config_home: ?[]const u8 = null, system_directory: []const u8 = compose.default_system_directory, io: std.Io = std.Options.debug_io, diagnostic_context: ?*anyopaque = null, diagnostic: ?compose.DiagnosticFn = null, pub fn pathOptions(self: Options) compose.PathOptions { return .{ .locale = self.locale, .home = self.home, .xcompose_file = self.xcompose_file, .xdg_config_home = self.xdg_config_home, .system_directory = self.system_directory, .io = self.io, }; } pub fn parserOptions(self: Options) compose.ParserOptions { return .{ .paths = self.pathOptions(), .diagnostic_context = self.diagnostic_context, .diagnostic = self.diagnostic, }; }};Source: lib/xkb/src/compose/parser.zig:15
pub const Diagnostic = struct { source: []const u8, line: usize, code: DiagnosticCode,};Source: lib/xkb/src/compose/parser.zig:7
pub const DiagnosticCode = enum { invalid_syntax, unknown_keysym, sequence_too_long, output_too_long, invalid_utf8,};Source: lib/xkb/src/compose/parser.zig:40
pub const Options = struct { paths: compose.PathOptions, diagnostic_context: ?*anyopaque = null, diagnostic: ?DiagnosticFn = null,};Source: lib/xkb/src/compose/path.zig:7
pub const Options = struct { locale: []const u8, home: ?[]const u8 = null, xcompose_file: ?[]const u8 = null, xdg_config_home: ?[]const u8 = null, system_directory: []const u8 = default_system_directory, io: std.Io = std.Options.debug_io,};Source: lib/xkb/src/compose/state.zig:14
pub const FeedResult = enum { ignored, accepted,};Source: lib/xkb/src/compose/state.zig:21
pub const State = struct { table: compose.View, previous: ?u32 = 0, current: ?u32 = 0, pub fn init(table: *const compose.Table) State { return .{ .table = table.view() }; } pub fn reset(self: *State) void { self.previous = 0; self.current = 0; } pub fn feed(self: *State, input_symbol: Keysym) FeedResult { if (xkb.keysym.isModifier(input_symbol)) return .ignored; const start = if (self.current) |node| if (node == 0 or self.table.result(node) == null) node else 0 else 0; self.previous = self.current; self.current = self.table.transition(start, input_symbol); return .accepted; } pub fn status(self: *const State) Status { const current = self.current orelse { const previous = self.previous orelse return .nothing; if (previous != 0 and self.table.result(previous) == null) { return .cancelled; } return .nothing; }; if (current == 0) return .nothing; return if (self.table.result(current) == null) .composing else .composed; } pub fn symbol(self: *const State) ?Keysym { const current = self.current orelse return null; const result_value = self.table.result(current) orelse return null; return result_value.symbol; } pub fn writeUtf8(self: *const State, buffer: []u8) TextError!?[]const u8 { const current = self.current orelse return null; const result_value = self.table.result(current) orelse return null; if (result_value.text) |text| { if (text.len > buffer.len) return error.BufferTooSmall; @memcpy(buffer[0..text.len], text); return buffer[0..text.len]; } const symbol_value = result_value.symbol orelse return null; const codepoint = xkb.keysym.codepoint(symbol_value) orelse return null; var encoded: [4]u8 = undefined; const length = std.unicode.utf8Encode(codepoint, &encoded) catch return null; if (length > buffer.len) return error.BufferTooSmall; @memcpy(buffer[0..length], encoded[0..length]); return buffer[0..length]; }};Source: lib/xkb/src/compose/state.zig:7
pub const Status = enum { nothing, composing, composed, cancelled,};Source: lib/xkb/src/compose/state.zig:19
pub const TextError = error{BufferTooSmall};Source: lib/xkb/src/compose/storage.zig:15
pub const Status = struct { phase: alloc_phase.capacity.Phase, in_use: bool, storage_bytes: usize, sequence_symbols: usize, text_bytes: usize, used_nodes: usize, used_edges: usize, used_text_bytes: usize,};Source: lib/xkb/src/compose/storage.zig:26
pub const Storage = struct { phase: alloc_phase.capacity.Phase, capacity: capacity_mod.Capacity, bytes: []align(capacity_mod.storage_alignment) u8, nodes: []table.Node, edges: []table.Edge, text: []u8, used_nodes: usize = 0, used_edges: usize = 0, used_text_bytes: usize = 0, in_use: bool = false, pub const Limits: type = capacity_mod.Limits; pub const Capacity: type = capacity_mod.Capacity; pub const Exhaustion: type = StorageExhaustion; pub const InitError = std.mem.Allocator.Error || capacity_mod.DeriveError; pub const AcquireError = Storage.Exhaustion; pub const claim: alloc_phase.capacity.Declaration = .{ .source = .{ .id = "xkb.compose_storage", .kind = .phase_static, .limit_source = .caller, .storage = .{ .covered = &.{ .{ .id = "compose_trie_nodes_and_sorted_transition_links", .lifetime = .steady, .detail = "Compose trie nodes and sorted transition links", }, .{ .id = "compose_result_text_bytes", .lifetime = .steady, .detail = "Compose result text bytes", }, }, .excluded = &.{ "caller-owned root Compose input bytes", "loading scratch covered by xkb.compose_scratch_storage", "diagnostic callbacks and filesystem handles", "windowing keymaps, operating-system state, and teardown storage", }, }, .capacity = .{ .inputs = &.{ alloc_phase.capacity.bindInput(Limits, "sequence_symbols", "sequence_symbols"), alloc_phase.capacity.bindInput(Limits, "text_bytes", "text_bytes"), }, .type_selectors = &.{}, .nodes = &.{ .{ .input = 0 }, .{ .constant = 1 }, .{ .input = 1 }, .{ .add = .{ .left = 0, .right = 1 } }, .{ .add = .{ .left = 3, .right = 0 } }, .{ .add = .{ .left = 4, .right = 2 } }, .{ .alignment = .{ .node = 5, .alignment = .{ .literal = 16 } } }, }, .assertions = &.{.{ .scope = .closure_total, .measure = .retained, .relation = .upper_bound, .expression = 6, }}, }, .overload = .{ .kind = .reject_before_mutation, .detail = "Each rule reserves all missing trie symbols and result text before private trie mutation.", }, .risks = .{ .transitive = .{ .status = .witnessed, .detail = "Trie construction, publication, lookup, iteration, and reuse stay inside fixed regions.", }, .foreign = .{ .status = .excluded, .detail = "filesystem handles remain foreign initialization effects outside the bounded scratch owner", }, }, .obligations = &.{ .{ .key = "xkb_compose_capacity", .role = .capacity_model }, .{ .key = "xkb_compose_acquisition", .role = .custom }, .{ .key = "xkb_compose_oom", .role = .custom }, .{ .key = "xkb_compose_boundaries", .role = .overload }, .{ .key = "xkb_compose_reuse", .role = .overload }, .{ .key = "xkb_compose_reserve", .role = .overload }, .{ .key = "xkb_compose_sealed", .role = .transitive_risk }, .{ .key = "xkb_compose_root", .role = .custom }, .{ .key = "xkb_compose_consumer", .role = .foreign_risk }, .{ .key = "xkb_compose_windowing_root", .role = .custom }, }, }, .bindings = .{ .owner = @This(), .seal = .{ .family = alloc_phase.capacity.selector(@This().activate), .premise = .{ .class = .checked_semantic_fact, .authority = .checker, }, }, .teardown = .{ .family = alloc_phase.capacity.selector(@This().deinit), .premise = .{ .class = .checked_semantic_fact, .authority = .checker, }, }, }, }; pub fn init(allocator: std.mem.Allocator, limits: Limits) InitError!Storage { const capacity = try Capacity.derive(limits); const bytes = try allocator.alignedAlloc( u8, .fromByteUnits(capacity_mod.storage_alignment), capacity.storage_bytes, ); return .{ .phase = .initialization, .capacity = capacity, .bytes = bytes, .nodes = typedSlice( table.Node, bytes, capacity.node_offset, capacity.node_count, ), .edges = typedSlice( table.Edge, bytes, capacity.edge_offset, capacity.edge_count, ), .text = bytes[capacity.text_offset..][0..capacity.limits.text_bytes], }; } pub fn activate(self: *Storage) void { std.debug.assert(self.phase == .initialization); std.debug.assert(self.bytes.len == self.capacity.storage_bytes); self.phase = .steady; } pub fn acquire(self: *Storage) Storage.Exhaustion!void { std.debug.assert(self.phase == .steady); if (self.in_use) return error.ComposeStorageInUse; self.in_use = true; self.used_nodes = 1; self.used_edges = 0; self.used_text_bytes = 0; self.nodes[0] = .{}; } pub fn insert( self: *Storage, sequence: []const Keysym, result_value: table.Result, ) Storage.Exhaustion!void { std.debug.assert(self.phase == .steady); std.debug.assert(self.in_use); std.debug.assert(sequence.len > 0); std.debug.assert(sequence.len <= table.max_sequence_length); if (result_value.text == null) std.debug.assert(result_value.symbol != null); if (result_value.symbol) |symbol| std.debug.assert(symbol != .no_symbol); const required_nodes = self.requiredNodes(sequence); if (required_nodes > self.nodes.len - self.used_nodes or required_nodes > self.edges.len - self.used_edges) { return error.SequenceSymbolCapacityExceeded; } const required_text = if (result_value.text) |value| value.len else 0; if (required_text > self.text.len - self.used_text_bytes) { return error.TextByteCapacityExceeded; } var node_index: u32 = 0; for (sequence, 0..) |symbol, sequence_index| { const last = sequence_index + 1 == sequence.len; node_index = self.childAssumeCapacity(node_index, symbol); const node = &self.nodes[node_index]; if (!last) { if (node.result.has_result) { node.result = .{}; node.first_edge = table.no_edge; } continue; } node.first_edge = table.no_edge; node.result = self.storeAssumeCapacity(result_value); } } pub fn publish(self: *const Storage) table.Table { std.debug.assert(self.phase == .steady); std.debug.assert(self.in_use); return .{ .nodes = self.nodes[0..self.used_nodes], .edges = self.edges[0..self.used_edges], .text = self.text[0..self.used_text_bytes], }; } pub fn reset(self: *Storage) void { std.debug.assert(self.phase == .steady); std.debug.assert(self.in_use); self.in_use = false; self.used_nodes = 0; self.used_edges = 0; self.used_text_bytes = 0; } pub fn status(self: *const Storage) Status { return .{ .phase = self.phase, .in_use = self.in_use, .storage_bytes = self.capacity.storage_bytes, .sequence_symbols = self.capacity.limits.sequence_symbols, .text_bytes = self.capacity.limits.text_bytes, .used_nodes = self.used_nodes, .used_edges = self.used_edges, .used_text_bytes = self.used_text_bytes, }; } pub fn deinit(self: *Storage, allocator: std.mem.Allocator) void { std.debug.assert(self.phase != .teardown); std.debug.assert(!self.in_use); std.debug.assert(self.bytes.len == self.capacity.storage_bytes); self.phase = .teardown; allocator.free(self.bytes); self.bytes = &.{}; self.nodes = &.{}; self.edges = &.{}; self.text = &.{}; self.used_nodes = 0; self.used_edges = 0; self.used_text_bytes = 0; } fn requiredNodes(self: *const Storage, sequence: []const Keysym) usize { var node_index: u32 = 0; for (sequence, 0..) |symbol, sequence_index| { const child_index = self.findChild(node_index, symbol) orelse return sequence.len - sequence_index; node_index = child_index; if (sequence_index + 1 < sequence.len and self.nodes[node_index].result.has_result) { return sequence.len - sequence_index - 1; } } return 0; } fn findChild(self: *const Storage, parent_index: u32, symbol: Keysym) ?u32 { var edge_index = self.nodes[parent_index].first_edge; while (edge_index != table.no_edge) { const edge = self.edges[edge_index]; const symbol_value = @backingInt(symbol); const candidate_value = @backingInt(edge.symbol); if (symbol_value < candidate_value) return null; if (symbol_value == candidate_value) return edge.node; edge_index = edge.next; } return null; } fn childAssumeCapacity(self: *Storage, parent_index: u32, symbol: Keysym) u32 { var previous_edge: u32 = table.no_edge; var next_edge = self.nodes[parent_index].first_edge; while (next_edge != table.no_edge) { const edge = self.edges[next_edge]; const symbol_value = @backingInt(symbol); const candidate_value = @backingInt(edge.symbol); if (symbol_value < candidate_value) break; if (symbol_value == candidate_value) return edge.node; previous_edge = next_edge; next_edge = edge.next; } std.debug.assert(self.used_nodes < self.nodes.len); std.debug.assert(self.used_edges < self.edges.len); const child_index: u32 = @intCast(self.used_nodes); const edge_index: u32 = @intCast(self.used_edges); self.nodes[child_index] = .{}; self.edges[edge_index] = .{ .symbol = symbol, .node = child_index, .next = next_edge, }; if (previous_edge == table.no_edge) { self.nodes[parent_index].first_edge = edge_index; } else { self.edges[previous_edge].next = edge_index; } self.used_nodes += 1; self.used_edges += 1; return child_index; } fn storeAssumeCapacity( self: *Storage, result_value: table.Result, ) table.StoredResult { var stored = table.StoredResult{ .has_result = true, .symbol = result_value.symbol orelse .no_symbol, }; if (result_value.text) |text_value| { std.debug.assert(text_value.len <= table.max_output_bytes); std.debug.assert(text_value.len <= self.text.len - self.used_text_bytes); stored.text_offset = @intCast(self.used_text_bytes); stored.text_length = @intCast(text_value.len); stored.has_text = true; @memcpy( self.text[self.used_text_bytes..][0..text_value.len], text_value, ); self.used_text_bytes += text_value.len; } return stored; }};Source: lib/xkb/src/compose/storage.zig:9
pub const StorageExhaustion = error{ ComposeStorageInUse, SequenceSymbolCapacityExceeded, TextByteCapacityExceeded,};Source: lib/xkb/src/compose/table.zig:35
pub const Entry = struct { sequence: []const Keysym, text: ?[]const u8, symbol: ?Keysym,};Source: lib/xkb/src/compose/table.zig:98
pub const Iterator = struct { table: View, frames: [max_sequence_length + 1]Frame = undefined, sequence: [max_sequence_length]Keysym = undefined, depth: usize = 0, const Frame = struct { node: u32, next_edge: u32, yielded: bool = false, }; fn init(table: *const Table) Iterator { var result = Iterator{ .table = table.view() }; result.frames[0] = .{ .node = 0, .next_edge = result.table.nodes[0].first_edge, }; return result; } pub fn next(self: *Iterator) ?Entry { while (true) { var frame = &self.frames[self.depth]; if (!frame.yielded) { frame.yielded = true; if (self.table.result(frame.node)) |result_value| { return .{ .sequence = self.sequence[0..self.depth], .text = result_value.text, .symbol = result_value.symbol, }; } } if (frame.next_edge != no_edge) { const edge = self.table.edges[frame.next_edge]; frame.next_edge = edge.next; self.sequence[self.depth] = edge.symbol; self.depth += 1; self.frames[self.depth] = .{ .node = edge.node, .next_edge = self.table.nodes[edge.node].first_edge, }; continue; } if (self.depth == 0) return null; self.depth -= 1; } }};Source: lib/xkb/src/compose/table.zig:11
pub const Result = struct { text: ?[]const u8 = null, symbol: ?Keysym = null,};Source: lib/xkb/src/compose/table.zig:41
pub const Table = struct { nodes: []const Node, edges: []const Edge, text: []const u8, pub fn iterator(self: *const Table) Iterator { return Iterator.init(self); } pub fn view(self: *const Table) View { return .{ .nodes = self.nodes, .edges = self.edges, .text = self.text, }; } pub fn transition(self: *const Table, node_index: u32, symbol: Keysym) ?u32 { return self.view().transition(node_index, symbol); } pub fn result(self: *const Table, node_index: u32) ?Result { return self.view().result(node_index); }};Source: lib/xkb/src/compose/table.zig:67
pub const View = struct { nodes: []const Node, edges: []const Edge, text: []const u8, pub fn transition(self: View, node_index: u32, symbol: Keysym) ?u32 { var edge_index = self.nodes[node_index].first_edge; while (edge_index != no_edge) { const edge = self.edges[edge_index]; const symbol_value = @backingInt(symbol); const candidate_value = @backingInt(edge.symbol); if (symbol_value < candidate_value) return null; if (symbol_value == candidate_value) return edge.node; edge_index = edge.next; } return null; } pub fn result(self: View, node_index: u32) ?Result { const stored = self.nodes[node_index].result; if (!stored.has_result) return null; return .{ .text = if (stored.has_text) self.text[stored.text_offset..][0..stored.text_length] else null, .symbol = if (stored.symbol == .no_symbol) null else stored.symbol, }; }};Source: lib/xkb/src/compose/workspace/capacity.zig:32
pub const Capacity = struct { limits: Limits, line_bytes_per_slot: usize, line_slot_count: usize, line_offset: usize, line_storage_bytes: usize, path_slot_count: usize, path_offset: usize, path_storage_bytes: usize, storage_bytes: usize, pub fn derive(limits: Limits) DeriveError!Capacity { if (limits.line_bytes == 0) return error.LineByteLimitZero; if (limits.line_bytes > max_file_bytes) return error.LineByteLimitExceeded; if (limits.path_bytes == 0) return error.PathByteLimitZero; if (limits.path_bytes > max_path_bytes) return error.PathByteLimitExceeded; const line_bytes_per_slot = try added(limits.line_bytes, 1); const line_storage_bytes = try multiplied(line_slot_count, line_bytes_per_slot); const path_storage_bytes = try multiplied(path_slot_count, limits.path_bytes); return .{ .limits = limits, .line_bytes_per_slot = line_bytes_per_slot, .line_slot_count = line_slot_count, .line_offset = 0, .line_storage_bytes = line_storage_bytes, .path_slot_count = path_slot_count, .path_offset = line_storage_bytes, .path_storage_bytes = path_storage_bytes, .storage_bytes = try added(line_storage_bytes, path_storage_bytes), }; }};Source: lib/xkb/src/compose/workspace/capacity.zig:14
pub const Limits = struct { line_bytes: usize, path_bytes: usize,};Source: lib/xkb/src/compose/workspace/storage.zig:11
pub const Status = struct { phase: alloc_phase.capacity.Phase, in_use: bool, storage_bytes: usize, line_bytes: usize, path_bytes: usize,};Source: lib/xkb/src/compose/workspace/storage.zig:19
pub const Storage = struct { phase: alloc_phase.capacity.Phase, capacity: capacity_mod.Capacity, bytes: []u8, lines: []u8, paths: []u8, in_use: bool = false, pub const Limits: type = capacity_mod.Limits; pub const Capacity: type = capacity_mod.Capacity; pub const Exhaustion: type = StorageExhaustion; pub const InitError = std.mem.Allocator.Error || capacity_mod.DeriveError; pub const AcquireError = Storage.Exhaustion; pub const claim: alloc_phase.capacity.Declaration = .{ .source = .{ .id = "xkb.compose_scratch_storage", .kind = .phase_static, .limit_source = .caller, .storage = .{ .covered = &.{ .{ .id = "recursive_compose_and_registry_line_input", .lifetime = .steady, .detail = "recursive Compose and registry line input", }, .{ .id = "compose_discovery_and_include_paths", .lifetime = .steady, .detail = "Compose discovery and include paths", }, }, .excluded = &.{ "caller-owned root Compose input bytes", "Compose trie and result storage", "diagnostic callbacks, operating-system file handles, and teardown storage", }, }, .capacity = .{ .inputs = &.{ alloc_phase.capacity.bindInput(Limits, "line_bytes", "line_bytes"), alloc_phase.capacity.bindInput(Limits, "path_bytes", "path_bytes"), }, .type_selectors = &.{}, .nodes = &.{ .{ .input = 0 }, .{ .constant = 1 }, .{ .add = .{ .left = 0, .right = 1 } }, .{ .scale = .{ .node = 2, .coefficient = .{ .literal = 7 } } }, .{ .input = 1 }, .{ .scale = .{ .node = 4, .coefficient = .{ .literal = 8 } } }, .{ .add = .{ .left = 3, .right = 5 } }, }, .assertions = &.{.{ .scope = .closure_total, .measure = .retained, .relation = .exact, .expression = 6, }}, }, .overload = .{ .kind = .terminal, .detail = "Line or path overload terminates compilation and resets private scratch and table state.", }, .risks = .{ .transitive = .{ .status = .witnessed, .detail = "File, registry, locale, include, and path processing use only fixed scratch slots after activation.", }, .foreign = .{ .status = .excluded, .detail = "filesystem handles and platform I/O internals remain foreign initialization effects", }, }, .obligations = &.{ .{ .key = "xkb_compose_scratch_capacity", .role = .capacity_model }, .{ .key = "xkb_compose_scratch_acquisition", .role = .custom }, .{ .key = "xkb_compose_scratch_oom", .role = .custom }, .{ .key = "xkb_compose_scratch_boundaries", .role = .overload }, .{ .key = "xkb_compose_scratch_reuse", .role = .overload }, .{ .key = "xkb_compose_scratch_depth", .role = .overload }, .{ .key = "xkb_compose_scratch_sealed", .role = .transitive_risk }, .{ .key = "xkb_compose_scratch_root", .role = .custom }, .{ .key = "xkb_compose_scratch_consumer", .role = .foreign_risk }, .{ .key = "xkb_compose_scratch_windowing_root", .role = .custom }, }, }, .bindings = .{ .owner = @This(), .seal = .{ .family = alloc_phase.capacity.selector(@This().activate), .premise = .{ .class = .checked_semantic_fact, .authority = .checker, }, }, .teardown = .{ .family = alloc_phase.capacity.selector(@This().deinit), .premise = .{ .class = .checked_semantic_fact, .authority = .checker, }, }, }, }; pub fn init(allocator: std.mem.Allocator, limits: Limits) InitError!Storage { const capacity = try Capacity.derive(limits); const bytes = try allocator.alloc(u8, capacity.storage_bytes); return .{ .phase = .initialization, .capacity = capacity, .bytes = bytes, .lines = bytes[capacity.line_offset..][0..capacity.line_storage_bytes], .paths = bytes[capacity.path_offset..][0..capacity.path_storage_bytes], }; } pub fn activate(self: *Storage) void { std.debug.assert(self.phase == .initialization); std.debug.assert(self.bytes.len == self.capacity.storage_bytes); self.phase = .steady; } pub fn acquire(self: *Storage) Storage.Exhaustion!void { std.debug.assert(self.phase == .steady); if (self.in_use) return error.ComposeScratchInUse; self.in_use = true; } pub fn reset(self: *Storage) void { std.debug.assert(self.phase == .steady); std.debug.assert(self.in_use); self.in_use = false; } pub fn fileLine(self: *Storage, depth: usize) []u8 { std.debug.assert(self.in_use); std.debug.assert(depth < capacity_mod.file_line_slot_count); return self.lineSlot(depth); } pub fn registryLine(self: *Storage) []u8 { std.debug.assert(self.in_use); return self.lineSlot(capacity_mod.registry_line_slot_index); } pub fn filePath(self: *Storage, depth: usize) []u8 { std.debug.assert(self.in_use); std.debug.assert(depth < capacity_mod.file_path_slot_count); return self.pathSlot(depth); } pub fn auxiliaryPath(self: *Storage, index: usize) []u8 { std.debug.assert(self.in_use); std.debug.assert(index < capacity_mod.auxiliary_path_slot_count); return self.pathSlot(capacity_mod.file_path_slot_count + index); } pub fn lineLimit(self: *const Storage) usize { return self.capacity.limits.line_bytes; } pub fn status(self: *const Storage) Status { return .{ .phase = self.phase, .in_use = self.in_use, .storage_bytes = self.capacity.storage_bytes, .line_bytes = self.capacity.limits.line_bytes, .path_bytes = self.capacity.limits.path_bytes, }; } pub fn deinit(self: *Storage, allocator: std.mem.Allocator) void { std.debug.assert(self.phase != .teardown); std.debug.assert(!self.in_use); std.debug.assert(self.bytes.len == self.capacity.storage_bytes); self.phase = .teardown; allocator.free(self.bytes); self.bytes = &.{}; self.lines = &.{}; self.paths = &.{}; } fn lineSlot(self: *Storage, index: usize) []u8 { const width = self.capacity.line_bytes_per_slot; const start = index * width; return self.lines[start..][0..width]; } fn pathSlot(self: *Storage, index: usize) []u8 { const width = self.capacity.limits.path_bytes; const start = index * width; return self.paths[start..][0..width]; }};Source: lib/xkb/src/compose/workspace/storage.zig:5
pub const StorageExhaustion = error{ ComposeScratchInUse, LineByteCapacityExceeded, PathByteCapacityExceeded,};Source: lib/xkb/src/compose/load.zig:4
pub const Error = compose.ParseError || compose.Storage.AcquireError || compose.ScratchStorage.AcquireError || error{ComposeFileNotFound};Source: lib/xkb/src/compose/load.zig:37
pub fn compile( storage: *compose.Storage, scratch_storage: *compose.ScratchStorage, input: []const u8, options: Options,) Error!compose.Table { try scratch_storage.acquire(); defer scratch_storage.reset(); return compileSource(storage, scratch_storage, input, "(buffer)", options);}Source: lib/xkb/src/compose/load.zig:48
pub fn load( storage: *compose.Storage, scratch_storage: *compose.ScratchStorage, options: Options,) Error!compose.Table { try scratch_storage.acquire(); defer scratch_storage.reset(); if (options.xcompose_file) |file_path| { if (file_path.len != 0) { if (try loadCandidate(storage, scratch_storage, file_path, options)) |table| { return table; } } } if (try compose.xdgPath( scratch_storage.filePath(0), options.pathOptions(), )) |file_path| { if (try loadCandidate(storage, scratch_storage, file_path, options)) |table| { return table; } } if (try compose.homePath( scratch_storage.filePath(0), options.pathOptions(), )) |file_path| { if (try loadCandidate(storage, scratch_storage, file_path, options)) |table| { return table; } } const locale_path = try compose.localePath( scratch_storage, scratch_storage.filePath(0), options.pathOptions(), ); return (try loadCandidate(storage, scratch_storage, locale_path, options)) orelse error.ComposeFileNotFound;}Source: lib/xkb/src/compose/parser.zig:21
pub const DiagnosticFn = *const fn (context: *anyopaque, diagnostic: Diagnostic) void;Source: lib/xkb/src/compose/parser.zig:23
pub const Error = std.Io.File.OpenError || std.Io.File.StatError || std.Io.File.Reader.Error || compose.Exhaustion || compose.ScratchExhaustion || error{ StreamTooLong, InvalidEncoding, TooManyErrors, InvalidSyntax, UnknownKeysym, SequenceTooLong, OutputTooLong, InvalidUtf8, InvalidIncludeExpansion, MissingHome, LocaleUnavailable, InvalidFileKind, IncludeDepthExceeded,};Source: lib/xkb/src/compose/parser.zig:46
pub fn parse( storage: *compose.Storage, scratch_storage: *compose.ScratchStorage, input: []const u8, source: []const u8, options: Options, include_depth: usize,) Error!void { if (!std.unicode.utf8ValidateSlice(input)) return error.InvalidEncoding; const content = if (std.mem.startsWith(u8, input, "\xef\xbb\xbf")) input[3..] else input; if (content.len >= 2 and (content[0] == 0 or content[1] == 0 or !std.ascii.isAscii(content[0]))) { return error.InvalidEncoding; } var error_count: usize = 0; var lines = std.mem.splitScalar(u8, content, '\n'); var line_number: usize = 0; while (lines.next()) |raw_line| { line_number += 1; if (raw_line.len > scratch_storage.lineLimit()) { return error.LineByteCapacityExceeded; } try parseRecovering( storage, scratch_storage, std.mem.trimEnd(u8, raw_line, "\r"), source, line_number, options, include_depth, &error_count, ); }}Source: lib/xkb/src/compose/parser.zig:83
pub fn parseOpenedFile( storage: *compose.Storage, scratch_storage: *compose.ScratchStorage, file: std.Io.File, file_bytes: u64, source: []const u8, options: Options, include_depth: usize,) Error!void { if (file_bytes >= compose.max_file_bytes) return error.StreamTooLong; var reader = file.reader(options.paths.io, scratch_storage.fileLine(include_depth)); var error_count: usize = 0; var line_number: usize = 0; while (true) { const raw_line = reader.interface.takeDelimiter('\n') catch |err| switch (err) { error.ReadFailed => return reader.err.?, error.StreamTooLong => return error.LineByteCapacityExceeded, } orelse return; if (raw_line.len > scratch_storage.lineLimit()) { return error.LineByteCapacityExceeded; } line_number += 1; if (!std.unicode.utf8ValidateSlice(raw_line)) return error.InvalidEncoding; const content = if (line_number == 1 and std.mem.startsWith(u8, raw_line, "\xef\xbb\xbf")) raw_line[3..] else raw_line; if (line_number == 1 and content.len >= 2 and (content[0] == 0 or content[1] == 0 or !std.ascii.isAscii(content[0]))) { return error.InvalidEncoding; } try parseRecovering( storage, scratch_storage, std.mem.trimEnd(u8, content, "\r"), source, line_number, options, include_depth, &error_count, ); }}Source: lib/xkb/src/compose/path.zig:4
pub const default_system_directory = "/usr/share/X11/locale";Source: lib/xkb/src/compose/path.zig:35
pub fn expandInclude( storage: *scratch.Storage, output: []u8, options: Options, input: []const u8,) ![]const u8 { var builder = Builder.init(output); var index: usize = 0; while (index < input.len) { if (input[index] != '%') { try builder.appendByte(input[index]); index += 1; continue; } if (index + 1 >= input.len) return error.InvalidIncludeExpansion; switch (input[index + 1]) { '%' => try builder.appendByte('%'), 'H' => try builder.append(options.home orelse return error.MissingHome), 'S' => try builder.append(options.system_directory), 'L' => try builder.append(try localeValue(storage, options)), else => return error.InvalidIncludeExpansion, } index += 2; } return builder.value();}Source: lib/xkb/src/compose/path.zig:26
pub fn home(output: []u8, options: Options) !?[]const u8 { const directory = options.home orelse return null; return try join(output, &.{ directory, ".XCompose" });}Source: lib/xkb/src/compose/path.zig:31
pub fn locale(storage: *scratch.Storage, output: []u8, options: Options) ![]const u8 { return try copy(output, try localeValue(storage, options));}Source: lib/xkb/src/compose/path.zig:16
pub fn xdg(output: []u8, options: Options) !?[]const u8 { if (options.xdg_config_home) |directory| { if (std.fs.path.isAbsolute(directory)) { return try join(output, &.{ directory, "XCompose" }); } } const home_directory = options.home orelse return null; return try join(output, &.{ home_directory, ".config", "XCompose" });}Source: lib/xkb/src/compose/table.zig:8
pub const max_nodes = 1 << 23;Source: lib/xkb/src/compose/table.zig:7
pub const max_output_bytes = 255;Source: lib/xkb/src/compose/table.zig:6
pub const max_sequence_length = 10;Source: lib/xkb/src/compose/workspace/capacity.zig:19
pub const default_limits = Limits{ .line_bytes = 256, .path_bytes = max_path_bytes,};Source: lib/xkb/src/compose/workspace/capacity.zig:4
pub const max_file_bytes: usize = 16 * 1024 * 1024;Source: lib/xkb/src/compose/workspace/capacity.zig:3
pub const max_include_depth: usize = 5;Source: lib/xkb/src/compose/workspace/capacity.zig:6
pub const max_path_bytes: usize = 4096;Source: lib/xkb/src/compose/workspace/capacity.zig:5
pub const max_registry_bytes: usize = 8 * 1024 * 1024;Source: lib/xkb/src/compose/root.zig
const table = @import("table.zig");const capacity = @import("capacity.zig");const storage = @import("storage.zig");const scratch = @import("workspace/root.zig");const path = @import("path.zig");const parser = @import("parser.zig");const loading = @import("load.zig");const state = @import("state.zig");pub const max_sequence_length = table.max_sequence_length;pub const max_output_bytes = table.max_output_bytes;pub const max_nodes = table.max_nodes;pub const max_include_depth = scratch.max_include_depth;pub const max_file_bytes = scratch.max_file_bytes;pub const max_registry_bytes = scratch.max_registry_bytes;pub const max_path_bytes = scratch.max_path_bytes;pub const default_system_directory = path.default_system_directory;pub const default_scratch_limits = scratch.default_limits;pub const Result = table.Result;pub const Entry = table.Entry;pub const Table = table.Table;pub const View = table.View;pub const Iterator = table.Iterator;pub const Limits = capacity.Limits;pub const Capacity = capacity.Capacity;pub const Storage = storage.Storage;pub const StorageStatus = storage.Status;pub const Exhaustion = storage.StorageExhaustion;pub const ScratchLimits = scratch.Limits;pub const ScratchCapacity = scratch.Capacity;pub const ScratchStorage = scratch.Storage;pub const ScratchStatus = scratch.Status;pub const ScratchExhaustion = scratch.Exhaustion;pub const PathOptions = path.Options;pub const xdgPath = path.xdg;pub const homePath = path.home;pub const localePath = path.locale;pub const expandInclude = path.expandInclude;pub const DiagnosticCode = parser.DiagnosticCode;pub const Diagnostic = parser.Diagnostic;pub const DiagnosticFn = parser.DiagnosticFn;pub const ParserOptions = parser.Options;pub const ParseError = parser.Error;pub const parse = parser.parse;pub const parseOpenedFile = parser.parseOpenedFile;pub const Options = loading.Options;pub const LoadError = loading.Error;pub const compile = loading.compile;pub const load = loading.load;pub const Status = state.Status;pub const FeedResult = state.FeedResult;pub const TextError = state.TextError;pub const State = state.State;Source: lib/xkb/src/root.zig:53
pub const compose = @import("compose/root.zig");Audit
| Definitions | 93 |
|---|---|
| Public names | 93 |
| Members | 107 |
| Version | 26.7.0 |
| Revision | daab053ee433 |