Why does iterating over command line arguments require an allocator on windows?

From std.process we can see that iterating over the command line arguments on windows requires an allocator, while on linux, it does not.

Why does iterating over command line arguments on windows require an allocator?

This is what I found after reading standart library:

  • On Linux, arguments are stored in a known location within the loaded binary, already processed and ready for use as-is, so the iterator can simply return a slice of them.

  • On Windows, however, the arguments are not pre-processed, so the iterator must handle this task. Since it needs to modify the arguments, it must copy them into its own buffer. So allocator is required to obtain said buffer.

Here we can see windows iterator handling escaping, unescaping and skiping whitespace.

While posix iterator just does nothing

pub fn next(self: *ArgIteratorPosix) ?[:0]const u8 {
    if (self.index == self.count) return null;

    const s = std.os.argv[self.index];
    self.index += 1;
    return mem.sliceTo(s, 0);
}
8 Likes

There’s also a more basic problem: on windows you get wtf16 encoded strings which are a pain in the ass to work with, so this interface transcodes them to utf8.

2 Likes

FWIW I just use argsWithAllocator() on all platforms, I actually thought the ‘other’ args() function is deprecated…

Would be nice if the Zig stdlib exposed a simple higher-level arg-parser, e.g. give it a array of accepted args (with long and short name, type, description and optional default value) and return a struct with the ‘resolved’ args (I know that such libs exist as 3rd party, but it’s such a common thing for command line tools that stdlib support would be nice). Could also use Zig comptime to build that resolved-args struct type.

2 Likes

Note that you linked the next implementation of ArgIteratorGeneral, which is currently only used for parsing response files. Here’s ArgIteratorWindows, which (as noted earlier) takes a single WTF-16 string as input:

1 Like