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