mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
get_env for Win32, @pierrec's get_config_dir and get_home_dir
This commit is contained in:
committed by
Christoffer Lerno
parent
2a683a6a05
commit
c5404c6573
@@ -448,6 +448,17 @@ fn void Path.free(self)
|
|||||||
free(self.path_string.ptr);
|
free(self.path_string.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn usz! Path.to_format(&self, Formatter* formatter) @dynamic
|
||||||
|
{
|
||||||
|
return formatter.print(self.str_view());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn String Path.to_string(&self, Allocator* using = mem::heap()) @dynamic
|
||||||
|
{
|
||||||
|
return self.str_view().copy(using);
|
||||||
|
}
|
||||||
|
|
||||||
const bool[256] RESERVED_PATH_CHAR_POSIX = {
|
const bool[256] RESERVED_PATH_CHAR_POSIX = {
|
||||||
[0] = true,
|
[0] = true,
|
||||||
['/'] = true,
|
['/'] = true,
|
||||||
|
|||||||
@@ -430,7 +430,7 @@ macro usz! Stream.write_varint(&self, x)
|
|||||||
{
|
{
|
||||||
var $Type = $typeof(x);
|
var $Type = $typeof(x);
|
||||||
const MAX = MAX_VARS[$Type.sizeof];
|
const MAX = MAX_VARS[$Type.sizeof];
|
||||||
char[MAX] buffer;
|
char[MAX] buffer @noinit;
|
||||||
usz i;
|
usz i;
|
||||||
while (x >= 0x80)
|
while (x >= 0x80)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2021 Christoffer Lerno. All rights reserved.
|
// Copyright (c) 2021-2023 Christoffer Lerno. All rights reserved.
|
||||||
// Use of this source code is governed by the MIT license
|
// Use of this source code is governed by the MIT license
|
||||||
// a copy of which can be found in the LICENSE_STDLIB file.
|
// a copy of which can be found in the LICENSE_STDLIB file.
|
||||||
module std::os::env;
|
module std::os::env;
|
||||||
@@ -7,53 +7,119 @@ import libc;
|
|||||||
/**
|
/**
|
||||||
* @param [in] name
|
* @param [in] name
|
||||||
* @require name.len > 0
|
* @require name.len > 0
|
||||||
|
* @return! SearchResult.MISSING
|
||||||
**/
|
**/
|
||||||
fn String! get_var(String name)
|
fn String! get_var(String name, Allocator* using = mem::heap())
|
||||||
{
|
{
|
||||||
$if env::LIBC && !env::WIN32:
|
@pool(using)
|
||||||
@pool()
|
|
||||||
{
|
{
|
||||||
|
$switch
|
||||||
|
$case env::LIBC && !env::WIN32:
|
||||||
ZString val = libc::getenv(name.zstr_tcopy());
|
ZString val = libc::getenv(name.zstr_tcopy());
|
||||||
return val ? val.str_view() : SearchResult.MISSING?;
|
return val ? val.copy(using) : SearchResult.MISSING?;
|
||||||
|
$case env::WIN32:
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getenvironmentvariable
|
||||||
|
const usz BUFSIZE = 1024;
|
||||||
|
WString buff = (WString)tcalloc(BUFSIZE * 2 + 2);
|
||||||
|
WString wstr = name.to_wstring(mem::temp())!;
|
||||||
|
usz len = win32::getEnvironmentVariableW(wstr, buff, BUFSIZE);
|
||||||
|
if (len == 0) return SearchResult.MISSING?;
|
||||||
|
if (len > BUFSIZE)
|
||||||
|
{
|
||||||
|
buff = (WString)tmalloc(len * 2 + 2);
|
||||||
|
win32::getEnvironmentVariableW(wstr, buff, (Win32_DWORD)len);
|
||||||
|
}
|
||||||
|
return string::from_wstring(buff, using);
|
||||||
|
$default:
|
||||||
|
return "";
|
||||||
|
$endswitch
|
||||||
};
|
};
|
||||||
$else
|
|
||||||
return "";
|
|
||||||
$endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param [in] name
|
* @param [in] name
|
||||||
* @param [in] value
|
* @param [in] value
|
||||||
* @require name.len > 0
|
* @require name.len > 0
|
||||||
**/
|
**/
|
||||||
fn void set_var(String name, String value, bool overwrite = true)
|
fn bool set_var(String name, String value, bool overwrite = true)
|
||||||
{
|
{
|
||||||
$if env::LIBC && !env::WIN32:
|
|
||||||
@pool()
|
@pool()
|
||||||
{
|
{
|
||||||
if (libc::setenv(name.zstr_tcopy(), value.zstr_copy(), (int)overwrite))
|
$switch
|
||||||
|
$case env::WIN32:
|
||||||
|
WString wname = name.to_wstring(mem::temp())!!;
|
||||||
|
if (!overwrite)
|
||||||
{
|
{
|
||||||
unreachable();
|
Char16[8] buff;
|
||||||
|
if (win32::getEnvironmentVariableW(wname, &buff, 8) > 0) return true;
|
||||||
}
|
}
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setenvironmentvariable
|
||||||
|
return (win32::setEnvironmentVariableW(wname, value.to_wstring(mem::temp())) ?? 1) == 0;
|
||||||
|
$case env::LIBC && !env::WIN32:
|
||||||
|
return libc::setenv(name.zstr_tcopy(), value.zstr_copy(), (int)overwrite) == 0;
|
||||||
|
$default:
|
||||||
|
return false;
|
||||||
|
$endswitch
|
||||||
};
|
};
|
||||||
$endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current user's home directory.
|
||||||
|
**/
|
||||||
|
fn String! get_home_dir(Allocator* using = mem::heap())
|
||||||
|
{
|
||||||
|
String home;
|
||||||
|
$if !env::WIN32:
|
||||||
|
home = "HOME";
|
||||||
|
$else
|
||||||
|
home = "USERPROFILE";
|
||||||
|
$endif
|
||||||
|
return get_var(home, using);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current user's config directory.
|
||||||
|
**/
|
||||||
|
fn Path! get_config_dir(Allocator* using = mem::heap())
|
||||||
|
{
|
||||||
|
@pool(using)
|
||||||
|
{
|
||||||
|
$if env::WIN32:
|
||||||
|
return path::new(get_var("AppData", .using = mem::temp()), .using = using);
|
||||||
|
$else
|
||||||
|
$if env::DARWIN:
|
||||||
|
String s = get_var("HOME", .using = mem::temp())!;
|
||||||
|
const DIR = "Library/Application Support";
|
||||||
|
$else
|
||||||
|
String s = get_var("XDG_CONFIG_HOME", .using = mem::temp()) ?? get_var("HOME", .using = mem::temp())!;
|
||||||
|
const DIR = ".config";
|
||||||
|
$endif
|
||||||
|
return path::new(s, .using = mem::temp()).append(DIR, .using = using);
|
||||||
|
$endif
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param [in] name
|
* @param [in] name
|
||||||
* @require name.len > 0
|
* @require name.len > 0
|
||||||
**/
|
**/
|
||||||
fn void clear_var(String name)
|
fn bool clear_var(String name)
|
||||||
{
|
{
|
||||||
$if env::LIBC && !env::WIN32:
|
|
||||||
@pool()
|
@pool()
|
||||||
{
|
{
|
||||||
if (libc::unsetenv(name.zstr_tcopy()))
|
$switch
|
||||||
{
|
$case env::WIN32:
|
||||||
unreachable();
|
WString wname = name.to_wstring(mem::temp())!!;
|
||||||
}
|
return win32::setEnvironmentVariableW(wname, null) == 0;
|
||||||
|
$case env::LIBC && !env::WIN32:
|
||||||
|
return libc::unsetenv(name.zstr_tcopy()) == 0;
|
||||||
|
$default:
|
||||||
|
return false;
|
||||||
|
$endswitch
|
||||||
};
|
};
|
||||||
$endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn String! executable_path(Allocator *using = mem::heap())
|
fn String! executable_path(Allocator *using = mem::heap())
|
||||||
|
|||||||
@@ -83,7 +83,15 @@ extern fn Win32_BOOL getOverlappedResult(
|
|||||||
Win32_LPDWORD lpNumberOfBytesTransferred,
|
Win32_LPDWORD lpNumberOfBytesTransferred,
|
||||||
Win32_BOOL bWait
|
Win32_BOOL bWait
|
||||||
) @extern("GetOverlappedResult");
|
) @extern("GetOverlappedResult");
|
||||||
|
extern fn Win32_DWORD getEnvironmentVariableW(
|
||||||
|
Win32_LPCWSTR lpName,
|
||||||
|
Win32_LPWSTR lpBuffer,
|
||||||
|
Win32_DWORD nSize
|
||||||
|
) @extern("GetEnvironmentVariableW");
|
||||||
|
extern fn Win32_BOOL setEnvironmentVariableW(
|
||||||
|
Win32_LPCWSTR lpName,
|
||||||
|
Win32_LPCWSTR lpValue
|
||||||
|
) @extern("SetEnvironmentVariableW");
|
||||||
|
|
||||||
struct SystemInfo
|
struct SystemInfo
|
||||||
{
|
{
|
||||||
|
|||||||
17
test/unit/stdlib/os/env.c3
Normal file
17
test/unit/stdlib/os/env.c3
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
module std::os::env @test;
|
||||||
|
|
||||||
|
fn void! set_get_unset()
|
||||||
|
{
|
||||||
|
const NAME = "C3_TEST_ENVVAR";
|
||||||
|
const VALUE = "foobar";
|
||||||
|
|
||||||
|
env::set_var(NAME, VALUE);
|
||||||
|
String v = env::get_var(NAME)!;
|
||||||
|
assert(v == VALUE, "got %s; want %s", v, VALUE);
|
||||||
|
|
||||||
|
env::clear_var(NAME);
|
||||||
|
if (try env::get_var(NAME))
|
||||||
|
{
|
||||||
|
assert(false, "environment variable should no longer exist");
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user