#ifndef WOFF2_WOFF2_OUT_H_
#define WOFF2_WOFF2_OUT_H_
#include <stddef.h>
#include <stdint.h>
#include <algorithm>
#include <cstring>
#include <memory>
#include <string>
namespace woff2 {
const size_t kDefaultMaxSize = 128 * 1024 * 1024;
class WOFF2Out {
public:
virtual ~WOFF2Out(void) {}
virtual bool Write(const void *buf, size_t n) = 0;
virtual bool Write(const void *buf, size_t offset, size_t n) = 0;
virtual size_t Size() = 0;
};
class WOFF2StringOut : public WOFF2Out {
public:
explicit WOFF2StringOut(std::string* buf)
: buf_(buf), max_size_(kDefaultMaxSize), offset_(0) {}
bool Write(const void *buf, size_t n) override {
return Write(buf, offset_, n);
}
bool Write(const void *buf, size_t offset, size_t n) override {
if (offset > max_size_ || n > max_size_ - offset) {
return false;
}
if (offset == buf_->size()) {
buf_->append(static_cast<const char*>(buf), n);
} else {
if (offset + n > buf_->size()) {
buf_->append(offset + n - buf_->size(), 0);
}
buf_->replace(offset, n, static_cast<const char*>(buf), n);
}
offset_ = std::max(offset_, offset + n);
return true;
}
size_t Size() override { return offset_; }
size_t MaxSize() { return max_size_; }
void SetMaxSize(size_t max_size) {
max_size_ = max_size;
if (offset_ > max_size_) {
offset_ = max_size_;
}
}
private:
std::string *buf_;
size_t max_size_;
size_t offset_;
};
class WOFF2MemoryOut : public WOFF2Out {
public:
WOFF2MemoryOut(uint8_t* buf, size_t buf_size)
: buf_(buf), buf_size_(buf_size), offset_(0) {}
bool Write(const void *buf, size_t n) override {
return Write(buf, offset_, n);
}
bool Write(const void *buf, size_t offset, size_t n) override {
if (offset > buf_size_ || n > buf_size_ - offset) {
return false;
}
std::memcpy(buf_ + offset, buf, n);
offset_ = std::max(offset_, offset + n);
return true;
}
size_t Size() override { return offset_; }
private:
uint8_t* buf_;
size_t buf_size_;
size_t offset_;
};
}
#endif