Home | History | Annotate | Download | only in include
      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 
     13 namespace ots {
     14 
     15 class 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 
     48 class 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       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