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
64const char* B_SPECIFIER_ENTRY = "specifiers";
65const char* B_PROPERTY_ENTRY = "property";
66const char* B_PROPERTY_NAME_ENTRY = "name";
67
68
69static status_t handle_reply(port_id replyPort, int32* pCode,
70	bigtime_t timeout, BMessage* reply);
71
72
73extern "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
80BBlockCache* BMessage::sMsgCache = NULL;
81port_id BMessage::sReplyPorts[sNumReplyPorts];
82int32 BMessage::sReplyPortInUse[sNumReplyPorts];
83
84
85template<typename Type>
86static void
87print_to_stream_type(uint8* pointer)
88{
89	Type* item = (Type*)pointer;
90	item->PrintToStream();
91}
92
93
94template<typename Type>
95static void
96print_type(const char* format, uint8* pointer)
97{
98	Type* item = (Type*)pointer;
99	printf(format,* item,* item);
100}
101
102
103template<typename Type>
104static void
105print_type3(const char* format, uint8* pointer)
106{
107	Type* item = (Type*)pointer;
108	printf(format, *item, *item, *item);
109}
110
111
112static status_t
113handle_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
148BMessage::BMessage()
149{
150	DEBUG_FUNCTION_ENTER;
151	_InitCommon(true);
152}
153
154
155BMessage::BMessage(BMessage* other)
156{
157	DEBUG_FUNCTION_ENTER;
158	_InitCommon(false);
159	*this = *other;
160}
161
162
163BMessage::BMessage(uint32 _what)
164{
165	DEBUG_FUNCTION_ENTER;
166	if (_InitCommon(true))
167		fHeader->what = _what;
168	what = _what;
169}
170
171
172BMessage::BMessage(const BMessage& other)
173{
174	DEBUG_FUNCTION_ENTER;
175	_InitCommon(false);
176	*this = other;
177}
178
179
180BMessage::~BMessage()
181{
182	DEBUG_FUNCTION_ENTER;
183	_Clear();
184}
185
186
187BMessage&
188BMessage::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
246void*
247BMessage::operator new(size_t size)
248{
249	DEBUG_FUNCTION_ENTER2;
250	return sMsgCache->Get(size);
251}
252
253
254void*
255BMessage::operator new(size_t size, const std::nothrow_t& noThrow)
256{
257	DEBUG_FUNCTION_ENTER2;
258	return sMsgCache->Get(size);
259}
260
261
262void*
263BMessage::operator new(size_t, void* pointer)
264{
265	DEBUG_FUNCTION_ENTER2;
266	return pointer;
267}
268
269
270void
271BMessage::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
280bool
281BMessage::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
344status_t
345BMessage::_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
369status_t
370BMessage::_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
399status_t
400BMessage::_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
434status_t
435BMessage::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
479status_t
480BMessage::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
501status_t
502BMessage::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
520status_t
521BMessage::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
541int32
542BMessage::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
562bool
563BMessage::IsEmpty() const
564{
565	DEBUG_FUNCTION_ENTER;
566	return fHeader == NULL || fHeader->field_count == 0;
567}
568
569
570bool
571BMessage::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
592bool
593BMessage::IsReply() const
594{
595	DEBUG_FUNCTION_ENTER;
596	return fHeader != NULL && (fHeader->flags & MESSAGE_FLAG_IS_REPLY) != 0;
597}
598
599
600void
601BMessage::PrintToStream() const
602{
603	_PrintToStream("");
604	printf("}\n");
605}
606
607
608void
609BMessage::_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
770status_t
771BMessage::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
824bool
825BMessage::WasDelivered() const
826{
827	DEBUG_FUNCTION_ENTER;
828	return fHeader != NULL
829		&& (fHeader->flags & MESSAGE_FLAG_WAS_DELIVERED) != 0;
830}
831
832
833bool
834BMessage::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
843bool
844BMessage::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
853BMessenger
854BMessage::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
867const BMessage*
868BMessage::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
885bool
886BMessage::WasDropped() const
887{
888	DEBUG_FUNCTION_ENTER;
889	return fHeader != NULL
890		&& (fHeader->flags & MESSAGE_FLAG_WAS_DROPPED) != 0;
891}
892
893
894BPoint
895BMessage::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
905status_t
906BMessage::SendReply(uint32 command, BHandler* replyTo)
907{
908	DEBUG_FUNCTION_ENTER;
909	BMessage message(command);
910	return SendReply(&message, replyTo);
911}
912
913
914status_t
915BMessage::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
923status_t
924BMessage::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
967status_t
968BMessage::SendReply(uint32 command, BMessage* replyToReply)
969{
970	DEBUG_FUNCTION_ENTER;
971	BMessage message(command);
972	return SendReply(&message, replyToReply);
973}
974
975
976status_t
977BMessage::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
1024ssize_t
1025BMessage::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
1036status_t
1037BMessage::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
1065status_t
1066BMessage::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
1133status_t
1134BMessage::_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
1174status_t
1175BMessage::_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
1205status_t
1206BMessage::_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
1220status_t
1221BMessage::_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
1260status_t
1261BMessage::_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
1289status_t
1290BMessage::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
1305status_t
1306BMessage::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
1379status_t
1380BMessage::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
1392status_t
1393BMessage::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
1409status_t
1410BMessage::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
1433status_t
1434BMessage::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
1450status_t
1451BMessage::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
1464status_t
1465BMessage::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
1485status_t
1486BMessage::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
1518bool
1519BMessage::HasSpecifiers() const
1520{
1521	DEBUG_FUNCTION_ENTER;
1522	return fHeader != NULL
1523		&& (fHeader->flags & MESSAGE_FLAG_HAS_SPECIFIERS) != 0;
1524}
1525
1526
1527status_t
1528BMessage::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
1545void
1546BMessage::_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
1559status_t
1560BMessage::_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
1632uint32
1633BMessage::_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
1648status_t
1649BMessage::_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
1685status_t
1686BMessage::_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
1734status_t
1735BMessage::_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
1785status_t
1786BMessage::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
1854status_t
1855BMessage::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
1910status_t
1911BMessage::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
1933status_t
1934BMessage::MakeEmpty()
1935{
1936	DEBUG_FUNCTION_ENTER;
1937	_Clear();
1938	return _InitHeader();
1939}
1940
1941
1942status_t
1943BMessage::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
1978status_t
1979BMessage::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
2033bool
2034BMessage::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 */
2050void
2051BMessage::_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
2066void
2067BMessage::_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
2082void
2083BMessage::_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
2095void
2096BMessage::_StaticCacheCleanup()
2097{
2098	DEBUG_FUNCTION_ENTER2;
2099	delete sMsgCache;
2100	sMsgCache = NULL;
2101}
2102
2103
2104int32
2105BMessage::_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
2125status_t
2126BMessage::_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.
2272status_t
2273BMessage::_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
2371error:
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
2388status_t
2389BMessage::_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
2429void BMessage::_ReservedMessage1() {}
2430void BMessage::_ReservedMessage2() {}
2431void 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)							\
2440status_t																	\
2441BMessage::Add##typeName(const char* name, type val)							\
2442{																			\
2443	return AddData(name, typeCode, &val, sizeof(type), true);				\
2444}																			\
2445																			\
2446																			\
2447status_t																	\
2448BMessage::Find##typeName(const char* name, type* p) const					\
2449{																			\
2450	return Find##typeName(name, 0, p);										\
2451}																			\
2452																			\
2453																			\
2454status_t																	\
2455BMessage::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																			\
2471status_t																	\
2472BMessage::Replace##typeName(const char* name, type value)					\
2473{																			\
2474	return ReplaceData(name, typeCode, 0, &value, sizeof(type));			\
2475}																			\
2476																			\
2477																			\
2478status_t																	\
2479BMessage::Replace##typeName(const char* name, int32 index, type value)		\
2480{																			\
2481	return ReplaceData(name, typeCode, index, &value, sizeof(type));		\
2482}																			\
2483																			\
2484																			\
2485bool																		\
2486BMessage::Has##typeName(const char* name, int32 index) const				\
2487{																			\
2488	return HasData(name, typeCode, index);									\
2489}
2490
2491DEFINE_FUNCTIONS(BPoint, Point, B_POINT_TYPE);
2492DEFINE_FUNCTIONS(BRect, Rect, B_RECT_TYPE);
2493DEFINE_FUNCTIONS(BSize, Size, B_SIZE_TYPE);
2494DEFINE_FUNCTIONS(int8, Int8, B_INT8_TYPE);
2495DEFINE_FUNCTIONS(uint8, UInt8, B_UINT8_TYPE);
2496DEFINE_FUNCTIONS(int16, Int16, B_INT16_TYPE);
2497DEFINE_FUNCTIONS(uint16, UInt16, B_UINT16_TYPE);
2498DEFINE_FUNCTIONS(int32, Int32, B_INT32_TYPE);
2499DEFINE_FUNCTIONS(uint32, UInt32, B_UINT32_TYPE);
2500DEFINE_FUNCTIONS(int64, Int64, B_INT64_TYPE);
2501DEFINE_FUNCTIONS(uint64, UInt64, B_UINT64_TYPE);
2502DEFINE_FUNCTIONS(bool, Bool, B_BOOL_TYPE);
2503DEFINE_FUNCTIONS(float, Float, B_FLOAT_TYPE);
2504DEFINE_FUNCTIONS(double, Double, B_DOUBLE_TYPE);
2505DEFINE_FUNCTIONS(rgb_color, Color, B_RGB_32_BIT_TYPE);
2506
2507#undef DEFINE_FUNCTIONS
2508
2509#define DEFINE_HAS_FUNCTION(typeName, typeCode)								\
2510bool																		\
2511BMessage::Has##typeName(const char* name, int32 index) const				\
2512{																			\
2513	return HasData(name, typeCode, index);									\
2514}
2515
2516
2517DEFINE_HAS_FUNCTION(Alignment, B_ALIGNMENT_TYPE);
2518DEFINE_HAS_FUNCTION(String, B_STRING_TYPE);
2519DEFINE_HAS_FUNCTION(Pointer, B_POINTER_TYPE);
2520DEFINE_HAS_FUNCTION(Messenger, B_MESSENGER_TYPE);
2521DEFINE_HAS_FUNCTION(Ref, B_REF_TYPE);
2522DEFINE_HAS_FUNCTION(NodeRef, B_NODE_REF_TYPE);
2523DEFINE_HAS_FUNCTION(Message, B_MESSAGE_TYPE);
2524
2525#undef DEFINE_HAS_FUNCTION
2526
2527
2528#define DEFINE_LAZY_FIND_FUNCTION(type, typeName, initialize)				\
2529type																		\
2530BMessage::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
2538DEFINE_LAZY_FIND_FUNCTION(BRect, Rect, BRect());
2539DEFINE_LAZY_FIND_FUNCTION(BPoint, Point, BPoint());
2540DEFINE_LAZY_FIND_FUNCTION(const char*, String, NULL);
2541DEFINE_LAZY_FIND_FUNCTION(int8, Int8, 0);
2542DEFINE_LAZY_FIND_FUNCTION(int16, Int16, 0);
2543DEFINE_LAZY_FIND_FUNCTION(int32, Int32, 0);
2544DEFINE_LAZY_FIND_FUNCTION(int64, Int64, 0);
2545DEFINE_LAZY_FIND_FUNCTION(bool, Bool, false);
2546DEFINE_LAZY_FIND_FUNCTION(float, Float, 0);
2547DEFINE_LAZY_FIND_FUNCTION(double, Double, 0);
2548
2549#undef DEFINE_LAZY_FIND_FUNCTION
2550
2551
2552#define DEFINE_SET_GET_FUNCTIONS(type, typeName, typeCode)					\
2553type																		\
2554BMessage::Get##typeName(const char* name, type defaultValue) const			\
2555{																			\
2556	return Get##typeName(name, 0, defaultValue);							\
2557}																			\
2558																			\
2559																			\
2560type																		\
2561BMessage::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																			\
2572status_t																	\
2573BMessage::Set##typeName(const char* name, type value)						\
2574{																			\
2575	return SetData(name, typeCode, &value, sizeof(type));					\
2576}																			\
2577
2578
2579DEFINE_SET_GET_FUNCTIONS(int8, Int8, B_INT8_TYPE);
2580DEFINE_SET_GET_FUNCTIONS(uint8, UInt8, B_UINT8_TYPE);
2581DEFINE_SET_GET_FUNCTIONS(int16, Int16, B_INT16_TYPE);
2582DEFINE_SET_GET_FUNCTIONS(uint16, UInt16, B_UINT16_TYPE);
2583DEFINE_SET_GET_FUNCTIONS(int32, Int32, B_INT32_TYPE);
2584DEFINE_SET_GET_FUNCTIONS(uint32, UInt32, B_UINT32_TYPE);
2585DEFINE_SET_GET_FUNCTIONS(int64, Int64, B_INT64_TYPE);
2586DEFINE_SET_GET_FUNCTIONS(uint64, UInt64, B_UINT64_TYPE);
2587DEFINE_SET_GET_FUNCTIONS(bool, Bool, B_BOOL_TYPE);
2588DEFINE_SET_GET_FUNCTIONS(float, Float, B_FLOAT_TYPE);
2589DEFINE_SET_GET_FUNCTIONS(double, Double, B_DOUBLE_TYPE);
2590DEFINE_SET_GET_FUNCTIONS(rgb_color, Color, B_RGB_32_BIT_TYPE);
2591
2592#undef DEFINE_SET_GET_FUNCTION
2593
2594
2595const void*
2596BMessage::GetPointer(const char* name, const void* defaultValue) const
2597{
2598	return GetPointer(name, 0, defaultValue);
2599}
2600
2601
2602const void*
2603BMessage::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
2614status_t
2615BMessage::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)		\
2622type																		\
2623BMessage::Get##typeName(const char* name, const type& defaultValue) const	\
2624{																			\
2625	return Get##typeName(name, 0, defaultValue);							\
2626}																			\
2627																			\
2628																			\
2629type																		\
2630BMessage::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																			\
2641status_t																	\
2642BMessage::Set##typeName(const char* name, const type& value)				\
2643{																			\
2644	return SetData(name, typeCode, &value, sizeof(type));					\
2645}																			\
2646
2647
2648DEFINE_SET_GET_BY_REFERENCE_FUNCTIONS(BPoint, Point, B_POINT_TYPE);
2649DEFINE_SET_GET_BY_REFERENCE_FUNCTIONS(BRect, Rect, B_RECT_TYPE);
2650DEFINE_SET_GET_BY_REFERENCE_FUNCTIONS(BSize, Size, B_SIZE_TYPE);
2651DEFINE_SET_GET_BY_REFERENCE_FUNCTIONS(BAlignment, Alignment, B_ALIGNMENT_TYPE);
2652
2653#undef DEFINE_SET_GET_BY_REFERENCE_FUNCTIONS
2654
2655
2656status_t
2657BMessage::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
2664status_t
2665BMessage::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
2672status_t
2673BMessage::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
2680status_t
2681BMessage::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
2694status_t
2695BMessage::AddPointer(const char* name, const void* pointer)
2696{
2697	return AddData(name, B_POINTER_TYPE, &pointer, sizeof(pointer), true);
2698}
2699
2700
2701status_t
2702BMessage::AddMessenger(const char* name, BMessenger messenger)
2703{
2704	return AddData(name, B_MESSENGER_TYPE, &messenger, sizeof(messenger), true);
2705}
2706
2707
2708status_t
2709BMessage::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
2723status_t
2724BMessage::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
2738status_t
2739BMessage::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
2771status_t
2772BMessage::AddFlat(const char* name, BFlattenable* object, int32 count)
2773{
2774	return AddFlat(name, (const BFlattenable*)object, count);
2775}
2776
2777
2778status_t
2779BMessage::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
2807status_t
2808BMessage::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
2836status_t
2837BMessage::FindAlignment(const char* name, BAlignment* alignment) const
2838{
2839	return FindAlignment(name, 0, alignment);
2840}
2841
2842
2843status_t
2844BMessage::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
2868status_t
2869BMessage::FindString(const char* name, const char** string) const
2870{
2871	return FindString(name, 0, string);
2872}
2873
2874
2875status_t
2876BMessage::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
2883status_t
2884BMessage::FindString(const char* name, BString* string) const
2885{
2886	return FindString(name, 0, string);
2887}
2888
2889
2890status_t
2891BMessage::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
2905status_t
2906BMessage::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
2935status_t
2936BMessage::FindPointer(const char* name, void** pointer) const
2937{
2938	return FindPointer(name, 0, pointer);
2939}
2940
2941
2942status_t
2943BMessage::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
2962status_t
2963BMessage::FindMessenger(const char* name, BMessenger* messenger) const
2964{
2965	return FindMessenger(name, 0, messenger);
2966}
2967
2968
2969status_t
2970BMessage::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
2990status_t
2991BMessage::FindRef(const char* name, entry_ref* ref) const
2992{
2993	return FindRef(name, 0, ref);
2994}
2995
2996
2997status_t
2998BMessage::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
3017status_t
3018BMessage::FindNodeRef(const char* name, node_ref* ref) const
3019{
3020	return FindNodeRef(name, 0, ref);
3021}
3022
3023
3024status_t
3025BMessage::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
3044status_t
3045BMessage::FindMessage(const char* name, BMessage* message) const
3046{
3047	return FindMessage(name, 0, message);
3048}
3049
3050
3051status_t
3052BMessage::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
3071status_t
3072BMessage::FindFlat(const char* name, BFlattenable* object) const
3073{
3074	return FindFlat(name, 0, object);
3075}
3076
3077
3078status_t
3079BMessage::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
3096status_t
3097BMessage::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
3104status_t
3105BMessage::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
3112status_t
3113BMessage::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
3121status_t
3122BMessage::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
3131status_t
3132BMessage::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
3141status_t
3142BMessage::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
3149status_t
3150BMessage::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
3157status_t
3158BMessage::ReplacePointer(const char* name, const void* pointer)
3159{
3160	return ReplaceData(name, B_POINTER_TYPE, 0, &pointer, sizeof(pointer));
3161}
3162
3163
3164status_t
3165BMessage::ReplacePointer(const char* name, int32 index, const void* pointer)
3166{
3167	return ReplaceData(name, B_POINTER_TYPE, index, &pointer, sizeof(pointer));
3168}
3169
3170
3171status_t
3172BMessage::ReplaceMessenger(const char* name, BMessenger messenger)
3173{
3174	return ReplaceData(name, B_MESSENGER_TYPE, 0, &messenger,
3175		sizeof(BMessenger));
3176}
3177
3178
3179status_t
3180BMessage::ReplaceMessenger(const char* name, int32 index, BMessenger messenger)
3181{
3182	return ReplaceData(name, B_MESSENGER_TYPE, index, &messenger,
3183		sizeof(BMessenger));
3184}
3185
3186
3187status_t
3188BMessage::ReplaceRef(const char* name, const entry_ref* ref)
3189{
3190	return ReplaceRef(name, 0, ref);
3191}
3192
3193
3194status_t
3195BMessage::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
3209status_t
3210BMessage::ReplaceNodeRef(const char* name, const node_ref* ref)
3211{
3212	return ReplaceNodeRef(name, 0, ref);
3213}
3214
3215
3216status_t
3217BMessage::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
3231status_t
3232BMessage::ReplaceMessage(const char* name, const BMessage* message)
3233{
3234	return ReplaceMessage(name, 0, message);
3235}
3236
3237
3238status_t
3239BMessage::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
3259status_t
3260BMessage::ReplaceFlat(const char* name, BFlattenable* object)
3261{
3262	return ReplaceFlat(name, 0, object);
3263}
3264
3265
3266status_t
3267BMessage::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
3287status_t
3288BMessage::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
3295bool
3296BMessage::HasFlat(const char* name, const BFlattenable* object) const
3297{
3298	return HasFlat(name, 0, object);
3299}
3300
3301
3302bool
3303BMessage::HasFlat(const char* name, int32 index, const BFlattenable* object)
3304	const
3305{
3306	return HasData(name, object->TypeCode(), index);
3307}
3308
3309
3310const char*
3311BMessage::GetString(const char* name, const char* defaultValue) const
3312{
3313	return GetString(name, 0, defaultValue);
3314}
3315
3316
3317const char*
3318BMessage::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
3329status_t
3330BMessage::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
3337status_t
3338BMessage::SetString(const char* name, const char* value)
3339{
3340	return SetData(name, B_STRING_TYPE, value, strlen(value) + 1, false);
3341}
3342
3343
3344status_t
3345BMessage::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