2 * Copyright 2005-2011, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Michael Lotz <mmlr@mlotz.ch>
11 #include <MessageAdapter.h>
12 #include <MessagePrivate.h>
13 #include <MessageUtils.h>
15 #include <MessengerPrivate.h>
16 #include <TokenSpace.h>
18 #include <Application.h>
20 #include <BlockCache.h>
22 #include <MessageQueue.h>
23 #include <Messenger.h>
28 #include <StringList.h>
36 #include "tracing_config.h"
37 // kernel tracing configuration
39 //#define VERBOSE_DEBUG_OUTPUT
40 #ifdef VERBOSE_DEBUG_OUTPUT
41 #define DEBUG_FUNCTION_ENTER \
42 debug_printf("msg thread: %ld; this: %p; header: %p; fields: %p;" \
43 " data: %p; what: 0x%08lx '%.4s'; line: %d; func: %s\n", \
44 find_thread(NULL), this, fHeader, fFields, fData, what, (char *)&what, \
45 __LINE__, __PRETTY_FUNCTION__);
47 #define DEBUG_FUNCTION_ENTER2 \
48 debug_printf("msg thread: %ld; line: %d: func: %s\n", find_thread(NULL), \
49 __LINE__, __PRETTY_FUNCTION__);
51 #define DEBUG_FUNCTION_ENTER /* nothing */
52 #define DEBUG_FUNCTION_ENTER2 /* nothing */
56 # define KTRACE(format...) ktrace_printf(format)
58 # define KTRACE(format...)
62 const char *B_SPECIFIER_ENTRY
= "specifiers";
63 const char *B_PROPERTY_ENTRY
= "property";
64 const char *B_PROPERTY_NAME_ENTRY
= "name";
67 // private os function to set the owning team of an area
68 status_t
_kern_transfer_area(area_id area
, void **_address
,
69 uint32 addressSpec
, team_id target
);
73 BBlockCache
*BMessage::sMsgCache
= NULL
;
76 template<typename Type
>
78 print_to_stream_type(uint8
*pointer
)
80 Type
*item
= (Type
*)pointer
;
81 item
->PrintToStream();
85 template<typename Type
>
87 print_type(const char *format
, uint8
*pointer
)
89 Type
*item
= (Type
*)pointer
;
90 printf(format
, *item
, *item
);
104 BMessage::BMessage(BMessage
*other
)
106 DEBUG_FUNCTION_ENTER
;
112 BMessage::BMessage(uint32 _what
)
114 DEBUG_FUNCTION_ENTER
;
116 fHeader
->what
= what
= _what
;
120 BMessage::BMessage(const BMessage
&other
)
122 DEBUG_FUNCTION_ENTER
;
128 BMessage::~BMessage()
130 DEBUG_FUNCTION_ENTER
;
136 BMessage::operator=(const BMessage
&other
)
138 DEBUG_FUNCTION_ENTER
;
145 fHeader
= (message_header
*)malloc(sizeof(message_header
));
149 memcpy(fHeader
, other
.fHeader
, sizeof(message_header
));
151 // Clear some header flags inherited from the original message that don't
152 // apply to the clone.
153 fHeader
->flags
&= ~(MESSAGE_FLAG_REPLY_REQUIRED
| MESSAGE_FLAG_REPLY_DONE
154 | MESSAGE_FLAG_IS_REPLY
| MESSAGE_FLAG_WAS_DELIVERED
155 | MESSAGE_FLAG_PASS_BY_AREA
);
156 // Note, that BeOS R5 seems to keep the reply info.
158 if (fHeader
->field_count
> 0) {
159 size_t fieldsSize
= fHeader
->field_count
* sizeof(field_header
);
160 fFields
= (field_header
*)malloc(fieldsSize
);
161 if (fFields
== NULL
) {
162 fHeader
->field_count
= 0;
163 fHeader
->data_size
= 0;
165 memcpy(fFields
, other
.fFields
, fieldsSize
);
168 if (fHeader
->data_size
> 0) {
169 fData
= (uint8
*)malloc(fHeader
->data_size
);
171 fHeader
->field_count
= 0;
175 memcpy(fData
, other
.fData
, fHeader
->data_size
);
178 fHeader
->what
= what
= other
.what
;
179 fHeader
->message_area
= -1;
180 fFieldsAvailable
= 0;
188 BMessage::operator new(size_t size
)
190 DEBUG_FUNCTION_ENTER2
;
192 sMsgCache
= new BBlockCache(10, sizeof(BMessage
), B_OBJECT_CACHE
);
193 void *pointer
= sMsgCache
->Get(size
);
199 BMessage::operator new(size_t, void *pointer
)
201 DEBUG_FUNCTION_ENTER2
;
207 BMessage::operator delete(void *pointer
, size_t size
)
209 DEBUG_FUNCTION_ENTER2
;
210 sMsgCache
->Save(pointer
, size
);
215 BMessage::HasSameData(const BMessage
&other
, bool ignoreFieldOrder
,
221 if (fHeader
->field_count
!= other
.fHeader
->field_count
)
224 for (uint32 i
= 0; i
< fHeader
->field_count
; i
++) {
225 field_header
*field
= &fFields
[i
];
226 field_header
*otherField
= NULL
;
228 const char *name
= (const char *)fData
+ field
->offset
;
229 if (ignoreFieldOrder
) {
230 if (other
._FindField(name
, B_ANY_TYPE
, &otherField
) != B_OK
)
233 otherField
= &other
.fFields
[i
];
234 if (otherField
->name_length
!= field
->name_length
)
237 const char *otherName
= (const char *)other
.fData
238 + otherField
->offset
;
239 if (strncmp(name
, otherName
, field
->name_length
) != 0)
243 if (otherField
->type
!= field
->type
|| otherField
->count
!= field
->count
)
246 uint8
*data
= fData
+ field
->offset
+ field
->name_length
;
247 uint8
*otherData
= other
.fData
+ otherField
->offset
248 + otherField
->name_length
;
250 bool needsMemCompare
= true;
251 if (deep
&& field
->type
== B_MESSAGE_TYPE
) {
252 BMessage message
, otherMessage
;
253 if (message
.Unflatten((const char *)data
) == B_OK
254 && otherMessage
.Unflatten((const char *)otherData
) == B_OK
) {
255 if (!message
.HasSameData(ignoreFieldOrder
, deep
))
257 needsMemCompare
= false;
261 if (needsMemCompare
) {
262 if (otherField
->data_size
!= field
->data_size
)
264 if (memcmp(data
, otherData
, field
->data_size
) != 0)
274 BMessage::_InitCommon(bool initHeader
)
276 DEBUG_FUNCTION_ENTER
;
283 fFieldsAvailable
= 0;
290 return _InitHeader();
298 BMessage::_InitHeader()
300 DEBUG_FUNCTION_ENTER
;
301 if (fHeader
== NULL
) {
302 fHeader
= (message_header
*)malloc(sizeof(message_header
));
307 memset(fHeader
, 0, sizeof(message_header
) - sizeof(fHeader
->hash_table
));
309 fHeader
->format
= MESSAGE_FORMAT_HAIKU
;
310 fHeader
->flags
= MESSAGE_FLAG_VALID
;
311 fHeader
->what
= what
;
312 fHeader
->current_specifier
= -1;
313 fHeader
->message_area
= -1;
315 fHeader
->target
= B_NULL_TOKEN
;
316 fHeader
->reply_target
= B_NULL_TOKEN
;
317 fHeader
->reply_port
= -1;
318 fHeader
->reply_team
= -1;
320 // initializing the hash table to -1 because 0 is a valid index
321 fHeader
->hash_table_size
= MESSAGE_BODY_HASH_TABLE_SIZE
;
322 memset(&fHeader
->hash_table
, 255, sizeof(fHeader
->hash_table
));
330 DEBUG_FUNCTION_ENTER
;
331 if (fHeader
!= NULL
) {
341 fFieldsAvailable
= 0;
352 BMessage::GetInfo(type_code typeRequested
, int32 index
, char **nameFound
,
353 type_code
*typeFound
, int32
*countFound
) const
355 DEBUG_FUNCTION_ENTER
;
356 if (index
< 0 || (uint32
)index
>= fHeader
->field_count
)
359 if (typeRequested
== B_ANY_TYPE
) {
361 *nameFound
= (char *)fData
+ fFields
[index
].offset
;
363 *typeFound
= fFields
[index
].type
;
365 *countFound
= fFields
[index
].count
;
370 field_header
*field
= fFields
;
371 for (uint32 i
= 0; i
< fHeader
->field_count
; i
++, field
++) {
372 if (field
->type
== typeRequested
)
375 if (counter
== index
) {
377 *nameFound
= (char *)fData
+ field
->offset
;
379 *typeFound
= field
->type
;
381 *countFound
= field
->count
;
394 BMessage::GetInfo(const char *name
, type_code
*typeFound
, int32
*countFound
)
397 DEBUG_FUNCTION_ENTER
;
401 field_header
*field
= NULL
;
402 status_t result
= _FindField(name
, B_ANY_TYPE
, &field
);
403 if (result
< B_OK
|| field
== NULL
)
407 *typeFound
= field
->type
;
409 *countFound
= field
->count
;
416 BMessage::GetInfo(const char *name
, type_code
*typeFound
, bool *fixedSize
)
419 DEBUG_FUNCTION_ENTER
;
420 field_header
*field
= NULL
;
421 status_t result
= _FindField(name
, B_ANY_TYPE
, &field
);
422 if (result
< B_OK
|| field
== NULL
)
426 *typeFound
= field
->type
;
428 *fixedSize
= (field
->flags
& FIELD_FLAG_FIXED_SIZE
) != 0;
435 BMessage::CountNames(type_code type
) const
437 DEBUG_FUNCTION_ENTER
;
438 if (type
== B_ANY_TYPE
)
439 return fHeader
->field_count
;
442 field_header
*field
= fFields
;
443 for (uint32 i
= 0; i
< fHeader
->field_count
; i
++, field
++) {
444 if (field
->type
== type
)
453 BMessage::IsEmpty() const
455 DEBUG_FUNCTION_ENTER
;
456 return fHeader
->field_count
== 0;
461 BMessage::IsSystem() const
463 DEBUG_FUNCTION_ENTER
;
464 char a
= char(what
>> 24);
465 char b
= char(what
>> 16);
466 char c
= char(what
>> 8);
470 // ... we've adopted a strict convention for assigning values to all
471 // Be-defined constants. The value assigned will always be formed by
472 // combining four characters into a multicharacter constant, with the
473 // characters limited to uppercase letters and the underbar
474 // Between that and what's in AppDefs.h, this algo seems like a safe bet:
475 if (a
== '_' && isupper(b
) && isupper(c
) && isupper(d
))
483 BMessage::IsReply() const
485 DEBUG_FUNCTION_ENTER
;
486 return (fHeader
->flags
& MESSAGE_FLAG_IS_REPLY
) != 0;
491 BMessage::PrintToStream() const
499 BMessage::_PrintToStream(const char* indent
) const
501 DEBUG_FUNCTION_ENTER
;
503 int32 value
= B_BENDIAN_TO_HOST_INT32(what
);
505 if (isprint(*(char *)&value
))
506 printf("'%.4s'", (char *)&value
);
508 printf("0x%" B_PRIx32
, what
);
511 if (fHeader
== NULL
|| fFields
== NULL
|| fData
== NULL
)
514 field_header
*field
= fFields
;
515 for (uint32 i
= 0; i
< fHeader
->field_count
; i
++, field
++) {
516 value
= B_BENDIAN_TO_HOST_INT32(field
->type
);
518 if ((field
->flags
& FIELD_FLAG_FIXED_SIZE
) != 0 && field
->count
> 0)
519 size
= field
->data_size
/ field
->count
;
521 uint8
*pointer
= fData
+ field
->offset
+ field
->name_length
;
522 for (uint32 j
= 0; j
< field
->count
; j
++) {
523 if (field
->count
== 1) {
524 printf("%s %s = ", indent
,
525 (char *)(fData
+ field
->offset
));
527 printf("%s %s[%" B_PRIu32
"] = ", indent
,
528 (char *)(fData
+ field
->offset
), j
);
531 switch (field
->type
) {
533 print_to_stream_type
<BRect
>(pointer
);
537 print_to_stream_type
<BPoint
>(pointer
);
542 size
= *(uint32
*)pointer
;
543 pointer
+= sizeof(uint32
);
544 printf("string(\"%s\", %ld bytes)\n", (char *)pointer
,
550 print_type
<int8
>("int8(0x%hx or %d or '%.1s')\n", pointer
);
554 print_type
<uint8
>("uint8(0x%hx or %u or '%.1s')\n",
559 print_type
<int16
>("int16(0x%x or %d)\n", pointer
);
563 print_type
<uint16
>("uint16(0x%x or %u\n", pointer
);
567 print_type
<int32
>("int32(0x%lx or %ld)\n", pointer
);
571 print_type
<uint32
>("uint32(0x%lx or %lu\n", pointer
);
575 print_type
<int64
>("int64(0x%Lx or %Ld)\n", pointer
);
579 print_type
<uint64
>("uint64(0x%Lx or %Ld\n", pointer
);
583 printf("bool(%s)\n", *((bool *)pointer
) != 0
588 print_type
<float>("float(%.4f)\n", pointer
);
592 print_type
<double>("double(%.8f)\n", pointer
);
597 size
= *(uint32
*)pointer
;
598 pointer
+= sizeof(uint32
);
600 BPrivate::entry_ref_unflatten(&ref
, (char *)pointer
, size
);
602 printf("entry_ref(device=%d, directory=%lld"
603 ", name=\"%s\", ", (int)ref
.device
,
604 (long long)ref
.directory
, ref
.name
);
607 printf("path=\"%s\")\n", path
.Path());
614 sprintf(buffer
, "%s ", indent
);
617 size
= *(uint32
*)pointer
;
618 pointer
+= sizeof(uint32
);
619 status_t result
= message
.Unflatten((const char *)pointer
);
620 if (result
!= B_OK
) {
621 printf("failed unflatten: %s\n", strerror(result
));
625 message
._PrintToStream(buffer
);
626 printf("%s }\n", indent
);
632 printf("(type = '%.4s')(size = %ld)\n", (char *)&value
,
645 BMessage::Rename(const char *oldEntry
, const char *newEntry
)
647 DEBUG_FUNCTION_ENTER
;
648 if (oldEntry
== NULL
|| newEntry
== NULL
)
651 uint32 hash
= _HashName(oldEntry
) % fHeader
->hash_table_size
;
652 int32
*nextField
= &fHeader
->hash_table
[hash
];
654 while (*nextField
>= 0) {
655 field_header
*field
= &fFields
[*nextField
];
657 if (strncmp((const char *)(fData
+ field
->offset
), oldEntry
,
658 field
->name_length
) == 0) {
659 // nextField points to the field for oldEntry, save it and unlink
660 int32 index
= *nextField
;
661 *nextField
= field
->next_field
;
662 field
->next_field
= -1;
664 hash
= _HashName(newEntry
) % fHeader
->hash_table_size
;
665 nextField
= &fHeader
->hash_table
[hash
];
666 while (*nextField
>= 0)
667 nextField
= &fFields
[*nextField
].next_field
;
670 int32 newLength
= strlen(newEntry
) + 1;
671 status_t result
= _ResizeData(field
->offset
+ 1,
672 newLength
- field
->name_length
);
676 memcpy(fData
+ field
->offset
, newEntry
, newLength
);
677 field
->name_length
= newLength
;
681 nextField
= &field
->next_field
;
684 return B_NAME_NOT_FOUND
;
689 BMessage::WasDelivered() const
691 DEBUG_FUNCTION_ENTER
;
692 return (fHeader
->flags
& MESSAGE_FLAG_WAS_DELIVERED
) != 0;
697 BMessage::IsSourceWaiting() const
699 DEBUG_FUNCTION_ENTER
;
700 return (fHeader
->flags
& MESSAGE_FLAG_REPLY_REQUIRED
) != 0
701 && (fHeader
->flags
& MESSAGE_FLAG_REPLY_DONE
) == 0;
706 BMessage::ReturnAddress() const
708 DEBUG_FUNCTION_ENTER
;
709 if ((fHeader
->flags
& MESSAGE_FLAG_WAS_DELIVERED
) != 0) {
710 BMessenger messenger
;
711 BMessenger::Private(messenger
).SetTo(fHeader
->reply_team
,
712 fHeader
->reply_port
, fHeader
->reply_target
);
721 BMessage::Previous() const
723 DEBUG_FUNCTION_ENTER
;
724 /* ToDo: test if the "_previous_" field is used in R5 */
725 if (fOriginal
== NULL
) {
726 fOriginal
= new BMessage();
728 if (FindMessage("_previous_", fOriginal
) != B_OK
) {
739 BMessage::WasDropped() const
741 DEBUG_FUNCTION_ENTER
;
742 return (fHeader
->flags
& MESSAGE_FLAG_WAS_DROPPED
) != 0;
747 BMessage::DropPoint(BPoint
*offset
) const
749 DEBUG_FUNCTION_ENTER
;
751 *offset
= FindPoint("_drop_offset_");
753 return FindPoint("_drop_point_");
758 BMessage::FlattenedSize() const
760 DEBUG_FUNCTION_ENTER
;
761 return sizeof(message_header
) + fHeader
->field_count
* sizeof(field_header
)
762 + fHeader
->data_size
;
767 BMessage::Flatten(char *buffer
, ssize_t size
) const
769 DEBUG_FUNCTION_ENTER
;
770 if (buffer
== NULL
|| size
< 0)
776 /* we have to sync the what code as it is a public member */
777 fHeader
->what
= what
;
779 memcpy(buffer
, fHeader
, min_c(sizeof(message_header
), (size_t)size
));
780 buffer
+= sizeof(message_header
);
781 size
-= sizeof(message_header
);
783 size_t fieldsSize
= fHeader
->field_count
* sizeof(field_header
);
784 memcpy(buffer
, fFields
, min_c(fieldsSize
, (size_t)size
));
785 buffer
+= fieldsSize
;
788 memcpy(buffer
, fData
, min_c(fHeader
->data_size
, (size_t)size
));
789 if ((size_t)size
< fHeader
->data_size
)
790 return B_BUFFER_OVERFLOW
;
797 BMessage::Flatten(BDataIO
*stream
, ssize_t
*size
) const
799 DEBUG_FUNCTION_ENTER
;
806 /* we have to sync the what code as it is a public member */
807 fHeader
->what
= what
;
809 ssize_t result1
= stream
->Write(fHeader
, sizeof(message_header
));
810 if (result1
!= sizeof(message_header
))
811 return result1
< 0 ? result1
: B_ERROR
;
814 if (fHeader
->field_count
> 0) {
815 ssize_t fieldsSize
= fHeader
->field_count
* sizeof(field_header
);
816 result2
= stream
->Write(fFields
, fieldsSize
);
817 if (result2
!= fieldsSize
)
818 return result2
< 0 ? result2
: B_ERROR
;
822 if (fHeader
->data_size
> 0) {
823 result3
= stream
->Write(fData
, fHeader
->data_size
);
824 if (result3
!= (ssize_t
)fHeader
->data_size
)
825 return result3
< 0 ? result3
: B_ERROR
;
829 *size
= result1
+ result2
+ result3
;
836 BMessage::_ValidateMessage()
838 if (fHeader
->field_count
== 0)
844 for (uint32 i
= 0; i
< fHeader
->field_count
; i
++) {
845 field_header
*field
= &fFields
[i
];
846 if ((field
->next_field
>= 0
847 && (uint32
)field
->next_field
> fHeader
->field_count
)
848 || (field
->offset
+ field
->name_length
+ field
->data_size
849 > fHeader
->data_size
)) {
850 // the message is corrupt
861 BMessage::Unflatten(const char *flatBuffer
)
863 DEBUG_FUNCTION_ENTER
;
864 if (flatBuffer
== NULL
)
867 uint32 format
= *(uint32
*)flatBuffer
;
868 if (format
!= MESSAGE_FORMAT_HAIKU
)
869 return BPrivate::MessageAdapter::Unflatten(format
, this, flatBuffer
);
871 // native message unflattening
875 fHeader
= (message_header
*)malloc(sizeof(message_header
));
879 memcpy(fHeader
, flatBuffer
, sizeof(message_header
));
880 flatBuffer
+= sizeof(message_header
);
882 if (fHeader
->format
!= MESSAGE_FORMAT_HAIKU
883 || (fHeader
->flags
& MESSAGE_FLAG_VALID
) == 0) {
888 what
= fHeader
->what
;
890 if ((fHeader
->flags
& MESSAGE_FLAG_PASS_BY_AREA
) != 0
891 && fHeader
->message_area
>= 0) {
892 // status_t result = _Reference();
893 // if (result != B_OK)
896 fHeader
->message_area
= -1;
898 if (fHeader
->field_count
> 0) {
899 size_t fieldsSize
= fHeader
->field_count
* sizeof(field_header
);
900 fFields
= (field_header
*)malloc(fieldsSize
);
901 if (fFields
== NULL
) {
906 memcpy(fFields
, flatBuffer
, fieldsSize
);
907 flatBuffer
+= fieldsSize
;
910 if (fHeader
->data_size
> 0) {
911 fData
= (uint8
*)malloc(fHeader
->data_size
);
919 memcpy(fData
, flatBuffer
, fHeader
->data_size
);
923 return _ValidateMessage();
928 BMessage::Unflatten(BDataIO
*stream
)
930 DEBUG_FUNCTION_ENTER
;
935 stream
->Read(&format
, sizeof(uint32
));
936 if (format
!= MESSAGE_FORMAT_HAIKU
)
937 return BPrivate::MessageAdapter::Unflatten(format
, this, stream
);
939 // native message unflattening
943 fHeader
= (message_header
*)malloc(sizeof(message_header
));
947 fHeader
->format
= format
;
948 uint8
*header
= (uint8
*)fHeader
;
949 ssize_t result
= stream
->Read(header
+ sizeof(uint32
),
950 sizeof(message_header
) - sizeof(uint32
));
951 if (result
!= sizeof(message_header
) - sizeof(uint32
)
952 || (fHeader
->flags
& MESSAGE_FLAG_VALID
) == 0) {
954 return result
< 0 ? result
: B_BAD_VALUE
;
957 what
= fHeader
->what
;
959 fHeader
->message_area
= -1;
961 if (fHeader
->field_count
> 0) {
962 ssize_t fieldsSize
= fHeader
->field_count
* sizeof(field_header
);
963 fFields
= (field_header
*)malloc(fieldsSize
);
964 if (fFields
== NULL
) {
969 result
= stream
->Read(fFields
, fieldsSize
);
970 if (result
!= fieldsSize
)
971 return result
< 0 ? result
: B_BAD_VALUE
;
974 if (fHeader
->data_size
> 0) {
975 fData
= (uint8
*)malloc(fHeader
->data_size
);
983 result
= stream
->Read(fData
, fHeader
->data_size
);
984 if (result
!= (ssize_t
)fHeader
->data_size
)
985 return result
< 0 ? result
: B_BAD_VALUE
;
988 return _ValidateMessage();
993 BMessage::AddSpecifier(const char *property
)
995 DEBUG_FUNCTION_ENTER
;
996 BMessage
message(B_DIRECT_SPECIFIER
);
997 status_t result
= message
.AddString(B_PROPERTY_ENTRY
, property
);
1001 return AddSpecifier(&message
);
1006 BMessage::AddSpecifier(const char *property
, int32 index
)
1008 DEBUG_FUNCTION_ENTER
;
1009 BMessage
message(B_INDEX_SPECIFIER
);
1010 status_t result
= message
.AddString(B_PROPERTY_ENTRY
, property
);
1014 result
= message
.AddInt32("index", index
);
1018 return AddSpecifier(&message
);
1023 BMessage::AddSpecifier(const char *property
, int32 index
, int32 range
)
1025 DEBUG_FUNCTION_ENTER
;
1029 BMessage
message(B_RANGE_SPECIFIER
);
1030 status_t result
= message
.AddString(B_PROPERTY_ENTRY
, property
);
1034 result
= message
.AddInt32("index", index
);
1038 result
= message
.AddInt32("range", range
);
1042 return AddSpecifier(&message
);
1047 BMessage::AddSpecifier(const char *property
, const char *name
)
1049 DEBUG_FUNCTION_ENTER
;
1050 BMessage
message(B_NAME_SPECIFIER
);
1051 status_t result
= message
.AddString(B_PROPERTY_ENTRY
, property
);
1055 result
= message
.AddString(B_PROPERTY_NAME_ENTRY
, name
);
1059 return AddSpecifier(&message
);
1064 BMessage::AddSpecifier(const BMessage
*specifier
)
1066 DEBUG_FUNCTION_ENTER
;
1067 status_t result
= AddMessage(B_SPECIFIER_ENTRY
, specifier
);
1071 fHeader
->current_specifier
++;
1072 fHeader
->flags
|= MESSAGE_FLAG_HAS_SPECIFIERS
;
1078 BMessage::SetCurrentSpecifier(int32 index
)
1080 DEBUG_FUNCTION_ENTER
;
1086 status_t result
= GetInfo(B_SPECIFIER_ENTRY
, &type
, &count
);
1093 fHeader
->current_specifier
= index
;
1099 BMessage::GetCurrentSpecifier(int32
*index
, BMessage
*specifier
, int32
*_what
,
1100 const char **property
) const
1102 DEBUG_FUNCTION_ENTER
;
1105 *index
= fHeader
->current_specifier
;
1107 if (fHeader
->current_specifier
< 0
1108 || (fHeader
->flags
& MESSAGE_FLAG_WAS_DELIVERED
) == 0)
1109 return B_BAD_SCRIPT_SYNTAX
;
1112 if (FindMessage(B_SPECIFIER_ENTRY
, fHeader
->current_specifier
,
1114 return B_BAD_SCRIPT_SYNTAX
;
1117 *_what
= specifier
->what
;
1120 if (specifier
->FindString(B_PROPERTY_ENTRY
, property
) < B_OK
)
1121 return B_BAD_SCRIPT_SYNTAX
;
1130 BMessage::HasSpecifiers() const
1132 DEBUG_FUNCTION_ENTER
;
1133 return (fHeader
->flags
& MESSAGE_FLAG_HAS_SPECIFIERS
) != 0;
1138 BMessage::PopSpecifier()
1140 DEBUG_FUNCTION_ENTER
;
1141 if (fHeader
->current_specifier
< 0 ||
1142 (fHeader
->flags
& MESSAGE_FLAG_WAS_DELIVERED
) == 0)
1145 if (fHeader
->current_specifier
>= 0)
1146 fHeader
->current_specifier
--;
1153 BMessage::_ResizeData(uint32 offset
, int32 change
)
1158 /* optimize for the most usual case: appending data */
1159 if (offset
< fHeader
->data_size
) {
1160 field_header
*field
= fFields
;
1161 for (uint32 i
= 0; i
< fHeader
->field_count
; i
++, field
++) {
1162 if (field
->offset
>= offset
)
1163 field
->offset
+= change
;
1168 if (fDataAvailable
>= (uint32
)change
) {
1169 if (offset
< fHeader
->data_size
) {
1170 memmove(fData
+ offset
+ change
, fData
+ offset
,
1171 fHeader
->data_size
- offset
);
1174 fDataAvailable
-= change
;
1175 fHeader
->data_size
+= change
;
1179 size_t size
= fHeader
->data_size
* 2;
1180 size
= min_c(size
, fHeader
->data_size
+ MAX_DATA_PREALLOCATION
);
1181 size
= max_c(size
, fHeader
->data_size
+ change
);
1183 uint8
*newData
= (uint8
*)realloc(fData
, size
);
1184 if (size
> 0 && newData
== NULL
)
1188 if (offset
< fHeader
->data_size
) {
1189 memmove(fData
+ offset
+ change
, fData
+ offset
,
1190 fHeader
->data_size
- offset
);
1193 fHeader
->data_size
+= change
;
1194 fDataAvailable
= size
- fHeader
->data_size
;
1196 ssize_t length
= fHeader
->data_size
- offset
+ change
;
1198 memmove(fData
+ offset
, fData
+ offset
- change
, length
);
1200 // change is negative
1201 fHeader
->data_size
+= change
;
1202 fDataAvailable
-= change
;
1204 if (fDataAvailable
> MAX_DATA_PREALLOCATION
) {
1205 ssize_t available
= MAX_DATA_PREALLOCATION
/ 2;
1206 ssize_t size
= fHeader
->data_size
+ available
;
1207 uint8
*newData
= (uint8
*)realloc(fData
, size
);
1208 if (size
> 0 && newData
== NULL
) {
1209 // this is strange, but not really fatal
1214 fDataAvailable
= available
;
1223 BMessage::_HashName(const char *name
) const
1228 while ((ch
= *name
++) != 0) {
1229 result
= (result
<< 7) ^ (result
>> 24);
1233 result
^= result
<< 12;
1239 BMessage::_FindField(const char *name
, type_code type
, field_header
**result
) const
1244 if (fHeader
== NULL
|| fFields
== NULL
|| fData
== NULL
)
1245 return B_NAME_NOT_FOUND
;
1247 uint32 hash
= _HashName(name
) % fHeader
->hash_table_size
;
1248 int32 nextField
= fHeader
->hash_table
[hash
];
1250 while (nextField
>= 0) {
1251 field_header
*field
= &fFields
[nextField
];
1252 if ((field
->flags
& FIELD_FLAG_VALID
) == 0)
1255 if (strncmp((const char *)(fData
+ field
->offset
), name
,
1256 field
->name_length
) == 0) {
1257 if (type
!= B_ANY_TYPE
&& field
->type
!= type
)
1264 nextField
= field
->next_field
;
1267 return B_NAME_NOT_FOUND
;
1272 BMessage::_AddField(const char *name
, type_code type
, bool isFixedSize
,
1273 field_header
**result
)
1275 if (fHeader
== NULL
)
1278 if (fFieldsAvailable
<= 0) {
1279 uint32 count
= fHeader
->field_count
* 2 + 1;
1280 count
= min_c(count
, fHeader
->field_count
+ MAX_FIELD_PREALLOCATION
);
1282 field_header
*newFields
= (field_header
*)realloc(fFields
,
1283 count
* sizeof(field_header
));
1284 if (count
> 0 && newFields
== NULL
)
1287 fFields
= newFields
;
1288 fFieldsAvailable
= count
- fHeader
->field_count
;
1291 uint32 hash
= _HashName(name
) % fHeader
->hash_table_size
;
1292 int32
*nextField
= &fHeader
->hash_table
[hash
];
1293 while (*nextField
>= 0)
1294 nextField
= &fFields
[*nextField
].next_field
;
1295 *nextField
= fHeader
->field_count
;
1297 field_header
*field
= &fFields
[fHeader
->field_count
];
1300 field
->data_size
= 0;
1301 field
->next_field
= -1;
1302 field
->offset
= fHeader
->data_size
;
1303 field
->name_length
= strlen(name
) + 1;
1304 status_t status
= _ResizeData(field
->offset
, field
->name_length
);
1308 memcpy(fData
+ field
->offset
, name
, field
->name_length
);
1309 field
->flags
= FIELD_FLAG_VALID
;
1311 field
->flags
|= FIELD_FLAG_FIXED_SIZE
;
1314 fHeader
->field_count
++;
1321 BMessage::_RemoveField(field_header
*field
)
1323 status_t result
= _ResizeData(field
->offset
, -(field
->data_size
1324 + field
->name_length
));
1328 int32 index
= ((uint8
*)field
- (uint8
*)fFields
) / sizeof(field_header
);
1329 int32 nextField
= field
->next_field
;
1330 if (nextField
> index
)
1333 int32
*value
= fHeader
->hash_table
;
1334 for (uint32 i
= 0; i
< fHeader
->hash_table_size
; i
++, value
++) {
1337 else if (*value
== index
)
1341 field_header
*other
= fFields
;
1342 for (uint32 i
= 0; i
< fHeader
->field_count
; i
++, other
++) {
1343 if (other
->next_field
> index
)
1344 other
->next_field
--;
1345 else if (other
->next_field
== index
)
1346 other
->next_field
= nextField
;
1349 size_t size
= (fHeader
->field_count
- index
- 1) * sizeof(field_header
);
1350 memmove(fFields
+ index
, fFields
+ index
+ 1, size
);
1351 fHeader
->field_count
--;
1354 if (fFieldsAvailable
> MAX_FIELD_PREALLOCATION
) {
1355 ssize_t available
= MAX_FIELD_PREALLOCATION
/ 2;
1356 size
= (fHeader
->field_count
+ available
) * sizeof(field_header
);
1357 field_header
*newFields
= (field_header
*)realloc(fFields
, size
);
1358 if (size
> 0 && newFields
== NULL
) {
1359 // this is strange, but not really fatal
1363 fFields
= newFields
;
1364 fFieldsAvailable
= available
;
1372 BMessage::AddData(const char *name
, type_code type
, const void *data
,
1373 ssize_t numBytes
, bool isFixedSize
, int32 count
)
1375 // Note that the "count" argument is only a hint at how many items
1376 // the caller expects to add to this field. Since we do no item pre-
1377 // allocation, we ignore this argument.
1378 DEBUG_FUNCTION_ENTER
;
1379 if (numBytes
<= 0 || data
== NULL
)
1382 field_header
*field
= NULL
;
1383 status_t result
= _FindField(name
, type
, &field
);
1384 if (result
== B_NAME_NOT_FOUND
)
1385 result
= _AddField(name
, type
, isFixedSize
, &field
);
1393 uint32 offset
= field
->offset
+ field
->name_length
+ field
->data_size
;
1394 if ((field
->flags
& FIELD_FLAG_FIXED_SIZE
) != 0) {
1396 ssize_t size
= field
->data_size
/ field
->count
;
1397 if (size
!= numBytes
)
1401 result
= _ResizeData(offset
, numBytes
);
1402 if (result
< B_OK
) {
1403 if (field
->count
== 0)
1404 _RemoveField(field
);
1408 memcpy(fData
+ offset
, data
, numBytes
);
1409 field
->data_size
+= numBytes
;
1411 int32 change
= numBytes
+ sizeof(uint32
);
1412 result
= _ResizeData(offset
, change
);
1413 if (result
< B_OK
) {
1414 if (field
->count
== 0)
1415 _RemoveField(field
);
1419 uint32 size
= (uint32
)numBytes
;
1420 memcpy(fData
+ offset
, &size
, sizeof(uint32
));
1421 memcpy(fData
+ offset
+ sizeof(uint32
), data
, size
);
1422 field
->data_size
+= change
;
1431 BMessage::RemoveData(const char *name
, int32 index
)
1433 DEBUG_FUNCTION_ENTER
;
1437 field_header
*field
= NULL
;
1438 status_t result
= _FindField(name
, B_ANY_TYPE
, &field
);
1446 if ((uint32
)index
>= field
->count
)
1449 if (field
->count
== 1)
1450 return _RemoveField(field
);
1452 uint32 offset
= field
->offset
+ field
->name_length
;
1453 if ((field
->flags
& FIELD_FLAG_FIXED_SIZE
) != 0) {
1454 ssize_t size
= field
->data_size
/ field
->count
;
1455 result
= _ResizeData(offset
+ index
* size
, -size
);
1459 field
->data_size
-= size
;
1461 uint8
*pointer
= fData
+ offset
;
1462 for (int32 i
= 0; i
< index
; i
++) {
1463 offset
+= *(uint32
*)pointer
+ sizeof(uint32
);
1464 pointer
= fData
+ offset
;
1467 size_t currentSize
= *(uint32
*)pointer
+ sizeof(uint32
);
1468 result
= _ResizeData(offset
, -currentSize
);
1472 field
->data_size
-= currentSize
;
1481 BMessage::RemoveName(const char *name
)
1483 DEBUG_FUNCTION_ENTER
;
1484 field_header
*field
= NULL
;
1485 status_t result
= _FindField(name
, B_ANY_TYPE
, &field
);
1493 return _RemoveField(field
);
1498 BMessage::MakeEmpty()
1500 DEBUG_FUNCTION_ENTER
;
1508 BMessage::FindData(const char *name
, type_code type
, int32 index
,
1509 const void **data
, ssize_t
*numBytes
) const
1511 DEBUG_FUNCTION_ENTER
;
1516 field_header
*field
= NULL
;
1517 status_t result
= _FindField(name
, type
, &field
);
1525 if (index
< 0 || (uint32
)index
>= field
->count
)
1528 if ((field
->flags
& FIELD_FLAG_FIXED_SIZE
) != 0) {
1529 size_t bytes
= field
->data_size
/ field
->count
;
1530 *data
= fData
+ field
->offset
+ field
->name_length
+ index
* bytes
;
1531 if (numBytes
!= NULL
)
1534 uint8
*pointer
= fData
+ field
->offset
+ field
->name_length
;
1535 for (int32 i
= 0; i
< index
; i
++)
1536 pointer
+= *(uint32
*)pointer
+ sizeof(uint32
);
1538 *data
= pointer
+ sizeof(uint32
);
1539 if (numBytes
!= NULL
)
1540 *numBytes
= *(uint32
*)pointer
;
1548 BMessage::ReplaceData(const char *name
, type_code type
, int32 index
,
1549 const void *data
, ssize_t numBytes
)
1551 DEBUG_FUNCTION_ENTER
;
1552 if (numBytes
<= 0 || data
== NULL
)
1555 field_header
*field
= NULL
;
1556 status_t result
= _FindField(name
, type
, &field
);
1564 if (index
< 0 || (uint32
)index
>= field
->count
)
1567 if ((field
->flags
& FIELD_FLAG_FIXED_SIZE
) != 0) {
1568 ssize_t size
= field
->data_size
/ field
->count
;
1569 if (size
!= numBytes
)
1572 memcpy(fData
+ field
->offset
+ field
->name_length
+ index
* size
, data
,
1575 uint32 offset
= field
->offset
+ field
->name_length
;
1576 uint8
*pointer
= fData
+ offset
;
1578 for (int32 i
= 0; i
< index
; i
++) {
1579 offset
+= *(uint32
*)pointer
+ sizeof(uint32
);
1580 pointer
= fData
+ offset
;
1583 size_t currentSize
= *(uint32
*)pointer
;
1584 int32 change
= numBytes
- currentSize
;
1585 result
= _ResizeData(offset
, change
);
1589 uint32 newSize
= (uint32
)numBytes
;
1590 memcpy(fData
+ offset
, &newSize
, sizeof(uint32
));
1591 memcpy(fData
+ offset
+ sizeof(uint32
), data
, newSize
);
1592 field
->data_size
+= change
;
1600 BMessage::HasData(const char *name
, type_code type
, int32 index
) const
1602 DEBUG_FUNCTION_ENTER
;
1603 field_header
*field
= NULL
;
1604 status_t result
= _FindField(name
, type
, &field
);
1612 if (index
< 0 || (uint32
)index
>= field
->count
)
1619 void BMessage::_ReservedMessage1(void) {};
1620 void BMessage::_ReservedMessage2(void) {};
1621 void BMessage::_ReservedMessage3(void) {};
1624 /* Relay functions from here on (Add... -> AddData, Find... -> FindData) */
1626 #define DEFINE_FUNCTIONS(type, typeName, typeCode) \
1628 BMessage::Add##typeName(const char *name, type val) \
1630 return AddData(name, typeCode, &val, sizeof(type), true); \
1634 BMessage::Find##typeName(const char *name, type *p) const \
1637 ssize_t bytes = 0; \
1638 status_t error = B_OK; \
1641 error = FindData(name, typeCode, 0, (const void **)&ptr, &bytes); \
1643 if (error == B_OK) \
1644 memcpy(p, ptr, sizeof(type)); \
1650 BMessage::Find##typeName(const char *name, int32 index, type *p) const \
1653 ssize_t bytes = 0; \
1654 status_t error = B_OK; \
1657 error = FindData(name, typeCode, index, (const void **)&ptr, &bytes); \
1659 if (error == B_OK) \
1660 memcpy(p, ptr, sizeof(type)); \
1666 BMessage::Replace##typeName(const char *name, type val) \
1668 return ReplaceData(name, typeCode, 0, &val, sizeof(type)); \
1672 BMessage::Replace##typeName(const char *name, int32 index, type val) \
1674 return ReplaceData(name, typeCode, index, &val, sizeof(type)); \
1678 BMessage::Has##typeName(const char *name, int32 index) const \
1680 return HasData(name, typeCode, index); \
1683 DEFINE_FUNCTIONS(BPoint
, Point
, B_POINT_TYPE
);
1684 DEFINE_FUNCTIONS(BRect
, Rect
, B_RECT_TYPE
);
1685 DEFINE_FUNCTIONS(int8
, Int8
, B_INT8_TYPE
);
1686 DEFINE_FUNCTIONS(uint8
, UInt8
, B_UINT8_TYPE
);
1687 DEFINE_FUNCTIONS(int16
, Int16
, B_INT16_TYPE
);
1688 DEFINE_FUNCTIONS(uint16
, UInt16
, B_UINT16_TYPE
);
1689 DEFINE_FUNCTIONS(int32
, Int32
, B_INT32_TYPE
);
1690 DEFINE_FUNCTIONS(uint32
, UInt32
, B_UINT32_TYPE
);
1691 DEFINE_FUNCTIONS(int64
, Int64
, B_INT64_TYPE
);
1692 DEFINE_FUNCTIONS(uint64
, UInt64
, B_UINT64_TYPE
);
1693 DEFINE_FUNCTIONS(bool, Bool
, B_BOOL_TYPE
);
1694 DEFINE_FUNCTIONS(float, Float
, B_FLOAT_TYPE
);
1695 DEFINE_FUNCTIONS(double, Double
, B_DOUBLE_TYPE
);
1697 #undef DEFINE_FUNCTIONS
1699 #define DEFINE_HAS_FUNCTION(typeName, typeCode) \
1701 BMessage::Has##typeName(const char *name, int32 index) const \
1703 return HasData(name, typeCode, index); \
1706 DEFINE_HAS_FUNCTION(String
, B_STRING_TYPE
);
1707 DEFINE_HAS_FUNCTION(Pointer
, B_POINTER_TYPE
);
1708 DEFINE_HAS_FUNCTION(Messenger
, B_MESSENGER_TYPE
);
1709 DEFINE_HAS_FUNCTION(Ref
, B_REF_TYPE
);
1710 DEFINE_HAS_FUNCTION(Message
, B_MESSAGE_TYPE
);
1712 #undef DEFINE_HAS_FUNCTION
1714 #define DEFINE_LAZY_FIND_FUNCTION(type, typeName, initialize) \
1716 BMessage::Find##typeName(const char *name, int32 index) const \
1718 type val = initialize; \
1719 Find##typeName(name, index, &val); \
1723 DEFINE_LAZY_FIND_FUNCTION(BRect
, Rect
, BRect());
1724 DEFINE_LAZY_FIND_FUNCTION(BPoint
, Point
, BPoint());
1725 DEFINE_LAZY_FIND_FUNCTION(const char *, String
, NULL
);
1726 DEFINE_LAZY_FIND_FUNCTION(int8
, Int8
, 0);
1727 DEFINE_LAZY_FIND_FUNCTION(int16
, Int16
, 0);
1728 DEFINE_LAZY_FIND_FUNCTION(int32
, Int32
, 0);
1729 DEFINE_LAZY_FIND_FUNCTION(int64
, Int64
, 0);
1730 DEFINE_LAZY_FIND_FUNCTION(bool, Bool
, false);
1731 DEFINE_LAZY_FIND_FUNCTION(float, Float
, 0);
1732 DEFINE_LAZY_FIND_FUNCTION(double, Double
, 0);
1734 #undef DEFINE_LAZY_FIND_FUNCTION
1737 BMessage::AddString(const char *name
, const char *string
)
1739 return AddData(name
, B_STRING_TYPE
, string
, string
? strlen(string
) + 1 : 0, false);
1744 BMessage::AddString(const char *name
, const BString
&string
)
1746 return AddData(name
, B_STRING_TYPE
, string
.String(), string
.Length() + 1, false);
1751 BMessage::AddStrings(const char *name
, const BStringList
&list
)
1753 int32 count
= list
.CountStrings();
1754 for (int32 i
= 0; i
< count
; i
++) {
1755 status_t error
= AddString(name
, list
.StringAt(i
));
1765 BMessage::AddPointer(const char *name
, const void *pointer
)
1767 return AddData(name
, B_POINTER_TYPE
, &pointer
, sizeof(pointer
), true);
1772 BMessage::AddMessenger(const char *name
, BMessenger messenger
)
1774 return AddData(name
, B_MESSENGER_TYPE
, &messenger
, sizeof(messenger
), true);
1779 BMessage::AddRef(const char *name
, const entry_ref
*ref
)
1781 size_t size
= sizeof(entry_ref
) + B_PATH_NAME_LENGTH
;
1784 status_t error
= BPrivate::entry_ref_flatten(buffer
, &size
, ref
);
1787 error
= AddData(name
, B_REF_TYPE
, buffer
, size
, false);
1794 BMessage::AddMessage(const char *name
, const BMessage
*message
)
1796 if (message
== NULL
)
1799 // TODO: This and the following functions waste time by allocating and
1800 // copying an extra buffer. Functions can be added that return a direct
1801 // pointer into the message.
1803 char stackBuffer
[16384];
1804 ssize_t size
= message
->FlattenedSize();
1807 if (size
> (ssize_t
)sizeof(stackBuffer
)) {
1808 buffer
= (char *)malloc(size
);
1812 buffer
= stackBuffer
;
1814 status_t error
= message
->Flatten(buffer
, size
);
1817 error
= AddData(name
, B_MESSAGE_TYPE
, buffer
, size
, false);
1819 if (buffer
!= stackBuffer
)
1827 BMessage::AddFlat(const char *name
, BFlattenable
*object
, int32 count
)
1832 char stackBuffer
[16384];
1833 ssize_t size
= object
->FlattenedSize();
1836 if (size
> (ssize_t
)sizeof(stackBuffer
)) {
1837 buffer
= (char *)malloc(size
);
1841 buffer
= stackBuffer
;
1843 status_t error
= object
->Flatten(buffer
, size
);
1846 error
= AddData(name
, object
->TypeCode(), buffer
, size
, false);
1848 if (buffer
!= stackBuffer
)
1856 BMessage::FindString(const char *name
, const char **string
) const
1858 return FindString(name
, 0, string
);
1863 BMessage::FindString(const char *name
, int32 index
, const char **string
) const
1866 return FindData(name
, B_STRING_TYPE
, index
, (const void **)string
, &bytes
);
1871 BMessage::FindString(const char *name
, BString
*string
) const
1873 return FindString(name
, 0, string
);
1878 BMessage::FindString(const char *name
, int32 index
, BString
*string
) const
1884 status_t error
= FindString(name
, index
, &cstr
);
1894 BMessage::FindStrings(const char *name
, BStringList
*list
) const
1901 // get the number of items
1904 if (GetInfo(name
, &type
, &count
) != B_OK
)
1905 return B_NAME_NOT_FOUND
;
1907 if (type
!= B_STRING_TYPE
)
1910 for (int32 i
= 0; i
< count
; i
++) {
1912 status_t error
= FindString(name
, i
, &string
);
1915 if (!list
->Add(string
))
1924 BMessage::FindPointer(const char *name
, void **pointer
) const
1926 return FindPointer(name
, 0, pointer
);
1931 BMessage::FindPointer(const char *name
, int32 index
, void **pointer
) const
1933 if (pointer
== NULL
)
1938 status_t error
= FindData(name
, B_POINTER_TYPE
, index
,
1939 (const void **)&data
, &size
);
1951 BMessage::FindMessenger(const char *name
, BMessenger
*messenger
) const
1953 return FindMessenger(name
, 0, messenger
);
1958 BMessage::FindMessenger(const char *name
, int32 index
, BMessenger
*messenger
)
1961 if (messenger
== NULL
)
1966 status_t error
= FindData(name
, B_MESSENGER_TYPE
, index
,
1967 (const void **)&data
, &size
);
1970 memcpy(messenger
, data
, sizeof(BMessenger
));
1972 *messenger
= BMessenger();
1979 BMessage::FindRef(const char *name
, entry_ref
*ref
) const
1981 return FindRef(name
, 0, ref
);
1986 BMessage::FindRef(const char *name
, int32 index
, entry_ref
*ref
) const
1993 status_t error
= FindData(name
, B_REF_TYPE
, index
,
1994 (const void **)&data
, &size
);
1997 error
= BPrivate::entry_ref_unflatten(ref
, (char *)data
, size
);
2006 BMessage::FindMessage(const char *name
, BMessage
*message
) const
2008 return FindMessage(name
, 0, message
);
2013 BMessage::FindMessage(const char *name
, int32 index
, BMessage
*message
) const
2015 if (message
== NULL
)
2020 status_t error
= FindData(name
, B_MESSAGE_TYPE
, index
,
2021 (const void **)&data
, &size
);
2024 error
= message
->Unflatten((const char *)data
);
2026 *message
= BMessage();
2033 BMessage::FindFlat(const char *name
, BFlattenable
*object
) const
2035 return FindFlat(name
, 0, object
);
2040 BMessage::FindFlat(const char *name
, int32 index
, BFlattenable
*object
) const
2046 ssize_t numBytes
= 0;
2047 status_t error
= FindData(name
, object
->TypeCode(), index
,
2048 (const void **)&data
, &numBytes
);
2051 error
= object
->Unflatten(object
->TypeCode(), data
, numBytes
);
2058 BMessage::FindData(const char *name
, type_code type
, const void **data
,
2059 ssize_t
*numBytes
) const
2061 return FindData(name
, type
, 0, data
, numBytes
);
2066 BMessage::ReplaceString(const char *name
, const char *string
)
2071 return ReplaceData(name
, B_STRING_TYPE
, 0, string
, strlen(string
) + 1);
2076 BMessage::ReplaceString(const char *name
, int32 index
, const char *string
)
2081 return ReplaceData(name
, B_STRING_TYPE
, index
, string
, strlen(string
) + 1);
2086 BMessage::ReplaceString(const char *name
, const BString
&string
)
2088 return ReplaceData(name
, B_STRING_TYPE
, 0, string
.String(),
2089 string
.Length() + 1);
2094 BMessage::ReplaceString(const char *name
, int32 index
, const BString
&string
)
2096 return ReplaceData(name
, B_STRING_TYPE
, index
, string
.String(),
2097 string
.Length() + 1);
2102 BMessage::ReplacePointer(const char *name
, const void *pointer
)
2104 return ReplaceData(name
, B_POINTER_TYPE
, 0, &pointer
, sizeof(pointer
));
2109 BMessage::ReplacePointer(const char *name
, int32 index
, const void *pointer
)
2111 return ReplaceData(name
, B_POINTER_TYPE
, index
, &pointer
, sizeof(pointer
));
2116 BMessage::ReplaceMessenger(const char *name
, BMessenger messenger
)
2118 return ReplaceData(name
, B_MESSENGER_TYPE
, 0, &messenger
,
2119 sizeof(BMessenger
));
2124 BMessage::ReplaceMessenger(const char *name
, int32 index
, BMessenger messenger
)
2126 return ReplaceData(name
, B_MESSENGER_TYPE
, index
, &messenger
,
2127 sizeof(BMessenger
));
2132 BMessage::ReplaceRef(const char *name
, const entry_ref
*ref
)
2134 return ReplaceRef(name
, 0, ref
);
2139 BMessage::ReplaceRef(const char *name
, int32 index
, const entry_ref
*ref
)
2141 size_t size
= sizeof(entry_ref
) + B_PATH_NAME_LENGTH
;
2144 status_t error
= BPrivate::entry_ref_flatten(buffer
, &size
, ref
);
2147 error
= ReplaceData(name
, B_REF_TYPE
, index
, &buffer
, size
);
2154 BMessage::ReplaceMessage(const char *name
, const BMessage
*message
)
2156 return ReplaceMessage(name
, 0, message
);
2161 BMessage::ReplaceMessage(const char *name
, int32 index
, const BMessage
*message
)
2163 if (message
== NULL
)
2166 ssize_t size
= message
->FlattenedSize();
2169 status_t error
= message
->Flatten(buffer
, size
);
2172 error
= ReplaceData(name
, B_MESSAGE_TYPE
, index
, &buffer
, size
);
2179 BMessage::ReplaceFlat(const char *name
, BFlattenable
*object
)
2181 return ReplaceFlat(name
, 0, object
);
2186 BMessage::ReplaceFlat(const char *name
, int32 index
, BFlattenable
*object
)
2191 ssize_t size
= object
->FlattenedSize();
2194 status_t error
= object
->Flatten(buffer
, size
);
2197 error
= ReplaceData(name
, object
->TypeCode(), index
, &buffer
, size
);
2204 BMessage::ReplaceData(const char *name
, type_code type
, const void *data
,
2207 return ReplaceData(name
, type
, 0, data
, numBytes
);
2212 BMessage::HasFlat(const char *name
, const BFlattenable
*object
) const
2214 return HasFlat(name
, 0, object
);
2219 BMessage::HasFlat(const char *name
, int32 index
, const BFlattenable
*object
)
2222 return HasData(name
, object
->TypeCode(), index
);