Изучаю код
tinyproxy. и вот приводится такой код. почему он такой избыточный? или мой вариант избыточный? вот вариант разработчика.
#define SEGMENT_LEN (512)
#define MAXIMUM_BUFFER_LENGTH (128 * 1024)
ssize_t readline (int fd, char **whole_buffer)
{
ssize_t whole_buffer_len;
char buffer[SEGMENT_LEN];
char *ptr;
ssize_t ret;
ssize_t diff;
struct read_lines_s {
char *data;
size_t len;
struct read_lines_s *next;
};
struct read_lines_s *first_line, *line_ptr;
first_line =
(struct read_lines_s *) safecalloc (sizeof (struct read_lines_s),
1);
if (!first_line)
return -ENOMEM;
line_ptr = first_line;
whole_buffer_len = 0;
for (;;) {
ret = recv (fd, buffer, SEGMENT_LEN, MSG_PEEK);
if (ret <= 0)
goto CLEANUP;
ptr = (char *) memchr (buffer, '\n', ret);
if (ptr)
diff = ptr - buffer + 1;
else
diff = ret;
whole_buffer_len += diff;
/*
* Don't allow the buffer to grow without bound. If we
* get to more than MAXIMUM_BUFFER_LENGTH close.
*/
if (whole_buffer_len > MAXIMUM_BUFFER_LENGTH) {
ret = -ERANGE;
goto CLEANUP;
}
line_ptr->data = (char *) safemalloc (diff);
if (!line_ptr->data) {
ret = -ENOMEM;
goto CLEANUP;
}
ret = recv (fd, line_ptr->data, diff, 0);
if (ret == -1) {
goto CLEANUP;
}
line_ptr->len = diff;
if (ptr) {
line_ptr->next = NULL;
break;
}
line_ptr->next =
(struct read_lines_s *)
safecalloc (sizeof (struct read_lines_s), 1);
if (!line_ptr->next) {
ret = -ENOMEM;
goto CLEANUP;
}
line_ptr = line_ptr->next;
}
*whole_buffer = (char *) safemalloc (whole_buffer_len + 1);
if (!*whole_buffer) {
ret = -ENOMEM;
goto CLEANUP;
}
*(*whole_buffer + whole_buffer_len) = '\0';
whole_buffer_len = 0;
line_ptr = first_line;
while (line_ptr) {
memcpy (*whole_buffer + whole_buffer_len, line_ptr->data,
line_ptr->len);
whole_buffer_len += line_ptr->len;
line_ptr = line_ptr->next;
}
ret = whole_buffer_len;
CLEANUP:
do {
line_ptr = first_line->next;
if (first_line->data)
safefree (first_line->data);
safefree (first_line);
first_line = line_ptr;
} while (first_line);
return ret;
}
ну я уже понимаю чем избыточен мой вариант. тем что чем больше данных, тем более медленней выделяется новая память с realloc. вот мой вариант, он не полный, я только нужный кусок привел.
ssize_t readline ( int fd, char **whole_buffer ) {
ssize_t whole_buffer_len = 0;
ssize_t ret;
ssize_t pos = 0;
char buffer[SEGMENT_LEN];
*whole_buffer = calloc ( 0, sizeof ( char * ) );
for(;;) {
ret = recv ( fd, buffer, SEGMENT_LEN, 0 );
if ( ret <= 0 ) goto CLEANUP;
whole_buffer_len += ret;
*whole_buffer = realloc ( *whole_buffer, whole_buffer_len );
strncpy ( *whole_buffer + pos, buffer, ret );
pos += ret;
}
...
}
наверное если размер будет мегабайт, то следующая порция данных будет искать новую область памяти на несколько байт больше.