1/*
2Open Tracker License
3
4Terms and Conditions
5
6Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
7
8Permission is hereby granted, free of charge, to any person obtaining a copy of
9this software and associated documentation files (the "Software"), to deal in
10the Software without restriction, including without limitation the rights to
11use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12of the Software, and to permit persons to whom the Software is furnished to do
13so, subject to the following conditions:
14
15The above copyright notice and this permission notice applies to all licensees
16and shall be included in all copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25Except as contained in this notice, the name of Be Incorporated shall not be
26used in advertising or otherwise to promote the sale, use or other dealings in
27this Software without prior written authorization from Be Incorporated.
28
29Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30of Be Incorporated in the United States and other countries. Other brand product
31names are registered trademarks or trademarks of their respective holders.
32All 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
47AttributeInfo::AttributeInfo(const AttributeInfo &cloneThis)
48	:	fName(cloneThis.fName),
49		fInfo(cloneThis.fInfo)
50
51{
52}
53
54
55AttributeInfo::AttributeInfo(const char* name, attr_info info)
56	:	fName(name),
57		fInfo(info)
58{
59}
60
61
62AttributeInfo::AttributeInfo(const char* name, uint32 type, off_t size)
63	:	fName(name)
64{
65	fInfo.size = size;
66	fInfo.type = type;
67}
68
69
70const char*
71AttributeInfo::Name() const
72{
73	return fName.String();
74}
75
76uint32
77AttributeInfo::Type() const
78{
79	return fInfo.type;
80}
81
82off_t
83AttributeInfo::Size() const
84{
85	return fInfo.size;
86}
87
88
89void
90AttributeInfo::SetTo(const AttributeInfo &attr)
91{
92	fName = attr.fName;
93	fInfo = attr.fInfo;
94}
95
96void
97AttributeInfo::SetTo(const char* name, attr_info info)
98{
99	fName = name;
100	fInfo = info;
101}
102
103void
104AttributeInfo::SetTo(const char* name, uint32 type, off_t size)
105{
106	fName = name;
107	fInfo.type = type;
108	fInfo.size = size;
109}
110
111
112AttributeStreamNode::AttributeStreamNode()
113	:	fReadFrom(NULL),
114		fWriteTo(NULL)
115{
116}
117
118
119AttributeStreamNode::~AttributeStreamNode()
120{
121	Detach();
122}
123
124AttributeStreamNode&
125AttributeStreamNode::operator<<(AttributeStreamNode &source)
126{
127	fReadFrom = &source;
128	fReadFrom->fWriteTo = this;
129	if (fReadFrom->CanFeed())
130		fReadFrom->Start();
131
132	return source;
133}
134
135void
136AttributeStreamNode::Rewind()
137{
138	if (fReadFrom)
139		fReadFrom->Rewind();
140}
141
142void
143AttributeStreamFileNode::MakeEmpty()
144{
145	TRESPASS();
146}
147
148off_t
149AttributeStreamNode::Contains(const char* name, uint32 type)
150{
151	if (!fReadFrom)
152		return 0;
153
154	return fReadFrom->Contains(name, type);
155}
156
157
158off_t
159AttributeStreamNode::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
169off_t
170AttributeStreamNode::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
180bool
181AttributeStreamNode::Drive()
182{
183	ASSERT(CanFeed());
184	if (!fReadFrom)
185		return false;
186
187	Rewind();
188	return true;
189}
190
191
192const AttributeInfo*
193AttributeStreamNode::Next()
194{
195	if (fReadFrom)
196		return fReadFrom->Next();
197
198	return NULL;
199}
200
201
202const char*
203AttributeStreamNode::Get()
204{
205	ASSERT(fReadFrom);
206	if (!fReadFrom)
207		return NULL;
208
209	return fReadFrom->Get();
210}
211
212
213bool
214AttributeStreamNode::Fill(char* buffer) const
215{
216	ASSERT(fReadFrom);
217	return fReadFrom->Fill(buffer);
218}
219
220
221bool
222AttributeStreamNode::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
232void
233AttributeStreamNode::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
247AttributeStreamFileNode::AttributeStreamFileNode()
248	:	fNode(NULL)
249{
250}
251
252
253AttributeStreamFileNode::AttributeStreamFileNode(BNode* node)
254	:	fNode(node)
255{
256	ASSERT(fNode);
257}
258
259
260void
261AttributeStreamFileNode::Rewind()
262{
263	_inherited::Rewind();
264	fNode->RewindAttrs();
265}
266
267
268void
269AttributeStreamFileNode::SetTo(BNode* node)
270{
271	fNode = node;
272}
273
274
275off_t
276AttributeStreamFileNode::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
290off_t
291AttributeStreamFileNode::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
309off_t
310AttributeStreamFileNode::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
325bool
326AttributeStreamFileNode::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
344const char*
345AttributeStreamFileNode::Get()
346{
347	ASSERT(fNode);
348	TRESPASS();
349	return NULL;
350}
351
352
353bool
354AttributeStreamFileNode::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
362const AttributeInfo*
363AttributeStreamFileNode::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
380AttributeStreamMemoryNode::AttributeStreamMemoryNode()
381	:	fAttributes(5, true),
382		fCurrentIndex(-1)
383{
384}
385
386
387void
388AttributeStreamMemoryNode::MakeEmpty()
389{
390	fAttributes.MakeEmpty();
391}
392
393
394void
395AttributeStreamMemoryNode::Rewind()
396{
397	_inherited::Rewind();
398	fCurrentIndex = -1;
399}
400
401
402int32
403AttributeStreamMemoryNode::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
415off_t
416AttributeStreamMemoryNode::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
425off_t
426AttributeStreamMemoryNode::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
457off_t
458AttributeStreamMemoryNode::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
470bool
471AttributeStreamMemoryNode::Drive()
472{
473	if (!_inherited::Drive())
474		return false;
475
476	while (BufferingGet())
477		;
478
479	return true;
480}
481
482
483AttributeStreamMemoryNode::AttrNode*
484AttributeStreamMemoryNode::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
499AttributeStreamMemoryNode::AttrNode*
500AttributeStreamMemoryNode::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
513const AttributeInfo*
514AttributeStreamMemoryNode::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
528const char*
529AttributeStreamMemoryNode::Get()
530{
531	ASSERT(fCurrentIndex < fAttributes.CountItems());
532	return fAttributes.ItemAt(fCurrentIndex)->fData;
533}
534
535
536bool
537AttributeStreamMemoryNode::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
547AttributeStreamTemplateNode::AttributeStreamTemplateNode(
548	const AttributeTemplate* attrTemplates, int32 count)
549	:	fAttributes(attrTemplates),
550		fCurrentIndex(-1),
551		fCount(count)
552{
553}
554
555
556off_t
557AttributeStreamTemplateNode::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
567void
568AttributeStreamTemplateNode::Rewind()
569{
570	fCurrentIndex = -1;
571}
572
573
574const AttributeInfo*
575AttributeStreamTemplateNode::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
590const char*
591AttributeStreamTemplateNode::Get()
592{
593	ASSERT(fCurrentIndex < fCount);
594	return fAttributes[fCurrentIndex].fBits;
595}
596
597
598bool
599AttributeStreamTemplateNode::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
609int32
610AttributeStreamTemplateNode::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
623bool
624AttributeStreamFilterNode::Reject(const char*, uint32, off_t)
625{
626	// simple pass everything filter
627	return false;
628}
629
630
631const AttributeInfo*
632AttributeStreamFilterNode::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
649off_t
650AttributeStreamFilterNode::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
664off_t
665AttributeStreamFilterNode::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
680off_t
681AttributeStreamFilterNode::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
694NamesToAcceptAttrFilter::NamesToAcceptAttrFilter(const char** nameList)
695	:	fNameList(nameList)
696{
697}
698
699
700bool
701NamesToAcceptAttrFilter::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
718SelectiveAttributeTransformer::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
730SelectiveAttributeTransformer::~SelectiveAttributeTransformer()
731{
732	for (int32 index = fTransformedBuffers.CountItems() - 1; index >= 0;
733			index--) {
734		delete [] fTransformedBuffers.ItemAt(index);
735	}
736}
737
738
739void
740SelectiveAttributeTransformer::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
751off_t
752SelectiveAttributeTransformer::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
768bool
769SelectiveAttributeTransformer::WillTransform(const char* name, uint32, off_t,
770	const char*) const
771{
772	return strcmp(name, fAttributeNameToTransform) == 0;
773}
774
775
776bool
777SelectiveAttributeTransformer::ApplyTransformer(const char* name, uint32 type,
778	off_t size, char* data)
779{
780	return (fTransformFunc)(name, type, size, data, fTransformParams);
781}
782
783char*
784SelectiveAttributeTransformer::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
802const AttributeInfo*
803SelectiveAttributeTransformer::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
814const char*
815SelectiveAttributeTransformer::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