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