Skip to content

Instantly share code, notes, and snippets.

@Hachem-H
Last active February 10, 2024 17:26
Show Gist options
  • Save Hachem-H/597bb42cf8f8ef44f50beb2ebb9c14ec to your computer and use it in GitHub Desktop.
Save Hachem-H/597bb42cf8f8ef44f50beb2ebb9c14ec to your computer and use it in GitHub Desktop.
Hachem's C Extensions
/*
* hext.h - Hachem's C Extensions.
*
* A set of utility functions, definitions and macros
* which make programming in C, a little less annoying.
*
*
* Author: Hachem H.
* Version: 0.1.1
*
*
* ## Documentation
* ### Type definitions
*
* ```c
* typedef uint64_t u64;
* typedef uint32_t u32;
* typedef uint16_t u16;
* typedef uint8_t u8;
*
* typedef int64_t i64;
* typedef int32_t i32;
* typedef int16_t i16;
* typedef int8_t i8;
*
* typedef float f32;
* typedef double f64;
*
* typedef size_t usize;
* typedef ptrdiff_t isize;
*
* typedef uint8_t byte;
* typedef unsigned char uchar;
* ```
*
* ### Memory utility functions
* Traditionally in C memory is allocated through the `malloc` function, which has to
* take in a size and returns a pointer which has to be casted into the proper buffer
* type. `hext` offers a macro which takes in the type and the number of elements instead.
*
* ```c
* #include <hext.h>
*
* int main(void)
* {
* u32* buffer = alloc(u32, 100);
* for (u32 i = 0; i < 100; i++)
* buffer[i] = i;
* free(buffer);
* }
* ```
*
* ### Error and optional types
* The first type is the `Possible` type, which is defined by a `Possible(errorType, okayType)`.
* Its a result type which can give either an error of a given type or a default type in
* case of success. The following example shows an over engineered examples of a division function:
*
* ```c
* #include "hext.h"
*
* typedef enum DivideError_t
* {
* DivisionByZero,
* IllegalNumber,
* } DivideError;
*
* typedef Possible(DivideError, i32) DivisionResult;
* DivisionResult Divide(i32 a, i32 b)
* {
* if (b == 0)
* return Error(DivisionResult, DivisionByZero);
* i32 result = a/b;
* if (result == 69)
* return Error(DivisionResult, IllegalNumber);
* return Some(DivisionResult, result);
* }
*
* int main(void)
* {
* DivisionResult number = Divide(1, 0);
* if (!number.ok)
* {
* switch (number.error)
* {
* case IllegalNumber:
* puts("Illegal number obtained.");
* break;
* case DivisionByZero:
* puts("Division by zero error.");
* break;
* default: break;
* }
* } else
* printf("Result: %d\n", number.some);
* }
* ```
*
* We first define a division result which can either be an error or an actual number.
* In case of errors, we simply return an `Error` containing the function return type
* and the actual error value (which should be in so called error type), or in case of
* success, we return `Some` value in the same manner. Later we can check if the function
* ran properly by checking the `ok` flag.
*
* ### Miscellaneous
* Testing if two strings are equal is somewhat long winded in C, so we have a macro
* `streql(string1, string2)` which just returns a boolean. `hext` also have 2 new
* keywords for context static. `global` and `internal`.
*
* ## Logging
* It's pretty common in C to write a logging system with colors as an alternative
* to the now ubiquitous `printf`, `hext` provides simple logging functions:
* - `HEXT_INFO`
* - `HEXT_DEBUG`
* - `HEXT_WARN`
* - `HEXT_INFO`
* which take formatting arguments similar to those in the standard library.
* `hext` also provides certain constants which allow color printing and style formatting
* for the tty. For example:
*
* ```c
* printf("%sThis is bold\n%sThis is bold and red\n%s%sThis is just red.",
* HEXT_CONSOLE_MODE_BOLD, HEXT_CONSOLE_COLOR_RED,
* HEXT_CONSOLE_MODE_RESET, HEXT_CONSOLE_COLOR_RED);
* ```
*
* All of the available options in the header file are:
* - `HEXT_CONSOLE_MODE_RESET`
* - `HEXT_CONSOLE_MODE_BOLD`
* - `HEXT_CONSOLE_MODE_UNDERLINE`
* - `HEXT_CONSOLE_MODE_ITALIC`
*
* - `HEXT_CONSOLE_COLORS_RED`
* - `HEXT_CONSOLE_COLORS_GREEN`
* - `HEXT_CONSOLE_COLORS_YELLOW`
* - `HEXT_CONSOLE_COLORS_BLUE`
* - `HEXT_CONSOLE_COLORS_MAGENTA`
* - `HEXT_CONSOLE_COLORS_CYAN`
*
*
* MIT License
*
* Copyright (c) 2024 Hachem
*
* 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 substantial 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.
*
*/
#pragma once
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#define internal static
#define global static
typedef uint64_t u64;
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;
typedef int64_t i64;
typedef int32_t i32;
typedef int16_t i16;
typedef int8_t i8;
typedef float f32;
typedef double f64;
typedef size_t usize;
typedef ptrdiff_t isize;
typedef uint8_t byte;
typedef unsigned char uchar;
#define streql(str1, str2) (strcmp(str1, str2) == 0)
#define alloc(type, count) (type*) malloc(sizeof(type)*count);
#define Possible(errorType, okayType) \
struct { bool ok; \
union { errorType error; \
okayType some; }; }
#define Error(T, errorExpression) \
(T) { .ok = false, .error = errorExpression, }
#define Some(T, okayExpression) \
(T) { .ok = true, .some = okayExpression, }
global const char* const HEXT_CONSOLE_MODE_RESET = "\033[0m";
global const char* const HEXT_CONSOLE_MODE_BOLD = "\033[1m";
global const char* const HEXT_CONSOLE_MODE_UNDERLINE = "\033[4m";
global const char* const HEXT_CONSOLE_MODE_ITALIC = "\033[3m";
global const char* const HEXT_CONSOLE_COLORS_RED = "\033[91m";
global const char* const HEXT_CONSOLE_COLORS_GREEN = "\033[92m";
global const char* const HEXT_CONSOLE_COLORS_YELLOW = "\033[93m";
global const char* const HEXT_CONSOLE_COLORS_BLUE = "\033[94m";
global const char* const HEXT_CONSOLE_COLORS_MAGENTA = "\033[95m";
global const char* const HEXT_CONSOLE_COLORS_CYAN = "\033[96m";
#define HEXT_INFO(...) { \
printf("[%s%sINFO%s]: ", HEXT_CONSOLE_COLORS_CYAN, \
HEXT_CONSOLE_MODE_BOLD, \
HEXT_CONSOLE_MODE_RESET); \
printf(__VA_ARGS__); putchar('\n'); }
#define HEXT_DEBUG(...) { \
printf("[%s%sDEBUG%s]: ", HEXT_CONSOLE_COLORS_BLUE, \
HEXT_CONSOLE_MODE_BOLD, \
HEXT_CONSOLE_MODE_RESET); \
printf(__VA_ARGS__); putchar('\n'); }
#define HEXT_WARN(...) { \
printf("[%s%sWARN%s]: ", HEXT_CONSOLE_COLORS_YELLOW, \
HEXT_CONSOLE_MODE_BOLD, \
HEXT_CONSOLE_MODE_RESET); \
printf(__VA_ARGS__); putchar('\n'); }
#define HEXT_ERROR(...) { \
printf("[%s%sERROR%s]: ", HEXT_CONSOLE_COLORS_RED, \
HEXT_CONSOLE_MODE_BOLD, \
HEXT_CONSOLE_MODE_RESET); \
printf(__VA_ARGS__); putchar('\n'); }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment