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