mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 05:44:20 +00:00
Merge pull request #25351 from ziglang/chomp
std.mem: introduce cut functions; rename "index of" to "find"
This commit is contained in:
commit
3b365a1f9b
2 changed files with 327 additions and 203 deletions
291
lib/std/mem.zig
291
lib/std/mem.zig
|
|
@ -806,9 +806,12 @@ fn eqlBytes(a: []const u8, b: []const u8) bool {
|
|||
return !Scan.isNotEqual(last_a_chunk, last_b_chunk);
|
||||
}
|
||||
|
||||
/// Deprecated in favor of `findDiff`.
|
||||
pub const indexOfDiff = findDiff;
|
||||
|
||||
/// Compares two slices and returns the index of the first inequality.
|
||||
/// Returns null if the slices are equal.
|
||||
pub fn indexOfDiff(comptime T: type, a: []const T, b: []const T) ?usize {
|
||||
pub fn findDiff(comptime T: type, a: []const T, b: []const T) ?usize {
|
||||
const shortest = @min(a.len, b.len);
|
||||
if (a.ptr == b.ptr)
|
||||
return if (a.len == b.len) null else shortest;
|
||||
|
|
@ -817,12 +820,12 @@ pub fn indexOfDiff(comptime T: type, a: []const T, b: []const T) ?usize {
|
|||
return if (a.len == b.len) null else shortest;
|
||||
}
|
||||
|
||||
test indexOfDiff {
|
||||
try testing.expectEqual(indexOfDiff(u8, "one", "one"), null);
|
||||
try testing.expectEqual(indexOfDiff(u8, "one two", "one"), 3);
|
||||
try testing.expectEqual(indexOfDiff(u8, "one", "one two"), 3);
|
||||
try testing.expectEqual(indexOfDiff(u8, "one twx", "one two"), 6);
|
||||
try testing.expectEqual(indexOfDiff(u8, "xne", "one"), 0);
|
||||
test findDiff {
|
||||
try testing.expectEqual(findDiff(u8, "one", "one"), null);
|
||||
try testing.expectEqual(findDiff(u8, "one two", "one"), 3);
|
||||
try testing.expectEqual(findDiff(u8, "one", "one two"), 3);
|
||||
try testing.expectEqual(findDiff(u8, "one twx", "one two"), 6);
|
||||
try testing.expectEqual(findDiff(u8, "xne", "one"), 0);
|
||||
}
|
||||
|
||||
/// Takes a sentinel-terminated pointer and returns a slice preserving pointer attributes.
|
||||
|
|
@ -1014,7 +1017,7 @@ fn lenSliceTo(ptr: anytype, comptime end: std.meta.Elem(@TypeOf(ptr))) usize {
|
|||
return indexOfSentinel(array_info.child, end, ptr);
|
||||
}
|
||||
}
|
||||
return indexOfScalar(array_info.child, ptr, end) orelse array_info.len;
|
||||
return findScalar(array_info.child, ptr, end) orelse array_info.len;
|
||||
},
|
||||
else => {},
|
||||
},
|
||||
|
|
@ -1039,7 +1042,7 @@ fn lenSliceTo(ptr: anytype, comptime end: std.meta.Elem(@TypeOf(ptr))) usize {
|
|||
return indexOfSentinel(ptr_info.child, s, ptr);
|
||||
}
|
||||
}
|
||||
return indexOfScalar(ptr_info.child, ptr, end) orelse ptr.len;
|
||||
return findScalar(ptr_info.child, ptr, end) orelse ptr.len;
|
||||
},
|
||||
},
|
||||
else => {},
|
||||
|
|
@ -1109,9 +1112,12 @@ test len {
|
|||
try testing.expect(len(c_ptr) == 2);
|
||||
}
|
||||
|
||||
/// Deprecated in favor of `findSentinel`.
|
||||
pub const indexOfSentinel = findSentinel;
|
||||
|
||||
/// Returns the index of the sentinel value in a sentinel-terminated pointer.
|
||||
/// Linear search through memory until the sentinel is found.
|
||||
pub fn indexOfSentinel(comptime T: type, comptime sentinel: T, p: [*:sentinel]const T) usize {
|
||||
pub fn findSentinel(comptime T: type, comptime sentinel: T, p: [*:sentinel]const T) usize {
|
||||
var i: usize = 0;
|
||||
|
||||
if (use_vectors_for_comparison and
|
||||
|
|
@ -1223,7 +1229,7 @@ pub fn allEqual(comptime T: type, slice: []const T, scalar: T) bool {
|
|||
/// Remove a set of values from the beginning of a slice.
|
||||
pub fn trimStart(comptime T: type, slice: []const T, values_to_strip: []const T) []const T {
|
||||
var begin: usize = 0;
|
||||
while (begin < slice.len and indexOfScalar(T, values_to_strip, slice[begin]) != null) : (begin += 1) {}
|
||||
while (begin < slice.len and findScalar(T, values_to_strip, slice[begin]) != null) : (begin += 1) {}
|
||||
return slice[begin..];
|
||||
}
|
||||
|
||||
|
|
@ -1237,7 +1243,7 @@ pub const trimLeft = trimStart;
|
|||
/// Remove a set of values from the end of a slice.
|
||||
pub fn trimEnd(comptime T: type, slice: []const T, values_to_strip: []const T) []const T {
|
||||
var end: usize = slice.len;
|
||||
while (end > 0 and indexOfScalar(T, values_to_strip, slice[end - 1]) != null) : (end -= 1) {}
|
||||
while (end > 0 and findScalar(T, values_to_strip, slice[end - 1]) != null) : (end -= 1) {}
|
||||
return slice[0..end];
|
||||
}
|
||||
|
||||
|
|
@ -1252,8 +1258,8 @@ pub const trimRight = trimEnd;
|
|||
pub fn trim(comptime T: type, slice: []const T, values_to_strip: []const T) []const T {
|
||||
var begin: usize = 0;
|
||||
var end: usize = slice.len;
|
||||
while (begin < end and indexOfScalar(T, values_to_strip, slice[begin]) != null) : (begin += 1) {}
|
||||
while (end > begin and indexOfScalar(T, values_to_strip, slice[end - 1]) != null) : (end -= 1) {}
|
||||
while (begin < end and findScalar(T, values_to_strip, slice[begin]) != null) : (begin += 1) {}
|
||||
while (end > begin and findScalar(T, values_to_strip, slice[end - 1]) != null) : (end -= 1) {}
|
||||
return slice[begin..end];
|
||||
}
|
||||
|
||||
|
|
@ -1262,13 +1268,19 @@ test trim {
|
|||
try testing.expectEqualSlices(u8, "foo", trim(u8, "foo", " \n"));
|
||||
}
|
||||
|
||||
/// Deprecated in favor of `findScalar`.
|
||||
pub const indexOfScalar = findScalar;
|
||||
|
||||
/// Linear search for the index of a scalar value inside a slice.
|
||||
pub fn indexOfScalar(comptime T: type, slice: []const T, value: T) ?usize {
|
||||
pub fn findScalar(comptime T: type, slice: []const T, value: T) ?usize {
|
||||
return indexOfScalarPos(T, slice, 0, value);
|
||||
}
|
||||
|
||||
/// Deprecated in favor of `findScalarLast`.
|
||||
pub const lastIndexOfScalar = findScalarLast;
|
||||
|
||||
/// Linear search for the last index of a scalar value inside a slice.
|
||||
pub fn lastIndexOfScalar(comptime T: type, slice: []const T, value: T) ?usize {
|
||||
pub fn findScalarLast(comptime T: type, slice: []const T, value: T) ?usize {
|
||||
var i: usize = slice.len;
|
||||
while (i != 0) {
|
||||
i -= 1;
|
||||
|
|
@ -1277,9 +1289,12 @@ pub fn lastIndexOfScalar(comptime T: type, slice: []const T, value: T) ?usize {
|
|||
return null;
|
||||
}
|
||||
|
||||
/// Deprecated in favor of `findScalarPos`.
|
||||
pub const indexOfScalarPos = findScalarPos;
|
||||
|
||||
/// Linear search for the index of a scalar value inside a slice, starting from a given position.
|
||||
/// Returns null if the value is not found.
|
||||
pub fn indexOfScalarPos(comptime T: type, slice: []const T, start_index: usize, value: T) ?usize {
|
||||
pub fn findScalarPos(comptime T: type, slice: []const T, start_index: usize, value: T) ?usize {
|
||||
if (start_index >= slice.len) return null;
|
||||
|
||||
var i: usize = start_index;
|
||||
|
|
@ -1355,15 +1370,21 @@ test indexOfScalarPos {
|
|||
}
|
||||
}
|
||||
|
||||
/// Deprecated in favor of `findAny`.
|
||||
pub const indexOfAny = findAny;
|
||||
|
||||
/// Linear search for the index of any value in the provided list inside a slice.
|
||||
/// Returns null if no values are found.
|
||||
pub fn indexOfAny(comptime T: type, slice: []const T, values: []const T) ?usize {
|
||||
pub fn findAny(comptime T: type, slice: []const T, values: []const T) ?usize {
|
||||
return indexOfAnyPos(T, slice, 0, values);
|
||||
}
|
||||
|
||||
/// Deprecated in favor of `findLastAny`.
|
||||
pub const lastIndexOfAny = findLastAny;
|
||||
|
||||
/// Linear search for the last index of any value in the provided list inside a slice.
|
||||
/// Returns null if no values are found.
|
||||
pub fn lastIndexOfAny(comptime T: type, slice: []const T, values: []const T) ?usize {
|
||||
pub fn findLastAny(comptime T: type, slice: []const T, values: []const T) ?usize {
|
||||
var i: usize = slice.len;
|
||||
while (i != 0) {
|
||||
i -= 1;
|
||||
|
|
@ -1374,9 +1395,12 @@ pub fn lastIndexOfAny(comptime T: type, slice: []const T, values: []const T) ?us
|
|||
return null;
|
||||
}
|
||||
|
||||
/// Deprecated in favor of `findAnyPos`.
|
||||
pub const indexOfAnyPos = findAnyPos;
|
||||
|
||||
/// Linear search for the index of any value in the provided list inside a slice, starting from a given position.
|
||||
/// Returns null if no values are found.
|
||||
pub fn indexOfAnyPos(comptime T: type, slice: []const T, start_index: usize, values: []const T) ?usize {
|
||||
pub fn findAnyPos(comptime T: type, slice: []const T, start_index: usize, values: []const T) ?usize {
|
||||
if (start_index >= slice.len) return null;
|
||||
for (slice[start_index..], start_index..) |c, i| {
|
||||
for (values) |value| {
|
||||
|
|
@ -1386,17 +1410,34 @@ pub fn indexOfAnyPos(comptime T: type, slice: []const T, start_index: usize, val
|
|||
return null;
|
||||
}
|
||||
|
||||
/// Deprecated in favor of `findNone`.
|
||||
pub const indexOfNone = findNone;
|
||||
|
||||
/// Find the first item in `slice` which is not contained in `values`.
|
||||
///
|
||||
/// Comparable to `strspn` in the C standard library.
|
||||
pub fn indexOfNone(comptime T: type, slice: []const T, values: []const T) ?usize {
|
||||
pub fn findNone(comptime T: type, slice: []const T, values: []const T) ?usize {
|
||||
return indexOfNonePos(T, slice, 0, values);
|
||||
}
|
||||
|
||||
test findNone {
|
||||
try testing.expect(findNone(u8, "abc123", "123").? == 0);
|
||||
try testing.expect(findLastNone(u8, "abc123", "123").? == 2);
|
||||
try testing.expect(findNone(u8, "123abc", "123").? == 3);
|
||||
try testing.expect(findLastNone(u8, "123abc", "123").? == 5);
|
||||
try testing.expect(findNone(u8, "123123", "123") == null);
|
||||
try testing.expect(findNone(u8, "333333", "123") == null);
|
||||
|
||||
try testing.expect(indexOfNonePos(u8, "abc123", 3, "321") == null);
|
||||
}
|
||||
|
||||
/// Deprecated in favor of `findLastNone`.
|
||||
pub const lastIndexOfNone = findLastNone;
|
||||
|
||||
/// Find the last item in `slice` which is not contained in `values`.
|
||||
///
|
||||
/// Like `strspn` in the C standard library, but searches from the end.
|
||||
pub fn lastIndexOfNone(comptime T: type, slice: []const T, values: []const T) ?usize {
|
||||
pub fn findLastNone(comptime T: type, slice: []const T, values: []const T) ?usize {
|
||||
var i: usize = slice.len;
|
||||
outer: while (i != 0) {
|
||||
i -= 1;
|
||||
|
|
@ -1408,11 +1449,13 @@ pub fn lastIndexOfNone(comptime T: type, slice: []const T, values: []const T) ?u
|
|||
return null;
|
||||
}
|
||||
|
||||
pub const indexOfNonePos = findNonePos;
|
||||
|
||||
/// Find the first item in `slice[start_index..]` which is not contained in `values`.
|
||||
/// The returned index will be relative to the start of `slice`, and never less than `start_index`.
|
||||
///
|
||||
/// Comparable to `strspn` in the C standard library.
|
||||
pub fn indexOfNonePos(comptime T: type, slice: []const T, start_index: usize, values: []const T) ?usize {
|
||||
pub fn findNonePos(comptime T: type, slice: []const T, start_index: usize, values: []const T) ?usize {
|
||||
if (start_index >= slice.len) return null;
|
||||
outer: for (slice[start_index..], start_index..) |c, i| {
|
||||
for (values) |value| {
|
||||
|
|
@ -1423,29 +1466,24 @@ pub fn indexOfNonePos(comptime T: type, slice: []const T, start_index: usize, va
|
|||
return null;
|
||||
}
|
||||
|
||||
test indexOfNone {
|
||||
try testing.expect(indexOfNone(u8, "abc123", "123").? == 0);
|
||||
try testing.expect(lastIndexOfNone(u8, "abc123", "123").? == 2);
|
||||
try testing.expect(indexOfNone(u8, "123abc", "123").? == 3);
|
||||
try testing.expect(lastIndexOfNone(u8, "123abc", "123").? == 5);
|
||||
try testing.expect(indexOfNone(u8, "123123", "123") == null);
|
||||
try testing.expect(indexOfNone(u8, "333333", "123") == null);
|
||||
|
||||
try testing.expect(indexOfNonePos(u8, "abc123", 3, "321") == null);
|
||||
}
|
||||
/// Deprecated in favor of `find`.
|
||||
pub const indexOf = find;
|
||||
|
||||
/// Search for needle in haystack and return the index of the first occurrence.
|
||||
/// Uses Boyer-Moore-Horspool algorithm on large inputs; linear search on small inputs.
|
||||
/// Returns null if needle is not found.
|
||||
pub fn indexOf(comptime T: type, haystack: []const T, needle: []const T) ?usize {
|
||||
pub fn find(comptime T: type, haystack: []const T, needle: []const T) ?usize {
|
||||
return indexOfPos(T, haystack, 0, needle);
|
||||
}
|
||||
|
||||
/// Deprecated in favor of `findLastLinear`.
|
||||
pub const lastIndexOfLinear = findLastLinear;
|
||||
|
||||
/// Find the index in a slice of a sub-slice, searching from the end backwards.
|
||||
/// To start looking at a different index, slice the haystack first.
|
||||
/// Consider using `lastIndexOf` instead of this, which will automatically use a
|
||||
/// more sophisticated algorithm on larger inputs.
|
||||
pub fn lastIndexOfLinear(comptime T: type, haystack: []const T, needle: []const T) ?usize {
|
||||
pub fn findLastLinear(comptime T: type, haystack: []const T, needle: []const T) ?usize {
|
||||
if (needle.len > haystack.len) return null;
|
||||
var i: usize = haystack.len - needle.len;
|
||||
while (true) : (i -= 1) {
|
||||
|
|
@ -1454,9 +1492,11 @@ pub fn lastIndexOfLinear(comptime T: type, haystack: []const T, needle: []const
|
|||
}
|
||||
}
|
||||
|
||||
pub const indexOfPosLinear = findPosLinear;
|
||||
|
||||
/// Consider using `indexOfPos` instead of this, which will automatically use a
|
||||
/// more sophisticated algorithm on larger inputs.
|
||||
pub fn indexOfPosLinear(comptime T: type, haystack: []const T, start_index: usize, needle: []const T) ?usize {
|
||||
pub fn findPosLinear(comptime T: type, haystack: []const T, start_index: usize, needle: []const T) ?usize {
|
||||
if (needle.len > haystack.len) return null;
|
||||
var i: usize = start_index;
|
||||
const end = haystack.len - needle.len;
|
||||
|
|
@ -1466,24 +1506,24 @@ pub fn indexOfPosLinear(comptime T: type, haystack: []const T, start_index: usiz
|
|||
return null;
|
||||
}
|
||||
|
||||
test indexOfPosLinear {
|
||||
try testing.expectEqual(0, indexOfPosLinear(u8, "", 0, ""));
|
||||
try testing.expectEqual(0, indexOfPosLinear(u8, "123", 0, ""));
|
||||
test findPosLinear {
|
||||
try testing.expectEqual(0, findPosLinear(u8, "", 0, ""));
|
||||
try testing.expectEqual(0, findPosLinear(u8, "123", 0, ""));
|
||||
|
||||
try testing.expectEqual(null, indexOfPosLinear(u8, "", 0, "1"));
|
||||
try testing.expectEqual(0, indexOfPosLinear(u8, "1", 0, "1"));
|
||||
try testing.expectEqual(null, indexOfPosLinear(u8, "2", 0, "1"));
|
||||
try testing.expectEqual(1, indexOfPosLinear(u8, "21", 0, "1"));
|
||||
try testing.expectEqual(null, indexOfPosLinear(u8, "222", 0, "1"));
|
||||
try testing.expectEqual(null, findPosLinear(u8, "", 0, "1"));
|
||||
try testing.expectEqual(0, findPosLinear(u8, "1", 0, "1"));
|
||||
try testing.expectEqual(null, findPosLinear(u8, "2", 0, "1"));
|
||||
try testing.expectEqual(1, findPosLinear(u8, "21", 0, "1"));
|
||||
try testing.expectEqual(null, findPosLinear(u8, "222", 0, "1"));
|
||||
|
||||
try testing.expectEqual(null, indexOfPosLinear(u8, "", 0, "12"));
|
||||
try testing.expectEqual(null, indexOfPosLinear(u8, "1", 0, "12"));
|
||||
try testing.expectEqual(null, indexOfPosLinear(u8, "2", 0, "12"));
|
||||
try testing.expectEqual(0, indexOfPosLinear(u8, "12", 0, "12"));
|
||||
try testing.expectEqual(null, indexOfPosLinear(u8, "21", 0, "12"));
|
||||
try testing.expectEqual(1, indexOfPosLinear(u8, "212", 0, "12"));
|
||||
try testing.expectEqual(0, indexOfPosLinear(u8, "122", 0, "12"));
|
||||
try testing.expectEqual(1, indexOfPosLinear(u8, "212112", 0, "12"));
|
||||
try testing.expectEqual(null, findPosLinear(u8, "", 0, "12"));
|
||||
try testing.expectEqual(null, findPosLinear(u8, "1", 0, "12"));
|
||||
try testing.expectEqual(null, findPosLinear(u8, "2", 0, "12"));
|
||||
try testing.expectEqual(0, findPosLinear(u8, "12", 0, "12"));
|
||||
try testing.expectEqual(null, findPosLinear(u8, "21", 0, "12"));
|
||||
try testing.expectEqual(1, findPosLinear(u8, "212", 0, "12"));
|
||||
try testing.expectEqual(0, findPosLinear(u8, "122", 0, "12"));
|
||||
try testing.expectEqual(1, findPosLinear(u8, "212112", 0, "12"));
|
||||
}
|
||||
|
||||
fn boyerMooreHorspoolPreprocessReverse(pattern: []const u8, table: *[256]usize) void {
|
||||
|
|
@ -1512,11 +1552,14 @@ fn boyerMooreHorspoolPreprocess(pattern: []const u8, table: *[256]usize) void {
|
|||
}
|
||||
}
|
||||
|
||||
/// Deprecated in favor of `find`.
|
||||
pub const lastIndexOf = findLast;
|
||||
|
||||
/// Find the index in a slice of a sub-slice, searching from the end backwards.
|
||||
/// To start looking at a different index, slice the haystack first.
|
||||
/// Uses the Reverse Boyer-Moore-Horspool algorithm on large inputs;
|
||||
/// `lastIndexOfLinear` on small inputs.
|
||||
pub fn lastIndexOf(comptime T: type, haystack: []const T, needle: []const T) ?usize {
|
||||
pub fn findLast(comptime T: type, haystack: []const T, needle: []const T) ?usize {
|
||||
if (needle.len > haystack.len) return null;
|
||||
if (needle.len == 0) return haystack.len;
|
||||
|
||||
|
|
@ -1542,8 +1585,11 @@ pub fn lastIndexOf(comptime T: type, haystack: []const T, needle: []const T) ?us
|
|||
return null;
|
||||
}
|
||||
|
||||
/// Deprecated in favor of `findPos`.
|
||||
pub const indexOfPos = findPos;
|
||||
|
||||
/// Uses Boyer-Moore-Horspool algorithm on large inputs; `indexOfPosLinear` on small inputs.
|
||||
pub fn indexOfPos(comptime T: type, haystack: []const T, start_index: usize, needle: []const T) ?usize {
|
||||
pub fn findPos(comptime T: type, haystack: []const T, start_index: usize, needle: []const T) ?usize {
|
||||
if (needle.len > haystack.len) return null;
|
||||
if (needle.len < 2) {
|
||||
if (needle.len == 0) return start_index;
|
||||
|
|
@ -1593,7 +1639,7 @@ test indexOf {
|
|||
try testing.expect(indexOf(u8, "foo foo", "foo").? == 0);
|
||||
try testing.expect(lastIndexOf(u8, "foo foo", "foo").? == 4);
|
||||
try testing.expect(lastIndexOfAny(u8, "boo, cat", "abo").? == 6);
|
||||
try testing.expect(lastIndexOfScalar(u8, "boo", 'o').? == 2);
|
||||
try testing.expect(findScalarLast(u8, "boo", 'o').? == 2);
|
||||
}
|
||||
|
||||
test "indexOf multibyte" {
|
||||
|
|
@ -3079,6 +3125,101 @@ test endsWith {
|
|||
try testing.expect(!endsWith(u8, "Bob", "Bo"));
|
||||
}
|
||||
|
||||
/// If `slice` starts with `prefix`, returns the rest of `slice` starting at `prefix.len`.
|
||||
pub fn cutPrefix(comptime T: type, slice: []const T, prefix: []const T) ?[]const T {
|
||||
return if (startsWith(T, slice, prefix)) slice[prefix.len..] else null;
|
||||
}
|
||||
|
||||
test cutPrefix {
|
||||
try testing.expectEqualStrings("foo", cutPrefix(u8, "--example=foo", "--example=").?);
|
||||
try testing.expectEqual(null, cutPrefix(u8, "--example=foo", "-example="));
|
||||
}
|
||||
|
||||
/// If `slice` ends with `suffix`, returns `slice` from beginning to start of `suffix`.
|
||||
pub fn cutSuffix(comptime T: type, slice: []const T, suffix: []const T) ?[]const T {
|
||||
return if (endsWith(T, slice, suffix)) slice[0 .. slice.len - suffix.len] else null;
|
||||
}
|
||||
|
||||
test cutSuffix {
|
||||
try testing.expectEqualStrings("foo", cutSuffix(u8, "foobar", "bar").?);
|
||||
try testing.expectEqual(null, cutSuffix(u8, "foobar", "baz"));
|
||||
}
|
||||
|
||||
/// Returns slice of `haystack` before and after first occurrence of `needle`,
|
||||
/// or `null` if not found.
|
||||
///
|
||||
/// See also:
|
||||
/// * `cutScalar`
|
||||
/// * `split`
|
||||
/// * `tokenizeAny`
|
||||
pub fn cut(comptime T: type, haystack: []const T, needle: []const T) ?struct { []const T, []const T } {
|
||||
const index = find(T, haystack, needle) orelse return null;
|
||||
return .{ haystack[0..index], haystack[index + needle.len ..] };
|
||||
}
|
||||
|
||||
test cut {
|
||||
try testing.expectEqual(null, cut(u8, "a b c", "B"));
|
||||
const before, const after = cut(u8, "a be c", "be") orelse return error.TestFailed;
|
||||
try testing.expectEqualStrings("a ", before);
|
||||
try testing.expectEqualStrings(" c", after);
|
||||
}
|
||||
|
||||
/// Returns slice of `haystack` before and after last occurrence of `needle`,
|
||||
/// or `null` if not found.
|
||||
///
|
||||
/// See also:
|
||||
/// * `cut`
|
||||
/// * `cutScalarLast`
|
||||
pub fn cutLast(comptime T: type, haystack: []const T, needle: []const T) ?struct { []const T, []const T } {
|
||||
const index = findLast(T, haystack, needle) orelse return null;
|
||||
return .{ haystack[0..index], haystack[index + needle.len ..] };
|
||||
}
|
||||
|
||||
test cutLast {
|
||||
try testing.expectEqual(null, cutLast(u8, "a b c", "B"));
|
||||
const before, const after = cutLast(u8, "a be c be d", "be") orelse return error.TestFailed;
|
||||
try testing.expectEqualStrings("a be c ", before);
|
||||
try testing.expectEqualStrings(" d", after);
|
||||
}
|
||||
|
||||
/// Returns slice of `haystack` before and after first occurrence `needle`, or
|
||||
/// `null` if not found.
|
||||
///
|
||||
/// See also:
|
||||
/// * `cut`
|
||||
/// * `splitScalar`
|
||||
/// * `tokenizeScalar`
|
||||
pub fn cutScalar(comptime T: type, haystack: []const T, needle: T) ?struct { []const T, []const T } {
|
||||
const index = findScalar(T, haystack, needle) orelse return null;
|
||||
return .{ haystack[0..index], haystack[index + 1 ..] };
|
||||
}
|
||||
|
||||
test cutScalar {
|
||||
try testing.expectEqual(null, cutScalar(u8, "a b c", 'B'));
|
||||
const before, const after = cutScalar(u8, "a b c", 'b') orelse return error.TestFailed;
|
||||
try testing.expectEqualStrings("a ", before);
|
||||
try testing.expectEqualStrings(" c", after);
|
||||
}
|
||||
|
||||
/// Returns slice of `haystack` before and after last occurrence of `needle`,
|
||||
/// or `null` if not found.
|
||||
///
|
||||
/// See also:
|
||||
/// * `cut`
|
||||
/// * `splitScalar`
|
||||
/// * `tokenizeScalar`
|
||||
pub fn cutScalarLast(comptime T: type, haystack: []const T, needle: T) ?struct { []const T, []const T } {
|
||||
const index = findScalarLast(T, haystack, needle) orelse return null;
|
||||
return .{ haystack[0..index], haystack[index + 1 ..] };
|
||||
}
|
||||
|
||||
test cutScalarLast {
|
||||
try testing.expectEqual(null, cutScalarLast(u8, "a b c", 'B'));
|
||||
const before, const after = cutScalarLast(u8, "a b c b d", 'b') orelse return error.TestFailed;
|
||||
try testing.expectEqualStrings("a b c ", before);
|
||||
try testing.expectEqualStrings(" d", after);
|
||||
}
|
||||
|
||||
/// Delimiter type for tokenization and splitting operations.
|
||||
pub const DelimiterType = enum { sequence, any, scalar };
|
||||
|
||||
|
|
@ -3248,7 +3389,7 @@ pub fn SplitBackwardsIterator(comptime T: type, comptime delimiter_type: Delimit
|
|||
const start = if (switch (delimiter_type) {
|
||||
.sequence => lastIndexOf(T, self.buffer[0..end], self.delimiter),
|
||||
.any => lastIndexOfAny(T, self.buffer[0..end], self.delimiter),
|
||||
.scalar => lastIndexOfScalar(T, self.buffer[0..end], self.delimiter),
|
||||
.scalar => findScalarLast(T, self.buffer[0..end], self.delimiter),
|
||||
}) |delim_start| blk: {
|
||||
self.index = delim_start;
|
||||
break :blk delim_start + switch (delimiter_type) {
|
||||
|
|
@ -3562,9 +3703,12 @@ test minMax {
|
|||
}
|
||||
}
|
||||
|
||||
/// Deprecated in favor of `findMin`.
|
||||
pub const indexOfMin = findMin;
|
||||
|
||||
/// Returns the index of the smallest number in a slice. O(n).
|
||||
/// `slice` must not be empty.
|
||||
pub fn indexOfMin(comptime T: type, slice: []const T) usize {
|
||||
pub fn findMin(comptime T: type, slice: []const T) usize {
|
||||
assert(slice.len > 0);
|
||||
var best = slice[0];
|
||||
var index: usize = 0;
|
||||
|
|
@ -3577,15 +3721,17 @@ pub fn indexOfMin(comptime T: type, slice: []const T) usize {
|
|||
return index;
|
||||
}
|
||||
|
||||
test indexOfMin {
|
||||
try testing.expectEqual(indexOfMin(u8, "abcdefg"), 0);
|
||||
try testing.expectEqual(indexOfMin(u8, "bcdefga"), 6);
|
||||
try testing.expectEqual(indexOfMin(u8, "a"), 0);
|
||||
test findMin {
|
||||
try testing.expectEqual(findMin(u8, "abcdefg"), 0);
|
||||
try testing.expectEqual(findMin(u8, "bcdefga"), 6);
|
||||
try testing.expectEqual(findMin(u8, "a"), 0);
|
||||
}
|
||||
|
||||
pub const indexOfMax = findMax;
|
||||
|
||||
/// Returns the index of the largest number in a slice. O(n).
|
||||
/// `slice` must not be empty.
|
||||
pub fn indexOfMax(comptime T: type, slice: []const T) usize {
|
||||
pub fn findMax(comptime T: type, slice: []const T) usize {
|
||||
assert(slice.len > 0);
|
||||
var best = slice[0];
|
||||
var index: usize = 0;
|
||||
|
|
@ -3598,16 +3744,19 @@ pub fn indexOfMax(comptime T: type, slice: []const T) usize {
|
|||
return index;
|
||||
}
|
||||
|
||||
test indexOfMax {
|
||||
try testing.expectEqual(indexOfMax(u8, "abcdefg"), 6);
|
||||
try testing.expectEqual(indexOfMax(u8, "gabcdef"), 0);
|
||||
try testing.expectEqual(indexOfMax(u8, "a"), 0);
|
||||
test findMax {
|
||||
try testing.expectEqual(findMax(u8, "abcdefg"), 6);
|
||||
try testing.expectEqual(findMax(u8, "gabcdef"), 0);
|
||||
try testing.expectEqual(findMax(u8, "a"), 0);
|
||||
}
|
||||
|
||||
/// Deprecated in favor of `findMinMax`.
|
||||
pub const indexOfMinMax = findMinMax;
|
||||
|
||||
/// Finds the indices of the smallest and largest number in a slice. O(n).
|
||||
/// Returns the indices of the smallest and largest numbers in that order.
|
||||
/// `slice` must not be empty.
|
||||
pub fn indexOfMinMax(comptime T: type, slice: []const T) struct { usize, usize } {
|
||||
pub fn findMinMax(comptime T: type, slice: []const T) struct { usize, usize } {
|
||||
assert(slice.len > 0);
|
||||
var minVal = slice[0];
|
||||
var maxVal = slice[0];
|
||||
|
|
@ -3626,10 +3775,10 @@ pub fn indexOfMinMax(comptime T: type, slice: []const T) struct { usize, usize }
|
|||
return .{ minIdx, maxIdx };
|
||||
}
|
||||
|
||||
test indexOfMinMax {
|
||||
try testing.expectEqual(.{ 0, 6 }, indexOfMinMax(u8, "abcdefg"));
|
||||
try testing.expectEqual(.{ 1, 0 }, indexOfMinMax(u8, "gabcdef"));
|
||||
try testing.expectEqual(.{ 0, 0 }, indexOfMinMax(u8, "a"));
|
||||
test findMinMax {
|
||||
try testing.expectEqual(.{ 0, 6 }, findMinMax(u8, "abcdefg"));
|
||||
try testing.expectEqual(.{ 1, 0 }, findMinMax(u8, "gabcdef"));
|
||||
try testing.expectEqual(.{ 0, 0 }, findMinMax(u8, "a"));
|
||||
}
|
||||
|
||||
/// Exchanges contents of two memory locations.
|
||||
|
|
|
|||
239
src/main.zig
239
src/main.zig
|
|
@ -1022,10 +1022,9 @@ fn buildOutputType(
|
|||
|
||||
var file_ext: ?Compilation.FileExt = null;
|
||||
args_loop: while (args_iter.next()) |arg| {
|
||||
if (mem.startsWith(u8, arg, "@")) {
|
||||
if (mem.cutPrefix(u8, arg, "@")) |resp_file_path| {
|
||||
// This is a "compiler response file". We must parse the file and treat its
|
||||
// contents as command line parameters.
|
||||
const resp_file_path = arg[1..];
|
||||
args_iter.resp_file = initArgIteratorResponseFile(arena, resp_file_path) catch |err| {
|
||||
fatal("unable to read response file '{s}': {s}", .{ resp_file_path, @errorName(err) });
|
||||
};
|
||||
|
|
@ -1043,9 +1042,8 @@ fn buildOutputType(
|
|||
fatal("unexpected end-of-parameter mark: --", .{});
|
||||
}
|
||||
} else if (mem.eql(u8, arg, "--dep")) {
|
||||
var it = mem.splitScalar(u8, args_iter.nextOrFatal(), '=');
|
||||
const key = it.first();
|
||||
const value = if (it.peek() != null) it.rest() else key;
|
||||
const next_arg = args_iter.nextOrFatal();
|
||||
const key, const value = mem.cutScalar(u8, next_arg, '=') orelse .{ next_arg, next_arg };
|
||||
if (mem.eql(u8, key, "std") and !mem.eql(u8, value, "std")) {
|
||||
fatal("unable to import as '{s}': conflicts with builtin module", .{
|
||||
key,
|
||||
|
|
@ -1062,10 +1060,8 @@ fn buildOutputType(
|
|||
.key = key,
|
||||
.value = value,
|
||||
});
|
||||
} else if (mem.startsWith(u8, arg, "-M")) {
|
||||
var it = mem.splitScalar(u8, arg["-M".len..], '=');
|
||||
const mod_name = it.first();
|
||||
const root_src_orig = if (it.peek() != null) it.rest() else null;
|
||||
} else if (mem.cutPrefix(u8, arg, "-M")) |rest| {
|
||||
const mod_name, const root_src_orig = mem.cutScalar(u8, rest, '=') orelse .{ rest, null };
|
||||
try handleModArg(
|
||||
arena,
|
||||
mod_name,
|
||||
|
|
@ -1096,8 +1092,8 @@ fn buildOutputType(
|
|||
}
|
||||
} else if (mem.eql(u8, arg, "-rcincludes")) {
|
||||
rc_includes = parseRcIncludes(args_iter.nextOrFatal());
|
||||
} else if (mem.startsWith(u8, arg, "-rcincludes=")) {
|
||||
rc_includes = parseRcIncludes(arg["-rcincludes=".len..]);
|
||||
} else if (mem.cutPrefix(u8, arg, "-rcincludes=")) |rest| {
|
||||
rc_includes = parseRcIncludes(rest);
|
||||
} else if (mem.eql(u8, arg, "-rcflags")) {
|
||||
extra_rcflags.shrinkRetainingCapacity(0);
|
||||
while (true) {
|
||||
|
|
@ -1107,9 +1103,9 @@ fn buildOutputType(
|
|||
if (mem.eql(u8, next_arg, "--")) break;
|
||||
try extra_rcflags.append(arena, next_arg);
|
||||
}
|
||||
} else if (mem.startsWith(u8, arg, "-fstructured-cfg")) {
|
||||
} else if (mem.eql(u8, arg, "-fstructured-cfg")) {
|
||||
mod_opts.structured_cfg = true;
|
||||
} else if (mem.startsWith(u8, arg, "-fno-structured-cfg")) {
|
||||
} else if (mem.eql(u8, arg, "-fno-structured-cfg")) {
|
||||
mod_opts.structured_cfg = false;
|
||||
} else if (mem.eql(u8, arg, "--color")) {
|
||||
const next_arg = args_iter.next() orelse {
|
||||
|
|
@ -1118,8 +1114,7 @@ fn buildOutputType(
|
|||
color = std.meta.stringToEnum(Color, next_arg) orelse {
|
||||
fatal("expected [auto|on|off] after --color, found '{s}'", .{next_arg});
|
||||
};
|
||||
} else if (mem.startsWith(u8, arg, "-j")) {
|
||||
const str = arg["-j".len..];
|
||||
} else if (mem.cutPrefix(u8, arg, "-j")) |str| {
|
||||
const num = std.fmt.parseUnsigned(u32, str, 10) catch |err| {
|
||||
fatal("unable to parse jobs count '{s}': {s}", .{
|
||||
str, @errorName(err),
|
||||
|
|
@ -1133,8 +1128,8 @@ fn buildOutputType(
|
|||
subsystem = try parseSubSystem(args_iter.nextOrFatal());
|
||||
} else if (mem.eql(u8, arg, "-O")) {
|
||||
mod_opts.optimize_mode = parseOptimizeMode(args_iter.nextOrFatal());
|
||||
} else if (mem.startsWith(u8, arg, "-fentry=")) {
|
||||
entry = .{ .named = arg["-fentry=".len..] };
|
||||
} else if (mem.cutPrefix(u8, arg, "-fentry=")) |rest| {
|
||||
entry = .{ .named = rest };
|
||||
} else if (mem.eql(u8, arg, "--force_undefined")) {
|
||||
try force_undefined_symbols.put(arena, args_iter.nextOrFatal(), {});
|
||||
} else if (mem.eql(u8, arg, "--discard-all")) {
|
||||
|
|
@ -1161,8 +1156,7 @@ fn buildOutputType(
|
|||
try create_module.frameworks.put(arena, args_iter.nextOrFatal(), .{ .needed = true });
|
||||
} else if (mem.eql(u8, arg, "-install_name")) {
|
||||
install_name = args_iter.nextOrFatal();
|
||||
} else if (mem.startsWith(u8, arg, "--compress-debug-sections=")) {
|
||||
const param = arg["--compress-debug-sections=".len..];
|
||||
} else if (mem.cutPrefix(u8, arg, "--compress-debug-sections=")) |param| {
|
||||
linker_compress_debug_sections = std.meta.stringToEnum(link.File.Lld.Elf.CompressDebugSections, param) orelse {
|
||||
fatal("expected --compress-debug-sections=[none|zlib|zstd], found '{s}'", .{param});
|
||||
};
|
||||
|
|
@ -1260,8 +1254,8 @@ fn buildOutputType(
|
|||
try cc_argv.appendSlice(arena, &.{ arg, args_iter.nextOrFatal() });
|
||||
} else if (mem.eql(u8, arg, "-I")) {
|
||||
try cssan.addIncludePath(arena, &cc_argv, .I, arg, args_iter.nextOrFatal(), false);
|
||||
} else if (mem.startsWith(u8, arg, "--embed-dir=")) {
|
||||
try cssan.addIncludePath(arena, &cc_argv, .embed_dir, arg, arg["--embed-dir=".len..], true);
|
||||
} else if (mem.cutPrefix(u8, arg, "--embed-dir=")) |rest| {
|
||||
try cssan.addIncludePath(arena, &cc_argv, .embed_dir, arg, rest, true);
|
||||
} else if (mem.eql(u8, arg, "-isystem")) {
|
||||
try cssan.addIncludePath(arena, &cc_argv, .isystem, arg, args_iter.nextOrFatal(), false);
|
||||
} else if (mem.eql(u8, arg, "-iwithsysroot")) {
|
||||
|
|
@ -1288,14 +1282,14 @@ fn buildOutputType(
|
|||
target_mcpu = args_iter.nextOrFatal();
|
||||
} else if (mem.eql(u8, arg, "-mcmodel")) {
|
||||
mod_opts.code_model = parseCodeModel(args_iter.nextOrFatal());
|
||||
} else if (mem.startsWith(u8, arg, "-mcmodel=")) {
|
||||
mod_opts.code_model = parseCodeModel(arg["-mcmodel=".len..]);
|
||||
} else if (mem.startsWith(u8, arg, "-ofmt=")) {
|
||||
create_module.object_format = arg["-ofmt=".len..];
|
||||
} else if (mem.startsWith(u8, arg, "-mcpu=")) {
|
||||
target_mcpu = arg["-mcpu=".len..];
|
||||
} else if (mem.startsWith(u8, arg, "-O")) {
|
||||
mod_opts.optimize_mode = parseOptimizeMode(arg["-O".len..]);
|
||||
} else if (mem.cutPrefix(u8, arg, "-mcmodel=")) |rest| {
|
||||
mod_opts.code_model = parseCodeModel(rest);
|
||||
} else if (mem.cutPrefix(u8, arg, "-ofmt=")) |rest| {
|
||||
create_module.object_format = rest;
|
||||
} else if (mem.cutPrefix(u8, arg, "-mcpu=")) |rest| {
|
||||
target_mcpu = rest;
|
||||
} else if (mem.cutPrefix(u8, arg, "-O")) |rest| {
|
||||
mod_opts.optimize_mode = parseOptimizeMode(rest);
|
||||
} else if (mem.eql(u8, arg, "--dynamic-linker")) {
|
||||
create_module.dynamic_linker = args_iter.nextOrFatal();
|
||||
} else if (mem.eql(u8, arg, "--sysroot")) {
|
||||
|
|
@ -1331,9 +1325,7 @@ fn buildOutputType(
|
|||
} else {
|
||||
dev.check(.network_listen);
|
||||
// example: --listen 127.0.0.1:9000
|
||||
var it = std.mem.splitScalar(u8, next_arg, ':');
|
||||
const host = it.next().?;
|
||||
const port_text = it.next() orelse "14735";
|
||||
const host, const port_text = mem.cutScalar(u8, next_arg, ':') orelse .{ next_arg, "14735" };
|
||||
const port = std.fmt.parseInt(u16, port_text, 10) catch |err|
|
||||
fatal("invalid port number: '{s}': {s}", .{ port_text, @errorName(err) });
|
||||
listen = .{ .ip4 = std.net.Ip4Address.parse(host, port) catch |err|
|
||||
|
|
@ -1393,8 +1385,7 @@ fn buildOutputType(
|
|||
create_module.opts.pie = false;
|
||||
} else if (mem.eql(u8, arg, "-flto")) {
|
||||
create_module.opts.lto = .full;
|
||||
} else if (mem.startsWith(u8, arg, "-flto=")) {
|
||||
const mode = arg["-flto=".len..];
|
||||
} else if (mem.cutPrefix(u8, arg, "-flto=")) |mode| {
|
||||
if (mem.eql(u8, mode, "full")) {
|
||||
create_module.opts.lto = .full;
|
||||
} else if (mem.eql(u8, mode, "thin")) {
|
||||
|
|
@ -1428,8 +1419,7 @@ fn buildOutputType(
|
|||
mod_opts.omit_frame_pointer = false;
|
||||
} else if (mem.eql(u8, arg, "-fsanitize-c")) {
|
||||
mod_opts.sanitize_c = .full;
|
||||
} else if (mem.startsWith(u8, arg, "-fsanitize-c=")) {
|
||||
const mode = arg["-fsanitize-c=".len..];
|
||||
} else if (mem.cutPrefix(u8, arg, "-fsanitize-c=")) |mode| {
|
||||
if (mem.eql(u8, mode, "trap")) {
|
||||
mod_opts.sanitize_c = .trap;
|
||||
} else if (mem.eql(u8, mode, "full")) {
|
||||
|
|
@ -1477,8 +1467,7 @@ fn buildOutputType(
|
|||
create_module.opts.san_cov_trace_pc_guard = false;
|
||||
} else if (mem.eql(u8, arg, "-freference-trace")) {
|
||||
reference_trace = 256;
|
||||
} else if (mem.startsWith(u8, arg, "-freference-trace=")) {
|
||||
const num = arg["-freference-trace=".len..];
|
||||
} else if (mem.cutPrefix(u8, arg, "-freference-trace=")) |num| {
|
||||
reference_trace = std.fmt.parseUnsigned(u32, num, 10) catch |err| {
|
||||
fatal("unable to parse reference_trace count '{s}': {s}", .{ num, @errorName(err) });
|
||||
};
|
||||
|
|
@ -1492,51 +1481,51 @@ fn buildOutputType(
|
|||
create_module.opts.rdynamic = true;
|
||||
} else if (mem.eql(u8, arg, "-fsoname")) {
|
||||
soname = .yes_default_value;
|
||||
} else if (mem.startsWith(u8, arg, "-fsoname=")) {
|
||||
soname = .{ .yes = arg["-fsoname=".len..] };
|
||||
} else if (mem.cutPrefix(u8, arg, "-fsoname=")) |rest| {
|
||||
soname = .{ .yes = rest };
|
||||
} else if (mem.eql(u8, arg, "-fno-soname")) {
|
||||
soname = .no;
|
||||
} else if (mem.eql(u8, arg, "-femit-bin")) {
|
||||
emit_bin = .yes_default_path;
|
||||
} else if (mem.startsWith(u8, arg, "-femit-bin=")) {
|
||||
emit_bin = .{ .yes = arg["-femit-bin=".len..] };
|
||||
} else if (mem.cutPrefix(u8, arg, "-femit-bin=")) |rest| {
|
||||
emit_bin = .{ .yes = rest };
|
||||
} else if (mem.eql(u8, arg, "-fno-emit-bin")) {
|
||||
emit_bin = .no;
|
||||
} else if (mem.eql(u8, arg, "-femit-h")) {
|
||||
emit_h = .yes_default_path;
|
||||
} else if (mem.startsWith(u8, arg, "-femit-h=")) {
|
||||
emit_h = .{ .yes = arg["-femit-h=".len..] };
|
||||
} else if (mem.cutPrefix(u8, arg, "-femit-h=")) |rest| {
|
||||
emit_h = .{ .yes = rest };
|
||||
} else if (mem.eql(u8, arg, "-fno-emit-h")) {
|
||||
emit_h = .no;
|
||||
} else if (mem.eql(u8, arg, "-femit-asm")) {
|
||||
emit_asm = .yes_default_path;
|
||||
} else if (mem.startsWith(u8, arg, "-femit-asm=")) {
|
||||
emit_asm = .{ .yes = arg["-femit-asm=".len..] };
|
||||
} else if (mem.cutPrefix(u8, arg, "-femit-asm=")) |rest| {
|
||||
emit_asm = .{ .yes = rest };
|
||||
} else if (mem.eql(u8, arg, "-fno-emit-asm")) {
|
||||
emit_asm = .no;
|
||||
} else if (mem.eql(u8, arg, "-femit-llvm-ir")) {
|
||||
emit_llvm_ir = .yes_default_path;
|
||||
} else if (mem.startsWith(u8, arg, "-femit-llvm-ir=")) {
|
||||
emit_llvm_ir = .{ .yes = arg["-femit-llvm-ir=".len..] };
|
||||
} else if (mem.cutPrefix(u8, arg, "-femit-llvm-ir=")) |rest| {
|
||||
emit_llvm_ir = .{ .yes = rest };
|
||||
} else if (mem.eql(u8, arg, "-fno-emit-llvm-ir")) {
|
||||
emit_llvm_ir = .no;
|
||||
} else if (mem.eql(u8, arg, "-femit-llvm-bc")) {
|
||||
emit_llvm_bc = .yes_default_path;
|
||||
} else if (mem.startsWith(u8, arg, "-femit-llvm-bc=")) {
|
||||
emit_llvm_bc = .{ .yes = arg["-femit-llvm-bc=".len..] };
|
||||
} else if (mem.cutPrefix(u8, arg, "-femit-llvm-bc=")) |rest| {
|
||||
emit_llvm_bc = .{ .yes = rest };
|
||||
} else if (mem.eql(u8, arg, "-fno-emit-llvm-bc")) {
|
||||
emit_llvm_bc = .no;
|
||||
} else if (mem.eql(u8, arg, "-femit-docs")) {
|
||||
emit_docs = .yes_default_path;
|
||||
} else if (mem.startsWith(u8, arg, "-femit-docs=")) {
|
||||
emit_docs = .{ .yes = arg["-femit-docs=".len..] };
|
||||
} else if (mem.cutPrefix(u8, arg, "-femit-docs=")) |rest| {
|
||||
emit_docs = .{ .yes = rest };
|
||||
} else if (mem.eql(u8, arg, "-fno-emit-docs")) {
|
||||
emit_docs = .no;
|
||||
} else if (mem.eql(u8, arg, "-femit-implib")) {
|
||||
emit_implib = .yes_default_path;
|
||||
emit_implib_arg_provided = true;
|
||||
} else if (mem.startsWith(u8, arg, "-femit-implib=")) {
|
||||
emit_implib = .{ .yes = arg["-femit-implib=".len..] };
|
||||
} else if (mem.cutPrefix(u8, arg, "-femit-implib=")) |rest| {
|
||||
emit_implib = .{ .yes = rest };
|
||||
emit_implib_arg_provided = true;
|
||||
} else if (mem.eql(u8, arg, "-fno-emit-implib")) {
|
||||
emit_implib = .no;
|
||||
|
|
@ -1586,8 +1575,7 @@ fn buildOutputType(
|
|||
mod_opts.no_builtin = false;
|
||||
} else if (mem.eql(u8, arg, "-fno-builtin")) {
|
||||
mod_opts.no_builtin = true;
|
||||
} else if (mem.startsWith(u8, arg, "-fopt-bisect-limit=")) {
|
||||
const next_arg = arg["-fopt-bisect-limit=".len..];
|
||||
} else if (mem.cutPrefix(u8, arg, "-fopt-bisect-limit=")) |next_arg| {
|
||||
llvm_opt_bisect_limit = std.fmt.parseInt(c_int, next_arg, 0) catch |err|
|
||||
fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
|
||||
} else if (mem.eql(u8, arg, "--eh-frame-hdr")) {
|
||||
|
|
@ -1630,10 +1618,10 @@ fn buildOutputType(
|
|||
linker_z_relro = true;
|
||||
} else if (mem.eql(u8, z_arg, "norelro")) {
|
||||
linker_z_relro = false;
|
||||
} else if (mem.startsWith(u8, z_arg, "common-page-size=")) {
|
||||
linker_z_common_page_size = parseIntSuffix(z_arg, "common-page-size=".len);
|
||||
} else if (mem.startsWith(u8, z_arg, "max-page-size=")) {
|
||||
linker_z_max_page_size = parseIntSuffix(z_arg, "max-page-size=".len);
|
||||
} else if (prefixedIntArg(z_arg, "common-page-size=")) |int| {
|
||||
linker_z_common_page_size = int;
|
||||
} else if (prefixedIntArg(z_arg, "max-page-size=")) |int| {
|
||||
linker_z_max_page_size = int;
|
||||
} else {
|
||||
fatal("unsupported linker extension flag: -z {s}", .{z_arg});
|
||||
}
|
||||
|
|
@ -1654,16 +1642,16 @@ fn buildOutputType(
|
|||
linker_import_table = true;
|
||||
} else if (mem.eql(u8, arg, "--export-table")) {
|
||||
linker_export_table = true;
|
||||
} else if (mem.startsWith(u8, arg, "--initial-memory=")) {
|
||||
linker_initial_memory = parseIntSuffix(arg, "--initial-memory=".len);
|
||||
} else if (mem.startsWith(u8, arg, "--max-memory=")) {
|
||||
linker_max_memory = parseIntSuffix(arg, "--max-memory=".len);
|
||||
} else if (prefixedIntArg(arg, "--initial-memory=")) |int| {
|
||||
linker_initial_memory = int;
|
||||
} else if (prefixedIntArg(arg, "--max-memory=")) |int| {
|
||||
linker_max_memory = int;
|
||||
} else if (mem.eql(u8, arg, "--shared-memory")) {
|
||||
create_module.opts.shared_memory = true;
|
||||
} else if (mem.startsWith(u8, arg, "--global-base=")) {
|
||||
linker_global_base = parseIntSuffix(arg, "--global-base=".len);
|
||||
} else if (mem.startsWith(u8, arg, "--export=")) {
|
||||
try linker_export_symbol_names.append(arena, arg["--export=".len..]);
|
||||
} else if (prefixedIntArg(arg, "--global-base=")) |int| {
|
||||
linker_global_base = int;
|
||||
} else if (mem.cutPrefix(u8, arg, "--export=")) |rest| {
|
||||
try linker_export_symbol_names.append(arena, rest);
|
||||
} else if (mem.eql(u8, arg, "-Bsymbolic")) {
|
||||
linker_bind_global_refs_locally = true;
|
||||
} else if (mem.eql(u8, arg, "--gc-sections")) {
|
||||
|
|
@ -1672,8 +1660,7 @@ fn buildOutputType(
|
|||
linker_gc_sections = false;
|
||||
} else if (mem.eql(u8, arg, "--build-id")) {
|
||||
build_id = .fast;
|
||||
} else if (mem.startsWith(u8, arg, "--build-id=")) {
|
||||
const style = arg["--build-id=".len..];
|
||||
} else if (mem.cutPrefix(u8, arg, "--build-id=")) |style| {
|
||||
build_id = std.zig.BuildId.parse(style) catch |err| {
|
||||
fatal("unable to parse --build-id style '{s}': {s}", .{
|
||||
style, @errorName(err),
|
||||
|
|
@ -1697,26 +1684,26 @@ fn buildOutputType(
|
|||
verbose_generic_instances = true;
|
||||
} else if (mem.eql(u8, arg, "--verbose-llvm-ir")) {
|
||||
verbose_llvm_ir = "-";
|
||||
} else if (mem.startsWith(u8, arg, "--verbose-llvm-ir=")) {
|
||||
verbose_llvm_ir = arg["--verbose-llvm-ir=".len..];
|
||||
} else if (mem.startsWith(u8, arg, "--verbose-llvm-bc=")) {
|
||||
verbose_llvm_bc = arg["--verbose-llvm-bc=".len..];
|
||||
} else if (mem.cutPrefix(u8, arg, "--verbose-llvm-ir=")) |rest| {
|
||||
verbose_llvm_ir = rest;
|
||||
} else if (mem.cutPrefix(u8, arg, "--verbose-llvm-bc=")) |rest| {
|
||||
verbose_llvm_bc = rest;
|
||||
} else if (mem.eql(u8, arg, "--verbose-cimport")) {
|
||||
verbose_cimport = true;
|
||||
} else if (mem.eql(u8, arg, "--verbose-llvm-cpu-features")) {
|
||||
verbose_llvm_cpu_features = true;
|
||||
} else if (mem.startsWith(u8, arg, "-T")) {
|
||||
linker_script = arg[2..];
|
||||
} else if (mem.startsWith(u8, arg, "-L")) {
|
||||
try create_module.lib_dir_args.append(arena, arg[2..]);
|
||||
} else if (mem.startsWith(u8, arg, "-F")) {
|
||||
try create_module.framework_dirs.append(arena, arg[2..]);
|
||||
} else if (mem.startsWith(u8, arg, "-l")) {
|
||||
} else if (mem.cutPrefix(u8, arg, "-T")) |rest| {
|
||||
linker_script = rest;
|
||||
} else if (mem.cutPrefix(u8, arg, "-L")) |rest| {
|
||||
try create_module.lib_dir_args.append(arena, rest);
|
||||
} else if (mem.cutPrefix(u8, arg, "-F")) |rest| {
|
||||
try create_module.framework_dirs.append(arena, rest);
|
||||
} else if (mem.cutPrefix(u8, arg, "-l")) |name| {
|
||||
// We don't know whether this library is part of libc
|
||||
// or libc++ until we resolve the target, so we append
|
||||
// to the list for now.
|
||||
try create_module.cli_link_inputs.append(arena, .{ .name_query = .{
|
||||
.name = arg["-l".len..],
|
||||
.name = name,
|
||||
.query = .{
|
||||
.needed = false,
|
||||
.weak = false,
|
||||
|
|
@ -1725,9 +1712,9 @@ fn buildOutputType(
|
|||
.allow_so_scripts = allow_so_scripts,
|
||||
},
|
||||
} });
|
||||
} else if (mem.startsWith(u8, arg, "-needed-l")) {
|
||||
} else if (mem.cutPrefix(u8, arg, "-needed-l")) |name| {
|
||||
try create_module.cli_link_inputs.append(arena, .{ .name_query = .{
|
||||
.name = arg["-needed-l".len..],
|
||||
.name = name,
|
||||
.query = .{
|
||||
.needed = true,
|
||||
.weak = false,
|
||||
|
|
@ -1736,9 +1723,9 @@ fn buildOutputType(
|
|||
.allow_so_scripts = allow_so_scripts,
|
||||
},
|
||||
} });
|
||||
} else if (mem.startsWith(u8, arg, "-weak-l")) {
|
||||
} else if (mem.cutPrefix(u8, arg, "-weak-l")) |name| {
|
||||
try create_module.cli_link_inputs.append(arena, .{ .name_query = .{
|
||||
.name = arg["-weak-l".len..],
|
||||
.name = name,
|
||||
.query = .{
|
||||
.needed = false,
|
||||
.weak = true,
|
||||
|
|
@ -1749,13 +1736,10 @@ fn buildOutputType(
|
|||
} });
|
||||
} else if (mem.startsWith(u8, arg, "-D")) {
|
||||
try cc_argv.append(arena, arg);
|
||||
} else if (mem.startsWith(u8, arg, "-I")) {
|
||||
try cssan.addIncludePath(arena, &cc_argv, .I, arg, arg[2..], true);
|
||||
} else if (mem.startsWith(u8, arg, "-x")) {
|
||||
const lang = if (arg.len == "-x".len)
|
||||
args_iter.nextOrFatal()
|
||||
else
|
||||
arg["-x".len..];
|
||||
} else if (mem.cutPrefix(u8, arg, "-I")) |rest| {
|
||||
try cssan.addIncludePath(arena, &cc_argv, .I, arg, rest, true);
|
||||
} else if (mem.cutPrefix(u8, arg, "-x")) |rest| {
|
||||
const lang = if (rest.len == 0) args_iter.nextOrFatal() else rest;
|
||||
if (mem.eql(u8, lang, "none")) {
|
||||
file_ext = null;
|
||||
} else if (Compilation.LangToExt.get(lang)) |got_ext| {
|
||||
|
|
@ -1763,8 +1747,8 @@ fn buildOutputType(
|
|||
} else {
|
||||
fatal("language not recognized: '{s}'", .{lang});
|
||||
}
|
||||
} else if (mem.startsWith(u8, arg, "-mexec-model=")) {
|
||||
create_module.opts.wasi_exec_model = parseWasiExecModel(arg["-mexec-model=".len..]);
|
||||
} else if (mem.cutPrefix(u8, arg, "-mexec-model=")) |rest| {
|
||||
create_module.opts.wasi_exec_model = parseWasiExecModel(rest);
|
||||
} else if (mem.eql(u8, arg, "-municode")) {
|
||||
mingw_unicode_entry_point = true;
|
||||
} else {
|
||||
|
|
@ -2442,8 +2426,8 @@ fn buildOutputType(
|
|||
linker_enable_new_dtags = false;
|
||||
} else if (mem.eql(u8, arg, "-O")) {
|
||||
linker_optimization = linker_args_it.nextOrFatal();
|
||||
} else if (mem.startsWith(u8, arg, "-O")) {
|
||||
linker_optimization = arg["-O".len..];
|
||||
} else if (mem.cutPrefix(u8, arg, "-O")) |rest| {
|
||||
linker_optimization = rest;
|
||||
} else if (mem.eql(u8, arg, "-pagezero_size")) {
|
||||
const next_arg = linker_args_it.nextOrFatal();
|
||||
pagezero_size = std.fmt.parseUnsigned(u64, eatIntPrefix(next_arg, 16), 16) catch |err| {
|
||||
|
|
@ -2525,11 +2509,8 @@ fn buildOutputType(
|
|||
linker_compress_debug_sections = std.meta.stringToEnum(link.File.Lld.Elf.CompressDebugSections, arg1) orelse {
|
||||
fatal("expected [none|zlib|zstd] after --compress-debug-sections, found '{s}'", .{arg1});
|
||||
};
|
||||
} else if (mem.startsWith(u8, arg, "-z")) {
|
||||
var z_arg = arg[2..];
|
||||
if (z_arg.len == 0) {
|
||||
z_arg = linker_args_it.nextOrFatal();
|
||||
}
|
||||
} else if (mem.cutPrefix(u8, arg, "-z")) |z_rest| {
|
||||
const z_arg = if (z_rest.len == 0) linker_args_it.nextOrFatal() else z_rest;
|
||||
if (mem.eql(u8, z_arg, "nodelete")) {
|
||||
linker_z_nodelete = true;
|
||||
} else if (mem.eql(u8, z_arg, "notext")) {
|
||||
|
|
@ -2552,12 +2533,12 @@ fn buildOutputType(
|
|||
linker_z_relro = true;
|
||||
} else if (mem.eql(u8, z_arg, "norelro")) {
|
||||
linker_z_relro = false;
|
||||
} else if (mem.startsWith(u8, z_arg, "stack-size=")) {
|
||||
stack_size = parseStackSize(z_arg["stack-size=".len..]);
|
||||
} else if (mem.startsWith(u8, z_arg, "common-page-size=")) {
|
||||
linker_z_common_page_size = parseIntSuffix(z_arg, "common-page-size=".len);
|
||||
} else if (mem.startsWith(u8, z_arg, "max-page-size=")) {
|
||||
linker_z_max_page_size = parseIntSuffix(z_arg, "max-page-size=".len);
|
||||
} else if (mem.cutPrefix(u8, z_arg, "stack-size=")) |rest| {
|
||||
stack_size = parseStackSize(rest);
|
||||
} else if (prefixedIntArg(z_arg, "common-page-size=")) |int| {
|
||||
linker_z_common_page_size = int;
|
||||
} else if (prefixedIntArg(z_arg, "max-page-size=")) |int| {
|
||||
linker_z_max_page_size = int;
|
||||
} else {
|
||||
fatal("unsupported linker extension flag: -z {s}", .{z_arg});
|
||||
}
|
||||
|
|
@ -2671,9 +2652,9 @@ fn buildOutputType(
|
|||
.allow_so_scripts = allow_so_scripts,
|
||||
},
|
||||
} });
|
||||
} else if (mem.startsWith(u8, arg, "-weak-l")) {
|
||||
} else if (mem.cutPrefix(u8, arg, "-weak-l")) |rest| {
|
||||
try create_module.cli_link_inputs.append(arena, .{ .name_query = .{
|
||||
.name = arg["-weak-l".len..],
|
||||
.name = rest,
|
||||
.query = .{
|
||||
.weak = true,
|
||||
.needed = false,
|
||||
|
|
@ -3768,8 +3749,7 @@ fn createModule(
|
|||
try mcpu_buffer.appendSlice(cli_mod.target_mcpu orelse "baseline");
|
||||
|
||||
for (create_module.llvm_m_args.items) |llvm_m_arg| {
|
||||
if (mem.startsWith(u8, llvm_m_arg, "mno-")) {
|
||||
const llvm_name = llvm_m_arg["mno-".len..];
|
||||
if (mem.cutPrefix(u8, llvm_m_arg, "mno-")) |llvm_name| {
|
||||
const zig_name = llvm_to_zig_name.get(llvm_name) orelse {
|
||||
fatal("target architecture {s} has no LLVM CPU feature named '{s}'", .{
|
||||
@tagName(cpu_arch), llvm_name,
|
||||
|
|
@ -3777,8 +3757,7 @@ fn createModule(
|
|||
};
|
||||
try mcpu_buffer.append('-');
|
||||
try mcpu_buffer.appendSlice(zig_name);
|
||||
} else if (mem.startsWith(u8, llvm_m_arg, "m")) {
|
||||
const llvm_name = llvm_m_arg["m".len..];
|
||||
} else if (mem.cutPrefix(u8, llvm_m_arg, "m")) |llvm_name| {
|
||||
const zig_name = llvm_to_zig_name.get(llvm_name) orelse {
|
||||
fatal("target architecture {s} has no LLVM CPU feature named '{s}'", .{
|
||||
@tagName(cpu_arch), llvm_name,
|
||||
|
|
@ -4850,9 +4829,8 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
|
|||
reference_trace = 256;
|
||||
} else if (mem.eql(u8, arg, "--fetch")) {
|
||||
fetch_only = true;
|
||||
} else if (mem.startsWith(u8, arg, "--fetch=")) {
|
||||
} else if (mem.cutPrefix(u8, arg, "--fetch=")) |sub_arg| {
|
||||
fetch_only = true;
|
||||
const sub_arg = arg["--fetch=".len..];
|
||||
fetch_mode = std.meta.stringToEnum(Package.Fetch.JobQueue.Mode, sub_arg) orelse
|
||||
fatal("expected [needed|all] after '--fetch=', found '{s}'", .{
|
||||
sub_arg,
|
||||
|
|
@ -4863,8 +4841,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
|
|||
system_pkg_dir_path = args[i];
|
||||
try child_argv.append("--system");
|
||||
continue;
|
||||
} else if (mem.startsWith(u8, arg, "-freference-trace=")) {
|
||||
const num = arg["-freference-trace=".len..];
|
||||
} else if (mem.cutPrefix(u8, arg, "-freference-trace=")) |num| {
|
||||
reference_trace = std.fmt.parseUnsigned(u32, num, 10) catch |err| {
|
||||
fatal("unable to parse reference_trace count '{s}': {s}", .{ num, @errorName(err) });
|
||||
};
|
||||
|
|
@ -4914,10 +4891,10 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
|
|||
verbose_generic_instances = true;
|
||||
} else if (mem.eql(u8, arg, "--verbose-llvm-ir")) {
|
||||
verbose_llvm_ir = "-";
|
||||
} else if (mem.startsWith(u8, arg, "--verbose-llvm-ir=")) {
|
||||
verbose_llvm_ir = arg["--verbose-llvm-ir=".len..];
|
||||
} else if (mem.startsWith(u8, arg, "--verbose-llvm-bc=")) {
|
||||
verbose_llvm_bc = arg["--verbose-llvm-bc=".len..];
|
||||
} else if (mem.cutPrefix(u8, arg, "--verbose-llvm-ir=")) |rest| {
|
||||
verbose_llvm_ir = rest;
|
||||
} else if (mem.cutPrefix(u8, arg, "--verbose-llvm-bc=")) |rest| {
|
||||
verbose_llvm_bc = rest;
|
||||
} else if (mem.eql(u8, arg, "--verbose-cimport")) {
|
||||
verbose_cimport = true;
|
||||
} else if (mem.eql(u8, arg, "--verbose-llvm-cpu-features")) {
|
||||
|
|
@ -4930,8 +4907,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
|
|||
};
|
||||
try child_argv.appendSlice(&.{ arg, args[i] });
|
||||
continue;
|
||||
} else if (mem.startsWith(u8, arg, "-j")) {
|
||||
const str = arg["-j".len..];
|
||||
} else if (mem.cutPrefix(u8, arg, "-j")) |str| {
|
||||
const num = std.fmt.parseUnsigned(u32, str, 10) catch |err| {
|
||||
fatal("unable to parse jobs count '{s}': {s}", .{
|
||||
str, @errorName(err),
|
||||
|
|
@ -6507,10 +6483,9 @@ fn eatIntPrefix(arg: []const u8, base: u8) []const u8 {
|
|||
return arg;
|
||||
}
|
||||
|
||||
fn parseIntSuffix(arg: []const u8, prefix_len: usize) u64 {
|
||||
return std.fmt.parseUnsigned(u64, arg[prefix_len..], 0) catch |err| {
|
||||
fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
|
||||
};
|
||||
fn prefixedIntArg(arg: []const u8, prefix: []const u8) ?u64 {
|
||||
const number = mem.cutPrefix(u8, arg, prefix) orelse return null;
|
||||
return std.fmt.parseUnsigned(u64, number, 0) catch |err| fatal("unable to parse '{s}': {t}", .{ arg, err });
|
||||
}
|
||||
|
||||
fn warnAboutForeignBinaries(
|
||||
|
|
@ -6837,12 +6812,12 @@ fn cmdFetch(
|
|||
debug_hash = true;
|
||||
} else if (mem.eql(u8, arg, "--save")) {
|
||||
save = .{ .yes = null };
|
||||
} else if (mem.startsWith(u8, arg, "--save=")) {
|
||||
save = .{ .yes = arg["--save=".len..] };
|
||||
} else if (mem.cutPrefix(u8, arg, "--save=")) |rest| {
|
||||
save = .{ .yes = rest };
|
||||
} else if (mem.eql(u8, arg, "--save-exact")) {
|
||||
save = .{ .exact = null };
|
||||
} else if (mem.startsWith(u8, arg, "--save-exact=")) {
|
||||
save = .{ .exact = arg["--save-exact=".len..] };
|
||||
} else if (mem.cutPrefix(u8, arg, "--save-exact=")) |rest| {
|
||||
save = .{ .exact = rest };
|
||||
} else {
|
||||
fatal("unrecognized parameter: '{s}'", .{arg});
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue