1d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// Copyright (c) 2009 The Chromium Authors. All rights reserved.
2d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// Use of this source code is governed by a BSD-style license that can be
3d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// found in the LICENSE file.
4d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
5d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org#ifndef OTS_MEMORY_STREAM_H_
6d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org#define OTS_MEMORY_STREAM_H_
7d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
8d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org#include <cstring>
9d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org#include <limits>
10d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
11d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org#include "opentype-sanitiser.h"
12d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
13d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgnamespace ots {
14d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
15d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgclass MemoryStream : public OTSStream {
16d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org public:
17d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  MemoryStream(void *ptr, size_t length)
18d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      : ptr_(ptr), length_(length), off_(0) {
19d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  }
20d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
2178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  virtual bool WriteRaw(const void *data, size_t length) {
22d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    if ((off_ + length > length_) ||
23d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org        (length > std::numeric_limits<size_t>::max() - off_)) {
24d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org      return false;
25d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    }
26d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    std::memcpy(static_cast<char*>(ptr_) + off_, data, length);
27d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    off_ += length;
28d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    return true;
29d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  }
30d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
3178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  virtual bool Seek(off_t position) {
32d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    if (position < 0) return false;
33d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    if (static_cast<size_t>(position) > length_) return false;
34d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    off_ = position;
35d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    return true;
36d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  }
37d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
3878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  virtual off_t Tell() const {
39d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org    return off_;
40d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  }
41d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
42d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org private:
435089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org  void* const ptr_;
44d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  size_t length_;
45d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org  off_t off_;
46d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org};
47d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
485089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.orgclass ExpandingMemoryStream : public OTSStream {
495089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org public:
505089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org  ExpandingMemoryStream(size_t initial, size_t limit)
515089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org      : length_(initial), limit_(limit), off_(0) {
525089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org    ptr_ = new uint8_t[length_];
535089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org  }
545089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org
555089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org  ~ExpandingMemoryStream() {
565089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org    delete[] static_cast<uint8_t*>(ptr_);
575089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org  }
585089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org
595089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org  void* get() const {
605089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org    return ptr_;
615089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org  }
625089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org
635089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org  bool WriteRaw(const void *data, size_t length) {
645089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org    if ((off_ + length > length_) ||
655089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org        (length > std::numeric_limits<size_t>::max() - off_)) {
665089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org      if (length_ == limit_)
675089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org        return false;
685089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org      size_t new_length = (length_ + 1) * 2;
695089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org      if (new_length < length_)
705089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org        return false;
715089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org      if (new_length > limit_)
725089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org        new_length = limit_;
735089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org      uint8_t* new_buf = new uint8_t[new_length];
7459f812a4538f2bcb91598ae48504594a9322eb4cksakamoto@chromium.org      std::memcpy(new_buf, ptr_, length_);
755089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org      length_ = new_length;
765089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org      delete[] static_cast<uint8_t*>(ptr_);
775089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org      ptr_ = new_buf;
785089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org      return WriteRaw(data, length);
795089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org    }
805089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org    std::memcpy(static_cast<char*>(ptr_) + off_, data, length);
815089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org    off_ += length;
825089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org    return true;
835089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org  }
845089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org
855089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org  bool Seek(off_t position) {
865089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org    if (position < 0) return false;
875089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org    if (static_cast<size_t>(position) > length_) return false;
885089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org    off_ = position;
895089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org    return true;
905089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org  }
915089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org
925089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org  off_t Tell() const {
935089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org    return off_;
945089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org  }
955089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org
965089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org private:
975089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org  void* ptr_;
985089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org  size_t length_;
995089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org  const size_t limit_;
1005089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org  off_t off_;
1015089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org};
1025089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org
103d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org}  // namespace ots
104d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org
105d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org#endif  // OTS_MEMORY_STREAM_H_
106