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