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 }