1/* 2 * Copyright (c) 2000-2004,2011,2014 Apple 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// bufferfifo - a Sink that queues data in a FIFO of buffers for retrieval 27// 28#include "bufferfifo.h" 29#include <security_utilities/memutils.h> 30 31 32namespace Security { 33 34 35// 36// On destruction, throw away all queued buffers (that haven't been picked up) 37// 38BufferFifo::~BufferFifo() 39{ 40 while (!mBuffers.empty()) { 41 delete mBuffers.front(); 42 mBuffers.pop(); 43 } 44} 45 46void BufferFifo::clearBuffer() 47{ 48 while (!mBuffers.empty()) { 49 delete mBuffers.front(); 50 mBuffers.pop(); 51 } 52 mSize = 0; 53} 54 55// 56// This is the put function of a Sink. We store the data in at most two buffers: 57// First we append to the last (partially filled) one; then we allocate a new one 58// (if needed) to hold the rest. 59// 60void BufferFifo::consume(const void *data, size_t size) 61{ 62 mSize += size; 63 64 // step 1: fill the rearmost (partially filled) buffer 65 if (size > 0 && !mBuffers.empty()) { 66 Buffer *current = mBuffers.back(); 67 size_t length = current->put(data, size); 68 data = LowLevelMemoryUtilities::increment(data, length); 69 size -= length; 70 } 71 // step 2: if there's anything left, make a new buffer and fill it 72 if (size > 0) { // not done 73 Buffer *current = new Buffer(max(bufferLength, size)); 74 mBuffers.push(current); 75 assert(current->available() >= size); 76 current->put(data, size); 77 } 78} 79 80 81// 82// Pull the first (FI) buffer off the queue and deliver it. 83// We retain no memory of it; it belongs to the caller now. 84// 85Buffer *BufferFifo::pop() 86{ 87 assert(!mBuffers.empty()); 88 Buffer *top = mBuffers.front(); 89 mBuffers.pop(); 90 return top; 91} 92 93 94} // end namespace Security 95