1/* 2 * Copyright 2005-2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5#ifndef _KERNEL_UTIL_KMESSAGE_H 6#define _KERNEL_UTIL_KMESSAGE_H 7 8 9#include <string.h> 10 11#include <OS.h> 12#include <TypeConstants.h> 13 14 15#ifdef __cplusplus 16 17 18class BMessage; 19 20 21namespace BPrivate { 22 23class KMessageField; 24class MessageAdapter; 25 26 27class KMessage { 28public: 29 enum { 30 KMESSAGE_OWNS_BUFFER = 0x01, 31 KMESSAGE_INIT_FROM_BUFFER = 0x02, 32 KMESSAGE_CLONE_BUFFER = 0x04, 33 KMESSAGE_READ_ONLY = 0x08, 34 35 KMESSAGE_FLAG_MASK = 0x07, 36 }; 37 38public: 39 KMessage(); 40 KMessage(uint32 what); 41 ~KMessage(); 42 43 status_t SetTo(uint32 what, uint32 flags = 0); 44 status_t SetTo(void* buffer, int32 bufferSize, 45 uint32 what, uint32 flags = 0); 46 status_t SetTo(const void* buffer, int32 bufferSize = -1, 47 uint32 flags = 0); 48 // KMESSAGE_INIT_FROM_BUFFER and 49 // KMESSAGE_READ_ONLY are implied 50 void Unset(); 51 52 void SetWhat(uint32 what); 53 uint32 What() const; 54 55 const void* Buffer() const; 56 int32 BufferCapacity() const; 57 int32 ContentSize() const; 58 59 status_t AddField(const char* name, type_code type, 60 int32 elementSize = -1, 61 KMessageField* field = NULL); 62 status_t FindField(const char* name, 63 KMessageField* field) const; 64 status_t FindField(const char* name, type_code type, 65 KMessageField* field) const; 66 status_t GetNextField(KMessageField* field) const; 67 bool IsEmpty() const; 68 69 status_t AddData(const char* name, type_code type, 70 const void* data, int32 numBytes, 71 bool isFixedSize = true); 72 status_t AddArray(const char* name, type_code type, 73 const void* data, int32 elementSize, 74 int32 elementCount); 75 inline status_t AddBool(const char* name, bool value); 76 inline status_t AddInt8(const char* name, int8 value); 77 inline status_t AddInt16(const char* name, int16 value); 78 inline status_t AddInt32(const char* name, int32 value); 79 inline status_t AddInt64(const char* name, int64 value); 80 inline status_t AddPointer(const char* name, const void* value); 81 inline status_t AddString(const char* name, const char* value); 82 83 status_t FindData(const char* name, type_code type, 84 const void** data, int32* numBytes) const; 85 status_t FindData(const char* name, type_code type, 86 int32 index, const void** data, 87 int32* numBytes) const; 88 inline status_t FindBool(const char* name, bool* value) const; 89 inline status_t FindBool(const char* name, int32 index, 90 bool* value) const; 91 inline status_t FindInt8(const char* name, int8* value) const; 92 inline status_t FindInt8(const char* name, int32 index, 93 int8* value) const; 94 inline status_t FindInt16(const char* name, int16* value) const; 95 inline status_t FindInt16(const char* name, int32 index, 96 int16* value) const; 97 inline status_t FindInt32(const char* name, int32* value) const; 98 inline status_t FindInt32(const char* name, int32 index, 99 int32* value) const; 100 inline status_t FindInt64(const char* name, int64* value) const; 101 inline status_t FindInt64(const char* name, int32 index, 102 int64* value) const; 103 inline status_t FindPointer(const char* name, 104 void** value) const; 105 inline status_t FindPointer(const char* name, int32 index, 106 void** value) const; 107 inline status_t FindString(const char* name, 108 const char** value) const; 109 inline status_t FindString(const char* name, int32 index, 110 const char** value) const; 111 112 inline bool GetBool(const char* name, 113 bool defaultValue) const; 114 inline bool GetBool(const char* name, int32 index, 115 bool defaultValue) const; 116 inline int8 GetInt8(const char* name, 117 int8 defaultValue) const; 118 inline int8 GetInt8(const char* name, int32 index, 119 int8 defaultValue) const; 120 inline int16 GetInt16(const char* name, 121 int16 defaultValue) const; 122 inline int16 GetInt16(const char* name, int32 index, 123 int16 defaultValue) const; 124 inline int32 GetInt32(const char* name, 125 int32 defaultValue) const; 126 inline int32 GetInt32(const char* name, int32 index, 127 int32 defaultValue) const; 128 inline int64 GetInt64(const char* name, 129 int64 defaultValue) const; 130 inline int64 GetInt64(const char* name, int32 index, 131 int64 defaultValue) const; 132 inline void* GetPointer(const char* name, 133 const void* defaultValue) const; 134 inline void* GetPointer(const char* name, int32 index, 135 const void* defaultValue) const; 136 inline const char* GetString(const char* name, 137 const char* defaultValue) const; 138 inline const char* GetString(const char* name, int32 index, 139 const char* defaultValue) const; 140 141 // fixed size fields only 142 status_t SetData(const char* name, type_code type, 143 const void* data, int32 numBytes); 144 inline status_t SetBool(const char* name, bool value); 145 inline status_t SetInt8(const char* name, int8 value); 146 inline status_t SetInt16(const char* name, int16 value); 147 inline status_t SetInt32(const char* name, int32 value); 148 inline status_t SetInt64(const char* name, int64 value); 149 inline status_t SetPointer(const char* name, const void* value); 150 151 // message delivery 152 team_id Sender() const; 153 int32 TargetToken() const; 154 port_id ReplyPort() const; 155 int32 ReplyToken() const; 156 157 void SetDeliveryInfo(int32 targetToken, 158 port_id replyPort, int32 replyToken, 159 team_id senderTeam); 160 161 status_t SendTo(port_id targetPort, 162 int32 targetToken = -1, 163 port_id replyPort = -1, 164 int32 replyToken = -1, 165 bigtime_t timeout = -1, 166 team_id senderTeam = -1); 167 status_t SendTo(port_id targetPort, int32 targetToken, 168 KMessage* reply, 169 bigtime_t deliveryTimeout = -1, 170 bigtime_t replyTimeout = -1, 171 team_id senderTeam = -1); 172 status_t SendReply(KMessage* message, 173 port_id replyPort = -1, 174 int32 replyToken = -1, 175 bigtime_t timeout = -1, 176 team_id senderTeam = -1); 177 status_t SendReply(KMessage* message, KMessage* reply, 178 bigtime_t deliveryTimeout = -1, 179 bigtime_t replyTimeout = -1, 180 team_id senderTeam = -1); 181 status_t ReceiveFrom(port_id fromPort, 182 bigtime_t timeout = -1, 183 port_message_info* messageInfo = NULL); 184 185 void Dump(void (*printFunc)(const char*, ...)) const; 186 187private: 188 friend class KMessageField; 189 friend class MessageAdapter; 190 friend class ::BMessage; // not so nice, but makes things easier 191 192 struct Header { 193 uint32 magic; 194 int32 size; 195 uint32 what; 196 team_id sender; 197 int32 targetToken; 198 port_id replyPort; 199 int32 replyToken; 200 }; 201 202 struct FieldHeader; 203 struct FieldValueHeader; 204 205private: 206 Header* _Header() const; 207 int32 _BufferOffsetFor(const void* data) const; 208 FieldHeader* _FirstFieldHeader() const; 209 FieldHeader* _LastFieldHeader() const; 210 FieldHeader* _FieldHeaderForOffset(int32 offset) const; 211 status_t _AddField(const char* name, type_code type, 212 int32 elementSize, KMessageField* field); 213 status_t _AddFieldData(KMessageField* field, 214 const void* data, int32 elementSize, 215 int32 elementCount); 216 217 status_t _InitFromBuffer(bool sizeFromBuffer); 218 void _InitBuffer(uint32 what); 219 220 void _CheckBuffer(); // debugging only 221 222 status_t _AllocateSpace(int32 size, bool alignAddress, 223 bool alignSize, void** address, 224 int32* alignedSize); 225 int32 _CapacityFor(int32 size); 226 227 template<typename T> 228 inline status_t _FindType(const char* name, type_code type, 229 int32 index, T* value) const; 230 231 template<typename T> 232 inline T _GetType(const char* name, type_code type, 233 int32 index, const T& defaultValue) const; 234 235private: 236 Header fHeader; // pointed to by fBuffer, if nothing 237 // is allocated 238 void* fBuffer; 239 int32 fBufferCapacity; 240 uint32 fFlags; 241 int32 fLastFieldOffset; 242 243 static const uint32 kMessageHeaderMagic; 244}; 245 246 247class KMessageField { 248public: 249 KMessageField(); 250 251 void Unset(); 252 253 KMessage* Message() const; 254 255 const char* Name() const; 256 type_code TypeCode() const; 257 bool HasFixedElementSize() const; 258 int32 ElementSize() const; 259 // only if HasFixedElementSize() 260 261 status_t AddElement(const void* data, int32 size = -1); 262 status_t AddElements(const void* data, int32 count, 263 int32 elementSize = -1); 264 const void* ElementAt(int32 index, 265 int32* size = NULL) const; 266 int32 CountElements() const; 267 268private: 269 friend class KMessage; 270 271private: 272 void SetTo(KMessage* message, int32 headerOffset); 273 274 KMessage::FieldHeader* _Header() const; 275 276private: 277 KMessage* fMessage; 278 int32 fHeaderOffset; 279}; 280 281} // namespace BPrivate 282 283 284using BPrivate::KMessage; 285using BPrivate::KMessageField; 286 287 288// #pragma mark - inline functions 289 290 291status_t 292KMessage::AddBool(const char* name, bool value) 293{ 294 return AddData(name, B_BOOL_TYPE, &value, sizeof(bool), true); 295} 296 297 298status_t 299KMessage::AddInt8(const char* name, int8 value) 300{ 301 return AddData(name, B_INT8_TYPE, &value, sizeof(int8), true); 302} 303 304 305status_t 306KMessage::AddInt16(const char* name, int16 value) 307{ 308 return AddData(name, B_INT16_TYPE, &value, sizeof(int16), true); 309} 310 311 312status_t 313KMessage::AddInt32(const char* name, int32 value) 314{ 315 return AddData(name, B_INT32_TYPE, &value, sizeof(int32), true); 316} 317 318 319status_t 320KMessage::AddInt64(const char* name, int64 value) 321{ 322 return AddData(name, B_INT64_TYPE, &value, sizeof(int64), true); 323} 324 325 326status_t 327KMessage::AddPointer(const char* name, const void* value) 328{ 329 return AddData(name, B_POINTER_TYPE, &value, sizeof(value), true); 330} 331 332 333// AddString 334status_t 335KMessage::AddString(const char* name, const char* value) 336{ 337 if (!value) 338 return B_BAD_VALUE; 339 return AddData(name, B_STRING_TYPE, value, strlen(value) + 1, false); 340} 341 342 343// #pragma mark - 344 345 346template<typename T> 347status_t 348KMessage::_FindType(const char* name, type_code type, int32 index, 349 T* value) const 350{ 351 const void* data; 352 int32 size; 353 status_t error = FindData(name, type, index, &data, &size); 354 if (error != B_OK) 355 return error; 356 357 if (size != sizeof(T)) 358 return B_BAD_DATA; 359 360 *value = *(T*)data; 361 362 return B_OK; 363} 364 365 366status_t 367KMessage::FindBool(const char* name, bool* value) const 368{ 369 return FindBool(name, 0, value); 370} 371 372 373status_t 374KMessage::FindBool(const char* name, int32 index, bool* value) const 375{ 376 return _FindType(name, B_BOOL_TYPE, index, value); 377} 378 379 380status_t 381KMessage::FindInt8(const char* name, int8* value) const 382{ 383 return FindInt8(name, 0, value); 384} 385 386 387status_t 388KMessage::FindInt8(const char* name, int32 index, int8* value) const 389{ 390 return _FindType(name, B_INT8_TYPE, index, value); 391} 392 393 394status_t 395KMessage::FindInt16(const char* name, int16* value) const 396{ 397 return FindInt16(name, 0, value); 398} 399 400 401status_t 402KMessage::FindInt16(const char* name, int32 index, int16* value) const 403{ 404 return _FindType(name, B_INT16_TYPE, index, value); 405} 406 407 408status_t 409KMessage::FindInt32(const char* name, int32* value) const 410{ 411 return FindInt32(name, 0, value); 412} 413 414 415status_t 416KMessage::FindInt32(const char* name, int32 index, int32* value) const 417{ 418 return _FindType(name, B_INT32_TYPE, index, value); 419} 420 421 422status_t 423KMessage::FindInt64(const char* name, int64* value) const 424{ 425 return FindInt64(name, 0, value); 426} 427 428 429status_t 430KMessage::FindInt64(const char* name, int32 index, int64* value) const 431{ 432 return _FindType(name, B_INT64_TYPE, index, value); 433} 434 435 436status_t 437KMessage::FindPointer(const char* name, void** value) const 438{ 439 return FindPointer(name, 0, value); 440} 441 442 443status_t 444KMessage::FindPointer(const char* name, int32 index, void** value) const 445{ 446 return _FindType(name, B_POINTER_TYPE, index, value); 447} 448 449 450status_t 451KMessage::FindString(const char* name, const char** value) const 452{ 453 return FindString(name, 0, value); 454} 455 456 457status_t 458KMessage::FindString(const char* name, int32 index, const char** value) const 459{ 460 int32 size; 461 return FindData(name, B_STRING_TYPE, index, (const void**)value, &size); 462} 463 464 465template<typename T> 466inline T 467KMessage::_GetType(const char* name, type_code type, int32 index, 468 const T& defaultValue) const 469{ 470 T value; 471 if (_FindType(name, type, index, &value) == B_OK) 472 return value; 473 return defaultValue; 474} 475 476 477inline bool 478KMessage::GetBool(const char* name, bool defaultValue) const 479{ 480 return _GetType(name, B_BOOL_TYPE, 0, defaultValue); 481} 482 483 484inline bool 485KMessage::GetBool(const char* name, int32 index, bool defaultValue) const 486{ 487 return _GetType(name, B_BOOL_TYPE, index, defaultValue); 488} 489 490 491int8 492KMessage::GetInt8(const char* name, int8 defaultValue) const 493{ 494 return _GetType(name, B_INT8_TYPE, 0, defaultValue); 495} 496 497 498int8 499KMessage::GetInt8(const char* name, int32 index, int8 defaultValue) const 500{ 501 return _GetType(name, B_INT8_TYPE, index, defaultValue); 502} 503 504 505int16 506KMessage::GetInt16(const char* name, int16 defaultValue) const 507{ 508 return _GetType(name, B_INT16_TYPE, 0, defaultValue); 509} 510 511 512int16 513KMessage::GetInt16(const char* name, int32 index, int16 defaultValue) const 514{ 515 return _GetType(name, B_INT16_TYPE, index, defaultValue); 516} 517 518 519int32 520KMessage::GetInt32(const char* name, int32 defaultValue) const 521{ 522 return _GetType(name, B_INT32_TYPE, 0, defaultValue); 523} 524 525 526int32 527KMessage::GetInt32(const char* name, int32 index, int32 defaultValue) const 528{ 529 return _GetType(name, B_INT32_TYPE, index, defaultValue); 530} 531 532 533int64 534KMessage::GetInt64(const char* name, int64 defaultValue) const 535{ 536 return _GetType(name, B_INT64_TYPE, 0, defaultValue); 537} 538 539 540int64 541KMessage::GetInt64(const char* name, int32 index, int64 defaultValue) const 542{ 543 return _GetType(name, B_INT64_TYPE, index, defaultValue); 544} 545 546 547void* 548KMessage::GetPointer(const char* name, const void* defaultValue) const 549{ 550 return const_cast<void*>(_GetType(name, B_POINTER_TYPE, 0, defaultValue)); 551} 552 553 554void* 555KMessage::GetPointer(const char* name, int32 index, 556 const void* defaultValue) const 557{ 558 return const_cast<void*>(_GetType(name, B_POINTER_TYPE, index, 559 defaultValue)); 560} 561 562 563const char* 564KMessage::GetString(const char* name, int32 index, 565 const char* defaultValue) const 566{ 567 // don't use _GetType() here, since it checks field size == sizeof(T) 568 int32 size; 569 const char* value; 570 if (FindData(name, B_STRING_TYPE, index, (const void**)&value, &size) 571 == B_OK) { 572 return value; 573 } 574 return defaultValue; 575} 576 577 578const char* 579KMessage::GetString(const char* name, const char* defaultValue) const 580{ 581 return GetString(name, 0, defaultValue); 582} 583 584 585status_t 586KMessage::SetBool(const char* name, bool value) 587{ 588 return SetData(name, B_BOOL_TYPE, &value, sizeof(bool)); 589} 590 591 592status_t 593KMessage::SetInt8(const char* name, int8 value) 594{ 595 return SetData(name, B_INT8_TYPE, &value, sizeof(int8)); 596} 597 598 599status_t 600KMessage::SetInt16(const char* name, int16 value) 601{ 602 return SetData(name, B_INT16_TYPE, &value, sizeof(int16)); 603} 604 605 606status_t 607KMessage::SetInt32(const char* name, int32 value) 608{ 609 return SetData(name, B_INT32_TYPE, &value, sizeof(int32)); 610} 611 612 613status_t 614KMessage::SetInt64(const char* name, int64 value) 615{ 616 return SetData(name, B_INT64_TYPE, &value, sizeof(int64)); 617} 618 619 620status_t 621KMessage::SetPointer(const char* name, const void* value) 622{ 623 return SetData(name, B_POINTER_TYPE, &value, sizeof(value)); 624} 625 626 627#else // !__cplusplus 628 629 630typedef struct KMessage { 631 struct Header { 632 uint32 magic; 633 int32 size; 634 uint32 what; 635 team_id sender; 636 int32 targetToken; 637 port_id replyPort; 638 int32 replyToken; 639 } fHeader; 640 void* fBuffer; 641 int32 fBufferCapacity; 642 uint32 fFlags; 643 int32 fLastFieldOffset; 644} KMessage; 645 646 647#endif // !__cplusplus 648 649 650#endif // KMESSAGE_H 651