aboutsummaryrefslogtreecommitdiff
path: root/ft_atoi_base.s
blob: 581b68bf60c9389d6d45209c72ec988175b9c3aa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
; **************************************************************************** ;
;                                                                              ;
;                                                         :::      ::::::::    ;
;    ft_atoi_base.s                                     :+:      :+:    :+:    ;
;                                                     +:+ +:+         +:+      ;
;    By: cacharle <marvin@42.fr>                    +;+  +:+       +;+         ;
;                                                 +;+;+;+;+;+   +;+            ;
;    Created: 2019/11/22 03:59:15 by cacharle          ;+;    ;+;              ;
;    Updated: 2019/11/22 21:18:08 by cacharle         ;;;   ;;;;;;;;.fr        ;
;                                                                              ;
; **************************************************************************** ;

extern _ft_strlen

global _ft_atoi_base

; int ft_atoi_base(const char *str, const char *base);
_ft_atoi_base:
	mov r12, rdi  ; r12 = str
	mov r13, rsi  ; r13 = base

	; check if the base is valid
	mov rdi, r13
	call _check_base
	cmp rax, 0
	je CHECK_BASE_FALSE


	; ignore space in front
	mov r15, -1  ; str index
	FT_ATOI_BASE_IGNORE_SPACES:
		inc r15
		mov dil, byte [r12 + r15]
		call _ft_isspace
		cmp rax, 1
		je FT_ATOI_BASE_IGNORE_SPACES


	; cmp byte [r12 + r15], 0x2d
	; mov r11, zf ; r11 = is negative

	mov rdi, r13
	call _ft_strlen
	mov r14, rax  ; r14 = radix

	xor rcx, rcx  ; return value
	FT_ATOI_BASE_LOOP:
		mov sil, [r12 + r15]
		call _base_pos  ; get value of the current char int the base
		cmp rax, -1     ; if is not in base break
		je FT_ATOI_BASE_LOOP_END

		imul rcx, r14   ; multiply by the radix
		add rcx, rax    ; add the current value
		inc r15
		jmp FT_ATOI_BASE_LOOP
	FT_ATOI_BASE_LOOP_END:
	mov rax, rcx
	ret


; rdi: char *base
; sil: char searched
_base_pos:
	mov rax, -1
	BASE_POS_LOOP:
		inc rax
		cmp byte [rdi + rax], 0    ; if '\0' char not in base
		je BASE_POS_NOT_FOUND
		cmp sil, byte [rdi + rax]  ; loop until '\0' or found
		jne BASE_POS_LOOP
	ret
	BASE_POS_NOT_FOUND:
		mov rax, -1
		ret


; rdi: char *base
_check_base:
	; check for empty or size 1 base
	push rdi
	call _ft_strlen
	pop rdi
	cmp rax, 2
	jl CHECK_BASE_FALSE

	xor rcx, rcx                    ; rcx = index
	CHECK_BASE_LOOP:
		cmp byte [rdi + rcx], 0
		je CHECK_BASE_LOOP_END
		cmp byte [rdi + rcx], 0x2b  ; check '+'
		je CHECK_BASE_FALSE
		cmp byte [rdi + rcx], 0x2d  ; check '-'
		je CHECK_BASE_FALSE

		push rdi               ; save base
		mov dil, [rdi + rcx]   ; pass current char as argument
		call _ft_isspace
		pop rdi                ; recover base
		cmp rax, 1
		je CHECK_BASE_FALSE    ; check for spaces

		; check for duplicates in base
		mov rdx, rcx                                ; index from curr +1
		CHECK_BASE_DUP_LOOP:
			inc rdx
			mov r10b, byte [rdi + rcx]  ; r10b = checked char
			cmp r10b, byte [rdi + rdx]  ; check if found dup
			je CHECK_BASE_FALSE
			cmp byte [rdi + rdx], 0                 ; if \0 end dup check
			jne CHECK_BASE_DUP_LOOP

		inc rcx
		jmp CHECK_BASE_LOOP
	CHECK_BASE_LOOP_END:

	mov rax, 1
	ret
	CHECK_BASE_FALSE:
		xor rax, rax
		ret


; dil: char c
_ft_isspace:
	cmp dil, 20h  ; if space jump next
	je ISSPACE_TRUE_END
	sub dil, 9h
	cmp dil, 5h
	jl ISSPACE_TRUE_END
	xor rax, rax
	ret
	ISSPACE_TRUE_END:
		mov rax, 1
		ret