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