1// Copyright (c) 2009 The Chromium 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
13namespace ots {
14
15class MemoryStream : public OTSStream {
16 public:
17  MemoryStream(void *ptr, size_t length)
18      : ptr_(ptr), length_(length), off_(0) {
19  }
20
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
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
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
48class ExpandingMemoryStream : public OTSStream {
49 public:
50  ExpandingMemoryStream(size_t initial, size_t limit)
51      : length_(initial), limit_(limit), off_(0) {
52    ptr_ = new uint8_t[length_];
53  }
54
55  ~ExpandingMemoryStream() {
56    delete[] static_cast<uint8_t*>(ptr_);
57  }
58
59  void* get() const {
60    return ptr_;
61  }
62
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
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
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