diff --git a/include/ss/common.hpp b/include/ss/common.hpp index 0a4f934..95953c6 100644 --- a/include/ss/common.hpp +++ b/include/ss/common.hpp @@ -1,7 +1,9 @@ #pragma once +#include #include #include #include +#include #include namespace ss { @@ -33,54 +35,58 @@ inline ssize_t get_line_file(char** lineptr, size_t* n, FILE* stream) { #else using ssize_t = int64_t; -inline ssize_t get_line_file(char** lineptr, size_t* n, FILE* stream) { - size_t pos; - int c; - if (lineptr == nullptr || stream == nullptr || n == nullptr) { +ssize_t get_line_file(char** lineptr, size_t* n, FILE* fp) { + if (lineptr == nullptr || n == nullptr || fp == nullptr) { errno = EINVAL; return -1; } - c = getc(stream); - if (c == EOF) { - return -1; - } + char buff[get_line_initial_buffer_size]; - if (*lineptr == nullptr) { - *lineptr = static_cast(malloc(get_line_initial_buffer_size)); - if (*lineptr == nullptr) { + if (*lineptr == nullptr || *n < sizeof(buff)) { + size_t new_n = sizeof(buff); + auto new_lineptr = static_cast(realloc(*lineptr, new_n)); + if (new_lineptr == nullptr) { + errno = ENOMEM; return -1; } - *n = 128; + + *lineptr = new_lineptr; + *n = new_n; } - pos = 0; - while (c != EOF) { - if (pos + 1 >= *n) { - size_t new_size = *n + (*n >> 2); - if (new_size < get_line_initial_buffer_size) { - new_size = get_line_initial_buffer_size; - } - char* new_ptr = static_cast( - realloc(static_cast(*lineptr), new_size)); - if (new_ptr == nullptr) { + (*lineptr)[0] = '\0'; + + while (fgets(buff, sizeof(buff), fp) != nullptr) { + size_t line_used = strlen(*lineptr); + size_t buff_used = strlen(buff); + + if (*n < buff_used + line_used) { + size_t new_n = *n * 2; + + auto new_lineptr = static_cast(realloc(*lineptr, *n)); + if (new_lineptr == nullptr) { + errno = ENOMEM; return -1; } - *n = new_size; - *lineptr = new_ptr; + + *lineptr = new_lineptr; + *n = new_n; } - (*lineptr)[pos++] = c; - if (c == '\n') { - break; + memcpy(*lineptr + line_used, buff, buff_used); + line_used += buff_used; + (*lineptr)[line_used] = '\0'; + + if ((*lineptr)[line_used - 1] == '\n') { + return line_used; } - c = getc(stream); } - (*lineptr)[pos] = '\0'; - return pos; + return -1; } + #endif } /* ss */ diff --git a/ssp.hpp b/ssp.hpp index 72e4c2f..c6e6620 100644 --- a/ssp.hpp +++ b/ssp.hpp @@ -647,54 +647,58 @@ inline ssize_t get_line_file(char** lineptr, size_t* n, FILE* stream) { #else using ssize_t = int64_t; -inline ssize_t get_line_file(char** lineptr, size_t* n, FILE* stream) { - size_t pos; - int c; - if (lineptr == nullptr || stream == nullptr || n == nullptr) { +ssize_t get_line_file(char** lineptr, size_t* n, FILE* fp) { + if (lineptr == nullptr || n == nullptr || fp == nullptr) { errno = EINVAL; return -1; } - c = getc(stream); - if (c == EOF) { - return -1; - } + char buff[get_line_initial_buffer_size]; - if (*lineptr == nullptr) { - *lineptr = static_cast(malloc(get_line_initial_buffer_size)); - if (*lineptr == nullptr) { + if (*lineptr == nullptr || *n < sizeof(buff)) { + size_t new_n = sizeof(buff); + auto new_lineptr = static_cast(realloc(*lineptr, new_n)); + if (new_lineptr == nullptr) { + errno = ENOMEM; return -1; } - *n = 128; + + *lineptr = new_lineptr; + *n = new_n; } - pos = 0; - while (c != EOF) { - if (pos + 1 >= *n) { - size_t new_size = *n + (*n >> 2); - if (new_size < get_line_initial_buffer_size) { - new_size = get_line_initial_buffer_size; - } - char* new_ptr = static_cast( - realloc(static_cast(*lineptr), new_size)); - if (new_ptr == nullptr) { + (*lineptr)[0] = '\0'; + + while (fgets(buff, sizeof(buff), fp) != nullptr) { + size_t line_used = strlen(*lineptr); + size_t buff_used = strlen(buff); + + if (*n < buff_used + line_used) { + size_t new_n = *n * 2; + + auto new_lineptr = static_cast(realloc(*lineptr, *n)); + if (new_lineptr == nullptr) { + errno = ENOMEM; return -1; } - *n = new_size; - *lineptr = new_ptr; + + *lineptr = new_lineptr; + *n = new_n; } - (*lineptr)[pos++] = c; - if (c == '\n') { - break; + memcpy(*lineptr + line_used, buff, buff_used); + line_used += buff_used; + (*lineptr)[line_used] = '\0'; + + if ((*lineptr)[line_used - 1] == '\n') { + return line_used; } - c = getc(stream); } - (*lineptr)[pos] = '\0'; - return pos; + return -1; } + #endif } /* ss */