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