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
11
12extern net_buffer_module_info* gBufferModule;
13
14
15class NetBufferModuleGetter {
16	public:
17		static net_buffer_module_info *Get() { return gBufferModule; }
18};
19
20
21//! A class to access a field safely across node boundaries
22template<typename Type, int Offset, typename Module = NetBufferModuleGetter>
23class NetBufferFieldReader {
24public:
25	NetBufferFieldReader(net_buffer* buffer)
26		:
27		fBuffer(buffer)
28	{
29		fStatus = Module::Get()->direct_access(fBuffer, Offset, sizeof(Type),
30			(void**)&fData);
31		if (fStatus != B_OK) {
32			fStatus = Module::Get()->read(fBuffer, Offset, &fDataBuffer,
33				sizeof(Type));
34			fData = &fDataBuffer;
35		}
36	}
37
38	status_t Status() const
39	{
40		return fStatus;
41	}
42
43	Type& Data() const
44	{
45		return *fData;
46	}
47
48	Type* operator->() const
49	{
50		return fData;
51	}
52
53	Type& operator*() const
54	{
55		return *fData;
56	}
57
58	void Sync()
59	{
60		if (fBuffer == NULL || fStatus < B_OK)
61			return;
62
63		if (fData == &fDataBuffer)
64			Module::Get()->write(fBuffer, Offset, fData, sizeof(Type));
65
66		fBuffer = NULL;
67	}
68
69protected:
70	NetBufferFieldReader()
71	{
72	}
73
74	net_buffer*	fBuffer;
75	status_t	fStatus;
76	Type*		fData;
77	Type		fDataBuffer;
78};
79
80
81//! Writes back any changed data on destruction
82template<typename Type, int Offset, typename Module = NetBufferModuleGetter>
83class NetBufferField : public NetBufferFieldReader<Type, Offset, Module> {
84public:
85	NetBufferField(net_buffer* buffer)
86		:
87		NetBufferFieldReader<Type, Offset, Module>(buffer)
88	{
89	}
90
91	~NetBufferField()
92	{
93		// Note, "this->" is needed here for GCC4
94		this->Sync();
95	}
96};
97
98
99//! Can remove the header from the buffer
100template<typename Type, typename Module = NetBufferModuleGetter>
101class NetBufferHeaderReader : public NetBufferFieldReader<Type, 0, Module> {
102public:
103	NetBufferHeaderReader(net_buffer* buffer)
104		:
105		NetBufferFieldReader<Type, 0, Module>(buffer)
106	{
107	}
108
109	void Remove()
110	{
111		Remove(sizeof(Type));
112	}
113
114	void Remove(size_t bytes)
115	{
116		if (this->fBuffer != NULL) {
117			Module::Get()->remove_header(this->fBuffer, bytes);
118			this->fBuffer = NULL;
119		}
120	}
121};
122
123
124//!	Removes the header on destruction
125template<typename Type, typename Module = NetBufferModuleGetter>
126class NetBufferHeaderRemover : public NetBufferHeaderReader<Type, Module> {
127public:
128	NetBufferHeaderRemover(net_buffer* buffer)
129		:
130		NetBufferHeaderReader<Type, Module>(buffer)
131	{
132	}
133
134	~NetBufferHeaderRemover()
135	{
136		this->Remove();
137	}
138};
139
140
141//! A class to add a header to a buffer, syncs itself on destruction
142template<typename Type, typename Module = NetBufferModuleGetter>
143class NetBufferPrepend : public NetBufferFieldReader<Type, 0, Module> {
144public:
145	NetBufferPrepend(net_buffer* buffer, size_t size = sizeof(Type))
146	{
147		this->fBuffer = buffer;
148
149		this->fStatus = Module::Get()->prepend_size(buffer, size,
150			(void**)&this->fData);
151		if (this->fStatus == B_OK && this->fData == NULL)
152			this->fData = &this->fDataBuffer;
153	}
154
155	~NetBufferPrepend()
156	{
157		this->Sync();
158	}
159};
160
161
162#endif	// NET_BUFFER_UTILITIES_H
163