]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_utilities/lib/streams.h
Security-58286.270.3.0.1.tar.gz
[apple/security.git] / OSX / libsecurity_utilities / lib / streams.h
1 /*
2 * Copyright (c) 2000-2002,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 // streams.h - lightweight source and sink objects
27 //
28 #ifndef _H_STREAMS
29 #define _H_STREAMS
30
31 #include "unix++.h"
32
33
34 namespace Security {
35
36 using UnixPlusPlus::FileDesc;
37
38
39 //
40 // An abstract Source object.
41 // Source can yield data when its produce method is called. Produce can yield
42 // anything between zero and length bytes and sets length accordingly.
43 // If the last call to produce returned zero bytes (and only then), the state method
44 // will yield an explanation:
45 // producing -> we're in business; there just no data quite yet (try again)
46 // stalled -> there may be more data coming, but not in the near future;
47 // wait a while then call state again to see
48 // endOfData -> no more data will be produced by this Source
49 // When called *before* the first call to produce, getSize may return the number
50 // of bytes that all calls to produce will yield together. If getSize returns unknownSize,
51 // this value cannot be determined beforehand. GetSize *may* yield the number of bytes
52 // yet to come when called after produce, but this is not guaranteed for all Sources.
53 //
54 class Source {
55 public:
56 virtual void produce(void *data, size_t &length) = 0;
57 virtual ~Source() { }
58
59 static const size_t unknownSize = size_t(-1);
60 virtual size_t getSize();
61
62 enum State {
63 producing, // yielding data (go ahead)
64 stalled, // no data now, perhaps more later
65 endOfData // end of data (no more data)
66 };
67 virtual State state() const;
68
69 protected:
70 State mState; // auto-regulated state (can be overridden)
71 };
72
73
74 //
75 // An abstract Sink object.
76 // Sinks can cansume data when their consume method is called.
77 // Sinks cannot refuse data; they always consume all data given to consume.
78 // There is currently no flow control/throttle mechanism (one will probably
79 // be added soon).
80 //
81 class Sink {
82 public:
83 Sink() : mSize(0) {}
84 virtual ~Sink() { }
85 virtual void consume(const void *data, size_t length) = 0;
86 virtual void setSize(size_t expectedSize);
87 size_t getSize() {return mSize;}
88
89 protected:
90 size_t mSize;
91
92 };
93
94
95 //
96 // The NullSource produces no data.
97 //
98 class NullSource : public Source {
99 public:
100 void produce(void *addr, size_t &len);
101 State state() const;
102 };
103
104
105 //
106 // A FileSource reads from a UNIX file or file descriptor.
107 // Note that getSize will yield the size of the underlying i-node,
108 // which is usually correct but may not be in the case of simultaneous
109 // access.
110 //
111 class FileSource : public Source, public FileDesc {
112 public:
113 FileSource(const char *path, int mode = O_RDONLY) : FileDesc(path, mode) { mState = producing; }
114 FileSource(int fd) : FileDesc(fd) { mState = producing; }
115 void produce(void *data, size_t &length);
116 size_t getSize();
117 };
118
119
120 //
121 // A MemorySource yields the contents of a preset contiguous memory block.
122 //
123 class MemorySource : public Source {
124 public:
125 MemorySource(const void *data, size_t length) : mData(data), mRemaining(length) { }
126
127 template <class Data>
128 MemorySource(const Data &data) : mData(data.data()), mRemaining(data.length()) { }
129
130 void produce(void *data, size_t &length);
131 size_t getSize();
132 State state() const;
133
134 private:
135 const void *mData;
136 size_t mRemaining;
137 };
138
139
140 //
141 // A NullSink eats all data and discards it quietly.
142 //
143 class NullSink : public Sink {
144 public:
145 void consume(const void *data, size_t length);
146 };
147
148
149 //
150 // A FileSink writes its received data to a UNIX file or file descriptor.
151 //
152 class FileSink : public Sink, public FileDesc {
153 public:
154 FileSink(const char *path, int mode = O_WRONLY | O_CREAT | O_TRUNC)
155 : FileDesc(path, mode) { }
156 FileSink(int fd) : FileDesc(fd) { }
157 void consume(const void *data, size_t length);
158 };
159
160
161 //
162 // MemorySinks collect output in a contiguous memory block.
163 // This is not often a good idea, so if you find yourself using this,
164 // consider consuming on-the-fly or streaming to secondary media,
165 // or (at least) use a BufferFifo instead.
166 //
167 class MemorySink : public Sink {
168 public:
169 MemorySink() : mBuffer(NULL), mMax(0) { }
170 ~MemorySink() { free(mBuffer); }
171
172 void consume(const void *data, size_t length);
173 void setSize(size_t expectedSize);
174
175 void *data() const { return mBuffer; }
176 size_t length() const { return mSize; }
177
178 void clear() { free(mBuffer); mBuffer = NULL; mSize = mMax = 0; }
179
180 private:
181 void grow(size_t newSize);
182
183 private:
184 void *mBuffer; // buffer base
185 size_t mMax; // currently allocated
186 };
187
188
189 } // end namespace Security
190
191
192 #endif /* _H_STREAMS */