Home | History | Annotate | Download | only in include
      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