Skip to content

Instantly share code, notes, and snippets.

@ljmccarthy
Last active April 9, 2019 14:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ljmccarthy/ef3e4e828a940812ae9d23f4d3713053 to your computer and use it in GitHub Desktop.
Save ljmccarthy/ef3e4e828a940812ae9d23f4d3713053 to your computer and use it in GitHub Desktop.
const std = @import("std");
use std.os.windows;
pub extern "kernel32" stdcallcc fn GetCommandLineW() LPWSTR;
pub extern "kernel32" stdcallcc fn LocalFree(hMem: *c_void) ?*c_void;
pub extern "shell32" stdcallcc fn CommandLineToArgvW(lpCmdLine: LPCWSTR, out_pNumArgs: *c_int) ?[*]LPWSTR;
pub const ArgIteratorWindows = struct {
index: usize,
count: usize,
raw: ?[*]LPWSTR,
pub const NextError = @typeOf(std.unicode.utf16leToUtf8Alloc).ReturnType.ErrorSet;
pub fn init() ArgIteratorWindows {
return initWithCmdLine(GetCommandLineW());
}
pub fn initWithCmdLine(cmd_line: [*]const u16) ArgIteratorWindows {
var num_args: c_int = undefined;
var raw = CommandLineToArgvW(GetCommandLineW(), &num_args);
return ArgIteratorWindows{
.index = 0,
.count = @intCast(usize, num_args),
.raw = raw,
};
}
pub fn deinit(self: *ArgIteratorWindows) void {
if (self.raw != null) {
_ = LocalFree(@ptrCast(*c_void, self.raw));
}
}
/// You must free the returned memory when done.
pub fn next(self: *ArgIteratorWindows, allocator: *std.mem.Allocator) ?(NextError![]u8) {
if (self.raw == null) {
return null; // error.OutOfMemory;
}
if (self.index == self.count) {
return null;
}
const arg = std.mem.toSlice(u16, self.raw.?[self.index]);
self.index += 1;
return std.unicode.utf16leToUtf8Alloc(allocator, arg);
}
pub fn skip(self: *ArgIteratorWindows) bool {
if (self.index == self.count) return false;
self.index += 1;
return true;
}
};
fn printArgs(allocator: *std.mem.Allocator) !void {
const stdout = try std.io.getStdOut();
var argsIter = ArgIteratorWindows.init();
defer argsIter.deinit();
while (argsIter.next(allocator)) |argOrError| {
var arg = try argOrError;
defer allocator.free(arg);
try stdout.write(arg);
try stdout.write("\n");
}
}
pub fn main() !void {
var direct_allocator = std.heap.DirectAllocator.init();
defer direct_allocator.deinit();
var arena = std.heap.ArenaAllocator.init(&direct_allocator.allocator);
defer arena.deinit();
try printArgs(&arena.allocator);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment