summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuhaitz <zuhaitz.zechhub@gmail.com>2026-01-22 23:30:21 +0000
committerGitHub <noreply@github.com>2026-01-22 23:30:21 +0000
commit3a4a72a38675893c3a1854d05c72b957a6bd9364 (patch)
tree91c79a71830c72f8cedfa2b051e4bab4037dc5a4
parent03df9c337355dc45a14e2c2fbe3276dfe890c68d (diff)
parent2a4edc7f2c9241ec7845cecadef850a1db45b3dd (diff)
Merge pull request #97 from Burnett01/feat/std-env-for-environment-variables
feat: New std library "env" for accessing the process environment
-rw-r--r--docs/std/env.md66
-rw-r--r--examples/process/env.zc49
-rw-r--r--std.zc1
-rw-r--r--std/env.zc65
-rw-r--r--tests/std/test_env.zc61
5 files changed, 242 insertions, 0 deletions
diff --git a/docs/std/env.md b/docs/std/env.md
new file mode 100644
index 0000000..09ece60
--- /dev/null
+++ b/docs/std/env.md
@@ -0,0 +1,66 @@
+# Standard Library: Env (`std/env.zc`)
+
+`Env` is a Zen-C library for accessing the environment of the process environment.
+
+## Usage
+
+```zc
+import "std/env.zc"
+
+fn main() {
+ Env::set("HELLO", "world");
+
+ var hello = Env::get("HELLO");
+
+ if (hello.is_some()) {
+ println "Hello {hello.unwrap()}";
+ }
+}
+```
+
+## Enum
+
+```zc
+enum EnvRes {
+ ERR,
+ OK,
+}
+```
+
+## Methods
+
+### get
+
+Retrieves the env-var as borrowed string (char *) (no alloc)
+
+```zc
+fn get(name: string) -> Option<string>
+```
+
+### get_dup
+
+Retrieves the env-var as caller-owned String() (heap alloc)
+
+```zc
+fn get_dup(name: string) -> Option<String>
+```
+
+### set
+
+Sets an env-var variable
+
+```zc
+fn set(name: string, value: string) -> EnvRes
+```
+
+### unset
+
+Unsets an existing env-var
+
+```zc
+fn unset(name: string) -> EnvRes
+```
+
+---
+
+Check the ``examples`` folder for more.
diff --git a/examples/process/env.zc b/examples/process/env.zc
new file mode 100644
index 0000000..1506229
--- /dev/null
+++ b/examples/process/env.zc
@@ -0,0 +1,49 @@
+//> cflags: -Ofast
+
+import "std/env.zc"
+
+fn main() -> int {
+ // ----
+ // get: Retrieves the env-var as borrowed string (char *) (no alloc)
+ // ---
+ // @Example usage: On Linux (and some variants) PATH is already defined.
+ // ---
+ var path = Env::get("PATH");
+
+ if (path.is_some()) {
+ println "PATH is: {path.unwrap()}";
+ } else {
+ println "PATH is not set";
+ }
+
+ // ----
+ // set: Sets an env-var variable
+ // get_dup: Retrieves the env-var as caller-owned String() (heap alloc)
+ // ---
+ // @Example usage: In your terminal type "export HELLO=world" or use Env::set()
+ // ---
+ var res = Env::set("HELLO", "world");
+ //=> check res against EnvRes::OK()
+
+ var hello = Env::get_dup("HELLO");
+
+ if (hello.is_some()) {
+ var hello_str = hello.unwrap();
+ defer hello_str.free();
+
+ println "HELLO is: {hello_str.c_str()}";
+ } else {
+ println "HELLO is not set";
+ }
+
+ // ----
+ // unset: Unsets an existing env-var
+ // ---
+ Env::unset("HELLO");
+
+ var hello_now2 = Env::get("HELLO");
+
+ if (hello_now2.is_none()) {
+ println "HELLO is now unset";
+ }
+}
diff --git a/std.zc b/std.zc
index b2b1bf1..3f08207 100644
--- a/std.zc
+++ b/std.zc
@@ -16,3 +16,4 @@ import "./std/path.zc"
import "./std/mem.zc"
import "./std/stack.zc"
import "./std/queue.zc"
+import "./std/env.zc"
diff --git a/std/env.zc b/std/env.zc
new file mode 100644
index 0000000..7757be0
--- /dev/null
+++ b/std/env.zc
@@ -0,0 +1,65 @@
+import "./core.zc"
+import "./option.zc"
+import "./string.zc"
+
+raw {
+ char *_z_env_get(char *name) {
+ return getenv(name);
+ }
+
+ int _z_env_set(char *name, char *value, int overwrite) {
+ return setenv(name, value, overwrite);
+ }
+
+ int _z_env_unset(char *name) {
+ return unsetenv(name);
+ }
+}
+
+extern fn _z_env_get(name: char*) -> char*;
+extern fn _z_env_set(name: char*, value: char*, overwrite: int) -> int;
+extern fn _z_env_unset(name: char*) -> int;
+
+@derive(Eq)
+enum EnvRes {
+ ERR,
+ OK,
+}
+
+struct Env {}
+
+impl Env {
+ fn get(name: string) -> Option<string> {
+ var value: string = _z_env_get(name);
+ if (value == NULL) {
+ return Option<string>::None();
+ }
+
+ return Option<string>::Some(value);
+ }
+
+ fn get_dup(name: string) -> Option<String> {
+ var value: string = _z_env_get(name);
+ if (value == NULL) {
+ return Option<String>::None();
+ }
+
+ var v = String::from(value);
+ var o = Option<String>::Some(v);
+ v.forget();
+
+ return o;
+ }
+
+ fn set(name: string, value: string) -> EnvRes {
+ var ret: int = _z_env_set(name, value, 1);
+
+ return (ret == 0) ? EnvRes::OK() : EnvRes::ERR();
+ }
+
+ fn unset(name: string) -> EnvRes {
+ var ret: int = _z_env_unset(name);
+
+ return (ret == 0) ? EnvRes::OK() : EnvRes::ERR();
+ }
+}
diff --git a/tests/std/test_env.zc b/tests/std/test_env.zc
new file mode 100644
index 0000000..75bba3b
--- /dev/null
+++ b/tests/std/test_env.zc
@@ -0,0 +1,61 @@
+import "std.zc"
+import "std/env.zc"
+
+test "test_std_env_set_and_get" {
+ var res = Env::set("TEST1", "ok1");
+ assert(res == EnvRes::OK(), "result should be EnvRes::OK()");
+
+ var env_var = Env::get("TEST1");
+ assert(env_var.is_some(), "env_var should have a value");
+ assert(env_var.unwrap() == "ok1", "env_var should be ok1");
+}
+
+test "test_std_env_set_with_overwrite" {
+ var res = Env::set("TEST2", "ok2");
+ assert(res == EnvRes::OK(), "res should be EnvRes::OK()");
+
+ var res2 = Env::set("TEST2", "ok2-ovwr");
+ assert(res2 == EnvRes::OK(), "res2 should be EnvRes::OK()");
+
+ var env_var = Env::get("TEST2");
+ assert(env_var.is_some(), "env_var should have a value");
+ assert(env_var.unwrap() == "ok2-ovwr", "env_var should be ok2-ovwr");
+}
+
+test "test_std_env_get_dup" {
+ var res = Env::set("TEST3", "ok3");
+ assert(res == EnvRes::OK(), "result should be EnvRes::OK()");
+
+ var env_var = Env::get_dup("TEST3");
+ assert(env_var.is_some(), "env_var should have a value");
+
+ var value = env_var.unwrap();
+ assert(value.c_str() == "ok3", "value should be ok3");
+
+ value.free();
+
+ assert(value.is_empty(), "value should be empty");
+}
+
+test "test_std_env_get_and_get_dup_with_invalid" {
+ var env_var = Env::get("TEST4");
+ assert(env_var.is_none(), "env_var should not have a value");
+
+ var env_var2 = Env::get_dup("TEST4");
+ assert(env_var2.is_none(), "env_var2 should not have a value");
+}
+
+test "test_std_env_unset" {
+ var res = Env::set("TEST5", "ok5");
+ assert(res == EnvRes::OK(), "res should be EnvRes::OK()");
+
+ var env_var = Env::get("TEST5");
+ assert(env_var.is_some(), "env_var should have a value");
+ assert(env_var.unwrap() == "ok5", "env_var should be ok5");
+
+ var res2 = Env::unset("TEST5");
+ assert(res2 == EnvRes::OK(), "res2 should be EnvRes::OK()");
+
+ var env_var2 = Env::get("TEST5");
+ assert(env_var2.is_none(), "env_var2 should not have a value");
+}