This commit is contained in:
Niklas Gollenstede
2025-10-31 22:37:36 +01:00
commit 174fe17e89
197 changed files with 79558 additions and 0 deletions

15
kernel/utils/alloc.cc Normal file
View File

@@ -0,0 +1,15 @@
#include "./alloc.h"
#include "../debug/assert.h"
void *malloc([[maybe_unused]] size_t size) {
assert(!"Memory allocation not supported");
return nullptr;
}
void *calloc([[maybe_unused]] size_t nmemb, [[maybe_unused]] size_t size) {
assert(!"Memory allocation not supported");
return nullptr;
}
void free([[maybe_unused]] void *ptr) {
assert(!"Memory allocation not supported");
}

36
kernel/utils/alloc.h Normal file
View File

@@ -0,0 +1,36 @@
// vim: set noet ts=4 sw=4:
/*! \file
* \brief C-style dynamic memory allocation interface
*/
#pragma once
#include "../types.h"
/*! \brief Allocate a memory block
* The memory is not initialized.
*
* \param size Requested size of memory in bytes.
* \return Pointer to memory or `nullptr` on error (no memory available) or if
* size was zero.
* \opt Implement method
*/
extern "C" void *malloc(size_t size);
/*! \brief Free an allocated memory block
*
* \param ptr Pointer to an previously allocated memory block.
* \opt Implement method
*/
extern "C" void free(void *ptr);
/*! \brief Allocate memory for an array of elements
* The memory is set to zero.
*
* \param nmemb Number of elements
* \param size Size of an element in bytes
* \return pointer to the allocated memory or `nullptr` if the request fails
* \opt Implement method
*/
extern "C" void *calloc(size_t nmemb, size_t size);

27
kernel/utils/math.h Normal file
View File

@@ -0,0 +1,27 @@
// vim: set noet ts=4 sw=4:
/*! \file
* \brief General purpose \ref Math "math functions"
*/
#pragma once
#include "types.h"
/*! \brief Basic math helper functions
*/
namespace Math {
template <typename T>
T abs(T a) {
return (a >= 0 ? a : -a);
}
template <typename T>
T min(T a, T b) {
return a > b ? b : a;
}
template <typename T>
T max(T a, T b) {
return a > b ? a : b;
}
} // namespace Math

1215
kernel/utils/png.cc Normal file

File diff suppressed because it is too large Load Diff

222
kernel/utils/png.h Normal file
View File

