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