xref: /haiku/headers/private/kernel/util/KMessage.h (revision d2e1e872611179c9cfaa43ce11bd58b1e3554e4b)
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 		port_message_info* messageInfo = NULL);
137 
138 	void Dump(void (*printFunc)(const char*,...));
139 
140 private:
141 	friend class KMessageField;
142 	friend class MessageAdapter;
143 	friend class ::BMessage;		// not so nice, but makes things easier
144 
145 	struct Header {
146 		uint32		magic;
147 		int32		size;
148 		uint32		what;
149 		team_id		sender;
150 		int32		targetToken;
151 		port_id		replyPort;
152 		int32		replyToken;
153 	};
154 
155 	struct FieldHeader;
156 	struct FieldValueHeader;
157 
158 	Header *_Header() const;
159 	int32 _BufferOffsetFor(const void* data) const;
160 	FieldHeader *_FirstFieldHeader() const;
161 	FieldHeader *_LastFieldHeader() const;
162 	FieldHeader *_FieldHeaderForOffset(int32 offset) const;
163 	status_t _AddField(const char *name, type_code type, int32 elementSize,
164 		KMessageField *field);
165 	status_t _AddFieldData(KMessageField *field, const void *data,
166 		int32 elementSize, int32 elementCount);
167 
168 	status_t _InitFromBuffer(bool sizeFromBuffer);
169 	void _InitBuffer(uint32 what);
170 
171 	void _CheckBuffer();	// debugging only
172 
173 	status_t _AllocateSpace(int32 size, bool alignAddress, bool alignSize,
174 		void **address, int32 *alignedSize);
175 	int32 _CapacityFor(int32 size);
176 	template<typename T> inline status_t _FindType(const char* name,
177 		type_code type, int32 index, T *value) const;
178 	template<typename T> inline T _GetType(const char* name, type_code type,
179 		int32 index, const T& defaultValue) const;
180 
181 	Header			fHeader;	// pointed to by fBuffer, if nothing is
182 								// allocated
183 	void*			fBuffer;
184 	int32			fBufferCapacity;
185 	uint32			fFlags;
186 	int32			fLastFieldOffset;
187 
188 	static const uint32	kMessageHeaderMagic;
189 };
190 
191 // KMessageField
192 class KMessageField {
193 public:
194 	KMessageField();
195 
196 	void Unset();
197 
198 	KMessage *Message() const;
199 
200 	const char *Name() const;
201 	type_code TypeCode() const;
202 	bool HasFixedElementSize() const;
203 	int32 ElementSize() const;		// if HasFixedElementSize()
204 
205 	status_t AddElement(const void *data, int32 size = -1);
206 	status_t AddElements(const void *data, int32 count, int32 elementSize = -1);
207 	const void *ElementAt(int32 index, int32 *size = NULL) const;
208 	int32 CountElements() const;
209 
210 private:
211 	void SetTo(KMessage *message, int32 headerOffset);
212 
213 	KMessage::FieldHeader* _Header() const;
214 
215 	friend class KMessage;
216 
217 	KMessage				*fMessage;
218 	int32					fHeaderOffset;
219 };
220 
221 } // namespace BPrivate
222 
223 using BPrivate::KMessage;
224 using BPrivate::KMessageField;
225 
226 
227 // #pragma mark - inline functions
228 
229 
230 // AddBool
231 inline
232 status_t
233 KMessage::AddBool(const char *name, bool value)
234 {
235 	return AddData(name, B_BOOL_TYPE, &value, sizeof(bool), true);
236 }
237 
238 // AddInt8
239 inline
240 status_t
241 KMessage::AddInt8(const char *name, int8 value)
242 {
243 	return AddData(name, B_INT8_TYPE, &value, sizeof(int8), true);
244 }
245 
246 // AddInt16
247 inline
248 status_t
249 KMessage::AddInt16(const char *name, int16 value)
250 {
251 	return AddData(name, B_INT16_TYPE, &value, sizeof(int16), true);
252 }
253 
254 // AddInt32
255 inline
256 status_t
257 KMessage::AddInt32(const char *name, int32 value)
258 {
259 	return AddData(name, B_INT32_TYPE, &value, sizeof(int32), true);
260 }
261 
262 // AddInt64
263 inline
264 status_t
265 KMessage::AddInt64(const char *name, int64 value)
266 {
267 	return AddData(name, B_INT64_TYPE, &value, sizeof(int64), true);
268 }
269 
270 // AddString
271 inline
272 status_t
273 KMessage::AddString(const char *name, const char *value)
274 {
275 	if (!value)
276 		return B_BAD_VALUE;
277 	return AddData(name, B_STRING_TYPE, value, strlen(value) + 1, false);
278 }
279 
280 
281 // #pragma mark -
282 
283 
284 // _FindType
285 template<typename T>
286 inline status_t
287 KMessage::_FindType(const char* name, type_code type, int32 index,
288 	T *value) const
289 {
290 	const void *data;
291 	int32 size;
292 	status_t error = FindData(name, type, index, &data, &size);
293 	if (error != B_OK)
294 		return error;
295 
296 	if (size != sizeof(T))
297 		return B_BAD_DATA;
298 
299 	*value = *(T*)data;
300 
301 	return B_OK;
302 }
303 
304 // FindBool
305 inline
306 status_t
307 KMessage::FindBool(const char *name, bool *value) const
308 {
309 	return FindBool(name, 0, value);
310 }
311 
312 // FindBool
313 inline
314 status_t
315 KMessage::FindBool(const char *name, int32 index, bool *value) const
316 {
317 	return _FindType(name, B_BOOL_TYPE, index, value);
318 }
319 
320 // FindInt8
321 inline
322 status_t
323 KMessage::FindInt8(const char *name, int8 *value) const
324 {
325 	return FindInt8(name, 0, value);
326 }
327 
328 // FindInt8
329 inline
330 status_t
331 KMessage::FindInt8(const char *name, int32 index, int8 *value) const
332 {
333 	return _FindType(name, B_INT8_TYPE, index, value);
334 }
335 
336 // FindInt16
337 inline
338 status_t
339 KMessage::FindInt16(const char *name, int16 *value) const
340 {
341 	return FindInt16(name, 0, value);
342 }
343 
344 // FindInt16
345 inline
346 status_t
347 KMessage::FindInt16(const char *name, int32 index, int16 *value) const
348 {
349 	return _FindType(name, B_INT16_TYPE, index, value);
350 }
351 
352 // FindInt32
353 inline
354 status_t
355 KMessage::FindInt32(const char *name, int32 *value) const
356 {
357 	return FindInt32(name, 0, value);
358 }
359 
360 // FindInt32
361 inline
362 status_t
363 KMessage::FindInt32(const char *name, int32 index, int32 *value) const
364 {
365 	return _FindType(name, B_INT32_TYPE, index, value);
366 }
367 
368 // FindInt64
369 inline
370 status_t
371 KMessage::FindInt64(const char *name, int64 *value) const
372 {
373 	return FindInt64(name, 0, value);
374 }
375 
376 // FindInt64
377 inline
378 status_t
379 KMessage::FindInt64(const char *name, int32 index, int64 *value) const
380 {
381 	return _FindType(name, B_INT64_TYPE, index, value);
382 }
383 
384 // FindString
385 inline
386 status_t
387 KMessage::FindString(const char *name, const char **value) const
388 {
389 	return FindString(name, 0, value);
390 }
391 
392 // FindString
393 inline
394 status_t
395 KMessage::FindString(const char *name, int32 index, const char **value) const
396 {
397 	int32 size;
398 	return FindData(name, B_STRING_TYPE, index, (const void**)value, &size);
399 }
400 
401 
402 // _GetType
403 template<typename T>
404 inline T
405 KMessage::_GetType(const char* name, type_code type, int32 index,
406 	const T& defaultValue) const
407 {
408 	T value;
409 	if (_FindType(name, type, index, &value) == B_OK)
410 		return value;
411 	return defaultValue;
412 }
413 
414 
415 // GetBool
416 inline bool
417 KMessage::GetBool(const char* name, bool defaultValue) const
418 {
419 	return _GetType(name, B_BOOL_TYPE, 0, defaultValue);
420 }
421 
422 
423 // GetBool
424 inline bool
425 KMessage::GetBool(const char* name, int32 index, bool defaultValue) const
426 {
427 	return _GetType(name, B_BOOL_TYPE, index, defaultValue);
428 }
429 
430 // GetInt8
431 inline int8
432 KMessage::GetInt8(const char* name, int8 defaultValue) const
433 {
434 	return _GetType(name, B_INT8_TYPE, 0, defaultValue);
435 }
436 
437 
438 // GetInt8
439 inline int8
440 KMessage::GetInt8(const char* name, int32 index, int8 defaultValue) const
441 {
442 	return _GetType(name, B_INT8_TYPE, index, defaultValue);
443 }
444 
445 
446 // GetInt16
447 inline int16
448 KMessage::GetInt16(const char* name, int16 defaultValue) const
449 {
450 	return _GetType(name, B_INT16_TYPE, 0, defaultValue);
451 }
452 
453 
454 // GetInt16
455 inline int16
456 KMessage::GetInt16(const char* name, int32 index, int16 defaultValue) const
457 {
458 	return _GetType(name, B_INT16_TYPE, index, defaultValue);
459 }
460 
461 
462 // GetInt32
463 inline int32
464 KMessage::GetInt32(const char* name, int32 defaultValue) const
465 {
466 	return _GetType(name, B_INT32_TYPE, 0, defaultValue);
467 }
468 
469 
470 // GetInt32
471 inline int32
472 KMessage::GetInt32(const char* name, int32 index, int32 defaultValue) const
473 {
474 	return _GetType(name, B_INT32_TYPE, index, defaultValue);
475 }
476 
477 
478 // GetInt64
479 inline int64
480 KMessage::GetInt64(const char* name, int64 defaultValue) const
481 {
482 	return _GetType(name, B_INT64_TYPE, 0, defaultValue);
483 }
484 
485 
486 // GetInt64
487 inline int64
488 KMessage::GetInt64(const char* name, int32 index, int64 defaultValue) const
489 {
490 	return _GetType(name, B_INT64_TYPE, index, defaultValue);
491 }
492 
493 
494 // GetString
495 inline const char*
496 KMessage::GetString(const char* name, int32 index,
497 	const char* defaultValue) const
498 {
499 	// don't use _GetType() here, since it checks field size == sizeof(T)
500 	int32 size;
501 	const char* value;
502 	if (FindData(name, B_STRING_TYPE, index, (const void**)&value, &size)
503 			== B_OK) {
504 		return value;
505 	}
506 	return defaultValue;
507 }
508 
509 
510 // GetString
511 inline const char*
512 KMessage::GetString(const char* name, const char* defaultValue) const
513 {
514 	return GetString(name, 0, defaultValue);
515 }
516 
517 
518 // SetBool
519 inline status_t
520 KMessage::SetBool(const char* name, bool value)
521 {
522 	return SetData(name, B_BOOL_TYPE, &value, sizeof(bool));
523 }
524 
525 
526 // SetInt8
527 inline status_t
528 KMessage::SetInt8(const char* name, int8 value)
529 {
530 	return SetData(name, B_INT8_TYPE, &value, sizeof(int8));
531 }
532 
533 
534 // SetInt16
535 inline status_t
536 KMessage::SetInt16(const char* name, int16 value)
537 {
538 	return SetData(name, B_INT16_TYPE, &value, sizeof(int16));
539 }
540 
541 
542 // SetInt32
543 inline status_t
544 KMessage::SetInt32(const char* name, int32 value)
545 {
546 	return SetData(name, B_INT32_TYPE, &value, sizeof(int32));
547 }
548 
549 
550 // SetInt64
551 inline status_t
552 KMessage::SetInt64(const char* name, int64 value)
553 {
554 	return SetData(name, B_INT64_TYPE, &value, sizeof(int64));
555 }
556 
557 
558 #else	// !__cplusplus
559 
560 
561 typedef struct KMessage {
562 	struct Header {
563 		uint32		magic;
564 		int32		size;
565 		uint32		what;
566 		team_id		sender;
567 		int32		targetToken;
568 		port_id		replyPort;
569 		int32		replyToken;
570 	}				fHeader;
571 	void*			fBuffer;
572 	int32			fBufferCapacity;
573 	uint32			fFlags;
574 	int32			fLastFieldOffset;
575 } KMessage;
576 
577 
578 #endif	// !__cplusplus
579 
580 
581 #endif	// KMESSAGE_H
582