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