1/* 2Open Tracker License 3 4Terms and Conditions 5 6Copyright (c) 1991-2000, Be Incorporated. All rights reserved. 7 8Permission is hereby granted, free of charge, to any person obtaining a copy of 9this software and associated documentation files (the "Software"), to deal in 10the Software without restriction, including without limitation the rights to 11use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12of the Software, and to permit persons to whom the Software is furnished to do 13so, subject to the following conditions: 14 15The above copyright notice and this permission notice applies to all licensees 16and shall be included in all copies or substantial portions of the Software. 17 18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, 20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION 23WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25Except as contained in this notice, the name of Be Incorporated shall not be 26used in advertising or otherwise to promote the sale, use or other dealings in 27this Software without prior written authorization from Be Incorporated. 28 29Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks 30of Be Incorporated in the United States and other countries. Other brand product 31names are registered trademarks or trademarks of their respective holders. 32All 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 53AttributeInfo::AttributeInfo() 54 : 55 fName("") 56{ 57 fInfo.type = B_RAW_TYPE; 58 fInfo.size = 0; 59} 60 61 62AttributeInfo::AttributeInfo(const AttributeInfo& other) 63 : 64 fName(other.fName), 65 fInfo(other.fInfo) 66 67{ 68} 69 70 71AttributeInfo::AttributeInfo(const char* name, attr_info info) 72 : 73 fName(name), 74 fInfo(info) 75{ 76} 77 78 79AttributeInfo::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 88const char* 89AttributeInfo::Name() const 90{ 91 return fName.String(); 92} 93 94 95uint32 96AttributeInfo::Type() const 97{ 98 return fInfo.type; 99} 100 101 102off_t 103AttributeInfo::Size() const 104{ 105 return fInfo.size; 106} 107 108 109void 110AttributeInfo::SetTo(const AttributeInfo& other) 111{ 112 fName = other.fName; 113 fInfo = other.fInfo; 114} 115 116 117void 118AttributeInfo::SetTo(const char* name, attr_info info) 119{ 120 fName = name; 121 fInfo = info; 122} 123 124 125void 126AttributeInfo::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 137AttributeStreamNode::AttributeStreamNode() 138 : 139 fReadFrom(NULL), 140 fWriteTo(NULL) 141{ 142} 143 144 145AttributeStreamNode::~AttributeStreamNode() 146{ 147 Detach(); 148} 149 150 151AttributeStreamNode& 152AttributeStreamNode::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 163void 164AttributeStreamNode::Rewind() 165{ 166 if (fReadFrom != NULL) 167 fReadFrom->Rewind(); 168} 169 170 171void 172AttributeStreamFileNode::MakeEmpty() 173{ 174 TRESPASS(); 175} 176 177 178off_t 179AttributeStreamNode::Contains(const char* name, uint32 type) 180{ 181 if (fReadFrom == NULL) 182 return 0; 183 184 return fReadFrom->Contains(name, type); 185} 186 187 188off_t 189AttributeStreamNode::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 199off_t 200AttributeStreamNode::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 210bool 211AttributeStreamNode::Drive() 212{ 213 ASSERT(CanFeed()); 214 if (fReadFrom == NULL) 215 return false; 216 217 Rewind(); 218 return true; 219} 220 221 222const AttributeInfo* 223AttributeStreamNode::Next() 224{ 225 if (fReadFrom != NULL) 226 return fReadFrom->Next(); 227 228 return NULL; 229} 230 231 232const char* 233AttributeStreamNode::Get() 234{ 235 ASSERT(fReadFrom != NULL); 236 237 return fReadFrom->Get(); 238} 239 240 241bool 242AttributeStreamNode::Fill(char* buffer) const 243{ 244 ASSERT(fReadFrom != NULL); 245 246 return fReadFrom->Fill(buffer); 247} 248 249 250bool 251AttributeStreamNode::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 262void 263AttributeStreamNode::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 281AttributeStreamFileNode::AttributeStreamFileNode() 282 : 283 fNode(NULL) 284{ 285} 286 287 288AttributeStreamFileNode::AttributeStreamFileNode(BNode* node) 289 : 290 fNode(node) 291{ 292 ASSERT(fNode != NULL); 293} 294 295 296void 297AttributeStreamFileNode::Rewind() 298{ 299 _inherited::Rewind(); 300 fNode->RewindAttrs(); 301} 302 303 304void 305AttributeStreamFileNode::SetTo(BNode* node) 306{ 307 fNode = node; 308} 309 310 311off_t 312AttributeStreamFileNode::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 327off_t 328AttributeStreamFileNode::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 350off_t 351AttributeStreamFileNode::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 367bool 368AttributeStreamFileNode::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 388const char* 389AttributeStreamFileNode::Get() 390{ 391 ASSERT(fNode != NULL); 392 TRESPASS(); 393 394 return NULL; 395} 396 397 398bool 399AttributeStreamFileNode::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 408const AttributeInfo* 409AttributeStreamFileNode::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 431AttributeStreamMemoryNode::AttributeStreamMemoryNode() 432 : 433 fAttributes(5, true), 434 fCurrentIndex(-1) 435{ 436} 437 438 439void 440AttributeStreamMemoryNode::MakeEmpty() 441{ 442 fAttributes.MakeEmpty(); 443} 444 445 446void 447AttributeStreamMemoryNode::Rewind() 448{ 449 _inherited::Rewind(); 450 fCurrentIndex = -1; 451} 452 453 454int32 455AttributeStreamMemoryNode::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 469off_t 470AttributeStreamMemoryNode::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 478off_t 479AttributeStreamMemoryNode::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 512off_t 513AttributeStreamMemoryNode::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 526bool 527AttributeStreamMemoryNode::Drive() 528{ 529 if (!_inherited::Drive()) 530 return false; 531 532 while (BufferingGet()) 533 ; 534 535 return true; 536} 537 538 539AttributeStreamMemoryNode::AttrNode* 540AttributeStreamMemoryNode::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 556AttributeStreamMemoryNode::AttrNode* 557AttributeStreamMemoryNode::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 570const AttributeInfo* 571AttributeStreamMemoryNode::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 586const char* 587AttributeStreamMemoryNode::Get() 588{ 589 ASSERT(fCurrentIndex < fAttributes.CountItems()); 590 591 return fAttributes.ItemAt(fCurrentIndex)->fData; 592} 593 594 595bool 596AttributeStreamMemoryNode::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 609AttributeStreamTemplateNode::AttributeStreamTemplateNode( 610 const AttributeTemplate* attrTemplates, int32 count) 611 : 612 fAttributes(attrTemplates), 613 fCurrentIndex(-1), 614 fCount(count) 615{ 616} 617 618 619off_t 620AttributeStreamTemplateNode::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 630void 631AttributeStreamTemplateNode::Rewind() 632{ 633 fCurrentIndex = -1; 634} 635 636 637const AttributeInfo* 638AttributeStreamTemplateNode::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 653const char* 654AttributeStreamTemplateNode::Get() 655{ 656 ASSERT(fCurrentIndex < fCount); 657 658 return fAttributes[fCurrentIndex].fBits; 659} 660 661 662bool 663AttributeStreamTemplateNode::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 673int32 674AttributeStreamTemplateNode::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 690bool 691AttributeStreamFilterNode::Reject(const char*, uint32, off_t) 692{ 693 // simple pass everything filter 694 return false; 695} 696 697 698const AttributeInfo* 699AttributeStreamFilterNode::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 717off_t 718AttributeStreamFilterNode::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 732off_t 733AttributeStreamFilterNode::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 748off_t 749AttributeStreamFilterNode::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 765NamesToAcceptAttrFilter::NamesToAcceptAttrFilter(const char** nameList) 766 : 767 fNameList(nameList) 768{ 769} 770 771 772bool 773NamesToAcceptAttrFilter::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 793SelectiveAttributeTransformer::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 806SelectiveAttributeTransformer::~SelectiveAttributeTransformer() 807{ 808 for (int32 index = fTransformedBuffers.CountItems() - 1; index >= 0; 809 index--) { 810 delete[] fTransformedBuffers.ItemAt(index); 811 } 812} 813 814 815void 816SelectiveAttributeTransformer::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 827off_t 828SelectiveAttributeTransformer::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 844bool 845SelectiveAttributeTransformer::WillTransform(const char* name, uint32, off_t, 846 const char*) const 847{ 848 return strcmp(name, fAttributeNameToTransform) == 0; 849} 850 851 852bool 853SelectiveAttributeTransformer::ApplyTransformer(const char* name, uint32 type, 854 off_t size, char* data) 855{ 856 return (fTransformFunc)(name, type, size, data, fTransformParams); 857} 858 859char* 860SelectiveAttributeTransformer::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 879const AttributeInfo* 880SelectiveAttributeTransformer::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 892const char* 893SelectiveAttributeTransformer::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