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