xref: /haiku/headers/os/app/Message.h (revision 4f00613311d0bd6b70fa82ce19931c41f071ea4e)
1 /*
2  * Copyright 2001-2005, Haiku Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *	Erik Jaesler (erik@cgsoftware.com)
7  *	DarkWyrm <bpmagic@columbus.rr.com>
8  */
9 #ifdef USING_MESSAGE4
10 #	include <Message4.h>
11 #else
12 
13 #ifndef _MESSAGE_H
14 #define _MESSAGE_H
15 
16 #include <DataIO.h>
17 #include <Flattenable.h>
18 #include <Messenger.h>
19 #include <OS.h>
20 #include <Rect.h>
21 
22 // for convenience
23 #include <AppDefs.h>
24 #include <TypeConstants.h>
25 
26 
27 class BBlockCache;
28 class BMessenger;
29 class BHandler;
30 class BString;
31 struct entry_ref;
32 
33 // Private or reserved ---------------------------------------------------------
34 extern "C" void _msg_cache_cleanup_();
35 extern "C" int _init_message_();
36 extern "C" int _delete_message_();
37 
38 
39 // Name lengths and Scripting specifiers ---------------------------------------
40 #define B_FIELD_NAME_LENGTH			255
41 #define B_PROPERTY_NAME_LENGTH		255
42 
43 enum {
44 	B_NO_SPECIFIER = 0,
45 	B_DIRECT_SPECIFIER,
46 	B_INDEX_SPECIFIER,
47 	B_REVERSE_INDEX_SPECIFIER,
48 	B_RANGE_SPECIFIER,
49 	B_REVERSE_RANGE_SPECIFIER,
50 	B_NAME_SPECIFIER,
51 	B_ID_SPECIFIER,
52 
53 	B_SPECIFIERS_END = 128
54 	// app-defined specifiers start at B_SPECIFIERS_END+1
55 };
56 
57 namespace BPrivate {
58 	class BMessageBody;
59 }
60 
61 // BMessage class --------------------------------------------------------------
62 class BMessage {
63 public:
64 		uint32		what;
65 
66 					BMessage();
67 					BMessage(uint32 what);
68 					BMessage(const BMessage &a_message);
69 virtual				~BMessage();
70 
71 		BMessage	&operator=(const BMessage &msg);
72 
73 // Statistics and misc info
74 		status_t	GetInfo(type_code typeRequested, int32 which, char **name,
75 							type_code *typeReturned, int32 *count = NULL) const;
76 
77 		status_t	GetInfo(const char *name, type_code *type, int32 *c = 0) const;
78 		status_t	GetInfo(const char *name, type_code *type, bool *fixed_size) const;
79 
80 		int32		CountNames(type_code type) const;
81 		bool		IsEmpty() const;
82 		bool		IsSystem() const;
83 		bool		IsReply() const;
84 		void		PrintToStream() const;
85 
86 		status_t	Rename(const char *old_entry, const char *new_entry);
87 
88 // Delivery info
89 		bool		WasDelivered() const;
90 		bool		IsSourceWaiting() const;
91 		bool		IsSourceRemote() const;
92 		BMessenger	ReturnAddress() const;
93 		const BMessage	*Previous() const;
94 		bool		WasDropped() const;
95 		BPoint		DropPoint(BPoint *offset = NULL) const;
96 
97 // Replying
98 		status_t	SendReply(uint32 command, BHandler *reply_to = NULL);
99 		status_t	SendReply(BMessage *the_reply, BHandler *reply_to = NULL,
100 							bigtime_t timeout = B_INFINITE_TIMEOUT);
101 		status_t	SendReply(BMessage *the_reply, BMessenger reply_to,
102 							bigtime_t timeout = B_INFINITE_TIMEOUT);
103 
104 		status_t	SendReply(uint32 command, BMessage *reply_to_reply);
105 		status_t	SendReply(BMessage *the_reply, BMessage *reply_to_reply,
106 							bigtime_t send_timeout = B_INFINITE_TIMEOUT,
107 							bigtime_t reply_timeout = B_INFINITE_TIMEOUT);
108 
109 // Flattening data
110 		ssize_t		FlattenedSize() const;
111 		status_t	Flatten(char *buffer, ssize_t size) const;
112 		status_t	Flatten(BDataIO *stream, ssize_t *size = NULL) const;
113 		status_t	Unflatten(const char *flat_buffer);
114 		status_t	Unflatten(BDataIO *stream);
115 
116 
117 // Specifiers (scripting)
118 		status_t	AddSpecifier(const char *property);
119 		status_t	AddSpecifier(const char *property, int32 index);
120 		status_t	AddSpecifier(const char *property, int32 index, int32 range);
121 		status_t	AddSpecifier(const char *property, const char *name);
122 		status_t	AddSpecifier(const BMessage *specifier);
123 
124 		status_t	SetCurrentSpecifier(int32 index);
125 		status_t	GetCurrentSpecifier(int32 *index, BMessage *specifier = NULL,
126 							int32 *form = NULL, const char **property = NULL) const;
127 		bool		HasSpecifiers() const;
128 		status_t	PopSpecifier();
129 
130 // Adding data
131 		status_t	AddRect(const char *name, BRect a_rect);
132 		status_t	AddPoint(const char *name, BPoint a_point);
133 		status_t	AddString(const char *name, const char *a_string);
134 		status_t	AddString(const char *name, const BString& a_string);
135 		status_t	AddInt8(const char *name, int8 val);
136 		status_t	AddInt16(const char *name, int16 val);
137 		status_t	AddInt32(const char *name, int32 val);
138 		status_t	AddInt64(const char *name, int64 val);
139 		status_t	AddBool(const char *name, bool a_boolean);
140 		status_t	AddFloat(const char *name, float a_float);
141 		status_t	AddDouble(const char *name, double a_double);
142 		status_t	AddPointer(const char *name, const void *ptr);
143 		status_t	AddMessenger(const char *name, BMessenger messenger);
144 		status_t	AddRef(const char *name, const entry_ref *ref);
145 		status_t	AddMessage(const char *name, const BMessage *msg);
146 		status_t	AddFlat(const char *name, BFlattenable *obj, int32 count = 1);
147 		status_t	AddData(const char *name, type_code type, const void *data,
148 						ssize_t numBytes, bool is_fixed_size = true, int32 count = 1);
149 
150 // Removing data
151 		status_t	RemoveData(const char *name, int32 index = 0);
152 		status_t	RemoveName(const char *name);
153 		status_t	MakeEmpty();
154 
155 // Finding data
156 		status_t	FindRect(const char *name, BRect *rect) const;
157 		status_t	FindRect(const char *name, int32 index, BRect *rect) const;
158 		status_t	FindPoint(const char *name, BPoint *pt) const;
159 		status_t	FindPoint(const char *name, int32 index, BPoint *pt) const;
160 		status_t	FindString(const char *name, const char **str) const;
161 		status_t	FindString(const char *name, int32 index, const char **str) const;
162 		status_t	FindString(const char *name, BString *str) const;
163 		status_t	FindString(const char *name, int32 index, BString *str) const;
164 		status_t	FindInt8(const char *name, int8 *value) const;
165 		status_t	FindInt8(const char *name, int32 index, int8 *val) const;
166 		status_t	FindInt16(const char *name, int16 *value) const;
167 		status_t	FindInt16(const char *name, int32 index, int16 *val) const;
168 		status_t	FindInt32(const char *name, int32 *value) const;
169 		status_t	FindInt32(const char *name, int32 index, int32 *val) const;
170 		status_t	FindInt64(const char *name, int64 *value) const;
171 		status_t	FindInt64(const char *name, int32 index, int64 *val) const;
172 		status_t	FindBool(const char *name, bool *value) const;
173 		status_t	FindBool(const char *name, int32 index, bool *value) const;
174 		status_t	FindFloat(const char *name, float *f) const;
175 		status_t	FindFloat(const char *name, int32 index, float *f) const;
176 		status_t	FindDouble(const char *name, double *d) const;
177 		status_t	FindDouble(const char *name, int32 index, double *d) const;
178 		status_t	FindPointer(const char *name, void **ptr) const;
179 		status_t	FindPointer(const char *name, int32 index,  void **ptr) const;
180 		status_t	FindMessenger(const char *name, BMessenger *m) const;
181 		status_t	FindMessenger(const char *name, int32 index, BMessenger *m) const;
182 		status_t	FindRef(const char *name, entry_ref *ref) const;
183 		status_t	FindRef(const char *name, int32 index, entry_ref *ref) const;
184 		status_t	FindMessage(const char *name, BMessage *msg) const;
185 		status_t	FindMessage(const char *name, int32 index, BMessage *msg) const;
186 		status_t	FindFlat(const char *name, BFlattenable *obj) const;
187 		status_t	FindFlat(const char *name, int32 index, BFlattenable *obj) const;
188 		status_t	FindData(const char *name, type_code type,
189 							const void **data, ssize_t *numBytes) const;
190 		status_t	FindData(const char *name, type_code type, int32 index,
191 							const void **data, ssize_t *numBytes) const;
192 
193 // Replacing data
194 		status_t	ReplaceRect(const char *name, BRect a_rect);
195 		status_t	ReplaceRect(const char *name, int32 index, BRect a_rect);
196 		status_t	ReplacePoint(const char *name, BPoint a_point);
197 		status_t	ReplacePoint(const char *name, int32 index, BPoint a_point);
198 		status_t	ReplaceString(const char *name, const char *string);
199 		status_t	ReplaceString(const char *name, int32 index, const char *string);
200 		status_t	ReplaceString(const char *name, const BString& string);
201 		status_t	ReplaceString(const char *name, int32 index, const BString& string);
202 		status_t	ReplaceInt8(const char *name, int8 val);
203 		status_t	ReplaceInt8(const char *name, int32 index, int8 val);
204 		status_t	ReplaceInt16(const char *name, int16 val);
205 		status_t	ReplaceInt16(const char *name, int32 index, int16 val);
206 		status_t	ReplaceInt32(const char *name, int32 val);
207 		status_t	ReplaceInt32(const char *name, int32 index, int32 val);
208 		status_t	ReplaceInt64(const char *name, int64 val);
209 		status_t	ReplaceInt64(const char *name, int32 index, int64 val);
210 		status_t	ReplaceBool(const char *name, bool a_bool);
211 		status_t	ReplaceBool(const char *name, int32 index, bool a_bool);
212 		status_t	ReplaceFloat(const char *name, float a_float);
213 		status_t	ReplaceFloat(const char *name, int32 index, float a_float);
214 		status_t	ReplaceDouble(const char *name, double a_double);
215 		status_t	ReplaceDouble(const char *name, int32 index, double a_double);
216 		status_t	ReplacePointer(const char *name, const void *ptr);
217 		status_t	ReplacePointer(const char *name,int32 index,const void *ptr);
218 		status_t	ReplaceMessenger(const char *name, BMessenger messenger);
219 		status_t	ReplaceMessenger(const char *name, int32 index, BMessenger msngr);
220 		status_t	ReplaceRef(	const char *name,const entry_ref *ref);
221 		status_t	ReplaceRef(	const char *name, int32 index, const entry_ref *ref);
222 		status_t	ReplaceMessage(const char *name, const BMessage *msg);
223 		status_t	ReplaceMessage(const char *name, int32 index, const BMessage *msg);
224 		status_t	ReplaceFlat(const char *name, BFlattenable *obj);
225 		status_t	ReplaceFlat(const char *name, int32 index, BFlattenable *obj);
226 		status_t	ReplaceData(const char *name, type_code type,
227 								const void *data, ssize_t data_size);
228 		status_t	ReplaceData(const char *name, type_code type, int32 index,
229 								const void *data, ssize_t data_size);
230 
231 		void		*operator new(size_t size);
232 		void		*operator new(size_t, void* p);
233 		void		operator delete(void *ptr, size_t size);
234 
235 // Private, reserved, or obsolete ----------------------------------------------
236 		bool		HasRect(const char *, int32 n = 0) const;
237 		bool		HasPoint(const char *, int32 n = 0) const;
238 		bool		HasString(const char *, int32 n = 0) const;
239 		bool		HasInt8(const char *, int32 n = 0) const;
240 		bool		HasInt16(const char *, int32 n = 0) const;
241 		bool		HasInt32(const char *, int32 n = 0) const;
242 		bool		HasInt64(const char *, int32 n = 0) const;
243 		bool		HasBool(const char *, int32 n = 0) const;
244 		bool		HasFloat(const char *, int32 n = 0) const;
245 		bool		HasDouble(const char *, int32 n = 0) const;
246 		bool		HasPointer(const char *, int32 n = 0) const;
247 		bool		HasMessenger(const char *, int32 n = 0) const;
248 		bool		HasRef(const char *, int32 n = 0) const;
249 		bool		HasMessage(const char *, int32 n = 0) const;
250 		bool		HasFlat(const char *, const BFlattenable *) const;
251 		bool		HasFlat(const char *,int32 ,const BFlattenable *) const;
252 		bool		HasData(const char *, type_code , int32 n = 0) const;
253 		BRect		FindRect(const char *, int32 n = 0) const;
254 		BPoint		FindPoint(const char *, int32 n = 0) const;
255 		const char	*FindString(const char *, int32 n = 0) const;
256 		int8		FindInt8(const char *, int32 n = 0) const;
257 		int16		FindInt16(const char *, int32 n = 0) const;
258 		int32		FindInt32(const char *, int32 n = 0) const;
259 		int64		FindInt64(const char *, int32 n = 0) const;
260 		bool		FindBool(const char *, int32 n = 0) const;
261 		float		FindFloat(const char *, int32 n = 0) const;
262 		double		FindDouble(const char *, int32 n = 0) const;
263 
264 		class Private;
265 
266 private:
267 		class Header;
268 
269 friend class	BMessageQueue;
270 friend class	BMessenger;
271 friend class	BApplication;
272 friend class	Header;
273 friend class	Private;
274 
275 friend inline	void		_set_message_target_(BMessage *, int32, bool);
276 friend inline	void		_set_message_reply_(BMessage *, BMessenger);
277 friend inline	int32		_get_message_target_(BMessage *);
278 friend inline	bool		_use_preferred_target_(BMessage *);
279 
280 					// deprecated
281 					BMessage(BMessage *a_message);
282 
283 virtual	void		_ReservedMessage1();
284 virtual	void		_ReservedMessage2();
285 virtual	void		_ReservedMessage3();
286 
287 		void		init_data();
288 		status_t	flatten_target_info(BDataIO *stream,
289 										ssize_t size,
290 										uchar flags) const;
291 		status_t	real_flatten(char *result,
292 								ssize_t size) const;
293 		status_t	real_flatten(BDataIO *stream) const;
294 		char		*stack_flatten(char *stack_ptr,
295 									ssize_t stack_size,
296 									bool incl_reply,
297 									ssize_t *size = NULL) const;
298 
299 		status_t	_UnflattenKMessage(const char *buffer);
300 
301 		ssize_t		calc_size(uchar flags) const;
302 		ssize_t		calc_hdr_size(uchar flags) const;
303 		status_t	nfind_data(	const char *name,
304 								type_code type,
305 								int32 index,
306 								const void **data,
307 								ssize_t *data_size) const;
308 		status_t	copy_data(	const char *name,
309 								type_code type,
310 								int32 index,
311 								void *data,
312 								ssize_t data_size) const;
313 
314 		status_t	_send_(port_id port,
315 							int32 token,
316 							bigtime_t timeout,
317 							bool reply_required,
318 							BMessenger &reply_to) const;
319 		status_t	send_message(port_id port,
320 								team_id port_owner,
321 								int32 token,
322 								BMessage *reply,
323 								bigtime_t send_timeout,
324 								bigtime_t reply_timeout) const;
325 static	status_t	_SendFlattenedMessage(void *data, int32 size,
326 						port_id port, int32 token, bigtime_t timeout);
327 
328 static	void		_StaticInit();
329 static	void		_StaticCleanup();
330 static	void		_StaticCacheCleanup();
331 
332 		enum		{ sNumReplyPorts = 3 };
333 static	port_id		sReplyPorts[sNumReplyPorts];
334 static	long		sReplyPortInUse[sNumReplyPorts];
335 static	int32		sGetCachedReplyPort();
336 
337 static	BBlockCache	*sMsgCache;
338 
339 		struct dyn_array {
340 			int32		fLogicalBytes;
341 			int32		fPhysicalBytes;
342 			int32		fChunkSize;
343 			int32		fCount;
344 			int32		fEntryHdrSize;
345 		};
346 
347 		struct entry_hdr  : public dyn_array {
348 			entry_hdr	*fNext;
349 			uint32		fType;
350 			uchar		fNameLength;
351 			char		fName[1];
352 		};
353 
354 		struct var_chunk {
355 			int32	fDataSize;
356 			char	fData[1];
357 		};
358 
359 		entry_hdr 	*entry_find(const char *name, uint32 type,status_t *result=NULL) const;
360 		void 		entry_remove(entry_hdr *entry);
361 
362 		void		*da_create(int32 header_size, int32 chunk_size,
363 								bool fixed, int32 nchunks);
364 		status_t	da_add_data(dyn_array **da, const void *data, int32 size);
365 		void		*da_find_data(dyn_array *da, int32 index,
366 									int32 *size = NULL) const;
367 		status_t	da_delete_data(dyn_array **pda, int32 index);
368 		status_t	da_replace_data(dyn_array **pda, int32 index,
369 									const void *data, int32 dsize);
370 		int32		da_calc_size(int32 hdr_size, int32 chunksize,
371 								bool is_fixed, int32 nchunks) const;
372 		void		*da_grow(dyn_array **pda, int32 increase);
373 		void		da_dump(dyn_array *da);
374 
375 		int32		da_chunk_hdr_size() const
376 						{ return sizeof(int32); }
377 		int32		da_chunk_size(var_chunk *v) const
378 						{ return (v->fDataSize + da_chunk_hdr_size() + 7) & ~7; }
379 		var_chunk	*da_first_chunk(dyn_array *da) const
380 						{ return (var_chunk *) da_start_of_data(da); }
381 		var_chunk	*da_next_chunk(var_chunk *v) const
382 						{ return (var_chunk *) (((char*) v) + da_chunk_size(v)); }
383 		var_chunk	*da_chunk_ptr(void *data) const
384 						{ return (var_chunk*) (((char *) data) - da_chunk_hdr_size()); }
385 
386 		int32		da_pad_8(int32 val) const
387 						{ return (val + 7) & ~7; }
388 		int32		da_total_size(dyn_array *da) const
389 						{ return (int32)sizeof(dyn_array) + da->fEntryHdrSize +
390 											da->fPhysicalBytes; }
391 		int32		da_total_logical_size(dyn_array *da) const
392 						{ return (int32)sizeof(dyn_array) + da->fEntryHdrSize +
393 											da->fLogicalBytes; }
394 		char		*da_start_of_data(dyn_array *da) const
395 						{ return ((char *) da) + (sizeof(dyn_array) +
396 											da->fEntryHdrSize); }
397 		bool		da_is_mini_data(dyn_array *da) const
398 						{ return ((da->fLogicalBytes <= (int32) UCHAR_MAX) &&
399 											(da->fCount <= (int32) UCHAR_MAX));}
400 		void		da_swap_var_sized(dyn_array *da);
401 		void		da_swap_fixed_sized(dyn_array *da);
402 
403 		BMessage			*fQueueLink;
404 		int32				fTarget;
405 		BMessage			*fOriginal;
406 		uint32				fChangeCount;
407 		int32				fCurSpecifier;
408 		uint32				fPtrOffset;
409 
410 		// ejaesler: Stealing one for my whacky BMessageBody l33tness
411 		uint32				_reserved[2];
412 		BPrivate::BMessageBody*	fBody;
413 
414 		BMessage::entry_hdr	*fEntries;
415 
416 		struct reply_to_info {
417 			port_id				port;
418 			int32				target;
419 			team_id				team;
420 			bool				preferred;
421 		} fReplyTo;
422 
423 		bool				fPreferred;
424 		bool				fReplyRequired;
425 		bool				fReplyDone;
426 		bool				fIsReply;
427 		bool				fWasDelivered;
428 		bool				fReadOnly;
429 		bool				fHasSpecifiers;
430 };
431 
432 #endif	// _MESSAGE_H
433 #endif	// USING_MESSAGE4
434 
435