1 /* 2 Open Tracker License 3 4 Terms and Conditions 5 6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved. 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy of 9 this software and associated documentation files (the "Software"), to deal in 10 the Software without restriction, including without limitation the rights to 11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 of the Software, and to permit persons to whom the Software is furnished to do 13 so, subject to the following conditions: 14 15 The above copyright notice and this permission notice applies to all licensees 16 and shall be included in all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION 23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25 Except as contained in this notice, the name of Be Incorporated shall not be 26 used in advertising or otherwise to promote the sale, use or other dealings in 27 this Software without prior written authorization from Be Incorporated. 28 29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks 30 of Be Incorporated in the United States and other countries. Other brand product 31 names are registered trademarks or trademarks of their respective holders. 32 All rights reserved. 33 */ 34 35 36 #include "AttributeStream.h" 37 38 #include <Debug.h> 39 #include <Node.h> 40 41 #include "Utilities.h" 42 43 44 // ToDo: 45 // lazy Rewind from Drive, only if data is available 46 // BMessage node 47 // partial feeding (part, not the whole buffer) 48 49 50 // #pragma mark - AttributeInfo 51 52 53 AttributeInfo::AttributeInfo() 54 : 55 fName("") 56 { 57 fInfo.type = B_RAW_TYPE; 58 fInfo.size = 0; 59 } 60 61 62 AttributeInfo::AttributeInfo(const AttributeInfo& other) 63 : 64 fName(other.fName), 65 fInfo(other.fInfo) 66 67 { 68 } 69 70 71 AttributeInfo::AttributeInfo(const char* name, attr_info info) 72 : 73 fName(name), 74 fInfo(info) 75 { 76 } 77 78 79 AttributeInfo::AttributeInfo(const char* name, uint32 type, off_t size) 80 : 81 fName(name) 82 { 83 fInfo.type = type; 84 fInfo.size = size; 85 } 86 87 88 const char* 89 AttributeInfo::Name() const 90 { 91 return fName.String(); 92 } 93 94 95 uint32 96 AttributeInfo::Type() const 97 { 98 return fInfo.type; 99 } 100 101 102 off_t 103 AttributeInfo::Size() const 104 { 105 return fInfo.size; 106 } 107 108 109 void 110 AttributeInfo::SetTo(const AttributeInfo& other) 111 { 112 fName = other.fName; 113 fInfo = other.fInfo; 114 } 115 116 117 void 118 AttributeInfo::SetTo(const char* name, attr_info info) 119 { 120 fName = name; 121 fInfo = info; 122 } 123 124 125 void 126 AttributeInfo::SetTo(const char* name, uint32 type, off_t size) 127 { 128 fName = name; 129 fInfo.type = type; 130 fInfo.size = size; 131 } 132 133 134 // #pragma mark - AttributeStreamNode 135 136 137 AttributeStreamNode::AttributeStreamNode() 138 : 139 fReadFrom(NULL), 140 fWriteTo(NULL) 141 { 142 } 143 144 145 AttributeStreamNode::~AttributeStreamNode() 146 { 147 Detach(); 148 } 149 150 151 AttributeStreamNode& 152 AttributeStreamNode::operator<<(AttributeStreamNode &source) 153 { 154 fReadFrom = &source; 155 fReadFrom->fWriteTo = this; 156 if (fReadFrom->CanFeed()) 157 fReadFrom->Start(); 158 159 return source; 160 } 161 162 163 void 164 AttributeStreamNode::Rewind() 165 { 166 if (fReadFrom != NULL) 167 fReadFrom->Rewind(); 168 } 169 170 171 void 172 AttributeStreamFileNode::MakeEmpty() 173 { 174 TRESPASS(); 175 } 176 177 178 off_t 179 AttributeStreamNode::Contains(const char* name, uint32 type) 180 { 181 if (fReadFrom == NULL) 182 return 0; 183 184 return fReadFrom->Contains(name, type); 185 } 186 187 188 off_t 189 AttributeStreamNode::Read(const char* name, const char* foreignName, 190 uint32 type, off_t size, void* buffer, void (*swapFunc)(void*)) 191 { 192 if (fReadFrom == NULL) 193 return 0; 194 195 return fReadFrom->Read(name, foreignName, type, size, buffer, swapFunc); 196 } 197 198 199 off_t 200 AttributeStreamNode::Write(const char* name, const char* foreignName, 201 uint32 type, off_t size, const void* buffer) 202 { 203 if (fWriteTo == NULL) 204 return 0; 205 206 return fWriteTo->Write(name, foreignName, type, size, buffer); 207 } 208 209 210 bool 211 AttributeStreamNode::Drive() 212 { 213 ASSERT(CanFeed()); 214 if (fReadFrom == NULL) 215 return false; 216 217 Rewind(); 218 return true; 219 } 220 221 222 const AttributeInfo* 223 AttributeStreamNode::Next() 224 { 225 if (fReadFrom != NULL) 226 return fReadFrom->Next(); 227 228 return NULL; 229 } 230 231 232 const char* 233 AttributeStreamNode::Get() 234 { 235 ASSERT(fReadFrom != NULL); 236 237 return fReadFrom->Get(); 238 } 239 240 241 bool 242 AttributeStreamNode::Fill(char* buffer) const 243 { 244 ASSERT(fReadFrom != NULL); 245 246 return fReadFrom->Fill(buffer); 247 } 248 249 250 bool 251 AttributeStreamNode::Start() 252 { 253 if (fWriteTo == NULL) { 254 // we are at the head of the stream, start drivin' 255 return Drive(); 256 } 257 258 return fWriteTo->Start(); 259 } 260 261 262 void 263 AttributeStreamNode::Detach() 264 { 265 AttributeStreamNode* tmpFrom = fReadFrom; 266 AttributeStreamNode* tmpTo = fWriteTo; 267 fReadFrom = NULL; 268 fWriteTo = NULL; 269 270 if (tmpFrom != NULL) 271 tmpFrom->Detach(); 272 273 if (tmpTo != NULL) 274 tmpTo->Detach(); 275 } 276 277 278 // #pragma mark - AttributeStreamFileNode 279 280 281 AttributeStreamFileNode::AttributeStreamFileNode() 282 : 283 fNode(NULL) 284 { 285 } 286 287 288 AttributeStreamFileNode::AttributeStreamFileNode(BNode* node) 289 : 290 fNode(node) 291 { 292 ASSERT(fNode != NULL); 293 } 294 295 296 void 297 AttributeStreamFileNode::Rewind() 298 { 299 _inherited::Rewind(); 300 fNode->RewindAttrs(); 301 } 302 303 304 void 305 AttributeStreamFileNode::SetTo(BNode* node) 306 { 307 fNode = node; 308 } 309 310 311 off_t 312 AttributeStreamFileNode::Contains(const char* name, uint32 type) 313 { 314 ThrowOnAssert(fNode != NULL); 315 316 attr_info info; 317 if (fNode->GetAttrInfo(name, &info) != B_OK) 318 return 0; 319 320 if (info.type != type) 321 return 0; 322 323 return info.size; 324 } 325 326 327 off_t 328 AttributeStreamFileNode::Read(const char* name, const char* foreignName, 329 uint32 type, off_t size, void* buffer, void (*swapFunc)(void*)) 330 { 331 if (name != NULL 332 && fNode->ReadAttr(name, type, 0, buffer, (size_t)size) == size) { 333 return size; 334 } 335 336 // didn't find the attribute under the native name, try the foreign name 337 if (foreignName != NULL && fNode->ReadAttr(foreignName, type, 0, buffer, 338 (size_t)size) == size) { 339 // foreign attribute, swap the data 340 if (swapFunc != NULL) 341 (swapFunc)(buffer); 342 343 return size; 344 } 345 346 return 0; 347 } 348 349 350 off_t 351 AttributeStreamFileNode::Write(const char* name, const char* foreignName, 352 uint32 type, off_t size, const void* buffer) 353 { 354 ThrowOnAssert(fNode != NULL); 355 356 off_t result = fNode->WriteAttr(name, type, 0, buffer, (size_t)size); 357 if (result == size && foreignName != NULL) { 358 // the write operation worked fine, remove the foreign attribute 359 // to not let stale data hang around 360 fNode->RemoveAttr(foreignName); 361 } 362 363 return result; 364 } 365 366 367 bool 368 AttributeStreamFileNode::Drive() 369 { 370 if (!_inherited::Drive()) 371 return false; 372 373 ThrowOnAssert(fNode != NULL); 374 375 const AttributeInfo* attr; 376 while ((attr = fReadFrom->Next()) != 0) { 377 const char* data = fReadFrom->Get(); 378 off_t result = fNode->WriteAttr(attr->Name(), attr->Type(), 0, 379 data, (size_t)attr->Size()); 380 if (result < attr->Size()) 381 return true; 382 } 383 384 return true; 385 } 386 387 388 const char* 389 AttributeStreamFileNode::Get() 390 { 391 ASSERT(fNode != NULL); 392 TRESPASS(); 393 394 return NULL; 395 } 396 397 398 bool 399 AttributeStreamFileNode::Fill(char* buffer) const 400 { 401 ThrowOnAssert(fNode != NULL); 402 403 return fNode->ReadAttr(fCurrentAttr.Name(), fCurrentAttr.Type(), 0, 404 buffer, (size_t)fCurrentAttr.Size()) == (ssize_t)fCurrentAttr.Size(); 405 } 406 407 408 const AttributeInfo* 409 AttributeStreamFileNode::Next() 410 { 411 ASSERT(fReadFrom == NULL); 412 ThrowOnAssert(fNode != NULL); 413 414 char attrName[256]; 415 if (fNode->GetNextAttrName(attrName) != B_OK) 416 return NULL; 417 418 attr_info info; 419 if (fNode->GetAttrInfo(attrName, &info) != B_OK) 420 return NULL; 421 422 fCurrentAttr.SetTo(attrName, info); 423 424 return &fCurrentAttr; 425 } 426 427 428 // #pragma mark - AttributeStreamMemoryNode 429 430 431 AttributeStreamMemoryNode::AttributeStreamMemoryNode() 432 : 433 fAttributes(5, true), 434 fCurrentIndex(-1) 435 { 436 } 437 438 439 void 440 AttributeStreamMemoryNode::MakeEmpty() 441 { 442 fAttributes.MakeEmpty(); 443 } 444 445 446 void 447 AttributeStreamMemoryNode::Rewind() 448 { 449 _inherited::Rewind(); 450 fCurrentIndex = -1; 451 } 452 453 454 int32 455 AttributeStreamMemoryNode::Find(const char* name, uint32 type) const 456 { 457 int32 count = fAttributes.CountItems(); 458 for (int32 index = 0; index < count; index++) { 459 if (strcmp(fAttributes.ItemAt(index)->fAttr.Name(), name) == 0 460 && fAttributes.ItemAt(index)->fAttr.Type() == type) { 461 return index; 462 } 463 } 464 465 return -1; 466 } 467 468 469 off_t 470 AttributeStreamMemoryNode::Contains(const char* name, uint32 type) 471 { 472 int32 index = Find(name, type); 473 474 return index < 0 ? 0 : fAttributes.ItemAt(index)->fAttr.Size(); 475 } 476 477 478 off_t 479 AttributeStreamMemoryNode::Read(const char* name, 480 const char* DEBUG_ONLY(foreignName), uint32 type, off_t bufferSize, 481 void* buffer, void (*DEBUG_ONLY(swapFunc))(void*)) 482 { 483 ASSERT(foreignName == NULL); 484 ASSERT(swapFunc == NULL); 485 486 AttrNode* attrNode = NULL; 487 488 int32 index = Find(name, type); 489 if (index < 0) { 490 if (fReadFrom == NULL) 491 return 0; 492 493 off_t size = fReadFrom->Contains(name, type); 494 if (size == 0) 495 return 0; 496 497 attrNode = BufferingGet(name, type, size); 498 if (attrNode == NULL) 499 return 0; 500 } else 501 attrNode = fAttributes.ItemAt(index); 502 503 if (attrNode->fAttr.Size() > bufferSize) 504 return 0; 505 506 memcpy(buffer, attrNode->fData, (size_t)attrNode->fAttr.Size()); 507 508 return attrNode->fAttr.Size(); 509 } 510 511 512 off_t 513 AttributeStreamMemoryNode::Write(const char* name, const char*, uint32 type, 514 off_t size, const void* buffer) 515 { 516 char* newBuffer = new char[size]; 517 memcpy(newBuffer, buffer, (size_t)size); 518 519 AttrNode* attrNode = new AttrNode(name, type, size, newBuffer); 520 fAttributes.AddItem(attrNode); 521 522 return size; 523 } 524 525 526 bool 527 AttributeStreamMemoryNode::Drive() 528 { 529 if (!_inherited::Drive()) 530 return false; 531 532 while (BufferingGet()) 533 ; 534 535 return true; 536 } 537 538 539 AttributeStreamMemoryNode::AttrNode* 540 AttributeStreamMemoryNode::BufferingGet(const char* name, uint32 type, 541 off_t size) 542 { 543 char* newBuffer = new char[size]; 544 if (!fReadFrom->Fill(newBuffer)) { 545 delete[] newBuffer; 546 return NULL; 547 } 548 549 AttrNode* attrNode = new AttrNode(name, type, size, newBuffer); 550 fAttributes.AddItem(attrNode); 551 552 return fAttributes.LastItem(); 553 } 554 555 556 AttributeStreamMemoryNode::AttrNode* 557 AttributeStreamMemoryNode::BufferingGet() 558 { 559 if (fReadFrom == NULL) 560 return NULL; 561 562 const AttributeInfo* attr = fReadFrom->Next(); 563 if (attr == NULL) 564 return NULL; 565 566 return BufferingGet(attr->Name(), attr->Type(), attr->Size()); 567 } 568 569 570 const AttributeInfo* 571 AttributeStreamMemoryNode::Next() 572 { 573 if (fReadFrom != NULL) { 574 // the buffer is in the middle of the stream, get 575 // one buffer at a time 576 BufferingGet(); 577 } 578 579 if (fCurrentIndex + 1 >= fAttributes.CountItems()) 580 return NULL; 581 582 return &fAttributes.ItemAt(++fCurrentIndex)->fAttr; 583 } 584 585 586 const char* 587 AttributeStreamMemoryNode::Get() 588 { 589 ASSERT(fCurrentIndex < fAttributes.CountItems()); 590 591 return fAttributes.ItemAt(fCurrentIndex)->fData; 592 } 593 594 595 bool 596 AttributeStreamMemoryNode::Fill(char* buffer) const 597 { 598 ASSERT(fCurrentIndex < fAttributes.CountItems()); 599 memcpy(buffer, fAttributes.ItemAt(fCurrentIndex)->fData, 600 (size_t)fAttributes.ItemAt(fCurrentIndex)->fAttr.Size()); 601 602 return true; 603 } 604 605 606 // #pragma mark - AttributeStreamTemplateNode 607 608 609 AttributeStreamTemplateNode::AttributeStreamTemplateNode( 610 const AttributeTemplate* attrTemplates, int32 count) 611 : 612 fAttributes(attrTemplates), 613 fCurrentIndex(-1), 614 fCount(count) 615 { 616 } 617 618 619 off_t 620 AttributeStreamTemplateNode::Contains(const char* name, uint32 type) 621 { 622 int32 index = Find(name, type); 623 if (index < 0) 624 return 0; 625 626 return fAttributes[index].fSize; 627 } 628 629 630 void 631 AttributeStreamTemplateNode::Rewind() 632 { 633 fCurrentIndex = -1; 634 } 635 636 637 const AttributeInfo* 638 AttributeStreamTemplateNode::Next() 639 { 640 if (fCurrentIndex + 1 >= fCount) 641 return NULL; 642 643 ++fCurrentIndex; 644 645 fCurrentAttr.SetTo(fAttributes[fCurrentIndex].fAttributeName, 646 fAttributes[fCurrentIndex].fAttributeType, 647 fAttributes[fCurrentIndex].fSize); 648 649 return &fCurrentAttr; 650 } 651 652 653 const char* 654 AttributeStreamTemplateNode::Get() 655 { 656 ASSERT(fCurrentIndex < fCount); 657 658 return fAttributes[fCurrentIndex].fBits; 659 } 660 661 662 bool 663 AttributeStreamTemplateNode::Fill(char* buffer) const 664 { 665 ASSERT(fCurrentIndex < fCount); 666 memcpy(buffer, fAttributes[fCurrentIndex].fBits, 667 (size_t)fAttributes[fCurrentIndex].fSize); 668 669 return true; 670 } 671 672 673 int32 674 AttributeStreamTemplateNode::Find(const char* name, uint32 type) const 675 { 676 for (int32 index = 0; index < fCount; index++) { 677 if (fAttributes[index].fAttributeType == type && 678 strcmp(name, fAttributes[index].fAttributeName) == 0) { 679 return index; 680 } 681 } 682 683 return -1; 684 } 685 686 687 // #pragma mark - AttributeStreamFilterNode 688 689 690 bool 691 AttributeStreamFilterNode::Reject(const char*, uint32, off_t) 692 { 693 // simple pass everything filter 694 return false; 695 } 696 697 698 const AttributeInfo* 699 AttributeStreamFilterNode::Next() 700 { 701 if (fReadFrom == NULL) 702 return NULL; 703 704 for (;;) { 705 const AttributeInfo* attr = fReadFrom->Next(); 706 if (attr == NULL) 707 break; 708 709 if (!Reject(attr->Name(), attr->Type(), attr->Size())) 710 return attr; 711 } 712 713 return NULL; 714 } 715 716 717 off_t 718 AttributeStreamFilterNode::Contains(const char* name, uint32 type) 719 { 720 if (fReadFrom == NULL) 721 return 0; 722 723 off_t size = fReadFrom->Contains(name, type); 724 725 if (!Reject(name, type, size)) 726 return size; 727 728 return 0; 729 } 730 731 732 off_t 733 AttributeStreamFilterNode::Read(const char* name, const char* foreignName, 734 uint32 type, off_t size, void* buffer, void (*swapFunc)(void*)) 735 { 736 if (fReadFrom == NULL) 737 return 0; 738 739 if (!Reject(name, type, size)) { 740 return fReadFrom->Read(name, foreignName, type, size, buffer, 741 swapFunc); 742 } 743 744 return 0; 745 } 746 747 748 off_t 749 AttributeStreamFilterNode::Write(const char* name, const char* foreignName, 750 uint32 type, off_t size, const void* buffer) 751 { 752 if (fWriteTo == NULL) 753 return 0; 754 755 if (!Reject(name, type, size)) 756 return fWriteTo->Write(name, foreignName, type, size, buffer); 757 758 return size; 759 } 760 761 762 // #pragma mark - NamesToAcceptAttrFilter 763 764 765 NamesToAcceptAttrFilter::NamesToAcceptAttrFilter(const char** nameList) 766 : 767 fNameList(nameList) 768 { 769 } 770 771 772 bool 773 NamesToAcceptAttrFilter::Reject(const char* name, uint32, off_t) 774 { 775 for (int32 index = 0; ; index++) { 776 if (fNameList[index] == NULL) 777 break; 778 779 if (strcmp(name, fNameList[index]) == 0) { 780 //PRINT(("filter passing through %s\n", name)); 781 return false; 782 } 783 } 784 785 //PRINT(("filter rejecting %s\n", name)); 786 return true; 787 } 788 789 790 // #pragma mark - SelectiveAttributeTransformer 791 792 793 SelectiveAttributeTransformer::SelectiveAttributeTransformer( 794 const char* attributeName, 795 bool (*transformFunc)(const char* , uint32 , off_t, void*, void*), 796 void* params) 797 : 798 fAttributeNameToTransform(attributeName), 799 fTransformFunc(transformFunc), 800 fTransformParams(params), 801 fTransformedBuffers(10, false) 802 { 803 } 804 805 806 SelectiveAttributeTransformer::~SelectiveAttributeTransformer() 807 { 808 for (int32 index = fTransformedBuffers.CountItems() - 1; index >= 0; 809 index--) { 810 delete[] fTransformedBuffers.ItemAt(index); 811 } 812 } 813 814 815 void 816 SelectiveAttributeTransformer::Rewind() 817 { 818 for (int32 index = fTransformedBuffers.CountItems() - 1; index >= 0; 819 index--) { 820 delete[] fTransformedBuffers.ItemAt(index); 821 } 822 823 fTransformedBuffers.MakeEmpty(); 824 } 825 826 827 off_t 828 SelectiveAttributeTransformer::Read(const char* name, const char* foreignName, 829 uint32 type, off_t size, void* buffer, void (*swapFunc)(void*)) 830 { 831 if (fReadFrom == NULL) 832 return 0; 833 834 off_t result = fReadFrom->Read(name, foreignName, type, size, buffer, 835 swapFunc); 836 837 if (WillTransform(name, type, size, (const char*)buffer)) 838 ApplyTransformer(name, type, size, (char*)buffer); 839 840 return result; 841 } 842 843 844 bool 845 SelectiveAttributeTransformer::WillTransform(const char* name, uint32, off_t, 846 const char*) const 847 { 848 return strcmp(name, fAttributeNameToTransform) == 0; 849 } 850 851 852 bool 853 SelectiveAttributeTransformer::ApplyTransformer(const char* name, uint32 type, 854 off_t size, char* data) 855 { 856 return (fTransformFunc)(name, type, size, data, fTransformParams); 857 } 858 859 char* 860 SelectiveAttributeTransformer::CopyAndApplyTransformer(const char* name, 861 uint32 type, off_t size, const char* data) 862 { 863 char* result = NULL; 864 865 if (data != NULL) { 866 result = new char[size]; 867 memcpy(result, data, (size_t)size); 868 } 869 870 if (!(fTransformFunc)(name, type, size, result, fTransformParams)) { 871 delete[] result; 872 return NULL; 873 } 874 875 return result; 876 } 877 878 879 const AttributeInfo* 880 SelectiveAttributeTransformer::Next() 881 { 882 const AttributeInfo* result = fReadFrom->Next(); 883 884 if (result == NULL) 885 return NULL; 886 887 fCurrentAttr.SetTo(*result); 888 return result; 889 } 890 891 892 const char* 893 SelectiveAttributeTransformer::Get() 894 { 895 if (fReadFrom == NULL) 896 return NULL; 897 898 const char* result = fReadFrom->Get(); 899 900 if (!WillTransform(fCurrentAttr.Name(), fCurrentAttr.Type(), 901 fCurrentAttr.Size(), result)) { 902 return result; 903 } 904 905 char* transformedData = CopyAndApplyTransformer(fCurrentAttr.Name(), 906 fCurrentAttr.Type(), fCurrentAttr.Size(), result); 907 908 // enlist for proper disposal when our job is done 909 if (transformedData != NULL) { 910 fTransformedBuffers.AddItem(transformedData); 911 return transformedData; 912 } 913 914 return result; 915 } 916