outbuf = (UCHAR*) malloc(bufsize);
if (!outbuf) return 0;
bufferSize = bufsize;
- bufferHead = bufferTail = 0;
+ bufferHead = 0;
+ bufferTail = 0;
+ bufferMark = -1;
initted = 1;
return 1;
}
void Stream::flush()
{
- bufferHead = bufferTail = 0;
+ bufferHead = 0;
+ bufferTail = 0;
+ bufferMark = -1;
}
int Stream::put(UCHAR* inbuf, int len)
{
int ret = 0;
- int freespace;
- int localTail = bufferTail;
- if (localTail == 0) localTail = bufferSize;
- if (len == 0) return ret;
+ int tail = bufferTail;
+ int head = bufferHead;
+ if (tail == 0) tail = bufferSize;
- freespace = localTail - bufferHead - 1;
- if (freespace < 0) freespace += bufferSize;
- if (len > freespace) return ret;
-
- if (bufferHead >= localTail)
+ if (head < tail)
{
- // We have free rein to the end of the buffer
- if (len < (bufferSize - bufferHead))
+ // The free space is in one continuous chunk.
+ if (len < tail - head)
{
- // We won't reach the end of the buffer.
- memcpy(outbuf + bufferHead, inbuf, len);
+ memcpy(outbuf + head, inbuf, len);
bufferHead += len;
- ret += len; return ret;
- } else
- {
- // We'll reach the end of the buffer and loop round.
- memcpy(outbuf + bufferHead, inbuf, (bufferSize - bufferHead));
- inbuf += (bufferSize - bufferHead);
- ret += (bufferSize - bufferHead);
- len -= (bufferSize - bufferHead);
- bufferHead = 0;
- if (len == 0) return ret;
+ ret = len;
}
}
-
- if (localTail - bufferHead == 1) return ret; // Full
-
- // We can advance the head up to the tail
- // If we reach it, we are full.
- if (len < (localTail - bufferHead - 1))
+ else if (len <= bufferSize - head)
{
- // We'll fall short of the tail.
- memcpy(outbuf + bufferHead, inbuf, len);
- bufferHead += len;
- ret += len; return ret;
- } else
+ // There is enough space above the Head.
+ memcpy(outbuf + head, inbuf, len);
+ if (head + len == bufferSize)
+ bufferHead = 0;
+ else
+ bufferHead += len;
+ ret = len;
+ }
+ else if (len < tail)
{
- // We'll hit the tail.
- memcpy(outbuf + bufferHead, inbuf, (localTail - bufferHead - 1));
- ret += (localTail - bufferHead - 1);
- bufferHead = localTail - 1;
- return ret;
+ bufferMark = head;
+ memcpy(outbuf, inbuf, len);
+ bufferHead = len;
+ ret = len;
}
+ return ret;
}
-
+
int Stream::drain(int fd)
{
int ret = 0;
- int localHead = bufferHead;
+ int head = bufferHead;
+ int tail = bufferTail;
+ int mark = bufferMark;
int written;
- if (localHead < bufferTail)
+ if (mark == -1 && tail > head) mark = bufferSize;
+
+ if (mark >= 0)
{
- // Drain to the end of the buffer
- written = write(fd, outbuf + bufferTail, (bufferSize - bufferTail));
+ // Drain up to the marker.
+ written = write(fd, outbuf + tail, (mark - tail));
if (written < 0) return ret;
ret += written;
- if (written == (bufferSize - bufferTail))
- bufferTail = 0;
+ if (written == (mark - tail))
+ {
+ bufferMark = -1;
+ bufferTail = tail = 0;
+ }
else
{
bufferTail += written;
}
}
- if (localHead == bufferTail) return ret; // Empty
+ if (tail == head) return ret; // Empty
- written = write(fd, outbuf + bufferTail, (localHead - bufferTail));
+ written = write(fd, outbuf + tail, (head - tail));
if (written < 0) return ret;
ret += written;
- bufferTail += written;
+ bufferTail = tail + written;
return ret;
}