Core: FilterStream

git-svn-id: svn://ultimatepp.org/upp/trunk@5830 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2013-02-19 09:32:42 +00:00
parent baab578f97
commit 156acf2cbd
6 changed files with 232 additions and 7 deletions

View file

@ -295,6 +295,8 @@ class JsonIO;
#include "Callback.h"
#include "Util.h"
#include "FilterStream.h"
#include "Format.h"
#include "Convert.h"

View file

@ -63,6 +63,8 @@ file
Stream.h,
Stream.cpp optimize_speed,
BlockStream.cpp optimize_speed,
FilterStream.h,
FilterStream.cpp,
Profile.h,
Diag.h,
Log.cpp,

View file

@ -0,0 +1,158 @@
#include "Core.h"
NAMESPACE_UPP
InputFilterStream::InputFilterStream()
{
Init();
}
void InputFilterStream::Init()
{
static byte h[1];
ptr = rdlim = h;
in = NULL;
eof = false;
}
dword InputFilterStream::Avail()
{
return dword(rdlim - ptr);
}
bool InputFilterStream::IsOpen() const
{
return in->IsOpen();
}
int InputFilterStream::_Term()
{
if(ptr == rdlim)
Fetch(1);
return ptr == rdlim ? -1 : *ptr;
}
int InputFilterStream::_Get()
{
if(ptr == rdlim)
Fetch(1);
return ptr == rdlim ? -1 : *ptr++;
}
dword InputFilterStream::_Get(void *data, dword size)
{
byte *p = (byte *)data;
int nn = 0;
for(int pass = 0; size && pass < 2; pass++) {
int n = min(size, Avail());
memcpy(p, ptr, n);
size -= n;
p += n;
ptr += n;
nn += n;
if(size)
Fetch(size);
}
return nn;
}
void InputFilterStream::Out(const void *ptr, int size)
{
int l = buffer.GetCount();
buffer.SetCount(l + size);
memcpy(buffer.Begin() + l, ptr, size);
}
void InputFilterStream::Fetch(int size)
{
buffer.Clear();
if(eof) {
static byte h[1];
ptr = rdlim = h;
return;
}
if(More)
while(buffer.GetCount() < size && More());
else {
Buffer<byte> b(4096);
while(buffer.GetCount() < size) {
int n = in->Get(~b, 4096);
if(n == 0) {
End();
eof = true;
break;
}
Filter(~b, n);
}
}
ptr = buffer.Begin();
rdlim = buffer.End();
}
OutputFilterStream::OutputFilterStream()
{
Init();
}
void OutputFilterStream::Init()
{
buffer.Alloc(4096);
wrlim = ~buffer + 4096;
ptr = ~buffer;
out = NULL;
}
OutputFilterStream::~OutputFilterStream()
{
Close();
}
void OutputFilterStream::Close()
{
if(buffer) {
FlushOut();
End();
buffer.Clear();
}
}
void OutputFilterStream::FlushOut()
{
if(ptr != ~buffer) {
Filter(~buffer, ptr - ~buffer);
ptr = ~buffer;
}
}
void OutputFilterStream::_Put(int w)
{
FlushOut();
*ptr++ = w;
}
void OutputFilterStream::_Put(const void *data, dword size)
{
const byte *p = (const byte *)data;
for(;;) {
int n = min(Avail(), size);
memcpy(ptr, p, n);
size -= n;
p += n;
ptr += n;
if(size == 0)
return;
FlushOut();
}
}
bool OutputFilterStream::IsOpen() const
{
return buffer;
}
void OutputFilterStream::Out(const void *ptr, int size)
{
out->Put(ptr, size);
}
END_UPP_NAMESPACE

View file

@ -0,0 +1,68 @@
class InputFilterStream : public Stream {
public:
virtual bool IsOpen() const;
protected:
virtual int _Term();
virtual int _Get();
virtual dword _Get(void *data, dword size);
Vector<byte> buffer;
bool eof;
void Init();
void Fetch(int size);
dword Avail();
public:
Stream *in;
Callback2<const void *, int> Filter;
Callback End;
Gate More;
void Out(const void *ptr, int size);
template <class F>
void Set(Stream& in_, F& filter) {
in = &in_;
filter.WhenOut = callback(this, &InputFilterStream::Out);
Filter = callback<F, F, const void *, int>(&filter, &F::Put);
End = callback(&filter, &F::End);
}
InputFilterStream();
template <class F> InputFilterStream(Stream& in, F& filter) { Init(); Set(in, filter); }
};
class OutputFilterStream : public Stream {
public:
virtual void Close();
virtual bool IsOpen() const;
protected:
virtual void _Put(int w);
virtual void _Put(const void *data, dword size);
Buffer<byte> buffer;
void FlushOut();
dword Avail() { return 4096 - (ptr - ~buffer); }
void Init();
public:
Stream *out;
Callback2<const void *, int> Filter;
Callback End;
void Out(const void *ptr, int size);
template <class F>
void Set(Stream& out_, F& filter) {
out = &out_;
filter.WhenOut = callback(this, &OutputFilterStream::Out);
Filter = callback<F, F, const void *, int>(&filter, &F::Put);
End = callback(&filter, &F::End);
}
OutputFilterStream();
template <class F> OutputFilterStream(Stream& in, F& filter) { Init(); Set(in, filter); }
~OutputFilterStream();
};

View file

@ -63,11 +63,6 @@ Stream::Stream() {
Stream::~Stream() {}
bool Stream::_IsEof() const
{
return GetPos() >= GetSize();
}
void Stream::LoadError() {
SetError(ERROR_LOADING_FAILED);
if(style & STRM_THROW)

View file

@ -45,7 +45,6 @@ private:
int _Get16();
int _Get32();
int64 _Get64();
bool _IsEof() const;
public:
virtual void Seek(int64 pos);
@ -73,11 +72,12 @@ public:
void ClearError() { style = style & ~STRM_ERROR; errorcode = 0; }
int64 GetPos() const { return dword(ptr - buffer) + pos; }
bool IsEof() const { return ptr >= rdlim && _IsEof(); }
int64 GetLeft() const { return GetSize() - GetPos(); }
void SeekEnd(int64 rel = 0) { Seek(GetSize() + rel); }
void SeekCur(int64 rel) { Seek(GetPos() + rel); }
bool IsEof() { return ptr >= rdlim && _Term() < 0; }
void Put(int c) { if(ptr < wrlim) *ptr++ = c; else _Put(c); }
int Term() { return ptr < rdlim ? *ptr : _Term(); }
int Peek() { return Term(); }