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 OPENTYPE_SANITISER_H_ 6 #define OPENTYPE_SANITISER_H_ 7 8 #if defined(_WIN32) 9 #include <stdlib.h> 10 typedef signed char int8_t; 11 typedef unsigned char uint8_t; 12 typedef short int16_t; 13 typedef unsigned short uint16_t; 14 typedef int int32_t; 15 typedef unsigned int uint32_t; 16 typedef __int64 int64_t; 17 typedef unsigned __int64 uint64_t; 18 #define ntohl(x) _byteswap_ulong (x) 19 #define ntohs(x) _byteswap_ushort (x) 20 #define htonl(x) _byteswap_ulong (x) 21 #define htons(x) _byteswap_ushort (x) 22 #else 23 #include <arpa/inet.h> 24 #include <stdint.h> 25 #endif 26 27 #include <algorithm> // for std::min 28 #include <cassert> 29 #include <cstddef> 30 #include <cstring> 31 32 namespace ots { 33 34 // ----------------------------------------------------------------------------- 35 // This is an interface for an abstract stream class which is used for writing 36 // the serialised results out. 37 // ----------------------------------------------------------------------------- 38 class OTSStream { 39 public: 40 OTSStream() { 41 ResetChecksum(); 42 } 43 44 virtual ~OTSStream() {} 45 46 // This should be implemented to perform the actual write. 47 virtual bool WriteRaw(const void *data, size_t length) = 0; 48 49 bool Write(const void *data, size_t length) { 50 if (!length) return false; 51 52 const size_t orig_length = length; 53 size_t offset = 0; 54 if (chksum_buffer_offset_) { 55 const size_t l = 56 std::min(length, static_cast<size_t>(4) - chksum_buffer_offset_); 57 std::memcpy(chksum_buffer_ + chksum_buffer_offset_, data, l); 58 chksum_buffer_offset_ += l; 59 offset += l; 60 length -= l; 61 } 62 63 if (chksum_buffer_offset_ == 4) { 64 uint32_t chksum; 65 std::memcpy(&chksum, chksum_buffer_, 4); 66 chksum_ += ntohl(chksum); 67 chksum_buffer_offset_ = 0; 68 } 69 70 while (length >= 4) { 71 chksum_ += ntohl(*reinterpret_cast<const uint32_t*>( 72 reinterpret_cast<const uint8_t*>(data) + offset)); 73 length -= 4; 74 offset += 4; 75 } 76 77 if (length) { 78 if (chksum_buffer_offset_ != 0) return false; // not reached 79 if (length > 4) return false; // not reached 80 std::memcpy(chksum_buffer_, 81 reinterpret_cast<const uint8_t*>(data) + offset, length); 82 chksum_buffer_offset_ = length; 83 } 84 85 return WriteRaw(data, orig_length); 86 } 87 88 virtual bool Seek(off_t position) = 0; 89 virtual off_t Tell() const = 0; 90 91 virtual bool Pad(size_t bytes) { 92 static const uint32_t kZero = 0; 93 while (bytes >= 4) { 94 if (!WriteTag(kZero)) return false; 95 bytes -= 4; 96 } 97 while (bytes) { 98 static const uint8_t kZerob = 0; 99 if (!Write(&kZerob, 1)) return false; 100 bytes--; 101 } 102 return true; 103 } 104 105 bool WriteU8(uint8_t v) { 106 return Write(&v, sizeof(v)); 107 } 108 109 bool WriteU16(uint16_t v) { 110 v = htons(v); 111 return Write(&v, sizeof(v)); 112 } 113 114 bool WriteS16(int16_t v) { 115 v = htons(v); 116 return Write(&v, sizeof(v)); 117 } 118 119 bool WriteU24(uint32_t v) { 120 v = htonl(v); 121 return Write(reinterpret_cast<uint8_t*>(&v)+1, 3); 122 } 123 124 bool WriteU32(uint32_t v) { 125 v = htonl(v); 126 return Write(&v, sizeof(v)); 127 } 128 129 bool WriteS32(int32_t v) { 130 v = htonl(v); 131 return Write(&v, sizeof(v)); 132 } 133 134 bool WriteR64(uint64_t v) { 135 return Write(&v, sizeof(v)); 136 } 137 138 bool WriteTag(uint32_t v) { 139 return Write(&v, sizeof(v)); 140 } 141 142 void ResetChecksum() { 143 chksum_ = 0; 144 chksum_buffer_offset_ = 0; 145 } 146 147 uint32_t chksum() const { 148 assert(chksum_buffer_offset_ == 0); 149 return chksum_; 150 } 151 152 struct ChecksumState { 153 uint32_t chksum; 154 uint8_t chksum_buffer[4]; 155 unsigned chksum_buffer_offset; 156 }; 157 158 ChecksumState SaveChecksumState() const { 159 ChecksumState s; 160 s.chksum = chksum_; 161 s.chksum_buffer_offset = chksum_buffer_offset_; 162 std::memcpy(s.chksum_buffer, chksum_buffer_, 4); 163 164 return s; 165 } 166 167 void RestoreChecksum(const ChecksumState &s) { 168 assert(chksum_buffer_offset_ == 0); 169 chksum_ += s.chksum; 170 chksum_buffer_offset_ = s.chksum_buffer_offset; 171 std::memcpy(chksum_buffer_, s.chksum_buffer, 4); 172 } 173 174 protected: 175 uint32_t chksum_; 176 uint8_t chksum_buffer_[4]; 177 unsigned chksum_buffer_offset_; 178 }; 179 180 // ----------------------------------------------------------------------------- 181 // Process a given OpenType file and write out a sanitised version 182 // output: a pointer to an object implementing the OTSStream interface. The 183 // sanitisied output will be written to this. In the even of a failure, 184 // partial output may have been written. 185 // input: the OpenType file 186 // length: the size, in bytes, of |input| 187 // ----------------------------------------------------------------------------- 188 bool Process(OTSStream *output, const uint8_t *input, size_t length); 189 190 // Force to disable debug output even when the library is compiled with 191 // -DOTS_DEBUG. 192 void DisableDebugOutput(); 193 194 // Enable WOFF2 support(experimental). 195 void EnableWOFF2(); 196 197 } // namespace ots 198 199 #endif // OPENTYPE_SANITISER_H_ 200