1// KMessage.h
2
3#ifndef KMESSAGE_H
4#define KMESSAGE_H
5
6#include <SupportDefs.h>
7#include <TypeConstants.h>
8
9namespace BPrivate {
10
11class KMessageField;
12
13// KMessage
14class KMessage {
15public:
16	enum {
17		KMESSAGE_OWNS_BUFFER		= 0x01,
18		KMESSAGE_INIT_FROM_BUFFER	= 0x02,
19		KMESSAGE_READ_ONLY			= 0x04,
20
21		KMESSAGE_FLAG_MASK			= 0x07,
22	};
23
24	KMessage();
25	KMessage(uint32 what);
26	~KMessage();
27
28	status_t SetTo(uint32 what, uint32 flags = 0);
29	status_t SetTo(void *buffer, int32 bufferSize, uint32 what,
30		uint32 flags = 0);
31	status_t SetTo(const void *buffer, int32 bufferSize);
32	void Unset();
33
34	void SetWhat(uint32 what);
35	uint32 What() const;
36
37	const void *Buffer() const;
38	int32 BufferCapacity() const;
39	int32 ContentSize() const;
40
41	status_t AddField(const char *name, type_code type, int32 elementSize = -1,
42		KMessageField *field = NULL);
43	status_t FindField(const char *name, KMessageField *field) const;
44	status_t FindField(const char *name, type_code type,
45		KMessageField *field) const;
46	status_t GetNextField(KMessageField *field) const;
47
48	status_t AddData(const char *name, type_code type, const void *data,
49		int32 numBytes, bool isFixedSize = true);
50	status_t AddArray(const char *name, type_code type, const void *data,
51		int32 elementSize, int32 elementCount);
52	inline status_t AddBool(const char *name, bool value);
53	inline status_t AddInt8(const char *name, int8 value);
54	inline status_t AddInt16(const char *name, int16 value);
55	inline status_t AddInt32(const char *name, int32 value);
56	inline status_t AddInt64(const char *name, int64 value);
57	inline status_t AddString(const char *name, const char *value);
58
59	status_t FindData(const char *name, type_code type,
60		const void **data, int32 *numBytes) const;
61	status_t FindData(const char *name, type_code type, int32 index,
62		const void **data, int32 *numBytes) const;
63	inline status_t FindBool(const char *name, bool *value) const;
64	inline status_t FindBool(const char *name, int32 index, bool *value) const;
65	inline status_t FindInt8(const char *name, int8 *value) const;
66	inline status_t FindInt8(const char *name, int32 index, int8 *value) const;
67	inline status_t FindInt16(const char *name, int16 *value) const;
68	inline status_t FindInt16(const char *name, int32 index, int16 *value) const;
69	inline status_t FindInt32(const char *name, int32 *value) const;
70	inline status_t FindInt32(const char *name, int32 index, int32 *value) const;
71	inline status_t FindInt64(const char *name, int64 *value) const;
72	inline status_t FindInt64(const char *name, int32 index, int64 *value) const;
73	inline status_t FindString(const char *name, const char **value) const;
74	inline status_t FindString(const char *name, int32 index,
75		const char **value) const;
76
77	// message delivery
78	team_id Sender() const;
79	int32 TargetToken() const;
80	port_id ReplyPort() const;
81	int32 ReplyToken() const;
82
83	status_t SendTo(port_id targetPort, int32 targetToken = -1,
84		port_id replyPort = -1, int32 replyToken = -1, bigtime_t timeout = -1,
85		team_id senderTeam = -1);
86	status_t SendTo(port_id targetPort, int32 targetToken,
87		KMessage* reply, bigtime_t deliveryTimeout = -1,
88		bigtime_t replyTimeout = -1, team_id senderTeam = -1);
89	status_t SendReply(KMessage* message, port_id replyPort = -1,
90		int32 replyToken = -1, bigtime_t timeout = -1, team_id senderTeam = -1);
91	status_t SendReply(KMessage* message, KMessage* reply,
92		bigtime_t deliveryTimeout = -1, bigtime_t replyTimeout = -1,
93		team_id senderTeam = -1);
94	status_t ReceiveFrom(port_id fromPort, bigtime_t timeout = -1);
95
96private:
97	friend class KMessageField;
98
99	struct Header {
100		uint32		magic;
101		int32		size;
102		uint32		what;
103		team_id		sender;
104		int32		targetToken;
105		port_id		replyPort;
106		int32		replyToken;
107	};
108
109	struct FieldHeader;
110	struct FieldValueHeader;
111
112	Header *_Header() const;
113	int32 _BufferOffsetFor(const void* data) const;
114	FieldHeader *_FirstFieldHeader() const;
115	FieldHeader *_LastFieldHeader() const;
116	FieldHeader *_FieldHeaderForOffset(int32 offset) const;
117//	FieldHeader *_NextFieldHeader(FieldHeader *fieldHeader) const;
118	status_t _AddField(const char *name, type_code type, int32 elementSize,
119		KMessageField *field);
120	status_t _AddFieldData(KMessageField *field, const void *data,
121		int32 elementSize, int32 elementCount);
122
123	status_t _InitFromBuffer();
124	void _InitBuffer(uint32 what);
125
126	void _CheckBuffer();	// debugging only
127
128	status_t _AllocateSpace(int32 size, bool alignAddress, bool alignSize,
129		void **address, int32 *alignedSize);
130	int32 _CapacityFor(int32 size);
131	template<typename T> status_t _FindType(const char* name,
132		type_code type, int32 index, T *value) const;
133
134	Header			fHeader;	// pointed to by fBuffer, if nothing is
135								// allocated
136	void*			fBuffer;
137	int32			fBufferCapacity;
138	uint32			fFlags;
139	int32			fLastFieldOffset;
140};
141
142// KMessageField
143class KMessageField {
144public:
145	KMessageField();
146
147	void Unset();
148
149	KMessage *Message() const;
150
151	const char *Name() const;
152	type_code TypeCode() const;
153	bool HasFixedElementSize() const;
154	int32 ElementSize() const;		// if HasFixedElementSize()
155
156	status_t AddElement(const void *data, int32 size = -1);
157	status_t AddElements(const void *data, int32 count, int32 elementSize = -1);
158	const void *ElementAt(int32 index, int32 *size = NULL) const;
159	int32 CountElements() const;
160
161private:
162	void SetTo(KMessage *message, int32 headerOffset);
163
164	KMessage::FieldHeader* _Header() const;
165
166	friend class KMessage;
167
168	KMessage				*fMessage;
169	int32					fHeaderOffset;
170};
171
172} // namespace BPrivate
173
174using BPrivate::KMessage;
175using BPrivate::KMessageField;
176
177// #pragma mark -
178// inline functions
179
180// AddBool
181inline
182status_t
183KMessage::AddBool(const char *name, bool value)
184{
185	return AddData(name, B_BOOL_TYPE, &value, sizeof(bool), true);
186}
187
188// AddInt8
189inline
190status_t
191KMessage::AddInt8(const char *name, int8 value)
192{
193	return AddData(name, B_INT8_TYPE, &value, sizeof(int8), true);
194}
195
196// AddInt16
197inline
198status_t
199KMessage::AddInt16(const char *name, int16 value)
200{
201	return AddData(name, B_INT16_TYPE, &value, sizeof(int16), true);
202}
203
204// AddInt32
205inline
206status_t
207KMessage::AddInt32(const char *name, int32 value)
208{
209	return AddData(name, B_INT32_TYPE, &value, sizeof(int32), true);
210}
211
212// AddInt64
213inline
214status_t
215KMessage::AddInt64(const char *name, int64 value)
216{
217	return AddData(name, B_INT64_TYPE, &value, sizeof(int64), true);
218}
219
220// AddString
221inline
222status_t
223KMessage::AddString(const char *name, const char *value)
224{
225	if (!value)
226		return B_BAD_VALUE;
227	return AddData(name, B_STRING_TYPE, value, strlen(value) + 1, false);
228}
229
230// #pragma mark -
231
232// FindBool
233inline
234status_t
235KMessage::FindBool(const char *name, bool *value) const
236{
237	return FindBool(name, 0, value);
238}
239
240// FindBool
241inline
242status_t
243KMessage::FindBool(const char *name, int32 index, bool *value) const
244{
245	return _FindType(name, B_BOOL_TYPE, index, value);
246}
247
248// FindInt8
249inline
250status_t
251KMessage::FindInt8(const char *name, int8 *value) const
252{
253	return FindInt8(name, 0, value);
254}
255
256// FindInt8
257inline
258status_t
259KMessage::FindInt8(const char *name, int32 index, int8 *value) const
260{
261	return _FindType(name, B_INT8_TYPE, index, value);
262}
263
264// FindInt16
265inline
266status_t
267KMessage::FindInt16(const char *name, int16 *value) const
268{
269	return FindInt16(name, 0, value);
270}
271
272// FindInt16
273inline
274status_t
275KMessage::FindInt16(const char *name, int32 index, int16 *value) const
276{
277	return _FindType(name, B_INT16_TYPE, index, value);
278}
279
280// FindInt32
281inline
282status_t
283KMessage::FindInt32(const char *name, int32 *value) const
284{
285	return FindInt32(name, 0, value);
286}
287
288// FindInt32
289inline
290status_t
291KMessage::FindInt32(const char *name, int32 index, int32 *value) const
292{
293	return _FindType(name, B_INT32_TYPE, index, value);
294}
295
296// FindInt64
297inline
298status_t
299KMessage::FindInt64(const char *name, int64 *value) const
300{
301	return FindInt64(name, 0, value);
302}
303
304// FindInt64
305inline
306status_t
307KMessage::FindInt64(const char *name, int32 index, int64 *value) const
308{
309	return _FindType(name, B_INT64_TYPE, index, value);
310}
311
312// FindString
313inline
314status_t
315KMessage::FindString(const char *name, const char **value) const
316{
317	return FindString(name, 0, value);
318}
319
320// FindString
321inline
322status_t
323KMessage::FindString(const char *name, int32 index, const char **value) const
324{
325	int32 size;
326	return FindData(name, B_STRING_TYPE, index, (const void**)value, &size);
327}
328
329#endif	// KMESSAGE_H
330