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