xref: /haiku/src/kits/app/Message.cpp (revision d1d811ec7007913f727f6b44d2d730554eacfa19)
1 //------------------------------------------------------------------------------
2 //	Copyright (c) 2001-2002, OpenBeOS
3 //
4 //	Permission is hereby granted, free of charge, to any person obtaining a
5 //	copy of this software and associated documentation files (the "Software"),
6 //	to deal in the Software without restriction, including without limitation
7 //	the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 //	and/or sell copies of the Software, and to permit persons to whom the
9 //	Software is furnished to do so, subject to the following conditions:
10 //
11 //	The above copyright notice and this permission notice shall be included in
12 //	all copies or substantial portions of the Software.
13 //
14 //	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 //	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 //	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 //	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 //	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 //	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 //	DEALINGS IN THE SOFTWARE.
21 //
22 //	File Name:		Message.h
23 //	Author(s):		Erik Jaesler (erik@cgsoftware.com)
24 //					DarkWyrm <bpmagic@columbus.rr.com>
25 //	Description:	BMessage class creates objects that store data and that
26 //					can be processed in a message loop.  BMessage objects
27 //					are also used as data containers by the archiving and
28 //					the scripting mechanisms.
29 //------------------------------------------------------------------------------
30 
31 #define USING_TEMPLATE_MADNESS
32 
33 // Standard Includes -----------------------------------------------------------
34 #include <stdio.h>
35 
36 // System Includes -------------------------------------------------------------
37 #include <Application.h>
38 #include <BlockCache.h>
39 #include <ByteOrder.h>
40 #include <Errors.h>
41 #include <Message.h>
42 #include <Messenger.h>
43 #include <String.h>
44 
45 //#include <CRTDBG.H>
46 
47 // Project Includes ------------------------------------------------------------
48 #ifdef USING_TEMPLATE_MADNESS
49 #include <AppMisc.h>
50 #include <DataBuffer.h>
51 #include <MessageBody.h>
52 #include <MessageUtils.h>
53 #include <TokenSpace.h>
54 #endif	// USING_TEMPLATE_MADNESS
55 
56 // Local Includes --------------------------------------------------------------
57 
58 // Local Defines ---------------------------------------------------------------
59 #define	MSG_FIELD_VERSION		'FOB1'
60 
61 // flags for the overall message (the bitfield is 1 byte)
62 #define MSG_FLAG_BIG_ENDIAN		0x01
63 #define MSG_FLAG_INCL_TARGET	0x02
64 #define MSG_FLAG_INCL_REPLY		0x04
65 #define MSG_FLAG_SCRIPT_MSG		0x08
66 // These are for future improvement
67 #if 0
68 #define MSG_FLAG_USE_PREFERRED	0x10
69 #define MSG_FLAG_REPLY_WANTED	0x20
70 #define MSG_FLAG_REPLY_DONE		0x40
71 #define MSG_FLAG_IS_REPLY		0x80
72 
73 #define MSG_FLAG_HDR_MASK		0xF0
74 #endif
75 
76 #define MSG_HEADER_MAX_SIZE		38
77 #define MSG_NAME_MAX_SIZE		256
78 
79 // Globals ---------------------------------------------------------------------
80 
81 #ifdef USING_TEMPLATE_MADNESS
82 using namespace BPrivate;
83 #endif	// USING_TEMPLATE_MADNESS
84 const char* B_SPECIFIER_ENTRY = "specifiers";
85 const char* B_PROPERTY_ENTRY = "property";
86 const char* B_PROPERTY_NAME_ENTRY = "name";
87 
88 BBlockCache* BMessage::sMsgCache = NULL;
89 port_id BMessage::sReplyPorts[sNumReplyPorts];
90 long BMessage::sReplyPortInUse[sNumReplyPorts];
91 
92 
93 static status_t handle_reply(port_id   reply_port,
94                              int32*    pCode,
95                              bigtime_t timeout,
96                              BMessage* reply);
97 
98 //------------------------------------------------------------------------------
99 extern "C" {
100 void _msg_cache_cleanup_()
101 {
102 	delete BMessage::sMsgCache;
103 	BMessage::sMsgCache = NULL;
104 }
105 //------------------------------------------------------------------------------
106 int _init_message_()
107 {
108 	BMessage::sReplyPorts[0] = create_port(1, "tmp_rport0");
109 	BMessage::sReplyPorts[1] = create_port(1, "tmp_rport1");
110 	BMessage::sReplyPorts[2] = create_port(1, "tmp_rport2");
111 
112 	BMessage::sReplyPortInUse[0] = 0;
113 	BMessage::sReplyPortInUse[1] = 0;
114 	BMessage::sReplyPortInUse[2] = 0;
115 	return 0;
116 }
117 //------------------------------------------------------------------------------
118 int _delete_message_()
119 {
120 	delete_port(BMessage::sReplyPorts[0]);
121 	BMessage::sReplyPorts[0] = -1;
122 	delete_port(BMessage::sReplyPorts[1]);
123 	BMessage::sReplyPorts[1] = -1;
124 	delete_port(BMessage::sReplyPorts[2]);
125 	BMessage::sReplyPorts[2] = -1;
126 	return 0;
127 }
128 }	// extern "C"
129 //------------------------------------------------------------------------------
130 BMessage *_reconstruct_msg_(uint32,uint32,uint32)
131 {
132 	return NULL;
133 }
134 //------------------------------------------------------------------------------
135 
136 #ifdef USING_TEMPLATE_MADNESS
137 void BMessage::_ReservedMessage1() {}
138 void BMessage::_ReservedMessage2() {}
139 void BMessage::_ReservedMessage3() {}
140 
141 //------------------------------------------------------------------------------
142 BMessage::BMessage()
143 	:	what(0), fBody(NULL)
144 {
145 	init_data();
146 }
147 //------------------------------------------------------------------------------
148 BMessage::BMessage(uint32 w)
149 	:	fBody(NULL)
150 {
151 	init_data();
152 	what = w;
153 }
154 //------------------------------------------------------------------------------
155 BMessage::BMessage(const BMessage& a_message)
156 	:	fBody(NULL)
157 {
158 	init_data();
159 	*this = a_message;
160 }
161 //------------------------------------------------------------------------------
162 BMessage::BMessage(BMessage *a_message)
163 	:	fBody(NULL)
164 {
165 	init_data();
166 	*this = *a_message;
167 }
168 //------------------------------------------------------------------------------
169 BMessage::~BMessage()
170 {
171 	if (IsSourceWaiting())
172 	{
173 		SendReply(B_NO_REPLY);
174 	}
175 	delete fBody;
176 }
177 //------------------------------------------------------------------------------
178 BMessage& BMessage::operator=(const BMessage& msg)
179 {
180 	what = msg.what;
181 
182 	link = msg.link;
183 	fTarget = msg.fTarget;
184 	fOriginal = msg.fOriginal;
185 	fChangeCount = msg.fChangeCount;
186 	fCurSpecifier = msg.fCurSpecifier;
187 	fPtrOffset = msg.fPtrOffset;
188 
189 	fEntries = msg.fEntries;
190 
191 	fReplyTo.port = msg.fReplyTo.port;
192 	fReplyTo.target = msg.fReplyTo.target;
193 	fReplyTo.team = msg.fReplyTo.team;
194 	fReplyTo.preferred = msg.fReplyTo.preferred;
195 
196 	fPreferred = msg.fPreferred;
197 	fReplyRequired = msg.fReplyRequired;
198 	fReplyDone = msg.fReplyDone;
199 	fIsReply = msg.fIsReply;
200 	fWasDelivered = msg.fWasDelivered;
201 	fReadOnly = msg.fReadOnly;
202 	fHasSpecifiers = msg.fHasSpecifiers;
203 
204 	*fBody = *(msg.fBody);
205 	return *this;
206 }
207 //------------------------------------------------------------------------------
208 void BMessage::init_data()
209 {
210 	what = 0;
211 
212 	link = NULL;
213 	fTarget = B_NULL_TOKEN;
214 	fOriginal = NULL;
215 	fChangeCount = 0;
216 	fCurSpecifier = -1;
217 	fPtrOffset = 0;
218 
219 	fEntries = NULL;
220 
221 	fReplyTo.port = -1;
222 	fReplyTo.target = B_NULL_TOKEN;
223 	fReplyTo.team = -1;
224 	fReplyTo.preferred = false;
225 
226 	fPreferred = false;
227 	fReplyRequired = false;
228 	fReplyDone = false;
229 	fIsReply = false;
230 	fWasDelivered = false;
231 	fReadOnly = false;
232 	fHasSpecifiers = false;
233 
234 	if (fBody)
235 	{
236 		fBody->MakeEmpty();
237 	}
238 	else
239 	{
240 		fBody = new BPrivate::BMessageBody;
241 	}
242 }
243 //------------------------------------------------------------------------------
244 status_t BMessage::GetInfo(type_code typeRequested, int32 which, char** name,
245 						   type_code* typeReturned, int32* count) const
246 {
247 	return fBody->GetInfo(typeRequested, which, name, typeReturned, count);
248 }
249 //------------------------------------------------------------------------------
250 status_t BMessage::GetInfo(const char* name, type_code* type, int32* c) const
251 {
252 	return fBody->GetInfo(name, type, c);
253 }
254 //------------------------------------------------------------------------------
255 status_t BMessage::GetInfo(const char* name, type_code* type,
256 						   bool* fixed_size) const
257 {
258 	return fBody->GetInfo(name, type, fixed_size);
259 }
260 //------------------------------------------------------------------------------
261 int32 BMessage::CountNames(type_code type) const
262 {
263 	return fBody->CountNames(type);
264 }
265 //------------------------------------------------------------------------------
266 bool BMessage::IsEmpty() const
267 {
268 	return fBody->IsEmpty();
269 }
270 //------------------------------------------------------------------------------
271 bool BMessage::IsSystem() const
272 {
273 	char a = char(what >> 24);
274 	char b = char(what >> 16);
275 	char c = char(what >> 8);
276 	char d = char(what);
277 
278 	// The BeBook says:
279 	//		... we've adopted a strict convention for assigning values to all
280 	//		Be-defined constants.  The value assigned will always be formed by
281 	//		combining four characters into a multicharacter constant, with the
282 	//		characters limited to uppercase letters and the underbar
283 	// Between that and what's in AppDefs.h, this algo seems like a safe bet:
284 	if (a == '_' && isupper(b) && isupper(c) && isupper(d))
285 	{
286 		return true;
287 	}
288 
289 	return false;
290 }
291 //------------------------------------------------------------------------------
292 bool BMessage::IsReply() const
293 {
294 	return fIsReply;
295 }
296 //------------------------------------------------------------------------------
297 void BMessage::PrintToStream() const
298 {
299 	printf("\nBMessage: what =  (0x%lX or %ld)\n", what, what);
300 	fBody->PrintToStream();
301 }
302 //------------------------------------------------------------------------------
303 status_t BMessage::Rename(const char* old_entry, const char* new_entry)
304 {
305 	return fBody->Rename(old_entry, new_entry);
306 }
307 //------------------------------------------------------------------------------
308 bool BMessage::WasDelivered() const
309 {
310 	return fWasDelivered;
311 }
312 //------------------------------------------------------------------------------
313 bool BMessage::IsSourceWaiting() const
314 {
315 	return fReplyRequired && !fReplyDone;
316 }
317 //------------------------------------------------------------------------------
318 bool BMessage::IsSourceRemote() const
319 {
320 	return WasDelivered() && fReplyTo.team != BPrivate::current_team();
321 }
322 //------------------------------------------------------------------------------
323 BMessenger BMessage::ReturnAddress() const
324 {
325 	if (WasDelivered())
326 	{
327 		return BMessenger(fReplyTo.team, fReplyTo.port, fReplyTo.target,
328 						  fReplyTo.preferred);
329 	}
330 
331 	return BMessenger();
332 }
333 //------------------------------------------------------------------------------
334 const BMessage* BMessage::Previous() const
335 {
336 	// TODO: test
337 	// In particular, look to see if the "_previous_" field is used in R5
338 	if (!fOriginal)
339 	{
340 		BMessage* fOriginal = new BMessage;
341 		if (FindMessage("_previous_", fOriginal) != B_OK)
342 		{
343 			delete fOriginal;
344 			fOriginal = NULL;
345 		}
346 	}
347 
348 	return fOriginal;
349 }
350 //------------------------------------------------------------------------------
351 bool BMessage::WasDropped() const
352 {
353 	return fReadOnly;
354 }
355 //------------------------------------------------------------------------------
356 BPoint BMessage::DropPoint(BPoint* offset) const
357 {
358 	// TODO: Where do we get this stuff???
359 	if (offset)
360 	{
361 		*offset = FindPoint("_drop_offset_");
362 	}
363 	return FindPoint("_drop_point_");
364 }
365 //------------------------------------------------------------------------------
366 status_t BMessage::SendReply(uint32 command, BHandler* reply_to)
367 {
368 	BMessage msg(command);
369 	return SendReply(&msg, reply_to);
370 }
371 //------------------------------------------------------------------------------
372 status_t BMessage::SendReply(BMessage* the_reply, BHandler* reply_to,
373 							 bigtime_t timeout)
374 {
375 	BMessenger messenger(reply_to);
376 	return SendReply(the_reply, messenger, timeout);
377 }
378 //------------------------------------------------------------------------------
379 #if 0
380 template<class Sender>
381 status_t SendReplyHelper(BMessage* the_message, BMessage* the_reply,
382 						 Sender& the_sender)
383 {
384 	BMessenger messenger(the_message->fReplyTo.team, the_message->fReplyTo.port,
385 						 the_message->fReplyTo.target,
386 						 the_message->fReplyTo.preferred);
387 	if (the_message->fReplyRequired)
388 	{
389 		if (the_message->fReplyDone)
390 		{
391 			return B_DUPLICATE_REPLY;
392 		}
393 		the_message->fReplyDone = true;
394 		the_reply->fIsReply = true;
395 		status_t err = the_sender.Send(messenger, the_reply);
396 		the_reply->fIsReply = false;
397 		if (err)
398 		{
399 			if (set_port_owner(messenger.fPort, messenger.fTeam) == B_BAD_TEAM_ID)
400 			{
401 				delete_port(messenger.fPort);
402 			}
403 		}
404 		return err;
405 	}
406 	// no reply required
407 	if (!the_message->fWasDelivered)
408 	{
409 		return B_BAD_REPLY;
410 	}
411 
412 #if 0
413 	char tmp[0x800];
414 	ssize_t size;
415 	char* p = stack_flatten(tmp, sizeof(tmp), true /* include reply */, &size);
416 	the_reply->AddData("_previous_", B_RAW_TYPE, p ? p : tmp, &size);
417 	if (p)
418 	{
419 		free(p);
420 	}
421 #endif
422 	the_reply->AddMessage("_previous_", the_message);
423 	the_reply->fIsReply = true;
424 	status_t err = the_sender.Send(messenger, the_reply);
425 	the_reply->fIsReply = false;
426 	the_reply->RemoveName("_previous_");
427 	return err;
428 };
429 #endif
430 //------------------------------------------------------------------------------
431 #if 0
432 struct Sender1
433 {
434 	BMessenger& reply_to;
435 	bigtime_t timeout;
436 
437 	Sender1(BMessenger& m, bigtime_t t) : reply_to(m), timeout(t) {;}
438 
439 	status_t Send(BMessenger& messenger, BMessage* the_reply)
440 	{
441 		return messenger.SendMessage(the_reply, reply_to, timeout);
442 	}
443 };
444 status_t BMessage::SendReply(BMessage* the_reply, BMessenger reply_to,
445 							 bigtime_t timeout)
446 {
447 	Sender1 mySender(reply_to, timeout);
448 	return SendReplyHelper(this, the_reply, mySender);
449 }
450 #endif
451 status_t BMessage::SendReply(BMessage* the_reply, BMessenger reply_to,
452 							 bigtime_t timeout)
453 {
454 	// TODO: test
455 	BMessenger messenger(fReplyTo.team, fReplyTo.port,
456 						 fReplyTo.target,
457 						 fReplyTo.preferred);
458 	if (fReplyRequired)
459 	{
460 		if (fReplyDone)
461 		{
462 			return B_DUPLICATE_REPLY;
463 		}
464 		fReplyDone = true;
465 		the_reply->fIsReply = true;
466 		status_t err = messenger.SendMessage(the_reply, reply_to, timeout);
467 		the_reply->fIsReply = false;
468 		if (err)
469 		{
470 			if (set_port_owner(messenger.fPort, messenger.fTeam) == B_BAD_TEAM_ID)
471 			{
472 				delete_port(messenger.fPort);
473 			}
474 		}
475 		return err;
476 	}
477 	// no reply required
478 	if (!fWasDelivered)
479 	{
480 		return B_BAD_REPLY;
481 	}
482 
483 	the_reply->AddMessage("_previous_", this);
484 	the_reply->fIsReply = true;
485 	status_t err = messenger.SendMessage(the_reply, reply_to, timeout);
486 	the_reply->fIsReply = false;
487 	the_reply->RemoveName("_previous_");
488 	return err;
489 }
490 //------------------------------------------------------------------------------
491 status_t BMessage::SendReply(uint32 command, BMessage* reply_to_reply)
492 {
493 	BMessage msg(command);
494 	return SendReply(&msg, reply_to_reply);
495 }
496 //------------------------------------------------------------------------------
497 #if 0
498 struct Sender2
499 {
500 	BMessage* reply_to_reply;
501 	bigtime_t send_timeout;
502 	bigtime_t reply_timeout;
503 
504 	Sender2(BMessage* m, bigtime_t t1, bigtime_t t2)
505 		:	reply_to_reply(m), send_timeout(t1), reply_timeout(t2) {;}
506 
507 	status_t Send(BMessenger& messenger, BMessage* the_reply)
508 	{
509 		return messenger.SendMessage(the_reply, reply_to_reply,
510 									 send_timeout, reply_timeout);
511 	}
512 };
513 status_t BMessage::SendReply(BMessage* the_reply, BMessage* reply_to_reply,
514 							 bigtime_t send_timeout, bigtime_t reply_timeout)
515 {
516 	Sender2 mySender(reply_to_reply, send_timeout, reply_timeout);
517 	return SendReplyHelper(this, the_reply, mySender);
518 }
519 #endif
520 status_t BMessage::SendReply(BMessage* the_reply, BMessage* reply_to_reply,
521 							 bigtime_t send_timeout, bigtime_t reply_timeout)
522 {
523 	// TODO: test
524 	BMessenger messenger(fReplyTo.team, fReplyTo.port,
525 						 fReplyTo.target,
526 						 fReplyTo.preferred);
527 	if (fReplyRequired)
528 	{
529 		if (fReplyDone)
530 		{
531 			return B_DUPLICATE_REPLY;
532 		}
533 		fReplyDone = true;
534 		the_reply->fIsReply = true;
535 		status_t err = messenger.SendMessage(the_reply, reply_to_reply,
536 											 send_timeout, reply_timeout);
537 		the_reply->fIsReply = false;
538 		if (err)
539 		{
540 			if (set_port_owner(messenger.fPort, messenger.fTeam) == B_BAD_TEAM_ID)
541 			{
542 				delete_port(messenger.fPort);
543 			}
544 		}
545 		return err;
546 	}
547 	// no reply required
548 	if (!fWasDelivered)
549 	{
550 		return B_BAD_REPLY;
551 	}
552 
553 	the_reply->AddMessage("_previous_", this);
554 	the_reply->fIsReply = true;
555 	status_t err = messenger.SendMessage(the_reply, reply_to_reply,
556 										 send_timeout, reply_timeout);
557 	the_reply->fIsReply = false;
558 	the_reply->RemoveName("_previous_");
559 	return err;
560 }
561 //------------------------------------------------------------------------------
562 ssize_t BMessage::FlattenedSize() const
563 {
564 	return calc_hdr_size(0) + fBody->FlattenedSize();
565 }
566 //------------------------------------------------------------------------------
567 status_t BMessage::Flatten(char* buffer, ssize_t size) const
568 {
569 	return real_flatten(buffer, size);
570 }
571 //------------------------------------------------------------------------------
572 status_t BMessage::Flatten(BDataIO* stream, ssize_t* size) const
573 {
574 	status_t err = B_OK;
575 	ssize_t len = FlattenedSize();
576 	char* buffer = new(nothrow) char[len];
577 	if (buffer)
578 	{
579 		err = Flatten(buffer, len);
580 		if (!err)
581 		{
582 			// size is an optional parameter, don't crash on NULL
583 			if (size != NULL)
584 			{
585 				*size = len;
586 			}
587 			err = stream->Write(buffer, len);
588 			if (err > B_OK)
589 				err = B_OK;
590 		}
591 
592 		delete[] buffer;
593 	}
594 	else
595 	{
596 		err = B_NO_MEMORY;
597 	}
598 
599 	return err;
600 }
601 //------------------------------------------------------------------------------
602 status_t BMessage::Unflatten(const char* flat_buffer)
603 {
604 	uint32 size = ((uint32*)flat_buffer)[2];
605 
606 	BMemoryIO MemIO(flat_buffer, size);
607 	return Unflatten(&MemIO);
608 }
609 //------------------------------------------------------------------------------
610 status_t BMessage::Unflatten(BDataIO* stream)
611 {
612 	bool swap;
613 	status_t err = unflatten_hdr(stream, swap);
614 
615 	if (!err)
616 	{
617 		TReadHelper reader(stream, swap);
618 		int8 flags;
619 		type_code type;
620 		uint32 count;
621 		uint32 dataLen;
622 		uint8 nameLen;
623 		char name[MSG_NAME_MAX_SIZE];
624 		unsigned char* databuffer = NULL;
625 
626 		try
627 		{
628 			reader(flags);
629 			while (flags != MSG_LAST_ENTRY)
630 			{
631 				reader(type);
632 				// Is there more than one data item? (!flags & MSG_FLAG_SINGLE_ITEM)
633 				if (flags & MSG_FLAG_SINGLE_ITEM)
634 				{
635 					count = 1;
636 					if (flags & MSG_FLAG_MINI_DATA)
637 					{
638 						uint8 littleLen;
639 						reader(littleLen);
640 						dataLen = littleLen;
641 					}
642 					else
643 					{
644 						reader(dataLen);
645 					}
646 				}
647 				else
648 				{
649 					// Is there a little data? (flags & MSG_FLAG_MINI_DATA)
650 					if (flags & MSG_FLAG_MINI_DATA)
651 					{
652 						// Get item count (1 byte)
653 						uint8 littleCount;
654 						reader(littleCount);
655 						count = littleCount;
656 
657 						// Get data length (1 byte)
658 						uint8 littleLen;
659 						reader(littleLen);
660 						dataLen = littleLen;
661 					}
662 					else
663 					{
664 					// Is there a lot of data? (!flags & MSG_FLAG_MINI_DATA)
665 						// Get item count (4 bytes)
666 						reader(count);
667 						// Get data length (4 bytes)
668 						reader(dataLen);
669 					}
670 				}
671 
672 				// Get the name length (1 byte)
673 				reader(nameLen);
674 				// Get the name (name length bytes)
675 				reader(name, nameLen);
676 				name[nameLen] = '\0';
677 
678 				// Copy the data into a new buffer to byte align it
679 				databuffer = (unsigned char*)realloc(databuffer, dataLen);
680 				if (!databuffer)
681 					throw B_NO_MEMORY;
682 				// Get the data
683 				reader(databuffer, dataLen);
684 
685 				// Is the data fixed size? (flags & MSG_FLAG_FIXED_SIZE)
686 				if (flags & MSG_FLAG_FIXED_SIZE && swap)
687 				{
688 					// Make sure to swap the data
689 					err = swap_data(type, (void*)databuffer, dataLen,
690 									B_SWAP_ALWAYS);
691 					if (err)
692 						throw err;
693 				}
694 				// Is the data variable size? (!flags & MSG_FLAG_FIXED_SIZE)
695 				else if (swap && type == B_REF_TYPE)
696 				{
697 					// Apparently, entry_refs are the only variable-length data
698 					// 	  explicitely swapped -- the dev_t and ino_t
699 					//    specifically
700 					byte_swap(*(entry_ref*)databuffer);
701 				}
702 
703 				// Add each data field to the message
704 				uint32 itemSize = 0;
705 				if (flags & MSG_FLAG_FIXED_SIZE)
706 				{
707 					itemSize = dataLen / count;
708 				}
709 				unsigned char* dataPtr = databuffer;
710 				for (uint32 i = 0; i < count; ++i)
711 				{
712 					// Line up for the next item
713 					if (i)
714 					{
715 						if (flags & MSG_FLAG_FIXED_SIZE)
716 						{
717 							dataPtr += itemSize;
718 						}
719 						else
720 						{
721 							// Have to account for 8-byte boundary padding
722 							// We add 4 because padding as calculated during
723 							// flattening includes the four-byte size header
724 							dataPtr += itemSize + calc_padding(itemSize + 4, 8);
725 						}
726 					}
727 
728 					if ((flags & MSG_FLAG_FIXED_SIZE) == 0)
729 					{
730 						itemSize = *(uint32*)dataPtr;
731 						dataPtr += sizeof (uint32);
732 					}
733 
734 					err = AddData(name, type, dataPtr, itemSize,
735 								  flags & MSG_FLAG_FIXED_SIZE);
736 					if (err)
737 						throw err;
738 				}
739 
740 				reader(flags);
741 			}
742 		}
743 		catch (status_t& e)
744 		{
745 			err = e;
746 		}
747 	}
748 
749 	return err;
750 }
751 //------------------------------------------------------------------------------
752 status_t BMessage::AddSpecifier(const char* property)
753 {
754 	BMessage message(B_DIRECT_SPECIFIER);
755 	status_t err = message.AddString(B_PROPERTY_ENTRY, property);
756 	if (err)
757 		return err;
758 
759 	return AddSpecifier(&message);
760 }
761 //------------------------------------------------------------------------------
762 status_t BMessage::AddSpecifier(const char* property, int32 index)
763 {
764 	BMessage message(B_INDEX_SPECIFIER);
765 	status_t err = message.AddString(B_PROPERTY_ENTRY, property);
766 	if (err)
767 		return err;
768 
769 	err = message.AddInt32("index", index);
770 	if (err)
771 		return err;
772 
773 	return AddSpecifier(&message);
774 }
775 //------------------------------------------------------------------------------
776 status_t BMessage::AddSpecifier(const char* property, int32 index, int32 range)
777 {
778 	if (range < 0)
779 		return B_BAD_VALUE;
780 
781 	BMessage message(B_RANGE_SPECIFIER);
782 	status_t err = message.AddString(B_PROPERTY_ENTRY, property);
783 	if (err)
784 		return err;
785 
786 	err = message.AddInt32("index", index);
787 	if (err)
788 		return err;
789 
790 	err = message.AddInt32("range", range);
791 	if (err)
792 		return err;
793 
794 	return AddSpecifier(&message);
795 }
796 //------------------------------------------------------------------------------
797 status_t BMessage::AddSpecifier(const char* property, const char* name)
798 {
799 	BMessage message(B_NAME_SPECIFIER);
800 	status_t err = message.AddString(B_PROPERTY_ENTRY, property);
801 	if (err)
802 		return err;
803 
804 	err = message.AddString(B_PROPERTY_NAME_ENTRY, name);
805 	if (err)
806 		return err;
807 
808 	return AddSpecifier(&message);
809 }
810 //------------------------------------------------------------------------------
811 status_t BMessage::AddSpecifier(const BMessage* specifier)
812 {
813 	status_t err = AddMessage(B_SPECIFIER_ENTRY, specifier);
814 	if (!err)
815 	{
816 		++fCurSpecifier;
817 		fHasSpecifiers = true;
818 	}
819 	return err;
820 }
821 //------------------------------------------------------------------------------
822 status_t BMessage::SetCurrentSpecifier(int32 index)
823 {
824 	type_code	type;
825 	int32		count;
826 	status_t	err = GetInfo(B_SPECIFIER_ENTRY, &type, &count);
827 	if (err)
828 		return err;
829 
830 	if (index < 0 || index >= count)
831 		return B_BAD_INDEX;
832 
833 	fCurSpecifier = index;
834 
835 	return B_OK;
836 }
837 //------------------------------------------------------------------------------
838 status_t BMessage::GetCurrentSpecifier(int32* index, BMessage* specifier,
839 									   int32* what, const char** property) const
840 {
841 	if (fCurSpecifier == -1 || !WasDelivered())
842 		return B_BAD_SCRIPT_SYNTAX;
843 
844 	if (index)
845 		*index = fCurSpecifier;
846 
847 	if (specifier)
848 	{
849 		if (FindMessage(B_SPECIFIER_ENTRY, fCurSpecifier, specifier))
850 			return B_BAD_SCRIPT_SYNTAX;
851 
852 		if (what)
853 			*what = specifier->what;
854 
855 		if (property)
856 		{
857 			if (specifier->FindString(B_PROPERTY_ENTRY, property))
858 				return B_BAD_SCRIPT_SYNTAX;
859 		}
860 	}
861 
862 	return B_OK;
863 }
864 //------------------------------------------------------------------------------
865 bool BMessage::HasSpecifiers() const
866 {
867 	return fHasSpecifiers;
868 }
869 //------------------------------------------------------------------------------
870 status_t BMessage::PopSpecifier()
871 {
872 	if (fCurSpecifier < 0 || !WasDelivered())
873 	{
874 		return B_BAD_VALUE;
875 	}
876 
877 	--fCurSpecifier;
878 	return B_OK;
879 }
880 //------------------------------------------------------------------------------
881 //	return fBody->AddData<TYPE>(name, val, TYPESPEC);
882 //	return fBody->FindData<TYPE>(name, index, val, TYPESPEC);
883 //	return fBody->ReplaceData<TYPE>(name, index, val, TYPESPEC);
884 //	return fBody->HasData(name, TYPESPEC, n);
885 
886 #define DEFINE_FUNCTIONS(TYPE, fnName, TYPESPEC)									\
887 	status_t BMessage::Add ## fnName(const char* name, TYPE val)					\
888 	{ return fBody->AddData<TYPE>(name, val, TYPESPEC); }							\
889 	status_t BMessage::Find ## fnName(const char* name, TYPE* p) const				\
890 	{ return Find ## fnName(name, 0, p); }											\
891 	status_t BMessage::Find ## fnName(const char* name, int32 index, TYPE* p) const	\
892 	{																				\
893 		*p = TYPE();																\
894 		return fBody->FindData<TYPE>(name, index, p, TYPESPEC);						\
895 	}																				\
896 	status_t BMessage::Replace ## fnName(const char* name, TYPE val)				\
897 	{ return Replace ## fnName(name, 0, val); }										\
898 	status_t BMessage::Replace ## fnName(const char *name, int32 index, TYPE val)	\
899 	{  return fBody->ReplaceData<TYPE>(name, index, val, TYPESPEC); }				\
900 	bool BMessage::Has ## fnName(const char* name, int32 n) const					\
901 	{ return fBody->HasData(name, TYPESPEC, n); }
902 
903 DEFINE_FUNCTIONS(int8  , Int8  , B_INT8_TYPE)
904 DEFINE_FUNCTIONS(int16 , Int16 , B_INT16_TYPE)
905 DEFINE_FUNCTIONS(int32 , Int32 , B_INT32_TYPE)
906 DEFINE_FUNCTIONS(int64 , Int64 , B_INT64_TYPE)
907 DEFINE_FUNCTIONS(BPoint, Point , B_POINT_TYPE)
908 DEFINE_FUNCTIONS(BRect , Rect  , B_RECT_TYPE)
909 DEFINE_FUNCTIONS(float , Float , B_FLOAT_TYPE)
910 DEFINE_FUNCTIONS(double, Double, B_DOUBLE_TYPE)
911 DEFINE_FUNCTIONS(bool  , Bool  , B_BOOL_TYPE)
912 
913 #undef DEFINE_FUNCTIONS
914 
915 
916 #define DEFINE_HAS_FUNCTION(fnName, TYPESPEC)						\
917 	bool BMessage::Has ## fnName(const char* name, int32 n) const	\
918 	{ return HasData(name, TYPESPEC, n); }
919 
920 DEFINE_HAS_FUNCTION(Message  , B_MESSAGE_TYPE)
921 DEFINE_HAS_FUNCTION(String   , B_STRING_TYPE)
922 DEFINE_HAS_FUNCTION(Pointer  , B_POINTER_TYPE)
923 DEFINE_HAS_FUNCTION(Messenger, B_MESSENGER_TYPE)
924 DEFINE_HAS_FUNCTION(Ref      , B_REF_TYPE)
925 
926 #undef DEFINE_HAS_FUNCTION
927 
928 #define DEFINE_LAZY_FIND_FUNCTION(TYPE, fnName)						\
929 	TYPE BMessage::Find ## fnName(const char* name, int32 n) const	\
930 	{																\
931 		TYPE i = 0;													\
932 		Find ## fnName(name, n, &i);								\
933 		return i;													\
934 	}
935 
936 DEFINE_LAZY_FIND_FUNCTION(int8			, Int8)
937 DEFINE_LAZY_FIND_FUNCTION(int16			, Int16)
938 DEFINE_LAZY_FIND_FUNCTION(int32			, Int32)
939 DEFINE_LAZY_FIND_FUNCTION(int64			, Int64)
940 DEFINE_LAZY_FIND_FUNCTION(float			, Float)
941 DEFINE_LAZY_FIND_FUNCTION(double		, Double)
942 DEFINE_LAZY_FIND_FUNCTION(bool			, Bool)
943 DEFINE_LAZY_FIND_FUNCTION(const char*	, String)
944 
945 #undef DEFINE_LAZY_FIND_FUNCTION
946 
947 //------------------------------------------------------------------------------
948 status_t BMessage::AddString(const char* name, const char* a_string)
949 {
950 	return fBody->AddData<BString>(name, a_string, B_STRING_TYPE);
951 }
952 //------------------------------------------------------------------------------
953 status_t BMessage::AddString(const char* name, const BString& a_string)
954 {
955 	return AddString(name, a_string.String());
956 }
957 //------------------------------------------------------------------------------
958 status_t BMessage::AddPointer(const char* name, const void* ptr)
959 {
960 	return fBody->AddData<void*>(name, (void*)ptr, B_POINTER_TYPE);
961 }
962 //------------------------------------------------------------------------------
963 status_t BMessage::AddMessenger(const char* name, BMessenger messenger)
964 {
965 	return fBody->AddData<BMessenger>(name, messenger, B_MESSENGER_TYPE);
966 }
967 //------------------------------------------------------------------------------
968 status_t BMessage::AddRef(const char* name, const entry_ref* ref)
969 {
970 	char* buffer = new(nothrow) char[sizeof (entry_ref) + B_PATH_NAME_LENGTH];
971 	size_t size;
972 	status_t err = entry_ref_flatten(buffer, &size, ref);
973 	if (!err)
974 	{
975 		BDataBuffer DB((void*)buffer, size);
976 		err = fBody->AddData<BDataBuffer>(name, DB, B_REF_TYPE);
977 	}
978 
979 	return err;
980 }
981 //------------------------------------------------------------------------------
982 status_t BMessage::AddMessage(const char* name, const BMessage* msg)
983 {
984 	status_t err = B_OK;
985 	ssize_t size = msg->FlattenedSize();
986 	char* buffer = new(nothrow) char[size];
987 	if (buffer)
988 	{
989 		err = msg->Flatten(buffer, size);
990 		if (!err)
991 		{
992 			BDataBuffer DB((void*)buffer, size);
993 			err = fBody->AddData<BDataBuffer>(name, DB, B_MESSAGE_TYPE);
994 		}
995 	}
996 	else
997 	{
998 		err = B_NO_MEMORY;
999 	}
1000 
1001 	return err;
1002 }
1003 //------------------------------------------------------------------------------
1004 status_t BMessage::AddFlat(const char* name, BFlattenable* obj, int32 count)
1005 {
1006 	status_t err = B_OK;
1007 	ssize_t size = obj->FlattenedSize();
1008 	char* buffer = new(nothrow) char[size];
1009 	if (buffer)
1010 	{
1011 		err = obj->Flatten((void*)buffer, size);
1012 		if (!err)
1013 		{
1014 			err = AddData(name, obj->TypeCode(), (void*)buffer, size,
1015 						  obj->IsFixedSize(), count);
1016 		}
1017 		delete[] buffer;
1018 	}
1019 	else
1020 	{
1021 		err = B_NO_MEMORY;
1022 	}
1023 
1024 	return err;
1025 }
1026 //------------------------------------------------------------------------------
1027 status_t BMessage::AddData(const char* name, type_code type, const void* data,
1028 						   ssize_t numBytes, bool is_fixed_size, int32 /*count*/)
1029 {
1030 /**
1031 	@note	Because we're using vectors for our item storage, the count param
1032 			is no longer useful to us:  dynamically adding more items is not
1033 			really a performance issue, so pre-allocating space for objects
1034 			gives us no real advantage.
1035  */
1036 
1037 	// TODO: test
1038 	// In particular, we want to see what happens if is_fixed_size == true and
1039 	// the user attempts to add something bigger or smaller.  We may need to
1040 	// enforce the size thing.
1041 	//--------------------------------------------------------------------------
1042 	// voidref suggests creating a BDataBuffer type which we can use here to
1043 	// avoid having to specialize BMessageBody::AddData().
1044 	//--------------------------------------------------------------------------
1045 
1046 	// TODO: Fix this horrible hack
1047 	status_t err = B_OK;
1048 	switch (type)
1049 	{
1050 		case B_BOOL_TYPE:
1051 			err = AddBool(name, *(bool*)data);
1052 			break;
1053 		case B_INT8_TYPE:
1054 		case B_UINT8_TYPE:
1055 			err = AddInt8(name, *(int8*)data);
1056 			break;
1057 		case B_INT16_TYPE:
1058 		case B_UINT16_TYPE:
1059 			err = AddInt16(name, *(int16*)data);
1060 			break;
1061 		case B_INT32_TYPE:
1062 		case B_UINT32_TYPE:
1063 			err = AddInt32(name, *(int32*)data);
1064 			break;
1065 		case B_INT64_TYPE:
1066 		case B_UINT64_TYPE:
1067 			err = AddInt64(name, *(int64*)data);
1068 			break;
1069 		case B_FLOAT_TYPE:
1070 			err = AddFloat(name, *(float*)data);
1071 			break;
1072 		case B_DOUBLE_TYPE:
1073 			err = AddDouble(name, *(double*)data);
1074 			break;
1075 		case B_POINT_TYPE:
1076 			err = AddPoint(name, *(BPoint*)data);
1077 			break;
1078 		case B_RECT_TYPE:
1079 			err = AddRect(name, *(BRect*)data);
1080 			break;
1081 		case B_REF_TYPE:
1082 		{
1083 			BDataBuffer DB((void*)data, numBytes, true);
1084 			err = fBody->AddData<BDataBuffer>(name, DB, type);
1085 			break;
1086 		}
1087 		case B_MESSAGE_TYPE:
1088 		{
1089 			BDataBuffer DB((void*)data, numBytes, true);
1090 			err = fBody->AddData<BDataBuffer>(name, DB, type);
1091 			break;
1092 		}
1093 		case B_MESSENGER_TYPE:
1094 			err = AddMessenger(name, *(BMessenger*)data);
1095 			break;
1096 		case B_POINTER_TYPE:
1097 			err = AddPointer(name, *(void**)data);
1098 			break;
1099 		case B_STRING_TYPE:
1100 			err = AddString(name, (const char*)data);
1101 			break;
1102 		default:
1103 			// TODO: test
1104 			// Using the mythical BDataBuffer
1105 			BDataBuffer DB((void*)data, numBytes, true);
1106 			err = fBody->AddData<BDataBuffer>(name, DB, type);
1107 			break;
1108 	}
1109 
1110 	return err;
1111 }
1112 //------------------------------------------------------------------------------
1113 status_t BMessage::RemoveData(const char* name, int32 index)
1114 {
1115 	return fReadOnly ? B_ERROR : fBody->RemoveData(name, index);
1116 }
1117 //------------------------------------------------------------------------------
1118 status_t BMessage::RemoveName(const char* name)
1119 {
1120 	return fReadOnly ? B_ERROR : fBody->RemoveName(name);
1121 }
1122 //------------------------------------------------------------------------------
1123 status_t BMessage::MakeEmpty()
1124 {
1125 	return fReadOnly ? B_ERROR : fBody->MakeEmpty();
1126 }
1127 //------------------------------------------------------------------------------
1128 status_t BMessage::FindString(const char* name, const char** str) const
1129 {
1130 	return FindString(name, 0, str);
1131 }
1132 //------------------------------------------------------------------------------
1133 status_t BMessage::FindString(const char* name, int32 index,
1134 							  const char** str) const
1135 {
1136 	ssize_t bytes;
1137 	return FindData(name, B_STRING_TYPE, index,
1138 					(const void**)str, &bytes);
1139 }
1140 //------------------------------------------------------------------------------
1141 status_t BMessage::FindString(const char* name, BString* str) const
1142 {
1143 	return FindString(name, 0, str);
1144 }
1145 //------------------------------------------------------------------------------
1146 status_t BMessage::FindString(const char* name, int32 index, BString* str) const
1147 {
1148 	const char* cstr;
1149 	status_t err = FindString(name, index, &cstr);
1150 	if (!err)
1151 	{
1152 		*str = cstr;
1153 	}
1154 
1155 	return err;
1156 }
1157 //------------------------------------------------------------------------------
1158 status_t BMessage::FindPointer(const char* name, void** ptr) const
1159 {
1160 	return FindPointer(name, 0, ptr);
1161 }
1162 //------------------------------------------------------------------------------
1163 status_t BMessage::FindPointer(const char* name, int32 index, void** ptr) const
1164 {
1165 	*ptr = NULL;
1166 	return fBody->FindData<void*>(name, index, ptr, B_POINTER_TYPE);
1167 }
1168 //------------------------------------------------------------------------------
1169 status_t BMessage::FindMessenger(const char* name, BMessenger* m) const
1170 {
1171 	return FindMessenger(name, 0, m);
1172 }
1173 //------------------------------------------------------------------------------
1174 status_t BMessage::FindMessenger(const char* name, int32 index, BMessenger* m) const
1175 {
1176 	return fBody->FindData<BMessenger>(name, index, m, B_MESSENGER_TYPE);
1177 }
1178 //------------------------------------------------------------------------------
1179 status_t BMessage::FindRef(const char* name, entry_ref* ref) const
1180 {
1181 	return FindRef(name, 0, ref);
1182 }
1183 //------------------------------------------------------------------------------
1184 status_t BMessage::FindRef(const char* name, int32 index, entry_ref* ref) const
1185 {
1186 	void* data = NULL;
1187 	ssize_t size = 0;
1188 	status_t err = FindData(name, B_REF_TYPE, index, (const void**)&data, &size);
1189 	if (!err)
1190 	{
1191 		err = entry_ref_unflatten(ref, (char*)data, size);
1192 	}
1193 
1194 	return err;
1195 }
1196 //------------------------------------------------------------------------------
1197 status_t BMessage::FindMessage(const char* name, BMessage* msg) const
1198 {
1199 	return FindMessage(name, 0, msg);
1200 }
1201 //------------------------------------------------------------------------------
1202 status_t BMessage::FindMessage(const char* name, int32 index, BMessage* msg) const
1203 {
1204 	void* data = NULL;
1205 	ssize_t size = 0;
1206 	status_t err = FindData(name, B_MESSAGE_TYPE, index,
1207 							(const void**)&data, &size);
1208 	if (!err)
1209 	{
1210 		err = msg->Unflatten((const char*)data);
1211 	}
1212 
1213 	return err;
1214 }
1215 //------------------------------------------------------------------------------
1216 status_t BMessage::FindFlat(const char* name, BFlattenable* obj) const
1217 {
1218 	return FindFlat(name, 0, obj);
1219 }
1220 //------------------------------------------------------------------------------
1221 status_t BMessage::FindFlat(const char* name, int32 index,
1222 							BFlattenable* obj) const
1223 {
1224 	const void* data;
1225 	ssize_t numBytes;
1226 	status_t err = FindData(name, obj->TypeCode(), index, &data, &numBytes);
1227 	if (!err)
1228 	{
1229 		err = obj->Unflatten(obj->TypeCode(), data, numBytes);
1230 	}
1231 
1232 	return err;
1233 }
1234 //------------------------------------------------------------------------------
1235 status_t BMessage::FindData(const char* name, type_code type, const void** data,
1236 							ssize_t* numBytes) const
1237 {
1238 	return FindData(name, type, 0, data, numBytes);
1239 }
1240 //------------------------------------------------------------------------------
1241 status_t BMessage::FindData(const char* name, type_code type, int32 index,
1242 							const void** data, ssize_t* numBytes) const
1243 {
1244 	status_t err = B_OK;
1245 	// Oh, the humanity!
1246 	err = fBody->FindData(name, type, index, data, numBytes);
1247 
1248 	return err;
1249 }
1250 //------------------------------------------------------------------------------
1251 status_t BMessage::ReplaceString(const char* name, const char* string)
1252 {
1253 	return ReplaceString(name, 0, string);
1254 }
1255 //------------------------------------------------------------------------------
1256 status_t BMessage::ReplaceString(const char* name, int32 index,
1257 								 const char* string)
1258 {
1259 	return fBody->ReplaceData<BString>(name, index, string, B_STRING_TYPE);
1260 }
1261 //------------------------------------------------------------------------------
1262 status_t BMessage::ReplaceString(const char* name, const BString& string)
1263 {
1264 	return ReplaceString(name, 0, string);
1265 }
1266 //------------------------------------------------------------------------------
1267 status_t BMessage::ReplaceString(const char* name, int32 index, const BString& string)
1268 {
1269 	return fBody->ReplaceData<BString>(name, index, string, B_STRING_TYPE);
1270 }
1271 //------------------------------------------------------------------------------
1272 status_t BMessage::ReplacePointer(const char* name, const void* ptr)
1273 {
1274 	return ReplacePointer(name, 0, ptr);
1275 }
1276 //------------------------------------------------------------------------------
1277 status_t BMessage::ReplacePointer(const char* name, int32 index,
1278 								  const void* ptr)
1279 {
1280 	return fBody->ReplaceData<void*>(name, index, (void*)ptr, B_POINTER_TYPE);
1281 }
1282 //------------------------------------------------------------------------------
1283 status_t BMessage::ReplaceMessenger(const char* name, BMessenger messenger)
1284 {
1285 	// Don't want to copy the BMessenger
1286 	return fBody->ReplaceData<BMessenger>(name, 0, messenger, B_MESSENGER_TYPE);
1287 }
1288 //------------------------------------------------------------------------------
1289 status_t BMessage::ReplaceMessenger(const char* name, int32 index,
1290 									BMessenger msngr)
1291 {
1292 	return fBody->ReplaceData<BMessenger>(name, index, msngr, B_MESSENGER_TYPE);
1293 }
1294 //------------------------------------------------------------------------------
1295 status_t BMessage::ReplaceRef(const char* name, const entry_ref* ref)
1296 {
1297 	return ReplaceRef(name, 0, ref);
1298 }
1299 //------------------------------------------------------------------------------
1300 status_t BMessage::ReplaceRef(const char* name, int32 index, const entry_ref* ref)
1301 {
1302 	// TODO: test
1303 	// Use voidref's theoretical BDataBuffer
1304 	char* buffer = new(nothrow) char[sizeof (entry_ref) + B_PATH_NAME_LENGTH];
1305 	size_t size;
1306 	status_t err = entry_ref_flatten(buffer, &size, ref);
1307 	if (!err)
1308 	{
1309 		BDataBuffer DB((void*)buffer, size);
1310 		err = fBody->ReplaceData<BDataBuffer>(name, index, DB, B_REF_TYPE);
1311 	}
1312 
1313 	return err;
1314 }
1315 //------------------------------------------------------------------------------
1316 status_t BMessage::ReplaceMessage(const char* name, const BMessage* msg)
1317 {
1318 	return ReplaceMessage(name, 0, msg);
1319 }
1320 //------------------------------------------------------------------------------
1321 status_t BMessage::ReplaceMessage(const char* name, int32 index,
1322 								  const BMessage* msg)
1323 {
1324 	status_t err = B_OK;
1325 	ssize_t size = msg->FlattenedSize();
1326 	char* buffer = new(nothrow) char[size];
1327 	if (buffer)
1328 	{
1329 		err = msg->Flatten(buffer, size);
1330 		if (!err)
1331 		{
1332 			BDataBuffer DB((void*)buffer, size);
1333 			err = fBody->ReplaceData<BDataBuffer>(name, index, DB,
1334 												  B_MESSAGE_TYPE);
1335 		}
1336 	}
1337 	else
1338 	{
1339 		err = B_NO_MEMORY;
1340 	}
1341 
1342 	return err;
1343 }
1344 //------------------------------------------------------------------------------
1345 status_t BMessage::ReplaceFlat(const char* name, BFlattenable* obj)
1346 {
1347 	return ReplaceFlat(name, 0, obj);
1348 }
1349 //------------------------------------------------------------------------------
1350 status_t BMessage::ReplaceFlat(const char* name, int32 index, BFlattenable* obj)
1351 {
1352 	// TODO: test
1353 	status_t err = B_OK;
1354 	ssize_t size = obj->FlattenedSize();
1355 	char* buffer = new(nothrow) char[size];
1356 	if (buffer)
1357 	{
1358 		err = obj->Flatten(buffer, size);
1359 		if (!err)
1360 		{
1361 			err = ReplaceData(name, obj->TypeCode(), index, (void*)buffer, size);
1362 		}
1363 		delete[] buffer;
1364 	}
1365 
1366 	return err;
1367 }
1368 //------------------------------------------------------------------------------
1369 status_t BMessage::ReplaceData(const char* name, type_code type,
1370 							   const void* data, ssize_t data_size)
1371 {
1372 	return ReplaceData(name, type, 0, data, data_size);
1373 }
1374 //------------------------------------------------------------------------------
1375 status_t BMessage::ReplaceData(const char* name, type_code type, int32 index,
1376 							   const void* data, ssize_t data_size)
1377 {
1378 	// TODO: Fix this horrible hack
1379 	status_t err = B_OK;
1380 	switch (type)
1381 	{
1382 		case B_BOOL_TYPE:
1383 			err = ReplaceBool(name, index, *(bool*)data);
1384 			break;
1385 		case B_INT8_TYPE:
1386 		case B_UINT8_TYPE:
1387 			err = ReplaceInt8(name, index, *(int8*)data);
1388 			break;
1389 		case B_INT16_TYPE:
1390 		case B_UINT16_TYPE:
1391 			err = ReplaceInt16(name, index, *(int16*)data);
1392 			break;
1393 		case B_INT32_TYPE:
1394 		case B_UINT32_TYPE:
1395 			err = ReplaceInt32(name, index, *(int32*)data);
1396 			break;
1397 		case B_INT64_TYPE:
1398 		case B_UINT64_TYPE:
1399 			err = ReplaceInt64(name, index, *(int64*)data);
1400 			break;
1401 		case B_FLOAT_TYPE:
1402 			err = ReplaceFloat(name, index, *(float*)data);
1403 			break;
1404 		case B_DOUBLE_TYPE:
1405 			err = ReplaceDouble(name, index, *(double*)data);
1406 			break;
1407 		case B_POINT_TYPE:
1408 			err = ReplacePoint(name, index, *(BPoint*)data);
1409 			break;
1410 		case B_RECT_TYPE:
1411 			err = ReplaceRect(name, index, *(BRect*)data);
1412 			break;
1413 		case B_REF_TYPE:
1414 			err = ReplaceRef(name, index, (entry_ref*)data);
1415 			break;
1416 		case B_MESSAGE_TYPE:
1417 			err = ReplaceMessage(name, index, (BMessage*)data);
1418 			break;
1419 		case B_MESSENGER_TYPE:
1420 			err = ReplaceMessenger(name, index, *(BMessenger*)data);
1421 			break;
1422 		case B_POINTER_TYPE:
1423 			err = ReplacePointer(name, index, (void**)data);
1424 			break;
1425 		default:
1426 			// TODO: test
1427 			// Using the mythical BDataBuffer
1428 			BDataBuffer DB((void*)data, data_size, true);
1429 			err = fBody->ReplaceData<BDataBuffer>(name, index, DB, type);
1430 			break;
1431 	}
1432 
1433 	return err;
1434 }
1435 //------------------------------------------------------------------------------
1436 void* BMessage::operator new(size_t size)
1437 {
1438 	if (!sMsgCache)
1439 	{
1440 		sMsgCache = new BBlockCache(10, size, B_OBJECT_CACHE);
1441 	}
1442 	return sMsgCache->Get(size);
1443 }
1444 //------------------------------------------------------------------------------
1445 void* BMessage::operator new(size_t, void* p)
1446 {
1447 	return p;
1448 }
1449 //------------------------------------------------------------------------------
1450 void BMessage::operator delete(void* ptr, size_t size)
1451 {
1452 	sMsgCache->Save(ptr, size);
1453 }
1454 //------------------------------------------------------------------------------
1455 bool BMessage::HasFlat(const char* name, const BFlattenable* flat) const
1456 {
1457 	return HasFlat(name, 0, flat);
1458 }
1459 //------------------------------------------------------------------------------
1460 bool BMessage::HasFlat(const char* name, int32 n, const BFlattenable* flat) const
1461 {
1462 	return fBody->HasData(name, flat->TypeCode(), n);
1463 }
1464 //------------------------------------------------------------------------------
1465 bool BMessage::HasData(const char* name, type_code t, int32 n) const
1466 {
1467 	return fBody->HasData(name, t, n);
1468 }
1469 //------------------------------------------------------------------------------
1470 BRect BMessage::FindRect(const char* name, int32 n) const
1471 {
1472 	BRect r(0, 0, -1, -1);
1473 	FindRect(name, n, &r);
1474 	return r;
1475 }
1476 //------------------------------------------------------------------------------
1477 BPoint BMessage::FindPoint(const char* name, int32 n) const
1478 {
1479 	BPoint p(0, 0);
1480 	FindPoint(name, n, &p);
1481 	return p;
1482 }
1483 //------------------------------------------------------------------------------
1484 status_t BMessage::flatten_hdr(BDataIO* stream) const
1485 {
1486 	status_t err = B_OK;
1487 	int32 data = MSG_FIELD_VERSION;
1488 
1489 	// Write the version of the binary data format
1490 	write_helper(stream, (const void*)&data, sizeof (data), err);
1491 	if (!err)
1492 	{
1493 		// faked up checksum; we'll fix it up later
1494 		write_helper(stream, (const void*)&data, sizeof (data), err);
1495 	}
1496 	if (!err)
1497 	{
1498 		// Write the flattened size of the entire message
1499 		data = fBody->FlattenedSize() + calc_hdr_size(0);
1500 		write_helper(stream, (const void*)&data, sizeof (data), err);
1501 	}
1502 	if (!err)
1503 	{
1504 		// Write the 'what' member
1505 		write_helper(stream, (const void*)&what, sizeof (what), err);
1506 	}
1507 
1508 	uint8 flags = 0;
1509 #ifdef B_HOST_IS_BENDIAN
1510 	flags |= MSG_FLAG_BIG_ENDIAN;
1511 #endif
1512 	if (HasSpecifiers())
1513 	{
1514 		flags |= MSG_FLAG_SCRIPT_MSG;
1515 	}
1516 
1517 	if (fTarget != B_NULL_TOKEN)
1518 	{
1519 		flags |= MSG_FLAG_INCL_TARGET;
1520 	}
1521 
1522 	if (fReplyTo.port >= 0 &&
1523 		fReplyTo.target != B_NULL_TOKEN &&
1524 		fReplyTo.team >= 0)
1525 	{
1526 		flags |= MSG_FLAG_INCL_REPLY;
1527 	}
1528 
1529 	if (!err)
1530 	{
1531 		// Write the header flags
1532 		write_helper(stream, (const void*)&flags, sizeof (flags), err);
1533 	}
1534 
1535 	// Write targeting info if necessary
1536 	if (!err && (flags & MSG_FLAG_INCL_TARGET))
1537 	{
1538 		data = fPreferred ? B_PREFERRED_TOKEN : fTarget;
1539 		write_helper(stream, (const void*)&data, sizeof (data), err);
1540 	}
1541 
1542 	// Write reply info if necessary
1543 	if (!err && (flags & MSG_FLAG_INCL_REPLY))
1544 	{
1545 		write_helper(stream, (const void*)&fReplyTo.port,
1546 					 sizeof (fReplyTo.port), err);
1547 		if (!err)
1548 		{
1549 			write_helper(stream, (const void*)&fReplyTo.target,
1550 						 sizeof (fReplyTo.target), err);
1551 		}
1552 		if (!err)
1553 		{
1554 			write_helper(stream, (const void*)&fReplyTo.team,
1555 						 sizeof (fReplyTo.team), err);
1556 		}
1557 
1558 		uint8 bigFlags;
1559 		if (!err)
1560 		{
1561 			bigFlags = fPreferred ? 1 : 0;
1562 			write_helper(stream, (const void*)&bigFlags,
1563 						 sizeof (bigFlags), err);
1564 		}
1565 		if (!err)
1566 		{
1567 			bigFlags = fReplyRequired ? 1 : 0;
1568 			write_helper(stream, (const void*)&bigFlags,
1569 						 sizeof (bigFlags), err);
1570 		}
1571 		if (!err)
1572 		{
1573 			bigFlags = fReplyDone ? 1 : 0;
1574 			write_helper(stream, (const void*)&bigFlags,
1575 						 sizeof (bigFlags), err);
1576 		}
1577 		if (!err)
1578 		{
1579 			bigFlags = fIsReply ? 1 : 0;
1580 			write_helper(stream, (const void*)&bigFlags,
1581 						 sizeof (bigFlags), err);
1582 		}
1583 	}
1584 
1585 	return err;
1586 }
1587 //------------------------------------------------------------------------------
1588 status_t BMessage::unflatten_hdr(BDataIO* stream, bool& swap)
1589 {
1590 	status_t err = B_OK;
1591 	int32 data;
1592 	int32 checksum;
1593 	uchar csBuffer[MSG_HEADER_MAX_SIZE];
1594 
1595 	TReadHelper read_helper(stream);
1596 	TChecksumHelper checksum_helper(csBuffer);
1597 
1598 	try {
1599 
1600 	// Get the message version
1601 	read_helper(data);
1602 	if (data == '1BOF')
1603 	{
1604 		swap = true;
1605 	}
1606 	else if (data == 'FOB1')
1607 	{
1608 		swap = false;
1609 	}
1610 	else
1611 	{
1612 		// This is *not* a message
1613 		return B_NOT_A_MESSAGE;
1614 	}
1615 
1616 	// Make way for the new data
1617 	MakeEmpty();
1618 
1619 	read_helper.SetSwap(swap);
1620 
1621 	// get the checksum
1622 	read_helper(checksum);
1623 	// get the size
1624 	read_helper(data);
1625 	checksum_helper.Cache(data);
1626 	// Get the what
1627 	read_helper(what);
1628 	checksum_helper.Cache(what);
1629 	// Get the flags
1630 	uint8 flags = 0;
1631 	read_helper(flags);
1632 	checksum_helper.Cache(flags);
1633 
1634 	fHasSpecifiers = flags & MSG_FLAG_SCRIPT_MSG;
1635 
1636 	if (flags & MSG_FLAG_BIG_ENDIAN)
1637 	{
1638 		// TODO: ???
1639 		// Isn't this already indicated by the byte order of the message version?
1640 	}
1641 	if (flags & MSG_FLAG_INCL_TARGET)
1642 	{
1643 		// Get the target data
1644 		read_helper(data);
1645 		checksum_helper.Cache(data);
1646 		fTarget = data;
1647 	}
1648 	if (flags & MSG_FLAG_INCL_REPLY)
1649 	{
1650 		// Get the reply port
1651 		read_helper(fReplyTo.port);
1652 		read_helper(fReplyTo.target);
1653 		read_helper(fReplyTo.team);
1654 		checksum_helper.Cache(fReplyTo.port);
1655 		checksum_helper.Cache(fReplyTo.target);
1656 		checksum_helper.Cache(fReplyTo.team);
1657 
1658 		fWasDelivered = true;
1659 
1660 		// Get the "big flags"
1661 		uint8 bigFlags;
1662 		// Get the preferred flag
1663 		read_helper(bigFlags);
1664 		checksum_helper.Cache(bigFlags);
1665 		fPreferred = bigFlags;
1666 		if (fPreferred)
1667 		{
1668 			fTarget = B_PREFERRED_TOKEN;
1669 		}
1670 		// Get the reply requirement flag
1671 		read_helper(bigFlags);
1672 		checksum_helper.Cache(bigFlags);
1673 		fReplyRequired = bigFlags;
1674 		// Get the reply done flag
1675 		read_helper(bigFlags);
1676 		checksum_helper.Cache(bigFlags);
1677 		fReplyDone = bigFlags;
1678 		// Get the "is reply" flag
1679 		read_helper(bigFlags);
1680 		checksum_helper.Cache(bigFlags);
1681 		fIsReply = bigFlags;
1682 	}
1683 	}
1684 	catch (status_t& e)
1685 	{
1686 		err = e;
1687 	}
1688 
1689 	if (checksum != checksum_helper.CheckSum())
1690 		err = B_NOT_A_MESSAGE;
1691 
1692 	return err;
1693 }
1694 //------------------------------------------------------------------------------
1695 status_t BMessage::real_flatten(char* result, ssize_t size) const
1696 {
1697 	BMemoryIO stream((void*)result, size);
1698 	status_t err = real_flatten(&stream);
1699 
1700 	if (!err)
1701 	{
1702 		// Fixup the checksum; it is calculated on data size, what, flags,
1703 		// and target info (including big flags if appropriate)
1704 		((uint32*)result)[1] = _checksum_((uchar*)result + (sizeof (uint32) * 2),
1705 										  calc_hdr_size(0) - (sizeof (uint32) * 2));
1706 	}
1707 
1708 	return err;
1709 }
1710 //------------------------------------------------------------------------------
1711 status_t BMessage::real_flatten(BDataIO* stream) const
1712 {
1713 	status_t err = flatten_hdr(stream);
1714 
1715 	if (!err)
1716 	{
1717 		err = fBody->Flatten(stream);
1718 	}
1719 
1720 	return err;
1721 }
1722 //------------------------------------------------------------------------------
1723 char* BMessage::stack_flatten(char* stack_ptr, ssize_t stack_size,
1724 							  bool /*incl_reply*/, ssize_t* size) const
1725 {
1726 	const ssize_t calcd_size = calc_hdr_size(0) + fBody->FlattenedSize();
1727 	char* new_ptr = NULL;
1728 	if (calcd_size > stack_size)
1729 	{
1730 		stack_ptr = new char[calcd_size];
1731 		new_ptr = stack_ptr;
1732 	}
1733 	real_flatten(stack_ptr, calcd_size);
1734 	if (size)
1735 	{
1736 		*size = calcd_size;
1737 	}
1738 	return new_ptr;
1739 }
1740 //------------------------------------------------------------------------------
1741 ssize_t BMessage::calc_hdr_size(uchar flags) const
1742 {
1743 	ssize_t size = min_hdr_size();
1744 
1745 	if (fTarget != B_NULL_TOKEN)
1746 	{
1747 		size += sizeof (fTarget);
1748 	}
1749 
1750 	if (fReplyTo.port >= 0 &&
1751 		fReplyTo.target != B_NULL_TOKEN &&
1752 		fReplyTo.team >= 0)
1753 	{
1754 		size += sizeof (fReplyTo.port);
1755 		size += sizeof (fReplyTo.target);
1756 		size += sizeof (fReplyTo.team);
1757 
1758 		size += 4;	// For the "big" flags
1759 	}
1760 
1761 	return size;
1762 }
1763 //------------------------------------------------------------------------------
1764 ssize_t BMessage::min_hdr_size() const
1765 {
1766 	ssize_t size = 0;
1767 
1768 	size += 4;	// version
1769 	size += 4;	// checksum
1770 	size += 4;	// flattened size
1771 	size += 4;	// 'what'
1772 	size += 1;	// flags
1773 
1774 	return size;
1775 }
1776 //------------------------------------------------------------------------------
1777 status_t BMessage::_send_(port_id port, int32 token, bool preferred,
1778 						  bigtime_t timeout, bool reply_required,
1779 						  BMessenger& reply_to) const
1780 {
1781 	BMessage tmp_msg;
1782 	tmp_msg.fPreferred     = fPreferred;
1783 	tmp_msg.fTarget        = fTarget;
1784 	tmp_msg.fReplyRequired = fReplyRequired;
1785 	tmp_msg.fReplyTo       = fReplyTo;
1786 
1787 	BMessage* self = const_cast<BMessage*>(this);
1788 	self->fPreferred         = preferred;
1789 	self->fTarget            = token;
1790 	self->fReplyRequired     = reply_required;
1791 	self->fReplyTo.team      = reply_to.fTeam;
1792 	self->fReplyTo.port      = reply_to.fPort;
1793 	self->fReplyTo.target    = (reply_to.fPreferredTarget
1794 								? B_PREFERRED_TOKEN : reply_to.fHandlerToken);
1795 	self->fReplyTo.preferred = reply_to.fPreferredTarget;
1796 
1797 	char tmp[0x800];
1798 	ssize_t size;
1799 	char* p = stack_flatten(tmp, sizeof(tmp), true /* include reply */, &size);
1800 	char* pMem = p ? p : tmp;
1801 	status_t err;
1802 	do
1803 	{
1804 		err = write_port_etc(port, 'pjpp', pMem, size, B_RELATIVE_TIMEOUT, timeout);
1805 	} while (err == B_INTERRUPTED);
1806 	if (p)
1807 	{
1808 		delete[] p;
1809 	}
1810 	self->fPreferred     = tmp_msg.fPreferred;
1811 	self->fTarget        = tmp_msg.fTarget;
1812 	self->fReplyRequired = tmp_msg.fReplyRequired;
1813 	self->fReplyTo       = tmp_msg.fReplyTo;
1814 	tmp_msg.init_data();
1815 	return err;
1816 }
1817 //------------------------------------------------------------------------------
1818 status_t BMessage::send_message(port_id port, team_id port_owner, int32 token,
1819 								bool preferred, BMessage* reply,
1820 								bigtime_t send_timeout,
1821 								bigtime_t reply_timeout) const
1822 {
1823 	const int32 cached_reply_port = sGetCachedReplyPort();
1824 	port_id reply_port;
1825 	status_t err;
1826 	if (cached_reply_port == -1)
1827 	{
1828 		// All the cached reply ports are in use; create a new one
1829 		reply_port = create_port(1 /* for one message */, "tmp_reply_port");
1830 		if (reply_port < 0)
1831 		{
1832 			return reply_port;
1833 		}
1834 	}
1835 	else
1836 	{
1837 		assert(cached_reply_port < sNumReplyPorts);
1838 		reply_port = sReplyPorts[cached_reply_port];
1839 	}
1840 
1841 	team_id team = B_BAD_TEAM_ID;
1842 	if (be_app != NULL)
1843 		team = be_app->Team();
1844 	else {
1845 		port_info pi;
1846 		err = get_port_info(reply_port, &pi);
1847 		if (err)
1848 			goto error;
1849 
1850 		team = pi.team;
1851 	}
1852 
1853 	err = set_port_owner(reply_port, port_owner);
1854 	if (err)
1855 		goto error;
1856 
1857 	{
1858 		BMessenger messenger(team, reply_port, B_PREFERRED_TOKEN, false);
1859 		err = _send_(port, token, preferred, send_timeout, true, messenger);
1860 	}
1861 	if (err)
1862 	{
1863 		goto error;
1864 	}
1865 	int32 code;
1866 	err = handle_reply(reply_port, &code, reply_timeout, reply);
1867 	if (err && cached_reply_port >= 0)
1868 	{
1869 		delete_port(reply_port);
1870 		sReplyPorts[cached_reply_port] = create_port(1, "tmp_rport");
1871 	}
1872 
1873 error:
1874 	if (cached_reply_port >= 0)
1875 	{
1876 		// Reclaim ownership of cached port
1877 		set_port_owner(reply_port, team);
1878 		// Flag as available
1879 		atomic_add(&sReplyPortInUse[cached_reply_port], -1);
1880 		return err;
1881 	}
1882 	delete_port(reply_port);
1883 	return err;
1884 }
1885 //------------------------------------------------------------------------------
1886 int32 BMessage::sGetCachedReplyPort()
1887 {
1888 	int index = -1;
1889 	for (int32 i = 0; i < sNumReplyPorts; i++)
1890 	{
1891 		int32 old = atomic_add(&(sReplyPortInUse[i]), 1);
1892 		if (old == 0)
1893 		{
1894 			// This entry is free
1895 			index = i;
1896 			break;
1897 		}
1898 		else
1899 		{
1900 			// This entry is being used.
1901 			atomic_add(&(sReplyPortInUse[i]), -1);
1902 		}
1903 	}
1904 
1905 	return index;
1906 }
1907 //------------------------------------------------------------------------------
1908 static status_t handle_reply(port_id   reply_port,
1909                              int32*    pCode,
1910                              bigtime_t timeout,
1911                              BMessage* reply)
1912 {
1913 	status_t err;
1914 	do
1915 	{
1916 		err = port_buffer_size_etc(reply_port, 8, timeout);
1917 	} while (err == B_INTERRUPTED);
1918 	if (err < 0)
1919 	{
1920 		return err;
1921 	}
1922 	// The API lied. It really isn't an error code, but the message size...
1923 	char* pAllocd = NULL;
1924 	char* pMem    = NULL;
1925 	char tmp[0x800];
1926 	if (err < 0x800)
1927 	{
1928 		pMem = tmp;
1929 	}
1930 	else
1931 	{
1932 		pAllocd = new char[err];
1933 		pMem = pAllocd;
1934 	}
1935 	do
1936 	{
1937 		err = read_port(reply_port, pCode, pMem, err);
1938 	} while (err == B_INTERRUPTED);
1939 
1940 	if (err < 0)
1941 	{
1942 		return err;
1943 	}
1944 
1945 	if (*pCode == 'PUSH')
1946 	{
1947 		return B_ERROR;
1948 	}
1949 	if (*pCode != 'pjpp')
1950 	{
1951 		return B_OK;
1952 	}
1953 
1954 	err = reply->Unflatten(pMem);
1955 
1956 	// There seems to be a bug in the original Be implementation.
1957 	// It never free'd pAllocd !
1958 	if (pAllocd)
1959 	{
1960 		delete[] pAllocd;
1961 	}
1962 	return err;
1963 }
1964 //------------------------------------------------------------------------------
1965 
1966 #else	// USING_TEMPLATE_MADNESS
1967 
1968 //------------------------------------------------------------------------------
1969 BMessage::BMessage(uint32 command)
1970 {
1971 	init_data();
1972 
1973 	what = command;
1974 }
1975 //------------------------------------------------------------------------------
1976 BMessage::BMessage(const BMessage &message)
1977 {
1978 	*this = message;
1979 }
1980 //------------------------------------------------------------------------------
1981 BMessage::BMessage()
1982 {
1983 	init_data();
1984 }
1985 //------------------------------------------------------------------------------
1986 BMessage::~BMessage ()
1987 {
1988 }
1989 //------------------------------------------------------------------------------
1990 BMessage &BMessage::operator=(const BMessage &message)
1991 {
1992 	what = message.what;
1993 
1994 	link = message.link;
1995 	fTarget = message.fTarget;
1996 	fOriginal = message.fOriginal;
1997 	fChangeCount = message.fChangeCount;
1998 	fCurSpecifier = message.fCurSpecifier;
1999 	fPtrOffset = message.fPtrOffset;
2000 
2001 	fEntries = NULL;
2002 
2003     entry_hdr *src_entry;
2004 
2005     for ( src_entry = message.fEntries; src_entry != NULL; src_entry = src_entry->fNext )
2006 	{
2007 		entry_hdr* new_entry = (entry_hdr*)new char[da_total_logical_size ( src_entry )];
2008 
2009 		if ( new_entry != NULL )
2010 		{
2011 			memcpy ( new_entry, src_entry, da_total_logical_size ( src_entry ) );
2012 
2013 			new_entry->fNext = fEntries;
2014 			new_entry->fPhysicalBytes = src_entry->fLogicalBytes;
2015 
2016 			fEntries = new_entry;
2017 		}
2018     }
2019 
2020 	fReplyTo.port = message.fReplyTo.port;
2021 	fReplyTo.target = message.fReplyTo.target;
2022 	fReplyTo.team = message.fReplyTo.team;
2023 	fReplyTo.preferred = message.fReplyTo.preferred;
2024 
2025 	fPreferred = message.fPreferred;
2026 	fReplyRequired = message.fReplyRequired;
2027 	fReplyDone = message.fReplyDone;
2028 	fIsReply = message.fIsReply;
2029 	fWasDelivered = message.fWasDelivered;
2030 	fReadOnly = message.fReadOnly;
2031 	fHasSpecifiers = message.fHasSpecifiers;
2032 
2033     return *this;
2034 }
2035 //------------------------------------------------------------------------------
2036 status_t BMessage::GetInfo(const char *name, type_code *typeFound,
2037 							int32 *countFound) const
2038 {
2039 	for(entry_hdr *entry = fEntries; entry != NULL; entry = entry->fNext)
2040 	{
2041 		if (entry->fNameLength == strlen(name) &&
2042 			strncmp(entry->fName, name, entry->fNameLength) == 0)
2043 		{
2044 			if (typeFound)
2045 				*typeFound = entry->fType;
2046 
2047 			if (countFound)
2048 				*countFound = entry->fCount;
2049 
2050 			return B_OK;
2051 		}
2052 	}
2053 
2054 	return B_NAME_NOT_FOUND;
2055 }
2056 //------------------------------------------------------------------------------
2057 status_t BMessage::GetInfo(const char *name, type_code *typeFound, bool *fixedSize) const
2058 {
2059 	return B_ERROR;
2060 }
2061 //------------------------------------------------------------------------------
2062 status_t BMessage::GetInfo(type_code type, int32 index, char **nameFound, type_code *typeFound,
2063 	int32 *countFound) const
2064 {
2065 	return B_ERROR;
2066 }
2067 //------------------------------------------------------------------------------
2068 int32 BMessage::CountNames(type_code type) const
2069 {
2070 	return -1;
2071 }
2072 //------------------------------------------------------------------------------
2073 //bool BMessage::IsEmpty () const;
2074 //------------------------------------------------------------------------------
2075 //bool BMessage::IsSystem () const;
2076 //------------------------------------------------------------------------------
2077 bool BMessage::IsReply() const
2078 {
2079 	return fIsReply;
2080 }
2081 //------------------------------------------------------------------------------
2082 void BMessage::PrintToStream() const
2083 {
2084 	char name[256];
2085 
2086 	for (entry_hdr *entry = fEntries; entry != NULL; entry = entry->fNext)
2087 	{
2088 		memcpy(name, entry->fName, entry->fNameLength);
2089 		name[entry->fNameLength] = 0;
2090 
2091 		printf("#entry %s, type = %c%c%c%c, count = %d\n", name,
2092 			(entry->fType & 0xFF000000) >> 24, (entry->fType & 0x00FF0000) >> 16,
2093 			(entry->fType & 0x0000FF00) >> 8, entry->fType & 0x000000FF, entry->fCount);
2094 
2095 		((BMessage*)this)->da_dump((dyn_array*)entry);
2096 	}
2097 }
2098 //------------------------------------------------------------------------------
2099 //status_t BMessage::Rename(const char *old_entry, const char *new_entry);
2100 //------------------------------------------------------------------------------
2101 //------------------------------------------------------------------------------
2102 bool BMessage::WasDelivered () const
2103 {
2104 	return fWasDelivered;
2105 }
2106 //------------------------------------------------------------------------------
2107 //bool BMessage::IsSourceWaiting() const;
2108 //------------------------------------------------------------------------------
2109 //bool BMessage::IsSourceRemote() const;
2110 //------------------------------------------------------------------------------
2111 BMessenger BMessage::ReturnAddress() const
2112 {
2113 	return BMessenger(fReplyTo.team, fReplyTo.port, fReplyTo.target,
2114 		fReplyTo.preferred);
2115 }
2116 //------------------------------------------------------------------------------
2117 const BMessage *BMessage::Previous () const
2118 {
2119 	return fOriginal;
2120 }
2121 //------------------------------------------------------------------------------
2122 bool BMessage::WasDropped () const
2123 {
2124 	if (GetInfo("_drop_point_", NULL, (int32*)NULL) == B_OK)
2125 		return true;
2126 	else
2127 		return false;
2128 }
2129 //------------------------------------------------------------------------------
2130 BPoint BMessage::DropPoint(BPoint *offset) const
2131 {
2132 	BPoint point;
2133 
2134 	FindPoint("_drop_point_", &point);
2135 
2136 	if (offset)
2137 		FindPoint("_drop_offset_", offset);
2138 
2139 	return point;
2140 }
2141 //------------------------------------------------------------------------------
2142 status_t BMessage::SendReply(uint32 command, BHandler *reply_to)
2143 {
2144 	return B_ERROR;
2145 }
2146 //------------------------------------------------------------------------------
2147 status_t BMessage::SendReply(BMessage *the_reply, BHandler *reply_to,
2148 					bigtime_t timeout)
2149 {
2150 	return B_ERROR;
2151 }
2152 //------------------------------------------------------------------------------
2153 status_t BMessage::SendReply(BMessage *the_reply, BMessenger reply_to,
2154 					bigtime_t timeout)
2155 {
2156 	return B_ERROR;
2157 }
2158 //------------------------------------------------------------------------------
2159 status_t BMessage::SendReply(uint32 command, BMessage *reply_to_reply)
2160 {
2161 	return B_ERROR;
2162 }
2163 //------------------------------------------------------------------------------
2164 status_t BMessage::SendReply(BMessage *the_reply, BMessage *reply_to_reply,
2165 					bigtime_t send_timeout,
2166 					bigtime_t reply_timeout)
2167 {
2168 	return B_ERROR;
2169 }
2170 //------------------------------------------------------------------------------
2171 ssize_t BMessage::FlattenedSize() const
2172 {
2173 	ssize_t size = 7 * sizeof(int32);
2174 
2175 	for (entry_hdr *entry = fEntries; entry != NULL; entry = entry->fNext)
2176 		size += da_total_logical_size(entry);
2177 
2178 	return size;
2179 }
2180 //------------------------------------------------------------------------------
2181 status_t BMessage::Flatten(char *address, ssize_t numBytes) const
2182 {
2183 	if (address!= NULL && numBytes < FlattenedSize())
2184 		return B_NO_MEMORY;
2185 
2186 	int position = 7 * sizeof(int32);
2187 
2188 	((int32*)address)[1] = what;
2189 	((int32*)address)[2] = fCurSpecifier;
2190 	((int32*)address)[3] = fHasSpecifiers;
2191 	((int32*)address)[4] = 0;
2192 	((int32*)address)[5] = 0;
2193 	((int32*)address)[6] = 0;
2194 
2195 	for (entry_hdr *entry = fEntries; entry != NULL; entry = entry->fNext)
2196 	{
2197 		memcpy(address + position, entry, da_total_logical_size(entry));
2198 
2199 		position += da_total_logical_size(entry);
2200     }
2201 
2202     ((size_t*)address)[0] = position;
2203 
2204 	return B_OK;
2205 }
2206 //------------------------------------------------------------------------------
2207 status_t BMessage::Flatten(BDataIO *object, ssize_t *numBytes) const
2208 {
2209 	if (numBytes != NULL && *numBytes < FlattenedSize())
2210 		return B_NO_MEMORY;
2211 
2212 	int32 size = FlattenedSize();
2213 	char *buffer = new char[size];
2214 
2215 	Flatten(buffer, size);
2216 
2217 	object->Write(buffer, size);
2218 
2219 	delete buffer;
2220 
2221 	return B_OK;
2222 }
2223 //------------------------------------------------------------------------------
2224 status_t BMessage::Unflatten(const char *address)
2225 {
2226 	size_t size;
2227 
2228     MakeEmpty();
2229 
2230     size = ((size_t*)address)[0];
2231     what = ((int32*)address)[1];
2232 	fCurSpecifier = ((int32*)address)[2];
2233 	fHasSpecifiers = ((int32*)address)[3];
2234 
2235     size_t position = 7 * sizeof(int32);
2236 
2237     while (position < size)
2238 	{
2239 		entry_hdr* src_entry = (entry_hdr*)&address[position];
2240 		entry_hdr* new_entry = (entry_hdr*)new char[da_total_logical_size ( src_entry )];
2241 
2242 		if (new_entry != NULL)
2243 		{
2244 			memcpy(new_entry, src_entry, da_total_logical_size(src_entry));
2245 
2246 			new_entry->fNext = fEntries;
2247 			new_entry->fPhysicalBytes = src_entry->fLogicalBytes;
2248 			position += da_total_logical_size(src_entry);
2249 
2250 			fEntries = new_entry;
2251 		}
2252 		else
2253 			return B_NO_MEMORY;
2254     }
2255 
2256     if (position != size)
2257 	{
2258 		MakeEmpty();
2259 		return B_BAD_VALUE;
2260     }
2261 
2262     return B_OK;
2263 }
2264 //------------------------------------------------------------------------------
2265 status_t BMessage::Unflatten(BDataIO *object)
2266 {
2267 	size_t size;
2268 
2269 	object->Read(&size, sizeof(int32));
2270 
2271 	char *buffer = new char[size];
2272 
2273 	*(int32*)buffer = size;
2274 
2275 	object->Read(buffer + sizeof(int32), size - sizeof(int32));
2276 
2277 	status_t status =  Unflatten(buffer);
2278 
2279 	delete[] buffer;
2280 
2281     return status;
2282 }
2283 //------------------------------------------------------------------------------
2284 status_t BMessage::AddSpecifier(const char *property)
2285 {
2286 	BMessage message(B_DIRECT_SPECIFIER);
2287 	message.AddString("property", property);
2288 
2289 	fCurSpecifier ++;
2290 	fHasSpecifiers = true;
2291 
2292 	return AddMessage("specifiers", &message);
2293 }
2294 //------------------------------------------------------------------------------
2295 status_t BMessage::AddSpecifier(const char *property, int32 index)
2296 {
2297 	BMessage message(B_INDEX_SPECIFIER);
2298 	message.AddString("property", property);
2299 	message.AddInt32("index", index);
2300 
2301 	fCurSpecifier++;
2302 	fHasSpecifiers = true;
2303 
2304 	return AddMessage("specifiers", &message);
2305 }
2306 //------------------------------------------------------------------------------
2307 status_t BMessage::AddSpecifier(const char *property, int32 index, int32 range)
2308 {
2309 	BMessage message(B_RANGE_SPECIFIER);
2310 	message.AddString("property", property);
2311 	message.AddInt32("index", index);
2312 	message.AddInt32("range", range);
2313 
2314 	fCurSpecifier ++;
2315 	fHasSpecifiers = true;
2316 
2317 	return AddMessage("specifiers", &message);
2318 }
2319 //------------------------------------------------------------------------------
2320 status_t BMessage::AddSpecifier(const char *property, const char *name)
2321 {
2322 	BMessage message(B_NAME_SPECIFIER);
2323 	message.AddString("property", property);
2324 	message.AddString("name", name);
2325 
2326 	fCurSpecifier ++;
2327 	fHasSpecifiers = true;
2328 
2329 	return AddMessage("specifiers", &message);
2330 }
2331 //------------------------------------------------------------------------------
2332 //status_t BMessage::AddSpecifier(const BMessage *message);
2333 //------------------------------------------------------------------------------
2334 status_t SetCurrentSpecifier(int32 index)
2335 {
2336 	return B_ERROR;
2337 }
2338 //------------------------------------------------------------------------------
2339 status_t BMessage::GetCurrentSpecifier(int32 *index, BMessage *specifier,
2340 									   int32 *what, const char **property) const
2341 {
2342 	if (fCurSpecifier == -1)
2343 		return B_BAD_SCRIPT_SYNTAX;
2344 
2345 	if (index)
2346 		*index = fCurSpecifier;
2347 
2348 	if (specifier)
2349 	{
2350 		FindMessage("specifiers", fCurSpecifier, specifier);
2351 
2352 		if (what)
2353 			*what = specifier->what;
2354 
2355 		if (property)
2356 			specifier->FindString("property", property);
2357 	}
2358 
2359 	return B_OK;
2360 }
2361 //------------------------------------------------------------------------------
2362 bool BMessage::HasSpecifiers() const
2363 {
2364 	return fHasSpecifiers;
2365 }
2366 //------------------------------------------------------------------------------
2367 status_t BMessage::PopSpecifier()
2368 {
2369 	if (fCurSpecifier)
2370 	{
2371 		fCurSpecifier--;
2372 		return B_OK;
2373 	}
2374 	else
2375 		return B_BAD_VALUE;
2376 }
2377 //------------------------------------------------------------------------------
2378 status_t BMessage::AddRect(const char *name, BRect rect)
2379 {
2380 	return AddData(name, B_RECT_TYPE, &rect, sizeof(BRect), true);
2381 }
2382 //------------------------------------------------------------------------------
2383 status_t BMessage::AddPoint(const char *name, BPoint point)
2384 {
2385 	return AddData(name, B_POINT_TYPE, &point, sizeof(BPoint), true);
2386 }
2387 //------------------------------------------------------------------------------
2388 status_t BMessage::AddString(const char *name, const char *string)
2389 {
2390 	return AddData(name, B_STRING_TYPE, string, strlen(string) + 1, false);
2391 }
2392 //------------------------------------------------------------------------------
2393 //status_t BMessage::AddString(const char *name, const CString &string);
2394 //------------------------------------------------------------------------------
2395 status_t BMessage::AddInt8(const char *name, int8 anInt8)
2396 {
2397 	return AddData(name, B_INT8_TYPE, &anInt8, sizeof(int8));
2398 }
2399 //------------------------------------------------------------------------------
2400 status_t BMessage::AddInt16(const char *name, int16 anInt16)
2401 {
2402 	return AddData(name, B_INT16_TYPE, &anInt16, sizeof(int16));
2403 }
2404 //------------------------------------------------------------------------------
2405 status_t BMessage::AddInt32(const char *name, int32 anInt32)
2406 {
2407 	return AddData(name, B_INT32_TYPE, &anInt32, sizeof(int32));
2408 }
2409 //------------------------------------------------------------------------------
2410 status_t BMessage::AddInt64(const char *name, int64 anInt64)
2411 {
2412 	return AddData(name, B_INT64_TYPE, &anInt64, sizeof(int64));
2413 }
2414 //------------------------------------------------------------------------------
2415 status_t BMessage::AddBool(const char *name, bool aBool)
2416 {
2417 	return AddData(name, B_BOOL_TYPE, &aBool, sizeof(bool));
2418 }
2419 //------------------------------------------------------------------------------
2420 status_t BMessage::AddFloat ( const char *name, float aFloat)
2421 {
2422 	return AddData(name, B_FLOAT_TYPE, &aFloat, sizeof(float));
2423 }
2424 //------------------------------------------------------------------------------
2425 status_t BMessage::AddDouble ( const char *name, double aDouble)
2426 {
2427 	return AddData(name, B_DOUBLE_TYPE, &aDouble, sizeof(double));
2428 }
2429 //------------------------------------------------------------------------------
2430 status_t BMessage::AddPointer(const char *name, const void *pointer)
2431 {
2432 	return AddData(name, B_POINTER_TYPE, &pointer, sizeof(void*), true);
2433 }
2434 //------------------------------------------------------------------------------
2435 status_t BMessage::AddMessenger(const char *name, BMessenger messenger)
2436 {
2437 	return B_OK;
2438 }
2439 //------------------------------------------------------------------------------
2440 //status_t BMessage::AddRef(const char *name, const entry_ref *ref);
2441 //------------------------------------------------------------------------------
2442 status_t BMessage::AddMessage(const char *name, const BMessage *message)
2443 {
2444 	int32 size = message->FlattenedSize();
2445 	char *buffer = new char[size];
2446 
2447 	message->Flatten (buffer, size);
2448 
2449 	return AddData(name, B_MESSAGE_TYPE, buffer, size, false);
2450 }
2451 //------------------------------------------------------------------------------
2452 status_t BMessage::AddFlat(const char *name, BFlattenable *object,
2453 						   int32 numItems)
2454 {
2455 	int32 size = object->FlattenedSize ();
2456 	char *buffer = new char[size];
2457 
2458 	object->Flatten(buffer, size);
2459 
2460 	return AddData(name, object->TypeCode(), buffer, size,
2461 		object->IsFixedSize(), numItems);
2462 }
2463 //------------------------------------------------------------------------------
2464 status_t BMessage::AddData(const char *name, type_code type, const void *data,
2465 						   ssize_t numBytes, bool fixedSize, int32 numItems)
2466 {
2467 	entry_hdr *entry = entry_find(name, type);
2468 
2469 	if (entry == NULL)
2470 	{
2471 		if ( strlen(name) > 255)
2472 			return B_BAD_VALUE;
2473 
2474 		entry = (entry_hdr*)da_create(sizeof(entry_hdr) - sizeof(dyn_array) +
2475 			strlen(name), numBytes, fixedSize, numItems);
2476 
2477 		entry->fNext = fEntries;
2478 		entry->fType = type;
2479 		entry->fNameLength = strlen(name);
2480 		memcpy(entry->fName, name, entry->fNameLength);
2481 
2482 		fEntries = entry;
2483 	}
2484 
2485 	return da_add_data((dyn_array**)&entry, data, numBytes);
2486 }
2487 //------------------------------------------------------------------------------
2488 //status_t BMessage::RemoveData(const char *name, int32 index);
2489 //status_t BMessage::RemoveName(const char *name);
2490 //------------------------------------------------------------------------------
2491 status_t BMessage::MakeEmpty()
2492 {
2493 	entry_hdr *entry;
2494 
2495     while(entry = fEntries)
2496 	{
2497 		fEntries = entry->fNext;
2498 		delete entry;
2499     }
2500 
2501 	return B_OK;
2502 }
2503 //------------------------------------------------------------------------------
2504 status_t BMessage::FindRect(const char *name, BRect *rect) const
2505 {
2506 	entry_hdr *entry = entry_find(name, B_RECT_TYPE);
2507 
2508 	if (entry == NULL)
2509 		return B_NAME_NOT_FOUND;
2510 
2511 	*rect = *(BRect*)da_first_chunk(entry);
2512 
2513 	return B_OK;
2514 }
2515 //------------------------------------------------------------------------------
2516 status_t BMessage::FindRect(const char *name, int32 index, BRect *rect) const
2517 {
2518 	entry_hdr *entry = entry_find(name, B_RECT_TYPE);
2519 
2520 	if (entry == NULL)
2521 		return B_NAME_NOT_FOUND;
2522 
2523 	if (index < entry->fCount)
2524 	{
2525 		BRect* data = (BRect*)da_first_chunk(entry);
2526 		*rect = data[index];
2527 
2528 		return B_OK;
2529 	}
2530 
2531 	return B_BAD_INDEX;
2532 }
2533 //------------------------------------------------------------------------------
2534 status_t BMessage::FindPoint(const char *name, BPoint *point) const
2535 {
2536 	entry_hdr *entry = entry_find(name, B_POINT_TYPE);
2537 
2538 	if (entry == NULL)
2539 		return B_NAME_NOT_FOUND;
2540 
2541 	*point = *(BPoint*)da_first_chunk(entry);
2542 
2543 	return B_OK;
2544 }
2545 //------------------------------------------------------------------------------
2546 status_t BMessage::FindPoint(const char *name, int32 index, BPoint *point) const
2547 {
2548 	entry_hdr *entry = entry_find(name, B_POINT_TYPE);
2549 
2550 	if (entry == NULL)
2551 		return B_NAME_NOT_FOUND;
2552 
2553 	if (index < entry->fCount)
2554 	{
2555 		BPoint* data = (BPoint*)da_first_chunk(entry);
2556 		*point = data[index];
2557 
2558 		return B_OK;
2559 	}
2560 
2561 	return B_BAD_INDEX;
2562 }
2563 //------------------------------------------------------------------------------
2564 status_t BMessage::FindString(const char *name, int32 index,
2565 							  const char **string) const
2566 {
2567 	return FindData(name, B_STRING_TYPE, index, (const void**)string, NULL);
2568 }
2569 //------------------------------------------------------------------------------
2570 status_t BMessage::FindString(const char *name, const char **string) const
2571 {
2572 	return FindData(name, B_STRING_TYPE, (const void**)string, NULL);
2573 }
2574 //------------------------------------------------------------------------------
2575 //status_t BMessage::FindString ( const char *name, int32 index,
2576 //CString *string ) const;
2577 //------------------------------------------------------------------------------
2578 //status_t BMessage::FindString ( const char *name, CString *string ) const;
2579 //------------------------------------------------------------------------------
2580 status_t BMessage::FindInt8(const char *name, int8 *anInt8) const
2581 {
2582 	entry_hdr *entry = entry_find(name, B_INT8_TYPE);
2583 
2584 	if (entry == NULL)
2585 		return B_NAME_NOT_FOUND;
2586 
2587 	*anInt8 = *(int8*)da_first_chunk(entry);
2588 
2589 	return B_OK;
2590 }
2591 //------------------------------------------------------------------------------
2592 status_t BMessage::FindInt8(const char *name, int32 index, int8 *anInt8) const
2593 {
2594 	entry_hdr *entry = entry_find(name, B_INT8_TYPE);
2595 
2596 	if (entry == NULL)
2597 		return B_NAME_NOT_FOUND;
2598 
2599 	if (index < entry->fCount)
2600 	{
2601 		int8* data = (int8*)da_first_chunk(entry);
2602 		*anInt8 = data[index];
2603 
2604 		return B_OK;
2605 	}
2606 
2607 	return B_BAD_INDEX;
2608 }
2609 //------------------------------------------------------------------------------
2610 status_t BMessage::FindInt16(const char *name, int16 *anInt16) const
2611 {
2612 	entry_hdr *entry = entry_find(name, B_INT16_TYPE);
2613 
2614 	if (entry == NULL)
2615 		return B_NAME_NOT_FOUND;
2616 
2617 	*anInt16 = *(int16*)da_first_chunk(entry);
2618 
2619 	return B_OK;
2620 }
2621 //------------------------------------------------------------------------------
2622 status_t BMessage::FindInt16(const char *name, int32 index, int16 *anInt16) const
2623 {
2624 	entry_hdr *entry = entry_find(name, B_INT16_TYPE);
2625 
2626 	if (entry == NULL)
2627 		return B_NAME_NOT_FOUND;
2628 
2629 	if (index < entry->fCount)
2630 	{
2631 		int16* data = (int16*)da_first_chunk(entry);
2632 		*anInt16 = data[index];
2633 
2634 		return B_OK;
2635 	}
2636 
2637 	return B_BAD_INDEX;
2638 }
2639 //------------------------------------------------------------------------------
2640 status_t BMessage::FindInt32(const char *name, int32 *anInt32) const
2641 {
2642 	entry_hdr *entry = entry_find(name, B_INT32_TYPE);
2643 
2644 	if (entry == NULL)
2645 		return B_NAME_NOT_FOUND;
2646 
2647 	*anInt32 = *(int32*)da_first_chunk(entry);
2648 
2649 	return B_OK;
2650 }
2651 //------------------------------------------------------------------------------
2652 status_t BMessage::FindInt32(const char *name, int32 index,
2653 							 int32 *anInt32) const
2654 {
2655 	entry_hdr *entry = entry_find(name, B_INT32_TYPE);
2656 
2657 	if (entry == NULL)
2658 		return B_NAME_NOT_FOUND;
2659 
2660 	if (index < entry->fCount)
2661 	{
2662 		int32* data = (int32*)da_first_chunk(entry);
2663 		*anInt32 = data[index];
2664 
2665 		return B_OK;
2666 	}
2667 
2668 	return B_BAD_INDEX;
2669 }
2670 //------------------------------------------------------------------------------
2671 //status_t BMessage::FindInt64 ( const char *name, int64 *anInt64) const;
2672 //------------------------------------------------------------------------------
2673 //status_t BMessage::FindInt64 ( const char *name, int32 index,
2674 //							  int64 *anInt64 ) const;
2675 //------------------------------------------------------------------------------
2676 status_t BMessage::FindBool(const char *name, bool *aBool) const
2677 {
2678 	entry_hdr *entry = entry_find(name, B_BOOL_TYPE);
2679 
2680 	if (entry == NULL)
2681 		return B_NAME_NOT_FOUND;
2682 
2683 	*aBool = *(bool*)da_first_chunk(entry);
2684 
2685 	return B_OK;
2686 }
2687 //------------------------------------------------------------------------------
2688 status_t BMessage::FindBool(const char *name, int32 index, bool *aBool) const
2689 {
2690 	entry_hdr *entry = entry_find(name, B_BOOL_TYPE);
2691 
2692 	if (entry == NULL)
2693 		return B_NAME_NOT_FOUND;
2694 
2695 	if (index < entry->fCount)
2696 	{
2697 		bool* data = (bool*)da_first_chunk(entry);
2698 		*aBool = data[index];
2699 
2700 		return B_OK;
2701 	}
2702 
2703 	return B_BAD_INDEX;
2704 }
2705 //------------------------------------------------------------------------------
2706 status_t BMessage::FindFloat(const char *name, float *aFloat) const
2707 {
2708 	entry_hdr *entry = entry_find(name, B_FLOAT_TYPE);
2709 
2710 	if (entry == NULL)
2711 		return B_NAME_NOT_FOUND;
2712 
2713 	*aFloat = *(float*)da_first_chunk(entry);
2714 
2715 	return B_OK;
2716 }
2717 //------------------------------------------------------------------------------
2718 status_t BMessage::FindFloat(const char *name, int32 index, float *aFloat) const
2719 {
2720 	entry_hdr *entry = entry_find(name, B_FLOAT_TYPE);
2721 
2722 	if (entry == NULL)
2723 		return B_NAME_NOT_FOUND;
2724 
2725 	if (index < entry->fCount)
2726 	{
2727 		float* data = (float*)da_first_chunk(entry);
2728 		*aFloat = data[index];
2729 
2730 		return B_OK;
2731 	}
2732 
2733 	return B_BAD_INDEX;
2734 }
2735 //------------------------------------------------------------------------------
2736 status_t BMessage::FindDouble(const char *name, double *aDouble) const
2737 {
2738 	entry_hdr *entry = entry_find(name, B_DOUBLE_TYPE);
2739 
2740 	if (entry == NULL)
2741 		return B_NAME_NOT_FOUND;
2742 
2743 	*aDouble = *(double*)da_first_chunk(entry);
2744 
2745 	return B_OK;
2746 }
2747 //------------------------------------------------------------------------------
2748 status_t BMessage::FindDouble(const char *name, int32 index,
2749 							  double *aDouble) const
2750 {
2751 	entry_hdr *entry = entry_find(name, B_DOUBLE_TYPE);
2752 
2753 	if (entry == NULL)
2754 		return B_NAME_NOT_FOUND;
2755 
2756 	if (index < entry->fCount)
2757 	{
2758 		double* data = (double*)da_first_chunk(entry);
2759 		*aDouble = data[index];
2760 
2761 		return B_OK;
2762 	}
2763 
2764 	return B_BAD_INDEX;
2765 }
2766 //------------------------------------------------------------------------------
2767 status_t BMessage::FindPointer(const char *name, void **pointer) const
2768 {
2769 	entry_hdr *entry = entry_find(name, B_POINTER_TYPE);
2770 
2771 	if (entry == NULL)
2772 	{
2773 		*pointer = NULL;
2774 		return B_NAME_NOT_FOUND;
2775 	}
2776 
2777 	*pointer = *(void**)da_first_chunk(entry);
2778 
2779 	return B_OK;
2780 }
2781 //------------------------------------------------------------------------------
2782 status_t BMessage::FindPointer(const char *name, int32 index,
2783 							   void **pointer) const
2784 {
2785 	entry_hdr *entry = entry_find(name, B_POINTER_TYPE);
2786 
2787 	if (entry == NULL)
2788 	{
2789 		*pointer = NULL;
2790 		return B_NAME_NOT_FOUND;
2791 	}
2792 
2793 	if (index >= entry->fCount)
2794 	{
2795 		*pointer = NULL;
2796 		return B_BAD_INDEX;
2797 	}
2798 
2799 	void** data = (void**)da_first_chunk(entry);
2800 	*pointer = data[index];
2801 
2802 	return B_OK;
2803 }
2804 //------------------------------------------------------------------------------
2805 //status_t BMessage::FindMessenger ( const char *name, CMessenger *messenger ) const;
2806 //------------------------------------------------------------------------------
2807 //status_t BMessage::FindMessenger ( const char *name, int32 index, CMessenger *messenger ) const;
2808 //------------------------------------------------------------------------------
2809 //status_t BMessage::FindRef ( const char *name, entry_ref *ref ) const;
2810 //------------------------------------------------------------------------------
2811 //status_t BMessage::FindRef ( const char *name, int32 index, entry_ref *ref ) const;
2812 //------------------------------------------------------------------------------
2813 status_t BMessage::FindMessage(const char *name, BMessage *message) const
2814 {
2815 	const char *data;
2816 
2817 	if ( FindData(name, B_MESSAGE_TYPE, (const void**)&data, NULL) != B_OK)
2818 		return B_NAME_NOT_FOUND;
2819 
2820 	return message->Unflatten(data);
2821 }
2822 //------------------------------------------------------------------------------
2823 status_t BMessage::FindMessage(const char *name, int32 index,
2824 							   BMessage *message) const
2825 {
2826 	const char *data;
2827 
2828 	if ( FindData(name, B_MESSAGE_TYPE, index, (const void**)&data,
2829 		NULL) != B_OK)
2830 		return B_NAME_NOT_FOUND;
2831 
2832 	return message->Unflatten(data);
2833 }
2834 //------------------------------------------------------------------------------
2835 status_t BMessage::FindFlat(const char *name, BFlattenable *object) const
2836 {
2837 	status_t ret;
2838 	const void *data;
2839 	ssize_t numBytes;
2840 
2841 	ret = FindData(name, object->TypeCode (), &data, &numBytes);
2842 
2843 	if ( ret != B_OK )
2844 		return ret;
2845 
2846 	if ( object->Unflatten(object->TypeCode (), data, numBytes) != B_OK)
2847 		return B_BAD_VALUE;
2848 
2849 	return B_OK;
2850 }
2851 //------------------------------------------------------------------------------
2852 status_t BMessage::FindFlat(const char *name, int32 index,
2853 							BFlattenable *object) const
2854 {
2855 	status_t ret;
2856 	const void *data;
2857 	ssize_t numBytes;
2858 
2859 	ret = FindData(name, object->TypeCode(), index, &data, &numBytes);
2860 
2861 	if (ret != B_OK)
2862 		return ret;
2863 
2864 	if (object->Unflatten(object->TypeCode(), data, numBytes) != B_OK)
2865 		return B_BAD_VALUE;
2866 
2867 	return B_OK;
2868 }
2869 //------------------------------------------------------------------------------
2870 status_t BMessage::FindData(const char *name, type_code type, const void **data,
2871 							ssize_t *numBytes) const
2872 {
2873 	entry_hdr *entry = entry_find(name, type);
2874 
2875 	if (entry == NULL)
2876 	{
2877 		*data = NULL;
2878 		return B_NAME_NOT_FOUND;
2879 	}
2880 
2881 	int32 size;
2882 
2883 	*data = da_find_data(entry, 0, &size);
2884 
2885 	if (numBytes)
2886 		*numBytes = size;
2887 
2888 	return B_OK;
2889 }
2890 //------------------------------------------------------------------------------
2891 status_t BMessage::FindData(const char *name, type_code type, int32 index,
2892 							const void **data, ssize_t *numBytes) const
2893 {
2894 	entry_hdr *entry = entry_find(name, type);
2895 
2896 	if (entry == NULL)
2897 	{
2898 		*data = NULL;
2899 		return B_NAME_NOT_FOUND;
2900 	}
2901 
2902 	if (index >= entry->fCount)
2903 	{
2904 		*data = NULL;
2905 		return B_BAD_INDEX;
2906 	}
2907 
2908 	int32 size;
2909 
2910 	*data = da_find_data(entry, index, &size);
2911 
2912 	if (numBytes)
2913 		*numBytes = size;
2914 
2915 	return B_OK;
2916 }
2917 //------------------------------------------------------------------------------
2918 //status_t BMessage::ReplaceRect(const char *name, BRect rect);
2919 //------------------------------------------------------------------------------
2920 //status_t BMessage::ReplaceRect(const char *name, int32 index, BRect rect);
2921 //------------------------------------------------------------------------------
2922 status_t BMessage::ReplacePoint(const char *name, BPoint point)
2923 {
2924 	return ReplaceData(name, B_POINT_TYPE, &point, sizeof(BPoint));
2925 }
2926 //------------------------------------------------------------------------------
2927 //status_t BMessage::ReplacePoint(const char *name, int32 index, BPoint point);
2928 //------------------------------------------------------------------------------
2929 status_t BMessage::ReplaceString(const char *name, const char *string)
2930 {
2931 	return B_ERROR;
2932 }
2933 //------------------------------------------------------------------------------
2934 //status_t BMessage::ReplaceString(const char *name, int32 index,
2935 //								 const char *string);
2936 //------------------------------------------------------------------------------
2937 //status_t BMessage::ReplaceString(const char *name, CString &string);
2938 //------------------------------------------------------------------------------
2939 //status_t BMessage::ReplaceString(const char *name, int32 index, CString &string);
2940 //------------------------------------------------------------------------------
2941 status_t BMessage::ReplaceInt8(const char *name, int8 anInt8)
2942 {
2943 	return ReplaceData(name, B_INT8_TYPE, &anInt8, sizeof(int8));
2944 }
2945 //------------------------------------------------------------------------------
2946 //status_t BMessage::ReplaceInt8(const char *name, int32 index, int8 anInt8);
2947 //------------------------------------------------------------------------------
2948 //status_t BMessage::ReplaceInt16(const char *name, int16 anInt16);
2949 //------------------------------------------------------------------------------
2950 //status_t BMessage::ReplaceInt16(const char *name, int32 index, int16 anInt16);
2951 //------------------------------------------------------------------------------
2952 status_t BMessage::ReplaceInt32(const char *name, long anInt32)
2953 {
2954 	return ReplaceData(name, B_INT32_TYPE, &anInt32, sizeof(int32));
2955 }
2956 //------------------------------------------------------------------------------
2957 //status_t BMessage::ReplaceInt32(const char *name, int32 index, int32 anInt32);
2958 //------------------------------------------------------------------------------
2959 status_t BMessage::ReplaceInt64(const char *name, int64 anInt64)
2960 {
2961 	return ReplaceData(name, B_INT64_TYPE, &anInt64, sizeof(int64));
2962 }
2963 //------------------------------------------------------------------------------
2964 //status_t BMessage::ReplaceInt64(const char *name, int32 index, int64 anInt64);
2965 //------------------------------------------------------------------------------
2966 //status_t BMessage::ReplaceBool(const char *name, bool aBool);
2967 //------------------------------------------------------------------------------
2968 //status_t BMessage::ReplaceBool(const char *name, int32 index, bool aBool);
2969 //------------------------------------------------------------------------------
2970 //status_t BMessage::ReplaceFloat(const char *name, float aFloat);
2971 //------------------------------------------------------------------------------
2972 //status_t BMessage::ReplaceFloat(const char *name, int32 index, float aFloat);
2973 //------------------------------------------------------------------------------
2974 //status_t BMessage::ReplaceDouble(const char *name, double aDouble);
2975 //------------------------------------------------------------------------------
2976 //status_t BMessage::ReplaceDouble(const char *name, int32 index, double aDouble);
2977 //------------------------------------------------------------------------------
2978 //status_t BMessage::ReplacePointer(const char *name, const void *pointer);
2979 //------------------------------------------------------------------------------
2980 //status_t BMessage::ReplacePointer(const char *name, int32 index,
2981 //								  const void *pointer);
2982 //------------------------------------------------------------------------------
2983 //status_t BMessage::ReplaceMessenger(const char *name, BMessenger messenger);
2984 //------------------------------------------------------------------------------
2985 //status_t BMessage::ReplaceMessenger(const char *name, int32 index,
2986 //									BMessenger messenger);
2987 //------------------------------------------------------------------------------
2988 //status_t BMessage::ReplaceRef(const char *name, entry_ref *ref);
2989 //------------------------------------------------------------------------------
2990 //status_t BMessage::ReplaceRef(const char *name, int32 index, entry_ref *ref);
2991 //------------------------------------------------------------------------------
2992 //status_t ReplaceMessage(const char *name, const BMessage *msg);
2993 //------------------------------------------------------------------------------
2994 //status_t ReplaceMessage(const char *name, int32 index, const BMessage *msg);
2995 //------------------------------------------------------------------------------
2996 //status_t BMessage::ReplaceFlat(const char *name, BFlattenable *object);
2997 //------------------------------------------------------------------------------
2998 //status_t BMessage::ReplaceFlat(const char *name, int32 index,
2999 //							   BFlattenable *object);
3000 //------------------------------------------------------------------------------
3001 status_t BMessage::ReplaceData(const char *name, type_code type,
3002 							   const void *data, ssize_t numBytes)
3003 {
3004 	entry_hdr *entry = entry_find(name, type);
3005 
3006 	if (entry == NULL)
3007 		return B_NAME_NOT_FOUND;
3008 
3009 	if (entry->fType != type)
3010 		return B_BAD_TYPE;
3011 
3012 	da_replace_data((dyn_array**)&entry, 0, data, numBytes);
3013 
3014 	return B_OK;
3015 }
3016 //------------------------------------------------------------------------------
3017 //status_t BMessage::ReplaceData(const char *name, type_code type, int32 index,
3018 //							   const void *data, size_t numBytes);
3019 //------------------------------------------------------------------------------
3020 //void *BMessage::operator new(size_t numBytes);
3021 //------------------------------------------------------------------------------
3022 //void BMessage::operator delete(void *memory, size_t numBytes);
3023 //------------------------------------------------------------------------------
3024 /*bool		HasRect(const char *, int32 n = 0) const;
3025 bool		HasPoint(const char *, int32 n = 0) const;
3026 bool		HasString(const char *, int32 n = 0) const;
3027 bool		HasInt8(const char *, int32 n = 0) const;
3028 bool		HasInt16(const char *, int32 n = 0) const;
3029 bool		HasInt32(const char *, int32 n = 0) const;
3030 bool		HasInt64(const char *, int32 n = 0) const;
3031 bool		HasBool(const char *, int32 n = 0) const;
3032 bool		HasFloat(const char *, int32 n = 0) const;
3033 bool		HasDouble(const char *, int32 n = 0) const;
3034 bool		HasPointer(const char *, int32 n = 0) const;
3035 bool		HasMessenger(const char *, int32 n = 0) const;
3036 bool		HasRef(const char *, int32 n = 0) const;
3037 bool		HasMessage(const char *, int32 n = 0) const;
3038 bool		HasFlat(const char *, const BFlattenable *) const;
3039 bool		HasFlat(const char *,int32 ,const BFlattenable *) const;
3040 bool		HasData(const char *, type_code , int32 n = 0) const;
3041 BRect		FindRect(const char *, int32 n = 0) const;
3042 BPoint		FindPoint(const char *, int32 n = 0) const;
3043 const char	*FindString(const char *, int32 n = 0) const;
3044 int8		FindInt8(const char *, int32 n = 0) const;
3045 int16		FindInt16(const char *, int32 n = 0) const;*/
3046 //------------------------------------------------------------------------------
3047 int32 BMessage::FindInt32(const char *name, int32 index) const
3048 {
3049 	int32 anInt32 = 0;
3050 
3051 	BMessage::FindInt32(name, index, &anInt32);
3052 
3053 	return anInt32;
3054 }
3055 //------------------------------------------------------------------------------
3056 /*int64		FindInt64(const char *, int32 n = 0) const;
3057 bool		FindBool(const char *, int32 n = 0) const;
3058 float		FindFloat(const char *, int32 n = 0) const;
3059 double		FindDouble(const char *, int32 n = 0) const;*/
3060 //------------------------------------------------------------------------------
3061 BMessage::BMessage(BMessage *a_message)
3062 {
3063 	*this=*a_message;
3064 }
3065 //------------------------------------------------------------------------------
3066 void BMessage::_ReservedMessage1() {}
3067 void BMessage::_ReservedMessage2() {}
3068 void BMessage::_ReservedMessage3() {}
3069 //------------------------------------------------------------------------------
3070 void BMessage::init_data()
3071 {
3072 	what = 0;
3073 
3074 	link = NULL;
3075 	fTarget = -1;
3076 	fOriginal = NULL;
3077 	fChangeCount = 0;
3078 	fCurSpecifier = -1;
3079 	fPtrOffset = 0;
3080 
3081 	fEntries = NULL;
3082 
3083 	fReplyTo.port = -1;
3084 	fReplyTo.target = -1;
3085 	fReplyTo.team = -1;
3086 	fReplyTo.preferred = false;
3087 
3088 	fPreferred = false;
3089 	fReplyRequired = false;
3090 	fReplyDone = false;
3091 	fIsReply = false;
3092 	fWasDelivered = false;
3093 	fReadOnly = false;
3094 	fHasSpecifiers = false;
3095 }
3096 //------------------------------------------------------------------------------
3097 //	These are not declared in the header anymore and aren't actually used by the
3098 //	"old" implementation.
3099 #if 0
3100 int32 BMessage::flatten_hdr(uchar *result, ssize_t size, uchar flags) const
3101 {
3102 	return -1;
3103 }
3104 //------------------------------------------------------------------------------
3105 status_t BMessage::real_flatten(char *result, ssize_t size, uchar flags) const
3106 {
3107 	return B_ERROR;
3108 }
3109 //------------------------------------------------------------------------------
3110 status_t BMessage::real_flatten(BDataIO *stream, ssize_t size,
3111 								uchar flags) const
3112 {
3113 	return B_ERROR;
3114 }
3115 #endif
3116 //------------------------------------------------------------------------------
3117 char* BMessage::stack_flatten(char* stack_ptr, ssize_t stack_size,
3118 							  bool incl_reply, ssize_t* size) const
3119 {
3120 	return NULL;
3121 }
3122 //------------------------------------------------------------------------------
3123 ssize_t BMessage::calc_size(uchar flags) const
3124 {
3125 	return -1;
3126 }
3127 //------------------------------------------------------------------------------
3128 ssize_t BMessage::calc_hdr_size(uchar flags) const
3129 {
3130 	return -1;
3131 }
3132 //------------------------------------------------------------------------------
3133 ssize_t BMessage::min_hdr_size() const
3134 {
3135 	return -1;
3136 }
3137 //------------------------------------------------------------------------------
3138 status_t BMessage::nfind_data(const char *name, type_code type, int32 index,
3139 							  const void **data, ssize_t *data_size) const
3140 {
3141 	return B_ERROR;
3142 }
3143 //------------------------------------------------------------------------------
3144 status_t BMessage::copy_data(const char *name, type_code type, int32 index,
3145 							 void *data, ssize_t data_size) const
3146 {
3147 	return B_ERROR;
3148 }
3149 //------------------------------------------------------------------------------
3150 status_t BMessage::_send_(port_id port, int32 token, bool preferred,
3151 						  bigtime_t timeout, bool reply_required,
3152 						  BMessenger &reply_to) const
3153 {
3154 	/*_set_message_target_(this, token, preferred);
3155 	_set_message_reply_(this, reply_to);
3156 
3157 	int32 size;
3158 	char *buffer;
3159 
3160 	write_port_etc(port, what, buffer, size, B_TIMEOUT, timeout);*/
3161 
3162 	return B_ERROR;
3163 }
3164 //------------------------------------------------------------------------------
3165 status_t BMessage::send_message(port_id port, team_id port_owner, int32 token,
3166 								bool preferred, BMessage *reply,
3167 								bigtime_t send_timeout,
3168 								bigtime_t reply_timeout) const
3169 {
3170 	return B_ERROR;
3171 }
3172 //------------------------------------------------------------------------------
3173 BMessage::entry_hdr * BMessage::entry_find(const char *name, uint32 type,
3174 											status_t *result) const
3175 {
3176 	for (entry_hdr *entry = fEntries; entry != NULL; entry = entry->fNext)
3177 		if (entry->fType ==type && entry->fNameLength == strlen(name) &&
3178 			strncmp(entry->fName, name, entry->fNameLength) == 0)
3179 		{
3180 			if (result)
3181 				*result = B_OK;
3182 
3183 			return entry;
3184 		}
3185 
3186 	if (result)
3187 		*result = B_NAME_NOT_FOUND;
3188 
3189 	return NULL;
3190 }
3191 //------------------------------------------------------------------------------
3192 void BMessage::entry_remove(entry_hdr *entry)
3193 {
3194 	if (entry == fEntries)
3195 		fEntries = entry->fNext;
3196 	else
3197 	{
3198 		for (entry_hdr *entry_ptr = fEntries; entry_ptr != NULL; entry_ptr = entry_ptr->fNext)
3199 			if (entry_ptr->fNext == entry)
3200 				entry_ptr->fNext = entry->fNext;
3201 	}
3202 }
3203 //------------------------------------------------------------------------------
3204 void *BMessage::da_create(int32 header_size, int32 chunk_size, bool fixed,
3205 						  int32 nchunks)
3206 {
3207 	int size = da_calc_size(header_size, chunk_size, fixed, nchunks);
3208 
3209 	dyn_array *da = (dyn_array*)new char[size];
3210 
3211 	da->fLogicalBytes = 0;
3212 	da->fPhysicalBytes = size - sizeof(dyn_array) - header_size;
3213 
3214 	if ( fixed )
3215 		da->fChunkSize = chunk_size;
3216 	else
3217 		da->fChunkSize = 0;
3218 
3219 	da->fCount = 0;
3220 	da->fEntryHdrSize = header_size;
3221 
3222 	return da;
3223 }
3224 //------------------------------------------------------------------------------
3225 status_t BMessage::da_add_data(dyn_array **da, const void *data, int32 size )
3226 {
3227 //	_ASSERT(_CrtCheckMemory());
3228 
3229 	int32 new_size = (*da)->fLogicalBytes + ((*da)->fChunkSize ? (*da)->fChunkSize :
3230 		da_pad_8(size + da_chunk_hdr_size()));
3231 
3232 	if (new_size > (*da)->fPhysicalBytes)
3233 		da_grow(da, new_size - (*da)->fPhysicalBytes);
3234 
3235 	void *ptr = da_find_data(*da, (*da)->fCount++, NULL);
3236 
3237 	memcpy(ptr, data, size);
3238 
3239 	if ((*da)->fChunkSize)
3240 		(*da)->fLogicalBytes += size;
3241 	else
3242 	{
3243 		da_chunk_ptr(ptr)->fDataSize = size;
3244 		(*da)->fLogicalBytes += da_chunk_size(da_chunk_ptr(ptr));
3245 	}
3246 
3247 //	_ASSERT(_CrtCheckMemory());
3248 
3249 	return B_OK;
3250 }
3251 //------------------------------------------------------------------------------
3252 void *BMessage::da_find_data(dyn_array *da, int32 index, int32 *size) const
3253 {
3254 	if (da->fChunkSize)
3255 	{
3256 		if (size)
3257 			*size = da->fChunkSize;
3258 
3259 		return (char*)da_start_of_data(da) + index * da->fChunkSize;
3260 	}
3261 	else
3262 	{
3263 		var_chunk *chunk = da_first_chunk(da);
3264 
3265 		for (int i = 0; i < index; i++)
3266 			chunk = da_next_chunk(chunk);
3267 
3268 		if (size)
3269 			*size = chunk->fDataSize;
3270 
3271 		return chunk->fData;
3272 	}
3273 }
3274 //------------------------------------------------------------------------------
3275 status_t BMessage::da_delete_data(dyn_array **pda, int32 index)
3276 {
3277 	return 0;
3278 }
3279 //------------------------------------------------------------------------------
3280 status_t BMessage::da_replace_data(dyn_array **pda, int32 index,
3281 								   const void *data, int32 dsize)
3282 {
3283 	void *ptr = da_find_data(*pda, index, NULL);
3284 
3285 	memcpy(ptr, data, dsize);
3286 
3287 	return B_OK;
3288 }
3289 //------------------------------------------------------------------------------
3290 int32 BMessage::da_calc_size(int32 hdr_size, int32 chunksize, bool is_fixed,
3291 							  int32 nchunks) const
3292 {
3293 	int size = sizeof(dyn_array) + hdr_size;
3294 
3295 	if (is_fixed)
3296 		size += chunksize * nchunks;
3297 	else
3298 		size += (chunksize + da_chunk_hdr_size()) * nchunks;
3299 
3300 	return size;
3301 }
3302 //------------------------------------------------------------------------------
3303 void *BMessage::da_grow(dyn_array **pda, int32 increase)
3304 {
3305 	dyn_array *da = (dyn_array*)new char[da_total_size(*pda) + increase];
3306 	dyn_array *old_da = *pda;
3307 
3308 	memcpy(da, *pda, da_total_size(*pda));
3309 
3310 	*pda = da;
3311 	(*pda)->fPhysicalBytes += increase;
3312 
3313 	entry_remove((entry_hdr*)old_da);
3314 
3315 	delete old_da;
3316 
3317 	((entry_hdr*)*pda)->fNext = fEntries;
3318 	fEntries = (entry_hdr*)*pda;
3319 
3320 	return *pda;
3321 }
3322 //------------------------------------------------------------------------------
3323 void BMessage::da_dump(dyn_array *da)
3324 {
3325 	entry_hdr *entry = (entry_hdr*)da;
3326 
3327 	printf("\tLogicalBytes=%d\n\tPhysicalBytes=%d\n\tChunkSize=%d\n\tCount=%d\n\tEntryHdrSize=%d\n",
3328 		entry->fLogicalBytes, entry->fPhysicalBytes, entry->fChunkSize, entry->fCount,
3329 		entry->fEntryHdrSize);
3330 	printf("\tNext=%p\n\tType=%c%c%c%c\n\tNameLength=%d\n\tName=%s\n",
3331 		entry->fNext, (entry->fType & 0xFF000000) >> 24, (entry->fType & 0x00FF0000) >> 16,
3332 			(entry->fType & 0x0000FF00) >> 8, entry->fType & 0x000000FF, entry->fNameLength,
3333 			entry->fName);
3334 
3335 	printf("\tData=");
3336 
3337 	switch (entry->fType)
3338 	{
3339 		case B_BOOL_TYPE:
3340 		{
3341 			printf("%s", *(bool*)da_find_data(entry, 0, NULL) ? "true" : "false");
3342 
3343 			for (int i = 1; i < entry->fCount; i++)
3344 				printf(", %s", *(bool*)da_find_data ( entry, i, NULL ) ? "true" : "false");
3345 			break;
3346 		}
3347 		case B_INT32_TYPE:
3348 		{
3349 			printf("%d", *(int32*)da_find_data(entry, 0, NULL));
3350 
3351 			for (int i = 1; i < entry->fCount; i++)
3352 				printf(", %d", *(int32*)da_find_data(entry, i, NULL));
3353 			break;
3354 		}
3355 		case B_FLOAT_TYPE:
3356 		{
3357 			printf("%f", *(float*)da_find_data(entry, 0, NULL));
3358 
3359 			for (int i = 1; i < entry->fCount; i++)
3360 				printf(", %f", *(float*)da_find_data ( entry, i, NULL));
3361 			break;
3362 		}
3363 		case B_STRING_TYPE:
3364 		{
3365 			printf("%s", da_find_data(entry, 0, NULL));
3366 
3367 			for (int i = 1; i < entry->fCount; i++)
3368 				printf(", %s", da_find_data(entry, i, NULL));
3369 			break;
3370 		}
3371 		case B_POINT_TYPE:
3372 		{
3373 			float *data = (float*)da_find_data(entry, 0, NULL);
3374 
3375 			printf("[%f,%f]", data[0], data[1]);
3376 
3377 			for (int i = 1; i < entry->fCount; i++)
3378 			{
3379 				data = (float*)da_find_data ( entry, i, NULL);
3380 				printf(", [%f,%f]", data[0], data[1]);
3381 			}
3382 			break;
3383 		}
3384 		case B_RECT_TYPE:
3385 		{
3386 			float *data = (float*)da_find_data(entry, 0, NULL);
3387 
3388 			printf("[%f,%f,%f,%f]", data[0], data[1], data[2], data[3]);
3389 
3390 			for (int i = 1; i < entry->fCount; i++)
3391 			{
3392 				data = (float*)da_find_data ( entry, i, NULL);
3393 				printf(", [%f,%f,%f,%f]", data[0], data[1], data[2], data[3]);
3394 			}
3395 			break;
3396 		}
3397 	}
3398 
3399 	printf("\n");
3400 }
3401 //------------------------------------------------------------------------------
3402 void BMessage::da_swap_var_sized(dyn_array *da)
3403 {
3404 }
3405 //------------------------------------------------------------------------------
3406 void BMessage::da_swap_fixed_sized(dyn_array *da)
3407 {
3408 }
3409 //------------------------------------------------------------------------------
3410 
3411 #endif	// USING_TEMPLATE_MADNESS
3412