1// Copyright 2013 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// The parts of ots.h & opentype-sanitiser.h that we need, taken from the
16// https://code.google.com/p/ots/ project.
17
18#ifndef WOFF2_BUFFER_H_
19#define WOFF2_BUFFER_H_
20
21#if defined(_WIN32)
22#include <stdlib.h>
23typedef signed char int8_t;
24typedef unsigned char uint8_t;
25typedef short int16_t;
26typedef unsigned short uint16_t;
27typedef int int32_t;
28typedef unsigned int uint32_t;
29typedef __int64 int64_t;
30typedef unsigned __int64 uint64_t;
31#define ntohl(x) _byteswap_ulong (x)
32#define ntohs(x) _byteswap_ushort (x)
33#define htonl(x) _byteswap_ulong (x)
34#define htons(x) _byteswap_ushort (x)
35#else
36#include <arpa/inet.h>
37#include <stdint.h>
38#endif
39
40#include <cstdlib>
41#include <cstring>
42#include <limits>
43
44namespace woff2 {
45
46#if defined(_MSC_VER) || !defined(FONT_COMPRESSION_DEBUG)
47#define FONT_COMPRESSION_FAILURE() false
48#else
49#define FONT_COMPRESSION_FAILURE() \
50  util::compression::font::Failure(__FILE__, __LINE__, __PRETTY_FUNCTION__)
51inline bool Failure(const char *f, int l, const char *fn) {
52  std::fprintf(stderr, "ERROR at %s:%d (%s)\n", f, l, fn);
53  std::fflush(stderr);
54  return false;
55}
56#endif
57
58// -----------------------------------------------------------------------------
59// Buffer helper class
60//
61// This class perform some trival buffer operations while checking for
62// out-of-bounds errors. As a family they return false if anything is amiss,
63// updating the current offset otherwise.
64// -----------------------------------------------------------------------------
65class Buffer {
66 public:
67  Buffer(const uint8_t *buffer, size_t len)
68      : buffer_(buffer),
69        length_(len),
70        offset_(0) { }
71
72  bool Skip(size_t n_bytes) {
73    return Read(NULL, n_bytes);
74  }
75
76  bool Read(uint8_t *buffer, size_t n_bytes) {
77    if (n_bytes > 1024 * 1024 * 1024) {
78      return FONT_COMPRESSION_FAILURE();
79    }
80    if ((offset_ + n_bytes > length_) ||
81        (offset_ > length_ - n_bytes)) {
82      return FONT_COMPRESSION_FAILURE();
83    }
84    if (buffer) {
85      std::memcpy(buffer, buffer_ + offset_, n_bytes);
86    }
87    offset_ += n_bytes;
88    return true;
89  }
90
91  inline bool ReadU8(uint8_t *value) {
92    if (offset_ + 1 > length_) {
93      return FONT_COMPRESSION_FAILURE();
94    }
95    *value = buffer_[offset_];
96    ++offset_;
97    return true;
98  }
99
100  bool ReadU16(uint16_t *value) {
101    if (offset_ + 2 > length_) {
102      return FONT_COMPRESSION_FAILURE();
103    }
104    std::memcpy(value, buffer_ + offset_, sizeof(uint16_t));
105    *value = ntohs(*value);
106    offset_ += 2;
107    return true;
108  }
109
110  bool ReadS16(int16_t *value) {
111    return ReadU16(reinterpret_cast<uint16_t*>(value));
112  }
113
114  bool ReadU24(uint32_t *value) {
115    if (offset_ + 3 > length_) {
116      return FONT_COMPRESSION_FAILURE();
117    }
118    *value = static_cast<uint32_t>(buffer_[offset_]) << 16 |
119        static_cast<uint32_t>(buffer_[offset_ + 1]) << 8 |
120        static_cast<uint32_t>(buffer_[offset_ + 2]);
121    offset_ += 3;
122    return true;
123  }
124
125  bool ReadU32(uint32_t *value) {
126    if (offset_ + 4 > length_) {
127      return FONT_COMPRESSION_FAILURE();
128    }
129    std::memcpy(value, buffer_ + offset_, sizeof(uint32_t));
130    *value = ntohl(*value);
131    offset_ += 4;
132    return true;
133  }
134
135  bool ReadS32(int32_t *value) {
136    return ReadU32(reinterpret_cast<uint32_t*>(value));
137  }
138
139  bool ReadTag(uint32_t *value) {
140    if (offset_ + 4 > length_) {
141      return FONT_COMPRESSION_FAILURE();
142    }
143    std::memcpy(value, buffer_ + offset_, sizeof(uint32_t));
144    offset_ += 4;
145    return true;
146  }
147
148  bool ReadR64(uint64_t *value) {
149    if (offset_ + 8 > length_) {
150      return FONT_COMPRESSION_FAILURE();
151    }
152    std::memcpy(value, buffer_ + offset_, sizeof(uint64_t));
153    offset_ += 8;
154    return true;
155  }
156
157  const uint8_t *buffer() const { return buffer_; }
158  size_t offset() const { return offset_; }
159  size_t length() const { return length_; }
160
161  void set_offset(size_t newoffset) { offset_ = newoffset; }
162
163 private:
164  const uint8_t * const buffer_;
165  const size_t length_;
166  size_t offset_;
167};
168
169} // namespace woff2
170
171#endif  // WOFF2_BUFFER_H_
172