xref: /haiku/src/kits/app/PortLink.cpp (revision e5430a086c769ea76c3944046b1f07cf049c1ae0)
1 //------------------------------------------------------------------------------
2 //	Copyright (c) 2001-2002, OpenBeOS
3 //
4 //	Permission is hereby granted, free of charge, to any person obtaining a
5 //	copy of this software and associated documentation files (the "Software"),
6 //	to deal in the Software without restriction, including without limitation
7 //	the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 //	and/or sell copies of the Software, and to permit persons to whom the
9 //	Software is furnished to do so, subject to the following conditions:
10 //
11 //	The above copyright notice and this permission notice shall be included in
12 //	all copies or substantial portions of the Software.
13 //
14 //	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 //	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 //	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 //	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 //	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 //	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 //	DEALINGS IN THE SOFTWARE.
21 //
22 //	File Name:		PortLink.cpp
23 //	Author:			DarkWyrm <bpmagic@columbus.rr.com>
24 //	Description:	A helper class for port-based messaging
25 //
26 //------------------------------------------------------------------------------
27 #include <PortLink.h>
28 #include <PortMessage.h>
29 #include <string.h>
30 #include <stdio.h>
31 #include <malloc.h>
32 
33 //#define PLDEBUG
34 //#define PLD_DEBUG
35 
36 //#define CAPACITY_CHECKING
37 
38 #ifdef PLDEBUG
39 #include <stdio.h>
40 #endif
41 
42 #ifdef PLD_DEBUG
43 #include <stdio.h>
44 #endif
45 
46 /*!
47 	\class PortLinkData PortLink.cpp
48 	\brief Internal data storage class
49 
50 	PortLinkData objects serve to hold attached data whilst it is waiting to be Flattened()
51 	and then Flushed(). There is no need for this to be used outside the PortLink class.
52 */
53 class PortLinkData
54 {
55 public:
56 	PortLinkData(void);
57 	~PortLinkData(void);
58 	status_t Set(const void *data, size_t size);
59 	char *buffer;
60 	size_t buffersize;
61 };
62 
63 /*!
64 	\brief Constructor
65 	\param port A valid target port_id
66 */
67 PortLink::PortLink(port_id port)
68 {
69 #ifdef PLDEBUG
70 printf("PortLink(%lu)\n",port);
71 #endif
72 	target=port;
73 	port_info pi;
74 	port_ok=(get_port_info(target,&pi)==B_OK)?true:false;
75 	capacity=pi.capacity;
76 
77 	// We start out without any data attached to the port message
78 	opcode=0;
79 	bufferlength=0;
80 	replyport=create_port(30,"PortLink reply port");
81 	attachlist=new BList(0);
82 #ifdef PLDEBUG
83 printf("\tPort valid: %s\n",(port_ok)?"true":"false");
84 printf("\tReply port: %lu\n",replyport);
85 #endif
86 
87 	// TODO: initialize all attachments pointers to NULL
88 }
89 
90 /*!
91 	\brief Copy Constructor
92 	\param port A valid target port_id
93 
94 	The copy constructor copies everything except a PortLink's attachments.
95 */
96 PortLink::PortLink(const PortLink &link)
97 {
98 #ifdef PLDEBUG
99 printf("PortLink(PortLink*)\n");
100 #endif
101 	target=link.target;
102 	opcode=link.opcode;
103 	port_ok=link.port_ok;
104 	capacity=link.capacity;
105 	bufferlength=0;
106 	replyport=create_port(30,"PortLink reply port");
107 	attachlist=new BList(0);
108 #ifdef PLDEBUG
109 printf("\tOpcode: %lu\n",opcode);
110 printf("\tTarget port: %lu\n",target);
111 printf("\tCapacity: %lu\n",capacity);
112 printf("\tPort valid: %s\n",(port_ok)?"true":"false");
113 printf("\tReply port: %lu\n",replyport);
114 #endif
115 	// TODO: initialize all attachments pointers to NULL
116 }
117 
118 //! Empties all attachments in addition to deleting the attachment list itself
119 PortLink::~PortLink(void)
120 {
121 #ifdef PLDEBUG
122 printf("~PortLink()\n");
123 #endif
124 	// If, for some odd reason, this is deleted with something attached,
125 	// free the memory used by the attachments. We do not flush the queue
126 	// because the port may no longer be valid in cases such as the app
127 	// is in the process of quitting
128 	if(attachlist->CountItems()>0)
129 		MakeEmpty();
130 
131 	delete attachlist;
132 }
133 
134 /*!
135 	\brief Sets the link's message code
136 	\param code Message code to use
137 
138 	This code is persistent over sending messages - it will not change unless
139 	SetOpCode is called again.
140 */
141 void PortLink::SetOpCode(int32 code)
142 {
143 #ifdef PLDEBUG
144 printf("PortLink::SetOpCode(%c%c%c%c)\n",
145 (char)((code & 0xFF000000) >>  24),
146 (char)((code & 0x00FF0000) >>  16),
147 (char)((code & 0x0000FF00) >>  8),
148 (char)((code & 0x000000FF)) );
149 #endif
150 	// Sets the message code. This does not change once the message is sent.
151 	// Another call to SetOpCode() is required for such things.
152 	opcode=code;
153 }
154 
155 /*!
156 	\brief Changes the PortLink's target port
157 	\param port A valid target port_id
158 */
159 void PortLink::SetPort(port_id port)
160 {
161 #ifdef PLDEBUG
162 printf("PortLink::SetPort(%lu)\n",port);
163 #endif
164 	// Sets the target port. While not necessary in most uses, this exists
165 	// mostly to prevent flexibility problems
166 	target=port;
167 	port_info pi;
168 	port_ok=(get_port_info(target,&pi)==B_OK)?true:false;
169 	capacity=pi.capacity;
170 }
171 
172 /*!
173 	\brief Returns the PortLink's target port
174 	\return The PortLink's target port
175 */
176 port_id PortLink::GetPort(void)
177 {
178 #ifdef PLDEBUG
179 printf("PortLink::GetPort() returned %lu\n",target);
180 #endif
181 	// Simply returns the port at which the object is pointed.
182 	return target;
183 }
184 
185 status_t PortLink::Flush(bigtime_t timeout=B_INFINITE_TIMEOUT)
186 {
187 #ifdef PLDEBUG
188 printf("PortLink::Flush()\n");
189 #endif
190 	// Fires a message off to the target, complete with attachments.
191 	int8 *msgbuffer;
192 	int32 size;
193 	status_t write_stat=B_OK;
194 
195 	if(!port_ok)
196 	{
197 #ifdef PLDEBUG
198 printf("\tFlush(): invalid port\n");
199 #endif
200 		return B_BAD_VALUE;
201 	}
202 
203 	if(attachlist->CountItems()>0)
204 	{
205 #ifdef PLDEBUG
206 printf("\tFlush(): flushing %d attachments\n",num_attachments);
207 #endif
208 		FlattenData(&msgbuffer,&size);
209 
210 		// Dump message to port, reset attachments, and clean up
211 		if(timeout!=B_INFINITE_TIMEOUT)
212 			write_stat=write_port_etc(target,opcode,msgbuffer,size,B_TIMEOUT, timeout);
213 		else
214 			write_stat=write_port(target,opcode,msgbuffer,size);
215 		MakeEmpty();
216 	}
217 	else
218 	{
219 #ifdef PLDEBUG
220 printf("\tFlush(): flushing without attachments\n");
221 #endif
222 		if(timeout!=B_INFINITE_TIMEOUT)
223 			write_stat=write_port_etc(target,opcode,NULL,0,B_TIMEOUT, timeout);
224 		else
225 			write_stat=write_port(target,opcode,NULL,0);
226 	}
227 	return write_stat;
228 }
229 
230 
231 int8* PortLink::FlushWithReply(int32 *code, status_t *status, ssize_t *buffersize, bigtime_t timeout=B_INFINITE_TIMEOUT)
232 {
233 	// Deprecated call which functions exactly like PortLink(PortLink::ReplyData *data)
234 #ifdef PLDEBUG
235 printf("PortLink::FlushWithReply(int32*,status_t*,ssize_t*,bigtime_t)\n");
236 #endif
237 
238 	if(!port_ok)
239 	{
240 #ifdef PLDEBUG
241 printf("PortLink::FlushWithReply(): bad port\n");
242 #endif
243 		*status=B_BAD_VALUE;
244 		return NULL;
245 	}
246 
247 	// create a new storage object and stash the data
248 	PortLinkData *pld=new PortLinkData;
249 	if(pld->Set(&replyport,sizeof(port_id))==B_OK)
250 	{
251 		bufferlength+=sizeof(port_id);
252 	}
253 	else
254 	{
255 		delete pld;
256 		*status=B_ERROR;
257 		return NULL;
258 	}
259 
260 	// Flatten() inlined to make some necessary changes
261 	int8 *buffer=new int8[bufferlength];
262 	int8 *bufferindex=buffer;
263 	size_t size=0;
264 
265 	// attach our port_id first
266 	memcpy(bufferindex, pld->buffer, pld->buffersize);
267 	bufferindex += pld->buffersize;
268 	size+=pld->buffersize;
269 
270 	// attach everything else
271 	for(int i=0;i<attachlist->CountItems();i++)
272 	{
273 		pld=(PortLinkData*)attachlist->ItemAt(i);
274 		memcpy(bufferindex, pld->buffer, pld->buffersize);
275 		bufferindex += pld->buffersize;
276 		size+=pld->buffersize;
277 	}
278 
279 	// Flush the thing....FOOSH! :P
280 	write_port(target,opcode,buffer,size);
281 	MakeEmpty();
282 	delete buffer;
283 
284 	// Now we wait for the reply
285 	buffer=NULL;
286 	if(timeout==B_INFINITE_TIMEOUT)
287 	{
288 		*buffersize=port_buffer_size(replyport);
289 		if(*buffersize>0)
290 			buffer=(int8*)new int8[*buffersize];
291 		read_port(replyport,code, buffer, *buffersize);
292 	}
293 	else
294 	{
295 		*buffersize=port_buffer_size_etc(replyport,0,timeout);
296 		if(*buffersize==B_TIMED_OUT)
297 		{
298 			*status=*buffersize;
299 			return NULL;
300 		}
301 		if(*buffersize>0)
302 			buffer=(int8*)new int8[*buffersize];
303 		read_port(replyport,code, buffer, *buffersize);
304 	}
305 
306 	// We got this far, so we apparently have some data
307 	*status=B_OK;
308 	return buffer;
309 }
310 
311 
312 status_t PortLink::FlushWithReply(PortLink::ReplyData *data,bigtime_t timeout=B_INFINITE_TIMEOUT)
313 {
314 #ifdef PLDEBUG
315 printf("PortLink::FlushWithReply(ReplyData*,bigtime_t)\n");
316 #endif
317 	// Fires a message to the target and then waits for a reply. The target will
318 	// receive a message with the first item being the port_id to reply to.
319 	// NOTE: like Flush(), any attached data must be deleted.
320 
321 	// Effectively, an Attach() call inlined for changes
322 
323 	if(!port_ok)
324 	{
325 #ifdef PLDEBUG
326 printf("\tFlushWithReply(): invalid port\n");
327 #endif
328 		return B_BAD_VALUE;
329 	}
330 
331 	// create a new storage object and stash the data
332 	PortLinkData *pld=new PortLinkData;
333 	if(pld->Set(&replyport,sizeof(port_id))==B_OK)
334 	{
335 		bufferlength+=sizeof(port_id);
336 	}
337 	else
338 	{
339 #ifdef PLDEBUG
340 printf("\tFlushWithReply(): unable to assign reply port to data\n");
341 #endif
342 		delete pld;
343 		return B_ERROR;
344 	}
345 
346 	// Flatten() inlined to make some necessary changes
347 	int8 *buffer=new int8[bufferlength];
348 	int8 *bufferindex=buffer;
349 	size_t size=0;
350 
351 	// attach our port_id first
352 	memcpy(bufferindex, pld->buffer, pld->buffersize);
353 	bufferindex += pld->buffersize;
354 	size+=pld->buffersize;
355 
356 	// attach everything else
357 	for(int i=0;i<attachlist->CountItems();i++)
358 	{
359 		pld=(PortLinkData*)attachlist->ItemAt(i);
360 		memcpy(bufferindex, pld->buffer, pld->buffersize);
361 		bufferindex += pld->buffersize;
362 		size+=pld->buffersize;
363 	}
364 
365 	// Flush the thing....FOOSH! :P
366 	write_port(target,opcode,buffer,size);
367 	MakeEmpty();
368 	delete buffer;
369 
370 	// Now we wait for the reply
371 	if(timeout==B_INFINITE_TIMEOUT)
372 	{
373 		data->buffersize=port_buffer_size(replyport);
374 		if(data->buffersize>0)
375 		{
376 			if(data->buffer)
377 				delete data->buffer;
378 			data->buffer=(int8*)new int8[data->buffersize];
379 		}
380 		read_port(replyport,&(data->code),data->buffer, data->buffersize);
381 	}
382 	else
383 	{
384 		data->buffersize=port_buffer_size_etc(replyport,0,timeout);
385 		if(data->buffersize==B_TIMED_OUT)
386 			return B_TIMED_OUT;
387 
388 		if(data->buffersize>0)
389 		{
390 			data->buffer=(int8*)new int8[data->buffersize];
391 		}
392 		read_port(replyport,&(data->code),data->buffer, data->buffersize);
393 	}
394 
395 	// We got this far, so we apparently have some data
396 	return B_OK;
397 }
398 
399 status_t PortLink::FlushWithReply(PortMessage *msg,bigtime_t timeout=B_INFINITE_TIMEOUT)
400 {
401 #ifdef PLDEBUG
402 printf("PortLink::FlushWithReply(PortMessage*,bigtime_t)\n");
403 #endif
404 	// Fires a message to the target and then waits for a reply. The target will
405 	// receive a message with the first item being the port_id to reply to.
406 
407 	// Effectively, an Attach() call inlined for changes
408 	if(!port_ok || !msg)
409 	{
410 #ifdef PLDEBUG
411 printf("\tFlushWithReply(): invalid port\n");
412 #endif
413 		return B_BAD_VALUE;
414 	}
415 
416 	// create a new storage object and stash the data
417 	PortLinkData *pld=new PortLinkData;
418 	if(pld->Set(&replyport,sizeof(port_id))==B_OK)
419 	{
420 		bufferlength+=sizeof(port_id);
421 	}
422 	else
423 	{
424 #ifdef PLDEBUG
425 printf("\tFlushWithReply(): unable to assign reply port to data\n");
426 #endif
427 		delete pld;
428 		return B_ERROR;
429 	}
430 
431 	// Flatten() inlined to make some necessary changes
432 	int8 *buffer=new int8[bufferlength];
433 	int8 *bufferindex=buffer;
434 	size_t size=0;
435 
436 	// attach our port_id first
437 	memcpy(bufferindex, pld->buffer, pld->buffersize);
438 	bufferindex += pld->buffersize;
439 	size+=pld->buffersize;
440 
441 	// attach everything else
442 	for(int i=0;i<attachlist->CountItems();i++)
443 	{
444 		pld=(PortLinkData*)attachlist->ItemAt(i);
445 		memcpy(bufferindex, pld->buffer, pld->buffersize);
446 		bufferindex += pld->buffersize;
447 		size+=pld->buffersize;
448 	}
449 
450 	// Flush the thing....FOOSH! :P
451 	write_port(target,opcode,buffer,size);
452 	MakeEmpty();
453 	delete buffer;
454 
455 	// Now we wait for the reply
456 	ssize_t rbuffersize;
457 	int8 *rbuffer=NULL;
458 	int32 rcode;
459 
460 	if(timeout==B_INFINITE_TIMEOUT)
461 	{
462 		rbuffersize=port_buffer_size(replyport);
463 		if(rbuffersize>0)
464 			rbuffer=(int8*)new int8[rbuffersize];
465 
466 		read_port(replyport,&rcode,rbuffer,rbuffersize);
467 	}
468 	else
469 	{
470 		rbuffersize=port_buffer_size_etc(replyport,0,timeout);
471 		if(rbuffersize==B_TIMED_OUT)
472 			return B_TIMED_OUT;
473 
474 		if(rbuffersize>0)
475 			rbuffer=(int8*)new int8[rbuffersize];
476 
477 		read_port(replyport,&rcode,rbuffer,rbuffersize);
478 	}
479 
480 	// We got this far, so we apparently have some data
481 	msg->SetCode(rcode);
482 	msg->SetBuffer(rbuffer,rbuffersize,false);
483 
484 	return B_OK;
485 }
486 
487 status_t PortLink::Attach(const void *data, size_t size)
488 {
489 #ifdef PLDEBUG
490 printf("Attach(%p,%ld)\n",data,size);
491 #endif
492 	// This is the member called to attach data to a message. Attachments are
493 	// treated to be in 'Append' mode, tacking on each attached piece of data
494 	// to the end of the list.
495 
496 	// Prevent parameter problems
497 	if(size==0)
498 	{
499 #ifdef PLDEBUG
500 printf("\tAttach(): size invalid -> size=0\n");
501 #endif
502 		return B_ERROR;
503 	}
504 
505 #ifdef CAPACITY_CHECKING
506 	if(bufferlength+size>capacity)
507 	{
508 #ifdef PLDEBUG
509 printf("\tAttach(): bufferlength+size > port capacity\n");
510 #endif
511 		return B_NO_MEMORY;
512 	}
513 #endif
514 
515 	// create a new storage object and stash the data
516 	PortLinkData *pld=new PortLinkData;
517 	if(pld->Set(data,size)==B_OK)
518 	{
519 		attachlist->AddItem(pld);
520 		bufferlength+=size;
521 #ifdef PLDEBUG
522 printf("\tAttach(): successful\n");
523 printf("\t\tAttach(): attachments now %u\n", num_attachments);
524 printf("\t\tAttach(): buffer length is %lu\n", bufferlength);
525 #endif
526 	}
527 	else
528 	{
529 #ifdef PLDEBUG
530 printf("\tAttach(): Couldn't assign data to PortLinkData object\n");
531 #endif
532 		delete pld;
533 		return B_ERROR;
534 	}
535 
536 	return B_OK;
537 }
538 
539 // These functions were added for a major convenience in passing common types
540 // Eventually, I'd like to templatize these, but for now, this'll do
541 
542 status_t PortLink::Attach(int32 data)
543 {
544 #ifdef PLDEBUG
545 printf("Attach(%ld)\n",data);
546 #endif
547 	int32 size=sizeof(int32);
548 
549 #ifdef CAPACITY_CHECKING
550 	if(bufferlength+size>capacity)
551 		return B_NO_MEMORY;
552 #endif
553 
554 	// create a new storage object and stash the data
555 	PortLinkData *pld=new PortLinkData;
556 	if(pld->Set(&data,size)==B_OK)
557 	{
558 		attachlist->AddItem(pld);
559 		bufferlength+=size;
560 	}
561 	else
562 	{
563 		delete pld;
564 		return B_ERROR;
565 	}
566 	return B_OK;
567 }
568 
569 status_t PortLink::Attach(int16 data)
570 {
571 #ifdef PLDEBUG
572 printf("Attach(%d)\n",data);
573 #endif
574 	int32 size=sizeof(int16);
575 
576 #ifdef CAPACITY_CHECKING
577 	if(bufferlength+size>capacity)
578 		return B_NO_MEMORY;
579 #endif
580 
581 	// create a new storage object and stash the data
582 	PortLinkData *pld=new PortLinkData;
583 	if(pld->Set(&data,size)==B_OK)
584 	{
585 		attachlist->AddItem(pld);
586 		bufferlength+=size;
587 	}
588 	else
589 	{
590 		delete pld;
591 		return B_ERROR;
592 	}
593 	return B_OK;
594 }
595 
596 status_t PortLink::Attach(int8 data)
597 {
598 #ifdef PLDEBUG
599 printf("Attach(%d)\n",data);
600 #endif
601 	int32 size=sizeof(int8);
602 
603 #ifdef CAPACITY_CHECKING
604 	if(bufferlength+size>capacity)
605 		return B_NO_MEMORY;
606 #endif
607 
608 	// create a new storage object and stash the data
609 	PortLinkData *pld=new PortLinkData;
610 	if(pld->Set(&data,size)==B_OK)
611 	{
612 		attachlist->AddItem(pld);
613 		bufferlength+=size;
614 	}
615 	else
616 	{
617 		delete pld;
618 		return B_ERROR;
619 	}
620 	return B_OK;
621 }
622 
623 status_t PortLink::Attach(float data)
624 {
625 #ifdef PLDEBUG
626 printf("Attach(%f)\n",data);
627 #endif
628 	int32 size=sizeof(float);
629 
630 #ifdef CAPACITY_CHECKING
631 	if(bufferlength+size>capacity)
632 		return B_NO_MEMORY;
633 #endif
634 
635 	// create a new storage object and stash the data
636 	PortLinkData *pld=new PortLinkData;
637 	if(pld->Set(&data,size)==B_OK)
638 	{
639 		attachlist->AddItem(pld);
640 		bufferlength+=size;
641 	}
642 	else
643 	{
644 		delete pld;
645 		return B_ERROR;
646 	}
647 	return B_OK;
648 }
649 
650 status_t PortLink::Attach(bool data)
651 {
652 #ifdef PLDEBUG
653 printf("Attach(%s)\n",(data)?"true":"false");
654 #endif
655 
656 	int32 size=sizeof(bool);
657 
658 #ifdef CAPACITY_CHECKING
659 	if(bufferlength+size>capacity)
660 		return B_NO_MEMORY;
661 #endif
662 
663 	// create a new storage object and stash the data
664 	PortLinkData *pld=new PortLinkData;
665 	if(pld->Set(&data,size)==B_OK)
666 	{
667 		attachlist->AddItem(pld);
668 		bufferlength+=size;
669 	}
670 	else
671 	{
672 		delete pld;
673 		return B_ERROR;
674 	}
675 	return B_OK;
676 }
677 
678 status_t PortLink::Attach(BRect data)
679 {
680 #ifdef PLDEBUG
681 printf("Attach(BRect(%f,%f,%f,%f))\n",data.left,data.top,data.right,data.bottom);
682 #endif
683 	int32 size=sizeof(BRect);
684 
685 #ifdef CAPACITY_CHECKING
686 	if(bufferlength+size>capacity)
687 		return B_NO_MEMORY;
688 #endif
689 
690 	// create a new storage object and stash the data
691 	PortLinkData *pld=new PortLinkData;
692 	if(pld->Set(&data,size)==B_OK)
693 	{
694 		attachlist->AddItem(pld);
695 		bufferlength+=size;
696 	}
697 	else
698 	{
699 		delete pld;
700 		return B_ERROR;
701 	}
702 	return B_OK;
703 }
704 
705 status_t PortLink::Attach(BPoint data)
706 {
707 #ifdef PLDEBUG
708 printf("Attach(BPoint(%f,%f))\n",data.x,data.y);
709 #endif
710 	int32 size=sizeof(BPoint);
711 
712 #ifdef CAPACITY_CHECKING
713 	if(bufferlength+size>capacity)
714 		return B_NO_MEMORY;
715 #endif
716 
717 	// create a new storage object and stash the data
718 	PortLinkData *pld=new PortLinkData;
719 	if(pld->Set(&data,size)==B_OK)
720 	{
721 		attachlist->AddItem(pld);
722 		bufferlength+=size;
723 	}
724 	else
725 	{
726 		delete pld;
727 		return B_ERROR;
728 	}
729 	return B_OK;
730 }
731 
732 void PortLink::FlattenData(int8 **buffer,int32 *size)
733 {
734 	// This function is where all the magic happens, but it is strictly internal.
735 	// It iterates through each PortLinkData object and copies it to the main buffer
736 	// which ends up, ultimately, being written to the PortLink's target port.
737 
738 	// skip if there aree no attachments
739 	if(bufferlength<1)
740 	{
741 #ifdef PLDEBUG
742 printf("PortLink::FlattenData: bufferlength<1\n");
743 #endif
744 		return;
745 	}
746 
747 	*buffer=new int8[bufferlength];
748 	int8 *bufferindex=*buffer;
749 	PortLinkData *pld;
750 	*size=0;
751 
752 	int32 count=attachlist->CountItems();
753 	for(int i=0;i<count;i++)
754 	{
755 		pld=(PortLinkData*)attachlist->ItemAt(i);
756 		memcpy(bufferindex, pld->buffer, pld->buffersize);
757 		bufferindex += pld->buffersize;
758 		*size+=pld->buffersize;
759 	}
760 }
761 
762 void PortLink::MakeEmpty(void)
763 {
764 #ifdef PLDEBUG
765 printf("PortLink::MakeEmpty\n");
766 #endif
767 	// Nukes all the attachments currently held by the PortLink class
768 	PortLinkData *pld;
769 	int32 count=attachlist->CountItems();
770 	for(int32 i=0; i<count; i++)
771 	{
772 		pld=(PortLinkData*)attachlist->ItemAt(i);
773 		if(pld)
774 			delete pld;
775 	}
776 	attachlist->MakeEmpty();
777 	bufferlength=0;
778 }
779 
780 PortLinkData::PortLinkData(void)
781 {
782 	// Initialize object to empty
783 	buffersize=0;
784 	buffer=NULL;
785 }
786 
787 PortLinkData::~PortLinkData(void)
788 {
789 	// Frees the buffer if we actually used the class to store data
790 	if(buffersize>0 && buffer!=NULL)
791 		free(buffer);
792 }
793 
794 status_t PortLinkData::Set(const void *data, size_t size)
795 {
796 #ifdef PLD_DEBUG
797 printf("PortLinkData::Set(%p,%lu)\n",data,size);
798 #endif
799 	// Function copies the passed to the internal buffers for storage
800 	if(size>0 && buffersize==0 && data!=NULL)
801 	{
802 		buffer=(char *)malloc(size);
803 		if(!buffer)
804 		{
805 #ifdef PLD_DEBUG
806 printf("\tSet(): Couldn't allocate buffer\n");
807 #endif
808 			return B_NO_MEMORY;
809 		}
810 		memcpy(buffer, data, size);
811 		buffersize=size;
812 #ifdef PLD_DEBUG
813 printf("\tSet(): SUCCESS\n");
814 #endif
815 		return B_OK;
816 	}
817 
818 #ifdef PLD_DEBUG
819 if(size==0)
820 	printf("\tSet(): given an invalid size\n");
821 if(buffersize>0)
822 	printf("\tSet(): buffersize is nonzero\n");
823 if(buffersize>0)
824 	printf("\tSet(): data is NULL\n");
825 #endif
826 
827 	return B_ERROR;
828 }
829