@@ -0,0 +1,222 @@
/*! \file
* \brief \ref PNG library
*
* The PNG library 'uPNG' was written by Sean Middleditch and Lode Vandevenne
* and modified for StuBS by Bernhard Heinloth.
*
* \see https://github.com/elanthis/upng
*
* uPNG -- derived from LodePNG version 20100808
*
* Copyright (c) 2005-2010 Lode Vandevenne
* Copyright (c) 2010 Sean Middleditch
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not
*be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#pragma once
/**! \brief Portable Network Graphics file format
*/
class PNG {
public:
enum error {
PNG_EOK = 0, ///< success (no error)
PNG_ENOMEM = 1, ///< memory allocation failed
PNG_ENOTFOUND = 2, ///< resource not found (file missing)
PNG_ENOTPNG = 3, ///< image data does not have a PNG header
PNG_EMALFORMED = 4, ///< image data is not a valid PNG image
PNG_EUNSUPPORTED = 5, ///< critical PNG chunk type is not supported
PNG_EUNINTERLACED = 6, ///< image interlacing is not supported
PNG_EUNFORMAT = 7, ///< image color format is not supported
PNG_EPARAM = 8, ///< invalid parameter to method call
PNG_EIOERROR = 9 ///< Filesystem issues
};
enum format {
BADFORMAT, ///< Invalid format
RGB8, ///< 24bit RGB (8bit per color)
RGB16, ///< 48bit RGB (16bit per color)
RGBA8, ///< 32bit RGB (including alpha channel)
RGBA16, ///< 64bit RGB (including alpha channel)
LUMINANCE1, ///< Monochrome (black-white)
LUMINANCE2, ///< four shades of gray (2bit gray scale)
LUMINANCE4, ///< 16 shades of gray (4bit gray scale)
LUMINANCE8, ///< 8bit gray scale
LUMINANCE_ALPHA1, ///< Monochrome (black-white) with alpha channel
LUMINANCE_ALPHA2, ///< 2bit gray scale with alpha channel
LUMINANCE_ALPHA4, ///< 4bit gray scale with alpha channel
LUMINANCE_ALPHA8 ///< 8bit gray scale with alpha channel
};
private:
enum color { COLOR_LUM = 0, COLOR_RGB = 2, COLOR_LUMA = 4, COLOR_RGBA = 6 };
unsigned width = 0;
unsigned height = 0;
enum color color_type;
unsigned color_depth;
enum format format = BADFORMAT;
unsigned char* buffer = nullptr;
unsigned long size = 0;
enum {
STATE_ERROR = -1,
STATE_DECODED = 0,
STATE_HEADER = 1,
STATE_NEW = 2
} state;
struct {
const unsigned char* buffer;
unsigned long size;
char owning;
} source;
struct huffman_tree {
unsigned* tree2d;
unsigned maxbitlen; ///< maximum number of bits a single code can get
unsigned
numcodes; ///< number of symbols in the alphabet = number of codes
};
void free_source();
static void huffman_tree_init(struct huffman_tree* tree, unsigned* buffer,
unsigned numcodes, unsigned maxbitlen);
void huffman_tree_create_lengths(struct huffman_tree* tree,
const unsigned* bitlen);
unsigned huffman_decode_symbol(const unsigned char* in, unsigned long* bp,
const struct huffman_tree* codetree,
unsigned long inlength);
void get_tree_inflate_dynamic(struct huffman_tree* codetree,
struct huffman_tree* codetreeD,
struct huffman_tree* codelengthcodetree,
const unsigned char* in, unsigned long* bp,
unsigned long inlength);
void inflate_huffman(unsigned char* out, unsigned long outsize,
const unsigned char* in, unsigned long* bp,
unsigned long* pos, unsigned long inlength,
unsigned btype);
void inflate_uncompressed(unsigned char* out, unsigned long outsize,
const unsigned char* in, unsigned long* bp,
unsigned long* pos, unsigned long inlength);
enum error uz_inflate_data(unsigned char* out, unsigned long outsize,
const unsigned char* in, unsigned long insize,
unsigned long inpos);
enum error uz_inflate(unsigned char* out, unsigned long outsize,
const unsigned char* in, unsigned long insize);
void unfilter_scanline(unsigned char* recon, const unsigned char* scanline,
const unsigned char* precon, unsigned long bytewidth,
unsigned char filterType, unsigned long length);
void unfilter(unsigned char* out, const unsigned char* in, unsigned w,
unsigned h, unsigned bpp);
static void remove_padding_bits(unsigned char* out, const unsigned char* in,
unsigned long olinebits,
unsigned long ilinebits, unsigned h);
void post_process_scanlines(unsigned char* out, unsigned char* in,
const PNG* info_png);
enum format determine_format();
protected:
enum error error;
unsigned error_line;
/*! \brief Extract header (image attributes)
*/
enum error header();
/*! \brief Decode whole image
*/
enum error decode();
public:
/*! \brief Load PNG image from memory
* \param buffer pointer to memory buffer
* \param size size of memory buffer
*/
PNG(const unsigned char* buffer, unsigned long size);
/*! \brief Free memory reserved for PNG image
*/
~PNG();
/*! \brief Width of image (pixels)
*/
unsigned get_width() const { return width; }
/*! \brief Height of image (pixels)
*/
unsigned get_height() const { return height; }
/*! \brief Bits per pixel
*/
unsigned get_bpp() const { return get_bitdepth() * get_components(); }
/*! \brief Depth of color (bits pro color channel)
*/
unsigned get_bitdepth() const { return color_depth; }
/*! \brief Number of components per pixel
*/
unsigned get_components() const {
switch (color_type) {
case COLOR_LUM:
return 1;
case COLOR_RGB:
return 3;
case COLOR_LUMA:
return 2;
case COLOR_RGBA:
return 4;
default:
return 0;
}
}
/*! \brief Number of bytes per pixel
*/
unsigned get_pixelsize() const {
unsigned bits = get_bitdepth() * get_components();
bits += bits % 8;
return bits;
}
/*! \brief Retrieve the format
*/
enum format get_format() const { return format; }
/*! \brief Image buffer address
* \return Pointer to image buffer
*/
const unsigned char* get_buffer() {
decode();
return buffer;
}
/*! \brief Size of image buffer
* \return Total size of image buffer in bytes
*/
unsigned get_size() {
decode();
return size;
}
};

42
kernel/utils/random.cc Normal file
View File

