diff options
| -rw-r--r-- | docs/std/env.md | 74 | ||||
| -rw-r--r-- | examples/process/env.zc | 60 | ||||
| -rw-r--r-- | std/env.zc | 71 | ||||
| -rw-r--r-- | tests/std/test_env.zc | 68 |
4 files changed, 273 insertions, 0 deletions
diff --git a/docs/std/env.md b/docs/std/env.md new file mode 100644 index 0000000..b4ff5dd --- /dev/null +++ b/docs/std/env.md @@ -0,0 +1,74 @@ +# 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 +``` + +### set_overwrite + +Overwrites an exisiting env-var / creates it if it doesn't exist + +```zc +fn set_overwrite(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..8b30de3 --- /dev/null +++ b/examples/process/env.zc @@ -0,0 +1,60 @@ +//> 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"; + } + + // ---- + // set_overwrite: Overwrites an exisiting env-var / creates it if it doesn't exist + // --- + Env::set_overwrite("HELLO", "world-overwritten"); + + var hello_now = Env::get("HELLO"); + + if (hello_now.is_some()) { + println "HELLO is now {hello_now.unwrap()}"; + } + + // ---- + // 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/env.zc b/std/env.zc new file mode 100644 index 0000000..7d5fd5a --- /dev/null +++ b/std/env.zc @@ -0,0 +1,71 @@ +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, 0); + + return (ret == 0) ? EnvRes::OK() : EnvRes::ERR(); + } + + fn set_overwrite(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..94a7ee0 --- /dev/null +++ b/tests/std/test_env.zc @@ -0,0 +1,68 @@ +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_overwrite" { + var res = Env::set("TEST2", "ok2"); + assert(res == EnvRes::OK(), "res should be EnvRes::OK()"); + + var res2 = Env::set("TEST2", "ok2-no-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", "env_var should be ok2"); + + var res3 = Env::set_overwrite("TEST2", "ok2-with-ovwr"); + assert(res3 == EnvRes::OK(), "res3 should be EnvRes::OK()"); + + var env_var2 = Env::get("TEST2"); + assert(env_var2.is_some(), "env_var2 should have a value"); + assert(env_var2.unwrap() == "ok2-with-ovwr", "env_var2 should be ok2-with-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"); +} |
