1c22d69bfSAxel Dörfler/*
2f6a57629SAxel Dörfler * Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
3c22d69bfSAxel Dörfler * Distributed under the terms of the MIT License.
4c22d69bfSAxel Dörfler */
5c22d69bfSAxel Dörfler#ifndef NET_BUFFER_UTILITIES_H
6c22d69bfSAxel Dörfler#define NET_BUFFER_UTILITIES_H
7c22d69bfSAxel Dörfler
8c22d69bfSAxel Dörfler
9c22d69bfSAxel Dörfler#include <net_buffer.h>
10c22d69bfSAxel Dörfler
11c22d69bfSAxel Dörfler
12f6a57629SAxel Dörflerextern net_buffer_module_info* gBufferModule;
13f6a57629SAxel Dörfler
14c22d69bfSAxel Dörfler
15c22d69bfSAxel Dörflerclass NetBufferModuleGetter {
16c22d69bfSAxel Dörfler	public:
17c35b04deSAxel Dörfler		static net_buffer_module_info *Get() { return gBufferModule; }
18c22d69bfSAxel Dörfler};
19c22d69bfSAxel Dörfler
20f6a57629SAxel Dörfler
2187001e05SHugo Santos//! A class to access a field safely across node boundaries
2287001e05SHugo Santostemplate<typename Type, int Offset, typename Module = NetBufferModuleGetter>
2387001e05SHugo Santosclass NetBufferFieldReader {
24f6a57629SAxel Dörflerpublic:
25f6a57629SAxel Dörfler	NetBufferFieldReader(net_buffer* buffer)
26f6a57629SAxel Dörfler		:
27f6a57629SAxel Dörfler		fBuffer(buffer)
28f6a57629SAxel Dörfler	{
29f6a57629SAxel Dörfler		fStatus = Module::Get()->direct_access(fBuffer, Offset, sizeof(Type),
30f6a57629SAxel Dörfler			(void**)&fData);
31f6a57629SAxel Dörfler		if (fStatus != B_OK) {
32f6a57629SAxel Dörfler			fStatus = Module::Get()->read(fBuffer, Offset, &fDataBuffer,
33f6a57629SAxel Dörfler				sizeof(Type));
34f6a57629SAxel Dörfler			fData = &fDataBuffer;
35c22d69bfSAxel Dörfler		}
36f6a57629SAxel Dörfler	}
37f6a57629SAxel Dörfler
38f6a57629SAxel Dörfler	status_t Status() const
39f6a57629SAxel Dörfler	{
40f6a57629SAxel Dörfler		return fStatus;
41f6a57629SAxel Dörfler	}
42f6a57629SAxel Dörfler
43f6a57629SAxel Dörfler	Type& Data() const
44f6a57629SAxel Dörfler	{
45f6a57629SAxel Dörfler		return *fData;
46f6a57629SAxel Dörfler	}
47f6a57629SAxel Dörfler
48f6a57629SAxel Dörfler	Type* operator->() const
49f6a57629SAxel Dörfler	{
50f6a57629SAxel Dörfler		return fData;
51f6a57629SAxel Dörfler	}
52f6a57629SAxel Dörfler
53f6a57629SAxel Dörfler	Type& operator*() const
54f6a57629SAxel Dörfler	{
55f6a57629SAxel Dörfler		return *fData;
56f6a57629SAxel Dörfler	}
57f6a57629SAxel Dörfler
58f6a57629SAxel Dörfler	void Sync()
59f6a57629SAxel Dörfler	{
60f6a57629SAxel Dörfler		if (fBuffer == NULL || fStatus < B_OK)
61f6a57629SAxel Dörfler			return;
62f6a57629SAxel Dörfler
63f6a57629SAxel Dörfler		if (fData == &fDataBuffer)
64f6a57629SAxel Dörfler			Module::Get()->write(fBuffer, Offset, fData, sizeof(Type));
65f6a57629SAxel Dörfler
66f6a57629SAxel Dörfler		fBuffer = NULL;
67f6a57629SAxel Dörfler	}
68f6a57629SAxel Dörfler
69f6a57629SAxel Dörflerprotected:
70f6a57629SAxel Dörfler	NetBufferFieldReader()
71f6a57629SAxel Dörfler	{
72f6a57629SAxel Dörfler	}
73f6a57629SAxel Dörfler
74f6a57629SAxel Dörfler	net_buffer*	fBuffer;
75f6a57629SAxel Dörfler	status_t	fStatus;
76f6a57629SAxel Dörfler	Type*		fData;
77f6a57629SAxel Dörfler	Type		fDataBuffer;
78c22d69bfSAxel Dörfler};
79c22d69bfSAxel Dörfler
80f6a57629SAxel Dörfler
81f6a57629SAxel Dörfler//! Writes back any changed data on destruction
8287001e05SHugo Santostemplate<typename Type, int Offset, typename Module = NetBufferModuleGetter>
8387001e05SHugo Santosclass NetBufferField : public NetBufferFieldReader<Type, Offset, Module> {
84f6a57629SAxel Dörflerpublic:
85f6a57629SAxel Dörfler	NetBufferField(net_buffer* buffer)
86f6a57629SAxel Dörfler		:
87f6a57629SAxel Dörfler		NetBufferFieldReader<Type, Offset, Module>(buffer)
88f6a57629SAxel Dörfler	{
89f6a57629SAxel Dörfler	}
90f6a57629SAxel Dörfler
91f6a57629SAxel Dörfler	~NetBufferField()
92f6a57629SAxel Dörfler	{
93f6a57629SAxel Dörfler		// Note, "this->" is needed here for GCC4
94f6a57629SAxel Dörfler		this->Sync();
95f6a57629SAxel Dörfler	}
9687001e05SHugo Santos};
97c22d69bfSAxel Dörfler
98f6a57629SAxel Dörfler
99f6a57629SAxel Dörfler//! Can remove the header from the buffer
10087001e05SHugo Santostemplate<typename Type, typename Module = NetBufferModuleGetter>
10187001e05SHugo Santosclass NetBufferHeaderReader : public NetBufferFieldReader<Type, 0, Module> {
102f6a57629SAxel Dörflerpublic:
103f6a57629SAxel Dörfler	NetBufferHeaderReader(net_buffer* buffer)
104f6a57629SAxel Dörfler		:
105f6a57629SAxel Dörfler		NetBufferFieldReader<Type, 0, Module>(buffer)
106f6a57629SAxel Dörfler	{
107f6a57629SAxel Dörfler	}
108f6a57629SAxel Dörfler
109f6a57629SAxel Dörfler	void Remove()
110f6a57629SAxel Dörfler	{
111f6a57629SAxel Dörfler		Remove(sizeof(Type));
112f6a57629SAxel Dörfler	}
113f6a57629SAxel Dörfler
114f6a57629SAxel Dörfler	void Remove(size_t bytes)
115f6a57629SAxel Dörfler	{
116f6a57629SAxel Dörfler		if (this->fBuffer != NULL) {
117f6a57629SAxel Dörfler			Module::Get()->remove_header(this->fBuffer, bytes);
118f6a57629SAxel Dörfler			this->fBuffer = NULL;
119c22d69bfSAxel Dörfler		}
120f6a57629SAxel Dörfler	}
12187001e05SHugo Santos};
122c22d69bfSAxel Dörfler
123f6a57629SAxel Dörfler
124f6a57629SAxel Dörfler//!	Removes the header on destruction
12587001e05SHugo Santostemplate<typename Type, typename Module = NetBufferModuleGetter>
12687001e05SHugo Santosclass NetBufferHeaderRemover : public NetBufferHeaderReader<Type, Module> {
127f6a57629SAxel Dörflerpublic:
128f6a57629SAxel Dörfler	NetBufferHeaderRemover(net_buffer* buffer)
129f6a57629SAxel Dörfler		:
130f6a57629SAxel Dörfler		NetBufferHeaderReader<Type, Module>(buffer)
131f6a57629SAxel Dörfler	{
132f6a57629SAxel Dörfler	}
133f6a57629SAxel Dörfler
134f6a57629SAxel Dörfler	~NetBufferHeaderRemover()
135f6a57629SAxel Dörfler	{
136f6a57629SAxel Dörfler		this->Remove();
137f6a57629SAxel Dörfler	}
138c22d69bfSAxel Dörfler};
139c22d69bfSAxel Dörfler
140f6a57629SAxel Dörfler
141f6a57629SAxel Dörfler//! A class to add a header to a buffer, syncs itself on destruction
142af56b5b2SHugo Santostemplate<typename Type, typename Module = NetBufferModuleGetter>
14387001e05SHugo Santosclass NetBufferPrepend : public NetBufferFieldReader<Type, 0, Module> {
144f6a57629SAxel Dörflerpublic:
145f6a57629SAxel Dörfler	NetBufferPrepend(net_buffer* buffer, size_t size = sizeof(Type))
146f6a57629SAxel Dörfler	{
147f6a57629SAxel Dörfler		this->fBuffer = buffer;
148f6a57629SAxel Dörfler
149f6a57629SAxel Dörfler		this->fStatus = Module::Get()->prepend_size(buffer, size,
150f6a57629SAxel Dörfler			(void**)&this->fData);
151f6a57629SAxel Dörfler		if (this->fStatus == B_OK && this->fData == NULL)
152f6a57629SAxel Dörfler			this->fData = &this->fDataBuffer;
153f6a57629SAxel Dörfler	}
154f6a57629SAxel Dörfler
155f6a57629SAxel Dörfler	~NetBufferPrepend()
156f6a57629SAxel Dörfler	{
157f6a57629SAxel Dörfler		this->Sync();
158f6a57629SAxel Dörfler	}
159af56b5b2SHugo Santos};
160af56b5b2SHugo Santos
161f6a57629SAxel Dörfler
162c22d69bfSAxel Dörfler#endif	// NET_BUFFER_UTILITIES_H