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