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