130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/*
230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * Copyright 2011 Google Inc. All Rights Reserved.
330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *
430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * Licensed under the Apache License, Version 2.0 (the "License");
530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * you may not use this file except in compliance with the License.
630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * You may obtain a copy of the License at
730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *
830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *      http://www.apache.org/licenses/LICENSE-2.0
930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *
1030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * Unless required by applicable law or agreed to in writing, software
1130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * distributed under the License is distributed on an "AS IS" BASIS,
1230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * See the License for the specific language governing permissions and
1430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * limitations under the License.
1530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun */
1630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
1730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if defined (WIN32)
1830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <windows.h>
1930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
2030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
2130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <string.h>
2230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
2330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/port/memory_input_stream.h"
2430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/port/exception_type.h"
2530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
2630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunnamespace sfntly {
2730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
2830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunMemoryInputStream::MemoryInputStream()
2930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : buffer_(NULL),
3030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      position_(0),
3130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      length_(0) {
3230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
3330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
3430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunMemoryInputStream::~MemoryInputStream() {
3530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Close();
3630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
3730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
3830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t MemoryInputStream::Available() {
3930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return length_ - position_;
4030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
4130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
4230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid MemoryInputStream::Close() {
4330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
4430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
4530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid MemoryInputStream::Mark(int32_t readlimit) {
4630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // NOP
4730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  UNREFERENCED_PARAMETER(readlimit);
4830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
4930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
5030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool MemoryInputStream::MarkSupported() {
5130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return false;
5230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
5330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
5430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t MemoryInputStream::Read() {
5530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (!buffer_) {
5630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if !defined (SFNTLY_NO_EXCEPTION)
5730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    throw IOException("no memory attached");
5830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
5930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return 0;
6030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
6130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (position_ >= length_) {
6230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if !defined (SFNTLY_NO_EXCEPTION)
6330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    throw IOException("eof reached");
6430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
6530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return 0;
6630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
6730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  byte_t value = buffer_[position_++];
6830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return value;
6930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
7030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
7130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t MemoryInputStream::Read(ByteVector* b) {
7230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return Read(b, 0, b->size());
7330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
7430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
7530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t MemoryInputStream::Read(ByteVector* b, int32_t offset, int32_t length) {
7630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  assert(b);
7730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (!buffer_) {
7830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if !defined (SFNTLY_NO_EXCEPTION)
7930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    throw IOException("no memory attached");
8030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
8130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return 0;
8230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
8330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (position_ >= length_) {
8430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if !defined (SFNTLY_NO_EXCEPTION)
8530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    throw IOException("eof reached");
8630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
8730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return 0;
8830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
8930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  size_t read_count = std::min<size_t>(length_ - position_, length);
9030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (b->size() < (size_t)(offset + read_count)) {
9130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    b->resize((size_t)(offset + read_count));
9230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
9330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  memcpy(&((*b)[offset]), buffer_ + position_, read_count);
9430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  position_ += read_count;
9530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return read_count;
9630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
9730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
9830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid MemoryInputStream::Reset() {
9930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // NOP
10030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
10130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
10230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint64_t MemoryInputStream::Skip(int64_t n) {
10330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (!buffer_) {
10430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if !defined (SFNTLY_NO_EXCEPTION)
10530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    throw IOException("no memory attached");
10630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
10730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return 0;
10830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
10930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int64_t skip_count = 0;
11030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (n < 0) {  // move backwards
11130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    skip_count = std::max<int64_t>(0 - (int64_t)position_, n);
11230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    position_ -= (size_t)(0 - skip_count);
11330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  } else {
11430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    skip_count = std::min<size_t>(length_ - position_, (size_t)n);
11530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    position_ += (size_t)skip_count;
11630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
11730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return skip_count;
11830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
11930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
12030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid MemoryInputStream::Unread(ByteVector* b) {
12130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Unread(b, 0, b->size());
12230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
12330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
12430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid MemoryInputStream::Unread(ByteVector* b, int32_t offset, int32_t length) {
12530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  assert(b);
12630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  assert(b->size() >= size_t(offset + length));
12730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (!buffer_) {
12830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if !defined (SFNTLY_NO_EXCEPTION)
12930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    throw IOException("no memory attached");
13030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
13130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return;
13230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
13330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  size_t unread_count = std::min<size_t>(position_, length);
13430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  position_ -= unread_count;
13530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Read(b, offset, length);
13630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  position_ -= unread_count;
13730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
13830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
13930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool MemoryInputStream::Attach(const byte_t* buffer, size_t length) {
14030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  assert(buffer);
14130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  assert(length);
14230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  buffer_ = buffer;
14330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  length_ = length;
14430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return true;
14530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
14630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
14730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}  // namespace sfntly
148