class
#include <Corrade/Utility/Resource.h>
Resource Access to compiled-in resources.
This class provides access to data files compiled into the executable using the corrade_
Resource compilation
Resources are organized in groups, where a group is a set of files that are encoded in a hexadecimal form into a single *.cpp
file which is then compiled alongside your other sources.
The corrade-rc executable and the corrade_
group=game-data [file] filename=license.txt [file] filename=../resources/intro-new-final.ogg alias=intro.ogg [file] filename=levels/insane.conf alias=levels/easy.conf
The group
is an identifier that you'll subsequently pass to the Resource() constructor, each [file]
section then describes one file to be compiled in, with paths relative to location of the configuration file. By default, the filename
is the name under which the files will be available when calling getRaw() or getString() later, including any directory separators. Use the alias
option to override the name.
There can be just one resource group or several, organization of the files is completely up to you. For example, if there's a set of files used only by a particular library but not other parts of the application, it might be useful to have them in a dedicated group. Or if there's a lot of files, you might wish to split them up into multiple groups to speed up the compilation and reduce compiler memory use.
Using CMake
Assuming the above file was named resources.conf
, the following CMake snippet will compile the referenced files into a C++ source stored inside the build directory. Its filename gets saved into a ${MyGame_RESOURCES}
variable, which subsequently gets passed to the add_executable()
call:
corrade_add_resource(MyGame_RESOURCES resources.conf) add_executable(MyGame … ${MyGame_RESOURCES})
The corrade_
The variable name also acts as a name used for symbols in the generated file — it has to be a valid C identifier and has to be unique among all resources compiled into the same executable. But apart from that, you'd need the name only if you deal with resources in static libraries as explained below.
Compiling the resources manually
If you're not using CMake, you can execute the corrade-rc utility manually to produce a C++ file that you then compile together with your project. The following invocation would be equivalent to the above CMake macro call:
corrade-rc MyGame_RESOURCES path/to/resources.conf output.cpp
This will generate output.cpp
in current directory, which you then compile together with your sources. The first parameter is again a name used for the symbols in the generated file.
Resource null termination and alignment
By default, resource data are tightly packed right after each other. Use nullTerminated=true
to mark them null-terminated, for example to pass strings to C APIs without having to make a null-terminated copy first, or to use them with Containers::
The resources are compiled in a char[]
, meaning you can't rely on them being aligned in any way by default. Specify an align
option to override this, allowed values are power-of-two values up to 128, with 1 being the default.
These options can be specified either globally or for particular [file]
section, which will then override the global setting. For example:
group=data # Files will be null-terminated and unaligned by default nullTerminated=true [file] filename=shader.vert [file] filename=shader.frag # This file is four-byte aligned but doesn't need null termination [file] filename=shader.spv nullTerminated=false align=4
Accessing the resources
If you compiled the resources directly into an executable or into a shared library, you can access them from the C++ code without having to do anything else. First instantiate the class with a group name matching the group
value in the configuration file, and then access the files by their filenames:
Utility::Resource rs{"game-data"}; Containers::StringView licenseText = rs.getString("license.txt"); Containers::ArrayView<const char> soundData = rs.getRaw("intro.ogg"); … std::istringstream in{rs.getString("levels/easy.conf")}; Utility::Configuration easyLevel{in}; …
Because the data are coming from a readonly memory inside the executable itself, the class returns non-owning views. In most conditions you can assume unlimited lifetime of the data, see getRaw() and getString() for details.
Resources in static libraries
If you compile the resources into a static library, the linker will implicitly treat the data as unreferenced and won't include them in the final executable, leading to a not-found assertion during Resource construction. To prevent this, you need to reference them. This can be done using the CORRADE_
int main(int argc, char** argv) { CORRADE_RESOURCE_INITIALIZE(MyGame_RESOURCES) … }
It's important to call it outside of any namespace, otherwise you'll get a linker error. The main()
function is ideal for this, or you can create a dedicated function outside a namespace and then call it from within a namespace.
Overriding compiled-in resources
For shorter turnaround times when iterating on compiled-in resources it's possible to override them at runtime using overrideGroup(). That way you won't need to wait for a recompilation, relink and restart of the application when making changes — instead you tell the application to fetch the data at runtime from the same location the resource compiler would, by pointing it to the original resources.conf
file on disk.
Resource instances created after that point will parse the configuration file and fetch the data from there, falling back to the compiled-in resources if the files are not found in the override or if there's an error. The files get cached for the lifetime of a particular Resource instance, any subsequent changes in files thus get picked up only next time a Resource instance is created.
Utility::Resource::overrideGroup("game-data", Utility::Path::join( /* Assuming resources.conf is next to this C++ source file */ Utility::Path::split(Utility::Path::fromNativeSeparators(__FILE__)).first(), "resources.conf" )); … Utility::Resource rs{"game-data"}; /* This now loads license.txt from a file instead */ Containers::StringView licenseText = rs.getString("license.txt");
Memory access and operation complexity
Resource registration (either automatic or using CORRADE_
The group lookup during construction and hasGroup() is done with a complexity as the resource groups register themselves into a linked list. Actual file lookup after is done in-place on the compiled-in data in a time.
Thread safety
The resources register themselves into a global storage. If done implicitly, the registration is executed before entering main()
and thus serially. If done explicitly via CORRADE_
On the other hand, all other functionality only reads from the global storage and thus is thread-safe.
Public static functions
-
static void overrideGroup(Containers::
StringView group, Containers:: StringView configurationFile) - Override a group.
-
static auto hasGroup(Containers::
StringView group) -> bool - Whether given group exists.
Constructors, destructors, conversion operators
-
Resource(Containers::
StringView group) explicit - Constructor.
Public functions
-
auto list() const -> Containers::
StringIterable - List of all files in the group.
-
auto hasFile(Containers::
StringView filename) const -> bool new in Git master - Whether a file is present in the resource group.
-
auto getRaw(Containers::
StringView filename) const -> Containers:: ArrayView<const char> - Get resource data.
-
auto getString(Containers::
StringView filename) const -> Containers:: StringView new in Git master - Get resource data as a string.
-
auto get(const std::
string& filename) const -> std:: string deprecated in Git master - Get resource data as a string.
Function documentation
static void Corrade:: Utility:: Resource:: overrideGroup(Containers:: StringView group,
Containers:: StringView configurationFile)
Override a group.
Parameters | |
---|---|
group | Group name |
configurationFile | Filename of the configuration file. Use an empty string to discard a previously set override. |
Overrides compiled-in resources of given group with live data specified in given configuration file. See Overriding compiled-in resources for more information.
static bool Corrade:: Utility:: Resource:: hasGroup(Containers:: StringView group)
Whether given group exists.
Corrade:: Utility:: Resource:: Resource(Containers:: StringView group) explicit
Constructor.
Expects that the group exists.
Containers:: StringIterable Corrade:: Utility:: Resource:: list() const
List of all files in the group.
The resource group has no concept of a directory hierarchy — if filenames in the input configuration file contain path separators, the returned list will contain them verbatim. The returned strings all have Containers::
Note that the list contains only the compiled-in files, no additional filenames supplied by an overriden group are included. This is done to avoid overrides causing unexpected behavior in code that assumes a fixed set of files.
bool Corrade:: Utility:: Resource:: hasFile(Containers:: StringView filename) const new in Git master
Whether a file is present in the resource group.
The filename
is expected to be in in UTF-8.
Containers:: ArrayView<const char> Corrade:: Utility:: Resource:: getRaw(Containers:: StringView filename) const
Get resource data.
Expects that the resource group contains given filename
. If the file is empty, returns a zero-sized nullptr
view. The filename
is expected to be in in UTF-8. Unlike with Path::
Unless the file is coming from an overriden group, the returned view can be assumed to have unlimited lifetime, otherwise it's alive only until the next overrideGroup() call on the same group. The data pointer is aligned according to the align
option if it was set for given file. If the file is coming from an overriden group however, its alignment isn't respected at the moment.
Containers:: StringView Corrade:: Utility:: Resource:: getString(Containers:: StringView filename) const new in Git master
Get resource data as a string.
Expects that the resource group contains given filename
. If the file is empty, returns a zero-sized nullptr
view. The filename
is expected to be in in UTF-8. Unlike with Path::
The returned string has Containers::align
option if it was set for given file. If the file is coming from an overriden group however, its alignment isn't respected at the moment.
The returned string is Containers::nullTerminated
option was set for given file, or if it's coming from an overriden group. Otherwise it may be marked as null terminated if there's some padding after in order to align the next file, but such behavior is specific to the internal implementation and thus null termination isn't guaranteed.
std:: string Corrade:: Utility:: Resource:: get(const std:: string& filename) const
Get resource data as a string.