• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
OTSStream()40   OTSStream() {
41     ResetChecksum();
42   }
43 
~OTSStream()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 
Write(const void * data,size_t length)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 
Pad(size_t bytes)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 
WriteU8(uint8_t v)105   bool WriteU8(uint8_t v) {
106     return Write(&v, sizeof(v));
107   }
108 
WriteU16(uint16_t v)109   bool WriteU16(uint16_t v) {
110     v = htons(v);
111     return Write(&v, sizeof(v));
112   }
113 
WriteS16(int16_t v)114   bool WriteS16(int16_t v) {
115     v = htons(v);
116     return Write(&v, sizeof(v));
117   }
118 
WriteU24(uint32_t v)119   bool WriteU24(uint32_t v) {
120     v = htonl(v);
121     return Write(reinterpret_cast<uint8_t*>(&v)+1, 3);
122   }
123 
WriteU32(uint32_t v)124   bool WriteU32(uint32_t v) {
125     v = htonl(v);
126     return Write(&v, sizeof(v));
127   }
128 
WriteS32(int32_t v)129   bool WriteS32(int32_t v) {
130     v = htonl(v);
131     return Write(&v, sizeof(v));
132   }
133 
WriteR64(uint64_t v)134   bool WriteR64(uint64_t v) {
135     return Write(&v, sizeof(v));
136   }
137 
WriteTag(uint32_t v)138   bool WriteTag(uint32_t v) {
139     return Write(&v, sizeof(v));
140   }
141 
ResetChecksum()142   void ResetChecksum() {
143     chksum_ = 0;
144     chksum_buffer_offset_ = 0;
145   }
146 
chksum()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 
SaveChecksumState()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 
RestoreChecksum(const ChecksumState & s)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