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 18 class BMessage; 19 20 21 namespace BPrivate { 22 23 class KMessageField; 24 class MessageAdapter; 25 26 27 class KMessage { 28 public: 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 38 public: 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 187 private: 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 205 private: 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 235 private: 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 247 class KMessageField { 248 public: 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 268 private: 269 friend class KMessage; 270 271 private: 272 void SetTo(KMessage* message, int32 headerOffset); 273 274 KMessage::FieldHeader* _Header() const; 275 276 private: 277 KMessage* fMessage; 278 int32 fHeaderOffset; 279 }; 280 281 } // namespace BPrivate 282 283 284 using BPrivate::KMessage; 285 using BPrivate::KMessageField; 286 287 288 // #pragma mark - inline functions 289 290 291 status_t 292 KMessage::AddBool(const char* name, bool value) 293 { 294 return AddData(name, B_BOOL_TYPE, &value, sizeof(bool), true); 295 } 296 297 298 status_t 299 KMessage::AddInt8(const char* name, int8 value) 300 { 301 return AddData(name, B_INT8_TYPE, &value, sizeof(int8), true); 302 } 303 304 305 status_t 306 KMessage::AddInt16(const char* name, int16 value) 307 { 308 return AddData(name, B_INT16_TYPE, &value, sizeof(int16), true); 309 } 310 311 312 status_t 313 KMessage::AddInt32(const char* name, int32 value) 314 { 315 return AddData(name, B_INT32_TYPE, &value, sizeof(int32), true); 316 } 317 318 319 status_t 320 KMessage::AddInt64(const char* name, int64 value) 321 { 322 return AddData(name, B_INT64_TYPE, &value, sizeof(int64), true); 323 } 324 325 326 status_t 327 KMessage::AddPointer(const char* name, const void* value) 328 { 329 return AddData(name, B_POINTER_TYPE, &value, sizeof(value), true); 330 } 331 332 333 // AddString 334 status_t 335 KMessage::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 346 template<typename T> 347 status_t 348 KMessage::_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 366 status_t 367 KMessage::FindBool(const char* name, bool* value) const 368 { 369 return FindBool(name, 0, value); 370 } 371 372 373 status_t 374 KMessage::FindBool(const char* name, int32 index, bool* value) const 375 { 376 return _FindType(name, B_BOOL_TYPE, index, value); 377 } 378 379 380 status_t 381 KMessage::FindInt8(const char* name, int8* value) const 382 { 383 return FindInt8(name, 0, value); 384 } 385 386 387 status_t 388 KMessage::FindInt8(const char* name, int32 index, int8* value) const 389 { 390 return _FindType(name, B_INT8_TYPE, index, value); 391 } 392 393 394 status_t 395 KMessage::FindInt16(const char* name, int16* value) const 396 { 397 return FindInt16(name, 0, value); 398 } 399 400 401 status_t 402 KMessage::FindInt16(const char* name, int32 index, int16* value) const 403 { 404 return _FindType(name, B_INT16_TYPE, index, value); 405 } 406 407 408 status_t 409 KMessage::FindInt32(const char* name, int32* value) const 410 { 411 return FindInt32(name, 0, value); 412 } 413 414 415 status_t 416 KMessage::FindInt32(const char* name, int32 index, int32* value) const 417 { 418 return _FindType(name, B_INT32_TYPE, index, value); 419 } 420 421 422 status_t 423 KMessage::FindInt64(const char* name, int64* value) const 424 { 425 return FindInt64(name, 0, value); 426 } 427 428 429 status_t 430 KMessage::FindInt64(const char* name, int32 index, int64* value) const 431 { 432 return _FindType(name, B_INT64_TYPE, index, value); 433 } 434 435 436 status_t 437 KMessage::FindPointer(const char* name, void** value) const 438 { 439 return FindPointer(name, 0, value); 440 } 441 442 443 status_t 444 KMessage::FindPointer(const char* name, int32 index, void** value) const 445 { 446 return _FindType(name, B_POINTER_TYPE, index, value); 447 } 448 449 450 status_t 451 KMessage::FindString(const char* name, const char** value) const 452 { 453 return FindString(name, 0, value); 454 } 455 456 457 status_t 458 KMessage::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 465 template<typename T> 466 inline T 467 KMessage::_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 477 inline bool 478 KMessage::GetBool(const char* name, bool defaultValue) const 479 { 480 return _GetType(name, B_BOOL_TYPE, 0, defaultValue); 481 } 482 483 484 inline bool 485 KMessage::GetBool(const char* name, int32 index, bool defaultValue) const 486 { 487 return _GetType(name, B_BOOL_TYPE, index, defaultValue); 488 } 489 490 491 int8 492 KMessage::GetInt8(const char* name, int8 defaultValue) const 493 { 494 return _GetType(name, B_INT8_TYPE, 0, defaultValue); 495 } 496 497 498 int8 499 KMessage::GetInt8(const char* name, int32 index, int8 defaultValue) const 500 { 501 return _GetType(name, B_INT8_TYPE, index, defaultValue); 502 } 503 504 505 int16 506 KMessage::GetInt16(const char* name, int16 defaultValue) const 507 { 508 return _GetType(name, B_INT16_TYPE, 0, defaultValue); 509 } 510 511 512 int16 513 KMessage::GetInt16(const char* name, int32 index, int16 defaultValue) const 514 { 515 return _GetType(name, B_INT16_TYPE, index, defaultValue); 516 } 517 518 519 int32 520 KMessage::GetInt32(const char* name, int32 defaultValue) const 521 { 522 return _GetType(name, B_INT32_TYPE, 0, defaultValue); 523 } 524 525 526 int32 527 KMessage::GetInt32(const char* name, int32 index, int32 defaultValue) const 528 { 529 return _GetType(name, B_INT32_TYPE, index, defaultValue); 530 } 531 532 533 int64 534 KMessage::GetInt64(const char* name, int64 defaultValue) const 535 { 536 return _GetType(name, B_INT64_TYPE, 0, defaultValue); 537 } 538 539 540 int64 541 KMessage::GetInt64(const char* name, int32 index, int64 defaultValue) const 542 { 543 return _GetType(name, B_INT64_TYPE, index, defaultValue); 544 } 545 546 547 void* 548 KMessage::GetPointer(const char* name, const void* defaultValue) const 549 { 550 return const_cast<void*>(_GetType(name, B_POINTER_TYPE, 0, defaultValue)); 551 } 552 553 554 void* 555 KMessage::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 563 const char* 564 KMessage::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 578 const char* 579 KMessage::GetString(const char* name, const char* defaultValue) const 580 { 581 return GetString(name, 0, defaultValue); 582 } 583 584 585 status_t 586 KMessage::SetBool(const char* name, bool value) 587 { 588 return SetData(name, B_BOOL_TYPE, &value, sizeof(bool)); 589 } 590 591 592 status_t 593 KMessage::SetInt8(const char* name, int8 value) 594 { 595 return SetData(name, B_INT8_TYPE, &value, sizeof(int8)); 596 } 597 598 599 status_t 600 KMessage::SetInt16(const char* name, int16 value) 601 { 602 return SetData(name, B_INT16_TYPE, &value, sizeof(int16)); 603 } 604 605 606 status_t 607 KMessage::SetInt32(const char* name, int32 value) 608 { 609 return SetData(name, B_INT32_TYPE, &value, sizeof(int32)); 610 } 611 612 613 status_t 614 KMessage::SetInt64(const char* name, int64 value) 615 { 616 return SetData(name, B_INT64_TYPE, &value, sizeof(int64)); 617 } 618 619 620 status_t 621 KMessage::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 630 typedef 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