1/*
2 * Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef NET_BUFFER_UTILITIES_H
6#define NET_BUFFER_UTILITIES_H
7
8
9#include <net_buffer.h>
10#include <AutoDeleter.h>
11
12
13extern net_buffer_module_info* gBufferModule;
14
15
16class NetBufferModuleGetter {
17	public:
18		static net_buffer_module_info *Get() { return gBufferModule; }
19};
20
21
22//! A class to access a field safely across node boundaries
23template<typename Type, int Offset, typename Module = NetBufferModuleGetter>
24class NetBufferFieldReader {
25public:
26	NetBufferFieldReader(net_buffer* buffer)
27		:
28		fBuffer(buffer)
29	{
30		fStatus = Module::Get()->direct_access(fBuffer, Offset, sizeof(Type),
31			(void**)&fData);
32		if (fStatus != B_OK) {
33			fStatus = Module::Get()->read(fBuffer, Offset, &fDataBuffer,
34				sizeof(Type));
35			fData = &fDataBuffer;
36		}
37	}
38
39	status_t Status() const
40	{
41		return fStatus;
42	}
43
44	Type& Data() const
45	{
46		return *fData;
47	}
48
49	Type* operator->() const
50	{
51		return fData;
52	}
53
54	Type& operator*() const
55	{
56		return *fData;
57	}
58
59	void Sync()
60	{
61		if (fBuffer == NULL || fStatus < B_OK)
62			return;
63
64		if (fData == &fDataBuffer)
65			Module::Get()->write(fBuffer, Offset, fData, sizeof(Type));
66
67		fBuffer = NULL;
68	}
69
70protected:
71	NetBufferFieldReader()
72	{
73	}
74
75	net_buffer*	fBuffer;
76	status_t	fStatus;
77	Type*		fData;
78	Type		fDataBuffer;
79};
80
81
82//! Writes back any changed data on destruction
83template<typename Type, int Offset, typename Module = NetBufferModuleGetter>
84class NetBufferField : public NetBufferFieldReader<Type, Offset, Module> {
85public:
86	NetBufferField(net_buffer* buffer)
87		:
88		NetBufferFieldReader<Type, Offset, Module>(buffer)
89	{
90	}
91
92	~NetBufferField()
93	{
94		// Note, "this->" is needed here for GCC4
95		this->Sync();
96	}
97};
98
99
100//! Can remove the header from the buffer
101template<typename Type, typename Module = NetBufferModuleGetter>
102class NetBufferHeaderReader : public NetBufferFieldReader<Type, 0, Module> {
103public:
104	NetBufferHeaderReader(net_buffer* buffer)
105		:
106		NetBufferFieldReader<Type, 0, Module>(buffer)
107	{
108	}
109
110	void Remove()
111	{
112		Remove(sizeof(Type));
113	}
114
115	void Remove(size_t bytes)
116	{
117		if (this->fBuffer != NULL) {
118			Module::Get()->remove_header(this->fBuffer, bytes);
119			this->fBuffer = NULL;
120		}
121	}
122};
123
124
125//!	Removes the header on destruction
126template<typename Type, typename Module = NetBufferModuleGetter>
127class NetBufferHeaderRemover : public NetBufferHeaderReader<Type, Module> {
128public:
129	NetBufferHeaderRemover(net_buffer* buffer)
130		:
131		NetBufferHeaderReader<Type, Module>(buffer)
132	{
133	}
134
135	~NetBufferHeaderRemover()
136	{
137		this->Remove();
138	}
139};
140
141
142//! A class to add a header to a buffer, syncs itself on destruction
143template<typename Type, typename Module = NetBufferModuleGetter>
144class NetBufferPrepend : public NetBufferFieldReader<Type, 0, Module> {
145public:
146	NetBufferPrepend(net_buffer* buffer, size_t size = sizeof(Type))
147	{
148		this->fBuffer = buffer;
149
150		this->fStatus = Module::Get()->prepend_size(buffer, size,
151			(void**)&this->fData);
152		if (this->fStatus == B_OK && this->fData == NULL)
153			this->fData = &this->fDataBuffer;
154	}
155
156	~NetBufferPrepend()
157	{
158		this->Sync();
159	}
160};
161
162
163//! A class to automatically delete buffers on scope exit
164template<typename Module>
165struct NetBufferDelete
166{
167	inline void operator()(net_buffer* buffer)
168	{
169		if (buffer != NULL)
170			Module::Get()->free(buffer);
171	}
172};
173
174
175template<typename Module = NetBufferModuleGetter>
176struct NetBufferDeleter
177	: BPrivate::AutoDeleter<net_buffer, NetBufferDelete<Module> >
178{
179	NetBufferDeleter(net_buffer* buffer)
180		: BPrivate::AutoDeleter<net_buffer, NetBufferDelete<Module> >(buffer)
181	{}
182};
183
184
185
186#endif	// NET_BUFFER_UTILITIES_H
187