1//----------------------------------------------------------------------
2//  This software is part of the Haiku distribution and is covered
3//  by the MIT License.
4//---------------------------------------------------------------------
5/*!
6	\file ResourcesContainer.cpp
7	ResourcesContainer implementation.
8*/
9
10#include <stdio.h>
11
12#include "ResourcesContainer.h"
13
14#include "ResourceItem.h"
15
16namespace BPrivate {
17namespace Storage {
18
19// constructor
20ResourcesContainer::ResourcesContainer()
21				  : fResources(),
22					fIsModified(false)
23{
24}
25
26// destructor
27ResourcesContainer::~ResourcesContainer()
28{
29	MakeEmpty();
30}
31
32// AddResource
33//
34// Returns false, if item is NULL or memory is insufficient, true otherwise.
35bool
36ResourcesContainer::AddResource(ResourceItem *item, int32 index,
37								bool replace)
38{
39	bool result = false;
40	if (item) {
41		// replace an item with the same type and id
42		if (replace)
43			delete RemoveResource(IndexOf(item->Type(), item->ID()));
44		int32 count = CountResources();
45		if (index < 0 || index > count)
46			index = count;
47		result = fResources.AddItem(item, index);
48		SetModified(true);
49	}
50	return result;
51}
52
53// RemoveResource
54ResourceItem*
55ResourcesContainer::RemoveResource(int32 index)
56{
57	ResourceItem* item = (ResourceItem*)fResources.RemoveItem(index);
58	if (item)
59		SetModified(true);
60	return item;
61}
62
63// RemoveResource
64bool
65ResourcesContainer::RemoveResource(ResourceItem *item)
66{
67	return RemoveResource(IndexOf(item));
68}
69
70// MakeEmpty
71void
72ResourcesContainer::MakeEmpty()
73{
74	for (int32 i = 0; ResourceItem *item = ResourceAt(i); i++)
75		delete item;
76	fResources.MakeEmpty();
77	SetModified(false);
78}
79
80// AssimilateResources
81void
82ResourcesContainer::AssimilateResources(ResourcesContainer &container)
83{
84	// Resistance is futile! ;-)
85	int32 newCount = container.CountResources();
86	for (int32 i = 0; i < newCount; i++) {
87		ResourceItem *item = container.ResourceAt(i);
88		if (item->IsLoaded())
89			AddResource(item);
90		else {
91			// That should not happen.
92			// Delete the item to have a consistent behavior.
93			delete item;
94		}
95	}
96	container.fResources.MakeEmpty();
97	container.SetModified(true);
98	SetModified(true);
99}
100
101// IndexOf
102int32
103ResourcesContainer::IndexOf(ResourceItem *item) const
104{
105	return fResources.IndexOf(item);
106}
107
108// IndexOf
109int32
110ResourcesContainer::IndexOf(const void *data) const
111{
112	int32 index = -1;
113	if (data) {
114		int32 count = CountResources();
115		for (int32 i = 0; index == -1 && i < count; i++) {
116			if (ResourceAt(i)->Data() == data)
117				index = i;
118		}
119	}
120	return index;
121}
122
123// IndexOf
124int32
125ResourcesContainer::IndexOf(type_code type, int32 id) const
126{
127	int32 index = -1;
128	int32 count = CountResources();
129	for (int32 i = 0; index == -1 && i < count; i++) {
130		ResourceItem *item = ResourceAt(i);
131		if (item->Type() == type && item->ID() == id)
132			index = i;
133	}
134	return index;
135}
136
137// IndexOf
138int32
139ResourcesContainer::IndexOf(type_code type, const char *name) const
140{
141	int32 index = -1;
142	int32 count = CountResources();
143	for (int32 i = 0; index == -1 && i < count; i++) {
144		ResourceItem *item = ResourceAt(i);
145		const char *itemName = item->Name();
146		if (item->Type() == type && ((name == NULL && itemName == NULL)
147									 || (name != NULL && itemName != NULL
148										&& strcmp(name, itemName) == 0))) {
149			index = i;
150		}
151	}
152	return index;
153}
154
155// IndexOfType
156int32
157ResourcesContainer::IndexOfType(type_code type, int32 typeIndex) const
158{
159	int32 index = -1;
160	int32 count = CountResources();
161	for (int32 i = 0; index == -1 && i < count; i++) {
162		ResourceItem *item = ResourceAt(i);
163		if (item->Type() == type) {
164			if (typeIndex == 0)
165				index = i;
166			typeIndex--;
167		}
168	}
169	return index;
170}
171
172// ResourceAt
173ResourceItem*
174ResourcesContainer::ResourceAt(int32 index) const
175{
176	return (ResourceItem*)fResources.ItemAt(index);
177}
178
179// CountResources
180int32
181ResourcesContainer::CountResources() const
182{
183	return fResources.CountItems();
184}
185
186// SetModified
187void
188ResourcesContainer::SetModified(bool modified)
189{
190	fIsModified = modified;
191	// If unmodified, set the resource item's modified flag as well.
192	if (!modified) {
193		int32 count = CountResources();
194		for (int32 i = 0; i < count; i++)
195			ResourceAt(i)->SetModified(false);
196	}
197}
198
199// IsModified
200bool
201ResourcesContainer::IsModified() const
202{
203	bool isModified = fIsModified;
204	int32 count = CountResources();
205	for (int32 i = 0; !isModified && i < count; i++)
206		isModified |= ResourceAt(i)->IsModified();
207	return isModified;
208}
209
210
211};	// namespace Storage
212};	// namespace BPrivate
213
214
215
216
217