1 //------------------------------------------------------------------------------ 2 // Copyright (c) 2001-2002, OpenBeOS 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a 5 // copy of this software and associated documentation files (the "Software"), 6 // to deal in the Software without restriction, including without limitation 7 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 // and/or sell copies of the Software, and to permit persons to whom the 9 // Software is furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 // DEALINGS IN THE SOFTWARE. 21 // 22 // File Name: Message.h 23 // Author(s): Erik Jaesler (erik@cgsoftware.com) 24 // DarkWyrm <bpmagic@columbus.rr.com> 25 // Description: BMessage class creates objects that store data and that 26 // can be processed in a message loop. BMessage objects 27 // are also used as data containers by the archiving and 28 // the scripting mechanisms. 29 //------------------------------------------------------------------------------ 30 31 #define USING_TEMPLATE_MADNESS 32 33 // Standard Includes ----------------------------------------------------------- 34 #include <stdio.h> 35 36 // System Includes ------------------------------------------------------------- 37 #include <Application.h> 38 #include <BlockCache.h> 39 #include <ByteOrder.h> 40 #include <Errors.h> 41 #include <Message.h> 42 #include <Messenger.h> 43 #include <String.h> 44 45 //#include <CRTDBG.H> 46 47 // Project Includes ------------------------------------------------------------ 48 #ifdef USING_TEMPLATE_MADNESS 49 #include <AppMisc.h> 50 #include <DataBuffer.h> 51 #include <MessageBody.h> 52 #include <MessageUtils.h> 53 #include <TokenSpace.h> 54 #endif // USING_TEMPLATE_MADNESS 55 56 // Local Includes -------------------------------------------------------------- 57 58 // Local Defines --------------------------------------------------------------- 59 #define MSG_FIELD_VERSION 'FOB1' 60 61 // flags for the overall message (the bitfield is 1 byte) 62 #define MSG_FLAG_BIG_ENDIAN 0x01 63 #define MSG_FLAG_INCL_TARGET 0x02 64 #define MSG_FLAG_INCL_REPLY 0x04 65 #define MSG_FLAG_SCRIPT_MSG 0x08 66 // These are for future improvement 67 #if 0 68 #define MSG_FLAG_USE_PREFERRED 0x10 69 #define MSG_FLAG_REPLY_WANTED 0x20 70 #define MSG_FLAG_REPLY_DONE 0x40 71 #define MSG_FLAG_IS_REPLY 0x80 72 73 #define MSG_FLAG_HDR_MASK 0xF0 74 #endif 75 76 #define MSG_HEADER_MAX_SIZE 38 77 #define MSG_NAME_MAX_SIZE 256 78 79 // Globals --------------------------------------------------------------------- 80 81 #ifdef USING_TEMPLATE_MADNESS 82 using namespace BPrivate; 83 #endif // USING_TEMPLATE_MADNESS 84 const char* B_SPECIFIER_ENTRY = "specifiers"; 85 const char* B_PROPERTY_ENTRY = "property"; 86 const char* B_PROPERTY_NAME_ENTRY = "name"; 87 88 BBlockCache* BMessage::sMsgCache = NULL; 89 port_id BMessage::sReplyPorts[sNumReplyPorts]; 90 long BMessage::sReplyPortInUse[sNumReplyPorts]; 91 92 93 static status_t handle_reply(port_id reply_port, 94 int32* pCode, 95 bigtime_t timeout, 96 BMessage* reply); 97 98 //------------------------------------------------------------------------------ 99 extern "C" { 100 void _msg_cache_cleanup_() 101 { 102 delete BMessage::sMsgCache; 103 BMessage::sMsgCache = NULL; 104 } 105 //------------------------------------------------------------------------------ 106 int _init_message_() 107 { 108 BMessage::sReplyPorts[0] = create_port(1, "tmp_rport0"); 109 BMessage::sReplyPorts[1] = create_port(1, "tmp_rport1"); 110 BMessage::sReplyPorts[2] = create_port(1, "tmp_rport2"); 111 112 BMessage::sReplyPortInUse[0] = 0; 113 BMessage::sReplyPortInUse[1] = 0; 114 BMessage::sReplyPortInUse[2] = 0; 115 return 0; 116 } 117 //------------------------------------------------------------------------------ 118 int _delete_message_() 119 { 120 delete_port(BMessage::sReplyPorts[0]); 121 BMessage::sReplyPorts[0] = NULL; 122 delete_port(BMessage::sReplyPorts[1]); 123 BMessage::sReplyPorts[1] = NULL; 124 delete_port(BMessage::sReplyPorts[2]); 125 BMessage::sReplyPorts[2] = NULL; 126 return 0; 127 } 128 } // extern "C" 129 //------------------------------------------------------------------------------ 130 BMessage *_reconstruct_msg_(uint32,uint32,uint32) 131 { 132 return NULL; 133 } 134 //------------------------------------------------------------------------------ 135 136 #ifdef USING_TEMPLATE_MADNESS 137 void BMessage::_ReservedMessage1() {} 138 void BMessage::_ReservedMessage2() {} 139 void BMessage::_ReservedMessage3() {} 140 141 //------------------------------------------------------------------------------ 142 BMessage::BMessage() 143 : what(0), fBody(NULL) 144 { 145 init_data(); 146 } 147 //------------------------------------------------------------------------------ 148 BMessage::BMessage(uint32 w) 149 : fBody(NULL) 150 { 151 init_data(); 152 what = w; 153 } 154 //------------------------------------------------------------------------------ 155 BMessage::BMessage(const BMessage& a_message) 156 : fBody(NULL) 157 { 158 init_data(); 159 *this = a_message; 160 } 161 //------------------------------------------------------------------------------ 162 BMessage::BMessage(BMessage *a_message) 163 : fBody(NULL) 164 { 165 init_data(); 166 *this = *a_message; 167 } 168 //------------------------------------------------------------------------------ 169 BMessage::~BMessage() 170 { 171 // ToDo: send outstanding reply! 172 delete fBody; 173 } 174 //------------------------------------------------------------------------------ 175 BMessage& BMessage::operator=(const BMessage& msg) 176 { 177 what = msg.what; 178 179 link = msg.link; 180 fTarget = msg.fTarget; 181 fOriginal = msg.fOriginal; 182 fChangeCount = msg.fChangeCount; 183 fCurSpecifier = msg.fCurSpecifier; 184 fPtrOffset = msg.fPtrOffset; 185 186 fEntries = msg.fEntries; 187 188 fReplyTo.port = msg.fReplyTo.port; 189 fReplyTo.target = msg.fReplyTo.target; 190 fReplyTo.team = msg.fReplyTo.team; 191 fReplyTo.preferred = msg.fReplyTo.preferred; 192 193 fPreferred = msg.fPreferred; 194 fReplyRequired = msg.fReplyRequired; 195 fReplyDone = msg.fReplyDone; 196 fIsReply = msg.fIsReply; 197 fWasDelivered = msg.fWasDelivered; 198 fReadOnly = msg.fReadOnly; 199 fHasSpecifiers = msg.fHasSpecifiers; 200 201 *fBody = *(msg.fBody); 202 return *this; 203 } 204 //------------------------------------------------------------------------------ 205 void BMessage::init_data() 206 { 207 what = 0; 208 209 link = NULL; 210 fTarget = B_NULL_TOKEN; 211 fOriginal = NULL; 212 fChangeCount = 0; 213 fCurSpecifier = -1; 214 fPtrOffset = 0; 215 216 fEntries = NULL; 217 218 fReplyTo.port = -1; 219 fReplyTo.target = B_NULL_TOKEN; 220 fReplyTo.team = -1; 221 fReplyTo.preferred = false; 222 223 fPreferred = false; 224 fReplyRequired = false; 225 fReplyDone = false; 226 fIsReply = false; 227 fWasDelivered = false; 228 fReadOnly = false; 229 fHasSpecifiers = false; 230 231 if (fBody) 232 { 233 fBody->MakeEmpty(); 234 } 235 else 236 { 237 fBody = new BPrivate::BMessageBody; 238 } 239 } 240 //------------------------------------------------------------------------------ 241 status_t BMessage::GetInfo(type_code typeRequested, int32 which, char** name, 242 type_code* typeReturned, int32* count) const 243 { 244 return fBody->GetInfo(typeRequested, which, name, typeReturned, count); 245 } 246 //------------------------------------------------------------------------------ 247 status_t BMessage::GetInfo(const char* name, type_code* type, int32* c) const 248 { 249 return fBody->GetInfo(name, type, c); 250 } 251 //------------------------------------------------------------------------------ 252 status_t BMessage::GetInfo(const char* name, type_code* type, 253 bool* fixed_size) const 254 { 255 return fBody->GetInfo(name, type, fixed_size); 256 } 257 //------------------------------------------------------------------------------ 258 int32 BMessage::CountNames(type_code type) const 259 { 260 return fBody->CountNames(type); 261 } 262 //------------------------------------------------------------------------------ 263 bool BMessage::IsEmpty() const 264 { 265 return fBody->IsEmpty(); 266 } 267 //------------------------------------------------------------------------------ 268 bool BMessage::IsSystem() const 269 { 270 char a = char(what >> 24); 271 char b = char(what >> 16); 272 char c = char(what >> 8); 273 char d = char(what); 274 275 // The BeBook says: 276 // ... we've adopted a strict convention for assigning values to all 277 // Be-defined constants. The value assigned will always be formed by 278 // combining four characters into a multicharacter constant, with the 279 // characters limited to uppercase letters and the underbar 280 // Between that and what's in AppDefs.h, this algo seems like a safe bet: 281 if (a == '_' && isupper(b) && isupper(c) && isupper(d)) 282 { 283 return true; 284 } 285 286 return false; 287 } 288 //------------------------------------------------------------------------------ 289 bool BMessage::IsReply() const 290 { 291 return fIsReply; 292 } 293 //------------------------------------------------------------------------------ 294 void BMessage::PrintToStream() const 295 { 296 printf("\nBMessage: what = (0x%lX or %ld)\n", what, what); 297 fBody->PrintToStream(); 298 } 299 //------------------------------------------------------------------------------ 300 status_t BMessage::Rename(const char* old_entry, const char* new_entry) 301 { 302 return fBody->Rename(old_entry, new_entry); 303 } 304 //------------------------------------------------------------------------------ 305 bool BMessage::WasDelivered() const 306 { 307 return fWasDelivered; 308 } 309 //------------------------------------------------------------------------------ 310 bool BMessage::IsSourceWaiting() const 311 { 312 return fReplyRequired && !fReplyDone; 313 } 314 //------------------------------------------------------------------------------ 315 bool BMessage::IsSourceRemote() const 316 { 317 return WasDelivered() && fReplyTo.team != BPrivate::current_team(); 318 } 319 //------------------------------------------------------------------------------ 320 BMessenger BMessage::ReturnAddress() const 321 { 322 if (WasDelivered()) 323 { 324 return BMessenger(fReplyTo.team, fReplyTo.port, fReplyTo.target, 325 fReplyTo.preferred); 326 } 327 328 return BMessenger(); 329 } 330 //------------------------------------------------------------------------------ 331 const BMessage* BMessage::Previous() const 332 { 333 // TODO: test 334 // In particular, look to see if the "_previous_" field is used in R5 335 if (!fOriginal) 336 { 337 BMessage* fOriginal = new BMessage; 338 if (FindMessage("_previous_", fOriginal) != B_OK) 339 { 340 delete fOriginal; 341 fOriginal = NULL; 342 } 343 } 344 345 return fOriginal; 346 } 347 //------------------------------------------------------------------------------ 348 bool BMessage::WasDropped() const 349 { 350 return fReadOnly; 351 } 352 //------------------------------------------------------------------------------ 353 BPoint BMessage::DropPoint(BPoint* offset) const 354 { 355 // TODO: Where do we get this stuff??? 356 if (offset) 357 { 358 *offset = FindPoint("_drop_offset_"); 359 } 360 return FindPoint("_drop_point_"); 361 } 362 //------------------------------------------------------------------------------ 363 status_t BMessage::SendReply(uint32 command, BHandler* reply_to) 364 { 365 BMessage msg(command); 366 return SendReply(&msg, reply_to); 367 } 368 //------------------------------------------------------------------------------ 369 status_t BMessage::SendReply(BMessage* the_reply, BHandler* reply_to, 370 bigtime_t timeout) 371 { 372 BMessenger messenger(reply_to); 373 return SendReply(the_reply, messenger, timeout); 374 } 375 //------------------------------------------------------------------------------ 376 #if 0 377 template<class Sender> 378 status_t SendReplyHelper(BMessage* the_message, BMessage* the_reply, 379 Sender& the_sender) 380 { 381 BMessenger messenger(the_message->fReplyTo.team, the_message->fReplyTo.port, 382 the_message->fReplyTo.target, 383 the_message->fReplyTo.preferred); 384 if (the_message->fReplyRequired) 385 { 386 if (the_message->fReplyDone) 387 { 388 return B_DUPLICATE_REPLY; 389 } 390 the_message->fReplyDone = true; 391 the_reply->fIsReply = true; 392 status_t err = the_sender.Send(messenger, the_reply); 393 the_reply->fIsReply = false; 394 if (err) 395 { 396 if (set_port_owner(messenger.fPort, messenger.fTeam) == B_BAD_TEAM_ID) 397 { 398 delete_port(messenger.fPort); 399 } 400 } 401 return err; 402 } 403 // no reply required 404 if (!the_message->fWasDelivered) 405 { 406 return B_BAD_REPLY; 407 } 408 409 #if 0 410 char tmp[0x800]; 411 ssize_t size; 412 char* p = stack_flatten(tmp, sizeof(tmp), true /* include reply */, &size); 413 the_reply->AddData("_previous_", B_RAW_TYPE, p ? p : tmp, &size); 414 if (p) 415 { 416 free(p); 417 } 418 #endif 419 the_reply->AddMessage("_previous_", the_message); 420 the_reply->fIsReply = true; 421 status_t err = the_sender.Send(messenger, the_reply); 422 the_reply->fIsReply = false; 423 the_reply->RemoveName("_previous_"); 424 return err; 425 }; 426 #endif 427 //------------------------------------------------------------------------------ 428 #if 0 429 struct Sender1 430 { 431 BMessenger& reply_to; 432 bigtime_t timeout; 433 434 Sender1(BMessenger& m, bigtime_t t) : reply_to(m), timeout(t) {;} 435 436 status_t Send(BMessenger& messenger, BMessage* the_reply) 437 { 438 return messenger.SendMessage(the_reply, reply_to, timeout); 439 } 440 }; 441 status_t BMessage::SendReply(BMessage* the_reply, BMessenger reply_to, 442 bigtime_t timeout) 443 { 444 Sender1 mySender(reply_to, timeout); 445 return SendReplyHelper(this, the_reply, mySender); 446 } 447 #endif 448 status_t BMessage::SendReply(BMessage* the_reply, BMessenger reply_to, 449 bigtime_t timeout) 450 { 451 // TODO: test 452 BMessenger messenger(fReplyTo.team, fReplyTo.port, 453 fReplyTo.target, 454 fReplyTo.preferred); 455 if (fReplyRequired) 456 { 457 if (fReplyDone) 458 { 459 return B_DUPLICATE_REPLY; 460 } 461 fReplyDone = true; 462 the_reply->fIsReply = true; 463 status_t err = messenger.SendMessage(the_reply, reply_to, timeout); 464 the_reply->fIsReply = false; 465 if (err) 466 { 467 if (set_port_owner(messenger.fPort, messenger.fTeam) == B_BAD_TEAM_ID) 468 { 469 delete_port(messenger.fPort); 470 } 471 } 472 return err; 473 } 474 // no reply required 475 if (!fWasDelivered) 476 { 477 return B_BAD_REPLY; 478 } 479 480 the_reply->AddMessage("_previous_", this); 481 the_reply->fIsReply = true; 482 status_t err = messenger.SendMessage(the_reply, reply_to, timeout); 483 the_reply->fIsReply = false; 484 the_reply->RemoveName("_previous_"); 485 return err; 486 } 487 //------------------------------------------------------------------------------ 488 status_t BMessage::SendReply(uint32 command, BMessage* reply_to_reply) 489 { 490 BMessage msg(command); 491 return SendReply(&msg, reply_to_reply); 492 } 493 //------------------------------------------------------------------------------ 494 #if 0 495 struct Sender2 496 { 497 BMessage* reply_to_reply; 498 bigtime_t send_timeout; 499 bigtime_t reply_timeout; 500 501 Sender2(BMessage* m, bigtime_t t1, bigtime_t t2) 502 : reply_to_reply(m), send_timeout(t1), reply_timeout(t2) {;} 503 504 status_t Send(BMessenger& messenger, BMessage* the_reply) 505 { 506 return messenger.SendMessage(the_reply, reply_to_reply, 507 send_timeout, reply_timeout); 508 } 509 }; 510 status_t BMessage::SendReply(BMessage* the_reply, BMessage* reply_to_reply, 511 bigtime_t send_timeout, bigtime_t reply_timeout) 512 { 513 Sender2 mySender(reply_to_reply, send_timeout, reply_timeout); 514 return SendReplyHelper(this, the_reply, mySender); 515 } 516 #endif 517 status_t BMessage::SendReply(BMessage* the_reply, BMessage* reply_to_reply, 518 bigtime_t send_timeout, bigtime_t reply_timeout) 519 { 520 // TODO: test 521 BMessenger messenger(fReplyTo.team, fReplyTo.port, 522 fReplyTo.target, 523 fReplyTo.preferred); 524 if (fReplyRequired) 525 { 526 if (fReplyDone) 527 { 528 return B_DUPLICATE_REPLY; 529 } 530 fReplyDone = true; 531 the_reply->fIsReply = true; 532 status_t err = messenger.SendMessage(the_reply, reply_to_reply, 533 send_timeout, reply_timeout); 534 the_reply->fIsReply = false; 535 if (err) 536 { 537 if (set_port_owner(messenger.fPort, messenger.fTeam) == B_BAD_TEAM_ID) 538 { 539 delete_port(messenger.fPort); 540 } 541 } 542 return err; 543 } 544 // no reply required 545 if (!fWasDelivered) 546 { 547 return B_BAD_REPLY; 548 } 549 550 the_reply->AddMessage("_previous_", this); 551 the_reply->fIsReply = true; 552 status_t err = messenger.SendMessage(the_reply, reply_to_reply, 553 send_timeout, reply_timeout); 554 the_reply->fIsReply = false; 555 the_reply->RemoveName("_previous_"); 556 return err; 557 } 558 //------------------------------------------------------------------------------ 559 ssize_t BMessage::FlattenedSize() const 560 { 561 return calc_hdr_size(0) + fBody->FlattenedSize(); 562 } 563 //------------------------------------------------------------------------------ 564 status_t BMessage::Flatten(char* buffer, ssize_t size) const 565 { 566 return real_flatten(buffer, size); 567 } 568 //------------------------------------------------------------------------------ 569 status_t BMessage::Flatten(BDataIO* stream, ssize_t* size) const 570 { 571 status_t err = B_OK; 572 ssize_t len = FlattenedSize(); 573 char* buffer = new(nothrow) char[len]; 574 if (buffer) 575 { 576 err = Flatten(buffer, len); 577 if (!err) 578 { 579 // size is an optional parameter, don't crash on NULL 580 if (size != NULL) 581 { 582 *size = len; 583 } 584 err = stream->Write(buffer, len); 585 if (err > B_OK) 586 err = B_OK; 587 } 588 589 delete[] buffer; 590 } 591 else 592 { 593 err = B_NO_MEMORY; 594 } 595 596 return err; 597 } 598 //------------------------------------------------------------------------------ 599 status_t BMessage::Unflatten(const char* flat_buffer) 600 { 601 uint32 size = ((uint32*)flat_buffer)[2]; 602 603 BMemoryIO MemIO(flat_buffer, size); 604 return Unflatten(&MemIO); 605 } 606 //------------------------------------------------------------------------------ 607 status_t BMessage::Unflatten(BDataIO* stream) 608 { 609 bool swap; 610 status_t err = unflatten_hdr(stream, swap); 611 612 if (!err) 613 { 614 TReadHelper reader(stream, swap); 615 int8 flags; 616 type_code type; 617 uint32 count; 618 uint32 dataLen; 619 uint8 nameLen; 620 char name[MSG_NAME_MAX_SIZE]; 621 unsigned char* databuffer = NULL; 622 623 try 624 { 625 reader(flags); 626 while (flags != MSG_LAST_ENTRY) 627 { 628 reader(type); 629 // Is there more than one data item? (!flags & MSG_FLAG_SINGLE_ITEM) 630 if (flags & MSG_FLAG_SINGLE_ITEM) 631 { 632 count = 1; 633 if (flags & MSG_FLAG_MINI_DATA) 634 { 635 uint8 littleLen; 636 reader(littleLen); 637 dataLen = littleLen; 638 } 639 else 640 { 641 reader(dataLen); 642 } 643 } 644 else 645 { 646 // Is there a little data? (flags & MSG_FLAG_MINI_DATA) 647 if (flags & MSG_FLAG_MINI_DATA) 648 { 649 // Get item count (1 byte) 650 uint8 littleCount; 651 reader(littleCount); 652 count = littleCount; 653 654 // Get data length (1 byte) 655 uint8 littleLen; 656 reader(littleLen); 657 dataLen = littleLen; 658 } 659 else 660 { 661 // Is there a lot of data? (!flags & MSG_FLAG_MINI_DATA) 662 // Get item count (4 bytes) 663 reader(count); 664 // Get data length (4 bytes) 665 reader(dataLen); 666 } 667 } 668 669 // Get the name length (1 byte) 670 reader(nameLen); 671 // Get the name (name length bytes) 672 reader(name, nameLen); 673 name[nameLen] = '\0'; 674 675 // Copy the data into a new buffer to byte align it 676 databuffer = (unsigned char*)realloc(databuffer, dataLen); 677 if (!databuffer) 678 throw B_NO_MEMORY; 679 // Get the data 680 reader(databuffer, dataLen); 681 682 // Is the data fixed size? (flags & MSG_FLAG_FIXED_SIZE) 683 if (flags & MSG_FLAG_FIXED_SIZE && swap) 684 { 685 // Make sure to swap the data 686 err = swap_data(type, (void*)databuffer, dataLen, 687 B_SWAP_ALWAYS); 688 if (err) 689 throw err; 690 } 691 // Is the data variable size? (!flags & MSG_FLAG_FIXED_SIZE) 692 else if (swap && type == B_REF_TYPE) 693 { 694 // Apparently, entry_refs are the only variable-length data 695 // explicitely swapped -- the dev_t and ino_t 696 // specifically 697 byte_swap(*(entry_ref*)databuffer); 698 } 699 700 // Add each data field to the message 701 uint32 itemSize; 702 if (flags & MSG_FLAG_FIXED_SIZE) 703 { 704 itemSize = dataLen / count; 705 } 706 unsigned char* dataPtr = databuffer; 707 for (uint32 i = 0; i < count; ++i) 708 { 709 // Line up for the next item 710 if (i) 711 { 712 if (flags & MSG_FLAG_FIXED_SIZE) 713 { 714 dataPtr += itemSize; 715 } 716 else 717 { 718 // Have to account for 8-byte boundary padding 719 dataPtr += itemSize + (8 - (itemSize % 8)); 720 } 721 } 722 723 if ((flags & MSG_FLAG_FIXED_SIZE) == 0) 724 { 725 itemSize = *(uint32*)dataPtr; 726 dataPtr += sizeof (uint32); 727 } 728 729 err = AddData(name, type, dataPtr, itemSize, 730 flags & MSG_FLAG_FIXED_SIZE); 731 if (err) 732 throw err; 733 } 734 735 reader(flags); 736 } 737 } 738 catch (status_t& e) 739 { 740 err = e; 741 } 742 } 743 744 return err; 745 } 746 //------------------------------------------------------------------------------ 747 status_t BMessage::AddSpecifier(const char* property) 748 { 749 BMessage message(B_DIRECT_SPECIFIER); 750 status_t err = message.AddString(B_PROPERTY_ENTRY, property); 751 if (err) 752 return err; 753 754 return AddSpecifier(&message); 755 } 756 //------------------------------------------------------------------------------ 757 status_t BMessage::AddSpecifier(const char* property, int32 index) 758 { 759 BMessage message(B_INDEX_SPECIFIER); 760 status_t err = message.AddString(B_PROPERTY_ENTRY, property); 761 if (err) 762 return err; 763 764 err = message.AddInt32("index", index); 765 if (err) 766 return err; 767 768 return AddSpecifier(&message); 769 } 770 //------------------------------------------------------------------------------ 771 status_t BMessage::AddSpecifier(const char* property, int32 index, int32 range) 772 { 773 if (range < 0) 774 return B_BAD_VALUE; 775 776 BMessage message(B_RANGE_SPECIFIER); 777 status_t err = message.AddString(B_PROPERTY_ENTRY, property); 778 if (err) 779 return err; 780 781 err = message.AddInt32("index", index); 782 if (err) 783 return err; 784 785 err = message.AddInt32("range", range); 786 if (err) 787 return err; 788 789 return AddSpecifier(&message); 790 } 791 //------------------------------------------------------------------------------ 792 status_t BMessage::AddSpecifier(const char* property, const char* name) 793 { 794 BMessage message(B_NAME_SPECIFIER); 795 status_t err = message.AddString(B_PROPERTY_ENTRY, property); 796 if (err) 797 return err; 798 799 err = message.AddString(B_PROPERTY_NAME_ENTRY, name); 800 if (err) 801 return err; 802 803 return AddSpecifier(&message); 804 } 805 //------------------------------------------------------------------------------ 806 status_t BMessage::AddSpecifier(const BMessage* specifier) 807 { 808 status_t err = AddMessage(B_SPECIFIER_ENTRY, specifier); 809 if (!err) 810 { 811 ++fCurSpecifier; 812 fHasSpecifiers = true; 813 } 814 return err; 815 } 816 //------------------------------------------------------------------------------ 817 status_t BMessage::SetCurrentSpecifier(int32 index) 818 { 819 type_code type; 820 int32 count; 821 status_t err = GetInfo(B_SPECIFIER_ENTRY, &type, &count); 822 if (err) 823 return err; 824 825 if (index < 0 || index >= count) 826 return B_BAD_INDEX; 827 828 fCurSpecifier = index; 829 830 return B_OK; 831 } 832 //------------------------------------------------------------------------------ 833 status_t BMessage::GetCurrentSpecifier(int32* index, BMessage* specifier, 834 int32* what, const char** property) const 835 { 836 if (fCurSpecifier == -1 || !WasDelivered()) 837 return B_BAD_SCRIPT_SYNTAX; 838 839 if (index) 840 *index = fCurSpecifier; 841 842 if (specifier) 843 { 844 if (FindMessage(B_SPECIFIER_ENTRY, fCurSpecifier, specifier)) 845 return B_BAD_SCRIPT_SYNTAX; 846 847 if (what) 848 *what = specifier->what; 849 850 if (property) 851 { 852 if (specifier->FindString(B_PROPERTY_ENTRY, property)) 853 return B_BAD_SCRIPT_SYNTAX; 854 } 855 } 856 857 return B_OK; 858 } 859 //------------------------------------------------------------------------------ 860 bool BMessage::HasSpecifiers() const 861 { 862 return fHasSpecifiers; 863 } 864 //------------------------------------------------------------------------------ 865 status_t BMessage::PopSpecifier() 866 { 867 if (fCurSpecifier < 0 || !WasDelivered()) 868 { 869 return B_BAD_VALUE; 870 } 871 872 --fCurSpecifier; 873 return B_OK; 874 } 875 //------------------------------------------------------------------------------ 876 // return fBody->AddData<TYPE>(name, val, TYPESPEC); 877 // return fBody->FindData<TYPE>(name, index, val, TYPESPEC); 878 // return fBody->ReplaceData<TYPE>(name, index, val, TYPESPEC); 879 // return fBody->HasData(name, TYPESPEC, n); 880 881 #define DEFINE_FUNCTIONS(TYPE, fnName, TYPESPEC) \ 882 status_t BMessage::Add ## fnName(const char* name, TYPE val) \ 883 { return fBody->AddData<TYPE>(name, val, TYPESPEC); } \ 884 status_t BMessage::Find ## fnName(const char* name, TYPE* p) const \ 885 { return Find ## fnName(name, 0, p); } \ 886 status_t BMessage::Find ## fnName(const char* name, int32 index, TYPE* p) const \ 887 { \ 888 *p = TYPE(); \ 889 return fBody->FindData<TYPE>(name, index, p, TYPESPEC); \ 890 } \ 891 status_t BMessage::Replace ## fnName(const char* name, TYPE val) \ 892 { return Replace ## fnName(name, 0, val); } \ 893 status_t BMessage::Replace ## fnName(const char *name, int32 index, TYPE val) \ 894 { return fBody->ReplaceData<TYPE>(name, index, val, TYPESPEC); } \ 895 bool BMessage::Has ## fnName(const char* name, int32 n) const \ 896 { return fBody->HasData(name, TYPESPEC, n); } 897 898 DEFINE_FUNCTIONS(int8 , Int8 , B_INT8_TYPE) 899 DEFINE_FUNCTIONS(int16 , Int16 , B_INT16_TYPE) 900 DEFINE_FUNCTIONS(int32 , Int32 , B_INT32_TYPE) 901 DEFINE_FUNCTIONS(int64 , Int64 , B_INT64_TYPE) 902 DEFINE_FUNCTIONS(BPoint, Point , B_POINT_TYPE) 903 DEFINE_FUNCTIONS(BRect , Rect , B_RECT_TYPE) 904 DEFINE_FUNCTIONS(float , Float , B_FLOAT_TYPE) 905 DEFINE_FUNCTIONS(double, Double, B_DOUBLE_TYPE) 906 DEFINE_FUNCTIONS(bool , Bool , B_BOOL_TYPE) 907 908 #undef DEFINE_FUNCTIONS 909 910 911 #define DEFINE_HAS_FUNCTION(fnName, TYPESPEC) \ 912 bool BMessage::Has ## fnName(const char* name, int32 n) const \ 913 { return HasData(name, TYPESPEC, n); } 914 915 DEFINE_HAS_FUNCTION(Message , B_MESSAGE_TYPE) 916 DEFINE_HAS_FUNCTION(String , B_STRING_TYPE) 917 DEFINE_HAS_FUNCTION(Pointer , B_POINTER_TYPE) 918 DEFINE_HAS_FUNCTION(Messenger, B_MESSENGER_TYPE) 919 DEFINE_HAS_FUNCTION(Ref , B_REF_TYPE) 920 921 #undef DEFINE_HAS_FUNCTION 922 923 #define DEFINE_LAZY_FIND_FUNCTION(TYPE, fnName) \ 924 TYPE BMessage::Find ## fnName(const char* name, int32 n) const \ 925 { \ 926 TYPE i = 0; \ 927 Find ## fnName(name, n, &i); \ 928 return i; \ 929 } 930 931 DEFINE_LAZY_FIND_FUNCTION(int8 , Int8) 932 DEFINE_LAZY_FIND_FUNCTION(int16 , Int16) 933 DEFINE_LAZY_FIND_FUNCTION(int32 , Int32) 934 DEFINE_LAZY_FIND_FUNCTION(int64 , Int64) 935 DEFINE_LAZY_FIND_FUNCTION(float , Float) 936 DEFINE_LAZY_FIND_FUNCTION(double , Double) 937 DEFINE_LAZY_FIND_FUNCTION(bool , Bool) 938 DEFINE_LAZY_FIND_FUNCTION(const char* , String) 939 940 #undef DEFINE_LAZY_FIND_FUNCTION 941 942 //------------------------------------------------------------------------------ 943 status_t BMessage::AddString(const char* name, const char* a_string) 944 { 945 return fBody->AddData<BString>(name, a_string, B_STRING_TYPE); 946 } 947 //------------------------------------------------------------------------------ 948 status_t BMessage::AddString(const char* name, const BString& a_string) 949 { 950 return AddString(name, a_string.String()); 951 } 952 //------------------------------------------------------------------------------ 953 status_t BMessage::AddPointer(const char* name, const void* ptr) 954 { 955 return fBody->AddData<void*>(name, (void*)ptr, B_POINTER_TYPE); 956 } 957 //------------------------------------------------------------------------------ 958 status_t BMessage::AddMessenger(const char* name, BMessenger messenger) 959 { 960 return fBody->AddData<BMessenger>(name, messenger, B_MESSENGER_TYPE); 961 } 962 //------------------------------------------------------------------------------ 963 status_t BMessage::AddRef(const char* name, const entry_ref* ref) 964 { 965 char* buffer = new(nothrow) char[sizeof (entry_ref) + B_PATH_NAME_LENGTH]; 966 size_t size; 967 status_t err = entry_ref_flatten(buffer, &size, ref); 968 if (!err) 969 { 970 BDataBuffer DB((void*)buffer, size); 971 err = fBody->AddData<BDataBuffer>(name, DB, B_REF_TYPE); 972 } 973 974 return err; 975 } 976 //------------------------------------------------------------------------------ 977 status_t BMessage::AddMessage(const char* name, const BMessage* msg) 978 { 979 status_t err = B_OK; 980 ssize_t size = msg->FlattenedSize(); 981 char* buffer = new(nothrow) char[size]; 982 if (buffer) 983 { 984 err = msg->Flatten(buffer, size); 985 if (!err) 986 { 987 BDataBuffer DB((void*)buffer, size); 988 err = fBody->AddData<BDataBuffer>(name, DB, B_MESSAGE_TYPE); 989 } 990 } 991 else 992 { 993 err = B_NO_MEMORY; 994 } 995 996 return err; 997 } 998 //------------------------------------------------------------------------------ 999 status_t BMessage::AddFlat(const char* name, BFlattenable* obj, int32 count) 1000 { 1001 status_t err = B_OK; 1002 ssize_t size = obj->FlattenedSize(); 1003 char* buffer = new(nothrow) char[size]; 1004 if (buffer) 1005 { 1006 err = obj->Flatten((void*)buffer, size); 1007 if (!err) 1008 { 1009 err = AddData(name, obj->TypeCode(), (void*)buffer, size, 1010 obj->IsFixedSize(), count); 1011 } 1012 delete[] buffer; 1013 } 1014 else 1015 { 1016 err = B_NO_MEMORY; 1017 } 1018 1019 return err; 1020 } 1021 //------------------------------------------------------------------------------ 1022 status_t BMessage::AddData(const char* name, type_code type, const void* data, 1023 ssize_t numBytes, bool is_fixed_size, int32 /*count*/) 1024 { 1025 /** 1026 @note Because we're using vectors for our item storage, the count param 1027 is no longer useful to us: dynamically adding more items is not 1028 really a performance issue, so pre-allocating space for objects 1029 gives us no real advantage. 1030 */ 1031 1032 // TODO: test 1033 // In particular, we want to see what happens if is_fixed_size == true and 1034 // the user attempts to add something bigger or smaller. We may need to 1035 // enforce the size thing. 1036 //-------------------------------------------------------------------------- 1037 // voidref suggests creating a BDataBuffer type which we can use here to 1038 // avoid having to specialize BMessageBody::AddData(). 1039 //-------------------------------------------------------------------------- 1040 1041 // TODO: Fix this horrible hack 1042 status_t err = B_OK; 1043 switch (type) 1044 { 1045 case B_BOOL_TYPE: 1046 err = AddBool(name, *(bool*)data); 1047 break; 1048 case B_INT8_TYPE: 1049 case B_UINT8_TYPE: 1050 err = AddInt8(name, *(int8*)data); 1051 break; 1052 case B_INT16_TYPE: 1053 case B_UINT16_TYPE: 1054 err = AddInt16(name, *(int16*)data); 1055 break; 1056 case B_INT32_TYPE: 1057 case B_UINT32_TYPE: 1058 err = AddInt32(name, *(int32*)data); 1059 break; 1060 case B_INT64_TYPE: 1061 case B_UINT64_TYPE: 1062 err = AddInt64(name, *(int64*)data); 1063 break; 1064 case B_FLOAT_TYPE: 1065 err = AddFloat(name, *(float*)data); 1066 break; 1067 case B_DOUBLE_TYPE: 1068 err = AddDouble(name, *(double*)data); 1069 break; 1070 case B_POINT_TYPE: 1071 err = AddPoint(name, *(BPoint*)data); 1072 break; 1073 case B_RECT_TYPE: 1074 err = AddRect(name, *(BRect*)data); 1075 break; 1076 case B_REF_TYPE: 1077 { 1078 BDataBuffer DB((void*)data, numBytes, true); 1079 err = fBody->AddData<BDataBuffer>(name, DB, type); 1080 break; 1081 } 1082 case B_MESSAGE_TYPE: 1083 { 1084 BDataBuffer DB((void*)data, numBytes, true); 1085 err = fBody->AddData<BDataBuffer>(name, DB, type); 1086 break; 1087 } 1088 case B_MESSENGER_TYPE: 1089 err = AddMessenger(name, *(BMessenger*)data); 1090 break; 1091 case B_POINTER_TYPE: 1092 err = AddPointer(name, *(void**)data); 1093 break; 1094 case B_STRING_TYPE: 1095 err = AddString(name, (const char*)data); 1096 break; 1097 default: 1098 // TODO: test 1099 // Using the mythical BDataBuffer 1100 BDataBuffer DB((void*)data, numBytes, true); 1101 err = fBody->AddData<BDataBuffer>(name, DB, type); 1102 break; 1103 } 1104 1105 return err; 1106 } 1107 //------------------------------------------------------------------------------ 1108 status_t BMessage::RemoveData(const char* name, int32 index) 1109 { 1110 return fReadOnly ? B_ERROR : fBody->RemoveData(name, index); 1111 } 1112 //------------------------------------------------------------------------------ 1113 status_t BMessage::RemoveName(const char* name) 1114 { 1115 return fReadOnly ? B_ERROR : fBody->RemoveName(name); 1116 } 1117 //------------------------------------------------------------------------------ 1118 status_t BMessage::MakeEmpty() 1119 { 1120 return fReadOnly ? B_ERROR : fBody->MakeEmpty(); 1121 } 1122 //------------------------------------------------------------------------------ 1123 status_t BMessage::FindString(const char* name, const char** str) const 1124 { 1125 return FindString(name, 0, str); 1126 } 1127 //------------------------------------------------------------------------------ 1128 status_t BMessage::FindString(const char* name, int32 index, 1129 const char** str) const 1130 { 1131 ssize_t bytes; 1132 return FindData(name, B_STRING_TYPE, index, 1133 (const void**)str, &bytes); 1134 } 1135 //------------------------------------------------------------------------------ 1136 status_t BMessage::FindString(const char* name, BString* str) const 1137 { 1138 return FindString(name, 0, str); 1139 } 1140 //------------------------------------------------------------------------------ 1141 status_t BMessage::FindString(const char* name, int32 index, BString* str) const 1142 { 1143 const char* cstr; 1144 status_t err = FindString(name, index, &cstr); 1145 if (!err) 1146 { 1147 *str = cstr; 1148 } 1149 1150 return err; 1151 } 1152 //------------------------------------------------------------------------------ 1153 status_t BMessage::FindPointer(const char* name, void** ptr) const 1154 { 1155 return FindPointer(name, 0, ptr); 1156 } 1157 //------------------------------------------------------------------------------ 1158 status_t BMessage::FindPointer(const char* name, int32 index, void** ptr) const 1159 { 1160 *ptr = NULL; 1161 return fBody->FindData<void*>(name, index, ptr, B_POINTER_TYPE); 1162 } 1163 //------------------------------------------------------------------------------ 1164 status_t BMessage::FindMessenger(const char* name, BMessenger* m) const 1165 { 1166 return FindMessenger(name, 0, m); 1167 } 1168 //------------------------------------------------------------------------------ 1169 status_t BMessage::FindMessenger(const char* name, int32 index, BMessenger* m) const 1170 { 1171 return fBody->FindData<BMessenger>(name, index, m, B_MESSENGER_TYPE); 1172 } 1173 //------------------------------------------------------------------------------ 1174 status_t BMessage::FindRef(const char* name, entry_ref* ref) const 1175 { 1176 return FindRef(name, 0, ref); 1177 } 1178 //------------------------------------------------------------------------------ 1179 status_t BMessage::FindRef(const char* name, int32 index, entry_ref* ref) const 1180 { 1181 void* data = NULL; 1182 ssize_t size = 0; 1183 status_t err = FindData(name, B_REF_TYPE, index, (const void**)&data, &size); 1184 if (!err) 1185 { 1186 err = entry_ref_unflatten(ref, (char*)data, size); 1187 } 1188 1189 return err; 1190 } 1191 //------------------------------------------------------------------------------ 1192 status_t BMessage::FindMessage(const char* name, BMessage* msg) const 1193 { 1194 return FindMessage(name, 0, msg); 1195 } 1196 //------------------------------------------------------------------------------ 1197 status_t BMessage::FindMessage(const char* name, int32 index, BMessage* msg) const 1198 { 1199 void* data = NULL; 1200 ssize_t size = 0; 1201 status_t err = FindData(name, B_MESSAGE_TYPE, index, 1202 (const void**)&data, &size); 1203 if (!err) 1204 { 1205 err = msg->Unflatten((const char*)data); 1206 } 1207 1208 return err; 1209 } 1210 //------------------------------------------------------------------------------ 1211 status_t BMessage::FindFlat(const char* name, BFlattenable* obj) const 1212 { 1213 return FindFlat(name, 0, obj); 1214 } 1215 //------------------------------------------------------------------------------ 1216 status_t BMessage::FindFlat(const char* name, int32 index, 1217 BFlattenable* obj) const 1218 { 1219 const void* data; 1220 ssize_t numBytes; 1221 status_t err = FindData(name, obj->TypeCode(), index, &data, &numBytes); 1222 if (!err) 1223 { 1224 err = obj->Unflatten(obj->TypeCode(), data, numBytes); 1225 } 1226 1227 return err; 1228 } 1229 //------------------------------------------------------------------------------ 1230 status_t BMessage::FindData(const char* name, type_code type, const void** data, 1231 ssize_t* numBytes) const 1232 { 1233 return FindData(name, type, 0, data, numBytes); 1234 } 1235 //------------------------------------------------------------------------------ 1236 status_t BMessage::FindData(const char* name, type_code type, int32 index, 1237 const void** data, ssize_t* numBytes) const 1238 { 1239 status_t err = B_OK; 1240 // Oh, the humanity! 1241 err = fBody->FindData(name, type, index, data, numBytes); 1242 1243 return err; 1244 } 1245 //------------------------------------------------------------------------------ 1246 status_t BMessage::ReplaceString(const char* name, const char* string) 1247 { 1248 return ReplaceString(name, 0, string); 1249 } 1250 //------------------------------------------------------------------------------ 1251 status_t BMessage::ReplaceString(const char* name, int32 index, 1252 const char* string) 1253 { 1254 return fBody->ReplaceData<BString>(name, index, string, B_STRING_TYPE); 1255 } 1256 //------------------------------------------------------------------------------ 1257 status_t BMessage::ReplaceString(const char* name, const BString& string) 1258 { 1259 return ReplaceString(name, 0, string); 1260 } 1261 //------------------------------------------------------------------------------ 1262 status_t BMessage::ReplaceString(const char* name, int32 index, const BString& string) 1263 { 1264 return fBody->ReplaceData<BString>(name, index, string, B_STRING_TYPE); 1265 } 1266 //------------------------------------------------------------------------------ 1267 status_t BMessage::ReplacePointer(const char* name, const void* ptr) 1268 { 1269 return ReplacePointer(name, 0, ptr); 1270 } 1271 //------------------------------------------------------------------------------ 1272 status_t BMessage::ReplacePointer(const char* name, int32 index, 1273 const void* ptr) 1274 { 1275 return fBody->ReplaceData<void*>(name, index, (void*)ptr, B_POINTER_TYPE); 1276 } 1277 //------------------------------------------------------------------------------ 1278 status_t BMessage::ReplaceMessenger(const char* name, BMessenger messenger) 1279 { 1280 // Don't want to copy the BMessenger 1281 return fBody->ReplaceData<BMessenger>(name, 0, messenger, B_MESSENGER_TYPE); 1282 } 1283 //------------------------------------------------------------------------------ 1284 status_t BMessage::ReplaceMessenger(const char* name, int32 index, 1285 BMessenger msngr) 1286 { 1287 return fBody->ReplaceData<BMessenger>(name, index, msngr, B_MESSENGER_TYPE); 1288 } 1289 //------------------------------------------------------------------------------ 1290 status_t BMessage::ReplaceRef(const char* name, const entry_ref* ref) 1291 { 1292 return ReplaceRef(name, 0, ref); 1293 } 1294 //------------------------------------------------------------------------------ 1295 status_t BMessage::ReplaceRef(const char* name, int32 index, const entry_ref* ref) 1296 { 1297 // TODO: test 1298 // Use voidref's theoretical BDataBuffer 1299 char* buffer = new(nothrow) char[sizeof (entry_ref) + B_PATH_NAME_LENGTH]; 1300 size_t size; 1301 status_t err = entry_ref_flatten(buffer, &size, ref); 1302 if (!err) 1303 { 1304 BDataBuffer DB((void*)buffer, size); 1305 err = fBody->ReplaceData<BDataBuffer>(name, index, DB, B_REF_TYPE); 1306 } 1307 1308 return err; 1309 } 1310 //------------------------------------------------------------------------------ 1311 status_t BMessage::ReplaceMessage(const char* name, const BMessage* msg) 1312 { 1313 return ReplaceMessage(name, 0, msg); 1314 } 1315 //------------------------------------------------------------------------------ 1316 status_t BMessage::ReplaceMessage(const char* name, int32 index, 1317 const BMessage* msg) 1318 { 1319 status_t err = B_OK; 1320 ssize_t size = msg->FlattenedSize(); 1321 char* buffer = new(nothrow) char[size]; 1322 if (buffer) 1323 { 1324 err = msg->Flatten(buffer, size); 1325 if (!err) 1326 { 1327 BDataBuffer DB((void*)buffer, size); 1328 err = fBody->ReplaceData<BDataBuffer>(name, index, DB, 1329 B_MESSAGE_TYPE); 1330 } 1331 } 1332 else 1333 { 1334 err = B_NO_MEMORY; 1335 } 1336 1337 return err; 1338 } 1339 //------------------------------------------------------------------------------ 1340 status_t BMessage::ReplaceFlat(const char* name, BFlattenable* obj) 1341 { 1342 return ReplaceFlat(name, 0, obj); 1343 } 1344 //------------------------------------------------------------------------------ 1345 status_t BMessage::ReplaceFlat(const char* name, int32 index, BFlattenable* obj) 1346 { 1347 // TODO: test 1348 status_t err = B_OK; 1349 ssize_t size = obj->FlattenedSize(); 1350 char* buffer = new(nothrow) char[size]; 1351 if (buffer) 1352 { 1353 err = obj->Flatten(buffer, size); 1354 if (!err) 1355 { 1356 err = ReplaceData(name, obj->TypeCode(), index, (void*)buffer, size); 1357 } 1358 delete[] buffer; 1359 } 1360 1361 return err; 1362 } 1363 //------------------------------------------------------------------------------ 1364 status_t BMessage::ReplaceData(const char* name, type_code type, 1365 const void* data, ssize_t data_size) 1366 { 1367 return ReplaceData(name, type, 0, data, data_size); 1368 } 1369 //------------------------------------------------------------------------------ 1370 status_t BMessage::ReplaceData(const char* name, type_code type, int32 index, 1371 const void* data, ssize_t data_size) 1372 { 1373 // TODO: Fix this horrible hack 1374 status_t err = B_OK; 1375 switch (type) 1376 { 1377 case B_BOOL_TYPE: 1378 err = ReplaceBool(name, index, *(bool*)data); 1379 break; 1380 case B_INT8_TYPE: 1381 case B_UINT8_TYPE: 1382 err = ReplaceInt8(name, index, *(int8*)data); 1383 break; 1384 case B_INT16_TYPE: 1385 case B_UINT16_TYPE: 1386 err = ReplaceInt16(name, index, *(int16*)data); 1387 break; 1388 case B_INT32_TYPE: 1389 case B_UINT32_TYPE: 1390 err = ReplaceInt32(name, index, *(int32*)data); 1391 break; 1392 case B_INT64_TYPE: 1393 case B_UINT64_TYPE: 1394 err = ReplaceInt64(name, index, *(int64*)data); 1395 break; 1396 case B_FLOAT_TYPE: 1397 err = ReplaceFloat(name, index, *(float*)data); 1398 break; 1399 case B_DOUBLE_TYPE: 1400 err = ReplaceDouble(name, index, *(double*)data); 1401 break; 1402 case B_POINT_TYPE: 1403 err = ReplacePoint(name, index, *(BPoint*)data); 1404 break; 1405 case B_RECT_TYPE: 1406 err = ReplaceRect(name, index, *(BRect*)data); 1407 break; 1408 case B_REF_TYPE: 1409 err = ReplaceRef(name, index, (entry_ref*)data); 1410 break; 1411 case B_MESSAGE_TYPE: 1412 err = ReplaceMessage(name, index, (BMessage*)data); 1413 break; 1414 case B_MESSENGER_TYPE: 1415 err = ReplaceMessenger(name, index, *(BMessenger*)data); 1416 break; 1417 case B_POINTER_TYPE: 1418 err = ReplacePointer(name, index, (void**)data); 1419 break; 1420 default: 1421 // TODO: test 1422 // Using the mythical BDataBuffer 1423 BDataBuffer DB((void*)data, data_size, true); 1424 err = fBody->ReplaceData<BDataBuffer>(name, index, DB, type); 1425 break; 1426 } 1427 1428 return err; 1429 } 1430 //------------------------------------------------------------------------------ 1431 void* BMessage::operator new(size_t size) 1432 { 1433 if (!sMsgCache) 1434 { 1435 sMsgCache = new BBlockCache(10, size, B_OBJECT_CACHE); 1436 } 1437 return sMsgCache->Get(size); 1438 } 1439 //------------------------------------------------------------------------------ 1440 void* BMessage::operator new(size_t, void* p) 1441 { 1442 return p; 1443 } 1444 //------------------------------------------------------------------------------ 1445 void BMessage::operator delete(void* ptr, size_t size) 1446 { 1447 sMsgCache->Save(ptr, size); 1448 } 1449 //------------------------------------------------------------------------------ 1450 bool BMessage::HasFlat(const char* name, const BFlattenable* flat) const 1451 { 1452 return HasFlat(name, 0, flat); 1453 } 1454 //------------------------------------------------------------------------------ 1455 bool BMessage::HasFlat(const char* name, int32 n, const BFlattenable* flat) const 1456 { 1457 return fBody->HasData(name, flat->TypeCode(), n); 1458 } 1459 //------------------------------------------------------------------------------ 1460 bool BMessage::HasData(const char* name, type_code t, int32 n) const 1461 { 1462 return fBody->HasData(name, t, n); 1463 } 1464 //------------------------------------------------------------------------------ 1465 BRect BMessage::FindRect(const char* name, int32 n) const 1466 { 1467 BRect r(0, 0, -1, -1); 1468 FindRect(name, n, &r); 1469 return r; 1470 } 1471 //------------------------------------------------------------------------------ 1472 BPoint BMessage::FindPoint(const char* name, int32 n) const 1473 { 1474 BPoint p(0, 0); 1475 FindPoint(name, n, &p); 1476 return p; 1477 } 1478 //------------------------------------------------------------------------------ 1479 status_t BMessage::flatten_hdr(BDataIO* stream) const 1480 { 1481 status_t err = B_OK; 1482 int32 data = MSG_FIELD_VERSION; 1483 1484 write_helper(stream, (const void*)&data, sizeof (data), err); 1485 if (!err) 1486 { 1487 // faked up checksum; we'll fix it up later 1488 write_helper(stream, (const void*)&data, sizeof (data), err); 1489 } 1490 if (!err) 1491 { 1492 data = fBody->FlattenedSize() + calc_hdr_size(0); 1493 write_helper(stream, (const void*)&data, sizeof (data), err); 1494 } 1495 if (!err) 1496 { 1497 write_helper(stream, (const void*)&what, sizeof (what), err); 1498 } 1499 1500 uint8 flags = 0; 1501 #ifdef B_HOST_IS_BENDIAN 1502 flags |= MSG_FLAG_BIG_ENDIAN; 1503 #endif 1504 if (HasSpecifiers()) 1505 { 1506 flags |= MSG_FLAG_SCRIPT_MSG; 1507 } 1508 1509 if (fTarget != B_NULL_TOKEN) 1510 { 1511 flags |= MSG_FLAG_INCL_TARGET; 1512 } 1513 1514 if (fReplyTo.port >= 0 && 1515 fReplyTo.target != B_NULL_TOKEN && 1516 fReplyTo.team >= 0) 1517 { 1518 flags |= MSG_FLAG_INCL_REPLY; 1519 } 1520 1521 write_helper(stream, (const void*)&flags, sizeof (flags), err); 1522 1523 // Write targeting and reply info if necessary 1524 if (!err && (flags & MSG_FLAG_INCL_TARGET)) 1525 { 1526 data = fPreferred ? B_PREFERRED_TOKEN : fTarget; 1527 write_helper(stream, (const void*)&data, sizeof (data), err); 1528 } 1529 1530 if (!err && (flags & MSG_FLAG_INCL_REPLY)) 1531 { 1532 write_helper(stream, (const void*)&fReplyTo.port, 1533 sizeof (fReplyTo.port), err); 1534 if (!err) 1535 { 1536 write_helper(stream, (const void*)&fReplyTo.target, 1537 sizeof (fReplyTo.target), err); 1538 } 1539 if (!err) 1540 { 1541 write_helper(stream, (const void*)&fReplyTo.team, 1542 sizeof (fReplyTo.team), err); 1543 } 1544 1545 uint8 bigFlags; 1546 if (!err) 1547 { 1548 bigFlags = fPreferred ? 1 : 0; 1549 write_helper(stream, (const void*)&bigFlags, 1550 sizeof (bigFlags), err); 1551 } 1552 if (!err) 1553 { 1554 bigFlags = fReplyRequired ? 1 : 0; 1555 write_helper(stream, (const void*)&bigFlags, 1556 sizeof (bigFlags), err); 1557 } 1558 if (!err) 1559 { 1560 bigFlags = fReplyDone ? 1 : 0; 1561 write_helper(stream, (const void*)&bigFlags, 1562 sizeof (bigFlags), err); 1563 } 1564 if (!err) 1565 { 1566 bigFlags = fIsReply ? 1 : 0; 1567 write_helper(stream, (const void*)&bigFlags, 1568 sizeof (bigFlags), err); 1569 } 1570 } 1571 1572 return err; 1573 } 1574 //------------------------------------------------------------------------------ 1575 status_t BMessage::unflatten_hdr(BDataIO* stream, bool& swap) 1576 { 1577 status_t err = B_OK; 1578 int32 data; 1579 int32 checksum; 1580 uchar csBuffer[MSG_HEADER_MAX_SIZE]; 1581 1582 TReadHelper read_helper(stream); 1583 TChecksumHelper checksum_helper(csBuffer); 1584 1585 try { 1586 1587 // Get the message version 1588 read_helper(data); 1589 if (data == '1BOF') 1590 { 1591 swap = true; 1592 } 1593 else if (data == 'FOB1') 1594 { 1595 swap = false; 1596 } 1597 else 1598 { 1599 // This is *not* a message 1600 return B_NOT_A_MESSAGE; 1601 } 1602 1603 // Make way for the new data 1604 MakeEmpty(); 1605 1606 read_helper.SetSwap(swap); 1607 1608 // get the checksum 1609 read_helper(checksum); 1610 // get the size 1611 read_helper(data); 1612 checksum_helper.Cache(data); 1613 // Get the what 1614 read_helper(what); 1615 checksum_helper.Cache(what); 1616 // Get the flags 1617 uint8 flags = 0; 1618 read_helper(flags); 1619 checksum_helper.Cache(flags); 1620 1621 fHasSpecifiers = flags & MSG_FLAG_SCRIPT_MSG; 1622 1623 if (flags & MSG_FLAG_BIG_ENDIAN) 1624 { 1625 // TODO: ??? 1626 // Isn't this already indicated by the byte order of the message version? 1627 } 1628 if (flags & MSG_FLAG_INCL_TARGET) 1629 { 1630 // Get the target data 1631 read_helper(data); 1632 checksum_helper.Cache(data); 1633 fTarget = data; 1634 } 1635 if (flags & MSG_FLAG_INCL_REPLY) 1636 { 1637 // Get the reply port 1638 read_helper(fReplyTo.port); 1639 read_helper(fReplyTo.target); 1640 read_helper(fReplyTo.team); 1641 checksum_helper.Cache(fReplyTo.port); 1642 checksum_helper.Cache(fReplyTo.target); 1643 checksum_helper.Cache(fReplyTo.team); 1644 1645 // Get the "big flags" 1646 uint8 bigFlags; 1647 // Get the preferred flag 1648 read_helper(bigFlags); 1649 checksum_helper.Cache(bigFlags); 1650 fPreferred = bigFlags; 1651 if (fPreferred) 1652 { 1653 fTarget = B_PREFERRED_TOKEN; 1654 } 1655 // Get the reply requirement flag 1656 read_helper(bigFlags); 1657 checksum_helper.Cache(bigFlags); 1658 fReplyRequired = bigFlags; 1659 // Get the reply done flag 1660 read_helper(bigFlags); 1661 checksum_helper.Cache(bigFlags); 1662 fReplyDone = bigFlags; 1663 // Get the "is reply" flag 1664 read_helper(bigFlags); 1665 checksum_helper.Cache(bigFlags); 1666 fIsReply = bigFlags; 1667 } 1668 } 1669 catch (status_t& e) 1670 { 1671 err = e; 1672 } 1673 1674 if (checksum != checksum_helper.CheckSum()) 1675 err = B_NOT_A_MESSAGE; 1676 1677 return err; 1678 } 1679 //------------------------------------------------------------------------------ 1680 status_t BMessage::real_flatten(char* result, ssize_t size) const 1681 { 1682 BMemoryIO stream((void*)result, size); 1683 status_t err = real_flatten(&stream); 1684 1685 if (!err) 1686 { 1687 // Fixup the checksum; it is calculated on data size, what, flags, 1688 // and target info (including big flags if appropriate) 1689 ((uint32*)result)[1] = _checksum_((uchar*)result + (sizeof (uint32) * 2), 1690 calc_hdr_size(0) - (sizeof (uint32) * 2)); 1691 } 1692 1693 return err; 1694 } 1695 //------------------------------------------------------------------------------ 1696 status_t BMessage::real_flatten(BDataIO* stream) const 1697 { 1698 status_t err = flatten_hdr(stream); 1699 1700 if (!err) 1701 { 1702 err = fBody->Flatten(stream); 1703 } 1704 1705 return err; 1706 } 1707 //------------------------------------------------------------------------------ 1708 char* BMessage::stack_flatten(char* stack_ptr, ssize_t stack_size, 1709 bool /*incl_reply*/, ssize_t* size) const 1710 { 1711 const ssize_t calcd_size = calc_hdr_size(0) + fBody->FlattenedSize(); 1712 char* new_ptr = NULL; 1713 if (calcd_size > stack_size) 1714 { 1715 stack_ptr = new char[calcd_size]; 1716 new_ptr = stack_ptr; 1717 } 1718 real_flatten(stack_ptr, calcd_size); 1719 if (size) 1720 { 1721 *size = calcd_size; 1722 } 1723 return new_ptr; 1724 } 1725 //------------------------------------------------------------------------------ 1726 ssize_t BMessage::calc_hdr_size(uchar flags) const 1727 { 1728 ssize_t size = min_hdr_size(); 1729 1730 if (fTarget != B_NULL_TOKEN) 1731 { 1732 size += sizeof (fTarget); 1733 } 1734 1735 if (fReplyTo.port >= 0 && 1736 fReplyTo.target != B_NULL_TOKEN && 1737 fReplyTo.team >= 0) 1738 { 1739 size += sizeof (fReplyTo.port); 1740 size += sizeof (fReplyTo.target); 1741 size += sizeof (fReplyTo.team); 1742 1743 size += 4; // For the "big" flags 1744 } 1745 1746 return size; 1747 } 1748 //------------------------------------------------------------------------------ 1749 ssize_t BMessage::min_hdr_size() const 1750 { 1751 ssize_t size = 0; 1752 1753 size += 4; // version 1754 size += 4; // checksum 1755 size += 4; // flattened size 1756 size += 4; // 'what' 1757 size += 1; // flags 1758 1759 return size; 1760 } 1761 //------------------------------------------------------------------------------ 1762 status_t BMessage::_send_(port_id port, int32 token, bool preferred, 1763 bigtime_t timeout, bool reply_required, 1764 BMessenger& reply_to) const 1765 { 1766 BMessage tmp_msg; 1767 tmp_msg.fPreferred = fPreferred; 1768 tmp_msg.fTarget = fTarget; 1769 tmp_msg.fReplyRequired = fReplyRequired; 1770 tmp_msg.fReplyTo = fReplyTo; 1771 1772 BMessage* self = const_cast<BMessage*>(this); 1773 self->fPreferred = preferred; 1774 self->fTarget = token; 1775 self->fReplyRequired = reply_required; 1776 self->fReplyTo.team = reply_to.fTeam; 1777 self->fReplyTo.port = reply_to.fPort; 1778 self->fReplyTo.target = reply_to.fHandlerToken; 1779 self->fReplyTo.preferred = reply_to.fPreferredTarget; 1780 1781 char tmp[0x800]; 1782 ssize_t size; 1783 char* p = stack_flatten(tmp, sizeof(tmp), true /* include reply */, &size); 1784 char* pMem = p ? p : tmp; 1785 status_t err; 1786 do 1787 { 1788 err = write_port_etc(port, 'pjpp', pMem, size, B_RELATIVE_TIMEOUT, timeout); 1789 } while (err == B_INTERRUPTED); 1790 if (p) 1791 { 1792 delete[] p; 1793 } 1794 self->fPreferred = tmp_msg.fPreferred; 1795 self->fTarget = tmp_msg.fTarget; 1796 self->fReplyRequired = tmp_msg.fReplyRequired; 1797 self->fReplyTo = tmp_msg.fReplyTo; 1798 tmp_msg.init_data(); 1799 return err; 1800 } 1801 //------------------------------------------------------------------------------ 1802 status_t BMessage::send_message(port_id port, team_id port_owner, int32 token, 1803 bool preferred, BMessage* reply, 1804 bigtime_t send_timeout, 1805 bigtime_t reply_timeout) const 1806 { 1807 const int32 cached_reply_port = sGetCachedReplyPort(); 1808 port_id reply_port; 1809 status_t err; 1810 if (cached_reply_port == -1) 1811 { 1812 // All the cached reply ports are in use; create a new one 1813 reply_port = create_port(1 /* for one message */, "tmp_reply_port"); 1814 if (reply_port < 0) 1815 { 1816 return reply_port; 1817 } 1818 } 1819 else 1820 { 1821 assert(cached_reply_port < sNumReplyPorts); 1822 reply_port = sReplyPorts[cached_reply_port]; 1823 } 1824 team_id team; 1825 if (be_app) 1826 { 1827 team = be_app->Team(); 1828 } 1829 else 1830 { 1831 port_info pi; 1832 err = get_port_info(reply_port, &pi); 1833 if (err) 1834 { 1835 goto error; 1836 } 1837 team = pi.team; 1838 } 1839 err = set_port_owner(reply_port, port_owner); 1840 if (err) 1841 { 1842 goto error; 1843 } 1844 1845 { 1846 BMessenger messenger(team, reply_port, B_PREFERRED_TOKEN, false); 1847 err = _send_(port, token, preferred, send_timeout, true, messenger); 1848 } 1849 if (err) 1850 { 1851 goto error; 1852 } 1853 int32 code; 1854 err = handle_reply(reply_port, &code, reply_timeout, reply); 1855 if (err && cached_reply_port >= 0) 1856 { 1857 delete_port(reply_port); 1858 sReplyPorts[cached_reply_port] = create_port(1, "tmp_rport"); 1859 } 1860 1861 error: 1862 if (cached_reply_port >= 0) 1863 { 1864 // Reclaim ownership of cached port 1865 set_port_owner(reply_port, team); 1866 // Flag as available 1867 atomic_add(&sReplyPortInUse[cached_reply_port], -1); 1868 return err; 1869 } 1870 delete_port(reply_port); 1871 return err; 1872 } 1873 //------------------------------------------------------------------------------ 1874 int32 BMessage::sGetCachedReplyPort() 1875 { 1876 int index = -1; 1877 for (int32 i = 0; i < sNumReplyPorts; i++) 1878 { 1879 int32 old = atomic_add(&(sReplyPortInUse[i]), 1); 1880 if (old == 0) 1881 { 1882 // This entry is free 1883 index = i; 1884 break; 1885 } 1886 else 1887 { 1888 // This entry is being used. 1889 atomic_add(&(sReplyPortInUse[i]), -1); 1890 } 1891 } 1892 1893 return index; 1894 } 1895 //------------------------------------------------------------------------------ 1896 static status_t handle_reply(port_id reply_port, 1897 int32* pCode, 1898 bigtime_t timeout, 1899 BMessage* reply) 1900 { 1901 status_t err; 1902 do 1903 { 1904 err = port_buffer_size_etc(reply_port, 8, timeout); 1905 } while (err == B_INTERRUPTED); 1906 if (err < 0) 1907 { 1908 return err; 1909 } 1910 // The API lied. It really isn't an error code, but the message size... 1911 char* pAllocd = NULL; 1912 char* pMem = NULL; 1913 char tmp[0x800]; 1914 if (err < 0x800) 1915 { 1916 pMem = tmp; 1917 } 1918 else 1919 { 1920 pAllocd = new char[0x800]; 1921 pMem = pAllocd; 1922 } 1923 do 1924 { 1925 err = read_port(reply_port, pCode, pMem, err); 1926 } while (err == B_INTERRUPTED); 1927 1928 if (err < 0) 1929 { 1930 return err; 1931 } 1932 1933 if (*pCode == 'PUSH') 1934 { 1935 return B_ERROR; 1936 } 1937 if (*pCode != 'pjpp') 1938 { 1939 return B_OK; 1940 } 1941 1942 err = reply->Unflatten(pMem); 1943 1944 // There seems to be a bug in the original Be implementation. 1945 // It never free'd pAllocd ! 1946 if (pAllocd) 1947 { 1948 delete[] pAllocd; 1949 } 1950 return err; 1951 } 1952 //------------------------------------------------------------------------------ 1953 1954 #else // USING_TEMPLATE_MADNESS 1955 1956 //------------------------------------------------------------------------------ 1957 BMessage::BMessage(uint32 command) 1958 { 1959 init_data(); 1960 1961 what = command; 1962 } 1963 //------------------------------------------------------------------------------ 1964 BMessage::BMessage(const BMessage &message) 1965 { 1966 *this = message; 1967 } 1968 //------------------------------------------------------------------------------ 1969 BMessage::BMessage() 1970 { 1971 init_data(); 1972 } 1973 //------------------------------------------------------------------------------ 1974 BMessage::~BMessage () 1975 { 1976 } 1977 //------------------------------------------------------------------------------ 1978 BMessage &BMessage::operator=(const BMessage &message) 1979 { 1980 what = message.what; 1981 1982 link = message.link; 1983 fTarget = message.fTarget; 1984 fOriginal = message.fOriginal; 1985 fChangeCount = message.fChangeCount; 1986 fCurSpecifier = message.fCurSpecifier; 1987 fPtrOffset = message.fPtrOffset; 1988 1989 fEntries = NULL; 1990 1991 entry_hdr *src_entry; 1992 1993 for ( src_entry = message.fEntries; src_entry != NULL; src_entry = src_entry->fNext ) 1994 { 1995 entry_hdr* new_entry = (entry_hdr*)new char[da_total_logical_size ( src_entry )]; 1996 1997 if ( new_entry != NULL ) 1998 { 1999 memcpy ( new_entry, src_entry, da_total_logical_size ( src_entry ) ); 2000 2001 new_entry->fNext = fEntries; 2002 new_entry->fPhysicalBytes = src_entry->fLogicalBytes; 2003 2004 fEntries = new_entry; 2005 } 2006 } 2007 2008 fReplyTo.port = message.fReplyTo.port; 2009 fReplyTo.target = message.fReplyTo.target; 2010 fReplyTo.team = message.fReplyTo.team; 2011 fReplyTo.preferred = message.fReplyTo.preferred; 2012 2013 fPreferred = message.fPreferred; 2014 fReplyRequired = message.fReplyRequired; 2015 fReplyDone = message.fReplyDone; 2016 fIsReply = message.fIsReply; 2017 fWasDelivered = message.fWasDelivered; 2018 fReadOnly = message.fReadOnly; 2019 fHasSpecifiers = message.fHasSpecifiers; 2020 2021 return *this; 2022 } 2023 //------------------------------------------------------------------------------ 2024 status_t BMessage::GetInfo(const char *name, type_code *typeFound, 2025 int32 *countFound) const 2026 { 2027 for(entry_hdr *entry = fEntries; entry != NULL; entry = entry->fNext) 2028 { 2029 if (entry->fNameLength == strlen(name) && 2030 strncmp(entry->fName, name, entry->fNameLength) == 0) 2031 { 2032 if (typeFound) 2033 *typeFound = entry->fType; 2034 2035 if (countFound) 2036 *countFound = entry->fCount; 2037 2038 return B_OK; 2039 } 2040 } 2041 2042 return B_NAME_NOT_FOUND; 2043 } 2044 //------------------------------------------------------------------------------ 2045 status_t BMessage::GetInfo(const char *name, type_code *typeFound, bool *fixedSize) const 2046 { 2047 return B_ERROR; 2048 } 2049 //------------------------------------------------------------------------------ 2050 status_t BMessage::GetInfo(type_code type, int32 index, char **nameFound, type_code *typeFound, 2051 int32 *countFound) const 2052 { 2053 return B_ERROR; 2054 } 2055 //------------------------------------------------------------------------------ 2056 int32 BMessage::CountNames(type_code type) const 2057 { 2058 return -1; 2059 } 2060 //------------------------------------------------------------------------------ 2061 //bool BMessage::IsEmpty () const; 2062 //------------------------------------------------------------------------------ 2063 //bool BMessage::IsSystem () const; 2064 //------------------------------------------------------------------------------ 2065 bool BMessage::IsReply() const 2066 { 2067 return fIsReply; 2068 } 2069 //------------------------------------------------------------------------------ 2070 void BMessage::PrintToStream() const 2071 { 2072 char name[256]; 2073 2074 for (entry_hdr *entry = fEntries; entry != NULL; entry = entry->fNext) 2075 { 2076 memcpy(name, entry->fName, entry->fNameLength); 2077 name[entry->fNameLength] = 0; 2078 2079 printf("#entry %s, type = %c%c%c%c, count = %d\n", name, 2080 (entry->fType & 0xFF000000) >> 24, (entry->fType & 0x00FF0000) >> 16, 2081 (entry->fType & 0x0000FF00) >> 8, entry->fType & 0x000000FF, entry->fCount); 2082 2083 ((BMessage*)this)->da_dump((dyn_array*)entry); 2084 } 2085 } 2086 //------------------------------------------------------------------------------ 2087 //status_t BMessage::Rename(const char *old_entry, const char *new_entry); 2088 //------------------------------------------------------------------------------ 2089 //------------------------------------------------------------------------------ 2090 bool BMessage::WasDelivered () const 2091 { 2092 return fWasDelivered; 2093 } 2094 //------------------------------------------------------------------------------ 2095 //bool BMessage::IsSourceWaiting() const; 2096 //------------------------------------------------------------------------------ 2097 //bool BMessage::IsSourceRemote() const; 2098 //------------------------------------------------------------------------------ 2099 BMessenger BMessage::ReturnAddress() const 2100 { 2101 return BMessenger(fReplyTo.team, fReplyTo.port, fReplyTo.target, 2102 fReplyTo.preferred); 2103 } 2104 //------------------------------------------------------------------------------ 2105 const BMessage *BMessage::Previous () const 2106 { 2107 return fOriginal; 2108 } 2109 //------------------------------------------------------------------------------ 2110 bool BMessage::WasDropped () const 2111 { 2112 if (GetInfo("_drop_point_", NULL, (int32*)NULL) == B_OK) 2113 return true; 2114 else 2115 return false; 2116 } 2117 //------------------------------------------------------------------------------ 2118 BPoint BMessage::DropPoint(BPoint *offset) const 2119 { 2120 BPoint point; 2121 2122 FindPoint("_drop_point_", &point); 2123 2124 if (offset) 2125 FindPoint("_drop_offset_", offset); 2126 2127 return point; 2128 } 2129 //------------------------------------------------------------------------------ 2130 status_t BMessage::SendReply(uint32 command, BHandler *reply_to) 2131 { 2132 return B_ERROR; 2133 } 2134 //------------------------------------------------------------------------------ 2135 status_t BMessage::SendReply(BMessage *the_reply, BHandler *reply_to, 2136 bigtime_t timeout) 2137 { 2138 return B_ERROR; 2139 } 2140 //------------------------------------------------------------------------------ 2141 status_t BMessage::SendReply(BMessage *the_reply, BMessenger reply_to, 2142 bigtime_t timeout) 2143 { 2144 return B_ERROR; 2145 } 2146 //------------------------------------------------------------------------------ 2147 status_t BMessage::SendReply(uint32 command, BMessage *reply_to_reply) 2148 { 2149 return B_ERROR; 2150 } 2151 //------------------------------------------------------------------------------ 2152 status_t BMessage::SendReply(BMessage *the_reply, BMessage *reply_to_reply, 2153 bigtime_t send_timeout, 2154 bigtime_t reply_timeout) 2155 { 2156 return B_ERROR; 2157 } 2158 //------------------------------------------------------------------------------ 2159 ssize_t BMessage::FlattenedSize() const 2160 { 2161 ssize_t size = 7 * sizeof(int32); 2162 2163 for (entry_hdr *entry = fEntries; entry != NULL; entry = entry->fNext) 2164 size += da_total_logical_size(entry); 2165 2166 return size; 2167 } 2168 //------------------------------------------------------------------------------ 2169 status_t BMessage::Flatten(char *address, ssize_t numBytes) const 2170 { 2171 if (address!= NULL && numBytes < FlattenedSize()) 2172 return B_NO_MEMORY; 2173 2174 int position = 7 * sizeof(int32); 2175 2176 ((int32*)address)[1] = what; 2177 ((int32*)address)[2] = fCurSpecifier; 2178 ((int32*)address)[3] = fHasSpecifiers; 2179 ((int32*)address)[4] = 0; 2180 ((int32*)address)[5] = 0; 2181 ((int32*)address)[6] = 0; 2182 2183 for (entry_hdr *entry = fEntries; entry != NULL; entry = entry->fNext) 2184 { 2185 memcpy(address + position, entry, da_total_logical_size(entry)); 2186 2187 position += da_total_logical_size(entry); 2188 } 2189 2190 ((size_t*)address)[0] = position; 2191 2192 return B_OK; 2193 } 2194 //------------------------------------------------------------------------------ 2195 status_t BMessage::Flatten(BDataIO *object, ssize_t *numBytes) const 2196 { 2197 if (numBytes != NULL && *numBytes < FlattenedSize()) 2198 return B_NO_MEMORY; 2199 2200 int32 size = FlattenedSize(); 2201 char *buffer = new char[size]; 2202 2203 Flatten(buffer, size); 2204 2205 object->Write(buffer, size); 2206 2207 delete buffer; 2208 2209 return B_OK; 2210 } 2211 //------------------------------------------------------------------------------ 2212 status_t BMessage::Unflatten(const char *address) 2213 { 2214 size_t size; 2215 2216 MakeEmpty(); 2217 2218 size = ((size_t*)address)[0]; 2219 what = ((int32*)address)[1]; 2220 fCurSpecifier = ((int32*)address)[2]; 2221 fHasSpecifiers = ((int32*)address)[3]; 2222 2223 size_t position = 7 * sizeof(int32); 2224 2225 while (position < size) 2226 { 2227 entry_hdr* src_entry = (entry_hdr*)&address[position]; 2228 entry_hdr* new_entry = (entry_hdr*)new char[da_total_logical_size ( src_entry )]; 2229 2230 if (new_entry != NULL) 2231 { 2232 memcpy(new_entry, src_entry, da_total_logical_size(src_entry)); 2233 2234 new_entry->fNext = fEntries; 2235 new_entry->fPhysicalBytes = src_entry->fLogicalBytes; 2236 position += da_total_logical_size(src_entry); 2237 2238 fEntries = new_entry; 2239 } 2240 else 2241 return B_NO_MEMORY; 2242 } 2243 2244 if (position != size) 2245 { 2246 MakeEmpty(); 2247 return B_BAD_VALUE; 2248 } 2249 2250 return B_OK; 2251 } 2252 //------------------------------------------------------------------------------ 2253 status_t BMessage::Unflatten(BDataIO *object) 2254 { 2255 size_t size; 2256 2257 object->Read(&size, sizeof(int32)); 2258 2259 char *buffer = new char[size]; 2260 2261 *(int32*)buffer = size; 2262 2263 object->Read(buffer + sizeof(int32), size - sizeof(int32)); 2264 2265 status_t status = Unflatten(buffer); 2266 2267 delete[] buffer; 2268 2269 return status; 2270 } 2271 //------------------------------------------------------------------------------ 2272 status_t BMessage::AddSpecifier(const char *property) 2273 { 2274 BMessage message(B_DIRECT_SPECIFIER); 2275 message.AddString("property", property); 2276 2277 fCurSpecifier ++; 2278 fHasSpecifiers = true; 2279 2280 return AddMessage("specifiers", &message); 2281 } 2282 //------------------------------------------------------------------------------ 2283 status_t BMessage::AddSpecifier(const char *property, int32 index) 2284 { 2285 BMessage message(B_INDEX_SPECIFIER); 2286 message.AddString("property", property); 2287 message.AddInt32("index", index); 2288 2289 fCurSpecifier++; 2290 fHasSpecifiers = true; 2291 2292 return AddMessage("specifiers", &message); 2293 } 2294 //------------------------------------------------------------------------------ 2295 status_t BMessage::AddSpecifier(const char *property, int32 index, int32 range) 2296 { 2297 BMessage message(B_RANGE_SPECIFIER); 2298 message.AddString("property", property); 2299 message.AddInt32("index", index); 2300 message.AddInt32("range", range); 2301 2302 fCurSpecifier ++; 2303 fHasSpecifiers = true; 2304 2305 return AddMessage("specifiers", &message); 2306 } 2307 //------------------------------------------------------------------------------ 2308 status_t BMessage::AddSpecifier(const char *property, const char *name) 2309 { 2310 BMessage message(B_NAME_SPECIFIER); 2311 message.AddString("property", property); 2312 message.AddString("name", name); 2313 2314 fCurSpecifier ++; 2315 fHasSpecifiers = true; 2316 2317 return AddMessage("specifiers", &message); 2318 } 2319 //------------------------------------------------------------------------------ 2320 //status_t BMessage::AddSpecifier(const BMessage *message); 2321 //------------------------------------------------------------------------------ 2322 status_t SetCurrentSpecifier(int32 index) 2323 { 2324 return B_ERROR; 2325 } 2326 //------------------------------------------------------------------------------ 2327 status_t BMessage::GetCurrentSpecifier(int32 *index, BMessage *specifier, 2328 int32 *what, const char **property) const 2329 { 2330 if (fCurSpecifier == -1) 2331 return B_BAD_SCRIPT_SYNTAX; 2332 2333 if (index) 2334 *index = fCurSpecifier; 2335 2336 if (specifier) 2337 { 2338 FindMessage("specifiers", fCurSpecifier, specifier); 2339 2340 if (what) 2341 *what = specifier->what; 2342 2343 if (property) 2344 specifier->FindString("property", property); 2345 } 2346 2347 return B_OK; 2348 } 2349 //------------------------------------------------------------------------------ 2350 bool BMessage::HasSpecifiers() const 2351 { 2352 return fHasSpecifiers; 2353 } 2354 //------------------------------------------------------------------------------ 2355 status_t BMessage::PopSpecifier() 2356 { 2357 if (fCurSpecifier) 2358 { 2359 fCurSpecifier--; 2360 return B_OK; 2361 } 2362 else 2363 return B_BAD_VALUE; 2364 } 2365 //------------------------------------------------------------------------------ 2366 status_t BMessage::AddRect(const char *name, BRect rect) 2367 { 2368 return AddData(name, B_RECT_TYPE, &rect, sizeof(BRect), true); 2369 } 2370 //------------------------------------------------------------------------------ 2371 status_t BMessage::AddPoint(const char *name, BPoint point) 2372 { 2373 return AddData(name, B_POINT_TYPE, &point, sizeof(BPoint), true); 2374 } 2375 //------------------------------------------------------------------------------ 2376 status_t BMessage::AddString(const char *name, const char *string) 2377 { 2378 return AddData(name, B_STRING_TYPE, string, strlen(string) + 1, false); 2379 } 2380 //------------------------------------------------------------------------------ 2381 //status_t BMessage::AddString(const char *name, const CString &string); 2382 //------------------------------------------------------------------------------ 2383 status_t BMessage::AddInt8(const char *name, int8 anInt8) 2384 { 2385 return AddData(name, B_INT8_TYPE, &anInt8, sizeof(int8)); 2386 } 2387 //------------------------------------------------------------------------------ 2388 status_t BMessage::AddInt16(const char *name, int16 anInt16) 2389 { 2390 return AddData(name, B_INT16_TYPE, &anInt16, sizeof(int16)); 2391 } 2392 //------------------------------------------------------------------------------ 2393 status_t BMessage::AddInt32(const char *name, int32 anInt32) 2394 { 2395 return AddData(name, B_INT32_TYPE, &anInt32, sizeof(int32)); 2396 } 2397 //------------------------------------------------------------------------------ 2398 status_t BMessage::AddInt64(const char *name, int64 anInt64) 2399 { 2400 return AddData(name, B_INT64_TYPE, &anInt64, sizeof(int64)); 2401 } 2402 //------------------------------------------------------------------------------ 2403 status_t BMessage::AddBool(const char *name, bool aBool) 2404 { 2405 return AddData(name, B_BOOL_TYPE, &aBool, sizeof(bool)); 2406 } 2407 //------------------------------------------------------------------------------ 2408 status_t BMessage::AddFloat ( const char *name, float aFloat) 2409 { 2410 return AddData(name, B_FLOAT_TYPE, &aFloat, sizeof(float)); 2411 } 2412 //------------------------------------------------------------------------------ 2413 status_t BMessage::AddDouble ( const char *name, double aDouble) 2414 { 2415 return AddData(name, B_DOUBLE_TYPE, &aDouble, sizeof(double)); 2416 } 2417 //------------------------------------------------------------------------------ 2418 status_t BMessage::AddPointer(const char *name, const void *pointer) 2419 { 2420 return AddData(name, B_POINTER_TYPE, &pointer, sizeof(void*), true); 2421 } 2422 //------------------------------------------------------------------------------ 2423 status_t BMessage::AddMessenger(const char *name, BMessenger messenger) 2424 { 2425 return B_OK; 2426 } 2427 //------------------------------------------------------------------------------ 2428 //status_t BMessage::AddRef(const char *name, const entry_ref *ref); 2429 //------------------------------------------------------------------------------ 2430 status_t BMessage::AddMessage(const char *name, const BMessage *message) 2431 { 2432 int32 size = message->FlattenedSize(); 2433 char *buffer = new char[size]; 2434 2435 message->Flatten (buffer, size); 2436 2437 return AddData(name, B_MESSAGE_TYPE, buffer, size, false); 2438 } 2439 //------------------------------------------------------------------------------ 2440 status_t BMessage::AddFlat(const char *name, BFlattenable *object, 2441 int32 numItems) 2442 { 2443 int32 size = object->FlattenedSize (); 2444 char *buffer = new char[size]; 2445 2446 object->Flatten(buffer, size); 2447 2448 return AddData(name, object->TypeCode(), buffer, size, 2449 object->IsFixedSize(), numItems); 2450 } 2451 //------------------------------------------------------------------------------ 2452 status_t BMessage::AddData(const char *name, type_code type, const void *data, 2453 ssize_t numBytes, bool fixedSize, int32 numItems) 2454 { 2455 entry_hdr *entry = entry_find(name, type); 2456 2457 if (entry == NULL) 2458 { 2459 if ( strlen(name) > 255) 2460 return B_BAD_VALUE; 2461 2462 entry = (entry_hdr*)da_create(sizeof(entry_hdr) - sizeof(dyn_array) + 2463 strlen(name), numBytes, fixedSize, numItems); 2464 2465 entry->fNext = fEntries; 2466 entry->fType = type; 2467 entry->fNameLength = strlen(name); 2468 memcpy(entry->fName, name, entry->fNameLength); 2469 2470 fEntries = entry; 2471 } 2472 2473 return da_add_data((dyn_array**)&entry, data, numBytes); 2474 } 2475 //------------------------------------------------------------------------------ 2476 //status_t BMessage::RemoveData(const char *name, int32 index); 2477 //status_t BMessage::RemoveName(const char *name); 2478 //------------------------------------------------------------------------------ 2479 status_t BMessage::MakeEmpty() 2480 { 2481 entry_hdr *entry; 2482 2483 while(entry = fEntries) 2484 { 2485 fEntries = entry->fNext; 2486 delete entry; 2487 } 2488 2489 return B_OK; 2490 } 2491 //------------------------------------------------------------------------------ 2492 status_t BMessage::FindRect(const char *name, BRect *rect) const 2493 { 2494 entry_hdr *entry = entry_find(name, B_RECT_TYPE); 2495 2496 if (entry == NULL) 2497 return B_NAME_NOT_FOUND; 2498 2499 *rect = *(BRect*)da_first_chunk(entry); 2500 2501 return B_OK; 2502 } 2503 //------------------------------------------------------------------------------ 2504 status_t BMessage::FindRect(const char *name, int32 index, BRect *rect) const 2505 { 2506 entry_hdr *entry = entry_find(name, B_RECT_TYPE); 2507 2508 if (entry == NULL) 2509 return B_NAME_NOT_FOUND; 2510 2511 if (index < entry->fCount) 2512 { 2513 BRect* data = (BRect*)da_first_chunk(entry); 2514 *rect = data[index]; 2515 2516 return B_OK; 2517 } 2518 2519 return B_BAD_INDEX; 2520 } 2521 //------------------------------------------------------------------------------ 2522 status_t BMessage::FindPoint(const char *name, BPoint *point) const 2523 { 2524 entry_hdr *entry = entry_find(name, B_POINT_TYPE); 2525 2526 if (entry == NULL) 2527 return B_NAME_NOT_FOUND; 2528 2529 *point = *(BPoint*)da_first_chunk(entry); 2530 2531 return B_OK; 2532 } 2533 //------------------------------------------------------------------------------ 2534 status_t BMessage::FindPoint(const char *name, int32 index, BPoint *point) const 2535 { 2536 entry_hdr *entry = entry_find(name, B_POINT_TYPE); 2537 2538 if (entry == NULL) 2539 return B_NAME_NOT_FOUND; 2540 2541 if (index < entry->fCount) 2542 { 2543 BPoint* data = (BPoint*)da_first_chunk(entry); 2544 *point = data[index]; 2545 2546 return B_OK; 2547 } 2548 2549 return B_BAD_INDEX; 2550 } 2551 //------------------------------------------------------------------------------ 2552 status_t BMessage::FindString(const char *name, int32 index, 2553 const char **string) const 2554 { 2555 return FindData(name, B_STRING_TYPE, index, (const void**)string, NULL); 2556 } 2557 //------------------------------------------------------------------------------ 2558 status_t BMessage::FindString(const char *name, const char **string) const 2559 { 2560 return FindData(name, B_STRING_TYPE, (const void**)string, NULL); 2561 } 2562 //------------------------------------------------------------------------------ 2563 //status_t BMessage::FindString ( const char *name, int32 index, 2564 //CString *string ) const; 2565 //------------------------------------------------------------------------------ 2566 //status_t BMessage::FindString ( const char *name, CString *string ) const; 2567 //------------------------------------------------------------------------------ 2568 status_t BMessage::FindInt8(const char *name, int8 *anInt8) const 2569 { 2570 entry_hdr *entry = entry_find(name, B_INT8_TYPE); 2571 2572 if (entry == NULL) 2573 return B_NAME_NOT_FOUND; 2574 2575 *anInt8 = *(int8*)da_first_chunk(entry); 2576 2577 return B_OK; 2578 } 2579 //------------------------------------------------------------------------------ 2580 status_t BMessage::FindInt8(const char *name, int32 index, int8 *anInt8) const 2581 { 2582 entry_hdr *entry = entry_find(name, B_INT8_TYPE); 2583 2584 if (entry == NULL) 2585 return B_NAME_NOT_FOUND; 2586 2587 if (index < entry->fCount) 2588 { 2589 int8* data = (int8*)da_first_chunk(entry); 2590 *anInt8 = data[index]; 2591 2592 return B_OK; 2593 } 2594 2595 return B_BAD_INDEX; 2596 } 2597 //------------------------------------------------------------------------------ 2598 status_t BMessage::FindInt16(const char *name, int16 *anInt16) const 2599 { 2600 entry_hdr *entry = entry_find(name, B_INT16_TYPE); 2601 2602 if (entry == NULL) 2603 return B_NAME_NOT_FOUND; 2604 2605 *anInt16 = *(int16*)da_first_chunk(entry); 2606 2607 return B_OK; 2608 } 2609 //------------------------------------------------------------------------------ 2610 status_t BMessage::FindInt16(const char *name, int32 index, int16 *anInt16) const 2611 { 2612 entry_hdr *entry = entry_find(name, B_INT16_TYPE); 2613 2614 if (entry == NULL) 2615 return B_NAME_NOT_FOUND; 2616 2617 if (index < entry->fCount) 2618 { 2619 int16* data = (int16*)da_first_chunk(entry); 2620 *anInt16 = data[index]; 2621 2622 return B_OK; 2623 } 2624 2625 return B_BAD_INDEX; 2626 } 2627 //------------------------------------------------------------------------------ 2628 status_t BMessage::FindInt32(const char *name, int32 *anInt32) const 2629 { 2630 entry_hdr *entry = entry_find(name, B_INT32_TYPE); 2631 2632 if (entry == NULL) 2633 return B_NAME_NOT_FOUND; 2634 2635 *anInt32 = *(int32*)da_first_chunk(entry); 2636 2637 return B_OK; 2638 } 2639 //------------------------------------------------------------------------------ 2640 status_t BMessage::FindInt32(const char *name, int32 index, 2641 int32 *anInt32) const 2642 { 2643 entry_hdr *entry = entry_find(name, B_INT32_TYPE); 2644 2645 if (entry == NULL) 2646 return B_NAME_NOT_FOUND; 2647 2648 if (index < entry->fCount) 2649 { 2650 int32* data = (int32*)da_first_chunk(entry); 2651 *anInt32 = data[index]; 2652 2653 return B_OK; 2654 } 2655 2656 return B_BAD_INDEX; 2657 } 2658 //------------------------------------------------------------------------------ 2659 //status_t BMessage::FindInt64 ( const char *name, int64 *anInt64) const; 2660 //------------------------------------------------------------------------------ 2661 //status_t BMessage::FindInt64 ( const char *name, int32 index, 2662 // int64 *anInt64 ) const; 2663 //------------------------------------------------------------------------------ 2664 status_t BMessage::FindBool(const char *name, bool *aBool) const 2665 { 2666 entry_hdr *entry = entry_find(name, B_BOOL_TYPE); 2667 2668 if (entry == NULL) 2669 return B_NAME_NOT_FOUND; 2670 2671 *aBool = *(bool*)da_first_chunk(entry); 2672 2673 return B_OK; 2674 } 2675 //------------------------------------------------------------------------------ 2676 status_t BMessage::FindBool(const char *name, int32 index, bool *aBool) const 2677 { 2678 entry_hdr *entry = entry_find(name, B_BOOL_TYPE); 2679 2680 if (entry == NULL) 2681 return B_NAME_NOT_FOUND; 2682 2683 if (index < entry->fCount) 2684 { 2685 bool* data = (bool*)da_first_chunk(entry); 2686 *aBool = data[index]; 2687 2688 return B_OK; 2689 } 2690 2691 return B_BAD_INDEX; 2692 } 2693 //------------------------------------------------------------------------------ 2694 status_t BMessage::FindFloat(const char *name, float *aFloat) const 2695 { 2696 entry_hdr *entry = entry_find(name, B_FLOAT_TYPE); 2697 2698 if (entry == NULL) 2699 return B_NAME_NOT_FOUND; 2700 2701 *aFloat = *(float*)da_first_chunk(entry); 2702 2703 return B_OK; 2704 } 2705 //------------------------------------------------------------------------------ 2706 status_t BMessage::FindFloat(const char *name, int32 index, float *aFloat) const 2707 { 2708 entry_hdr *entry = entry_find(name, B_FLOAT_TYPE); 2709 2710 if (entry == NULL) 2711 return B_NAME_NOT_FOUND; 2712 2713 if (index < entry->fCount) 2714 { 2715 float* data = (float*)da_first_chunk(entry); 2716 *aFloat = data[index]; 2717 2718 return B_OK; 2719 } 2720 2721 return B_BAD_INDEX; 2722 } 2723 //------------------------------------------------------------------------------ 2724 status_t BMessage::FindDouble(const char *name, double *aDouble) const 2725 { 2726 entry_hdr *entry = entry_find(name, B_DOUBLE_TYPE); 2727 2728 if (entry == NULL) 2729 return B_NAME_NOT_FOUND; 2730 2731 *aDouble = *(double*)da_first_chunk(entry); 2732 2733 return B_OK; 2734 } 2735 //------------------------------------------------------------------------------ 2736 status_t BMessage::FindDouble(const char *name, int32 index, 2737 double *aDouble) const 2738 { 2739 entry_hdr *entry = entry_find(name, B_DOUBLE_TYPE); 2740 2741 if (entry == NULL) 2742 return B_NAME_NOT_FOUND; 2743 2744 if (index < entry->fCount) 2745 { 2746 double* data = (double*)da_first_chunk(entry); 2747 *aDouble = data[index]; 2748 2749 return B_OK; 2750 } 2751 2752 return B_BAD_INDEX; 2753 } 2754 //------------------------------------------------------------------------------ 2755 status_t BMessage::FindPointer(const char *name, void **pointer) const 2756 { 2757 entry_hdr *entry = entry_find(name, B_POINTER_TYPE); 2758 2759 if (entry == NULL) 2760 { 2761 *pointer = NULL; 2762 return B_NAME_NOT_FOUND; 2763 } 2764 2765 *pointer = *(void**)da_first_chunk(entry); 2766 2767 return B_OK; 2768 } 2769 //------------------------------------------------------------------------------ 2770 status_t BMessage::FindPointer(const char *name, int32 index, 2771 void **pointer) const 2772 { 2773 entry_hdr *entry = entry_find(name, B_POINTER_TYPE); 2774 2775 if (entry == NULL) 2776 { 2777 *pointer = NULL; 2778 return B_NAME_NOT_FOUND; 2779 } 2780 2781 if (index >= entry->fCount) 2782 { 2783 *pointer = NULL; 2784 return B_BAD_INDEX; 2785 } 2786 2787 void** data = (void**)da_first_chunk(entry); 2788 *pointer = data[index]; 2789 2790 return B_OK; 2791 } 2792 //------------------------------------------------------------------------------ 2793 //status_t BMessage::FindMessenger ( const char *name, CMessenger *messenger ) const; 2794 //------------------------------------------------------------------------------ 2795 //status_t BMessage::FindMessenger ( const char *name, int32 index, CMessenger *messenger ) const; 2796 //------------------------------------------------------------------------------ 2797 //status_t BMessage::FindRef ( const char *name, entry_ref *ref ) const; 2798 //------------------------------------------------------------------------------ 2799 //status_t BMessage::FindRef ( const char *name, int32 index, entry_ref *ref ) const; 2800 //------------------------------------------------------------------------------ 2801 status_t BMessage::FindMessage(const char *name, BMessage *message) const 2802 { 2803 const char *data; 2804 2805 if ( FindData(name, B_MESSAGE_TYPE, (const void**)&data, NULL) != B_OK) 2806 return B_NAME_NOT_FOUND; 2807 2808 return message->Unflatten(data); 2809 } 2810 //------------------------------------------------------------------------------ 2811 status_t BMessage::FindMessage(const char *name, int32 index, 2812 BMessage *message) const 2813 { 2814 const char *data; 2815 2816 if ( FindData(name, B_MESSAGE_TYPE, index, (const void**)&data, 2817 NULL) != B_OK) 2818 return B_NAME_NOT_FOUND; 2819 2820 return message->Unflatten(data); 2821 } 2822 //------------------------------------------------------------------------------ 2823 status_t BMessage::FindFlat(const char *name, BFlattenable *object) const 2824 { 2825 status_t ret; 2826 const void *data; 2827 ssize_t numBytes; 2828 2829 ret = FindData(name, object->TypeCode (), &data, &numBytes); 2830 2831 if ( ret != B_OK ) 2832 return ret; 2833 2834 if ( object->Unflatten(object->TypeCode (), data, numBytes) != B_OK) 2835 return B_BAD_VALUE; 2836 2837 return B_OK; 2838 } 2839 //------------------------------------------------------------------------------ 2840 status_t BMessage::FindFlat(const char *name, int32 index, 2841 BFlattenable *object) const 2842 { 2843 status_t ret; 2844 const void *data; 2845 ssize_t numBytes; 2846 2847 ret = FindData(name, object->TypeCode(), index, &data, &numBytes); 2848 2849 if (ret != B_OK) 2850 return ret; 2851 2852 if (object->Unflatten(object->TypeCode(), data, numBytes) != B_OK) 2853 return B_BAD_VALUE; 2854 2855 return B_OK; 2856 } 2857 //------------------------------------------------------------------------------ 2858 status_t BMessage::FindData(const char *name, type_code type, const void **data, 2859 ssize_t *numBytes) const 2860 { 2861 entry_hdr *entry = entry_find(name, type); 2862 2863 if (entry == NULL) 2864 { 2865 *data = NULL; 2866 return B_NAME_NOT_FOUND; 2867 } 2868 2869 int32 size; 2870 2871 *data = da_find_data(entry, 0, &size); 2872 2873 if (numBytes) 2874 *numBytes = size; 2875 2876 return B_OK; 2877 } 2878 //------------------------------------------------------------------------------ 2879 status_t BMessage::FindData(const char *name, type_code type, int32 index, 2880 const void **data, ssize_t *numBytes) const 2881 { 2882 entry_hdr *entry = entry_find(name, type); 2883 2884 if (entry == NULL) 2885 { 2886 *data = NULL; 2887 return B_NAME_NOT_FOUND; 2888 } 2889 2890 if (index >= entry->fCount) 2891 { 2892 *data = NULL; 2893 return B_BAD_INDEX; 2894 } 2895 2896 int32 size; 2897 2898 *data = da_find_data(entry, index, &size); 2899 2900 if (numBytes) 2901 *numBytes = size; 2902 2903 return B_OK; 2904 } 2905 //------------------------------------------------------------------------------ 2906 //status_t BMessage::ReplaceRect(const char *name, BRect rect); 2907 //------------------------------------------------------------------------------ 2908 //status_t BMessage::ReplaceRect(const char *name, int32 index, BRect rect); 2909 //------------------------------------------------------------------------------ 2910 status_t BMessage::ReplacePoint(const char *name, BPoint point) 2911 { 2912 return ReplaceData(name, B_POINT_TYPE, &point, sizeof(BPoint)); 2913 } 2914 //------------------------------------------------------------------------------ 2915 //status_t BMessage::ReplacePoint(const char *name, int32 index, BPoint point); 2916 //------------------------------------------------------------------------------ 2917 status_t BMessage::ReplaceString(const char *name, const char *string) 2918 { 2919 return B_ERROR; 2920 } 2921 //------------------------------------------------------------------------------ 2922 //status_t BMessage::ReplaceString(const char *name, int32 index, 2923 // const char *string); 2924 //------------------------------------------------------------------------------ 2925 //status_t BMessage::ReplaceString(const char *name, CString &string); 2926 //------------------------------------------------------------------------------ 2927 //status_t BMessage::ReplaceString(const char *name, int32 index, CString &string); 2928 //------------------------------------------------------------------------------ 2929 status_t BMessage::ReplaceInt8(const char *name, int8 anInt8) 2930 { 2931 return ReplaceData(name, B_INT8_TYPE, &anInt8, sizeof(int8)); 2932 } 2933 //------------------------------------------------------------------------------ 2934 //status_t BMessage::ReplaceInt8(const char *name, int32 index, int8 anInt8); 2935 //------------------------------------------------------------------------------ 2936 //status_t BMessage::ReplaceInt16(const char *name, int16 anInt16); 2937 //------------------------------------------------------------------------------ 2938 //status_t BMessage::ReplaceInt16(const char *name, int32 index, int16 anInt16); 2939 //------------------------------------------------------------------------------ 2940 status_t BMessage::ReplaceInt32(const char *name, long anInt32) 2941 { 2942 return ReplaceData(name, B_INT32_TYPE, &anInt32, sizeof(int32)); 2943 } 2944 //------------------------------------------------------------------------------ 2945 //status_t BMessage::ReplaceInt32(const char *name, int32 index, int32 anInt32); 2946 //------------------------------------------------------------------------------ 2947 status_t BMessage::ReplaceInt64(const char *name, int64 anInt64) 2948 { 2949 return ReplaceData(name, B_INT64_TYPE, &anInt64, sizeof(int64)); 2950 } 2951 //------------------------------------------------------------------------------ 2952 //status_t BMessage::ReplaceInt64(const char *name, int32 index, int64 anInt64); 2953 //------------------------------------------------------------------------------ 2954 //status_t BMessage::ReplaceBool(const char *name, bool aBool); 2955 //------------------------------------------------------------------------------ 2956 //status_t BMessage::ReplaceBool(const char *name, int32 index, bool aBool); 2957 //------------------------------------------------------------------------------ 2958 //status_t BMessage::ReplaceFloat(const char *name, float aFloat); 2959 //------------------------------------------------------------------------------ 2960 //status_t BMessage::ReplaceFloat(const char *name, int32 index, float aFloat); 2961 //------------------------------------------------------------------------------ 2962 //status_t BMessage::ReplaceDouble(const char *name, double aDouble); 2963 //------------------------------------------------------------------------------ 2964 //status_t BMessage::ReplaceDouble(const char *name, int32 index, double aDouble); 2965 //------------------------------------------------------------------------------ 2966 //status_t BMessage::ReplacePointer(const char *name, const void *pointer); 2967 //------------------------------------------------------------------------------ 2968 //status_t BMessage::ReplacePointer(const char *name, int32 index, 2969 // const void *pointer); 2970 //------------------------------------------------------------------------------ 2971 //status_t BMessage::ReplaceMessenger(const char *name, BMessenger messenger); 2972 //------------------------------------------------------------------------------ 2973 //status_t BMessage::ReplaceMessenger(const char *name, int32 index, 2974 // BMessenger messenger); 2975 //------------------------------------------------------------------------------ 2976 //status_t BMessage::ReplaceRef(const char *name, entry_ref *ref); 2977 //------------------------------------------------------------------------------ 2978 //status_t BMessage::ReplaceRef(const char *name, int32 index, entry_ref *ref); 2979 //------------------------------------------------------------------------------ 2980 //status_t ReplaceMessage(const char *name, const BMessage *msg); 2981 //------------------------------------------------------------------------------ 2982 //status_t ReplaceMessage(const char *name, int32 index, const BMessage *msg); 2983 //------------------------------------------------------------------------------ 2984 //status_t BMessage::ReplaceFlat(const char *name, BFlattenable *object); 2985 //------------------------------------------------------------------------------ 2986 //status_t BMessage::ReplaceFlat(const char *name, int32 index, 2987 // BFlattenable *object); 2988 //------------------------------------------------------------------------------ 2989 status_t BMessage::ReplaceData(const char *name, type_code type, 2990 const void *data, ssize_t numBytes) 2991 { 2992 entry_hdr *entry = entry_find(name, type); 2993 2994 if (entry == NULL) 2995 return B_NAME_NOT_FOUND; 2996 2997 if (entry->fType != type) 2998 return B_BAD_TYPE; 2999 3000 da_replace_data((dyn_array**)&entry, 0, data, numBytes); 3001 3002 return B_OK; 3003 } 3004 //------------------------------------------------------------------------------ 3005 //status_t BMessage::ReplaceData(const char *name, type_code type, int32 index, 3006 // const void *data, size_t numBytes); 3007 //------------------------------------------------------------------------------ 3008 //void *BMessage::operator new(size_t numBytes); 3009 //------------------------------------------------------------------------------ 3010 //void BMessage::operator delete(void *memory, size_t numBytes); 3011 //------------------------------------------------------------------------------ 3012 /*bool HasRect(const char *, int32 n = 0) const; 3013 bool HasPoint(const char *, int32 n = 0) const; 3014 bool HasString(const char *, int32 n = 0) const; 3015 bool HasInt8(const char *, int32 n = 0) const; 3016 bool HasInt16(const char *, int32 n = 0) const; 3017 bool HasInt32(const char *, int32 n = 0) const; 3018 bool HasInt64(const char *, int32 n = 0) const; 3019 bool HasBool(const char *, int32 n = 0) const; 3020 bool HasFloat(const char *, int32 n = 0) const; 3021 bool HasDouble(const char *, int32 n = 0) const; 3022 bool HasPointer(const char *, int32 n = 0) const; 3023 bool HasMessenger(const char *, int32 n = 0) const; 3024 bool HasRef(const char *, int32 n = 0) const; 3025 bool HasMessage(const char *, int32 n = 0) const; 3026 bool HasFlat(const char *, const BFlattenable *) const; 3027 bool HasFlat(const char *,int32 ,const BFlattenable *) const; 3028 bool HasData(const char *, type_code , int32 n = 0) const; 3029 BRect FindRect(const char *, int32 n = 0) const; 3030 BPoint FindPoint(const char *, int32 n = 0) const; 3031 const char *FindString(const char *, int32 n = 0) const; 3032 int8 FindInt8(const char *, int32 n = 0) const; 3033 int16 FindInt16(const char *, int32 n = 0) const;*/ 3034 //------------------------------------------------------------------------------ 3035 int32 BMessage::FindInt32(const char *name, int32 index) const 3036 { 3037 int32 anInt32 = 0; 3038 3039 BMessage::FindInt32(name, index, &anInt32); 3040 3041 return anInt32; 3042 } 3043 //------------------------------------------------------------------------------ 3044 /*int64 FindInt64(const char *, int32 n = 0) const; 3045 bool FindBool(const char *, int32 n = 0) const; 3046 float FindFloat(const char *, int32 n = 0) const; 3047 double FindDouble(const char *, int32 n = 0) const;*/ 3048 //------------------------------------------------------------------------------ 3049 BMessage::BMessage(BMessage *a_message) 3050 { 3051 *this=*a_message; 3052 } 3053 //------------------------------------------------------------------------------ 3054 void BMessage::_ReservedMessage1() {} 3055 void BMessage::_ReservedMessage2() {} 3056 void BMessage::_ReservedMessage3() {} 3057 //------------------------------------------------------------------------------ 3058 void BMessage::init_data() 3059 { 3060 what = 0; 3061 3062 link = NULL; 3063 fTarget = -1; 3064 fOriginal = NULL; 3065 fChangeCount = 0; 3066 fCurSpecifier = -1; 3067 fPtrOffset = 0; 3068 3069 fEntries = NULL; 3070 3071 fReplyTo.port = -1; 3072 fReplyTo.target = -1; 3073 fReplyTo.team = -1; 3074 fReplyTo.preferred = false; 3075 3076 fPreferred = false; 3077 fReplyRequired = false; 3078 fReplyDone = false; 3079 fIsReply = false; 3080 fWasDelivered = false; 3081 fReadOnly = false; 3082 fHasSpecifiers = false; 3083 } 3084 //------------------------------------------------------------------------------ 3085 // These are not declared in the header anymore and aren't actually used by the 3086 // "old" implementation. 3087 #if 0 3088 int32 BMessage::flatten_hdr(uchar *result, ssize_t size, uchar flags) const 3089 { 3090 return -1; 3091 } 3092 //------------------------------------------------------------------------------ 3093 status_t BMessage::real_flatten(char *result, ssize_t size, uchar flags) const 3094 { 3095 return B_ERROR; 3096 } 3097 //------------------------------------------------------------------------------ 3098 status_t BMessage::real_flatten(BDataIO *stream, ssize_t size, 3099 uchar flags) const 3100 { 3101 return B_ERROR; 3102 } 3103 #endif 3104 //------------------------------------------------------------------------------ 3105 char* BMessage::stack_flatten(char* stack_ptr, ssize_t stack_size, 3106 bool incl_reply, ssize_t* size) const 3107 { 3108 return NULL; 3109 } 3110 //------------------------------------------------------------------------------ 3111 ssize_t BMessage::calc_size(uchar flags) const 3112 { 3113 return -1; 3114 } 3115 //------------------------------------------------------------------------------ 3116 ssize_t BMessage::calc_hdr_size(uchar flags) const 3117 { 3118 return -1; 3119 } 3120 //------------------------------------------------------------------------------ 3121 ssize_t BMessage::min_hdr_size() const 3122 { 3123 return -1; 3124 } 3125 //------------------------------------------------------------------------------ 3126 status_t BMessage::nfind_data(const char *name, type_code type, int32 index, 3127 const void **data, ssize_t *data_size) const 3128 { 3129 return B_ERROR; 3130 } 3131 //------------------------------------------------------------------------------ 3132 status_t BMessage::copy_data(const char *name, type_code type, int32 index, 3133 void *data, ssize_t data_size) const 3134 { 3135 return B_ERROR; 3136 } 3137 //------------------------------------------------------------------------------ 3138 status_t BMessage::_send_(port_id port, int32 token, bool preferred, 3139 bigtime_t timeout, bool reply_required, 3140 BMessenger &reply_to) const 3141 { 3142 /*_set_message_target_(this, token, preferred); 3143 _set_message_reply_(this, reply_to); 3144 3145 int32 size; 3146 char *buffer; 3147 3148 write_port_etc(port, what, buffer, size, B_TIMEOUT, timeout);*/ 3149 3150 return B_ERROR; 3151 } 3152 //------------------------------------------------------------------------------ 3153 status_t BMessage::send_message(port_id port, team_id port_owner, int32 token, 3154 bool preferred, BMessage *reply, 3155 bigtime_t send_timeout, 3156 bigtime_t reply_timeout) const 3157 { 3158 return B_ERROR; 3159 } 3160 //------------------------------------------------------------------------------ 3161 BMessage::entry_hdr * BMessage::entry_find(const char *name, uint32 type, 3162 status_t *result) const 3163 { 3164 for (entry_hdr *entry = fEntries; entry != NULL; entry = entry->fNext) 3165 if (entry->fType ==type && entry->fNameLength == strlen(name) && 3166 strncmp(entry->fName, name, entry->fNameLength) == 0) 3167 { 3168 if (result) 3169 *result = B_OK; 3170 3171 return entry; 3172 } 3173 3174 if (result) 3175 *result = B_NAME_NOT_FOUND; 3176 3177 return NULL; 3178 } 3179 //------------------------------------------------------------------------------ 3180 void BMessage::entry_remove(entry_hdr *entry) 3181 { 3182 if (entry == fEntries) 3183 fEntries = entry->fNext; 3184 else 3185 { 3186 for (entry_hdr *entry_ptr = fEntries; entry_ptr != NULL; entry_ptr = entry_ptr->fNext) 3187 if (entry_ptr->fNext == entry) 3188 entry_ptr->fNext = entry->fNext; 3189 } 3190 } 3191 //------------------------------------------------------------------------------ 3192 void *BMessage::da_create(int32 header_size, int32 chunk_size, bool fixed, 3193 int32 nchunks) 3194 { 3195 int size = da_calc_size(header_size, chunk_size, fixed, nchunks); 3196 3197 dyn_array *da = (dyn_array*)new char[size]; 3198 3199 da->fLogicalBytes = 0; 3200 da->fPhysicalBytes = size - sizeof(dyn_array) - header_size; 3201 3202 if ( fixed ) 3203 da->fChunkSize = chunk_size; 3204 else 3205 da->fChunkSize = 0; 3206 3207 da->fCount = 0; 3208 da->fEntryHdrSize = header_size; 3209 3210 return da; 3211 } 3212 //------------------------------------------------------------------------------ 3213 status_t BMessage::da_add_data(dyn_array **da, const void *data, int32 size ) 3214 { 3215 // _ASSERT(_CrtCheckMemory()); 3216 3217 int32 new_size = (*da)->fLogicalBytes + ((*da)->fChunkSize ? (*da)->fChunkSize : 3218 da_pad_8(size + da_chunk_hdr_size())); 3219 3220 if (new_size > (*da)->fPhysicalBytes) 3221 da_grow(da, new_size - (*da)->fPhysicalBytes); 3222 3223 void *ptr = da_find_data(*da, (*da)->fCount++, NULL); 3224 3225 memcpy(ptr, data, size); 3226 3227 if ((*da)->fChunkSize) 3228 (*da)->fLogicalBytes += size; 3229 else 3230 { 3231 da_chunk_ptr(ptr)->fDataSize = size; 3232 (*da)->fLogicalBytes += da_chunk_size(da_chunk_ptr(ptr)); 3233 } 3234 3235 // _ASSERT(_CrtCheckMemory()); 3236 3237 return B_OK; 3238 } 3239 //------------------------------------------------------------------------------ 3240 void *BMessage::da_find_data(dyn_array *da, int32 index, int32 *size) const 3241 { 3242 if (da->fChunkSize) 3243 { 3244 if (size) 3245 *size = da->fChunkSize; 3246 3247 return (char*)da_start_of_data(da) + index * da->fChunkSize; 3248 } 3249 else 3250 { 3251 var_chunk *chunk = da_first_chunk(da); 3252 3253 for (int i = 0; i < index; i++) 3254 chunk = da_next_chunk(chunk); 3255 3256 if (size) 3257 *size = chunk->fDataSize; 3258 3259 return chunk->fData; 3260 } 3261 } 3262 //------------------------------------------------------------------------------ 3263 status_t BMessage::da_delete_data(dyn_array **pda, int32 index) 3264 { 3265 return 0; 3266 } 3267 //------------------------------------------------------------------------------ 3268 status_t BMessage::da_replace_data(dyn_array **pda, int32 index, 3269 const void *data, int32 dsize) 3270 { 3271 void *ptr = da_find_data(*pda, index, NULL); 3272 3273 memcpy(ptr, data, dsize); 3274 3275 return B_OK; 3276 } 3277 //------------------------------------------------------------------------------ 3278 int32 BMessage::da_calc_size(int32 hdr_size, int32 chunksize, bool is_fixed, 3279 int32 nchunks) const 3280 { 3281 int size = sizeof(dyn_array) + hdr_size; 3282 3283 if (is_fixed) 3284 size += chunksize * nchunks; 3285 else 3286 size += (chunksize + da_chunk_hdr_size()) * nchunks; 3287 3288 return size; 3289 } 3290 //------------------------------------------------------------------------------ 3291 void *BMessage::da_grow(dyn_array **pda, int32 increase) 3292 { 3293 dyn_array *da = (dyn_array*)new char[da_total_size(*pda) + increase]; 3294 dyn_array *old_da = *pda; 3295 3296 memcpy(da, *pda, da_total_size(*pda)); 3297 3298 *pda = da; 3299 (*pda)->fPhysicalBytes += increase; 3300 3301 entry_remove((entry_hdr*)old_da); 3302 3303 delete old_da; 3304 3305 ((entry_hdr*)*pda)->fNext = fEntries; 3306 fEntries = (entry_hdr*)*pda; 3307 3308 return *pda; 3309 } 3310 //------------------------------------------------------------------------------ 3311 void BMessage::da_dump(dyn_array *da) 3312 { 3313 entry_hdr *entry = (entry_hdr*)da; 3314 3315 printf("\tLogicalBytes=%d\n\tPhysicalBytes=%d\n\tChunkSize=%d\n\tCount=%d\n\tEntryHdrSize=%d\n", 3316 entry->fLogicalBytes, entry->fPhysicalBytes, entry->fChunkSize, entry->fCount, 3317 entry->fEntryHdrSize); 3318 printf("\tNext=%p\n\tType=%c%c%c%c\n\tNameLength=%d\n\tName=%s\n", 3319 entry->fNext, (entry->fType & 0xFF000000) >> 24, (entry->fType & 0x00FF0000) >> 16, 3320 (entry->fType & 0x0000FF00) >> 8, entry->fType & 0x000000FF, entry->fNameLength, 3321 entry->fName); 3322 3323 printf("\tData="); 3324 3325 switch (entry->fType) 3326 { 3327 case B_BOOL_TYPE: 3328 { 3329 printf("%s", *(bool*)da_find_data(entry, 0, NULL) ? "true" : "false"); 3330 3331 for (int i = 1; i < entry->fCount; i++) 3332 printf(", %s", *(bool*)da_find_data ( entry, i, NULL ) ? "true" : "false"); 3333 break; 3334 } 3335 case B_INT32_TYPE: 3336 { 3337 printf("%d", *(int32*)da_find_data(entry, 0, NULL)); 3338 3339 for (int i = 1; i < entry->fCount; i++) 3340 printf(", %d", *(int32*)da_find_data(entry, i, NULL)); 3341 break; 3342 } 3343 case B_FLOAT_TYPE: 3344 { 3345 printf("%f", *(float*)da_find_data(entry, 0, NULL)); 3346 3347 for (int i = 1; i < entry->fCount; i++) 3348 printf(", %f", *(float*)da_find_data ( entry, i, NULL)); 3349 break; 3350 } 3351 case B_STRING_TYPE: 3352 { 3353 printf("%s", da_find_data(entry, 0, NULL)); 3354 3355 for (int i = 1; i < entry->fCount; i++) 3356 printf(", %s", da_find_data(entry, i, NULL)); 3357 break; 3358 } 3359 case B_POINT_TYPE: 3360 { 3361 float *data = (float*)da_find_data(entry, 0, NULL); 3362 3363 printf("[%f,%f]", data[0], data[1]); 3364 3365 for (int i = 1; i < entry->fCount; i++) 3366 { 3367 data = (float*)da_find_data ( entry, i, NULL); 3368 printf(", [%f,%f]", data[0], data[1]); 3369 } 3370 break; 3371 } 3372 case B_RECT_TYPE: 3373 { 3374 float *data = (float*)da_find_data(entry, 0, NULL); 3375 3376 printf("[%f,%f,%f,%f]", data[0], data[1], data[2], data[3]); 3377 3378 for (int i = 1; i < entry->fCount; i++) 3379 { 3380 data = (float*)da_find_data ( entry, i, NULL); 3381 printf(", [%f,%f,%f,%f]", data[0], data[1], data[2], data[3]); 3382 } 3383 break; 3384 } 3385 } 3386 3387 printf("\n"); 3388 } 3389 //------------------------------------------------------------------------------ 3390 void BMessage::da_swap_var_sized(dyn_array *da) 3391 { 3392 } 3393 //------------------------------------------------------------------------------ 3394 void BMessage::da_swap_fixed_sized(dyn_array *da) 3395 { 3396 } 3397 //------------------------------------------------------------------------------ 3398 3399 #endif // USING_TEMPLATE_MADNESS 3400