mirror of
https://github.com/johnkerl/miller.git
synced 2026-07-25 08:53:55 +00:00
line-reader iterate
This commit is contained in:
parent
00a7125b04
commit
dee19f1896
3 changed files with 152 additions and 1 deletions
|
|
@ -148,3 +148,46 @@ ssize_t local_getdelim(char** restrict pline, size_t* restrict plinecap, int del
|
|||
//
|
||||
// reuse linecap on subsequent calls. power of two above last readlen.
|
||||
// work autodetect deeper into the callstack
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
char* mlr_alloc_read_line_single_delimiter(
|
||||
FILE* fp,
|
||||
int delimiter,
|
||||
int* preached_eof,
|
||||
size_t* pold_then_new_strlen,
|
||||
size_t* pold_then_new_linecap)
|
||||
{
|
||||
// xxx wip
|
||||
size_t linecap = power_of_two_above(*pold_then_new_strlen);
|
||||
char* restrict line = mlr_malloc_or_die(linecap);
|
||||
char* restrict p = line;
|
||||
int reached_eof = FALSE;
|
||||
int c;
|
||||
|
||||
while (TRUE) {
|
||||
size_t offset = p - line;
|
||||
if (offset >= linecap) {
|
||||
linecap = linecap << 1;
|
||||
line = mlr_realloc_or_die(line, linecap);
|
||||
p = line + offset;
|
||||
}
|
||||
c = mlr_arch_getc(fp);
|
||||
if (c == delimiter) {
|
||||
*(p++) = 0;
|
||||
break;
|
||||
} else if (c == EOF) {
|
||||
*(p++) = 0;
|
||||
if (p == line)
|
||||
reached_eof = TRUE;
|
||||
break;
|
||||
} else {
|
||||
*(p++) = c;
|
||||
}
|
||||
}
|
||||
|
||||
*preached_eof = reached_eof;
|
||||
*pold_then_new_strlen = p - line - 1; // exclude null terminator
|
||||
*pold_then_new_linecap = linecap;
|
||||
|
||||
return line;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,4 +24,25 @@ char* mlr_get_sline(FILE* input_stream, char* irs, int irslen);
|
|||
// inside mlr_arch.c, for unit-testing visibility.
|
||||
ssize_t local_getdelim(char** restrict pline, size_t* restrict plinecap, int delimiter, FILE* restrict stream);
|
||||
|
||||
// xxx type up comments:
|
||||
// * in delimiter (single/multiple)
|
||||
// * in fp
|
||||
// * -in do_auto_line_term- separate variant
|
||||
// * -inout pctx- separate variant
|
||||
// * out line
|
||||
// * out reached eof
|
||||
// * inout strlen (old/new). DEFAULT_SIZE @ first call
|
||||
// * inout linecap (old/new) DEFAULT_SIZE @ first call
|
||||
//
|
||||
// reuse linecap on subsequent calls. power of two above last readlen.
|
||||
// work autodetect deeper into the callstack
|
||||
|
||||
#define MLR_ALLOC_READ_LINE_INITIAL_SIZE 128
|
||||
char* mlr_alloc_read_line_single_delimiter(
|
||||
FILE* fp,
|
||||
int delimiter,
|
||||
int* preached_eof,
|
||||
size_t* pold_then_new_strlen,
|
||||
size_t* pold_then_new_linecap);
|
||||
|
||||
#endif // LINE_READERS_H
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ static FILE* fopen_or_die(char* filename) {
|
|||
return fp;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static char* test_getdelim_impl(getdelim_t* pgetdelim) {
|
||||
char delimiter = '\n';
|
||||
char* contents = NULL;
|
||||
|
|
@ -108,6 +109,92 @@ static char* test_getdelim_impl(getdelim_t* pgetdelim) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static char* test_mlr_alloc_read_line_single_delimiter() {
|
||||
#if 0
|
||||
char delimiter = '\n';
|
||||
char* path = NULL;
|
||||
FILE* fp = NULL;
|
||||
char* contents = NULL;
|
||||
char* line = NULL;
|
||||
int reached_eof = FALSE;
|
||||
size_t linelen = 0;
|
||||
size_t linecap = 0;
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
contents = "";
|
||||
path = write_temp_file_or_die(contents);
|
||||
fp = fopen_or_die(path);
|
||||
|
||||
// Read line
|
||||
linecap = 4;
|
||||
line = mlr_alloc_read_line_single_delimiter(fp, delimiter, &reached_eof, &linelen, &linecap);
|
||||
printf("reof=%d,linelen=%d,linecap=%d,line=\"%s\"\n", (int)reached_eof, (int)linelen, (int)linecap, line);
|
||||
mu_assert_lf(line != NULL);
|
||||
mu_assert_lf(streq(line, ""));
|
||||
mu_assert_lf(reached_eof == TRUE);
|
||||
mu_assert_lf(linelen == strlen(""));
|
||||
mu_assert_lf(linecap > linelen);
|
||||
|
||||
// Read past EOF
|
||||
line = mlr_alloc_read_line_single_delimiter(fp, delimiter, &reached_eof, &linelen, &linecap);
|
||||
mu_assert_lf(line != NULL);
|
||||
mu_assert_lf(streq(line, ""));
|
||||
mu_assert_lf(reached_eof == TRUE);
|
||||
|
||||
fclose(fp);
|
||||
unlink_file_or_die(path);
|
||||
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
contents = "\n";
|
||||
path = write_temp_file_or_die(contents);
|
||||
fp = fopen_or_die(path);
|
||||
|
||||
// Read line
|
||||
line = NULL;
|
||||
linecap = 0;
|
||||
rc = (*pgetdelim)(&line, &linecap, delimiter, fp);
|
||||
mu_assert_lf(rc == 1);
|
||||
mu_assert_lf(streq(line, "\n"));
|
||||
mu_assert_lf(linecap >= 1+strlen(contents));
|
||||
|
||||
// Read past EOF
|
||||
line = NULL;
|
||||
linecap = 0;
|
||||
rc = (*pgetdelim)(&line, &linecap, delimiter, fp);
|
||||
mu_assert_lf(rc == -1);
|
||||
|
||||
|
||||
fclose(fp);
|
||||
unlink_file_or_die(path);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
contents = "\r\n";
|
||||
path = write_temp_file_or_die(contents);
|
||||
fp = fopen_or_die(path);
|
||||
|
||||
// Read line
|
||||
line = NULL;
|
||||
linecap = 0;
|
||||
rc = (*pgetdelim)(&line, &linecap, delimiter, fp);
|
||||
mu_assert_lf(rc == 2);
|
||||
mu_assert_lf(streq(line, "\r\n"));
|
||||
mu_assert_lf(linecap >= 1+strlen(contents));
|
||||
|
||||
// Read past EOF
|
||||
line = NULL;
|
||||
linecap = 0;
|
||||
rc = (*pgetdelim)(&line, &linecap, delimiter, fp);
|
||||
mu_assert_lf(rc == -1);
|
||||
|
||||
|
||||
fclose(fp);
|
||||
unlink_file_or_die(path);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// On unixish platforms this is testing the system getdelim() which is correct by definition.
|
||||
// (At least, we verify it's behaving as we expect.) On Windows, this tests our local_getdelim
|
||||
|
|
@ -126,7 +213,7 @@ static char* test_getdelim() {
|
|||
// ================================================================
|
||||
static char * run_all_tests() {
|
||||
mu_run_test(test_getdelim);
|
||||
// xxx WIP mu_run_test(test_local_getdelim);
|
||||
mu_run_test(test_mlr_alloc_read_line_single_delimiter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue