diff --git a/Makefile b/Makefile index 7e35da0..7e5a0a0 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,7 @@ TEST_NAME = tests_bin # --------------- FILES --------------- # LIST_ASM_SRC = \ + ft_atoi_base.s \ ft_create_elem.s \ ft_list.s \ ft_list_push_front.s \ @@ -20,6 +21,7 @@ LIST_ASM_SRC = \ ft_write.s LIST_TEST_SRC = \ + ft_atoi_base.c \ ft_create_elem.c \ ft_list_push_front.c \ ft_list_remove_if.c \ diff --git a/include/libasm.h b/include/libasm.h index 2c9c110..42bcc0b 100644 --- a/include/libasm.h +++ b/include/libasm.h @@ -10,10 +10,10 @@ /* */ /* ************************************************************************** */ -#ifndef LIBASM_BUILD_INCLUDE_LIBASM_H_ -# define LIBASM_BUILD_INCLUDE_LIBASM_H_ +#ifndef LIBASM_H +# define LIBASM_H -# include +#include typedef struct s_list { @@ -34,5 +34,5 @@ void ft_list_push_front(t_list **begin_list, void *data); int ft_list_size(t_list *begin_list); void ft_list_remove_if(t_list **begin_list, void *data_ref, int (*cmp)(), void (*free_fct)(void *)); void ft_list_sort(t_list **begin_list, int (*cmp)()); - +int ft_atoi_base(char *str, char *base); #endif \ No newline at end of file diff --git a/src/ft_atoi_base.s b/src/ft_atoi_base.s new file mode 100644 index 0000000..9cdd051 --- /dev/null +++ b/src/ft_atoi_base.s @@ -0,0 +1,284 @@ +bits 64 + +extern ft_strlen + +global ft_atoi_base + +section .note.GNU-stack + +; int ft_atoi_base(char *str, char *base) +;{ +; int index; +; int result; +; int sign; +; int base_len; +; +; if (!(ft_is_valid_base(base))) +; return (0); +; index = 0; +; result = 0; +; sign = 1; +; base_len = ft_strlen(base); +; str = ft_remove_isspace_nbr(str); +; while (str[index] == '-' || str[index] == '+') +; { +; if (str[index] == '-') +; sign *= -1; +; index++; +; } +; while (ft_char_is_in_base(str[index], base) != -1) +; { +; result = result * base_len + ft_char_is_in_base(str[index], base); +; index++; +; } +; return (result * sign); +; } +; +; int ft_is_valid_base(char *base) +;{ +; int index; +; int index_temp; +; +; index = 0; +; while (base[index] != '\0') +; { +; if (base[index] == '+' || base[index] == '-' +; || (base[index] >= 9 && base[index] <= 13) || base[index] == ' ') +; return (0); +; index_temp = 0; +; while (index_temp < index) +; { +; if (base[index] == base[index_temp]) +; return (0); +; index_temp++; +; } +; index++; +; } +; return (index >= 2); +; } +; +; int ft_strlen(char *str) +;{ +; char *first_ptr; +; +; first_ptr = str; +; while (*str != '\0') +; str++; +; return (str - first_ptr); +; } +; +; char *ft_remove_isspace_nbr(char *str) +;{ +; while ((*str >= 9 && *str <= 13) || *str == ' ') +; str++; +; return (str); +; } +; +; int ft_char_is_in_base(char c, char *base) +;{ +; int index; +; +; index = 0; +; while (base[index] != '\0') +; { +; if (base[index] == c) +; return (index); +; index++; +; } +; return (-1); +; } + +section .text +;int ft_atoi_base(char *str, char *base); +ft_atoi_base: + push rdi + push rsi + mov rdi, rsi + call is_valid_base + pop rsi + pop rdi + test rax, rax + jz .ft_atoi_base_return_false + sub rsp, 32 + ; index + mov qword [rsp + 0], 0 + ; result + mov qword [rsp + 8], 0 + ; sign + mov qword [rsp + 16], 1 + ; base_len + push rdi + push rsi + mov rdi, rsi + call ft_strlen + pop rsi + pop rdi + mov [rsp + 24], rax + ; str + push rsi + call remove_spaces_from_str + pop rsi + mov rdi, rax + jmp .ft_atoi_base_first_loop + +.ft_atoi_base_first_loop: + mov r8, rdi + add r8, [rsp + 0] + mov r8, [r8] + cmp byte r8b, '-' + je .ft_atoi_base_first_loop_process + cmp byte r8b, '+' + je .ft_atoi_base_first_loop_process + jmp .ft_atoi_base_second_loop + +.ft_atoi_base_second_loop: + push rdi + push rsi + ; str[index] + add rdi, [rsp + 0 + 16] + mov rdi, [rdi] + call char_is_in_base + pop rsi + pop rdi + cmp rax, -1 + je .ft_atoi_base_return + mov r8, [rsp + 8] + mov r9, [rsp + 24] + imul r8, r9 + add r8, rax + mov [rsp + 8], r8 + ; index++ + mov rax, [rsp + 0] + inc rax + mov [rsp + 0], rax + jmp .ft_atoi_base_second_loop + + +.ft_atoi_base_return: + mov rax, [rsp + 8] + mov r8, [rsp + 16] + imul rax, r8 + add rsp, 32 + ret + + +.ft_atoi_base_first_loop_process: + cmp byte r8b, '-' + je .ft_atoi_base_first_loop_inverse_sign + add qword [rsp + 0], 1 + jmp .ft_atoi_base_first_loop + + +.ft_atoi_base_first_loop_inverse_sign: + mov rax, [rsp + 16] + imul rax, -1 + mov [rsp + 16], rax + add qword [rsp + 0], 1 + jmp .ft_atoi_base_first_loop + + + +.ft_atoi_base_return_false: + mov rax, 0 + ret + +remove_spaces_from_str: + cmp byte [rdi], ' ' + je .remove_spaces_from_str_inc + cmp byte [rdi], 9 + jl .remove_spaces_from_str_end + cmp byte [rdi], 13 + jg .remove_spaces_from_str_end + jmp .remove_spaces_from_str_inc + +.remove_spaces_from_str_inc: + inc rdi + jmp remove_spaces_from_str + +.remove_spaces_from_str_end: + mov rax, rdi + ret + +char_is_in_base: + xor rax, rax + jmp .char_is_in_base_loop + +.char_is_in_base_loop: + mov r8, rsi + add r8, rax + mov r8, [r8] + ; only u8 in r8 + test r8b, r8b + jz .char_is_in_base_end_loop + ; only u8 in r8 and rdi + cmp r8b, dil + je .char_is_in_base_end_loop_found + inc rax + jmp .char_is_in_base_loop + +.char_is_in_base_end_loop: + mov rax, -1 + ret + +.char_is_in_base_end_loop_found: + ret + +is_valid_base: + xor rax, rax + +.is_valid_base_first_loop: + mov r8, rdi + add r8, rax + mov r8, [r8] + test r8b, r8b + jz .is_valid_base_first_loop_end + jmp .is_valid_base_second_loop + +.is_valid_base_second_loop: + mov r8, rdi + add r8, rax + mov r8, [r8] + cmp byte r8b, '+' + jz .is_valid_base_ret_false + cmp byte r8b, '-' + jz .is_valid_base_ret_false + cmp byte [rdi], 9 + jl .is_valid_base_second_loop_pre + cmp byte [rdi], 13 + jg .is_valid_base_second_loop_pre + jmp .is_valid_base_ret_false + +.is_valid_base_second_loop_pre: + ; r9 = index_temp + xor r9, r9 + jmp .is_valid_base_second_loop_2 + +.is_valid_base_second_loop_2: + cmp r9, rax + jge .is_valid_base_second_loop_end + ; r10 = base[index_temp] + mov r10, rdi + add r10, r9 + mov r10, [r10] + ; base[index] == base[index_temp] + cmp r8b, r10b + jz .is_valid_base_ret_false + inc r9 + jmp .is_valid_base_second_loop_2 + +.is_valid_base_second_loop_end: + inc rax + jmp .is_valid_base_first_loop + +.is_valid_base_first_loop_end: + cmp rax, 2 + jl .is_valid_base_ret_false + jmp .is_valid_base_ret_true + +.is_valid_base_ret_false: + mov rax, 0 + ret + +.is_valid_base_ret_true: + mov rax, 1 + ret diff --git a/test/ft_atoi_base.c b/test/ft_atoi_base.c new file mode 100644 index 0000000..63c8fd0 --- /dev/null +++ b/test/ft_atoi_base.c @@ -0,0 +1,78 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_atoi_base.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: tdameros +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2022/08/09 22:39:58 by tdameros #+# #+# */ +/* Updated: 2022/08/09 23:28:19 by tdameros ### ########lyon.fr */ +/* */ +/* ************************************************************************** */ + +#include + +#include "libasm.h" +#include "utest.h" +#include "utils.h" + +UTEST(ft_atoi_base, simple_binary) { + ASSERT_EQ(ft_atoi_base("11", "01"), 3); +} + +UTEST(ft_atoi_base, binary_byte) { + ASSERT_EQ(ft_atoi_base("11111111", "01"), 255); +} + +UTEST(ft_atoi_base, convert_decimal_string_to_integer) { + ASSERT_EQ(ft_atoi_base("123", "0123456789"), 123); +} + +UTEST(ft_atoi_base, convert_hexadecimal_string_to_integer) { + ASSERT_EQ(ft_atoi_base("FF", "0123456789ABCDEF"), 255); +} + +UTEST(ft_atoi_base, convert_binary_string_to_integer_with_leading_zeros) { + ASSERT_EQ(ft_atoi_base("00001111", "01"), 15); +} + +UTEST(ft_atoi_base, convert_empty_string_to_integer) { + ASSERT_EQ(ft_atoi_base("", "01"), 0); +} + +UTEST(ft_atoi_base, convert_string_with_invalid_characters_to_integer) { + ASSERT_EQ(ft_atoi_base("12G4", "0123456789ABCDEF"), 18); +} + +UTEST(ft_atoi_base, convert_string_with_negative_sign_to_integer) { + ASSERT_EQ(ft_atoi_base("-111", "01"), -7); +} + +UTEST(ft_atoi_base, convert_string_with_multiple_negative_signs_to_integer) { + ASSERT_EQ(ft_atoi_base("--1111", "01"), 15); +} + +UTEST(ft_atoi_base, + convert_string_with_positive_and_negative_signs_to_integer) { + ASSERT_EQ(ft_atoi_base("-+1111", "01"), -15); +} + +UTEST(ft_atoi_base, convert_string_with_invalid_base_to_integer) { + ASSERT_EQ(ft_atoi_base("123", "0123456789AAB"), 0); +} + +UTEST(ft_atoi_base, invalid_base_with_spaces) { + ASSERT_EQ(ft_atoi_base("42", " \r\t"), 0); +} + +UTEST(ft_atoi_base, invalid_base_with_duplicate_char) { + ASSERT_EQ(ft_atoi_base("42", "01245670"), 0); +} + +UTEST(ft_atoi_base, invalid_base_with_minus) { + ASSERT_EQ(ft_atoi_base("42", "0124-567"), 0); +} + +UTEST(ft_atoi_base, invalid_base_with_plus) { + ASSERT_EQ(ft_atoi_base("42", "0+124567"), 0); +}