Add startings of new kernel-side library
Lainlib is libk. It is separate from Helix, which will become the 3D engine common to the kernel and the userspace.
This commit is contained in:
parent
61dbcc0dec
commit
a915465fc1
327
chroma/inc/lainlib/compression/lzg.h
Normal file
327
chroma/inc/lainlib/compression/lzg.h
Normal file
|
@ -0,0 +1,327 @@
|
||||||
|
/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of liblzg.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2018 Marcus Geelnard
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LIBLZG_H_
|
||||||
|
#define _LIBLZG_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LZG_VERSION "1.0.10" /**< @brief LZG library version string */
|
||||||
|
#define LZG_VERNUM 0x0100000a /**< @brief LZG library version number (strictly
|
||||||
|
incremental) */
|
||||||
|
#define LZG_VER_MAJOR 1 /**< @brief LZG library major version */
|
||||||
|
#define LZG_VER_MINOR 0 /**< @brief LZG library minor version */
|
||||||
|
#define LZG_VER_REVISION 10 /**< @brief LZG library revision */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @mainpage
|
||||||
|
*
|
||||||
|
* @section intro_sec Introduction
|
||||||
|
*
|
||||||
|
* liblzg is a minimal implementation of an LZ77 class compression library. The
|
||||||
|
* main characteristic of the library is that the decoding routine is very
|
||||||
|
* simple, fast and requires no extra memory (except for the encoded and decoded
|
||||||
|
* data buffers).
|
||||||
|
*
|
||||||
|
* @section funcs_sec Functions
|
||||||
|
*
|
||||||
|
* @li LZG_MaxEncodedSize() - Determine the maximum size of the encoded data for
|
||||||
|
* a given uncompressed buffer (worst case).
|
||||||
|
* @li LZG_InitEncoderConfig() - Set default encoder configuration.
|
||||||
|
* @li LZG_Encode() - Encode uncompressed data as LZG coded data.
|
||||||
|
* @li LZG_EncodeFull() - Same as LZG_Encode(), but using custom memory
|
||||||
|
* allocation.
|
||||||
|
* @li LZG_WorkMemSize() - Determine the amount of memory required for encoding
|
||||||
|
* (useful for LZG_EncodeFull()).
|
||||||
|
*
|
||||||
|
* @li LZG_DecodedSize() - Determine the size of the decoded data for a given
|
||||||
|
* LZG coded buffer.
|
||||||
|
* @li LZG_Decode() - Decode LZG coded data.
|
||||||
|
*
|
||||||
|
* @li LZG_Version() - Get the version of the LZG library.
|
||||||
|
* @li LZG_VersionString() - Get the version of the LZG library.
|
||||||
|
*
|
||||||
|
* @section compr_sec Compression
|
||||||
|
* Here is a simple example of compressing an uncompressed data buffer (given
|
||||||
|
* as buf/bufSize).
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* unsigned char *encBuf;
|
||||||
|
* lzg_uint32_t encSize, maxEncSize;
|
||||||
|
*
|
||||||
|
* // Determine maximum size of compressed data
|
||||||
|
* maxEncSize = LZG_MaxEncodedSize(bufSize);
|
||||||
|
*
|
||||||
|
* // Allocate memory for the compressed data
|
||||||
|
* encBuf = (unsigned char*) malloc(maxEncSize);
|
||||||
|
* if (encBuf)
|
||||||
|
* {
|
||||||
|
* // Compress
|
||||||
|
* encSize = LZG_Encode(buf, bufSize, encBuf, maxEncSize, NULL);
|
||||||
|
* if (encSize)
|
||||||
|
* {
|
||||||
|
* // Compressed data is now in encBuf, use it...
|
||||||
|
* // ...
|
||||||
|
* }
|
||||||
|
* else
|
||||||
|
* fprintf(stderr, "Compression failed!\n");
|
||||||
|
*
|
||||||
|
* // Free memory when we're done with the compressed data
|
||||||
|
* free(encBuf);
|
||||||
|
* }
|
||||||
|
* else
|
||||||
|
* fprintf(stderr, "Out of memory!\n");
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* @section decompr_sec Decompression
|
||||||
|
* Here is a simple example of decompressing a compressed data buffer (given
|
||||||
|
* as buf/bufSize).
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* unsigned char *decBuf;
|
||||||
|
* lzg_uint32_t decSize;
|
||||||
|
*
|
||||||
|
* // Determine size of decompressed data
|
||||||
|
* decSize = LZG_DecodedSize(buf, bufSize);
|
||||||
|
* if (decSize)
|
||||||
|
* {
|
||||||
|
* // Allocate memory for the decompressed data
|
||||||
|
* decBuf = (unsigned char*) malloc(decSize);
|
||||||
|
* if (decBuf)
|
||||||
|
* {
|
||||||
|
* // Decompress
|
||||||
|
* decSize = LZG_Decode(buf, bufSize, decBuf, decSize);
|
||||||
|
* if (decSize)
|
||||||
|
* {
|
||||||
|
* // Uncompressed data is now in decBuf, use it...
|
||||||
|
* // ...
|
||||||
|
* }
|
||||||
|
* else
|
||||||
|
* printf("Decompression failed (bad data)!\n");
|
||||||
|
*
|
||||||
|
* // Free memory when we're done with the decompressed data
|
||||||
|
* free(decBuf);
|
||||||
|
* }
|
||||||
|
* else
|
||||||
|
* printf("Out of memory!\n");
|
||||||
|
* }
|
||||||
|
* else
|
||||||
|
* printf("Bad input data!\n");
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Basic types */
|
||||||
|
typedef int lzg_bool_t; /**< @brief Boolean (@ref LZG_TRUE/@ref LZG_FALSE) */
|
||||||
|
typedef int lzg_int32_t; /**< @brief Signed 32-bit integer */
|
||||||
|
typedef unsigned int lzg_uint32_t; /**< @brief Unsigned 32-bit integer */
|
||||||
|
|
||||||
|
#define LZG_FALSE 0 /**< @brief Boolean FALSE (see @ref lzg_bool_t) */
|
||||||
|
#define LZG_TRUE 1 /**< @brief Boolean TRUE (see @ref lzg_bool_t) */
|
||||||
|
|
||||||
|
/* Compression levels */
|
||||||
|
#define LZG_LEVEL_1 1 /**< @brief Lowest/fastest compression level */
|
||||||
|
#define LZG_LEVEL_2 2 /**< @brief Compression level 2 */
|
||||||
|
#define LZG_LEVEL_3 3 /**< @brief Compression level 3 */
|
||||||
|
#define LZG_LEVEL_4 4 /**< @brief Compression level 4 */
|
||||||
|
#define LZG_LEVEL_5 5 /**< @brief Medium compression level */
|
||||||
|
#define LZG_LEVEL_6 6 /**< @brief Compression level 6 */
|
||||||
|
#define LZG_LEVEL_7 7 /**< @brief Compression level 7 */
|
||||||
|
#define LZG_LEVEL_8 8 /**< @brief Compression level 8 */
|
||||||
|
#define LZG_LEVEL_9 9 /**< @brief Best/slowest compression level */
|
||||||
|
|
||||||
|
/** @brief Default compression level */
|
||||||
|
#define LZG_LEVEL_DEFAULT LZG_LEVEL_5
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Progress callback function.
|
||||||
|
* @param[in] progress The current progress (0-100).
|
||||||
|
* @param[in] userdata User supplied data pointer.
|
||||||
|
*/
|
||||||
|
typedef void (*LZGPROGRESSFUN)(lzg_int32_t progress, void *userdata);
|
||||||
|
|
||||||
|
/** @brief LZG compression configuration parameters.
|
||||||
|
*
|
||||||
|
* This structure is used for passing configuration options to the LZG_Encode()
|
||||||
|
* function. Initialize this structure to default values with
|
||||||
|
* @ref LZG_InitEncoderConfig().
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
/** @brief Compression level (1-9).
|
||||||
|
|
||||||
|
For convenience, you can use the predefined constants
|
||||||
|
@ref LZG_LEVEL_1 (fast) to @ref LZG_LEVEL_9 (slow), or
|
||||||
|
@ref LZG_LEVEL_DEFAULT.
|
||||||
|
|
||||||
|
Default value: LZG_LEVEL_DEFAULT */
|
||||||
|
lzg_int32_t level;
|
||||||
|
|
||||||
|
/** @brief Use fast method (LZG_FALSE or LZG_TRUE).
|
||||||
|
|
||||||
|
Boolean flag that specifies whether or not to use a faster encoding
|
||||||
|
acceleration data structure, which requires more memory. When using the
|
||||||
|
fast method, the compression ratio is usually slightly improved.
|
||||||
|
|
||||||
|
Default value: LZG_TRUE */
|
||||||
|
lzg_bool_t fast;
|
||||||
|
|
||||||
|
/** @brief Encoding progress callback function.
|
||||||
|
|
||||||
|
This function will be called during compression to report progress
|
||||||
|
back to the caller (set this to NULL to disable progress
|
||||||
|
callback).
|
||||||
|
|
||||||
|
Default value: NULL */
|
||||||
|
LZGPROGRESSFUN progressfun;
|
||||||
|
|
||||||
|
/** @brief User data pointer for the progress callback function.
|
||||||
|
|
||||||
|
A user defined data pointer that can point to anything that the
|
||||||
|
progress callback function may need, such as an object reference
|
||||||
|
(this can set to NULL if the callback function does not need it).
|
||||||
|
|
||||||
|
Default value: NULL */
|
||||||
|
void *userdata;
|
||||||
|
} lzg_encoder_config_t;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine the maximum size of the encoded data for a given uncompressed
|
||||||
|
* buffer.
|
||||||
|
* @param[in] insize Size of the uncompressed buffer (number of bytes).
|
||||||
|
* @return Worst case (maximum) size of the encoded data.
|
||||||
|
*/
|
||||||
|
lzg_uint32_t LZG_MaxEncodedSize(lzg_uint32_t insize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize an encoder configuration object.
|
||||||
|
* @param[out] config Configuration object.
|
||||||
|
*/
|
||||||
|
void LZG_InitEncoderConfig(lzg_encoder_config_t *config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine the amount of memory required for encoding.
|
||||||
|
* @param[in] config Compression configuration (if set to NULL, default encoder
|
||||||
|
* configuration parameters are used).
|
||||||
|
* @retrun The size of the buffer required.
|
||||||
|
*/
|
||||||
|
lzg_uint32_t LZG_WorkMemSize(lzg_encoder_config_t *config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode uncompressed data using the LZG coder (i.e. compress the data).
|
||||||
|
* @param[in] in Input (uncompressed) buffer.
|
||||||
|
* @param[in] insize Size of the input buffer (number of bytes).
|
||||||
|
* @param[out] out Output (compressed) buffer.
|
||||||
|
* @param[in] outsize Size of the output buffer (number of bytes).
|
||||||
|
* @param[in] config Compression configuration (if set to NULL, default encoder
|
||||||
|
* configuration parameters are used).
|
||||||
|
* @return The size of the encoded data, or zero if the function failed
|
||||||
|
* (e.g. if the end of the output buffer was reached before the
|
||||||
|
* entire input buffer was encoded).
|
||||||
|
* @note For the slow method (config->fast = 0), the memory requirement during
|
||||||
|
* compression is 136 KB (LZG_LEVEL_1) to 2 MB (LZG_LEVEL_9). For the fast
|
||||||
|
* method (config->fast = 1), the memory requirement is 64 MB (LZG_LEVEL_1) to
|
||||||
|
* 66 MB (LZG_LEVEL_9). Also note that these figures are doubled on 64-bit
|
||||||
|
* systems.
|
||||||
|
*/
|
||||||
|
lzg_uint32_t LZG_Encode(const unsigned char *in, lzg_uint32_t insize,
|
||||||
|
unsigned char *out, lzg_uint32_t outsize,
|
||||||
|
lzg_encoder_config_t *config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode uncompressed data using the LZG coder (i.e. compress the data).
|
||||||
|
* @param[in] in Input (uncompressed) buffer.
|
||||||
|
* @param[in] insize Size of the input buffer (number of bytes).
|
||||||
|
* @param[out] out Output (compressed) buffer.
|
||||||
|
* @param[in] outsize Size of the output buffer (number of bytes).
|
||||||
|
* @param[in] config Compression configuration (if set to NULL, default encoder
|
||||||
|
* configuration parameters are used).
|
||||||
|
* @param[in] workmem Buffer to be used for compression, or NULL. See
|
||||||
|
* @ref LZG_WorkMemSize.
|
||||||
|
* @return The size of the encoded data, or zero if the function failed
|
||||||
|
* (e.g. if the end of the output buffer was reached before the
|
||||||
|
* entire input buffer was encoded).
|
||||||
|
* @note For the slow method (config->fast = 0), the memory requirement during
|
||||||
|
* compression is 136 KB (LZG_LEVEL_1) to 2 MB (LZG_LEVEL_9). For the fast
|
||||||
|
* method (config->fast = 1), the memory requirement is 64 MB (LZG_LEVEL_1) to
|
||||||
|
* 66 MB (LZG_LEVEL_9). Also note that these figures are doubled on 64-bit
|
||||||
|
* systems.
|
||||||
|
*/
|
||||||
|
lzg_uint32_t LZG_EncodeFull(const unsigned char *in, lzg_uint32_t insize,
|
||||||
|
unsigned char *out, lzg_uint32_t outsize,
|
||||||
|
lzg_encoder_config_t *config,
|
||||||
|
void *workmem);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine the size of the decoded data for a given LZG coded buffer.
|
||||||
|
* @param[in] in Input (compressed) buffer.
|
||||||
|
* @param[in] insize Size of the input buffer (number of bytes). This does
|
||||||
|
* not have to be the size of the entire compressed data, but
|
||||||
|
* it has to be at least 7 bytes (the first few bytes of the
|
||||||
|
* header, including the decompression size).
|
||||||
|
* @return The size of the decoded data, or zero if the function failed
|
||||||
|
* (e.g. if the magic header ID could not be found).
|
||||||
|
*/
|
||||||
|
lzg_uint32_t LZG_DecodedSize(const unsigned char *in, lzg_uint32_t insize);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode LZG coded data.
|
||||||
|
* @param[in] in Input (compressed) buffer.
|
||||||
|
* @param[in] insize Size of the input buffer (number of bytes).
|
||||||
|
* @param[out] out Output (uncompressed) buffer.
|
||||||
|
* @param[in] outsize Size of the output buffer (number of bytes).
|
||||||
|
* @return The size of the decoded data, or zero if the function failed
|
||||||
|
* (e.g. if the end of the output buffer was reached before the
|
||||||
|
* entire input buffer was decoded).
|
||||||
|
*/
|
||||||
|
lzg_uint32_t LZG_Decode(const unsigned char *in, lzg_uint32_t insize,
|
||||||
|
unsigned char *out, lzg_uint32_t outsize);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the version of the LZG library.
|
||||||
|
* @return The version of the LZG library, on the same format as
|
||||||
|
* @ref LZG_VERNUM.
|
||||||
|
*/
|
||||||
|
lzg_uint32_t LZG_Version(void);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the version string of the LZG library.
|
||||||
|
* @return The version of the LZG library, on the same format as
|
||||||
|
* @ref LZG_VERSION.
|
||||||
|
*/
|
||||||
|
const char* LZG_VersionString(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // _LIBLZG_H_
|
25
chroma/inc/lainlib/lainlib.h
Normal file
25
chroma/inc/lainlib/lainlib.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/************************
|
||||||
|
*** Team Kitty, 2020 ***
|
||||||
|
*** Chroma ***
|
||||||
|
***********************/
|
||||||
|
|
||||||
|
|
||||||
|
/* Defines all of the temporary library functions.
|
||||||
|
* All of this must be moved into the Chroma stdlib.
|
||||||
|
* They exist here as guidance, and as utility for the kernel itself.
|
||||||
|
* If need be, they can also be moved into a trimmed-down "kernel libc" or "libk".
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <lainlib/vector/vector.h>
|
||||||
|
|
||||||
|
#include <lainlib/list/list.h>
|
||||||
|
|
||||||
|
#include <lainlib/mutex/spinlock.h>
|
||||||
|
#include <lainlib/mutex/ticketlock.h>
|
||||||
|
|
||||||
|
#include <lainlib/compression/lzg.h>
|
34
chroma/inc/lainlib/list/list.h
Normal file
34
chroma/inc/lainlib/list/list.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef struct list_entry {
|
||||||
|
struct list_entry* Previous;
|
||||||
|
struct list_entry* Next;
|
||||||
|
} list_entry_t;
|
||||||
|
|
||||||
|
#define UNSAFE_CAST(ptr, type, member) \
|
||||||
|
((type*)((char*)(ptr) - (char*)offsetof(type, member)))
|
||||||
|
|
||||||
|
#define LISTNEW(var) \
|
||||||
|
((list_entry_t){ 0, 0 })
|
||||||
|
|
||||||
|
void ListAdd(list_entry_t* Head, list_entry_t* New);
|
||||||
|
|
||||||
|
void ListEmplaceBack(list_entry_t* Head, list_entry_t* Tail);
|
||||||
|
|
||||||
|
void ListRemove(list_entry_t* List);
|
||||||
|
|
||||||
|
bool ListIsEmpty(list_entry_t* Head);
|
||||||
|
|
||||||
|
#define LISTNEXT(current, member) \
|
||||||
|
UNSAFE_CAST((current)->member.next, typeof(*(current)), member);
|
||||||
|
|
||||||
|
#define LISTPREV(current, member) \
|
||||||
|
UNSAFE_CAST((current)->member.prev, typeof(*(curent)), member)
|
||||||
|
|
||||||
|
#define LISTFOREACH(pos, head) \
|
||||||
|
for (pos = (head)->next; pos != (head); pos = pos->next)
|
||||||
|
|
||||||
|
#define LISTFOREACHENTRY(pos, head, member) \
|
||||||
|
for(pos = UNSAFE_CAST((head)->next, typeof(*(pos)), member); &pos->member != (head); pos = LISTNEXT(pos, member))
|
||||||
|
|
||||||
|
#define LASTENTRY 0
|
22
chroma/inc/lainlib/mutex/spinlock.h
Normal file
22
chroma/inc/lainlib/mutex/spinlock.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/************************
|
||||||
|
*** Team Kitty, 2020 ***
|
||||||
|
*** Chroma ***
|
||||||
|
***********************/
|
||||||
|
|
||||||
|
|
||||||
|
typedef volatile int spinlock_t;
|
||||||
|
|
||||||
|
/* A set of macros that acquire and release a mutex spinlock. */
|
||||||
|
//TODO: this *needs* to be moved to a kernel header.
|
||||||
|
|
||||||
|
#define SPINLOCK(name) \
|
||||||
|
while( !__sync_bool_compare_and_swap(name, 0, 1)); \
|
||||||
|
__sync_synchronize();
|
||||||
|
|
||||||
|
|
||||||
|
#define SPUNLOCK(name) \
|
||||||
|
__sync_synchronize(); \
|
||||||
|
name = 0;
|
||||||
|
|
32
chroma/inc/lainlib/mutex/ticketlock.h
Normal file
32
chroma/inc/lainlib/mutex/ticketlock.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#pragma once
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdatomic.h>
|
||||||
|
|
||||||
|
/************************
|
||||||
|
*** Team Kitty, 2020 ***
|
||||||
|
*** Chroma ***
|
||||||
|
***********************/
|
||||||
|
|
||||||
|
/* This file provides a simple implementation of a ticket-based locking system.
|
||||||
|
* You should probably prefer Spinlock over Ticketlock.
|
||||||
|
*
|
||||||
|
* Create a new lock with NEW_TICKETLOCK(),
|
||||||
|
* lock a resource with TicketLock().
|
||||||
|
*
|
||||||
|
* Use TicketUnlock() to free the resource after you are done.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
atomic_size_t NowServing;
|
||||||
|
atomic_size_t NextTicket;
|
||||||
|
} ticketlock_t;
|
||||||
|
|
||||||
|
#define NEW_TICKETLOCK() (ticketlock_t{0})
|
||||||
|
|
||||||
|
void TicketLock(ticketlock_t* Lock);
|
||||||
|
|
||||||
|
bool TicketAttemptLock(ticketlock_t* Lock);
|
||||||
|
|
||||||
|
void TicketUnlock(ticketlock_t* Lock);
|
||||||
|
|
30
chroma/inc/lainlib/vector/vector.h
Normal file
30
chroma/inc/lainlib/vector/vector.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/************************
|
||||||
|
*** Team Kitty, 2020 ***
|
||||||
|
*** Chroma ***
|
||||||
|
***********************/
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include<stddef.h>
|
||||||
|
#include<stdint.h>
|
||||||
|
#include <lainlib/mutex/spinlock.h>
|
||||||
|
|
||||||
|
struct vector_t {
|
||||||
|
void** items;
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
spinlock_t vector_lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
int VectorRemoveItem(struct vector_t* vec, void* item);
|
||||||
|
|
||||||
|
int VectorRemove(struct vector_t* vec, size_t index);
|
||||||
|
|
||||||
|
void* VectorGet(struct vector_t* vec, size_t index);
|
||||||
|
|
||||||
|
int VectorInsert(struct vector_t* vec, void* item, size_t index);
|
||||||
|
|
||||||
|
int VectorAppend(struct vector_t* vec, void* item);
|
||||||
|
|
||||||
|
int VectorDestroy(struct vector_t* vec);
|
190
chroma/lainlib/compression/lzgmini.c
Normal file
190
chroma/lainlib/compression/lzgmini.c
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of liblzg.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Marcus Geelnard
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <lainlib/lainlib.h>
|
||||||
|
|
||||||
|
/*-- PRIVATE -----------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Internal definitions */
|
||||||
|
#define LZG_HEADER_SIZE 16
|
||||||
|
#define LZG_METHOD_COPY 0
|
||||||
|
#define LZG_METHOD_LZG1 1
|
||||||
|
|
||||||
|
/* Endian and alignment independent reader for 32-bit integers */
|
||||||
|
#define _LZG_GetUINT32(in, offs) \
|
||||||
|
((((lzg_uint32_t)in[offs]) << 24) | \
|
||||||
|
(((lzg_uint32_t)in[offs+1]) << 16) | \
|
||||||
|
(((lzg_uint32_t)in[offs+2]) << 8) | \
|
||||||
|
((lzg_uint32_t)in[offs+3]))
|
||||||
|
|
||||||
|
/* Calculate the checksum */
|
||||||
|
static lzg_uint32_t _LZG_CalcChecksum(const unsigned char *data, lzg_uint32_t size)
|
||||||
|
{
|
||||||
|
unsigned short a = 1, b = 0;
|
||||||
|
unsigned char *end = (unsigned char *)data + size;
|
||||||
|
while (data != end)
|
||||||
|
{
|
||||||
|
a += *data++;
|
||||||
|
b += a;
|
||||||
|
}
|
||||||
|
return (((lzg_uint32_t)b) << 16) | a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LUT for decoding the copy length parameter */
|
||||||
|
static const unsigned char _LZG_LENGTH_DECODE_LUT[32] = {
|
||||||
|
2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,
|
||||||
|
18,19,20,21,22,23,24,25,26,27,28,29,35,48,72,128
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*-- PUBLIC ------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
lzg_uint32_t LZG_DecodedSize(const unsigned char *in, lzg_uint32_t insize)
|
||||||
|
{
|
||||||
|
/* Check header */
|
||||||
|
if ((insize < 7) || (in[0] != 'L') || (in[1] != 'Z') || (in[2] != 'G'))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Get output buffer size */
|
||||||
|
return _LZG_GetUINT32(in, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
lzg_uint32_t LZG_Decode(const unsigned char *in, lzg_uint32_t insize,
|
||||||
|
unsigned char *out, lzg_uint32_t outsize)
|
||||||
|
{
|
||||||
|
unsigned char *src, *inEnd, *dst, *outEnd, *copy, symbol, b, b2;
|
||||||
|
unsigned char m1, m2, m3, m4, method;
|
||||||
|
lzg_uint32_t i, length, offset, encodedSize, decodedSize, checksum;
|
||||||
|
|
||||||
|
/* Check magic ID */
|
||||||
|
if ((insize < LZG_HEADER_SIZE) || (in[0] != 'L') || (in[1] != 'Z') || (in[2] != 'G'))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Get header data */
|
||||||
|
decodedSize = _LZG_GetUINT32(in, 3);
|
||||||
|
encodedSize = _LZG_GetUINT32(in, 7);
|
||||||
|
checksum = _LZG_GetUINT32(in, 11);
|
||||||
|
|
||||||
|
/* Check sizes */
|
||||||
|
if ((outsize < decodedSize) || (encodedSize != (insize - LZG_HEADER_SIZE)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Check checksum */
|
||||||
|
if (_LZG_CalcChecksum(&in[LZG_HEADER_SIZE], encodedSize) != checksum)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Initialize the byte streams */
|
||||||
|
src = (unsigned char *)in + LZG_HEADER_SIZE;;
|
||||||
|
inEnd = ((unsigned char *)in) + insize;
|
||||||
|
dst = out;
|
||||||
|
outEnd = out + outsize;
|
||||||
|
|
||||||
|
/* Check which method to use */
|
||||||
|
method = in[15];
|
||||||
|
if (method == LZG_METHOD_LZG1)
|
||||||
|
{
|
||||||
|
if (!((src + 4) <= inEnd)) return 0;
|
||||||
|
m1 = *src++; m2 = *src++; m3 = *src++; m4 = *src++;
|
||||||
|
|
||||||
|
/* Main decompression loop */
|
||||||
|
while (src < inEnd)
|
||||||
|
{
|
||||||
|
symbol = *src++;
|
||||||
|
|
||||||
|
if ((symbol != m1) && (symbol != m2) && (symbol != m3) && (symbol != m4))
|
||||||
|
{
|
||||||
|
/* Literal copy */
|
||||||
|
if (!(dst < outEnd)) return 0;
|
||||||
|
*dst++ = symbol;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Decode offset / length parameters */
|
||||||
|
if (!(src < inEnd)) return 0;
|
||||||
|
if ((b = *src++))
|
||||||
|
{
|
||||||
|
if (symbol == m1)
|
||||||
|
{
|
||||||
|
/* Distant copy */
|
||||||
|
if (!((src + 2) <= inEnd)) return 0;
|
||||||
|
length = _LZG_LENGTH_DECODE_LUT[b & 0x1f];
|
||||||
|
b2 = *src++;
|
||||||
|
offset = (((unsigned int)(b & 0xe0)) << 11) |
|
||||||
|
(((unsigned int)b2) << 8) |
|
||||||
|
(*src++);
|
||||||
|
offset += 2056;
|
||||||
|
}
|
||||||
|
else if (symbol == m2)
|
||||||
|
{
|
||||||
|
/* Medium copy */
|
||||||
|
if (!(src < inEnd)) return 0;
|
||||||
|
length = _LZG_LENGTH_DECODE_LUT[b & 0x1f];
|
||||||
|
b2 = *src++;
|
||||||
|
offset = (((unsigned int)(b & 0xe0)) << 3) | b2;
|
||||||
|
offset += 8;
|
||||||
|
}
|
||||||
|
else if (symbol == m3)
|
||||||
|
{
|
||||||
|
/* Short copy */
|
||||||
|
length = (b >> 6) + 3;
|
||||||
|
offset = (b & 0x3f) + 8;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Near copy (including RLE) */
|
||||||
|
length = _LZG_LENGTH_DECODE_LUT[b & 0x1f];
|
||||||
|
offset = (b >> 5) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the corresponding data from the history window */
|
||||||
|
copy = dst - offset;
|
||||||
|
if (!((copy >= out) && ((dst + length) <= outEnd))) return 0;
|
||||||
|
for (i = 0; i < length; ++i)
|
||||||
|
*dst++ = *copy++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Literal copy (single occurance of a marker symbol) */
|
||||||
|
if (!(dst < outEnd)) return 0;
|
||||||
|
*dst++ = symbol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (method == LZG_METHOD_COPY)
|
||||||
|
{
|
||||||
|
/* Plain copy */
|
||||||
|
while ((src < inEnd) && (dst < outEnd))
|
||||||
|
*dst++ = *src++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All OK? */
|
||||||
|
if ((unsigned int)(dst - out) != decodedSize)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return decodedSize;
|
||||||
|
}
|
27
chroma/lainlib/list/basic_list.c
Normal file
27
chroma/lainlib/list/basic_list.c
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#include <lainlib/list/list.h>
|
||||||
|
|
||||||
|
void ListAdd(list_entry_t* Head, list_entry_t* New) {
|
||||||
|
New->Next = Head->Next;
|
||||||
|
New->Previous = Head;
|
||||||
|
New->Next->Previous = New;
|
||||||
|
Head->Next = New;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListEmplaceBack(list_entry_t* Head, list_entry_t* New) {
|
||||||
|
New->Next = Head;
|
||||||
|
New->Previous = Head->Previous;
|
||||||
|
New->Previous->Next = New;
|
||||||
|
Head->Previous = New;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListRemove(list_entry_t* Entry) {
|
||||||
|
Entry->Next->Previous = Entry->Previous;
|
||||||
|
Entry->Previous->Next = Entry->Next;
|
||||||
|
|
||||||
|
Entry->Previous = (void*)0xDEADull;
|
||||||
|
Entry->Next = (void*)0xBEEFull;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ListIsEmpty(list_entry_t* Head) {
|
||||||
|
return Head->Next == Head;
|
||||||
|
}
|
21
chroma/lainlib/mutex/ticketlock.c
Normal file
21
chroma/lainlib/mutex/ticketlock.c
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#include <kernel/chroma.h>
|
||||||
|
#include <lainlib/lainlib.h>
|
||||||
|
|
||||||
|
void TicketLock(ticketlock_t* Lock) {
|
||||||
|
size_t Ticket = atomic_fetch_add_explicit(&Lock->NextTicket, 1, memory_order_relaxed);
|
||||||
|
|
||||||
|
while(atomic_load_explicit(&Lock->NowServing, memory_order_acquire) != Ticket) {
|
||||||
|
PAUSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TicketAttemptLock(ticketlock_t* Lock) {
|
||||||
|
size_t Ticket = atomic_load_explicit(&Lock->NowServing, memory_order_relaxed);
|
||||||
|
|
||||||
|
return atomic_compare_exchange_strong_explicit(&Lock->NowServing, &Ticket, Ticket + 1, memory_order_acquire, memory_order_relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TicketUnlock(ticketlock_t* Lock) {
|
||||||
|
size_t NextTicket = atomic_load_explicit(&Lock->NowServing, memory_order_relaxed) + 1;
|
||||||
|
atomic_store_explicit(&Lock->NowServing, NextTicket, memory_order_release);
|
||||||
|
}
|
68
chroma/lainlib/vector.c
Normal file
68
chroma/lainlib/vector.c
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
#include <templib/templib.h>
|
||||||
|
|
||||||
|
/************************
|
||||||
|
*** Team Kitty, 2020 ***
|
||||||
|
*** Chroma ***
|
||||||
|
***********************/
|
||||||
|
|
||||||
|
/* This file provides a Chroma implementation of std::vector, a C++ standard library class.
|
||||||
|
* It has a lot of work left to be done, but it's usable for its intended function (Graphics)
|
||||||
|
*/
|
||||||
|
|
||||||
|
int VectorRemoveItem(struct vector_t* vec, void* item) {
|
||||||
|
//TODO
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int VectorRemove(struct vector_t* vec, size_t index) {
|
||||||
|
|
||||||
|
if (!vec) return 0;
|
||||||
|
|
||||||
|
//TODO: Vector spinlock
|
||||||
|
// AcqSpinlock(&vec->lock);
|
||||||
|
|
||||||
|
if((index + 1) > vec->n) return 0;
|
||||||
|
|
||||||
|
vec->items[index] = NULL;
|
||||||
|
|
||||||
|
for (int i = 0; i < vec->n; i++) {
|
||||||
|
vec->items[i] = vec->items[i + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: vector reallocate
|
||||||
|
// realloc(vec->items, vec->n - 1);
|
||||||
|
|
||||||
|
vec->n--;
|
||||||
|
|
||||||
|
// ReleaseSpinlock(&vec->lock);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void* VectorGet(struct vector_t* vec, size_t index) {
|
||||||
|
|
||||||
|
if(!vec) return 0;
|
||||||
|
|
||||||
|
//TODO: Vector spinlock
|
||||||
|
// AcqSpinlock(&vec->lock);
|
||||||
|
|
||||||
|
if((index + 1) > vec->n) return NULL;
|
||||||
|
|
||||||
|
// ReleaseSpinlock(&vec->lock);
|
||||||
|
return vec->items[index];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int VectorInsert(struct vector_t* vec, void* item, size_t index) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int VectorAppend(struct vector_t* vec, void* item) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int VectorDestroy(struct vector_t* vec) {
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user