From 80c91aa91e18f94e3bcaefb15a26a9f55875024c Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Wed, 3 Jul 2013 16:16:38 +0200 Subject: [PATCH] stream/livestatus: refactor ReadLine with context saving --- components/livestatus/component.cpp | 6 +-- lib/base/stream.cpp | 60 +++++++++++++++++------------ lib/base/stream.h | 13 ++++++- 3 files changed, 50 insertions(+), 29 deletions(-) diff --git a/components/livestatus/component.cpp b/components/livestatus/component.cpp index fe30e165d..7ef313851 100644 --- a/components/livestatus/component.cpp +++ b/components/livestatus/component.cpp @@ -84,13 +84,11 @@ void LivestatusComponent::ClientThreadProc(const Socket::Ptr& client) for (;;) { String line; - bool read_line = false; + ReadLineContext context; std::vector lines; - while (stream->ReadLine(&line)) { - read_line = true; - + while (stream->ReadLine(&line, context)) { if (line.GetLength() > 0) lines.push_back(line); else diff --git a/lib/base/stream.cpp b/lib/base/stream.cpp index 1405194c4..0ef95715c 100644 --- a/lib/base/stream.cpp +++ b/lib/base/stream.cpp @@ -24,42 +24,54 @@ using namespace icinga; -bool Stream::ReadLine(String *line, size_t maxLength) +bool Stream::ReadLine(String *line, ReadLineContext& context, size_t maxLength) { - BOOST_THROW_EXCEPTION(std::runtime_error("Not implemented.")); - /* - char *buffer = new char[maxLength]; + if (context.Eof) + return false; - size_t rc = Peek(buffer, maxLength); + for (;;) { + if (context.MustRead) { + context.Buffer = (char *)realloc(context.Buffer, context.Size + maxLength); - if (rc == 0) - return false; + if (!context.Buffer) + throw std::bad_alloc(); - for (size_t i = 0; i < rc; i++) { - if (buffer[i] == '\n') { - *line = String(buffer, &(buffer[i])); - boost::algorithm::trim_right(*line); + size_t rc = Read(context.Buffer + context.Size, maxLength); - Read(NULL, i + 1); + if (rc == 0) { + *line = String(context.Buffer, &(context.Buffer[context.Size])); + boost::algorithm::trim_right(*line); - delete buffer; + context.Eof = true; - return true; + return true; + } + + context.Size += rc; } - } - if (IsReadEOF()) { - *line = String(buffer, buffer + rc); - boost::algorithm::trim_right(*line); + int count = 0; + size_t first_newline; - Read(NULL, rc); + for (size_t i = 0; i < context.Size; i++) { + if (context.Buffer[i] == '\n') { + count++; - delete buffer; + if (count == 1) + first_newline = i; + } + } - return true; - } + context.MustRead = (count <= 1); + + if (count > 0) { + *line = String(context.Buffer, &(context.Buffer[first_newline])); + boost::algorithm::trim_right(*line); - delete buffer;*/ + memmove(context.Buffer, context.Buffer + first_newline + 1, context.Size - first_newline - 1); + context.Size -= first_newline + 1; - return false; + return true; + } + } } diff --git a/lib/base/stream.h b/lib/base/stream.h index 510cbb0cd..b51eb59ad 100644 --- a/lib/base/stream.h +++ b/lib/base/stream.h @@ -29,6 +29,17 @@ namespace icinga { +struct ReadLineContext +{ + ReadLineContext(void) : Buffer(NULL), Size(0), Eof(false), MustRead(true) + { } + + char *Buffer; + size_t Size; + bool Eof; + bool MustRead; +}; + /** * A stream. * @@ -64,7 +75,7 @@ public: */ virtual void Close(void) = 0; - bool ReadLine(String *line, size_t maxLength = 4096); + bool ReadLine(String *line, ReadLineContext& context, size_t maxLength = 4096); }; } -- 2.40.0