mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2024-12-28 04:23:36 +01:00
Added a --extended-libc option and some headers to allow porting external programs.
This commit is contained in:
parent
765bb97ee7
commit
7a888fc90a
15 changed files with 412 additions and 58 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -18,3 +18,5 @@ gintdemo.g1a
|
|||
|
||||
# Configuration files
|
||||
gcc.cfg
|
||||
Makefile.cfg
|
||||
|
||||
|
|
15
Makefile
15
Makefile
|
@ -5,7 +5,7 @@
|
|||
#
|
||||
#---
|
||||
|
||||
|
||||
include Makefile.cfg
|
||||
|
||||
#---
|
||||
# Project variables.
|
||||
|
@ -48,7 +48,10 @@ obj-lib-spec = build/display_font_system.bmp.o
|
|||
obj-std-spec =
|
||||
|
||||
# Configuration files
|
||||
config = gcc.cfg
|
||||
config = gcc.cfg
|
||||
ifeq ($(wildcard $(config)),)
|
||||
$(error "Configuration files are missing. Did you ./configure ?")
|
||||
endif
|
||||
|
||||
# Target folder
|
||||
folder := $(shell fxsdk --folder)
|
||||
|
@ -127,16 +130,13 @@ endef
|
|||
all: $(config) $(target-std) $(target-lib) $(target-g1a)
|
||||
@ printf '\e[32;1mmsg \u00bb\e[0m All done!\n'
|
||||
|
||||
$(config):
|
||||
$(error "Configuration files are missing. Did you ./configure?")
|
||||
|
||||
build:
|
||||
$(if $(VERBOSE),,@ printf '\e[35;1mdir \u00bb\e[0m mkdir $@\n')
|
||||
$(if $(VERBOSE),,@) mkdir -p $@
|
||||
|
||||
$(obj-std) $(obj-lib) $(demo-obj): | build
|
||||
|
||||
$(target-std): $(config) $(obj-std)
|
||||
$(target-std): $(obj-std)
|
||||
$(if $(VERBOSE),,@ printf '\e[35;1mlib \u00bb\e[0m ar $@\n')
|
||||
$(if $(VERBOSE),,@) $(ar) rcs $@ $(obj-std)
|
||||
@ printf '\e[32;1mmsg \u00bb\e[0m Succesfully built libc ('
|
||||
|
@ -217,6 +217,9 @@ install: $(target-std) $(target-lib)
|
|||
install -m 644 -T demo/gintdemo.ld $(folder)/linker.ld
|
||||
mkdir -p $(folder)/gint
|
||||
install -m 644 include/*.h $(folder)/gint
|
||||
ifdef config_ext
|
||||
install -m 644 include/extended/*.h $(folder)/gint
|
||||
endif
|
||||
@ printf '\e[32;1mmsg \u00bb\e[0m All installed!\n'
|
||||
|
||||
install_demo:
|
||||
|
|
2
TODO
2
TODO
|
@ -12,6 +12,8 @@ Simple improvements:
|
|||
- core: Add VBR handlers debugging information (if possible)
|
||||
- events: Introduce KeyRepeat events
|
||||
- library: Implement C99's inttypes.h for Cake's UpdateExe
|
||||
- string: Use cmp/str to implement memchr() (assembler examples)
|
||||
- string: Do some tests for memcmp()
|
||||
Larger improvements:
|
||||
- errno: Introduce errno and use it more or less everywhere
|
||||
- bopti: Monochrome bitmaps blending modes
|
||||
|
|
50
configure
vendored
50
configure
vendored
|
@ -5,8 +5,16 @@ conf[ATEXIT_MAX]=16
|
|||
conf[RTC_CB_ARRAY_SIZE]=5
|
||||
conf[EVENTS_QUEUE_SIZE]=64
|
||||
conf[GINT_NO_SYSCALLS]=
|
||||
conf[GINT_EXTENDED_LIBC]=
|
||||
fail=false
|
||||
output="gcc.cfg"
|
||||
output_gcc="gcc.cfg"
|
||||
output_make="Makefile.cfg"
|
||||
|
||||
error="\e[31;1merror:\e[0m"
|
||||
Cr="$(tput setaf 1)$(tput bold)"
|
||||
Cg="$(tput setaf 2)$(tput bold)"
|
||||
Cp="$(tput setaf 5)$(tput setaf 62)$(tput bold)"
|
||||
C0="$(tput setaf 0)$(tput sgr 0)"
|
||||
|
||||
help()
|
||||
{
|
||||
|
@ -14,16 +22,19 @@ help()
|
|||
Configuration script for the gint library.
|
||||
|
||||
Options that affect the behavior of the library:
|
||||
--no-syscalls [default: false]
|
||||
$Cr--no-syscalls$C0 [default:$Cp false$C0]
|
||||
Never use syscalls. Expect some trouble with the malloc() function...
|
||||
Do not trigger this option unless you know what you are doing.
|
||||
Do not enable this option unless you know what you are doing.
|
||||
$Cr--extended-libc$C0 [default:$Cp false$C0]
|
||||
Enable specific C99 headers/features that are normally not required by
|
||||
calculator programs. May allow porting programs from other platforms.
|
||||
|
||||
Options that customize size limits:
|
||||
--atexit-max=<integer> [default: 16]
|
||||
$Cr--atexit-max=$C0$Cg<integer>$C0 [default:$Cp 16$C0]
|
||||
Number of exit handlers that can be registered by atexit().
|
||||
--rtc-callbacks=<integer> [default: 5]
|
||||
$Cr--rtc-callbacks=$C0$Cg<integer>$C0 [default:$Cp 5$C0]
|
||||
Number of RTC callbacks that can be registered.
|
||||
--events-queue-size=<integer> [default: 64]
|
||||
$Cr--events-queue-size=$C0$Cg<integer>$C0 [default:$Cp 64$C0]
|
||||
Number of events simultaneously stored in the event queue.
|
||||
EOF
|
||||
|
||||
|
@ -33,34 +44,36 @@ EOF
|
|||
for arg; do case "$arg" in
|
||||
-h | --help) help;;
|
||||
--no-syscalls) conf[GINT_NO_SYSCALLS]=true;;
|
||||
--extended-libc) conf[GINT_EXTENDED_LIBC]=true;;
|
||||
|
||||
--atexit-max=*)
|
||||
size=${arg#*=}
|
||||
if [[ $size == +([0-9]) ]]; then
|
||||
conf[ATEXIT_MAX]=$size
|
||||
else echo "error: --atexit-max expects an integer value"
|
||||
else echo -e "$error --atexit-max expects an integer value"
|
||||
fail=true; fi;;
|
||||
--rtc-callbacks=*)
|
||||
size=${arg#*=}
|
||||
if [[ $size == +([0-9]) ]]; then
|
||||
conf[RTC_CB_ARRAY_SIZE]=$size
|
||||
else echo "error: --rtc-callbacks expects an integer value"
|
||||
else echo -e "$error --rtc-callbacks expects an integer value"
|
||||
fail=true; fi;;
|
||||
--events-queue-size=*)
|
||||
size=${arg#*=}
|
||||
if [[ $size == +([0-9]) ]]; then
|
||||
conf[EVENTS_QUEUE_SIZE]=$size
|
||||
else echo "error: --events-queue-size expects an integer value"
|
||||
else echo -e "$error --events-queue-size expects an integer"\
|
||||
"value"
|
||||
fail=true; fi;;
|
||||
|
||||
--atexit-max | --rtc-callbacks | --events-queue-size)
|
||||
echo "error: syntax for $arg is $arg=<integer-value>";;
|
||||
echo -e "$error syntax for $arg is $arg=<integer-value>";;
|
||||
|
||||
*)
|
||||
echo "error: unrecognized argument '$arg'"; fail=true;;
|
||||
echo -e "$error unrecognized argument '$arg'"; fail=true;;
|
||||
esac; done
|
||||
|
||||
output_config()
|
||||
output_config_gcc()
|
||||
{
|
||||
echo "-D ATEXIT_MAX=${conf[ATEXIT_MAX]}"
|
||||
echo "-D RTC_CB_ARRAY_SIZE=${conf[RTC_CB_ARRAY_SIZE]}"
|
||||
|
@ -68,11 +81,20 @@ output_config()
|
|||
if [ "${conf[GINT_NO_SYSCALLS]}" != "" ]; then
|
||||
echo "-D GINT_NO_SYSCALLS"
|
||||
fi
|
||||
if [ "${conf[GINT_EXTENDED_LIBC]}" != "" ]; then
|
||||
echo "-D GINT_EXTENDED_LIBC"
|
||||
fi
|
||||
}
|
||||
|
||||
output_config_make()
|
||||
{
|
||||
[ "${conf[GINT_EXTENDED_LIBC]}" != "" ] && echo "config_ext=true"
|
||||
}
|
||||
|
||||
if $fail; then
|
||||
echo "Configuration has not been modified."
|
||||
else
|
||||
output_config > $output
|
||||
echo "Configuration details have been output to file $output."
|
||||
output_config_gcc > $output_gcc
|
||||
output_config_make > $output_make
|
||||
echo "Configuration saved in $output_gcc and $output_make."
|
||||
fi
|
||||
|
|
|
@ -9,27 +9,76 @@
|
|||
#ifndef _CTYPE_H
|
||||
#define _CTYPE_H 1
|
||||
|
||||
// Character definition macros.
|
||||
#define isalnum(c) (isdigit(c) || isalpha(c))
|
||||
#define isalpha(c) (islower(c) || isupper(c))
|
||||
#include <stdint.h>
|
||||
|
||||
#define iscntrl(c) ((c) <= 0x1f || (c) == 0x7f)
|
||||
#define isdigit(c) ((c) >= '0' && (c) <= '9')
|
||||
#define isgraph(c) ((c) > ' ' && (c) < 0x7f)
|
||||
#define islower(c) ((c) >= 'a' && (c) <= 'z')
|
||||
#define isprint(c) ((c) >= ' ' && (c) < 0x7f)
|
||||
#define ispunct(c) (((c) >= '!' && (c) <= '/') || \
|
||||
((c) >= ':' && (c) <= '@') || \
|
||||
((c) >= '[' && (c) <= '`') || \
|
||||
((c) >= '{' && (c) <= '~'))
|
||||
#define isspace(c) (((c) >= '\t' && (c) <= '\r') || (c) == ' ')
|
||||
#define isupper(c) ((c) >= 'A' && (c) <= 'Z')
|
||||
#define isxdigit(c) (((c) >= '0' && (c) <= '9') || \
|
||||
((c) >= 'A' && (c) <= 'F') || \
|
||||
((c) >= 'a' && (c) <= 'f'))
|
||||
//---
|
||||
// Character classes.
|
||||
//---
|
||||
|
||||
// Character manipulation macros.
|
||||
#define tolower(c) (isupper(c) ? (c) | 32 : (c))
|
||||
#define toupper(c) (islower(c) ? (c) & ~32 : (c))
|
||||
extern uint8_t ctype_classes[0x80];
|
||||
|
||||
__attribute__((always_inline)) static inline int isalnum(int c) {
|
||||
return ctype_classes[c] & 0xf0;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline int isalpha(int c) {
|
||||
return ctype_classes[c] & 0x30;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline int iscntrl(int c) {
|
||||
return ctype_classes[c] & 0x01;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline int isdigit(int c) {
|
||||
return ctype_classes[c] & 0x40;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline int isgraph(int c) {
|
||||
return ctype_classes[c] & 0xf4;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline int islower(int c) {
|
||||
return ctype_classes[c] & 0x10;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline int isprint(int c) {
|
||||
return ctype_classes[c] & 0x08;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline int ispunct(int c) {
|
||||
return ctype_classes[c] & 0x04;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline int isspace(int c) {
|
||||
return ctype_classes[c] & 0x02;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline int isupper(int c) {
|
||||
return ctype_classes[c] & 0x20;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline int isxdigit(int c) {
|
||||
return ctype_classes[c] & 0x80;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline int isascii(int c) {
|
||||
return (c >= 0 && c <= 0x7f);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline int isblank(int c) {
|
||||
return (c == '\t' || c == ' ');
|
||||
}
|
||||
|
||||
//---
|
||||
// Character manipulation.
|
||||
//---
|
||||
|
||||
__attribute__((always_inline)) static inline int tolower(int c) {
|
||||
return c | isupper(c);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline int toupper(int c) {
|
||||
return c & ~(islower(c) << 1);
|
||||
}
|
||||
|
||||
#endif // _CTYPE_H
|
||||
|
|
46
include/extended/endian.h
Normal file
46
include/extended/endian.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
#ifndef _ENDIAN_H
|
||||
#define _ENDIAN_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
//---
|
||||
// Assembler-optimized byte-ordering functions.
|
||||
//---
|
||||
|
||||
__attribute__((always_inline)) static inline uint16_t swap16(uint16_t word)
|
||||
{
|
||||
uint16_t result;
|
||||
__asm__("swap.b %1, %0": "=r"(result): "r"(word));
|
||||
return result;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t swap32(uint32_t longw)
|
||||
{
|
||||
uint32_t result;
|
||||
__asm__(
|
||||
"swap.b %1, r0 \n\t"
|
||||
"swap.w r0, r0 \n\t"
|
||||
"swap.b r0, %0 \n\t"
|
||||
: "=r"(result)
|
||||
: "r"(longw)
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Conversion of values of different endianness.
|
||||
//---
|
||||
|
||||
#define htobe16(host16) (host16)
|
||||
#define htole16(host16) (swap16(host16))
|
||||
#define be16toh(be16) (be16)
|
||||
#define le16toh(le16) (swap16(le16))
|
||||
|
||||
#define htobe32(host32) (host32)
|
||||
#define htole32(host32) (swap32(host32))
|
||||
#define be32toh(be32) (be32)
|
||||
#define le32toh(le32) (swap32(le32))
|
||||
|
||||
#endif // _ENDIAN_H
|
|
@ -17,18 +17,34 @@
|
|||
//---
|
||||
|
||||
/*
|
||||
memcpy() O(byte_number)
|
||||
memcpy() O(byte_count)
|
||||
Copies a memory area. The two areas must not overlap (if they do, use
|
||||
memmove()). A smart copy is performed when possible. To enhance
|
||||
performance, make sure than destination and source are both 4-aligned.
|
||||
*/
|
||||
void *memcpy(void *destination, const void *source, size_t byte_number);
|
||||
void *memcpy(void *destination, const void *source, size_t byte_count);
|
||||
|
||||
/*
|
||||
memset() O(byte_number)
|
||||
memset() O(byte_count)
|
||||
Sets the contents of a memory area. A smart copy is performed.
|
||||
*/
|
||||
void *memset(void *destination, int byte, size_t byte_number);
|
||||
void *memset(void *destination, int byte, size_t byte_count);
|
||||
|
||||
/*
|
||||
memchr() O(byte_count)
|
||||
Looks for a byte in a memory area. Returns the address of the first
|
||||
occurrence if found, NULL otherwise.
|
||||
*/
|
||||
void *memchr(const void *area, int byte, size_t byte_count);
|
||||
|
||||
/*
|
||||
memcmp() O(byte_count)
|
||||
Compares two memory areas. Returns 0 if all bytes are equal in both
|
||||
areas, a negative number if the first unequal byte is lower in the
|
||||
first area, and a positive number otherwise.
|
||||
A smart comparison is performed when possible.
|
||||
*/
|
||||
int memcmp(const void *area1, const void *area2, size_t byte_count);
|
||||
|
||||
|
||||
|
||||
|
@ -42,12 +58,25 @@ void *memset(void *destination, int byte, size_t byte_number);
|
|||
*/
|
||||
size_t strlen(const char *str);
|
||||
|
||||
/*
|
||||
strnlen() O(len(str))
|
||||
Returns the minimum of the length of the string and n. This function
|
||||
never access more than n bytes at the beginning of the string.
|
||||
*/
|
||||
size_t strnlen(const char *str, size_t n);
|
||||
|
||||
/*
|
||||
strcpy() O(len(source))
|
||||
Copies a string to another.
|
||||
*/
|
||||
char *strcpy(char *destination, const char *source);
|
||||
|
||||
/*
|
||||
strncpy() O(min(len(source), size))
|
||||
Copies part of a string to another.
|
||||
*/
|
||||
char *strncpy(char *destination, const char *source, size_t size);
|
||||
|
||||
/*
|
||||
strchr() O(len(str))
|
||||
Searches a character in a string.
|
||||
|
@ -55,9 +84,11 @@ char *strcpy(char *destination, const char *source);
|
|||
const char *strchr(const char *str, int value);
|
||||
|
||||
/*
|
||||
strncpy() O(min(len(source), size))
|
||||
Copies part of a string to another.
|
||||
strcmp() O(max(len(str1), len(str2)))
|
||||
Compares two strings. Returns 0 if they are identical, a negative
|
||||
number if the first unequal byte is lower in str1 than in str2, and a
|
||||
positive number otherwise.
|
||||
*/
|
||||
char *strncpy(char *destination, const char *source, size_t size);
|
||||
int strcmp(const char *str1, const char *str2);
|
||||
|
||||
#endif // _STRING_H
|
||||
|
|
64
src/string/ctype.c
Normal file
64
src/string/ctype.c
Normal file
|
@ -0,0 +1,64 @@
|
|||
#include <ctype.h>
|
||||
|
||||
enum {
|
||||
cntrl = 0x01,
|
||||
space = 0x02,
|
||||
punct = 0x04,
|
||||
print = 0x08,
|
||||
upper = 0x20,
|
||||
lower = 0x10,
|
||||
digit = 0x40,
|
||||
xdigt = 0x80,
|
||||
};
|
||||
|
||||
uint8_t ctype_classes[0x80] = {
|
||||
// Control characters.
|
||||
cntrl, cntrl, cntrl, cntrl, cntrl, cntrl, cntrl, cntrl, cntrl,
|
||||
cntrl | space, // Tabulation
|
||||
cntrl | space, cntrl | space, cntrl | space, cntrl | space,
|
||||
cntrl, cntrl, cntrl, cntrl, cntrl, cntrl, cntrl, cntrl, cntrl, cntrl,
|
||||
cntrl, cntrl, cntrl, cntrl, cntrl, cntrl, cntrl, cntrl,
|
||||
|
||||
// Space and some punctuation.
|
||||
space | print,
|
||||
punct | print, punct | print, punct | print, punct | print,
|
||||
punct | print, punct | print, punct | print, punct | print,
|
||||
punct | print, punct | print, punct | print, punct | print,
|
||||
punct | print, punct | print, punct | print,
|
||||
|
||||
// Decimal digits.
|
||||
digit | xdigt | print, digit | xdigt | print, digit | xdigt | print,
|
||||
digit | xdigt | print, digit | xdigt | print, digit | xdigt | print,
|
||||
digit | xdigt | print, digit | xdigt | print, digit | xdigt | print,
|
||||
digit | xdigt | print,
|
||||
|
||||
// Some punctuation.
|
||||
punct | print, punct | print, punct | print, punct | print,
|
||||
punct | print, punct | print, punct | print,
|
||||
|
||||
// Uppercase alphabet.
|
||||
upper | xdigt | print, upper | xdigt | print, upper | xdigt | print,
|
||||
upper | xdigt | print, upper | xdigt | print, upper | xdigt | print,
|
||||
upper | print, upper | print, upper | print, upper | print,
|
||||
upper | print, upper | print, upper | print, upper | print,
|
||||
upper | print, upper | print, upper | print, upper | print,
|
||||
upper | print, upper | print, upper | print, upper | print,
|
||||
upper | print, upper | print, upper | print, upper | print,
|
||||
|
||||
// Other punctuation symbols.
|
||||
punct | print, punct | print, punct | print, punct | print,
|
||||
punct | print, punct | print,
|
||||
|
||||
// Lowercase alphabet.
|
||||
lower | xdigt | print, lower | xdigt | print, lower | xdigt | print,
|
||||
lower | xdigt | print, lower | xdigt | print, lower | xdigt | print,
|
||||
lower | print, lower | print, lower | print, lower | print,
|
||||
lower | print, lower | print, lower | print, lower | print,
|
||||
lower | print, lower | print, lower | print, lower | print,
|
||||
lower | print, lower | print, lower | print, lower | print,
|
||||
lower | print, lower | print, lower | print, lower | print,
|
||||
|
||||
// Last punctuation characters and DEL.
|
||||
punct | print, punct | print, punct | print, punct | print,
|
||||
cntrl
|
||||
};
|
20
src/string/memchr.c
Normal file
20
src/string/memchr.c
Normal file
|
@ -0,0 +1,20 @@
|
|||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
memchr() O(byte_count)
|
||||
Looks for a byte in a memory area. Returns the address of the first
|
||||
occurrence if found, NULL otherwise.
|
||||
*/
|
||||
void *memchr(const void *area, int byte, size_t byte_count)
|
||||
{
|
||||
const uint8_t *mem = area;
|
||||
|
||||
while(byte_count--)
|
||||
{
|
||||
if(*mem == byte) return (void *)mem;
|
||||
mem++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
84
src/string/memcmp.c
Normal file
84
src/string/memcmp.c
Normal file
|
@ -0,0 +1,84 @@
|
|||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
int raw_cmp(const uint8_t *mem1, const uint8_t *mem2, size_t byte_count);
|
||||
|
||||
/*
|
||||
memcmp() O(byte_count)
|
||||
Compares two memory areas. Returns 0 if all bytes are equal in both
|
||||
areas, a negative number if the first unequal byte is lower in the
|
||||
first area, and a positive number otherwise.
|
||||
A smart comparison is performed when possible.
|
||||
*/
|
||||
int memcmp(const void *area1, const void *area2, size_t byte_count)
|
||||
{
|
||||
const uint8_t *mem1 = (const uint8_t *)area1;
|
||||
const uint8_t *mem2 = (const uint8_t *)area2;
|
||||
|
||||
// Trying to do long-based comparisons.
|
||||
if(((intptr_t)area1 & 3) == ((intptr_t)area2 & 3))
|
||||
{
|
||||
// Getting to a 4-byte offset.
|
||||
while((intptr_t)mem1 & 3)
|
||||
{
|
||||
if(*mem1 != *mem2) return *mem1 - *mem2;
|
||||
mem1++, mem2++;
|
||||
byte_count--;
|
||||
}
|
||||
|
||||
// Testing groups of four bytes.
|
||||
while(byte_count >= 4)
|
||||
{
|
||||
uint32_t long1 = *((uint32_t *)mem1);
|
||||
uint32_t long2 = *((uint32_t *)mem2);
|
||||
if(long1 != long2) return raw_cmp(mem1, mem2, 4);
|
||||
mem1 += 4, mem2 += 4;
|
||||
byte_count -= 4;
|
||||
}
|
||||
|
||||
// Testing the last bytes.
|
||||
return raw_cmp(mem1, mem2, byte_count);
|
||||
}
|
||||
|
||||
// Well, maybe we can do a word-based operation?
|
||||
else if(((intptr_t)area1 & 1) == ((intptr_t)area2 & 3))
|
||||
{
|
||||
// Getting to the word offset.
|
||||
if((intptr_t)mem1 & 1)
|
||||
{
|
||||
if(*mem1 != *mem2) return *mem1 - *mem2;
|
||||
mem1++, mem2++;
|
||||
byte_count--;
|
||||
}
|
||||
|
||||
// Testing groups of two bytes.
|
||||
while(byte_count >= 2)
|
||||
{
|
||||
uint16_t word1 = *((uint16_t *)mem1);
|
||||
uint16_t word2 = *((uint16_t *)mem2);
|
||||
if(word1 != word2) return raw_cmp(mem1, mem2, 2);
|
||||
mem1 += 2, mem2 += 2;
|
||||
byte_count -= 2;
|
||||
}
|
||||
|
||||
// Testing the last byte.
|
||||
if(!byte_count) return 0;
|
||||
return *mem1 - *mem2;
|
||||
}
|
||||
|
||||
// That's too bad, we'll have to compare everything manually.
|
||||
else return raw_cmp(mem1, mem2, byte_count);
|
||||
}
|
||||
|
||||
int raw_cmp(const uint8_t *mem1, const uint8_t *mem2, size_t byte_count)
|
||||
{
|
||||
while(byte_count)
|
||||
{
|
||||
if(*mem1 != *mem2) return *mem1 - *mem2;
|
||||
mem1++;
|
||||
mem2++;
|
||||
byte_count--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
memcpy()
|
||||
memcpy() O(n)
|
||||
Copies a memory area. A smart copy is performed if possible.
|
||||
*/
|
||||
void *memcpy(void *d, const void *s, size_t n)
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
memset()
|
||||
memset() O(byte_count)
|
||||
Sets the contents of a memory area. A smart copy is performed.
|
||||
*/
|
||||
void *memset(void *d, int byte, size_t byte_number)
|
||||
void *memset(void *d, int byte, size_t byte_count)
|
||||
{
|
||||
uint8_t *dest = (uint8_t *)d;
|
||||
unsigned short word = (byte << 8) | byte;
|
||||
|
@ -13,12 +13,12 @@ void *memset(void *d, int byte, size_t byte_number)
|
|||
|
||||
// When the area is small, simply copying using byte operations. The
|
||||
// minimum length used for long operations must be at least 3.
|
||||
if(byte_number < 8)
|
||||
if(byte_count < 8)
|
||||
{
|
||||
while(byte_number)
|
||||
while(byte_count)
|
||||
{
|
||||
*dest++ = byte;
|
||||
byte_number--;
|
||||
byte_count--;
|
||||
}
|
||||
|
||||
return d;
|
||||
|
@ -28,20 +28,20 @@ void *memset(void *d, int byte, size_t byte_number)
|
|||
while((intptr_t)dest & 3)
|
||||
{
|
||||
*dest++ = byte;
|
||||
byte_number--;
|
||||
byte_count--;
|
||||
}
|
||||
// Copying using long operations.
|
||||
while(byte_number >= 4)
|
||||
while(byte_count >= 4)
|
||||
{
|
||||
*((uint32_t *)dest) = longword;
|
||||
dest += 4;
|
||||
byte_number -= 4;
|
||||
byte_count -= 4;
|
||||
}
|
||||
// Ending the copy.
|
||||
while(byte_number)
|
||||
while(byte_count)
|
||||
{
|
||||
*dest++ = byte;
|
||||
byte_number--;
|
||||
byte_count--;
|
||||
}
|
||||
|
||||
return d;
|
||||
|
|
18
src/string/strcmp.c
Normal file
18
src/string/strcmp.c
Normal file
|
@ -0,0 +1,18 @@
|
|||
#include <string.h>
|
||||
|
||||
/*
|
||||
strcmp() O(max(len(str1), len(str2)))
|
||||
Compares two strings. Returns 0 if they are identical, a negative
|
||||
number if the first unequal byte is lower in str1 than in str2, and a
|
||||
positive number otherwise.
|
||||
*/
|
||||
int strcmp(const char *str1, const char *str2)
|
||||
{
|
||||
while(*str1 && *str2 && *str1 == *str2)
|
||||
{
|
||||
str1++;
|
||||
str2++;
|
||||
}
|
||||
|
||||
return *str1 - *str2;
|
||||
}
|
13
src/string/strnlen.c
Normal file
13
src/string/strnlen.c
Normal file
|
@ -0,0 +1,13 @@
|
|||
#include <string.h>
|
||||
|
||||
/*
|
||||
strnlen() O(len(str))
|
||||
Returns the minimum of the length of the string and n. This function
|
||||
never access more than n bytes at the beginning of the string.
|
||||
*/
|
||||
size_t strnlen(const char *str, size_t n)
|
||||
{
|
||||
size_t len = 0;
|
||||
while(len < n && str[len]) len++;
|
||||
return len;
|
||||
}
|
Loading…
Reference in a new issue