diff --git a/src/Int64.c b/src/Int64.c deleted file mode 100644 index 21f07f5..0000000 --- a/src/Int64.c +++ /dev/null @@ -1,399 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include - -#include -#include - -#include - -#ifdef INT64_NATIVE -#define Int64Sign(x) ((int) (((UInt64) (x)) >> 63)) -#else -#define Int64Sign(x) ((int) ((x).i[1] >> 31)) -#endif - -size_t -Int64Str(Int64 x, int base, char *out, size_t len) -{ - static const char symbols[] = "0123456789ABCDEF"; - - size_t i = len - 1; - size_t j = 0; - - int neg = Int64Sign(x); - - Int64 base64 = Int64Create(0, base); - - /* We only have symbols up to base 16 */ - if (base < 2 || base > 16) - { - return 0; - } - - /* - * This algorithm doesn't work on INT64_MIN. - * - * But it works on all other integers in the range, so we - * just scoot the range in by one for now. It's a hack and - * I'm not a huge fan of it, but this function is mostly - * used in Json, which shouldn't have a range this large - * anyway (Json is limited to -2^53 -> 2^53-1). - * - * Proper fixes are always welcome. - */ - if (Int64Eq(x, Int64Create(0x80000000, 0x00000000))) - { - x = Int64Add(x, Int64Create(0, 1)); - } -#if 0 - else if (Int64Eq(x, Int64Create(0x7FFFFFFF, 0xFFFFFFFF))) - { - x = Int64Sub(x, Int64Create(0, 1)); - } -#endif - - if (base != 2 && base != 8 && base != 16 && neg) - { - x = Int64Neg(x); - } - - do - { - Int64 mod = Int64Rem(x, base64); - Int32 low = Int64Low(mod); - - out[i] = symbols[low]; - i--; - x = Int64Div(x, base64); - } while (Int64Gt(x, Int64Create(0, 0))); - - if (base != 2 && base != 8 && base != 16) - { - /* - * Binary, octal, and hexadecimal are known to - * be bit representations. Everything else (notably - * decimal) should include the negative sign. - */ - if (neg) - { - out[i] = '-'; - i--; - } - } - - while (++i < len) - { - out[j++] = out[i]; - } - - out[j] = '\0'; - - return j; -} - -#ifndef INT64_NATIVE - -/* No native 64-bit support, add our own */ - -Int64 -Int64Create(UInt32 high, UInt32 low) -{ - Int64 x; - - x.i[0] = low; - x.i[1] = high; - - return x; -} - -Int64 -Int64Add(Int64 x, Int64 y) -{ - Int64 z = Int64Create(0, 0); - int carry; - - z.i[0] = x.i[0] + y.i[0]; - carry = z.i[0] < x.i[0]; - z.i[1] = x.i[1] + y.i[1] + carry; - - return z; -} - -Int64 -Int64Sub(Int64 x, Int64 y) -{ - return Int64Add(x, Int64Neg(y)); -} - -Int64 -Int64Mul(Int64 x, Int64 y) -{ - Int64 z = Int64Create(0, 0); - - int xneg = Int64Sign(x); - int yneg = Int64Sign(y); - - if (xneg) - { - x = Int64Neg(x); - } - - if (yneg) - { - y = Int64Neg(y); - } - - /* while (y > 0) */ - while (Int64Gt(y, Int64Create(0, 0))) - { - /* if (y & 1 != 0) */ - if (Int64Neq(Int64And(y, Int64Create(0, 1)), Int64Create(0, 0))) - { - z = Int64Add(z, x); - } - - x = Int64Sll(x, 1); - y = Int64Sra(y, 1); - } - - if (xneg != yneg) - { - z = Int64Neg(z); - } - - return z; -} - -typedef struct -{ - Int64 q; - Int64 r; -} Int64Ldiv; - -static Int64Ldiv -Int64LongDivision(Int64 n, Int64 d) -{ - Int64Ldiv o; - - int i; - - int nneg = Int64Sign(n); - int dneg = Int64Sign(d); - - o.q = Int64Create(0, 0); - o.r = Int64Create(0, 0); - - if (Int64Eq(d, Int64Create(0, 0))) - { - raise(SIGFPE); - return o; - } - - if (nneg) - { - n = Int64Neg(n); - } - - if (dneg) - { - d = Int64Neg(d); - } - - for (i = 63; i >= 0; i--) - { - Int64 bit = Int64And(Int64Sra(n, i), Int64Create(0, 1)); - - o.r = Int64Sll(o.r, 1); - o.r = Int64Or(o.r, bit); - - if (Int64Geq(o.r, d)) - { - o.r = Int64Sub(o.r, d); - o.q = Int64Or(o.q, Int64Sll(Int64Create(0, 1), i)); - } - } - - if (nneg != dneg) - { - o.r = Int64Neg(o.r); - o.q = Int64Neg(o.q); - } - - return o; -} - -Int64 -Int64Div(Int64 x, Int64 y) -{ - return Int64LongDivision(x, y).q; -} - -Int64 -Int64Rem(Int64 x, Int64 y) -{ - return Int64LongDivision(x, y).r; -} - -Int64 -Int64Sll(Int64 x, int y) -{ - Int64 z; - - if (!y) - { - return x; - } - - z = Int64Create(0, 0); - - if (y < 32) - { - z.i[1] = (x.i[0] >> (32 - y)) | (x.i[1] << y); - z.i[0] = x.i[0] << y; - } - else - { - z.i[1] = x.i[0] << (y - 32); - } - - return z; -} - -Int64 -Int64Sra(Int64 x, int y) -{ - Int64 z; - - int neg = Int64Sign(x); - - if (!y) - { - return x; - } - - z = Int64Create(0, 0); - - if (y < 32) - { - z.i[0] = (x.i[1] << (32 - y)) | (x.i[0] >> y); - z.i[1] = x.i[1] >> y; - } - else - { - z.i[0] = x.i[1] >> (y - 32); - } - - if (neg) - { - Int64 mask = Int64Create(0xFFFFFFFF, 0xFFFFFFFF); - - z = Int64Or(Int64Sll(mask, (64 - y)), z); - } - - return z; -} - -Int64 -Int64And(Int64 x, Int64 y) -{ - return Int64Create(x.i[1] & y.i[1], x.i[0] & y.i[0]); -} - -Int64 -Int64Or(Int64 x, Int64 y) -{ - return Int64Create(x.i[1] | y.i[1], x.i[0] | y.i[0]); -} - -Int64 -Int64Xor(Int64 x, Int64 y) -{ - return Int64Create(x.i[1] ^ y.i[1], x.i[0] ^ y.i[0]); -} - -Int64 -Int64Not(Int64 x) -{ - return Int64Create(~(x.i[1]), ~(x.i[0])); -} - -int -Int64Eq(Int64 x, Int64 y) -{ - return x.i[0] == y.i[0] && x.i[1] == y.i[1]; -} - -int -Int64Lt(Int64 x, Int64 y) -{ - int xneg = Int64Sign(x); - int yneg = Int64Sign(y); - - if (xneg != yneg) - { - return xneg > yneg; - } - else - { - if (xneg) - { - /* Both negative */ - return x.i[1] > y.i[1] || (x.i[1] == y.i[1] && x.i[0] > y.i[0]); - } - else - { - /* Both positive */ - return x.i[1] < y.i[1] || (x.i[1] == y.i[1] && x.i[0] < y.i[0]); - } - } -} - -int -Int64Gt(Int64 x, Int64 y) -{ - int xneg = Int64Sign(x); - int yneg = Int64Sign(y); - - if (xneg != yneg) - { - return xneg < yneg; - } - else - { - if (xneg) - { - /* Both negative */ - return x.i[1] < y.i[1] || (x.i[1] == y.i[1] && x.i[0] < y.i[0]); - } - else - { - /* Both positive */ - return x.i[1] > y.i[1] || (x.i[1] == y.i[1] && x.i[0] > y.i[0]); - } - } - -} - -#endif diff --git a/src/UInt64.c b/src/UInt64.c deleted file mode 100644 index ae8eff7..0000000 --- a/src/UInt64.c +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include - -#include -#include - -size_t -UInt64Str(UInt64 x, int base, char *out, size_t len) -{ - static const char symbols[] = "0123456789ABCDEF"; - - size_t i = len - 1; - size_t j = 0; - - UInt64 base64 = UInt64Create(0, base); - - /* We only have symbols up to base 16 */ - if (base < 2 || base > 16) - { - return 0; - } - - do - { - UInt64 mod = UInt64Rem(x, base64); - UInt32 low = UInt64Low(mod); - - out[i] = symbols[low]; - i--; - x = UInt64Div(x, base64); - } while (UInt64Gt(x, UInt64Create(0, 0))); - - while (++i < len) - { - out[j++] = out[i]; - } - - out[j] = '\0'; - - return j; -} - -#ifndef UINT64_NATIVE - -/* No native 64-bit support, add our own */ - -UInt64 -UInt64Create(UInt32 high, UInt32 low) -{ - UInt64 x; - - x.i[0] = low; - x.i[1] = high; - - return x; -} - -UInt64 -UInt64Add(UInt64 x, UInt64 y) -{ - UInt64 z = UInt64Create(0, 0); - int carry; - - z.i[0] = x.i[0] + y.i[0]; - carry = z.i[0] < x.i[0]; - z.i[1] = x.i[1] + y.i[1] + carry; - - return z; -} - -UInt64 -UInt64Sub(UInt64 x, UInt64 y) -{ - UInt64 twosCompl = UInt64Add(UInt64Not(y), UInt64Create(0, 1)); - - return UInt64Add(x, twosCompl); -} - -UInt64 -UInt64Mul(UInt64 x, UInt64 y) -{ - UInt64 z = UInt64Create(0, 0); - - /* while (y > 0) */ - while (UInt64Gt(y, UInt64Create(0, 0))) - { - /* if (y & 1 != 0) */ - if (UInt64Neq(UInt64And(y, UInt64Create(0, 1)), UInt64Create(0, 0))) - { - z = UInt64Add(z, x); - } - - x = UInt64Sll(x, 1); - y = UInt64Srl(y, 1); - } - - return z; -} - -typedef struct -{ - UInt64 q; - UInt64 r; -} UInt64Ldiv; - -static UInt64Ldiv -UInt64LongDivision(UInt64 n, UInt64 d) -{ - UInt64Ldiv o; - - int i; - - o.q = UInt64Create(0, 0); - o.r = UInt64Create(0, 0); - - if (UInt64Eq(d, UInt64Create(0, 0))) - { - raise(SIGFPE); - return o; - } - - for (i = 63; i >= 0; i--) - { - UInt64 bit = UInt64And(UInt64Srl(n, i), UInt64Create(0, 1)); - - o.r = UInt64Sll(o.r, 1); - o.r = UInt64Or(o.r, bit); - - if (UInt64Geq(o.r, d)) - { - o.r = UInt64Sub(o.r, d); - o.q = UInt64Or(o.q, UInt64Sll(UInt64Create(0, 1), i)); - } - } - - return o; -} - -UInt64 -UInt64Div(UInt64 x, UInt64 y) -{ - return UInt64LongDivision(x, y).q; -} - -UInt64 -UInt64Rem(UInt64 x, UInt64 y) -{ - return UInt64LongDivision(x, y).r; -} - -UInt64 -UInt64Sll(UInt64 x, int y) -{ - UInt64 z; - - if (!y) - { - return x; - } - - z = UInt64Create(0, 0); - - if (y < 32) - { - z.i[1] = (x.i[0] >> (32 - y)) | (x.i[1] << y); - z.i[0] = x.i[0] << y; - } - else - { - z.i[1] = x.i[0] << (y - 32); - } - - return z; -} - -UInt64 -UInt64Srl(UInt64 x, int y) -{ - UInt64 z; - - if (!y) - { - return x; - } - - z = UInt64Create(0, 0); - - if (y < 32) - { - z.i[0] = (x.i[1] << (32 - y)) | (x.i[0] >> y); - z.i[1] = x.i[1] >> y; - } - else - { - z.i[0] = x.i[1] >> (y - 32); - } - - return z; -} - -UInt64 -UInt64And(UInt64 x, UInt64 y) -{ - return UInt64Create(x.i[1] & y.i[1], x.i[0] & y.i[0]); -} - -UInt64 -UInt64Or(UInt64 x, UInt64 y) -{ - return UInt64Create(x.i[1] | y.i[1], x.i[0] | y.i[0]); -} - -UInt64 -UInt64Xor(UInt64 x, UInt64 y) -{ - return UInt64Create(x.i[1] ^ y.i[1], x.i[0] ^ y.i[0]); -} - -UInt64 -UInt64Not(UInt64 x) -{ - return UInt64Create(~(x.i[1]), ~(x.i[0])); -} - -int -UInt64Eq(UInt64 x, UInt64 y) -{ - return x.i[0] == y.i[0] && x.i[1] == y.i[1]; -} - -int -UInt64Lt(UInt64 x, UInt64 y) -{ - return x.i[1] < y.i[1] || (x.i[1] == y.i[1] && x.i[0] < y.i[0]); -} - -int -UInt64Gt(UInt64 x, UInt64 y) -{ - return x.i[1] > y.i[1] || (x.i[1] == y.i[1] && x.i[0] > y.i[0]); -} - -#endif diff --git a/src/include/Args.h b/src/include/Args.h deleted file mode 100644 index 3108de3..0000000 --- a/src/include/Args.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef CYTOPLASM_ARGS_H -#define CYTOPLASM_ARGS_H - -/*** - * @Nm Args - * @Nd Getopt-style argument parser that operates on arrays. - * @Dd May 12 2023 - * @Xr Array - * - * .Nm - * provides a simple argument parser in the style of - * .Xr getopt 3 . - * It exists because the runtime passes the program arguments as - * an Array, and it is often useful to parse the arguments to - * provide the standard command line interface. - */ - -#include - -/** - * All state is stored in this structure, instead of global - * variables. This makes - * .Nm - * thread-safe and easy to reset. - */ -typedef struct ArgParseState -{ - int optInd; - int optErr; - int optOpt; - char *optArg; - - int optPos; -} ArgParseState; - -/** - * Initialize the variables in the given parser state structure - * to their default values. This should be called before - * .Fn ArgParse - * is called with the parser state. It should also be called if - * .Fn ArgParse - * will be used again on a different array, or the same array all - * over again. - */ -extern void ArgParseStateInit(ArgParseState *); - -/** - * Parse command line arguments stored in the given array, using - * the given state and option string. This function behaves - * identically to the POSIX - * .Fn getopt - * function, and should be used in exactly the same way. Refer to - * your system's - * .Xr getopt 3 - * page for details. - */ -extern int ArgParse(ArgParseState *, Array *, const char *); - -#endif /* CYTOPLASM_ARGS_H */ diff --git a/src/include/Array.h b/src/include/Array.h deleted file mode 100644 index 0ba1335..0000000 --- a/src/include/Array.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef CYTOPLASM_ARRAY_H -#define CYTOPLASM_ARRAY_H - -/*** - * @Nm Array - * @Nd A simple dynamic array data structure. - * @Dd November 24 2022 - * @Xr HashMap Queue - * - * These functions implement a simple array data structure that is - * automatically resized as necessary when new values are added. This - * implementation does not actually store the values of the items in it; - * it only stores pointers to the data. As such, you will still have to - * manually maintain all your data. The advantage of this is that these - * functions don't have to copy data, and thus don't care how big the - * data is. Furthermore, arbitrary data can be stored in the array. - * .Pp - * This array implementation is optimized for storage space and - * appending. Deletions are expensive in that all the items of the list - * above a deletion are moved down to fill the hole where the deletion - * occurred. Insertions are also expensive in that all the elements - * above the given index must be shifted up to make room for the new - * element. - * .Pp - * Due to these design choices, this array implementation is best - * suited to linear writing, and then linear or random reading. - */ - -#include -#include - -/** - * The functions in this API operate on an array structure which is - * opaque to the caller. - */ -typedef struct Array Array; - -/** - * Allocate a new array. This function returns a pointer that can be - * used with the other functions in this API, or NULL if there was an - * error allocating memory for the array. - */ -extern Array *ArrayCreate(void); - -/** - * Deallocate an array. Note that this function does not free any of - * the values stored in the array; it is the caller's job to manage the - * memory for each item. Typically, the caller would iterate over all - * the items in the array and free them before freeing the array. - */ -extern void ArrayFree(Array *); - -/** - * Get the size, in number of elements, of the given array. - */ -extern size_t ArraySize(Array *); - -/** - * Get the element at the specified index from the specified array. - * This function will return NULL if the array is NULL, or the index - * is out of bounds. Otherwise, it will return a pointer to a value - * put into the array using - * .Fn ArrayInsert - * or - * .Fn ArraySet . - */ -extern void *ArrayGet(Array *, size_t); - -/** - * Insert the specified element at the specified index in the specified - * array. This function will shift the element currently at that index, - * and any elements after it before inserting the given element. - * .Pp - * This function returns a boolean value indicating whether or not it - * suceeded. - */ -extern int ArrayInsert(Array *, size_t, void *); - -/** - * Set the value at the specified index in the specified array to the - * specified value. This function will return the old value at that - * index, if any. - */ -extern void *ArraySet(Array *, size_t, void *); - -/** - * Append the specified element to the end of the specified array. This - * function uses - * .Fn ArrayInsert - * under the hood to insert an element at the end. It thus has the same - * return value as - * .Fn ArrayInsert . - */ -extern int ArrayAdd(Array *, void *); - -/** - * Remove the element at the specified index from the specified array. - * This function returns the element removed, if any. - */ -extern void *ArrayDelete(Array *, size_t); - -/** - * Sort the specified array using the specified sort function. The - * sort function compares two elements. It takes two void pointers as - * parameters, and returns an integer. The return value indicates to - * the sorting algorithm how the elements relate to each other. A - * return value of 0 indicates that the elements are identical. A - * return value greater than 0 indicates that the first item is - * ``bigger'' than the second item and should thus appear after it in - * the array. A return value less than 0 indicates the opposite: the - * second element should appear after the first in the array. - */ -extern void ArraySort(Array *, int (*) (void *, void *)); - -/** - * Remove all duplicates from an array by using the given comparison - * function to sort the array, then remove matching values. This - * function returns a new array with all duplicates removed. The - * original array is unaffected. Note that arrays only store pointers - * to values, usually values on the heap. Thus, it is possible to lose - * pointers to duplicate values and have them leak. - * .P - * This is a relatively expensive operation. The array must first be - * duplicated. Then it is sorted, then it is iterated from beginning - * to end to remove duplicate entires. Note that the comparison - * function is executed on each element at least twice. - */ -extern Array *ArrayUnique(Array *, int (*) (void *, void *)); - - -/** - * Reverses the order of all elements in the array into a new array on - * the heap, to be freed using - * .Fn ArrayFree . - */ -extern Array *ArrayReverse(Array *); - -/** - * If possible, reduce the amount of memory allocated to this array - * by calling - * .Fn Realloc - * on the internal structure to perfectly fit the elements in the - * array. This function is intended to be used by functions that return - * relatively read-only arrays that will be long-lived. - */ -extern int ArrayTrim(Array *); - -/** - * Convert a variadic arguments list into an Array. In most cases, the - * Array API is much easier to work with than - * .Fn va_arg - * and friends. - */ -extern Array *ArrayFromVarArgs(size_t, va_list); - -/** - * Duplicate an existing array. Note that arrays only hold pointers to - * their data, not the data itself, so the duplicated array will point - * to the same places in memory as the original array. - */ -extern Array *ArrayDuplicate(Array *); - -#endif /* CYTOPLASM_ARRAY_H */ diff --git a/src/include/Base64.h b/src/include/Base64.h deleted file mode 100644 index b36a48c..0000000 --- a/src/include/Base64.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef CYTOPLASM_BASE64_H -#define CYTOPLASM_BASE64_H - -/*** - * @Nm Base64 - * @Nd A simple base64 encoder/decoder with unpadded base64 support. - * @Dd September 30 2022 - * @Xr Sha2 - * - * This is an efficient yet simple base64 encoding and decoding API - * that supports regular base64, as well as the Matrix specification's - * extension to base64, called ``unpadded base64.'' This API provides - * the ability to convert between the two, instead of just implementing - * unpadded base64. - */ - -#include - -/** - * This function computes the amount of bytes needed to store a message - * of the specified number of bytes as base64. - */ -extern size_t - Base64EncodedSize(size_t); - -/** - * This function computes the amount of bytes needed to store a decoded - * representation of the encoded message. It takes a pointer to the - * encoded string because it must read a few bytes off the end in order - * to accurately compute the size. - */ -extern size_t - Base64DecodedSize(const char *, size_t); - -/** - * Encode the specified number of bytes from the specified buffer as - * base64. This function returns a string on the heap that should be - * freed with - * .Fn Free , - * or NULL if a memory allocation error ocurred. - */ -extern char * - Base64Encode(const char *, size_t); - -/** - * Decode the specified number of bytes from the specified buffer of - * base64. This function returns a string on the heap that should be - * freed with - * .Fn Free , - * or NULL if a memory allocation error occured. - */ -extern char * - Base64Decode(const char *, size_t); - -/** - * Remove the padding from a specified base64 string. This function - * modifies the specified string in place. It thus has no return value - * because it cannot fail. If the passed pointer is invalid, the - * behavior is undefined. - */ -extern void - Base64Unpad(char *, size_t); - -/** - * Add padding to an unpadded base64 string. This function takes a - * pointer to a pointer because it may be necessary to grow the memory - * allocated to the string. This function returns a boolean value - * indicating whether the pad operation was successful. In practice, - * this means it will only fail if a bigger string is necessary, but it - * could not be automatically allocated on the heap. - */ -extern int - Base64Pad(char **, size_t); - -#endif /* CYTOPLASM_BASE64_H */ diff --git a/src/include/Cron.h b/src/include/Cron.h deleted file mode 100644 index e78900d..0000000 --- a/src/include/Cron.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef CYTOPLASM_CRON_H -#define CYTOPLASM_CRON_H - -/*** - * @Nm Cron - * @Nd Basic periodic job scheduler. - * @Dd December 24 2022 - * - * This is an extremely basic job scheduler. So basic, in fact, that - * it currently runs all jobs on a single thread, which means that it - * is intended for short-lived jobs. In the future, it might be - * extended to support a one-thread-per-job model, but for now, jobs - * should take into consideration the fact that they are sharing their - * thread, so they should not be long-running. - * .Pp - * .Nm - * works by ``ticking'' at an interval defined by the caller of - * .Fn CronCreate . - * At each tick, all the registered jobs are queried, and if they are - * due to run again, their function is executed. As much as possible, - * .Nm - * tries to tick at constant intervals, however it is possible that one - * or more jobs may overrun the tick duration. If this happens, - * .Nm - * ticks again immediately after all the jobs for the previous tick - * have completed. This is in an effort to compensate for lost time, - * however it is important to note that when jobs overrun the tick - * interval, the interval is pushed back by the amount that it was - * overrun. Because of this, - * .Nm - * is best suited for scheduling jobs that should happen - * ``aproximately'' every so often; it is not a real-time scheduler - * by any means. - */ - -#include - -/** - * All functions defined here operate on a structure opaque to the - * caller. - */ -typedef struct Cron Cron; - -/** - * A job function is a function that takes a void pointer and returns - * nothing. The pointer is passed when the job is scheduled, and - * is expected to remain valid until the job is no longer registered. - * The pointer is passed each time the job executes. - */ -typedef void (JobFunc) (void *); - -/** - * Create a new - * .Nm - * object that all other functions operate on. Like most of the other - * APIs in this project, it must be freed with - * .Fn CronFree - * when it is no longer needed. - * .Pp - * This function takes the tick interval in milliseconds. - */ -extern Cron * CronCreate(UInt32); - -/** - * Schedule a one-off job to be executed only at the next tick, and - * then immediately discarded. This is useful for scheduling tasks that - * only have to happen once, or very infrequently depending on - * conditions other than the current time, but don't have to happen - * immediately. The caller simply indicates that it wishes for the task - * to execute at some time in the future. How far into the future this - * practically ends up being is determined by how long it takes for - * other registered jobs to finish, and what the tick interval is. - * .Pp - * This function takes a job function and a pointer to pass to that - * function when it is executed. - */ -extern void - CronOnce(Cron *, JobFunc *, void *); - -/** - * Schedule a repetitive task to be executed at aproximately the given - * interval. As stated above, this is as fuzzy interval; depending on - * the jobs being run and the tick interval, tasks may not execute at - * exactly the scheduled time, but they will eventually execute. - * .Pp - * This function takes an interval in milliseconds, a job function, - * and a pointer to pass to that function when it is executed. - */ -extern void - CronEvery(Cron *, unsigned long, JobFunc *, void *); - -/** - * Start ticking the clock and executing registered jobs. - */ -extern void - CronStart(Cron *); - -/** - * Stop ticking the clock. Jobs that are already executing will - * continue to execute, but when they are finished, no new jobs will - * be executed until - * .Fn CronStart - * is called. - */ -extern void - CronStop(Cron *); - -/** - * Discard all job references and free all memory associated with the - * given - * .Nm Cron - * instance. - */ -extern void - CronFree(Cron *); - -#endif /* CYTOPLASM_CRON_H */ diff --git a/src/include/Db.h b/src/include/Db.h deleted file mode 100644 index 618a2e2..0000000 --- a/src/include/Db.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef CYTOPLASM_DB_H -#define CYTOPLASM_DB_H - -/*** - * @Nm Db - * @Nd A minimal flat-file database with mutex locking and cache. - * @Dd April 27 2023 - * @Xr Json - * - * Cytoplasm operates on a flat-file database instead of a - * traditional relational database. This greatly simplifies the - * persistent storage code, and creates a relatively basic API, - * described here. - */ - -#include - -#include -#include - -/** - * All functions in this API operate on a database structure that is - * opaque to the caller. - */ -typedef struct Db Db; - -/** - * When an object is locked, a reference is returned. This reference - * is owned by the current thread, and the database is inaccessible to - * other threads until all references have been returned to the - * database. - * .Pp - * This reference is opaque, but can be manipulated by the functions - * defined here. - */ -typedef struct DbRef DbRef; - -/** - * Open a data directory. This function takes a path to open, and a - * cache size in bytes. If the cache size is 0, then caching is - * disabled and objects are loaded off the disk every time they are - * locked. Otherwise, objects are stored in the cache, and they are - * evicted in a least-recently-used manner. - */ -extern Db * DbOpen(char *, size_t); - -/** - * Close the database. This function will flush anything in the cache - * to the disk, and then close the data directory. It assumes that - * all references have been unlocked. If a reference has not been - * unlocked, undefined behavior results. - */ -extern void DbClose(Db *); - -/** - * Set the maximum cache size allowed before - * .Nm - * starts evicting old objects. If this is set to 0, everything in the - * cache is immediately evicted and caching is disabled. If the - * database was opened with a cache size of 0, setting this will - * initialize the cache, and subsequent calls to - * .Fn DbLock - * will begin caching objects. - */ -extern void DbMaxCacheSet(Db *, size_t); - -/** - * Create a new object in the database with the specified name. This - * function will fail if the object already exists in the database. It - * takes a variable number of C strings, with the exact number being - * specified by the second parameter. These C strings are used to - * generate a filesystem path at which to store the object. These paths - * ensure each object is uniquely identifiable, and provides semantic - * meaning to an object. - */ -extern DbRef * DbCreate(Db *, size_t,...); - -/** - * Lock an existing object in the database. This function will fail - * if the object does not exist. It takes a variable number of C - * strings, with the exact number being specified by the second - * parameter. These C strings are used to generate the filesystem path - * at which to load the object. These paths ensure each object is - * uniquely identifiable, and provides semantic meaning to an object. - */ -extern DbRef * DbLock(Db *, size_t,...); - -/** - * Immediately and permanently remove an object from the database. - * This function assumes the object is not locked, otherwise undefined - * behavior will result. - */ -extern int DbDelete(Db *, size_t,...); - -/** - * Unlock an object and return it back to the database. This function - * immediately syncs the object to the filesystem. The cache is a - * read cache; writes are always immediate to ensure data integrity in - * the event of a system failure. - */ -extern int DbUnlock(Db *, DbRef *); - -/** - * Check the existence of the given database object in a more efficient - * manner than attempting to lock it with - * .Fn DbLock . - * This function does not lock the object, nor does it load it into - * memory if it exists. - */ -extern int DbExists(Db *, size_t,...); - -/** - * List all of the objects at a given path. Unlike the other varargs - * functions, this one does not take a path to a specific object; it - * takes a directory to be iterated, where each path part is its own - * C string. Note that the resulting list only contains the objects - * in the specified directory, it does not list any subdirectories. - * .Pp - * The array returned is an array of C strings containing the object - * name. - */ -extern Array * DbList(Db *, size_t,...); - -/** - * Free the list returned by - * .Fn DbListFree . - */ -extern void DbListFree(Array *); - -/** - * Convert a database reference into JSON that can be manipulated. - * At this time, the database actually stores objects as JSON on the - * disk, so this function just returns an internal pointer, but in the - * future it may have to be generated by decompressing a binary blob, - * or something of that nature. - */ -extern HashMap * DbJson(DbRef *); - -/** - * Free the existing JSON associated with the given reference, and - * replace it with new JSON. This is more efficient than duplicating - * a separate object into the database reference. - */ -extern int DbJsonSet(DbRef *, HashMap *); - -#endif diff --git a/src/include/Graph.h b/src/include/Graph.h deleted file mode 100644 index 02e4e02..0000000 --- a/src/include/Graph.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef CYTOPLASM_GRAPH_H -#define CYTOPLASM_GRAPH_H - -/*** - * @Nm Graph - * @Nd Extremely simple graph, implemented as an adjacency matrix. - * @Dd July 15 2023 - * - * .Nm - * is a basic graph data structure originally written for a computer - * science class on data structures and algorithms, in which it - * received full credit. This is an adaptation of the original - * implementation that follows the Cytoplasm style and uses Cytoplasm - * APIs when convenient. - * .P - * .Nm - * stores data in an adjacency matrix, which means the storage - * complexity is O(N^2), where N is the number of vertices (called - * Nodes in this implementation) in the graph. However, this makes the - * algorithms fast and efficient. - * .P - * Nodes are identified by index, so the first node is 0, the second - * is 1, and so on. This data structure does not support storing - * arbitrary data as nodes; rather, the intended use case is to add - * all your node data to an Array, thus giving each node an index, - * and then manipulating the graph with that index. This allows access - * to node data in O(1) time in call cases, and is the most memory - * efficient. - * .P - * .Nm - * can be used to store a variety of types of graphs, although it is - * primarily suited to directed and weighted graphs. - */ - -#include - -/** - * The functions provided here operate on an opaque graph structure. - * This structure really just stores a matrix in a contiguous block of - * memory, as well as the number of nodes in the graph, but the - * structure is kept opaque so that it remains internally consistent. - * It also maintains the style of the Cytoplasm library. - */ -typedef struct Graph Graph; - -/** - * An Edge is really just a weight, which is easily represented by an - * integer. However, it makes sense to alias this to Edge for clarity, - * both in the documentation and in the implementation. - */ -typedef int Edge; - -/** - * A Node is really just a row or column in the matrix, which is easily - * represented by an unsigned integer. However, it makes sense to alias - * this to Node for clarity, both in the documentation and the - * implementation. - */ -typedef size_t Node; - -/** - * Create a new graph structure with the given number of vertices. - */ -extern Graph *GraphCreate(size_t); - -/** - * Create a new graph data structure with the given number of vertices - * and the given adjacency matrix. The adjacency matrix is copied - * verbatim into the graph data structure without any validation. - */ -extern Graph *GraphCreateWithEdges(size_t, Edge *); - -/** - * Free all memory associated with the given graph. Since graphs are - * just a collection of numbers, they do not depend on each other in - * any way. - */ -extern void GraphFree(Graph *); - -/** - * Get the weight of the edge connecting the node specified first to - * the node specified second. If this is a directed graph, it does not - * necessarily follow that there is an edge from the node specified - * second to the node specified first. It also does not follow that - * such an edge, if it exists, has the same weight. - * .P - * This function will return -1 if the graph is invalid or either node - * is out of bounds. It will return 0 if there is no such edge from the - * node specified first to the node specified second. - */ -extern Edge GraphEdgeGet(Graph *, Node, Node); - -/** - * Set the weight of the edge connecting the node specified first to - * the node specified second. If this is not a directed graph, this - * function will have to be called twice, the second time reversing the - * order of the nodes. To remove the edge, specify a weight of 0. - */ -extern Edge GraphEdgeSet(Graph *, Node, Node, Edge); - -/** - * Get the number of nodes in the given graph. This operation is a - * simple memory access that happens in O(1) time. - */ -extern size_t GraphCountNodes(Graph *); - -/** - * Perform a breadth-first search on the given graph, starting at the - * specified node. This function returns a list of nodes in the order - * they were touched. The size of the list is stored in the unsigned - * integer pointed to by the last argument. - * .P - * If an error occurs, NULL will be returned. Otherwise, the returned - * pointer should be freed with the Memory API when it is no longer - * needed. - */ -extern Node * GraphBreadthFirstSearch(Graph *, Node, size_t *); - -/** - * Perform a depth-first search on the given graph, starting at the - * specified node. This function returns a list of nodes in the order - * they were touched. The size of the list is stored in the unsigned - * integer pointed to by the last argument. - * .P - * If an error occurs, NULL will be returned. Otherwise the returned - * pointer should be freed with the Memory API when it is no longer - * needed. - */ -extern Node *GraphDepthFirstSearch(Graph *, Node, size_t *); - -/** - * Perform a topological sort on the given graph. This function returns - * a list of nodes in topological ordering, though note that this is - * probably not the only topological ordering that exists for the - * graph. The size of the list is stored in the unsigned integer - * pointed to by the last argument. It should always be the number of - * nodes in the graph, but is provided for consistency and convenience. - * .P - * If an error occurs, NULL will be returned. Otherwise the returned - * pointer should be freed with the Memory API when it is no longer - * needed. - */ -extern Node *GraphTopologicalSort(Graph *, size_t *); - -/** - * Transpose the given graph, returning a brand new graph that is the - * result of the transposition. - */ -extern Graph * GraphTranspose(Graph *); - -#endif /* CYTOPLASM_GRAPH_H */ diff --git a/src/include/HashMap.h b/src/include/HashMap.h deleted file mode 100644 index 1359400..0000000 --- a/src/include/HashMap.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef CYTOPLASM_HASHMAP_H -#define CYTOPLASM_HASHMAP_H - -/*** - * @Nm HashMap - * @Nd A simple hash map implementation. - * @Dd October 11 2022 - * @Xr Array Queue - * - * This is the public interface for Cytoplasm's hash map - * implementation. This hash map is designed to be simple, - * well-documented, and generally readable and understandable, yet also - * performant enough to be useful, because it is used extensively - * throughout the project. - * .Pp - * Fundamentally, this is an entirely generic map implementation. It - * can be used for many general purposes, but it is designed only to - * implement the features Cytoplasm needs to be functional. One - * example of a Cytoplasm-specific feature is that keys cannot be - * arbitrary data; they are NULL-terminated C strings. - */ - -#include - -#include - -/** - * These functions operate on an opaque structure, which the caller - * has no knowledge about. - */ -typedef struct HashMap HashMap; - -/** - * Create a new hash map that is ready to be used with the rest of the - * functions defined here. - */ -extern HashMap * HashMapCreate(void); - -/** - * Free the specified hash map such that it becomes invalid and any - * future use results in undefined behavior. Note that this function - * does not free the values stored in the hash map, but since it stores - * the keys internally, it will free the keys. You should use - * .Fn HashMapIterate - * to free the values stored in this map appropriately before calling - * this function. - */ -extern void HashMapFree(HashMap *); - -/** - * Control the maximum load of the hash map before it is expanded. - * When the hash map reaches the given capacity, it is grown. You - * don't want to only grow hash maps when they are full, because that - * makes them perform very poorly. The maximum load value is a - * percentage of how full the hash map is, and it should be between - * 0 and 1, where 0 means that no elements will cause the map to be - * expanded, and 1 means that the hash map must be completely full - * before it is expanded. The default maximum load on a new hash map - * is 0.75, which should be good enough for most purposes, however, - * this function exists specifically so that the maximum load can be - * fine-tuned. - */ -extern void HashMapMaxLoadSet(HashMap *, float); - -/** - * Use a custom hashing function with the given hash map. New hash - * maps have a sane hashing function that should work okay for most - * use cases, but if you have a better hashing function, it can be - * specified this way. Do not change the hash function after keys have - * been added; doing so results in undefined behavior. Only set a new - * hash function immediately after constructing a new hash map, before - * anything has been added to it. - * .Pp - * The hash function takes a pointer to a C string, and is expected - * to return a fairly unique numerical hash value which will be - * converted into an array index. - */ -extern void -HashMapFunctionSet(HashMap *, unsigned long (*) (const char *)); - -/** - * Set the given string key to the given value. Note that the key is - * copied into the hash map's own memory space, but the value is not. - * It is the caller's job to ensure that the value pointer remains - * valid for the life of the hash map, and are freed when no longer - * needed. - */ -extern void * HashMapSet(HashMap *, char *, void *); - -/** - * Retrieve the value for the given key, or return NULL if no such - * key exists in the hash map. - */ -extern void * HashMapGet(HashMap *, const char *); - -/** - * Remove a value specified by the given key from the hash map, and - * return it to the caller to deal with. This function returns NULL - * if no such key exists. - */ -extern void * HashMapDelete(HashMap *, const char *); - -/** - * Iterate over all the keys and values of a hash map. This function - * works very similarly to - * .Xr getopt 3 , - * where calls are repeatedly made in a while loop until there are no - * more items to go over. The difference is that this function does not - * rely on globals; it takes pointer pointers, and stores all - * necessary state inside the hash map itself. - * .Pp - * Note that this function is not thread-safe; two threads cannot be - * iterating over any given hash map at the same time, though they - * can each be iterating over different hash maps. - * .Pp - * This function can be tricky to use in some scenarios, as it - * continues where it left off on each call, until there are no more - * elements to go through in the hash map. If you are not iterating - * over the entire map in one go, and happen to break the loop, then - * the next time you attempt to iterate the hash map, you'll start - * somewhere in the middle, which is most likely not the intended - * behavior. Thus, it is always recommended to iterate over the entire - * hash map if you're going to use this function. - * .Pp - * Also note that the behavior of this function is undefined if - * insertions or deletions occur during the iteration. This - * functionality has not been tested, and will likely not work. - */ -extern int HashMapIterate(HashMap *, char **, void **); - -/** - * A reentrant version of - * .Fn HashMapIterate - * that allows the caller to overcome the flaws of that function by - * storing the cursor outside of the hash map structure itself. This - * allows multiple threads to iterate over the same hash map at the - * same time, and it allows the iteration to be halted midway through - * without causing any unintended side effects. - * .Pp - * The cursor should be initialized to 0 at the start of iteration. - */ -extern int -HashMapIterateReentrant(HashMap *, char **, void **, size_t *); - -/** - * Collect the string keys of a hash map and return them as an array. - * The returned array holds pointers to the strings stored in the - * hash map, so the strings should NOT be freed; it is sufficient to - * free the array itself. Likewise, once the hash map is freed, the - * array elements are invalid and the array should be freed. - */ -extern Array * HashMapKeys(HashMap *); - -/** - * Collect the values of a hash map and return them as an array. The - * returned array holds the same pointers to the values as the hash - * map. - */ -extern Array * HashMapValues(HashMap *); - -#endif /* CYTOPLASM_HASHMAP_H */ diff --git a/src/include/HeaderParser.h b/src/include/HeaderParser.h deleted file mode 100644 index ffb3d0b..0000000 --- a/src/include/HeaderParser.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef CYTOPLASM_HEADERPARSER_H -#define CYTOPLASM_HEADERPARSER_H - -/*** - * @Nm HeaderParser - * @Nd Parse simple C header files. - * @Dd April 29 2023 - * - * .Nm - * is an extremely simple parser that lacks most of the functionality - * one would expect from a C code parser. It simply maps a stream - * of tokens into a few categories, parsing major ``milestones'' in - * a header, without actually understanding any of the details. - * .Pp - * This exists because it is used to generate man pages from headers. - * See - * .Xr hdoc 1 - * for example usage of this parser. - */ - -#include -#include - -#define HEADER_EXPR_MAX 4096 - -/** - * Headers are parsed as expressions. These are the expressions that - * this parser recognizes. - */ -typedef enum HeaderExprType -{ - HP_COMMENT, - HP_PREPROCESSOR_DIRECTIVE, - HP_TYPEDEF, - HP_DECLARATION, - HP_GLOBAL, - HP_UNKNOWN, - HP_SYNTAX_ERROR, - HP_PARSE_ERROR, - HP_EOF -} HeaderExprType; - -/** - * A representation of a function declaration. - */ -typedef struct HeaderDeclaration -{ - char returnType[64]; - char name[32]; /* Enforced by ANSI C */ - Array *args; -} HeaderDeclaration; - -/** - * A global variable declaration. The type must be of the same size - * as the function declaration's return type due to the way parsing - * them is implemented. - */ -typedef struct HeaderGlobal -{ - char type[64]; - char name[HEADER_EXPR_MAX - 64]; -} HeaderGlobal; - -/** - * A representation of a single header expression. Note that that state - * structure is entirely internally managed, so it should not be - * accessed or manipulated by functions outside the functions defined - * here. - * .Pp - * The type field should be used to determine which field in the data - * union is valid. - */ -typedef struct HeaderExpr -{ - HeaderExprType type; - union - { - char text[HEADER_EXPR_MAX]; - HeaderDeclaration declaration; - HeaderGlobal global; - struct - { - int lineNo; - char *msg; - } error; - } data; - - struct - { - Stream *stream; - int lineNo; - } state; -} HeaderExpr; - -/** - * Parse the next expression into the given header expression structure. - * To parse an entire C header, this function should be called in a - * loop until the type of the expression is HP_EOF. - */ -extern void HeaderParse(Stream *, HeaderExpr *); - -#endif /* CYTOPLASM_HEADERPARSER_H */ diff --git a/src/include/Http.h b/src/include/Http.h deleted file mode 100644 index d2de020..0000000 --- a/src/include/Http.h +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef CYTOPLASM_HTTP_H -#define CYTOPLASM_HTTP_H - -/*** - * @Nm Http - * @Nd Encode and decode various parts of the HTTP protocol. - * @Dd March 12 2023 - * @Xr HttpClient HttpServer HashMap Queue Memory - * - * .Nm - * is a collection of utility functions and type definitions that are - * useful for dealing with HTTP. HTTP is not a complex protocol, but - * this API makes it a lot easier to work with. - * .Pp - * Note that this API doesn't target any particular HTTP version, but - * it is currently used with HTTP 1.0 clients and servers, and - * therefore may be lacking functionality added in later HTTP versions. - */ - -#include - -#include -#include - -#define HTTP_FLAG_NONE 0 -#define HTTP_FLAG_TLS (1 << 0) - -/** - * The request methods defined by the HTTP standard. These numeric - * constants should be preferred to strings when building HTTP APIs - * because they are more efficient. - */ -typedef enum HttpRequestMethod -{ - HTTP_METHOD_UNKNOWN, - HTTP_GET, - HTTP_HEAD, - HTTP_POST, - HTTP_PUT, - HTTP_DELETE, - HTTP_CONNECT, - HTTP_OPTIONS, - HTTP_TRACE, - HTTP_PATCH -} HttpRequestMethod; - -/** - * An enumeration that corresponds to the actual integer values of the - * valid HTTP response codes. - */ -typedef enum HttpStatus -{ - HTTP_STATUS_UNKNOWN = 0, - - /* Informational responses */ - HTTP_CONTINUE = 100, - HTTP_SWITCHING_PROTOCOLS = 101, - HTTP_EARLY_HINTS = 103, - - /* Successful responses */ - HTTP_OK = 200, - HTTP_CREATED = 201, - HTTP_ACCEPTED = 202, - HTTP_NON_AUTHORITATIVE_INFORMATION = 203, - HTTP_NO_CONTENT = 204, - HTTP_RESET_CONTENT = 205, - HTTP_PARTIAL_CONTENT = 206, - - /* Redirection messages */ - HTTP_MULTIPLE_CHOICES = 300, - HTTP_MOVED_PERMANENTLY = 301, - HTTP_FOUND = 302, - HTTP_SEE_OTHER = 303, - HTTP_NOT_MODIFIED = 304, - HTTP_TEMPORARY_REDIRECT = 307, - HTTP_PERMANENT_REDIRECT = 308, - - /* Client error messages */ - HTTP_BAD_REQUEST = 400, - HTTP_UNAUTHORIZED = 401, - HTTP_FORBIDDEN = 403, - HTTP_NOT_FOUND = 404, - HTTP_METHOD_NOT_ALLOWED = 405, - HTTP_NOT_ACCEPTABLE = 406, - HTTP_PROXY_AUTH_REQUIRED = 407, - HTTP_REQUEST_TIMEOUT = 408, - HTTP_CONFLICT = 409, - HTTP_GONE = 410, - HTTP_LENGTH_REQUIRED = 411, - HTTP_PRECONDITION_FAILED = 412, - HTTP_PAYLOAD_TOO_LARGE = 413, - HTTP_URI_TOO_LONG = 414, - HTTP_UNSUPPORTED_MEDIA_TYPE = 415, - HTTP_RANGE_NOT_SATISFIABLE = 416, - HTTP_EXPECTATION_FAILED = 417, - HTTP_TEAPOT = 418, - HTTP_UPGRADE_REQUIRED = 426, - HTTP_PRECONDITION_REQUIRED = 428, - HTTP_TOO_MANY_REQUESTS = 429, - HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431, - HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451, - - /* Server error responses */ - HTTP_INTERNAL_SERVER_ERROR = 500, - HTTP_NOT_IMPLEMENTED = 501, - HTTP_BAD_GATEWAY = 502, - HTTP_SERVICE_UNAVAILABLE = 503, - HTTP_GATEWAY_TIMEOUT = 504, - HTTP_VERSION_NOT_SUPPORTED = 505, - HTTP_VARIANT_ALSO_NEGOTIATES = 506, - HTTP_NOT_EXTENDED = 510, - HTTP_NETWORK_AUTH_REQUIRED = 511 -} HttpStatus; - -/** - * Convert an HTTP status enumeration value into a string description - * of the status, which is to be used in server response to a client, - * or a client response to a user. For example, calling - * .Fn HttpStatusToString "HTTP_GATEWAY_TIMEOUT" - * (or - * .Fn HttpStatusToString "504" ) - * produces the string "Gateway Timeout". Note that the returned - * pointers point to static space, so their manipulation is forbidden. - */ -extern const char * HttpStatusToString(const HttpStatus); - -/** - * Convert a string into a numeric code that can be used throughout - * the code of a program in an efficient manner. See the definition - * of HttpRequestMethod. This function does case-sensitive matching, - * and does not trim or otherwise process the input string. - */ -extern HttpRequestMethod HttpRequestMethodFromString(const char *); - -/** - * Convert a numeric code as defined by HttpRequestMethod into a - * string that can be sent to a server. Note that the returned pointers - * point to static space, so their manipulation is forbidden. - */ -extern const char * HttpRequestMethodToString(const HttpRequestMethod); - -/** - * Encode a C string such that it can safely appear in a URL by - * performing the necessary percent escaping. A new string on the - * heap is returned. It should be freed with - * .Fn Free , - * defined in the - * .Xr Memory 3 - * API. - */ -extern char * HttpUrlEncode(char *); - -/** - * Decode a percent-encoded string into a C string, ignoring encoded - * null characters entirely, because those would do nothing but cause - * problems. - */ -extern char * HttpUrlDecode(char *); - -/** - * Decode an encoded parameter string in the form of - * ``key=val&key2=val2'' into a hash map whose values are C strings. - * This function properly decodes keys and values using the functions - * defined above. - */ -extern HashMap * HttpParamDecode(char *); - -/** - * Encode a hash map whose values are strings as an HTTP parameter - * string suitable for GET or POST requests. - */ -extern char * HttpParamEncode(HashMap *); - -/** - * Read HTTP headers from a stream and return a hash map whose values - * are strings. All keys are lowercased to make querying them - * consistent and not dependent on the case that was read from the - * stream. This is useful for both client and server code, since the - * headers are in the same format. This function should be used after - * parsing the HTTP status line, because it does not parse that line. - * It will stop when it encounters the first blank line, which - * indicates that the body is beginning. After this function completes, - * the body may be immediately read from the stream without any - * additional processing. - */ -extern HashMap * HttpParseHeaders(Stream *); - -#endif diff --git a/src/include/HttpClient.h b/src/include/HttpClient.h deleted file mode 100644 index f757041..0000000 --- a/src/include/HttpClient.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef CYTOPLASM_HTTPCLIENT_H -#define CYTOPLASM_HTTPCLIENT_H - -/*** - * @Nm HttpClient - * @Nd Extremely simple HTTP client. - * @Dd April 29 2023 - * @Xr Http HttpServer Tls - * - * .Nm - * HttpClient - * builds on the HTTP API to provide a simple yet functional HTTP - * client. It aims at being easy to use and minimal, yet also - * efficient. - */ - -#include - -#include -#include - -/** - * A server response is represented by a client context. It is - * opaque, so the functions defined in this API should be used to - * fetch data from and manipulate it. - */ -typedef struct HttpClientContext HttpClientContext; - -/** - * Make an HTTP request. This function takes the request method, - * any flags defined in the HTTP API, the port, hostname, and path, - * all in that order. It returns NULL if there was an error making - * the request. Otherwise it returns a client context. Note that this - * function does not actually send any data, it simply makes the - * connection. Use - * .Fn HttpRequestHeader - * to add headers to the request. Then, send headers with - * .Fn HttpRequestSendHeaders . - * Finally, the request body, if any, can be written to the output - * stream, and then the request can be fully sent using - * .Fn HttpRequestSend . - */ -extern HttpClientContext * - HttpRequest(HttpRequestMethod, int, unsigned short, char *, char *); - -/** - * Set a request header to send to the server when making the - * request. - */ -extern void HttpRequestHeader(HttpClientContext *, char *, char *); - -/** - * Send the request headers to the server. This must be called before - * the request body can be written or a response body can be read. - */ -extern void HttpRequestSendHeaders(HttpClientContext *); - -/** - * Flush the request stream to the server. This function should be - * called before the response body is read. - */ -extern HttpStatus HttpRequestSend(HttpClientContext *); - -/** - * Get the headers returned by the server. - */ -extern HashMap * HttpResponseHeaders(HttpClientContext *); - -/** - * Get the stream used to write the request body and read the - * response body. - */ -extern Stream * HttpClientStream(HttpClientContext *); - -/** - * Free all memory associated with the client context. This closes the - * connection, if it was still open. - */ -extern void HttpClientContextFree(HttpClientContext *); - -#endif /* CYTOPLASM_HTTPCLIENT_H */ diff --git a/src/include/HttpRouter.h b/src/include/HttpRouter.h deleted file mode 100644 index 6816178..0000000 --- a/src/include/HttpRouter.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef CYTOPLASM_HTTPROUTER_H -#define CYTOPLASM_HTTPROUTER_H - -/*** - * @Nm HttpRouter - * @Nd Simple HTTP request router with regular expression support. - * @Dd April 29 2023 - * @Xr HttpServer Http - * - * .Nm - * provides a simple mechanism for assigning functions to an HTTP - * request path. It is a simple tree data structure that parses the - * registered request paths and maps functions onto each part of the - * path. Then, requests can be easily routed to their appropriate - * handler functions. - */ - -#include - -/** - * The router structure is opaque and thus managed entirely by the - * functions defined in this API. - */ -typedef struct HttpRouter HttpRouter; - -/** - * A function written to handle an HTTP request takes an array - * consisting of the matched path parts in the order they appear in - * the path, and a pointer to caller-provided arguments, if any. - * It returns a pointer that the caller is assumed to know how to - * handle. - */ -typedef void *(HttpRouteFunc) (Array *, void *); - -/** - * Create a new empty routing tree. - */ -extern HttpRouter * HttpRouterCreate(void); - -/** - * Free all the memory associated with the given routing tree. - */ -extern void HttpRouterFree(HttpRouter *); - -/** - * Register the specified route function to be executed upon requests - * for the specified HTTP path. The path is parsed by splitting at - * each path separator. Each part of the path is a regular expression - * that matches the entire path part. A regular expression cannot - * match more than one path part. This allows for paths like - * .Pa /some/path/(.*)/parts - * to work as one would expect. - */ -extern int HttpRouterAdd(HttpRouter *, char *, HttpRouteFunc *); - -/** - * Route the specified request path using the specified routing - * tree. This function will parse the path and match it to the - * appropriate route handler function. The return value is a boolean - * value that indicates whether or not an appropriate route function - * was found. If an appropriate function was found, then the void - * pointer is passed to it as arguments that it is expected to know - * how to handle, and the pointer to a void pointer is where the - * route function's response will be placed. - */ -extern int HttpRouterRoute(HttpRouter *, char *, void *, void **); - -#endif /* CYTOPLASM_HTTPROUTER_H */ diff --git a/src/include/HttpServer.h b/src/include/HttpServer.h deleted file mode 100644 index f8e449a..0000000 --- a/src/include/HttpServer.h +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef CYTOPLASM_HTTPSERVER_H -#define CYTOPLASM_HTTPSERVER_H - -/*** - * @Nm HttpServer - * @Nd Extremely simple HTTP server. - * @Dd December 13 2022 - * @Xr Http HttpClient - * - * .Nm - * builds on the - * .Xr Http 3 - * API, and provides a very simple, yet very functional API for - * creating an HTTP server. It aims at being easy to use and minimal, - * yet also efficient. It uses non-blocking I/O, is fully - * multi-threaded, and is very configurable. It can be set up in just - * two function calls and minimal supporting code. - * .Pp - * This API should be familar to those that have dealt with the HTTP - * server libraries of other programming languages, particularly Java. - * In fact, much of the terminology used in this API came from Java, - * and you'll notice that the way responses are sent and received very - * closely resembles Java. - */ - -#include - -#include - -#include -#include - -/** - * The functions on this API operate on an opaque structure. - */ -typedef struct HttpServer HttpServer; - -/** - * Each request receives a context structure. It is opaque, so the - * functions defined in this API should be used to fetch data from - * it. These functions allow the handler to figure out the context of - * the request, which includes the path requested, any parameters, - * and the headers and method used to make the request. The context - * also provides the means by which the handler responds to the - * request, allowing it to set the status code, headers, and body. - */ -typedef struct HttpServerContext HttpServerContext; - -/** - * The request handler function is executed when an HTTP request is - * received. It takes a request context, and a pointer as specified - * in the server configuration. - */ -typedef void (HttpHandler) (HttpServerContext *, void *); - -/** - * The number of arguments to - * .Fn HttpServerCreate - * has grown so large that arguments are now stuffed into a - * configuration structure, which is in turn passed to - * .Fn HttpServerCreate . - * This configuration is copied by value into the internal - * structures of the server. It is copied with very minimal - * validation, so ensure that all values are sensible. It may - * make sense to use - * .Fn memset - * to zero out everything in here before assigning values. - */ -typedef struct HttpServerConfig -{ - unsigned short port; - unsigned int threads; - unsigned int maxConnections; - - int flags; /* Http(3) flags */ - char *tlsCert; /* File path */ - char *tlsKey; /* File path */ - - HttpHandler *handler; - void *handlerArgs; -} HttpServerConfig; - -/** - * Create a new HTTP server using the specified configuration. - * This will set up all internal structures used by the server, - * and bind the socket and start listening for connections. However, - * it will not start accepting connections. - */ -extern HttpServer * HttpServerCreate(HttpServerConfig *); - -/** - * Retrieve the configuration that was used to instantiate the given - * server. Note that this configuration is not necessarily the exact - * one that was provided; even though its values are the same, it - * should be treated as an entirely separate configuration with no - * connection to the original. - */ -extern HttpServerConfig * HttpServerConfigGet(HttpServer *); - -/** - * Free the resources associated with the given HTTP server. Note that - * the server can only be freed after it has been stopped. Calling this - * function while the server is still running results in undefined - * behavior. - */ -extern void HttpServerFree(HttpServer *); - -/** - * Attempt to start the HTTP server, and return immediately with the - * status. This API is fully multi-threaded and asynchronous, so the - * caller can continue working while the HTTP server is running in a - * separate thread and managing a pool of threads to handle responses. - */ -extern int HttpServerStart(HttpServer *); - -/** - * Typically, at some point after calling - * .Fn HttpServerStart , - * the program will have no more work to do, so it will want to wait - * for the HTTP server to finish. This is accomplished via this - * function, which joins the HTTP worker thread to the calling thread, - * pausing the calling thread until the HTTP server has stopped. - */ -extern void HttpServerJoin(HttpServer *); - -/** - * Stop the HTTP server. Only the execution of this function will - * cause the proper shutdown of the HTTP server. If the main program - * is joined to the HTTP thread, then either another thread or a - * signal handler will have to stop the server using this function. - * The typical use case is to install a signal handler that executes - * this function on a global HTTP server. - */ -extern void HttpServerStop(HttpServer *); - -/** - * Get the request headers for the request represented by the given - * context. The data in the returned hash map should be treated as - * read only and should not be freed; it is managed entirely by the - * server. - */ -extern HashMap * HttpRequestHeaders(HttpServerContext *); - -/** - * Get the request method used to make the request represented by - * the given context. - */ -extern HttpRequestMethod HttpRequestMethodGet(HttpServerContext *); - -/** - * Get the request path for the request represented by the given - * context. The return value of this function should be treated as - * read-only, and should not be freed; it is managed entirely by the - * server. - */ -extern char * HttpRequestPath(HttpServerContext *); - -/** - * Retrieve the parsed GET parameters for the request represented by - * the given context. The returned hash map should be treated as - * read-only, and should not be freed; it is managed entirely by the - * server. - */ -extern HashMap * HttpRequestParams(HttpServerContext *); - -/** - * Set a response header to return to the client. The old value for - * the given header is returned, if any, otherwise NULL is returned. - */ -extern char * HttpResponseHeader(HttpServerContext *, char *, char *); - -/** - * Set the response status to return to the client. - */ -extern void HttpResponseStatus(HttpServerContext *, HttpStatus); - -/** - * Get the current response status that will be sent to the client - * making the request represented by the given context. - */ -extern HttpStatus HttpResponseStatusGet(HttpServerContext *); - -/** - * Send the response headers to the client that made the request - * represented by the specified context. This function must be called - * before the response body can be written, otherwise a malformed - * response will be sent. - */ -extern void HttpSendHeaders(HttpServerContext *); - -/** - * Get a stream that is both readable and writable. Reading from the - * stream reads the request body that the client sent, if there is one. - * Note that the rquest headers have already been read, so the stream - * is correctly positioned at the beginning of the body of the request. - * .Fn HttpSendHeaders - * must be called before the stream is written, otherwise a malformed - * HTTP response will be sent. An HTTP handler should properly set all - * the headers it itends to send, send those headers, and then write - * the response body to this stream. - * .Pp - * Note that the stream does not need to be closed by the HTTP - * handler; in fact doing so results in undefined behavior. The stream - * is managed entirely by the server itself, so it will close it when - * necessary. This allows the underlying protocol to differ: for - * instance, an HTTP/1.1 connection may stay for multiple requests and - * responses. - */ -extern Stream * HttpServerStream(HttpServerContext *); - -#endif /* CYTOPLASM_HTTPSERVER_H */ diff --git a/src/include/Int.h b/src/include/Int.h deleted file mode 100644 index 7933a69..0000000 --- a/src/include/Int.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef CYTOPLASM_INT_H -#define CYTOPLASM_INT_H - -/*** - * @Nm Int - * @Nd Fixed-width integer types. - * @Dd April 27 2023 - * - * This header provides cross-platform, fixed-width integer types. - * Specifically, it uses preprocessor magic to define the following - * types: - * .Bl -bullet -offset indent - * .It - * Int8 and UInt8 - * .It - * Int16 and UInt16 - * .It - * Int32 and UInt32 - * .El - * .Pp - * Note that there is no 64-bit integer type, because the ANSI C - * standard makes no guarantee that such a type will exist, even - * though it does on most platforms. - * .Pp - * The reason Cytoplasm provides its own header for this is - * because ANSI C does not define fixed-width types, and while it - * should be safe to rely on C99 fixed-width types in most cases, - * there may be cases where even that is not possible. - * - * @ignore-typedefs - */ - -#include - -#define BIT32_MAX 4294967295UL -#define BIT16_MAX 65535UL -#define BIT8_MAX 255UL - -#ifndef UCHAR_MAX -#error Size of char data type is unknown. Define UCHAR_MAX. -#endif - -#ifndef USHRT_MAX -#error Size of short data type is unknown. Define USHRT_MAX. -#endif - -#ifndef UINT_MAX -#error Size of int data type is unknown. Define UINT_MAX. -#endif - -#ifndef ULONG_MAX -#error Size of long data type is unknown. Define ULONG_MAX. -#endif - -#if UCHAR_MAX == BIT8_MAX -typedef signed char Int8; -typedef unsigned char UInt8; - -#else -#error Unable to determine suitable data type for 8-bit integers. -#endif - -#if UINT_MAX == BIT16_MAX -typedef signed int Int16; -typedef unsigned int UInt16; - -#elif USHRT_MAX == BIT16_MAX -typedef signed short Int16; -typedef unsigned short UInt16; - -#elif UCHAR_MAX == BIT16_MAX -typedef signed char Int16; -typedef unsigned char UInt16; - -#else -#error Unable to determine suitable data type for 16-bit integers. -#endif - -#if ULONG_MAX == BIT32_MAX -typedef signed long Int32; -typedef unsigned long UInt32; - -#elif UINT_MAX == BIT32_MAX -typedef signed int Int32; -typedef unsigned int UInt32; - -#elif USHRT_MAX == BIT32_MAX -typedef signed short Int32; -typedef unsigned short UInt32; - -#elif UCHAR_MAX == BIT32_MAX -typedef signed char Int32; -typedef unsigned char UInt32; - -#else -#error Unable to determine suitable data type for 32-bit integers. -#endif - -#endif /* CYTOPLASM_INT_H */ diff --git a/src/include/Int64.h b/src/include/Int64.h deleted file mode 100644 index 08083c1..0000000 --- a/src/include/Int64.h +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef CYTOPLASM_INT64_H -#define CYTOPLASM_INT64_H - -/*** - * @Nm Int64 - * @Nd Fixed-width 64 bit integers. - * @Dd August 11, 2023 - * - * .Pp - * ANSI C89 (or C99 for that matter) provides no required mechanism - * for 64 bit integers. Nevertheless, many compilers provide them as - * extensions. However, since it is not a gaurantee, and to be fully - * standards-compliant and thus portable, a platform-agnostic interface - * is required. This header provides such an interface. If the platform - * has a 64 bit integer type, that is used, and native operations are - * performed by C preprocessor macro expansion. Otherwise, a - * compatibility layer is provided, which implements 64-bit - * arithmetic on an array of 2 32-bit numbers which are provided by - * .Xr Int 3 . - * .Pp - * Note that 64-bit emulation is certainly not as performant as using - * native 64-bit operations, so whenever possible, the native - * operations should be preferred. However, since C provides no required - * 64 bit integer on 32-bit and less platforms, this API can be used as - * a "good enough" fallback mechanism. - * .Pp - * Also note that this implementation, both in the native and - * non-native forms, makes some assumptions: - * .Bl -bullet -width Ds - * .It - * When a cast from a larger integer to a smaller integer is performed, - * the upper bits are truncated, not the lower bits. - * .It - * Negative numbers are represented in memory and in registers in two's - * compliment form. - * .El - * .Pp - * This API may provide unexpected output if these assumptions are - * false for a given platform. - * - * @ignore-typedefs - */ - -#include -#include - -#include - -#ifndef INT64_FORCE_EMULATED - -#define BIT64_MAX 18446744073709551615UL - -#if UINT_MAX == BIT64_MAX -typedef signed int Int64; - -#define INT64_NATIVE - -#elif ULONG_MAX == BIT64_MAX -typedef signed long Int64; - -#define INT64_NATIVE - -#endif - -#endif /* ifndef INT64_FORCE_EMULATED */ - -#ifdef INT64_NATIVE - -#define Int64Create(high, low) ((Int64) (((UInt64) (high) << 32) | (low))) -#define Int64Neg(x) (-(x)) - -#define Int64Low(a) ((UInt32) (a)) -#define Int64High(a) ((UInt32) ((a) >> 32)) - -#define Int64Add(a, b) ((a) + (b)) -#define Int64Sub(a, b) ((a) - (b)) -#define Int64Mul(a, b) ((a) * (b)) -#define Int64Div(a, b) ((a) / (b)) -#define Int64Rem(a, b) ((a) % (b)) - -#define Int64Sll(a, b) ((a) << (b)) -#define Int64Sra(a, b) ((a) >> (b)) - -#define Int64And(a, b) ((a) & (b)) -#define Int64Or(a, b) ((a) | (b)) -#define Int64Xor(a, b) ((a) ^ (b)) -#define Int64Not(a) (~(a)) - -#define Int64Eq(a, b) ((a) == (b)) -#define Int64Lt(a, b) ((a) < (b)) -#define Int64Gt(a, b) ((a) > (b)) - -#define Int64Neq(a, b) ((a) != (b)) -#define Int64Leq(a, b) ((a) <= (b)) -#define Int64Geq(a, b) ((a) >= (b)) - -#else - -#define Int64Neg(x) (Int64Add(Int64Not(x), Int64Create(0, 1))) - -/** - * The internal bit representation of a signed integer is identical - * to an unsigned integer, the difference is in the algorithms and - * the way the bits are interpreted. - */ -typedef UInt64 Int64; - -/** - * Create a new signed 64 bit integer using the given high and low - * bits. - */ -extern Int64 Int64Create(UInt32, UInt32); - -/** - * Add two signed 64 bit integers together. - */ -extern Int64 Int64Add(Int64, Int64); - -/** - * Subtract the second 64 bit integer from the first. - */ -extern Int64 Int64Sub(Int64, Int64); - -/** - * Multiply two 64 bit integers together. The non-native version of - * this function uses the Russian Peasant method of multiplication, - * which should afford more performance than a naive multiplication by - * addition, but it is still rather slow and depends on the size of - * the integers being multiplied. - */ -extern Int64 Int64Mul(Int64, Int64); - -/** - * Divide the first 64 bit integer by the second and return the - * quotient. The non-native version of this function uses naive binary - * long division, which is slow, but gauranteed to finish in constant - * time. - */ -extern Int64 Int64Div(Int64, Int64); - -/** - * Divide the first 64 bit integer by the second and return the - * remainder. The non-native version of this function uses naive binary - * long division, which is slow, but gauranteed to finish in constant - * time. - */ -extern Int64 Int64Rem(Int64, Int64); - -/** - * Perform a left logical bit shift of a 64 bit integer. The second - * parameter is how many places to shift, and is declared as a regular - * integer because anything more than 64 does not make sense. - */ -extern Int64 Int64Sll(Int64, int); - -/** - * Perform a right arithmetic bit shift of a 64 bit integer. The second - * parameter is how many places to shift, and is declared as a regular - * integer because anything more than 64 does not make sense. - * .Pp - * Note that on platforms that use the native 64-bit implementation, - * this is technically implementation-defined, and may in fact be a - * logical shift instead of an arithmetic shift. Note that typically - * this operation is not performed on signed integers. - */ -extern Int64 Int64Sra(Int64, int); - -/** - * Perform a bitwise AND (&) of the provided 64 bit integers. - */ -extern Int64 Int64And(Int64, Int64); - -/** - * Perform a bitwise OR (|) of the provided 64 bit integers. - */ -extern Int64 Int64Or(Int64, Int64); - -/** - * Perform a bitwise XOR (^) of the provided 64 bit integers. - */ -extern Int64 Int64Xor(Int64, Int64); - -/** - * Perform a bitwise NOT (~) of the provided 64 bit integer. - */ -extern Int64 Int64Not(Int64); - -/** - * Perform a comparison of the provided 64 bit integers and return a C - * boolean that is true if and only if they are equal. - */ -extern int Int64Eq(Int64, Int64); - -/** - * Perform a comparison of the provided 64 bit integers and return a C - * boolean that is true if and only if the second operand is strictly - * less than the first. - */ -extern int Int64Lt(Int64, Int64); - -/** - * Perform a comparison of the provided 64 bit integers and return a C - * boolean that is true if and only if the second operand is strictly - * greater than the first. - */ -extern int Int64Gt(Int64, Int64); - -#define Int64Low(a) ((a).i[0]) -#define Int64High(a) ((a).i[1]) - -#define Int64Neq(a, b) (!Int64Eq(a, b)) -#define Int64Leq(a, b) (Int64Eq(a, b) || Int64Lt(a, b)) -#define Int64Geq(a, b) (Int64Eq(a, b) || Int64Gt(a, b)) - -#endif - -#define INT64_STRBUF 65 /* Base 2 representation with '\0' */ - -/** - * Convert a 64 bit integer to a string in an arbitrary base - * representation specified by the second parameter, using the provided - * buffer and length specified by the third and fourth parameters. To - * guarantee that the string will fit in the buffer, allocate it of - * size INT64_STRBUF or larger. Note that a buffer size smaller than - * INT64_STRBUF will invoke undefined behavior. - */ -extern size_t Int64Str(Int64, int, char *, size_t); - -#endif /* CYTOPLASM_INT64_H */ diff --git a/src/include/Io.h b/src/include/Io.h deleted file mode 100644 index 06afb77..0000000 --- a/src/include/Io.h +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef CYTOPLASM_IO_H -#define CYTOPLASM_IO_H - -/*** - * @Nm Io - * @Nd Source/sink-agnostic I/O for implementing custom streams. - * @Dd April 29 2023 - * @Xr Stream Tls - * - * Many systems provide platform-specific means of implementing custom - * streams using file pointers. However, POSIX does not define a way - * of programmatically creating custom streams. - * .Nm - * therefore fills this gap in POSIX by mimicking all of the - * functionality of these platform-specific functions, but in pure - * POSIX C. It defines a number of callback funtions to be executed - * in place of the standard POSIX I/O functions, which are used to - * implement arbitrary streams that may not be to a file or socket. - * Additionally, streams can now be pipelined; the sink of one stream - * may be the source of another lower-level stream. Additionally, all - * streams, regardless of their source or sink, share the same API, so - * streams can be handled in a much more generic manner. This allows - * the HTTP client and server libraries to seemlessly support TLS and - * plain connections without having to handle each separately. - * .Pp - * .Nm - * was heavily inspired by GNU's - * .Fn fopencookie - * and BSD's - * .Fn funopen . - * It aims to combine the best of both of these functions into a single - * API that is intuitive and easy to use. - */ - -#include -#include -#include -#include - -#ifndef IO_BUFFER -#define IO_BUFFER 4096 -#endif - -/** - * An opaque structure analogous to a POSIX file descriptor. - */ -typedef struct Io Io; - -/** - * Read input from the source of a stream. This function should - * attempt to read the specified number of bytes of data from the - * given cookie into the given buffer. It should behave identically - * to the POSIX - * .Xr read 2 - * system call, except instead of using an integer descriptor as the - * first parameter, a pointer to an implementation-defined cookie - * stores any information the function needs to read from the source. - */ -typedef ssize_t (IoReadFunc) (void *, void *, size_t); - -/** - * Write output to a sink. This function should attempt to write the - * specified number of bytes of data from the given buffer into the - * stream described by the given cookie. It should behave identically - * to the POSIX - * .Xr write 2 - * system call, except instead of using an integer descriptor as the - * first parameter, a pointer to an implementation-defined cookie - * stores any information the function needs to write to the sink. - */ -typedef ssize_t (IoWriteFunc) (void *, void *, size_t); - -/** - * Repositions the offset of the stream described by the specified - * cookie. This function should behave identically to the POSIX - * .Xr lseek 2 - * system call, except instead of using an integer descriptor as the - * first parameter, a pointer to an implementation-defined cookie - * stores any information the function needs to seek the stream. - */ -typedef off_t (IoSeekFunc) (void *, off_t, int); - -/** - * Close the given stream, making future reads or writes result in - * undefined behavior. This function should also free all memory - * associated with the cookie. It should behave identically to the - * .Xr close 2 - * system call, except instead of using an integer descriptor for the - * parameter, a pointer to an implementation-defined cookie stores any - * information the function needs to close the stream. - */ -typedef int (IoCloseFunc) (void *); - -/** - * A simple mechanism for grouping together a set of stream functions, - * to be passed to - * .Fn IoCreate . - */ -typedef struct IoFunctions -{ - IoReadFunc *read; - IoWriteFunc *write; - IoSeekFunc *seek; - IoCloseFunc *close; -} IoFunctions; - -/** - * Create a new stream using the specified cookie and the specified - * I/O functions. - */ -extern Io * IoCreate(void *, IoFunctions); - -/** - * Read the specified number of bytes from the specified stream into - * the specified buffer. This calls the stream's underlying IoReadFunc, - * which should behave identically to the POSIX - * .Xr read 2 - * system call. - */ -extern ssize_t IoRead(Io *, void *, size_t); - -/** - * Write the specified number of bytes from the specified stream into - * the specified buffer. This calls the stream's underlying - * IoWriteFunc, which should behave identically to the POSIX - * .Xr write 2 - * system call. - */ -extern ssize_t IoWrite(Io *, void *, size_t); - -/** - * Seek the specified stream using the specified offset and whence - * value. This calls the stream's underlying IoSeekFunc, which should - * behave identically to the POSIX - * .Xr lseek 2 - * system call. - */ -extern off_t IoSeek(Io *, off_t, int); - -/** - * Close the specified stream. This calls the stream's underlying - * IoCloseFunc, which should behave identically to the POSIX - * .Xr close 2 - * system call. - */ -extern int IoClose(Io *); - -/** - * Print a formatted string to the given stream. This is a - * re-implementation of the standard library function - * .Xr vfprintf 3 , - * and behaves identically. - */ -extern int IoVprintf(Io *, const char *, va_list); - -/** - * Print a formatted string to the given stream. This is a - * re-implementation of the standard library function - * .Xr fprintf 3 , - * and behaves identically. - */ -extern int IoPrintf(Io *, const char *,...); - -/** - * Read all the bytes from the first stream and write them to the - * second stream. Neither stream is closed upon the completion of this - * function. This can be used for quick and convenient buffered - * copying of data from one stream into another. - */ -extern ssize_t IoCopy(Io *, Io *); - -/** - * Wrap a POSIX file descriptor to take advantage of this API. The - * common use case for this function is when a regular file descriptor - * needs to be accessed by an application that uses this API to also - * access non-POSIX streams. - */ -extern Io * IoFd(int); - -/** - * Open or create a file for reading or writing. The specified file - * name is opened for reading or writing as specified by the given - * flags and mode. This function is a simple convenience wrapper around - * the POSIX - * .Xr open 2 - * system call that passes the opened file descriptor into - * .Fn IoFd . - */ -extern Io * IoOpen(const char *, int, mode_t); - -/** - * Wrap a standard C file pointer to take advantage of this API. The - * common use case for this function is when a regular C file pointer - * needs to be accessed by an application that uses this API to also - * access custom streams. - */ -extern Io * IoFile(FILE *); - -#endif /* CYTOPLASM_IO_H */ diff --git a/src/include/Json.h b/src/include/Json.h deleted file mode 100644 index 4185260..0000000 --- a/src/include/Json.h +++ /dev/null @@ -1,323 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef CYTOPLASM_JSON_H -#define CYTOPLASM_JSON_H - -/*** - * @Nm Json - * @Nd A fully-featured JSON API. - * @Dd March 12 2023 - * @Xr HashMap Array Stream - * - * .Nm - * is a fully-featured JSON API for C using the array and hash map - * APIs. It can parse JSON, ans serialize an in-memory structure to - * JSON. It build on the foundation of Array and HashMap because that's - * all JSON really is, just arrays and maps. - * .Nm - * also provides a structure for encapsulating an arbitrary value and - * identifying its type, making it easy for a strictly-typed language - * like C to work with loosely-typed JSON data. - * .Nm - * is very strict and tries to adhere as closely as possible to the - * proper definition of JSON. It will fail on syntax errors of any - * kind, which is fine for a Matrix homeserver that can just return - * M_BAD_JSON if anything in here fails, but this behavior may not be - * suitable for other purposes. - * .Pp - * This JSON implementation focuses primarily on serialization and - * deserialization to and from streams. It does not provide facilities - * for handling JSON strings; it only writes JSON to output streams, - * and reads them from input streams. Of course, you can use the - * POSIX - * .Xr fmemopen 3 - * and - * .Xr open_memstream 3 - * functions if you want to deal with JSON strings, but JSON is - * intended to be an exchange format. Data should be converted to JSON - * right when it is leaving the program, and converted from JSON to the - * in-memory format as soon as it is coming in. - * .Pp - * JSON objects are represented as hash maps consisting entirely of - * JsonValue structures, and arrays are represented as arrays - * consisting entirely of JsonValue structures. When generating a - * JSON object, any attempt to stuff a value into a hash map or array - * without first encoding it as a JsonValue will result in undefined - * behavior. - */ - -#include -#include -#include -#include - -#include -#include - -#define JSON_DEFAULT -1 -#define JSON_PRETTY 0 - -/** - * This opaque structure encapsulates all the possible types that can - * be stored in JSON. It is managed entirely by the functions defined - * in this API. It is important to note that strings, integers, floats, - * booleans, and the NULL value are all stored by value, but objects - * and arrays are stored by reference. That is, it doesn't store these - * itself, just pointers to them, however, the data - * .Em is - * freed when using - * .Fn JsonFree . - */ -typedef struct JsonValue JsonValue; - -/** - * These are the types that can be used to identify a JsonValue - * and act on it accordingly. - */ -typedef enum JsonType -{ - JSON_NULL, /* Maps to a C NULL */ - JSON_OBJECT, /* Maps to a HashMap of JsonValues */ - JSON_ARRAY, /* Maps to an Array of JsonValues */ - JSON_STRING, /* Maps to a null-terminated C string */ - JSON_INTEGER, /* Maps to an Int64 */ - JSON_FLOAT, /* Maps to a C double */ - JSON_BOOLEAN /* Maps to a C integer of either 0 or 1 */ -} JsonType; - -/** - * Determine the type of the specified JSON value. - */ -extern JsonType JsonValueType(JsonValue *); - -/** - * Encode a JSON object as a JSON value that can be added to another - * object, or an array. - */ -extern JsonValue * JsonValueObject(HashMap *); - -/** - * Unwrap a JSON value that represents an object. This function will - * return NULL if the value is not actually an object. - */ -extern HashMap * JsonValueAsObject(JsonValue *); - -/** - * Encode a JSON array as a JSON value that can be added to an object - * or another array. - */ -extern JsonValue * JsonValueArray(Array *); - -/** - * Unwrap a JSON value that represents an array. This function will - * return NULL if the value is not actually an array. - */ -extern Array * JsonValueAsArray(JsonValue *); - -/** - * Encode a C string as a JSON value that can be added to an object or - * an array. - */ -extern JsonValue * JsonValueString(char *); - -/** - * Unwrap a JSON value that represents a string. This function will - * return NULL if the value is not actually a string. - */ -extern char * JsonValueAsString(JsonValue *); - -/** - * Encode a number as a JSON value that can be added to an object or - * an array. - */ -extern JsonValue * JsonValueInteger(Int64); - -/** - * Unwrap a JSON value that represents a number. This function will - * return 0 if the value is not actually a number, which may be - * misleading. Check the type of the value before making assumptions - * about its value. - */ -extern Int64 JsonValueAsInteger(JsonValue *); - -/** - * Encode a floating point number as a JSON value that can be added - * to an object or an array. - */ -extern JsonValue * JsonValueFloat(double); - -/** - * Unwrap a JSON value that represents a floating point number. This - * function will return 0 if the value is not actually a floating - * point number, which may be misleading. Check the type of the value - * before making assumptions about its type. - */ -extern double JsonValueAsFloat(JsonValue *); - -/** - * Encode a C integer according to the way C treats integers in boolean - * expressions as a JSON value that can be added to an object or an - * array. - */ -extern JsonValue * JsonValueBoolean(int); - -/** - * Unwrap a JSON value that represents a boolean. This function will - * return 0 if the value is not actually a boolean, which may be - * misleading. Check the type of the value before making assumptions - * about its type. - */ -extern int JsonValueAsBoolean(JsonValue *); - -/** - * This is a special case that represents a JSON null. Because the - * Array and HashMap APIs do not accept NULL values, this function - * should be used to represent NULL in JSON. Even though a small - * amount of memory is allocated just to be a placeholder for nothing, - * this keeps the APIs clean. - */ -extern JsonValue * JsonValueNull(void); - -/** - * Free the memory being used by a JSON value. Note that this will - * recursively free all Arrays, HashMaps, and other JsonValues that are - * reachable from the given value, including any strings attached to - * this value. - */ -extern void JsonValueFree(JsonValue *); - -/** - * Recursively duplicate the given JSON value. This returns a new - * JSON value that is completely identical to the specified value, but - * in no way connected to it. - */ -extern JsonValue * JsonValueDuplicate(JsonValue *); - -/** - * Recursively duplicate the given JSON object. This returns a new - * JSON object that is completely identical to the specified object, - * but in no way connect to it. - */ -extern HashMap * JsonDuplicate(HashMap *); - -/** - * Recursively free a JSON object by iterating over all of its values - * and freeing them using - * .Fn JsonValueFree . - */ -extern void JsonFree(HashMap *); - -/** - * Encode the given string in such a way that it can be safely - * embedded in a JSON stream. This entails: - * .Bl -bullet -offset indent - * .It - * Escaping quotes, backslashes, and other special characters using - * their backslash escape. - * .It - * Encoding bytes that are not UTF-8 using escapes. - * .It - * Wrapping the entire string in double quotes. - * .El - * .Pp - * This function is only provided via the public - * .Nm - * API so that it is accessible to custom JSON encoders, such as the - * CanonicalJson encoder. This will typically be used for encoding - * object keys; to encode values, just use - * .Fn JsonEncodeValue . - * .Pp - * This function returns the number of bytes written to the stream, - * or if the stream is NULL, the number of bytes that would have - * been written. - */ -extern int JsonEncodeString(const char *, Stream *); - -/** - * Serialize a JSON value as it would appear in JSON output. This is - * a recursive function that also encodes all child values reachable - * from the given value. This function is exposed via the public - * .Nm - * API so that it is accessible to custom JSON encoders. Normal users - * that are not writing custom encoders should in most cases just use - * .Fn JsonEncode - * to encode an entire object. - * .Pp - * The third parameter is an integer that represents the indent level - * of the value to be printed, or a negative number if pretty-printing - * should be disabled and JSON should be printed as minimized as - * possible. To pretty-print a JSON object, set this to - * .Va JSON_PRETTY . - * To get minified output, set it to - * .Va JSON_DEFAULT . - * .Pp - * This function returns the number of bytes written to the stream, - * or if the stream is NULL, the number of bytes that would have - * been written. - */ -extern int JsonEncodeValue(JsonValue *, Stream *, int); - -/** - * Encode a JSON object as it would appear in JSON output, writing it - * to the given output stream. This function is recursive; it will - * serialize everything accessible from the passed object. The third - * parameter has the same behavior as described above. - * .Pp - * This function returns the number of bytes written to the stream, - * or if the stream is NULL, the number of bytes that would have - * been written. - */ -extern int JsonEncode(HashMap *, Stream *, int); - -/** - * Decode a JSON object from the given input stream and parse it into - * a hash map of JSON values. - */ -extern HashMap * JsonDecode(Stream *); - -/** - * A convenience function that allows the caller to retrieve and - * arbitrarily deep keys within a JSON object. It takes a root JSON - * object, the number of levels deep to go, and then that number of - * keys as a varargs list. All keys must have objects as values, with - * the exception of the last one, which is the value that will be - * returned. Otherwise, NULL indicates the specified path doas not - * exist. - */ -extern JsonValue * JsonGet(HashMap *, size_t,...); - -/** - * A convenience function that allows the caller to set arbitrarily - * deep keys within a JSON object. It takes a root JSON object, the - * number of levels deep to go, and then that number of keys as a - * varargs list. All keys must have object as values, with the - * exception of the last one, which is the value that will be set. - * The value currently at that key, if any, will be returned. - * This function will create any intermediate objects as necessary to - * set the proper key. - */ -extern JsonValue * JsonSet(HashMap *, JsonValue *, size_t,...); - -#endif /* CYTOPLASM_JSON_H */ diff --git a/src/include/Log.h b/src/include/Log.h deleted file mode 100644 index d0300ca..0000000 --- a/src/include/Log.h +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef CYTOPLASM_LOG_H -#define CYTOPLASM_LOG_H - -/*** - * @Nm Log - * @Nd A simple logging framework for logging to multiple destinations. - * @Dd April 27 2023 - * @Xr Stream - * - * .Nm - * is a simple C logging library that allows for colorful outputs, - * timestamps, and custom log levels. It also features the ability to - * have multiple logs open at one time, although Cytoplasm primarily - * utilizes the global log. All logs are thread safe. - */ - -#include -#include -#include - -#include - -#define LOG_FLAG_COLOR (1 << 0) -#define LOG_FLAG_SYSLOG (1 << 1) - -/** - * A log is defined as a configuration that describes the properties - * of the log. This opaque structure can be manipulated by the - * functions defined in this API. - */ -typedef struct LogConfig LogConfig; - -/** - * Create a new log configuration with sane defaults that can be used - * immediately with the logging functions. - */ -extern LogConfig * LogConfigCreate(void); - -/** - * Get the global log configuration, creating a new one with - * .Fn LogConfigCreate - * if necessary. - */ -extern LogConfig * LogConfigGlobal(void); - -/** - * Free the given log configuration. Note that this does not close the - * underlying stream associated with the log, if there is one. Also - * note that to avoid memory leaks, the global log configuration must - * also be freed, but it cannot be used after it is freed. - */ -extern void LogConfigFree(LogConfig *); - -/** - * Set the current log level on the specified log configuration. - * This indicates that only messages at or above this level should be - * logged; all others are silently discarded. The passed log level - * should be one of the log levels defined by - * .Xr syslog 3 . - * Refer to that page for a complete list of acceptable log levels, - * and note that passing an invalid log level will result in undefined - * behavior. - */ -extern void LogConfigLevelSet(LogConfig *, int); - -/** - * Cause the log output to be indented two more spaces than it was - * previously. This can be helpful when generating stack traces or - * other hierarchical output. This is a simple convenience wrapper - * around - * .Fn LogConfigIndentSet . - */ -extern void LogConfigIndent(LogConfig *); - -/** - * Cause the log output to be indented two less spaces than it was - * previously. This is a simple convenience wrapper around - * .Fn LogConfigIndentSet . - */ -extern void LogConfigUnindent(LogConfig *); - -/** - * Indent future log output using the specified config by some - * arbitrary amount. - */ -extern void LogConfigIndentSet(LogConfig *, size_t); - -/** - * Set the file stream that logging output should be written to. This - * defaults to standard output, but it can be set to standard error, - * or any other arbitrary stream. Passing a NULL value for the stream - * pointer sets the log output to the standard output. Note that the - * output stream is only used if - * .Va LOG_FLAG_SYSLOG - * is not set. - */ -extern void LogConfigOutputSet(LogConfig *, Stream *); - -/** - * Set a number of boolean options on a log configuration. This - * function uses bitwise operators, so multiple options can be set with - * a single function call using bitwise OR operators. The flags are - * defined as preprocessor macros, and are as follows: - * .Bl -tag -width Ds - * .It LOG_FLAG_COLOR - * When set, enable color-coded output on TTYs. Note that colors are - * implemented as ANSI escape sequences, and are not written to file - * streams that are not actually connected to a TTY, to prevent those - * sequences from being written to a file. - * .Xr isatty 3 - * is checked before writing any terminal sequences. - * .It LOG_FLAG_SYSLOG - * When set, log output to the syslog using - * .Xr syslog 3 , - * instead of logging to the file set by - * .Fn LogConfigOutputSet . - * This flag always overrides the stream set by that function, - * regardless of when it was set, even if it was set after this flag - * was set. - * .El - */ -extern void LogConfigFlagSet(LogConfig *, int); - -/** - * Clear a boolean flag from the specified log format. See above for - * the list of flags. - */ -extern void LogConfigFlagClear(LogConfig *, int); - -/** - * Set a custom timestamp to be prepended to each message if the - * output is not going to the system log. Consult your system's - * documentation for - * .Xr strftime 3 . - * A value of NULL disables the timestamp output before messages. - */ -extern void LogConfigTimeStampFormatSet(LogConfig *, char *); - -/** - * This function does the actual logging of messages using a - * specified configuration. It takes the configuration, the log - * level, a format string, and then a list of arguments, all in that - * order. This function only logs messages if their level is above - * or equal to the currently configured log level, making it easy to - * turn some messages on or off. - * .Pp - * This function has the same usage as - * .Xr vprintf 3 . - * Consult that page for the list of format specifiers and their - * arguments. This function is typically not used directly, see the - * other log functions for the most common use cases. - */ -extern void Logv(LogConfig *, int, const char *, va_list); - -/** - * Log a message using - * .Fn Logv . - * with the specified configuration. This function has the same usage - * as - * .Xr printf 3 . - */ -extern void LogTo(LogConfig *, int, const char *, ...); - -/** - * Log a message to the global log using - * .Fn Logv . - * This function has the same usage as - * .Xr printf 3 . - */ -extern void Log(int, const char *, ...); - -#endif diff --git a/src/include/Memory.h b/src/include/Memory.h deleted file mode 100644 index 5d5ecec..0000000 --- a/src/include/Memory.h +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef CYTOPLASM_MEMORY_H -#define CYTOPLASM_MEMORY_H - -/*** - * @Nm Memory - * @Nd Smart memory management. - * @Dd January 9 2023 - * - * .Nm - * is an API that allows for smart memory management and profiling. It - * wraps the standard library functions - * .Xr malloc 3 , - * .Xr realloc 3 , - * and - * .Xr free 3 , - * and offers identical semantics, while providing functionality that - * the standard library doesn't have, such as getting statistics on the - * total memory allocated on the heap, and getting the size of a block - * given a pointer. Additionally, thanks to preprocessor macros, the - * exact file and line number at which an allocation, re-allocation, or - * free occured can be obtained given a pointer. Finally, all the - * blocks allocated on the heap can be iterated and evaluated, and a - * callback function can be executed every time a memory operation - * occurs. - * .Pp - * In the future, this API could include a garbage collector that - * automatically frees memory it detects as being no longer in use. - * However, this feature does not yet exist. - * .Pp - * A number of macros are available, which make the - * .Nm - * API much easier to use. They are as follows: - * .Bl -bullet -offset indent - * .It - * .Fn Malloc "x" - * .It - * .Fn Realloc "x" "y" - * .It - * .Fn Free "x" - * .El - * .Pp - * These macros expand to - * .Fn MemoryAllocate , - * .Fn MemoryReallocate , - * and - * .Fn MemoryFree - * with the second and third parameters set to __FILE__ and __LINE__. - * This allows - * .Nm - * to be used exactly how the standard library functions would be - * used. In fact, the functions to which these macros expand are not - * intended to be used directly; for the best results, use these - * macros. - */ -#include - -/** - * These values are passed into the memory hook function to indicate - * the action that just happened. - */ -typedef enum MemoryAction -{ - MEMORY_ALLOCATE, - MEMORY_REALLOCATE, - MEMORY_FREE, - MEMORY_BAD_POINTER, - MEMORY_CORRUPTED -} MemoryAction; - -#define Malloc(x) MemoryAllocate(x, __FILE__, __LINE__) -#define Realloc(x, s) MemoryReallocate(x, s, __FILE__, __LINE__) -#define Free(x) MemoryFree(x, __FILE__, __LINE__) - -/** - * The memory information is opaque, but can be accessed using the - * functions defined by this API. - */ -typedef struct MemoryInfo MemoryInfo; - -/** - * Allocate the specified number of bytes on the heap. This function - * has the same semantics as - * .Xr malloc 3 , - * except that it takes the file name and line number at which the - * allocation occurred. - */ -extern void * MemoryAllocate(size_t, const char *, int); - -/** - * Change the size of the object pointed to by the given pointer - * to the given number of bytes. This function has the same semantics - * as - * .Xr realloc 3 , - * except that it takes the file name and line number at which the - * reallocation occurred. - */ -extern void * MemoryReallocate(void *, size_t, const char *, int); - -/** - * Free the memory at the given pointer. This function has the same - * semantics as - * .Xr free 3 , - * except that it takes the file name and line number at which the - * free occurred. - */ -extern void MemoryFree(void *, const char *, int); - -/** - * Get the total number of bytes that the program has allocated on the - * heap. This operation iterates over all heap allocations made with - * .Fn MemoryAllocate - * and then returns a total count, in bytes. - */ -extern size_t MemoryAllocated(void); - -/** - * Iterate over all heap allocations made with - * .Fn MemoryAllocate - * and call - * .Fn MemoryFree - * on them. This function immediately invalidates all pointers to - * blocks on the heap, and any subsequent attempt to read or write to - * data on the heap will result in undefined behavior. This is - * typically called at the end of the program, just before exit. - */ -extern void MemoryFreeAll(void); - -/** - * Fetch information about an allocation. This function takes a raw - * pointer, and if - * . Nm - * knows about the pointer, it returns a structure that can be used - * to obtain information about the block of memory that the pointer - * points to. - */ -extern MemoryInfo * MemoryInfoGet(void *); - -/** - * Get the size in bytes of the block of memory represented by the - * specified memory info structure. - */ -extern size_t MemoryInfoGetSize(MemoryInfo *); - -/** - * Get the file name in which the block of memory represented by the - * specified memory info structure was allocated. - */ -extern const char * MemoryInfoGetFile(MemoryInfo *); - -/** - * Get the line number on which the block of memory represented by the - * specified memory info structure was allocated. - */ -extern int MemoryInfoGetLine(MemoryInfo *); - -/** - * Get a pointer to the block of memory represented by the specified - * memory info structure. - */ -extern void * MemoryInfoGetPointer(MemoryInfo *); - -/** - * This function takes a pointer to a function that takes the memory - * info structure, as well as a void pointer for caller-provided - * arguments. It iterates over all the heap memory currently allocated - * at the time of calling, executing the function on each allocation. - */ -extern void MemoryIterate(void (*) (MemoryInfo *, void *), void *); - -/** - * Specify a function to be executed whenever a memory operation - * occurs. The MemoryAction argument specifies the operation that - * occurred on the block of memory represented by the memory info - * structure. The function also takes a void pointer to caller-provided - * arguments. - */ -extern void MemoryHook(void (*) (MemoryAction, MemoryInfo *, void *), void *); - -/** - * The default memory hook, which has sane behavior and is installed - * at runtime. This function does not use any memory on the heap, - * except for the MemoryInfo passed to it, which it assumes to be - * valid. Everything else happens on the stack only, to ensure that - * the hook doesn't make any memory problems worse. - */ -extern void MemoryDefaultHook(MemoryAction, MemoryInfo *, void *); - -/** - * Read over the block of memory represented by the given memory info - * structure and generate a hexadecimal and ASCII string for each - * chunk of the block. This function takes a callback function that - * takes the following parameters in order: - * .Bl -bullet -offset indent - * .It - * The current offset from the beginning of the block of memory in - * bytes. - * .It - * A null-terminated string containing the next 16 bytes of the block - * encoded as space-separated hex values. - * .It - * A null-terminated string containing the ASCII representation of the - * same 16 bytes of memory. This ASCII representation is safe to print - * to a terminal or other text device, because non-printable characters - * are encoded as a . (period). - * .It - * Caller-passed pointer. - * .El - */ -extern void -MemoryHexDump(MemoryInfo *, void (*) (size_t, char *, char *, void *), void *); - -#endif diff --git a/src/include/Queue.h b/src/include/Queue.h deleted file mode 100644 index 35821d3..0000000 --- a/src/include/Queue.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef CYTOPLASM_QUEUE_H -#define CYTOPLASM_QUEUE_H - -/*** - * @Nm Queue - * @Nd A simple static queue data structure. - * @Dd November 25 2022 - * @Xr Array HashMap - * - * .Nm - * implements a simple queue data structure that is statically sized. - * This implementation does not actually store the values of the items - * in it; it only stores pointers to the data. As such, you will have - * to manually maintain data and make sure it remains valid as long as - * it is in the queue. The advantage of this is that - * .Nm - * doesn't have to copy data, and thus doesn't care how big the data - * is. Furthermore, any arbitrary data can be stored in the queue. - * .Pp - * This queue implementation operates on the heap. It is a circular - * queue, and it does not grow as it is used. Once the size is set, - * the queue never gets any bigger. - */ - -#include - -/** - * These functions operate on a queue structure that is opaque to the - * caller. - */ -typedef struct Queue Queue; - -/** - * Allocate a new queue that is able to store the specified number of - * items in it. - */ -extern Queue * QueueCreate(size_t); - -/** - * Free the memory associated with the specified queue structure. Note - * that this function does not free any of the values stored in the - * queue; it is the caller's job to manage memory for each item. - * Typically, the caller would dequeue all the items in the queue and - * deal with them before freeing the queue itself. - */ -extern void QueueFree(Queue *); - -/** - * Push an element into the queue. This function returns a boolean - * value indicating whether or not the push succeeded. Pushing items - * into the queue will fail if the queue is full. - */ -extern int QueuePush(Queue *, void *); - -/** - * Pop an element out of the queue. This function returns NULL if the - * queue is empty. Otherwise, it returns a pointer to the item that is - * next up in the queue. - */ -extern void * QueuePop(Queue *); - -/** - * Retrieve a pointer to the item that is next up in the queue without - * actually discarding it, such that the next call to - * .Fn QueuePeek - * or - * .Fn QueuePop - * will return the same pointer. - */ -extern void * QueuePeek(Queue *); - -/** - * Determine whether or not the queue is full. - */ -extern int QueueFull(Queue *); - -/** - * Determine whether or not the queue is empty. - */ -extern int QueueEmpty(Queue *); - -#endif diff --git a/src/include/Rand.h b/src/include/Rand.h deleted file mode 100644 index a5be3ce..0000000 --- a/src/include/Rand.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef CYTOPLASM_RAND_H -#define CYTOPLASM_RAND_H - -/*** - * @Nm Rand - * @Nd Thread-safe random numbers. - * @Dd February 16 2023 - * @Xr Util - * - * .Nm - * is used for generating random numbers in a thread-safe way. - * Currently, one generator state is shared across all threads, which - * means that only one thread can generate random numbers at a time. - * This state is protected with a mutex to guarantee this behavior. - * In the future, a seed pool may be maintained to allow multiple - * threads to generate random numbers at the same time. - * .Pp - * The generator state is seeded on the first call to a function that - * needs it. The seed is determined by the current timestamp, the ID - * of the process, and the thread ID. These should all be sufficiently - * random sources, so the seed should be secure enough. - * .Pp - * .Nm - * currently uses a simple Mersenne Twister algorithm to generate - * random numbers. This algorithm was chosen because it is extremely - * popular and widespread. While it is likely not cryptographically - * secure, and does suffer some unfortunate pitfalls, this algorithm - * has stood the test of time and is simple enough to implement, so - * it was chosen over the alternatives. - * .Pp - * .Nm - * does not use any random number generator functions from the C - * standard library, since these are often flawed. - */ - -#include - -/** - * Generate a single random integer between 0 and the passed value. - */ -extern int RandInt(unsigned int); - -/** - * Generate the number of integers specified by the second argument - * storing them into the buffer pointed to in the first argument. - * Ensure that each number is between 0 and the third argument. - * .Pp - * This function allows a caller to get multiple random numbers at once - * in a more efficient manner than repeatedly calling - * .Fn RandInt , - * since each call to these functions - * has to lock and unlock a mutex. It is therefore better to obtain - * multiple random numbers in one pass if multiple are needed. - */ -extern void RandIntN(int *, size_t, unsigned int); - -#endif /* CYTOPLASM_RAND_H */ diff --git a/src/include/Runtime.h b/src/include/Runtime.h deleted file mode 100644 index 6e13b6a..0000000 --- a/src/include/Runtime.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef CYTOPLASM_RUNTIME_H -#define CYTOPLASM_RUNTIME_H - -/*** - * @Nm Runtime - * @Nd Supporting functions for the Cytoplasm runtime. - * @Dd May 23 2023 - * @Xr Memory - * - * .Nm - * provides supporting functions for the Cytoplasm runtime. These - * functions are not intended to be called directly by programs, - * but are used internally. They're exposed via a header because - * the runtime stub needs to know their definitions. - */ - -#include - -/** - * Write a memory report to a file in the current directory, using - * the provided program arguments, including the program name that - * executed. This function is to be called after all memory is - * supposed to have been freed. It iterates over all remaining - * memory and generates a text file containing all of the - * recorded information about each block, including a hex dump of - * the data stored in them. - */ -extern void GenerateMemoryReport(int argc, char **argv); - -#endif /* CYTOPLASM_RUNTIME_H */ diff --git a/src/include/Sha.h b/src/include/Sha.h deleted file mode 100644 index 25b6247..0000000 --- a/src/include/Sha.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef CYTOPLASM_SHA_H -#define CYTOPLASM_SHA_H - -/*** - * @Nm Sha - * @Nd A simple implementation of a few SHA hashing functions. - * @Dd December 19 2022 - * @Xr Memory Base64 - * - * This API defines simple functions for computing SHA hashes. - * At the moment, it only defines - * .Fn Sha256 - * and - * .Fn Sha1 , - * which compute the SHA-256 and SHA-1 hashes of the given C string, - * respectively. It is not trivial to implement SHA-512 in ANSI C - * due to the lack of a 64-bit integer type, so that hash - * function has been omitted. - */ - -/** - * This function takes a pointer to a NULL-terminated C string, and - * returns a NULL-terminated byte buffer allocated on the heap using - * the Memory API, or NULL if there was an error allocating memory. - * The returned byte buffer should be freed when it is no longer - * needed. It is important to note that the returned buffer is not - * a printable string; to get a printable string, use - * .Fn ShaToHex . - */ -extern unsigned char * Sha256(char *); - -/** - * This function takes a pointer to a NULL-terminated C string, and - * returns a NULL-terminated byte buffer allocated on the heap using - * the Memory API, or NULL if there was an error allocating memory. - * The returned byte buffer should be freed when it is no longer - * needed. It is important to note that the returned buffer is not - * a printable string; to get a printable string, use - * .Fn ShaToHex . - */ -extern unsigned char * Sha1(char *); - -/** - * Convert a SHA byte buffer into a hex string. These hex strings - * are typically what is transmitted, stored, and compared, however - * there may be times when it is necessary to work with the raw - * bytes directly, which is why the conversion to a hex string is - * a separate step. - */ -extern char * ShaToHex(unsigned char *); - -#endif /* CYTOPLASM_SHA_H */ diff --git a/src/include/Str.h b/src/include/Str.h deleted file mode 100644 index 714b8d8..0000000 --- a/src/include/Str.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef CYTOPLASM_STR_H -#define CYTOPLASM_STR_H - -/*** - * @Nm Str - * @Nd Functions for creating and manipulating strings. - * @Dd February 15 2023 - * @Xr Memory - * - * .Nm - * provides string-related functions. It is called - * .Nm , - * not String, because some platforms (Windows) do not have - * case-sensitive filesystems, which poses a problem since - * .Pa string.h - * is a standard library header. - */ - -#include - -#include - -/** - * Convert UTF-16 into a Unicode codepoint. - */ -extern UInt32 StrUtf16Decode(UInt16, UInt16); - -/** - * Take a Unicode codepoint and encode it into a string buffer containing - * between 1 and 4 bytes. The string buffer is allocated on the heap, - * so it should be freed when it is no longer needed. - */ -extern char * StrUtf8Encode(UInt32); - -/** - * Duplicate a null-terminated string, returning a new string on the - * heap. This is useful when a function takes in a string that it needs - * to store for long amounts of time, even perhaps after the original - * string is gone. - */ -extern char * StrDuplicate(const char *); - -/** - * Extract part of a null-terminated string, returning a new string on - * the heap containing only the requested subsection. Like the - * substring functions included with most programming languages, the - * starting index is inclusive, and the ending index is exclusive. - */ -extern char * StrSubstr(const char *, size_t, size_t); - -/** - * A varargs function that takes a number of null-terminated strings - * specified by the first argument, and returns a new string that - * contains their concatenation. It works similarly to - * .Xr strcat 3 , - * but it takes care of allocating memory big enough to hold all the - * strings. Any string in the list may be NULL. If a NULL pointer is - * passed, it is treated like an empty string. - */ -extern char * StrConcat(size_t,...); - -/** - * Return a boolean value indicating whether or not the null-terminated - * string consists only of blank characters, as determined by - * .Xr isblank 3 . - */ -extern int StrBlank(const char *str); - -/** - * Generate a string of the specified length, containing random - * lowercase and uppercase letters. - */ -extern char * StrRandom(size_t); - -/** - * Convert the specified integer into a string, returning the string - * on the heap, or NULL if there was a memory allocation error. The - * returned string should be freed by the caller after it is no longer - * needed. - */ -extern char * StrInt(long); - -/** - * Converts a string into a lowercase version of it using - * .Xr tolower 3 , - * returning the lowercase version on the heap, or NULL if there was - * a memory allocation error. The returned string should be freed by - * the caller after it is no longer needed. - */ -extern char * StrLower(char *); - -/** - * Compare two strings and determine whether or not they are equal. - * This is the most common use case of strcmp() in Cytoplasm, but - * strcmp() doesn't like NULL pointers, so these have to be checked - * explicitly and can cause problems if they aren't. This function, - * on the other hand, makes NULL pointers special cases. If both - * arguments are NULL, then they are considered equal. If only one - * argument is NULL, they are considered not equal. Otherwise, if - * no arguments are NULL, a regular strcmp() takes place and this - * function returns a boolean value indicating whether or not - * strcmp() returned 0. - */ -extern int StrEquals(const char *, const char *); - -#endif /* CYTOPLASM_STR_H */ diff --git a/src/include/Stream.h b/src/include/Stream.h deleted file mode 100644 index 3ddacc6..0000000 --- a/src/include/Stream.h +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef CYTOPLASM_STREAM_H -#define CYTOPLASM_STREAM_H - -/*** - * @Nm Stream - * @Nd An abstraction over the Io API that implements standard C I/O. - * @Dd April 29 2023 - * @Xr Io - * - * .Nm - * implements an abstraction layer over the Io API. This layer buffers - * I/O and makes it much easier to work with, mimicking the standard - * C library and offering some more convenience features. - */ - -#include - -#include - -/** - * An opaque structure analogous to C's FILE pointers. - */ -typedef struct Stream Stream; - -/** - * Create a new stream using the specified Io for underlying I/O - * operations. - */ -extern Stream * StreamIo(Io * io); - -/** - * Create a new stream using the specified POSIX file descriptor. - * This is a convenience function for calling - * .Fn IoFd - * and then passing the result into - * .Fn StreamIo . - */ -extern Stream * StreamFd(int); - -/** - * Create a new stream using the specified C FILE pointer. This is a - * convenience function for calling - * .Fn IoFile - * and then passing the result into - * .Fn StreamIo . - */ -extern Stream * StreamFile(FILE *); - -/** - * Create a new stream using the specified path and mode. This is a - * convenience function for calling - * .Xr fopen 3 - * and then passing the result into - * .Fn StreamFile . - */ -extern Stream * StreamOpen(const char *, const char *); - -/** - * Get a stream that writes to the standard output. - */ -extern Stream * StreamStdout(void); - -/** - * Get a stream that writes to the standard error. - */ -extern Stream * StreamStderr(void); - -/** - * Get a stream that reads from the standard input. - */ -extern Stream * StreamStdin(void); - -/** - * Close the stream. This flushes the buffers and closes the underlying - * Io. It is analogous to the standard - * .Xr fclose 3 - * function. - */ -extern int StreamClose(Stream *); - -/** - * Print a formatted string. This function is analogous to the standard - * .Xr vfprintf 3 - * function. - */ -extern int StreamVprintf(Stream *, const char *, va_list); - -/** - * Print a formatted string. This function is analogous to the - * standard - * .Xr fprintf 3 - * function. - */ -extern int StreamPrintf(Stream *, const char *,...); - -/** - * Get a single character from a stream. This function is analogous to - * the standard - * .Xr fgetc 3 - * function. - */ -extern int StreamGetc(Stream *); - -/** - * Push a character back onto the input stream. This function is - * analogous to the standard - * .Xr ungetc 3 - * function. - */ -extern int StreamUngetc(Stream *, int); - -/** - * Write a single character to the stream. This function is analogous - * to the standard - * .Xr fputc 3 - * function. - */ -extern int StreamPutc(Stream *, int); - -/** - * Write a null-terminated string to the stream. This function is - * analogous to the standard - * .Xr fputs 3 - * function. - */ -extern int StreamPuts(Stream *, char *); - -/** - * Read at most the specified number of characters minus 1 from the - * specified stream and store them at the memory located at the - * specified pointer. This function is analogous to the standard - * .Xr fgets 3 - * function. - */ -extern char * StreamGets(Stream *, char *, int); - -/** - * Set the file position indicator for the specified stream. This - * function is analogous to the standard - * .Xr fseeko - * function. - */ -extern off_t StreamSeek(Stream *, off_t, int); - -/** - * Test the end-of-file indicator for the given stream, returning a - * boolean value indicating whether or not it is set. This is analogous - * to the standard - * .Xr feof 3 - * function. - */ -extern int StreamEof(Stream *); - -/** - * Test the stream for an error condition, returning a boolean value - * indicating whether or not one is present. This is analogous to the - * standard - * .Xr ferror 3 - * function. - */ -extern int StreamError(Stream *); - -/** - * Clear the error condition associated with the given stream, allowing - * future reads or writes to potentially be successful. This functio - * is analogous to the standard - * .Xr clearerr 3 - * function. - */ -extern void StreamClearError(Stream *); - -/** - * Flush all buffered data using the streams underlying write function. - * This function is analogous to the standard - * .Xr fflush 3 - * function. - */ -extern int StreamFlush(Stream *); - -/** - * Read all the bytes from the first stream and write them to the - * second stream. This is analogous to - * .Fn IoCopy , - * but it uses the internal buffers of the streams. It is probably - * less efficient than doing a - * .Fn IoCopy - * instead, but it is more convenient. - */ -extern ssize_t StreamCopy(Stream *, Stream *); - -/** - * Get the file descriptor associated with the given stream, or -1 if - * the stream is not associated with any file descriptor. This function - * is analogous to the standard - * .Xr fileno 3 - * function. - */ -extern int StreamFileno(Stream *); - -#endif /* CYTOPLASM_STREAM_H */ diff --git a/src/include/Tls.h b/src/include/Tls.h deleted file mode 100644 index 4407ed0..0000000 --- a/src/include/Tls.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef CYTOPLASM_TLS_H -#define CYTOPLASM_TLS_H - -/*** - * @Nm Tls - * @Nd Interface to platform-dependent TLS libraries. - * @Dd April 29 2023 - * @Xr Stream Io - * - * .Nm - * provides an interface to platform-dependent TLS libraries. It allows - * Cytoplasm to support any TLS library with no changes to existing - * code. Support for additional TLS libraries is added by creating a - * new compilation unit that implements all the functions here, with - * the exception of a few, which are noted. - * .Pp - * Currently, Cytoplasm has support for the following TLS libraries: - * .Bl -bullet -offset indent - * .It - * LibreSSL - * .It - * OpenSSL - * .El - */ - -#include - -#define TLS_LIBRESSL 2 -#define TLS_OPENSSL 3 - -/** - * Create a new TLS client stream using the given file descriptor and - * the given server hostname. The hostname should be used to verify - * that the server actually is who it says it is. - * .Pp - * This function does not need to be implemented by the individual - * TLS support stubs. - */ -extern Stream * TlsClientStream(int, const char *); - -/** - * Create a new TLS server stream using the given certificate and key - * file, in the format natively supported by the TLS library. - * .Pp - * This function does not need to be implemented by the individual - * TLS support stubs. - */ -extern Stream * TlsServerStream(int, const char *, const char *); - -/** - * Initialize a cookie that stores information about the given client - * connection. This cookie will be passed into the other functions - * defined by this API. - */ -extern void * TlsInitClient(int, const char *); - -/** - * Initialize a cookie that stores information about the given - * server connection. This cookie will be passed into the other - * functions defined by this API. - */ -extern void * TlsInitServer(int, const char *, const char *); - -/** - * Read from a TLS stream, decrypting it and storing the result in the - * specified buffer. This function takes the cookie, buffer, and - * number of decrypted bytes to read into it. See the documentation for - * .Fn IoRead . - */ -extern ssize_t TlsRead(void *, void *, size_t); - -/** - * Write to a TLS stream, encrypting the buffer. This function takes - * the cookie, buffer, and number of unencrypted bytes to write to - * the stream. See the documentation for - * .Fn IoWrite . - */ -extern ssize_t TlsWrite(void *, void *, size_t); - -/** - * Close the TLS stream, also freeing all memory associated with the - * cookie. - */ -extern int TlsClose(void *); - -#endif /* CYTOPLASM_TLS_H */ diff --git a/src/include/UInt64.h b/src/include/UInt64.h deleted file mode 100644 index 51cc30c..0000000 --- a/src/include/UInt64.h +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef CYTOPLASM_UINT64_H -#define CYTOPLASM_UINT64_H - -/*** - * @Nm UInt64 - * @Nd Fixed-width 64 bit integers. - * @Dd August 11, 2023 - * - * .Pp - * ANSI C89 (or C99 for that matter) provides no required mechanism - * for 64 bit integers. Nevertheless, many compilers provide them as - * extensions. However, since it is not a gaurantee, and to be fully - * standards-compliant and thus portable, a platform-agnostic interface - * is required. This header provides such an interface. If the platform - * has a 64 bit integer type, that is used, and native operations are - * performed by C preprocessor macro expansion. Otherwise, a - * compatibility layer is provided, which implements 64-bit - * arithmetic on an array of 2 32-bit numbers which are provided by - * .Xr Int 3 . - * .Pp - * Note that 64-bit emulation is certainly not as performant as using - * native 64-bit operations, so whenever possible, the native - * operations should be preferred. However, since C provides no required - * 64 bit integer on 32-bit and less platforms, this API can be used as - * a "good enough" fallback mechanism. - * .Pp - * Also note that this implementation, both in the native and - * non-native forms, makes some assumptions: - * .Bl -bullet -width Ds - * .It - * When a cast from a larger integer to a smaller integer is performed, - * the upper bits are truncated, not the lower bits. - * .It - * Negative numbers are represented in memory and in registers in two's - * compliment form. - * .El - * .Pp - * This API may provide unexpected output if these assumptions are - * false for a given platform. - * - * @ignore-typedefs - */ - -#include - -#include - -#ifndef INT64_FORCE_EMULATED - -#define BIT64_MAX 18446744073709551615UL - -#if UINT_MAX == BIT64_MAX -/* typedef signed int Int64; */ -typedef unsigned int UInt64; - -#define UINT64_NATIVE - -#elif ULONG_MAX == BIT64_MAX -/* typedef signed int Int64; */ -typedef unsigned long UInt64; - -#define UINT64_NATIVE - -#endif - -#endif /* ifndef INT64_FORCE_EMULATED */ - -#ifdef UINT64_NATIVE - -#define UInt64Create(high, low) (((UInt64) (high) << 32) | (low)) -#define UInt64Low(a) ((UInt32) ((a) & 0x00000000FFFFFFFF)) -#define UInt64High(a) ((UInt32) ((a) >> 32)) - -#define UInt64Add(a, b) ((a) + (b)) -#define UInt64Sub(a, b) ((a) - (b)) -#define UInt64Mul(a, b) ((a) * (b)) -#define UInt64Div(a, b) ((a) / (b)) -#define UInt64Rem(a, b) ((a) % (b)) - -#define UInt64Sll(a, b) ((a) << (b)) -#define UInt64Srl(a, b) ((a) >> (b)) - -#define UInt64And(a, b) ((a) & (b)) -#define UInt64Or(a, b) ((a) | (b)) -#define UInt64Xor(a, b) ((a) ^ (b)) -#define UInt64Not(a) (~(a)) - -#define UInt64Eq(a, b) ((a) == (b)) -#define UInt64Lt(a, b) ((a) < (b)) -#define UInt64Gt(a, b) ((a) > (b)) - -#define UInt64Neq(a, b) ((a) != (b)) -#define UInt64Leq(a, b) ((a) <= (b)) -#define UInt64Geq(a, b) ((a) >= (b)) - -#else - -/** - * For platforms that do not have a native integer large enough to - * store a 64 bit integer, this struct is used. i[0] contains the low - * bits of integer, and i[1] contains the high bits of the integer. - * .Pp - * This struct should not be accessed directly, because UInt64 may not - * actually be this struct, it might be an actual integer type. For - * maximum portability, only use the functions defined here to - * manipulate 64 bit integers. - */ -typedef struct -{ - UInt32 i[2]; -} UInt64; - -/** - * Create a new unsigned 64 bit integer using the given high and low - * bits. - */ -extern UInt64 UInt64Create(UInt32, UInt32); - -/** - * Add two unsigned 64 bit integers together. - */ -extern UInt64 UInt64Add(UInt64, UInt64); - -/** - * Subtract the second 64 bit integer from the first. - */ -extern UInt64 UInt64Sub(UInt64, UInt64); - -/** - * Multiply two 64 bit integers together. The non-native version of - * this function uses the Russian Peasant method of multiplication, - * which should afford more performance than a naive multiplication by - * addition, but it is still rather slow and depends on the size of - * the integers being multiplied. - */ -extern UInt64 UInt64Mul(UInt64, UInt64); - -/** - * Divide the first 64 bit integer by the second and return the - * quotient. The non-native version of this function uses naive binary - * long division, which is slow, but gauranteed to finish in constant - * time. - */ -extern UInt64 UInt64Div(UInt64, UInt64); - -/** - * Divide the first 64 bit integer by the second and return the - * remainder. The non-native version of this function uses naive binary - * long division, which is slow, but gauranteed to finish in constant - * time. - */ -extern UInt64 UInt64Rem(UInt64, UInt64); - -/** - * Perform a left logical bit shift of a 64 bit integer. The second - * parameter is how many places to shift, and is declared as a regular - * integer because anything more than 64 does not make sense. - */ -extern UInt64 UInt64Sll(UInt64, int); - -/** - * Perform a right logical bit shift of a 64 bit integer. The second - * parameter is how many places to shift, and is declared as a regular - * integer because anything more than 64 does not make sense. - */ -extern UInt64 UInt64Srl(UInt64, int); - -/** - * Perform a bitwise AND (&) of the provided 64 bit integers. - */ -extern UInt64 UInt64And(UInt64, UInt64); - -/** - * Perform a bitwise OR (|) of the provided 64 bit integers. - */ -extern UInt64 UInt64Or(UInt64, UInt64); - -/** - * Perform a bitwise XOR (^) of the provided 64 bit integers. - */ -extern UInt64 UInt64Xor(UInt64, UInt64); - -/** - * Perform a bitwise NOT (~) of the provided 64 bit integer. - */ -extern UInt64 UInt64Not(UInt64); - -/** - * Perform a comparison of the provided 64 bit integers and return a C - * boolean that is true if and only if they are equal. - */ -extern int UInt64Eq(UInt64, UInt64); - -/** - * Perform a comparison of the provided 64 bit integers and return a C - * boolean that is true if and only if the second operand is strictly - * less than the first. - */ -extern int UInt64Lt(UInt64, UInt64); - -/** - * Perform a comparison of the provided 64 bit integers and return a C - * boolean that is true if and only if the second operand is strictly - * greater than the first. - */ -extern int UInt64Gt(UInt64, UInt64); - -#define UInt64Low(a) ((a).i[0]) -#define UInt64High(a) ((a).i[1]) - -#define UInt64Neq(a, b) (!UInt64Eq(a, b)) -#define UInt64Leq(a, b) (UInt64Eq(a, b) || UInt64Lt(a, b)) -#define UInt64Geq(a, b) (UInt64Eq(a, b) || UInt64Gt(a, b)) - -#endif - -#define UINT64_STRBUF 65 /* Base 2 representation with '\0' */ - -/** - * Convert a 64 bit integer to a string in an arbitrary base - * representation specified by the second parameter, using the provided - * buffer and length specified by the third and fourth parameters. To - * guarantee that the string will fit in the buffer, allocate it of - * size UINT64_STRBUF or larger. Note that a buffer size smaller than - * UINT64_STRBUF will invoke undefined behavior. - */ -extern size_t UInt64Str(UInt64, int, char *, size_t); - -#endif /* CYTOPLASM_UINT64_H */ diff --git a/src/include/Uri.h b/src/include/Uri.h deleted file mode 100644 index a47bf28..0000000 --- a/src/include/Uri.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef CYTOPLASM_URI_H -#define CYTOPLASM_URI_H - -/*** - * @Nm Uri - * @Nd Parse a URI. Typically used to parse HTTP(s) URLs. - * @Dd April 29 2023 - * @Xr Http - * - * .Nm - * provides a simple mechanism for parsing URIs. This is an extremely - * basic parser that (ab)uses - * .Xr sscanf 3 - * to parse URIs, so it may not be the most reliable, but it should - * work in most cases and on reasonable URIs that aren't too long, as - * the _MAX definitions are modest. - */ - -#define URI_PROTO_MAX 8 -#define URI_HOST_MAX 128 -#define URI_PATH_MAX 256 - -/** - * The parsed URI is stored in this structure. - */ -typedef struct Uri -{ - char proto[URI_PROTO_MAX]; - char host[URI_HOST_MAX]; - char path[URI_PATH_MAX]; - unsigned short port; -} Uri; - -/** - * Parse a URI string into the Uri structure as described above, or - * return NULL if there was a parsing error. - */ -extern Uri * UriParse(const char *); - -/** - * Free the memory associated with a Uri structure returned by - * .Fn UriParse . - */ -extern void UriFree(Uri *); - -#endif /* CYTOPLASM_URI_H */ diff --git a/src/include/Util.h b/src/include/Util.h deleted file mode 100644 index d6c3830..0000000 --- a/src/include/Util.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef CYTOPLASM_UTIL_H -#define CYTOPLASM_UTIL_H - -/*** - * @Nm Util - * @Nd Some misc. helper functions that don't need their own headers. - * @Dd February 15 2023 - * - * This header holds a number of random functions related to strings, - * time, the filesystem, and other simple tasks that don't require a - * full separate API. For the most part, the functions here are - * entirely standalone, depending only on POSIX functions, however - * there are a few that depend explicitly on a few other APIs. Those - * are noted. - */ - -#include -#include -#include - -#include -#include - -/** - * Get the current timestamp in milliseconds since the Unix epoch. This - * uses - * .Xr gettimeofday 2 - * and time_t, and converts it to a single number, which is then - * returned to the caller. - * .Pp - * A note on the 2038 problem: as long as sizeof(time_t) >= 8, that is, - * as long as the time_t type is 64 bits or more, then everything - * should be fine. On most, if not, all, 64-bit systems, time_t is 64 - * bits. time_t is promoted to a 64-bit integer before it is converted - * to milliseconds, so there is no risk of overflue due to the - * multiplication by 1000. However, if time_t is only 32 bits, it will - * overflow before it even gets to this function, which will cause this - * function to produce unexpected results. - */ -extern UInt64 UtilServerTs(void); - -/** - * Use - * .Xr stat 2 - * to get the last modified time of the given file, or zero if there - * was an error getting the last modified time of a file. This is - * primarily useful for caching file data. - */ -extern UInt64 UtilLastModified(char *); - -/** - * This function behaves just like the system call - * .Xr mkdir 2 , - * but it creates any intermediate directories as necessary, unlike - * .Xr mkdir 2 . - */ -extern int UtilMkdir(const char *, const mode_t); - -/** - * Sleep the calling thread for the given number of milliseconds. - * POSIX does not have a very friendly way to sleep, so this wraps - * .Xr nanosleep 2 - * to make its usage much, much simpler. - */ -extern int UtilSleepMillis(UInt64); - -/** - * This function works identically to the POSIX - * .Xr getdelim 3 , - * except that it assumes pointers were allocated with the Memory API - * and it reads from a Stream instead of a file pointer. - */ -extern ssize_t UtilGetDelim(char **, size_t *, int, Stream *); - -/** - * This function is just a special case of - * .Fn UtilGetDelim - * that sets the delimiter to the newline character. - */ -extern ssize_t UtilGetLine(char **, size_t *, Stream *); - -/** - * Get a unique number associated with the current thread. - * Numbers are assigned in the order that threads call this - * function, but are guaranteed to be unique in identifying - * the thread in a more human-readable way than just casting - * the return value of - * .Fn pthread_self - * to a number. - */ -extern UInt32 UtilThreadNo(void); - -#endif /* CYTOPLASM_UTIL_H */ diff --git a/tools/int64.c b/tools/int64.c deleted file mode 100644 index fb9c5cf..0000000 --- a/tools/int64.c +++ /dev/null @@ -1,145 +0,0 @@ -#include - -#include - -/* AssertEquals(actual, expected) */ -int -AssertEquals(char *msg, Int64 x, Int64 y) -{ - if (!Int64Eq(x, y)) - { - Log(LOG_ERR, "%s: Expected 0x%X 0x%X, got 0x%X 0x%X", msg, - Int64High(y), Int64Low(y), - Int64High(x), Int64Low(x)); - - return 0; - } - - return 1; -} - -int -Main(void) -{ - Int64 x, y; - - Log(LOG_INFO, "sizeof(Int64) = %lu", sizeof(Int64)); - -#ifdef INT64_NATIVE - Log(LOG_INFO, "Using native 64-bit integers."); -#else - Log(LOG_INFO, "Using emulated 64-bit integers."); -#endif - - /* BSR Tests */ - - x = Int64Create(0x000000FF, 0x00000000); - - y = Int64Sra(x, 4); - AssertEquals("x >> 4", y, Int64Create(0x0000000F, 0xF0000000)); - - y = Int64Sra(x, 8); - AssertEquals("x >> 8", y, Int64Create(0x00000000, 0xFF000000)); - - y = Int64Sra(x, 36); - AssertEquals("x >> 36", y, Int64Create(0x00000000, 0x0000000F)); - - x = Int64Create(0xFF000000, 0x00000000); - - y = Int64Sra(x, 4); - AssertEquals("x >> 4", y, Int64Create(0xFFF00000, 0x00000000)); - - y = Int64Sra(x, 8); - AssertEquals("x >> 8", y, Int64Create(0xFFFF0000, 0x00000000)); - - y = Int64Sra(x, 63); - AssertEquals("x >> 63", y, Int64Create(0xFFFFFFFF, 0xFFFFFFFF)); - - /* BSL Tests */ - - x = Int64Create(0x00000000, 0xFF000000); - - y = Int64Sll(x, 4); - AssertEquals("x << 4", y, Int64Create(0x0000000F, 0xF0000000)); - - y = Int64Sll(x, 8); - AssertEquals("x << 8", y, Int64Create(0x000000FF, 0x00000000)); - - y = Int64Sll(x, 36); - AssertEquals("x << 36", y, Int64Create(0xF0000000, 0x00000000)); - - /* ADD Tests */ - - x = Int64Create(0x00000000, 0xF0000001); - y = Int64Create(0x00000000, 0x00000002); - AssertEquals("0xF0000001 + 0x00000002", Int64Add(x, y), Int64Create(0x00000000, 0xF0000003)); - - x = Int64Create(0x00000000, 0xF0000000); - y = Int64Create(0x00000000, 0x10000000); - AssertEquals("0xF0000000 + 0x10000000", Int64Add(x, y), Int64Create(0x00000001, 0x00000000)); - - x = Int64Create(0, 5); - y = Int64Neg(Int64Create(0, 10)); - AssertEquals("5 + (-10)", Int64Add(x, y), Int64Neg(Int64Create(0, 5))); - - /* SUB Tests */ - x = Int64Create(0x00000000, 0x00000005); - y = Int64Create(0x00000000, 0x00000002); - AssertEquals("0x00000005 - 0x00000002", Int64Sub(x, y), Int64Create(0x00000000, 0x00000003)); - - x = Int64Create(0x00000001, 0x00000000); - y = Int64Create(0x00000000, 0x00000001); - AssertEquals("0x00000001 0x00000000 - 0x00000001", Int64Sub(x, y), Int64Create(0x00000000, 0xFFFFFFFF)); - - x = Int64Create(0, 5); - y = Int64Create(0, 10); - AssertEquals("5 - 10", Int64Sub(x, y), Int64Neg(Int64Create(0, 5))); - - x = Int64Create(0, 5); - y = Int64Neg(Int64Create(0, 10)); - AssertEquals("5 - (-10)", Int64Sub(x, y), Int64Create(0, 15)); - - /* MUL Tests */ - x = Int64Create(0, 18); - y = Int64Create(0, 1); - AssertEquals("18 * 1", Int64Mul(x, y), Int64Create(0, 18)); - - x = Int64Create(0, 20); - y = Int64Create(0, 12); - AssertEquals("20 * 12", Int64Mul(x, y), Int64Create(0, 240)); - - x = Int64Create(0x00000000, 0x00000005); - y = Int64Create(0x00000000, 0x00000005); - AssertEquals("0x00000005 * 0x00000005", Int64Mul(x, y), Int64Create(0x00000000, 0x00000019)); - - x = Int64Create(0x00000001, 0x00000000); - y = Int64Create(0x00000000, 0x00000005); - AssertEquals("0x00000001 0x00000000 * 0x00000005", Int64Mul(x, y), Int64Create(0x00000005, 0x00000000)); - - /* DIV Tests */ - x = Int64Create(0, 12); - y = Int64Create(0, 4); - AssertEquals("12 / 4", Int64Div(x, y), Int64Create(0, 3)); - - /* MOD Tests */ - x = Int64Create(0x000000FF, 0x00000000); - y = Int64Create(0x00000000, 0x00000010); - AssertEquals("0x000000FF 0x00000000 mod 0x00000010", Int64Rem(x, y), Int64Create(0, 0)); - - x = Int64Create(0x00000000, 0xFF000000); - y = Int64Create(0x00000000, 0x00000010); - AssertEquals("0x00000000 0xFF000000 mod 0x00000010", Int64Rem(x, y), Int64Create(0, 0)); - - x = Int64Create(0xFF000000, 0x00000000); - y = Int64Create(0x00000000, 0x00000010); - AssertEquals("0xFF000000 0x00000000 mod 0x00000010", Int64Rem(x, y), Int64Create(0, 0)); - - x = Int64Create(0x00000000, 0x000000F0); - y = Int64Create(0x00000000, 0x00000010); - AssertEquals("0x00000000 0x000000F0 mod 0x00000010", Int64Rem(x, y), Int64Create(0, 0)); - - /* TODO: Add more tests for negative multiplication, division, and - * mod */ - - return 0; -} diff --git a/tools/uint64.c b/tools/uint64.c deleted file mode 100644 index 8e9f5f5..0000000 --- a/tools/uint64.c +++ /dev/null @@ -1,119 +0,0 @@ -#include - -#include - -/* AssertEquals(actual, expected) */ -int -AssertEquals(char *msg, UInt64 x, UInt64 y) -{ - if (!UInt64Eq(x, y)) - { - Log(LOG_ERR, "%s: Expected 0x%X 0x%X, got 0x%X 0x%X", msg, - UInt64High(y), UInt64Low(y), - UInt64High(x), UInt64Low(x)); - - return 0; - } - - return 1; -} - -int -Main(void) -{ - UInt64 x, y; - - Log(LOG_INFO, "sizeof(UInt64) = %lu", sizeof(UInt64)); - -#ifdef UINT64_NATIVE - Log(LOG_INFO, "Using native 64-bit integers."); -#else - Log(LOG_INFO, "Using emulated 64-bit integers."); -#endif - - /* BSR Tests */ - - x = UInt64Create(0x000000FF, 0x00000000); - - y = UInt64Srl(x, 4); - AssertEquals("x >> 4", y, UInt64Create(0x0000000F, 0xF0000000)); - - y = UInt64Srl(x, 8); - AssertEquals("x >> 8", y, UInt64Create(0x00000000, 0xFF000000)); - - y = UInt64Srl(x, 36); - AssertEquals("x >> 36", y, UInt64Create(0x00000000, 0x0000000F)); - - /* BSL Tests */ - - x = UInt64Create(0x00000000, 0xFF000000); - - y = UInt64Sll(x, 4); - AssertEquals("x << 4", y, UInt64Create(0x0000000F, 0xF0000000)); - - y = UInt64Sll(x, 8); - AssertEquals("x << 8", y, UInt64Create(0x000000FF, 0x00000000)); - - y = UInt64Sll(x, 36); - AssertEquals("x << 36", y, UInt64Create(0xF0000000, 0x00000000)); - - /* ADD Tests */ - - x = UInt64Create(0x00000000, 0xF0000001); - y = UInt64Create(0x00000000, 0x00000002); - AssertEquals("0xF0000001 + 0x00000002", UInt64Add(x, y), UInt64Create(0x00000000, 0xF0000003)); - - x = UInt64Create(0x00000000, 0xF0000000); - y = UInt64Create(0x00000000, 0x10000000); - AssertEquals("0xF0000000 + 0x10000000", UInt64Add(x, y), UInt64Create(0x00000001, 0x00000000)); - - /* SUB Tests */ - x = UInt64Create(0x00000000, 0x00000005); - y = UInt64Create(0x00000000, 0x00000002); - AssertEquals("0x00000005 - 0x00000002", UInt64Sub(x, y), UInt64Create(0x00000000, 0x00000003)); - - x = UInt64Create(0x00000001, 0x00000000); - y = UInt64Create(0x00000000, 0x00000001); - AssertEquals("0x00000001 0x00000000 - 0x00000001", UInt64Sub(x, y), UInt64Create(0x00000000, 0xFFFFFFFF)); - - /* MUL Tests */ - x = UInt64Create(0, 18); - y = UInt64Create(0, 1); - AssertEquals("18 * 1", UInt64Mul(x, y), UInt64Create(0, 18)); - - x = UInt64Create(0, 20); - y = UInt64Create(0, 12); - AssertEquals("20 * 12", UInt64Mul(x, y), UInt64Create(0, 240)); - - x = UInt64Create(0x00000000, 0x00000005); - y = UInt64Create(0x00000000, 0x00000005); - AssertEquals("0x00000005 * 0x00000005", UInt64Mul(x, y), UInt64Create(0x00000000, 0x00000019)); - - x = UInt64Create(0x00000001, 0x00000000); - y = UInt64Create(0x00000000, 0x00000005); - AssertEquals("0x00000001 0x00000000 * 0x00000005", UInt64Mul(x, y), UInt64Create(0x00000005, 0x00000000)); - - /* DIV Tests */ - x = UInt64Create(0, 12); - y = UInt64Create(0, 4); - AssertEquals("12 / 4", UInt64Div(x, y), UInt64Create(0, 3)); - - /* MOD Tests */ - x = UInt64Create(0x000000FF, 0x00000000); - y = UInt64Create(0x00000000, 0x00000010); - AssertEquals("0x000000FF 0x00000000 mod 0x00000010", UInt64Rem(x, y), UInt64Create(0, 0)); - - x = UInt64Create(0x00000000, 0xFF000000); - y = UInt64Create(0x00000000, 0x00000010); - AssertEquals("0x00000000 0xFF000000 mod 0x00000010", UInt64Rem(x, y), UInt64Create(0, 0)); - - x = UInt64Create(0xFF000000, 0x00000000); - y = UInt64Create(0x00000000, 0x00000010); - AssertEquals("0xFF000000 0x00000000 mod 0x00000010", UInt64Rem(x, y), UInt64Create(0, 0)); - - x = UInt64Create(0x00000000, 0x000000F0); - y = UInt64Create(0x00000000, 0x00000010); - AssertEquals("0x00000000 0x000000F0 mod 0x00000010", UInt64Rem(x, y), UInt64Create(0, 0)); - - return 0; -}