diff options
author | Max Kellermann <max@duempel.org> | 2014-08-07 12:41:39 +0200 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2014-08-07 16:08:02 +0200 |
commit | 36ff991960f4d298a97cee3f8f0ffcaa30686466 (patch) | |
tree | 005d598b9157c31ff6e27f3d217405f9fa8cc708 /src/input | |
parent | 59d38f876a22ef520c6b897a356e8fb8677481aa (diff) | |
download | mpd-36ff991960f4d298a97cee3f8f0ffcaa30686466.tar.gz mpd-36ff991960f4d298a97cee3f8f0ffcaa30686466.tar.xz mpd-36ff991960f4d298a97cee3f8f0ffcaa30686466.zip |
TextInputStream: move code to ReadBufferedLine()
Look at the buffer first, before trying to read from the file. This
reduces overhead because we don't refill the buffer after every line.
Diffstat (limited to 'src/input')
-rw-r--r-- | src/input/TextInputStream.cxx | 76 | ||||
-rw-r--r-- | src/input/TextInputStream.hxx | 3 |
2 files changed, 45 insertions, 34 deletions
diff --git a/src/input/TextInputStream.cxx b/src/input/TextInputStream.cxx index 177606d6d..0eb5bc1a8 100644 --- a/src/input/TextInputStream.cxx +++ b/src/input/TextInputStream.cxx @@ -28,51 +28,59 @@ #include <string.h> char * -TextInputStream::ReadLine() +TextInputStream::ReadBufferedLine() { - char *src, *p; - - do { - size_t nbytes; - auto dest = buffer.Write(); - if (dest.size >= 2) { - /* reserve one byte for the null terminator if - the last line is not terminated by a - newline character */ - --dest.size; + auto r = buffer.Read(); + char *newline = reinterpret_cast<char*>(memchr(r.data, '\n', r.size)); + if (newline == nullptr) + return nullptr; - Error error; - nbytes = is.LockRead(dest.data, dest.size, error); - if (nbytes > 0) - buffer.Append(nbytes); - else if (error.IsDefined()) { - LogError(error); - return nullptr; - } - } else - nbytes = 0; + buffer.Consume(newline + 1 - r.data); - auto src_p = buffer.Read(); - if (src_p.IsEmpty()) - return nullptr; + char *end = StripRight(r.data, newline); + *end = 0; + return r.data; +} - src = src_p.data; +char * +TextInputStream::ReadLine() +{ + char *line = ReadBufferedLine(); + if (line != nullptr) + return line; - p = reinterpret_cast<char*>(memchr(src, '\n', src_p.size)); - if (p == nullptr && nbytes == 0) { + while (true) { + auto dest = buffer.Write(); + if (dest.size < 2) { /* end of file (or line too long): terminate the current line */ - dest = buffer.Write(); + assert(!dest.IsEmpty()); dest[0] = 0; + line = buffer.Read().data; buffer.Clear(); - return src; + return line; } - } while (p == nullptr); - buffer.Consume(p - src + 1); + /* reserve one byte for the null terminator if the + last line is not terminated by a newline + character */ + --dest.size; - char *end = StripRight(src, p); - *end = 0; - return src; + Error error; + size_t nbytes = is.LockRead(dest.data, dest.size, error); + if (nbytes > 0) + buffer.Append(nbytes); + else if (error.IsDefined()) { + LogError(error); + return nullptr; + } + + line = ReadBufferedLine(); + if (line != nullptr) + return line; + + if (nbytes == 0) + return nullptr; + } } diff --git a/src/input/TextInputStream.hxx b/src/input/TextInputStream.hxx index 6f39d22cf..ce1eaddff 100644 --- a/src/input/TextInputStream.hxx +++ b/src/input/TextInputStream.hxx @@ -47,6 +47,9 @@ public: * @return a pointer to the line, or nullptr on end-of-file or error */ char *ReadLine(); + +private: + char *ReadBufferedLine(); }; #endif |