1/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 2 * 3 * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. 4 * 5 * @APPLE_LICENSE_HEADER_START@ 6 * 7 * This file contains Original Code and/or Modifications of Original Code 8 * as defined in and that are subject to the Apple Public Source License 9 * Version 2.0 (the 'License'). You may not use this file except in 10 * compliance with the License. Please obtain a copy of the License at 11 * http://www.opensource.apple.com/apsl/ and read it before using this 12 * file. 13 * 14 * The Original Code and all software distributed under the License are 15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 19 * Please see the License for the specific language governing rights and 20 * limitations under the License. 21 * 22 * @APPLE_LICENSE_HEADER_END@ 23 */ 24#ifndef __FILE_ABSTRACTION__ 25#define __FILE_ABSTRACTION__ 26 27 28#include <stdint.h> 29#include <string.h> 30#include <libkern/OSByteOrder.h> 31 32#ifdef __OPTIMIZE__ 33#define INLINE __attribute__((always_inline)) 34#else 35#define INLINE 36#endif 37 38// 39// This abstraction layer is for use with file formats that have 64-bit/32-bit and Big-Endian/Little-Endian variants 40// 41// For example: to make a utility that handles 32-bit little enidan files use: Pointer32<LittleEndian> 42// 43// 44// get16() read a 16-bit number from an E endian struct 45// set16() write a 16-bit number to an E endian struct 46// get32() read a 32-bit number from an E endian struct 47// set32() write a 32-bit number to an E endian struct 48// get64() read a 64-bit number from an E endian struct 49// set64() write a 64-bit number to an E endian struct 50// 51// getBits() read a bit field from an E endian struct (bitCount=number of bits in field, firstBit=bit index of field) 52// setBits() write a bit field to an E endian struct (bitCount=number of bits in field, firstBit=bit index of field) 53// 54// getBitsRaw() read a bit field from a struct with native endianness 55// setBitsRaw() write a bit field from a struct with native endianness 56// 57 58class BigEndian 59{ 60public: 61 static uint16_t get16(const uint16_t& from) INLINE { return OSReadBigInt16(&from, 0); } 62 static void set16(uint16_t& into, uint16_t value) INLINE { OSWriteBigInt16(&into, 0, value); } 63 64 static uint32_t get32(const uint32_t& from) INLINE { return OSReadBigInt32(&from, 0); } 65 static void set32(uint32_t& into, uint32_t value) INLINE { OSWriteBigInt32(&into, 0, value); } 66 67 static int32_t get32(const int32_t& from) INLINE { return OSReadBigInt32(&from, 0); } 68 static void set32(int32_t& into, int32_t value) INLINE { OSWriteBigInt32(&into, 0, value); } 69 70 static uint64_t get64(const uint64_t& from) INLINE { return OSReadBigInt64(&from, 0); } 71 static void set64(uint64_t& into, uint64_t value) INLINE { OSWriteBigInt64(&into, 0, value); } 72 73 static uint32_t getBits(const uint32_t& from, 74 uint8_t firstBit, uint8_t bitCount) INLINE { return getBitsRaw(get32(from), firstBit, bitCount); } 75 static void setBits(uint32_t& into, uint32_t value, 76 uint8_t firstBit, uint8_t bitCount) INLINE { uint32_t temp = get32(into); setBitsRaw(temp, value, firstBit, bitCount); set32(into, temp); } 77 78 static uint32_t getBitsRaw(const uint32_t& from, 79 uint8_t firstBit, uint8_t bitCount) INLINE { return ((from >> (32-firstBit-bitCount)) & ((1<<bitCount)-1)); } 80 static void setBitsRaw(uint32_t& into, uint32_t value, 81 uint8_t firstBit, uint8_t bitCount) INLINE { uint32_t temp = into; 82 const uint32_t mask = ((1<<bitCount)-1); 83 temp &= ~(mask << (32-firstBit-bitCount)); 84 temp |= ((value & mask) << (32-firstBit-bitCount)); 85 into = temp; } 86 enum { little_endian = 0 }; 87}; 88 89 90class LittleEndian 91{ 92public: 93 static uint16_t get16(const uint16_t& from) INLINE { return OSReadLittleInt16(&from, 0); } 94 static void set16(uint16_t& into, uint16_t value) INLINE { OSWriteLittleInt16(&into, 0, value); } 95 96 static uint32_t get32(const uint32_t& from) INLINE { return OSReadLittleInt32(&from, 0); } 97 static void set32(uint32_t& into, uint32_t value) INLINE { OSWriteLittleInt32(&into, 0, value); } 98 99 static int32_t get32(const int32_t& from) INLINE { return OSReadLittleInt32(&from, 0); } 100 static void set32(int32_t& into, int32_t value) INLINE { OSWriteLittleInt32(&into, 0, value); } 101 102 static uint64_t get64(const uint64_t& from) INLINE { return OSReadLittleInt64(&from, 0); } 103 static void set64(uint64_t& into, uint64_t value) INLINE { OSWriteLittleInt64(&into, 0, value); } 104 105 static uint32_t getBits(const uint32_t& from, 106 uint8_t firstBit, uint8_t bitCount) INLINE { return getBitsRaw(get32(from), firstBit, bitCount); } 107 static void setBits(uint32_t& into, uint32_t value, 108 uint8_t firstBit, uint8_t bitCount) INLINE { uint32_t temp = get32(into); setBitsRaw(temp, value, firstBit, bitCount); set32(into, temp); } 109 110 static uint32_t getBitsRaw(const uint32_t& from, 111 uint8_t firstBit, uint8_t bitCount) INLINE { return ((from >> firstBit) & ((1<<bitCount)-1)); } 112 static void setBitsRaw(uint32_t& into, uint32_t value, 113 uint8_t firstBit, uint8_t bitCount) INLINE { uint32_t temp = into; 114 const uint32_t mask = ((1<<bitCount)-1); 115 temp &= ~(mask << firstBit); 116 temp |= ((value & mask) << firstBit); 117 into = temp; } 118 enum { little_endian = 1 }; 119}; 120 121 122template <typename _E> 123class Pointer32 124{ 125public: 126 typedef uint32_t uint_t; 127 typedef _E E; 128 129 static uint64_t getP(const uint_t& from) INLINE { return _E::get32(from); } 130 static void setP(uint_t& into, uint64_t value) INLINE { _E::set32(into, (uint32_t)value); } 131 132 // Round to a P-size boundary 133 template <typename T> 134 static T round_up(T value) { return (value+3) & ~(T)3; } 135 template <typename T> 136 static T round_down(T value) { return value & ~(T)3; } 137}; 138 139 140template <typename _E> 141class Pointer64 142{ 143public: 144 typedef uint64_t uint_t; 145 typedef _E E; 146 147 static uint64_t getP(const uint_t& from) INLINE { return _E::get64(from); } 148 static void setP(uint_t& into, uint64_t value) INLINE { _E::set64(into, value); } 149 150 // Round to a P-size boundary 151 template <typename T> 152 static T round_up(T value) { return (value+7) & ~(T)7; } 153 template <typename T> 154 static T round_down(T value) { return value & ~(T)7; } 155}; 156 157 158 159 160 161#endif // __FILE_ABSTRACTION__ 162 163 164