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