michael@0: // Copyright (c) 2009 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #ifndef OTS_MEMORY_STREAM_H_ michael@0: #define OTS_MEMORY_STREAM_H_ michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #include "opentype-sanitiser.h" michael@0: michael@0: namespace ots { michael@0: michael@0: class MemoryStream : public OTSStream { michael@0: public: michael@0: MemoryStream(void *ptr, size_t length) michael@0: : ptr_(ptr), length_(length), off_(0) { michael@0: } michael@0: michael@0: virtual bool WriteRaw(const void *data, size_t length) { michael@0: if ((off_ + length > length_) || michael@0: (length > std::numeric_limits::max() - off_)) { michael@0: return false; michael@0: } michael@0: std::memcpy(static_cast(ptr_) + off_, data, length); michael@0: off_ += length; michael@0: return true; michael@0: } michael@0: michael@0: virtual bool Seek(off_t position) { michael@0: if (position < 0) return false; michael@0: if (static_cast(position) > length_) return false; michael@0: off_ = position; michael@0: return true; michael@0: } michael@0: michael@0: virtual off_t Tell() const { michael@0: return off_; michael@0: } michael@0: michael@0: private: michael@0: void* const ptr_; michael@0: size_t length_; michael@0: off_t off_; michael@0: }; michael@0: michael@0: class ExpandingMemoryStream : public OTSStream { michael@0: public: michael@0: ExpandingMemoryStream(size_t initial, size_t limit) michael@0: : length_(initial), limit_(limit), off_(0) { michael@0: ptr_ = new uint8_t[length_]; michael@0: } michael@0: michael@0: ~ExpandingMemoryStream() { michael@0: delete[] static_cast(ptr_); michael@0: } michael@0: michael@0: void* get() const { michael@0: return ptr_; michael@0: } michael@0: michael@0: bool WriteRaw(const void *data, size_t length) { michael@0: if ((off_ + length > length_) || michael@0: (length > std::numeric_limits::max() - off_)) { michael@0: if (length_ == limit_) michael@0: return false; michael@0: size_t new_length = (length_ + 1) * 2; michael@0: if (new_length < length_) michael@0: return false; michael@0: if (new_length > limit_) michael@0: new_length = limit_; michael@0: uint8_t* new_buf = new uint8_t[new_length]; michael@0: std::memcpy(new_buf, ptr_, length_); michael@0: length_ = new_length; michael@0: delete[] static_cast(ptr_); michael@0: ptr_ = new_buf; michael@0: return WriteRaw(data, length); michael@0: } michael@0: std::memcpy(static_cast(ptr_) + off_, data, length); michael@0: off_ += length; michael@0: return true; michael@0: } michael@0: michael@0: bool Seek(off_t position) { michael@0: if (position < 0) return false; michael@0: if (static_cast(position) > length_) return false; michael@0: off_ = position; michael@0: return true; michael@0: } michael@0: michael@0: off_t Tell() const { michael@0: return off_; michael@0: } michael@0: michael@0: private: michael@0: void* ptr_; michael@0: size_t length_; michael@0: const size_t limit_; michael@0: off_t off_; michael@0: }; michael@0: michael@0: } // namespace ots michael@0: michael@0: #endif // OTS_MEMORY_STREAM_H_