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