authorgravatar for rpkak@noreply.codeberg.orgrpkak <rpkak@noreply.codeberg.org> 2026-04-21 17:24:00+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-04-22 19:30:39+02:00
log03955476ad9d838850392a0d5a7baa6beea3452b
treede220cb1844536db032a588157d7be208eb7b12a
parent9df02121d0d87c17173f79d55692bed9cb65722c

zigc: test and fix strtol and similar


4 files changed, 316 insertions(+), 22 deletions(-)

lib/c/stdlib.zig+32-22
......@@ -158,29 +158,40 @@ fn stringToInteger(comptime T: type, noalias buf: [*:0]const u8, noalias maybe_e
158158 };
159159
160160 // The prefix is allowed iff base == 0 or base == base of the prefix
161 const real_base: u6 = if (current[0] == '0') blk: {
162 current += 1;
163
164 if ((base == 0 or base == 16) and std.ascii.toLower(current[0]) == 'x' and std.ascii.isHex(current[1])) {
165 current += 1;
166 break :blk 16;
167 }
168
169 if ((base == 0 or base == 8) and std.ascii.isDigit(current[0])) {
170 break :blk 8;
161 const real_base: u6, const digits = blk: {
162 if (current[0] == '0') {
163 if ((base == 0 or base == 16) and std.ascii.toLower(current[1]) == 'x' and std.ascii.isHex(current[2])) {
164 break :blk .{ 16, current[2..] };
165 } else if (base == 0) {
166 break :blk .{ 8, current };
167 } else {
168 break :blk .{
169 switch (base) {
170 0 => 10,
171 else => @intCast(base),
172 },
173 current,
174 };
175 }
176 } else {
177 const real_base: u6 = switch (base) {
178 0 => 10,
179 else => @intCast(base),
180 };
181
182 _ = std.fmt.charToDigit(current[0], real_base) catch {
183 // No digits to parse. Setting errno to .INVAL is optional in this case.
184 if (maybe_end) |end| {
185 end.* = buf;
186 }
187 return 0;
188 };
189 break :blk .{ real_base, current };
171190 }
172
173 break :blk switch (base) {
174 0 => 10,
175 else => @intCast(base),
176 };
177 } else switch (base) {
178 0 => 10,
179 else => @intCast(base),
180191 };
181192
182193 if (@typeInfo(T).int.signedness == .unsigned) {
183 const result = parseDigitsWithSignGenericCharacter(T, u8, current, maybe_end, real_base, .pos) catch {
194 const result = parseDigitsWithSignGenericCharacter(T, u8, digits, maybe_end, real_base, .pos) catch {
184195 std.c._errno().* = @intFromEnum(std.c.E.RANGE);
185196 return std.math.maxInt(T);
186197 };
......@@ -188,12 +199,12 @@ fn stringToInteger(comptime T: type, noalias buf: [*:0]const u8, noalias maybe_e
188199 return if (negative) -%result else result;
189200 }
190201
191 if (negative) return parseDigitsWithSignGenericCharacter(T, u8, current, maybe_end, real_base, .neg) catch blk: {
202 if (negative) return parseDigitsWithSignGenericCharacter(T, u8, digits, maybe_end, real_base, .neg) catch blk: {
192203 std.c._errno().* = @intFromEnum(std.c.E.RANGE);
193204 break :blk std.math.minInt(T);
194205 };
195206
196 return parseDigitsWithSignGenericCharacter(T, u8, current, maybe_end, real_base, .pos) catch blk: {
207 return parseDigitsWithSignGenericCharacter(T, u8, digits, maybe_end, real_base, .pos) catch blk: {
197208 std.c._errno().* = @intFromEnum(std.c.E.RANGE);
198209 break :blk std.math.maxInt(T);
199210 };
......@@ -222,7 +233,6 @@ fn parseDigitsWithSignGenericCharacter(
222233 var value: T = 0;
223234 while (true) {
224235 const c: u8 = std.math.cast(u8, current[0]) orelse break;
225 if (!std.ascii.isAlphanumeric(c)) break;
226236
227237 const digit: u6 = @intCast(std.fmt.charToDigit(c, base) catch break);
228238 defer current += 1;
lib/std/c.zig+7
......@@ -11166,6 +11166,13 @@ pub extern "c" fn atoi(str: [*:0]const c_char) c_int;
1116611166pub extern "c" fn atol(str: [*:0]const c_char) c_long;
1116711167pub extern "c" fn atoll(str: [*:0]const c_char) c_longlong;
1116811168
11169pub extern "c" fn strtol(noalias str: [*:0]const c_char, noalias str_end: ?*[*:0]c_char, base: c_int) callconv(.c) c_long;
11170pub extern "c" fn strtoll(noalias str: [*:0]const c_char, noalias str_end: ?*[*:0]c_char, base: c_int) callconv(.c) c_longlong;
11171pub extern "c" fn strtoul(noalias str: [*:0]const c_char, noalias str_end: ?*[*:0]c_char, base: c_int) callconv(.c) c_ulong;
11172pub extern "c" fn strtoull(noalias str: [*:0]const c_char, noalias str_end: ?*[*:0]c_char, base: c_int) callconv(.c) c_ulonglong;
11173pub extern "c" fn strtoimax(noalias str: [*:0]const c_char, noalias str_end: ?*[*:0]c_char, base: c_int) callconv(.c) intmax_t;
11174pub extern "c" fn strtoumax(noalias str: [*:0]const c_char, noalias str_end: ?*[*:0]c_char, base: c_int) callconv(.c) uintmax_t;
11175
1116911176pub extern "c" fn bsearch(
1117011177 key: *const anyopaque,
1117111178 base: *const anyopaque,
test/c.zig+24
......@@ -1,5 +1,6 @@
11const builtin = @import("builtin");
22const std = @import("std");
3const c = std.c;
34
45test {
56 _ = @import("c/inttypes.zig");
......@@ -12,3 +13,26 @@ test {
1213 _ = @import("c/unistd.zig");
1314 _ = @import("c/wchar.zig");
1415}
16
17pub fn expectErrno(expected_errno: c.E) !void {
18 try std.testing.expectEqual(expected_errno, @as(c.E, @enumFromInt(c._errno().*)));
19 c._errno().* = @intFromEnum(c.E.SUCCESS);
20}
21
22pub fn expectErrnoAny(expected_errnos: []const c.E) !void {
23 const errno = c._errno().*;
24 for (expected_errnos) |expected_errno| {
25 if (errno == @intFromEnum(expected_errno)) break;
26 } else {
27 var buffer: [64]u8 = undefined;
28 const stderr = std.debug.lockStderr(&buffer);
29 defer std.debug.unlockStderr();
30 try stderr.file_writer.interface.print("expected one of {t}", .{expected_errnos[0]});
31 for (expected_errnos[1..]) |expected_errno| {
32 try stderr.file_writer.interface.print(", {t}", .{expected_errno});
33 }
34 try stderr.file_writer.interface.print(", found {t}\n", .{@as(c.E, @enumFromInt(errno))});
35 return error.TestExpectedEqual;
36 }
37 c._errno().* = @intFromEnum(c.E.SUCCESS);
38}
test/c/stdlib.zig+253
......@@ -6,6 +6,9 @@ const fmt = std.fmt;
66const math = std.math;
77const testing = std.testing;
88
9const expectErrno = @import("../c.zig").expectErrno;
10const expectErrnoAny = @import("../c.zig").expectErrnoAny;
11
912test "abs" {
1013 if (builtin.target.cpu.arch.isMIPS64()) return error.SkipZigTest; // TODO
1114
......@@ -97,6 +100,256 @@ test "atoll" {
97100 try testing.expectEqual(math.minInt(c_longlong), c.atoll(@ptrCast(fmt.comptimePrint("{d}", .{math.minInt(c_longlong)}))));
98101}
99102
103fn testStrToLLikeFunction(
104 func: anytype,
105 str: [*:0]const c_char,
106 base: c_int,
107 expected: comptime_int,
108 expected_len: ?usize,
109 expected_errno: c.E,
110) !void {
111 var end_ptr: [*:0]c_char = undefined;
112 try testing.expectEqual(expected, func(str, if (expected_len == null) null else &end_ptr, base));
113 if (expected_len) |len| try testing.expectEqual(len, end_ptr - str);
114 try expectErrno(expected_errno);
115}
116
117fn testStrToLLikeFunctionAnyErrno(
118 func: anytype,
119 str: [*:0]const c_char,
120 base: c_int,
121 expected: comptime_int,
122 expected_len: ?usize,
123 expected_errnos: []const c.E,
124) !void {
125 var end_ptr: [*:0]c_char = undefined;
126 try testing.expectEqual(expected, func(str, if (expected_len == null) null else &end_ptr, base));
127 if (expected_len) |len| try testing.expectEqual(len, end_ptr - str);
128 try expectErrnoAny(expected_errnos);
129}
130
131test "strtol" {
132 c._errno().* = @intFromEnum(c.E.SUCCESS);
133 try testStrToLLikeFunctionAnyErrno(c.strtol, @ptrCast("stop42true"), 0, 0, 0, &.{ .SUCCESS, .INVAL });
134 try testStrToLLikeFunction(c.strtol, @ptrCast("42true"), 0, 42, 2, .SUCCESS);
135 try testStrToLLikeFunction(c.strtol, @ptrCast("-01"), 0, -1, 3, .SUCCESS);
136 try testStrToLLikeFunction(c.strtol, @ptrCast("+001"), 0, 1, 4, .SUCCESS);
137 try testStrToLLikeFunction(c.strtol, @ptrCast(" 100"), 0, 100, 15, .SUCCESS);
138 try testStrToLLikeFunction(c.strtol, @ptrCast("000000000000500"), 0, 0o500, 15, .SUCCESS);
139 try testStrToLLikeFunction(c.strtol, @ptrCast("000000000000500"), 10, 500, 15, .SUCCESS);
140 try testStrToLLikeFunction(c.strtol, @ptrCast(" 0500"), 0, 0o500, 15, .SUCCESS);
141 try testStrToLLikeFunction(c.strtol, @ptrCast("0000000000001111_0000"), 10, 1111, 16, .SUCCESS);
142 try testStrToLLikeFunction(c.strtol, @ptrCast(" 1111_0000"), 0, 1111, 16, .SUCCESS);
143 try testStrToLLikeFunction(c.strtol, @ptrCast("0xAA"), 0, 0xAA, 4, .SUCCESS);
144 try testStrToLLikeFunction(c.strtol, @ptrCast("0xAA"), 10, 0, 1, .SUCCESS);
145 try testStrToLLikeFunction(c.strtol, @ptrCast("0xAA"), 16, 0xAA, 4, .SUCCESS);
146 try testStrToLLikeFunction(c.strtol, @ptrCast("0xAA"), 36, 43138, 4, .SUCCESS);
147 try testStrToLLikeFunction(c.strtol, @ptrCast("700B"), 0, 700, 3, .SUCCESS);
148 try testStrToLLikeFunction(c.strtol, @ptrCast("32453more"), 0, 32453, 5, .SUCCESS);
149 try testStrToLLikeFunction(c.strtol, @ptrCast(fmt.comptimePrint("{d}", .{math.maxInt(c_long)})), 0, math.maxInt(c_long), null, .SUCCESS);
150 try testStrToLLikeFunction(c.strtol, @ptrCast(fmt.comptimePrint("{d}", .{math.minInt(c_long)})), 0, math.minInt(c_long), null, .SUCCESS);
151 try testStrToLLikeFunction(c.strtol, @ptrCast(fmt.comptimePrint("{d}", .{math.maxInt(c_long) + 1})), 0, math.maxInt(c_long), null, .RANGE);
152 try testStrToLLikeFunction(c.strtol, @ptrCast(fmt.comptimePrint("{d}", .{math.minInt(c_long) - 1})), 0, math.minInt(c_long), null, .RANGE);
153 try testStrToLLikeFunctionAnyErrno(c.strtol, @ptrCast(""), 0, 0, 0, &.{ .SUCCESS, .INVAL });
154 try testStrToLLikeFunctionAnyErrno(c.strtol, @ptrCast(""), 12, 0, 0, &.{ .SUCCESS, .INVAL });
155 try testStrToLLikeFunctionAnyErrno(c.strtol, @ptrCast("-"), 0, 0, 0, &.{ .SUCCESS, .INVAL });
156 try testStrToLLikeFunctionAnyErrno(c.strtol, @ptrCast(" -"), 0, 0, 0, &.{ .SUCCESS, .INVAL });
157 try testStrToLLikeFunctionAnyErrno(c.strtol, @ptrCast(" "), 0, 0, 0, &.{ .SUCCESS, .INVAL });
158 try testStrToLLikeFunction(c.strtol, @ptrCast("0"), 0, 0, 1, .SUCCESS);
159 try testStrToLLikeFunction(c.strtol, @ptrCast("0"), 8, 0, 1, .SUCCESS);
160 try testStrToLLikeFunction(c.strtol, @ptrCast("09"), 0, 0, 1, .SUCCESS);
161 try testStrToLLikeFunction(c.strtol, @ptrCast("09"), 10, 9, 2, .SUCCESS);
162 if (builtin.os.tag != .windows)
163 try testStrToLLikeFunction(c.strtol, @ptrCast("0x"), 0, 0, 1, .SUCCESS);
164 try testStrToLLikeFunction(c.strtol, @ptrCast("1"), 37, 0, null, .INVAL);
165 try testStrToLLikeFunction(c.strtol, @ptrCast("1"), 1, 0, null, .INVAL);
166 try testStrToLLikeFunction(c.strtol, @ptrCast("1"), -1, 0, null, .INVAL);
167}
168
169test "strtoll" {
170 c._errno().* = @intFromEnum(c.E.SUCCESS);
171 try testStrToLLikeFunctionAnyErrno(c.strtoll, @ptrCast("stop42true"), 0, 0, 0, &.{ .SUCCESS, .INVAL });
172 try testStrToLLikeFunction(c.strtoll, @ptrCast("42true"), 0, 42, 2, .SUCCESS);
173 try testStrToLLikeFunction(c.strtoll, @ptrCast("-01"), 0, -1, 3, .SUCCESS);
174 try testStrToLLikeFunction(c.strtoll, @ptrCast("+001"), 0, 1, 4, .SUCCESS);
175 try testStrToLLikeFunction(c.strtoll, @ptrCast(" 100"), 0, 100, 15, .SUCCESS);
176 try testStrToLLikeFunction(c.strtoll, @ptrCast("000000000000500"), 0, 0o500, 15, .SUCCESS);
177 try testStrToLLikeFunction(c.strtoll, @ptrCast("000000000000500"), 10, 500, 15, .SUCCESS);
178 try testStrToLLikeFunction(c.strtoll, @ptrCast(" 0500"), 0, 0o500, 15, .SUCCESS);
179 try testStrToLLikeFunction(c.strtoll, @ptrCast("0000000000001111_0000"), 10, 1111, 16, .SUCCESS);
180 try testStrToLLikeFunction(c.strtoll, @ptrCast(" 1111_0000"), 0, 1111, 16, .SUCCESS);
181 try testStrToLLikeFunction(c.strtoll, @ptrCast("0xAA"), 0, 0xAA, 4, .SUCCESS);
182 try testStrToLLikeFunction(c.strtoll, @ptrCast("0xAA"), 10, 0, 1, .SUCCESS);
183 try testStrToLLikeFunction(c.strtoll, @ptrCast("0xAA"), 16, 0xAA, 4, .SUCCESS);
184 try testStrToLLikeFunction(c.strtoll, @ptrCast("0xAA"), 36, 43138, 4, .SUCCESS);
185 try testStrToLLikeFunction(c.strtoll, @ptrCast("700B"), 0, 700, 3, .SUCCESS);
186 try testStrToLLikeFunction(c.strtoll, @ptrCast("32453more"), 0, 32453, 5, .SUCCESS);
187 try testStrToLLikeFunction(c.strtoll, @ptrCast(fmt.comptimePrint("{d}", .{math.maxInt(c_longlong)})), 0, math.maxInt(c_longlong), null, .SUCCESS);
188 try testStrToLLikeFunction(c.strtoll, @ptrCast(fmt.comptimePrint("{d}", .{math.minInt(c_longlong)})), 0, math.minInt(c_longlong), null, .SUCCESS);
189 try testStrToLLikeFunction(c.strtoll, @ptrCast(fmt.comptimePrint("{d}", .{math.maxInt(c_longlong) + 1})), 0, math.maxInt(c_longlong), null, .RANGE);
190 try testStrToLLikeFunction(c.strtoll, @ptrCast(fmt.comptimePrint("{d}", .{math.minInt(c_longlong) - 1})), 0, math.minInt(c_longlong), null, .RANGE);
191 try testStrToLLikeFunctionAnyErrno(c.strtoll, @ptrCast(""), 0, 0, 0, &.{ .SUCCESS, .INVAL });
192 try testStrToLLikeFunctionAnyErrno(c.strtoll, @ptrCast(""), 12, 0, 0, &.{ .SUCCESS, .INVAL });
193 try testStrToLLikeFunctionAnyErrno(c.strtoll, @ptrCast("-"), 0, 0, 0, &.{ .SUCCESS, .INVAL });
194 try testStrToLLikeFunctionAnyErrno(c.strtoll, @ptrCast(" -"), 0, 0, 0, &.{ .SUCCESS, .INVAL });
195 try testStrToLLikeFunctionAnyErrno(c.strtoll, @ptrCast(" "), 0, 0, 0, &.{ .SUCCESS, .INVAL });
196 try testStrToLLikeFunction(c.strtoll, @ptrCast("0"), 0, 0, 1, .SUCCESS);
197 try testStrToLLikeFunction(c.strtoll, @ptrCast("0"), 8, 0, 1, .SUCCESS);
198 try testStrToLLikeFunction(c.strtoll, @ptrCast("09"), 0, 0, 1, .SUCCESS);
199 try testStrToLLikeFunction(c.strtoll, @ptrCast("09"), 10, 9, 2, .SUCCESS);
200 if (builtin.os.tag != .windows)
201 try testStrToLLikeFunction(c.strtoll, @ptrCast("0x"), 0, 0, 1, .SUCCESS);
202 try testStrToLLikeFunction(c.strtoll, @ptrCast("1"), 37, 0, null, .INVAL);
203 try testStrToLLikeFunction(c.strtoll, @ptrCast("1"), 1, 0, null, .INVAL);
204 try testStrToLLikeFunction(c.strtoll, @ptrCast("1"), -1, 0, null, .INVAL);
205}
206
207test "strtoul" {
208 c._errno().* = @intFromEnum(c.E.SUCCESS);
209 try testStrToLLikeFunctionAnyErrno(c.strtoul, @ptrCast("stop42true"), 0, 0, 0, &.{ .SUCCESS, .INVAL });
210 try testStrToLLikeFunction(c.strtoul, @ptrCast("42true"), 0, 42, 2, .SUCCESS);
211 try testStrToLLikeFunction(c.strtoul, @ptrCast("-01"), 0, math.maxInt(c_ulong), 3, .SUCCESS);
212 try testStrToLLikeFunction(c.strtoul, @ptrCast("+001"), 0, 1, 4, .SUCCESS);
213 try testStrToLLikeFunction(c.strtoul, @ptrCast(" 100"), 0, 100, 15, .SUCCESS);
214 try testStrToLLikeFunction(c.strtoul, @ptrCast("000000000000500"), 0, 0o500, 15, .SUCCESS);
215 try testStrToLLikeFunction(c.strtoul, @ptrCast("000000000000500"), 10, 500, 15, .SUCCESS);
216 try testStrToLLikeFunction(c.strtoul, @ptrCast(" 0500"), 0, 0o500, 15, .SUCCESS);
217 try testStrToLLikeFunction(c.strtoul, @ptrCast("0000000000001111_0000"), 10, 1111, 16, .SUCCESS);
218 try testStrToLLikeFunction(c.strtoul, @ptrCast(" 1111_0000"), 0, 1111, 16, .SUCCESS);
219 try testStrToLLikeFunction(c.strtoul, @ptrCast("0xAA"), 0, 0xAA, 4, .SUCCESS);
220 try testStrToLLikeFunction(c.strtoul, @ptrCast("0xAA"), 10, 0, 1, .SUCCESS);
221 try testStrToLLikeFunction(c.strtoul, @ptrCast("0xAA"), 16, 0xAA, 4, .SUCCESS);
222 try testStrToLLikeFunction(c.strtoul, @ptrCast("0xAA"), 36, 43138, 4, .SUCCESS);
223 try testStrToLLikeFunction(c.strtoul, @ptrCast("700B"), 0, 700, 3, .SUCCESS);
224 try testStrToLLikeFunction(c.strtoul, @ptrCast("32453more"), 0, 32453, 5, .SUCCESS);
225 try testStrToLLikeFunction(c.strtoul, @ptrCast(fmt.comptimePrint("{d}", .{math.maxInt(c_ulong)})), 0, math.maxInt(c_ulong), null, .SUCCESS);
226 try testStrToLLikeFunction(c.strtoul, @ptrCast(fmt.comptimePrint("{d}", .{math.maxInt(c_ulong) + 1})), 0, math.maxInt(c_ulong), null, .RANGE);
227 try testStrToLLikeFunctionAnyErrno(c.strtoul, @ptrCast(""), 0, 0, 0, &.{ .SUCCESS, .INVAL });
228 try testStrToLLikeFunctionAnyErrno(c.strtoul, @ptrCast(""), 12, 0, 0, &.{ .SUCCESS, .INVAL });
229 try testStrToLLikeFunctionAnyErrno(c.strtoul, @ptrCast("-"), 0, 0, 0, &.{ .SUCCESS, .INVAL });
230 try testStrToLLikeFunctionAnyErrno(c.strtoul, @ptrCast(" -"), 0, 0, 0, &.{ .SUCCESS, .INVAL });
231 try testStrToLLikeFunctionAnyErrno(c.strtoul, @ptrCast(" "), 0, 0, 0, &.{ .SUCCESS, .INVAL });
232 try testStrToLLikeFunction(c.strtoul, @ptrCast("0"), 0, 0, 1, .SUCCESS);
233 try testStrToLLikeFunction(c.strtoul, @ptrCast("0"), 8, 0, 1, .SUCCESS);
234 try testStrToLLikeFunction(c.strtoul, @ptrCast("09"), 0, 0, 1, .SUCCESS);
235 try testStrToLLikeFunction(c.strtoul, @ptrCast("09"), 10, 9, 2, .SUCCESS);
236 if (builtin.os.tag != .windows)
237 try testStrToLLikeFunction(c.strtoul, @ptrCast("0x"), 0, 0, 1, .SUCCESS);
238 try testStrToLLikeFunction(c.strtoul, @ptrCast("1"), 37, 0, null, .INVAL);
239 try testStrToLLikeFunction(c.strtoul, @ptrCast("1"), 1, 0, null, .INVAL);
240 try testStrToLLikeFunction(c.strtoul, @ptrCast("1"), -1, 0, null, .INVAL);
241}
242
243test "strtoull" {
244 c._errno().* = @intFromEnum(c.E.SUCCESS);
245 try testStrToLLikeFunctionAnyErrno(c.strtoull, @ptrCast("stop42true"), 0, 0, 0, &.{ .SUCCESS, .INVAL });
246 try testStrToLLikeFunction(c.strtoull, @ptrCast("42true"), 0, 42, 2, .SUCCESS);
247 try testStrToLLikeFunction(c.strtoull, @ptrCast("-01"), 0, math.maxInt(c_ulonglong), 3, .SUCCESS);
248 try testStrToLLikeFunction(c.strtoull, @ptrCast("+001"), 0, 1, 4, .SUCCESS);
249 try testStrToLLikeFunction(c.strtoull, @ptrCast(" 100"), 0, 100, 15, .SUCCESS);
250 try testStrToLLikeFunction(c.strtoull, @ptrCast("000000000000500"), 0, 0o500, 15, .SUCCESS);
251 try testStrToLLikeFunction(c.strtoull, @ptrCast("000000000000500"), 10, 500, 15, .SUCCESS);
252 try testStrToLLikeFunction(c.strtoull, @ptrCast(" 0500"), 0, 0o500, 15, .SUCCESS);
253 try testStrToLLikeFunction(c.strtoull, @ptrCast("0000000000001111_0000"), 10, 1111, 16, .SUCCESS);
254 try testStrToLLikeFunction(c.strtoull, @ptrCast(" 1111_0000"), 0, 1111, 16, .SUCCESS);
255 try testStrToLLikeFunction(c.strtoull, @ptrCast("0xAA"), 0, 0xAA, 4, .SUCCESS);
256 try testStrToLLikeFunction(c.strtoull, @ptrCast("0xAA"), 10, 0, 1, .SUCCESS);
257 try testStrToLLikeFunction(c.strtoull, @ptrCast("0xAA"), 16, 0xAA, 4, .SUCCESS);
258 try testStrToLLikeFunction(c.strtoull, @ptrCast("0xAA"), 36, 43138, 4, .SUCCESS);
259 try testStrToLLikeFunction(c.strtoull, @ptrCast("700B"), 0, 700, 3, .SUCCESS);
260 try testStrToLLikeFunction(c.strtoull, @ptrCast("32453more"), 0, 32453, 5, .SUCCESS);
261 try testStrToLLikeFunction(c.strtoull, @ptrCast(fmt.comptimePrint("{d}", .{math.maxInt(c_ulonglong)})), 0, math.maxInt(c_ulonglong), null, .SUCCESS);
262 try testStrToLLikeFunction(c.strtoull, @ptrCast(fmt.comptimePrint("{d}", .{math.maxInt(c_ulonglong) + 1})), 0, math.maxInt(c_ulonglong), null, .RANGE);
263 try testStrToLLikeFunctionAnyErrno(c.strtoull, @ptrCast(""), 0, 0, 0, &.{ .SUCCESS, .INVAL });
264 try testStrToLLikeFunctionAnyErrno(c.strtoull, @ptrCast(""), 12, 0, 0, &.{ .SUCCESS, .INVAL });
265 try testStrToLLikeFunctionAnyErrno(c.strtoull, @ptrCast("-"), 0, 0, 0, &.{ .SUCCESS, .INVAL });
266 try testStrToLLikeFunctionAnyErrno(c.strtoull, @ptrCast(" -"), 0, 0, 0, &.{ .SUCCESS, .INVAL });
267 try testStrToLLikeFunctionAnyErrno(c.strtoull, @ptrCast(" "), 0, 0, 0, &.{ .SUCCESS, .INVAL });
268 try testStrToLLikeFunction(c.strtoull, @ptrCast("0"), 0, 0, 1, .SUCCESS);
269 try testStrToLLikeFunction(c.strtoull, @ptrCast("0"), 8, 0, 1, .SUCCESS);
270 try testStrToLLikeFunction(c.strtoull, @ptrCast("09"), 0, 0, 1, .SUCCESS);
271 try testStrToLLikeFunction(c.strtoull, @ptrCast("09"), 10, 9, 2, .SUCCESS);
272 if (builtin.os.tag != .windows)
273 try testStrToLLikeFunction(c.strtoull, @ptrCast("0x"), 0, 0, 1, .SUCCESS);
274 try testStrToLLikeFunction(c.strtoull, @ptrCast("1"), 37, 0, null, .INVAL);
275 try testStrToLLikeFunction(c.strtoull, @ptrCast("1"), 1, 0, null, .INVAL);
276 try testStrToLLikeFunction(c.strtoull, @ptrCast("1"), -1, 0, null, .INVAL);
277}
278
279test "strtoimax" {
280 c._errno().* = @intFromEnum(c.E.SUCCESS);
281 try testStrToLLikeFunctionAnyErrno(c.strtoimax, @ptrCast("stop42true"), 0, 0, 0, &.{ .SUCCESS, .INVAL });
282 try testStrToLLikeFunction(c.strtoimax, @ptrCast("42true"), 0, 42, 2, .SUCCESS);
283 try testStrToLLikeFunction(c.strtoimax, @ptrCast("-01"), 0, -1, 3, .SUCCESS);
284 try testStrToLLikeFunction(c.strtoimax, @ptrCast("+001"), 0, 1, 4, .SUCCESS);
285 try testStrToLLikeFunction(c.strtoimax, @ptrCast(" 100"), 0, 100, 15, .SUCCESS);
286 try testStrToLLikeFunction(c.strtoimax, @ptrCast("000000000000500"), 0, 0o500, 15, .SUCCESS);
287 try testStrToLLikeFunction(c.strtoimax, @ptrCast("000000000000500"), 10, 500, 15, .SUCCESS);
288 try testStrToLLikeFunction(c.strtoimax, @ptrCast(" 0500"), 0, 0o500, 15, .SUCCESS);
289 try testStrToLLikeFunction(c.strtoimax, @ptrCast("0000000000001111_0000"), 10, 1111, 16, .SUCCESS);
290 try testStrToLLikeFunction(c.strtoimax, @ptrCast(" 1111_0000"), 0, 1111, 16, .SUCCESS);
291 try testStrToLLikeFunction(c.strtoimax, @ptrCast("0xAA"), 0, 0xAA, 4, .SUCCESS);
292 try testStrToLLikeFunction(c.strtoimax, @ptrCast("0xAA"), 10, 0, 1, .SUCCESS);
293 try testStrToLLikeFunction(c.strtoimax, @ptrCast("0xAA"), 16, 0xAA, 4, .SUCCESS);
294 try testStrToLLikeFunction(c.strtoimax, @ptrCast("0xAA"), 36, 43138, 4, .SUCCESS);
295 try testStrToLLikeFunction(c.strtoimax, @ptrCast("700B"), 0, 700, 3, .SUCCESS);
296 try testStrToLLikeFunction(c.strtoimax, @ptrCast("32453more"), 0, 32453, 5, .SUCCESS);
297 try testStrToLLikeFunction(c.strtoimax, @ptrCast(fmt.comptimePrint("{d}", .{math.maxInt(c.intmax_t)})), 0, math.maxInt(c.intmax_t), null, .SUCCESS);
298 try testStrToLLikeFunction(c.strtoimax, @ptrCast(fmt.comptimePrint("{d}", .{math.minInt(c.intmax_t)})), 0, math.minInt(c.intmax_t), null, .SUCCESS);
299 try testStrToLLikeFunction(c.strtoimax, @ptrCast(fmt.comptimePrint("{d}", .{math.maxInt(c.intmax_t) + 1})), 0, math.maxInt(c.intmax_t), null, .RANGE);
300 try testStrToLLikeFunction(c.strtoimax, @ptrCast(fmt.comptimePrint("{d}", .{math.minInt(c.intmax_t) - 1})), 0, math.minInt(c.intmax_t), null, .RANGE);
301 try testStrToLLikeFunctionAnyErrno(c.strtoimax, @ptrCast(""), 0, 0, 0, &.{ .SUCCESS, .INVAL });
302 try testStrToLLikeFunctionAnyErrno(c.strtoimax, @ptrCast(""), 12, 0, 0, &.{ .SUCCESS, .INVAL });
303 try testStrToLLikeFunctionAnyErrno(c.strtoimax, @ptrCast("-"), 0, 0, 0, &.{ .SUCCESS, .INVAL });
304 try testStrToLLikeFunctionAnyErrno(c.strtoimax, @ptrCast(" -"), 0, 0, 0, &.{ .SUCCESS, .INVAL });
305 try testStrToLLikeFunctionAnyErrno(c.strtoimax, @ptrCast(" "), 0, 0, 0, &.{ .SUCCESS, .INVAL });
306 try testStrToLLikeFunction(c.strtoimax, @ptrCast("0"), 0, 0, 1, .SUCCESS);
307 try testStrToLLikeFunction(c.strtoimax, @ptrCast("0"), 8, 0, 1, .SUCCESS);
308 try testStrToLLikeFunction(c.strtoimax, @ptrCast("09"), 0, 0, 1, .SUCCESS);
309 try testStrToLLikeFunction(c.strtoimax, @ptrCast("09"), 10, 9, 2, .SUCCESS);
310 if (builtin.os.tag != .windows)
311 try testStrToLLikeFunction(c.strtoimax, @ptrCast("0x"), 0, 0, 1, .SUCCESS);
312 try testStrToLLikeFunction(c.strtoimax, @ptrCast("1"), 37, 0, null, .INVAL);
313 try testStrToLLikeFunction(c.strtoimax, @ptrCast("1"), 1, 0, null, .INVAL);
314 try testStrToLLikeFunction(c.strtoimax, @ptrCast("1"), -1, 0, null, .INVAL);
315}
316
317test "strtoumax" {
318 c._errno().* = @intFromEnum(c.E.SUCCESS);
319 try testStrToLLikeFunctionAnyErrno(c.strtoumax, @ptrCast("stop42true"), 0, 0, 0, &.{ .SUCCESS, .INVAL });
320 try testStrToLLikeFunction(c.strtoumax, @ptrCast("42true"), 0, 42, 2, .SUCCESS);
321 try testStrToLLikeFunction(c.strtoumax, @ptrCast("-01"), 0, math.maxInt(c.uintmax_t), 3, .SUCCESS);
322 try testStrToLLikeFunction(c.strtoumax, @ptrCast("+001"), 0, 1, 4, .SUCCESS);
323 try testStrToLLikeFunction(c.strtoumax, @ptrCast(" 100"), 0, 100, 15, .SUCCESS);
324 try testStrToLLikeFunction(c.strtoumax, @ptrCast("000000000000500"), 0, 0o500, 15, .SUCCESS);
325 try testStrToLLikeFunction(c.strtoumax, @ptrCast("000000000000500"), 10, 500, 15, .SUCCESS);
326 try testStrToLLikeFunction(c.strtoumax, @ptrCast(" 0500"), 0, 0o500, 15, .SUCCESS);
327 try testStrToLLikeFunction(c.strtoumax, @ptrCast("0000000000001111_0000"), 10, 1111, 16, .SUCCESS);
328 try testStrToLLikeFunction(c.strtoumax, @ptrCast(" 1111_0000"), 0, 1111, 16, .SUCCESS);
329 try testStrToLLikeFunction(c.strtoumax, @ptrCast("0xAA"), 0, 0xAA, 4, .SUCCESS);
330 try testStrToLLikeFunction(c.strtoumax, @ptrCast("0xAA"), 10, 0, 1, .SUCCESS);
331 try testStrToLLikeFunction(c.strtoumax, @ptrCast("0xAA"), 16, 0xAA, 4, .SUCCESS);
332 try testStrToLLikeFunction(c.strtoumax, @ptrCast("0xAA"), 36, 43138, 4, .SUCCESS);
333 try testStrToLLikeFunction(c.strtoumax, @ptrCast("700B"), 0, 700, 3, .SUCCESS);
334 try testStrToLLikeFunction(c.strtoumax, @ptrCast("32453more"), 0, 32453, 5, .SUCCESS);
335 try testStrToLLikeFunction(c.strtoumax, @ptrCast(fmt.comptimePrint("{d}", .{math.maxInt(c_ulonglong)})), 0, math.maxInt(c_ulonglong), null, .SUCCESS);
336 try testStrToLLikeFunction(c.strtoumax, @ptrCast(fmt.comptimePrint("{d}", .{math.maxInt(c_ulonglong) + 1})), 0, math.maxInt(c_ulonglong), null, .RANGE);
337 try testStrToLLikeFunctionAnyErrno(c.strtoumax, @ptrCast(""), 0, 0, 0, &.{ .SUCCESS, .INVAL });
338 try testStrToLLikeFunctionAnyErrno(c.strtoumax, @ptrCast(""), 12, 0, 0, &.{ .SUCCESS, .INVAL });
339 try testStrToLLikeFunctionAnyErrno(c.strtoumax, @ptrCast("-"), 0, 0, 0, &.{ .SUCCESS, .INVAL });
340 try testStrToLLikeFunctionAnyErrno(c.strtoumax, @ptrCast(" -"), 0, 0, 0, &.{ .SUCCESS, .INVAL });
341 try testStrToLLikeFunctionAnyErrno(c.strtoumax, @ptrCast(" "), 0, 0, 0, &.{ .SUCCESS, .INVAL });
342 try testStrToLLikeFunction(c.strtoumax, @ptrCast("0"), 0, 0, 1, .SUCCESS);
343 try testStrToLLikeFunction(c.strtoumax, @ptrCast("0"), 8, 0, 1, .SUCCESS);
344 try testStrToLLikeFunction(c.strtoumax, @ptrCast("09"), 0, 0, 1, .SUCCESS);
345 try testStrToLLikeFunction(c.strtoumax, @ptrCast("09"), 10, 9, 2, .SUCCESS);
346 if (builtin.os.tag != .windows)
347 try testStrToLLikeFunction(c.strtoumax, @ptrCast("0x"), 0, 0, 1, .SUCCESS);
348 try testStrToLLikeFunction(c.strtoumax, @ptrCast("1"), 37, 0, null, .INVAL);
349 try testStrToLLikeFunction(c.strtoumax, @ptrCast("1"), 1, 0, null, .INVAL);
350 try testStrToLLikeFunction(c.strtoumax, @ptrCast("1"), -1, 0, null, .INVAL);
351}
352
100353test "bsearch" {
101354 const Comparison = struct {
102355 pub fn compare(a: *const anyopaque, b: *const anyopaque) callconv(.c) c_int {