diff options
Diffstat (limited to 'src/paths.zig')
-rw-r--r-- | src/paths.zig | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/src/paths.zig b/src/paths.zig new file mode 100644 index 0000000..b64ff04 --- /dev/null +++ b/src/paths.zig @@ -0,0 +1,125 @@ +const std = @import("std"); +const Allocator = std.mem.Allocator; +const ArrayList = std.ArrayList; + +pub fn formatDosPath(allocator: Allocator, path: []const u8) ![]const u8 { + var result = ArrayList(u8).init(allocator); + defer result.deinit(); + + // Convert path to DOS format with uppercase drive letter and backslashes + var converted_path = ArrayList(u8).init(allocator); + defer converted_path.deinit(); + + for (path) |ch| { + if (ch == '/') { + try converted_path.append('\\'); + } else { + try converted_path.append(std.ascii.toUpper(ch)); + } + } + + // Split into components and convert each to 8.3 format + var it = std.mem.splitScalar(u8, converted_path.items, '\\'); + var first = true; + + while (it.next()) |component| { + if (component.len == 0) continue; + + if (!first) { + try result.append('\\'); + } + first = false; + + // Convert component to 8.3 format + const short_name = try convertTo83(allocator, component); + defer allocator.free(short_name); + try result.appendSlice(short_name); + } + + // Ensure it starts with a drive letter if it's an absolute path + if (result.items.len == 0 or (result.items.len >= 1 and result.items[0] == '\\')) { + var prefixed = ArrayList(u8).init(allocator); + defer prefixed.deinit(); + try prefixed.appendSlice("C:"); + if (result.items.len > 0 and result.items[0] != '\\') { + try prefixed.append('\\'); + } + try prefixed.appendSlice(result.items); + return allocator.dupe(u8, prefixed.items); + } + + return allocator.dupe(u8, result.items); +} + +pub fn convertTo83(allocator: Allocator, filename: []const u8) ![]const u8 { + // Handle special directories + if (std.mem.eql(u8, filename, ".") or std.mem.eql(u8, filename, "..")) { + return allocator.dupe(u8, filename); + } + + // Handle drive letters (like C:) + if (filename.len == 2 and filename[1] == ':') { + return allocator.dupe(u8, filename); + } + + // Split filename and extension + var name_part: []const u8 = filename; + var ext_part: []const u8 = ""; + + if (std.mem.lastIndexOf(u8, filename, ".")) |dot_pos| { + if (dot_pos > 0) { // Don't treat leading dot as extension separator + name_part = filename[0..dot_pos]; + ext_part = filename[dot_pos + 1 ..]; + } + } + + // Clean name part (remove spaces and invalid chars, convert to uppercase) + var clean_name = ArrayList(u8).init(allocator); + defer clean_name.deinit(); + + for (name_part) |ch| { + if (std.ascii.isAlphanumeric(ch)) { + try clean_name.append(std.ascii.toUpper(ch)); + } else if (ch == '-' or ch == '_') { + try clean_name.append(ch); + } + // Skip spaces and other invalid characters + } + + // Clean extension part (max 3 chars, uppercase) + var clean_ext = ArrayList(u8).init(allocator); + defer clean_ext.deinit(); + + for (ext_part) |ch| { + if (clean_ext.items.len >= 3) break; + if (std.ascii.isAlphanumeric(ch)) { + try clean_ext.append(std.ascii.toUpper(ch)); + } + } + + // Build 8.3 filename + var result = ArrayList(u8).init(allocator); + defer result.deinit(); + + if (clean_name.items.len <= 8 and clean_ext.items.len <= 3) { + // Name fits in 8.3, use as-is + try result.appendSlice(clean_name.items); + if (clean_ext.items.len > 0) { + try result.append('.'); + try result.appendSlice(clean_ext.items); + } + } else { + // Need to abbreviate with ~1 + const max_name_len = if (clean_name.items.len > 6) 6 else clean_name.items.len; + try result.appendSlice(clean_name.items[0..max_name_len]); + try result.appendSlice("~1"); + + if (clean_ext.items.len > 0) { + try result.append('.'); + const max_ext_len = if (clean_ext.items.len > 3) 3 else clean_ext.items.len; + try result.appendSlice(clean_ext.items[0..max_ext_len]); + } + } + + return allocator.dupe(u8, result.items); +} |