diff options
| author | Zuhaitz <zuhaitz.zechhub@gmail.com> | 2026-01-22 23:30:21 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-22 23:30:21 +0000 |
| commit | 3a4a72a38675893c3a1854d05c72b957a6bd9364 (patch) | |
| tree | 91c79a71830c72f8cedfa2b051e4bab4037dc5a4 | |
| parent | 03df9c337355dc45a14e2c2fbe3276dfe890c68d (diff) | |
| parent | 2a4edc7f2c9241ec7845cecadef850a1db45b3dd (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.md | 66 | ||||
| -rw-r--r-- | examples/process/env.zc | 49 | ||||
| -rw-r--r-- | std.zc | 1 | ||||
| -rw-r--r-- | std/env.zc | 65 | ||||
| -rw-r--r-- | tests/std/test_env.zc | 61 |
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"; + } +} @@ -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"); +} |
