Integer overflow in generic atoi

Hi, I’m getting an integer overflow error when I try to multiply a generic T by 10

fn atou(comptime T: type, data: []const u8) T {
    var out: T = 0;

    for (data) |c| {
        out *= @as(T, 10);
        out += @as(T, c - '0');
    }

    return out;
}
thread 91640 panic: integer overflow
/Users/poss/code/zig/PossSMP/src/main.zig:19:13: 0x100cc73ef in atou__anon_19660 (PossSMP)
        out *= @as(T, 10);

How can I get around that ?

(I know there’s probably a standard atoi-like function in the stdlib, but im reinventing the wheel to learn more)

Thanks !

That’s a panic, so it’s happening at runtime. You don’t have a T, but rather, an instance of T.

Which instance? By which I mean, what’s the first argument you pass?

ah yes sorry, here are the calls

const secsBeforeFadeOut = atou(u16, header[0xa9..0xac]); // size 3
const msFadeOut = atou(u16, header[0xac..0xb1]); // size 5

u16 should hold both of these

“Should” is doing a lot of the heavy lifting here.

It didn’t, so you need to look at those slices.

    for (data) |c| {
        out *= @as(T, 10);
        if ('0' <= c and c <= '9') {
           out += @as(T, c - '0');
        } else {} // Log it
    }

Might be a place to start.

ah yes sorry, one of those slices was null terminated

000000a9: 3136 3339 3030 3000 [...]  1639000

the first one (of size 3) reads 163 perfectly, but the second read (of size 5) didn’t like finding a null character

thank you very much

1 Like

If it’s not clear, atou should not handle termination as it’s taking a non terminated slice, even if it took a terminated slice, the terminator should be after the slice, as described by its len, though you should check that in safe build modes.

std.fmt.parseInt is the std lib function

1 Like

It’s std.fmt.parseInt or std.fmt.parseUnsigned if you want to compare implementations.

1 Like

As a matter of interest, Zig has a separate data structure for sentinel-terminated slices. In this case [:0]u8, but in fact any sentinel can be used.

For sentinel terminated slices, slice[slice.len] is valid, and will return the sentinel. Therefore slice[0...slice.len] will return the non-terminated subsection of that slice, as a []u8.

Note that the sentinel value is permitted inside the prefixed section of the slice, although in practice, weird things are likely to occur if this is the case.

1 Like