btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / kits / debug / DebugEventStream.cpp
blobec2711e38674555efa8c3bc0fd5f8340b0a4a308
1 /*
2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
6 #include <DebugEventStream.h>
8 #include <stdlib.h>
9 #include <string.h>
11 #include <DataIO.h>
13 #include <system_profiler_defs.h>
16 #define INPUT_BUFFER_SIZE (128 * 1024)
19 BDebugEventInputStream::BDebugEventInputStream()
21 fStream(NULL),
22 fFlags(0),
23 fEventMask(0),
24 fBuffer(NULL),
25 fBufferCapacity(0),
26 fBufferSize(0),
27 fBufferPosition(0),
28 fStreamPosition(0),
29 fOwnsBuffer(false)
34 BDebugEventInputStream::~BDebugEventInputStream()
36 Unset();
38 if (fOwnsBuffer)
39 free(fBuffer);
43 status_t
44 BDebugEventInputStream::SetTo(BDataIO* stream)
46 Unset();
48 // set the new values
49 if (stream == NULL)
50 return B_BAD_VALUE;
52 fStream = stream;
54 // allocate a buffer
55 if (fBuffer == NULL) {
56 fBuffer = (uint8*)malloc(INPUT_BUFFER_SIZE);
57 if (fBuffer == NULL) {
58 Unset();
59 return B_NO_MEMORY;
62 fOwnsBuffer = true;
63 fBufferCapacity = INPUT_BUFFER_SIZE;
64 fBufferSize = 0;
67 return _Init();
71 status_t
72 BDebugEventInputStream::SetTo(const void* data, size_t size,
73 bool takeOverOwnership)
75 Unset();
77 if (data == NULL || size == 0)
78 return B_BAD_VALUE;
80 if (fBuffer != NULL) {
81 if (fOwnsBuffer)
82 free(fBuffer);
83 fBuffer = NULL;
84 fBufferCapacity = 0;
85 fBufferSize = 0;
88 fBuffer = (uint8*)data;
89 fBufferCapacity = fBufferSize = size;
90 fOwnsBuffer = takeOverOwnership;
92 return _Init();
96 void
97 BDebugEventInputStream::Unset()
99 fStream = NULL;
100 fFlags = 0;
101 fEventMask = 0;
103 // If we have a buffer that we own and has the right size, we keep it.
104 if (fOwnsBuffer) {
105 if (fBuffer != NULL && fBufferSize != INPUT_BUFFER_SIZE) {
106 free(fBuffer);
107 fBuffer = NULL;
108 fBufferCapacity = 0;
109 fBufferSize = 0;
111 } else {
112 fBuffer = NULL;
113 fBufferCapacity = 0;
114 fBufferSize = 0;
119 status_t
120 BDebugEventInputStream::Seek(off_t streamOffset)
122 // TODO: Support for streams, at least for BPositionIOs.
123 if (fStream != NULL)
124 return B_UNSUPPORTED;
126 if (streamOffset < 0 || streamOffset > (off_t)fBufferCapacity)
127 return B_BUFFER_OVERFLOW;
129 fStreamPosition = 0;
130 fBufferPosition = streamOffset;
131 fBufferSize = fBufferCapacity - streamOffset;
133 return B_OK;
137 /*! \brief Returns the next event in the stream.
139 At the end of the stream \c 0 is returned and \c *_buffer is set to \c NULL.
140 For events that don't have data associated with them, \c *_buffer will still
141 be non-NULL, even if dereferencing that address is not allowed.
143 \param _event Pointer to a pre-allocated location where the event ID shall
144 be stored.
145 \param _cpu Pointer to a pre-allocated location where the CPU index shall
146 be stored.
147 \param _buffer Pointer to a pre-allocated location where the pointer to the
148 event data shall be stored.
149 \param _streamOffset Pointer to a pre-allocated location where the event
150 header's offset relative to the beginning of the stream shall be stored.
151 May be \c NULL.
152 \return A negative error code in case an error occurred while trying to read
153 the info, the size of the data associated with the event otherwise.
155 ssize_t
156 BDebugEventInputStream::ReadNextEvent(uint32* _event, uint32* _cpu,
157 const void** _buffer, off_t* _streamOffset)
159 // get the next header
160 status_t error = _GetData(sizeof(system_profiler_event_header));
161 if (error != B_OK) {
162 if (error == B_BAD_DATA && fBufferSize == 0) {
163 *_buffer = NULL;
164 return 0;
166 return error;
169 system_profiler_event_header header
170 = *(system_profiler_event_header*)(fBuffer + fBufferPosition);
172 off_t streamOffset = fStreamPosition + fBufferPosition;
174 // skip the header in the buffer
175 fBufferSize -= sizeof(system_profiler_event_header);
176 fBufferPosition += sizeof(system_profiler_event_header);
178 // get the data
179 if (header.size > 0) {
180 error = _GetData(header.size);
181 if (error != B_OK)
182 return error;
185 *_event = header.event;
186 *_cpu = header.cpu;
187 *_buffer = fBuffer + fBufferPosition;
188 if (_streamOffset)
189 *_streamOffset = streamOffset;
191 // skip the event in the buffer
192 fBufferSize -= header.size;
193 fBufferPosition += header.size;
195 return header.size;
199 status_t
200 BDebugEventInputStream::_Init()
202 fStreamPosition = 0;
203 fBufferPosition = 0;
205 // get the header
206 status_t error = _GetData(sizeof(debug_event_stream_header));
207 if (error != B_OK) {
208 Unset();
209 return error;
211 const debug_event_stream_header& header
212 = *(const debug_event_stream_header*)(fBuffer + fBufferPosition);
214 fBufferPosition += sizeof(debug_event_stream_header);
215 fBufferSize -= sizeof(debug_event_stream_header);
217 // check the header
218 if (strncmp(header.signature, B_DEBUG_EVENT_STREAM_SIGNATURE,
219 sizeof(header.signature)) != 0
220 || header.version != B_DEBUG_EVENT_STREAM_VERSION
221 || (header.flags & B_DEBUG_EVENT_STREAM_FLAG_HOST_ENDIAN) == 0) {
222 // TODO: Support non-host endianess!
223 Unset();
224 return B_BAD_DATA;
227 fFlags = header.flags;
228 fEventMask = header.event_mask;
230 return B_OK;
234 ssize_t
235 BDebugEventInputStream::_Read(void* _buffer, size_t size)
237 uint8* buffer = (uint8*)_buffer;
238 size_t totalBytesRead = 0;
239 ssize_t bytesRead = 0;
241 while (size > 0 && (bytesRead = fStream->Read(buffer, size)) > 0) {
242 totalBytesRead += bytesRead;
243 buffer += bytesRead;
244 size -= bytesRead;
247 if (bytesRead < 0)
248 return bytesRead;
250 return totalBytesRead;
254 status_t
255 BDebugEventInputStream::_GetData(size_t size)
257 if (fBufferSize >= size)
258 return B_OK;
260 if (size > fBufferCapacity)
261 return B_BUFFER_OVERFLOW;
263 // move remaining data to the start of the buffer
264 if (fBufferSize > 0 && fBufferPosition > 0)
265 memmove(fBuffer, fBuffer + fBufferPosition, fBufferSize);
266 fStreamPosition += fBufferPosition;
267 fBufferPosition = 0;
269 // read more data
270 if (fStream != NULL) {
271 ssize_t bytesRead = _Read(fBuffer + fBufferSize,
272 fBufferCapacity - fBufferSize);
273 if (bytesRead < 0)
274 return bytesRead;
276 fBufferSize += bytesRead;
279 return fBufferSize >= size ? B_OK : B_BAD_DATA;
283 // #pragma mark - BDebugEventOutputStream
286 BDebugEventOutputStream::BDebugEventOutputStream()
288 fStream(NULL),
289 fFlags(0)
294 BDebugEventOutputStream::~BDebugEventOutputStream()
296 Unset();
300 status_t
301 BDebugEventOutputStream::SetTo(BDataIO* stream, uint32 flags, uint32 eventMask)
303 Unset();
305 // set the new values
306 if (stream == NULL)
307 return B_BAD_VALUE;
309 fStream = stream;
310 fFlags = /*(flags & B_DEBUG_EVENT_STREAM_FLAG_ZIPPED)
311 |*/ B_DEBUG_EVENT_STREAM_FLAG_HOST_ENDIAN;
312 // TODO: Support zipped data!
314 // init and write the header
315 debug_event_stream_header header;
316 memset(header.signature, 0, sizeof(header.signature));
317 strlcpy(header.signature, B_DEBUG_EVENT_STREAM_SIGNATURE,
318 sizeof(header.signature));
319 header.version = B_DEBUG_EVENT_STREAM_VERSION;
320 header.flags = fFlags;
321 header.event_mask = eventMask;
323 ssize_t written = fStream->Write(&header, sizeof(header));
324 if (written < 0) {
325 Unset();
326 return written;
328 if ((size_t)written != sizeof(header)) {
329 Unset();
330 return B_FILE_ERROR;
333 return B_OK;
337 void
338 BDebugEventOutputStream::Unset()
340 Flush();
341 fStream = NULL;
342 fFlags = 0;
346 status_t
347 BDebugEventOutputStream::Write(const void* buffer, size_t size)
349 if (size == 0)
350 return B_OK;
351 if (buffer == NULL)
352 return B_BAD_VALUE;
354 ssize_t written = fStream->Write(buffer, size);
355 if (written < 0)
356 return written;
357 if ((size_t)written != size)
358 return B_FILE_ERROR;
360 return B_OK;
364 status_t
365 BDebugEventOutputStream::Flush()
367 return B_OK;