if __SOURCE__ = __FILE__;-------------------------------------------- TEST CASES
format PE64 NX CONSOLE 6.2 at 0x1234_5678_0000 ; 64-bit addresses throughout
include 'umbrella.g'
main: entry $
push rax
GetStdHandle STD_OUTPUT_HANDLE
xchg rbx, rax
xor esi, esi ; failed test count, %ERRORLEVEL% on exit
label .P5:8 at rsp+32

iterate <EXPECTED,	NUMBER,				DESCRIPTION>,\
	FAIL,		<<0>>,				'empty, insufficient digits',\
	FAIL,		<<'.',0>>,			'non-number, insufficient digits',\
	FAIL,		<<'-',0>>,			'sign, insufficient digits',\
	FAIL,		0x1_0000_0000_0000_0000,	'radix overflow',\
	FAIL,		0x8000_0000_0000_0000,		'overflow',\
	PASS,		0x7FFF_FFFF_FFFF_FFFF,		'maximum value',\
	PASS,		0,				'zero',\
	PASS,		-0x8000_0000_0000_0000,		'minimum value',\
	FAIL,		-0x8000_0000_0000_0001,		'overflow',\
	FAIL,		-0x1_0000_0000_0000_0000,	'radix overflow',\

	virtual DATA.1
		label .%.string
		db 9,DESCRIPTION,', "'
		label .%.number
		match < ANY >, NUMBER
			db ANY
		else if NUMBER < 0
			repeat 1, N:-NUMBER
				db '-',`N,0
			end repeat
		else
			repeat 1, N:NUMBER
				db `N,0
			end repeat
		end if
		.%.strlen := $ - .%.string
	end virtual

	lea rdi, [.%.number]
	call UTF8__dec_i64_RDI
	match =PASS, EXPECTED
		jz .%.bad_result ; PASS != PASS
		virtual CONST.8
			.%.value dq NUMBER
		end virtual
		cmp [.%.value], rax
	end match
	jnz .%.bad_result ; FAIL != FAIL, or value incorrect
	lea rdx, <_A 13,10,27,'[32m','pass',27,'[m'>
	WriteConsoleA rbx, rdx, .bytes, & .P5, 0
	jmp .%.continue
.%.bad_result:
	inc esi
	lea rdx, <_A 13,10,27,'[91m','FAIL',27,'[m'>
	WriteConsoleA rbx, rdx, .bytes, & .P5, 0
.%.continue:
	mov byte [.%.string + .%.strlen - 1], '"'
	WriteConsoleA rbx, & .%.string, .%.strlen, & .P5, 0
end iterate

; TODO: perform batch of random tests in boundary ranges
; [-0x2_0000_0000_0000_0000, 0x2_0000_0000_0000_0000]

ExitProcess rsi ; return failed tests
int3
end if;-------------------------------------------------------------- TEST CASES


if used UTF8__dec_i64_RDI

; Translate ASCII decimal digits (and sign) to signed-qword value,
; stop on any other byte value. (End of digits acts as token separator.)
 
; RAX is signed qword result
; RDX [0,9]
; RCX digits read
; ZF = 1, invalid result
align 16, codepad #
UTF8__dec_i64_RDI:
	xor ecx, ecx
	cmp byte [rdi], '-'
	setz cl
	add rdi, rcx
	bts rcx, 63
	xor eax, eax
	push rdi
.read_digits:
	movzx edx, byte [rdi]
	sub edx, '0'
	jc .done
	cmp edx, 10
	jnc .done
	imul rax, rax, 10
	jo .overflow
	add rax, rdx
	add rdi, 1;scasb;
	cmp rax, rcx ; 0x8000_0000_0000_0000,	0x8000_0000_0000_0001
	jc .read_digits
.overflow:
	pop rdi ; digits
	push rdi ; force zero, fall through ...
.done:
	jecxz .positive ; note ECX!
	imul rax, rax, -1
.positive:
	pop rcx
	sub ecx, edi
	retn ; ZF=1, RCX=Z on error

repeat 1, B:$-UTF8__dec_i64_RDI
	display 10,`B,' bytes, UTF8__dec_i64_RDI:'
end repeat

end if ; used UTF8__dec_i64_RDI
