1
/* Copyright (C) 2008 PrimeBase Technologies GmbH, Germany
3
* PrimeBase Media Stream for MySQL
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
* Original author: Paul McCullagh (H&G2JCtL)
20
* Continued development: Barry Leslie
25
* Basic input and output streams.
27
* These objects wrap the system streams, and simplify things.
28
* I also want to standardize exceptions and implement
29
* socket based streams.
43
* ---------------------------------------------------------------
47
void CSStream::pipe(CSOutputStream *out, CSInputStream *in)
56
buffer = (char *) cs_malloc(DEFAULT_BUFFER_SIZE);
60
size = in->read(buffer, DEFAULT_BUFFER_SIZE);
64
out->write(buffer, size);
77
* ---------------------------------------------------------------
81
CSStringBuffer *CSInputStream::readLine()
84
CSStringBuffer *sb = NULL;
90
new_(sb, CSStringBuffer(20));
93
while (ch != '\n' && ch != '\r' && ch != -1) {
94
sb->append((char) ch);
109
* ---------------------------------------------------------------
113
void CSOutputStream::printLine(const char *cstr)
122
void CSOutputStream::print(const char *cstr)
125
write(cstr, strlen(cstr));
129
void CSOutputStream::print(CSString *s)
132
print(s->getCString());
136
void CSOutputStream::print(int value)
140
snprintf(buffer, 20, "%d", value);
144
void CSOutputStream::print(uint64_t value)
148
snprintf(buffer, 30, "%"PRIu64"", value);
153
* ---------------------------------------------------------------
157
CSFileInputStream::~CSFileInputStream()
163
size_t CSFileInputStream::read(char *b, size_t len)
168
size = iFile->read(b, iReadOffset, len, 0);
173
int CSFileInputStream::read()
179
size = iFile->read(&ch, iReadOffset, 1, 0);
181
return_(size == 0 ? -1 : (int) ch);
184
void CSFileInputStream::reset()
189
const char *CSFileInputStream::identify()
191
return iFile->myFilePath->getCString();
194
int CSFileInputStream::peek()
200
size = iFile->read(&ch, iReadOffset, 1, 0);
201
return_(size == 0 ? -1 : (int) ch);
204
void CSFileInputStream::close()
211
CSFileInputStream *CSFileInputStream::newStream(CSFile *f)
213
CSFileInputStream *s;
215
if (!(s = new CSFileInputStream())) {
217
CSException::throwOSError(CS_CONTEXT, ENOMEM);
223
CSFileInputStream *CSFileInputStream::newStream(CSFile *f, off64_t offset)
225
CSFileInputStream *s;
227
if (!(s = new CSFileInputStream())) {
229
CSException::throwOSError(CS_CONTEXT, ENOMEM);
232
s->iReadOffset = offset;
237
* ---------------------------------------------------------------
238
* FILE OUTPUT STREAMS
241
CSFileOutputStream::~CSFileOutputStream()
247
void CSFileOutputStream::write(const char *b, size_t len)
250
iFile->write(b, iWriteOffset, len);
255
const char *CSFileOutputStream::getEOL()
258
return_(iFile->getEOL());
261
void CSFileOutputStream::flush()
268
void CSFileOutputStream::write(char b)
271
iFile->write(&b, iWriteOffset, 1);
276
void CSFileOutputStream::reset()
281
const char *CSFileOutputStream::identify()
283
return iFile->myFilePath->getCString();
286
void CSFileOutputStream::close()
293
CSFileOutputStream *CSFileOutputStream::newStream(CSFile *f)
295
CSFileOutputStream *s;
297
if (!(s = new CSFileOutputStream())) {
299
CSException::throwOSError(CS_CONTEXT, ENOMEM);
305
CSFileOutputStream *CSFileOutputStream::newStream(CSFile *f, off64_t offset)
307
CSFileOutputStream *s;
309
if (!(s = new CSFileOutputStream())) {
311
CSException::throwOSError(CS_CONTEXT, ENOMEM);
314
s->iWriteOffset = offset;
319
* ---------------------------------------------------------------
320
* SOCKET INPUT STREAMS
323
CSSocketInputStream::~CSSocketInputStream()
329
void CSSocketInputStream::close()
336
size_t CSSocketInputStream::read(char *b, size_t len)
339
return_(iSocket->read(b, len));
342
int CSSocketInputStream::read()
345
return_(iSocket->read());
348
int CSSocketInputStream::peek()
351
return_(iSocket->peek());
354
void CSSocketInputStream::reset()
357
CSException::throwException(CS_CONTEXT, CS_ERR_OPERATION_NOT_SUPPORTED, "CSSocketInputStream::reset() not supported");
361
const char *CSSocketInputStream::identify()
363
return iSocket->identify();
366
CSSocketInputStream *CSSocketInputStream::newStream(CSSocket *s)
368
CSSocketInputStream *str;
370
if (!(str = new CSSocketInputStream())) {
372
CSException::throwOSError(CS_CONTEXT, ENOMEM);
379
* ---------------------------------------------------------------
380
* SOCKET OUTPUT STREAMS
383
CSSocketOutputStream::~CSSocketOutputStream()
389
void CSSocketOutputStream::close()
396
void CSSocketOutputStream::write(const char *b, size_t len)
399
iSocket->write(b, len);
403
void CSSocketOutputStream::flush()
410
void CSSocketOutputStream::write(char b)
417
void CSSocketOutputStream::reset()
420
CSException::throwException(CS_CONTEXT, CS_ERR_OPERATION_NOT_SUPPORTED, "CSSocketOutputStream::reset() not supported");
424
const char *CSSocketOutputStream::identify()
426
return iSocket->identify();
429
CSSocketOutputStream *CSSocketOutputStream::newStream(CSSocket *s)
431
CSSocketOutputStream *str;
433
if (!(str = new CSSocketOutputStream())) {
435
CSException::throwOSError(CS_CONTEXT, ENOMEM);
442
* ---------------------------------------------------------------
443
* BUFFERED INPUT STREAMS
446
CSBufferedInputStream::~CSBufferedInputStream()
452
void CSBufferedInputStream::close()
459
size_t CSBufferedInputStream::read(char *b, size_t len)
464
if (iBuffPos < iBuffTotal) {
465
tfer = iBuffTotal - iBuffPos;
468
memcpy(b, iBuffer + iBuffPos, tfer);
472
tfer = iStream->read(b, len);
476
int CSBufferedInputStream::read()
481
if (iBuffPos == iBuffTotal) {
482
iBuffTotal = iStream->read((char *) iBuffer, CS_STREAM_BUFFER_SIZE);
485
if (iBuffPos < iBuffTotal) {
486
ch = iBuffer[iBuffPos];
494
int CSBufferedInputStream::peek()
499
if (iBuffPos == iBuffTotal) {
500
iBuffTotal = iStream->read((char *) iBuffer, CS_STREAM_BUFFER_SIZE);
503
if (iBuffPos < iBuffTotal)
504
ch = iBuffer[iBuffPos];
510
void CSBufferedInputStream::reset()
512
iBuffPos = iBuffTotal =0;
516
const char *CSBufferedInputStream::identify()
518
return iStream->identify();
521
CSBufferedInputStream *CSBufferedInputStream::newStream(CSInputStream* i)
523
CSBufferedInputStream *s;
525
if (!(s = new CSBufferedInputStream())) {
527
CSException::throwOSError(CS_CONTEXT, ENOMEM);
534
* ---------------------------------------------------------------
535
* BUFFERED OUTPUT STREAMS
538
CSBufferedOutputStream::~CSBufferedOutputStream()
544
void CSBufferedOutputStream::close()
551
void CSBufferedOutputStream::write(const char *b, size_t len)
555
// If the length of the data being written is greater than half
556
// the buffer size then the data is written directly through
557
// with out buffering.
559
if (iBuffTotal < CS_STREAM_BUFFER_SIZE/2) {
560
tfer = CS_STREAM_BUFFER_SIZE - iBuffTotal;
564
memcpy(iBuffer + iBuffTotal, b, tfer);
571
if (len > CS_STREAM_BUFFER_SIZE/2)
572
iStream->write(b, len);
574
memcpy(iBuffer, b, len);
581
void CSBufferedOutputStream::flush()
586
if ((len = iBuffTotal)) {
587
/* Discard the contents of the buffer
588
* if flush fails, because we do
589
* not know how much was written anyway!
592
iStream->write((char *) iBuffer, len);
597
void CSBufferedOutputStream::write(char b)
600
if (iBuffTotal == CS_STREAM_BUFFER_SIZE)
602
iBuffer[iBuffTotal] = b;
607
void CSBufferedOutputStream::reset()
613
const char *CSBufferedOutputStream::identify()
615
return iStream->identify();
618
CSBufferedOutputStream *CSBufferedOutputStream::newStream(CSOutputStream* i)
620
CSBufferedOutputStream *s;
622
if (!(s = new CSBufferedOutputStream())) {
624
CSException::throwOSError(CS_CONTEXT, ENOMEM);
631
* ---------------------------------------------------------------
632
* MEMORY INPUT STREAMS
634
CSMemoryInputStream *CSMemoryInputStream::newStream(const u_char* buffer, uint32_t length)
636
CSMemoryInputStream *s;
638
if (!(s = new CSMemoryInputStream())) {
639
CSException::throwOSError(CS_CONTEXT, ENOMEM);
642
s->iMemTotal = length;
647
CSMemoryOutputStream *CSMemoryOutputStream::newStream(size_t init_length, size_t min_alloc)
649
CSMemoryOutputStream *s;
651
if (!(s = new CSMemoryOutputStream())) {
652
CSException::throwOSError(CS_CONTEXT, ENOMEM);
655
s->iMemory = (u_char *) cs_malloc(init_length);
656
s->iMemTotal = init_length;
657
s->iMemSpace = init_length;
658
s->iMemPos = s->iMemory;
659
s->iMemMin = min_alloc;
663
CSMemoryOutputStream::~CSMemoryOutputStream()
669
void CSMemoryOutputStream::write(const char *b, size_t len)
671
if (iMemSpace < len) {
672
size_t new_size = iMemTotal + ((len < iMemMin)? iMemMin:len);
674
cs_realloc((void**) &iMemory, new_size);
675
iMemPos = iMemory + (iMemTotal - iMemSpace);
676
iMemSpace += (new_size - iMemTotal);
677
iMemTotal = new_size;
679
memcpy(iMemPos, b, len);
684
void CSMemoryOutputStream::write(const char b)
687
cs_realloc((void**) &iMemory, iMemTotal + iMemMin);
688
iMemPos = iMemory + iMemTotal;
689
iMemSpace += iMemMin;
690
iMemTotal += iMemMin;
697
void CSMemoryOutputStream::reset()
700
iMemSpace = iMemTotal;
703
const char *CSMemoryOutputStream::identify()
705
return "memory stream";
709
* ---------------------------------------------------------------
710
* STATIC (user) MEMORY OUTPUT STREAM
712
void CSStaticMemoryOutputStream::write(const char *b, size_t len)
714
if (iMemSpace < len) {
716
CSException::throwException(CS_CONTEXT, CS_ERR_GENERIC_ERROR, "CSStaticMemoryOutputStream: overflow");
719
memcpy(iMemPos, b, len);
724
void CSStaticMemoryOutputStream::write(const char b)
728
CSException::throwException(CS_CONTEXT, CS_ERR_GENERIC_ERROR, "CSStaticMemoryOutputStream: overflow");
737
* ---------------------------------------------------------------
738
* Callback InPUT STREAM
741
CSCallbackInputStream *CSCallbackInputStream::newStream(CSStreamReadCallbackFunc in_callback, void *user_data)
743
CSCallbackInputStream *s;
745
if (!(s = new CSCallbackInputStream())) {
746
CSException::throwOSError(CS_CONTEXT, ENOMEM);
749
s->callback = in_callback;
750
s->cb_data = user_data;