diff options
Diffstat (limited to 'src/libutil/serialise.hh')
-rw-r--r-- | src/libutil/serialise.hh | 108 |
1 files changed, 56 insertions, 52 deletions
diff --git a/src/libutil/serialise.hh b/src/libutil/serialise.hh index d7fe0b81e..5bbbc7ce3 100644 --- a/src/libutil/serialise.hh +++ b/src/libutil/serialise.hh @@ -5,6 +5,7 @@ #include "types.hh" #include "util.hh" +namespace boost::context { struct stack_context; } namespace nix { @@ -13,19 +14,14 @@ namespace nix { struct Sink { virtual ~Sink() { } - virtual void operator () (const unsigned char * data, size_t len) = 0; + virtual void operator () (std::string_view data) = 0; virtual bool good() { return true; } - - void operator () (const std::string & s) - { - (*this)((const unsigned char *) s.data(), s.size()); - } }; /* Just throws away data. */ struct NullSink : Sink { - void operator () (const unsigned char * data, size_t len) override + void operator () (std::string_view data) override { } }; @@ -34,21 +30,16 @@ struct NullSink : Sink struct BufferedSink : virtual Sink { size_t bufSize, bufPos; - std::unique_ptr<unsigned char[]> buffer; + std::unique_ptr<char[]> buffer; BufferedSink(size_t bufSize = 32 * 1024) : bufSize(bufSize), bufPos(0), buffer(nullptr) { } - void operator () (const unsigned char * data, size_t len) override; - - void operator () (const std::string & s) - { - Sink::operator()(s); - } + void operator () (std::string_view data) override; void flush(); - virtual void write(const unsigned char * data, size_t len) = 0; + virtual void write(std::string_view data) = 0; }; @@ -60,12 +51,12 @@ struct Source /* Store exactly ‘len’ bytes in the buffer pointed to by ‘data’. It blocks until all the requested data is available, or throws an error if it is not going to be available. */ - void operator () (unsigned char * data, size_t len); + void operator () (char * data, size_t len); /* Store up to ‘len’ in the buffer pointed to by ‘data’, and return the number of bytes stored. It blocks until at least one byte is available. */ - virtual size_t read(unsigned char * data, size_t len) = 0; + virtual size_t read(char * data, size_t len) = 0; virtual bool good() { return true; } @@ -80,18 +71,18 @@ struct Source struct BufferedSource : Source { size_t bufSize, bufPosIn, bufPosOut; - std::unique_ptr<unsigned char[]> buffer; + std::unique_ptr<char[]> buffer; BufferedSource(size_t bufSize = 32 * 1024) : bufSize(bufSize), bufPosIn(0), bufPosOut(0), buffer(nullptr) { } - size_t read(unsigned char * data, size_t len) override; + size_t read(char * data, size_t len) override; bool hasData(); protected: /* Underlying read call, to be overridden. */ - virtual size_t readUnbuffered(unsigned char * data, size_t len) = 0; + virtual size_t readUnbuffered(char * data, size_t len) = 0; }; @@ -118,7 +109,7 @@ struct FdSink : BufferedSink ~FdSink(); - void write(const unsigned char * data, size_t len) override; + void write(std::string_view data) override; bool good() override; @@ -147,7 +138,7 @@ struct FdSource : BufferedSource bool good() override; protected: - size_t readUnbuffered(unsigned char * data, size_t len) override; + size_t readUnbuffered(char * data, size_t len) override; private: bool _good = true; }; @@ -162,7 +153,7 @@ struct StringSink : Sink s->reserve(reservedSize); }; StringSink(ref<std::string> s) : s(s) { }; - void operator () (const unsigned char * data, size_t len) override; + void operator () (std::string_view data) override; }; @@ -172,7 +163,7 @@ struct StringSource : Source const string & s; size_t pos; StringSource(const string & _s) : s(_s), pos(0) { } - size_t read(unsigned char * data, size_t len) override; + size_t read(char * data, size_t len) override; }; @@ -181,10 +172,10 @@ struct TeeSink : Sink { Sink & sink1, & sink2; TeeSink(Sink & sink1, Sink & sink2) : sink1(sink1), sink2(sink2) { } - virtual void operator () (const unsigned char * data, size_t len) + virtual void operator () (std::string_view data) { - sink1(data, len); - sink2(data, len); + sink1(data); + sink2(data); } }; @@ -196,10 +187,10 @@ struct TeeSource : Source Sink & sink; TeeSource(Source & orig, Sink & sink) : orig(orig), sink(sink) { } - size_t read(unsigned char * data, size_t len) + size_t read(char * data, size_t len) { size_t n = orig.read(data, len); - sink(data, n); + sink({data, n}); return n; } }; @@ -211,7 +202,7 @@ struct SizedSource : Source size_t remain; SizedSource(Source & orig, size_t size) : orig(orig), remain(size) { } - size_t read(unsigned char * data, size_t len) + size_t read(char * data, size_t len) { if (this->remain <= 0) { throw EndOfFile("sized: unexpected end-of-file"); @@ -225,7 +216,7 @@ struct SizedSource : Source /* Consume the original source until no remain data is left to consume. */ size_t drainAll() { - std::vector<unsigned char> buf(8192); + std::vector<char> buf(8192); size_t sum = 0; while (this->remain > 0) { size_t n = read(buf.data(), buf.size()); @@ -240,24 +231,24 @@ struct LengthSink : Sink { uint64_t length = 0; - virtual void operator () (const unsigned char * _, size_t len) + void operator () (std::string_view data) override { - length += len; + length += data.size(); } }; /* Convert a function into a sink. */ struct LambdaSink : Sink { - typedef std::function<void(const unsigned char *, size_t)> lambda_t; + typedef std::function<void(std::string_view data)> lambda_t; lambda_t lambda; LambdaSink(const lambda_t & lambda) : lambda(lambda) { } - virtual void operator () (const unsigned char * data, size_t len) + void operator () (std::string_view data) override { - lambda(data, len); + lambda(data); } }; @@ -265,13 +256,13 @@ struct LambdaSink : Sink /* Convert a function into a source. */ struct LambdaSource : Source { - typedef std::function<size_t(unsigned char *, size_t)> lambda_t; + typedef std::function<size_t(char *, size_t)> lambda_t; lambda_t lambda; LambdaSource(const lambda_t & lambda) : lambda(lambda) { } - size_t read(unsigned char * data, size_t len) override + size_t read(char * data, size_t len) override { return lambda(data, len); } @@ -287,7 +278,7 @@ struct ChainSource : Source : source1(s1), source2(s2) { } - size_t read(unsigned char * data, size_t len) override; + size_t read(char * data, size_t len) override; }; @@ -301,7 +292,7 @@ std::unique_ptr<Source> sinkToSource( void writePadding(size_t len, Sink & sink); -void writeString(const unsigned char * buf, size_t len, Sink & sink); +void writeString(std::string_view s, Sink & sink); inline Sink & operator << (Sink & sink, uint64_t n) { @@ -314,7 +305,7 @@ inline Sink & operator << (Sink & sink, uint64_t n) buf[5] = (n >> 40) & 0xff; buf[6] = (n >> 48) & 0xff; buf[7] = (unsigned char) (n >> 56) & 0xff; - sink(buf, sizeof(buf)); + sink({(char *) buf, sizeof(buf)}); return sink; } @@ -331,7 +322,7 @@ template<typename T> T readNum(Source & source) { unsigned char buf[8]; - source(buf, sizeof(buf)); + source((char *) buf, sizeof(buf)); uint64_t n = ((uint64_t) buf[0]) | @@ -363,7 +354,7 @@ inline uint64_t readLongLong(Source & source) void readPadding(size_t len, Source & source); -size_t readString(unsigned char * buf, size_t max, Source & source); +size_t readString(char * buf, size_t max, Source & source); string readString(Source & source, size_t max = std::numeric_limits<size_t>::max()); template<class T> T readStrings(Source & source); @@ -395,9 +386,9 @@ struct StreamToSourceAdapter : Source : istream(istream) { } - size_t read(unsigned char * data, size_t len) override + size_t read(char * data, size_t len) override { - if (!istream->read((char *) data, len)) { + if (!istream->read(data, len)) { if (istream->eof()) { if (istream->gcount() == 0) throw EndOfFile("end of file"); @@ -420,7 +411,7 @@ struct FramedSource : Source { Source & from; bool eof = false; - std::vector<unsigned char> pending; + std::vector<char> pending; size_t pos = 0; FramedSource(Source & from) : from(from) @@ -432,13 +423,13 @@ struct FramedSource : Source while (true) { auto n = readInt(from); if (!n) break; - std::vector<unsigned char> data(n); + std::vector<char> data(n); from(data.data(), n); } } } - size_t read(unsigned char * data, size_t len) override + size_t read(char * data, size_t len) override { if (eof) throw EndOfFile("reached end of FramedSource"); @@ -448,7 +439,7 @@ struct FramedSource : Source eof = true; return 0; } - pending = std::vector<unsigned char>(len); + pending = std::vector<char>(len); pos = 0; from(pending.data(), len); } @@ -483,7 +474,7 @@ struct FramedSink : nix::BufferedSink } } - void write(const unsigned char * data, size_t len) override + void write(std::string_view data) override { /* Don't send more data if the remote has encountered an error. */ @@ -492,10 +483,23 @@ struct FramedSink : nix::BufferedSink ex = nullptr; std::rethrow_exception(ex2); } - to << len; - to(data, len); + to << data.size(); + to(data); }; }; +/* Stack allocation strategy for sinkToSource. + Mutable to avoid a boehm gc dependency in libutil. + + boost::context doesn't provide a virtual class, so we define our own. + */ +struct StackAllocator { + virtual boost::context::stack_context allocate() = 0; + virtual void deallocate(boost::context::stack_context sctx) = 0; + + /* The stack allocator to use in sinkToSource and potentially elsewhere. + It is reassigned by the initGC() method in libexpr. */ + static StackAllocator *defaultAllocator; +}; } |