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