liblash

Basic tools written and used by lash in c programming.
Log | Files | Refs

commit a09362ba95ef5581dc5fcc05384d61ed3f662c15
Author: lash <dev@holbrook.no>
Date:   Mon, 15 Apr 2024 18:12:37 +0100

Initial commit

Diffstat:
A.gitignore | 3+++
AMakefile | 12++++++++++++
Asrc/Makefile | 23+++++++++++++++++++++++
Asrc/endian.c | 48++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/endian.h | 48++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/strip.c | 21+++++++++++++++++++++
Asrc/strip.h | 6++++++
Asrc/tests/Makefile | 20++++++++++++++++++++
Asrc/tests/test_endian.c | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tests/test_strip.c | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10 files changed, 303 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,3 @@ +*.o +*.testbin +*.so diff --git a/Makefile b/Makefile @@ -0,0 +1,12 @@ +all: src + +src: + make -C src + +test: src + make -C src test + +clean: + make -C src clean + +.PHONY: clean diff --git a/src/Makefile b/src/Makefile @@ -0,0 +1,23 @@ +OBJS := $(patsubst %.c,%.o,$(wildcard *.c)) +CFLAGS += -Wall -Werror + +all: $(OBJS) + +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + make -C tests clean + rm -vf *.o + +test: all + make -C tests test + + +shared: strip.so.o endian.so.o + $(CC) $(CFLAGS) -c strip.c -o strip.so.o -fpic + $(CC) $(CFLAGS) -c endian.c -o endian.so.o -fpic + $(CC) $(CFLAGS) -shared -o liblash.so $^ + + +.PHONY: clean diff --git a/src/endian.c b/src/endian.c @@ -0,0 +1,48 @@ +#include "endian.h" + +int is_le() { + unsigned short s = 42; + return *((unsigned char*)&s) == 42; +} + + +void flip_endian(int l, void *v) { + int i; + char t; + char *ne; + char *p; + + p = (char*)v; + ne = p+(l-1); + for (i = 0; i < l/2; i++) { + t = *(p+i); + *(p+i) = *(ne-i); + *(ne-i) = t; + } +} + +// convert unsigned integer to little-endian representation +int to_endian(char direction, int l, void *n) { + union le un; + + if (l == 1 || is_le() == direction) { + return 0; + } + switch(l) { + case sizeof(long long): + un.ll = (long long*)n; + break; + case sizeof(int): + un.i = (int*)n; + break; + case sizeof(short): + un.s = (short*)n; + break; + default: + return 1; + } + flip_endian(l, un.c); + + return 0; +} + diff --git a/src/endian.h b/src/endian.h @@ -0,0 +1,48 @@ +#ifndef LASH_ENDIAN_H_ +#define LASH_ENDIAN_H_ + +#define TO_ENDIAN_BIG 0 +#define TO_ENDIAN_LITTLE 1 + +/** + * + * \brief Encapsulats all suppoerted integer lengths for endian conversion. + * + */ +union le { + short *s; + int *i; + long long *ll; + unsigned char *c; +}; + +//int le(int l, void *n); +/* + * Return true (1) if system is little-endian. + */ +int is_le(); +/** + * Convert to specified endian order. + * + * The integer data in \c n is changed in-place. + * + * If \c direction is same as system endianness, or \c l==1, no action is taken. + * + * \param direction 0 for big-endian, 1 for little-endian. + * \param l Length of integer \c n in bytes. + * \param n Integer data. + * \return 1 if \c l is invalid byte size, 0 (success) otherwise. + * + */ +int to_endian(char direction, int l, void *n); +/** + * Change endian order of given number. + * + * The integer data in \c n is changed in-place. + * + * \param l Length of integer \c in bytes. + * \param v Integer data + */ +void flip_endian(int l, void *v); + +#endif // LASH_ENDIAN_H_ diff --git a/src/strip.c b/src/strip.c @@ -0,0 +1,21 @@ +#include <stddef.h> + + +char* zerostrip_be(char *value, size_t *len) { + int i; + char *p; + + p = value; + for (i = 0; i < *len; i++) { + if (*p & 0xff) { + break; + } + p++; + } + *len -= i; + if (!*len) { + *len = 1; + p--; + } + return p; +} diff --git a/src/strip.h b/src/strip.h @@ -0,0 +1,6 @@ +#ifndef LASH_BYTES_H_ +#define LASH_BYTES_H_ + +char* zerostrip_be(char *value, size_t *len); + +#endif diff --git a/src/tests/Makefile b/src/tests/Makefile @@ -0,0 +1,20 @@ +TESTS := $(patsubst %.c,%.testbin,$(wildcard *.c)) +LINKOBJS := $(wildcard ../*.o) +INCLUDES := -I.. +CFLAGS += $(INCLUDES) -g3 -Wall + +all: $(TESTS) + +%.testbin: %.c + $(CC) $(CFLAGS) $< -o $@ $(LINKOBJS) + ./$@ + +#test_run: $(wildcard out_*) +# for f in $^; do ./$$f; done + +test: all + +clean: + rm -vf *.testbin + +.PHONY: clean diff --git a/src/tests/test_endian.c b/src/tests/test_endian.c @@ -0,0 +1,62 @@ +#include <string.h> +#include <stdio.h> + +#include "endian.h" + + +int main() { + int r; + int i; + char left[] = { 0x02, 0x13, 0x24, 0x35}; + char right[] = { 0x35, 0x24, 0x13, 0x02}; + unsigned char tmp[4]; + + memcpy(tmp, left, 4); + + // four byte flip + flip_endian(4, tmp); + for (i = 0; i < 4; i++) { + if (tmp[i] != *(right+i)) { + return 1; + } + } + + // two byte flip + memcpy(tmp, left, 2); + flip_endian(2, tmp); + for (i = 0; i < 4; i++) { + if (tmp[i] != *(right+2+i)) { + return 1; + } + } + + // single byte flip + tmp[0] = 0x2a; + flip_endian(1, tmp); + tmp[0] = 0x2a; + + + // check explicit endian convert + if (is_le()) { + memcpy(tmp, left, 4); + } else { + memcpy(tmp, right, 4); + } + r = to_endian(0, 4, (void*)tmp); + if (r) { + return 1; + } + for (i = 0; i < 4; i++) { + if (tmp[i] != *(right+i)) { + return 1; + } + } + + // check invalid length + r = to_endian(0, 3, (void*)tmp); + if (!r) { + return 1; + } + + return 0; +} diff --git a/src/tests/test_strip.c b/src/tests/test_strip.c @@ -0,0 +1,60 @@ +#include <stddef.h> +#include <stdio.h> + +#include "strip.h" + +int main() { + size_t l = 4; + char be_int_semi[4] = {0x00, 0x00, 0x02, 0x9f}; + char be_int_full[4] = {0x40, 0x00, 0x02, 0x9f}; + char be_int_zero[4] = {0x00, 0x00, 0x00, 0x00}; + char be_int_mini[1] = {0x2a}; + char be_int_mini_zero[1] = {0x00}; + char *r; + + r = zerostrip_be((char*)be_int_semi, &l); + if (l != 2) { + return 1; + } + if (*r != 0x02) { + return 1; + } + + l = 4; + r = zerostrip_be((char*)be_int_full, &l); + if (l != 4) { + return 1; + } + if (*r != 0x40) { + return 1; + } + + l = 4; + r = zerostrip_be((char*)be_int_zero, &l); + if (l != 1) { + return 1; + } + if (*r != 0x00) { + return 1; + } + + l = 1; + r = zerostrip_be((char*)be_int_mini, &l); + if (l != 1) { + return 1; + } + if (*r != 0x2a) { + return 1; + } + + l = 1; + r = zerostrip_be((char*)be_int_mini_zero, &l); + if (l != 1) { + return 1; + } + if (*r != 0x00) { + return 1; + } + + return 0; +}