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