Create a new TeeSink abstraction

This is a bit complex because we want to expose extra functionality the
wrapped class has. Perhaps there is some inheritancy trickery to do this
nicer, but I don't know it, and this is the first thing we tried after a
series of attempts that did build.

This design is kind of like that of Rust's Writer, Reader, or Iter
adapters, which impliment more traits based on what the inner type
implements.
This commit is contained in:
Carlo Nucera 2020-06-16 15:14:11 -04:00 committed by John Ericson
parent fb05a6adcf
commit 289b9b8dcf
2 changed files with 34 additions and 0 deletions

View file

@ -25,4 +25,16 @@ MakeError(UnknownCompressionMethod, Error);
MakeError(CompressionError, Error); MakeError(CompressionError, Error);
template<>
struct TeeSink<ref<CompressionSink>> : CompressionSink
{
MAKE_TEE_SINK(ref<CompressionSink>);
void finish() override {
orig->finish();
}
void write(const unsigned char * data, size_t len) override {
return orig->write(data, len);
}
};
} }

View file

@ -181,6 +181,28 @@ struct TeeSource : Source
} }
}; };
#define MAKE_TEE_SINK(T) \
T orig; \
ref<std::string> data; \
TeeSink(T && orig) \
: orig(std::move(orig)), data(make_ref<std::string>()) { } \
void operator () (const unsigned char * data, size_t len) { \
this->data->append((const char *) data, len); \
(*this->orig)(data, len); \
} \
void operator () (const std::string & s) \
{ \
*data += s; \
(*this->orig)(s); \
}
template<typename T>
struct TeeSink : Sink
{
MAKE_TEE_SINK(T);
};
/* A reader that consumes the original Source until 'size'. */ /* A reader that consumes the original Source until 'size'. */
struct SizedSource : Source struct SizedSource : Source
{ {