Skip to content

Commit dd973fb

Browse files
LemonBoyandrewrk
authored andcommitted
std: Use {s} instead of {} when printing strings
1 parent 5a06fdf commit dd973fb

32 files changed

+771
-231
lines changed

lib/std/SemanticVersion.zig

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,8 @@ pub fn format(
164164
) !void {
165165
if (fmt.len != 0) @compileError("Unknown format string: '" ++ fmt ++ "'");
166166
try std.fmt.format(out_stream, "{}.{}.{}", .{ self.major, self.minor, self.patch });
167-
if (self.pre) |pre| try std.fmt.format(out_stream, "-{}", .{pre});
168-
if (self.build) |build| try std.fmt.format(out_stream, "+{}", .{build});
167+
if (self.pre) |pre| try std.fmt.format(out_stream, "-{s}", .{pre});
168+
if (self.build) |build| try std.fmt.format(out_stream, "+{s}", .{build});
169169
}
170170

171171
const expect = std.testing.expect;
@@ -287,9 +287,9 @@ fn testFmt(expected: []const u8, comptime template: []const u8, args: anytype) !
287287
if (std.mem.eql(u8, result, expected)) return;
288288

289289
std.debug.warn("\n====== expected this output: =========\n", .{});
290-
std.debug.warn("{}", .{expected});
290+
std.debug.warn("{s}", .{expected});
291291
std.debug.warn("\n======== instead found this: =========\n", .{});
292-
std.debug.warn("{}", .{result});
292+
std.debug.warn("{s}", .{result});
293293
std.debug.warn("\n======================================\n", .{});
294294
return error.TestFailed;
295295
}

