Update get_line_buffer, update new version of get_line_file to work with data that has no new line at eof

This commit is contained in:
ado 2024-02-23 23:25:03 +01:00
parent 273e8ad950
commit 8881649aca
3 changed files with 46 additions and 30 deletions

View File

@ -58,14 +58,15 @@ ssize_t get_line_file(char** lineptr, size_t* n, FILE* fp) {
(*lineptr)[0] = '\0'; (*lineptr)[0] = '\0';
size_t line_used = 0;
while (fgets(buff, sizeof(buff), fp) != nullptr) { while (fgets(buff, sizeof(buff), fp) != nullptr) {
size_t line_used = strlen(*lineptr); line_used = strlen(*lineptr);
size_t buff_used = strlen(buff); size_t buff_used = strlen(buff);
if (*n < buff_used + line_used) { if (*n <= buff_used + line_used) {
size_t new_n = *n * 2; size_t new_n = *n * 2;
auto new_lineptr = static_cast<char*>(realloc(*lineptr, *n)); auto new_lineptr = static_cast<char*>(realloc(*lineptr, new_n));
if (new_lineptr == nullptr) { if (new_lineptr == nullptr) {
errno = ENOMEM; errno = ENOMEM;
return -1; return -1;
@ -84,7 +85,7 @@ ssize_t get_line_file(char** lineptr, size_t* n, FILE* fp) {
} }
} }
return -1; return (line_used != 0) ? line_used : -1;
} }
#endif #endif

View File

@ -744,50 +744,52 @@ private:
reader& operator=(const reader& other) = delete; reader& operator=(const reader& other) = delete;
ssize_t get_line_buffer(char** lineptr, size_t* n, ssize_t get_line_buffer(char** lineptr, size_t* n,
const char* const buffer, size_t csv_data_size, const char* const csv_data_buffer,
size_t& curr_char) { size_t csv_data_size, size_t& curr_char) {
size_t pos; if (lineptr == nullptr || n == nullptr ||
int c; csv_data_buffer == nullptr) {
errno = EINVAL;
return -1;
}
if (curr_char >= csv_data_size) { if (curr_char >= csv_data_size) {
return -1; return -1;
} }
c = buffer[curr_char++];
if (*lineptr == nullptr) { if (*lineptr == nullptr || *n < get_line_initial_buffer_size) {
*lineptr = auto new_lineptr = static_cast<char*>(
static_cast<char*>(malloc(get_line_initial_buffer_size)); realloc(*lineptr, get_line_initial_buffer_size));
if (*lineptr == nullptr) { if (new_lineptr == nullptr) {
return -1; return -1;
} }
*n = 128; *lineptr = new_lineptr;
*n = get_line_initial_buffer_size;
} }
pos = 0; size_t line_used = 0;
while (curr_char <= csv_data_size) { while (curr_char <= csv_data_size) {
if (pos + 1 >= *n) { if (line_used + 1 >= *n) {
size_t new_size = *n + (*n >> 2); size_t new_n = *n * 2;
if (new_size < get_line_initial_buffer_size) {
new_size = get_line_initial_buffer_size; char* new_lineptr =
} static_cast<char*>(realloc(*lineptr, new_n));
char* new_ptr = static_cast<char*>( if (new_lineptr == nullptr) {
realloc(static_cast<void*>(*lineptr), new_size)); errno = ENOMEM;
if (new_ptr == nullptr) {
return -1; return -1;
} }
*n = new_size; *n = new_n;
*lineptr = new_ptr; *lineptr = new_lineptr;
} }
(*lineptr)[pos++] = c; auto c = csv_data_buffer[curr_char++];
(*lineptr)[line_used++] = c;
if (c == '\n') { if (c == '\n') {
break; (*lineptr)[line_used] = '\0';
return line_used;
} }
c = buffer[curr_char++];
} }
(*lineptr)[pos] = '\0'; return (line_used != 0) ? line_used : -1;
return pos;
} }
// read next line each time in order to set eof_ // read next line each time in order to set eof_

View File

@ -571,9 +571,22 @@ template <bool buffer_mode>
void test_no_new_line_at_eof() { void test_no_new_line_at_eof() {
test_no_new_line_at_eof_impl<buffer_mode>({}); test_no_new_line_at_eof_impl<buffer_mode>({});
test_no_new_line_at_eof_impl<buffer_mode>({{1, 2, "X"}}); test_no_new_line_at_eof_impl<buffer_mode>({{1, 2, "X"}});
test_no_new_line_at_eof_impl<buffer_mode>({{1, 2, "X"}, {}});
test_no_new_line_at_eof_impl<buffer_mode>({{1, 2, "X"}, {3, 4, "YY"}}); test_no_new_line_at_eof_impl<buffer_mode>({{1, 2, "X"}, {3, 4, "YY"}});
test_no_new_line_at_eof_impl<buffer_mode>({{1, 2, "X"}, {3, 4, "YY"}, {}});
test_no_new_line_at_eof_impl<buffer_mode>( test_no_new_line_at_eof_impl<buffer_mode>(
{{1, 2, "X"}, {3, 4, "YY"}, {5, 6, "ZZZ"}, {7, 8, "UUU"}}); {{1, 2, "X"}, {3, 4, "YY"}, {5, 6, "ZZZ"}, {7, 8, "UUU"}});
for (size_t i = 0; i < 2 * ss::get_line_initial_buffer_size; ++i) {
test_no_new_line_at_eof_impl<buffer_mode>(
{{1, 2, std::string(i, 'X')}});
for (size_t j = 0; j < 2 * ss::get_line_initial_buffer_size; ++j) {
test_no_new_line_at_eof_impl<buffer_mode>(
{{1, 2, std::string(i, 'X')}, {3, 4, std::string(j, 'Y')}});
}
}
} }
TEST_CASE("test no new line at end of data") { TEST_CASE("test no new line at end of data") {