xref: /haiku/headers/private/kernel/util/KMessage.h (revision 079c69cbfd7cd3c97baae91332251c8388a8bb02)
1 /*
2  * Copyright 2005-2007, Ingo Weinhold, bonefish@users.sf.net. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 #ifndef KMESSAGE_H
6 #define KMESSAGE_H
7 
8 #include <string.h>
9 
10 #include <OS.h>
11 #include <TypeConstants.h>
12 
13 
14 #ifdef __cplusplus
15 
16 
17 class BMessage;
18 
19 namespace BPrivate {
20 
21 class KMessageField;
22 class MessageAdapter;
23 
24 // KMessage
25 class KMessage {
26 public:
27 	enum {
28 		KMESSAGE_OWNS_BUFFER		= 0x01,
29 		KMESSAGE_INIT_FROM_BUFFER	= 0x02,
30 		KMESSAGE_READ_ONLY			= 0x04,
31 
32 		KMESSAGE_FLAG_MASK			= 0x07,
33 	};
34 
35 	KMessage();
36 	KMessage(uint32 what);
37 	~KMessage();
38 
39 	status_t SetTo(uint32 what, uint32 flags = 0);
40 	status_t SetTo(void *buffer, int32 bufferSize, uint32 what,
41 		uint32 flags = 0);
42 	status_t SetTo(const void *buffer, int32 bufferSize = -1);
43 	void Unset();
44 
45 	void SetWhat(uint32 what);
46 	uint32 What() const;
47 
48 	const void *Buffer() const;
49 	int32 BufferCapacity() const;
50 	int32 ContentSize() const;
51 
52 	status_t AddField(const char *name, type_code type, int32 elementSize = -1,
53 		KMessageField *field = NULL);
54 	status_t FindField(const char *name, KMessageField *field) const;
55 	status_t FindField(const char *name, type_code type,
56 		KMessageField *field) const;
57 	status_t GetNextField(KMessageField *field) const;
58 
59 	status_t AddData(const char *name, type_code type, const void *data,
60 		int32 numBytes, bool isFixedSize = true);
61 	status_t AddArray(const char *name, type_code type, const void *data,
62 		int32 elementSize, int32 elementCount);
63 	inline status_t AddBool(const char *name, bool value);
64 	inline status_t AddInt8(const char *name, int8 value);
65 	inline status_t AddInt16(const char *name, int16 value);
66 	inline status_t AddInt32(const char *name, int32 value);
67 	inline status_t AddInt64(const char *name, int64 value);
68 	inline status_t AddString(const char *name, const char *value);
69 
70 	status_t FindData(const char *name, type_code type,
71 		const void **data, int32 *numBytes) const;
72 	status_t FindData(const char *name, type_code type, int32 index,
73 		const void **data, int32 *numBytes) const;
74 	inline status_t FindBool(const char *name, bool *value) const;
75 	inline status_t FindBool(const char *name, int32 index, bool *value) const;
76 	inline status_t FindInt8(const char *name, int8 *value) const;
77 	inline status_t FindInt8(const char *name, int32 index, int8 *value) const;
78 	inline status_t FindInt16(const char *name, int16 *value) const;
79 	inline status_t FindInt16(const char *name, int32 index, int16 *value) const;
80 	inline status_t FindInt32(const char *name, int32 *value) const;
81 	inline status_t FindInt32(const char *name, int32 index, int32 *value) const;
82 	inline status_t FindInt64(const char *name, int64 *value) const;
83 	inline status_t FindInt64(const char *name, int32 index, int64 *value) const;
84 	inline status_t FindString(const char *name, const char **value) const;
85 	inline status_t FindString(const char *name, int32 index,
86 		const char **value) const;
87 
88 	inline bool GetBool(const char* name, bool defaultValue) const;
89 	inline bool GetBool(const char* name, int32 index, bool defaultValue) const;
90 	inline int8 GetInt8(const char* name, int8 defaultValue) const;
91 	inline int8 GetInt8(const char* name, int32 index, int8 defaultValue) const;
92 	inline int16 GetInt16(const char* name, int16 defaultValue) const;
93 	inline int16 GetInt16(const char* name, int32 index,
94 		int16 defaultValue) const;
95 	inline int32 GetInt32(const char* name, int32 defaultValue) const;
96 	inline int32 GetInt32(const char* name, int32 index,
97 		int32 defaultValue) const;
98 	inline int64 GetInt64(const char* name, int64 defaultValue) const;
99 	inline int64 GetInt64(const char* name, int32 index,
100 		int64 defaultValue) const;
101 	inline const char* GetString(const char* name,
102 		const char* defaultValue) const;
103 	inline const char* GetString(const char* name, int32 index,
104 		const char* defaultValue) const;
105 
106 	// fixed size fields only
107 	status_t SetData(const char* name, type_code type, const void* data,
108 		int32 numBytes);
109 	inline status_t SetBool(const char* name, bool value);
110 	inline status_t SetInt8(const char* name, int8 value);
111 	inline status_t SetInt16(const char* name, int16 value);
112 	inline status_t SetInt32(const char* name, int32 value);
113 	inline status_t SetInt64(const char* name, int64 value);
114 
115 	// message delivery
116 	team_id Sender() const;
117 	int32 TargetToken() const;
118 	port_id ReplyPort() const;
119 	int32 ReplyToken() const;
120 
121 	void SetDeliveryInfo(int32 targetToken, port_id replyPort,
122 		int32 replyToken, team_id senderTeam);
123 
124 	status_t SendTo(port_id targetPort, int32 targetToken = -1,
125 		port_id replyPort = -1, int32 replyToken = -1, bigtime_t timeout = -1,
126 		team_id senderTeam = -1);
127 	status_t SendTo(port_id targetPort, int32 targetToken,
128 		KMessage* reply, bigtime_t deliveryTimeout = -1,
129 		bigtime_t replyTimeout = -1, team_id senderTeam = -1);
130 	status_t SendReply(KMessage* message, port_id replyPort = -1,
131 		int32 replyToken = -1, bigtime_t timeout = -1, team_id senderTeam = -1);
132 	status_t SendReply(KMessage* message, KMessage* reply,
133 		bigtime_t deliveryTimeout = -1, bigtime_t replyTimeout = -1,
134 		team_id senderTeam = -1);
135 	status_t ReceiveFrom(port_id fromPort, bigtime_t timeout = -1);
136 
137 private:
138 	friend class KMessageField;
139 	friend class MessageAdapter;
140 	friend class ::BMessage;		// not so nice, but makes things easier
141 
142 	struct Header {
143 		uint32		magic;
144 		int32		size;
145 		uint32		what;
146 		team_id		sender;
147 		int32		targetToken;
148 		port_id		replyPort;
149 		int32		replyToken;
150 	};
151 
152 	struct FieldHeader;
153 	struct FieldValueHeader;
154 
155 	Header *_Header() const;
156 	int32 _BufferOffsetFor(const void* data) const;
157 	FieldHeader *_FirstFieldHeader() const;
158 	FieldHeader *_LastFieldHeader() const;
159 	FieldHeader *_FieldHeaderForOffset(int32 offset) const;
160 	status_t _AddField(const char *name, type_code type, int32 elementSize,
161 		KMessageField *field);
162 	status_t _AddFieldData(KMessageField *field, const void *data,
163 		int32 elementSize, int32 elementCount);
164 
165 	status_t _InitFromBuffer(bool sizeFromBuffer);
166 	void _InitBuffer(uint32 what);
167 
168 	void _CheckBuffer();	// debugging only
169 
170 	status_t _AllocateSpace(int32 size, bool alignAddress, bool alignSize,
171 		void **address, int32 *alignedSize);
172 	int32 _CapacityFor(int32 size);
173 	template<typename T> inline status_t _FindType(const char* name,
174 		type_code type, int32 index, T *value) const;
175 	template<typename T> inline T _GetType(const char* name, type_code type,
176 		int32 index, const T& defaultValue) const;
177 
178 	Header			fHeader;	// pointed to by fBuffer, if nothing is
179 								// allocated
180 	void*			fBuffer;
181 	int32			fBufferCapacity;
182 	uint32			fFlags;
183 	int32			fLastFieldOffset;
184 
185 	static const uint32	kMessageHeaderMagic;
186 };
187 
188 // KMessageField
189 class KMessageField {
190 public:
191 	KMessageField();
192 
193 	void Unset();
194 
195 	KMessage *Message() const;
196 
197 	const char *Name() const;
198 	type_code TypeCode() const;
199 	bool HasFixedElementSize() const;
200 	int32 ElementSize() const;		// if HasFixedElementSize()
201 
202 	status_t AddElement(const void *data, int32 size = -1);
203 	status_t AddElements(const void *data, int32 count, int32 elementSize = -1);
204 	const void *ElementAt(int32 index, int32 *size = NULL) const;
205 	int32 CountElements() const;
206 
207 private:
208 	void SetTo(KMessage *message, int32 headerOffset);
209 
210 	KMessage::FieldHeader* _Header() const;
211 
212 	friend class KMessage;
213 
214 	KMessage				*fMessage;
215 	int32					fHeaderOffset;
216 };
217 
218 } // namespace BPrivate
219 
220 using BPrivate::KMessage;
221 using BPrivate::KMessageField;
222 
223 
224 // #pragma mark - inline functions
225 
226 
227 // AddBool
228 inline
229 status_t
230 KMessage::AddBool(const char *name, bool value)
231 {
232 	return AddData(name, B_BOOL_TYPE, &value, sizeof(bool), true);
233 }
234 
235 // AddInt8
236 inline
237 status_t
238 KMessage::AddInt8(const char *name, int8 value)
239 {
240 	return AddData(name, B_INT8_TYPE, &value, sizeof(int8), true);
241 }
242 
243 // AddInt16
244 inline
245 status_t
246 KMessage::AddInt16(const char *name, int16 value)
247 {
248 	return AddData(name, B_INT16_TYPE, &value, sizeof(int16), true);
249 }
250 
251 // AddInt32
252 inline
253 status_t
254 KMessage::AddInt32(const char *name, int32 value)
255 {
256 	return AddData(name, B_INT32_TYPE, &value, sizeof(int32), true);
257 }
258 
259 // AddInt64
260 inline
261 status_t
262 KMessage::AddInt64(const char *name, int64 value)
263 {
264 	return AddData(name, B_INT64_TYPE, &value, sizeof(int64), true);
265 }
266 
267 // AddString
268 inline
269 status_t
270 KMessage::AddString(const char *name, const char *value)
271 {
272 	if (!value)
273 		return B_BAD_VALUE;
274 	return AddData(name, B_STRING_TYPE, value, strlen(value) + 1, false);
275 }
276 
277 
278 // #pragma mark -
279 
280 
281 // _FindType
282 template<typename T>
283 inline status_t
284 KMessage::_FindType(const char* name, type_code type, int32 index,
285 	T *value) const
286 {
287 	const void *data;
288 	int32 size;
289 	status_t error = FindData(name, type, index, &data, &size);
290 	if (error != B_OK)
291 		return error;
292 
293 	if (size != sizeof(T))
294 		return B_BAD_DATA;
295 
296 	*value = *(T*)data;
297 
298 	return B_OK;
299 }
300 
301 // FindBool
302 inline
303 status_t
304 KMessage::FindBool(const char *name, bool *value) const
305 {
306 	return FindBool(name, 0, value);
307 }
308 
309 // FindBool
310 inline
311 status_t
312 KMessage::FindBool(const char *name, int32 index, bool *value) const
313 {
314 	return _FindType(name, B_BOOL_TYPE, index, value);
315 }
316 
317 // FindInt8
318 inline
319 status_t
320 KMessage::FindInt8(const char *name, int8 *value) const
321 {
322 	return FindInt8(name, 0, value);
323 }
324 
325 // FindInt8
326 inline
327 status_t
328 KMessage::FindInt8(const char *name, int32 index, int8 *value) const
329 {
330 	return _FindType(name, B_INT8_TYPE, index, value);
331 }
332 
333 // FindInt16
334 inline
335 status_t
336 KMessage::FindInt16(const char *name, int16 *value) const
337 {
338 	return FindInt16(name, 0, value);
339 }
340 
341 // FindInt16
342 inline
343 status_t
344 KMessage::FindInt16(const char *name, int32 index, int16 *value) const
345 {
346 	return _FindType(name, B_INT16_TYPE, index, value);
347 }
348 
349 // FindInt32
350 inline
351 status_t
352 KMessage::FindInt32(const char *name, int32 *value) const
353 {
354 	return FindInt32(name, 0, value);
355 }
356 
357 // FindInt32
358 inline
359 status_t
360 KMessage::FindInt32(const char *name, int32 index, int32 *value) const
361 {
362 	return _FindType(name, B_INT32_TYPE, index, value);
363 }
364 
365 // FindInt64
366 inline
367 status_t
368 KMessage::FindInt64(const char *name, int64 *value) const
369 {
370 	return FindInt64(name, 0, value);
371 }
372 
373 // FindInt64
374 inline
375 status_t
376 KMessage::FindInt64(const char *name, int32 index, int64 *value) const
377 {
378 	return _FindType(name, B_INT64_TYPE, index, value);
379 }
380 
381 // FindString
382 inline
383 status_t
384 KMessage::FindString(const char *name, const char **value) const
385 {
386 	return FindString(name, 0, value);
387 }
388 
389 // FindString
390 inline
391 status_t
392 KMessage::FindString(const char *name, int32 index, const char **value) const
393 {
394 	int32 size;
395 	return FindData(name, B_STRING_TYPE, index, (const void**)value, &size);
396 }
397 
398 
399 // _GetType
400 template<typename T>
401 inline T
402 KMessage::_GetType(const char* name, type_code type, int32 index,
403 	const T& defaultValue) const
404 {
405 	T value;
406 	if (_FindType(name, type, index, &value) == B_OK)
407 		return value;
408 	return defaultValue;
409 }
410 
411 
412 // GetBool
413 inline bool
414 KMessage::GetBool(const char* name, bool defaultValue) const
415 {
416 	return _GetType(name, B_BOOL_TYPE, 0, defaultValue);
417 }
418 
419 
420 // GetBool
421 inline bool
422 KMessage::GetBool(const char* name, int32 index, bool defaultValue) const
423 {
424 	return _GetType(name, B_BOOL_TYPE, index, defaultValue);
425 }
426 
427 // GetInt8
428 inline int8
429 KMessage::GetInt8(const char* name, int8 defaultValue) const
430 {
431 	return _GetType(name, B_INT8_TYPE, 0, defaultValue);
432 }
433 
434 
435 // GetInt8
436 inline int8
437 KMessage::GetInt8(const char* name, int32 index, int8 defaultValue) const
438 {
439 	return _GetType(name, B_INT8_TYPE, index, defaultValue);
440 }
441 
442 
443 // GetInt16
444 inline int16
445 KMessage::GetInt16(const char* name, int16 defaultValue) const
446 {
447 	return _GetType(name, B_INT16_TYPE, 0, defaultValue);
448 }
449 
450 
451 // GetInt16
452 inline int16
453 KMessage::GetInt16(const char* name, int32 index, int16 defaultValue) const
454 {
455 	return _GetType(name, B_INT16_TYPE, index, defaultValue);
456 }
457 
458 
459 // GetInt32
460 inline int32
461 KMessage::GetInt32(const char* name, int32 defaultValue) const
462 {
463 	return _GetType(name, B_INT32_TYPE, 0, defaultValue);
464 }
465 
466 
467 // GetInt32
468 inline int32
469 KMessage::GetInt32(const char* name, int32 index, int32 defaultValue) const
470 {
471 	return _GetType(name, B_INT32_TYPE, index, defaultValue);
472 }
473 
474 
475 // GetInt64
476 inline int64
477 KMessage::GetInt64(const char* name, int64 defaultValue) const
478 {
479 	return _GetType(name, B_INT64_TYPE, 0, defaultValue);
480 }
481 
482 
483 // GetInt64
484 inline int64
485 KMessage::GetInt64(const char* name, int32 index, int64 defaultValue) const
486 {
487 	return _GetType(name, B_INT64_TYPE, index, defaultValue);
488 }
489 
490 
491 // GetString
492 inline const char*
493 KMessage::GetString(const char* name, int32 index,
494 	const char* defaultValue) const
495 {
496 	// don't use _GetType() here, since it checks field size == sizeof(T)
497 	int32 size;
498 	const char* value;
499 	if (FindData(name, B_STRING_TYPE, index, (const void**)&value, &size)
500 			== B_OK) {
501 		return value;
502 	}
503 	return defaultValue;
504 }
505 
506 
507 // GetString
508 inline const char*
509 KMessage::GetString(const char* name, const char* defaultValue) const
510 {
511 	return GetString(name, 0, defaultValue);
512 }
513 
514 
515 // SetBool
516 inline status_t
517 KMessage::SetBool(const char* name, bool value)
518 {
519 	return SetData(name, B_BOOL_TYPE, &value, sizeof(bool));
520 }
521 
522 
523 // SetInt8
524 inline status_t
525 KMessage::SetInt8(const char* name, int8 value)
526 {
527 	return SetData(name, B_INT8_TYPE, &value, sizeof(int8));
528 }
529 
530 
531 // SetInt16
532 inline status_t
533 KMessage::SetInt16(const char* name, int16 value)
534 {
535 	return SetData(name, B_INT16_TYPE, &value, sizeof(int16));
536 }
537 
538 
539 // SetInt32
540 inline status_t
541 KMessage::SetInt32(const char* name, int32 value)
542 {
543 	return SetData(name, B_INT32_TYPE, &value, sizeof(int32));
544 }
545 
546 
547 // SetInt64
548 inline status_t
549 KMessage::SetInt64(const char* name, int64 value)
550 {
551 	return SetData(name, B_INT64_TYPE, &value, sizeof(int64));
552 }
553 
554 
555 #else	// !__cplusplus
556 
557 
558 typedef struct KMessage {
559 	struct Header {
560 		uint32		magic;
561 		int32		size;
562 		uint32		what;
563 		team_id		sender;
564 		int32		targetToken;
565 		port_id		replyPort;
566 		int32		replyToken;
567 	}				fHeader;
568 	void*			fBuffer;
569 	int32			fBufferCapacity;
570 	uint32			fFlags;
571 	int32			fLastFieldOffset;
572 } KMessage;
573 
574 
575 #endif	// !__cplusplus
576 
577 
578 #endif	// KMESSAGE_H
579