diff options
Diffstat (limited to 'configd/src/apps/sentinel/line-splitter.cpp')
-rw-r--r-- | configd/src/apps/sentinel/line-splitter.cpp | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/configd/src/apps/sentinel/line-splitter.cpp b/configd/src/apps/sentinel/line-splitter.cpp new file mode 100644 index 00000000000..8e990475b99 --- /dev/null +++ b/configd/src/apps/sentinel/line-splitter.cpp @@ -0,0 +1,110 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + + +#include <errno.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include <algorithm> +#include <cstdlib> + +#include <unistd.h> + +#include "line-splitter.h" + +namespace config { +namespace sentinel { + + +LineSplitter::LineSplitter(int fd) + : _fd(fd), + _size(8192), + _buffer(static_cast<char *>(malloc(_size))), + _readPos(0), + _writePos(0), + _eof(false) +{ +} + +LineSplitter::~LineSplitter() +{ + free(_buffer); +} + +bool +LineSplitter::resize() +{ + _size = _size * 2; + _buffer = static_cast<char *>(realloc(_buffer, _size)); + return (_buffer != NULL); +} + + +bool +LineSplitter::fill() +{ + // Check if we have read to end + int leftToWrite = _writePos - _readPos; + if (leftToWrite == 0) { + _writePos = 0; + _readPos = 0; + } else if (_readPos > 0) { // Move to front + memmove(_buffer, &_buffer[_readPos], leftToWrite); + _writePos -= _readPos; + _readPos = 0; + } + + // If buffer is full, resize it + if (_writePos >= _size) { + if (!resize()) { + _eof = true; + shutdown(_fd, SHUT_RD); + return false; + } + } + + int readLen = read(_fd, &_buffer[_writePos], _size - _writePos); + if (readLen == -1) { + if (errno != EINTR && errno != EAGAIN) { + _eof = true; + } + } else if (readLen == 0) { + _eof = true; + if (_buffer[_writePos] != '\n') { + _buffer[_writePos++] = '\n'; // Fake a final separator + } + } else { + _writePos += readLen; + } + + return readLen > 0; +} + +char * +LineSplitter::getLine() +{ + do { + int bufLen = _writePos - _readPos; + + if (bufLen > 0) { + char *start = &_buffer[_readPos]; + char *end = static_cast<char *>(memchr(start, '\n', bufLen)); + if (end) { + *end = '\0'; + if (end - start > 0 && end[-1] == '\r') { + // Get rid of carriage return as well. + end[-1] = '\0'; + } + _readPos = (end - _buffer) + 1; + return start; + } + } + } while (!_eof && fill()); + return NULL; +} + +} // end namespace config::sentinel +} // end namespace config + + |