text: // Copyright 2013 Google Inc. All Rights Reserved.
  //
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //
  // http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  //
  // The parts of ots.h & opentype-sanitiser.h that we need, taken from the
  // https://code.google.com/p/ots/ project.
  
  #ifndef WOFF2_BUFFER_H_
  #define WOFF2_BUFFER_H_
  
  #if defined(_WIN32)
  #include <stdlib.h>
  typedef signed char int8_t;
  typedef unsigned char uint8_t;
  typedef short int16_t;
  typedef unsigned short uint16_t;
  typedef int int32_t;
  typedef unsigned int uint32_t;
  typedef __int64 int64_t;
  typedef unsigned __int64 uint64_t;
  #define ntohl(x) _byteswap_ulong (x)
  #define ntohs(x) _byteswap_ushort (x)
  #define htonl(x) _byteswap_ulong (x)
  #define htons(x) _byteswap_ushort (x)
  #else
  #include <arpa/inet.h>
  #include <stdint.h>
  #endif
  
  #include <cstdio>
  #include <cstdlib>
  #include <cstring>
  #include <limits>
  
  namespace woff2 {
  
  #if defined(_MSC_VER) || !defined(FONT_COMPRESSION_DEBUG)
  #define FONT_COMPRESSION_FAILURE() false
  #else
  #define FONT_COMPRESSION_FAILURE() \
    util::compression::font::Failure(__FILE__, __LINE__, __PRETTY_FUNCTION__)
  inline bool Failure(const char *f, int l, const char *fn) {
    fprintf(stderr, "ERROR at %s:%d (%s)\n", f, l, fn);
    fflush(stderr);
    return false;
  }
  #endif
  
  // -----------------------------------------------------------------------------
  // Buffer helper class
  //
  // This class perform some trival buffer operations while checking for
  // out-of-bounds errors. As a family they return false if anything is amiss,
  // updating the current offset otherwise.
  // -----------------------------------------------------------------------------
  class Buffer {
   public:
    Buffer(const uint8_t *buffer, size_t len)
        : buffer_(buffer),
          length_(len),
          offset_(0) { }
  
    bool Skip(size_t n_bytes) {
      return Read(NULL, n_bytes);
    }
  
    bool Read(uint8_t *buffer, size_t n_bytes) {
      if (n_bytes > 1024 * 1024 * 1024) {
        return FONT_COMPRESSION_FAILURE();
      }
      if ((offset_ + n_bytes > length_) ||
          (offset_ > length_ - n_bytes)) {
        return FONT_COMPRESSION_FAILURE();
      }
      if (buffer) {
        std::memcpy(buffer, buffer_ + offset_, n_bytes);
      }
      offset_ += n_bytes;
      return true;
    }
  
    inline bool ReadU8(uint8_t *value) {
      if (offset_ + 1 > length_) {
        return FONT_COMPRESSION_FAILURE();
      }
      *value = buffer_[offset_];
      ++offset_;
      return true;
    }
  
    bool ReadU16(uint16_t *value) {
      if (offset_ + 2 > length_) {
        return FONT_COMPRESSION_FAILURE();
      }
      std::memcpy(value, buffer_ + offset_, sizeof(uint16_t));
      *value = ntohs(*value);
      offset_ += 2;
      return true;
    }
  
    bool ReadS16(int16_t *value) {
      return ReadU16(reinterpret_cast<uint16_t*>(value));
    }
  
    bool ReadU24(uint32_t *value) {
      if (offset_ + 3 > length_) {
        return FONT_COMPRESSION_FAILURE();
      }
      *value = static_cast<uint32_t>(buffer_[offset_]) << 16 |
          static_cast<uint32_t>(buffer_[offset_ + 1]) << 8 |
          static_cast<uint32_t>(buffer_[offset_ + 2]);
      offset_ += 3;
      return true;
    }
  
    bool ReadU32(uint32_t *value) {
      if (offset_ + 4 > length_) {
        return FONT_COMPRESSION_FAILURE();
      }
      std::memcpy(value, buffer_ + offset_, sizeof(uint32_t));
      *value = ntohl(*value);
      offset_ += 4;
      return true;
    }
  
    bool ReadS32(int32_t *value) {
      return ReadU32(reinterpret_cast<uint32_t*>(value));
    }
  
    bool ReadTag(uint32_t *value) {
      if (offset_ + 4 > length_) {
        return FONT_COMPRESSION_FAILURE();
      }
      std::memcpy(value, buffer_ + offset_, sizeof(uint32_t));
      offset_ += 4;
      return true;
    }
  
    bool ReadR64(uint64_t *value) {
      if (offset_ + 8 > length_) {
        return FONT_COMPRESSION_FAILURE();
      }
      std::memcpy(value, buffer_ + offset_, sizeof(uint64_t));
      offset_ += 8;
      return true;
    }
  
    const uint8_t *buffer() const { return buffer_; }
    size_t offset() const { return offset_; }
    size_t length() const { return length_; }
  
    void set_offset(size_t newoffset) { offset_ = newoffset; }
  
   private:
    const uint8_t * const buffer_;
    const size_t length_;
    size_t offset_;
  };
  
  } // namespace woff2
  
  #endif  // WOFF2_BUFFER_H_
  