xref: /haiku/src/kits/app/Message.cpp (revision 81ec973846ea4816c53ed8901822e43c8b06878d)
1 /*
2  * Copyright 2005-2014 Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Michael Lotz, mmlr@mlotz.ch
7  */
8 
9 
10 #include <Message.h>
11 #include <MessageAdapter.h>
12 #include <MessagePrivate.h>
13 #include <MessageUtils.h>
14 
15 #include <DirectMessageTarget.h>
16 #include <MessengerPrivate.h>
17 #include <TokenSpace.h>
18 #include <util/KMessage.h>
19 
20 #include <Alignment.h>
21 #include <Application.h>
22 #include <AppMisc.h>
23 #include <BlockCache.h>
24 #include <Entry.h>
25 #include <MessageQueue.h>
26 #include <Messenger.h>
27 #include <Path.h>
28 #include <Point.h>
29 #include <Rect.h>
30 #include <String.h>
31 #include <StringList.h>
32 
33 #include <assert.h>
34 #include <ctype.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 
39 #include "tracing_config.h"
40 	// kernel tracing configuration
41 
42 //#define VERBOSE_DEBUG_OUTPUT
43 #ifdef VERBOSE_DEBUG_OUTPUT
44 #define DEBUG_FUNCTION_ENTER	\
45 	debug_printf("msg thread: %ld; this: %p; header: %p; fields: %p;" \
46 		" data: %p; what: 0x%08lx '%.4s'; line: %d; func: %s\n", \
47 		find_thread(NULL), this, fHeader, fFields, fData, what, (char*)&what, \
48 		__LINE__, __PRETTY_FUNCTION__);
49 
50 #define DEBUG_FUNCTION_ENTER2	\
51 	debug_printf("msg thread: %ld; line: %d: func: %s\n", find_thread(NULL), \
52 		__LINE__, __PRETTY_FUNCTION__);
53 #else
54 #define DEBUG_FUNCTION_ENTER	/* nothing */
55 #define DEBUG_FUNCTION_ENTER2	/* nothing */
56 #endif
57 
58 #if BMESSAGE_TRACING
59 #	define KTRACE(format...)	ktrace_printf(format)
60 #else
61 #	define KTRACE(format...)
62 #endif
63 
64 
65 const char* B_SPECIFIER_ENTRY = "specifiers";
66 const char* B_PROPERTY_ENTRY = "property";
67 const char* B_PROPERTY_NAME_ENTRY = "name";
68 
69 
70 static status_t handle_reply(port_id replyPort, int32* pCode,
71 	bigtime_t timeout, BMessage* reply);
72 
73 
74 extern "C" {
75 	// private os function to set the owning team of an area
76 	status_t _kern_transfer_area(area_id area, void** _address,
77 		uint32 addressSpec, team_id target);
78 }
79 
80 
81 BBlockCache* BMessage::sMsgCache = NULL;
82 port_id BMessage::sReplyPorts[sNumReplyPorts];
83 int32 BMessage::sReplyPortInUse[sNumReplyPorts];
84 
85 
86 template<typename Type>
87 static void
88 print_to_stream_type(uint8* pointer)
89 {
90 	Type* item = (Type*)pointer;
91 	item->PrintToStream();
92 }
93 
94 
95 template<typename Type>
96 static void
97 print_type(const char* format, uint8* pointer)
98 {
99 	Type* item = (Type*)pointer;
100 	printf(format,* item,* item);
101 }
102 
103 
104 template<typename Type>
105 static void
106 print_type3(const char* format, uint8* pointer)
107 {
108 	Type* item = (Type*)pointer;
109 	printf(format, *item, *item, *item);
110 }
111 
112 
113 static status_t
114 handle_reply(port_id replyPort, int32* _code, bigtime_t timeout,
115 	BMessage* reply)
116 {
117 	DEBUG_FUNCTION_ENTER2;
118 	ssize_t size;
119 	do {
120 		size = port_buffer_size_etc(replyPort, B_RELATIVE_TIMEOUT, timeout);
121 	} while (size == B_INTERRUPTED);
122 
123 	if (size < 0)
124 		return size;
125 
126 	status_t result;
127 	char* buffer = (char*)malloc(size);
128 	if (buffer == NULL)
129 		return B_NO_MEMORY;
130 
131 	do {
132 		result = read_port(replyPort, _code, buffer, size);
133 	} while (result == B_INTERRUPTED);
134 
135 	if (result < 0 || *_code != kPortMessageCode) {
136 		free(buffer);
137 		return result < 0 ? result : B_ERROR;
138 	}
139 
140 	result = reply->Unflatten(buffer);
141 	free(buffer);
142 	return result;
143 }
144 
145 
146 //	#pragma mark -
147 
148 
149 BMessage::BMessage()
150 {
151 	DEBUG_FUNCTION_ENTER;
152 	_InitCommon(true);
153 }
154 
155 
156 BMessage::BMessage(BMessage* other)
157 {
158 	DEBUG_FUNCTION_ENTER;
159 	_InitCommon(false);
160 	*this = *other;
161 }
162 
163 
164 BMessage::BMessage(uint32 _what)
165 {
166 	DEBUG_FUNCTION_ENTER;
167 	_InitCommon(true);
168 	fHeader->what = what = _what;
169 }
170 
171 
172 BMessage::BMessage(const BMessage& other)
173 {
174 	DEBUG_FUNCTION_ENTER;
175 	_InitCommon(false);
176 	*this = other;
177 }
178 
179 
180 BMessage::~BMessage()
181 {
182 	DEBUG_FUNCTION_ENTER;
183 	_Clear();
184 }
185 
186 
187 BMessage&
188 BMessage::operator=(const BMessage& other)
189 {
190 	DEBUG_FUNCTION_ENTER;
191 
192 	if (this == &other)
193 		return *this;
194 
195 	_Clear();
196 
197 	fHeader = (message_header*)malloc(sizeof(message_header));
198 	if (fHeader == NULL)
199 		return *this;
200 
201 	if (other.fHeader == NULL)
202 		return *this;
203 
204 	memcpy(fHeader, other.fHeader, sizeof(message_header));
205 
206 	// Clear some header flags inherited from the original message that don't
207 	// apply to the clone.
208 	fHeader->flags &= ~(MESSAGE_FLAG_REPLY_REQUIRED | MESSAGE_FLAG_REPLY_DONE
209 		| MESSAGE_FLAG_IS_REPLY | MESSAGE_FLAG_WAS_DELIVERED
210 		| MESSAGE_FLAG_PASS_BY_AREA);
211 	// Note, that BeOS R5 seems to keep the reply info.
212 
213 	if (fHeader->field_count > 0) {
214 		size_t fieldsSize = fHeader->field_count * sizeof(field_header);
215 		if (other.fFields != NULL)
216 			fFields = (field_header*)malloc(fieldsSize);
217 
218 		if (fFields == NULL) {
219 			fHeader->field_count = 0;
220 			fHeader->data_size = 0;
221 		} else
222 			memcpy(fFields, other.fFields, fieldsSize);
223 	}
224 
225 	if (fHeader->data_size > 0) {
226 		if (other.fData != NULL)
227 			fData = (uint8*)malloc(fHeader->data_size);
228 
229 		if (fData == NULL) {
230 			fHeader->field_count = 0;
231 			free(fFields);
232 			fFields = NULL;
233 		} else
234 			memcpy(fData, other.fData, fHeader->data_size);
235 	}
236 
237 	fHeader->what = what = other.what;
238 	fHeader->message_area = -1;
239 	fFieldsAvailable = 0;
240 	fDataAvailable = 0;
241 
242 	return *this;
243 }
244 
245 
246 void*
247 BMessage::operator new(size_t size)
248 {
249 	DEBUG_FUNCTION_ENTER2;
250 	return sMsgCache->Get(size);
251 }
252 
253 
254 void*
255 BMessage::operator new(size_t size, const std::nothrow_t& noThrow)
256 {
257 	DEBUG_FUNCTION_ENTER2;
258 	return sMsgCache->Get(size);
259 }
260 
261 
262 void*
263 BMessage::operator new(size_t, void* pointer)
264 {
265 	DEBUG_FUNCTION_ENTER2;
266 	return pointer;
267 }
268 
269 
270 void
271 BMessage::operator delete(void* pointer, size_t size)
272 {
273 	DEBUG_FUNCTION_ENTER2;
274 	if (pointer == NULL)
275 		return;
276 	sMsgCache->Save(pointer, size);
277 }
278 
279 
280 bool
281 BMessage::HasSameData(const BMessage& other, bool ignoreFieldOrder,
282 	bool deep) const
283 {
284 	if (this == &other)
285 		return true;
286 
287 	if (fHeader == NULL)
288 		return other.fHeader == NULL;
289 
290 	if (fHeader->field_count != other.fHeader->field_count)
291 		return false;
292 
293 	for (uint32 i = 0; i < fHeader->field_count; i++) {
294 		field_header* field = &fFields[i];
295 		field_header* otherField = NULL;
296 
297 		const char* name = (const char*)fData + field->offset;
298 		if (ignoreFieldOrder) {
299 			if (other._FindField(name, B_ANY_TYPE, &otherField) != B_OK)
300 				return false;
301 		} else {
302 			otherField = &other.fFields[i];
303 			if (otherField->name_length != field->name_length)
304 				return false;
305 
306 			const char* otherName = (const char*)other.fData
307 				+ otherField->offset;
308 			if (strncmp(name, otherName, field->name_length) != 0)
309 				return false;
310 		}
311 
312 		if (otherField->type != field->type
313 			|| otherField->count != field->count) {
314 			return false;
315 		}
316 
317 		uint8* data = fData + field->offset + field->name_length;
318 		uint8* otherData = other.fData + otherField->offset
319 			+ otherField->name_length;
320 
321 		bool needsMemCompare = true;
322 		if (deep && field->type == B_MESSAGE_TYPE) {
323 			BMessage message, otherMessage;
324 			if (message.Unflatten((const char*)data) == B_OK
325 				&& otherMessage.Unflatten((const char*)otherData) == B_OK) {
326 				if (!message.HasSameData(ignoreFieldOrder, deep))
327 					return false;
328 				needsMemCompare = false;
329 			}
330 		}
331 
332 		if (needsMemCompare) {
333 			if (otherField->data_size != field->data_size)
334 				return false;
335 			if (memcmp(data, otherData, field->data_size) != 0)
336 				return false;
337 		}
338 	}
339 
340 	return true;
341 }
342 
343 
344 status_t
345 BMessage::_InitCommon(bool initHeader)
346 {
347 	DEBUG_FUNCTION_ENTER;
348 	what = 0;
349 
350 	fHeader = NULL;
351 	fFields = NULL;
352 	fData = NULL;
353 
354 	fFieldsAvailable = 0;
355 	fDataAvailable = 0;
356 
357 	fOriginal = NULL;
358 	fQueueLink = NULL;
359 
360 	fArchivingPointer = NULL;
361 
362 	if (initHeader)
363 		return _InitHeader();
364 
365 	return B_OK;
366 }
367 
368 
369 status_t
370 BMessage::_InitHeader()
371 {
372 	DEBUG_FUNCTION_ENTER;
373 	if (fHeader == NULL) {
374 		fHeader = (message_header*)malloc(sizeof(message_header));
375 		if (fHeader == NULL)
376 			return B_NO_MEMORY;
377 	}
378 
379 	memset(fHeader, 0, sizeof(message_header) - sizeof(fHeader->hash_table));
380 
381 	fHeader->format = MESSAGE_FORMAT_HAIKU;
382 	fHeader->flags = MESSAGE_FLAG_VALID;
383 	fHeader->what = what;
384 	fHeader->current_specifier = -1;
385 	fHeader->message_area = -1;
386 
387 	fHeader->target = B_NULL_TOKEN;
388 	fHeader->reply_target = B_NULL_TOKEN;
389 	fHeader->reply_port = -1;
390 	fHeader->reply_team = -1;
391 
392 	// initializing the hash table to -1 because 0 is a valid index
393 	fHeader->hash_table_size = MESSAGE_BODY_HASH_TABLE_SIZE;
394 	memset(&fHeader->hash_table, 255, sizeof(fHeader->hash_table));
395 	return B_OK;
396 }
397 
398 
399 status_t
400 BMessage::_Clear()
401 {
402 	DEBUG_FUNCTION_ENTER;
403 	if (fHeader != NULL) {
404 		// We're going to destroy all information of this message. If there's
405 		// still someone waiting for a reply to this message, we have to send
406 		// one now.
407 		if (IsSourceWaiting())
408 			SendReply(B_NO_REPLY);
409 
410 		if (fHeader->message_area >= 0)
411 			_Dereference();
412 
413 		free(fHeader);
414 		fHeader = NULL;
415 	}
416 
417 	free(fFields);
418 	fFields = NULL;
419 	free(fData);
420 	fData = NULL;
421 
422 	fArchivingPointer = NULL;
423 
424 	fFieldsAvailable = 0;
425 	fDataAvailable = 0;
426 
427 	delete fOriginal;
428 	fOriginal = NULL;
429 
430 	return B_OK;
431 }
432 
433 
434 status_t
435 BMessage::GetInfo(type_code typeRequested, int32 index, char** nameFound,
436 	type_code* typeFound, int32* countFound) const
437 {
438 	DEBUG_FUNCTION_ENTER;
439 	if (fHeader == NULL)
440 		return B_NO_INIT;
441 
442 	if (index < 0 || (uint32)index >= fHeader->field_count)
443 		return B_BAD_INDEX;
444 
445 	if (typeRequested == B_ANY_TYPE) {
446 		if (nameFound != NULL)
447 			*nameFound = (char*)fData + fFields[index].offset;
448 		if (typeFound != NULL)
449 			*typeFound = fFields[index].type;
450 		if (countFound != NULL)
451 			*countFound = fFields[index].count;
452 		return B_OK;
453 	}
454 
455 	int32 counter = -1;
456 	field_header* field = fFields;
457 	for (uint32 i = 0; i < fHeader->field_count; i++, field++) {
458 		if (field->type == typeRequested)
459 			counter++;
460 
461 		if (counter == index) {
462 			if (nameFound != NULL)
463 				*nameFound = (char*)fData + field->offset;
464 			if (typeFound != NULL)
465 				*typeFound = field->type;
466 			if (countFound != NULL)
467 				*countFound = field->count;
468 			return B_OK;
469 		}
470 	}
471 
472 	if (counter == -1)
473 		return B_BAD_TYPE;
474 
475 	return B_BAD_INDEX;
476 }
477 
478 
479 status_t
480 BMessage::GetInfo(const char* name, type_code* typeFound,
481 	int32* countFound) const
482 {
483 	DEBUG_FUNCTION_ENTER;
484 	if (countFound != NULL)
485 		*countFound = 0;
486 
487 	field_header* field = NULL;
488 	status_t result = _FindField(name, B_ANY_TYPE, &field);
489 	if (result != B_OK)
490 		return result;
491 
492 	if (typeFound != NULL)
493 		*typeFound = field->type;
494 	if (countFound != NULL)
495 		*countFound = field->count;
496 
497 	return B_OK;
498 }
499 
500 
501 status_t
502 BMessage::GetInfo(const char* name, type_code* typeFound, bool* fixedSize)
503 	const
504 {
505 	DEBUG_FUNCTION_ENTER;
506 	field_header* field = NULL;
507 	status_t result = _FindField(name, B_ANY_TYPE, &field);
508 	if (result != B_OK)
509 		return result;
510 
511 	if (typeFound != NULL)
512 		*typeFound = field->type;
513 	if (fixedSize != NULL)
514 		*fixedSize = (field->flags & FIELD_FLAG_FIXED_SIZE) != 0;
515 
516 	return B_OK;
517 }
518 
519 
520 status_t
521 BMessage::GetInfo(const char* name, type_code* typeFound, int32* countFound,
522 	bool* fixedSize) const
523 {
524 	DEBUG_FUNCTION_ENTER;
525 	field_header* field = NULL;
526 	status_t result = _FindField(name, B_ANY_TYPE, &field);
527 	if (result != B_OK)
528 		return result;
529 
530 	if (typeFound != NULL)
531 		*typeFound = field->type;
532 	if (countFound != NULL)
533 		*countFound = field->count;
534 	if (fixedSize != NULL)
535 		*fixedSize = (field->flags & FIELD_FLAG_FIXED_SIZE) != 0;
536 
537 	return B_OK;
538 }
539 
540 
541 int32
542 BMessage::CountNames(type_code type) const
543 {
544 	DEBUG_FUNCTION_ENTER;
545 	if (fHeader == NULL)
546 		return 0;
547 
548 	if (type == B_ANY_TYPE)
549 		return fHeader->field_count;
550 
551 	int32 count = 0;
552 	field_header* field = fFields;
553 	for (uint32 i = 0; i < fHeader->field_count; i++, field++) {
554 		if (field->type == type)
555 			count++;
556 	}
557 
558 	return count;
559 }
560 
561 
562 bool
563 BMessage::IsEmpty() const
564 {
565 	DEBUG_FUNCTION_ENTER;
566 	return fHeader == NULL || fHeader->field_count == 0;
567 }
568 
569 
570 bool
571 BMessage::IsSystem() const
572 {
573 	DEBUG_FUNCTION_ENTER;
574 	char a = char(what >> 24);
575 	char b = char(what >> 16);
576 	char c = char(what >> 8);
577 	char d = char(what);
578 
579 	// The BeBook says:
580 	//		... we've adopted a strict convention for assigning values to all
581 	//		Be-defined constants.  The value assigned will always be formed by
582 	//		combining four characters into a multicharacter constant, with the
583 	//		characters limited to uppercase letters and the underbar
584 	// Between that and what's in AppDefs.h, this algo seems like a safe bet:
585 	if (a == '_' && isupper(b) && isupper(c) && isupper(d))
586 		return true;
587 
588 	return false;
589 }
590 
591 
592 bool
593 BMessage::IsReply() const
594 {
595 	DEBUG_FUNCTION_ENTER;
596 	return fHeader != NULL && (fHeader->flags & MESSAGE_FLAG_IS_REPLY) != 0;
597 }
598 
599 
600 void
601 BMessage::PrintToStream() const
602 {
603 	_PrintToStream("");
604 	printf("}\n");
605 }
606 
607 
608 void
609 BMessage::_PrintToStream(const char* indent) const
610 {
611 	DEBUG_FUNCTION_ENTER;
612 
613 	int32 value = B_BENDIAN_TO_HOST_INT32(what);
614 	printf("BMessage(");
615 	if (isprint(*(char*)&value))
616 		printf("'%.4s'", (char*)&value);
617 	else
618 		printf("0x%" B_PRIx32, what);
619 	printf(") {\n");
620 
621 	if (fHeader == NULL || fFields == NULL || fData == NULL)
622 		return;
623 
624 	field_header* field = fFields;
625 	for (uint32 i = 0; i < fHeader->field_count; i++, field++) {
626 		value = B_BENDIAN_TO_HOST_INT32(field->type);
627 		ssize_t size = 0;
628 		if ((field->flags & FIELD_FLAG_FIXED_SIZE) != 0 && field->count > 0)
629 			size = field->data_size / field->count;
630 
631 		uint8* pointer = fData + field->offset + field->name_length;
632 		for (uint32 j = 0; j < field->count; j++) {
633 			if (field->count == 1) {
634 				printf("%s        %s = ", indent,
635 					(char*)(fData + field->offset));
636 			} else {
637 				printf("%s        %s[%" B_PRIu32 "] = ", indent,
638 					(char*)(fData + field->offset), j);
639 			}
640 
641 			if ((field->flags & FIELD_FLAG_FIXED_SIZE) == 0) {
642 				size = *(uint32*)pointer;
643 				pointer += sizeof(uint32);
644 			}
645 
646 			switch (field->type) {
647 				case B_RECT_TYPE:
648 					print_to_stream_type<BRect>(pointer);
649 					break;
650 
651 				case B_POINT_TYPE:
652 					print_to_stream_type<BPoint>(pointer);
653 					break;
654 
655 				case B_STRING_TYPE:
656 					printf("string(\"%.*s\", %ld bytes)\n", (int)size,
657 						(char*)pointer, (long)size);
658 					break;
659 
660 				case B_INT8_TYPE:
661 					print_type3<int8>("int8(0x%hx or %d or '%c')\n",
662 						pointer);
663 					break;
664 
665 				case B_UINT8_TYPE:
666 					print_type3<uint8>("uint8(0x%hx or %u or '%c')\n",
667 						pointer);
668 					break;
669 
670 				case B_INT16_TYPE:
671 					print_type<int16>("int16(0x%x or %d)\n", pointer);
672 					break;
673 
674 				case B_UINT16_TYPE:
675 					print_type<uint16>("uint16(0x%x or %u\n", pointer);
676 					break;
677 
678 				case B_INT32_TYPE:
679 					print_type<int32>("int32(0x%lx or %ld)\n", pointer);
680 					break;
681 
682 				case B_UINT32_TYPE:
683 					print_type<uint32>("uint32(0x%lx or %lu\n", pointer);
684 					break;
685 
686 				case B_INT64_TYPE:
687 					print_type<int64>("int64(0x%Lx or %Ld)\n", pointer);
688 					break;
689 
690 				case B_UINT64_TYPE:
691 					print_type<uint64>("uint64(0x%Lx or %Ld\n", pointer);
692 					break;
693 
694 				case B_BOOL_TYPE:
695 					printf("bool(%s)\n", *((bool*)pointer) != 0
696 						? "true" : "false");
697 					break;
698 
699 				case B_FLOAT_TYPE:
700 					print_type<float>("float(%.4f)\n", pointer);
701 					break;
702 
703 				case B_DOUBLE_TYPE:
704 					print_type<double>("double(%.8f)\n", pointer);
705 					break;
706 
707 				case B_REF_TYPE:
708 				{
709 					entry_ref ref;
710 					BPrivate::entry_ref_unflatten(&ref, (char*)pointer, size);
711 
712 					printf("entry_ref(device=%d, directory=%" B_PRIdINO
713 						", name=\"%s\", ", (int)ref.device, ref.directory,
714 						ref.name);
715 
716 					BPath path(&ref);
717 					printf("path=\"%s\")\n", path.Path());
718 					break;
719 				}
720 
721 				case B_MESSAGE_TYPE:
722 				{
723 					char buffer[1024];
724 					snprintf(buffer, sizeof(buffer), "%s        ", indent);
725 
726 					BMessage message;
727 					status_t result = message.Unflatten((const char*)pointer);
728 					if (result != B_OK) {
729 						printf("failed unflatten: %s\n", strerror(result));
730 						break;
731 					}
732 
733 					message._PrintToStream(buffer);
734 					printf("%s        }\n", indent);
735 					break;
736 				}
737 
738 				default:
739 				{
740 					printf("(type = '%.4s')(size = %ld)\n", (char*)&value,
741 						(long)size);
742 					break;
743 				}
744 			}
745 
746 			pointer += size;
747 		}
748 	}
749 }
750 
751 
752 status_t
753 BMessage::Rename(const char* oldEntry, const char* newEntry)
754 {
755 	DEBUG_FUNCTION_ENTER;
756 	if (oldEntry == NULL || newEntry == NULL)
757 		return B_BAD_VALUE;
758 
759 	if (fHeader == NULL)
760 		return B_NO_INIT;
761 
762 	status_t result;
763 	if (fHeader->message_area >= 0) {
764 		result = _CopyForWrite();
765 		if (result != B_OK)
766 			return result;
767 	}
768 
769 	uint32 hash = _HashName(oldEntry) % fHeader->hash_table_size;
770 	int32* nextField = &fHeader->hash_table[hash];
771 
772 	while (*nextField >= 0) {
773 		field_header* field = &fFields[*nextField];
774 
775 		if (strncmp((const char*)(fData + field->offset), oldEntry,
776 			field->name_length) == 0) {
777 			// nextField points to the field for oldEntry, save it and unlink
778 			int32 index = *nextField;
779 			*nextField = field->next_field;
780 			field->next_field = -1;
781 
782 			hash = _HashName(newEntry) % fHeader->hash_table_size;
783 			nextField = &fHeader->hash_table[hash];
784 			while (*nextField >= 0)
785 				nextField = &fFields[*nextField].next_field;
786 			*nextField = index;
787 
788 			int32 newLength = strlen(newEntry) + 1;
789 			result = _ResizeData(field->offset + 1,
790 				newLength - field->name_length);
791 			if (result != B_OK)
792 				return result;
793 
794 			memcpy(fData + field->offset, newEntry, newLength);
795 			field->name_length = newLength;
796 			return B_OK;
797 		}
798 
799 		nextField = &field->next_field;
800 	}
801 
802 	return B_NAME_NOT_FOUND;
803 }
804 
805 
806 bool
807 BMessage::WasDelivered() const
808 {
809 	DEBUG_FUNCTION_ENTER;
810 	return fHeader != NULL
811 		&& (fHeader->flags & MESSAGE_FLAG_WAS_DELIVERED) != 0;
812 }
813 
814 
815 bool
816 BMessage::IsSourceWaiting() const
817 {
818 	DEBUG_FUNCTION_ENTER;
819 	return fHeader != NULL
820 		&& (fHeader->flags & MESSAGE_FLAG_REPLY_REQUIRED) != 0
821 		&& (fHeader->flags & MESSAGE_FLAG_REPLY_DONE) == 0;
822 }
823 
824 
825 bool
826 BMessage::IsSourceRemote() const
827 {
828 	DEBUG_FUNCTION_ENTER;
829 	return fHeader != NULL
830 		&& (fHeader->flags & MESSAGE_FLAG_WAS_DELIVERED) != 0
831 		&& fHeader->reply_team != BPrivate::current_team();
832 }
833 
834 
835 BMessenger
836 BMessage::ReturnAddress() const
837 {
838 	DEBUG_FUNCTION_ENTER;
839 	if (fHeader == NULL || (fHeader->flags & MESSAGE_FLAG_WAS_DELIVERED) == 0)
840 		return BMessenger();
841 
842 	BMessenger messenger;
843 	BMessenger::Private(messenger).SetTo(fHeader->reply_team,
844 		fHeader->reply_port, fHeader->reply_target);
845 	return messenger;
846 }
847 
848 
849 const BMessage*
850 BMessage::Previous() const
851 {
852 	DEBUG_FUNCTION_ENTER;
853 	/* ToDo: test if the "_previous_" field is used in R5 */
854 	if (fOriginal == NULL) {
855 		fOriginal = new BMessage();
856 
857 		if (FindMessage("_previous_", fOriginal) != B_OK) {
858 			delete fOriginal;
859 			fOriginal = NULL;
860 		}
861 	}
862 
863 	return fOriginal;
864 }
865 
866 
867 bool
868 BMessage::WasDropped() const
869 {
870 	DEBUG_FUNCTION_ENTER;
871 	return fHeader != NULL
872 		&& (fHeader->flags & MESSAGE_FLAG_WAS_DROPPED) != 0;
873 }
874 
875 
876 BPoint
877 BMessage::DropPoint(BPoint* offset) const
878 {
879 	DEBUG_FUNCTION_ENTER;
880 	if (offset != NULL)
881 		*offset = FindPoint("_drop_offset_");
882 
883 	return FindPoint("_drop_point_");
884 }
885 
886 
887 status_t
888 BMessage::SendReply(uint32 command, BHandler* replyTo)
889 {
890 	DEBUG_FUNCTION_ENTER;
891 	BMessage message(command);
892 	return SendReply(&message, replyTo);
893 }
894 
895 
896 status_t
897 BMessage::SendReply(BMessage* reply, BHandler* replyTo, bigtime_t timeout)
898 {
899 	DEBUG_FUNCTION_ENTER;
900 	BMessenger messenger(replyTo);
901 	return SendReply(reply, messenger, timeout);
902 }
903 
904 
905 status_t
906 BMessage::SendReply(BMessage* reply, BMessenger replyTo, bigtime_t timeout)
907 {
908 	DEBUG_FUNCTION_ENTER;
909 	if (fHeader == NULL)
910 		return B_NO_INIT;
911 
912 	BMessenger messenger;
913 	BMessenger::Private messengerPrivate(messenger);
914 	messengerPrivate.SetTo(fHeader->reply_team, fHeader->reply_port,
915 		fHeader->reply_target);
916 
917 	if ((fHeader->flags & MESSAGE_FLAG_REPLY_REQUIRED) != 0) {
918 		if ((fHeader->flags & MESSAGE_FLAG_REPLY_DONE) != 0)
919 			return B_DUPLICATE_REPLY;
920 
921 		fHeader->flags |= MESSAGE_FLAG_REPLY_DONE;
922 		reply->fHeader->flags |= MESSAGE_FLAG_IS_REPLY;
923 		status_t result = messenger.SendMessage(reply, replyTo, timeout);
924 		reply->fHeader->flags &= ~MESSAGE_FLAG_IS_REPLY;
925 
926 		if (result != B_OK) {
927 			if (set_port_owner(messengerPrivate.Port(),
928 				messengerPrivate.Team()) == B_BAD_TEAM_ID) {
929 				delete_port(messengerPrivate.Port());
930 			}
931 		}
932 
933 		return result;
934 	}
935 
936 	// no reply required
937 	if ((fHeader->flags & MESSAGE_FLAG_WAS_DELIVERED) == 0)
938 		return B_BAD_REPLY;
939 
940 	reply->AddMessage("_previous_", this);
941 	reply->fHeader->flags |= MESSAGE_FLAG_IS_REPLY;
942 	status_t result = messenger.SendMessage(reply, replyTo, timeout);
943 	reply->fHeader->flags &= ~MESSAGE_FLAG_IS_REPLY;
944 	reply->RemoveName("_previous_");
945 	return result;
946 }
947 
948 
949 status_t
950 BMessage::SendReply(uint32 command, BMessage* replyToReply)
951 {
952 	DEBUG_FUNCTION_ENTER;
953 	BMessage message(command);
954 	return SendReply(&message, replyToReply);
955 }
956 
957 
958 status_t
959 BMessage::SendReply(BMessage* reply, BMessage* replyToReply,
960 	bigtime_t sendTimeout, bigtime_t replyTimeout)
961 {
962 	DEBUG_FUNCTION_ENTER;
963 	if (fHeader == NULL)
964 		return B_NO_INIT;
965 
966 	BMessenger messenger;
967 	BMessenger::Private messengerPrivate(messenger);
968 	messengerPrivate.SetTo(fHeader->reply_team, fHeader->reply_port,
969 		fHeader->reply_target);
970 
971 	if ((fHeader->flags & MESSAGE_FLAG_REPLY_REQUIRED) != 0) {
972 		if ((fHeader->flags & MESSAGE_FLAG_REPLY_DONE) != 0)
973 			return B_DUPLICATE_REPLY;
974 
975 		fHeader->flags |= MESSAGE_FLAG_REPLY_DONE;
976 		reply->fHeader->flags |= MESSAGE_FLAG_IS_REPLY;
977 		status_t result = messenger.SendMessage(reply, replyToReply,
978 			sendTimeout, replyTimeout);
979 		reply->fHeader->flags &= ~MESSAGE_FLAG_IS_REPLY;
980 
981 		if (result != B_OK) {
982 			if (set_port_owner(messengerPrivate.Port(),
983 				messengerPrivate.Team()) == B_BAD_TEAM_ID) {
984 				delete_port(messengerPrivate.Port());
985 			}
986 		}
987 
988 		return result;
989 	}
990 
991 	// no reply required
992 	if ((fHeader->flags & MESSAGE_FLAG_WAS_DELIVERED) == 0)
993 		return B_BAD_REPLY;
994 
995 	reply->AddMessage("_previous_", this);
996 	reply->fHeader->flags |= MESSAGE_FLAG_IS_REPLY;
997 	status_t result = messenger.SendMessage(reply, replyToReply, sendTimeout,
998 		replyTimeout);
999 	reply->fHeader->flags &= ~MESSAGE_FLAG_IS_REPLY;
1000 	reply->RemoveName("_previous_");
1001 	return result;
1002 }
1003 
1004 
1005 ssize_t
1006 BMessage::FlattenedSize() const
1007 {
1008 	DEBUG_FUNCTION_ENTER;
1009 	if (fHeader == NULL)
1010 		return B_NO_INIT;
1011 
1012 	return sizeof(message_header) + fHeader->field_count * sizeof(field_header)
1013 		+ fHeader->data_size;
1014 }
1015 
1016 
1017 status_t
1018 BMessage::Flatten(char* buffer, ssize_t size) const
1019 {
1020 	DEBUG_FUNCTION_ENTER;
1021 	if (buffer == NULL || size < 0)
1022 		return B_BAD_VALUE;
1023 
1024 	if (fHeader == NULL)
1025 		return B_NO_INIT;
1026 
1027 	if (size < FlattenedSize())
1028 		return B_BUFFER_OVERFLOW;
1029 
1030 	/* we have to sync the what code as it is a public member */
1031 	fHeader->what = what;
1032 
1033 	memcpy(buffer, fHeader, sizeof(message_header));
1034 	buffer += sizeof(message_header);
1035 
1036 	size_t fieldsSize = fHeader->field_count * sizeof(field_header);
1037 	memcpy(buffer, fFields, fieldsSize);
1038 	buffer += fieldsSize;
1039 
1040 	memcpy(buffer, fData, fHeader->data_size);
1041 
1042 	return B_OK;
1043 }
1044 
1045 
1046 status_t
1047 BMessage::Flatten(BDataIO* stream, ssize_t* size) const
1048 {
1049 	DEBUG_FUNCTION_ENTER;
1050 	if (stream == NULL)
1051 		return B_BAD_VALUE;
1052 
1053 	if (fHeader == NULL)
1054 		return B_NO_INIT;
1055 
1056 	/* we have to sync the what code as it is a public member */
1057 	fHeader->what = what;
1058 
1059 	ssize_t result1 = stream->Write(fHeader, sizeof(message_header));
1060 	if (result1 != sizeof(message_header))
1061 		return result1 < 0 ? result1 : B_ERROR;
1062 
1063 	ssize_t result2 = 0;
1064 	if (fHeader->field_count > 0) {
1065 		ssize_t fieldsSize = fHeader->field_count * sizeof(field_header);
1066 		result2 = stream->Write(fFields, fieldsSize);
1067 		if (result2 != fieldsSize)
1068 			return result2 < 0 ? result2 : B_ERROR;
1069 	}
1070 
1071 	ssize_t result3 = 0;
1072 	if (fHeader->data_size > 0) {
1073 		result3 = stream->Write(fData, fHeader->data_size);
1074 		if (result3 != (ssize_t)fHeader->data_size)
1075 			return result3 < 0 ? result3 : B_ERROR;
1076 	}
1077 
1078 	if (size)
1079 		*size = result1 + result2 + result3;
1080 
1081 	return B_OK;
1082 }
1083 
1084 
1085 /*	The concept of message sending by area:
1086 
1087 	The traditional way of sending a message is to send it by flattening it to
1088 	a buffer, pushing it through a port, reading it into the outputbuffer and
1089 	unflattening it from there (copying the data again). While this works ok
1090 	for small messages it does not make any sense for larger ones and may even
1091 	hit some port capacity limit.
1092 	Often in the life of a BMessage, it will be sent to someone. Almost as
1093 	often the one receiving the message will not need to change the message
1094 	in any way, but uses it "read only" to get information from it. This means
1095 	that all that copying is pretty pointless in the first place since we
1096 	could simply pass the original buffers on.
1097 	It's obviously not exactly as simple as this, since we cannot just use the
1098 	memory of one application in another - but we can share areas with
1099 	eachother.
1100 	Therefore instead of flattening into a buffer, we copy the message data
1101 	into an area, put this information into the message header and only push
1102 	this through the port. The receiving looper then builds a BMessage from
1103 	the header, that only references the data in the area (not copying it),
1104 	allowing read only access to it.
1105 	Only if write access is necessary the message will be copyed from the area
1106 	to its own buffers (like in the unflatten step before).
1107 	The double copying is reduced to a single copy in most cases and we safe
1108 	the slower route of moving the data through a port.
1109 	Additionally we save us the reference counting with the use of areas that
1110 	are reference counted internally. So we don't have to worry about leaving
1111 	an area behind or deleting one that is still in use.
1112 */
1113 
1114 status_t
1115 BMessage::_FlattenToArea(message_header** _header) const
1116 {
1117 	DEBUG_FUNCTION_ENTER;
1118 	if (fHeader == NULL)
1119 		return B_NO_INIT;
1120 
1121 	message_header* header = (message_header*)malloc(sizeof(message_header));
1122 	if (header == NULL)
1123 		return B_NO_MEMORY;
1124 
1125 	memcpy(header, fHeader, sizeof(message_header));
1126 
1127 	header->what = what;
1128 	header->message_area = -1;
1129 	*_header = header;
1130 
1131 	if (header->field_count == 0 && header->data_size == 0)
1132 		return B_OK;
1133 
1134 	char* address = NULL;
1135 	size_t fieldsSize = header->field_count * sizeof(field_header);
1136 	size_t size = fieldsSize + header->data_size;
1137 	size = (size + B_PAGE_SIZE) & ~(B_PAGE_SIZE - 1);
1138 	area_id area = create_area("BMessage data", (void**)&address,
1139 		B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
1140 
1141 	if (area < 0) {
1142 		free(header);
1143 		*_header = NULL;
1144 		return area;
1145 	}
1146 
1147 	memcpy(address, fFields, fieldsSize);
1148 	memcpy(address + fieldsSize, fData, fHeader->data_size);
1149 	header->flags |= MESSAGE_FLAG_PASS_BY_AREA;
1150 	header->message_area = area;
1151 	return B_OK;
1152 }
1153 
1154 
1155 status_t
1156 BMessage::_Reference()
1157 {
1158 	DEBUG_FUNCTION_ENTER;
1159 	if (fHeader == NULL)
1160 		return B_NO_INIT;
1161 
1162 	fHeader->flags &= ~MESSAGE_FLAG_PASS_BY_AREA;
1163 
1164 	/* if there is no data at all we don't need the area */
1165 	if (fHeader->field_count == 0 && fHeader->data_size == 0)
1166 		return B_OK;
1167 
1168 	area_info areaInfo;
1169 	status_t result = get_area_info(fHeader->message_area, &areaInfo);
1170 	if (result != B_OK)
1171 		return result;
1172 
1173 	if (areaInfo.team != BPrivate::current_team())
1174 		return B_BAD_VALUE;
1175 
1176 	set_area_protection(fHeader->message_area, B_READ_AREA);
1177 
1178 	uint8* address = (uint8*)areaInfo.address;
1179 
1180 	fFields = (field_header*)address;
1181 	fData = address + fHeader->field_count * sizeof(field_header);
1182 	return B_OK;
1183 }
1184 
1185 
1186 status_t
1187 BMessage::_Dereference()
1188 {
1189 	DEBUG_FUNCTION_ENTER;
1190 	if (fHeader == NULL)
1191 		return B_NO_INIT;
1192 
1193 	delete_area(fHeader->message_area);
1194 	fHeader->message_area = -1;
1195 	fFields = NULL;
1196 	fData = NULL;
1197 	return B_OK;
1198 }
1199 
1200 
1201 status_t
1202 BMessage::_CopyForWrite()
1203 {
1204 	DEBUG_FUNCTION_ENTER;
1205 	if (fHeader == NULL)
1206 		return B_NO_INIT;
1207 
1208 	field_header* newFields = NULL;
1209 	uint8* newData = NULL;
1210 
1211 	if (fHeader->field_count > 0) {
1212 		size_t fieldsSize = fHeader->field_count * sizeof(field_header);
1213 		newFields = (field_header*)malloc(fieldsSize);
1214 		if (newFields == NULL)
1215 			return B_NO_MEMORY;
1216 
1217 		memcpy(newFields, fFields, fieldsSize);
1218 	}
1219 
1220 	if (fHeader->data_size > 0) {
1221 		newData = (uint8*)malloc(fHeader->data_size);
1222 		if (newData == NULL) {
1223 			free(newFields);
1224 			return B_NO_MEMORY;
1225 		}
1226 
1227 		memcpy(newData, fData, fHeader->data_size);
1228 	}
1229 
1230 	_Dereference();
1231 
1232 	fFieldsAvailable = 0;
1233 	fDataAvailable = 0;
1234 
1235 	fFields = newFields;
1236 	fData = newData;
1237 	return B_OK;
1238 }
1239 
1240 
1241 status_t
1242 BMessage::_ValidateMessage()
1243 {
1244 	DEBUG_FUNCTION_ENTER;
1245 	if (fHeader == NULL)
1246 		return B_NO_INIT;
1247 
1248 	if (fHeader->field_count == 0)
1249 		return B_OK;
1250 
1251 	if (fFields == NULL)
1252 		return B_NO_INIT;
1253 
1254 	for (uint32 i = 0; i < fHeader->field_count; i++) {
1255 		field_header* field = &fFields[i];
1256 		if ((field->next_field >= 0
1257 				&& (uint32)field->next_field > fHeader->field_count)
1258 			|| (field->offset + field->name_length + field->data_size
1259 				> fHeader->data_size)) {
1260 			// the message is corrupt
1261 			MakeEmpty();
1262 			return B_BAD_VALUE;
1263 		}
1264 	}
1265 
1266 	return B_OK;
1267 }
1268 
1269 
1270 status_t
1271 BMessage::Unflatten(const char* flatBuffer)
1272 {
1273 	DEBUG_FUNCTION_ENTER;
1274 	if (flatBuffer == NULL)
1275 		return B_BAD_VALUE;
1276 
1277 	BMemoryIO io(flatBuffer, SIZE_MAX);
1278 	return Unflatten(&io);
1279 }
1280 
1281 
1282 status_t
1283 BMessage::Unflatten(BDataIO* stream)
1284 {
1285 	DEBUG_FUNCTION_ENTER;
1286 	if (stream == NULL)
1287 		return B_BAD_VALUE;
1288 
1289 	uint32 format = 0;
1290 	stream->Read(&format, sizeof(uint32));
1291 	if (format != MESSAGE_FORMAT_HAIKU)
1292 		return BPrivate::MessageAdapter::Unflatten(format, this, stream);
1293 
1294 	// native message unflattening
1295 
1296 	_Clear();
1297 
1298 	fHeader = (message_header*)malloc(sizeof(message_header));
1299 	if (fHeader == NULL)
1300 		return B_NO_MEMORY;
1301 
1302 	fHeader->format = format;
1303 	uint8* header = (uint8*)fHeader;
1304 	ssize_t result = stream->Read(header + sizeof(uint32),
1305 		sizeof(message_header) - sizeof(uint32));
1306 	if (result != sizeof(message_header) - sizeof(uint32)
1307 		|| (fHeader->flags & MESSAGE_FLAG_VALID) == 0) {
1308 		_InitHeader();
1309 		return result < 0 ? result : B_BAD_VALUE;
1310 	}
1311 
1312 	what = fHeader->what;
1313 
1314 	fHeader->message_area = -1;
1315 
1316 	if (fHeader->field_count > 0) {
1317 		ssize_t fieldsSize = fHeader->field_count * sizeof(field_header);
1318 		fFields = (field_header*)malloc(fieldsSize);
1319 		if (fFields == NULL) {
1320 			_InitHeader();
1321 			return B_NO_MEMORY;
1322 		}
1323 
1324 		result = stream->Read(fFields, fieldsSize);
1325 		if (result != fieldsSize)
1326 			return result < 0 ? result : B_BAD_VALUE;
1327 	}
1328 
1329 	if (fHeader->data_size > 0) {
1330 		fData = (uint8*)malloc(fHeader->data_size);
1331 		if (fData == NULL) {
1332 			free(fFields);
1333 			fFields = NULL;
1334 			_InitHeader();
1335 			return B_NO_MEMORY;
1336 		}
1337 
1338 		result = stream->Read(fData, fHeader->data_size);
1339 		if (result != (ssize_t)fHeader->data_size)
1340 			return result < 0 ? result : B_BAD_VALUE;
1341 	}
1342 
1343 	return _ValidateMessage();
1344 }
1345 
1346 
1347 status_t
1348 BMessage::AddSpecifier(const char* property)
1349 {
1350 	DEBUG_FUNCTION_ENTER;
1351 	BMessage message(B_DIRECT_SPECIFIER);
1352 	status_t result = message.AddString(B_PROPERTY_ENTRY, property);
1353 	if (result != B_OK)
1354 		return result;
1355 
1356 	return AddSpecifier(&message);
1357 }
1358 
1359 
1360 status_t
1361 BMessage::AddSpecifier(const char* property, int32 index)
1362 {
1363 	DEBUG_FUNCTION_ENTER;
1364 	BMessage message(B_INDEX_SPECIFIER);
1365 	status_t result = message.AddString(B_PROPERTY_ENTRY, property);
1366 	if (result != B_OK)
1367 		return result;
1368 
1369 	result = message.AddInt32("index", index);
1370 	if (result != B_OK)
1371 		return result;
1372 
1373 	return AddSpecifier(&message);
1374 }
1375 
1376 
1377 status_t
1378 BMessage::AddSpecifier(const char* property, int32 index, int32 range)
1379 {
1380 	DEBUG_FUNCTION_ENTER;
1381 	if (range < 0)
1382 		return B_BAD_VALUE;
1383 
1384 	BMessage message(B_RANGE_SPECIFIER);
1385 	status_t result = message.AddString(B_PROPERTY_ENTRY, property);
1386 	if (result != B_OK)
1387 		return result;
1388 
1389 	result = message.AddInt32("index", index);
1390 	if (result != B_OK)
1391 		return result;
1392 
1393 	result = message.AddInt32("range", range);
1394 	if (result != B_OK)
1395 		return result;
1396 
1397 	return AddSpecifier(&message);
1398 }
1399 
1400 
1401 status_t
1402 BMessage::AddSpecifier(const char* property, const char* name)
1403 {
1404 	DEBUG_FUNCTION_ENTER;
1405 	BMessage message(B_NAME_SPECIFIER);
1406 	status_t result = message.AddString(B_PROPERTY_ENTRY, property);
1407 	if (result != B_OK)
1408 		return result;
1409 
1410 	result = message.AddString(B_PROPERTY_NAME_ENTRY, name);
1411 	if (result != B_OK)
1412 		return result;
1413 
1414 	return AddSpecifier(&message);
1415 }
1416 
1417 
1418 status_t
1419 BMessage::AddSpecifier(const BMessage* specifier)
1420 {
1421 	DEBUG_FUNCTION_ENTER;
1422 	status_t result = AddMessage(B_SPECIFIER_ENTRY, specifier);
1423 	if (result != B_OK)
1424 		return result;
1425 
1426 	fHeader->current_specifier++;
1427 	fHeader->flags |= MESSAGE_FLAG_HAS_SPECIFIERS;
1428 	return B_OK;
1429 }
1430 
1431 
1432 status_t
1433 BMessage::SetCurrentSpecifier(int32 index)
1434 {
1435 	DEBUG_FUNCTION_ENTER;
1436 	if (index < 0)
1437 		return B_BAD_INDEX;
1438 
1439 	type_code type;
1440 	int32 count;
1441 	status_t result = GetInfo(B_SPECIFIER_ENTRY, &type, &count);
1442 	if (result != B_OK)
1443 		return result;
1444 
1445 	if (index > count)
1446 		return B_BAD_INDEX;
1447 
1448 	fHeader->current_specifier = index;
1449 	return B_OK;
1450 }
1451 
1452 
1453 status_t
1454 BMessage::GetCurrentSpecifier(int32* index, BMessage* specifier, int32* _what,
1455 	const char** property) const
1456 {
1457 	DEBUG_FUNCTION_ENTER;
1458 	if (fHeader == NULL)
1459 		return B_NO_INIT;
1460 
1461 	if (index != NULL)
1462 		*index = fHeader->current_specifier;
1463 
1464 	if (fHeader->current_specifier < 0
1465 		|| (fHeader->flags & MESSAGE_FLAG_WAS_DELIVERED) == 0)
1466 		return B_BAD_SCRIPT_SYNTAX;
1467 
1468 	if (specifier) {
1469 		if (FindMessage(B_SPECIFIER_ENTRY, fHeader->current_specifier,
1470 			specifier) != B_OK)
1471 			return B_BAD_SCRIPT_SYNTAX;
1472 
1473 		if (_what != NULL)
1474 			*_what = specifier->what;
1475 
1476 		if (property) {
1477 			if (specifier->FindString(B_PROPERTY_ENTRY, property) != B_OK)
1478 				return B_BAD_SCRIPT_SYNTAX;
1479 		}
1480 	}
1481 
1482 	return B_OK;
1483 }
1484 
1485 
1486 bool
1487 BMessage::HasSpecifiers() const
1488 {
1489 	DEBUG_FUNCTION_ENTER;
1490 	return fHeader != NULL
1491 		&& (fHeader->flags & MESSAGE_FLAG_HAS_SPECIFIERS) != 0;
1492 }
1493 
1494 
1495 status_t
1496 BMessage::PopSpecifier()
1497 {
1498 	DEBUG_FUNCTION_ENTER;
1499 	if (fHeader == NULL)
1500 		return B_NO_INIT;
1501 
1502 	if (fHeader->current_specifier < 0 ||
1503 		(fHeader->flags & MESSAGE_FLAG_WAS_DELIVERED) == 0)
1504 		return B_BAD_VALUE;
1505 
1506 	if (fHeader->current_specifier >= 0)
1507 		fHeader->current_specifier--;
1508 
1509 	return B_OK;
1510 }
1511 
1512 
1513 void
1514 BMessage::_UpdateOffsets(uint32 offset, int32 change)
1515 {
1516 	// Update the header to match the new position of the fields
1517 	if (offset < fHeader->data_size) {
1518 		field_header* field = fFields;
1519 		for (uint32 i = 0; i < fHeader->field_count; i++, field++) {
1520 			if (field->offset >= offset)
1521 				field->offset += change;
1522 		}
1523 	}
1524 }
1525 
1526 
1527 status_t
1528 BMessage::_ResizeData(uint32 offset, int32 change)
1529 {
1530 	if (change == 0)
1531 		return B_OK;
1532 
1533 	/* optimize for the most usual case: appending data */
1534 
1535 	if (change > 0) {
1536 		// We need to make the field bigger
1537 		// check if there is enough free space allocated
1538 		if (fDataAvailable >= (uint32)change) {
1539 			// In this case, we just need to move the data after the growing
1540 			// field to get the space at the right place
1541 			if (offset < fHeader->data_size) {
1542 				memmove(fData + offset + change, fData + offset,
1543 					fHeader->data_size - offset);
1544 			}
1545 
1546 			_UpdateOffsets(offset, change);
1547 
1548 			fDataAvailable -= change;
1549 			fHeader->data_size += change;
1550 			return B_OK;
1551 		}
1552 
1553 		// We need to grow the buffer. We try to optimize reallocations by
1554 		// preallocating space for more fields.
1555 		size_t size = fHeader->data_size * 2;
1556 		size = min_c(size, fHeader->data_size + MAX_DATA_PREALLOCATION);
1557 		size = max_c(size, fHeader->data_size + change);
1558 
1559 		uint8* newData = (uint8*)realloc(fData, size);
1560 		if (size > 0 && newData == NULL)
1561 			return B_NO_MEMORY;
1562 
1563 		fData = newData;
1564 		if (offset < fHeader->data_size) {
1565 			memmove(fData + offset + change, fData + offset,
1566 				fHeader->data_size - offset);
1567 		}
1568 
1569 		fHeader->data_size += change;
1570 		fDataAvailable = size - fHeader->data_size;
1571 	} else {
1572 		ssize_t length = fHeader->data_size - offset + change;
1573 		if (length > 0)
1574 			memmove(fData + offset, fData + offset - change, length);
1575 
1576 		// change is negative
1577 		fHeader->data_size += change;
1578 		fDataAvailable -= change;
1579 
1580 		if (fDataAvailable > MAX_DATA_PREALLOCATION) {
1581 			ssize_t available = MAX_DATA_PREALLOCATION / 2;
1582 			ssize_t size = fHeader->data_size + available;
1583 			uint8* newData = (uint8*)realloc(fData, size);
1584 			if (size > 0 && newData == NULL) {
1585 				// this is strange, but not really fatal
1586 				_UpdateOffsets(offset, change);
1587 				return B_OK;
1588 			}
1589 
1590 			fData = newData;
1591 			fDataAvailable = available;
1592 		}
1593 	}
1594 
1595 	_UpdateOffsets(offset, change);
1596 	return B_OK;
1597 }
1598 
1599 
1600 uint32
1601 BMessage::_HashName(const char* name) const
1602 {
1603 	char ch;
1604 	uint32 result = 0;
1605 
1606 	while ((ch = *name++) != 0) {
1607 		result = (result << 7) ^ (result >> 24);
1608 		result ^= ch;
1609 	}
1610 
1611 	result ^= result << 12;
1612 	return result;
1613 }
1614 
1615 
1616 status_t
1617 BMessage::_FindField(const char* name, type_code type, field_header** result)
1618 	const
1619 {
1620 	if (name == NULL)
1621 		return B_BAD_VALUE;
1622 
1623 	if (fHeader == NULL)
1624 		return B_NO_INIT;
1625 
1626 	if (fHeader->field_count == 0 || fFields == NULL || fData == NULL)
1627 		return B_NAME_NOT_FOUND;
1628 
1629 	uint32 hash = _HashName(name) % fHeader->hash_table_size;
1630 	int32 nextField = fHeader->hash_table[hash];
1631 
1632 	while (nextField >= 0) {
1633 		field_header* field = &fFields[nextField];
1634 		if ((field->flags & FIELD_FLAG_VALID) == 0)
1635 			break;
1636 
1637 		if (strncmp((const char*)(fData + field->offset), name,
1638 			field->name_length) == 0) {
1639 			if (type != B_ANY_TYPE && field->type != type)
1640 				return B_BAD_TYPE;
1641 
1642 			*result = field;
1643 			return B_OK;
1644 		}
1645 
1646 		nextField = field->next_field;
1647 	}
1648 
1649 	return B_NAME_NOT_FOUND;
1650 }
1651 
1652 
1653 status_t
1654 BMessage::_AddField(const char* name, type_code type, bool isFixedSize,
1655 	field_header** result)
1656 {
1657 	if (fHeader == NULL)
1658 		return B_NO_INIT;
1659 
1660 	if (fFieldsAvailable <= 0) {
1661 		uint32 count = fHeader->field_count * 2 + 1;
1662 		count = min_c(count, fHeader->field_count + MAX_FIELD_PREALLOCATION);
1663 
1664 		field_header* newFields = (field_header*)realloc(fFields,
1665 			count * sizeof(field_header));
1666 		if (count > 0 && newFields == NULL)
1667 			return B_NO_MEMORY;
1668 
1669 		fFields = newFields;
1670 		fFieldsAvailable = count - fHeader->field_count;
1671 	}
1672 
1673 	uint32 hash = _HashName(name) % fHeader->hash_table_size;
1674 	int32* nextField = &fHeader->hash_table[hash];
1675 	while (*nextField >= 0)
1676 		nextField = &fFields[*nextField].next_field;
1677 	*nextField = fHeader->field_count;
1678 
1679 	field_header* field = &fFields[fHeader->field_count];
1680 	field->type = type;
1681 	field->count = 0;
1682 	field->data_size = 0;
1683 	field->next_field = -1;
1684 	field->offset = fHeader->data_size;
1685 	field->name_length = strlen(name) + 1;
1686 	status_t status = _ResizeData(field->offset, field->name_length);
1687 	if (status != B_OK)
1688 		return status;
1689 
1690 	memcpy(fData + field->offset, name, field->name_length);
1691 	field->flags = FIELD_FLAG_VALID;
1692 	if (isFixedSize)
1693 		field->flags |= FIELD_FLAG_FIXED_SIZE;
1694 
1695 	fFieldsAvailable--;
1696 	fHeader->field_count++;
1697 	*result = field;
1698 	return B_OK;
1699 }
1700 
1701 
1702 status_t
1703 BMessage::_RemoveField(field_header* field)
1704 {
1705 	status_t result = _ResizeData(field->offset, -(field->data_size
1706 		+ field->name_length));
1707 	if (result != B_OK)
1708 		return result;
1709 
1710 	int32 index = ((uint8*)field - (uint8*)fFields) / sizeof(field_header);
1711 	int32 nextField = field->next_field;
1712 	if (nextField > index)
1713 		nextField--;
1714 
1715 	int32* value = fHeader->hash_table;
1716 	for (uint32 i = 0; i < fHeader->hash_table_size; i++, value++) {
1717 		if (*value > index)
1718 			*value -= 1;
1719 		else if (*value == index)
1720 			*value = nextField;
1721 	}
1722 
1723 	field_header* other = fFields;
1724 	for (uint32 i = 0; i < fHeader->field_count; i++, other++) {
1725 		if (other->next_field > index)
1726 			other->next_field--;
1727 		else if (other->next_field == index)
1728 			other->next_field = nextField;
1729 	}
1730 
1731 	size_t size = (fHeader->field_count - index - 1) * sizeof(field_header);
1732 	memmove(fFields + index, fFields + index + 1, size);
1733 	fHeader->field_count--;
1734 	fFieldsAvailable++;
1735 
1736 	if (fFieldsAvailable > MAX_FIELD_PREALLOCATION) {
1737 		ssize_t available = MAX_FIELD_PREALLOCATION / 2;
1738 		size = (fHeader->field_count + available) * sizeof(field_header);
1739 		field_header* newFields = (field_header*)realloc(fFields, size);
1740 		if (size > 0 && newFields == NULL) {
1741 			// this is strange, but not really fatal
1742 			return B_OK;
1743 		}
1744 
1745 		fFields = newFields;
1746 		fFieldsAvailable = available;
1747 	}
1748 
1749 	return B_OK;
1750 }
1751 
1752 
1753 status_t
1754 BMessage::AddData(const char* name, type_code type, const void* data,
1755 	ssize_t numBytes, bool isFixedSize, int32 count)
1756 {
1757 	// Note that the "count" argument is only a hint at how many items
1758 	// the caller expects to add to this field. Since we do no item pre-
1759 	// allocation, we ignore this argument.
1760 	DEBUG_FUNCTION_ENTER;
1761 	if (numBytes <= 0 || data == NULL)
1762 		return B_BAD_VALUE;
1763 
1764 	if (fHeader == NULL)
1765 		return B_NO_INIT;
1766 
1767 	status_t result;
1768 	if (fHeader->message_area >= 0) {
1769 		result = _CopyForWrite();
1770 		if (result != B_OK)
1771 			return result;
1772 	}
1773 
1774 	field_header* field = NULL;
1775 	result = _FindField(name, type, &field);
1776 	if (result == B_NAME_NOT_FOUND)
1777 		result = _AddField(name, type, isFixedSize, &field);
1778 
1779 	if (result != B_OK)
1780 		return result;
1781 
1782 	if (field == NULL)
1783 		return B_ERROR;
1784 
1785 	uint32 offset = field->offset + field->name_length + field->data_size;
1786 	if ((field->flags & FIELD_FLAG_FIXED_SIZE) != 0) {
1787 		if (field->count) {
1788 			ssize_t size = field->data_size / field->count;
1789 			if (size != numBytes)
1790 				return B_BAD_VALUE;
1791 		}
1792 
1793 		result = _ResizeData(offset, numBytes);
1794 		if (result != B_OK) {
1795 			if (field->count == 0)
1796 				_RemoveField(field);
1797 			return result;
1798 		}
1799 
1800 		memcpy(fData + offset, data, numBytes);
1801 		field->data_size += numBytes;
1802 	} else {
1803 		int32 change = numBytes + sizeof(uint32);
1804 		result = _ResizeData(offset, change);
1805 		if (result != B_OK) {
1806 			if (field->count == 0)
1807 				_RemoveField(field);
1808 			return result;
1809 		}
1810 
1811 		uint32 size = (uint32)numBytes;
1812 		memcpy(fData + offset, &size, sizeof(uint32));
1813 		memcpy(fData + offset + sizeof(uint32), data, size);
1814 		field->data_size += change;
1815 	}
1816 
1817 	field->count++;
1818 	return B_OK;
1819 }
1820 
1821 
1822 status_t
1823 BMessage::RemoveData(const char* name, int32 index)
1824 {
1825 	DEBUG_FUNCTION_ENTER;
1826 	if (index < 0)
1827 		return B_BAD_INDEX;
1828 
1829 	if (fHeader == NULL)
1830 		return B_NO_INIT;
1831 
1832 	status_t result;
1833 	if (fHeader->message_area >= 0) {
1834 		result = _CopyForWrite();
1835 		if (result != B_OK)
1836 			return result;
1837 	}
1838 
1839 	field_header* field = NULL;
1840 	result = _FindField(name, B_ANY_TYPE, &field);
1841 	if (result != B_OK)
1842 		return result;
1843 
1844 	if ((uint32)index >= field->count)
1845 		return B_BAD_INDEX;
1846 
1847 	if (field->count == 1)
1848 		return _RemoveField(field);
1849 
1850 	uint32 offset = field->offset + field->name_length;
1851 	if ((field->flags & FIELD_FLAG_FIXED_SIZE) != 0) {
1852 		ssize_t size = field->data_size / field->count;
1853 		result = _ResizeData(offset + index * size, -size);
1854 		if (result != B_OK)
1855 			return result;
1856 
1857 		field->data_size -= size;
1858 	} else {
1859 		uint8* pointer = fData + offset;
1860 		for (int32 i = 0; i < index; i++) {
1861 			offset += *(uint32*)pointer + sizeof(uint32);
1862 			pointer = fData + offset;
1863 		}
1864 
1865 		size_t currentSize = *(uint32*)pointer + sizeof(uint32);
1866 		result = _ResizeData(offset, -currentSize);
1867 		if (result != B_OK)
1868 			return result;
1869 
1870 		field->data_size -= currentSize;
1871 	}
1872 
1873 	field->count--;
1874 	return B_OK;
1875 }
1876 
1877 
1878 status_t
1879 BMessage::RemoveName(const char* name)
1880 {
1881 	DEBUG_FUNCTION_ENTER;
1882 	if (fHeader == NULL)
1883 		return B_NO_INIT;
1884 
1885 	status_t result;
1886 	if (fHeader->message_area >= 0) {
1887 		result = _CopyForWrite();
1888 		if (result != B_OK)
1889 			return result;
1890 	}
1891 
1892 	field_header* field = NULL;
1893 	result = _FindField(name, B_ANY_TYPE, &field);
1894 	if (result != B_OK)
1895 		return result;
1896 
1897 	return _RemoveField(field);
1898 }
1899 
1900 
1901 status_t
1902 BMessage::MakeEmpty()
1903 {
1904 	DEBUG_FUNCTION_ENTER;
1905 	_Clear();
1906 	return _InitHeader();
1907 }
1908 
1909 
1910 status_t
1911 BMessage::FindData(const char* name, type_code type, int32 index,
1912 	const void** data, ssize_t* numBytes) const
1913 {
1914 	DEBUG_FUNCTION_ENTER;
1915 	if (data == NULL)
1916 		return B_BAD_VALUE;
1917 
1918 	*data = NULL;
1919 	field_header* field = NULL;
1920 	status_t result = _FindField(name, type, &field);
1921 	if (result != B_OK)
1922 		return result;
1923 
1924 	if (index < 0 || (uint32)index >= field->count)
1925 		return B_BAD_INDEX;
1926 
1927 	if ((field->flags & FIELD_FLAG_FIXED_SIZE) != 0) {
1928 		size_t bytes = field->data_size / field->count;
1929 		*data = fData + field->offset + field->name_length + index * bytes;
1930 		if (numBytes != NULL)
1931 			*numBytes = bytes;
1932 	} else {
1933 		uint8* pointer = fData + field->offset + field->name_length;
1934 		for (int32 i = 0; i < index; i++)
1935 			pointer += *(uint32*)pointer + sizeof(uint32);
1936 
1937 		*data = pointer + sizeof(uint32);
1938 		if (numBytes != NULL)
1939 			*numBytes = *(uint32*)pointer;
1940 	}
1941 
1942 	return B_OK;
1943 }
1944 
1945 
1946 status_t
1947 BMessage::ReplaceData(const char* name, type_code type, int32 index,
1948 	const void* data, ssize_t numBytes)
1949 {
1950 	DEBUG_FUNCTION_ENTER;
1951 	if (numBytes <= 0 || data == NULL)
1952 		return B_BAD_VALUE;
1953 
1954 	field_header* field = NULL;
1955 	status_t result = _FindField(name, type, &field);
1956 	if (result != B_OK)
1957 		return result;
1958 
1959 	if (index < 0 || (uint32)index >= field->count)
1960 		return B_BAD_INDEX;
1961 
1962 	if (fHeader->message_area >= 0) {
1963 		result = _CopyForWrite();
1964 		if (result != B_OK)
1965 			return result;
1966 	}
1967 
1968 	if ((field->flags & FIELD_FLAG_FIXED_SIZE) != 0) {
1969 		ssize_t size = field->data_size / field->count;
1970 		if (size != numBytes)
1971 			return B_BAD_VALUE;
1972 
1973 		memcpy(fData + field->offset + field->name_length + index * size, data,
1974 			size);
1975 	} else {
1976 		uint32 offset = field->offset + field->name_length;
1977 		uint8* pointer = fData + offset;
1978 
1979 		for (int32 i = 0; i < index; i++) {
1980 			offset += *(uint32*)pointer + sizeof(uint32);
1981 			pointer = fData + offset;
1982 		}
1983 
1984 		size_t currentSize = *(uint32*)pointer;
1985 		int32 change = numBytes - currentSize;
1986 		result = _ResizeData(offset, change);
1987 		if (result != B_OK)
1988 			return result;
1989 
1990 		uint32 newSize = (uint32)numBytes;
1991 		memcpy(fData + offset, &newSize, sizeof(uint32));
1992 		memcpy(fData + offset + sizeof(uint32), data, newSize);
1993 		field->data_size += change;
1994 	}
1995 
1996 	return B_OK;
1997 }
1998 
1999 
2000 bool
2001 BMessage::HasData(const char* name, type_code type, int32 index) const
2002 {
2003 	DEBUG_FUNCTION_ENTER;
2004 	field_header* field = NULL;
2005 	status_t result = _FindField(name, type, &field);
2006 	if (result != B_OK)
2007 		return false;
2008 
2009 	if (index < 0 || (uint32)index >= field->count)
2010 		return false;
2011 
2012 	return true;
2013 }
2014 
2015 
2016 /* Static functions for cache initialization and cleanup */
2017 void
2018 BMessage::_StaticInit()
2019 {
2020 	DEBUG_FUNCTION_ENTER2;
2021 	sReplyPorts[0] = create_port(1, "tmp_rport0");
2022 	sReplyPorts[1] = create_port(1, "tmp_rport1");
2023 	sReplyPorts[2] = create_port(1, "tmp_rport2");
2024 
2025 	sReplyPortInUse[0] = 0;
2026 	sReplyPortInUse[1] = 0;
2027 	sReplyPortInUse[2] = 0;
2028 
2029 	sMsgCache = new BBlockCache(20, sizeof(BMessage), B_OBJECT_CACHE);
2030 }
2031 
2032 
2033 void
2034 BMessage::_StaticReInitForkedChild()
2035 {
2036 	DEBUG_FUNCTION_ENTER2;
2037 
2038 	// overwrite the inherited ports with a set of our own
2039 	sReplyPorts[0] = create_port(1, "tmp_rport0");
2040 	sReplyPorts[1] = create_port(1, "tmp_rport1");
2041 	sReplyPorts[2] = create_port(1, "tmp_rport2");
2042 
2043 	sReplyPortInUse[0] = 0;
2044 	sReplyPortInUse[1] = 0;
2045 	sReplyPortInUse[2] = 0;
2046 }
2047 
2048 
2049 void
2050 BMessage::_StaticCleanup()
2051 {
2052 	DEBUG_FUNCTION_ENTER2;
2053 	delete_port(sReplyPorts[0]);
2054 	sReplyPorts[0] = -1;
2055 	delete_port(sReplyPorts[1]);
2056 	sReplyPorts[1] = -1;
2057 	delete_port(sReplyPorts[2]);
2058 	sReplyPorts[2] = -1;
2059 }
2060 
2061 
2062 void
2063 BMessage::_StaticCacheCleanup()
2064 {
2065 	DEBUG_FUNCTION_ENTER2;
2066 	delete sMsgCache;
2067 	sMsgCache = NULL;
2068 }
2069 
2070 
2071 int32
2072 BMessage::_StaticGetCachedReplyPort()
2073 {
2074 	DEBUG_FUNCTION_ENTER2;
2075 	int index = -1;
2076 	for (int32 i = 0; i < sNumReplyPorts; i++) {
2077 		int32 old = atomic_add(&(sReplyPortInUse[i]), 1);
2078 		if (old == 0) {
2079 			// This entry is free
2080 			index = i;
2081 			break;
2082 		} else {
2083 			// This entry is being used.
2084 			atomic_add(&(sReplyPortInUse[i]), -1);
2085 		}
2086 	}
2087 
2088 	return index;
2089 }
2090 
2091 
2092 status_t
2093 BMessage::_SendMessage(port_id port, team_id portOwner, int32 token,
2094 	bigtime_t timeout, bool replyRequired, BMessenger& replyTo) const
2095 {
2096 	DEBUG_FUNCTION_ENTER;
2097 	ssize_t size = 0;
2098 	char* buffer = NULL;
2099 	message_header* header = NULL;
2100 	status_t result = B_OK;
2101 
2102 	BPrivate::BDirectMessageTarget* direct = NULL;
2103 	BMessage* copy = NULL;
2104 	if (portOwner == BPrivate::current_team())
2105 		BPrivate::gDefaultTokens.AcquireHandlerTarget(token, &direct);
2106 
2107 	if (direct != NULL) {
2108 		// We have a direct local message target - we can just enqueue the
2109 		// message in its message queue. This will also prevent possible
2110 		// deadlocks when the queue is full.
2111 		copy = new BMessage(*this);
2112 		if (copy != NULL) {
2113 			header = copy->fHeader;
2114 			header->flags = fHeader->flags;
2115 		} else {
2116 			direct->Release();
2117 			return B_NO_MEMORY;
2118 		}
2119 #ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
2120 	} else if (fHeader->data_size > B_PAGE_SIZE * 10) {
2121 		// ToDo: bind the above size to the max port message size
2122 		// use message passing by area for such a large message
2123 		result = _FlattenToArea(&header);
2124 		if (result != B_OK)
2125 			return result;
2126 
2127 		buffer = (char*)header;
2128 		size = sizeof(message_header);
2129 
2130 		if (header->message_area >= 0) {
2131 			team_id target = portOwner;
2132 			if (target < 0) {
2133 				port_info info;
2134 				result = get_port_info(port, &info);
2135 				if (result != B_OK) {
2136 					free(header);
2137 					return result;
2138 				}
2139 				target = info.team;
2140 			}
2141 
2142 			void* address = NULL;
2143 			area_id transfered = _kern_transfer_area(header->message_area,
2144 				&address, B_ANY_ADDRESS, target);
2145 			if (transfered < 0) {
2146 				delete_area(header->message_area);
2147 				free(header);
2148 				return transfered;
2149 			}
2150 
2151 			header->message_area = transfered;
2152 		}
2153 #endif
2154 	} else {
2155 		size = FlattenedSize();
2156 		buffer = (char*)malloc(size);
2157 		if (buffer == NULL)
2158 			return B_NO_MEMORY;
2159 
2160 		result = Flatten(buffer, size);
2161 		if (result != B_OK) {
2162 			free(buffer);
2163 			return result;
2164 		}
2165 
2166 		header = (message_header*)buffer;
2167 	}
2168 
2169 	if (!replyTo.IsValid()) {
2170 		BMessenger::Private(replyTo).SetTo(fHeader->reply_team,
2171 			fHeader->reply_port, fHeader->reply_target);
2172 
2173 		if (!replyTo.IsValid())
2174 			replyTo = be_app_messenger;
2175 	}
2176 
2177 	BMessenger::Private replyToPrivate(replyTo);
2178 
2179 	if (replyRequired) {
2180 		header->flags |= MESSAGE_FLAG_REPLY_REQUIRED;
2181 		header->flags &= ~MESSAGE_FLAG_REPLY_DONE;
2182 	}
2183 
2184 	header->target = token;
2185 	header->reply_team = replyToPrivate.Team();
2186 	header->reply_port = replyToPrivate.Port();
2187 	header->reply_target = replyToPrivate.Token();
2188 	header->flags |= MESSAGE_FLAG_WAS_DELIVERED;
2189 
2190 	if (direct == NULL) {
2191 		KTRACE("BMessage send remote: team: %ld, port: %ld, token: %ld, "
2192 			"message: '%c%c%c%c'", portOwner, port, token,
2193 			char(what >> 24), char(what >> 16), char(what >> 8), (char)what);
2194 
2195 		do {
2196 			result = write_port_etc(port, kPortMessageCode, (void*)buffer,
2197 				size, B_RELATIVE_TIMEOUT, timeout);
2198 		} while (result == B_INTERRUPTED);
2199 	}
2200 
2201 	if (result == B_OK && IsSourceWaiting()) {
2202 		// the forwarded message will handle the reply - we must not do
2203 		// this anymore
2204 		fHeader->flags |= MESSAGE_FLAG_REPLY_DONE;
2205 	}
2206 
2207 	// we need to do this last because it is possible our
2208 	// message might be destroyed after it's enqueued in the
2209 	// target looper. Thus we don't want to do any ops that depend on
2210 	// members of this after the enqueue.
2211 	if (direct != NULL) {
2212 		KTRACE("BMessage send direct: port: %ld, token: %ld, "
2213 			"message: '%c%c%c%c'", port, token,
2214 			char(what >> 24), char(what >> 16), char(what >> 8), (char)what);
2215 
2216 		// this is a local message transmission
2217 		direct->AddMessage(copy);
2218 		if (direct->Queue()->IsNextMessage(copy) && port_count(port) <= 0) {
2219 			// there is currently no message waiting, and we need to wakeup the
2220 			// looper
2221 			write_port_etc(port, 0, NULL, 0, B_RELATIVE_TIMEOUT, 0);
2222 		}
2223 		direct->Release();
2224 	}
2225 
2226 	free(buffer);
2227 	return result;
2228 }
2229 
2230 
2231 // Sends a message and waits synchronously for a reply.
2232 status_t
2233 BMessage::_SendMessage(port_id port, team_id portOwner, int32 token,
2234 	BMessage* reply, bigtime_t sendTimeout, bigtime_t replyTimeout) const
2235 {
2236 	if (IsSourceWaiting()) {
2237 		// we can't forward this message synchronously when it's already
2238 		// waiting for a reply
2239 		return B_ERROR;
2240 	}
2241 
2242 	DEBUG_FUNCTION_ENTER;
2243 	const int32 cachedReplyPort = _StaticGetCachedReplyPort();
2244 	port_id replyPort = B_BAD_PORT_ID;
2245 	status_t result = B_OK;
2246 
2247 	if (cachedReplyPort < 0) {
2248 		// All the cached reply ports are in use; create a new one
2249 		replyPort = create_port(1 /* for one message */, "tmp_reply_port");
2250 		if (replyPort < 0)
2251 			return replyPort;
2252 	} else {
2253 		assert(cachedReplyPort < sNumReplyPorts);
2254 		replyPort = sReplyPorts[cachedReplyPort];
2255 	}
2256 
2257 	team_id team = B_BAD_TEAM_ID;
2258 	if (be_app != NULL)
2259 		team = be_app->Team();
2260 	else {
2261 		port_info portInfo;
2262 		result = get_port_info(replyPort, &portInfo);
2263 		if (result != B_OK)
2264 			goto error;
2265 
2266 		team = portInfo.team;
2267 	}
2268 
2269 	result = set_port_owner(replyPort, portOwner);
2270 	if (result != B_OK)
2271 		goto error;
2272 
2273 	// tests if the queue of the reply port is really empty
2274 #if 0
2275 	port_info portInfo;
2276 	if (get_port_info(replyPort, &portInfo) == B_OK
2277 		&& portInfo.queue_count > 0) {
2278 		debugger("reply port not empty!");
2279 		printf("  reply port not empty! %ld message(s) in queue\n",
2280 			portInfo.queue_count);
2281 
2282 		// fetch and print the messages
2283 		for (int32 i = 0; i < portInfo.queue_count; i++) {
2284 			char buffer[1024];
2285 			int32 code;
2286 			ssize_t size = read_port(replyPort, &code, buffer, sizeof(buffer));
2287 			if (size < 0) {
2288 				printf("failed to read message from reply port\n");
2289 				continue;
2290 			}
2291 			if (size >= (ssize_t)sizeof(buffer)) {
2292 				printf("message from reply port too big\n");
2293 				continue;
2294 			}
2295 
2296 			BMemoryIO stream(buffer, size);
2297 			BMessage reply;
2298 			if (reply.Unflatten(&stream) != B_OK) {
2299 				printf("failed to unflatten message from reply port\n");
2300 				continue;
2301 			}
2302 
2303 			printf("message %ld from reply port:\n", i);
2304 			reply.PrintToStream();
2305 		}
2306 	}
2307 #endif
2308 
2309 	{
2310 		BMessenger replyTarget;
2311 		BMessenger::Private(replyTarget).SetTo(team, replyPort,
2312 			B_PREFERRED_TOKEN);
2313 		// TODO: replying could also use a BDirectMessageTarget like mechanism
2314 		// for local targets
2315 		result = _SendMessage(port, -1, token, sendTimeout, true,
2316 			replyTarget);
2317 	}
2318 
2319 	if (result != B_OK)
2320 		goto error;
2321 
2322 	int32 code;
2323 	result = handle_reply(replyPort, &code, replyTimeout, reply);
2324 	if (result != B_OK && cachedReplyPort >= 0) {
2325 		delete_port(replyPort);
2326 		sReplyPorts[cachedReplyPort] = create_port(1, "tmp_rport");
2327 	}
2328 
2329 error:
2330 	if (cachedReplyPort >= 0) {
2331 		// Reclaim ownership of cached port
2332 		set_port_owner(replyPort, team);
2333 		// Flag as available
2334 		atomic_add(&sReplyPortInUse[cachedReplyPort], -1);
2335 		return result;
2336 	}
2337 
2338 	delete_port(replyPort);
2339 	return result;
2340 }
2341 
2342 
2343 status_t
2344 BMessage::_SendFlattenedMessage(void* data, int32 size, port_id port,
2345 	int32 token, bigtime_t timeout)
2346 {
2347 	DEBUG_FUNCTION_ENTER2;
2348 	if (data == NULL)
2349 		return B_BAD_VALUE;
2350 
2351 	uint32 magic = *(uint32*)data;
2352 
2353 	if (magic == MESSAGE_FORMAT_HAIKU
2354 		|| magic == MESSAGE_FORMAT_HAIKU_SWAPPED) {
2355 		message_header* header = (message_header*)data;
2356 		header->target = token;
2357 		header->flags |= MESSAGE_FLAG_WAS_DELIVERED;
2358 	} else if (magic == MESSAGE_FORMAT_R5) {
2359 		uint8* header = (uint8*)data;
2360 		header += sizeof(uint32) /* magic */ + sizeof(uint32) /* checksum */
2361 			+ sizeof(ssize_t) /* flattenedSize */ + sizeof(int32) /* what */
2362 			+ sizeof(uint8) /* flags */;
2363 		*(int32*)header = token;
2364 	} else if (((KMessage::Header*)data)->magic
2365 			== KMessage::kMessageHeaderMagic) {
2366 		KMessage::Header* header = (KMessage::Header*)data;
2367 		header->targetToken = token;
2368 	} else {
2369 		return B_NOT_A_MESSAGE;
2370 	}
2371 
2372 	// send the message
2373 	status_t result;
2374 
2375 	do {
2376 		result = write_port_etc(port, kPortMessageCode, data, size,
2377 			B_RELATIVE_TIMEOUT, timeout);
2378 	} while (result == B_INTERRUPTED);
2379 
2380 	return result;
2381 }
2382 
2383 
2384 void BMessage::_ReservedMessage1() {}
2385 void BMessage::_ReservedMessage2() {}
2386 void BMessage::_ReservedMessage3() {}
2387 
2388 
2389 // #pragma mark - Macro definitions for data access methods
2390 
2391 
2392 /* Relay functions from here on (Add... -> AddData, Find... -> FindData) */
2393 
2394 #define DEFINE_FUNCTIONS(type, typeName, typeCode)							\
2395 status_t																	\
2396 BMessage::Add##typeName(const char* name, type val)							\
2397 {																			\
2398 	return AddData(name, typeCode, &val, sizeof(type), true);				\
2399 }																			\
2400 																			\
2401 																			\
2402 status_t																	\
2403 BMessage::Find##typeName(const char* name, type* p) const					\
2404 {																			\
2405 	void* ptr = NULL;														\
2406 	ssize_t bytes = 0;														\
2407 	status_t error = B_OK;													\
2408 																			\
2409 	*p = type();															\
2410 	error = FindData(name, typeCode, 0, (const void**)&ptr, &bytes);		\
2411 																			\
2412 	if (error == B_OK)														\
2413 		memcpy(p, ptr, sizeof(type));										\
2414 																			\
2415 	return error;															\
2416 }																			\
2417 																			\
2418 																			\
2419 status_t																	\
2420 BMessage::Find##typeName(const char* name, int32 index, type* p) const		\
2421 {																			\
2422 	void* ptr = NULL;														\
2423 	ssize_t bytes = 0;														\
2424 	status_t error = B_OK;													\
2425 																			\
2426 	*p = type();															\
2427 	error = FindData(name, typeCode, index, (const void**)&ptr, &bytes);	\
2428 																			\
2429 	if (error == B_OK)														\
2430 		memcpy(p, ptr, sizeof(type));										\
2431 																			\
2432 	return error;															\
2433 }																			\
2434 																			\
2435 																			\
2436 status_t																	\
2437 BMessage::Replace##typeName(const char* name, type value)					\
2438 {																			\
2439 	return ReplaceData(name, typeCode, 0, &value, sizeof(type));			\
2440 }																			\
2441 																			\
2442 																			\
2443 status_t																	\
2444 BMessage::Replace##typeName(const char* name, int32 index, type value)		\
2445 {																			\
2446 	return ReplaceData(name, typeCode, index, &value, sizeof(type));		\
2447 }																			\
2448 																			\
2449 																			\
2450 bool																		\
2451 BMessage::Has##typeName(const char* name, int32 index) const				\
2452 {																			\
2453 	return HasData(name, typeCode, index);									\
2454 }
2455 
2456 DEFINE_FUNCTIONS(BPoint, Point, B_POINT_TYPE);
2457 DEFINE_FUNCTIONS(BRect, Rect, B_RECT_TYPE);
2458 DEFINE_FUNCTIONS(BSize, Size, B_SIZE_TYPE);
2459 DEFINE_FUNCTIONS(int8, Int8, B_INT8_TYPE);
2460 DEFINE_FUNCTIONS(uint8, UInt8, B_UINT8_TYPE);
2461 DEFINE_FUNCTIONS(int16, Int16, B_INT16_TYPE);
2462 DEFINE_FUNCTIONS(uint16, UInt16, B_UINT16_TYPE);
2463 DEFINE_FUNCTIONS(int32, Int32, B_INT32_TYPE);
2464 DEFINE_FUNCTIONS(uint32, UInt32, B_UINT32_TYPE);
2465 DEFINE_FUNCTIONS(int64, Int64, B_INT64_TYPE);
2466 DEFINE_FUNCTIONS(uint64, UInt64, B_UINT64_TYPE);
2467 DEFINE_FUNCTIONS(bool, Bool, B_BOOL_TYPE);
2468 DEFINE_FUNCTIONS(float, Float, B_FLOAT_TYPE);
2469 DEFINE_FUNCTIONS(double, Double, B_DOUBLE_TYPE);
2470 
2471 #undef DEFINE_FUNCTIONS
2472 
2473 #define DEFINE_HAS_FUNCTION(typeName, typeCode)								\
2474 bool																		\
2475 BMessage::Has##typeName(const char* name, int32 index) const				\
2476 {																			\
2477 	return HasData(name, typeCode, index);									\
2478 }
2479 
2480 
2481 DEFINE_HAS_FUNCTION(Alignment, B_ALIGNMENT_TYPE);
2482 DEFINE_HAS_FUNCTION(String, B_STRING_TYPE);
2483 DEFINE_HAS_FUNCTION(Pointer, B_POINTER_TYPE);
2484 DEFINE_HAS_FUNCTION(Messenger, B_MESSENGER_TYPE);
2485 DEFINE_HAS_FUNCTION(Ref, B_REF_TYPE);
2486 DEFINE_HAS_FUNCTION(Message, B_MESSAGE_TYPE);
2487 
2488 #undef DEFINE_HAS_FUNCTION
2489 
2490 
2491 #define DEFINE_LAZY_FIND_FUNCTION(type, typeName, initialize)				\
2492 type																		\
2493 BMessage::Find##typeName(const char* name, int32 index) const				\
2494 {																			\
2495 	type val = initialize;													\
2496 	Find##typeName(name, index, &val);										\
2497 	return val;																\
2498 }
2499 
2500 
2501 DEFINE_LAZY_FIND_FUNCTION(BRect, Rect, BRect());
2502 DEFINE_LAZY_FIND_FUNCTION(BPoint, Point, BPoint());
2503 DEFINE_LAZY_FIND_FUNCTION(const char*, String, NULL);
2504 DEFINE_LAZY_FIND_FUNCTION(int8, Int8, 0);
2505 DEFINE_LAZY_FIND_FUNCTION(int16, Int16, 0);
2506 DEFINE_LAZY_FIND_FUNCTION(int32, Int32, 0);
2507 DEFINE_LAZY_FIND_FUNCTION(int64, Int64, 0);
2508 DEFINE_LAZY_FIND_FUNCTION(bool, Bool, false);
2509 DEFINE_LAZY_FIND_FUNCTION(float, Float, 0);
2510 DEFINE_LAZY_FIND_FUNCTION(double, Double, 0);
2511 
2512 #undef DEFINE_LAZY_FIND_FUNCTION
2513 
2514 
2515 #define DEFINE_SET_GET_FUNCTIONS(type, typeName, typeCode)					\
2516 type																		\
2517 BMessage::Get##typeName(const char* name, type defaultValue) const			\
2518 {																			\
2519 	return Get##typeName(name, 0, defaultValue);							\
2520 }																			\
2521 																			\
2522 																			\
2523 type																		\
2524 BMessage::Get##typeName(const char* name, int32 index,						\
2525 	type defaultValue) const												\
2526 {																			\
2527 	type value;																\
2528 	if (Find##typeName(name, index, &value) == B_OK)						\
2529 		return value;														\
2530 																			\
2531 	return defaultValue;													\
2532 }																			\
2533 																			\
2534 																			\
2535 status_t																	\
2536 BMessage::Set##typeName(const char* name, type value)						\
2537 {																			\
2538 	return SetData(name, typeCode, &value, sizeof(type));					\
2539 }																			\
2540 
2541 
2542 DEFINE_SET_GET_FUNCTIONS(int8, Int8, B_INT8_TYPE);
2543 DEFINE_SET_GET_FUNCTIONS(uint8, UInt8, B_UINT8_TYPE);
2544 DEFINE_SET_GET_FUNCTIONS(int16, Int16, B_INT16_TYPE);
2545 DEFINE_SET_GET_FUNCTIONS(uint16, UInt16, B_UINT16_TYPE);
2546 DEFINE_SET_GET_FUNCTIONS(int32, Int32, B_INT32_TYPE);
2547 DEFINE_SET_GET_FUNCTIONS(uint32, UInt32, B_UINT32_TYPE);
2548 DEFINE_SET_GET_FUNCTIONS(int64, Int64, B_INT64_TYPE);
2549 DEFINE_SET_GET_FUNCTIONS(uint64, UInt64, B_UINT64_TYPE);
2550 DEFINE_SET_GET_FUNCTIONS(bool, Bool, B_BOOL_TYPE);
2551 DEFINE_SET_GET_FUNCTIONS(float, Float, B_FLOAT_TYPE);
2552 DEFINE_SET_GET_FUNCTIONS(double, Double, B_DOUBLE_TYPE);
2553 DEFINE_SET_GET_FUNCTIONS(const char *, String, B_STRING_TYPE);
2554 
2555 #undef DEFINE_SET_GET_FUNCTION
2556 
2557 
2558 #define DEFINE_SET_GET_BY_REFERENCE_FUNCTIONS(type, typeName, typeCode)		\
2559 type																		\
2560 BMessage::Get##typeName(const char* name, const type& defaultValue) const	\
2561 {																			\
2562 	return Get##typeName(name, 0, defaultValue);							\
2563 }																			\
2564 																			\
2565 																			\
2566 type																		\
2567 BMessage::Get##typeName(const char* name, int32 index,						\
2568 	const type& defaultValue) const											\
2569 {																			\
2570 	type value;																\
2571 	if (Find##typeName(name, index, &value) == B_OK)						\
2572 		return value;														\
2573 																			\
2574 	return defaultValue;													\
2575 }																			\
2576 																			\
2577 																			\
2578 status_t																	\
2579 BMessage::Set##typeName(const char* name, const type& value)				\
2580 {																			\
2581 	return SetData(name, typeCode, &value, sizeof(type));					\
2582 }																			\
2583 
2584 
2585 DEFINE_SET_GET_BY_REFERENCE_FUNCTIONS(BPoint, Point, B_POINT_TYPE);
2586 DEFINE_SET_GET_BY_REFERENCE_FUNCTIONS(BRect, Rect, B_RECT_TYPE);
2587 DEFINE_SET_GET_BY_REFERENCE_FUNCTIONS(BSize, Size, B_SIZE_TYPE);
2588 
2589 #undef DEFINE_SET_GET_BY_REFERENCE_FUNCTIONS
2590 
2591 
2592 status_t
2593 BMessage::AddAlignment(const char* name, const BAlignment& alignment)
2594 {
2595 	int32 data[2] = { alignment.horizontal, alignment.vertical };
2596 	return AddData(name, B_ALIGNMENT_TYPE, data, sizeof(data));
2597 }
2598 
2599 
2600 status_t
2601 BMessage::AddString(const char* name, const char* string)
2602 {
2603 	return AddData(name, B_STRING_TYPE, string, string ? strlen(string) + 1 : 0,
2604 		false);
2605 }
2606 
2607 
2608 status_t
2609 BMessage::AddString(const char* name, const BString& string)
2610 {
2611 	return AddData(name, B_STRING_TYPE, string.String(), string.Length() + 1,
2612 		false);
2613 }
2614 
2615 
2616 status_t
2617 BMessage::AddStrings(const char* name, const BStringList& list)
2618 {
2619 	int32 count = list.CountStrings();
2620 	for (int32 i = 0; i < count; i++) {
2621 		status_t error = AddString(name, list.StringAt(i));
2622 		if (error != B_OK)
2623 			return error;
2624 	}
2625 
2626 	return B_OK;
2627 }
2628 
2629 
2630 status_t
2631 BMessage::AddPointer(const char* name, const void* pointer)
2632 {
2633 	return AddData(name, B_POINTER_TYPE, &pointer, sizeof(pointer), true);
2634 }
2635 
2636 
2637 status_t
2638 BMessage::AddMessenger(const char* name, BMessenger messenger)
2639 {
2640 	return AddData(name, B_MESSENGER_TYPE, &messenger, sizeof(messenger), true);
2641 }
2642 
2643 
2644 status_t
2645 BMessage::AddRef(const char* name, const entry_ref* ref)
2646 {
2647 	size_t size = sizeof(entry_ref) + B_PATH_NAME_LENGTH;
2648 	char buffer[size];
2649 
2650 	status_t error = BPrivate::entry_ref_flatten(buffer, &size, ref);
2651 
2652 	if (error >= B_OK)
2653 		error = AddData(name, B_REF_TYPE, buffer, size, false);
2654 
2655 	return error;
2656 }
2657 
2658 
2659 status_t
2660 BMessage::AddMessage(const char* name, const BMessage* message)
2661 {
2662 	if (message == NULL)
2663 		return B_BAD_VALUE;
2664 
2665 	// TODO: This and the following functions waste time by allocating and
2666 	// copying an extra buffer. Functions can be added that return a direct
2667 	// pointer into the message.
2668 
2669 	char stackBuffer[16384];
2670 	ssize_t size = message->FlattenedSize();
2671 
2672 	char* buffer;
2673 	if (size > (ssize_t)sizeof(stackBuffer)) {
2674 		buffer = (char*)malloc(size);
2675 		if (buffer == NULL)
2676 			return B_NO_MEMORY;
2677 	} else
2678 		buffer = stackBuffer;
2679 
2680 	status_t error = message->Flatten(buffer, size);
2681 
2682 	if (error >= B_OK)
2683 		error = AddData(name, B_MESSAGE_TYPE, buffer, size, false);
2684 
2685 	if (buffer != stackBuffer)
2686 		free(buffer);
2687 
2688 	return error;
2689 }
2690 
2691 
2692 status_t
2693 BMessage::AddFlat(const char* name, BFlattenable* object, int32 count)
2694 {
2695 	return AddFlat(name, (const BFlattenable*)object, count);
2696 }
2697 
2698 
2699 status_t
2700 BMessage::AddFlat(const char* name, const BFlattenable* object, int32 count)
2701 {
2702 	if (object == NULL)
2703 		return B_BAD_VALUE;
2704 
2705 	char stackBuffer[16384];
2706 	ssize_t size = object->FlattenedSize();
2707 
2708 	char* buffer;
2709 	if (size > (ssize_t)sizeof(stackBuffer)) {
2710 		buffer = (char*)malloc(size);
2711 		if (buffer == NULL)
2712 			return B_NO_MEMORY;
2713 	} else
2714 		buffer = stackBuffer;
2715 
2716 	status_t error = object->Flatten(buffer, size);
2717 
2718 	if (error >= B_OK)
2719 		error = AddData(name, object->TypeCode(), buffer, size, false);
2720 
2721 	if (buffer != stackBuffer)
2722 		free(buffer);
2723 
2724 	return error;
2725 }
2726 
2727 
2728 status_t
2729 BMessage::Append(const BMessage& other)
2730 {
2731 	field_header* field = other.fFields;
2732 	for (uint32 i = 0; i < other.fHeader->field_count; i++, field++) {
2733 		const char* name = (const char*)(other.fData + field->offset);
2734 		const void* data = (const void*)(other.fData + field->offset
2735 			+ field->name_length);
2736 		bool isFixed = (field->flags & FIELD_FLAG_FIXED_SIZE) != 0;
2737 		size_t size = field->data_size / field->count;
2738 
2739 		for (uint32 j = 0; j < field->count; j++) {
2740 			if (!isFixed) {
2741 				size = *(uint32*)data;
2742 				data = (const void*)((const char*)data + sizeof(uint32));
2743 			}
2744 
2745 			status_t status = AddData(name, field->type, data, size,
2746 				isFixed, 1);
2747 			if (status != B_OK)
2748 				return status;
2749 
2750 			data = (const void*)((const char*)data + size);
2751 		}
2752 	}
2753 	return B_OK;
2754 }
2755 
2756 
2757 status_t
2758 BMessage::FindAlignment(const char* name, BAlignment* alignment) const
2759 {
2760 	return FindAlignment(name, 0, alignment);
2761 }
2762 
2763 
2764 status_t
2765 BMessage::FindAlignment(const char* name, int32 index, BAlignment* alignment)
2766 	const
2767 {
2768 	if (!alignment)
2769 		return B_BAD_VALUE;
2770 
2771 	int32* data;
2772 	ssize_t bytes;
2773 
2774 	status_t err = FindData(name, B_ALIGNMENT_TYPE, index,
2775 		(const void**)&data, &bytes);
2776 
2777 	if (err == B_OK) {
2778 		if (bytes != sizeof(int32[2]))
2779 			return B_ERROR;
2780 
2781 		alignment->horizontal = (enum alignment)(*data);
2782 		alignment->vertical = (vertical_alignment)*(data + 1);
2783 	}
2784 
2785 	return err;
2786 }
2787 
2788 
2789 status_t
2790 BMessage::FindString(const char* name, const char** string) const
2791 {
2792 	return FindString(name, 0, string);
2793 }
2794 
2795 
2796 status_t
2797 BMessage::FindString(const char* name, int32 index, const char** string) const
2798 {
2799 	ssize_t bytes;
2800 	return FindData(name, B_STRING_TYPE, index, (const void**)string, &bytes);
2801 }
2802 
2803 
2804 status_t
2805 BMessage::FindString(const char* name, BString* string) const
2806 {
2807 	return FindString(name, 0, string);
2808 }
2809 
2810 
2811 status_t
2812 BMessage::FindString(const char* name, int32 index, BString* string) const
2813 {
2814 	if (string == NULL)
2815 		return B_BAD_VALUE;
2816 
2817 	const char* value;
2818 	status_t error = FindString(name, index, &value);
2819 
2820 	// Find*() clobbers the object even on failure
2821 	string->SetTo(value);
2822 	return error;
2823 }
2824 
2825 
2826 status_t
2827 BMessage::FindStrings(const char* name, BStringList* list) const
2828 {
2829 	if (list == NULL)
2830 		return B_BAD_VALUE;
2831 
2832 	list->MakeEmpty();
2833 
2834 	// get the number of items
2835 	type_code type;
2836 	int32 count;
2837 	if (GetInfo(name, &type, &count) != B_OK)
2838 		return B_NAME_NOT_FOUND;
2839 
2840 	if (type != B_STRING_TYPE)
2841 		return B_BAD_DATA;
2842 
2843 	for (int32 i = 0; i < count; i++) {
2844 		BString string;
2845 		status_t error = FindString(name, i, &string);
2846 		if (error != B_OK)
2847 			return error;
2848 		if (!list->Add(string))
2849 			return B_NO_MEMORY;
2850 	}
2851 
2852 	return B_OK;
2853 }
2854 
2855 
2856 status_t
2857 BMessage::FindPointer(const char* name, void** pointer) const
2858 {
2859 	return FindPointer(name, 0, pointer);
2860 }
2861 
2862 
2863 status_t
2864 BMessage::FindPointer(const char* name, int32 index, void** pointer) const
2865 {
2866 	if (pointer == NULL)
2867 		return B_BAD_VALUE;
2868 
2869 	void** data = NULL;
2870 	ssize_t size = 0;
2871 	status_t error = FindData(name, B_POINTER_TYPE, index,
2872 		(const void**)&data, &size);
2873 
2874 	if (error == B_OK)
2875 		*pointer = *data;
2876 	else
2877 		*pointer = NULL;
2878 
2879 	return error;
2880 }
2881 
2882 
2883 status_t
2884 BMessage::FindMessenger(const char* name, BMessenger* messenger) const
2885 {
2886 	return FindMessenger(name, 0, messenger);
2887 }
2888 
2889 
2890 status_t
2891 BMessage::FindMessenger(const char* name, int32 index,
2892 	BMessenger* messenger) const
2893 {
2894 	if (messenger == NULL)
2895 		return B_BAD_VALUE;
2896 
2897 	void* data = NULL;
2898 	ssize_t size = 0;
2899 	status_t error = FindData(name, B_MESSENGER_TYPE, index,
2900 		(const void**)&data, &size);
2901 
2902 	if (error == B_OK)
2903 		memcpy(messenger, data, sizeof(BMessenger));
2904 	else
2905 		*messenger = BMessenger();
2906 
2907 	return error;
2908 }
2909 
2910 
2911 status_t
2912 BMessage::FindRef(const char* name, entry_ref* ref) const
2913 {
2914 	return FindRef(name, 0, ref);
2915 }
2916 
2917 
2918 status_t
2919 BMessage::FindRef(const char* name, int32 index, entry_ref* ref) const
2920 {
2921 	if (ref == NULL)
2922 		return B_BAD_VALUE;
2923 
2924 	void* data = NULL;
2925 	ssize_t size = 0;
2926 	status_t error = FindData(name, B_REF_TYPE, index,
2927 		(const void**)&data, &size);
2928 
2929 	if (error == B_OK)
2930 		error = BPrivate::entry_ref_unflatten(ref, (char*)data, size);
2931 	else
2932 		*ref = entry_ref();
2933 
2934 	return error;
2935 }
2936 
2937 
2938 status_t
2939 BMessage::FindMessage(const char* name, BMessage* message) const
2940 {
2941 	return FindMessage(name, 0, message);
2942 }
2943 
2944 
2945 status_t
2946 BMessage::FindMessage(const char* name, int32 index, BMessage* message) const
2947 {
2948 	if (message == NULL)
2949 		return B_BAD_VALUE;
2950 
2951 	void* data = NULL;
2952 	ssize_t size = 0;
2953 	status_t error = FindData(name, B_MESSAGE_TYPE, index,
2954 		(const void**)&data, &size);
2955 
2956 	if (error == B_OK)
2957 		error = message->Unflatten((const char*)data);
2958 	else
2959 		*message = BMessage();
2960 
2961 	return error;
2962 }
2963 
2964 
2965 status_t
2966 BMessage::FindFlat(const char* name, BFlattenable* object) const
2967 {
2968 	return FindFlat(name, 0, object);
2969 }
2970 
2971 
2972 status_t
2973 BMessage::FindFlat(const char* name, int32 index, BFlattenable* object) const
2974 {
2975 	if (object == NULL)
2976 		return B_BAD_VALUE;
2977 
2978 	void* data = NULL;
2979 	ssize_t numBytes = 0;
2980 	status_t error = FindData(name, object->TypeCode(), index,
2981 		(const void**)&data, &numBytes);
2982 
2983 	if (error == B_OK)
2984 		error = object->Unflatten(object->TypeCode(), data, numBytes);
2985 
2986 	return error;
2987 }
2988 
2989 
2990 status_t
2991 BMessage::FindData(const char* name, type_code type, const void** data,
2992 	ssize_t* numBytes) const
2993 {
2994 	return FindData(name, type, 0, data, numBytes);
2995 }
2996 
2997 
2998 status_t
2999 BMessage::ReplaceAlignment(const char* name, const BAlignment& alignment)
3000 {
3001 	int32 data[2] = {alignment.horizontal, alignment.vertical};
3002 	return ReplaceData(name, B_ALIGNMENT_TYPE, 0, data, sizeof(data));
3003 }
3004 
3005 
3006 status_t
3007 BMessage::ReplaceAlignment(const char* name, int32 index,
3008 	const BAlignment& alignment)
3009 {
3010 	int32 data[2] = {alignment.horizontal, alignment.vertical};
3011 	return ReplaceData(name, B_ALIGNMENT_TYPE, index, data, sizeof(data));
3012 }
3013 
3014 
3015 status_t
3016 BMessage::ReplaceString(const char* name, const char* string)
3017 {
3018 	if (string == NULL)
3019 		return B_BAD_VALUE;
3020 
3021 	return ReplaceData(name, B_STRING_TYPE, 0, string, strlen(string) + 1);
3022 }
3023 
3024 
3025 status_t
3026 BMessage::ReplaceString(const char* name, int32 index, const char* string)
3027 {
3028 	if (string == NULL)
3029 		return B_BAD_VALUE;
3030 
3031 	return ReplaceData(name, B_STRING_TYPE, index, string, strlen(string) + 1);
3032 }
3033 
3034 
3035 status_t
3036 BMessage::ReplaceString(const char* name, const BString& string)
3037 {
3038 	return ReplaceData(name, B_STRING_TYPE, 0, string.String(),
3039 		string.Length() + 1);
3040 }
3041 
3042 
3043 status_t
3044 BMessage::ReplaceString(const char* name, int32 index, const BString& string)
3045 {
3046 	return ReplaceData(name, B_STRING_TYPE, index, string.String(),
3047 		string.Length() + 1);
3048 }
3049 
3050 
3051 status_t
3052 BMessage::ReplacePointer(const char* name, const void* pointer)
3053 {
3054 	return ReplaceData(name, B_POINTER_TYPE, 0, &pointer, sizeof(pointer));
3055 }
3056 
3057 
3058 status_t
3059 BMessage::ReplacePointer(const char* name, int32 index, const void* pointer)
3060 {
3061 	return ReplaceData(name, B_POINTER_TYPE, index, &pointer, sizeof(pointer));
3062 }
3063 
3064 
3065 status_t
3066 BMessage::ReplaceMessenger(const char* name, BMessenger messenger)
3067 {
3068 	return ReplaceData(name, B_MESSENGER_TYPE, 0, &messenger,
3069 		sizeof(BMessenger));
3070 }
3071 
3072 
3073 status_t
3074 BMessage::ReplaceMessenger(const char* name, int32 index, BMessenger messenger)
3075 {
3076 	return ReplaceData(name, B_MESSENGER_TYPE, index, &messenger,
3077 		sizeof(BMessenger));
3078 }
3079 
3080 
3081 status_t
3082 BMessage::ReplaceRef(const char* name, const entry_ref* ref)
3083 {
3084 	return ReplaceRef(name, 0, ref);
3085 }
3086 
3087 
3088 status_t
3089 BMessage::ReplaceRef(const char* name, int32 index, const entry_ref* ref)
3090 {
3091 	size_t size = sizeof(entry_ref) + B_PATH_NAME_LENGTH;
3092 	char buffer[size];
3093 
3094 	status_t error = BPrivate::entry_ref_flatten(buffer, &size, ref);
3095 
3096 	if (error >= B_OK)
3097 		error = ReplaceData(name, B_REF_TYPE, index, buffer, size);
3098 
3099 	return error;
3100 }
3101 
3102 
3103 status_t
3104 BMessage::ReplaceMessage(const char* name, const BMessage* message)
3105 {
3106 	return ReplaceMessage(name, 0, message);
3107 }
3108 
3109 
3110 status_t
3111 BMessage::ReplaceMessage(const char* name, int32 index, const BMessage* message)
3112 {
3113 	if (message == NULL)
3114 		return B_BAD_VALUE;
3115 
3116 	ssize_t size = message->FlattenedSize();
3117 	char buffer[size];
3118 
3119 	status_t error = message->Flatten(buffer, size);
3120 
3121 	if (error >= B_OK)
3122 		error = ReplaceData(name, B_MESSAGE_TYPE, index, &buffer, size);
3123 
3124 	return error;
3125 }
3126 
3127 
3128 status_t
3129 BMessage::ReplaceFlat(const char* name, BFlattenable* object)
3130 {
3131 	return ReplaceFlat(name, 0, object);
3132 }
3133 
3134 
3135 status_t
3136 BMessage::ReplaceFlat(const char* name, int32 index, BFlattenable* object)
3137 {
3138 	if (object == NULL)
3139 		return B_BAD_VALUE;
3140 
3141 	ssize_t size = object->FlattenedSize();
3142 	char buffer[size];
3143 
3144 	status_t error = object->Flatten(buffer, size);
3145 
3146 	if (error >= B_OK)
3147 		error = ReplaceData(name, object->TypeCode(), index, &buffer, size);
3148 
3149 	return error;
3150 }
3151 
3152 
3153 status_t
3154 BMessage::ReplaceData(const char* name, type_code type, const void* data,
3155 	ssize_t numBytes)
3156 {
3157 	return ReplaceData(name, type, 0, data, numBytes);
3158 }
3159 
3160 
3161 bool
3162 BMessage::HasFlat(const char* name, const BFlattenable* object) const
3163 {
3164 	return HasFlat(name, 0, object);
3165 }
3166 
3167 
3168 bool
3169 BMessage::HasFlat(const char* name, int32 index, const BFlattenable* object)
3170 	const
3171 {
3172 	return HasData(name, object->TypeCode(), index);
3173 }
3174 
3175 
3176 const char*
3177 BMessage::GetString(const char* name, const char* defaultValue) const
3178 {
3179 	return GetString(name, 0, defaultValue);
3180 }
3181 
3182 
3183 const char*
3184 BMessage::GetString(const char* name, int32 index,
3185 	const char* defaultValue) const
3186 {
3187 	const char* value;
3188 	if (FindString(name, index, &value) == B_OK)
3189 		return value;
3190 
3191 	return defaultValue;
3192 }
3193 
3194 
3195 status_t
3196 BMessage::SetString(const char* name, const BString& value)
3197 {
3198 	return SetData(name, B_STRING_TYPE, value.String(), value.Length() + 1);
3199 }
3200 
3201 
3202 status_t
3203 BMessage::SetString(const char* name, const char* value)
3204 {
3205 	return SetData(name, B_STRING_TYPE, value, strlen(value) + 1);
3206 }
3207 
3208 
3209 status_t
3210 BMessage::SetString(const char *name, const BString& value)
3211 {
3212 	return SetData(name, B_STRING_TYPE, value.String(), value.Length() + 1);
3213 }
3214 
3215 
3216 status_t
3217 BMessage::SetData(const char* name, type_code type, const void* data,
3218 	ssize_t numBytes)
3219 {
3220 	if (numBytes <= 0 || data == NULL)
3221 		return B_BAD_VALUE;
3222 
3223 	if (ReplaceData(name, type, data, numBytes) == B_OK)
3224 		return B_OK;
3225 
3226 	return AddData(name, type, data, numBytes);
3227 }
3228