1 /** 2 * Output Buffer 3 * 4 * Copyright: 5 * (C) 1999-2007 Jack Lloyd 6 * (C) 2014-2015 Etienne Cimon 7 * 2012 Markus Wanner 8 * 9 * License: 10 * Botan is released under the Simplified BSD License (see LICENSE.md) 11 */ 12 module botan.filters.out_buf; 13 14 import botan.utils.types; 15 import botan.filters.pipe; 16 import botan.filters.secqueue; 17 /** 18 * Container of output buffers for Pipe 19 */ 20 struct OutputBuffers 21 { 22 public: 23 /* 24 * Read data from a message 25 */ 26 size_t read(ubyte* output, size_t length, 27 Pipe.message_id msg) 28 { 29 SecureQueue q = get(msg); 30 if (q) 31 return q.read(output, length); 32 return 0; 33 } 34 35 /* 36 * Peek at data in a message 37 */ 38 size_t peek(ubyte* output, size_t length, 39 size_t stream_offset, 40 Pipe.message_id msg) const 41 { 42 SecureQueue q = get(msg); 43 if (q) 44 return q.peek(output, length, stream_offset); 45 return 0; 46 } 47 48 /* 49 * Return the total bytes of a message that have already been read. 50 */ 51 size_t getBytesRead(Pipe.message_id msg) const 52 { 53 SecureQueue q = get(msg); 54 if (q) 55 return q.getBytesRead(); 56 return 0; 57 } 58 59 /* 60 * Check available bytes in a message 61 */ 62 size_t remaining(Pipe.message_id msg) const 63 { 64 SecureQueue q = get(msg); 65 if (q) 66 return q.length; 67 return 0; 68 } 69 70 /* 71 * Add a new output queue 72 */ 73 void add(SecureQueue queue) 74 { 75 assert(queue, "queue was provided"); 76 77 // assert(m_buffers.length < m_buffers.capacity, "Room was available in container"); 78 79 m_buffers.pushBack(queue); 80 } 81 82 /* 83 * Retire old output queues 84 */ 85 void retire() 86 { 87 foreach (size_t i; 0 .. m_buffers.length) 88 if (m_buffers[i] && m_buffers[i].length == 0) 89 { 90 destroy(m_buffers[i]); 91 m_buffers[i] = null; 92 } 93 94 while (m_buffers.length && !m_buffers[0]) 95 { 96 m_buffers = Vector!SecureQueue(m_buffers[1 .. $]); 97 m_offset = m_offset + Pipe.message_id(1); 98 } 99 } 100 101 /* 102 * Return the total number of messages 103 */ 104 Pipe.message_id messageCount() const 105 { 106 return (m_offset + m_buffers.length); 107 } 108 109 ~this() 110 { 111 for (size_t j = 0; j != m_buffers.length; ++j) 112 destroy(m_buffers[j]); 113 } 114 private: 115 /* 116 * Get a particular output queue 117 */ 118 SecureQueue get(Pipe.message_id msg) const 119 { 120 if (msg < m_offset) 121 return null; 122 123 assert(msg < messageCount(), "Message number is in range"); 124 125 return m_buffers[msg - m_offset]; 126 } 127 128 Vector!SecureQueue m_buffers; 129 Pipe.message_id m_offset; 130 }