xref: /haiku/src/kits/storage/Resources.cpp (revision d5cd5d63ff0ad395989db6cf4841a64d5b545d1d)
1 //----------------------------------------------------------------------
2 //  This software is part of the OpenBeOS distribution and is covered
3 //  by the OpenBeOS license.
4 //---------------------------------------------------------------------
5 /*!
6 	\file Resources.cpp
7 	BResources implementation.
8 
9 	BResources delegates most of the work to ResourcesContainer and
10 	ResourceFile. The first one manages a collections of ResourceItem's,
11 	the actual resources, whereas the latter provides the file I/O
12 	functionality.
13 	An InitCheck() method is not needed, since a BResources object will
14 	never be invalid. It always serves as a resources container, even if
15 	it is not associated with a file. It is always possible to WriteTo()
16 	the resources BResources contains to a file (a valid one of course).
17 */
18 #include <Resources.h>
19 
20 #include <new>
21 #include <stdlib.h>
22 
23 #include "ResourceFile.h"
24 #include "ResourceItem.h"
25 #include "ResourcesContainer.h"
26 
27 using namespace BPrivate::Storage;
28 using namespace std;
29 
30 enum {
31 	NOT_IMPLEMENTED	= B_ERROR,
32 };
33 
34 // constructor
35 /*!	\brief Creates an unitialized BResources object.
36 */
37 BResources::BResources()
38 		  : fFile(),
39 			fContainer(NULL),
40 			fResourceFile(NULL),
41 			fReadOnly(false)
42 {
43 	fContainer = new(nothrow) ResourcesContainer;
44 }
45 
46 // constructor
47 /*!	\brief Creates a BResources object that represents the resources of the
48 	supplied file.
49 	If the \a clobber argument is \c true, the data of the file are erased
50 	and it is turned into an empty resource file. Otherwise \a file
51 	must refer either to a resource file or to an executable (ELF or PEF
52 	binary). If the file has been opened \c B_READ_ONLY, only read access
53 	to its resources is possible.
54 	The BResources object makes a copy of \a file, that is the caller remains
55 	owner of the BFile object.
56 	\param file the file
57 	\param clobber if \c true, the \a file is truncated to size 0
58 */
59 BResources::BResources(const BFile *file, bool clobber)
60 		  : fFile(),
61 			fContainer(NULL),
62 			fResourceFile(NULL),
63 			fReadOnly(false)
64 {
65 	fContainer = new(nothrow) ResourcesContainer;
66 	SetTo(file, clobber);
67 }
68 
69 // destructor
70 /*!	\brief Frees all resources associated with this object
71 	Calls Sync() before doing so to make sure that the changes are written
72 	back to the file.
73 */
74 BResources::~BResources()
75 {
76 	Unset();
77 	delete fContainer;
78 }
79 
80 // SetTo
81 /*!	\brief Re-initialized the BResources object to represent the resources of
82 	the supplied file.
83 	What happens, if \a clobber is \c true, depends on the type of the file.
84 	If the file is capable of containing resources, that is, is a resource
85 	file or an executable (ELF or PEF), its resources are removed. Otherwise
86 	the file's data are erased and it is turned into an empty resource file.
87 	If \a clobber is \c false, \a file must refer to a file that is capable
88 	of containing resources.
89 	If the file has been opened \c B_READ_ONLY, only read access
90 	to its resources is possible.
91 	The BResources object makes a copy of \a file, that is the caller remains
92 	owner of the BFile object.
93 	\param file the file
94 	\param clobber if \c true, the \a file is truncated to size 0
95 	\return
96 	- \c B_OK: Everything went fine.
97 	- \c B_BAD_VALUE: \c NULL or uninitialized \a file.
98 	- \c B_ERROR: Failed to initialize the object (for whatever reason).
99 */
100 status_t
101 BResources::SetTo(const BFile *file, bool clobber)
102 {
103 	Unset();
104 	status_t error = B_OK;
105 	if (file) {
106 		error = file->InitCheck();
107 		if (error == B_OK) {
108 			fFile = *file;
109 			error = fFile.InitCheck();
110 		}
111 		if (error == B_OK) {
112 			fReadOnly = !fFile.IsWritable();
113 			fResourceFile = new(nothrow) ResourceFile;
114 			if (fResourceFile)
115 				error = fResourceFile->SetTo(&fFile, clobber);
116 			else
117 				error = B_NO_MEMORY;
118 		}
119 		if (error == B_OK) {
120 			if (fContainer)
121 				error = fResourceFile->InitContainer(*fContainer);
122 			else
123 				error = B_NO_MEMORY;
124 		}
125 	}
126 	if (error != B_OK) {
127 		delete fResourceFile;
128 		fResourceFile = NULL;
129 		if (fContainer)
130 			fContainer->MakeEmpty();
131 	}
132 	return error;
133 }
134 
135 // Unset
136 /*!	\brief Returns the BResources object to an uninitialized state.
137 	If the object represented resources that had been modified, the data are
138 	written back to the file.
139 	\note This method extends the BeOS R5 API.
140 */
141 void
142 BResources::Unset()
143 {
144 	if (fContainer && fContainer->IsModified())
145 		Sync();
146 	delete fResourceFile;
147 	fResourceFile = NULL;
148 	fFile.Unset();
149 	if (fContainer)
150 		fContainer->MakeEmpty();
151 	else
152 		fContainer = new(nothrow) ResourcesContainer;
153 	fReadOnly = false;
154 }
155 
156 // InitCheck
157 /*!	Returns the current initialization status.
158 	Unlike other Storage Kit classes a BResources object is always properly
159 	initialized, unless it couldn't allocate memory for some important
160 	internal structures. Thus even after a call to SetTo() that reported an
161 	error, InitCheck() is likely to return \c B_OK.
162 	\return
163 	- \c B_OK, if the objects is properly initialized,
164 	- \c B_NO_MEMORY otherwise.
165 	\note This method extends the BeOS R5 API.
166 */
167 status_t
168 BResources::InitCheck() const
169 {
170 	return (fContainer ? B_OK : B_NO_MEMORY);
171 }
172 
173 // File
174 /*!	\brief Returns a reference to the BResources' BFile object.
175 	\return a reference to the object's BFile.
176 */
177 const BFile &
178 BResources::File() const
179 {
180 	return fFile;
181 }
182 
183 // LoadResource
184 /*!	\brief Loads a resource identified by type and ID into memory.
185 	A resource is loaded into memory only once. A second call with the same
186 	parameters will result in the same pointer. The BResources object is the
187 	owner of the allocated memory and the pointer to it will be valid until
188 	the object is destroyed or the resource is removed or modified.
189 	\param type the type of the resource to be loaded
190 	\param id the ID of the resource to be loaded
191 	\param outSize a pointer to a variable into which the size of the resource
192 		   shall be written
193 	\return A pointer to the resource data, if everything went fine, or
194 			\c NULL, if the file does not have a resource that matchs the
195 			parameters or an error occured.
196 */
197 const void *
198 BResources::LoadResource(type_code type, int32 id, size_t *outSize)
199 {
200 	// find the resource
201 	status_t error = InitCheck();
202 	ResourceItem *resource = NULL;
203 	if (error == B_OK) {
204 		resource = fContainer->ResourceAt(fContainer->IndexOf(type, id));
205 		if (!resource)
206 			error = B_ENTRY_NOT_FOUND;
207 	}
208 	// load it, if necessary
209 	if (error == B_OK && !resource->IsLoaded() && fResourceFile)
210 		error = fResourceFile->ReadResource(*resource);
211 	// return the result
212 	const void *result = NULL;
213 	if (error == B_OK) {
214 		result = resource->Data();
215 		if (outSize)
216 			*outSize = resource->DataSize();
217 	}
218 	return result;
219 }
220 
221 // LoadResource
222 /*!	\brief Loads a resource identified by type and name into memory.
223 	A resource is loaded into memory only once. A second call with the same
224 	parameters will result in the same pointer. The BResources object is the
225 	owner of the allocated memory and the pointer to it will be valid until
226 	the object is destroyed or the resource is removed or modified.
227 	\param type the type of the resource to be loaded
228 	\param name the name of the resource to be loaded
229 	\param outSize a pointer to a variable into which the size of the resource
230 		   shall be written
231 	\return A pointer to the resource data, if everything went fine, or
232 			\c NULL, if the file does not have a resource that matches the
233 			parameters or an error occured.
234 	\note Since a type and name pair may not identify a resource uniquely,
235 		  this method always returns the first resource that matches the
236 		  parameters, that is the one with the least index.
237 */
238 const void *
239 BResources::LoadResource(type_code type, const char *name, size_t *outSize)
240 {
241 	// find the resource
242 	status_t error = InitCheck();
243 	ResourceItem *resource = NULL;
244 	if (error == B_OK) {
245 		resource = fContainer->ResourceAt(fContainer->IndexOf(type, name));
246 		if (!resource)
247 			error = B_ENTRY_NOT_FOUND;
248 	}
249 	// load it, if necessary
250 	if (error == B_OK && !resource->IsLoaded() && fResourceFile)
251 		error = fResourceFile->ReadResource(*resource);
252 	// return the result
253 	const void *result = NULL;
254 	if (error == B_OK) {
255 		result = resource->Data();
256 		if (outSize)
257 			*outSize = resource->DataSize();
258 	}
259 	return result;
260 }
261 
262 // PreloadResourceType
263 /*!	\brief Loads all resources of a certain type into memory.
264 	For performance reasons it might be useful to do that. If \a type is
265 	0, all resources are loaded.
266 	\param type of the resources to be loaded
267 	\return
268 	- \c B_OK: Everything went fine.
269 	- \c B_BAD_FILE: The resource map is empty???
270 	- The negative of the number of errors occured.
271 */
272 status_t
273 BResources::PreloadResourceType(type_code type)
274 {
275 	status_t error = InitCheck();
276 	if (error == B_OK && fResourceFile) {
277 		if (type == 0)
278 			error = fResourceFile->ReadResources(*fContainer);
279 		else {
280 			int32 count = fContainer->CountResources();
281 			int32 errorCount = 0;
282 			for (int32 i = 0; i < count; i++) {
283 				ResourceItem *resource = fContainer->ResourceAt(i);
284 				if (resource->Type() == type) {
285 					if (fResourceFile->ReadResource(*resource) != B_OK)
286 						errorCount++;
287 				}
288 			}
289 			error = -errorCount;
290 		}
291 	}
292 	return error;
293 }
294 
295 // Sync
296 /*!	\brief Writes all changes to the resources to the file.
297 	Since AddResource() and RemoveResource() may change the resources only in
298 	memory, this method can be used to make sure, that all changes are
299 	actually written to the file.
300 	The BResources object's destructor calls Sync() before cleaning up.
301 	\return
302 	- \c B_OK: Everything went fine.
303 	- \c B_BAD_FILE: The resource map is empty???
304 	- \c B_NOT_ALLOWED: The file is opened read only.
305 	- \c B_FILE_ERROR: A file error occured.
306 	- \c B_IO_ERROR: An error occured while writing the resources.
307 	\note When a resource is written to the file, its data are converted
308 		  to the endianess of the file, and when reading a resource, the
309 		  data are converted to the host's endianess. This does of course
310 		  only work for known types, i.e. those that swap_data() is able to
311 		  cope with.
312 */
313 status_t
314 BResources::Sync()
315 {
316 	status_t error = InitCheck();
317 	if (error == B_OK)
318 		error = fFile.InitCheck();
319 	if (error == B_OK) {
320 		if (fReadOnly)
321 			error = B_NOT_ALLOWED;
322 		else if (!fResourceFile)
323 			error = B_FILE_ERROR;
324 	}
325 	if (error == B_OK)
326 		error = fResourceFile->ReadResources(*fContainer);
327 	if (error == B_OK)
328 		error = fResourceFile->WriteResources(*fContainer);
329 	return error;
330 }
331 
332 // MergeFrom
333 /*!	\brief Adds the resources of the supplied file to this file's resources.
334 	\param fromFile the file whose resources shall be copied
335 	\return
336 	- \c B_OK: Everything went fine.
337 	- \c B_BAD_VALUE: \c NULL \a fromFile.
338 	- \c B_BAD_FILE: The resource map is empty???
339 	- \c B_FILE_ERROR: A file error occured.
340 	- \c B_IO_ERROR: An error occured while writing the resources.
341 */
342 status_t
343 BResources::MergeFrom(BFile *fromFile)
344 {
345 	status_t error = (fromFile ? B_OK : B_BAD_VALUE);
346 	if (error == B_OK)
347 		error = InitCheck();
348 	if (error == B_OK) {
349 		ResourceFile resourceFile;
350 		error = resourceFile.SetTo(fromFile);
351 		ResourcesContainer container;
352 		if (error == B_OK)
353 			error = resourceFile.InitContainer(container);
354 		if (error == B_OK)
355 			error = resourceFile.ReadResources(container);
356 		if (error == B_OK)
357 			fContainer->AssimilateResources(container);
358 	}
359 	return error;
360 }
361 
362 // WriteTo
363 /*!	\brief Writes the resources to a new file.
364 	The resources formerly contained in the target file (if any) are erased.
365 	When the method returns, the BResources object refers to the new file.
366 	\param file the file the resources shall be written to.
367 	\return
368 	- \c B_OK: Everything went fine.
369 	- a specific error code.
370 	\note If the resources have been modified, but not Sync()ed, the old file
371 		  remains unmodified.
372 */
373 status_t
374 BResources::WriteTo(BFile *file)
375 {
376 	status_t error = (file ? B_OK : B_BAD_VALUE);
377 	if (error == B_OK)
378 		error = InitCheck();
379 	// make sure, that all resources are loaded
380 	if (error == B_OK && fResourceFile) {
381 		error = fResourceFile->ReadResources(*fContainer);
382 		fResourceFile->Unset();
383 	}
384 	// set the new file, but keep the old container
385 	if (error == B_OK) {
386 		ResourcesContainer *container = fContainer;
387 		fContainer = new(nothrow) ResourcesContainer;
388 		if (fContainer) {
389 			error = SetTo(file, false);
390 			delete fContainer;
391 		} else
392 			error = B_NO_MEMORY;
393 		fContainer = container;
394 	}
395 	// write the resources
396 	if (error == B_OK && fResourceFile)
397 		error = fResourceFile->WriteResources(*fContainer);
398 	return error;
399 }
400 
401 // AddResource
402 /*!	\brief Adds a new resource to the file.
403 	If a resource with the same type and ID does already exist, it is
404 	replaced. The caller keeps the ownership of the supplied chunk of memory
405 	containing the resource data.
406 	Supplying an empty name (\c "") is equivalent to supplying a \c NULL name.
407 	\param type the type of the resource
408 	\param id the ID of the resource
409 	\param data the resource data
410 	\param length the size of the data in bytes
411 	\param name the name of the resource (may be \c NULL)
412 	\return
413 	- \c B_OK: Everything went fine.
414 	- \c B_BAD_VALUE: \c NULL \a data
415 	- \c B_NOT_ALLOWED: The file is opened read only.
416 	- \c B_FILE_ERROR: A file error occured.
417 	- \c B_NO_MEMORY: Not enough memory for that operation.
418 */
419 status_t
420 BResources::AddResource(type_code type, int32 id, const void *data,
421 						size_t length, const char *name)
422 {
423 	status_t error = (data ? B_OK : B_BAD_VALUE);
424 	if (error == B_OK)
425 		error = InitCheck();
426 	if (error == B_OK)
427 		error = (fReadOnly ? B_NOT_ALLOWED : B_OK);
428 	if (error == B_OK) {
429 		ResourceItem *item = new(nothrow) ResourceItem;
430 		if (!item)
431 			error = B_NO_MEMORY;
432 		if (error == B_OK) {
433 			item->SetIdentity(type, id, name);
434 			ssize_t written = item->WriteAt(0, data, length);
435 			if (written < 0)
436 				error = written;
437 			else if (written != (ssize_t)length)
438 				error = B_ERROR;
439 		}
440 		if (error == B_OK) {
441 			if (!fContainer->AddResource(item))
442 				error = B_NO_MEMORY;
443 		}
444 		if (error != B_OK)
445 			delete item;
446 	}
447 	return error;
448 }
449 
450 // HasResource
451 /*!	\brief Returns whether the file contains a resource with a certain
452 	type and ID.
453 	\param type the resource type
454 	\param id the ID of the resource
455 	\return \c true, if the file contains a matching resource, \false otherwise
456 */
457 bool
458 BResources::HasResource(type_code type, int32 id)
459 {
460 	return (InitCheck() == B_OK && fContainer->IndexOf(type, id) >= 0);
461 }
462 
463 // HasResource
464 /*!	\brief Returns whether the file contains a resource with a certain
465 	type and name.
466 	\param type the resource type
467 	\param name the name of the resource
468 	\return \c true, if the file contains a matching resource, \false otherwise
469 */
470 bool
471 BResources::HasResource(type_code type, const char *name)
472 {
473 	return (InitCheck() == B_OK && fContainer->IndexOf(type, name) >= 0);
474 }
475 
476 // GetResourceInfo
477 /*!	\brief Returns information about a resource identified by an index.
478 	\param byIndex the index of the resource in the file
479 	\param typeFound a pointer to a variable the type of the found resource
480 		   shall be written into
481 	\param idFound a pointer to a variable the ID of the found resource
482 		   shall be written into
483 	\param nameFound a pointer to a variable the name pointer of the found
484 		   resource shall be written into
485 	\param lengthFound a pointer to a variable the data size of the found
486 		   resource shall be written into
487 	\return \c true, if a matching resource could be found, false otherwise
488 */
489 bool
490 BResources::GetResourceInfo(int32 byIndex, type_code *typeFound,
491 							int32 *idFound, const char **nameFound,
492 							size_t *lengthFound)
493 {
494 	ResourceItem *item = NULL;
495 	if (InitCheck() == B_OK)
496 		item = fContainer->ResourceAt(byIndex);
497 	if (item) {
498 		if (typeFound)
499 			*typeFound = item->Type();
500 		if (idFound)
501 			*idFound = item->ID();
502 		if (nameFound)
503 			*nameFound = item->Name();
504 		if (lengthFound)
505 			*lengthFound = item->DataSize();
506 	}
507 	return item;
508 }
509 
510 // GetResourceInfo
511 /*!	\brief Returns information about a resource identified by a type and an
512 	index.
513 	\param byType the resource type
514 	\param andIndex the index into a array of resources of type \a byType
515 	\param idFound a pointer to a variable the ID of the found resource
516 		   shall be written into
517 	\param nameFound a pointer to a variable the name pointer of the found
518 		   resource shall be written into
519 	\param lengthFound a pointer to a variable the data size of the found
520 		   resource shall be written into
521 	\return \c true, if a matching resource could be found, false otherwise
522 */
523 bool
524 BResources::GetResourceInfo(type_code byType, int32 andIndex, int32 *idFound,
525 							const char **nameFound, size_t *lengthFound)
526 {
527 	ResourceItem *item = NULL;
528 	if (InitCheck() == B_OK) {
529 		item = fContainer->ResourceAt(fContainer->IndexOfType(byType,
530 															  andIndex));
531 	}
532 	if (item) {
533 		if (idFound)
534 			*idFound = item->ID();
535 		if (nameFound)
536 			*nameFound = item->Name();
537 		if (lengthFound)
538 			*lengthFound = item->DataSize();
539 	}
540 	return item;
541 }
542 
543 // GetResourceInfo
544 /*!	\brief Returns information about a resource identified by a type and an ID.
545 	\param byType the resource type
546 	\param andID the resource ID
547 	\param nameFound a pointer to a variable the name pointer of the found
548 		   resource shall be written into
549 	\param lengthFound a pointer to a variable the data size of the found
550 		   resource shall be written into
551 	\return \c true, if a matching resource could be found, false otherwise
552 */
553 bool
554 BResources::GetResourceInfo(type_code byType, int32 andID,
555 							const char **nameFound, size_t *lengthFound)
556 {
557 	ResourceItem *item = NULL;
558 	if (InitCheck() == B_OK)
559 		item = fContainer->ResourceAt(fContainer->IndexOf(byType, andID));
560 	if (item) {
561 		if (nameFound)
562 			*nameFound = item->Name();
563 		if (lengthFound)
564 			*lengthFound = item->DataSize();
565 	}
566 	return item;
567 }
568 
569 // GetResourceInfo
570 /*!	\brief Returns information about a resource identified by a type and a
571 	name.
572 	\param byType the resource type
573 	\param andName the resource name
574 	\param idFound a pointer to a variable the ID of the found resource
575 		   shall be written into
576 	\param lengthFound a pointer to a variable the data size of the found
577 		   resource shall be written into
578 	\return \c true, if a matching resource could be found, false otherwise
579 */
580 bool
581 BResources::GetResourceInfo(type_code byType, const char *andName,
582 							int32 *idFound, size_t *lengthFound)
583 {
584 	ResourceItem *item = NULL;
585 	if (InitCheck() == B_OK)
586 		item = fContainer->ResourceAt(fContainer->IndexOf(byType, andName));
587 	if (item) {
588 		if (idFound)
589 			*idFound = item->ID();
590 		if (lengthFound)
591 			*lengthFound = item->DataSize();
592 	}
593 	return item;
594 }
595 
596 // GetResourceInfo
597 /*!	\brief Returns information about a resource identified by a data pointer.
598 	\param byPointer the pointer to the resource data (formely returned by
599 		   LoadResource())
600 	\param typeFound a pointer to a variable the type of the found resource
601 		   shall be written into
602 	\param idFound a pointer to a variable the ID of the found resource
603 		   shall be written into
604 	\param lengthFound a pointer to a variable the data size of the found
605 		   resource shall be written into
606 	\param nameFound a pointer to a variable the name pointer of the found
607 		   resource shall be written into
608 	\return \c true, if a matching resource could be found, false otherwise
609 */
610 bool
611 BResources::GetResourceInfo(const void *byPointer, type_code *typeFound,
612 							int32 *idFound, size_t *lengthFound,
613 							const char **nameFound)
614 {
615 	ResourceItem *item = NULL;
616 	if (InitCheck() == B_OK)
617 		item = fContainer->ResourceAt(fContainer->IndexOf(byPointer));
618 	if (item) {
619 		if (typeFound)
620 			*typeFound = item->Type();
621 		if (idFound)
622 			*idFound = item->ID();
623 		if (nameFound)
624 			*nameFound = item->Name();
625 		if (lengthFound)
626 			*lengthFound = item->DataSize();
627 	}
628 	return item;
629 }
630 
631 // RemoveResource
632 /*!	\brief Removes a resource identified by its data pointer.
633 	\param resource the pointer to the resource data (formely returned by
634 		   LoadResource())
635 	\return
636 	- \c B_OK: Everything went fine.
637 	- \c B_BAD_VALUE: \c NULL or invalid (not pointing to any resource data of
638 	  this file) \a resource.
639 	- \c B_NOT_ALLOWED: The file is opened read only.
640 	- \c B_FILE_ERROR: A file error occured.
641 	- \c B_ERROR: An error occured while removing the resource.
642 */
643 status_t
644 BResources::RemoveResource(const void *resource)
645 {
646 	status_t error = (resource ? B_OK : B_BAD_VALUE);
647 	if (error == B_OK)
648 		error = InitCheck();
649 	if (error == B_OK)
650 		error = (fReadOnly ? B_NOT_ALLOWED : B_OK);
651 	if (error == B_OK) {
652 		ResourceItem *item
653 			= fContainer->RemoveResource(fContainer->IndexOf(resource));
654 		if (item)
655 			delete item;
656 		else
657 			error = B_BAD_VALUE;
658 	}
659 	return error;
660 }
661 
662 // RemoveResource
663 /*!	\brief Removes a resource identified by type and ID.
664 	\param type the type of the resource
665 	\param id the ID of the resource
666 	\return
667 	- \c B_OK: Everything went fine.
668 	- \c B_BAD_VALUE: No such resource.
669 	- \c B_NOT_ALLOWED: The file is opened read only.
670 	- \c B_FILE_ERROR: A file error occured.
671 	- \c B_ERROR: An error occured while removing the resource.
672 */
673 status_t
674 BResources::RemoveResource(type_code type, int32 id)
675 {
676 	status_t error = InitCheck();
677 	if (error == B_OK)
678 		error = (fReadOnly ? B_NOT_ALLOWED : B_OK);
679 	if (error == B_OK) {
680 		ResourceItem *item
681 			= fContainer->RemoveResource(fContainer->IndexOf(type, id));
682 		if (item)
683 			delete item;
684 		else
685 			error = B_BAD_VALUE;
686 	}
687 	return error;
688 }
689 
690 
691 // deprecated
692 
693 // WriteResource
694 /*!	\brief Writes data into an existing resource.
695 	If writing the data would exceed the bounds of the resource, it is
696 	enlarged respectively. If \a offset is past the end of the resource,
697 	padding with unspecified data is inserted.
698 	\param type the type of the resource
699 	\param id the ID of the resource
700 	\param data the data to be written
701 	\param offset the byte offset relative to the beginning of the resource at
702 		   which the data shall be written
703 	\param length the size of the data to be written
704 	\return
705 	- \c B_OK: Everything went fine.
706 	- \c B_BAD_VALUE: \a type and \a id do not identify an existing resource or
707 	  \c NULL \a data.
708 	- \c B_NO_MEMORY: Not enough memory for this operation.
709 	- other error codes.
710 	\deprecated Always use AddResource().
711 */
712 status_t
713 BResources::WriteResource(type_code type, int32 id, const void *data,
714 						  off_t offset, size_t length)
715 {
716 	status_t error = (data && offset >= 0 ? B_OK : B_BAD_VALUE);
717 	if (error == B_OK)
718 		error = InitCheck();
719 	if (error == B_OK)
720 		error = (fReadOnly ? B_NOT_ALLOWED : B_OK);
721 	ResourceItem *item = NULL;
722 	if (error == B_OK) {
723 		item = fContainer->ResourceAt(fContainer->IndexOf(type, id));
724 		if (!item)
725 			error = B_BAD_VALUE;
726 	}
727 	if (error == B_OK && fResourceFile)
728 		error = fResourceFile->ReadResource(*item);
729 	if (error == B_OK) {
730 		if (item) {
731 			ssize_t written = item->WriteAt(offset, data, length);
732 			if (written < 0)
733 				error = written;
734 			else if (written != (ssize_t)length)
735 				error = B_ERROR;
736 		}
737 	}
738 	return error;
739 }
740 
741 // ReadResource
742 /*!	\brief Reads data from an existing resource.
743 	If more data than existing are requested, this method does not fail. It
744 	will then read only the existing data. As a consequence an offset past
745 	the end of the resource will not cause the method to fail, but no data
746 	will be read at all.
747 	\param type the type of the resource
748 	\param id the ID of the resource
749 	\param data a pointer to a buffer into which the data shall be read
750 	\param offset the byte offset relative to the beginning of the resource
751 		   from which the data shall be read
752 	\param length the size of the data to be read
753 	\return
754 	- \c B_OK: Everything went fine.
755 	- \c B_BAD_VALUE: \a type and \a id do not identify an existing resource or
756 	  \c NULL \a data.
757 	- \c B_NO_MEMORY: Not enough memory for this operation.
758 	- other error codes.
759 	\deprecated Use LoadResource() only.
760 */
761 status_t
762 BResources::ReadResource(type_code type, int32 id, void *data, off_t offset,
763 						 size_t length)
764 {
765 	status_t error = (data && offset >= 0 ? B_OK : B_BAD_VALUE);
766 	if (error == B_OK)
767 		error = InitCheck();
768 	ResourceItem *item = NULL;
769 	if (error == B_OK) {
770 		item = fContainer->ResourceAt(fContainer->IndexOf(type, id));
771 		if (!item)
772 			error = B_BAD_VALUE;
773 	}
774 	if (error == B_OK && fResourceFile)
775 		error = fResourceFile->ReadResource(*item);
776 	if (error == B_OK) {
777 		if (item) {
778 			ssize_t read = item->ReadAt(offset, data, length);
779 			if (read < 0)
780 				error = read;
781 		} else
782 			error = B_BAD_VALUE;
783 	}
784 	return error;
785 }
786 
787 // FindResource
788 /*!	\brief Finds a resource by type and ID and returns a copy of its data.
789 	The caller is responsible for free()ing the returned memory.
790 	\param type the type of the resource
791 	\param id the ID of the resource
792 	\param lengthFound a pointer to a variable into which the size of the
793 		   resource data shall be written
794 	\return
795 	- a pointer to the resource data, if everything went fine,
796 	- \c NULL, if an error occured.
797 	\deprecated Use LoadResource().
798 */
799 void *
800 BResources::FindResource(type_code type, int32 id, size_t *lengthFound)
801 {
802 	void *result = NULL;
803 	size_t size = 0;
804 	if (const void *data = LoadResource(type, id, &size)) {
805 		if ((result = malloc(size)))
806 			memcpy(result, data, size);
807 	}
808 	if (lengthFound)
809 		*lengthFound = size;
810 	return result;
811 }
812 
813 // FindResource
814 /*!	\brief Finds a resource by type and name and returns a copy of its data.
815 	The caller is responsible for free()ing the returned memory.
816 	\param type the type of the resource
817 	\param name the name of the resource
818 	\param lengthFound a pointer to a variable into which the size of the
819 		   resource data shall be written
820 	\return
821 	- a pointer to the resource data, if everything went fine,
822 	- \c NULL, if an error occured.
823 	\deprecated Use LoadResource().
824 */
825 void *
826 BResources::FindResource(type_code type, const char *name, size_t *lengthFound)
827 {
828 	void *result = NULL;
829 	size_t size = 0;
830 	if (const void *data = LoadResource(type, name, &size)) {
831 		if ((result = malloc(size)))
832 			memcpy(result, data, size);
833 	}
834 	if (lengthFound)
835 		*lengthFound = size;
836 	return result;
837 }
838 
839 
840 // FBC
841 void BResources::_ReservedResources1() {}
842 void BResources::_ReservedResources2() {}
843 void BResources::_ReservedResources3() {}
844 void BResources::_ReservedResources4() {}
845 void BResources::_ReservedResources5() {}
846 void BResources::_ReservedResources6() {}
847 void BResources::_ReservedResources7() {}
848 void BResources::_ReservedResources8() {}
849 
850 
851 
852 
853