lib/std/array_list_sentineled.zig

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
// SPDX-License-Identifier: MIT
2+
// Copyright (c) 2015-2020 Zig Contributors
3+
// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
4+
// The MIT license requires this copyright notice to be included in all copies
5+
// and substantial portions of the software.
6+
const std = @import("std.zig");
7+
const debug = std.debug;
8+
const mem = std.mem;
9+
const Allocator = mem.Allocator;
10+
const assert = debug.assert;
11+
const testing = std.testing;
12+
const ArrayList = std.ArrayList;
13+
14+
/// A contiguous, growable list of items in memory, with a sentinel after them.
15+
/// The sentinel is maintained when appending, resizing, etc.
16+
/// If you do not need a sentinel, consider using `ArrayList` instead.
17+
pub fn ArrayListSentineled(comptime T: type, comptime sentinel: T) type {
18+
return struct {
19+
list: ArrayList(T),
20+
21+
const Self = @This();
22+
23+
/// Must deinitialize with deinit.
24+
pub fn init(allocator: *Allocator, m: []const T) !Self {
25+
var self = try initSize(allocator, m.len);
26+
mem.copy(T, self.list.items, m);
27+
return self;
28+
}
29+
30+
/// Initialize memory to size bytes of undefined values.
31+
/// Must deinitialize with deinit.
32+
pub fn initSize(allocator: *Allocator, size: usize) !Self {
33+
var self = initNull(allocator);
34+
try self.resize(size);
35+
return self;
36+
}
37+
38+
/// Initialize with capacity to hold at least num bytes.
39+
/// Must deinitialize with deinit.
40+
pub fn initCapacity(allocator: *Allocator, num: usize) !Self {
41+
var self = Self{ .list = try ArrayList(T).initCapacity(allocator, num + 1) };
42+
self.list.appendAssumeCapacity(sentinel);
43+
return self;
44+
}
45+
46+
/// Must deinitialize with deinit.
47+
/// None of the other operations are valid until you do one of these:
48+
/// * `replaceContents`
49+
/// * `resize`
50+
pub fn initNull(allocator: *Allocator) Self {
51+
return Self{ .list = ArrayList(T).init(allocator) };
52+
}
53+
54+
/// Must deinitialize with deinit.
55+
pub fn initFromBuffer(buffer: Self) !Self {
56+
return Self.init(buffer.list.allocator, buffer.span());
57+
}
58+
59+
/// Takes ownership of the passed in slice. The slice must have been
60+
/// allocated with `allocator`.
61+
/// Must deinitialize with deinit.
62+
pub fn fromOwnedSlice(allocator: *Allocator, slice: []T) !Self {
63+
var self = Self{ .list = ArrayList(T).fromOwnedSlice(allocator, slice) };
64+
try self.list.append(sentinel);
65+
return self;
66+
}
67+
68+
/// The caller owns the returned memory. The list becomes null and is safe to `deinit`.
69+
pub fn toOwnedSlice(self: *Self) [:sentinel]T {
70+
const allocator = self.list.allocator;
71+
const result = self.list.toOwnedSlice();
72+
self.* = initNull(allocator);
73+
return result[0 .. result.len - 1 :sentinel];
74+
}
75+
76+
/// Only works when `T` is `u8`.
77+
pub fn allocPrint(allocator: *Allocator, comptime format: []const u8, args: anytype) !Self {
78+
const size = std.math.cast(usize, std.fmt.count(format, args)) catch |err| switch (err) {
79+
error.Overflow => return error.OutOfMemory,
80+
};
81+
var self = try Self.initSize(allocator, size);
82+
assert((std.fmt.bufPrint(self.list.items, format, args) catch unreachable).len == size);
83+
return self;
84+
}
85+
86+
pub fn deinit(self: *Self) void {
87+
self.list.deinit();
88+
}
89+
90+
pub fn span(self: anytype) @TypeOf(self.list.items[0..:sentinel]) {
91+
return self.list.items[0..self.len() :sentinel];
92+
}
93+
94+
pub fn shrink(self: *Self, new_len: usize) void {
95+
assert(new_len <= self.len());
96+
self.list.shrink(new_len + 1);
97+
self.list.items[self.len()] = sentinel;
98+
}
99+
100+
pub fn resize(self: *Self, new_len: usize) !void {
101+
try self.list.resize(new_len + 1);
102+
self.list.items[self.len()] = sentinel;
103+
}
104+
105+
pub fn isNull(self: Self) bool {
106+
return self.list.items.len == 0;
107+
}
108+
109+
pub fn len(self: Self) usize {
110+
return self.list.items.len - 1;
111+
}
112+
113+
pub fn capacity(self: Self) usize {
114+
return if (self.list.capacity > 0)
115+
self.list.capacity - 1
116+
else
117+
0;
118+
}
119+
120+
pub fn appendSlice(self: *Self, m: []const T) !void {
121+
const old_len = self.len();
122+
try self.resize(old_len + m.len);
123+
mem.copy(T, self.list.items[old_len..], m);
124+
}
125+
126+
pub fn append(self: *Self, byte: T) !void {
127+
const old_len = self.len();
128+
try self.resize(old_len + 1);
129+
self.list.items[old_len] = byte;
130+
}
131+
132+
pub fn eql(self: Self, m: []const T) bool {
133+
return mem.eql(T, self.span(), m);
134+
}
135+
136+
pub fn startsWith(self: Self, m: []const T) bool {
137+
if (self.len() < m.len) return false;
138+
return mem.eql(T, self.list.items[0..m.len], m);
139+
}
140+
141+
pub fn endsWith(self: Self, m: []const T) bool {
142+
const l = self.len();
143+
if (l < m.len) return false;
144+
const start = l - m.len;
145+
return mem.eql(T, self.list.items[start..l], m);
146+
}
147+
148+
pub fn replaceContents(self: *Self, m: []const T) !void {
149+
try self.resize(m.len);
150+
mem.copy(T, self.list.items, m);
151+
}
152+
153+
/// Initializes an OutStream which will append to the list.
154+
/// This function may be called only when `T` is `u8`.
155+
pub fn outStream(self: *Self) std.io.OutStream(*Self, error{OutOfMemory}, appendWrite) {
156+
return .{ .context = self };
157+
}
158+
159+
/// Same as `append` except it returns the number of bytes written, which is always the same
160+
/// as `m.len`. The purpose of this function existing is to match `std.io.OutStream` API.
161+
/// This function may be called only when `T` is `u8`.
162+
pub fn appendWrite(self: *Self, m: []const u8) !usize {
163+
try self.appendSlice(m);
164+
return m.len;
165+
}
166+
};
167+
}
168+
169+
test "simple" {
170+
var buf = try ArrayListSentineled(u8, 0).init(testing.allocator, "");
171+
defer buf.deinit();
172+
173+
testing.expect(buf.len() == 0);
174+
try buf.appendSlice("hello");
175+
try buf.appendSlice(" ");
176+
try buf.appendSlice("world");
177+
testing.expect(buf.eql("hello world"));
178+
testing.expect(mem.eql(u8, mem.spanZ(buf.span().ptr), buf.span()));
179+
180+
var buf2 = try ArrayListSentineled(u8, 0).initFromBuffer(buf);
181+
defer buf2.deinit();
182+
testing.expect(buf.eql(buf2.span()));
183+
184+
testing.expect(buf.startsWith("hell"));
185+
testing.expect(buf.endsWith("orld"));
186+
187+
try buf2.resize(4);
188+
testing.expect(buf.startsWith(buf2.span()));
189+
}
190+
191+
test "initSize" {
192+
var buf = try ArrayListSentineled(u8, 0).initSize(testing.allocator, 3);
193+
defer buf.deinit();
194+
testing.expect(buf.len() == 3);
195+
try buf.appendSlice("hello");
196+
testing.expect(mem.eql(u8, buf.span()[3..], "hello"));
197+
}
198+
199+
test "initCapacity" {
200+
var buf = try ArrayListSentineled(u8, 0).initCapacity(testing.allocator, 10);
201+
defer buf.deinit();
202+
testing.expect(buf.len() == 0);
203+
testing.expect(buf.capacity() >= 10);
204+
const old_cap = buf.capacity();
205+
try buf.appendSlice("hello");
206+
testing.expect(buf.len() == 5);
207+
testing.expect(buf.capacity() == old_cap);
208+
testing.expect(mem.eql(u8, buf.span(), "hello"));
209+
}
210+
211+
test "print" {
212+
var buf = try ArrayListSentineled(u8, 0).init(testing.allocator, "");
213+
defer buf.deinit();
214+
215+
try buf.outStream().print("Hello {d} the {s}", .{ 2, "world" });
216+
testing.expect(buf.eql("Hello 2 the world"));
217+
}
218+
219+
test "outStream" {
220+
var buffer = try ArrayListSentineled(u8, 0).initSize(testing.allocator, 0);
221+
defer buffer.deinit();
222+
const buf_stream = buffer.outStream();
223+
224+
const x: i32 = 42;
225+
const y: i32 = 1234;
226+
try buf_stream.print("x: {}\ny: {}\n", .{ x, y });
227+
228+
testing.expect(mem.eql(u8, buffer.span(), "x: 42\ny: 1234\n"));
229+
}

0 commit comments

Comments
 (0)