diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2017-12-12 15:57:51 -0500 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2017-12-12 15:57:51 -0500 |
commit | 838ff9c67d4ade0e0e0ee7132eb933a7c861d384 (patch) | |
tree | 8013402e9bb89e342ef2d7545df1b0aacc40b547 /apps/misc.c | |
parent | cd3ea086ec3db709c6682d85f8a97b96646cbb4f (diff) |
Add a 32 byte read buffer to read_line.
Do as with fdprintf and avoid filesystem calls for every single
byte. If it overreads, just put the excess back with lseek, which
does no I/O itself.
Change-Id: Ifd5d21b5dca7183346e44d365d3f7d45e8cc6438
Diffstat (limited to 'apps/misc.c')
-rw-r--r-- | apps/misc.c | 42 |
1 files changed, 32 insertions, 10 deletions
diff --git a/apps/misc.c b/apps/misc.c index 047098556f..477efc6313 100644 --- a/apps/misc.c +++ b/apps/misc.c @@ -1029,32 +1029,54 @@ int format_sound_value(char *buf, size_t size, int snd, int val) */ int read_line(int fd, char* buffer, int buffer_size) { + if (!buffer || buffer_size-- <= 0) + { + errno = EINVAL; + return -1; + } + + unsigned char rdbuf[32]; + off_t rdbufend = 0; + int rdbufidx = 0; int count = 0; int num_read = 0; - errno = 0; - while (count < buffer_size) { - unsigned char c; + if (rdbufidx >= rdbufend) + { + rdbufidx = 0; + rdbufend = read(fd, rdbuf, sizeof (rdbuf)); - if (1 != read(fd, &c, 1)) - break; + if (rdbufend <= 0) + break; - num_read++; + num_read += rdbufend; + } + + int c = rdbuf[rdbufidx++]; - if ( c == '\n' ) + if (c == '\n') break; - if ( c == '\r' ) + if (c == '\r') continue; buffer[count++] = c; } - buffer[MIN(count, buffer_size - 1)] = 0; + rdbufidx -= rdbufend; + + if (rdbufidx < 0) + { + /* "put back" what wasn't read from the buffer */ + num_read += rdbufidx; + rdbufend = lseek(fd, rdbufidx, SEEK_CUR); + } + + buffer[count] = '\0'; - return errno ? -1 : num_read; + return rdbufend >= 0 ? num_read : -1; } |