clover: remove util/compat
Acked-by: Francisco Jerez <currojerez@riseup.net> Reviewed-by: Tom Stellard <thomas.stellard@amd.com>
This commit is contained in:
@@ -45,7 +45,6 @@ CPP_SOURCES := \
|
||||
util/adaptor.hpp \
|
||||
util/algebra.hpp \
|
||||
util/algorithm.hpp \
|
||||
util/compat.hpp \
|
||||
util/factor.hpp \
|
||||
util/functional.hpp \
|
||||
util/lazy.hpp \
|
||||
|
@@ -23,6 +23,8 @@
|
||||
#include "api/util.hpp"
|
||||
#include "core/program.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
using namespace clover;
|
||||
|
||||
namespace {
|
||||
@@ -94,12 +96,12 @@ clCreateProgramWithBinary(cl_context d_ctx, cl_uint n,
|
||||
return { CL_INVALID_VALUE, {} };
|
||||
|
||||
try {
|
||||
compat::istream::buffer_t bin(p, l);
|
||||
compat::istream s(bin);
|
||||
std::stringbuf bin( { (char*)p, l } );
|
||||
std::istream s(&bin);
|
||||
|
||||
return { CL_SUCCESS, module::deserialize(s) };
|
||||
|
||||
} catch (compat::istream::error &e) {
|
||||
} catch (std::istream::failure &e) {
|
||||
return { CL_INVALID_BINARY, {} };
|
||||
}
|
||||
},
|
||||
@@ -279,10 +281,10 @@ clGetProgramInfo(cl_program d_prog, cl_program_info param,
|
||||
|
||||
case CL_PROGRAM_BINARIES:
|
||||
buf.as_matrix<unsigned char>() = map([&](const device &dev) {
|
||||
compat::ostream::buffer_t bin;
|
||||
compat::ostream s(bin);
|
||||
std::stringbuf bin;
|
||||
std::ostream s(&bin);
|
||||
prog.binary(dev).serialize(s);
|
||||
return bin;
|
||||
return bin.str();
|
||||
},
|
||||
prog.devices());
|
||||
break;
|
||||
|
@@ -23,14 +23,12 @@
|
||||
#ifndef CLOVER_CORE_COMPILER_HPP
|
||||
#define CLOVER_CORE_COMPILER_HPP
|
||||
|
||||
#include "util/compat.hpp"
|
||||
#include "core/error.hpp"
|
||||
#include "core/module.hpp"
|
||||
#include "pipe/p_defines.h"
|
||||
|
||||
namespace clover {
|
||||
typedef compat::vector<std::pair<std::string,
|
||||
std::string> > header_map;
|
||||
typedef std::vector<std::pair<std::string, std::string> > header_map;
|
||||
|
||||
module compile_program_llvm(const std::string &source,
|
||||
const header_map &headers,
|
||||
|
@@ -27,8 +27,6 @@
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "util/compat.hpp"
|
||||
|
||||
namespace clover {
|
||||
class command_queue;
|
||||
class context;
|
||||
|
@@ -192,7 +192,7 @@ kernel::exec_context::bind(intrusive_ptr<command_queue> _q,
|
||||
if (st)
|
||||
_q->pipe->delete_compute_state(_q->pipe, st);
|
||||
|
||||
cs.prog = msec.data.begin();
|
||||
cs.prog = &(msec.data[0]);
|
||||
cs.req_local_mem = mem_local;
|
||||
cs.req_input_mem = input.size();
|
||||
st = q->pipe->create_compute_state(q->pipe, &cs);
|
||||
|
@@ -21,6 +21,7 @@
|
||||
//
|
||||
|
||||
#include <type_traits>
|
||||
#include <iostream>
|
||||
|
||||
#include "core/module.hpp"
|
||||
|
||||
@@ -33,20 +34,20 @@ namespace {
|
||||
/// Serialize the specified object.
|
||||
template<typename T>
|
||||
void
|
||||
_proc(compat::ostream &os, const T &x) {
|
||||
_proc(std::ostream &os, const T &x) {
|
||||
_serializer<T>::proc(os, x);
|
||||
}
|
||||
|
||||
/// Deserialize the specified object.
|
||||
template<typename T>
|
||||
void
|
||||
_proc(compat::istream &is, T &x) {
|
||||
_proc(std::istream &is, T &x) {
|
||||
_serializer<T>::proc(is, x);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T
|
||||
_proc(compat::istream &is) {
|
||||
_proc(std::istream &is) {
|
||||
T x;
|
||||
_serializer<T>::proc(is, x);
|
||||
return x;
|
||||
@@ -64,12 +65,12 @@ namespace {
|
||||
struct _serializer<T, typename std::enable_if<
|
||||
std::is_scalar<T>::value>::type> {
|
||||
static void
|
||||
proc(compat::ostream &os, const T &x) {
|
||||
proc(std::ostream &os, const T &x) {
|
||||
os.write(reinterpret_cast<const char *>(&x), sizeof(x));
|
||||
}
|
||||
|
||||
static void
|
||||
proc(compat::istream &is, T &x) {
|
||||
proc(std::istream &is, T &x) {
|
||||
is.read(reinterpret_cast<char *>(&x), sizeof(x));
|
||||
}
|
||||
|
||||
@@ -81,11 +82,11 @@ namespace {
|
||||
|
||||
/// (De)serialize a vector.
|
||||
template<typename T>
|
||||
struct _serializer<compat::vector<T>,
|
||||
struct _serializer<std::vector<T>,
|
||||
typename std::enable_if<
|
||||
!std::is_scalar<T>::value>::type> {
|
||||
static void
|
||||
proc(compat::ostream &os, const compat::vector<T> &v) {
|
||||
proc(std::ostream &os, const std::vector<T> &v) {
|
||||
_proc<uint32_t>(os, v.size());
|
||||
|
||||
for (size_t i = 0; i < v.size(); i++)
|
||||
@@ -93,7 +94,7 @@ namespace {
|
||||
}
|
||||
|
||||
static void
|
||||
proc(compat::istream &is, compat::vector<T> &v) {
|
||||
proc(std::istream &is, std::vector<T> &v) {
|
||||
v.resize(_proc<uint32_t>(is));
|
||||
|
||||
for (size_t i = 0; i < v.size(); i++)
|
||||
@@ -101,7 +102,7 @@ namespace {
|
||||
}
|
||||
|
||||
static void
|
||||
proc(module::size_t &sz, const compat::vector<T> &v) {
|
||||
proc(module::size_t &sz, const std::vector<T> &v) {
|
||||
sz += sizeof(uint32_t);
|
||||
|
||||
for (size_t i = 0; i < v.size(); i++)
|
||||
@@ -110,25 +111,25 @@ namespace {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct _serializer<compat::vector<T>,
|
||||
struct _serializer<std::vector<T>,
|
||||
typename std::enable_if<
|
||||
std::is_scalar<T>::value>::type> {
|
||||
static void
|
||||
proc(compat::ostream &os, const compat::vector<T> &v) {
|
||||
proc(std::ostream &os, const std::vector<T> &v) {
|
||||
_proc<uint32_t>(os, v.size());
|
||||
os.write(reinterpret_cast<const char *>(v.begin()),
|
||||
os.write(reinterpret_cast<const char *>(&v[0]),
|
||||
v.size() * sizeof(T));
|
||||
}
|
||||
|
||||
static void
|
||||
proc(compat::istream &is, compat::vector<T> &v) {
|
||||
proc(std::istream &is, std::vector<T> &v) {
|
||||
v.resize(_proc<uint32_t>(is));
|
||||
is.read(reinterpret_cast<char *>(v.begin()),
|
||||
is.read(reinterpret_cast<char *>(&v[0]),
|
||||
v.size() * sizeof(T));
|
||||
}
|
||||
|
||||
static void
|
||||
proc(module::size_t &sz, const compat::vector<T> &v) {
|
||||
proc(module::size_t &sz, const std::vector<T> &v) {
|
||||
sz += sizeof(uint32_t) + sizeof(T) * v.size();
|
||||
}
|
||||
};
|
||||
@@ -137,13 +138,13 @@ namespace {
|
||||
template<>
|
||||
struct _serializer<std::string> {
|
||||
static void
|
||||
proc(compat::ostream &os, const std::string &s) {
|
||||
proc(std::ostream &os, const std::string &s) {
|
||||
_proc<uint32_t>(os, s.size());
|
||||
os.write(&s[0], s.size() * sizeof(std::string::value_type));
|
||||
}
|
||||
|
||||
static void
|
||||
proc(compat::istream &is, std::string &s) {
|
||||
proc(std::istream &is, std::string &s) {
|
||||
s.resize(_proc<uint32_t>(is));
|
||||
is.read(&s[0], s.size() * sizeof(std::string::value_type));
|
||||
}
|
||||
@@ -209,12 +210,12 @@ namespace {
|
||||
|
||||
namespace clover {
|
||||
void
|
||||
module::serialize(compat::ostream &os) const {
|
||||
module::serialize(std::ostream &os) const {
|
||||
_proc(os, *this);
|
||||
}
|
||||
|
||||
module
|
||||
module::deserialize(compat::istream &is) {
|
||||
module::deserialize(std::istream &is) {
|
||||
return _proc<module>(is);
|
||||
}
|
||||
|
||||
|
@@ -23,7 +23,8 @@
|
||||
#ifndef CLOVER_CORE_MODULE_HPP
|
||||
#define CLOVER_CORE_MODULE_HPP
|
||||
|
||||
#include "util/compat.hpp"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace clover {
|
||||
struct module {
|
||||
@@ -40,14 +41,14 @@ namespace clover {
|
||||
};
|
||||
|
||||
section(resource_id id, enum type type, size_t size,
|
||||
const compat::vector<char> &data) :
|
||||
const std::vector<char> &data) :
|
||||
id(id), type(type), size(size), data(data) { }
|
||||
section() : id(0), type(text), size(0), data() { }
|
||||
|
||||
resource_id id;
|
||||
type type;
|
||||
size_t size;
|
||||
compat::vector<char> data;
|
||||
std::vector<char> data;
|
||||
};
|
||||
|
||||
struct argument {
|
||||
@@ -101,22 +102,22 @@ namespace clover {
|
||||
|
||||
struct symbol {
|
||||
symbol(const std::string &name, resource_id section,
|
||||
size_t offset, const compat::vector<argument> &args) :
|
||||
size_t offset, const std::vector<argument> &args) :
|
||||
name(name), section(section), offset(offset), args(args) { }
|
||||
symbol() : name(), section(0), offset(0), args() { }
|
||||
|
||||
std::string name;
|
||||
resource_id section;
|
||||
size_t offset;
|
||||
compat::vector<argument> args;
|
||||
std::vector<argument> args;
|
||||
};
|
||||
|
||||
void serialize(compat::ostream &os) const;
|
||||
static module deserialize(compat::istream &is);
|
||||
void serialize(std::ostream &os) const;
|
||||
static module deserialize(std::istream &is);
|
||||
size_t size() const;
|
||||
|
||||
compat::vector<symbol> syms;
|
||||
compat::vector<section> secs;
|
||||
std::vector<symbol> syms;
|
||||
std::vector<section> secs;
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -106,7 +106,7 @@ program::build_log(const device &dev) const {
|
||||
return _logs.count(&dev) ? _logs.find(&dev)->second : "";
|
||||
}
|
||||
|
||||
const compat::vector<module::symbol> &
|
||||
const std::vector<module::symbol> &
|
||||
program::symbols() const {
|
||||
if (_binaries.empty())
|
||||
throw error(CL_INVALID_PROGRAM_EXECUTABLE);
|
||||
|
@@ -60,7 +60,7 @@ namespace clover {
|
||||
std::string build_opts(const device &dev) const;
|
||||
std::string build_log(const device &dev) const;
|
||||
|
||||
const compat::vector<module::symbol> &symbols() const;
|
||||
const std::vector<module::symbol> &symbols() const;
|
||||
|
||||
unsigned kernel_ref_count() const;
|
||||
|
||||
|
@@ -340,11 +340,11 @@ namespace {
|
||||
PM.run(*mod);
|
||||
}
|
||||
|
||||
compat::vector<module::argument>
|
||||
std::vector<module::argument>
|
||||
get_kernel_args(const llvm::Module *mod, const std::string &kernel_name,
|
||||
const clang::LangAS::Map &address_spaces) {
|
||||
|
||||
compat::vector<module::argument> args;
|
||||
std::vector<module::argument> args;
|
||||
llvm::Function *kernel_func = mod->getFunction(kernel_name);
|
||||
|
||||
llvm::DataLayout TD(mod);
|
||||
@@ -449,15 +449,16 @@ namespace {
|
||||
|
||||
for (unsigned i = 0; i < kernels.size(); ++i) {
|
||||
std::string kernel_name = kernels[i]->getName();
|
||||
compat::vector<module::argument> args =
|
||||
std::vector<module::argument> args =
|
||||
get_kernel_args(mod, kernel_name, address_spaces);
|
||||
|
||||
m.syms.push_back(module::symbol(kernel_name, 0, i, args ));
|
||||
}
|
||||
|
||||
header.num_bytes = llvm_bitcode.size();
|
||||
std::string data;
|
||||
data.insert(0, (char*)(&header), sizeof(header));
|
||||
std::vector<char> data;
|
||||
data.insert(data.end(), (char*)(&header),
|
||||
(char*)(&header) + sizeof(header));
|
||||
data.insert(data.end(), llvm_bitcode.begin(),
|
||||
llvm_bitcode.end());
|
||||
m.secs.push_back(module::section(0, module::section::text,
|
||||
@@ -622,15 +623,16 @@ namespace {
|
||||
|
||||
// Store the generated ELF binary in the module's text section.
|
||||
header.num_bytes = code.size();
|
||||
std::string data;
|
||||
data.append((char*)(&header), sizeof(header));
|
||||
data.append(code.begin(), code.end());
|
||||
std::vector<char> data;
|
||||
data.insert(data.end(), (char*)(&header),
|
||||
(char*)(&header) + sizeof(header));
|
||||
data.insert(data.end(), code.begin(), code.end());
|
||||
m.secs.push_back(module::section(0, module::section::text,
|
||||
header.num_bytes, data));
|
||||
|
||||
for (std::map<std::string, unsigned>::iterator i = kernel_offsets.begin(),
|
||||
e = kernel_offsets.end(); i != e; ++i) {
|
||||
compat::vector<module::argument> args =
|
||||
std::vector<module::argument> args =
|
||||
get_kernel_args(mod, i->first, address_spaces);
|
||||
m.syms.push_back(module::symbol(i->first, 0, i->second, args ));
|
||||
}
|
||||
|
@@ -40,7 +40,7 @@ namespace {
|
||||
std::istringstream ts(line);
|
||||
std::string name, tok;
|
||||
module::size_t offset;
|
||||
compat::vector<module::argument> args;
|
||||
std::vector<module::argument> args;
|
||||
|
||||
if (!(ts >> name))
|
||||
continue;
|
||||
@@ -83,7 +83,8 @@ namespace {
|
||||
throw build_error("translate failed");
|
||||
|
||||
unsigned sz = tgsi_num_tokens(prog) * sizeof(tgsi_token);
|
||||
m.secs.push_back({ 0, module::section::text, sz, { (char *)prog, sz } });
|
||||
std::vector<char> data( (char *)prog, (char *)prog + sz );
|
||||
m.secs.push_back({ 0, module::section::text, sz, data });
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,313 +0,0 @@
|
||||
//
|
||||
// Copyright 2012 Francisco Jerez
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
#ifndef CLOVER_UTIL_COMPAT_HPP
|
||||
#define CLOVER_UTIL_COMPAT_HPP
|
||||
|
||||
#include <new>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace clover {
|
||||
namespace compat {
|
||||
// XXX - For cases where we can't rely on STL... I.e. the
|
||||
// interface between code compiled as C++98 and C++11
|
||||
// source. Get rid of this as soon as everything can be
|
||||
// compiled as C++11.
|
||||
|
||||
namespace detail {
|
||||
template<typename R, typename S>
|
||||
bool
|
||||
ranges_equal(const R &a, const S &b) {
|
||||
if (a.size() != b.size())
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < a.size(); ++i)
|
||||
if (a[i] != b[i])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class vector {
|
||||
protected:
|
||||
static T *
|
||||
alloc(int n, const T *q, int m) {
|
||||
T *p = reinterpret_cast<T *>(std::malloc(n * sizeof(T)));
|
||||
|
||||
for (int i = 0; i < m; ++i)
|
||||
new(&p[i]) T(q[i]);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static void
|
||||
free(int n, T *p) {
|
||||
for (int i = 0; i < n; ++i)
|
||||
p[i].~T();
|
||||
|
||||
std::free(p);
|
||||
}
|
||||
|
||||
public:
|
||||
typedef T *iterator;
|
||||
typedef const T *const_iterator;
|
||||
typedef T value_type;
|
||||
typedef T &reference;
|
||||
typedef const T &const_reference;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::size_t size_type;
|
||||
|
||||
vector() : p(NULL), _size(0), _capacity(0) {
|
||||
}
|
||||
|
||||
vector(const vector &v) :
|
||||
p(alloc(v._size, v.p, v._size)),
|
||||
_size(v._size), _capacity(v._size) {
|
||||
}
|
||||
|
||||
vector(const_iterator p, size_type n) :
|
||||
p(alloc(n, p, n)), _size(n), _capacity(n) {
|
||||
}
|
||||
|
||||
template<typename C>
|
||||
vector(const C &v) :
|
||||
p(alloc(v.size(), NULL, 0)), _size(0),
|
||||
_capacity(v.size()) {
|
||||
for (typename C::const_iterator it = v.begin(); it != v.end(); ++it)
|
||||
new(&p[_size++]) T(*it);
|
||||
}
|
||||
|
||||
~vector() {
|
||||
free(_size, p);
|
||||
}
|
||||
|
||||
vector &
|
||||
operator=(const vector &v) {
|
||||
free(_size, p);
|
||||
|
||||
p = alloc(v._size, v.p, v._size);
|
||||
_size = v._size;
|
||||
_capacity = v._size;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(const vector &v) const {
|
||||
return detail::ranges_equal(*this, v);
|
||||
}
|
||||
|
||||
void
|
||||
reserve(size_type n) {
|
||||
if (_capacity < n) {
|
||||
T *q = alloc(n, p, _size);
|
||||
free(_size, p);
|
||||
|
||||
p = q;
|
||||
_capacity = n;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
resize(size_type n, T x = T()) {
|
||||
if (n <= _size) {
|
||||
for (size_type i = n; i < _size; ++i)
|
||||
p[i].~T();
|
||||
|
||||
} else {
|
||||
reserve(n);
|
||||
|
||||
for (size_type i = _size; i < n; ++i)
|
||||
new(&p[i]) T(x);
|
||||
}
|
||||
|
||||
_size = n;
|
||||
}
|
||||
|
||||
void
|
||||
push_back(const T &x) {
|
||||
reserve(_size + 1);
|
||||
new(&p[_size]) T(x);
|
||||
++_size;
|
||||
}
|
||||
|
||||
size_type
|
||||
size() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
size_type
|
||||
capacity() const {
|
||||
return _capacity;
|
||||
}
|
||||
|
||||
iterator
|
||||
begin() {
|
||||
return p;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
begin() const {
|
||||
return p;
|
||||
}
|
||||
|
||||
iterator
|
||||
end() {
|
||||
return p + _size;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
end() const {
|
||||
return p + _size;
|
||||
}
|
||||
|
||||
reference
|
||||
operator[](size_type i) {
|
||||
return p[i];
|
||||
}
|
||||
|
||||
const_reference
|
||||
operator[](size_type i) const {
|
||||
return p[i];
|
||||
}
|
||||
|
||||
private:
|
||||
iterator p;
|
||||
size_type _size;
|
||||
size_type _capacity;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class vector_ref {
|
||||
public:
|
||||
typedef T *iterator;
|
||||
typedef const T *const_iterator;
|
||||
typedef T value_type;
|
||||
typedef T &reference;
|
||||
typedef const T &const_reference;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::size_t size_type;
|
||||
|
||||
vector_ref(iterator p, size_type n) : p(p), n(n) {
|
||||
}
|
||||
|
||||
template<typename C>
|
||||
vector_ref(C &v) : p(&*v.begin()), n(v.size()) {
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(const vector_ref &v) const {
|
||||
return detail::ranges_equal(*this, v);
|
||||
}
|
||||
|
||||
size_type
|
||||
size() const {
|
||||
return n;
|
||||
}
|
||||
|
||||
iterator
|
||||
begin() {
|
||||
return p;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
begin() const {
|
||||
return p;
|
||||
}
|
||||
|
||||
iterator
|
||||
end() {
|
||||
return p + n;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
end() const {
|
||||
return p + n;
|
||||
}
|
||||
|
||||
reference
|
||||
operator[](int i) {
|
||||
return p[i];
|
||||
}
|
||||
|
||||
const_reference
|
||||
operator[](int i) const {
|
||||
return p[i];
|
||||
}
|
||||
|
||||
private:
|
||||
iterator p;
|
||||
size_type n;
|
||||
};
|
||||
|
||||
class istream {
|
||||
public:
|
||||
typedef vector_ref<const unsigned char> buffer_t;
|
||||
|
||||
class error {
|
||||
public:
|
||||
virtual ~error() {}
|
||||
};
|
||||
|
||||
istream(const buffer_t &buf) : buf(buf), offset(0) {}
|
||||
|
||||
void
|
||||
read(char *p, size_t n) {
|
||||
if (offset + n > buf.size())
|
||||
throw error();
|
||||
|
||||
std::memcpy(p, buf.begin() + offset, n);
|
||||
offset += n;
|
||||
}
|
||||
|
||||
private:
|
||||
const buffer_t &buf;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
class ostream {
|
||||
public:
|
||||
typedef vector<unsigned char> buffer_t;
|
||||
|
||||
ostream(buffer_t &buf) : buf(buf), offset(buf.size()) {}
|
||||
|
||||
void
|
||||
write(const char *p, size_t n) {
|
||||
buf.resize(offset + n);
|
||||
std::memcpy(buf.begin() + offset, p, n);
|
||||
offset += n;
|
||||
}
|
||||
|
||||
private:
|
||||
buffer_t &buf;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user