1 // Copyright (c) 2009-2017 The OTS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef OTS_MEMORY_STREAM_H_
6 #define OTS_MEMORY_STREAM_H_
7 
8 #include <cstring>
9 #include <limits>
10 
11 #include "opentype-sanitiser.h"
12 
13 namespace ots {
14 
15 class MemoryStream : public OTSStream {
16  public:
MemoryStream(void * ptr,size_t length)17   MemoryStream(void *ptr, size_t length)
18       : ptr_(ptr), length_(length), off_(0) {
19   }
20 
WriteRaw(const void * data,size_t length)21   virtual bool WriteRaw(const void *data, size_t length) {
22     if ((off_ + length > length_) ||
23         (length > std::numeric_limits<size_t>::max() - off_)) {
24       return false;
25     }
26     std::memcpy(static_cast<char*>(ptr_) + off_, data, length);
27     off_ += length;
28     return true;
29   }
30 
Seek(off_t position)31   virtual bool Seek(off_t position) {
32     if (position < 0) return false;
33     if (static_cast<size_t>(position) > length_) return false;
34     off_ = position;
35     return true;
36   }
37 
Tell()38   virtual off_t Tell() const {
39     return off_;
40   }
41 
42  private:
43   void* const ptr_;
44   size_t length_;
45   off_t off_;
46 };
47 
48 class ExpandingMemoryStream : public OTSStream {
49  public:
ExpandingMemoryStream(size_t initial,size_t limit)50   ExpandingMemoryStream(size_t initial, size_t limit)
51       : length_(initial), limit_(limit), off_(0) {
52     ptr_ = new uint8_t[length_];
53   }
54 
~ExpandingMemoryStream()55   ~ExpandingMemoryStream() {
56     delete[] static_cast<uint8_t*>(ptr_);
57   }
58 
get()59   void* get() const {
60     return ptr_;
61   }
62 
WriteRaw(const void * data,size_t length)63   bool WriteRaw(const void *data, size_t length) {
64     if ((off_ + length > length_) ||
65         (length > std::numeric_limits<size_t>::max() - off_)) {
66       if (length_ == limit_)
67         return false;
68       size_t new_length = (length_ + 1) * 2;
69       if (new_length < length_)
70         return false;
71       if (new_length > limit_)
72         new_length = limit_;
73       uint8_t* new_buf = new uint8_t[new_length];
74       std::memcpy(new_buf, ptr_, length_);
75       length_ = new_length;
76       delete[] static_cast<uint8_t*>(ptr_);
77       ptr_ = new_buf;
78       return WriteRaw(data, length);
79     }
80     std::memcpy(static_cast<char*>(ptr_) + off_, data, length);
81     off_ += length;
82     return true;
83   }
84 
Seek(off_t position)85   bool Seek(off_t position) {
86     if (position < 0) return false;
87     if (static_cast<size_t>(position) > length_) return false;
88     off_ = position;
89     return true;
90   }
91 
Tell()92   off_t Tell() const {
93     return off_;
94   }
95 
96  private:
97   void* ptr_;
98   size_t length_;
99   const size_t limit_;
100   off_t off_;
101 };
102 
103 }  // namespace ots
104 
105 #endif  // OTS_MEMORY_STREAM_H_
106