2 * Copyright 2001-2006, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
3 * Copyright 2013 Haiku, Inc.
4 * All Rights Reserved. Distributed under the terms of the MIT License.
7 * John Scipione, jscipione@gmail.com
8 * Ingo Weinhold, bonefish@cs.tu-berlin.de
12 #include <Resources.h>
18 #include "ResourceFile.h"
19 #include "ResourceItem.h"
20 #include "ResourcesContainer.h"
23 using namespace BPrivate::Storage
;
33 // Creates an unitialized BResources object.
34 BResources::BResources()
41 fContainer
= new(nothrow
) ResourcesContainer
;
45 // Creates a BResources object that represents the resources of the
47 BResources::BResources(const BFile
* file
, bool clobber
)
54 fContainer
= new(nothrow
) ResourcesContainer
;
59 // Creates a BResources object that represents the resources of the
60 // file referenced by the supplied path.
61 BResources::BResources(const char* path
, bool clobber
)
68 fContainer
= new(nothrow
) ResourcesContainer
;
73 // Creates a BResources object that represents the resources of the
74 // file referenced by the supplied ref.
75 BResources::BResources(const entry_ref
* ref
, bool clobber
)
82 fContainer
= new(nothrow
) ResourcesContainer
;
87 // Frees all resources associated with this object
88 BResources::~BResources()
95 // Initialized the BResources object to represent the resources of
98 BResources::SetTo(const BFile
* file
, bool clobber
)
101 status_t error
= B_OK
;
103 error
= file
->InitCheck();
106 error
= fFile
.InitCheck();
109 fReadOnly
= !fFile
.IsWritable();
110 fResourceFile
= new(nothrow
) ResourceFile
;
112 error
= fResourceFile
->SetTo(&fFile
, clobber
);
118 error
= fResourceFile
->InitContainer(*fContainer
);
124 delete fResourceFile
;
125 fResourceFile
= NULL
;
127 fContainer
->MakeEmpty();
133 // Initialized the BResources object to represent the resources of
134 // the file referred to by the supplied path.
136 BResources::SetTo(const char* path
, bool clobber
)
143 status_t error
= file
.SetTo(path
, B_READ_WRITE
);
144 if (error
!= B_OK
&& error
!= B_ENTRY_NOT_FOUND
)
145 error
= file
.SetTo(path
, B_READ_ONLY
);
151 // delegate the actual work
152 return SetTo(&file
, clobber
);
156 // Initialized the BResources object to represent the resources of the
157 // file referenced by the supplied ref.
159 BResources::SetTo(const entry_ref
* ref
, bool clobber
)
166 status_t error
= file
.SetTo(ref
, B_READ_WRITE
);
167 if (error
!= B_OK
&& error
!= B_ENTRY_NOT_FOUND
)
168 error
= file
.SetTo(ref
, B_READ_ONLY
);
174 // delegate the actual work
175 return SetTo(&file
, clobber
);
179 // Initialized the BResources object to represent the resources of
180 // the file from which the specified image has been loaded.
182 BResources::SetToImage(image_id image
, bool clobber
)
184 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
187 status_t error
= get_image_info(image
, &info
);
193 // delegate the actual work
194 return SetTo(info
.name
, clobber
);
195 #else // HAIKU_TARGET_PLATFORM_HAIKU
196 return B_NOT_SUPPORTED
;
201 // Initialized the BResources object to represent the resources of
202 // the file from which the specified pointer has been loaded.
204 BResources::SetToImage(const void* codeOrDataPointer
, bool clobber
)
206 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
207 // iterate through the images and find the one in question
208 addr_t address
= (addr_t
)codeOrDataPointer
;
212 while (get_next_image_info(B_CURRENT_TEAM
, &cookie
, &info
) == B_OK
) {
214 ? info
.type
== B_APP_IMAGE
215 : (((addr_t
)info
.text
<= address
216 && address
- (addr_t
)info
.text
< (addr_t
)info
.text_size
)
217 || ((addr_t
)info
.data
<= address
218 && address
- (addr_t
)info
.data
< (addr_t
)info
.data_size
))) {
219 return SetTo(info
.name
, clobber
);
223 return B_ENTRY_NOT_FOUND
;
224 #else // HAIKU_TARGET_PLATFORM_HAIKU
225 return B_NOT_SUPPORTED
;
230 // Returns the BResources object to an uninitialized state.
234 if (fContainer
&& fContainer
->IsModified())
236 delete fResourceFile
;
237 fResourceFile
= NULL
;
240 fContainer
->MakeEmpty();
242 fContainer
= new(nothrow
) ResourcesContainer
;
247 // Gets the initialization status of the object.
249 BResources::InitCheck() const
251 return (fContainer
? B_OK
: B_NO_MEMORY
);
255 // Gets a reference to the internal BFile object.
257 BResources::File() const
263 // Loads a resource identified by type and id into memory.
265 BResources::LoadResource(type_code type
, int32 id
, size_t* _size
)
268 status_t error
= InitCheck();
269 ResourceItem
* resource
= NULL
;
271 resource
= fContainer
->ResourceAt(fContainer
->IndexOf(type
, id
));
273 error
= B_ENTRY_NOT_FOUND
;
275 // load it, if necessary
276 if (error
== B_OK
&& !resource
->IsLoaded() && fResourceFile
)
277 error
= fResourceFile
->ReadResource(*resource
);
279 const void *result
= NULL
;
281 result
= resource
->Data();
283 *_size
= resource
->DataSize();
289 // Loads a resource identified by type and name into memory.
291 BResources::LoadResource(type_code type
, const char* name
, size_t* _size
)
294 status_t error
= InitCheck();
295 ResourceItem
* resource
= NULL
;
297 resource
= fContainer
->ResourceAt(fContainer
->IndexOf(type
, name
));
299 error
= B_ENTRY_NOT_FOUND
;
301 // load it, if necessary
302 if (error
== B_OK
&& !resource
->IsLoaded() && fResourceFile
)
303 error
= fResourceFile
->ReadResource(*resource
);
305 const void* result
= NULL
;
307 result
= resource
->Data();
309 *_size
= resource
->DataSize();
315 // Loads all resources of the specified type into memory.
317 BResources::PreloadResourceType(type_code type
)
319 status_t error
= InitCheck();
320 if (error
== B_OK
&& fResourceFile
) {
322 error
= fResourceFile
->ReadResources(*fContainer
);
324 int32 count
= fContainer
->CountResources();
325 int32 errorCount
= 0;
326 for (int32 i
= 0; i
< count
; i
++) {
327 ResourceItem
*resource
= fContainer
->ResourceAt(i
);
328 if (resource
->Type() == type
) {
329 if (fResourceFile
->ReadResource(*resource
) != B_OK
)
340 // Writes all changes to the resources to the file.
344 status_t error
= InitCheck();
346 error
= fFile
.InitCheck();
349 error
= B_NOT_ALLOWED
;
350 else if (!fResourceFile
)
351 error
= B_FILE_ERROR
;
354 error
= fResourceFile
->ReadResources(*fContainer
);
356 error
= fResourceFile
->WriteResources(*fContainer
);
361 // Adds the resources of fromFile to the internal file of the
362 // BResources object.
364 BResources::MergeFrom(BFile
* fromFile
)
366 status_t error
= (fromFile
? B_OK
: B_BAD_VALUE
);
370 ResourceFile resourceFile
;
371 error
= resourceFile
.SetTo(fromFile
);
372 ResourcesContainer container
;
374 error
= resourceFile
.InitContainer(container
);
376 error
= resourceFile
.ReadResources(container
);
378 fContainer
->AssimilateResources(container
);
384 // Writes the resources to a new file.
386 BResources::WriteTo(BFile
* file
)
388 status_t error
= (file
? B_OK
: B_BAD_VALUE
);
391 // make sure, that all resources are loaded
392 if (error
== B_OK
&& fResourceFile
) {
393 error
= fResourceFile
->ReadResources(*fContainer
);
394 fResourceFile
->Unset();
396 // set the new file, but keep the old container
398 ResourcesContainer
*container
= fContainer
;
399 fContainer
= new(nothrow
) ResourcesContainer
;
401 error
= SetTo(file
, false);
405 fContainer
= container
;
407 // write the resources
408 if (error
== B_OK
&& fResourceFile
)
409 error
= fResourceFile
->WriteResources(*fContainer
);
414 // Adds a new resource to the file.
416 BResources::AddResource(type_code type
, int32 id
, const void* data
,
417 size_t length
, const char* name
)
419 status_t error
= (data
? B_OK
: B_BAD_VALUE
);
423 error
= (fReadOnly
? B_NOT_ALLOWED
: B_OK
);
425 ResourceItem
* item
= new(nothrow
) ResourceItem
;
429 item
->SetIdentity(type
, id
, name
);
430 ssize_t written
= item
->WriteAt(0, data
, length
);
433 else if (written
!= (ssize_t
)length
)
437 if (!fContainer
->AddResource(item
))
447 // Returns whether the file contains a resource with the specified
450 BResources::HasResource(type_code type
, int32 id
)
452 return (InitCheck() == B_OK
&& fContainer
->IndexOf(type
, id
) >= 0);
456 // Returns whether the file contains a resource with the specified
459 BResources::HasResource(type_code type
, const char* name
)
461 return (InitCheck() == B_OK
&& fContainer
->IndexOf(type
, name
) >= 0);
465 // Gets information about a resource identified by byindex.
467 BResources::GetResourceInfo(int32 byIndex
, type_code
* typeFound
,
468 int32
* idFound
, const char** nameFound
, size_t* lengthFound
)
470 ResourceItem
* item
= NULL
;
471 if (InitCheck() == B_OK
)
472 item
= fContainer
->ResourceAt(byIndex
);
475 *typeFound
= item
->Type();
477 *idFound
= item
->ID();
479 *nameFound
= item
->Name();
481 *lengthFound
= item
->DataSize();
487 // Gets information about a resource identified by byType and andIndex.
489 BResources::GetResourceInfo(type_code byType
, int32 andIndex
, int32
* idFound
,
490 const char** nameFound
, size_t* lengthFound
)
492 ResourceItem
* item
= NULL
;
493 if (InitCheck() == B_OK
) {
494 item
= fContainer
->ResourceAt(fContainer
->IndexOfType(byType
,
499 *idFound
= item
->ID();
501 *nameFound
= item
->Name();
503 *lengthFound
= item
->DataSize();
509 // Gets information about a resource identified by byType and andID.
511 BResources::GetResourceInfo(type_code byType
, int32 andID
,
512 const char** nameFound
, size_t* lengthFound
)
514 ResourceItem
* item
= NULL
;
515 if (InitCheck() == B_OK
)
516 item
= fContainer
->ResourceAt(fContainer
->IndexOf(byType
, andID
));
519 *nameFound
= item
->Name();
521 *lengthFound
= item
->DataSize();
527 // Gets information about a resource identified by byType and andName.
529 BResources::GetResourceInfo(type_code byType
, const char* andName
,
530 int32
* idFound
, size_t* lengthFound
)
532 ResourceItem
* item
= NULL
;
533 if (InitCheck() == B_OK
)
534 item
= fContainer
->ResourceAt(fContainer
->IndexOf(byType
, andName
));
537 *idFound
= item
->ID();
539 *lengthFound
= item
->DataSize();
545 // Gets information about a resource identified by byPointer.
547 BResources::GetResourceInfo(const void* byPointer
, type_code
* typeFound
,
548 int32
* idFound
, size_t* lengthFound
, const char** nameFound
)
550 ResourceItem
* item
= NULL
;
551 if (InitCheck() == B_OK
)
552 item
= fContainer
->ResourceAt(fContainer
->IndexOf(byPointer
));
555 *typeFound
= item
->Type();
557 *idFound
= item
->ID();
559 *nameFound
= item
->Name();
561 *lengthFound
= item
->DataSize();
567 // Removes a resource identified by its data pointer.
569 BResources::RemoveResource(const void* resource
)
571 status_t error
= (resource
? B_OK
: B_BAD_VALUE
);
575 error
= (fReadOnly
? B_NOT_ALLOWED
: B_OK
);
578 = fContainer
->RemoveResource(fContainer
->IndexOf(resource
));
588 // Removes a resource identified by type and id.
590 BResources::RemoveResource(type_code type
, int32 id
)
592 status_t error
= InitCheck();
594 error
= (fReadOnly
? B_NOT_ALLOWED
: B_OK
);
597 = fContainer
->RemoveResource(fContainer
->IndexOf(type
, id
));
607 // #pragma mark - deprecated methods
610 // Writes data into an existing resource
611 // (deprecated, use AddResource() instead).
613 BResources::WriteResource(type_code type
, int32 id
, const void* data
,
614 off_t offset
, size_t length
)
616 status_t error
= (data
&& offset
>= 0 ? B_OK
: B_BAD_VALUE
);
620 error
= (fReadOnly
? B_NOT_ALLOWED
: B_OK
);
625 ResourceItem
*item
= fContainer
->ResourceAt(fContainer
->IndexOf(type
, id
));
630 error
= fResourceFile
->ReadResource(*item
);
635 ssize_t written
= item
->WriteAt(offset
, data
, length
);
639 else if (written
!= (ssize_t
)length
)
646 // Reads data from an existing resource
647 // (deprecated, use LoadResource() instead).
649 BResources::ReadResource(type_code type
, int32 id
, void* data
, off_t offset
,
652 status_t error
= (data
&& offset
>= 0 ? B_OK
: B_BAD_VALUE
);
655 ResourceItem
* item
= NULL
;
657 item
= fContainer
->ResourceAt(fContainer
->IndexOf(type
, id
));
661 if (error
== B_OK
&& fResourceFile
)
662 error
= fResourceFile
->ReadResource(*item
);
665 ssize_t read
= item
->ReadAt(offset
, data
, length
);
675 // Finds a resource by type and id and returns a pointer to a copy of
676 // its data (deprecated, use LoadResource() instead).
678 BResources::FindResource(type_code type
, int32 id
, size_t* lengthFound
)
682 const void* data
= LoadResource(type
, id
, &size
);
684 if ((result
= malloc(size
)))
685 memcpy(result
, data
, size
);
693 // Finds a resource by type and name and returns a pointer to a copy of
694 // its data (deprecated, use LoadResource() instead).
696 BResources::FindResource(type_code type
, const char* name
, size_t* lengthFound
)
700 const void *data
= LoadResource(type
, name
, &size
);
702 if ((result
= malloc(size
)))
703 memcpy(result
, data
, size
);
712 void BResources::_ReservedResources1() {}
713 void BResources::_ReservedResources2() {}
714 void BResources::_ReservedResources3() {}
715 void BResources::_ReservedResources4() {}
716 void BResources::_ReservedResources5() {}
717 void BResources::_ReservedResources6() {}
718 void BResources::_ReservedResources7() {}
719 void BResources::_ReservedResources8() {}