(’\n’을 기준으로, ‘\n’이 나오기 전까지의 문자열을 line에 할당)
즉, 여러 개의 파일 디스크립터를 통해 여러 파일의 라인을 각각 읽을 수 있도록 한다.
(gcc -Wall -Wextra -Werror -D BUFFER_SIZE=42 get_next_line.c get_next_line_utils.c
abcde\n
12345\0
< Get Next Line 첫 호출, 1 Cycle>
File : a b c d e \n 1 2 3 4 5 \0
Buffer : abcd e\n12 \0
Result : a b c d e \n \0
Backup : 1 2
BUFFER_SIZE = 4;
File : files에 “abide\n12345\0” 데이터가 존재
Buffer : read_and_restore함수를 이용하여 File에 있는 문자열을 Buffer에 \n or \0(EOL)를 찾을때까지 BUFFER_SIZE가 4이므로 4 Bytes씩 복사를 한다. (Buffer 마지막에는 \0으로 처리)
Result : get_line 함수를 이용하여 Buffer의 문자열을 \n or \0 을 끝으로 하는 문자열로 정리하여 원하는 결과값으로 만든다.
Backup : backup_next함수를 이용하여 처리된 Result 값에서 남은 문자열을 정적 변수에 저장하여 백업을 한다.
<Get Next Line 두 번째 호출, 2 Cycle>
File : 3 4 5 \0
Buffer : 12(backup) 345 \0
Result : 1 2 3 4 5 \0
Backup : free
BUFFER_SIZE = 4;
File : files을 GNL로 다시 오픈하면 fd 기록을 확인하고 읽지 않은 문자열 부터 확인한다.
Buffer : read_and_restore을 이용하여 File에 있는 문자열을 Buffer에 \n or \0(EOL)를 찾을때까지 BUFFER_SIZE가 4이므로 4 Byte씩 복사를 한다. (Buffer 마지막에는 \0으로 처리)
Result : get_line함수를 이용하여 Buffer의 문자열을 \n or \0을 끝으로 하는 문자열로 정리하여 원하는 결과값을 만든다
Backup : File의 EOL을 확인하여 backup_next함수에서 할당했던 backup변수가 free됨
#ifndef GET_NEXT_LINE_H
# define GET_NEXT_LINE_H
# include <unistd.h>
# include <stdlib.h>
# ifndef BUFFER_SIZE
# define BUFFER_SIZE 42
# endif
char *get_next_line(int fd);
char *get_line(char *backup);
char *backup_next(char *backup);
char *read_and_store(int fd, char *backup);
char *ft_strchr(const char *s, int c);
size_t ft_strlen(const char *str);
size_t ft_strlcat(char *dst, const char *src, size_t dstsize);
size_t ft_strlcpy(char *dst, const char *src, size_t dstsize);
#endif
#include "get_next_line.h"
char *store_buf(char *buf, char *backup)
{
char *new_backup;
int new_len;
if (!backup)
{
backup = (char *)malloc(sizeof(char)); // 최초 backup은 빈공간이므로 1칸 할당
backup[0] = '\0'; // 널문자 입력
}
if (!backup)
return (NULL);
new_len = ft_strlen(buf) + ft_strlen(backup);
new_backup = (char *)malloc(sizeof(char) * (new_len + 1));
if (!new_backup)
{
free(backup);
return (NULL);
}
ft_strlcpy(new_backup, backup, new_len + 1); // 복사
ft_strlcat(new_backup, buf, new_len + 1); // 붙여넣기
free(backup);
return (new_backup);
}
char *read_and_store(int fd, char *backup)
{
char *buf;
int rbytes;
buf = (char *)malloc(sizeof(char) * (BUFFER_SIZE + 1));
// buf에 BUFFER_SIZE+1 만큼의 공간 할당
if (!buf)
return (NULL); // 널가드
rbytes = 1; // rbytes는 while문을 돌리기 위해서 1부터
while (rbytes != 0)
{
rbytes = read(fd, buf, BUFFER_SIZE); // 해당 fd를 사용해 BUFFER_SIZE 만큼 읽어옴
if (rbytes == -1) // 읽어오지 못했을 시 free 후 NULL 반환
{
free(buf);
free(backup);
return (NULL);
}
buf[rbytes] = '\0'; // 널문자
backup = store_buf(backup, buf); // 원래의 backup에 buf를 붙임
if (ft_strchr(buf, '\n')) // 개행문자를 발견하면 while문 break
break ;
}
free(buf); // buff 메모리 해제
return (backup); // backup반환
}
char *get_line(char *backup)
{
char *buf;
int i;
i = 0;
if (!backup[0]) // backup이 빈 문자열이라면 NULL 반환
return (NULL);
while (backup[i] && backup[i] != '\n') // backup이 개행문자가 올때까지 i++
i++;
buf = (char *)malloc(sizeof(char) * (i + 2));
// 원래의 backup의 개행문자를 제외한 길이 + 2만큼의 공간 할당
if (!buf)
return (NULL); // 널가드
i = 0;
while (backup[i] && backup[i] != '\n')
{
buf[i] = backup[i]; // 원래의 backup 복붙
i++;
}
if (backup[i] == '\n') // 개행문자가 나온다면
buf[i++] = '\n'; // 개행문자 넣고
buf[i] = '\0'; // 널문자 대입
return (buf); // buf반환
}
char *backup_next(char *backup)
{
char *new_backup;
int i;
int j;
i = 0;
while (backup[i] && backup[i] != '\n') // backup의 개행문자가 나올 때 까지 i++
i++;
if (!backup[i]) // 개행문자가 없다면
{
free(backup); // 메모리 해제
return (NULL); // NULL 반환
}
new_backup = (char *)malloc(sizeof(char) * (ft_strlen(backup) - i));
// backup에서 처리가 된 문자들을 빼고 널문자의 길이를 더한 공간 할당
if (!new_backup)
{
free(backup);
return (NULL); // 널가드
}
i++; // backup에 있는 \n 건너뜀
j = 0;
while (backup[i])
buf[j++] = backup[i++]; // backup에서 처리가 되지 않은 문자들을 복사
new_backup[j] = '\0';
free(backup);
return (new_backup); // 새로운 backup 최신화
}
char *get_next_line(int fd)
{
char *buf;
static char *backup;
if (fd < 0 || BUFFER_SIZE <= 0)
return (NULL);
backup = read_and_store(fd, backup); // backup 최신화
if (!backup)
return (NULL); // 널가드
buf = get_line(backup); // 널문자 포함 문자열 반환
backup = backup_next(backup);
return (buf);
}
#include "get_next_line.h"
// 문자열 내에서 문자가 있는지 확인
har *ft_strchr(const char *s, int c)
{
size_t i;
size_t len;
i = 0;
len = ft_strlen(s);
while (i <= len)
{
if (s[i] == (unsigned char)c)
return ((char *)(s + i));
i++;
}
return (0);
}
// 문자열 길이 반환
size_t ft_strlen(const char *s)
{
size_t i;
i = 0;
while (s[i])
i++;
return (i);
}
// 문자열 붙여넣기
size_t ft_strlcat(char *dst, const char *src, size_t dstsize)
{
size_t i;
size_t dst_len;
size_t src_len;
dst_len = ft_strlen(dst);
src_len = ft_strlen(src);
i = 0;
if (dstsize < dst_len + 1)
return (dstsize + src_len);
if (dstsize > dst_len + 1)
{
while (src[i] && dst_len + i + 1 < dstsize)
{
dst[dst_len + i] = src[i];
i++;
}
}
dst[dst_len + i] = '\0';
return (dst_len + src_len);
}
// 문자열 복사
size_t ft_strlcpy(char *dst, const char *src, size_t dstsize)
{
size_t srcsize;
size_t i;
srcsize = ft_strlen(src);
i = 0;
if (!dst || !src)
return (0);
if (dstsize == 0)
return (srcsize);
while (src[i] && i + 1 < dstsize)
{
dst[i] = src[i];
i++;
}
dst[i] = '\0';
return (srcsize);
}
#ifndef GET_NEXT_LINE_BONUS_H
# define GET_NEXT_LINE_BONUS_H
# include <unistd.h>
# include <stdlib.h>
# ifndef BUFFER_SIZE
# define BUFFSE_SIZE 42
# endif
char *get_next_line(int fd);
char *get_line(char *backup);
char *backup_next(char *backup);
char *read_and_store(int fd, char *backup);
char *ft_strchr(const char *s, int c);
size_t ft_strlen(const char *str);
size_t ft_strlcat(char *dst, const char *src, size_t dstsize);
size_t ft_strlcpy(char *dst, const char *src, size_t dstsize);
#endif
#include "get_next_line_bonus.h"
char *store_buf(char *buf, char *backup)
{
char *new_backup;
int new_len;
if (!backup)
{
backup = (char *)malloc(sizeof(char));
backup[0] = '\0';
}
if (!backup)
return (NULL);
new_len = ft_strlen(buf) + ft_strlen(backup);
new_backup = (char *)malloc(sizeof(char) * (new_len + 1));
if (!new_backup)
{
free(backup);
return (NULL);
}
ft_strlcpy(new_backup, backup, new_len + 1);
ft_strlcat(new_backup, buf, new_len + 1);
free(backup);
return (new_backup);
}
char *read_and_store(int fd, char *backup)
{
char *buf;
int rbytes;
buf = (char *)malloc(sizeof(char) * (BUFFER_SIZE + 1));
if (!buf)
return (NULL);
rbytes = 1;
while (rbytes != 0)
{
rbytes = read(fd, buf, BUFFER_SIZE);
if (rbytes == -1)
{
free(buf);
free(backup);
return (NULL);
}
buf[rbytes] = '\0';
backup = store_buf(buf, backup);
if (ft_strchr(buf, '\n'))
break ;
}
free(buf);
return (backup);
}
char *get_line(char *backup)
{
char *buf;
int i;
i = 0;
if (!backup[0])
return (NULL);
while (backup[i] && backup[i] != '\n')
i++;
buf = (char *)malloc(sizeof(char) * (i + 2));
if (!buf)
return (NULL);
i = 0;
while (backup[i] && backup[i] != '\n')
{
buf[i] = backup[i];
i++;
}
if (backup[i] == '\n')
buf[i++] = '\n';
buf[i] = '\0';
return (buf);
}
char *backup_next(char *backup)
{
char *new_backup;
int i;
int j;
i = 0;
while (backup[i] && backup[i] != '\n')
i++;
if (backup[i] != '\n')
{
free(backup);
return (NULL);
}
new_backup = (char *)malloc(sizeof(char) * (ft_strlen(backup) - i));
if (!new_backup)
{
free(backup);
return (NULL);
}
i++;
j = 0;
while (backup[i])
new_backup[j++] = backup[i++];
new_backup[j] = '\0';
free(backup);
return (new_backup);
}
char *get_next_line(int fd)
{
char *buf;
static char *backup[256]; // fd최댓값 만큼의 문자열을 정적변수로 선언
if (fd < 0 || fd + 1 > 256 || BUFFER_SIZE <= 0)
return (NULL);
backup[fd] = read_and_store(fd, backup[fd]);
if (!backup[fd])
return (NULL);
buf = get_line(backup[fd]);
backup[fd] = backup_next(backup[fd]);
return (buf);
}
#include "get_next_line_bonus.h"
char *ft_strchr(const char *s, int c)
{
size_t i;
size_t len;
i = 0;
len = ft_strlen(s);
while (i <= len)
{
if (s[i] == (unsigned char)c)
return ((char *)(s + i));
i++;
}
return (0);
}
size_t ft_strlen(const char *s)
{
size_t i;
i = 0;
while (s[i])
i++;
return (i);
}
size_t ft_strlcat(char *dst, const char *src, size_t dstsize)
{
size_t i;
size_t dst_len;
size_t src_len;
dst_len = ft_strlen(dst);
src_len = ft_strlen(src);
i = 0;
if (dstsize < dst_len + 1)
return (dstsize + src_len);
if (dstsize > dst_len + 1)
{
while (src[i] && dst_len + i + 1 < dstsize)
{
dst[dst_len + i] = src[i];
i++;
}
}
dst[dst_len + i] = '\0';
return (dst_len + src_len);
}
size_t ft_strlcpy(char *dst, const char *src, size_t dstsize)
{
size_t srcsize;
size_t i;
srcsize = ft_strlen(src);
i = 0;
if (!dst || !src)
return (0);
if (dstsize == 0)
return (srcsize);
while (src[i] && i + 1 < dstsize)
{
dst[i] = src[i];
i++;
}
dst[i] = '\0';
return (srcsize);
}