1// RequestMemberArray.h
2
3#ifndef NET_FS_REQUEST_MEMBER_ARRAY_H
4#define NET_FS_REQUEST_MEMBER_ARRAY_H
5
6#include <new>
7
8#include <stdlib.h>
9
10#include "Request.h"
11#include "RequestFlattener.h"
12#include "RequestUnflattener.h"
13
14template<typename Member>
15class RequestMemberArray : public FlattenableRequestMember {
16public:
17	RequestMemberArray()
18		: fElements(NULL),
19		  fSize(0),
20		  fCapacity(0)
21	{
22	}
23
24	virtual ~RequestMemberArray()
25	{
26		for (int32 i = 0; i < fSize; i++)
27			fElements[i].~Member();
28		free(fElements);
29	}
30
31	virtual void ShowAround(RequestMemberVisitor* visitor)
32	{
33		visitor->Visit(this, fSize);
34		for (int32 i = 0; i < fSize; i++)
35			visitor->Visit(this, fElements[i]);
36	}
37
38	virtual status_t Flatten(RequestFlattener* flattener)
39	{
40		if (flattener->WriteInt32(fSize) != B_OK)
41			return flattener->GetStatus();
42
43		for (int32 i = 0; i < fSize; i++)
44			flattener->Visit(this, fElements[i]);
45
46		return flattener->GetStatus();
47	}
48
49	virtual status_t Unflatten(RequestUnflattener* unflattener)
50	{
51		if (fSize > 0) {
52			for (int32 i = 0; i < fSize; i++)
53				fElements[i].~Member();
54			fSize = 0;
55		}
56
57		int32 size;
58		if (unflattener->ReadInt32(size) != B_OK)
59			return unflattener->GetStatus();
60
61		status_t error = _EnsureCapacity(size);
62		if (error != B_OK)
63			return error;
64
65		for (int32 i = 0; i < size; i++) {
66			Member* element = new(fElements + i) Member;
67			fSize = i + 1;
68			unflattener->Visit(this, *element);
69		}
70
71		return unflattener->GetStatus();
72	}
73
74	status_t Append(const Member& element)
75	{
76		status_t error = _EnsureCapacity(fSize + 1);
77		if (error != B_OK)
78			return error;
79		new(fElements + fSize) Member(element);
80		fSize++;
81		return B_OK;
82	}
83
84	int32 CountElements() const
85	{
86		return fSize;
87	}
88
89	Member* GetElements() const
90	{
91		return fElements;
92	}
93
94private:
95	status_t _EnsureCapacity(int32 capacity)
96	{
97		const int32 kMinCapacity = 10;
98		if (capacity < kMinCapacity)
99			capacity = kMinCapacity;
100
101		if (capacity > fCapacity) {
102			if (capacity < 2 * fCapacity)
103				capacity = 2 * fCapacity;
104
105			Member* elements
106				= (Member*)realloc(fElements, capacity * sizeof(Member));
107			if (!elements)
108				return B_NO_MEMORY;
109
110			fElements = elements;
111			fCapacity = capacity;
112		}
113
114		return B_OK;
115	}
116
117private:
118	Member*	fElements;
119	int32	fSize;
120	int32	fCapacity;
121};
122
123#endif	// NET_FS_REQUEST_MEMBER_ARRAY_H
124