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