[cpp.embed] # 15 Preprocessing directives [[cpp]](./#cpp) ## 15.4 Resource inclusion [cpp.embed] ### [15.4.1](#gen) General [[cpp.embed.gen]](cpp.embed.gen) [1](#gen-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L845) A [*bracket resource search*](#def:search,bracket_resource "15.4.1 General [cpp.embed.gen]") for a sequence of characters searches a sequence of places for a resource identified uniquely by that sequence of characters[.](#gen-1.sentence-1) How the places are determined or the resource identified is implementation-defined[.](#gen-1.sentence-2) [2](#gen-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L852) A [*quote resource search*](#def:search,quote_resource "15.4.1 General [cpp.embed.gen]") for a sequence of characters attempts to identify a resource that is named by the sequence of characters[.](#gen-2.sentence-1) The named resource is searched for in an implementation-defined manner[.](#gen-2.sentence-2) 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[.](#gen-2.sentence-3) [3](#gen-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L862) A preprocessing directive of the form # embed [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]")opt [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]") causes the replacement of that directive by preprocessing tokens derived from data in the resource identified by [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]"), as specified below[.](#gen-3.sentence-1) [4](#gen-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L872) If the [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") is of the form < [*h-char-sequence*](lex.header#nt:h-char-sequence "5.6 Header names [lex.header]") > the resource is identified by a bracket resource search for the sequence of characters of the [*h-char-sequence*](lex.header#nt:h-char-sequence "5.6 Header names [lex.header]")[.](#gen-4.sentence-1) [5](#gen-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L880) If the [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") is of the form " [*q-char-sequence*](lex.header#nt:q-char-sequence "5.6 Header names [lex.header]") " the resource is identified by a quote resource search for the sequence of characters of the [*q-char-sequence*](lex.header#nt:q-char-sequence "5.6 Header names [lex.header]")[.](#gen-5.sentence-1) [6](#gen-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L888) 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[.](#gen-6.sentence-1) [*Note [1](#gen-note-1)*: If the resource cannot be processed, the program is ill-formed even when processing #embed with limit(0) ([[cpp.embed.param.limit]](#param.limit "15.4.2.1 limit parameter")) or evaluating __has_embed[.](#gen-6.sentence-2) — *end note*] [7](#gen-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L898) *Recommended practice*: A mechanism similar to, but distinct from, theimplementation-defined search paths used for #include ([[cpp.include]](cpp.include "15.3 Source file inclusion")) is encouraged[.](#gen-7.sentence-1) [8](#gen-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L904) Either form of the #embed directive processes the[*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]"), if present, just as in normal text[.](#gen-8.sentence-1) The [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") shall then have the form[*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]")[.](#gen-8.sentence-2) [9](#gen-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L910) A resource is a source of data accessible from the translation environment[.](#gen-9.sentence-1) A resource has an [*implementation-resource-width*](#def:implementation-resource-width "15.4.1 General [cpp.embed.gen]"), which is theimplementation-defined size in bits of the resource[.](#gen-9.sentence-2) If the implementation-resource-width is not an integral multiple ofCHAR_BIT, the program is ill-formed[.](#gen-9.sentence-3) Let [*implementation-resource-count*](#def:implementation-resource-count "15.4.1 General [cpp.embed.gen]") be implementation-resource-width divided by CHAR_BIT[.](#gen-9.sentence-4) Every resource also has a [*resource-count*](#def:resource-count "15.4.1 General [cpp.embed.gen]"), which is - [(9.1)](#gen-9.1) the value as computed from the optionally-provided limit[*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") ([[cpp.embed.param.limit]](#param.limit "15.4.2.1 limit parameter")), if present; - [(9.2)](#gen-9.2) otherwise, the implementation-resource-count. A resource is empty if the resource-count is zero[.](#gen-9.sentence-6) [10](#gen-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L931) [*Example [1](#gen-example-1)*: // ill-formed if the implementation-resource-width is 6 bits#embed "6_bits.bin" — *end example*] [11](#gen-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L939) 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]](#param "15.4.2 Embed parameters"))[.](#gen-11.sentence-1) [12](#gen-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L944) The integer literals in the comma-separated list correspond to resource-count consecutive calls to std​::​fgetc ([[cstdio.syn]](cstdio.syn "31.13.1 Header synopsis")) from the resource, as a binary file[.](#gen-12.sentence-1) If any call to std​::​fgetc returns EOF, the program is ill-formed[.](#gen-12.sentence-2) [13](#gen-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L951) *Recommended practice*: The value of each integer literal should closely represent the bit stream of the resource unmodified[.](#gen-13.sentence-1) This can require an implementation to consider potential differences between translation and execution environments, as well as any other applicable sources of mismatch[.](#gen-13.sentence-2) [*Example [2](#gen-example-2)*: #include #include #include #include #include int main() {// If the file is the same as the resource in the translation environment, no assert in this program should fail.constexpr unsigned char d[] = {#embed }; const std::vector vec_d = {#embed }; constexpr std::size_t expected_size = sizeof(d); // same file in execution environment as was embedded std::ifstream f_source("data.dat", std::ios::binary | std::ios::in); unsigned char runtime_d[expected_size]; char* ifstream_ptr = reinterpret_cast(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](#gen-example-3)*: int i = {#embed "i.dat"}; // well-formed if i.dat produces a single valueint i2 =#embed "i.dat" ; // also well-formed if i.dat produces a single valuestruct s {double a, b, c; struct { double e, f, g; } x; double h, i, j;}; s x = {// well-formed if the directive produces nine or fewer values#embed "s.dat"}; — *end example*] [14](#gen-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1012) A preprocessing directive of the form # embed [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]") (that does not match the previous form) is permitted[.](#gen-14.sentence-1) 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)[.](#gen-14.sentence-2) Then, an attempt is made to form a [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") preprocessing token ([[lex.header]](lex.header "5.6 Header names")) 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[.](#gen-14.sentence-3) If the attempt succeeds, the directive with the so-formed [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") is processed as specified for the previous form[.](#gen-14.sentence-4) Otherwise, the program is ill-formed[.](#gen-14.sentence-5) [*Note [2](#gen-note-2)*: Adjacent [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]")*s* are not concatenated into a single[*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]") (see the translation phases in [[lex.phases]](lex.phases "5.2 Phases of translation")); thus, an expansion that results in two [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]")*s* is an invalid directive[.](#gen-14.sentence-6) — *end note*] Any further processing as in normal text described for the previous form is not performed[.](#gen-14.sentence-7) [*Note [3](#gen-note-3)*: That is, processing as in normal text happens once and only once for the entire directive[.](#gen-14.sentence-8) — *end note*] [*Example [4](#gen-example-4)*: If the directive matches the second form, the whole directive is replaced[.](#gen-14.sentence-9) If the directive matches the first form, everything after the name is replaced[.](#gen-14.sentence-10) #define EMPTY#define X myfile#define Y rsc#define Z 42#embed prefix(Z)#embed EMPTY prefix(Z) is equivalent to:#embed prefix(42)#embed prefix(42) — *end example*] ### [15.4.2](#param) Embed parameters [[cpp.embed.param]](cpp.embed.param) #### [15.4.2.1](#param.limit) limit parameter [[cpp.embed.param.limit]](cpp.embed.param.limit) [1](#param.limit-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1063) An [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") of the formlimit ( [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]") ) specifies the maximum possible number of elements in the comma-delimited list[.](#param.limit-1.sentence-1) It shall appear at most once in the [*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]")[.](#param.limit-1.sentence-2) The preprocessing token defined shall not appear in the[*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")[.](#param.limit-1.sentence-3) [2](#param.limit-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1072) The [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]") is evaluated as a[*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") using the rules as described in conditional inclusion ([[cpp.cond]](cpp.cond "15.2 Conditional inclusion")), but without being processed as in normal text an additional time[.](#param.limit-2.sentence-1) [*Example [1](#param.limit-example-1)*: #undef DATA_LIMIT#if __has_embed( limit(DATA_LIMIT))#endif is equivalent to: #if __has_embed( limit(0))#endif — *end example*] [*Example [2](#param.limit-example-2)*: #embed limit(__has_include("a.h"))#if __has_embed( limit(__has_include("a.h")))// ill-formed: __has_include ([[cpp.cond]](cpp.cond "15.2 Conditional inclusion")) cannot appear here#endif — *end example*] [3](#param.limit-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1103) The [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") shall be an integral constant expression whose value is greater than or equal to zero[.](#param.limit-3.sentence-1) The resource-count ([[cpp.embed.gen]](#gen "15.4.1 General")) becomes implementation-resource-count, if the value of the[*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") is greater than implementation-resource-count; otherwise, the value of the[*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]")[.](#param.limit-3.sentence-2) [*Example [3](#param.limit-example-3)*: constexpr unsigned char sound_signature[] = {// a hypothetical resource capable of expanding to four or more elements#embed limit(2+2)}; static_assert(sizeof(sound_signature) == 4); // OK — *end example*] #### [15.4.2.2](#param.prefix) prefix parameter [[cpp.embed.param.prefix]](cpp.embed.param.prefix) [1](#param.prefix-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1123) An [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") of the form prefix ( [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")opt ) shall appear at most once in the [*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]")[.](#param.prefix-1.sentence-1) [2](#param.prefix-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1130) If the resource is empty, this [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") is ignored[.](#param.prefix-2.sentence-1) Otherwise, the [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]") is placed immediately before the comma-delimited list of integral literals[.](#param.prefix-2.sentence-2) #### [15.4.2.3](#param.suffix) suffix parameter [[cpp.embed.param.suffix]](cpp.embed.param.suffix) [1](#param.suffix-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1136) An [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") of the form suffix ( [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")opt ) shall appear at most once in the [*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]")[.](#param.suffix-1.sentence-1) [2](#param.suffix-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1143) If the resource is empty, this [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") is ignored[.](#param.suffix-2.sentence-1) Otherwise, the [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]") is placed immediately after the comma-delimited list of the integral constant expressions[.](#param.suffix-2.sentence-2) [*Example [1](#param.suffix-example-1)*: constexpr unsigned char whl[] = {#embed "ches.glsl" \ prefix(0xEF, 0xBB, 0xBF, ) /* a sequence of bytes */ \ suffix(,)0};// always null-terminated, contains the sequence if not emptyconstexpr bool is_empty = sizeof(whl) == 1 && whl[0] == '\0';constexpr bool is_not_empty = sizeof(whl) >= 4&& whl[sizeof(whl) - 1] == '\0'&& whl[0] == '\xEF' && whl[1] == '\xBB' && whl[2] == '\xBF';static_assert(is_empty || is_not_empty); — *end example*] #### [15.4.2.4](#param.if.empty) if_empty parameter [[cpp.embed.param.if.empty]](cpp.embed.param.if.empty) [1](#param.if.empty-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1166) An embed-parameter of the form if_empty ( [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")opt ) shall appear at most once in the [*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]")[.](#param.if.empty-1.sentence-1) [2](#param.if.empty-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1173) If the resource is not empty, this [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") is ignored[.](#param.if.empty-2.sentence-1) Otherwise, the #embed directive is replaced by the[*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")[.](#param.if.empty-2.sentence-2) [*Example [1](#param.if.empty-example-1)*: limit(0) affects when a resource is considered empty[.](#param.if.empty-2.sentence-3) Therefore, the following program: #embed \ if_empty(42203) limit(0) expands to42203 — *end example*] [*Example [2](#param.if.empty-example-2)*: This resource is considered empty due to the limit(0) [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]"), always, including in __has_embed clauses[.](#param.if.empty-2.sentence-6) int infinity_zero () {#if __has_embed( limit(0) prefix(some tokens)) == __STDC_EMBED_EMPTY__ // if exists, this conditional inclusion branch is taken and the function returns 0.return 0;#else// otherwise, the resource does not exist#error "The resource does not exist"#endif} — *end example*]