xref: /haiku/src/kits/tracker/AttributeStream.cpp (revision 991dadd6324f7b7a68e94743a39ebae789823228)
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