[cpp.embed.gen] (original) (raw)
15 Preprocessing directives [cpp]
15.4 Resource inclusion [cpp.embed]
15.4.1 General [cpp.embed.gen]
A bracket resource search for a sequence of characters searches a sequence of places for a resource identified uniquely by that sequence of characters.
How the places are determined or the resource identified is implementation-defined.
A quote resource search for a sequence of characters attempts to identify a resource that is named by the sequence of characters.
The named resource is searched for in an implementation-defined manner.
If the implementation does not support a quote resource search for that sequence of characters, or if the search fails, the result of the quote resource search is the result of a bracket resource search for the same sequence of characters.
A preprocessing directive of the form
causes the replacement of that directive by preprocessing tokens derived from data in the resource identified by , as specified below.
the resource is identified by a bracket resource search for the sequence of characters of the h-char-sequence.
the resource is identified by a quote resource search for the sequence of characters of the q-char-sequence.
If a bracket resource search fails, or if a quote or bracket resource search identifies a resource that cannot be processed by the implementation, the program is ill-formed.
[Note 1:
If the resource cannot be processed, the program is ill-formed even when processing #embed with limit(0) ([cpp.embed.param.limit]) or evaluating __has_embed.
— _end note_]
Recommended practice: A mechanism similar to, but distinct from, theimplementation-defined search paths used for #include ([cpp.include]) is encouraged.
Either form of the #embed directive processes thepp-tokens, if present, just as in normal text.
A resource is a source of data accessible from the translation environment.
A resource has an implementation-resource-width, which is theimplementation-defined size in bits of the resource.
If the implementation-resource-width is not an integral multiple ofCHAR_BIT, the program is ill-formed.
Let implementation-resource-count be implementation-resource-width divided by CHAR_BIT.
Every resource also has a resource-count, which is
- the value as computed from the optionally-provided limit embed-parameter ([cpp.embed.param.limit]), if present;
- otherwise, the implementation-resource-count.
A resource is empty if the resource-count is zero.
[Example 1: #embed "6_bits.bin" — _end example_]
The #embed directive is replaced by a comma-separated list of integer literals of type int, unless otherwise modified by embed parameters ([cpp.embed.param]).
The integer literals in the comma-separated list correspond to resource-count consecutive calls to std::fgetc ([cstdio.syn]) from the resource, as a binary file.
If any call to std::fgetc returns EOF, the program is ill-formed.
Recommended practice: The value of each integer literal should closely represent the bit stream of the resource unmodified.
This can require an implementation to consider potential differences between translation and execution environments, as well as any other applicable sources of mismatch.
[Example 2: #include <cstring> #include <cstddef> #include <fstream> #include <vector> #include <cassert> int main() { constexpr unsigned char d[] = { #embed <data.dat> };const std::vector<unsigned char> vec_d = { #embed <data.dat> };constexpr std::size_t expected_size = sizeof(d); std::ifstream f_source("data.dat", std::ios::binary | std::ios::in);unsigned char runtime_d[expected_size];char* ifstream_ptr = reinterpret_cast<char*>(runtime_d); assert(!f_source.read(ifstream_ptr, expected_size)); std::size_t ifstream_size = f_source.gcount(); assert (ifstream_size == expected_size);int is_same = std::memcmp(&d[0], ifstream_ptr, ifstream_size); assert(is_same == 0);int is_same_vec = std::memcmp(vec_d.data(), ifstream_ptr, ifstream_size); assert(is_same_vec == 0);} — _end example_]
[Example 3: int i = { #embed "i.dat" }; int i2 = #embed "i.dat"; struct s { double a, b, c;struct { double e, f, g; } x;double h, i, j;}; s x = { #embed "s.dat" }; — _end example_]
A preprocessing directive of the form
(that does not match the previous form) is permitted.
The preprocessing tokens after embed in the directive are processed just as in normal text (i.e., each identifier currently defined as a macro name is replaced by its replacement list of preprocessing tokens).
Then, an attempt is made to form a preprocessing token ([lex.header]) from the whitespace and the characters of the spellings of the resulting sequence of preprocessing tokens immediately after embed; the treatment of whitespace is implementation-defined.
If the attempt succeeds, the directive with the so-formed is processed as specified for the previous form.
Otherwise, the program is ill-formed.
Any further processing as in normal text described for the previous form is not performed.
[Note 3:
That is, processing as in normal text happens once and only once for the entire directive.
— _end note_]
[Example 4:
If the directive matches the second form, the whole directive is replaced.
If the directive matches the first form, everything after the is replaced.
#define EMPTY#define X myfile#define Y rsc#define Z 42 #embed <myfile.rsc> prefix(Z) #embed EMPTY <X.Y> prefix(Z) is equivalent to:#embed <myfile.rsc> prefix(42) #embed <myfile.rsc> prefix(42)
— _end example_]