1 /* 2 * Copyright 2005-2007, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Michael Lotz <mmlr@mlotz.ch> 7 */ 8 #include <Message.h> 9 #include <MessageAdapter.h> 10 #include <MessagePrivate.h> 11 #include <MessageUtils.h> 12 13 #include <TokenSpace.h> 14 15 #include <Application.h> 16 #include <AppMisc.h> 17 #include <BlockCache.h> 18 #include <Entry.h> 19 #include <MessageQueue.h> 20 #include <Messenger.h> 21 #include <Path.h> 22 #include <Point.h> 23 #include <Rect.h> 24 #include <String.h> 25 26 #include <assert.h> 27 #include <ctype.h> 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <string.h> 31 32 33 const char *B_SPECIFIER_ENTRY = "specifiers"; 34 const char *B_PROPERTY_ENTRY = "property"; 35 const char *B_PROPERTY_NAME_ENTRY = "name"; 36 37 38 BBlockCache *BMessage::sMsgCache = NULL; 39 40 41 BMessage::BMessage() 42 { 43 _InitCommon(); 44 } 45 46 47 BMessage::BMessage(BMessage *other) 48 { 49 _InitCommon(); 50 *this = *other; 51 } 52 53 54 BMessage::BMessage(uint32 _what) 55 { 56 _InitCommon(); 57 fHeader->what = what = _what; 58 } 59 60 61 BMessage::BMessage(const BMessage &other) 62 { 63 _InitCommon(); 64 *this = other; 65 } 66 67 68 BMessage::~BMessage() 69 { 70 _Clear(); 71 } 72 73 74 BMessage & 75 BMessage::operator=(const BMessage &other) 76 { 77 _Clear(); 78 79 fHeader = (message_header *)malloc(sizeof(message_header)); 80 memcpy(fHeader, other.fHeader, sizeof(message_header)); 81 82 // Clear some header flags inherited from the original message that don't 83 // apply to the clone. 84 fHeader->flags &= ~(MESSAGE_FLAG_REPLY_REQUIRED | MESSAGE_FLAG_REPLY_DONE 85 | MESSAGE_FLAG_IS_REPLY | MESSAGE_FLAG_WAS_DELIVERED 86 | MESSAGE_FLAG_WAS_DROPPED | MESSAGE_FLAG_PASS_BY_AREA); 87 // Note, that BeOS R5 seems to keep the reply info. 88 89 if (fHeader->fields_size > 0) { 90 fFields = (field_header *)malloc(fHeader->fields_size); 91 memcpy(fFields, other.fFields, fHeader->fields_size); 92 } 93 94 if (fHeader->data_size > 0) { 95 fData = (uint8 *)malloc(fHeader->data_size); 96 memcpy(fData, other.fData, fHeader->data_size); 97 } 98 99 fHeader->shared_area = -1; 100 fHeader->fields_available = 0; 101 fHeader->data_available = 0; 102 fHeader->what = what = other.what; 103 104 return *this; 105 } 106 107 108 void * 109 BMessage::operator new(size_t size) 110 { 111 if (!sMsgCache) 112 sMsgCache = new BBlockCache(10, sizeof(BMessage), B_OBJECT_CACHE); 113 114 return sMsgCache->Get(size); 115 } 116 117 118 void * 119 BMessage::operator new(size_t, void *pointer) 120 { 121 return pointer; 122 } 123 124 125 void 126 BMessage::operator delete(void *pointer, size_t size) 127 { 128 sMsgCache->Save(pointer, size); 129 } 130 131 132 status_t 133 BMessage::_InitCommon() 134 { 135 what = 0; 136 137 fHeader = NULL; 138 fFields = NULL; 139 fData = NULL; 140 141 fOriginal = NULL; 142 fQueueLink = NULL; 143 144 return _InitHeader(); 145 } 146 147 148 status_t 149 BMessage::_InitHeader() 150 { 151 fHeader = (message_header *)malloc(sizeof(message_header)); 152 memset(fHeader, 0, sizeof(message_header) - sizeof(fHeader->hash_table)); 153 154 fHeader->format = MESSAGE_FORMAT_HAIKU; 155 fHeader->flags = MESSAGE_FLAG_VALID; 156 fHeader->what = what; 157 fHeader->current_specifier = -1; 158 fHeader->shared_area = -1; 159 160 fHeader->target = B_NULL_TOKEN; 161 fHeader->reply_target = B_NULL_TOKEN; 162 fHeader->reply_port = -1; 163 fHeader->reply_team = -1; 164 165 // initializing the hash table to -1 because 0 is a valid index 166 fHeader->hash_table_size = MESSAGE_BODY_HASH_TABLE_SIZE; 167 memset(&fHeader->hash_table, 255, sizeof(fHeader->hash_table)); 168 return B_OK; 169 } 170 171 172 status_t 173 BMessage::_Clear() 174 { 175 free(fHeader); 176 fHeader = NULL; 177 free(fFields); 178 fFields = NULL; 179 free(fData); 180 fData = NULL; 181 182 delete fOriginal; 183 fOriginal = NULL; 184 185 return B_OK; 186 } 187 188 189 status_t 190 BMessage::GetInfo(type_code typeRequested, int32 index, char **nameFound, 191 type_code *typeFound, int32 *countFound) const 192 { 193 if (typeRequested == B_ANY_TYPE) { 194 if (index >= fHeader->field_count) 195 return B_BAD_INDEX; 196 197 if (nameFound) 198 *nameFound = (char *)fData + fFields[index].offset; 199 if (typeFound) 200 *typeFound = fFields[index].type; 201 if (countFound) 202 *countFound = fFields[index].count; 203 return B_OK; 204 } 205 206 int32 counter = -1; 207 field_header *field = fFields; 208 for (int32 i = 0; i < fHeader->field_count; i++, field++) { 209 if (field->type == typeRequested) 210 counter++; 211 212 if (counter == index) { 213 if (nameFound) 214 *nameFound = (char *)fData + field->offset; 215 if (typeFound) 216 *typeFound = field->type; 217 if (countFound) 218 *countFound = field->count; 219 return B_OK; 220 } 221 } 222 223 if (counter == -1) 224 return B_BAD_TYPE; 225 226 return B_BAD_INDEX; 227 } 228 229 230 status_t 231 BMessage::GetInfo(const char *name, type_code *typeFound, int32 *countFound) 232 const 233 { 234 if (countFound) 235 *countFound = 0; 236 237 field_header *field = NULL; 238 status_t result = _FindField(name, B_ANY_TYPE, &field); 239 if (result < B_OK || !field) 240 return result; 241 242 if (typeFound) 243 *typeFound = field->type; 244 if (countFound) 245 *countFound = field->count; 246 247 return B_OK; 248 } 249 250 251 status_t 252 BMessage::GetInfo(const char *name, type_code *typeFound, bool *fixedSize) 253 const 254 { 255 field_header *field = NULL; 256 status_t result = _FindField(name, B_ANY_TYPE, &field); 257 if (result < B_OK || !field) 258 return result; 259 260 if (typeFound) 261 *typeFound = field->type; 262 if (fixedSize) 263 *fixedSize = field->flags & FIELD_FLAG_FIXED_SIZE; 264 265 return B_OK; 266 } 267 268 269 int32 270 BMessage::CountNames(type_code type) const 271 { 272 if (type == B_ANY_TYPE) 273 return fHeader->field_count; 274 275 int32 count = 0; 276 field_header *field = fFields; 277 for (int32 i = 0; i < fHeader->field_count; i++, field++) { 278 if (field->type == type) 279 count++; 280 } 281 282 return count; 283 } 284 285 286 bool 287 BMessage::IsEmpty() const 288 { 289 return fHeader->field_count == 0; 290 } 291 292 293 bool 294 BMessage::IsSystem() const 295 { 296 char a = char(what >> 24); 297 char b = char(what >> 16); 298 char c = char(what >> 8); 299 char d = char(what); 300 301 // The BeBook says: 302 // ... we've adopted a strict convention for assigning values to all 303 // Be-defined constants. The value assigned will always be formed by 304 // combining four characters into a multicharacter constant, with the 305 // characters limited to uppercase letters and the underbar 306 // Between that and what's in AppDefs.h, this algo seems like a safe bet: 307 if (a == '_' && isupper(b) && isupper(c) && isupper(d)) 308 return true; 309 310 return false; 311 } 312 313 314 bool 315 BMessage::IsReply() const 316 { 317 return fHeader->flags & MESSAGE_FLAG_IS_REPLY; 318 } 319 320 321 template<typename Type> static uint8 * 322 print_to_stream_type(uint8* pointer) 323 { 324 Type *item = (Type *)pointer; 325 item->PrintToStream(); 326 return (uint8 *)(item+1); 327 } 328 329 330 template<typename Type> static uint8 * 331 print_type(const char* format, uint8* pointer) 332 { 333 Type *item = (Type *)pointer; 334 printf(format, *item, *item); 335 return (uint8 *)(item+1); 336 } 337 338 339 void 340 BMessage::PrintToStream() const 341 { 342 _PrintToStream(""); 343 printf("}\n"); 344 } 345 346 347 void 348 BMessage::_PrintToStream(const char* indent) const 349 { 350 int32 value = B_BENDIAN_TO_HOST_INT32(what); 351 printf("BMessage("); 352 if (isprint(*(char *)&value)) { 353 printf("'%.4s'", (char *)&value); 354 } else 355 printf("0x%lx", what); 356 printf(") {\n"); 357 358 field_header *field = fFields; 359 for (int32 i = 0; i < fHeader->field_count; i++, field++) { 360 value = B_BENDIAN_TO_HOST_INT32(field->type); 361 ssize_t size = 0; 362 if (field->flags & FIELD_FLAG_FIXED_SIZE) 363 size = field->data_size / field->count; 364 365 uint8 *pointer = fData + field->offset + field->name_length; 366 367 for (int32 j=0; j<field->count; j++) { 368 if (field->count == 1) { 369 printf("%s %s = ", indent, 370 (char *)(fData + field->offset)); 371 } else { 372 printf("%s %s[%ld] = ", indent, 373 (char *)(fData + field->offset), j); 374 } 375 376 switch (field->type) { 377 case B_RECT_TYPE: 378 pointer = print_to_stream_type<BRect>(pointer); 379 break; 380 381 case B_POINT_TYPE: 382 pointer = print_to_stream_type<BPoint>(pointer); 383 break; 384 385 case B_STRING_TYPE: { 386 ssize_t size = *(ssize_t *)pointer; 387 pointer += sizeof(ssize_t); 388 printf("string(\"%s\", %ld bytes)\n", (char *)pointer, size); 389 pointer += size; 390 break; 391 } 392 393 case B_INT8_TYPE: 394 pointer = print_type<int8>("int8(0x%hx or %d or \'%.1s\')\n", pointer); 395 break; 396 397 case B_INT16_TYPE: 398 pointer = print_type<int16>("int16 (0x%x or %d)\n", pointer); 399 break; 400 401 case B_INT32_TYPE: 402 pointer = print_type<int32>("int32(0x%lx or %ld)\n", pointer); 403 break; 404 405 case B_INT64_TYPE: 406 pointer = print_type<int64>("int64(0x%Lx or %Ld)\n", pointer); 407 break; 408 409 case B_BOOL_TYPE: 410 printf("bool(%s)\n", *((bool *)pointer)!= 0 ? "true" : "false"); 411 pointer += sizeof(bool); 412 break; 413 414 case B_FLOAT_TYPE: 415 pointer = print_type<float>("float(%.4f)\n", pointer); 416 break; 417 418 case B_DOUBLE_TYPE: 419 pointer = print_type<double>("double(%.8f)\n", pointer); 420 break; 421 422 case B_REF_TYPE: { 423 ssize_t size = *(ssize_t *)pointer; 424 pointer += sizeof(ssize_t); 425 entry_ref ref; 426 BPrivate::entry_ref_unflatten(&ref, (char *)pointer, size); 427 428 printf("entry_ref(device=%ld, directory=%lld, name=\"%s\", ", 429 ref.device, ref.directory, ref.name); 430 431 BPath path(&ref); 432 printf("path=\"%s\")\n", path.Path()); 433 pointer += size; 434 break; 435 } 436 437 case B_MESSAGE_TYPE: 438 { 439 char buffer[1024]; 440 sprintf(buffer, "%s ", indent); 441 442 BMessage message; 443 const ssize_t size = *(const ssize_t *)pointer; 444 pointer += sizeof(ssize_t); 445 if (message.Unflatten((const char *)pointer)!=B_OK) { 446 fprintf(stderr, "couldn't unflatten item %ld\n", i); 447 break; 448 } 449 message._PrintToStream(buffer); 450 printf("%s }\n", indent); 451 pointer += size; 452 break; 453 } 454 455 default: { 456 printf("(type = '%.4s')(size = %ld)\n", (char *)&value, size); 457 } 458 } 459 } 460 } 461 } 462 463 464 status_t 465 BMessage::Rename(const char *oldEntry, const char *newEntry) 466 { 467 if (!oldEntry || !newEntry) 468 return B_BAD_VALUE; 469 470 uint32 hash = _HashName(oldEntry) % fHeader->hash_table_size; 471 int32 *nextField = &fHeader->hash_table[hash]; 472 473 while (*nextField >= 0) { 474 field_header *field = &fFields[*nextField]; 475 476 if (strncmp((const char *)(fData + field->offset), oldEntry, 477 field->name_length) == 0) { 478 // nextField points to the field for oldEntry, save it and unlink 479 int32 index = *nextField; 480 *nextField = field->next_field; 481 field->next_field = -1; 482 483 hash = _HashName(newEntry) % fHeader->hash_table_size; 484 nextField = &fHeader->hash_table[hash]; 485 while (*nextField >= 0) 486 nextField = &fFields[*nextField].next_field; 487 *nextField = index; 488 489 int32 oldLength = field->name_length; 490 field->name_length = strlen(newEntry) + 1; 491 _ResizeData(field->offset, field->name_length - oldLength); 492 memcpy(fData + field->offset, newEntry, field->name_length); 493 return B_OK; 494 } 495 496 nextField = &field->next_field; 497 } 498 499 return B_NAME_NOT_FOUND; 500 } 501 502 503 bool 504 BMessage::WasDelivered() const 505 { 506 return fHeader->flags & MESSAGE_FLAG_WAS_DELIVERED; 507 } 508 509 510 bool 511 BMessage::IsSourceWaiting() const 512 { 513 return (fHeader->flags & MESSAGE_FLAG_REPLY_REQUIRED) 514 && !(fHeader->flags & MESSAGE_FLAG_REPLY_DONE); 515 } 516 517 518 BMessenger 519 BMessage::ReturnAddress() const 520 { 521 return BMessenger(); 522 } 523 524 525 const BMessage * 526 BMessage::Previous() const 527 { 528 /* ToDo: test if the "_previous_" field is used in R5 */ 529 if (!fOriginal) { 530 fOriginal = new BMessage(); 531 532 if (FindMessage("_previous_", fOriginal) != B_OK) { 533 delete fOriginal; 534 fOriginal = NULL; 535 } 536 } 537 538 return fOriginal; 539 } 540 541 542 bool 543 BMessage::WasDropped() const 544 { 545 return fHeader->flags & MESSAGE_FLAG_WAS_DROPPED; 546 } 547 548 549 BPoint 550 BMessage::DropPoint(BPoint *offset) const 551 { 552 if (offset) 553 *offset = FindPoint("_drop_offset_"); 554 555 return FindPoint("_drop_point_"); 556 } 557 558 559 ssize_t 560 BMessage::FlattenedSize() const 561 { 562 return BPrivate::MessageAdapter::FlattenedSize(MESSAGE_FORMAT_R5, this); 563 } 564 565 566 status_t 567 BMessage::Flatten(char *buffer, ssize_t size) const 568 { 569 return BPrivate::MessageAdapter::Flatten(MESSAGE_FORMAT_R5, this, buffer, 570 &size); 571 } 572 573 574 status_t 575 BMessage::Flatten(BDataIO *stream, ssize_t *size) const 576 { 577 return BPrivate::MessageAdapter::Flatten(MESSAGE_FORMAT_R5, this, stream, 578 size); 579 } 580 581 582 ssize_t 583 BMessage::_NativeFlattenedSize() const 584 { 585 return sizeof(message_header) + fHeader->fields_size + fHeader->data_size; 586 } 587 588 589 status_t 590 BMessage::_NativeFlatten(char *buffer, ssize_t size) const 591 { 592 if (!buffer) 593 return B_BAD_VALUE; 594 595 if (!fHeader) 596 return B_NO_INIT; 597 598 /* we have to sync the what code as it is a public member */ 599 fHeader->what = what; 600 601 memcpy(buffer, fHeader, min_c(sizeof(message_header), (size_t)size)); 602 buffer += sizeof(message_header); 603 size -= sizeof(message_header); 604 605 memcpy(buffer, fFields, min_c(fHeader->fields_size, size)); 606 buffer += fHeader->fields_size; 607 size -= fHeader->fields_size; 608 609 memcpy(buffer, fData, min_c(fHeader->data_size, size)); 610 if (size >= fHeader->data_size) 611 return B_OK; 612 613 return B_NO_MEMORY; 614 } 615 616 617 status_t 618 BMessage::_NativeFlatten(BDataIO *stream, ssize_t *size) const 619 { 620 if (!stream) 621 return B_BAD_VALUE; 622 623 if (!fHeader) 624 return B_NO_INIT; 625 626 /* we have to sync the what code as it is a public member */ 627 fHeader->what = what; 628 629 ssize_t result1 = stream->Write(fHeader, sizeof(message_header)); 630 if (result1 != sizeof(message_header)) 631 return (result1 >= 0 ? B_ERROR : result1); 632 633 ssize_t result2 = 0; 634 if (fHeader->fields_size > 0) { 635 result2 = stream->Write(fFields, fHeader->fields_size); 636 if (result2 != fHeader->fields_size) 637 return (result2 >= 0 ? B_ERROR : result2); 638 } 639 640 ssize_t result3 = 0; 641 if (fHeader->data_size > 0) { 642 result3 = stream->Write(fData, fHeader->data_size); 643 if (result3 != fHeader->data_size) 644 return (result3 >= 0 ? B_ERROR : result3); 645 } 646 647 if (size) 648 *size = result1 + result2 + result3; 649 650 return B_OK; 651 } 652 653 654 status_t 655 BMessage::Unflatten(const char *flatBuffer) 656 { 657 if (!flatBuffer) 658 return B_BAD_VALUE; 659 660 uint32 format = *(uint32 *)flatBuffer; 661 if (format != MESSAGE_FORMAT_HAIKU) 662 return BPrivate::MessageAdapter::Unflatten(format, this, flatBuffer); 663 664 // native message unflattening 665 666 _Clear(); 667 668 fHeader = (message_header *)malloc(sizeof(message_header)); 669 if (!fHeader) 670 return B_NO_MEMORY; 671 672 memcpy(fHeader, flatBuffer, sizeof(message_header)); 673 flatBuffer += sizeof(message_header); 674 675 if (fHeader->format != MESSAGE_FORMAT_HAIKU 676 || !(fHeader->flags & MESSAGE_FLAG_VALID)) { 677 free(fHeader); 678 fHeader = NULL; 679 _InitHeader(); 680 return B_BAD_VALUE; 681 } 682 683 fHeader->fields_available = 0; 684 fHeader->data_available = 0; 685 what = fHeader->what; 686 687 fHeader->shared_area = -1; 688 689 if (fHeader->fields_size > 0) { 690 fFields = (field_header *)malloc(fHeader->fields_size); 691 if (!fFields) 692 return B_NO_MEMORY; 693 694 memcpy(fFields, flatBuffer, fHeader->fields_size); 695 flatBuffer += fHeader->fields_size; 696 } 697 698 if (fHeader->data_size > 0) { 699 fData = (uint8 *)malloc(fHeader->data_size); 700 if (!fData) 701 return B_NO_MEMORY; 702 703 memcpy(fData, flatBuffer, fHeader->data_size); 704 } 705 706 return B_OK; 707 } 708 709 710 status_t 711 BMessage::Unflatten(BDataIO *stream) 712 { 713 if (!stream) 714 return B_BAD_VALUE; 715 716 uint32 format = 0; 717 stream->Read(&format, sizeof(uint32)); 718 if (format != MESSAGE_FORMAT_HAIKU) 719 return BPrivate::MessageAdapter::Unflatten(format, this, stream); 720 721 // native message unflattening 722 723 _Clear(); 724 725 fHeader = (message_header *)malloc(sizeof(message_header)); 726 if (!fHeader) 727 return B_NO_MEMORY; 728 729 fHeader->format = format; 730 uint8 *header = (uint8 *)fHeader; 731 ssize_t result = stream->Read(header + sizeof(uint32), 732 sizeof(message_header) - sizeof(uint32)); 733 result -= sizeof(message_header) - sizeof(uint32); 734 735 if (result != B_OK || fHeader->format != MESSAGE_FORMAT_HAIKU 736 || !(fHeader->flags & MESSAGE_FLAG_VALID)) { 737 free(fHeader); 738 fHeader = NULL; 739 _InitHeader(); 740 return B_BAD_VALUE; 741 } 742 743 fHeader->fields_available = 0; 744 fHeader->data_available = 0; 745 what = fHeader->what; 746 747 fHeader->shared_area = -1; 748 749 if (result == B_OK && fHeader->fields_size > 0) { 750 fFields = (field_header *)malloc(fHeader->fields_size); 751 if (!fFields) 752 return B_NO_MEMORY; 753 754 result = stream->Read(fFields, fHeader->fields_size); 755 result -= fHeader->fields_size; 756 } 757 758 if (result == B_OK && fHeader->data_size > 0) { 759 fData = (uint8 *)malloc(fHeader->data_size); 760 if (!fData) 761 return B_NO_MEMORY; 762 763 result = stream->Read(fData, fHeader->data_size); 764 result -= fHeader->data_size; 765 } 766 767 if (result < B_OK) 768 return B_BAD_VALUE; 769 770 return B_OK; 771 } 772 773 774 status_t 775 BMessage::AddSpecifier(const char *property) 776 { 777 BMessage message(B_DIRECT_SPECIFIER); 778 status_t result = message.AddString(B_PROPERTY_ENTRY, property); 779 if (result < B_OK) 780 return result; 781 782 return AddSpecifier(&message); 783 } 784 785 786 status_t 787 BMessage::AddSpecifier(const char *property, int32 index) 788 { 789 BMessage message(B_INDEX_SPECIFIER); 790 status_t result = message.AddString(B_PROPERTY_ENTRY, property); 791 if (result < B_OK) 792 return result; 793 794 result = message.AddInt32("index", index); 795 if (result < B_OK) 796 return result; 797 798 return AddSpecifier(&message); 799 } 800 801 802 status_t 803 BMessage::AddSpecifier(const char *property, int32 index, int32 range) 804 { 805 if (range < 0) 806 return B_BAD_VALUE; 807 808 BMessage message(B_RANGE_SPECIFIER); 809 status_t result = message.AddString(B_PROPERTY_ENTRY, property); 810 if (result < B_OK) 811 return result; 812 813 result = message.AddInt32("index", index); 814 if (result < B_OK) 815 return result; 816 817 result = message.AddInt32("range", range); 818 if (result < B_OK) 819 return result; 820 821 return AddSpecifier(&message); 822 } 823 824 825 status_t 826 BMessage::AddSpecifier(const char *property, const char *name) 827 { 828 BMessage message(B_NAME_SPECIFIER); 829 status_t result = message.AddString(B_PROPERTY_ENTRY, property); 830 if (result < B_OK) 831 return result; 832 833 result = message.AddString(B_PROPERTY_NAME_ENTRY, name); 834 if (result < B_OK) 835 return result; 836 837 return AddSpecifier(&message); 838 } 839 840 841 status_t 842 BMessage::AddSpecifier(const BMessage *specifier) 843 { 844 status_t result = AddMessage(B_SPECIFIER_ENTRY, specifier); 845 if (result < B_OK) 846 return result; 847 848 fHeader->current_specifier++; 849 fHeader->flags |= MESSAGE_FLAG_HAS_SPECIFIERS; 850 return B_OK; 851 } 852 853 854 status_t 855 BMessage::SetCurrentSpecifier(int32 index) 856 { 857 if (index < 0) 858 return B_BAD_INDEX; 859 860 type_code type; 861 int32 count; 862 status_t result = GetInfo(B_SPECIFIER_ENTRY, &type, &count); 863 if (result < B_OK) 864 return result; 865 866 if (index > count) 867 return B_BAD_INDEX; 868 869 fHeader->current_specifier = index; 870 return B_OK; 871 } 872 873 874 status_t 875 BMessage::GetCurrentSpecifier(int32 *index, BMessage *specifier, int32 *what, 876 const char **property) const 877 { 878 if (index) 879 *index = fHeader->current_specifier; 880 881 if (fHeader->current_specifier < 0 882 || !(fHeader->flags & MESSAGE_FLAG_WAS_DELIVERED)) 883 return B_BAD_SCRIPT_SYNTAX; 884 885 if (specifier) { 886 if (FindMessage(B_SPECIFIER_ENTRY, fHeader->current_specifier, 887 specifier) < B_OK) 888 return B_BAD_SCRIPT_SYNTAX; 889 890 if (what) 891 *what = specifier->what; 892 893 if (property) { 894 if (specifier->FindString(B_PROPERTY_ENTRY, property) < B_OK) 895 return B_BAD_SCRIPT_SYNTAX; 896 } 897 } 898 899 return B_OK; 900 } 901 902 903 bool 904 BMessage::HasSpecifiers() const 905 { 906 return fHeader->flags & MESSAGE_FLAG_HAS_SPECIFIERS; 907 } 908 909 910 status_t 911 BMessage::PopSpecifier() 912 { 913 if (fHeader->current_specifier < 0 || 914 !(fHeader->flags & MESSAGE_FLAG_WAS_DELIVERED)) 915 return B_BAD_VALUE; 916 917 if (fHeader->current_specifier >= 0) 918 fHeader->current_specifier--; 919 920 return B_OK; 921 } 922 923 924 status_t 925 BMessage::_ResizeData(int32 offset, int32 change) 926 { 927 if (change == 0) 928 return B_OK; 929 930 /* optimize for the most usual case: appending data */ 931 if (offset < fHeader->data_size) { 932 field_header *field = fFields; 933 for (int32 i = 0; i < fHeader->field_count; i++, field++) { 934 if (field->offset >= offset) 935 field->offset += change; 936 } 937 } 938 939 if (change > 0) { 940 if (fHeader->data_available >= change) { 941 if (offset < fHeader->data_size) { 942 memmove(fData + offset + change, fData + offset, 943 fHeader->data_size - offset); 944 } 945 946 fHeader->data_available -= change; 947 fHeader->data_size += change; 948 return B_OK; 949 } 950 951 ssize_t size = fHeader->data_size * 2; 952 size = min_c(size, fHeader->data_size + MAX_DATA_PREALLOCATION); 953 size = max_c(size, fHeader->data_size + change); 954 955 fData = (uint8 *)realloc(fData, size); 956 if (!fData) 957 return B_NO_MEMORY; 958 959 if (offset < fHeader->data_size) { 960 memmove(fData + offset + change, fData + offset, 961 fHeader->data_size - offset); 962 } 963 964 fHeader->data_size += change; 965 fHeader->data_available = size - fHeader->data_size; 966 } else { 967 ssize_t length = fHeader->data_size - offset + change; 968 if (length > 0) 969 memmove(fData + offset, fData + offset - change, length); 970 971 fHeader->data_size += change; 972 fHeader->data_available -= change; 973 974 if (fHeader->data_available > MAX_DATA_PREALLOCATION) { 975 ssize_t available = MAX_DATA_PREALLOCATION / 2; 976 fData = (uint8 *)realloc(fData, fHeader->data_size + available); 977 if (!fData) 978 return B_NO_MEMORY; 979 980 fHeader->data_available = available; 981 } 982 } 983 984 return B_OK; 985 } 986 987 988 uint32 989 BMessage::_HashName(const char *name) const 990 { 991 char ch; 992 uint32 result = 0; 993 994 while ((ch = *name++) != 0) { 995 result = (result << 7) ^ (result >> 24); 996 result ^= ch; 997 } 998 999 result ^= result << 12; 1000 return result; 1001 } 1002 1003 1004 status_t 1005 BMessage::_FindField(const char *name, type_code type, field_header **result) const 1006 { 1007 if (!name) 1008 return B_BAD_VALUE; 1009 1010 if (!fHeader || !fFields || !fData) 1011 return B_NAME_NOT_FOUND; 1012 1013 uint32 hash = _HashName(name) % fHeader->hash_table_size; 1014 int32 nextField = fHeader->hash_table[hash]; 1015 1016 while (nextField >= 0) { 1017 field_header *field = &fFields[nextField]; 1018 1019 if (strncmp((const char *)(fData + field->offset), name, 1020 field->name_length) == 0) { 1021 if (type != B_ANY_TYPE && field->type != type) 1022 return B_BAD_TYPE; 1023 1024 *result = field; 1025 return B_OK; 1026 } 1027 1028 nextField = field->next_field; 1029 } 1030 1031 return B_NAME_NOT_FOUND; 1032 } 1033 1034 1035 status_t 1036 BMessage::_AddField(const char *name, type_code type, bool isFixedSize, 1037 field_header **result) 1038 { 1039 if (!fHeader) 1040 return B_ERROR; 1041 1042 if (fHeader->fields_available <= 0) { 1043 int32 count = fHeader->field_count * 2 + 1; 1044 count = min_c(count, fHeader->field_count + MAX_FIELD_PREALLOCATION); 1045 1046 fFields = (field_header *)realloc(fFields, count * sizeof(field_header)); 1047 if (!fFields) 1048 return B_NO_MEMORY; 1049 1050 fHeader->fields_available = count - fHeader->field_count; 1051 } 1052 1053 uint32 hash = _HashName(name) % fHeader->hash_table_size; 1054 1055 int32 *nextField = &fHeader->hash_table[hash]; 1056 while (*nextField >= 0) 1057 nextField = &fFields[*nextField].next_field; 1058 *nextField = fHeader->field_count; 1059 1060 field_header *field = &fFields[fHeader->field_count]; 1061 field->type = type; 1062 field->flags = FIELD_FLAG_VALID; 1063 if (isFixedSize) 1064 field->flags |= FIELD_FLAG_FIXED_SIZE; 1065 1066 field->count = 0; 1067 field->data_size = 0; 1068 field->allocated = 0; 1069 field->next_field = -1; 1070 field->offset = fHeader->data_size; 1071 field->name_length = strlen(name) + 1; 1072 _ResizeData(field->offset, field->name_length); 1073 memcpy(fData + field->offset, name, field->name_length); 1074 1075 fHeader->fields_available--; 1076 fHeader->fields_size += sizeof(field_header); 1077 fHeader->field_count++; 1078 *result = field; 1079 return B_OK; 1080 } 1081 1082 1083 status_t 1084 BMessage::_RemoveField(field_header *field) 1085 { 1086 int32 index = ((uint8 *)field - (uint8 *)fFields) / sizeof(field_header); 1087 int32 nextField = field->next_field; 1088 if (nextField > index) 1089 nextField--; 1090 1091 int32 *value = fHeader->hash_table; 1092 for (int32 i = 0; i < fHeader->hash_table_size; i++, value++) { 1093 if (*value > index) 1094 *value -= 1; 1095 else if (*value == index) 1096 *value = nextField; 1097 } 1098 1099 field_header *other = fFields; 1100 for (int32 i = 0; i < fHeader->field_count; i++, other++) { 1101 if (other->next_field > index) 1102 other->next_field--; 1103 else if (other->next_field == index) 1104 other->next_field = nextField; 1105 } 1106 1107 _ResizeData(field->offset, -(field->data_size + field->name_length)); 1108 1109 ssize_t size = fHeader->fields_size - (index + 1) * sizeof(field_header); 1110 memmove(fFields + index, fFields + index + 1, size); 1111 fHeader->fields_size -= sizeof(field_header); 1112 fHeader->field_count--; 1113 fHeader->fields_available++; 1114 1115 if (fHeader->fields_available > MAX_FIELD_PREALLOCATION) { 1116 ssize_t available = MAX_FIELD_PREALLOCATION / 2; 1117 fFields = (field_header *)realloc(fFields, fHeader->fields_size 1118 + available * sizeof(field_header)); 1119 if (!fFields) 1120 return B_NO_MEMORY; 1121 1122 fHeader->fields_available = available; 1123 } 1124 1125 return B_OK; 1126 } 1127 1128 1129 status_t 1130 BMessage::AddData(const char *name, type_code type, const void *data, 1131 ssize_t numBytes, bool isFixedSize, int32 count) 1132 { 1133 if (numBytes <= 0 || !data) 1134 return B_BAD_VALUE; 1135 1136 field_header *field = NULL; 1137 status_t result = _FindField(name, type, &field); 1138 if (result == B_NAME_NOT_FOUND) 1139 result = _AddField(name, type, isFixedSize, &field); 1140 1141 if (result < B_OK || !field) 1142 return result; 1143 1144 uint32 offset = field->offset + field->name_length + field->data_size; 1145 if (field->flags & FIELD_FLAG_FIXED_SIZE) { 1146 if (field->count) { 1147 ssize_t size = field->data_size / field->count; 1148 if (size != numBytes) 1149 return B_BAD_VALUE; 1150 } 1151 1152 _ResizeData(offset, numBytes); 1153 memcpy(fData + offset, data, numBytes); 1154 field->data_size += numBytes; 1155 } else { 1156 int32 change = numBytes + sizeof(numBytes); 1157 _ResizeData(offset, change); 1158 memcpy(fData + offset, &numBytes, sizeof(numBytes)); 1159 memcpy(fData + offset + sizeof(numBytes), data, numBytes); 1160 field->data_size += change; 1161 } 1162 1163 field->count++; 1164 return B_OK; 1165 } 1166 1167 1168 status_t 1169 BMessage::RemoveData(const char *name, int32 index) 1170 { 1171 if (index < 0) 1172 return B_BAD_VALUE; 1173 1174 field_header *field = NULL; 1175 status_t result = _FindField(name, B_ANY_TYPE, &field); 1176 1177 if (result < B_OK) 1178 return result; 1179 1180 if (!field) 1181 return B_ERROR; 1182 1183 if (index >= field->count) 1184 return B_BAD_INDEX; 1185 1186 if (field->count == 1) 1187 return _RemoveField(field); 1188 1189 uint32 offset = field->offset + field->name_length; 1190 if (field->flags & FIELD_FLAG_FIXED_SIZE) { 1191 ssize_t size = field->data_size / field->count; 1192 _ResizeData(offset + index * size, -size); 1193 field->data_size -= size; 1194 } else { 1195 uint8 *pointer = fData + offset; 1196 1197 for (int32 i = 0; i < index; i++) { 1198 offset += *(ssize_t *)pointer + sizeof(ssize_t); 1199 pointer = fData + offset; 1200 } 1201 1202 ssize_t currentSize = *(ssize_t *)pointer + sizeof(ssize_t); 1203 _ResizeData(offset, -currentSize); 1204 field->data_size -= currentSize; 1205 } 1206 1207 field->count--; 1208 return B_OK; 1209 } 1210 1211 1212 status_t 1213 BMessage::RemoveName(const char *name) 1214 { 1215 field_header *field = NULL; 1216 status_t result = _FindField(name, B_ANY_TYPE, &field); 1217 1218 if (result < B_OK) 1219 return result; 1220 1221 if (!field) 1222 return B_ERROR; 1223 1224 return _RemoveField(field); 1225 } 1226 1227 1228 status_t 1229 BMessage::MakeEmpty() 1230 { 1231 _Clear(); 1232 _InitHeader(); 1233 return B_OK; 1234 } 1235 1236 1237 status_t 1238 BMessage::FindData(const char *name, type_code type, int32 index, 1239 const void **data, ssize_t *numBytes) const 1240 { 1241 if (!data || !numBytes) 1242 return B_BAD_VALUE; 1243 1244 *data = NULL; 1245 field_header *field = NULL; 1246 status_t result = _FindField(name, type, &field); 1247 1248 if (result < B_OK) 1249 return result; 1250 1251 if (!field) 1252 return B_ERROR; 1253 1254 if (index >= field->count) 1255 return B_BAD_INDEX; 1256 1257 if (field->flags & FIELD_FLAG_FIXED_SIZE) { 1258 *numBytes = field->data_size / field->count; 1259 *data = fData + field->offset + field->name_length + index * *numBytes; 1260 } else { 1261 uint8 *pointer = fData + field->offset + field->name_length; 1262 1263 for (int32 i = 0; i < index; i++) 1264 pointer += *(ssize_t *)pointer + sizeof(ssize_t); 1265 1266 *numBytes = *(ssize_t *)pointer; 1267 *data = pointer + sizeof(ssize_t); 1268 } 1269 1270 return B_OK; 1271 } 1272 1273 1274 status_t 1275 BMessage::ReplaceData(const char *name, type_code type, int32 index, 1276 const void *data, ssize_t numBytes) 1277 { 1278 if (numBytes <= 0 || !data) 1279 return B_BAD_VALUE; 1280 1281 field_header *field = NULL; 1282 status_t result = _FindField(name, type, &field); 1283 1284 if (result < B_OK) 1285 return result; 1286 1287 if (!field) 1288 return B_ERROR; 1289 1290 if (index >= field->count) 1291 return B_BAD_INDEX; 1292 1293 if (field->flags & FIELD_FLAG_FIXED_SIZE) { 1294 ssize_t size = field->data_size / field->count; 1295 if (size != numBytes) 1296 return B_BAD_VALUE; 1297 1298 memcpy(fData + field->offset + field->name_length + index * size, data, 1299 size); 1300 } else { 1301 uint32 offset = field->offset + field->name_length; 1302 uint8 *pointer = fData + offset; 1303 1304 for (int32 i = 0; i < index; i++) { 1305 offset += *(ssize_t *)pointer + sizeof(ssize_t); 1306 pointer = fData + offset; 1307 } 1308 1309 ssize_t currentSize = *(ssize_t *)pointer; 1310 int32 change = numBytes - currentSize; 1311 _ResizeData(offset, change); 1312 memcpy(fData + offset, &numBytes, sizeof(numBytes)); 1313 memcpy(fData + offset + sizeof(numBytes), data, numBytes); 1314 field->data_size += change; 1315 } 1316 1317 return B_OK; 1318 } 1319 1320 1321 bool 1322 BMessage::HasData(const char *name, type_code type, int32 index) const 1323 { 1324 field_header *field = NULL; 1325 status_t result = _FindField(name, type, &field); 1326 1327 if (result < B_OK) 1328 return false; 1329 1330 if (!field) 1331 return false; 1332 1333 if (index >= field->count) 1334 return false; 1335 1336 return true; 1337 } 1338 1339 1340 void 1341 BMessage::_StaticCacheCleanup() 1342 { 1343 delete sMsgCache; 1344 sMsgCache = NULL; 1345 } 1346 1347 1348 /* Relay functions from here on (Add... -> AddData, Find... -> FindData) */ 1349 1350 #define DEFINE_FUNCTIONS(type, typeName, typeCode) \ 1351 status_t \ 1352 BMessage::Add##typeName(const char *name, type val) \ 1353 { \ 1354 return AddData(name, typeCode, &val, sizeof(type), true); \ 1355 } \ 1356 \ 1357 status_t \ 1358 BMessage::Find##typeName(const char *name, type *p) const \ 1359 { \ 1360 void *ptr = NULL; \ 1361 ssize_t bytes = 0; \ 1362 status_t error = B_OK; \ 1363 \ 1364 *p = type(); \ 1365 error = FindData(name, typeCode, 0, (const void **)&ptr, &bytes); \ 1366 \ 1367 if (error == B_OK) \ 1368 memcpy(p, ptr, sizeof(type)); \ 1369 \ 1370 return error; \ 1371 } \ 1372 \ 1373 status_t \ 1374 BMessage::Find##typeName(const char *name, int32 index, type *p) const \ 1375 { \ 1376 void *ptr = NULL; \ 1377 ssize_t bytes = 0; \ 1378 status_t error = B_OK; \ 1379 \ 1380 *p = type(); \ 1381 error = FindData(name, typeCode, index, (const void **)&ptr, &bytes); \ 1382 \ 1383 if (error == B_OK) \ 1384 memcpy(p, ptr, sizeof(type)); \ 1385 \ 1386 return error; \ 1387 } \ 1388 \ 1389 status_t \ 1390 BMessage::Replace##typeName(const char *name, type val) \ 1391 { \ 1392 return ReplaceData(name, typeCode, 0, &val, sizeof(type)); \ 1393 } \ 1394 \ 1395 status_t \ 1396 BMessage::Replace##typeName(const char *name, int32 index, type val) \ 1397 { \ 1398 return ReplaceData(name, typeCode, index, &val, sizeof(type)); \ 1399 } \ 1400 \ 1401 bool \ 1402 BMessage::Has##typeName(const char *name, int32 index) const \ 1403 { \ 1404 return HasData(name, typeCode, index); \ 1405 } 1406 1407 DEFINE_FUNCTIONS(BPoint, Point, B_POINT_TYPE); 1408 DEFINE_FUNCTIONS(BRect, Rect, B_RECT_TYPE); 1409 DEFINE_FUNCTIONS(int8, Int8, B_INT8_TYPE); 1410 DEFINE_FUNCTIONS(int16, Int16, B_INT16_TYPE); 1411 DEFINE_FUNCTIONS(int32, Int32, B_INT32_TYPE); 1412 DEFINE_FUNCTIONS(int64, Int64, B_INT64_TYPE); 1413 DEFINE_FUNCTIONS(bool, Bool, B_BOOL_TYPE); 1414 DEFINE_FUNCTIONS(float, Float, B_FLOAT_TYPE); 1415 DEFINE_FUNCTIONS(double, Double, B_DOUBLE_TYPE); 1416 1417 #undef DEFINE_FUNCTIONS 1418 1419 #define DEFINE_HAS_FUNCTION(typeName, typeCode) \ 1420 bool \ 1421 BMessage::Has##typeName(const char *name, int32 index) const \ 1422 { \ 1423 return HasData(name, typeCode, index); \ 1424 } 1425 1426 DEFINE_HAS_FUNCTION(String, B_STRING_TYPE); 1427 DEFINE_HAS_FUNCTION(Pointer, B_POINTER_TYPE); 1428 DEFINE_HAS_FUNCTION(Messenger, B_MESSENGER_TYPE); 1429 DEFINE_HAS_FUNCTION(Ref, B_REF_TYPE); 1430 DEFINE_HAS_FUNCTION(Message, B_MESSAGE_TYPE); 1431 1432 #undef DEFINE_HAS_FUNCTION 1433 1434 #define DEFINE_LAZY_FIND_FUNCTION(type, typeName, initialize) \ 1435 type \ 1436 BMessage::Find##typeName(const char *name, int32 index) const \ 1437 { \ 1438 type val = initialize; \ 1439 Find##typeName(name, index, &val); \ 1440 return val; \ 1441 } 1442 1443 DEFINE_LAZY_FIND_FUNCTION(BRect, Rect, BRect()); 1444 DEFINE_LAZY_FIND_FUNCTION(BPoint, Point, BPoint()); 1445 DEFINE_LAZY_FIND_FUNCTION(const char *, String, NULL); 1446 DEFINE_LAZY_FIND_FUNCTION(int8, Int8, 0); 1447 DEFINE_LAZY_FIND_FUNCTION(int16, Int16, 0); 1448 DEFINE_LAZY_FIND_FUNCTION(int32, Int32, 0); 1449 DEFINE_LAZY_FIND_FUNCTION(int64, Int64, 0); 1450 DEFINE_LAZY_FIND_FUNCTION(bool, Bool, false); 1451 DEFINE_LAZY_FIND_FUNCTION(float, Float, 0); 1452 DEFINE_LAZY_FIND_FUNCTION(double, Double, 0); 1453 1454 #undef DEFINE_LAZY_FIND_FUNCTION 1455 1456 status_t 1457 BMessage::AddString(const char *name, const char *string) 1458 { 1459 return AddData(name, B_STRING_TYPE, string, string ? strlen(string) + 1 : 0, false); 1460 } 1461 1462 1463 status_t 1464 BMessage::AddString(const char *name, const BString &string) 1465 { 1466 return AddData(name, B_STRING_TYPE, string.String(), string.Length() + 1, false); 1467 } 1468 1469 1470 status_t 1471 BMessage::AddPointer(const char *name, const void *pointer) 1472 { 1473 return AddData(name, B_POINTER_TYPE, &pointer, sizeof(pointer), true); 1474 } 1475 1476 1477 status_t 1478 BMessage::AddMessenger(const char *name, BMessenger messenger) 1479 { 1480 return AddData(name, B_MESSENGER_TYPE, &messenger, sizeof(messenger), true); 1481 } 1482 1483 1484 status_t 1485 BMessage::AddRef(const char *name, const entry_ref *ref) 1486 { 1487 size_t size = sizeof(entry_ref) + B_PATH_NAME_LENGTH; 1488 char buffer[size]; 1489 1490 status_t error = BPrivate::entry_ref_flatten(buffer, &size, ref); 1491 1492 if (error >= B_OK) 1493 error = AddData(name, B_REF_TYPE, buffer, size, false); 1494 1495 return error; 1496 } 1497 1498 1499 status_t 1500 BMessage::AddMessage(const char *name, const BMessage *message) 1501 { 1502 /* ToDo: This and the following functions waste time by allocating and 1503 copying an extra buffer. Functions can be added that return a direct 1504 pointer into the message. */ 1505 1506 ssize_t size = message->FlattenedSize(); 1507 char buffer[size]; 1508 1509 status_t error = message->Flatten(buffer, size); 1510 1511 if (error >= B_OK) 1512 error = AddData(name, B_MESSAGE_TYPE, &buffer, size, false); 1513 1514 return error; 1515 } 1516 1517 1518 status_t 1519 BMessage::AddFlat(const char *name, BFlattenable *object, int32 count) 1520 { 1521 ssize_t size = object->FlattenedSize(); 1522 char buffer[size]; 1523 1524 status_t error = object->Flatten(buffer, size); 1525 1526 if (error >= B_OK) 1527 error = AddData(name, object->TypeCode(), &buffer, size, false); 1528 1529 return error; 1530 } 1531 1532 1533 status_t 1534 BMessage::FindString(const char *name, const char **string) const 1535 { 1536 return FindString(name, 0, string); 1537 } 1538 1539 1540 status_t 1541 BMessage::FindString(const char *name, int32 index, const char **string) const 1542 { 1543 ssize_t bytes; 1544 return FindData(name, B_STRING_TYPE, index, (const void **)string, &bytes); 1545 } 1546 1547 1548 status_t 1549 BMessage::FindString(const char *name, BString *string) const 1550 { 1551 return FindString(name, 0, string); 1552 } 1553 1554 1555 status_t 1556 BMessage::FindString(const char *name, int32 index, BString *string) const 1557 { 1558 const char *cstr; 1559 status_t error = FindString(name, index, &cstr); 1560 if (error < B_OK) 1561 return error; 1562 1563 *string = cstr; 1564 return B_OK; 1565 } 1566 1567 1568 status_t 1569 BMessage::FindPointer(const char *name, void **pointer) const 1570 { 1571 return FindPointer(name, 0, pointer); 1572 } 1573 1574 1575 status_t 1576 BMessage::FindPointer(const char *name, int32 index, void **pointer) const 1577 { 1578 void **data = NULL; 1579 ssize_t size = 0; 1580 status_t error = FindData(name, B_POINTER_TYPE, index, 1581 (const void **)&data, &size); 1582 1583 if (error == B_OK) 1584 *pointer = *data; 1585 else 1586 *pointer = NULL; 1587 1588 return error; 1589 } 1590 1591 1592 status_t 1593 BMessage::FindMessenger(const char *name, BMessenger *messenger) const 1594 { 1595 return FindMessenger(name, 0, messenger); 1596 } 1597 1598 1599 status_t 1600 BMessage::FindMessenger(const char *name, int32 index, BMessenger *messenger) 1601 const 1602 { 1603 void *data = NULL; 1604 ssize_t size = 0; 1605 status_t error = FindData(name, B_MESSENGER_TYPE, index, 1606 (const void **)&data, &size); 1607 1608 if (error == B_OK) 1609 memcpy(messenger, data, sizeof(BMessenger)); 1610 else 1611 *messenger = BMessenger(); 1612 1613 return error; 1614 } 1615 1616 1617 status_t 1618 BMessage::FindRef(const char *name, entry_ref *ref) const 1619 { 1620 return FindRef(name, 0, ref); 1621 } 1622 1623 1624 status_t 1625 BMessage::FindRef(const char *name, int32 index, entry_ref *ref) const 1626 { 1627 void *data = NULL; 1628 ssize_t size = 0; 1629 status_t error = FindData(name, B_REF_TYPE, index, 1630 (const void **)&data, &size); 1631 1632 if (error == B_OK) 1633 error = BPrivate::entry_ref_unflatten(ref, (char *)data, size); 1634 else 1635 *ref = entry_ref(); 1636 1637 return error; 1638 } 1639 1640 1641 status_t 1642 BMessage::FindMessage(const char *name, BMessage *message) const 1643 { 1644 return FindMessage(name, 0, message); 1645 } 1646 1647 1648 status_t 1649 BMessage::FindMessage(const char *name, int32 index, BMessage *message) const 1650 { 1651 void *data = NULL; 1652 ssize_t size = 0; 1653 status_t error = FindData(name, B_MESSAGE_TYPE, index, 1654 (const void **)&data, &size); 1655 1656 if (error == B_OK) 1657 error = message->Unflatten((const char *)data); 1658 else 1659 *message = BMessage(); 1660 1661 return error; 1662 } 1663 1664 1665 status_t 1666 BMessage::FindFlat(const char *name, BFlattenable *object) const 1667 { 1668 return FindFlat(name, 0, object); 1669 } 1670 1671 1672 status_t 1673 BMessage::FindFlat(const char *name, int32 index, BFlattenable *object) const 1674 { 1675 void *data = NULL; 1676 ssize_t numBytes = 0; 1677 status_t error = FindData(name, object->TypeCode(), index, 1678 (const void **)&data, &numBytes); 1679 1680 if (error == B_OK) 1681 error = object->Unflatten(object->TypeCode(), data, numBytes); 1682 1683 return error; 1684 } 1685 1686 1687 status_t 1688 BMessage::FindData(const char *name, type_code type, const void **data, 1689 ssize_t *numBytes) const 1690 { 1691 return FindData(name, type, 0, data, numBytes); 1692 } 1693 1694 1695 status_t 1696 BMessage::ReplaceString(const char *name, const char *string) 1697 { 1698 return ReplaceData(name, B_STRING_TYPE, 0, string, strlen(string) + 1); 1699 } 1700 1701 1702 status_t 1703 BMessage::ReplaceString(const char *name, int32 index, const char *string) 1704 { 1705 return ReplaceData(name, B_STRING_TYPE, index, string, strlen(string) + 1); 1706 } 1707 1708 1709 status_t 1710 BMessage::ReplaceString(const char *name, const BString &string) 1711 { 1712 return ReplaceData(name, B_STRING_TYPE, 0, string.String(), 1713 string.Length() + 1); 1714 } 1715 1716 1717 status_t 1718 BMessage::ReplaceString(const char *name, int32 index, const BString &string) 1719 { 1720 return ReplaceData(name, B_STRING_TYPE, index, string.String(), 1721 string.Length() + 1); 1722 } 1723 1724 1725 status_t 1726 BMessage::ReplacePointer(const char *name, const void *pointer) 1727 { 1728 return ReplaceData(name, B_POINTER_TYPE, 0, &pointer, sizeof(pointer)); 1729 } 1730 1731 1732 status_t 1733 BMessage::ReplacePointer(const char *name, int32 index, const void *pointer) 1734 { 1735 return ReplaceData(name, B_POINTER_TYPE, index, &pointer, sizeof(pointer)); 1736 } 1737 1738 1739 status_t 1740 BMessage::ReplaceMessenger(const char *name, BMessenger messenger) 1741 { 1742 return ReplaceData(name, B_MESSENGER_TYPE, 0, &messenger, 1743 sizeof(BMessenger)); 1744 } 1745 1746 1747 status_t 1748 BMessage::ReplaceMessenger(const char *name, int32 index, BMessenger messenger) 1749 { 1750 return ReplaceData(name, B_MESSENGER_TYPE, index, &messenger, 1751 sizeof(BMessenger)); 1752 } 1753 1754 1755 status_t 1756 BMessage::ReplaceRef(const char *name, const entry_ref *ref) 1757 { 1758 return ReplaceRef(name, 0, ref); 1759 } 1760 1761 1762 status_t 1763 BMessage::ReplaceRef(const char *name, int32 index, const entry_ref *ref) 1764 { 1765 size_t size = sizeof(entry_ref) + B_PATH_NAME_LENGTH; 1766 char buffer[size]; 1767 1768 status_t error = BPrivate::entry_ref_flatten(buffer, &size, ref); 1769 1770 if (error >= B_OK) 1771 error = ReplaceData(name, B_REF_TYPE, index, &buffer, size); 1772 1773 return error; 1774 } 1775 1776 1777 status_t 1778 BMessage::ReplaceMessage(const char *name, const BMessage *message) 1779 { 1780 return ReplaceMessage(name, 0, message); 1781 } 1782 1783 1784 status_t 1785 BMessage::ReplaceMessage(const char *name, int32 index, const BMessage *message) 1786 { 1787 ssize_t size = message->FlattenedSize(); 1788 char buffer[size]; 1789 1790 status_t error = message->Flatten(buffer, size); 1791 1792 if (error >= B_OK) 1793 error = ReplaceData(name, B_MESSAGE_TYPE, index, &buffer, size); 1794 1795 return error; 1796 } 1797 1798 1799 status_t 1800 BMessage::ReplaceFlat(const char *name, BFlattenable *object) 1801 { 1802 return ReplaceFlat(name, 0, object); 1803 } 1804 1805 1806 status_t 1807 BMessage::ReplaceFlat(const char *name, int32 index, BFlattenable *object) 1808 { 1809 ssize_t size = object->FlattenedSize(); 1810 char buffer[size]; 1811 1812 status_t error = object->Flatten(buffer, size); 1813 1814 if (error >= B_OK) 1815 error = ReplaceData(name, object->TypeCode(), index, &buffer, size); 1816 1817 return error; 1818 } 1819 1820 1821 status_t 1822 BMessage::ReplaceData(const char *name, type_code type, const void *data, 1823 ssize_t numBytes) 1824 { 1825 return ReplaceData(name, type, 0, data, numBytes); 1826 } 1827 1828 1829 bool 1830 BMessage::HasFlat(const char *name, const BFlattenable *object) const 1831 { 1832 return HasFlat(name, 0, object); 1833 } 1834 1835 1836 bool 1837 BMessage::HasFlat(const char *name, int32 index, const BFlattenable *object) 1838 const 1839 { 1840 return HasData(name, object->TypeCode(), index); 1841 } 1842