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 AttributeInfo::AttributeInfo(const AttributeInfo &cloneThis) 48 : fName(cloneThis.fName), 49 fInfo(cloneThis.fInfo) 50 51 { 52 } 53 54 55 AttributeInfo::AttributeInfo(const char* name, attr_info info) 56 : fName(name), 57 fInfo(info) 58 { 59 } 60 61 62 AttributeInfo::AttributeInfo(const char* name, uint32 type, off_t size) 63 : fName(name) 64 { 65 fInfo.size = size; 66 fInfo.type = type; 67 } 68 69 70 const char* 71 AttributeInfo::Name() const 72 { 73 return fName.String(); 74 } 75 76 uint32 77 AttributeInfo::Type() const 78 { 79 return fInfo.type; 80 } 81 82 off_t 83 AttributeInfo::Size() const 84 { 85 return fInfo.size; 86 } 87 88 89 void 90 AttributeInfo::SetTo(const AttributeInfo &attr) 91 { 92 fName = attr.fName; 93 fInfo = attr.fInfo; 94 } 95 96 void 97 AttributeInfo::SetTo(const char* name, attr_info info) 98 { 99 fName = name; 100 fInfo = info; 101 } 102 103 void 104 AttributeInfo::SetTo(const char* name, uint32 type, off_t size) 105 { 106 fName = name; 107 fInfo.type = type; 108 fInfo.size = size; 109 } 110 111 112 AttributeStreamNode::AttributeStreamNode() 113 : fReadFrom(NULL), 114 fWriteTo(NULL) 115 { 116 } 117 118 119 AttributeStreamNode::~AttributeStreamNode() 120 { 121 Detach(); 122 } 123 124 AttributeStreamNode& 125 AttributeStreamNode::operator<<(AttributeStreamNode &source) 126 { 127 fReadFrom = &source; 128 fReadFrom->fWriteTo = this; 129 if (fReadFrom->CanFeed()) 130 fReadFrom->Start(); 131 132 return source; 133 } 134 135 void 136 AttributeStreamNode::Rewind() 137 { 138 if (fReadFrom) 139 fReadFrom->Rewind(); 140 } 141 142 void 143 AttributeStreamFileNode::MakeEmpty() 144 { 145 TRESPASS(); 146 } 147 148 off_t 149 AttributeStreamNode::Contains(const char* name, uint32 type) 150 { 151 if (!fReadFrom) 152 return 0; 153 154 return fReadFrom->Contains(name, type); 155 } 156 157 158 off_t 159 AttributeStreamNode::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 169 off_t 170 AttributeStreamNode::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 180 bool 181 AttributeStreamNode::Drive() 182 { 183 ASSERT(CanFeed()); 184 if (!fReadFrom) 185 return false; 186 187 Rewind(); 188 return true; 189 } 190 191 192 const AttributeInfo* 193 AttributeStreamNode::Next() 194 { 195 if (fReadFrom) 196 return fReadFrom->Next(); 197 198 return NULL; 199 } 200 201 202 const char* 203 AttributeStreamNode::Get() 204 { 205 ASSERT(fReadFrom); 206 if (!fReadFrom) 207 return NULL; 208 209 return fReadFrom->Get(); 210 } 211 212 213 bool 214 AttributeStreamNode::Fill(char* buffer) const 215 { 216 ASSERT(fReadFrom); 217 return fReadFrom->Fill(buffer); 218 } 219 220 221 bool 222 AttributeStreamNode::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 232 void 233 AttributeStreamNode::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 247 AttributeStreamFileNode::AttributeStreamFileNode() 248 : fNode(NULL) 249 { 250 } 251 252 253 AttributeStreamFileNode::AttributeStreamFileNode(BNode* node) 254 : fNode(node) 255 { 256 ASSERT(fNode); 257 } 258 259 260 void 261 AttributeStreamFileNode::Rewind() 262 { 263 _inherited::Rewind(); 264 fNode->RewindAttrs(); 265 } 266 267 268 void 269 AttributeStreamFileNode::SetTo(BNode* node) 270 { 271 fNode = node; 272 } 273 274 275 off_t 276 AttributeStreamFileNode::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 290 off_t 291 AttributeStreamFileNode::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 309 off_t 310 AttributeStreamFileNode::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 325 bool 326 AttributeStreamFileNode::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 344 const char* 345 AttributeStreamFileNode::Get() 346 { 347 ASSERT(fNode); 348 TRESPASS(); 349 return NULL; 350 } 351 352 353 bool 354 AttributeStreamFileNode::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 362 const AttributeInfo* 363 AttributeStreamFileNode::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 380 AttributeStreamMemoryNode::AttributeStreamMemoryNode() 381 : fAttributes(5, true), 382 fCurrentIndex(-1) 383 { 384 } 385 386 387 void 388 AttributeStreamMemoryNode::MakeEmpty() 389 { 390 fAttributes.MakeEmpty(); 391 } 392 393 394 void 395 AttributeStreamMemoryNode::Rewind() 396 { 397 _inherited::Rewind(); 398 fCurrentIndex = -1; 399 } 400 401 402 int32 403 AttributeStreamMemoryNode::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 415 off_t 416 AttributeStreamMemoryNode::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 425 off_t 426 AttributeStreamMemoryNode::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 457 off_t 458 AttributeStreamMemoryNode::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 470 bool 471 AttributeStreamMemoryNode::Drive() 472 { 473 if (!_inherited::Drive()) 474 return false; 475 476 while (BufferingGet()) 477 ; 478 479 return true; 480 } 481 482 483 AttributeStreamMemoryNode::AttrNode* 484 AttributeStreamMemoryNode::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 499 AttributeStreamMemoryNode::AttrNode* 500 AttributeStreamMemoryNode::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 513 const AttributeInfo* 514 AttributeStreamMemoryNode::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 528 const char* 529 AttributeStreamMemoryNode::Get() 530 { 531 ASSERT(fCurrentIndex < fAttributes.CountItems()); 532 return fAttributes.ItemAt(fCurrentIndex)->fData; 533 } 534 535 536 bool 537 AttributeStreamMemoryNode::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 547 AttributeStreamTemplateNode::AttributeStreamTemplateNode( 548 const AttributeTemplate* attrTemplates, int32 count) 549 : fAttributes(attrTemplates), 550 fCurrentIndex(-1), 551 fCount(count) 552 { 553 } 554 555 556 off_t 557 AttributeStreamTemplateNode::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 567 void 568 AttributeStreamTemplateNode::Rewind() 569 { 570 fCurrentIndex = -1; 571 } 572 573 574 const AttributeInfo* 575 AttributeStreamTemplateNode::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 590 const char* 591 AttributeStreamTemplateNode::Get() 592 { 593 ASSERT(fCurrentIndex < fCount); 594 return fAttributes[fCurrentIndex].fBits; 595 } 596 597 598 bool 599 AttributeStreamTemplateNode::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 609 int32 610 AttributeStreamTemplateNode::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 623 bool 624 AttributeStreamFilterNode::Reject(const char*, uint32, off_t) 625 { 626 // simple pass everything filter 627 return false; 628 } 629 630 631 const AttributeInfo* 632 AttributeStreamFilterNode::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 649 off_t 650 AttributeStreamFilterNode::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 664 off_t 665 AttributeStreamFilterNode::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 680 off_t 681 AttributeStreamFilterNode::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 694 NamesToAcceptAttrFilter::NamesToAcceptAttrFilter(const char** nameList) 695 : fNameList(nameList) 696 { 697 } 698 699 700 bool 701 NamesToAcceptAttrFilter::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 718 SelectiveAttributeTransformer::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 730 SelectiveAttributeTransformer::~SelectiveAttributeTransformer() 731 { 732 for (int32 index = fTransformedBuffers.CountItems() - 1; index >= 0; 733 index--) { 734 delete[] fTransformedBuffers.ItemAt(index); 735 } 736 } 737 738 739 void 740 SelectiveAttributeTransformer::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 751 off_t 752 SelectiveAttributeTransformer::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 768 bool 769 SelectiveAttributeTransformer::WillTransform(const char* name, uint32, off_t, 770 const char*) const 771 { 772 return strcmp(name, fAttributeNameToTransform) == 0; 773 } 774 775 776 bool 777 SelectiveAttributeTransformer::ApplyTransformer(const char* name, uint32 type, 778 off_t size, char* data) 779 { 780 return (fTransformFunc)(name, type, size, data, fTransformParams); 781 } 782 783 char* 784 SelectiveAttributeTransformer::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 802 const AttributeInfo* 803 SelectiveAttributeTransformer::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 814 const char* 815 SelectiveAttributeTransformer::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