mirror of
https://github.com/utkumaden/libmx.git
synced 2025-01-22 21:46:33 +01:00
Initial commit.
This commit is contained in:
commit
1c75c9d7c5
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
**/.vs*
|
||||
**/.atom
|
3
README.md
Normal file
3
README.md
Normal file
@ -0,0 +1,3 @@
|
||||
libmx
|
||||
======
|
||||
libmx is a collection of libraries for my personal use in my C projects.
|
12
include/mx/assert.h
Normal file
12
include/mx/assert.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef _MX_ASSERT_H_
|
||||
#define _MX_ASSERT_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include <mx/base.h>
|
||||
|
||||
#define MX_ASSERT(cond, msg) assert((cond) && ""msg)
|
||||
#define MX_ASSERT_PTR(ptr, message) assert((ptr) && ""message)
|
||||
#define MX_ASSERT_SELFPTR(ptr) MX_ASSERT_PTR(ptr, "Instance pointer "#ptr" must be valid.")
|
||||
#define MX_ASSERT_OOM(ptr) MX_ASSERT_PTR(ptr, "Out of memory.")
|
||||
|
||||
#endif
|
12
include/mx/base.h
Normal file
12
include/mx/base.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef _MX_BASE_H_
|
||||
#define _MX_BASE_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define MX_API
|
||||
#define MX_IMPL
|
||||
#define MX_INLINE inline static
|
||||
|
||||
#endif
|
40
include/mx/digest.h
Normal file
40
include/mx/digest.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef _MX_DIGEST_H_
|
||||
#define _MX_DIGEST_H_
|
||||
|
||||
#include <mx/base.h>
|
||||
|
||||
/**
|
||||
* @brief Common function pointer function for all mx digest functions.
|
||||
* @param[out] digest The digest result.
|
||||
* @param[in] src The source buffer.
|
||||
* @param[in] length The length of the buffer.
|
||||
*/
|
||||
typedef void (*mx_digest_function)(void *digest, const char *src, size_t length);
|
||||
|
||||
typedef uint32_t adler32_t; /**< The adler32 hash.*/
|
||||
typedef uint32_t fvn0_t; /**< The FVN-0 hash. */
|
||||
typedef uint32_t fvn1_t; /**< The FVN-1 hash. */
|
||||
typedef uint32_t fvn1a_t; /**< The FVN-1a hash. */
|
||||
|
||||
// typedef uint16_t crc16_t; /**< CRC16-CCIT checksum. */
|
||||
// typedef uint32_t crc32_t; /**< CRC32-IEEE checksum. */
|
||||
// typedef uint8_t md5sum_t[8]; /**< MD5SUM checksum. */
|
||||
// typedef uint8_t sha0_t [8]; /**< SHA0 checksum. */
|
||||
// typedef uint8_t sha128_t[8]; /**< SHA128 checksum. */
|
||||
// typedef uint8_t sha256_t[8]; /**< SHA256 checksum. */
|
||||
|
||||
MX_API void mx_adler32(adler32_t *digest, const char *src, size_t length);
|
||||
MX_API void mx_fvn0 (fvn0_t *digest, const char *src, size_t length);
|
||||
MX_API void mx_fvn1 (fvn1_t *digest, const char *src, size_t length);
|
||||
MX_API void mx_fvn1a (fvn1a_t *digest, const char *src, size_t length);
|
||||
|
||||
// MX_API void mx_crc16 (crc16_t *digest, const char *src, size_t length);
|
||||
// MX_API void mx_crc32 (crc32_t *digest, const char *src, size_t length);
|
||||
// MX_API void mx_md5sum (md5sum_t *digest, const char *src, size_t length);
|
||||
// MX_API void mx_sha0 (sha0_t *digest, const char *src, size_t length);
|
||||
// MX_API void mx_sha128 (sha128_t *digest, const char *src, size_t length);
|
||||
// MX_API void mx_sha256 (sha256_t *digest, const char *src, size_t length);
|
||||
|
||||
MX_API int mx_compare_digest(const void* a, const void *b, size_t size);
|
||||
|
||||
#endif
|
169
include/mx/options.h
Normal file
169
include/mx/options.h
Normal file
@ -0,0 +1,169 @@
|
||||
#ifndef _MX_GETOPTS_H_
|
||||
#define _MX_GETOPTS_H_
|
||||
|
||||
/**
|
||||
* @file options.h MX Library Options Parser
|
||||
* This is a very basic options parser built into my applications. It does what
|
||||
* getopts.h does on GNU except it's a whole lot less bloated. Simple is the
|
||||
* best.
|
||||
*
|
||||
* It works in two modes, pointer to structure mode and static mode. Static mode
|
||||
* works like the old unsafe, not thread safe, not reentrant strtok and familiar
|
||||
* static functions. Pointer mode allows you to pass the structure itself.
|
||||
* Pointer mode functions are postfixed with `_r`.
|
||||
*
|
||||
* @example mx_options_static Static Mode Usage.
|
||||
* @code{c}
|
||||
* #include <stdio.h>
|
||||
* #include <mx/options.h>
|
||||
*
|
||||
* int main(int argc, char** argv)
|
||||
* {
|
||||
* mx_optkind_t kind;
|
||||
* mx_options_begin(MX_OPT_DEFAULT, argc, argv);
|
||||
* while (kind = mx_options_next())
|
||||
* {
|
||||
* switch (kind)
|
||||
* {
|
||||
* case MX_OPTION_PAIR:
|
||||
* printf("key:%s value:%s\n", mx_option_key, mx_option_value);
|
||||
* break;
|
||||
* default:
|
||||
* printf("key:%s\n", mx_option_key);
|
||||
* break;
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @example mx_options_pointer Pointer Mode Usage
|
||||
* @code{c}
|
||||
* #include <stdio.h>
|
||||
* #include <mx/options.h>
|
||||
*
|
||||
* int main(int argc, char** argv)
|
||||
* {
|
||||
* mx_options_t opt;
|
||||
* mx_optkind_t kind;
|
||||
* mx_options_begin_r(&opt, MX_OPT_DEFAULT, argc, argv);
|
||||
* while (kind = mx_options_next_r(&opt))
|
||||
* {
|
||||
* switch (kind)
|
||||
* {
|
||||
* case MX_OPTION_PAIR:
|
||||
* printf("key:%s value:%s\n", opt.key, opt.value);
|
||||
* break;
|
||||
* default:
|
||||
* printf("key:%s\n", opt.key);
|
||||
* break;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* mx_options_end_r(&opt); // Free any resources allocated.
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
#include <mx/base.h>
|
||||
|
||||
/**
|
||||
* Option kind.
|
||||
*/
|
||||
typedef enum mx_optkind_t
|
||||
{
|
||||
MX_OPT_END, /**< End iterator. */
|
||||
MX_OPT_POSITIONAL, /**< Positional. */
|
||||
MX_OPT_SHORT, /**< (UNIX ONLY) Short flag(s). */
|
||||
MX_OPT_LONG, /**< Long flag. */
|
||||
MX_OPT_PAIR, /**< Key with value.*/
|
||||
MX_OPT_DASH, /**< (UNIX ONLY) A single dash. */
|
||||
MX_OPT_DDASH, /**< (UNIX ONLY) A double dash. */
|
||||
} mx_optkind_t;
|
||||
|
||||
/**
|
||||
* Option parse flags.
|
||||
*/
|
||||
typedef enum mx_optflag_t
|
||||
{
|
||||
MX_OPT_UNIX = 1 << 0, /**< Parse UNIX style options. [-h, --help, --include=a]*/
|
||||
MX_OPT_DOS = 1 << 1, /**< Parse DOS style options. [/?, /help, /include:a] */
|
||||
/** Default option style is both. */
|
||||
MX_OPT_DEFAULT = MX_OPT_UNIX | MX_OPT_DOS,
|
||||
} mx_optflag_t;
|
||||
|
||||
/**
|
||||
* Option parse storage struct.
|
||||
*/
|
||||
typedef struct mx_options_t
|
||||
{
|
||||
int argc; /**< Number of arguments. */
|
||||
const char **argv; /**< Array of arguments. */
|
||||
mx_optflag_t flags; /**< Parse flags. */
|
||||
int i; /**< Internal iterator. */
|
||||
mx_optkind_t kind; /**< Last option kind. */
|
||||
const char *key; /**< Last key. */
|
||||
const char *value; /**< Last value. */
|
||||
} mx_options_t;
|
||||
|
||||
/**
|
||||
* Begin parsing options with structure.
|
||||
* @param[in] self Storage.
|
||||
* @param[in] flags Parse flags.
|
||||
* @param[in] argc Number of arguments.
|
||||
* @param[in] argv Array of arguments.
|
||||
*/
|
||||
MX_API void mx_options_begin_r(mx_options_t *self, mx_optflag_t flags, int argc, const char **argv);
|
||||
|
||||
/**
|
||||
* Next token.
|
||||
* @param[in] self Storage.
|
||||
* @returns Option kind.
|
||||
*/
|
||||
MX_API mx_optkind_t mx_options_next_r(mx_options_t *self);
|
||||
|
||||
/**
|
||||
* Stop using the parser.
|
||||
* @param[in] self Storage.
|
||||
*/
|
||||
MX_API void mx_options_end_r(mx_options_t *self);
|
||||
|
||||
/**
|
||||
* Internal function that returns a pointer to a static options struct.
|
||||
*/
|
||||
MX_INLINE mx_options_t* __mx_options_ptr()
|
||||
{
|
||||
static mx_options_t opts = { };
|
||||
return &opts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin parsing options.
|
||||
* @param[in] flags Parse flags.
|
||||
* @param[in] argc Number of arguments.
|
||||
* @param[in] argv Array of arguments.
|
||||
*/
|
||||
MX_INLINE void mx_options_begin(mx_optflag_t flags, int argc, char **argv)
|
||||
{
|
||||
mx_options_begin_r(__mx_options_ptr(), flags, argc, argv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Next token.
|
||||
* @returns Option kind.
|
||||
*/
|
||||
MX_INLINE mx_optkind_t mx_options_next()
|
||||
{
|
||||
return mx_options_next_r(__mx_options_ptr());
|
||||
}
|
||||
|
||||
/**
|
||||
* Current option value.
|
||||
*/
|
||||
#define mx_option_key (__mx_options_ptr()->key)
|
||||
|
||||
/**
|
||||
* Current option key.
|
||||
*/
|
||||
#define mx_option_value (__mx_options_ptr()->value)
|
||||
|
||||
#endif
|
57
src/digest.c
Normal file
57
src/digest.c
Normal file
@ -0,0 +1,57 @@
|
||||
#include <mx/digest.h>
|
||||
#include <string.h>
|
||||
|
||||
const uint32_t FVN_BASIS = 0x811c9dc5;
|
||||
const uint32_t FVN_PRIME = 0x01000193;
|
||||
|
||||
MX_IMPL int mx_compare_digest(const void* a, const void *b, size_t size)
|
||||
{
|
||||
return memcmp(a, b, size);
|
||||
}
|
||||
|
||||
MX_IMPL void mx_adler32(adler32_t *digest, const char *src, size_t length)
|
||||
{
|
||||
const uint32_t modulo = 65521;
|
||||
uint32_t a = 1, b = 0;
|
||||
|
||||
while (length--)
|
||||
{
|
||||
a = (a + *(src++)) % modulo;
|
||||
b = (a + b) % modulo;
|
||||
}
|
||||
|
||||
return (b << 16) | (a << 0);
|
||||
}
|
||||
|
||||
MX_IMPL void mx_fvn0(fvn0_t *digest, const char *src, size_t length)
|
||||
{
|
||||
*digest = 0;
|
||||
|
||||
for (size_t i = 0; i < length; i++)
|
||||
{
|
||||
*digest *= FVN_PRIME;
|
||||
*digest ^= (fvn0_t)src[i];
|
||||
}
|
||||
}
|
||||
|
||||
MX_IMPL void mx_fvn1(fvn1_t *digest, const char *src, size_t length)
|
||||
{
|
||||
*digest = FVN_BASIS;
|
||||
|
||||
for (size_t i = 0; i < length; i++)
|
||||
{
|
||||
*digest *= FVN_PRIME;
|
||||
*digest ^= src[i];
|
||||
}
|
||||
}
|
||||
|
||||
MX_IMPL void mx_fvn1a(fvn1a_t *digest, const char *src, size_t length)
|
||||
{
|
||||
*digest = FVN_BASIS;
|
||||
|
||||
for (size_t i = 0; i < length; i++)
|
||||
{
|
||||
*digest ^= src[i];
|
||||
*digest *= FVN_PRIME;
|
||||
}
|
||||
}
|
178
src/options.c
Normal file
178
src/options.c
Normal file
@ -0,0 +1,178 @@
|
||||
#include <mx/options.h>
|
||||
#include <mx/assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
MX_INLINE char* mx_strdup(const char **pptr, char *nstr, size_t len)
|
||||
{
|
||||
if (len == 0)
|
||||
len = strlen(nstr);
|
||||
|
||||
char *ptr = realloc(*pptr, len + 1);
|
||||
MX_ASSERT_OOM(ptr);
|
||||
|
||||
memcpy(ptr, nstr, len);
|
||||
ptr[len] = '\0';
|
||||
|
||||
return (*pptr = ptr);
|
||||
}
|
||||
|
||||
MX_IMPL void mx_options_begin_r(mx_options_t *self, mx_optflag_t flags, int argc, const char **argv)
|
||||
{
|
||||
MX_ASSERT_SELFPTR(self);
|
||||
MX_ASSERT_PTR(argv, "Argument array must be non-null.");
|
||||
MX_ASSERT(argc > 0, "Arguments count must be greater than zero.");
|
||||
|
||||
self->flags = flags;
|
||||
self->argc = argv;
|
||||
self->argc = argc;
|
||||
self->i = 0;
|
||||
self->kind = MX_OPT_END;
|
||||
self->key = NULL;
|
||||
self->value = NULL;
|
||||
}
|
||||
|
||||
MX_IMPL mx_optkind_t mx_options_next_r(mx_options_t *self)
|
||||
{
|
||||
MX_ASSERT_SELFPTR(self);
|
||||
|
||||
if (self->i >= self->argc)
|
||||
{
|
||||
return (self->kind = MX_OPT_END);
|
||||
}
|
||||
|
||||
char *current = self->argv[self->i];
|
||||
char *next = (self->i + 1 < self->argc) ? self->argv[self->i + 1] : NULL;
|
||||
size_t clen = strlen(current);
|
||||
|
||||
if ((self->flags & MX_OPT_UNIX) && current[0] == '-')
|
||||
{
|
||||
/* - indicates a UNIX flag sequence. */
|
||||
|
||||
if (current[1] == '-')
|
||||
{
|
||||
if (current[2] == '\0')
|
||||
{
|
||||
/* -- */
|
||||
self->i++;
|
||||
return (self->kind = MX_OPT_DDASH);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* --long-flag or --key=pair*/
|
||||
|
||||
char *equals = strchr(current, '=');
|
||||
|
||||
if (equals)
|
||||
{
|
||||
/* The equals is in this token. */
|
||||
size_t len = (size_t)(equals - ¤t[2]);
|
||||
mx_strdup(&self->key, ¤t[2], len);
|
||||
|
||||
if (equals[1] == '\0')
|
||||
{
|
||||
/* The value is in the next token. */
|
||||
next = next ? next : "";
|
||||
mx_strdup(&self->value, next, 0);
|
||||
|
||||
self->i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The value is also in this token.*/
|
||||
mx_strdup(&self->value, &equals[1], 0);
|
||||
}
|
||||
|
||||
self->i++;
|
||||
return (self->kind = MX_OPT_PAIR);
|
||||
}
|
||||
else if (next && next[0] == '=')
|
||||
{
|
||||
/* The equals is in the next token. */
|
||||
mx_strdup(&self->key, ¤t[2], clen-2);
|
||||
mx_strdup(&self->value, &next[1], 0);
|
||||
|
||||
self->i += 2;
|
||||
return (self->kind = MX_OPT_PAIR);
|
||||
}
|
||||
|
||||
/* Don't treat this as a key pair. It's a long flag.*/
|
||||
mx_strdup(&self->key, current, clen-2);
|
||||
self->i++;
|
||||
return (self->kind = MX_OPT_LONG);
|
||||
}
|
||||
}
|
||||
else if (current[1] == '\0')
|
||||
{
|
||||
self->i++;
|
||||
return (self->kind = MX_OPT_DASH);
|
||||
}
|
||||
else
|
||||
{
|
||||
mx_strdup(&self->key,¤t[1], clen - 1);
|
||||
self->i++;
|
||||
return (self->kind = MX_OPT_SHORT);
|
||||
}
|
||||
}
|
||||
|
||||
if ((self->flags & MX_OPT_DOS) && current[0] == '/')
|
||||
{
|
||||
/* / indicated a DOS flag sequence. */
|
||||
|
||||
char *colon = strchr(current, ':');
|
||||
|
||||
if (colon)
|
||||
{
|
||||
/* The colon is in this token. */
|
||||
if (colon[1] == '\0')
|
||||
{
|
||||
/* The value is in the next token. */
|
||||
next = next ? next : "";
|
||||
mx_strdup(&self->value, next, 0);
|
||||
self->i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The value is in this token. */
|
||||
mx_strdup(&self->value, &colon[1], 0);
|
||||
}
|
||||
|
||||
self->i++;
|
||||
mx_strdup(&self->key, ¤t[1], (size_t)(colon-¤t[1]));
|
||||
return (self->kind = MX_OPT_PAIR);
|
||||
}
|
||||
else if (next && next[0]==':')
|
||||
{
|
||||
/* The colon is in the next token. */
|
||||
mx_strdup(&self->key, ¤t[1], clen-1);
|
||||
mx_strdup(&self->value, &next[1], 0);
|
||||
self->i+=2;
|
||||
return (self->kind = MX_OPT_PAIR);
|
||||
}
|
||||
else
|
||||
{
|
||||
self->i++;
|
||||
mx_strdup(&self->key, ¤t[1], clen - 1);
|
||||
return (self->kind = MX_OPT_LONG);
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise treate as a positional argument. */
|
||||
{
|
||||
char *ptr = realloc(self->value, clen);
|
||||
MX_ASSERT_OOM(ptr);
|
||||
|
||||
self->i++;
|
||||
self->value = memcpy(ptr, current, clen);
|
||||
return (self->kind = MX_OPT_POSITIONAL);
|
||||
}
|
||||
}
|
||||
|
||||
MX_IMPL void mx_options_end_r(mx_options_t *self)
|
||||
{
|
||||
if (self)
|
||||
{
|
||||
free(self->key);
|
||||
free(self->value);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user