Skip to content

Commit

Permalink
Add environment variable manip
Browse files Browse the repository at this point in the history
  • Loading branch information
LunaTheFoxgirl committed Dec 2, 2024
1 parent aaed153 commit 3cba792
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 4 deletions.
95 changes: 95 additions & 0 deletions source/numem/core/env.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
Copyright © 2024, Inochi2D Project
Distributed under the 2-Clause BSD License, see LICENSE file.
Authors: Luna the Foxgirl
*/

/**
Numem environment managment support
*/
module numem.core.env;
import numem.string;
import numem.text.unicode;
import numem.core.memory;

version(Windows) import core.sys.windows.winbase : GetEnvironmentVariableW, SetEnvironmentVariableW;
else import core.sys.posix.stdlib : setenv, getenv;

@nogc:

/**
Interface to system environment.
*/
struct Environment {
@nogc:
private:
static nstring get(const(char)* key) {
version(Windows) {
auto utf16k = key.toUTF16;

// Try getting the size of the env var.
// if this fails, the env var is probably empty.
uint bufSize = GetEnvironmentVariableW(utf16k.ptr, null, 0);
if (bufSize == 0)
return nstring.init;

// Windows includes the null terminator, but n*string does too
// so to not have 2 null terminators, subtract 1.
nwstring envstr = nwstring(bufSize-1);
bufSize = GetEnvironmentVariableW(utf16k.ptr, envstr.ptr, envstr.length+1);

nogc_delete(utf16k);
return envstr.toUTF8;
} else {
return nstring(getenv(key));
}
}

static bool set(const(char)* key, nstring value) {
version(Windows) {
auto utf16k = key.toUTF16();
auto utf16v = value.toUTF16();
return SetEnvironmentVariableW(utf16k.ptr, utf16v.ptr);
} else {
return setenv(key, value.ptr, 1) == 0;
}
}

public:

/**
Returns the value at the given key.
Returns an empty nstring if key was not found.
*/
static ref auto opIndex(const(char)* key) {
return get(key);
}

/**
Sets the value at the given key.
*/
static void opIndexAssign(string value, const(char)* key) {
set(key, nstring(value));
}

/**
Appends to the value at the given key.
*/
static void opIndexOpAssign(string op = "~")(string value, const(char)* key) {
auto tmp = get(key);
tmp ~= value;
set(key, tmp);
}
}

@("Environment: Get and Set")
unittest {
auto envA = Environment["A"];
assert(envA.empty());

Environment["A"] = "Hello, world!";
envA = Environment["A"];
assert(envA == "Hello, world!");
}
38 changes: 38 additions & 0 deletions source/numem/string.d
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,16 @@ public:
this.set_(text);
}

/**
Creates a string from a slice of strings.
*/
@trusted
this(const(T)[][] text) {
foreach(i; 0..text.length) {
this.append_(text[i]);
}
}

/**
Creates a string from a string with a different
encoding.
Expand All @@ -152,6 +162,17 @@ public:
this = encode!selfType(decode!T(rhs, true));
}

/**
Creates a string from a slice of strings with a different
encoding.
*/
this(T)(ref auto T[] rhs) if (isSomeSafeString!T) {
foreach(i; 0..rhs.length) {
import numem.text.unicode : decode, encode;
this = encode!selfType(decode!T(rhs[i], true));
}
}

/**
Makes a copy of a string
*/
Expand Down Expand Up @@ -420,6 +441,23 @@ public:
if (this.size() > s.size()) return 1;
return strncmp(this.toCString(), s.toCString(), this.size());
}

/**
Makes a copy of the string as a C string which is not owned
by any numem object.
You are responsible for freeing the resulting string.
*/
@system
const(T)* copyToUnowned() {
import core.stdc.string : memcpy;
import core.stdc.stdlib : malloc;
size_t buflen = T.sizeof * this.realLength;

const(T)* str = cast(const(T)*)malloc(buflen);
memcpy(cast(void*)str, cast(void*)this.ptr, buflen);
return str;
}
}

alias nstring = basic_string!char;
Expand Down
44 changes: 40 additions & 4 deletions source/numem/text/unicode/package.d
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ Endianess getEndianFromBOM(codepoint c) {
UnicodeSequence decode(T)(ref auto T str, bool stripBOM = false) if (isSomeSafeString!T) {
static if (StringCharSize!T == 1)
return utf8.decode(str);
static if (StringCharSize!T == 2)
else static if (StringCharSize!T == 2)
return utf16.decode(str, stripBOM);
static if (StringCharSize!T == 4)
else static if (StringCharSize!T == 4)
return utf32.decode(str, stripBOM);
else
assert(0, "String type not supported.");
Expand All @@ -97,14 +97,50 @@ UnicodeSequence decode(T)(ref auto T str, bool stripBOM = false) if (isSomeSafeS
T encode(T)(ref auto UnicodeSequence seq, bool addBOM = false) if (isSomeNString!T) {
static if (StringCharSize!T == 1)
return utf8.encode(seq);
static if (StringCharSize!T == 2)
else static if (StringCharSize!T == 2)
return utf16.encode(seq, addBOM);
static if (StringCharSize!T == 4)
else static if (StringCharSize!T == 4)
return utf32.encode(seq, addBOM);
else
assert(0, "String type not supported.");
}

/**
Converts the given string to a UTF-8 string.
This will always create a copy.
*/
ref auto toUTF8(FromT)(ref auto T from) if (isSomeSafeString!T) {
static if (StringCharSize!T == 1)
return nstring(from);
else
return encode!nstring(decode(from, true), false);
}

/**
Converts the given string to a UTF-16 string.
This will always create a copy.
*/
ref auto toUTF16(FromT)(ref auto T from, bool addBOM = false) if (isSomeSafeString!T) {
static if (StringCharSize!T == 2)
return nwstring(from);
else
return encode!nwstring(decode(from, true), addBOM);
}

/**
Converts the given string to a UTF-32 string.
This will always create a copy.
*/
ref auto toUTF32(FromT)(ref auto T from, bool addBOM = false) if (isSomeSafeString!T) {
static if (StringCharSize!T == 2)
return ndstring(from);
else
return encode!ndstring(decode(from, true), addBOM);
}

/**
Validates whether the codepoint is within spec
*/
Expand Down

0 comments on commit 3cba792

Please sign in to comment.