1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
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.name);
defer allocator.free(short_name.ext);
try result.appendSlice(short_name.name);
if (short_name.ext.len > 0) {
try result.append('.');
try result.appendSlice(short_name.ext);
}
}
// 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) !struct { name: []const u8, ext: []const u8 } {
// Handle special directories
if (std.mem.eql(u8, filename, ".") or std.mem.eql(u8, filename, "..")) {
return .{ .name = try allocator.dupe(u8, filename), .ext = try allocator.dupe(u8, "") };
}
// Handle drive letters (like C:)
if (filename.len == 2 and filename[1] == ':') {
return .{ .name = try allocator.dupe(u8, filename), .ext = try allocator.dupe(u8, "") };
}
// 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));
}
}
var name_result = ArrayList(u8).init(allocator);
defer name_result.deinit();
var ext_result = ArrayList(u8).init(allocator);
defer ext_result.deinit();
// Build 8.3 filename
if (clean_name.items.len <= 8 and clean_ext.items.len <= 3) {
// Name fits in 8.3, use as-is
try name_result.appendSlice(clean_name.items);
try ext_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 name_result.appendSlice(clean_name.items[0..max_name_len]);
try name_result.appendSlice("~1");
if (clean_ext.items.len > 0) {
const max_ext_len = if (clean_ext.items.len > 3) 3 else clean_ext.items.len;
try ext_result.appendSlice(clean_ext.items[0..max_ext_len]);
}
}
return .{ .name = try allocator.dupe(u8, name_result.items), .ext = try allocator.dupe(u8, ext_result.items) };
}
|