/**
* ======================== legal notice ======================
*
* File: StringBuilder.cc
* Created: 6. Juli 2012, 10:54
* Author: Geronimo
* Project: libutil - base classes used by other libraries
*
* CMP - compound media player
*
* is a client/server mediaplayer intended to play any media from any workstation
* without the need to export or mount shares. cmps is an easy to use backend
* with a (ready to use) HTML-interface. Additionally the backend supports
* authentication via HTTP-digest authorization.
* cmpc is a client with vdr-like osd-menues.
*
* Copyright (c) 2012 Reinhard Mantey, some rights reserved!
* published under Creative Commons by-sa
* For details see http://creativecommons.org/licenses/by-sa/3.0/
*
* The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp
*
* --------------------------------------------------------------
*/
#include
#include
#include
#include
#include
static void freeStringCallback(void *elem)
{
free(elem);
}
cStringBuilder::cStringBuilder(const char *First)
: chunkSize(127)
, readOffset(0)
, writeOffset(0)
, pool(freeStringCallback)
{
init();
if (First) Append(First);
}
cStringBuilder::cStringBuilder(int ChunkSize)
: chunkSize(ChunkSize)
, readOffset(0)
, writeOffset(0)
, pool(freeStringCallback)
{
init();
}
cStringBuilder::~cStringBuilder()
{
}
void cStringBuilder::init(void)
{
char *first = (char *) malloc(chunkSize);
pool.push_back(first);
}
void cStringBuilder::Write(const char *Text)
{
if (!Text) {
esyslog("ERROR: text to add is a NULL-ponter!");
return;
}
uint chunkFree = chunkSize - writeOffset;
char *curChunk = (char *) pool[pool.size() - 1];
const char *p = Text;
while (strlen(p) >= chunkFree) {
strncpy(curChunk + writeOffset, p, chunkFree);
p += chunkFree;
curChunk = (char *) malloc(chunkSize);
pool.push_back(curChunk);
writeOffset = 0;
chunkFree = chunkSize;
}
if (strlen(p)) {
strcpy(curChunk + writeOffset, p);
writeOffset += strlen(p);
}
}
size_t cStringBuilder::Size()
{
return (pool.size() - 1) * chunkSize + writeOffset;
}
size_t cStringBuilder::Size() const
{
return (pool.size() - 1) * chunkSize + writeOffset;
}
size_t cStringBuilder::Copy(char* Buf, size_t BufSize)
{
uint chunkNo = readOffset / chunkSize;
uint chunkOff = readOffset % chunkSize;
uint bytes2Write = chunkSize;
char *curChunk = (char *) pool[chunkNo];
size_t bytesWritten = 0;
if (chunkNo == (pool.size() - 1)) bytes2Write = writeOffset;
while ((BufSize - bytesWritten) > (bytes2Write - chunkOff)) {
strncpy(Buf + bytesWritten, curChunk + chunkOff, bytes2Write - chunkOff);
bytesWritten += bytes2Write - chunkOff;
chunkOff = 0;
if (++chunkNo < (pool.size() - 1)) bytes2Write = chunkSize;
else bytes2Write = writeOffset;
if (chunkNo == pool.size()) break;
curChunk = (char *) pool[chunkNo];
}
readOffset += bytesWritten;
return bytesWritten;
}
cStringBuilder &cStringBuilder::Append(const char* Text)
{
if (!Text) Write("(null)");
Write(Text);
return *this;
}
cStringBuilder &cStringBuilder::Append(bool v, const char *TrueValue, const char *FalseValue)
{
if (v) Write(TrueValue);
else Write(FalseValue);
return *this;
}
cStringBuilder &cStringBuilder::Append(double v)
{
char *elem = NULL;
asprintf(&elem, "%lg", v);
if (elem) {
Write(elem);
free(elem);
}
return *this;
}
cStringBuilder &cStringBuilder::Append(int v)
{
char buf[12];
if (snprintf(buf, sizeof(buf), "%d", v)) Write(buf);
return *this;
}
cStringBuilder &cStringBuilder::Append(long v)
{
char buf[24];
if (snprintf(buf, sizeof(buf), "%ld", v)) Write(buf);
return *this;
}
cStringBuilder &cStringBuilder::Append(size_t v)
{
char buf[24];
if (snprintf(buf, sizeof(buf), "%lu", v)) Write(buf);
return *this;
}