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
14ChainBuffer::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
22ChainBuffer::~ChainBuffer()
23{
24	_Destroy();
25}
26
27// DetachNext
28ChainBuffer *
29ChainBuffer::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
44void
45ChainBuffer::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
59void
60ChainBuffer::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
74void
75ChainBuffer::_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
86void
87ChainBuffer::_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