/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_print_memory.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: jayang <[email protected]> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/02/06 17:21:21 by jayang #+# #+# */
/* Updated: 2022/02/07 11:12:05 by jayang ### ########.fr */
/* */
/* ************************************************************************** */
#include <unistd.h>
void print_hex_element(unsigned char c) // 문자 치환 함수
{
char *c_hex;
char hex[2];
c_hex = "0123456789abcdef";
hex[0] = c_hex[c / 16];
hex[1] = c_hex[c % 16];
write(1, hex, 2);
}
void print_hex_addr(unsigned long long c_addr)
{
unsigned char sub[16]; //
int i;
i = 0;
while (c_addr > 0)
{
sub[15 - i] = c_addr % 16;
if (sub[15 - i] < 10)
sub[15 - i] += '0';
else
sub[15 - i] = (sub[15 - i] % 10) + 'a';
c_addr /= 16;
i++;
}
while (i < 16)
{
sub[15 - i] = '0';
i++;
}
while (i > 0)
{
write(1, sub + (16 - i), 1);
i--;
}
}
void print_padding(unsigned int spc)
{
while (spc > 0)
{
write(1, " ", 1);
spc--;
}
}
void print_line(unsigned char *c_addr, unsigned int size)
{
unsigned int idx;
idx = 0;
while (idx < size) // size(출력할 문자)만큼 인덱스에 접근
{
print_hex_element(c_addr[idx]); // 요소를 16진수로 치환하여 출력할 함수 호출
idx++;
if (idx % 2 == 0) // 문자 2개마다 공백 1번 출력
write(1, " ", 1);
}
print_padding(40 - (idx * 2) - (size / 2));
// 문자가 16개가 안 들어온 경우를 대비한 라인 맞추기용 공백
// 무식하게 계산한 인자 값을 던짐...
// => 입력값이 없을 때 공백을 출력한다던가 새로운 접근법이 가능할 듯 함. 피신 끝나고 재도전.
idx = 0;
while (idx < size) // 원본은 아스키 코드 값을 확인하여 걸러내는 과정을 거침
{
if (' ' <= c_addr[idx] && c_addr[idx] <= '~') // 출력 가능한 건 바로 출력
write(1, c_addr + idx, 1);
else
write(1, ".", 1); // 출력 불가능한 아스키 값은 .으로 치환해서 출력
idx++;
}
}
void *ft_print_memory(void *addr, unsigned int size)
{
unsigned int select_idx;
unsigned int element_size;
unsigned char *c_addr; // void 타입은 연산자로 인덱스 이동이 불가능 하므로 강제 형변환
select_idx = 0; // 16문자 단위로 인덱스 선택
c_addr = (unsigned char *)addr; // (unsigned char *)안 해줘도 되지만 불안해서 함
while (size > 0) // size가 addr의 길이보다 더 큰 값을 받았을 때,
{ // 엉뚱한 주소까지 계속 가리키게 되는 데 그것마저 모두 출력해주어야 함.
if (size >= 16)
{
element_size = 16;
size -= 16; // size가 0이 될 때까지 16씩 빼준다. (16개 크기만큼 처리하므로)
}
else
{
element_size = size; // 남은 문자 개수를 모두 던져준다.
size = 0; // size 값에 0을 넣고 다음 반복문을 멈춘다.
}
print_hex_addr((unsigned long long)c_addr + select_idx);
// unsigned long도 8byte지만 이것도 불안해서 long long 지정
// c_addr을 8byte 숫자로 강제 형변환하여 select_idx번 인덱스 주소'만' 전송.
// 즉, 0번, 16번,
write(1, ": ", 2);
print_line(c_addr + select_idx, element_size);
// c_addr의 select_idx번 인덱스 주소를 넘기고, 출력할 e_size 인자도 같이 전송.
write(1, "\\n", 1);
select_idx += 16; // 16개의 char 인덱스 단위로 잘라서 보내기 위함.
}
return (addr);
}