1/* 2 * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25// 26// buffer - simple data buffers with convenience 27// 28#ifndef _H_BUFFER 29#define _H_BUFFER 30 31#include <security_utilities/utilities.h> 32#include <cstdarg> 33#include <limits.h> 34 35 36namespace Security { 37 38 39class Buffer { 40public: 41 Buffer(size_t size); // allocate empty buffer 42 ~Buffer(); 43 44 static Buffer reader(void *base, size_t size, bool owned = false) 45 { return Buffer(base, size, true, owned); } 46 static Buffer writer(void *base, size_t size, bool owned = false) 47 { return Buffer(base, size, false, owned); } 48 49 size_t available(bool heavy = false) const 50 { return heavy ? ((mTop - mEnd) + (mStart - mBase)): (mTop - mEnd); } 51 bool isFull(bool heavy = false) const 52 { return heavy ? (mEnd == mTop && mStart == mBase) : (mEnd == mTop); } 53 bool isEmpty() const { return mStart == mEnd; } 54 55 size_t length() const { return mEnd - mStart; } 56 void *data() { assert(mStart == mBase); return mStart; } 57 58 void clear() { mStart = mEnd = mBase; } 59 60protected: 61 // private constructor with full flexibility 62 Buffer(void *base, size_t size, bool filled, bool owned = false); 63 64 // perform expensive realignment to coalesce freespace 65 size_t shuffle(size_t needed = UINT_MAX); 66 67 // perform cheap adjustments after data was taken out 68 void adjustGet() 69 { 70 if (isEmpty()) // empty buffer. Reset pointers to base 71 mStart = mEnd = mBase; 72 } 73 74public: 75 // elementary put: copy mode 76 size_t put(const void *data, size_t length) 77 { 78 if (length > available()) 79 length = shuffle(length); 80 memcpy(mEnd, data, length); 81 mEnd += length; 82 return length; 83 } 84 85 // elementary put: locate mode. Remember that each can shuffle memory 86 template <class T> void locatePut(T * &addr, size_t &length) 87 { 88 if (length > available()) 89 length = shuffle(length); 90 addr = reinterpret_cast<T *>(mEnd); 91 } 92 93 void usePut(size_t length) 94 { 95 assert(length <= available()); 96 mEnd += length; 97 } 98 99 // elementary get: locate mode 100 template <class T> void locateGet(T * &addr, size_t &length) 101 { 102 if (length > size_t(mEnd - mStart)) 103 length = mEnd - mStart; 104 addr = reinterpret_cast<T *>(mStart); 105 } 106 107 void useGet(size_t length) 108 { 109 assert(length <= this->length()); 110 mStart += length; 111 adjustGet(); 112 } 113 114 // 115 // I/O via FileDescoid objects 116 // 117 template <class IO> 118 size_t read(IO &io, size_t length) 119 { 120 if (length > available()) 121 length = shuffle(length); 122 size_t bytesRead = io.read(mEnd, length); 123 mEnd += bytesRead; 124 return bytesRead; 125 } 126 127 template <class IO> 128 size_t write(IO &io, size_t length) 129 { 130 length = min(this->length(), length); 131 size_t bytesWritten = io.write(mStart, length); 132 mStart += bytesWritten; 133 adjustGet(); 134 return bytesWritten; 135 } 136 137 template <class IO> size_t read(IO &io, bool heavy = false) 138 { return read(io, available(heavy)); } 139 140 template <class IO> size_t write(IO &io) 141 { return write(io, length()); } 142 143 // printf-style output to a buffer 144 void printf(const char *format, ...); 145 void vprintf(const char *format, va_list args); 146 147 // memory ownership 148 void own() { mOwningMemory = true; } 149 150private: 151 char *const mBase; // base pointer 152 char *const mTop; // end pointer + 1 153 char *mStart; // start of used area 154 char *mEnd; // end of used area + 1 155 bool mOwningMemory; // true if we own the memory (free on destruction) 156}; 157 158 159} // end namespace Security 160 161 162#endif //_H_BUFFER 163