@@ -0,0 +1,42 @@
#include "./random.h"
Random::Random(uint32_t seed) {
mt[0] = seed;
for (uint32_t i = 1; i < N; i++) {
mt[i] = (F * (mt[i - 1] ^ (mt[i - 1] >> 30)) + i);
}
index = N;
}
uint32_t Random::number() {
uint16_t v = index;
if (index >= N) {
// Twist
for (uint32_t i = 0; i < N; i++) {
uint32_t x = (mt[i] & MASK_UPPER) + (mt[(i + 1) % N] & MASK_LOWER);
uint32_t xA = x >> 1;
if ((x & 0x1) != 0) {
xA ^= A;
}
mt[i] = mt[(i + M) % N] ^ xA;
}
v = index = 0;
}
uint32_t y = mt[v];
index = v + 1;
y ^= (y >> U);
y ^= (y << S) & B;
y ^= (y << T) & C;
y ^= (y >> L);
return y;
}

51
kernel/utils/random.h Normal file
View File

@@ -0,0 +1,51 @@
/*! \file
* \brief Class \ref Random (PRNG based on Mersenne Twister)
*/
#pragma once
#include "types.h"
/*! Mersenne Twister (32 bit pseudorandom number generator)
*
* \see [Wikipedia](https://en.wikipedia.org/wiki/Mersenne_Twister)
*/
class Random {
private:
static const uint32_t N = 624;
static const uint32_t M = 397;
static const uint32_t R = 31;
static const uint32_t A = 0x9908B0DF;
// initialization multiplier
static const uint32_t F = 1812433253;
static const uint32_t U = 11;
static const uint32_t S = 7;
static const uint32_t B = 0x9D2C5680;
static const uint32_t T = 15;
static const uint32_t C = 0xEFC60000;
static const uint32_t L = 18;
static const uint32_t MASK_LOWER = (1UL << R) - 1;
static const uint32_t MASK_UPPER = (1UL << R);
uint32_t mt[N];
uint16_t index;
public:
/*! \brief Constructor
*
* \param seed initial value (seed) for the pseudorandom number generator.
*/
explicit Random(uint32_t seed);
/*! \brief Get the next (pseudo)random number.
* \return some number
*/
uint32_t number();
};

17
kernel/utils/size.h Normal file
View File

@@ -0,0 +1,17 @@
/*! \file
* \brief Template function to determine the length of an array
*/
#pragma once
#include "../types.h"
/* \brief Helper to retrieve the number of elements in an array
* (Warning: template magic)
* \param Array
* \return Number of elements
*/
template <class T, size_t N>
constexpr size_t size(T (& /*unused*/)[N]) {
return N;
}

30
kernel/utils/sort.h Normal file
View File

@@ -0,0 +1,30 @@
#pragma once
template <typename T>
void arraysort(T *array, int size, int (*comp)(T *a, T *b)) {
// this is shellsort
static const int gaps[] = {3548, 1577, 701, 301, 132, 57, 23, 10, 4, 1};
static const int gapsize = 10;
for (int g = 0; g < gapsize; ++g) {
const int gap = gaps[g];
for (int i = gap; i < size; i += 1) {
T tmp = array[i];
int j;
for (j = i; (j >= gap) && (comp(array + j - gap, &tmp) > 0);
j -= gap)
array[j] = array[j - gap];
array[j] = tmp;
}
}
}
template <typename T>
bool arraysort_check(T *array, int size, int (*comp)(T *a, T *b)) {
for (int i = 0; i < size - 1; ++i) {
if (comp(array + i, array + i + 1) > 0) {
return false;
}
}
return true;
}

117
kernel/utils/string.cc Normal file
View File

