2 * Copyright 2005-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
7 #include <util/KMessage.h>
12 #include <ByteOrder.h>
14 #include <KernelExport.h>
15 #include <TypeConstants.h>
18 #if defined(_BOOT_MODE) || defined(_LOADER_MODE)
19 # include <util/kernel_cpp.h>
25 // TODO: Add a field index using a hash map, so that lookup improves to O(1)
29 // define the PANIC macro
32 # define PANIC(str) panic(str)
34 # define PANIC(str) debugger(str)
39 #if !defined(HAIKU_TARGET_PLATFORM_HAIKU) || defined(_BOOT_MODE) \
40 || defined(_LOADER_MODE)
41 # define MEMALIGN(alignment, size) malloc(size)
42 // Built as part of a build tool or the boot or runtime loader.
45 # define MEMALIGN(alignment, size) memalign(alignment, size)
46 // Built as part of the kernel or userland. Using memalign allows use of
47 // special heap implementations that might otherwise return unaligned
48 // buffers for debugging purposes.
52 static const int32 kMessageReallocChunkSize
= 64;
53 static const size_t kMessageBufferAlignment
= 4;
55 const uint32
KMessage::kMessageHeaderMagic
= 'kMsG';
58 // #pragma mark - Helper Functions
63 return (offset
+ kMessageBufferAlignment
- 1)
64 & ~(kMessageBufferAlignment
- 1);
69 _Align(void* address
, int32 offset
= 0)
71 return (void*)(((addr_t
)address
+ offset
+ kMessageBufferAlignment
- 1)
72 & ~(kMessageBufferAlignment
- 1));
76 // #pragma mark - FieldValueHeader
79 struct KMessage::FieldValueHeader
{
84 return _Align(this, sizeof(FieldValueHeader
));
87 FieldValueHeader
* NextFieldValueHeader()
89 return (FieldValueHeader
*)_Align(Data(), size
);
94 // #pragma mark - FieldHeader
97 struct KMessage::FieldHeader
{
99 int32 elementSize
; // if < 0: non-fixed size
107 return (uint8
*)this + headerSize
;
110 bool HasFixedElementSize()
112 return elementSize
>= 0;
115 void* ElementAt(int32 index
, int32
* size
)
117 if (index
< 0 || index
>= elementCount
)
119 uint8
* data
= (uint8
*)this + headerSize
;
120 if (HasFixedElementSize()) {
122 return data
+ elementSize
* index
;
124 // non-fixed element size: we need to iterate
125 FieldValueHeader
* valueHeader
= (FieldValueHeader
*)data
;
126 for (int i
= 0; i
< index
; i
++)
127 valueHeader
= valueHeader
->NextFieldValueHeader();
128 *size
= valueHeader
->size
;
129 return valueHeader
->Data();
132 FieldHeader
* NextFieldHeader()
134 return (FieldHeader
*)_Align(this, fieldSize
);
139 // #pragma mark - KMessage
153 KMessage::KMessage(uint32 what
)
165 KMessage::~KMessage()
172 KMessage::SetTo(uint32 what
, uint32 flags
)
174 // There are no flags interesting in this case at the moment.
182 KMessage::SetTo(void* buffer
, int32 bufferSize
, uint32 what
, uint32 flags
)
189 if (bufferSize
< 0) {
190 if (!(flags
& KMESSAGE_INIT_FROM_BUFFER
))
192 } else if (bufferSize
< (int)sizeof(Header
))
195 // if read-only, we need to init from the buffer, too
196 if ((flags
& KMESSAGE_READ_ONLY
) != 0
197 && (flags
& KMESSAGE_INIT_FROM_BUFFER
) == 0) {
201 // if not initializing from the given buffer, cloning it doesn't make sense
202 if ((flags
& KMESSAGE_INIT_FROM_BUFFER
) == 0
203 && (flags
& KMESSAGE_CLONE_BUFFER
) != 0) {
208 fBufferCapacity
= bufferSize
;
211 status_t error
= B_OK
;
212 if (flags
& KMESSAGE_INIT_FROM_BUFFER
)
213 error
= _InitFromBuffer(bufferSize
< 0);
225 KMessage::SetTo(const void* buffer
, int32 bufferSize
, uint32 flags
)
227 return SetTo(const_cast<void*>(buffer
), bufferSize
, 0,
228 KMESSAGE_INIT_FROM_BUFFER
| KMESSAGE_READ_ONLY
| flags
);
236 if (fBuffer
&& fBuffer
!= &fHeader
&& (fFlags
& KMESSAGE_OWNS_BUFFER
))
239 fBufferCapacity
= sizeof(Header
);
245 KMessage::SetWhat(uint32 what
)
247 _Header()->what
= what
;
252 KMessage::What() const
254 return _Header()->what
;
259 KMessage::Buffer() const
266 KMessage::BufferCapacity() const
268 return fBufferCapacity
;
273 KMessage::ContentSize() const
275 return _Header()->size
;
280 KMessage::AddField(const char* name
, type_code type
, int32 elementSize
,
281 KMessageField
* field
)
283 if (!name
|| type
== B_ANY_TYPE
)
285 KMessageField existingField
;
286 if (FindField(name
, &existingField
) == B_OK
)
287 return B_NAME_IN_USE
;
288 return _AddField(name
, type
, elementSize
, field
);
293 KMessage::FindField(const char* name
, KMessageField
* field
) const
295 return FindField(name
, B_ANY_TYPE
, field
);
300 KMessage::FindField(const char* name
, type_code type
,
301 KMessageField
* field
) const
305 KMessageField stackField
;
310 while (GetNextField(field
) == B_OK
) {
311 if ((type
== B_ANY_TYPE
|| field
->TypeCode() == type
)
312 && strcmp(name
, field
->Name()) == 0) {
316 return B_NAME_NOT_FOUND
;
321 KMessage::GetNextField(KMessageField
* field
) const
323 if (!field
|| (field
->Message() != NULL
&& field
->Message() != this))
325 FieldHeader
* fieldHeader
= field
->_Header();
326 FieldHeader
* lastField
= _LastFieldHeader();
328 return B_NAME_NOT_FOUND
;
329 if (fieldHeader
== NULL
) {
330 fieldHeader
= _FirstFieldHeader();
332 if ((uint8
*)fieldHeader
< (uint8
*)_FirstFieldHeader()
333 || (uint8
*)fieldHeader
> (uint8
*)lastField
) {
336 if (fieldHeader
== lastField
)
337 return B_NAME_NOT_FOUND
;
338 fieldHeader
= fieldHeader
->NextFieldHeader();
340 field
->SetTo(const_cast<KMessage
*>(this), _BufferOffsetFor(fieldHeader
));
346 KMessage::IsEmpty() const
348 return _LastFieldHeader() == NULL
;
353 KMessage::AddData(const char* name
, type_code type
, const void* data
,
354 int32 numBytes
, bool isFixedSize
)
356 if (!name
|| type
== B_ANY_TYPE
|| !data
|| numBytes
< 0)
359 if (FindField(name
, &field
) == B_OK
) {
360 // field with that name already exists: check its type
361 if (field
.TypeCode() != type
)
364 // no such field yet: add it
365 status_t error
= _AddField(name
, type
, (isFixedSize
? numBytes
: -1),
370 return _AddFieldData(&field
, data
, numBytes
, 1);
375 KMessage::AddArray(const char* name
, type_code type
, const void* data
,
376 int32 elementSize
, int32 elementCount
)
378 if (!name
|| type
== B_ANY_TYPE
|| !data
|| elementSize
< 0
379 || elementCount
< 0) {
383 if (FindField(name
, &field
) == B_OK
) {
384 // field with that name already exists: check its type
385 if (field
.TypeCode() != type
)
388 // no such field yet: add it
389 status_t error
= _AddField(name
, type
, elementSize
, &field
);
393 return _AddFieldData(&field
, data
, elementSize
, elementCount
);
398 KMessage::SetData(const char* name
, type_code type
, const void* data
,
401 if (fBuffer
!= &fHeader
&& (fFlags
& KMESSAGE_READ_ONLY
))
402 return B_NOT_ALLOWED
;
406 if (FindField(name
, &field
) == B_OK
) {
407 // field already known
408 if (field
.TypeCode() != type
|| !field
.HasFixedElementSize()
409 || field
.ElementSize() != numBytes
) {
413 // if it has an element, just replace its value
414 if (field
.CountElements() > 0) {
415 const void* element
= field
.ElementAt(0);
416 memcpy(const_cast<void*>(element
), data
, numBytes
);
420 // no such field yet -- add it
421 status_t error
= _AddField(name
, type
, numBytes
, &field
);
426 // we've got an empty field -- add the element
427 return _AddFieldData(&field
, data
, numBytes
, 1);
432 KMessage::FindData(const char* name
, type_code type
, const void** data
,
433 int32
* numBytes
) const
435 return FindData(name
, type
, 0, data
, numBytes
);
440 KMessage::FindData(const char* name
, type_code type
, int32 index
,
441 const void** data
, int32
* numBytes
) const
443 if (!name
|| !data
|| !numBytes
)
446 status_t error
= FindField(name
, type
, &field
);
449 const void* foundData
= field
.ElementAt(index
, numBytes
);
459 KMessage::Sender() const
461 return _Header()->sender
;
466 KMessage::TargetToken() const
468 return _Header()->targetToken
;
473 KMessage::ReplyPort() const
475 return _Header()->replyPort
;
480 KMessage::ReplyToken() const
482 return _Header()->replyToken
;
487 KMessage::SetDeliveryInfo(int32 targetToken
, port_id replyPort
,
488 int32 replyToken
, team_id senderTeam
)
490 Header
* header
= _Header();
491 header
->sender
= senderTeam
;
492 header
->targetToken
= targetToken
;
493 header
->replyPort
= replyPort
;
494 header
->replyToken
= replyToken
;
495 header
->sender
= senderTeam
;
499 #ifndef KMESSAGE_CONTAINER_ONLY
503 KMessage::SendTo(port_id targetPort
, int32 targetToken
, port_id replyPort
,
504 int32 replyToken
, bigtime_t timeout
, team_id senderTeam
)
506 // get the sender team
507 if (senderTeam
< 0) {
509 status_t error
= get_thread_info(find_thread(NULL
), &info
);
513 senderTeam
= info
.team
;
516 SetDeliveryInfo(targetToken
, replyPort
, replyToken
, senderTeam
);
520 return write_port(targetPort
, 'KMSG', fBuffer
, ContentSize());
522 return write_port_etc(targetPort
, 'KMSG', fBuffer
, ContentSize(),
523 B_RELATIVE_TIMEOUT
, timeout
);
528 KMessage::SendTo(port_id targetPort
, int32 targetToken
, KMessage
* reply
,
529 bigtime_t deliveryTimeout
, bigtime_t replyTimeout
, team_id senderTeam
)
531 // get the team the target port belongs to
533 status_t error
= get_port_info(targetPort
, &portInfo
);
536 team_id targetTeam
= portInfo
.team
;
537 // allocate a reply port, if a reply is desired
538 port_id replyPort
= -1;
541 team_id ourTeam
= B_SYSTEM_TEAM
;
543 if (targetTeam
!= B_SYSTEM_TEAM
) {
544 thread_info threadInfo
;
545 error
= get_thread_info(find_thread(NULL
), &threadInfo
);
548 ourTeam
= threadInfo
.team
;
552 replyPort
= create_port(1, "KMessage reply port");
555 // If the target team is not our team and not the kernel team either,
556 // we transfer the ownership of the port to it, so we will not block
557 if (targetTeam
!= ourTeam
&& targetTeam
!= B_SYSTEM_TEAM
)
558 set_port_owner(replyPort
, targetTeam
);
561 PortDeleter(port_id port
) : port(port
) {}
569 } replyPortDeleter(replyPort
);
571 error
= SendTo(targetPort
, targetToken
, replyPort
, 0,
572 deliveryTimeout
, senderTeam
);
577 return reply
->ReceiveFrom(replyPort
, replyTimeout
);
583 KMessage::SendReply(KMessage
* message
, port_id replyPort
, int32 replyToken
,
584 bigtime_t timeout
, team_id senderTeam
)
588 return message
->SendTo(ReplyPort(), ReplyToken(), replyPort
, replyToken
,
589 timeout
, senderTeam
);
594 KMessage::SendReply(KMessage
* message
, KMessage
* reply
,
595 bigtime_t deliveryTimeout
, bigtime_t replyTimeout
, team_id senderTeam
)
599 return message
->SendTo(ReplyPort(), ReplyToken(), reply
, deliveryTimeout
,
600 replyTimeout
, senderTeam
);
605 KMessage::ReceiveFrom(port_id fromPort
, bigtime_t timeout
,
606 port_message_info
* messageInfo
)
608 port_message_info _messageInfo
;
609 if (messageInfo
== NULL
)
610 messageInfo
= &_messageInfo
;
612 // get the port buffer size
615 error
= get_port_message_info_etc(fromPort
, messageInfo
, 0, 0);
617 error
= get_port_message_info_etc(fromPort
, messageInfo
,
618 B_RELATIVE_TIMEOUT
, timeout
);
624 uint8
* buffer
= (uint8
*)MEMALIGN(kMessageBufferAlignment
,
631 ssize_t realSize
= read_port_etc(fromPort
, &what
, buffer
, messageInfo
->size
,
632 B_RELATIVE_TIMEOUT
, 0);
637 if (messageInfo
->size
!= (size_t)realSize
) {
643 return SetTo(buffer
, messageInfo
->size
, 0,
644 KMESSAGE_OWNS_BUFFER
| KMESSAGE_INIT_FROM_BUFFER
);
648 #endif // !KMESSAGE_CONTAINER_ONLY
652 KMessage::Dump(void (*printFunc
)(const char*, ...)) const
654 Header
* header
= _Header();
655 printFunc("KMessage: buffer: %p (size/capacity: %ld/%ld), flags: %#"
656 B_PRIx32
"\n", fBuffer
, header
->size
, fBufferCapacity
, fFlags
);
659 while (GetNextField(&field
) == B_OK
) {
660 type_code type
= field
.TypeCode();
661 uint32 bigEndianType
= B_HOST_TO_BENDIAN_INT32(type
);
662 int nameSpacing
= 17 - strlen(field
.Name());
666 printFunc(" field: \"%s\"%*s (%.4s): ", field
.Name(), nameSpacing
, "",
667 (char*)&bigEndianType
);
669 if (field
.CountElements() != 1)
673 for (int i
= 0; const void* data
= field
.ElementAt(i
, &size
); i
++) {
674 if (field
.CountElements() != 1)
675 printFunc(" [%2d] ", i
);
677 bool isIntType
= false;
681 printFunc("%s\n", (*(bool*)data
? "true" : "false"));
685 intData
= *(int8
*)data
;
689 intData
= *(int16
*)data
;
693 intData
= *(int32
*)data
;
697 intData
= *(int64
*)data
;
700 printFunc("\"%s\"\n", (char*)data
);
703 printFunc("data at %p, %ld bytes\n", (char*)data
, size
);
707 printFunc("%lld (0x%llx)\n", intData
, intData
);
714 KMessage::_Header() const
716 return (Header
*)fBuffer
;
721 KMessage::_BufferOffsetFor(const void* data
) const
725 return (uint8
*)data
- (uint8
*)fBuffer
;
729 KMessage::FieldHeader
*
730 KMessage::_FirstFieldHeader() const
732 return (FieldHeader
*)_Align(fBuffer
, sizeof(Header
));
736 KMessage::FieldHeader
*
737 KMessage::_LastFieldHeader() const
739 return _FieldHeaderForOffset(fLastFieldOffset
);
743 KMessage::FieldHeader
*
744 KMessage::_FieldHeaderForOffset(int32 offset
) const
746 if (offset
<= 0 || offset
>= _Header()->size
)
748 return (FieldHeader
*)((uint8
*)fBuffer
+ offset
);
753 KMessage::_AddField(const char* name
, type_code type
, int32 elementSize
,
754 KMessageField
* field
)
756 FieldHeader
* fieldHeader
;
758 status_t error
= _AllocateSpace(sizeof(FieldHeader
) + strlen(name
), true,
759 true, (void**)&fieldHeader
, &alignedSize
);
762 fieldHeader
->type
= type
;
763 fieldHeader
->elementSize
= elementSize
;
764 fieldHeader
->elementCount
= 0;
765 fieldHeader
->fieldSize
= alignedSize
;
766 fieldHeader
->headerSize
= alignedSize
;
767 strcpy(fieldHeader
->name
, name
);
768 fLastFieldOffset
= _BufferOffsetFor(fieldHeader
);
770 field
->SetTo(this, _BufferOffsetFor(fieldHeader
));
776 KMessage::_AddFieldData(KMessageField
* field
, const void* data
,
777 int32 elementSize
, int32 elementCount
)
781 FieldHeader
* fieldHeader
= field
->_Header();
782 FieldHeader
* lastField
= _LastFieldHeader();
783 if (!fieldHeader
|| fieldHeader
!= lastField
|| !data
784 || elementSize
< 0 || elementCount
< 0) {
787 if (elementCount
== 0)
790 if (fieldHeader
->HasFixedElementSize()) {
791 if (elementSize
!= fieldHeader
->elementSize
)
795 status_t error
= _AllocateSpace(elementSize
* elementCount
,
796 (fieldHeader
->elementCount
== 0), false, &address
, &alignedSize
);
799 fieldHeader
= field
->_Header(); // might have been relocated
800 memcpy(address
, data
, elementSize
* elementCount
);
801 fieldHeader
->elementCount
+= elementCount
;
802 fieldHeader
->fieldSize
= (uint8
*)address
+ alignedSize
803 - (uint8
*)fieldHeader
;
806 // non-fixed size values
807 // add the elements individually (TODO: Optimize!)
808 int32 valueHeaderSize
= _Align(sizeof(FieldValueHeader
));
809 int32 entrySize
= valueHeaderSize
+ elementSize
;
810 for (int32 i
= 0; i
< elementCount
; i
++) {
813 status_t error
= _AllocateSpace(entrySize
, true, false, &address
,
817 fieldHeader
= field
->_Header(); // might have been relocated
818 FieldValueHeader
* valueHeader
= (FieldValueHeader
*)address
;
819 valueHeader
->size
= elementSize
;
820 memcpy(valueHeader
->Data(), (const uint8
*)data
+ i
* elementSize
,
822 fieldHeader
->elementCount
++;
823 fieldHeader
->fieldSize
= (uint8
*)address
+ alignedSize
824 - (uint8
*)fieldHeader
;
831 KMessage::_InitFromBuffer(bool sizeFromBuffer
)
836 // clone the buffer, if requested
837 if ((fFlags
& KMESSAGE_CLONE_BUFFER
) != 0 || _Align(fBuffer
) != fBuffer
) {
838 if (sizeFromBuffer
) {
839 int32 size
= fBufferCapacity
;
840 memcpy(&size
, &_Header()->size
, 4);
841 fBufferCapacity
= size
;
844 void* buffer
= MEMALIGN(kMessageBufferAlignment
, fBufferCapacity
);
848 memcpy(buffer
, fBuffer
, fBufferCapacity
);
850 if ((fFlags
& KMESSAGE_OWNS_BUFFER
) != 0)
854 fFlags
&= ~(uint32
)(KMESSAGE_READ_ONLY
| KMESSAGE_CLONE_BUFFER
);
855 fFlags
|= KMESSAGE_OWNS_BUFFER
;
858 if (_Align(fBuffer
) != fBuffer
)
861 Header
* header
= _Header();
864 fBufferCapacity
= header
->size
;
866 if (fBufferCapacity
< (int)sizeof(Header
))
870 if (header
->magic
!= kMessageHeaderMagic
)
872 if (header
->size
< (int)sizeof(Header
) || header
->size
> fBufferCapacity
)
876 FieldHeader
* fieldHeader
= NULL
;
877 uint8
* data
= (uint8
*)_FirstFieldHeader();
878 int32 remainingBytes
= (uint8
*)fBuffer
+ header
->size
- data
;
879 while (remainingBytes
> 0) {
880 if (remainingBytes
< (int)sizeof(FieldHeader
))
882 fieldHeader
= (FieldHeader
*)data
;
883 // check field header
884 if (fieldHeader
->type
== B_ANY_TYPE
)
886 if (fieldHeader
->elementCount
< 0)
888 if (fieldHeader
->fieldSize
< (int)sizeof(FieldHeader
)
889 || fieldHeader
->fieldSize
> remainingBytes
) {
892 if (fieldHeader
->headerSize
< (int)sizeof(FieldHeader
)
893 || fieldHeader
->headerSize
> fieldHeader
->fieldSize
) {
896 int32 maxNameLen
= data
+ fieldHeader
->headerSize
897 - (uint8
*)fieldHeader
->name
;
898 int32 nameLen
= strnlen(fieldHeader
->name
, maxNameLen
);
899 if (nameLen
== maxNameLen
|| nameLen
== 0)
901 int32 fieldSize
= fieldHeader
->headerSize
;
902 if (fieldHeader
->HasFixedElementSize()) {
903 // fixed element size
904 int32 dataSize
= fieldHeader
->elementSize
905 * fieldHeader
->elementCount
;
906 fieldSize
= (uint8
*)fieldHeader
->Data() + dataSize
- data
;
908 // non-fixed element size
909 FieldValueHeader
* valueHeader
910 = (FieldValueHeader
*)fieldHeader
->Data();
911 for (int32 i
= 0; i
< fieldHeader
->elementCount
; i
++) {
912 remainingBytes
= (uint8
*)fBuffer
+ header
->size
913 - (uint8
*)valueHeader
;
914 if (remainingBytes
< (int)sizeof(FieldValueHeader
))
916 uint8
* value
= (uint8
*)valueHeader
->Data();
917 remainingBytes
= (uint8
*)fBuffer
+ header
->size
- (uint8
*)value
;
918 if (remainingBytes
< valueHeader
->size
)
920 fieldSize
= value
+ valueHeader
->size
- data
;
921 valueHeader
= valueHeader
->NextFieldValueHeader();
923 if (fieldSize
> fieldHeader
->fieldSize
)
926 data
= (uint8
*)fieldHeader
->NextFieldHeader();
927 remainingBytes
= (uint8
*)fBuffer
+ header
->size
- data
;
929 fLastFieldOffset
= _BufferOffsetFor(fieldHeader
);
935 KMessage::_InitBuffer(uint32 what
)
937 Header
* header
= _Header();
938 header
->magic
= kMessageHeaderMagic
;
939 header
->size
= sizeof(Header
);
942 header
->targetToken
= -1;
943 header
->replyPort
= -1;
944 header
->replyToken
= -1;
945 fLastFieldOffset
= 0;
950 KMessage::_CheckBuffer()
952 int32 lastFieldOffset
= fLastFieldOffset
;
953 if (_InitFromBuffer(false) != B_OK
) {
954 PANIC("internal data mangled");
956 if (fLastFieldOffset
!= lastFieldOffset
) {
957 PANIC("fLastFieldOffset changed during KMessage::_CheckBuffer()");
963 KMessage::_AllocateSpace(int32 size
, bool alignAddress
, bool alignSize
,
964 void** address
, int32
* alignedSize
)
966 if (fBuffer
!= &fHeader
&& (fFlags
& KMESSAGE_READ_ONLY
))
967 return B_NOT_ALLOWED
;
969 int32 offset
= ContentSize();
971 offset
= _Align(offset
);
972 int32 newSize
= offset
+ size
;
974 newSize
= _Align(newSize
);
975 // reallocate if necessary
976 if (fBuffer
== &fHeader
) {
977 int32 newCapacity
= _CapacityFor(newSize
);
978 void* newBuffer
= MEMALIGN(kMessageBufferAlignment
, newCapacity
);
982 fBufferCapacity
= newCapacity
;
983 fFlags
|= KMESSAGE_OWNS_BUFFER
;
984 memcpy(fBuffer
, &fHeader
, sizeof(fHeader
));
986 if (newSize
> fBufferCapacity
) {
987 // if we don't own the buffer, we can't resize it
988 if (!(fFlags
& KMESSAGE_OWNS_BUFFER
)) {
989 #if defined(_KERNEL_MODE) && 0
990 // optional debugging to find insufficiently sized KMessage
991 // buffers (e.g. for in-kernel notifications)
992 panic("KMessage: out of space: available: %" B_PRId32
993 ", needed: %" B_PRId32
"\n", fBufferCapacity
, newSize
);
995 return B_BUFFER_OVERFLOW
;
998 int32 newCapacity
= _CapacityFor(newSize
);
999 void* newBuffer
= realloc(fBuffer
, newCapacity
);
1002 fBuffer
= newBuffer
;
1003 fBufferCapacity
= newCapacity
;
1006 _Header()->size
= newSize
;
1007 *address
= (char*)fBuffer
+ offset
;
1008 *alignedSize
= newSize
- offset
;
1014 KMessage::_CapacityFor(int32 size
)
1016 return (size
+ kMessageReallocChunkSize
- 1) / kMessageReallocChunkSize
1017 * kMessageReallocChunkSize
;
1021 // #pragma mark - KMessageField
1024 KMessageField::KMessageField()
1033 KMessageField::Unset()
1041 KMessageField::Message() const
1048 KMessageField::Name() const
1050 KMessage::FieldHeader
* header
= _Header();
1051 return header
? header
->name
: NULL
;
1056 KMessageField::TypeCode() const
1058 KMessage::FieldHeader
* header
= _Header();
1059 return header
? header
->type
: 0;
1064 KMessageField::HasFixedElementSize() const
1066 KMessage::FieldHeader
* header
= _Header();
1067 return header
? header
->HasFixedElementSize() : false;
1072 KMessageField::ElementSize() const
1074 KMessage::FieldHeader
* header
= _Header();
1075 return header
? header
->elementSize
: -1;
1080 KMessageField::AddElement(const void* data
, int32 size
)
1082 KMessage::FieldHeader
* header
= _Header();
1083 if (!header
|| !data
)
1086 size
= ElementSize();
1090 return fMessage
->_AddFieldData(this, data
, size
, 1);
1095 KMessageField::AddElements(const void* data
, int32 count
, int32 elementSize
)
1097 KMessage::FieldHeader
* header
= _Header();
1098 if (!header
|| !data
|| count
< 0)
1100 if (elementSize
< 0) {
1101 elementSize
= ElementSize();
1102 if (elementSize
< 0)
1105 return fMessage
->_AddFieldData(this, data
, elementSize
, count
);
1110 KMessageField::ElementAt(int32 index
, int32
* size
) const
1112 KMessage::FieldHeader
* header
= _Header();
1113 return header
? header
->ElementAt(index
, size
) : NULL
;
1118 KMessageField::CountElements() const
1120 KMessage::FieldHeader
* header
= _Header();
1121 return header
? header
->elementCount
: 0;
1126 KMessageField::SetTo(KMessage
* message
, int32 headerOffset
)
1129 fHeaderOffset
= headerOffset
;
1133 KMessage::FieldHeader
*
1134 KMessageField::_Header() const
1136 return fMessage
? fMessage
->_FieldHeaderForOffset(fHeaderOffset
) : NULL
;