/* * Copyright 2005-2009, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ #ifndef _KERNEL_UTIL_KMESSAGE_H #define _KERNEL_UTIL_KMESSAGE_H #include #include #include #ifdef __cplusplus class BMessage; namespace BPrivate { class KMessageField; class MessageAdapter; class KMessage { public: enum { KMESSAGE_OWNS_BUFFER = 0x01, KMESSAGE_INIT_FROM_BUFFER = 0x02, KMESSAGE_CLONE_BUFFER = 0x04, KMESSAGE_READ_ONLY = 0x08, KMESSAGE_FLAG_MASK = 0x07, }; public: KMessage(); KMessage(uint32 what); ~KMessage(); status_t SetTo(uint32 what, uint32 flags = 0); status_t SetTo(void* buffer, int32 bufferSize, uint32 what, uint32 flags = 0); status_t SetTo(const void* buffer, int32 bufferSize = -1, uint32 flags = 0); // KMESSAGE_INIT_FROM_BUFFER and // KMESSAGE_READ_ONLY are implied void Unset(); void SetWhat(uint32 what); uint32 What() const; const void* Buffer() const; int32 BufferCapacity() const; int32 ContentSize() const; status_t AddField(const char* name, type_code type, int32 elementSize = -1, KMessageField* field = NULL); status_t FindField(const char* name, KMessageField* field) const; status_t FindField(const char* name, type_code type, KMessageField* field) const; status_t GetNextField(KMessageField* field) const; bool IsEmpty() const; status_t AddData(const char* name, type_code type, const void* data, int32 numBytes, bool isFixedSize = true); status_t AddArray(const char* name, type_code type, const void* data, int32 elementSize, int32 elementCount); inline status_t AddBool(const char* name, bool value); inline status_t AddInt8(const char* name, int8 value); inline status_t AddInt16(const char* name, int16 value); inline status_t AddInt32(const char* name, int32 value); inline status_t AddInt64(const char* name, int64 value); inline status_t AddPointer(const char* name, const void* value); inline status_t AddString(const char* name, const char* value); status_t FindData(const char* name, type_code type, const void** data, int32* numBytes) const; status_t FindData(const char* name, type_code type, int32 index, const void** data, int32* numBytes) const; inline status_t FindBool(const char* name, bool* value) const; inline status_t FindBool(const char* name, int32 index, bool* value) const; inline status_t FindInt8(const char* name, int8* value) const; inline status_t FindInt8(const char* name, int32 index, int8* value) const; inline status_t FindInt16(const char* name, int16* value) const; inline status_t FindInt16(const char* name, int32 index, int16* value) const; inline status_t FindInt32(const char* name, int32* value) const; inline status_t FindInt32(const char* name, int32 index, int32* value) const; inline status_t FindInt64(const char* name, int64* value) const; inline status_t FindInt64(const char* name, int32 index, int64* value) const; inline status_t FindPointer(const char* name, void** value) const; inline status_t FindPointer(const char* name, int32 index, void** value) const; inline status_t FindString(const char* name, const char** value) const; inline status_t FindString(const char* name, int32 index, const char** value) const; inline bool GetBool(const char* name, bool defaultValue) const; inline bool GetBool(const char* name, int32 index, bool defaultValue) const; inline int8 GetInt8(const char* name, int8 defaultValue) const; inline int8 GetInt8(const char* name, int32 index, int8 defaultValue) const; inline int16 GetInt16(const char* name, int16 defaultValue) const; inline int16 GetInt16(const char* name, int32 index, int16 defaultValue) const; inline int32 GetInt32(const char* name, int32 defaultValue) const; inline int32 GetInt32(const char* name, int32 index, int32 defaultValue) const; inline int64 GetInt64(const char* name, int64 defaultValue) const; inline int64 GetInt64(const char* name, int32 index, int64 defaultValue) const; inline void* GetPointer(const char* name, const void* defaultValue) const; inline void* GetPointer(const char* name, int32 index, const void* defaultValue) const; inline const char* GetString(const char* name, const char* defaultValue) const; inline const char* GetString(const char* name, int32 index, const char* defaultValue) const; // fixed size fields only status_t SetData(const char* name, type_code type, const void* data, int32 numBytes); inline status_t SetBool(const char* name, bool value); inline status_t SetInt8(const char* name, int8 value); inline status_t SetInt16(const char* name, int16 value); inline status_t SetInt32(const char* name, int32 value); inline status_t SetInt64(const char* name, int64 value); inline status_t SetPointer(const char* name, const void* value); // message delivery team_id Sender() const; int32 TargetToken() const; port_id ReplyPort() const; int32 ReplyToken() const; void SetDeliveryInfo(int32 targetToken, port_id replyPort, int32 replyToken, team_id senderTeam); status_t SendTo(port_id targetPort, int32 targetToken = -1, port_id replyPort = -1, int32 replyToken = -1, bigtime_t timeout = -1, team_id senderTeam = -1); status_t SendTo(port_id targetPort, int32 targetToken, KMessage* reply, bigtime_t deliveryTimeout = -1, bigtime_t replyTimeout = -1, team_id senderTeam = -1); status_t SendReply(KMessage* message, port_id replyPort = -1, int32 replyToken = -1, bigtime_t timeout = -1, team_id senderTeam = -1); status_t SendReply(KMessage* message, KMessage* reply, bigtime_t deliveryTimeout = -1, bigtime_t replyTimeout = -1, team_id senderTeam = -1); status_t ReceiveFrom(port_id fromPort, bigtime_t timeout = -1, port_message_info* messageInfo = NULL); void Dump(void (*printFunc)(const char*, ...)) const; private: friend class KMessageField; friend class MessageAdapter; friend class ::BMessage; // not so nice, but makes things easier struct Header { uint32 magic; int32 size; uint32 what; team_id sender; int32 targetToken; port_id replyPort; int32 replyToken; }; struct FieldHeader; struct FieldValueHeader; private: Header* _Header() const; int32 _BufferOffsetFor(const void* data) const; FieldHeader* _FirstFieldHeader() const; FieldHeader* _LastFieldHeader() const; FieldHeader* _FieldHeaderForOffset(int32 offset) const; status_t _AddField(const char* name, type_code type, int32 elementSize, KMessageField* field); status_t _AddFieldData(KMessageField* field, const void* data, int32 elementSize, int32 elementCount); status_t _InitFromBuffer(bool sizeFromBuffer); void _InitBuffer(uint32 what); void _CheckBuffer(); // debugging only status_t _AllocateSpace(int32 size, bool alignAddress, bool alignSize, void** address, int32* alignedSize); int32 _CapacityFor(int32 size); template inline status_t _FindType(const char* name, type_code type, int32 index, T* value) const; template inline T _GetType(const char* name, type_code type, int32 index, const T& defaultValue) const; private: Header fHeader; // pointed to by fBuffer, if nothing // is allocated void* fBuffer; int32 fBufferCapacity; uint32 fFlags; int32 fLastFieldOffset; static const uint32 kMessageHeaderMagic; }; class KMessageField { public: KMessageField(); void Unset(); KMessage* Message() const; const char* Name() const; type_code TypeCode() const; bool HasFixedElementSize() const; int32 ElementSize() const; // only if HasFixedElementSize() status_t AddElement(const void* data, int32 size = -1); status_t AddElements(const void* data, int32 count, int32 elementSize = -1); const void* ElementAt(int32 index, int32* size = NULL) const; int32 CountElements() const; private: friend class KMessage; private: void SetTo(KMessage* message, int32 headerOffset); KMessage::FieldHeader* _Header() const; private: KMessage* fMessage; int32 fHeaderOffset; }; } // namespace BPrivate using BPrivate::KMessage; using BPrivate::KMessageField; // #pragma mark - inline functions status_t KMessage::AddBool(const char* name, bool value) { return AddData(name, B_BOOL_TYPE, &value, sizeof(bool), true); } status_t KMessage::AddInt8(const char* name, int8 value) { return AddData(name, B_INT8_TYPE, &value, sizeof(int8), true); } status_t KMessage::AddInt16(const char* name, int16 value) { return AddData(name, B_INT16_TYPE, &value, sizeof(int16), true); } status_t KMessage::AddInt32(const char* name, int32 value) { return AddData(name, B_INT32_TYPE, &value, sizeof(int32), true); } status_t KMessage::AddInt64(const char* name, int64 value) { return AddData(name, B_INT64_TYPE, &value, sizeof(int64), true); } status_t KMessage::AddPointer(const char* name, const void* value) { return AddData(name, B_POINTER_TYPE, &value, sizeof(value), true); } // AddString status_t KMessage::AddString(const char* name, const char* value) { if (!value) return B_BAD_VALUE; return AddData(name, B_STRING_TYPE, value, strlen(value) + 1, false); } // #pragma mark - template status_t KMessage::_FindType(const char* name, type_code type, int32 index, T* value) const { const void* data; int32 size; status_t error = FindData(name, type, index, &data, &size); if (error != B_OK) return error; if (size != sizeof(T)) return B_BAD_DATA; *value = *(T*)data; return B_OK; } status_t KMessage::FindBool(const char* name, bool* value) const { return FindBool(name, 0, value); } status_t KMessage::FindBool(const char* name, int32 index, bool* value) const { return _FindType(name, B_BOOL_TYPE, index, value); } status_t KMessage::FindInt8(const char* name, int8* value) const { return FindInt8(name, 0, value); } status_t KMessage::FindInt8(const char* name, int32 index, int8* value) const { return _FindType(name, B_INT8_TYPE, index, value); } status_t KMessage::FindInt16(const char* name, int16* value) const { return FindInt16(name, 0, value); } status_t KMessage::FindInt16(const char* name, int32 index, int16* value) const { return _FindType(name, B_INT16_TYPE, index, value); } status_t KMessage::FindInt32(const char* name, int32* value) const { return FindInt32(name, 0, value); } status_t KMessage::FindInt32(const char* name, int32 index, int32* value) const { return _FindType(name, B_INT32_TYPE, index, value); } status_t KMessage::FindInt64(const char* name, int64* value) const { return FindInt64(name, 0, value); } status_t KMessage::FindInt64(const char* name, int32 index, int64* value) const { return _FindType(name, B_INT64_TYPE, index, value); } status_t KMessage::FindPointer(const char* name, void** value) const { return FindPointer(name, 0, value); } status_t KMessage::FindPointer(const char* name, int32 index, void** value) const { return _FindType(name, B_POINTER_TYPE, index, value); } status_t KMessage::FindString(const char* name, const char** value) const { return FindString(name, 0, value); } status_t KMessage::FindString(const char* name, int32 index, const char** value) const { int32 size; return FindData(name, B_STRING_TYPE, index, (const void**)value, &size); } template inline T KMessage::_GetType(const char* name, type_code type, int32 index, const T& defaultValue) const { T value; if (_FindType(name, type, index, &value) == B_OK) return value; return defaultValue; } inline bool KMessage::GetBool(const char* name, bool defaultValue) const { return _GetType(name, B_BOOL_TYPE, 0, defaultValue); } inline bool KMessage::GetBool(const char* name, int32 index, bool defaultValue) const { return _GetType(name, B_BOOL_TYPE, index, defaultValue); } int8 KMessage::GetInt8(const char* name, int8 defaultValue) const { return _GetType(name, B_INT8_TYPE, 0, defaultValue); } int8 KMessage::GetInt8(const char* name, int32 index, int8 defaultValue) const { return _GetType(name, B_INT8_TYPE, index, defaultValue); } int16 KMessage::GetInt16(const char* name, int16 defaultValue) const { return _GetType(name, B_INT16_TYPE, 0, defaultValue); } int16 KMessage::GetInt16(const char* name, int32 index, int16 defaultValue) const { return _GetType(name, B_INT16_TYPE, index, defaultValue); } int32 KMessage::GetInt32(const char* name, int32 defaultValue) const { return _GetType(name, B_INT32_TYPE, 0, defaultValue); } int32 KMessage::GetInt32(const char* name, int32 index, int32 defaultValue) const { return _GetType(name, B_INT32_TYPE, index, defaultValue); } int64 KMessage::GetInt64(const char* name, int64 defaultValue) const { return _GetType(name, B_INT64_TYPE, 0, defaultValue); } int64 KMessage::GetInt64(const char* name, int32 index, int64 defaultValue) const { return _GetType(name, B_INT64_TYPE, index, defaultValue); } void* KMessage::GetPointer(const char* name, const void* defaultValue) const { return const_cast(_GetType(name, B_POINTER_TYPE, 0, defaultValue)); } void* KMessage::GetPointer(const char* name, int32 index, const void* defaultValue) const { return const_cast(_GetType(name, B_POINTER_TYPE, index, defaultValue)); } const char* KMessage::GetString(const char* name, int32 index, const char* defaultValue) const { // don't use _GetType() here, since it checks field size == sizeof(T) int32 size; const char* value; if (FindData(name, B_STRING_TYPE, index, (const void**)&value, &size) == B_OK) { return value; } return defaultValue; } const char* KMessage::GetString(const char* name, const char* defaultValue) const { return GetString(name, 0, defaultValue); } status_t KMessage::SetBool(const char* name, bool value) { return SetData(name, B_BOOL_TYPE, &value, sizeof(bool)); } status_t KMessage::SetInt8(const char* name, int8 value) { return SetData(name, B_INT8_TYPE, &value, sizeof(int8)); } status_t KMessage::SetInt16(const char* name, int16 value) { return SetData(name, B_INT16_TYPE, &value, sizeof(int16)); } status_t KMessage::SetInt32(const char* name, int32 value) { return SetData(name, B_INT32_TYPE, &value, sizeof(int32)); } status_t KMessage::SetInt64(const char* name, int64 value) { return SetData(name, B_INT64_TYPE, &value, sizeof(int64)); } status_t KMessage::SetPointer(const char* name, const void* value) { return SetData(name, B_POINTER_TYPE, &value, sizeof(value)); } #else // !__cplusplus typedef struct KMessage { struct Header { uint32 magic; int32 size; uint32 what; team_id sender; int32 targetToken; port_id replyPort; int32 replyToken; } fHeader; void* fBuffer; int32 fBufferCapacity; uint32 fFlags; int32 fLastFieldOffset; } KMessage; #endif // !__cplusplus #endif // KMESSAGE_H