summaryrefslogtreecommitdiffstats
path: root/configd/src/apps/sentinel/line-splitter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'configd/src/apps/sentinel/line-splitter.cpp')
-rw-r--r--configd/src/apps/sentinel/line-splitter.cpp110
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
+
+