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