2613 lines
65 KiB
C
2613 lines
65 KiB
C
// Generated by Bux C Backend v2
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
typedef const char* String;
|
|
typedef unsigned char uint8;
|
|
typedef unsigned short uint16;
|
|
typedef unsigned int uint32;
|
|
typedef unsigned long long uint64;
|
|
typedef signed char int8;
|
|
typedef short int16;
|
|
typedef long long int64;
|
|
typedef float float32;
|
|
typedef double float64;
|
|
typedef char char8;
|
|
|
|
void* bux_alloc(unsigned int size);
|
|
void bux_free(void* ptr);
|
|
|
|
typedef struct TaskHandle TaskHandle;
|
|
typedef struct Mutex Mutex;
|
|
typedef struct RwLock RwLock;
|
|
typedef struct JsonValue JsonValue;
|
|
typedef struct JsonParser JsonParser;
|
|
typedef struct StringBuilder StringBuilder;
|
|
typedef struct Channel_int Channel_int;
|
|
typedef struct Channel_float64 Channel_float64;
|
|
|
|
typedef enum {
|
|
Result_Ok,
|
|
Result_Err
|
|
} Result_Tag;
|
|
|
|
typedef union {
|
|
int Ok_0;
|
|
String Err_0;
|
|
} Result_Data;
|
|
|
|
typedef struct {
|
|
Result_Tag tag;
|
|
Result_Data data;
|
|
} Result;
|
|
|
|
typedef enum {
|
|
Option_Some,
|
|
Option_None
|
|
} Option_Tag;
|
|
|
|
typedef union {
|
|
int Some_0;
|
|
} Option_Data;
|
|
|
|
typedef struct {
|
|
Option_Tag tag;
|
|
Option_Data data;
|
|
} Option;
|
|
|
|
typedef enum {
|
|
JwtAlg_HS256,
|
|
JwtAlg_HS384,
|
|
JwtAlg_HS512,
|
|
JwtAlg_RS256,
|
|
JwtAlg_RS384,
|
|
JwtAlg_RS512,
|
|
JwtAlg_ES256,
|
|
JwtAlg_ES384,
|
|
JwtAlg_EdDSA
|
|
} JwtAlg_Tag;
|
|
|
|
typedef struct {
|
|
JwtAlg_Tag tag;
|
|
} JwtAlg;
|
|
|
|
#define JsonTagNull 0
|
|
#define JsonTagBool 1
|
|
#define JsonTagNumber 2
|
|
#define JsonTagString 3
|
|
#define JsonTagArray 4
|
|
#define JsonTagObject 5
|
|
#define AES_KEY_SIZE 32
|
|
#define AES_IV_SIZE 16
|
|
#define AES_GCM_TAG_SIZE 16
|
|
#define ED25519_PUBKEY_SIZE 32
|
|
#define ED25519_PRIVKEY_SIZE 32
|
|
#define ED25519_SIG_SIZE 64
|
|
|
|
struct TaskHandle {
|
|
void* handle;
|
|
};
|
|
|
|
struct Mutex {
|
|
void* handle;
|
|
};
|
|
|
|
struct RwLock {
|
|
void* handle;
|
|
};
|
|
|
|
struct JsonValue {
|
|
int tag;
|
|
bool boolVal;
|
|
float64 numVal;
|
|
String strVal;
|
|
JsonValue* arrData;
|
|
uint arrLen;
|
|
uint arrCap;
|
|
String* objKeys;
|
|
JsonValue* objValues;
|
|
uint objLen;
|
|
uint objCap;
|
|
};
|
|
|
|
struct JsonParser {
|
|
String src;
|
|
uint pos;
|
|
uint len;
|
|
String error;
|
|
};
|
|
|
|
struct StringBuilder {
|
|
void* handle;
|
|
};
|
|
|
|
struct Channel_int {
|
|
void* handle;
|
|
};
|
|
|
|
struct Channel_float64 {
|
|
void* handle;
|
|
};
|
|
|
|
bool DirExists(String path);
|
|
bool Mkdir(String path);
|
|
String* ListDir(String dir, String ext, int* count);
|
|
String ReadFile(String path);
|
|
bool WriteFile(String path, String content);
|
|
bool FileExists(String path);
|
|
float64 Sqrt(float64 x);
|
|
float64 Pow(float64 x, float64 y);
|
|
int64 Abs(int64 n);
|
|
float64 AbsF(float64 f);
|
|
int64 Min(int64 a, int64 b);
|
|
int64 Max(int64 a, int64 b);
|
|
float64 MinF(float64 a, float64 b);
|
|
float64 MaxF(float64 a, float64 b);
|
|
void* Alloc(uint size);
|
|
void* Realloc(void* ptr, uint size);
|
|
void Free(void* ptr);
|
|
bool MemEq(void* a, void* b, uint size);
|
|
String Path_Join(String a, String b);
|
|
String Path_Parent(String path);
|
|
String Path_Ext(String path);
|
|
void Task_Init(int num_workers);
|
|
TaskHandle Task_Spawn(void* fn, void* arg);
|
|
void Task_Wait(TaskHandle t);
|
|
void Task_Sleep(int64 ms);
|
|
void Task_Yield();
|
|
int Task_CurrentId();
|
|
void Task_Shutdown();
|
|
int Os_ArgsCount();
|
|
String Os_Args(int index);
|
|
String Os_GetEnv(String name);
|
|
bool Os_SetEnv(String name, String value);
|
|
String Os_GetCwd();
|
|
bool Os_Chdir(String path);
|
|
int64 Time_NowMs();
|
|
int64 Time_NowUs();
|
|
void Time_SleepMs(int64 ms);
|
|
int Process_Run(String cmd);
|
|
String Process_Output(String cmd);
|
|
int Net_Create();
|
|
bool Net_SetReuse(int fd);
|
|
bool Net_Bind(int fd, String addr, int port);
|
|
bool Net_Listen(int fd, int backlog);
|
|
int Net_Accept(int fd);
|
|
bool Net_Connect(int fd, String addr, int port);
|
|
int Net_Send(int fd, String data);
|
|
String Net_Recv(int fd, int maxLen);
|
|
bool Net_Close(int fd);
|
|
String Net_LastError();
|
|
String Fmt_Fmt3(String tmpl, String a1, String a2, String a3);
|
|
String Fmt_Fmt2(String tmpl, String a1, String a2);
|
|
String Fmt_FmtFloat(String tmpl, float64 val);
|
|
String Fmt_FmtBool(String tmpl, bool val);
|
|
String Fmt_FmtInt(String tmpl, int64 val);
|
|
String Fmt_Fmt1(String tmpl, String a1);
|
|
String Fmt_Format(String tmpl, String* argStrs, int argCount);
|
|
String Crypto_Sha256(String data);
|
|
String Crypto_HmacSha256(String key, String message);
|
|
String Crypto_RandomBytes(int n);
|
|
String Crypto_Base64Encode(String s);
|
|
String Crypto_HmacSha256Raw(String key, String message);
|
|
String Crypto_Base64Decode(String s);
|
|
Mutex Mutex_New();
|
|
void Mutex_Lock(Mutex* m);
|
|
void Mutex_Unlock(Mutex* m);
|
|
void Mutex_Free(Mutex* m);
|
|
RwLock RwLock_New();
|
|
void RwLock_ReadLock(RwLock* rw);
|
|
void RwLock_WriteLock(RwLock* rw);
|
|
void RwLock_Unlock(RwLock* rw);
|
|
void RwLock_Free(RwLock* rw);
|
|
void Test_Exit(int code);
|
|
void Test_Assert(bool cond);
|
|
void Test_AssertEqInt(int a, int b);
|
|
void Test_AssertTrue(bool cond);
|
|
void Test_AssertFalse(bool cond);
|
|
void Test_Fail(String msg);
|
|
Result Result_NewOk(int value);
|
|
Result Result_NewErr(String msg);
|
|
bool Result_IsOk(Result r);
|
|
bool Result_IsErr(Result r);
|
|
int Result_Unwrap(Result r);
|
|
int Result_UnwrapOr(Result r, int fallback);
|
|
Option Option_NewSome(int value);
|
|
Option Option_NewNone();
|
|
bool Option_IsSome(Option o);
|
|
bool Option_IsNone(Option o);
|
|
int Option_Unwrap(Option o);
|
|
int Option_UnwrapOr(Option o, int fallback);
|
|
JsonValue Json_Null();
|
|
JsonValue Json_Bool(bool b);
|
|
JsonValue Json_Number(float64 n);
|
|
JsonValue Json_String(String s);
|
|
JsonValue Json_Array();
|
|
JsonValue Json_Object();
|
|
uint Json_ArrayLen(JsonValue v);
|
|
JsonValue Json_ArrayGet(JsonValue v, uint index);
|
|
void Json_ArrayPush(JsonValue* self, JsonValue val);
|
|
uint Json_ObjectLen(JsonValue v);
|
|
JsonValue Json_ObjectGet(JsonValue v, String key);
|
|
bool Json_ObjectHas(JsonValue v, String key);
|
|
void Json_ObjectSet(JsonValue* self, String key, JsonValue val);
|
|
bool Json_IsNull(JsonValue v);
|
|
bool Json_AsBool(JsonValue v);
|
|
float64 Json_AsNumber(JsonValue v);
|
|
String Json_AsString(JsonValue v);
|
|
int JsonParser_Peek(JsonParser* p);
|
|
void JsonParser_Advance(JsonParser* p);
|
|
void JsonParser_SkipWhitespace(JsonParser* p);
|
|
bool JsonParser_Match(JsonParser* p, String expected);
|
|
String JsonParser_ParseString(JsonParser* p);
|
|
JsonValue JsonParser_ParseNumber(JsonParser* p);
|
|
JsonValue JsonParser_ParseArray(JsonParser* p);
|
|
JsonValue JsonParser_ParseObject(JsonParser* p);
|
|
JsonValue JsonParser_ParseValue(JsonParser* p);
|
|
JsonValue Json_Parse(String s);
|
|
void Json_StringifyImpl(StringBuilder* sb, JsonValue v);
|
|
String Json_Stringify(JsonValue v);
|
|
String Hash_Sha1(String data);
|
|
String Hash_Sha256(String data);
|
|
String Hash_Sha384(String data);
|
|
String Hash_Sha512(String data);
|
|
void Hash_Sha256Raw(String data, void* out);
|
|
void Hash_Sha384Raw(String data, void* out);
|
|
void Hash_Sha512Raw(String data, void* out);
|
|
int Hash_Sha1Size();
|
|
int Hash_Sha256Size();
|
|
int Hash_Sha384Size();
|
|
int Hash_Sha512Size();
|
|
String Base64_Encode(String s);
|
|
String Base64_Decode(String s);
|
|
String Base64URL_Encode(String s);
|
|
String Base64URL_Decode(String s);
|
|
String Hmac_Sha256(String key, String message);
|
|
void Hmac_Sha256Raw(String key, String message, void* out);
|
|
String Hmac_Sha256Base64(String key, String message);
|
|
String Hmac_Sha384(String key, String message);
|
|
void Hmac_Sha384Raw(String key, String message, void* out);
|
|
String Hmac_Sha384Base64(String key, String message);
|
|
String Hmac_Sha512(String key, String message);
|
|
void Hmac_Sha512Raw(String key, String message, void* out);
|
|
String Hmac_Sha512Base64(String key, String message);
|
|
String Random_Bytes(int n);
|
|
String Random_Hex(int n);
|
|
String Random_Base64(int n);
|
|
uint Random_Uint32();
|
|
String Aes_GenerateKey();
|
|
String Aes_GenerateIV();
|
|
String Aes_CbcEncrypt(String plain, String key, String iv);
|
|
String Aes_CbcDecrypt(String cipher, String key, String iv);
|
|
String Aes_GcmEncrypt(String plain, String key, String iv, void* tag);
|
|
String Aes_GcmDecrypt(String cipher, String key, String iv, String tag);
|
|
String Jwt_MakeHeader(JwtAlg alg);
|
|
String Jwt_Sign(JwtAlg alg, String signingInput, String key);
|
|
bool Jwt_Verify(JwtAlg alg, String signingInput, String signatureB64, String key);
|
|
String Jwt_Encode(String headerJson, String payloadJson, JwtAlg alg, String key);
|
|
bool Jwt_Decode(String token, JwtAlg alg, String key, String* headerOut, String* payloadOut);
|
|
String Jwt_EncodeHS256(String payloadJson, String secret);
|
|
String Jwt_EncodeHS384(String payloadJson, String secret);
|
|
String Jwt_EncodeHS512(String payloadJson, String secret);
|
|
String Jwt_EncodeRS256(String payloadJson, String pemPrivateKey);
|
|
String Jwt_EncodeES256(String payloadJson, String pemPrivateKey);
|
|
String Jwt_EncodeEdDSA(String payloadJson, String rawPrivKey);
|
|
String Ecdsa_SignP256(String pemPrivateKey, String data);
|
|
String Ecdsa_SignP256Base64(String pemPrivateKey, String data);
|
|
bool Ecdsa_VerifyP256(String pemPublicKey, String data, String signature);
|
|
bool Ecdsa_VerifyP256Base64(String pemPublicKey, String data, String signatureB64);
|
|
String Ecdsa_SignP384(String pemPrivateKey, String data);
|
|
String Ecdsa_SignP384Base64(String pemPrivateKey, String data);
|
|
bool Ecdsa_VerifyP384(String pemPublicKey, String data, String signature);
|
|
bool Ecdsa_VerifyP384Base64(String pemPublicKey, String data, String signatureB64);
|
|
bool Ed25519_Keypair(void* pubKey, void* privKey);
|
|
String Ed25519_KeypairBase64();
|
|
String Ed25519_Sign(String privKey, String data);
|
|
String Ed25519_SignBase64(String privKey, String data);
|
|
bool Ed25519_Verify(String pubKey, String signature, String data);
|
|
bool Ed25519_VerifyBase64(String pubKey, String signatureB64, String data);
|
|
String Rsa_SignSha256(String pemPrivateKey, String data);
|
|
String Rsa_SignSha384(String pemPrivateKey, String data);
|
|
String Rsa_SignSha512(String pemPrivateKey, String data);
|
|
String Rsa_SignSha256Base64(String pemPrivateKey, String data);
|
|
String Rsa_SignSha384Base64(String pemPrivateKey, String data);
|
|
String Rsa_SignSha512Base64(String pemPrivateKey, String data);
|
|
bool Rsa_VerifySha256(String pemPublicKey, String data, String signature);
|
|
bool Rsa_VerifySha384(String pemPublicKey, String data, String signature);
|
|
bool Rsa_VerifySha512(String pemPublicKey, String data, String signature);
|
|
bool Rsa_VerifySha256Base64(String pemPublicKey, String data, String signatureB64);
|
|
bool Rsa_VerifySha384Base64(String pemPublicKey, String data, String signatureB64);
|
|
bool Rsa_VerifySha512Base64(String pemPublicKey, String data, String signatureB64);
|
|
uint String_Len(String s);
|
|
bool String_IsNull(String s);
|
|
bool String_Eq(String a, String b);
|
|
String String_Concat(String a, String b);
|
|
String String_Copy(String s);
|
|
bool String_StartsWith(String s, String prefix);
|
|
bool String_EndsWith(String s, String suffix);
|
|
bool String_Contains(String s, String substr);
|
|
String String_Slice(String s, uint start, uint len);
|
|
String String_Trim(String s);
|
|
String String_TrimLeft(String s);
|
|
String String_TrimRight(String s);
|
|
String String_FromInt(int64 n);
|
|
int64 String_ToInt(String s);
|
|
StringBuilder StringBuilder_New();
|
|
StringBuilder StringBuilder_NewCap(uint cap);
|
|
void StringBuilder_Append(StringBuilder* sb, String s);
|
|
void StringBuilder_AppendInt(StringBuilder* sb, int64 n);
|
|
void StringBuilder_AppendFloat(StringBuilder* sb, float64 f);
|
|
void StringBuilder_AppendChar(StringBuilder* sb, char8 c);
|
|
String StringBuilder_Build(StringBuilder* sb);
|
|
void StringBuilder_Free(StringBuilder* sb);
|
|
uint String_SplitCount(String s, String delim);
|
|
String String_SplitPart(String s, String delim, uint index);
|
|
String String_Join2(String a, String b, String sep);
|
|
String String_Chars(String s, uint index);
|
|
String String_Find(String haystack, String needle);
|
|
uint String_Offset(String pos, String base);
|
|
String String_Replace(String s, String old, String new);
|
|
float64 String_ToFloat(String s);
|
|
String String_FromBool(bool b);
|
|
String String_FromFloat(float64 f);
|
|
String String_Format1(String pattern, String a0);
|
|
String String_Format2(String pattern, String a0, String a1);
|
|
String String_Format3(String pattern, String a0, String a1, String a2);
|
|
void Channel_SendInt(Channel_int* ch, int value);
|
|
int Channel_RecvInt(Channel_int* ch);
|
|
void Channel_SendFloat64(Channel_float64* ch, float64 value);
|
|
float64 Channel_RecvFloat64(Channel_float64* ch);
|
|
int Main();
|
|
|
|
int bux_dir_exists(String path);
|
|
int bux_mkdir_if_needed(String path);
|
|
String* bux_list_dir(String dir, String ext, int* out_count);
|
|
void PrintLine(String s);
|
|
void Print(String s);
|
|
void PrintInt(int n);
|
|
void PrintInt64(int64 n);
|
|
void PrintFloat(float64 f);
|
|
void PrintBool(bool b);
|
|
String ReadLine();
|
|
String bux_read_file(String path);
|
|
int bux_write_file(String path, String content);
|
|
int bux_file_exists(String path);
|
|
float64 bux_sqrt(float64 x);
|
|
float64 bux_pow(float64 x, float64 y);
|
|
int64 bux_abs_i64(int64 x);
|
|
float64 bux_abs_f64(float64 x);
|
|
int64 bux_min_i64(int64 a, int64 b);
|
|
int64 bux_max_i64(int64 a, int64 b);
|
|
float64 bux_min_f64(float64 a, float64 b);
|
|
float64 bux_max_f64(float64 a, float64 b);
|
|
void* bux_alloc(uint size);
|
|
void* bux_realloc(void* ptr, uint size);
|
|
void bux_free(void* ptr);
|
|
int bux_mem_eq(void* a, void* b, uint size);
|
|
String bux_path_join(String a, String b);
|
|
String bux_path_parent(String path);
|
|
String bux_path_ext(String path);
|
|
void bux_task_init(int num_workers);
|
|
void* bux_task_spawn(void* fn, void* arg);
|
|
void bux_task_join(void* handle);
|
|
void bux_task_sleep(int64 ms);
|
|
void bux_task_yield();
|
|
int bux_task_current_id();
|
|
void bux_task_shutdown();
|
|
int bux_argc();
|
|
String bux_argv(int index);
|
|
String bux_getenv(String name);
|
|
int bux_setenv(String name, String value);
|
|
String bux_getcwd();
|
|
int bux_chdir(String path);
|
|
int64 bux_time_ms();
|
|
int64 bux_time_us();
|
|
void bux_sleep_ms(int64 ms);
|
|
int bux_process_run(String cmd);
|
|
String bux_process_output(String cmd);
|
|
int bux_socket_create();
|
|
int bux_socket_reuse(int fd);
|
|
int bux_socket_bind(int fd, String addr, int port);
|
|
int bux_socket_listen(int fd, int backlog);
|
|
int bux_socket_accept(int fd);
|
|
int bux_socket_connect(int fd, String addr, int port);
|
|
int bux_socket_send(int fd, String data, int len);
|
|
String bux_socket_recv(int fd, int maxLen);
|
|
int bux_socket_close(int fd);
|
|
String bux_socket_error();
|
|
void* bux_alloc(uint size);
|
|
int64 bux_str_to_int(String s);
|
|
uint bux_strlen(String s);
|
|
void bux_sha256(String data, int len, void* out);
|
|
void bux_hmac_sha256(String key, int keylen, String msg, int msglen, void* out);
|
|
int bux_random_bytes(void* buf, int len);
|
|
String bux_base64_encode(String data, int len);
|
|
String bux_base64_decode(String data, int len, int* outlen);
|
|
String bux_bytes_to_hex(void* data, int len);
|
|
void* bux_mutex_new();
|
|
void bux_mutex_lock(void* handle);
|
|
void bux_mutex_unlock(void* handle);
|
|
void bux_mutex_free(void* handle);
|
|
void* bux_rwlock_new();
|
|
void bux_rwlock_rdlock(void* handle);
|
|
void bux_rwlock_wrlock(void* handle);
|
|
void bux_rwlock_unlock(void* handle);
|
|
void bux_rwlock_free(void* handle);
|
|
void bux_exit(int code);
|
|
void bux_assert(int cond, String file, int line, String expr);
|
|
void bux_sha1(String data, int len, void* out);
|
|
void bux_sha256(String data, int len, void* out);
|
|
void bux_sha384(String data, int len, void* out);
|
|
void bux_sha512(String data, int len, void* out);
|
|
String bux_bytes_to_hex(void* data, int len);
|
|
String bux_base64_encode(String data, int len);
|
|
String bux_base64_decode(String data, int len, int* outlen);
|
|
String bux_base64url_encode(String data, int len);
|
|
String bux_base64url_decode(String data, int len, int* outlen);
|
|
void bux_hmac_sha256(String key, int keylen, String msg, int msglen, void* out);
|
|
void bux_hmac_sha384(String key, int keylen, String msg, int msglen, void* out);
|
|
void bux_hmac_sha512(String key, int keylen, String msg, int msglen, void* out);
|
|
String bux_bytes_to_hex(void* data, int len);
|
|
String bux_base64_encode(String data, int len);
|
|
int bux_random_bytes(void* buf, int len);
|
|
String bux_base64_encode(String data, int len);
|
|
String bux_bytes_to_hex(void* data, int len);
|
|
int bux_random_bytes(void* buf, int len);
|
|
String bux_aes_256_cbc_encrypt(String plain, int plainlen, String key, String iv, int* outlen);
|
|
String bux_aes_256_cbc_decrypt(String cipher, int cipherlen, String key, String iv, int* outlen);
|
|
String bux_aes_256_gcm_encrypt(String plain, int plainlen, String key, String iv, void* tag, int* outlen);
|
|
String bux_aes_256_gcm_decrypt(String cipher, int cipherlen, String key, String iv, String tag, int* outlen);
|
|
String bux_base64_encode(String data, int len);
|
|
uint bux_str_split_count(String s, String delim);
|
|
String bux_str_split_part(String s, String delim, uint index);
|
|
String bux_ecdsa_sign_p256(String key, int keylen, String data, int datalen, int* outlen);
|
|
int bux_ecdsa_verify_p256(String key, int keylen, String data, int datalen, String sig, int siglen);
|
|
String bux_ecdsa_sign_p384(String key, int keylen, String data, int datalen, int* outlen);
|
|
int bux_ecdsa_verify_p384(String key, int keylen, String data, int datalen, String sig, int siglen);
|
|
String bux_base64_encode(String data, int len);
|
|
String bux_base64_decode(String data, int len, int* outlen);
|
|
int bux_ed25519_keypair(void* pubKey, void* privKey);
|
|
int bux_ed25519_sign(String privKey, String data, int datalen, void* sig);
|
|
int bux_ed25519_verify(String pubKey, String sig, String data, int datalen);
|
|
String bux_base64_encode(String data, int len);
|
|
String bux_base64_decode(String data, int len, int* outlen);
|
|
String bux_rsa_sign_sha256(String key, int keylen, String data, int datalen, int* outlen);
|
|
String bux_rsa_sign_sha384(String key, int keylen, String data, int datalen, int* outlen);
|
|
String bux_rsa_sign_sha512(String key, int keylen, String data, int datalen, int* outlen);
|
|
int bux_rsa_verify_sha256(String key, int keylen, String data, int datalen, String sig, int siglen);
|
|
int bux_rsa_verify_sha384(String key, int keylen, String data, int datalen, String sig, int siglen);
|
|
int bux_rsa_verify_sha512(String key, int keylen, String data, int datalen, String sig, int siglen);
|
|
String bux_base64_encode(String data, int len);
|
|
String bux_base64_decode(String data, int len, int* outlen);
|
|
uint bux_strlen(String s);
|
|
int bux_strcmp(String a, String b);
|
|
int bux_strncmp(String a, String b, uint n);
|
|
char8* bux_strcpy(char8* dest, String src);
|
|
char8* bux_strcat(char8* dest, String src);
|
|
char8* bux_strncpy(char8* dest, String src, uint n);
|
|
String bux_strstr(String haystack, String needle);
|
|
int bux_str_contains(String haystack, String needle);
|
|
uint bux_str_offset(String pos, String base);
|
|
int bux_str_is_null(String s);
|
|
String bux_str_slice(String s, uint start, uint len);
|
|
String bux_str_trim_left(String s);
|
|
String bux_str_trim_right(String s);
|
|
String bux_str_trim(String s);
|
|
String bux_int_to_str(int64 n);
|
|
int64 bux_str_to_int(String s);
|
|
void* bux_sb_new(uint initial_cap);
|
|
void bux_sb_append(void* sb, String s);
|
|
void bux_sb_append_int(void* sb, int64 n);
|
|
void bux_sb_append_float(void* sb, float64 f);
|
|
void bux_sb_append_char(void* sb, char8 c);
|
|
String bux_sb_build(void* sb);
|
|
void bux_sb_free(void* sb);
|
|
uint bux_str_split_count(String s, String delim);
|
|
String bux_str_split_part(String s, String delim, uint index);
|
|
String bux_str_join2(String a, String b, String sep);
|
|
String bux_float_to_string(float64 f);
|
|
String bux_str_format(String pattern, String a0, String a1, String a2, String a3, String a4, String a5, String a6, String a7);
|
|
float64 bux_str_to_float(String s);
|
|
void bux_bounds_check(uint index, uint len);
|
|
void* bux_alloc(uint size);
|
|
void* bux_realloc(void* ptr, uint size);
|
|
void bux_free(void* ptr);
|
|
void bux_bounds_check(uint index, uint len);
|
|
void* bux_channel_new(int64 capacity, int64 elem_size);
|
|
void bux_channel_send(void* handle, void* elem);
|
|
int bux_channel_recv(void* handle, void* out);
|
|
void bux_channel_close(void* handle);
|
|
void bux_channel_free(void* handle);
|
|
uint bux_hash_bytes(void* ptr, uint size);
|
|
uint bux_hash_string(String s);
|
|
uint bux_hash_bytes(void* ptr, uint size);
|
|
int bux_mem_eq(void* a, void* b, uint size);
|
|
void* bux_alloc(uint size);
|
|
void bux_free(void* ptr);
|
|
|
|
bool DirExists(String path) {
|
|
return bux_dir_exists(path) != 0;
|
|
|
|
}
|
|
|
|
bool Mkdir(String path) {
|
|
return bux_mkdir_if_needed(path) != 0;
|
|
|
|
}
|
|
|
|
String* ListDir(String dir, String ext, int* count) {
|
|
return bux_list_dir(dir, ext, count);
|
|
|
|
}
|
|
|
|
String ReadFile(String path) {
|
|
return bux_read_file(path);
|
|
|
|
}
|
|
|
|
bool WriteFile(String path, String content) {
|
|
int r = bux_write_file(path, content);
|
|
return r != 0;
|
|
|
|
}
|
|
|
|
bool FileExists(String path) {
|
|
int r = bux_file_exists(path);
|
|
return r != 0;
|
|
|
|
}
|
|
|
|
float64 Sqrt(float64 x) {
|
|
return bux_sqrt(x);
|
|
|
|
}
|
|
|
|
float64 Pow(float64 x, float64 y) {
|
|
return bux_pow(x, y);
|
|
|
|
}
|
|
|
|
int64 Abs(int64 n) {
|
|
return bux_abs_i64(n);
|
|
|
|
}
|
|
|
|
float64 AbsF(float64 f) {
|
|
return bux_abs_f64(f);
|
|
|
|
}
|
|
|
|
int64 Min(int64 a, int64 b) {
|
|
return bux_min_i64(a, b);
|
|
|
|
}
|
|
|
|
int64 Max(int64 a, int64 b) {
|
|
return bux_max_i64(a, b);
|
|
|
|
}
|
|
|
|
float64 MinF(float64 a, float64 b) {
|
|
return bux_min_f64(a, b);
|
|
|
|
}
|
|
|
|
float64 MaxF(float64 a, float64 b) {
|
|
return bux_max_f64(a, b);
|
|
|
|
}
|
|
|
|
void* Alloc(uint size) {
|
|
return bux_alloc(size);
|
|
|
|
}
|
|
|
|
void* Realloc(void* ptr, uint size) {
|
|
return bux_realloc(ptr, size);
|
|
|
|
}
|
|
|
|
void Free(void* ptr) {
|
|
bux_free(ptr);
|
|
|
|
}
|
|
|
|
bool MemEq(void* a, void* b, uint size) {
|
|
return bux_mem_eq(a, b, size) != 0;
|
|
|
|
}
|
|
|
|
String Path_Join(String a, String b) {
|
|
return bux_path_join(a, b);
|
|
|
|
}
|
|
|
|
String Path_Parent(String path) {
|
|
return bux_path_parent(path);
|
|
|
|
}
|
|
|
|
String Path_Ext(String path) {
|
|
return bux_path_ext(path);
|
|
|
|
}
|
|
|
|
void Task_Init(int num_workers) {
|
|
bux_task_init(num_workers);
|
|
|
|
}
|
|
|
|
TaskHandle Task_Spawn(void* fn, void* arg) {
|
|
return ((TaskHandle){.handle = bux_task_spawn(fn, arg)});
|
|
|
|
}
|
|
|
|
void Task_Wait(TaskHandle t) {
|
|
bux_task_join(t.handle);
|
|
|
|
}
|
|
|
|
void Task_Sleep(int64 ms) {
|
|
bux_task_sleep(ms);
|
|
|
|
}
|
|
|
|
void Task_Yield() {
|
|
bux_task_yield();
|
|
|
|
}
|
|
|
|
int Task_CurrentId() {
|
|
return bux_task_current_id();
|
|
|
|
}
|
|
|
|
void Task_Shutdown() {
|
|
bux_task_shutdown();
|
|
|
|
}
|
|
|
|
int Os_ArgsCount() {
|
|
return bux_argc();
|
|
|
|
}
|
|
|
|
String Os_Args(int index) {
|
|
return bux_argv(index);
|
|
|
|
}
|
|
|
|
String Os_GetEnv(String name) {
|
|
return bux_getenv(name);
|
|
|
|
}
|
|
|
|
bool Os_SetEnv(String name, String value) {
|
|
return bux_setenv(name, value) == 0;
|
|
|
|
}
|
|
|
|
String Os_GetCwd() {
|
|
return bux_getcwd();
|
|
|
|
}
|
|
|
|
bool Os_Chdir(String path) {
|
|
return bux_chdir(path) == 0;
|
|
|
|
}
|
|
|
|
int64 Time_NowMs() {
|
|
return bux_time_ms();
|
|
|
|
}
|
|
|
|
int64 Time_NowUs() {
|
|
return bux_time_us();
|
|
|
|
}
|
|
|
|
void Time_SleepMs(int64 ms) {
|
|
bux_sleep_ms(ms);
|
|
|
|
}
|
|
|
|
int Process_Run(String cmd) {
|
|
return bux_process_run(cmd);
|
|
|
|
}
|
|
|
|
String Process_Output(String cmd) {
|
|
return bux_process_output(cmd);
|
|
|
|
}
|
|
|
|
int Net_Create() {
|
|
return bux_socket_create();
|
|
|
|
}
|
|
|
|
bool Net_SetReuse(int fd) {
|
|
return bux_socket_reuse(fd) == 0;
|
|
|
|
}
|
|
|
|
bool Net_Bind(int fd, String addr, int port) {
|
|
return bux_socket_bind(fd, addr, port) == 0;
|
|
|
|
}
|
|
|
|
bool Net_Listen(int fd, int backlog) {
|
|
return bux_socket_listen(fd, backlog) == 0;
|
|
|
|
}
|
|
|
|
int Net_Accept(int fd) {
|
|
return bux_socket_accept(fd);
|
|
|
|
}
|
|
|
|
bool Net_Connect(int fd, String addr, int port) {
|
|
return bux_socket_connect(fd, addr, port) == 0;
|
|
|
|
}
|
|
|
|
int Net_Send(int fd, String data) {
|
|
return bux_socket_send(fd, data, ((int)bux_strlen(data)));
|
|
|
|
}
|
|
|
|
String Net_Recv(int fd, int maxLen) {
|
|
return bux_socket_recv(fd, maxLen);
|
|
|
|
}
|
|
|
|
bool Net_Close(int fd) {
|
|
return bux_socket_close(fd) == 0;
|
|
|
|
}
|
|
|
|
String Net_LastError() {
|
|
return bux_socket_error();
|
|
|
|
}
|
|
|
|
String Fmt_Fmt3(String tmpl, String a1, String a2, String a3) {
|
|
String* args = ((String*)bux_alloc(3 * sizeof(String)));
|
|
args[0] = a1;
|
|
args[1] = a2;
|
|
args[2] = a3;
|
|
return Fmt_Format(tmpl, args, 3);
|
|
|
|
}
|
|
|
|
String Fmt_Fmt2(String tmpl, String a1, String a2) {
|
|
String* args = ((String*)bux_alloc(2 * sizeof(String)));
|
|
args[0] = a1;
|
|
args[1] = a2;
|
|
return Fmt_Format(tmpl, args, 2);
|
|
|
|
}
|
|
|
|
String Fmt_FmtFloat(String tmpl, float64 val) {
|
|
String s = String_FromFloat(val);
|
|
return Fmt_Fmt1(tmpl, s);
|
|
|
|
}
|
|
|
|
String Fmt_FmtBool(String tmpl, bool val) {
|
|
String s = String_FromBool(val);
|
|
return Fmt_Fmt1(tmpl, s);
|
|
|
|
}
|
|
|
|
String Fmt_FmtInt(String tmpl, int64 val) {
|
|
String s = String_FromInt(val);
|
|
return Fmt_Fmt1(tmpl, s);
|
|
|
|
}
|
|
|
|
String Fmt_Fmt1(String tmpl, String a1) {
|
|
String* args = ((String*)bux_alloc(sizeof(String)));
|
|
args[0] = a1;
|
|
return Fmt_Format(tmpl, args, 1);
|
|
|
|
}
|
|
|
|
String Fmt_Format(String tmpl, String* argStrs, int argCount) {
|
|
StringBuilder sb = StringBuilder_New();
|
|
uint i = 0;
|
|
uint tmplLen = bux_strlen(tmpl);
|
|
while (i < tmplLen) {
|
|
String ch = String_Chars(tmpl, i);
|
|
if (String_Eq(ch, "{")) {
|
|
uint digitIdx = i + 1;
|
|
if (digitIdx < tmplLen) {
|
|
String digitCh = String_Chars(tmpl, digitIdx);
|
|
int64 d = bux_str_to_int(digitCh);
|
|
if (d >= 0 && d < ((int64)argCount)) {
|
|
i = i + 2;
|
|
if (i < tmplLen) {
|
|
String closeCh = String_Chars(tmpl, i);
|
|
if (String_Eq(closeCh, "}")) {
|
|
i = i + 1;
|
|
String argStr = argStrs[((uint)d)];
|
|
StringBuilder_Append(&sb, argStr);
|
|
continue;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
StringBuilder_Append(&sb, ch);
|
|
i = i + 1;
|
|
}
|
|
return StringBuilder_Build(&sb);
|
|
|
|
}
|
|
|
|
String Crypto_Sha256(String data) {
|
|
int len = ((int)String_Len(data));
|
|
void* hashBuf = Alloc(32);
|
|
bux_sha256(data, len, hashBuf);
|
|
String result = bux_bytes_to_hex(((void*)hashBuf), 32);
|
|
Free(hashBuf);
|
|
return result;
|
|
|
|
}
|
|
|
|
String Crypto_HmacSha256(String key, String message) {
|
|
int keylen = ((int)String_Len(key));
|
|
int msglen = ((int)String_Len(message));
|
|
void* hmacBuf = Alloc(32);
|
|
bux_hmac_sha256(key, keylen, message, msglen, hmacBuf);
|
|
String result = bux_bytes_to_hex(((void*)hmacBuf), 32);
|
|
Free(hmacBuf);
|
|
return result;
|
|
|
|
}
|
|
|
|
String Crypto_RandomBytes(int n) {
|
|
if (n <= 0) {
|
|
return "";
|
|
}
|
|
|
|
void* buf = Alloc(((uint)n));
|
|
if (bux_random_bytes(buf, n) != 1) {
|
|
Free(buf);
|
|
return "";
|
|
}
|
|
|
|
String result = bux_base64_encode(((String)buf), n);
|
|
Free(buf);
|
|
return result;
|
|
|
|
}
|
|
|
|
String Crypto_Base64Encode(String s) {
|
|
return bux_base64_encode(s, ((int)String_Len(s)));
|
|
|
|
}
|
|
|
|
String Crypto_HmacSha256Raw(String key, String message) {
|
|
int keylen = ((int)String_Len(key));
|
|
int msglen = ((int)String_Len(message));
|
|
void* hmacBuf = Alloc(32);
|
|
bux_hmac_sha256(key, keylen, message, msglen, hmacBuf);
|
|
String result = bux_base64_encode(((String)hmacBuf), 32);
|
|
Free(hmacBuf);
|
|
return result;
|
|
|
|
}
|
|
|
|
String Crypto_Base64Decode(String s) {
|
|
int outlen = 0;
|
|
return bux_base64_decode(s, ((int)String_Len(s)), &outlen);
|
|
|
|
}
|
|
|
|
Mutex Mutex_New() {
|
|
return ((Mutex){.handle = bux_mutex_new()});
|
|
|
|
}
|
|
|
|
void Mutex_Lock(Mutex* m) {
|
|
bux_mutex_lock(m->handle);
|
|
|
|
}
|
|
|
|
void Mutex_Unlock(Mutex* m) {
|
|
bux_mutex_unlock(m->handle);
|
|
|
|
}
|
|
|
|
void Mutex_Free(Mutex* m) {
|
|
bux_mutex_free(m->handle);
|
|
|
|
}
|
|
|
|
RwLock RwLock_New() {
|
|
return ((RwLock){.handle = bux_rwlock_new()});
|
|
|
|
}
|
|
|
|
void RwLock_ReadLock(RwLock* rw) {
|
|
bux_rwlock_rdlock(rw->handle);
|
|
|
|
}
|
|
|
|
void RwLock_WriteLock(RwLock* rw) {
|
|
bux_rwlock_wrlock(rw->handle);
|
|
|
|
}
|
|
|
|
void RwLock_Unlock(RwLock* rw) {
|
|
bux_rwlock_unlock(rw->handle);
|
|
|
|
}
|
|
|
|
void RwLock_Free(RwLock* rw) {
|
|
bux_rwlock_free(rw->handle);
|
|
|
|
}
|
|
|
|
void Test_Exit(int code) {
|
|
bux_exit(code);
|
|
|
|
}
|
|
|
|
void Test_Assert(bool cond) {
|
|
bux_assert(((int)cond), "", 0, "");
|
|
|
|
}
|
|
|
|
void Test_AssertEqInt(int a, int b) {
|
|
if (a != b) {
|
|
PrintLine("ASSERT_EQ FAILED:");
|
|
PrintInt(a);
|
|
PrintLine(" != ");
|
|
PrintInt(b);
|
|
bux_exit(1);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
void Test_AssertTrue(bool cond) {
|
|
if (!cond) {
|
|
PrintLine("ASSERT_TRUE FAILED");
|
|
bux_exit(1);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
void Test_AssertFalse(bool cond) {
|
|
if (cond) {
|
|
PrintLine("ASSERT_FALSE FAILED");
|
|
bux_exit(1);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
void Test_Fail(String msg) {
|
|
PrintLine("FAIL:");
|
|
PrintLine(msg);
|
|
bux_exit(1);
|
|
|
|
}
|
|
|
|
Result Result_NewOk(int value) {
|
|
Result r = ((Result){.tag = Result_Ok});
|
|
r.data.Ok_0 = value;
|
|
return r;
|
|
|
|
}
|
|
|
|
Result Result_NewErr(String msg) {
|
|
Result r = ((Result){.tag = Result_Err});
|
|
r.data.Err_0 = msg;
|
|
return r;
|
|
|
|
}
|
|
|
|
bool Result_IsOk(Result r) {
|
|
return r.tag == Result_Ok;
|
|
|
|
}
|
|
|
|
bool Result_IsErr(Result r) {
|
|
return r.tag == Result_Err;
|
|
|
|
}
|
|
|
|
int Result_Unwrap(Result r) {
|
|
if (r.tag != Result_Ok) {
|
|
PrintLine("panic: unwrap on Err");
|
|
return 0;
|
|
}
|
|
|
|
return r.data.Ok_0;
|
|
|
|
}
|
|
|
|
int Result_UnwrapOr(Result r, int fallback) {
|
|
if (r.tag == Result_Ok) {
|
|
return r.data.Ok_0;
|
|
}
|
|
|
|
return fallback;
|
|
|
|
}
|
|
|
|
Option Option_NewSome(int value) {
|
|
Option o = ((Option){.tag = Option_Some});
|
|
o.data.Some_0 = value;
|
|
return o;
|
|
|
|
}
|
|
|
|
Option Option_NewNone() {
|
|
return ((Option){.tag = Option_None});
|
|
|
|
}
|
|
|
|
bool Option_IsSome(Option o) {
|
|
return o.tag == Option_Some;
|
|
|
|
}
|
|
|
|
bool Option_IsNone(Option o) {
|
|
return o.tag == Option_None;
|
|
|
|
}
|
|
|
|
int Option_Unwrap(Option o) {
|
|
if (o.tag != Option_Some) {
|
|
PrintLine("panic: unwrap on None");
|
|
return 0;
|
|
}
|
|
|
|
return o.data.Some_0;
|
|
|
|
}
|
|
|
|
int Option_UnwrapOr(Option o, int fallback) {
|
|
if (o.tag == Option_Some) {
|
|
return o.data.Some_0;
|
|
}
|
|
|
|
return fallback;
|
|
|
|
}
|
|
|
|
JsonValue Json_Null() {
|
|
return ((JsonValue){.tag = JsonTagNull, .boolVal = false, .numVal = 0.0, .strVal = "", .arrData = 0, .arrLen = 0, .arrCap = 0, .objKeys = 0, .objValues = 0, .objLen = 0, .objCap = 0});
|
|
|
|
}
|
|
|
|
JsonValue Json_Bool(bool b) {
|
|
return ((JsonValue){.tag = JsonTagBool, .boolVal = b, .numVal = 0.0, .strVal = "", .arrData = 0, .arrLen = 0, .arrCap = 0, .objKeys = 0, .objValues = 0, .objLen = 0, .objCap = 0});
|
|
|
|
}
|
|
|
|
JsonValue Json_Number(float64 n) {
|
|
return ((JsonValue){.tag = JsonTagNumber, .boolVal = false, .numVal = n, .strVal = "", .arrData = 0, .arrLen = 0, .arrCap = 0, .objKeys = 0, .objValues = 0, .objLen = 0, .objCap = 0});
|
|
|
|
}
|
|
|
|
JsonValue Json_String(String s) {
|
|
return ((JsonValue){.tag = JsonTagString, .boolVal = false, .numVal = 0.0, .strVal = s, .arrData = 0, .arrLen = 0, .arrCap = 0, .objKeys = 0, .objValues = 0, .objLen = 0, .objCap = 0});
|
|
|
|
}
|
|
|
|
JsonValue Json_Array() {
|
|
return ((JsonValue){.tag = JsonTagArray, .boolVal = false, .numVal = 0.0, .strVal = "", .arrData = 0, .arrLen = 0, .arrCap = 0, .objKeys = 0, .objValues = 0, .objLen = 0, .objCap = 0});
|
|
|
|
}
|
|
|
|
JsonValue Json_Object() {
|
|
return ((JsonValue){.tag = JsonTagObject, .boolVal = false, .numVal = 0.0, .strVal = "", .arrData = 0, .arrLen = 0, .arrCap = 0, .objKeys = 0, .objValues = 0, .objLen = 0, .objCap = 0});
|
|
|
|
}
|
|
|
|
uint Json_ArrayLen(JsonValue v) {
|
|
if (v.tag != JsonTagArray) {
|
|
return 0;
|
|
}
|
|
|
|
return v.arrLen;
|
|
|
|
}
|
|
|
|
JsonValue Json_ArrayGet(JsonValue v, uint index) {
|
|
if (v.tag != JsonTagArray) {
|
|
return Json_Null();
|
|
}
|
|
|
|
if (index >= v.arrLen) {
|
|
return Json_Null();
|
|
}
|
|
|
|
return v.arrData[index];
|
|
|
|
}
|
|
|
|
void Json_ArrayPush(JsonValue* self, JsonValue val) {
|
|
if (self->tag != JsonTagArray) {
|
|
return;
|
|
}
|
|
|
|
if (self->arrLen >= self->arrCap) {
|
|
uint arrNewCap = self->arrCap;
|
|
if (arrNewCap == 0) {
|
|
self->arrCap = 4;
|
|
self->arrData = ((JsonValue*)Alloc(4 * sizeof(JsonValue)));
|
|
} else {
|
|
uint doubleCap = arrNewCap * 2;
|
|
self->arrCap = doubleCap;
|
|
self->arrData = ((JsonValue*)Realloc(((void*)self->arrData), doubleCap * sizeof(JsonValue)));
|
|
}
|
|
|
|
}
|
|
|
|
self->arrData[self->arrLen] = val;
|
|
self->arrLen = self->arrLen + 1;
|
|
|
|
}
|
|
|
|
uint Json_ObjectLen(JsonValue v) {
|
|
if (v.tag != JsonTagObject) {
|
|
return 0;
|
|
}
|
|
|
|
return v.objLen;
|
|
|
|
}
|
|
|
|
JsonValue Json_ObjectGet(JsonValue v, String key) {
|
|
if (v.tag != JsonTagObject) {
|
|
return Json_Null();
|
|
}
|
|
|
|
uint i = 0;
|
|
while (i < v.objLen) {
|
|
if (String_Eq(v.objKeys[i], key)) {
|
|
return v.objValues[i];
|
|
}
|
|
|
|
i = i + 1;
|
|
}
|
|
return Json_Null();
|
|
|
|
}
|
|
|
|
bool Json_ObjectHas(JsonValue v, String key) {
|
|
if (v.tag != JsonTagObject) {
|
|
return false;
|
|
}
|
|
|
|
uint i = 0;
|
|
while (i < v.objLen) {
|
|
if (String_Eq(v.objKeys[i], key)) {
|
|
return true;
|
|
}
|
|
|
|
i = i + 1;
|
|
}
|
|
return false;
|
|
|
|
}
|
|
|
|
void Json_ObjectSet(JsonValue* self, String key, JsonValue val) {
|
|
if (self->tag != JsonTagObject) {
|
|
return;
|
|
}
|
|
|
|
uint i = 0;
|
|
while (i < self->objLen) {
|
|
if (String_Eq(self->objKeys[i], key)) {
|
|
self->objValues[i] = val;
|
|
return;
|
|
}
|
|
|
|
i = i + 1;
|
|
}
|
|
if (self->objLen >= self->objCap) {
|
|
uint objNewCap = self->objCap;
|
|
if (objNewCap == 0) {
|
|
self->objCap = 4;
|
|
self->objKeys = ((String*)Alloc(4 * sizeof(String)));
|
|
self->objValues = ((JsonValue*)Alloc(4 * sizeof(JsonValue)));
|
|
} else {
|
|
uint doubleCap = objNewCap * 2;
|
|
self->objCap = doubleCap;
|
|
self->objKeys = ((String*)Realloc(((void*)self->objKeys), doubleCap * sizeof(String)));
|
|
self->objValues = ((JsonValue*)Realloc(((void*)self->objValues), doubleCap * sizeof(JsonValue)));
|
|
}
|
|
|
|
}
|
|
|
|
self->objKeys[self->objLen] = key;
|
|
self->objValues[self->objLen] = val;
|
|
self->objLen = self->objLen + 1;
|
|
|
|
}
|
|
|
|
bool Json_IsNull(JsonValue v) {
|
|
return v.tag == JsonTagNull;
|
|
|
|
}
|
|
|
|
bool Json_AsBool(JsonValue v) {
|
|
if (v.tag == JsonTagBool) {
|
|
return v.boolVal;
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
float64 Json_AsNumber(JsonValue v) {
|
|
if (v.tag == JsonTagNumber) {
|
|
return v.numVal;
|
|
}
|
|
|
|
return 0.0;
|
|
|
|
}
|
|
|
|
String Json_AsString(JsonValue v) {
|
|
if (v.tag == JsonTagString) {
|
|
return v.strVal;
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
int JsonParser_Peek(JsonParser* p) {
|
|
if (p->pos >= p->len) {
|
|
return 0;
|
|
}
|
|
|
|
return ((int)p->src[p->pos]);
|
|
|
|
}
|
|
|
|
void JsonParser_Advance(JsonParser* p) {
|
|
if (p->pos < p->len) {
|
|
p->pos = p->pos + 1;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
void JsonParser_SkipWhitespace(JsonParser* p) {
|
|
while (true) {
|
|
int c = JsonParser_Peek(p);
|
|
if (c == 32 || c == 9 || c == 10 || c == 13) {
|
|
JsonParser_Advance(p);
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bool JsonParser_Match(JsonParser* p, String expected) {
|
|
uint elen = String_Len(expected);
|
|
if (p->pos + elen > p->len) {
|
|
return false;
|
|
}
|
|
|
|
uint i = 0;
|
|
while (i < elen) {
|
|
if (p->src[p->pos + i] != expected[i]) {
|
|
return false;
|
|
}
|
|
|
|
i = i + 1;
|
|
}
|
|
p->pos = p->pos + elen;
|
|
return true;
|
|
|
|
}
|
|
|
|
String JsonParser_ParseString(JsonParser* p) {
|
|
if (JsonParser_Peek(p) != 34) {
|
|
p->error = "Expected string";
|
|
return "";
|
|
}
|
|
|
|
JsonParser_Advance(p);
|
|
StringBuilder sb = StringBuilder_New();
|
|
while (true) {
|
|
int c = JsonParser_Peek(p);
|
|
if (c == 0 || c == 34) {
|
|
break;
|
|
}
|
|
|
|
if (c == 92) {
|
|
JsonParser_Advance(p);
|
|
int esc = JsonParser_Peek(p);
|
|
if (esc == 0) {
|
|
p->error = "Unterminated string escape";
|
|
StringBuilder_Free(&sb);
|
|
return "";
|
|
}
|
|
|
|
if (esc == 110) {
|
|
StringBuilder_AppendChar(&sb, ((char8)10));
|
|
} else {
|
|
if (esc == 116) {
|
|
StringBuilder_AppendChar(&sb, ((char8)9));
|
|
} else {
|
|
if (esc == 114) {
|
|
StringBuilder_AppendChar(&sb, ((char8)13));
|
|
} else {
|
|
if (esc == 98) {
|
|
StringBuilder_AppendChar(&sb, ((char8)8));
|
|
} else {
|
|
if (esc == 102) {
|
|
StringBuilder_AppendChar(&sb, ((char8)12));
|
|
} else {
|
|
if (esc == 34) {
|
|
StringBuilder_AppendChar(&sb, ((char8)34));
|
|
} else {
|
|
if (esc == 92) {
|
|
StringBuilder_AppendChar(&sb, ((char8)92));
|
|
} else {
|
|
StringBuilder_AppendChar(&sb, ((char8)92));
|
|
StringBuilder_AppendChar(&sb, ((char8)esc));
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
JsonParser_Advance(p);
|
|
} else {
|
|
StringBuilder_AppendChar(&sb, ((char8)c));
|
|
JsonParser_Advance(p);
|
|
}
|
|
|
|
}
|
|
if (JsonParser_Peek(p) != 34) {
|
|
p->error = "Unterminated string";
|
|
StringBuilder_Free(&sb);
|
|
return "";
|
|
}
|
|
|
|
JsonParser_Advance(p);
|
|
String result = StringBuilder_Build(&sb);
|
|
StringBuilder_Free(&sb);
|
|
return result;
|
|
|
|
}
|
|
|
|
JsonValue JsonParser_ParseNumber(JsonParser* p) {
|
|
uint start = p->pos;
|
|
int c0 = JsonParser_Peek(p);
|
|
if (c0 == 45) {
|
|
JsonParser_Advance(p);
|
|
}
|
|
|
|
while (true) {
|
|
int c = JsonParser_Peek(p);
|
|
if (c >= 48 && c <= 57) {
|
|
JsonParser_Advance(p);
|
|
} else {
|
|
break;
|
|
}
|
|
|
|
}
|
|
if (JsonParser_Peek(p) == 46) {
|
|
JsonParser_Advance(p);
|
|
while (true) {
|
|
int c = JsonParser_Peek(p);
|
|
if (c >= 48 && c <= 57) {
|
|
JsonParser_Advance(p);
|
|
} else {
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
String numStr = String_Slice(p->src, start, p->pos - start);
|
|
float64 n = String_ToFloat(numStr);
|
|
return Json_Number(n);
|
|
|
|
}
|
|
|
|
JsonValue JsonParser_ParseArray(JsonParser* p) {
|
|
JsonParser_Advance(p);
|
|
JsonValue arr = Json_Array();
|
|
JsonParser_SkipWhitespace(p);
|
|
if (JsonParser_Peek(p) == 93) {
|
|
JsonParser_Advance(p);
|
|
return arr;
|
|
}
|
|
|
|
while (true) {
|
|
JsonParser_SkipWhitespace(p);
|
|
JsonValue val = JsonParser_ParseValue(p);
|
|
if (p->error != "") {
|
|
return Json_Null();
|
|
}
|
|
|
|
Json_ArrayPush(&arr, val);
|
|
JsonParser_SkipWhitespace(p);
|
|
int c = JsonParser_Peek(p);
|
|
if (c == 93) {
|
|
JsonParser_Advance(p);
|
|
return arr;
|
|
}
|
|
|
|
if (c == 44) {
|
|
JsonParser_Advance(p);
|
|
} else {
|
|
p->error = "Expected ',' or ']' in array";
|
|
return Json_Null();
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
JsonValue JsonParser_ParseObject(JsonParser* p) {
|
|
JsonParser_Advance(p);
|
|
JsonValue obj = Json_Object();
|
|
JsonParser_SkipWhitespace(p);
|
|
if (JsonParser_Peek(p) == 125) {
|
|
JsonParser_Advance(p);
|
|
return obj;
|
|
}
|
|
|
|
while (true) {
|
|
JsonParser_SkipWhitespace(p);
|
|
String key = JsonParser_ParseString(p);
|
|
if (p->error != "") {
|
|
return Json_Null();
|
|
}
|
|
|
|
JsonParser_SkipWhitespace(p);
|
|
if (JsonParser_Peek(p) != 58) {
|
|
p->error = "Expected ':' after object key";
|
|
return Json_Null();
|
|
}
|
|
|
|
JsonParser_Advance(p);
|
|
JsonParser_SkipWhitespace(p);
|
|
JsonValue val = JsonParser_ParseValue(p);
|
|
if (p->error != "") {
|
|
return Json_Null();
|
|
}
|
|
|
|
Json_ObjectSet(&obj, key, val);
|
|
JsonParser_SkipWhitespace(p);
|
|
int c = JsonParser_Peek(p);
|
|
if (c == 125) {
|
|
JsonParser_Advance(p);
|
|
return obj;
|
|
}
|
|
|
|
if (c == 44) {
|
|
JsonParser_Advance(p);
|
|
} else {
|
|
p->error = "Expected ',' or '}' in object";
|
|
return Json_Null();
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
JsonValue JsonParser_ParseValue(JsonParser* p) {
|
|
JsonParser_SkipWhitespace(p);
|
|
int c = JsonParser_Peek(p);
|
|
if (c == 0) {
|
|
p->error = "Unexpected end of input";
|
|
return Json_Null();
|
|
}
|
|
|
|
if (c == 34) {
|
|
return Json_String(JsonParser_ParseString(p));
|
|
}
|
|
|
|
if (c == 123) {
|
|
return JsonParser_ParseObject(p);
|
|
}
|
|
|
|
if (c == 91) {
|
|
return JsonParser_ParseArray(p);
|
|
}
|
|
|
|
if (c == 116) {
|
|
if (JsonParser_Match(p, "true")) {
|
|
return Json_Bool(true);
|
|
}
|
|
|
|
p->error = "Expected 'true'";
|
|
return Json_Null();
|
|
}
|
|
|
|
if (c == 102) {
|
|
if (JsonParser_Match(p, "false")) {
|
|
return Json_Bool(false);
|
|
}
|
|
|
|
p->error = "Expected 'false'";
|
|
return Json_Null();
|
|
}
|
|
|
|
if (c == 110) {
|
|
if (JsonParser_Match(p, "null")) {
|
|
return Json_Null();
|
|
}
|
|
|
|
p->error = "Expected 'null'";
|
|
return Json_Null();
|
|
}
|
|
|
|
if (c >= 48 && c <= 57 || c == 45) {
|
|
return JsonParser_ParseNumber(p);
|
|
}
|
|
|
|
p->error = "Unexpected character";
|
|
return Json_Null();
|
|
|
|
}
|
|
|
|
JsonValue Json_Parse(String s) {
|
|
JsonParser p = ((JsonParser){.src = s, .pos = 0, .len = String_Len(s), .error = ""});
|
|
JsonValue result = JsonParser_ParseValue(&p);
|
|
JsonParser_SkipWhitespace(&p);
|
|
if (p.error == "" && p.pos != p.len) {
|
|
p.error = "Trailing data after JSON value";
|
|
return Json_Null();
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
void Json_StringifyImpl(StringBuilder* sb, JsonValue v) {
|
|
if (v.tag == JsonTagNull) {
|
|
StringBuilder_Append(sb, "null");
|
|
return;
|
|
}
|
|
|
|
if (v.tag == JsonTagBool) {
|
|
if (v.boolVal) {
|
|
StringBuilder_Append(sb, "true");
|
|
} else {
|
|
StringBuilder_Append(sb, "false");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (v.tag == JsonTagNumber) {
|
|
StringBuilder_AppendFloat(sb, v.numVal);
|
|
return;
|
|
}
|
|
|
|
if (v.tag == JsonTagString) {
|
|
StringBuilder_AppendChar(sb, ((char8)34));
|
|
StringBuilder_Append(sb, v.strVal);
|
|
StringBuilder_AppendChar(sb, ((char8)34));
|
|
return;
|
|
}
|
|
|
|
if (v.tag == JsonTagArray) {
|
|
StringBuilder_AppendChar(sb, ((char8)91));
|
|
uint i = 0;
|
|
while (i < v.arrLen) {
|
|
if (i > 0) {
|
|
StringBuilder_AppendChar(sb, ((char8)44));
|
|
}
|
|
|
|
Json_StringifyImpl(sb, v.arrData[i]);
|
|
i = i + 1;
|
|
}
|
|
StringBuilder_AppendChar(sb, ((char8)93));
|
|
return;
|
|
}
|
|
|
|
if (v.tag == JsonTagObject) {
|
|
StringBuilder_AppendChar(sb, ((char8)123));
|
|
uint i = 0;
|
|
while (i < v.objLen) {
|
|
if (i > 0) {
|
|
StringBuilder_AppendChar(sb, ((char8)44));
|
|
}
|
|
|
|
StringBuilder_AppendChar(sb, ((char8)34));
|
|
StringBuilder_Append(sb, v.objKeys[i]);
|
|
StringBuilder_AppendChar(sb, ((char8)34));
|
|
StringBuilder_AppendChar(sb, ((char8)58));
|
|
Json_StringifyImpl(sb, v.objValues[i]);
|
|
i = i + 1;
|
|
}
|
|
StringBuilder_AppendChar(sb, ((char8)125));
|
|
return;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
String Json_Stringify(JsonValue v) {
|
|
StringBuilder sb = StringBuilder_New();
|
|
Json_StringifyImpl(&sb, v);
|
|
return StringBuilder_Build(&sb);
|
|
|
|
}
|
|
|
|
String Hash_Sha1(String data) {
|
|
int len = ((int)String_Len(data));
|
|
void* buf = Alloc(20);
|
|
bux_sha1(data, len, buf);
|
|
String result = bux_bytes_to_hex(buf, 20);
|
|
Free(buf);
|
|
return result;
|
|
|
|
}
|
|
|
|
String Hash_Sha256(String data) {
|
|
int len = ((int)String_Len(data));
|
|
void* buf = Alloc(32);
|
|
bux_sha256(data, len, buf);
|
|
String result = bux_bytes_to_hex(buf, 32);
|
|
Free(buf);
|
|
return result;
|
|
|
|
}
|
|
|
|
String Hash_Sha384(String data) {
|
|
int len = ((int)String_Len(data));
|
|
void* buf = Alloc(48);
|
|
bux_sha384(data, len, buf);
|
|
String result = bux_bytes_to_hex(buf, 48);
|
|
Free(buf);
|
|
return result;
|
|
|
|
}
|
|
|
|
String Hash_Sha512(String data) {
|
|
int len = ((int)String_Len(data));
|
|
void* buf = Alloc(64);
|
|
bux_sha512(data, len, buf);
|
|
String result = bux_bytes_to_hex(buf, 64);
|
|
Free(buf);
|
|
return result;
|
|
|
|
}
|
|
|
|
void Hash_Sha256Raw(String data, void* out) {
|
|
bux_sha256(data, ((int)String_Len(data)), out);
|
|
|
|
}
|
|
|
|
void Hash_Sha384Raw(String data, void* out) {
|
|
bux_sha384(data, ((int)String_Len(data)), out);
|
|
|
|
}
|
|
|
|
void Hash_Sha512Raw(String data, void* out) {
|
|
bux_sha512(data, ((int)String_Len(data)), out);
|
|
|
|
}
|
|
|
|
int Hash_Sha1Size() {
|
|
return 20;
|
|
|
|
}
|
|
|
|
int Hash_Sha256Size() {
|
|
return 32;
|
|
|
|
}
|
|
|
|
int Hash_Sha384Size() {
|
|
return 48;
|
|
|
|
}
|
|
|
|
int Hash_Sha512Size() {
|
|
return 64;
|
|
|
|
}
|
|
|
|
String Base64_Encode(String s) {
|
|
return bux_base64_encode(s, ((int)String_Len(s)));
|
|
|
|
}
|
|
|
|
String Base64_Decode(String s) {
|
|
int outlen = 0;
|
|
return bux_base64_decode(s, ((int)String_Len(s)), &outlen);
|
|
|
|
}
|
|
|
|
String Base64URL_Encode(String s) {
|
|
return bux_base64url_encode(s, ((int)String_Len(s)));
|
|
|
|
}
|
|
|
|
String Base64URL_Decode(String s) {
|
|
int outlen = 0;
|
|
return bux_base64url_decode(s, ((int)String_Len(s)), &outlen);
|
|
|
|
}
|
|
|
|
String Hmac_Sha256(String key, String message) {
|
|
int kl = ((int)String_Len(key));
|
|
int ml = ((int)String_Len(message));
|
|
void* buf = Alloc(32);
|
|
bux_hmac_sha256(key, kl, message, ml, buf);
|
|
String result = bux_bytes_to_hex(buf, 32);
|
|
Free(buf);
|
|
return result;
|
|
|
|
}
|
|
|
|
void Hmac_Sha256Raw(String key, String message, void* out) {
|
|
bux_hmac_sha256(key, ((int)String_Len(key)), message, ((int)String_Len(message)), out);
|
|
|
|
}
|
|
|
|
String Hmac_Sha256Base64(String key, String message) {
|
|
int kl = ((int)String_Len(key));
|
|
int ml = ((int)String_Len(message));
|
|
void* buf = Alloc(32);
|
|
bux_hmac_sha256(key, kl, message, ml, buf);
|
|
String result = bux_base64_encode(((String)buf), 32);
|
|
Free(buf);
|
|
return result;
|
|
|
|
}
|
|
|
|
String Hmac_Sha384(String key, String message) {
|
|
int kl = ((int)String_Len(key));
|
|
int ml = ((int)String_Len(message));
|
|
void* buf = Alloc(48);
|
|
bux_hmac_sha384(key, kl, message, ml, buf);
|
|
String result = bux_bytes_to_hex(buf, 48);
|
|
Free(buf);
|
|
return result;
|
|
|
|
}
|
|
|
|
void Hmac_Sha384Raw(String key, String message, void* out) {
|
|
bux_hmac_sha384(key, ((int)String_Len(key)), message, ((int)String_Len(message)), out);
|
|
|
|
}
|
|
|
|
String Hmac_Sha384Base64(String key, String message) {
|
|
int kl = ((int)String_Len(key));
|
|
int ml = ((int)String_Len(message));
|
|
void* buf = Alloc(48);
|
|
bux_hmac_sha384(key, kl, message, ml, buf);
|
|
String result = bux_base64_encode(((String)buf), 48);
|
|
Free(buf);
|
|
return result;
|
|
|
|
}
|
|
|
|
String Hmac_Sha512(String key, String message) {
|
|
int kl = ((int)String_Len(key));
|
|
int ml = ((int)String_Len(message));
|
|
void* buf = Alloc(64);
|
|
bux_hmac_sha512(key, kl, message, ml, buf);
|
|
String result = bux_bytes_to_hex(buf, 64);
|
|
Free(buf);
|
|
return result;
|
|
|
|
}
|
|
|
|
void Hmac_Sha512Raw(String key, String message, void* out) {
|
|
bux_hmac_sha512(key, ((int)String_Len(key)), message, ((int)String_Len(message)), out);
|
|
|
|
}
|
|
|
|
String Hmac_Sha512Base64(String key, String message) {
|
|
int kl = ((int)String_Len(key));
|
|
int ml = ((int)String_Len(message));
|
|
void* buf = Alloc(64);
|
|
bux_hmac_sha512(key, kl, message, ml, buf);
|
|
String result = bux_base64_encode(((String)buf), 64);
|
|
Free(buf);
|
|
return result;
|
|
|
|
}
|
|
|
|
String Random_Bytes(int n) {
|
|
if (n <= 0) {
|
|
return "";
|
|
}
|
|
|
|
void* buf = Alloc(((uint)n));
|
|
if (bux_random_bytes(buf, n) != 1) {
|
|
Free(buf);
|
|
return "";
|
|
}
|
|
|
|
return ((String)buf);
|
|
|
|
}
|
|
|
|
String Random_Hex(int n) {
|
|
if (n <= 0) {
|
|
return "";
|
|
}
|
|
|
|
void* buf = Alloc(((uint)n));
|
|
if (bux_random_bytes(buf, n) != 1) {
|
|
Free(buf);
|
|
return "";
|
|
}
|
|
|
|
String result = bux_bytes_to_hex(buf, n);
|
|
Free(buf);
|
|
return result;
|
|
|
|
}
|
|
|
|
String Random_Base64(int n) {
|
|
if (n <= 0) {
|
|
return "";
|
|
}
|
|
|
|
void* buf = Alloc(((uint)n));
|
|
if (bux_random_bytes(buf, n) != 1) {
|
|
Free(buf);
|
|
return "";
|
|
}
|
|
|
|
String result = bux_base64_encode(((String)buf), n);
|
|
Free(buf);
|
|
return result;
|
|
|
|
}
|
|
|
|
uint Random_Uint32() {
|
|
void* buf = Alloc(4);
|
|
if (bux_random_bytes(buf, 4) != 1) {
|
|
Free(buf);
|
|
return 0;
|
|
}
|
|
|
|
uint* ptr = ((uint*)buf);
|
|
uint val = *ptr;
|
|
Free(buf);
|
|
return val;
|
|
|
|
}
|
|
|
|
String Aes_GenerateKey() {
|
|
void* buf = Alloc(((uint)AES_KEY_SIZE));
|
|
if (bux_random_bytes(buf, AES_KEY_SIZE) != 1) {
|
|
Free(buf);
|
|
return "";
|
|
}
|
|
|
|
return ((String)buf);
|
|
|
|
}
|
|
|
|
String Aes_GenerateIV() {
|
|
void* buf = Alloc(((uint)AES_IV_SIZE));
|
|
if (bux_random_bytes(buf, AES_IV_SIZE) != 1) {
|
|
Free(buf);
|
|
return "";
|
|
}
|
|
|
|
return ((String)buf);
|
|
|
|
}
|
|
|
|
String Aes_CbcEncrypt(String plain, String key, String iv) {
|
|
int outlen = 0;
|
|
return bux_aes_256_cbc_encrypt(plain, ((int)String_Len(plain)), key, iv, &outlen);
|
|
|
|
}
|
|
|
|
String Aes_CbcDecrypt(String cipher, String key, String iv) {
|
|
int outlen = 0;
|
|
return bux_aes_256_cbc_decrypt(cipher, ((int)String_Len(cipher)), key, iv, &outlen);
|
|
|
|
}
|
|
|
|
String Aes_GcmEncrypt(String plain, String key, String iv, void* tag) {
|
|
int outlen = 0;
|
|
return bux_aes_256_gcm_encrypt(plain, ((int)String_Len(plain)), key, iv, tag, &outlen);
|
|
|
|
}
|
|
|
|
String Aes_GcmDecrypt(String cipher, String key, String iv, String tag) {
|
|
int outlen = 0;
|
|
return bux_aes_256_gcm_decrypt(cipher, ((int)String_Len(cipher)), key, iv, tag, &outlen);
|
|
|
|
}
|
|
|
|
String Jwt_MakeHeader(JwtAlg alg) {
|
|
if (alg.tag == JwtAlg_HS256) {
|
|
return "{\"alg\":\"HS256\",\"typ\":\"JWT\"}";
|
|
}
|
|
|
|
if (alg.tag == JwtAlg_HS384) {
|
|
return "{\"alg\":\"HS384\",\"typ\":\"JWT\"}";
|
|
}
|
|
|
|
if (alg.tag == JwtAlg_HS512) {
|
|
return "{\"alg\":\"HS512\",\"typ\":\"JWT\"}";
|
|
}
|
|
|
|
if (alg.tag == JwtAlg_RS256) {
|
|
return "{\"alg\":\"RS256\",\"typ\":\"JWT\"}";
|
|
}
|
|
|
|
if (alg.tag == JwtAlg_RS384) {
|
|
return "{\"alg\":\"RS384\",\"typ\":\"JWT\"}";
|
|
}
|
|
|
|
if (alg.tag == JwtAlg_RS512) {
|
|
return "{\"alg\":\"RS512\",\"typ\":\"JWT\"}";
|
|
}
|
|
|
|
if (alg.tag == JwtAlg_ES256) {
|
|
return "{\"alg\":\"ES256\",\"typ\":\"JWT\"}";
|
|
}
|
|
|
|
if (alg.tag == JwtAlg_ES384) {
|
|
return "{\"alg\":\"ES384\",\"typ\":\"JWT\"}";
|
|
}
|
|
|
|
if (alg.tag == JwtAlg_EdDSA) {
|
|
return "{\"alg\":\"EdDSA\",\"typ\":\"JWT\"}";
|
|
}
|
|
|
|
return "{\"alg\":\"none\",\"typ\":\"JWT\"}";
|
|
|
|
}
|
|
|
|
String Jwt_Sign(JwtAlg alg, String signingInput, String key) {
|
|
if (alg.tag == JwtAlg_HS256) {
|
|
void* buf = Alloc(32);
|
|
Hmac_Sha256Raw(key, signingInput, buf);
|
|
String result = bux_base64_encode(((String)buf), 32);
|
|
Free(buf);
|
|
return result;
|
|
}
|
|
|
|
if (alg.tag == JwtAlg_HS384) {
|
|
void* buf = Alloc(48);
|
|
Hmac_Sha384Raw(key, signingInput, buf);
|
|
String result = bux_base64_encode(((String)buf), 48);
|
|
Free(buf);
|
|
return result;
|
|
}
|
|
|
|
if (alg.tag == JwtAlg_HS512) {
|
|
void* buf = Alloc(64);
|
|
Hmac_Sha512Raw(key, signingInput, buf);
|
|
String result = bux_base64_encode(((String)buf), 64);
|
|
Free(buf);
|
|
return result;
|
|
}
|
|
|
|
if (alg.tag == JwtAlg_RS256) {
|
|
String raw = Rsa_SignSha256(key, signingInput);
|
|
return bux_base64_encode(raw, ((int)String_Len(raw)));
|
|
}
|
|
|
|
if (alg.tag == JwtAlg_RS384) {
|
|
String raw = Rsa_SignSha384(key, signingInput);
|
|
return bux_base64_encode(raw, ((int)String_Len(raw)));
|
|
}
|
|
|
|
if (alg.tag == JwtAlg_RS512) {
|
|
String raw = Rsa_SignSha512(key, signingInput);
|
|
return bux_base64_encode(raw, ((int)String_Len(raw)));
|
|
}
|
|
|
|
if (alg.tag == JwtAlg_ES256) {
|
|
String raw = Ecdsa_SignP256(key, signingInput);
|
|
return bux_base64_encode(raw, ((int)String_Len(raw)));
|
|
}
|
|
|
|
if (alg.tag == JwtAlg_ES384) {
|
|
String raw = Ecdsa_SignP384(key, signingInput);
|
|
return bux_base64_encode(raw, ((int)String_Len(raw)));
|
|
}
|
|
|
|
if (alg.tag == JwtAlg_EdDSA) {
|
|
return Ed25519_Sign(key, signingInput);
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
bool Jwt_Verify(JwtAlg alg, String signingInput, String signatureB64, String key) {
|
|
if (alg.tag == JwtAlg_HS256) {
|
|
void* expectBuf = Alloc(32);
|
|
Hmac_Sha256Raw(key, signingInput, expectBuf);
|
|
String expectB64 = bux_base64_encode(((String)expectBuf), 32);
|
|
Free(expectBuf);
|
|
return String_Eq(expectB64, signatureB64);
|
|
}
|
|
|
|
if (alg.tag == JwtAlg_HS384) {
|
|
void* expectBuf = Alloc(48);
|
|
Hmac_Sha384Raw(key, signingInput, expectBuf);
|
|
String expectB64 = bux_base64_encode(((String)expectBuf), 48);
|
|
Free(expectBuf);
|
|
return String_Eq(expectB64, signatureB64);
|
|
}
|
|
|
|
if (alg.tag == JwtAlg_HS512) {
|
|
void* expectBuf = Alloc(64);
|
|
Hmac_Sha512Raw(key, signingInput, expectBuf);
|
|
String expectB64 = bux_base64_encode(((String)expectBuf), 64);
|
|
Free(expectBuf);
|
|
return String_Eq(expectB64, signatureB64);
|
|
}
|
|
|
|
if (alg.tag == JwtAlg_RS256) {
|
|
return Rsa_VerifySha256(key, signingInput, signatureB64);
|
|
}
|
|
|
|
if (alg.tag == JwtAlg_RS384) {
|
|
return Rsa_VerifySha384(key, signingInput, signatureB64);
|
|
}
|
|
|
|
if (alg.tag == JwtAlg_RS512) {
|
|
return Rsa_VerifySha512(key, signingInput, signatureB64);
|
|
}
|
|
|
|
if (alg.tag == JwtAlg_ES256) {
|
|
return Ecdsa_VerifyP256(key, signingInput, signatureB64);
|
|
}
|
|
|
|
if (alg.tag == JwtAlg_ES384) {
|
|
return Ecdsa_VerifyP384(key, signingInput, signatureB64);
|
|
}
|
|
|
|
if (alg.tag == JwtAlg_EdDSA) {
|
|
return Ed25519_Verify(key, signatureB64, signingInput);
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
String Jwt_Encode(String headerJson, String payloadJson, JwtAlg alg, String key) {
|
|
String headerB64 = Base64URL_Encode(headerJson);
|
|
String payloadB64 = Base64URL_Encode(payloadJson);
|
|
String signingInput = String_Concat(headerB64, ".");
|
|
String signingInputFull = String_Concat(signingInput, payloadB64);
|
|
String sigB64 = Jwt_Sign(alg, signingInputFull, key);
|
|
String part1 = String_Concat(signingInputFull, ".");
|
|
return String_Concat(part1, sigB64);
|
|
|
|
}
|
|
|
|
bool Jwt_Decode(String token, JwtAlg alg, String key, String* headerOut, String* payloadOut) {
|
|
uint partCount = bux_str_split_count(token, ".");
|
|
if (partCount != 3) {
|
|
return false;
|
|
}
|
|
|
|
String headerB64 = bux_str_split_part(token, ".", 0);
|
|
String payloadB64 = bux_str_split_part(token, ".", 1);
|
|
String sigB64 = bux_str_split_part(token, ".", 2);
|
|
String input = String_Concat(headerB64, ".");
|
|
String signingInput = String_Concat(input, payloadB64);
|
|
if (!Jwt_Verify(alg, signingInput, sigB64, key)) {
|
|
return false;
|
|
}
|
|
|
|
headerOut[0] = Base64URL_Decode(headerB64);
|
|
payloadOut[0] = Base64URL_Decode(payloadB64);
|
|
return true;
|
|
|
|
}
|
|
|
|
String Jwt_EncodeHS256(String payloadJson, String secret) {
|
|
String header = Jwt_MakeHeader(((JwtAlg){.tag = JwtAlg_HS256}));
|
|
return Jwt_Encode(header, payloadJson, ((JwtAlg){.tag = JwtAlg_HS256}), secret);
|
|
|
|
}
|
|
|
|
String Jwt_EncodeHS384(String payloadJson, String secret) {
|
|
String header = Jwt_MakeHeader(((JwtAlg){.tag = JwtAlg_HS384}));
|
|
return Jwt_Encode(header, payloadJson, ((JwtAlg){.tag = JwtAlg_HS384}), secret);
|
|
|
|
}
|
|
|
|
String Jwt_EncodeHS512(String payloadJson, String secret) {
|
|
String header = Jwt_MakeHeader(((JwtAlg){.tag = JwtAlg_HS512}));
|
|
return Jwt_Encode(header, payloadJson, ((JwtAlg){.tag = JwtAlg_HS512}), secret);
|
|
|
|
}
|
|
|
|
String Jwt_EncodeRS256(String payloadJson, String pemPrivateKey) {
|
|
String header = Jwt_MakeHeader(((JwtAlg){.tag = JwtAlg_RS256}));
|
|
return Jwt_Encode(header, payloadJson, ((JwtAlg){.tag = JwtAlg_RS256}), pemPrivateKey);
|
|
|
|
}
|
|
|
|
String Jwt_EncodeES256(String payloadJson, String pemPrivateKey) {
|
|
String header = Jwt_MakeHeader(((JwtAlg){.tag = JwtAlg_ES256}));
|
|
return Jwt_Encode(header, payloadJson, ((JwtAlg){.tag = JwtAlg_ES256}), pemPrivateKey);
|
|
|
|
}
|
|
|
|
String Jwt_EncodeEdDSA(String payloadJson, String rawPrivKey) {
|
|
String header = Jwt_MakeHeader(((JwtAlg){.tag = JwtAlg_EdDSA}));
|
|
return Jwt_Encode(header, payloadJson, ((JwtAlg){.tag = JwtAlg_EdDSA}), rawPrivKey);
|
|
|
|
}
|
|
|
|
String Ecdsa_SignP256(String pemPrivateKey, String data) {
|
|
int siglen = 0;
|
|
return bux_ecdsa_sign_p256(pemPrivateKey, ((int)String_Len(pemPrivateKey)), data, ((int)String_Len(data)), &siglen);
|
|
|
|
}
|
|
|
|
String Ecdsa_SignP256Base64(String pemPrivateKey, String data) {
|
|
String raw = Ecdsa_SignP256(pemPrivateKey, data);
|
|
return bux_base64_encode(raw, ((int)String_Len(raw)));
|
|
|
|
}
|
|
|
|
bool Ecdsa_VerifyP256(String pemPublicKey, String data, String signature) {
|
|
int r = bux_ecdsa_verify_p256(pemPublicKey, ((int)String_Len(pemPublicKey)), data, ((int)String_Len(data)), signature, ((int)String_Len(signature)));
|
|
return r == 1;
|
|
|
|
}
|
|
|
|
bool Ecdsa_VerifyP256Base64(String pemPublicKey, String data, String signatureB64) {
|
|
int outlen = 0;
|
|
String sig = bux_base64_decode(signatureB64, ((int)String_Len(signatureB64)), &outlen);
|
|
return Ecdsa_VerifyP256(pemPublicKey, data, sig);
|
|
|
|
}
|
|
|
|
String Ecdsa_SignP384(String pemPrivateKey, String data) {
|
|
int siglen = 0;
|
|
return bux_ecdsa_sign_p384(pemPrivateKey, ((int)String_Len(pemPrivateKey)), data, ((int)String_Len(data)), &siglen);
|
|
|
|
}
|
|
|
|
String Ecdsa_SignP384Base64(String pemPrivateKey, String data) {
|
|
String raw = Ecdsa_SignP384(pemPrivateKey, data);
|
|
return bux_base64_encode(raw, ((int)String_Len(raw)));
|
|
|
|
}
|
|
|
|
bool Ecdsa_VerifyP384(String pemPublicKey, String data, String signature) {
|
|
int r = bux_ecdsa_verify_p384(pemPublicKey, ((int)String_Len(pemPublicKey)), data, ((int)String_Len(data)), signature, ((int)String_Len(signature)));
|
|
return r == 1;
|
|
|
|
}
|
|
|
|
bool Ecdsa_VerifyP384Base64(String pemPublicKey, String data, String signatureB64) {
|
|
int outlen = 0;
|
|
String sig = bux_base64_decode(signatureB64, ((int)String_Len(signatureB64)), &outlen);
|
|
return Ecdsa_VerifyP384(pemPublicKey, data, sig);
|
|
|
|
}
|
|
|
|
bool Ed25519_Keypair(void* pubKey, void* privKey) {
|
|
int r = bux_ed25519_keypair(pubKey, privKey);
|
|
return r == 1;
|
|
|
|
}
|
|
|
|
String Ed25519_KeypairBase64() {
|
|
void* pubBuf = Alloc(((uint)ED25519_PUBKEY_SIZE));
|
|
void* priv = Alloc(((uint)ED25519_PRIVKEY_SIZE));
|
|
if (bux_ed25519_keypair(pubBuf, priv) != 1) {
|
|
Free(pubBuf);
|
|
Free(priv);
|
|
return "";
|
|
}
|
|
|
|
String pubB64 = bux_base64_encode(((String)pubBuf), ED25519_PUBKEY_SIZE);
|
|
String privB64 = bux_base64_encode(((String)priv), ED25519_PRIVKEY_SIZE);
|
|
Free(pubBuf);
|
|
Free(priv);
|
|
String pair = String_Concat(pubB64, ":");
|
|
return String_Concat(pair, privB64);
|
|
|
|
}
|
|
|
|
String Ed25519_Sign(String privKey, String data) {
|
|
void* sig = Alloc(((uint)ED25519_SIG_SIZE));
|
|
if (bux_ed25519_sign(privKey, data, ((int)String_Len(data)), sig) != 1) {
|
|
Free(sig);
|
|
return "";
|
|
}
|
|
|
|
return ((String)sig);
|
|
|
|
}
|
|
|
|
String Ed25519_SignBase64(String privKey, String data) {
|
|
String sig = Ed25519_Sign(privKey, data);
|
|
if (String_Len(sig) == 0) {
|
|
return "";
|
|
}
|
|
|
|
return bux_base64_encode(sig, ED25519_SIG_SIZE);
|
|
|
|
}
|
|
|
|
bool Ed25519_Verify(String pubKey, String signature, String data) {
|
|
int r = bux_ed25519_verify(pubKey, signature, data, ((int)String_Len(data)));
|
|
return r == 1;
|
|
|
|
}
|
|
|
|
bool Ed25519_VerifyBase64(String pubKey, String signatureB64, String data) {
|
|
int outlen = 0;
|
|
String sig = bux_base64_decode(signatureB64, ((int)String_Len(signatureB64)), &outlen);
|
|
if (outlen != ED25519_SIG_SIZE) {
|
|
return false;
|
|
}
|
|
|
|
return Ed25519_Verify(pubKey, sig, data);
|
|
|
|
}
|
|
|
|
String Rsa_SignSha256(String pemPrivateKey, String data) {
|
|
int siglen = 0;
|
|
return bux_rsa_sign_sha256(pemPrivateKey, ((int)String_Len(pemPrivateKey)), data, ((int)String_Len(data)), &siglen);
|
|
|
|
}
|
|
|
|
String Rsa_SignSha384(String pemPrivateKey, String data) {
|
|
int siglen = 0;
|
|
return bux_rsa_sign_sha384(pemPrivateKey, ((int)String_Len(pemPrivateKey)), data, ((int)String_Len(data)), &siglen);
|
|
|
|
}
|
|
|
|
String Rsa_SignSha512(String pemPrivateKey, String data) {
|
|
int siglen = 0;
|
|
return bux_rsa_sign_sha512(pemPrivateKey, ((int)String_Len(pemPrivateKey)), data, ((int)String_Len(data)), &siglen);
|
|
|
|
}
|
|
|
|
String Rsa_SignSha256Base64(String pemPrivateKey, String data) {
|
|
String raw = Rsa_SignSha256(pemPrivateKey, data);
|
|
return bux_base64_encode(raw, ((int)String_Len(raw)));
|
|
|
|
}
|
|
|
|
String Rsa_SignSha384Base64(String pemPrivateKey, String data) {
|
|
String raw = Rsa_SignSha384(pemPrivateKey, data);
|
|
return bux_base64_encode(raw, ((int)String_Len(raw)));
|
|
|
|
}
|
|
|
|
String Rsa_SignSha512Base64(String pemPrivateKey, String data) {
|
|
String raw = Rsa_SignSha512(pemPrivateKey, data);
|
|
return bux_base64_encode(raw, ((int)String_Len(raw)));
|
|
|
|
}
|
|
|
|
bool Rsa_VerifySha256(String pemPublicKey, String data, String signature) {
|
|
int r = bux_rsa_verify_sha256(pemPublicKey, ((int)String_Len(pemPublicKey)), data, ((int)String_Len(data)), signature, ((int)String_Len(signature)));
|
|
return r == 1;
|
|
|
|
}
|
|
|
|
bool Rsa_VerifySha384(String pemPublicKey, String data, String signature) {
|
|
int r = bux_rsa_verify_sha384(pemPublicKey, ((int)String_Len(pemPublicKey)), data, ((int)String_Len(data)), signature, ((int)String_Len(signature)));
|
|
return r == 1;
|
|
|
|
}
|
|
|
|
bool Rsa_VerifySha512(String pemPublicKey, String data, String signature) {
|
|
int r = bux_rsa_verify_sha512(pemPublicKey, ((int)String_Len(pemPublicKey)), data, ((int)String_Len(data)), signature, ((int)String_Len(signature)));
|
|
return r == 1;
|
|
|
|
}
|
|
|
|
bool Rsa_VerifySha256Base64(String pemPublicKey, String data, String signatureB64) {
|
|
int outlen = 0;
|
|
String sig = bux_base64_decode(signatureB64, ((int)String_Len(signatureB64)), &outlen);
|
|
return Rsa_VerifySha256(pemPublicKey, data, sig);
|
|
|
|
}
|
|
|
|
bool Rsa_VerifySha384Base64(String pemPublicKey, String data, String signatureB64) {
|
|
int outlen = 0;
|
|
String sig = bux_base64_decode(signatureB64, ((int)String_Len(signatureB64)), &outlen);
|
|
return Rsa_VerifySha384(pemPublicKey, data, sig);
|
|
|
|
}
|
|
|
|
bool Rsa_VerifySha512Base64(String pemPublicKey, String data, String signatureB64) {
|
|
int outlen = 0;
|
|
String sig = bux_base64_decode(signatureB64, ((int)String_Len(signatureB64)), &outlen);
|
|
return Rsa_VerifySha512(pemPublicKey, data, sig);
|
|
|
|
}
|
|
|
|
uint String_Len(String s) {
|
|
return bux_strlen(s);
|
|
|
|
}
|
|
|
|
bool String_IsNull(String s) {
|
|
return bux_str_is_null(s) != 0;
|
|
|
|
}
|
|
|
|
bool String_Eq(String a, String b) {
|
|
return bux_strcmp(a, b) == 0;
|
|
|
|
}
|
|
|
|
String String_Concat(String a, String b) {
|
|
uint len_a = bux_strlen(a);
|
|
uint len_b = bux_strlen(b);
|
|
uint total = len_a + len_b + 1;
|
|
char8* buf = ((char8*)bux_alloc(total));
|
|
bux_strcpy(buf, a);
|
|
bux_strcat(buf, b);
|
|
return buf;
|
|
|
|
}
|
|
|
|
String String_Copy(String s) {
|
|
uint len = bux_strlen(s);
|
|
char8* buf = ((char8*)bux_alloc(len + 1));
|
|
bux_strcpy(buf, s);
|
|
return buf;
|
|
|
|
}
|
|
|
|
bool String_StartsWith(String s, String prefix) {
|
|
uint s_len = bux_strlen(s);
|
|
uint p_len = bux_strlen(prefix);
|
|
if (p_len > s_len) {
|
|
return false;
|
|
}
|
|
|
|
int r = bux_strncmp(s, prefix, p_len);
|
|
return r == 0;
|
|
|
|
}
|
|
|
|
bool String_EndsWith(String s, String suffix) {
|
|
uint s_len = bux_strlen(s);
|
|
uint suf_len = bux_strlen(suffix);
|
|
if (suf_len > s_len) {
|
|
return false;
|
|
}
|
|
|
|
uint start = s_len - suf_len;
|
|
String tail = bux_str_slice(s, start, suf_len);
|
|
bool eq = bux_strcmp(tail, suffix) == 0;
|
|
return eq;
|
|
|
|
}
|
|
|
|
bool String_Contains(String s, String substr) {
|
|
int r = bux_str_contains(s, substr);
|
|
return r != 0;
|
|
|
|
}
|
|
|
|
String String_Slice(String s, uint start, uint len) {
|
|
return bux_str_slice(s, start, len);
|
|
|
|
}
|
|
|
|
String String_Trim(String s) {
|
|
return bux_str_trim(s);
|
|
|
|
}
|
|
|
|
String String_TrimLeft(String s) {
|
|
return bux_str_trim_left(s);
|
|
|
|
}
|
|
|
|
String String_TrimRight(String s) {
|
|
return bux_str_trim_right(s);
|
|
|
|
}
|
|
|
|
String String_FromInt(int64 n) {
|
|
return bux_int_to_str(n);
|
|
|
|
}
|
|
|
|
int64 String_ToInt(String s) {
|
|
return bux_str_to_int(s);
|
|
|
|
}
|
|
|
|
StringBuilder StringBuilder_New() {
|
|
return ((StringBuilder){.handle = bux_sb_new(64)});
|
|
|
|
}
|
|
|
|
StringBuilder StringBuilder_NewCap(uint cap) {
|
|
return ((StringBuilder){.handle = bux_sb_new(cap)});
|
|
|
|
}
|
|
|
|
void StringBuilder_Append(StringBuilder* sb, String s) {
|
|
bux_sb_append(sb->handle, s);
|
|
|
|
}
|
|
|
|
void StringBuilder_AppendInt(StringBuilder* sb, int64 n) {
|
|
bux_sb_append_int(sb->handle, n);
|
|
|
|
}
|
|
|
|
void StringBuilder_AppendFloat(StringBuilder* sb, float64 f) {
|
|
bux_sb_append_float(sb->handle, f);
|
|
|
|
}
|
|
|
|
void StringBuilder_AppendChar(StringBuilder* sb, char8 c) {
|
|
bux_sb_append_char(sb->handle, c);
|
|
|
|
}
|
|
|
|
String StringBuilder_Build(StringBuilder* sb) {
|
|
return bux_sb_build(sb->handle);
|
|
|
|
}
|
|
|
|
void StringBuilder_Free(StringBuilder* sb) {
|
|
bux_sb_free(sb->handle);
|
|
|
|
}
|
|
|
|
uint String_SplitCount(String s, String delim) {
|
|
return bux_str_split_count(s, delim);
|
|
|
|
}
|
|
|
|
String String_SplitPart(String s, String delim, uint index) {
|
|
return bux_str_split_part(s, delim, index);
|
|
|
|
}
|
|
|
|
String String_Join2(String a, String b, String sep) {
|
|
return bux_str_join2(a, b, sep);
|
|
|
|
}
|
|
|
|
String String_Chars(String s, uint index) {
|
|
return bux_str_slice(s, index, 1);
|
|
|
|
}
|
|
|
|
String String_Find(String haystack, String needle) {
|
|
return bux_strstr(haystack, needle);
|
|
|
|
}
|
|
|
|
uint String_Offset(String pos, String base) {
|
|
return bux_str_offset(pos, base);
|
|
|
|
}
|
|
|
|
String String_Replace(String s, String old, String new) {
|
|
String pos = bux_strstr(s, old);
|
|
if (String_IsNull(pos)) {
|
|
return s;
|
|
}
|
|
|
|
uint oldLen = bux_strlen(old);
|
|
uint prefixLen = String_Offset(pos, s);
|
|
String prefix = bux_str_slice(s, 0, prefixLen);
|
|
String suffix = bux_str_slice(s, prefixLen + oldLen, bux_strlen(s) - prefixLen - oldLen);
|
|
String temp = String_Concat(prefix, new);
|
|
String result = String_Concat(temp, suffix);
|
|
return result;
|
|
|
|
}
|
|
|
|
float64 String_ToFloat(String s) {
|
|
return bux_str_to_float(s);
|
|
|
|
}
|
|
|
|
String String_FromBool(bool b) {
|
|
if (b) {
|
|
return "true";
|
|
}
|
|
|
|
return "false";
|
|
|
|
}
|
|
|
|
String String_FromFloat(float64 f) {
|
|
return bux_float_to_string(f);
|
|
|
|
}
|
|
|
|
String String_Format1(String pattern, String a0) {
|
|
return bux_str_format(pattern, a0, "", "", "", "", "", "", "");
|
|
|
|
}
|
|
|
|
String String_Format2(String pattern, String a0, String a1) {
|
|
return bux_str_format(pattern, a0, a1, "", "", "", "", "", "");
|
|
|
|
}
|
|
|
|
String String_Format3(String pattern, String a0, String a1, String a2) {
|
|
return bux_str_format(pattern, a0, a1, a2, "", "", "", "", "");
|
|
|
|
}
|
|
|
|
void Channel_SendInt(Channel_int* ch, int value) {
|
|
bux_channel_send(ch->handle, ((void*)&value));
|
|
|
|
}
|
|
|
|
int Channel_RecvInt(Channel_int* ch) {
|
|
int result = 0;
|
|
bux_channel_recv(ch->handle, ((void*)&result));
|
|
return result;
|
|
|
|
}
|
|
|
|
void Channel_SendFloat64(Channel_float64* ch, float64 value) {
|
|
bux_channel_send(ch->handle, ((void*)&value));
|
|
|
|
}
|
|
|
|
float64 Channel_RecvFloat64(Channel_float64* ch) {
|
|
float64 result = 0.0;
|
|
bux_channel_recv(ch->handle, ((void*)&result));
|
|
return result;
|
|
|
|
}
|
|
|
|
int Main() {
|
|
int x = "hello";
|
|
return 0;
|
|
|
|
}
|
|
|
|
extern int g_argc;
|
|
extern char** g_argv;
|
|
int main(int argc, char** argv) {
|
|
g_argc = argc;
|
|
g_argv = argv;
|
|
return Main();
|
|
}
|