diff options
Diffstat (limited to 'gfx/ots/include/ots-memory-stream.h')
-rw-r--r-- | gfx/ots/include/ots-memory-stream.h | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/gfx/ots/include/ots-memory-stream.h b/gfx/ots/include/ots-memory-stream.h new file mode 100644 index 0000000000..cb844709c2 --- /dev/null +++ b/gfx/ots/include/ots-memory-stream.h @@ -0,0 +1,109 @@ +// Copyright (c) 2009-2017 The OTS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef OTS_MEMORY_STREAM_H_ +#define OTS_MEMORY_STREAM_H_ + +#include <cstring> +#include <limits> + +#include "opentype-sanitiser.h" + +namespace ots { + +class MemoryStream : public OTSStream { + public: + MemoryStream(void *ptr, size_t length) + : ptr_(ptr), length_(length), off_(0) { + } + + size_t size() override { return length_; } + + bool WriteRaw(const void *data, size_t length) override { + if ((off_ + length > length_) || + (length > std::numeric_limits<size_t>::max() - off_)) { + return false; + } + std::memcpy(static_cast<char*>(ptr_) + off_, data, length); + off_ += length; + return true; + } + + bool Seek(off_t position) override { + if (position < 0) return false; + if (static_cast<size_t>(position) > length_) return false; + off_ = position; + return true; + } + + off_t Tell() const override { + return off_; + } + + private: + void* const ptr_; + size_t length_; + off_t off_; +}; + +class ExpandingMemoryStream : public OTSStream { + public: + ExpandingMemoryStream(size_t initial, size_t limit) + : length_(initial), limit_(limit), off_(0) { + ptr_ = new uint8_t[length_]; + } + + ~ExpandingMemoryStream() { + delete[] static_cast<uint8_t*>(ptr_); + } + + void* get() const { + return ptr_; + } + + size_t size() override { return limit_; } + + bool WriteRaw(const void *data, size_t length) override { + if ((off_ + length > length_) || + (length > std::numeric_limits<size_t>::max() - off_)) { + if (length_ == limit_) + return false; + size_t new_length = (length_ + 1) * 2; + if (new_length < length_) + return false; + if (new_length > limit_) + new_length = limit_; + uint8_t* new_buf = new uint8_t[new_length]; + std::memcpy(new_buf, ptr_, length_); + length_ = new_length; + delete[] static_cast<uint8_t*>(ptr_); + ptr_ = new_buf; + return WriteRaw(data, length); + } + std::memcpy(static_cast<char*>(ptr_) + off_, data, length); + off_ += length; + return true; + } + + bool Seek(off_t position) override { + if (position < 0) return false; + if (static_cast<size_t>(position) > length_) return false; + off_ = position; + return true; + } + + off_t Tell() const override { + return off_; + } + + private: + void* ptr_; + size_t length_; + const size_t limit_; + off_t off_; +}; + +} // namespace ots + +#endif // OTS_MEMORY_STREAM_H_ |