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