diff --git a/Makefile b/Makefile index 031261c..a69e7cf 100644 --- a/Makefile +++ b/Makefile @@ -28,6 +28,7 @@ libasm_bonus.a : $(OBJS_DIR) $(OBJS) $(OBJS_BONUS) test: test.c libasm_bonus.a clang -z noexecstack test.c -L. -lasm_bonus -o test -g + ./test || echo -e "\033[31m tests exited with an error code" $(NAME): $(OBJS_DIR) $(OBJS) ar rcs $@ $(OBJS) diff --git a/srcs/bonus/ft_atoi_base.s b/srcs/bonus/ft_atoi_base.s index ef71c63..16f8718 100644 --- a/srcs/bonus/ft_atoi_base.s +++ b/srcs/bonus/ft_atoi_base.s @@ -1,12 +1,11 @@ -; atoi base -; prototype : int ft_atoi_base(char *str, char *base) -;global ft_atoi_base -global get_char_index -global check_base +global ft_atoi_base +global check_duplicate_char +extern ft_strlen section .data invalid_chars: db "+- ", 0x0c, 0x0a, 0x0d, 0x09, 0x0b, 0 +whitespaces: db " ", 0x0c, 0x0a, 0x0d, 0x09, 0x0b, 0 section .text @@ -24,7 +23,7 @@ get_char_index_loop: lea rsi, [rsi + 1] jne get_char_index_loop - xor rax, -1 ;not found and at the end + mov rax, -1 ;not found and at the end pop rsi ret @@ -34,12 +33,57 @@ get_char_index_found: mov rax, rsi ret +;function that ... it's in the name why are you looking here +; parameters : the string in rdi +; returns 1 if there is a duplicate char +check_duplicate_char: + + mov al ,[rdi] ; test if \0 + test al, al + je no_duplicate + + push rdi + mov rsi, rdi + lea rsi, [rsi + 1] + mov dil, [rdi] + call get_char_index + pop rdi + + cmp rax, -1 ;is char found + lea rdi, [rdi + 1] + je check_duplicate_char + mov rax, 1 + ret + +no_duplicate: + xor rax, rax + ret + + + ;function that checks if the base is valid -;a valid base does not have any of these char : "+-" or any space defined by isspace(3) and does not have any duplicate char +;a valid base does not have any of these char : "+-" or any space defined by isspace(3) and does not have any duplicate char or does not have any char ; returns 0 if base is not valid check_base: xor rax, rax + mov al, [rdi] ; check if it's an empty string + test al, al + jne chk_bs_duplicate + xor rax, rax + ret + +chk_bs_duplicate: + push rdi + call check_duplicate_char + pop rdi + test rax, rax + je chk_bs_char + + xor rax, rax + ret + + chk_bs_char: mov al, [rdi] ; if rdi is \0, return 0 test al, al @@ -61,3 +105,110 @@ chk_bs_char: base_ok: mov rax,1 ret + + +; prototype : int ft_atoi_base(char *str, char *base) +; rdi str +; rsi base +ft_atoi_base: + xor rax, rax ;check if there is a null pointer in rdi or rsi + test rdi, rdi + je final_number + test rsi, rsi + je final_number + + push rdi ; is base valid + push rsi + mov rdi, rsi + call check_base + pop rsi + pop rdi + + test rax, rax + jne whitespace_skip ; if 0 , base is not valid + xor rax, rax + ret + + xor rdx, rdx + +whitespace_skip_inc: + lea rdi, [rdi + 1] +whitespace_skip: + push rdi + push rsi + mov dil, [rdi] + lea rsi, [rel whitespaces] + call get_char_index + pop rsi + pop rdi + + cmp rax, 0 + jge whitespace_skip_inc + jmp plus_minus + +plus_minus_invert: + xor rdx, 1 + +plus_minus_inc: + lea rdi, [rdi + 1] + +plus_minus: + mov al, [rdi] + cmp al, '-' + je plus_minus_invert + + cmp al, '+' + je plus_minus_inc + + + + push rdi + push rsi + mov rdi, rsi + call ft_strlen + pop rsi + pop rdi + + mov rbx, rax + + xor rax, rax + + push rdx + +number_loop: + mov dl, [rdi] + test dl, dl + je final_number + + push rax + push rdi + push rsi + mov dil, dl + call get_char_index + pop rsi + pop rdi + + mov rdx, rax ; save return value in rdx + pop rax + + cmp rdx, -1 + je final_number + + push rdx ; imul sets rdx to 0 + imul rbx + pop rdx + add rax, rdx + + lea rdi, [rdi + 1] + + jmp number_loop + +final_number: + pop rdx + test rdx, rdx + jne neg_final_number + ret + +neg_final_number: + neg rax + ret diff --git a/test.c b/test.c index 012c645..0e48cf6 100644 --- a/test.c +++ b/test.c @@ -6,7 +6,7 @@ /* By: tomoron +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/03/29 19:53:58 by tomoron #+# #+# */ -/* Updated: 2025/03/31 16:42:55 by tomoron ### ########.fr */ +/* Updated: 2025/04/02 02:35:57 by tomoron ### ########.fr */ /* */ /* ************************************************************************** */ @@ -44,6 +44,7 @@ int ft_strcmp(char *dest, char *src); ssize_t ft_write(int fd, const void *buffer, size_t count); ssize_t ft_read(int fd, void *buffer, size_t count); char *ft_strdup(char *src); +int ft_atoi_base(char *nbr, char *base); int test_strlen(void) { @@ -180,17 +181,33 @@ int test_strdup(void) return(nb_tests == passed); } -size_t check_base(char *base); -int tmp(void) +int test_atoi_base(void) { int nb_tests; int passed; - nb_tests = 4; + nb_tests = 14; passed = 0; - TEST("a", check_base("a") == 1); - TEST("a", check_base("abcdef") == 1); + + TEST("normal number base 10", ft_atoi_base("42", "0123456789") == 42); + TEST("normal number base 16", ft_atoi_base("1A4", "0123456789ABCDEF") == 420); + TEST("normal number base 2", ft_atoi_base("101", "01") == 5); + + TEST("0", ft_atoi_base("0", "0123456789") == 0); + TEST("leading zeros", ft_atoi_base("0001", "0123456789") == 1); + TEST("max 16-bit hex", ft_atoi_base("FFFF", "0123456789ABCDEF") == 65535); + + TEST("empty number", ft_atoi_base("", "0123456789") == 0); + TEST("empty base", ft_atoi_base("123", "") == 0); + TEST("invalid digit in base", ft_atoi_base("42abc", "0123456789") == 42); + TEST("duplicate characters in base", ft_atoi_base("123", "01234566789") == 0); + + TEST("large number within int range", ft_atoi_base("2147483647", "0123456789") == 2147483647); + TEST("negative number", ft_atoi_base("-42", "0123456789") == -42); + + TEST("non-standard base ordering", ft_atoi_base("123", "9876543210") == 876); + TEST("base 3", ft_atoi_base("321", "123") == 21); return(nb_tests == passed); } @@ -209,5 +226,5 @@ int main(void) printf("\n\n"); FNC_TEST("ft_strdup", test_strdup()); printf("\n\n"); - FNC_TEST("tmp", tmp()); + FNC_TEST("atoi_base", test_atoi_base()); }