Derived from: public BFile
Declared in: <storage/ResourceFile.h>
The BResourceFile class defines structured files that contain a collection of data entries, or resources. A single resource file can hold an unlimited number of resources; a single resource within a resource file can contain an unlimited amount of data.
A resource file (as it lies on the disk) is tagged with an identifying header that distinguishes it (the file) from "plain" files. The distinction between a resource file and a plain file is important: Although you can (inadvertently, one assumes) refer a BResourceFile object to a plain file, you won't be able to use the object to open the file. Simply referring a BResourceFile object to an existing plain file will not transform the file into a resource file.
To create a new resource file--to create a file that's given a resource header --you pass a pointer to an allocated BResourceFile object to BDirectory's Create() function:
BResourceFile rFile; aDirectory->Create("NewFile", &rFile);
You can also create a new resource file by copying an existing resource file through BFile's CopyTo() function.
The only files that are automatically created (by the system) as resource files are executables: All applications and programs have the capacity to store resources.
After you've created (or otherwise obtained) a resource file, you open the BResourceFile object that refers to it through the Open() function (inherited from BFile), and then use the Manipulate Resource() functions (AddResource() , RemoveResource(), and so on) defined by the BResourceFile class to examine and manipulate the file's contents. Each of the resource-affecting functions performs its magic on one resource at a time.
BResourceFile doesn't disqualify BFile's Read() and Write() functions--but you shouldn't use them. These functions will read and write the resource file as flat data, as if it were a plain file. It's your file, but this probably isn't what you want. (To be a bit less prohibitive, reading a resource file is safe and might be slightly informative).
When you've had enough of manipulating resources (and not Write() -ing them), you should close the resource file, through the inherited Close() function.
A single resource within a resource file is tagged with a data type, an ID, and a name:
Taken singly, none of these tags needs to be unique: Any number of resources (within the same file) can have the same data type, ID, or name. It's the combination of the data type constant and the ID that uniquely identifies a resource within a file. The name, on the other hand, is more of a convenience; it never needs to be unique when combined with the data type or with the ID.
All resource data is assumed to be "raw": If you want to store a NULL-terminated string in a resource, for example, you have to write the NULL as part of the string data, or the application that reads the resource from the resource must apply the NULL itself. Put more generally, the data in a resource doesn't assume any particular structure or format, it's simply a vector of bytes.
The resource-manipulating functions cause data to be read from or written to the resource file directly and immediately. In other words, the BResourceFile object doesn't create its own "resource cache" that acts as an intermediary between your application and the resource file. This has a couple of implications:
BResourceFile(void) BResourceFile(record_ref ref)
The BResourceFile constructor creates a new object and returns a pointer to it. You can set the object's ref by passing it as an argument here; without the argument, the object won't refer to a file--it will be essentially useless--until the ref is set. The methods by which you set (or re-set) an unreferenced BResourceFile's ref are the same as for a BFile:
You can refer a BResourceFile object to any file; that is, you're allowed to do so. However, only those BResourceFile objects that refer to actual resource files are allowed to be opened--the Open() function will fail if the BResourceFile refers to a plain file.
Simply pointing the ref to a random file will not convert the file so that it can hold resources. Resource files can only be created by passing a BResourceFile object to BDirectory's Create() function, or by copying an existing resource file through CopyTo().
virtual ~BResourceFile(void)
Destroys the BResourceFile object; this doesn't remove the file that the object corresponds to (to remove a file, use BDirectory's Remove() function). The object is automatically closed (through a call to Close()) before the object is destroyed.
long AddResource(ulong type, long id, void *data, long dataLength, const char *name = NULL)
Adds a new resource to the file. For this function to have an effect, the file must be open for writing. The arguments are:
Ownership of the data pointer isn't assigned to the BResourceFile object by this function; after AddResrouce() returns, your application can free or otherwise manipulate the buffer that data points to without affecting the data that was written to the file.
If the combination of type and id is already being used by a resource in this BResourceFile, or if, for any other reason, the resource data couldn't be written to the file, the function returns B_ERROR. Otherwise, it returns B_NO_ERROR .
Warning: Currently, AddResource() will write over an existing resource. In this case, the function returns a positive integer (specifically, it returns the number of bytes that it just wrote), but it doesn't change the name of the resource. For now, you should call RemoveResource() just before calling AddResource(), passing the same type and id arguments to both functions.
See also: WriteResource()
virtual long FileCreated(void)
FileCreated() is a hook function, defined by BFile, that's called when a new file is created. BResourceFile implements FileCreated() to put a magic number at the top of the resource file. If you derive a class from BResourceFile and implement your own version of FileCreated(), you should call BResourceFile's version of the function before performing your own initializations.
void *FindResource(ulong type, long id, void *dataLength) void *FindResource(ulong type, const char *name, void *lengthFound)
Finds the resource identified by the first two arguments, and returns a pointer to a copy of the resource's data. The size of the data, in bytes, is returned by reference in *lengthFound.
It's the caller's responsibility to free the pointed-to data.
If the first two arguments don't identify an existing resource, NULL is returned.
See also: ReadResource()
bool GetResourceInfo(long byIndex, ulong *typeFound, long *idFound, char **nameFound, long *lengthFound) bool GetResourceInfo(ulong byType, long andIndex, long *idFound, char **nameFound, long *lengthFound) bool GetResourceInfo(ulong byType, long andId, char **nameFound, long *lengthFound) bool GetResourceInfo(ulong byType, char *andName, long *idFound, long *lengthFound)
These functions return information about a specific resource, as identified by the first one or two arguments:
The other arguments return the other statistics about the resource (if found). The pointer that's returned in *foundName belongs to the BResourceFile. Don't free it.
The functions return TRUE if a resource was found, and FALSE otherwise.
bool HasResource(ulong type, long id) bool HasResource(const char *name, ulong type)
Returns TRUE if the resource file contains a resource as identified by the arguments, otherwise it returns NOPE.
Keep in mind that there may be more than one resource in the file with the same name and type combination. The type and id combo, on the other hand, is unique.
long ReadResource(ulong type, long id, void *data, long offset, long dataLength)
Reads data from an existing resource (identified by type and id) and places it in the data buffer. offset gives the location (measured in bytes from the start of the resource data) from which the read commences, and dataLength is the number of bytes you want to read. The data buffer must already be allocated and should be at least dataLength bytes long.
You can ask for more data than the resource contains; in this case, the buffer is filled with as much resource data as exists (or from offset to the end of the resource). However, note well that the function doesn't tell you how much data it actually read.
The function returns B_ERROR if the buffer is only partially filled, or if the resource wasn't found. Otherwise, it returns B_NO_ERROR.
See also: FindResource(), WriteResource()
long RemoveResource(ulong type, long id)
Removes the resource identified by the arguments. The function returns B_NO_ERROR if the resource was successfully removed, and B_ERROR otherwise.
long WriteResource(ulong type, long id, void *data, long offset, long dataLength)
Writes data into an existing resource, possibly overwriting the data that the resource currently contains. The type and id arguments identify the target resource; this resource must already be present in the file--WriteResource() doesn't create a new resource if the type/id combination fails to identify with a winner.
data is a pointer to the new data that you want to place in the resource; dataLength is the length of the data buffer. offset gives the location at which you want the new data to be written; the offset is taken as the number of bytes from the beginning of the existing resource data. If the new data is placed such that it exceeds the size of the current resource data, the resource grows to accommodate the new data.
You can't use this function to "shrink" a resource. To remove a portion of data from a resource, you have to remove the resource and then re-add it.
If type and id don't identify an existing resource, of if the data couldn't be written, for whatever reason, this function return B_ERROR. Otherwise, it returns B_NO_ERROR.
See also: AddResource()
The Be Book, HTML Edition, for Developer Release 8 of the Be Operating System.
Copyright © 1996 Be, Inc. All rights reserved.
Be, the Be logo, BeBox, BeOS, BeWare, and GeekPort are trademarks of Be, Inc.
Last modified September 6, 1996.