| author | |
| committer | |
| log | 0a868dacdd31b7d5c529a332da718683477a2505 |
| tree | a5d91a35d7f66b78c26110923eda548e52eb6258 |
| parent | 852eb272bf895ee6fc242e298e31d666caa9d0df |
Signed-off-by: Eric Joldasov <bratishkaerik@getgoogleoff.me>12 files changed, 38 insertions(+), 116 deletions(-)
lib/c.zig+5-1| ... | @@ -153,7 +153,11 @@ test "strncat" { | ... | @@ -153,7 +153,11 @@ test "strncat" { |
| 153 | } | 153 | } |
| 154 | 154 | ||
| 155 | fn strcmp(s1: [*:0]const u8, s2: [*:0]const u8) callconv(.C) c_int { | 155 | fn strcmp(s1: [*:0]const u8, s2: [*:0]const u8) callconv(.C) c_int { |
| 156 | return std.cstr.cmp(s1, s2); | 156 | return switch (std.mem.orderZ(u8, s1, s2)) { |
| 157 | .lt => -1, | ||
| 158 | .eq => 0, | ||
| 159 | .gt => 1, | ||
| 160 | }; | ||
| 157 | } | 161 | } |
| 158 | 162 | ||
| 159 | fn strlen(s: [*:0]const u8) callconv(.C) usize { | 163 | fn strlen(s: [*:0]const u8) callconv(.C) usize { |
lib/std/child_process.zig-1| ... | @@ -1,6 +1,5 @@ | ... | @@ -1,6 +1,5 @@ |
| 1 | const std = @import("std.zig"); | 1 | const std = @import("std.zig"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const cstr = std.cstr; | ||
| 4 | const unicode = std.unicode; | 3 | const unicode = std.unicode; |
| 5 | const io = std.io; | 4 | const io = std.io; |
| 6 | const fs = std.fs; | 5 | const fs = std.fs; |
lib/std/cstr.zig+3-100| ... | @@ -1,100 +1,3 @@ | ... | @@ -1,100 +1,3 @@ |
| 1 | const std = @import("std.zig"); | 1 | pub const line_sep = @compileError("deprecated; choose correct end-of-line sequence of characters by yourself instead"); |
| 2 | const builtin = @import("builtin"); | 2 | pub const cmp = @compileError("deprecated; use `std.mem.orderZ` instead"); |
| 3 | const debug = std.debug; | 3 | pub const addNullByte = @compileError("deprecated; use `allocator.dupeZ(u8, stuff)` instead"); |
| 4 | const mem = std.mem; | ||
| 5 | const testing = std.testing; | ||
| 6 | |||
| 7 | pub const line_sep = switch (builtin.os.tag) { | ||
| 8 | .windows => "\r\n", | ||
| 9 | else => "\n", | ||
| 10 | }; | ||
| 11 | |||
| 12 | pub fn cmp(a: [*:0]const u8, b: [*:0]const u8) i8 { | ||
| 13 | var index: usize = 0; | ||
| 14 | while (a[index] == b[index] and a[index] != 0) : (index += 1) {} | ||
| 15 | if (a[index] > b[index]) { | ||
| 16 | return 1; | ||
| 17 | } else if (a[index] < b[index]) { | ||
| 18 | return -1; | ||
| 19 | } else { | ||
| 20 | return 0; | ||
| 21 | } | ||
| 22 | } | ||
| 23 | |||
| 24 | test "cstr fns" { | ||
| 25 | try comptime testCStrFnsImpl(); | ||
| 26 | try testCStrFnsImpl(); | ||
| 27 | } | ||
| 28 | |||
| 29 | fn testCStrFnsImpl() !void { | ||
| 30 | try testing.expect(cmp("aoeu", "aoez") == -1); | ||
| 31 | } | ||
| 32 | |||
| 33 | /// Returns a mutable, null-terminated slice with the same length as `slice`. | ||
| 34 | /// Caller owns the returned memory. | ||
| 35 | pub fn addNullByte(allocator: mem.Allocator, slice: []const u8) ![:0]u8 { | ||
| 36 | const result = try allocator.alloc(u8, slice.len + 1); | ||
| 37 | @memcpy(result[0..slice.len], slice); | ||
| 38 | result[slice.len] = 0; | ||
| 39 | return result[0..slice.len :0]; | ||
| 40 | } | ||
| 41 | |||
| 42 | test "addNullByte" { | ||
| 43 | const slice = try addNullByte(std.testing.allocator, "hello"[0..4]); | ||
| 44 | defer std.testing.allocator.free(slice); | ||
| 45 | try testing.expect(slice.len == 4); | ||
| 46 | try testing.expect(slice[4] == 0); | ||
| 47 | } | ||
| 48 | |||
| 49 | pub const NullTerminated2DArray = struct { | ||
| 50 | allocator: mem.Allocator, | ||
| 51 | byte_count: usize, | ||
| 52 | ptr: ?[*:null]?[*:0]u8, | ||
| 53 | |||
| 54 | /// Takes N lists of strings, concatenates the lists together, and adds a null terminator | ||
| 55 | /// Caller must deinit result | ||
| 56 | pub fn fromSlices(allocator: mem.Allocator, slices: []const []const []const u8) !NullTerminated2DArray { | ||
| 57 | var new_len: usize = 1; // 1 for the list null | ||
| 58 | var byte_count: usize = 0; | ||
| 59 | for (slices) |slice| { | ||
| 60 | new_len += slice.len; | ||
| 61 | for (slice) |inner| { | ||
| 62 | byte_count += inner.len; | ||
| 63 | } | ||
| 64 | byte_count += slice.len; // for the null terminators of inner | ||
| 65 | } | ||
| 66 | |||
| 67 | const index_size = @sizeOf(usize) * new_len; // size of the ptrs | ||
| 68 | byte_count += index_size; | ||
| 69 | |||
| 70 | const buf = try allocator.alignedAlloc(u8, @alignOf(?*u8), byte_count); | ||
| 71 | errdefer allocator.free(buf); | ||
| 72 | |||
| 73 | var write_index = index_size; | ||
| 74 | const index_buf = mem.bytesAsSlice(?[*]u8, buf); | ||
| 75 | |||
| 76 | var i: usize = 0; | ||
| 77 | for (slices) |slice| { | ||
| 78 | for (slice) |inner| { | ||
| 79 | index_buf[i] = buf.ptr + write_index; | ||
| 80 | i += 1; | ||
| 81 | @memcpy(buf[write_index..][0..inner.len], inner); | ||
| 82 | write_index += inner.len; | ||
| 83 | buf[write_index] = 0; | ||
| 84 | write_index += 1; | ||
| 85 | } | ||
| 86 | } | ||
| 87 | index_buf[i] = null; | ||
| 88 | |||
| 89 | return NullTerminated2DArray{ | ||
| 90 | .allocator = allocator, | ||
| 91 | .byte_count = byte_count, | ||
| 92 | .ptr = @as(?[*:null]?[*:0]u8, @ptrCast(buf.ptr)), | ||
| 93 | }; | ||
| 94 | } | ||
| 95 | |||
| 96 | pub fn deinit(self: *NullTerminated2DArray) void { | ||
| 97 | const buf = @as([*]u8, @ptrCast(self.ptr)); | ||
| 98 | self.allocator.free(buf[0..self.byte_count]); | ||
| 99 | } | ||
| 100 | }; |
lib/std/mem.zig+13-1| ... | @@ -607,12 +607,24 @@ pub fn order(comptime T: type, lhs: []const T, rhs: []const T) math.Order { | ... | @@ -607,12 +607,24 @@ pub fn order(comptime T: type, lhs: []const T, rhs: []const T) math.Order { |
| 607 | return math.order(lhs.len, rhs.len); | 607 | return math.order(lhs.len, rhs.len); |
| 608 | } | 608 | } |
| 609 | 609 | ||
| 610 | test "order" { | 610 | /// Compares two many-item pointers with NUL-termination lexicographically. |
| 611 | pub fn orderZ(comptime T: type, lhs: [*:0]const T, rhs: [*:0]const T) math.Order { | ||
| 612 | var i: usize = 0; | ||
| 613 | while (lhs[i] == rhs[i] and lhs[i] != 0) : (i += 1) {} | ||
| 614 | return math.order(lhs[i], rhs[i]); | ||
| 615 | } | ||
| 616 | |||
| 617 | test "order and orderZ" { | ||
| 611 | try testing.expect(order(u8, "abcd", "bee") == .lt); | 618 | try testing.expect(order(u8, "abcd", "bee") == .lt); |
| 619 | try testing.expect(orderZ(u8, "abcd", "bee") == .lt); | ||
| 612 | try testing.expect(order(u8, "abc", "abc") == .eq); | 620 | try testing.expect(order(u8, "abc", "abc") == .eq); |
| 621 | try testing.expect(orderZ(u8, "abc", "abc") == .eq); | ||
| 613 | try testing.expect(order(u8, "abc", "abc0") == .lt); | 622 | try testing.expect(order(u8, "abc", "abc0") == .lt); |
| 623 | try testing.expect(orderZ(u8, "abc", "abc0") == .lt); | ||
| 614 | try testing.expect(order(u8, "", "") == .eq); | 624 | try testing.expect(order(u8, "", "") == .eq); |
| 625 | try testing.expect(orderZ(u8, "", "") == .eq); | ||
| 615 | try testing.expect(order(u8, "", "a") == .lt); | 626 | try testing.expect(order(u8, "", "a") == .lt); |
| 627 | try testing.expect(orderZ(u8, "", "a") == .lt); | ||
| 616 | } | 628 | } |
| 617 | 629 | ||
| 618 | /// Returns true if lhs < rhs, false otherwise | 630 | /// Returns true if lhs < rhs, false otherwise |
lib/std/net.zig+2-2| ... | @@ -783,7 +783,7 @@ pub fn getAddressList(allocator: mem.Allocator, name: []const u8, port: u16) Get | ... | @@ -783,7 +783,7 @@ pub fn getAddressList(allocator: mem.Allocator, name: []const u8, port: u16) Get |
| 783 | errdefer result.deinit(); | 783 | errdefer result.deinit(); |
| 784 | 784 | ||
| 785 | if (builtin.target.os.tag == .windows) { | 785 | if (builtin.target.os.tag == .windows) { |
| 786 | const name_c = try std.cstr.addNullByte(allocator, name); | 786 | const name_c = try allocator.dupeZ(u8, name); |
| 787 | defer allocator.free(name_c); | 787 | defer allocator.free(name_c); |
| 788 | 788 | ||
| 789 | const port_c = try std.fmt.allocPrintZ(allocator, "{}", .{port}); | 789 | const port_c = try std.fmt.allocPrintZ(allocator, "{}", .{port}); |
| ... | @@ -855,7 +855,7 @@ pub fn getAddressList(allocator: mem.Allocator, name: []const u8, port: u16) Get | ... | @@ -855,7 +855,7 @@ pub fn getAddressList(allocator: mem.Allocator, name: []const u8, port: u16) Get |
| 855 | } | 855 | } |
| 856 | 856 | ||
| 857 | if (builtin.link_libc) { | 857 | if (builtin.link_libc) { |
| 858 | const name_c = try std.cstr.addNullByte(allocator, name); | 858 | const name_c = try allocator.dupeZ(u8, name); |
| 859 | defer allocator.free(name_c); | 859 | defer allocator.free(name_c); |
| 860 | 860 | ||
| 861 | const port_c = try std.fmt.allocPrintZ(allocator, "{}", .{port}); | 861 | const port_c = try std.fmt.allocPrintZ(allocator, "{}", .{port}); |
lib/std/zig/c_builtins.zig+5-1| ... | @@ -126,7 +126,11 @@ pub inline fn __builtin_strlen(s: [*c]const u8) usize { | ... | @@ -126,7 +126,11 @@ pub inline fn __builtin_strlen(s: [*c]const u8) usize { |
| 126 | return std.mem.sliceTo(s, 0).len; | 126 | return std.mem.sliceTo(s, 0).len; |
| 127 | } | 127 | } |
| 128 | pub inline fn __builtin_strcmp(s1: [*c]const u8, s2: [*c]const u8) c_int { | 128 | pub inline fn __builtin_strcmp(s1: [*c]const u8, s2: [*c]const u8) c_int { |
| 129 | return @as(c_int, std.cstr.cmp(s1, s2)); | 129 | return switch (std.mem.orderZ(u8, s1, s2)) { |
| 130 | .lt => -1, | ||
| 131 | .eq => 0, | ||
| 132 | .gt => 1, | ||
| 133 | }; | ||
| 130 | } | 134 | } |
| 131 | 135 | ||
| 132 | pub inline fn __builtin_object_size(ptr: ?*const anyopaque, ty: c_int) usize { | 136 | pub inline fn __builtin_object_size(ptr: ?*const anyopaque, ty: c_int) usize { |
src/Compilation.zig+1-1| ... | @@ -5066,7 +5066,7 @@ fn parseLldStderr(comp: *Compilation, comptime prefix: []const u8, stderr: []con | ... | @@ -5066,7 +5066,7 @@ fn parseLldStderr(comp: *Compilation, comptime prefix: []const u8, stderr: []con |
| 5066 | defer context_lines.deinit(); | 5066 | defer context_lines.deinit(); |
| 5067 | 5067 | ||
| 5068 | var current_err: ?*LldError = null; | 5068 | var current_err: ?*LldError = null; |
| 5069 | var lines = mem.splitSequence(u8, stderr, std.cstr.line_sep); | 5069 | var lines = mem.splitSequence(u8, stderr, if (builtin.os.tag == .windows) "\r\n" else "\n"); |
| 5070 | while (lines.next()) |line| { | 5070 | while (lines.next()) |line| { |
| 5071 | if (mem.startsWith(u8, line, prefix ++ ":")) { | 5071 | if (mem.startsWith(u8, line, prefix ++ ":")) { |
| 5072 | if (current_err) |err| { | 5072 | if (current_err) |err| { |
src/codegen/c/type.zig+1-2| ... | @@ -1,5 +1,4 @@ | ... | @@ -1,5 +1,4 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const cstr = std.cstr; | ||
| 3 | const mem = std.mem; | 2 | const mem = std.mem; |
| 4 | const Allocator = mem.Allocator; | 3 | const Allocator = mem.Allocator; |
| 5 | const assert = std.debug.assert; | 4 | const assert = std.debug.assert; |
| ... | @@ -1025,7 +1024,7 @@ pub const CType = extern union { | ... | @@ -1025,7 +1024,7 @@ pub const CType = extern union { |
| 1025 | for (lhs_data, rhs_data) |lhs_field, rhs_field| { | 1024 | for (lhs_data, rhs_data) |lhs_field, rhs_field| { |
| 1026 | if (!ctx.eqlIndex(lhs_field.type, rhs_field.type)) return false; | 1025 | if (!ctx.eqlIndex(lhs_field.type, rhs_field.type)) return false; |
| 1027 | if (lhs_field.alignas.@"align" != rhs_field.alignas.@"align") return false; | 1026 | if (lhs_field.alignas.@"align" != rhs_field.alignas.@"align") return false; |
| 1028 | if (cstr.cmp(lhs_field.name, rhs_field.name) != 0) return false; | 1027 | if (std.mem.orderZ(u8, lhs_field.name, rhs_field.name) != .eq) return false; |
| 1029 | } | 1028 | } |
| 1030 | return true; | 1029 | return true; |
| 1031 | }, | 1030 | }, |
test/behavior/basic.zig+1-1| ... | @@ -647,7 +647,7 @@ test "multiline string literal is null terminated" { | ... | @@ -647,7 +647,7 @@ test "multiline string literal is null terminated" { |
| 647 | \\three | 647 | \\three |
| 648 | ; | 648 | ; |
| 649 | const s2 = "one\ntwo)\nthree"; | 649 | const s2 = "one\ntwo)\nthree"; |
| 650 | try expect(std.cstr.cmp(s1, s2) == 0); | 650 | try expect(std.mem.orderZ(u8, s1, s2) == .eq); |
| 651 | } | 651 | } |
| 652 | 652 | ||
| 653 | test "string escapes" { | 653 | test "string escapes" { |
test/cbe.zig+5-4| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const Cases = @import("src/Cases.zig"); | 2 | const Cases = @import("src/Cases.zig"); |
| 3 | const nl = if (@import("builtin").os.tag == .windows) "\r\n" else "\n"; | ||
| 3 | 4 | ||
| 4 | // These tests should work with all platforms, but we're using linux_x64 for | 5 | // These tests should work with all platforms, but we're using linux_x64 for |
| 5 | // now for consistency. Will be expanded eventually. | 6 | // now for consistency. Will be expanded eventually. |
| ... | @@ -19,7 +20,7 @@ pub fn addCases(ctx: *Cases) !void { | ... | @@ -19,7 +20,7 @@ pub fn addCases(ctx: *Cases) !void { |
| 19 | \\ _ = puts("hello world!"); | 20 | \\ _ = puts("hello world!"); |
| 20 | \\ return 0; | 21 | \\ return 0; |
| 21 | \\} | 22 | \\} |
| 22 | , "hello world!" ++ std.cstr.line_sep); | 23 | , "hello world!" ++ nl); |
| 23 | 24 | ||
| 24 | // Now change the message only | 25 | // Now change the message only |
| 25 | case.addCompareOutput( | 26 | case.addCompareOutput( |
| ... | @@ -28,7 +29,7 @@ pub fn addCases(ctx: *Cases) !void { | ... | @@ -28,7 +29,7 @@ pub fn addCases(ctx: *Cases) !void { |
| 28 | \\ _ = puts("yo"); | 29 | \\ _ = puts("yo"); |
| 29 | \\ return 0; | 30 | \\ return 0; |
| 30 | \\} | 31 | \\} |
| 31 | , "yo" ++ std.cstr.line_sep); | 32 | , "yo" ++ nl); |
| 32 | 33 | ||
| 33 | // Add an unused Decl | 34 | // Add an unused Decl |
| 34 | case.addCompareOutput( | 35 | case.addCompareOutput( |
| ... | @@ -38,7 +39,7 @@ pub fn addCases(ctx: *Cases) !void { | ... | @@ -38,7 +39,7 @@ pub fn addCases(ctx: *Cases) !void { |
| 38 | \\ return 0; | 39 | \\ return 0; |
| 39 | \\} | 40 | \\} |
| 40 | \\fn unused() void {} | 41 | \\fn unused() void {} |
| 41 | , "yo!" ++ std.cstr.line_sep); | 42 | , "yo!" ++ nl); |
| 42 | 43 | ||
| 43 | // Comptime return type and calling convention expected. | 44 | // Comptime return type and calling convention expected. |
| 44 | case.addError( | 45 | case.addError( |
| ... | @@ -67,7 +68,7 @@ pub fn addCases(ctx: *Cases) !void { | ... | @@ -67,7 +68,7 @@ pub fn addCases(ctx: *Cases) !void { |
| 67 | \\ _ = printf("Hello, %s!\n", "world"); | 68 | \\ _ = printf("Hello, %s!\n", "world"); |
| 68 | \\ return 0; | 69 | \\ return 0; |
| 69 | \\} | 70 | \\} |
| 70 | , "Hello, world!" ++ std.cstr.line_sep); | 71 | , "Hello, world!" ++ nl); |
| 71 | } | 72 | } |
| 72 | 73 | ||
| 73 | { | 74 | { |
test/compare_output.zig+1-1| ... | @@ -15,7 +15,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { | ... | @@ -15,7 +15,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { |
| 15 | \\ _ = c.puts("Hello, world!"); | 15 | \\ _ = c.puts("Hello, world!"); |
| 16 | \\ return 0; | 16 | \\ return 0; |
| 17 | \\} | 17 | \\} |
| 18 | , "Hello, world!" ++ std.cstr.line_sep); | 18 | , "Hello, world!" ++ if (@import("builtin").os.tag == .windows) "\r\n" else "\n"); |
| 19 | 19 | ||
| 20 | cases.add("hello world without libc", | 20 | cases.add("hello world without libc", |
| 21 | \\const io = @import("std").io; | 21 | \\const io = @import("std").io; |
test/run_translated_c.zig+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const tests = @import("tests.zig"); | 2 | const tests = @import("tests.zig"); |
| 3 | const nl = std.cstr.line_sep; | 3 | const nl = if (@import("builtin").os.tag == .windows) "\r\n" else "\n"; |
| 4 | 4 | ||
| 5 | pub fn addCases(cases: *tests.RunTranslatedCContext) void { | 5 | pub fn addCases(cases: *tests.RunTranslatedCContext) void { |
| 6 | cases.add("dereference address of", | 6 | cases.add("dereference address of", |