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