@@ -0,0 +1,117 @@
#include "string.h"
extern "C" char *strchrnul(const char *s, int c) {
if (s != nullptr) {
while (*s != '\0') {
if (*s == c) {
break;
}
s++;
}
}
return const_cast<char *>(s);
}
extern "C" char *strchr(const char *s, int c) {
if (s != nullptr) {
s = strchrnul(s, c);
if (*s == c) {
return const_cast<char *>(s);
}
}
return nullptr;
}
extern "C" int strcmp(const char *s1, const char *s2) {
if (s1 == nullptr || s2 == nullptr) {
return 0;
}
while (*s1 == *s2++) {
if (*s1++ == '\0') {
return 0;
}
}
return static_cast<int>(*s1) - static_cast<int>(*(s2 - 1));
}
extern "C" int strncmp(const char *s1, const char *s2, size_t n) {
if (s1 != nullptr && s2 != nullptr) {
for (size_t i = 0; i < n; i++) {
if (s1[i] != s2[i]) {
return static_cast<int>(s1[i]) - static_cast<int>(s2[i]);
} else if (s1[i] == '\0') {
break;
}
}
}
return 0;
}
extern "C" size_t strlen(const char *s) {
size_t len = 0;
if (s != nullptr) {
while (*s++ != '\0') {
len++;
}
}
return len;
}
extern "C" char *strcpy(char *dest, const char *src) { // NOLINT
char *r = dest;
if (dest != nullptr && src != nullptr) {
while ((*dest++ = *src++) != '\0') {
}
}
return r;
}
extern "C" char *strncpy(char *dest, const char *src, size_t n) {
char *r = dest;
if (dest != nullptr && src != nullptr) {
while ((n--) != 0 && (*dest++ = *src++) != '\0') {
}
}
return r;
}
extern "C" void *memcpy(void *__restrict__ dest, void const *__restrict__ src,
size_t size) {
uint8_t *destination = reinterpret_cast<uint8_t *>(dest);
uint8_t const *source = (uint8_t const *)src;
for (size_t i = 0; i != size; ++i) {
destination[i] = source[i];
}
return dest;
}
extern "C" void *memmove(void *dest, void const *src, size_t size) {
uint8_t *destination = reinterpret_cast<uint8_t *>(dest);
uint8_t const *source = reinterpret_cast<uint8_t const *>(src);
if (source > destination) {
for (size_t i = 0; i != size; ++i) {
destination[i] = source[i];
}
} else {
for (size_t i = size; i != 0; --i) {
destination[i - 1] = source[i - 1];
}
}
return dest;
}
extern "C" void *memset(void *dest, int pattern, size_t size) {
uint8_t *destination = reinterpret_cast<uint8_t *>(dest);
for (size_t i = 0; i != size; ++i) {
destination[i] = static_cast<uint8_t>(pattern);
}
return dest;
}

108
kernel/utils/string.h Normal file
View File

@@ -0,0 +1,108 @@
/*! \file
* \brief General purpose \ref string "String functions"
*/
#pragma once
#include "types.h"
/*! \defgroup string String function
* \brief String functions as provided by `%string.h` in the C standard library
*/
/*! \brief Find the first occurrence of a character in a string
* \ingroup string
* \param s string to
* \param c character to find
* \return Pointer to first occurrence of the character
* or to null byte at the end of the string if not found
*/
extern "C" char *strchrnul(const char *s, int c);
/*! \brief Find the first occurrence of a character in a string
* \ingroup string
* \param s string to
* \param c character to find
* \return Pointer to first occurrence of the character
* or to nullptr if not found
*/
extern "C" char *strchr(const char *s, int c);
/*! \brief Compare two strings
* \ingroup string
* \param s1 first string
* \param s2 second string
* \return an integer less than, equal to, or greater than zero if first string
* is found, respectively, to be less than, to match, or be greater than second
* string
*/
extern "C" int strcmp(const char *s1, const char *s2);
/*! \brief Compare two strings
* \ingroup string
* \param s1 first string
* \param s2 second string
* \param n number of bytes to compare
* \return an integer less than, equal to, or greater than zero if the given
* number of bytes of the first string are found, respectively, to be less than,
* to match, or be greater than second string
*/
extern "C" int strncmp(const char *s1, const char *s2, size_t n);
/*! \brief Calculate the length of a string
* \ingroup string
* \param s pointer to a string
* \return number of bytes in the string
*/
extern "C" size_t strlen(const char *s);
/*! \brief Copy the contents of a string
* including the terminating null byte (`\0`)
* \ingroup string
* \param dest destination string buffer
* \param src source string buffer
* \return a pointer to the destination string buffer
* \note Beware of buffer overruns!
*/
extern "C" char *strcpy(char *dest, const char *src); // NOLINT
/*! \brief Copy the contents of a string up to a maximum length
* or the terminating null byte (`\0`), whatever comes first.
* \ingroup string
* \param dest destination string buffer
* \param src source string buffer
* \param n maximum number of bytes to copy
* \return a pointer to the destination string buffer
* \note If there is no null byte (`\0`) among the first `n` bytes, the
* destination will not be null-terminated!
*/
extern "C" char *strncpy(char *dest, const char *src, size_t n);
/*! \brief Copy a memory area
* \ingroup string
* \param dest destination buffer
* \param src source buffer
* \param size number of bytes to copy
* \return pointer to destination
* \note The memory must not overlap!
*/
extern "C" void *memcpy(void *__restrict__ dest, void const *__restrict__ src,
size_t size);
/*! \brief Copy a memory area
* while the source may overlap with the destination
* \ingroup string
* \param dest destination buffer
* \param src source buffer
* \param size number of bytes to copy
* \return pointer to destination
*/
extern "C" void *memmove(void *dest, void const *src, size_t size);
/*! \brief Fill a memory area with a pattern
* \ingroup string
* \param dest destination buffer
* \param pattern single byte pattern
* \param size number of bytes to fill with pattern
* \return pointer to destination
*/
extern "C" void *memset(void *dest, int pattern, size_t size);