module: Consolidate directory prefix scanning
a7dcdcfb69b8e5422d91abf61e8c589d8308337046e65c4dfef0798f137626c3
Directory length and basename start identify the same path boundary. Use one separator scan for both and retain the directory length already calculated when a module entry is allocated. Assisted-by: Codex:gpt-6-astra
1 parent
45c563a2
lib/std/lang/module.rad
+5 -22
| 147 | 147 | return child.id; |
|
| 148 | 148 | } |
|
| 149 | 149 | // Inherit packageId from parent. |
|
| 150 | 150 | let m = try allocModule(graph, parent.packageId, name, filePath); |
|
| 151 | 151 | ||
| 152 | - | set m.dirLen = dirLength(m.filePath); |
|
| 153 | 152 | set m.state = ModuleState::Registered; |
|
| 154 | 153 | set m.parent = parentId; |
|
| 155 | 154 | ||
| 156 | 155 | // Inherit path prefix from parent. |
|
| 157 | 156 | for p in moduleQualifiedPath(parent) { |
| 367 | 366 | fn isValidId(graph: *ModuleGraph, id: u16) -> bool { |
|
| 368 | 367 | return (id as u32) < graph.entriesLen; |
|
| 369 | 368 | } |
|
| 370 | 369 | ||
| 371 | 370 | /// Return the length of the directory prefix for `path`. |
|
| 371 | + | /// Return zero if the path has no separator. |
|
| 372 | 372 | fn dirLength(path: *[u8]) -> u32 { |
|
| 373 | - | if path.len == 0 { |
|
| 374 | - | return 0; |
|
| 375 | - | } |
|
| 376 | - | let mut last: i32 = -1; |
|
| 373 | + | let mut start: u32 = 0; |
|
| 377 | 374 | for i in 0..path.len { |
|
| 378 | 375 | if path[i] == PATH_SEP { |
|
| 379 | - | set last = i as i32; |
|
| 376 | + | set start = i + 1; |
|
| 380 | 377 | } |
|
| 381 | 378 | } |
|
| 382 | - | if last < 0 { |
|
| 383 | - | return 0; |
|
| 384 | - | } |
|
| 385 | - | return (last as u32) + 1; |
|
| 379 | + | return start; |
|
| 386 | 380 | } |
|
| 387 | 381 | ||
| 388 | 382 | /// Produce a subslice for the basename of `path` (without extension). |
|
| 389 | 383 | fn basenameSlice(path: *[u8]) -> *[u8] throws (ModuleError) { |
|
| 390 | - | let start = basenameStart(path); |
|
| 384 | + | let start = dirLength(path); |
|
| 391 | 385 | let withoutExt = trimExtension(path) else { |
|
| 392 | 386 | throw ModuleError::InvalidPath; |
|
| 393 | 387 | }; |
|
| 394 | 388 | return &withoutExt[start..]; |
|
| 395 | 389 | } |
|
| 396 | 390 | ||
| 397 | - | /// Find the byte offset immediately following the last separator. |
|
| 398 | - | fn basenameStart(path: *[u8]) -> u32 { |
|
| 399 | - | let mut start: u32 = 0; |
|
| 400 | - | for i in 0..path.len { |
|
| 401 | - | if path[i] == PATH_SEP { |
|
| 402 | - | set start = i + 1; |
|
| 403 | - | } |
|
| 404 | - | } |
|
| 405 | - | return start; |
|
| 406 | - | } |
|
| 407 | - | ||
| 408 | 391 | /// Trim the `.rad` extension from `path` if present. |
|
| 409 | 392 | /// Returns the path slice without the extension. |
|
| 410 | 393 | export fn trimExtension(path: *[u8]) -> ?*[u8] { |
|
| 411 | 394 | if path.len < SOURCE_EXT.len { |
|
| 412 | 395 | return nil; |