CnC_Red_Alert/LAUNCHER/STREAMER.CPP

143 lines
2.8 KiB
C++

/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "streamer.h"
#ifdef _WIN32
#include <windows.h>
#endif
Streamer::Streamer() : streambuf()
{
int state=unbuffered();
unbuffered(0); // 0 = buffered, 1 = unbuffered
}
Streamer::~Streamer()
{
sync();
delete[](base());
}
int Streamer::setOutputDevice(OutputDevice *device)
{
Output_Device=device;
return(0);
}
// put n chars from string into buffer
int Streamer::xsputn(const char* buf, int size) //implementation of sputn
{
if (size<=0) // Nothing to do
return(0);
const unsigned char *ptr=(const unsigned char *)buf;
for (int i=0; i<size; i++, ptr++)
{
if(*ptr=='\n')
{
if (overflow(*ptr)==EOF)
return(i);
}
else if (sputc(*ptr)==EOF)
return(i);
}
return(size);
}
// Flush the buffer and make more room if needed
int Streamer::overflow(int c)
{
if (c==EOF)
return(sync());
if ((pbase()==0) && (doallocate()==0))
return(EOF);
if((pptr() >= epptr()) && (sync()==EOF))
return(EOF);
else {
sputc(c);
if ((unbuffered() && c=='\n' || pptr() >= epptr())
&& sync()==EOF) {
return(EOF);
}
return(c);
}
}
// This is a write only stream, this should never happen
int Streamer::underflow(void)
{
return(EOF);
}
int Streamer::doallocate()
{
if (base()==NULL)
{
char *buf=new char[(2*STREAMER_BUFSIZ)]; // deleted by destructor
memset(buf,0,2*STREAMER_BUFSIZ);
// Buffer
setb(
buf, // base pointer
buf+STREAMER_BUFSIZ, // ebuf pointer (end of buffer);
0); // 0 = manual deletion of buff
// Get area
setg(
buf, // eback
buf, // gptr
buf); // egptr
buf+=STREAMER_BUFSIZ;
// Put area
setp(buf,buf+STREAMER_BUFSIZ);
return(1);
}
else
return(0);
}
int Streamer::sync()
{
if (pptr()<=pbase()) {
return(0);
}
int wlen=pptr()-pbase();
if (Output_Device)
{
Output_Device->print(pbase(),wlen);
}
if (unbuffered()) {
setp(pbase(),pbase());
}
else {
setp(pbase(),pbase()+STREAMER_BUFSIZ);
}
return(0);
}