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