tools api: Add io__getline
Reads a line to allocated memory up to a newline following the getline API. Committer notes: It also adds this new function to the 'api io' 'perf test' entry: $ perf test "api io" 64: Test api io : Ok $ Signed-off-by: Ian Rogers <irogers@google.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Acked-by: Namhyung Kim <namhyung@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Nathan Chancellor <nathan@kernel.org> Cc: Nick Desaulniers <ndesaulniers@google.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Tom Rix <trix@redhat.com> Cc: llvm@lists.linux.dev Link: https://lore.kernel.org/r/20230403184033.1836023-2-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
98b7ce0ed8
commit
c9dc580c43
@ -7,7 +7,9 @@
|
||||
#ifndef __API_IO__
|
||||
#define __API_IO__
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
struct io {
|
||||
@ -112,4 +114,47 @@ static inline int io__get_dec(struct io *io, __u64 *dec)
|
||||
}
|
||||
}
|
||||
|
||||
/* Read up to and including the first newline following the pattern of getline. */
|
||||
static inline ssize_t io__getline(struct io *io, char **line_out, size_t *line_len_out)
|
||||
{
|
||||
char buf[128];
|
||||
int buf_pos = 0;
|
||||
char *line = NULL, *temp;
|
||||
size_t line_len = 0;
|
||||
int ch = 0;
|
||||
|
||||
/* TODO: reuse previously allocated memory. */
|
||||
free(*line_out);
|
||||
while (ch != '\n') {
|
||||
ch = io__get_char(io);
|
||||
|
||||
if (ch < 0)
|
||||
break;
|
||||
|
||||
if (buf_pos == sizeof(buf)) {
|
||||
temp = realloc(line, line_len + sizeof(buf));
|
||||
if (!temp)
|
||||
goto err_out;
|
||||
line = temp;
|
||||
memcpy(&line[line_len], buf, sizeof(buf));
|
||||
line_len += sizeof(buf);
|
||||
buf_pos = 0;
|
||||
}
|
||||
buf[buf_pos++] = (char)ch;
|
||||
}
|
||||
temp = realloc(line, line_len + buf_pos + 1);
|
||||
if (!temp)
|
||||
goto err_out;
|
||||
line = temp;
|
||||
memcpy(&line[line_len], buf, buf_pos);
|
||||
line[line_len + buf_pos] = '\0';
|
||||
line_len += buf_pos;
|
||||
*line_out = line;
|
||||
*line_len_out = line_len;
|
||||
return line_len;
|
||||
err_out:
|
||||
free(line);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
#endif /* __API_IO__ */
|
||||
|
@ -289,6 +289,40 @@ static int test_get_dec(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int test_get_line(void)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
struct io io;
|
||||
char test_string[1024];
|
||||
char *line = NULL;
|
||||
size_t i, line_len = 0;
|
||||
size_t buf_size = 128;
|
||||
int ret = 0;
|
||||
|
||||
for (i = 0; i < 512; i++)
|
||||
test_string[i] = 'a';
|
||||
test_string[512] = '\n';
|
||||
for (i = 513; i < 1023; i++)
|
||||
test_string[i] = 'b';
|
||||
test_string[1023] = '\0';
|
||||
|
||||
if (setup_test(path, test_string, buf_size, &io))
|
||||
return -1;
|
||||
|
||||
EXPECT_EQUAL((int)io__getline(&io, &line, &line_len), 513);
|
||||
EXPECT_EQUAL((int)strlen(line), 513);
|
||||
for (i = 0; i < 512; i++)
|
||||
EXPECT_EQUAL(line[i], 'a');
|
||||
EXPECT_EQUAL(line[512], '\n');
|
||||
EXPECT_EQUAL((int)io__getline(&io, &line, &line_len), 510);
|
||||
for (i = 0; i < 510; i++)
|
||||
EXPECT_EQUAL(line[i], 'b');
|
||||
|
||||
free(line);
|
||||
cleanup_test(path, &io);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int test__api_io(struct test_suite *test __maybe_unused,
|
||||
int subtest __maybe_unused)
|
||||
{
|
||||
@ -300,6 +334,8 @@ static int test__api_io(struct test_suite *test __maybe_unused,
|
||||
ret = TEST_FAIL;
|
||||
if (test_get_dec())
|
||||
ret = TEST_FAIL;
|
||||
if (test_get_line())
|
||||
ret = TEST_FAIL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user