OLD | NEW |
(Empty) | |
| 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_H_ |
| 6 #define OTS_H_ |
| 7 |
| 8 #include <stddef.h> |
| 9 #include <cstdarg> |
| 10 #include <cstddef> |
| 11 #include <cstdio> |
| 12 #include <cstdlib> |
| 13 #include <cstring> |
| 14 #include <limits> |
| 15 |
| 16 #include "opentype-sanitiser.h" |
| 17 |
| 18 // arraysize borrowed from base/basictypes.h |
| 19 template <typename T, size_t N> |
| 20 char (&ArraySizeHelper(T (&array)[N]))[N]; |
| 21 #define arraysize(array) (sizeof(ArraySizeHelper(array))) |
| 22 |
| 23 namespace ots { |
| 24 |
| 25 #if !defined(OTS_DEBUG) |
| 26 #define OTS_FAILURE() false |
| 27 #else |
| 28 #define OTS_FAILURE() \ |
| 29 (\ |
| 30 std::fprintf(stderr, "ERROR at %s:%d (%s)\n", \ |
| 31 __FILE__, __LINE__, __FUNCTION__) \ |
| 32 && false\ |
| 33 ) |
| 34 #endif |
| 35 |
| 36 // All OTS_FAILURE_* macros ultimately evaluate to 'false', just like the origin
al |
| 37 // message-less OTS_FAILURE(), so that the current parser will return 'false' as |
| 38 // its result (indicating a failure). |
| 39 |
| 40 #if !defined(OTS_DEBUG) |
| 41 #define OTS_MESSAGE_(level,otf_,...) \ |
| 42 (otf_)->context->Message(level,__VA_ARGS__) |
| 43 #else |
| 44 #define OTS_MESSAGE_(level,otf_,...) \ |
| 45 OTS_FAILURE(), \ |
| 46 (otf_)->context->Message(level,__VA_ARGS__) |
| 47 #endif |
| 48 |
| 49 // Generate a simple message |
| 50 #define OTS_FAILURE_MSG_(otf_,...) \ |
| 51 (OTS_MESSAGE_(0,otf_,__VA_ARGS__), false) |
| 52 |
| 53 #define OTS_WARNING_MSG_(otf_,...) \ |
| 54 OTS_MESSAGE_(1,otf_,__VA_ARGS__) |
| 55 |
| 56 // Generate a message with an associated table tag |
| 57 #define OTS_FAILURE_MSG_TAG_(otf_,msg_,tag_) \ |
| 58 (OTS_MESSAGE_(0,otf_,"%4.4s: %s", tag_, msg_), false) |
| 59 |
| 60 // Convenience macros for use in files that only handle a single table tag, |
| 61 // defined as TABLE_NAME at the top of the file; the 'file' variable is |
| 62 // expected to be the current OpenTypeFile pointer. |
| 63 #define OTS_FAILURE_MSG(...) OTS_FAILURE_MSG_(file, TABLE_NAME ": " __VA_ARGS__) |
| 64 |
| 65 #define OTS_WARNING(...) OTS_WARNING_MSG_(file, TABLE_NAME ": " __VA_ARGS__) |
| 66 |
| 67 // ----------------------------------------------------------------------------- |
| 68 // Buffer helper class |
| 69 // |
| 70 // This class perform some trival buffer operations while checking for |
| 71 // out-of-bounds errors. As a family they return false if anything is amiss, |
| 72 // updating the current offset otherwise. |
| 73 // ----------------------------------------------------------------------------- |
| 74 class Buffer { |
| 75 public: |
| 76 Buffer(const uint8_t *buf, size_t len) |
| 77 : buffer_(buf), |
| 78 length_(len), |
| 79 offset_(0) { } |
| 80 |
| 81 bool Skip(size_t n_bytes) { |
| 82 return Read(NULL, n_bytes); |
| 83 } |
| 84 |
| 85 bool Read(uint8_t *buf, size_t n_bytes) { |
| 86 if (n_bytes > 1024 * 1024 * 1024) { |
| 87 return OTS_FAILURE(); |
| 88 } |
| 89 if ((offset_ + n_bytes > length_) || |
| 90 (offset_ > length_ - n_bytes)) { |
| 91 return OTS_FAILURE(); |
| 92 } |
| 93 if (buf) { |
| 94 std::memcpy(buf, buffer_ + offset_, n_bytes); |
| 95 } |
| 96 offset_ += n_bytes; |
| 97 return true; |
| 98 } |
| 99 |
| 100 inline bool ReadU8(uint8_t *value) { |
| 101 if (offset_ + 1 > length_) { |
| 102 return OTS_FAILURE(); |
| 103 } |
| 104 *value = buffer_[offset_]; |
| 105 ++offset_; |
| 106 return true; |
| 107 } |
| 108 |
| 109 bool ReadU16(uint16_t *value) { |
| 110 if (offset_ + 2 > length_) { |
| 111 return OTS_FAILURE(); |
| 112 } |
| 113 std::memcpy(value, buffer_ + offset_, sizeof(uint16_t)); |
| 114 *value = ntohs(*value); |
| 115 offset_ += 2; |
| 116 return true; |
| 117 } |
| 118 |
| 119 bool ReadS16(int16_t *value) { |
| 120 return ReadU16(reinterpret_cast<uint16_t*>(value)); |
| 121 } |
| 122 |
| 123 bool ReadU24(uint32_t *value) { |
| 124 if (offset_ + 3 > length_) { |
| 125 return OTS_FAILURE(); |
| 126 } |
| 127 *value = static_cast<uint32_t>(buffer_[offset_]) << 16 | |
| 128 static_cast<uint32_t>(buffer_[offset_ + 1]) << 8 | |
| 129 static_cast<uint32_t>(buffer_[offset_ + 2]); |
| 130 offset_ += 3; |
| 131 return true; |
| 132 } |
| 133 |
| 134 bool ReadU32(uint32_t *value) { |
| 135 if (offset_ + 4 > length_) { |
| 136 return OTS_FAILURE(); |
| 137 } |
| 138 std::memcpy(value, buffer_ + offset_, sizeof(uint32_t)); |
| 139 *value = ntohl(*value); |
| 140 offset_ += 4; |
| 141 return true; |
| 142 } |
| 143 |
| 144 bool ReadS32(int32_t *value) { |
| 145 return ReadU32(reinterpret_cast<uint32_t*>(value)); |
| 146 } |
| 147 |
| 148 bool ReadTag(uint32_t *value) { |
| 149 if (offset_ + 4 > length_) { |
| 150 return OTS_FAILURE(); |
| 151 } |
| 152 std::memcpy(value, buffer_ + offset_, sizeof(uint32_t)); |
| 153 offset_ += 4; |
| 154 return true; |
| 155 } |
| 156 |
| 157 bool ReadR64(uint64_t *value) { |
| 158 if (offset_ + 8 > length_) { |
| 159 return OTS_FAILURE(); |
| 160 } |
| 161 std::memcpy(value, buffer_ + offset_, sizeof(uint64_t)); |
| 162 offset_ += 8; |
| 163 return true; |
| 164 } |
| 165 |
| 166 const uint8_t *buffer() const { return buffer_; } |
| 167 size_t offset() const { return offset_; } |
| 168 size_t length() const { return length_; } |
| 169 |
| 170 void set_offset(size_t newoffset) { offset_ = newoffset; } |
| 171 |
| 172 private: |
| 173 const uint8_t * const buffer_; |
| 174 const size_t length_; |
| 175 size_t offset_; |
| 176 }; |
| 177 |
| 178 // Round a value up to the nearest multiple of 4. Don't round the value in the |
| 179 // case that rounding up overflows. |
| 180 template<typename T> T Round4(T value) { |
| 181 if (std::numeric_limits<T>::max() - value < 3) { |
| 182 return value; |
| 183 } |
| 184 return (value + 3) & ~3; |
| 185 } |
| 186 |
| 187 template<typename T> T Round2(T value) { |
| 188 if (value == std::numeric_limits<T>::max()) { |
| 189 return value; |
| 190 } |
| 191 return (value + 1) & ~1; |
| 192 } |
| 193 |
| 194 bool IsValidVersionTag(uint32_t tag); |
| 195 |
| 196 #define FOR_EACH_TABLE_TYPE \ |
| 197 F(cff, CFF) \ |
| 198 F(cmap, CMAP) \ |
| 199 F(cvt, CVT) \ |
| 200 F(fpgm, FPGM) \ |
| 201 F(gasp, GASP) \ |
| 202 F(gdef, GDEF) \ |
| 203 F(glyf, GLYF) \ |
| 204 F(gpos, GPOS) \ |
| 205 F(gsub, GSUB) \ |
| 206 F(hdmx, HDMX) \ |
| 207 F(head, HEAD) \ |
| 208 F(hhea, HHEA) \ |
| 209 F(hmtx, HMTX) \ |
| 210 F(kern, KERN) \ |
| 211 F(loca, LOCA) \ |
| 212 F(ltsh, LTSH) \ |
| 213 F(math, MATH) \ |
| 214 F(maxp, MAXP) \ |
| 215 F(name, NAME) \ |
| 216 F(os2, OS2) \ |
| 217 F(post, POST) \ |
| 218 F(prep, PREP) \ |
| 219 F(vdmx, VDMX) \ |
| 220 F(vorg, VORG) \ |
| 221 F(vhea, VHEA) \ |
| 222 F(vmtx, VMTX) |
| 223 |
| 224 #define F(name, capname) struct OpenType##capname; |
| 225 FOR_EACH_TABLE_TYPE |
| 226 #undef F |
| 227 |
| 228 struct OpenTypeFile { |
| 229 OpenTypeFile() { |
| 230 #define F(name, capname) name = NULL; |
| 231 FOR_EACH_TABLE_TYPE |
| 232 #undef F |
| 233 } |
| 234 |
| 235 uint32_t version; |
| 236 uint16_t num_tables; |
| 237 uint16_t search_range; |
| 238 uint16_t entry_selector; |
| 239 uint16_t range_shift; |
| 240 |
| 241 OTSContext *context; |
| 242 |
| 243 #define F(name, capname) OpenType##capname *name; |
| 244 FOR_EACH_TABLE_TYPE |
| 245 #undef F |
| 246 }; |
| 247 |
| 248 #define F(name, capname) \ |
| 249 bool ots_##name##_parse(OpenTypeFile *f, const uint8_t *d, size_t l); \ |
| 250 bool ots_##name##_should_serialise(OpenTypeFile *f); \ |
| 251 bool ots_##name##_serialise(OTSStream *s, OpenTypeFile *f); \ |
| 252 void ots_##name##_free(OpenTypeFile *f); |
| 253 // TODO(yusukes): change these function names to follow Chromium coding rule. |
| 254 FOR_EACH_TABLE_TYPE |
| 255 #undef F |
| 256 |
| 257 } // namespace ots |
| 258 |
| 259 #endif // OTS_H_ |
OLD | NEW |