6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
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:
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.
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.
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.
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.
36 #include "AttributeStream.h"
41 #include "Utilities.h"
45 // lazy Rewind from Drive, only if data is available
47 // partial feeding (part, not the whole buffer)
50 // #pragma mark - AttributeInfo
53 AttributeInfo::AttributeInfo()
57 fInfo
.type
= B_RAW_TYPE
;
62 AttributeInfo::AttributeInfo(const AttributeInfo
& other
)
71 AttributeInfo::AttributeInfo(const char* name
, attr_info info
)
79 AttributeInfo::AttributeInfo(const char* name
, uint32 type
, off_t size
)
89 AttributeInfo::Name() const
91 return fName
.String();
96 AttributeInfo::Type() const
103 AttributeInfo::Size() const
110 AttributeInfo::SetTo(const AttributeInfo
& other
)
118 AttributeInfo::SetTo(const char* name
, attr_info info
)
126 AttributeInfo::SetTo(const char* name
, uint32 type
, off_t size
)
134 // #pragma mark - AttributeStreamNode
137 AttributeStreamNode::AttributeStreamNode()
145 AttributeStreamNode::~AttributeStreamNode()
152 AttributeStreamNode::operator<<(AttributeStreamNode
&source
)
155 fReadFrom
->fWriteTo
= this;
156 if (fReadFrom
->CanFeed())
164 AttributeStreamNode::Rewind()
166 if (fReadFrom
!= NULL
)
172 AttributeStreamFileNode::MakeEmpty()
179 AttributeStreamNode::Contains(const char* name
, uint32 type
)
181 if (fReadFrom
== NULL
)
184 return fReadFrom
->Contains(name
, type
);
189 AttributeStreamNode::Read(const char* name
, const char* foreignName
,
190 uint32 type
, off_t size
, void* buffer
, void (*swapFunc
)(void*))
192 if (fReadFrom
== NULL
)
195 return fReadFrom
->Read(name
, foreignName
, type
, size
, buffer
, swapFunc
);
200 AttributeStreamNode::Write(const char* name
, const char* foreignName
,
201 uint32 type
, off_t size
, const void* buffer
)
203 if (fWriteTo
== NULL
)
206 return fWriteTo
->Write(name
, foreignName
, type
, size
, buffer
);
211 AttributeStreamNode::Drive()
214 if (fReadFrom
== NULL
)
223 AttributeStreamNode::Next()
225 if (fReadFrom
!= NULL
)
226 return fReadFrom
->Next();
233 AttributeStreamNode::Get()
235 ASSERT(fReadFrom
!= NULL
);
237 return fReadFrom
->Get();
242 AttributeStreamNode::Fill(char* buffer
) const
244 ASSERT(fReadFrom
!= NULL
);
246 return fReadFrom
->Fill(buffer
);
251 AttributeStreamNode::Start()
253 if (fWriteTo
== NULL
) {
254 // we are at the head of the stream, start drivin'
258 return fWriteTo
->Start();
263 AttributeStreamNode::Detach()
265 AttributeStreamNode
* tmpFrom
= fReadFrom
;
266 AttributeStreamNode
* tmpTo
= fWriteTo
;
278 // #pragma mark - AttributeStreamFileNode
281 AttributeStreamFileNode::AttributeStreamFileNode()
288 AttributeStreamFileNode::AttributeStreamFileNode(BNode
* node
)
292 ASSERT(fNode
!= NULL
);
297 AttributeStreamFileNode::Rewind()
299 _inherited::Rewind();
300 fNode
->RewindAttrs();
305 AttributeStreamFileNode::SetTo(BNode
* node
)
312 AttributeStreamFileNode::Contains(const char* name
, uint32 type
)
314 ThrowOnAssert(fNode
!= NULL
);
317 if (fNode
->GetAttrInfo(name
, &info
) != B_OK
)
320 if (info
.type
!= type
)
328 AttributeStreamFileNode::Read(const char* name
, const char* foreignName
,
329 uint32 type
, off_t size
, void* buffer
, void (*swapFunc
)(void*))
332 && fNode
->ReadAttr(name
, type
, 0, buffer
, (size_t)size
) == size
) {
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
)
351 AttributeStreamFileNode::Write(const char* name
, const char* foreignName
,
352 uint32 type
, off_t size
, const void* buffer
)
354 ThrowOnAssert(fNode
!= NULL
);
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
);
368 AttributeStreamFileNode::Drive()
370 if (!_inherited::Drive())
373 ThrowOnAssert(fNode
!= NULL
);
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())
389 AttributeStreamFileNode::Get()
391 ASSERT(fNode
!= NULL
);
399 AttributeStreamFileNode::Fill(char* buffer
) const
401 ThrowOnAssert(fNode
!= NULL
);
403 return fNode
->ReadAttr(fCurrentAttr
.Name(), fCurrentAttr
.Type(), 0,
404 buffer
, (size_t)fCurrentAttr
.Size()) == (ssize_t
)fCurrentAttr
.Size();
409 AttributeStreamFileNode::Next()
411 ASSERT(fReadFrom
== NULL
);
412 ThrowOnAssert(fNode
!= NULL
);
415 if (fNode
->GetNextAttrName(attrName
) != B_OK
)
419 if (fNode
->GetAttrInfo(attrName
, &info
) != B_OK
)
422 fCurrentAttr
.SetTo(attrName
, info
);
424 return &fCurrentAttr
;
428 // #pragma mark - AttributeStreamMemoryNode
431 AttributeStreamMemoryNode::AttributeStreamMemoryNode()
433 fAttributes(5, true),
440 AttributeStreamMemoryNode::MakeEmpty()
442 fAttributes
.MakeEmpty();
447 AttributeStreamMemoryNode::Rewind()
449 _inherited::Rewind();
455 AttributeStreamMemoryNode::Find(const char* name
, uint32 type
) const
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
) {
470 AttributeStreamMemoryNode::Contains(const char* name
, uint32 type
)
472 int32 index
= Find(name
, type
);
474 return index
< 0 ? 0 : fAttributes
.ItemAt(index
)->fAttr
.Size();
479 AttributeStreamMemoryNode::Read(const char* name
,
480 const char* DEBUG_ONLY(foreignName
), uint32 type
, off_t bufferSize
,
481 void* buffer
, void (*DEBUG_ONLY(swapFunc
))(void*))
483 ASSERT(foreignName
== NULL
);
484 ASSERT(swapFunc
== NULL
);
486 AttrNode
* attrNode
= NULL
;
488 int32 index
= Find(name
, type
);
490 if (fReadFrom
== NULL
)
493 off_t size
= fReadFrom
->Contains(name
, type
);
497 attrNode
= BufferingGet(name
, type
, size
);
498 if (attrNode
== NULL
)
501 attrNode
= fAttributes
.ItemAt(index
);
503 if (attrNode
->fAttr
.Size() > bufferSize
)
506 memcpy(buffer
, attrNode
->fData
, (size_t)attrNode
->fAttr
.Size());
508 return attrNode
->fAttr
.Size();
513 AttributeStreamMemoryNode::Write(const char* name
, const char*, uint32 type
,
514 off_t size
, const void* buffer
)
516 char* newBuffer
= new char[size
];
517 memcpy(newBuffer
, buffer
, (size_t)size
);
519 AttrNode
* attrNode
= new AttrNode(name
, type
, size
, newBuffer
);
520 fAttributes
.AddItem(attrNode
);
527 AttributeStreamMemoryNode::Drive()
529 if (!_inherited::Drive())
532 while (BufferingGet())
539 AttributeStreamMemoryNode::AttrNode
*
540 AttributeStreamMemoryNode::BufferingGet(const char* name
, uint32 type
,
543 char* newBuffer
= new char[size
];
544 if (!fReadFrom
->Fill(newBuffer
)) {
549 AttrNode
* attrNode
= new AttrNode(name
, type
, size
, newBuffer
);
550 fAttributes
.AddItem(attrNode
);
552 return fAttributes
.LastItem();
556 AttributeStreamMemoryNode::AttrNode
*
557 AttributeStreamMemoryNode::BufferingGet()
559 if (fReadFrom
== NULL
)
562 const AttributeInfo
* attr
= fReadFrom
->Next();
566 return BufferingGet(attr
->Name(), attr
->Type(), attr
->Size());
571 AttributeStreamMemoryNode::Next()
573 if (fReadFrom
!= NULL
) {
574 // the buffer is in the middle of the stream, get
575 // one buffer at a time
579 if (fCurrentIndex
+ 1 >= fAttributes
.CountItems())
582 return &fAttributes
.ItemAt(++fCurrentIndex
)->fAttr
;
587 AttributeStreamMemoryNode::Get()
589 ASSERT(fCurrentIndex
< fAttributes
.CountItems());
591 return fAttributes
.ItemAt(fCurrentIndex
)->fData
;
596 AttributeStreamMemoryNode::Fill(char* buffer
) const
598 ASSERT(fCurrentIndex
< fAttributes
.CountItems());
599 memcpy(buffer
, fAttributes
.ItemAt(fCurrentIndex
)->fData
,
600 (size_t)fAttributes
.ItemAt(fCurrentIndex
)->fAttr
.Size());
606 // #pragma mark - AttributeStreamTemplateNode
609 AttributeStreamTemplateNode::AttributeStreamTemplateNode(
610 const AttributeTemplate
* attrTemplates
, int32 count
)
612 fAttributes(attrTemplates
),
620 AttributeStreamTemplateNode::Contains(const char* name
, uint32 type
)
622 int32 index
= Find(name
, type
);
626 return fAttributes
[index
].fSize
;
631 AttributeStreamTemplateNode::Rewind()
638 AttributeStreamTemplateNode::Next()
640 if (fCurrentIndex
+ 1 >= fCount
)
645 fCurrentAttr
.SetTo(fAttributes
[fCurrentIndex
].fAttributeName
,
646 fAttributes
[fCurrentIndex
].fAttributeType
,
647 fAttributes
[fCurrentIndex
].fSize
);
649 return &fCurrentAttr
;
654 AttributeStreamTemplateNode::Get()
656 ASSERT(fCurrentIndex
< fCount
);
658 return fAttributes
[fCurrentIndex
].fBits
;
663 AttributeStreamTemplateNode::Fill(char* buffer
) const
665 ASSERT(fCurrentIndex
< fCount
);
666 memcpy(buffer
, fAttributes
[fCurrentIndex
].fBits
,
667 (size_t)fAttributes
[fCurrentIndex
].fSize
);
674 AttributeStreamTemplateNode::Find(const char* name
, uint32 type
) const
676 for (int32 index
= 0; index
< fCount
; index
++) {
677 if (fAttributes
[index
].fAttributeType
== type
&&
678 strcmp(name
, fAttributes
[index
].fAttributeName
) == 0) {
687 // #pragma mark - AttributeStreamFilterNode
691 AttributeStreamFilterNode::Reject(const char*, uint32
, off_t
)
693 // simple pass everything filter
699 AttributeStreamFilterNode::Next()
701 if (fReadFrom
== NULL
)
705 const AttributeInfo
* attr
= fReadFrom
->Next();
709 if (!Reject(attr
->Name(), attr
->Type(), attr
->Size()))
718 AttributeStreamFilterNode::Contains(const char* name
, uint32 type
)
720 if (fReadFrom
== NULL
)
723 off_t size
= fReadFrom
->Contains(name
, type
);
725 if (!Reject(name
, type
, size
))
733 AttributeStreamFilterNode::Read(const char* name
, const char* foreignName
,
734 uint32 type
, off_t size
, void* buffer
, void (*swapFunc
)(void*))
736 if (fReadFrom
== NULL
)
739 if (!Reject(name
, type
, size
)) {
740 return fReadFrom
->Read(name
, foreignName
, type
, size
, buffer
,
749 AttributeStreamFilterNode::Write(const char* name
, const char* foreignName
,
750 uint32 type
, off_t size
, const void* buffer
)
752 if (fWriteTo
== NULL
)
755 if (!Reject(name
, type
, size
))
756 return fWriteTo
->Write(name
, foreignName
, type
, size
, buffer
);
762 // #pragma mark - NamesToAcceptAttrFilter
765 NamesToAcceptAttrFilter::NamesToAcceptAttrFilter(const char** nameList
)
773 NamesToAcceptAttrFilter::Reject(const char* name
, uint32
, off_t
)
775 for (int32 index
= 0; ; index
++) {
776 if (fNameList
[index
] == NULL
)
779 if (strcmp(name
, fNameList
[index
]) == 0) {
780 //PRINT(("filter passing through %s\n", name));
785 //PRINT(("filter rejecting %s\n", name));
790 // #pragma mark - SelectiveAttributeTransformer
793 SelectiveAttributeTransformer::SelectiveAttributeTransformer(
794 const char* attributeName
,
795 bool (*transformFunc
)(const char* , uint32
, off_t
, void*, void*),
798 fAttributeNameToTransform(attributeName
),
799 fTransformFunc(transformFunc
),
800 fTransformParams(params
),
801 fTransformedBuffers(10, false)
806 SelectiveAttributeTransformer::~SelectiveAttributeTransformer()
808 for (int32 index
= fTransformedBuffers
.CountItems() - 1; index
>= 0;
810 delete[] fTransformedBuffers
.ItemAt(index
);
816 SelectiveAttributeTransformer::Rewind()
818 for (int32 index
= fTransformedBuffers
.CountItems() - 1; index
>= 0;
820 delete[] fTransformedBuffers
.ItemAt(index
);
823 fTransformedBuffers
.MakeEmpty();
828 SelectiveAttributeTransformer::Read(const char* name
, const char* foreignName
,
829 uint32 type
, off_t size
, void* buffer
, void (*swapFunc
)(void*))
831 if (fReadFrom
== NULL
)
834 off_t result
= fReadFrom
->Read(name
, foreignName
, type
, size
, buffer
,
837 if (WillTransform(name
, type
, size
, (const char*)buffer
))
838 ApplyTransformer(name
, type
, size
, (char*)buffer
);
845 SelectiveAttributeTransformer::WillTransform(const char* name
, uint32
, off_t
,
848 return strcmp(name
, fAttributeNameToTransform
) == 0;
853 SelectiveAttributeTransformer::ApplyTransformer(const char* name
, uint32 type
,
854 off_t size
, char* data
)
856 return (fTransformFunc
)(name
, type
, size
, data
, fTransformParams
);
860 SelectiveAttributeTransformer::CopyAndApplyTransformer(const char* name
,
861 uint32 type
, off_t size
, const char* data
)
866 result
= new char[size
];
867 memcpy(result
, data
, (size_t)size
);
870 if (!(fTransformFunc
)(name
, type
, size
, result
, fTransformParams
)) {
880 SelectiveAttributeTransformer::Next()
882 const AttributeInfo
* result
= fReadFrom
->Next();
887 fCurrentAttr
.SetTo(*result
);
893 SelectiveAttributeTransformer::Get()
895 if (fReadFrom
== NULL
)
898 const char* result
= fReadFrom
->Get();
900 if (!WillTransform(fCurrentAttr
.Name(), fCurrentAttr
.Type(),
901 fCurrentAttr
.Size(), result
)) {
905 char* transformedData
= CopyAndApplyTransformer(fCurrentAttr
.Name(),
906 fCurrentAttr
.Type(), fCurrentAttr
.Size(), result
);
908 // enlist for proper disposal when our job is done
909 if (transformedData
!= NULL
) {
910 fTransformedBuffers
.AddItem(transformedData
);
911 return transformedData
;