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