summaryrefslogtreecommitdiff
path: root/apps/misc.c
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2017-12-12 15:57:51 -0500
committerMichael Sevakis <jethead71@rockbox.org>2017-12-12 15:57:51 -0500
commit838ff9c67d4ade0e0e0ee7132eb933a7c861d384 (patch)
tree8013402e9bb89e342ef2d7545df1b0aacc40b547 /apps/misc.c
parentcd3ea086ec3db709c6682d85f8a97b96646cbb4f (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.c42
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;
}