xref: /haiku/src/system/boot/loader/net/ChainBuffer.cpp (revision d561d0ad6889135e08b83c18dede8872a75c6d75)
1 /*
2  * Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
3  * All rights reserved. Distributed under the terms of the MIT License.
4  */
5 
6 #include <boot/net/ChainBuffer.h>
7 
8 #include <stdlib.h>
9 #include <string.h>
10 
11 #include <util/kernel_cpp.h>
12 
13 // constructor
ChainBuffer(void * data,uint32 size,ChainBuffer * next,bool freeData)14 ChainBuffer::ChainBuffer(void *data, uint32 size, ChainBuffer *next,
15 	bool freeData)
16 {
17 	_Init(data, size, next,
18 		CHAIN_BUFFER_ON_STACK | (freeData ? CHAIN_BUFFER_FREE_DATA : 0));
19 }
20 
21 // destructor
~ChainBuffer()22 ChainBuffer::~ChainBuffer()
23 {
24 	_Destroy();
25 }
26 
27 // DetachNext
28 ChainBuffer *
DetachNext()29 ChainBuffer::DetachNext()
30 {
31 	if (!fNext)
32 		return NULL;
33 
34 	ChainBuffer *next = fNext;
35 
36 	fNext = NULL;
37 	next->fFlags |= CHAIN_BUFFER_HEAD;
38 	fTotalSize = fSize;
39 
40 	return next;
41 }
42 
43 // Append
44 void
Append(ChainBuffer * next)45 ChainBuffer::Append(ChainBuffer *next)
46 {
47 	if (!next)
48 		return;
49 
50 	if (fNext)
51 		fNext->Append(next);
52 	else
53 		fNext = next;
54 
55 	fTotalSize = fSize + fNext->fTotalSize;
56 }
57 
58 // Flatten
59 void
Flatten(void * _buffer) const60 ChainBuffer::Flatten(void *_buffer) const
61 {
62 	if (uint8 *buffer = (uint8*)_buffer) {
63 		if (fData && fSize > 0) {
64 			memcpy(buffer, fData, fSize);
65 			buffer += fSize;
66 		}
67 
68 		if (fNext)
69 			fNext->Flatten(buffer);
70 	}
71 }
72 
73 // _Init
74 void
_Init(void * data,uint32 size,ChainBuffer * next,uint32 flags)75 ChainBuffer::_Init(void *data, uint32 size, ChainBuffer *next, uint32 flags)
76 {
77 	fFlags = flags | CHAIN_BUFFER_HEAD;
78 	fSize = size;
79 	fTotalSize = fSize;
80 	fData = data;
81 	fNext = NULL;
82 	Append(next);
83 }
84 
85 // _Destroy
86 void
_Destroy()87 ChainBuffer::_Destroy()
88 {
89 	ChainBuffer *next = fNext;
90 	fNext = NULL;
91 	if ((fFlags & CHAIN_BUFFER_FREE_DATA) && fData) {
92 		free(fData);
93 		fData = NULL;
94 	}
95 
96 	if (!(fFlags & CHAIN_BUFFER_EMBEDDED_DATA))
97 		fSize = 0;
98 	fTotalSize = fSize;
99 
100 	if (next) {
101 		if (next->fFlags & CHAIN_BUFFER_ON_STACK)
102 			next->_Destroy();
103 		else
104 			delete next;
105 	}
106 }
107