From Jason Turner

[cpp.embed]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmprc1byyji/{from.md → to.md} +370 -0
tmp/tmprc1byyji/{from.md → to.md} RENAMED
@@ -0,0 +1,370 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Resource inclusion <a id="cpp.embed">[[cpp.embed]]</a>
2
+
3
+ ### General <a id="cpp.embed.gen">[[cpp.embed.gen]]</a>
4
+
5
+ A *bracket resource search* for a sequence of characters searches a
6
+ sequence of places for a resource identified uniquely by that sequence
7
+ of characters. How the places are determined or the resource identified
8
+ is *implementation-defined*.
9
+
10
+ A *quote resource search* for a sequence of characters attempts to
11
+ identify a resource that is named by the sequence of characters. The
12
+ named resource is searched for in an *implementation-defined* manner. If
13
+ the implementation does not support a quote resource search for that
14
+ sequence of characters, or if the search fails, the result of the quote
15
+ resource search is the result of a bracket resource search for the same
16
+ sequence of characters.
17
+
18
+ A preprocessing directive of the form
19
+
20
+ ``` bnf
21
+ '# embed' header-name pp-tokensₒₚₜ new-line
22
+ ```
23
+
24
+ causes the replacement of that directive by preprocessing tokens derived
25
+ from data in the resource identified by *header-name*, as specified
26
+ below.
27
+
28
+ If the *header-name* is of the form
29
+
30
+ ``` bnf
31
+ '<' h-char-sequence '>'
32
+ ```
33
+
34
+ the resource is identified by a bracket resource search for the sequence
35
+ of characters of the *h-char-sequence*.
36
+
37
+ If the *header-name* is of the form
38
+
39
+ ``` bnf
40
+ '"' q-char-sequence '"'
41
+ ```
42
+
43
+ the resource is identified by a quote resource search for the sequence
44
+ of characters of the *q-char-sequence*.
45
+
46
+ If a bracket resource search fails, or if a quote or bracket resource
47
+ search identifies a resource that cannot be processed by the
48
+ implementation, the program is ill-formed.
49
+
50
+ [*Note 1*: If the resource cannot be processed, the program is
51
+ ill-formed even when processing `#embed` with `limit(0)`
52
+ [[cpp.embed.param.limit]] or evaluating `__has_embed`. — *end note*]
53
+
54
+ *Recommended practice:* A mechanism similar to, but distinct from, the
55
+ *implementation-defined* search paths used for `#include`
56
+ [[cpp.include]] is encouraged.
57
+
58
+ Either form of the `#embed` directive processes the *pp-tokens*, if
59
+ present, just as in normal text. The *pp-tokens* shall then have the
60
+ form *embed-parameter-seq*.
61
+
62
+ A resource is a source of data accessible from the translation
63
+ environment. A resource has an *implementation-resource-width*, which is
64
+ the *implementation-defined* size in bits of the resource. If the
65
+ implementation-resource-width is not an integral multiple of `CHAR_BIT`,
66
+ the program is ill-formed. Let *implementation-resource-count* be
67
+ implementation-resource-width divided by `CHAR_BIT`. Every resource also
68
+ has a *resource-count*, which is
69
+
70
+ - the value as computed from the optionally-provided `limit`
71
+ *embed-parameter* [[cpp.embed.param.limit]], if present;
72
+ - otherwise, the implementation-resource-count.
73
+
74
+ A resource is empty if the resource-count is zero.
75
+
76
+ [*Example 1*:
77
+
78
+ ``` cpp
79
+ // ill-formed if the implementation-resource-width is 6 bits
80
+ #embed "6_bits.bin"
81
+ ```
82
+
83
+ — *end example*]
84
+
85
+ The `#embed` directive is replaced by a comma-separated list of integer
86
+ literals of type `int`, unless otherwise modified by embed parameters
87
+ [[cpp.embed.param]].
88
+
89
+ The integer literals in the comma-separated list correspond to
90
+ resource-count consecutive calls to `std::fgetc` [[cstdio.syn]] from the
91
+ resource, as a binary file. If any call to `std::fgetc` returns `EOF`,
92
+ the program is ill-formed.
93
+
94
+ *Recommended practice:* The value of each integer literal should closely
95
+ represent the bit stream of the resource unmodified. This can require an
96
+ implementation to consider potential differences between translation and
97
+ execution environments, as well as any other applicable sources of
98
+ mismatch.
99
+
100
+ [*Example 2*:
101
+
102
+ ``` cpp
103
+ #include <cstring>
104
+ #include <cstddef>
105
+ #include <fstream>
106
+ #include <vector>
107
+ #include <cassert>
108
+
109
+ int main() {
110
+ // If the file is the same as the resource in the translation environment, no assert in this program should fail.
111
+ constexpr unsigned char d[] = {
112
+ #embed <data.dat>
113
+ };
114
+ const std::vector<unsigned char> vec_d = {
115
+ #embed <data.dat>
116
+ };
117
+
118
+ constexpr std::size_t expected_size = sizeof(d);
119
+
120
+ // same file in execution environment as was embedded
121
+ std::ifstream f_source("data.dat", std::ios::binary | std::ios::in);
122
+ unsigned char runtime_d[expected_size];
123
+ char* ifstream_ptr = reinterpret_cast<char*>(runtime_d);
124
+ assert(!f_source.read(ifstream_ptr, expected_size));
125
+ std::size_t ifstream_size = f_source.gcount();
126
+ assert (ifstream_size == expected_size);
127
+ int is_same = std::memcmp(&d[0], ifstream_ptr, ifstream_size);
128
+ assert(is_same == 0);
129
+ int is_same_vec = std::memcmp(vec_d.data(), ifstream_ptr, ifstream_size);
130
+ assert(is_same_vec == 0);
131
+ }
132
+ ```
133
+
134
+ — *end example*]
135
+
136
+ [*Example 3*:
137
+
138
+ ``` cpp
139
+ int i = {
140
+ #embed "i.dat"
141
+ }; // well-formed if i.dat produces a single value
142
+ int i2 =
143
+ #embed "i.dat"
144
+ ; // also well-formed if i.dat produces a single value
145
+ struct s {
146
+ double a, b, c;
147
+ struct { double e, f, g; } x;
148
+ double h, i, j;
149
+ };
150
+ s x = {
151
+ // well-formed if the directive produces nine or fewer values
152
+ #embed "s.dat"
153
+ };
154
+ ```
155
+
156
+ — *end example*]
157
+
158
+ A preprocessing directive of the form
159
+
160
+ ``` bnf
161
+ '# embed' pp-tokens new-line
162
+ ```
163
+
164
+ (that does not match the previous form) is permitted. The preprocessing
165
+ tokens after `embed` in the directive are processed just as in normal
166
+ text (i.e., each identifier currently defined as a macro name is
167
+ replaced by its replacement list of preprocessing tokens). Then, an
168
+ attempt is made to form a *header-name* preprocessing token
169
+ [[lex.header]] from the whitespace and the characters of the spellings
170
+ of the resulting sequence of preprocessing tokens immediately after
171
+ `embed`; the treatment of whitespace is *implementation-defined*. If the
172
+ attempt succeeds, the directive with the so-formed *header-name* is
173
+ processed as specified for the previous form. Otherwise, the program is
174
+ ill-formed.
175
+
176
+ [*Note 2*: Adjacent *string-literal*s are not concatenated into a
177
+ single *string-literal* (see the translation phases in  [[lex.phases]]);
178
+ thus, an expansion that results in two *string-literal*s is an invalid
179
+ directive. — *end note*]
180
+
181
+ Any further processing as in normal text described for the previous form
182
+ is not performed.
183
+
184
+ [*Note 3*: That is, processing as in normal text happens once and only
185
+ once for the entire directive. — *end note*]
186
+
187
+ [*Example 4*:
188
+
189
+ If the directive matches the second form, the whole directive is
190
+ replaced. If the directive matches the first form, everything after the
191
+ *header-name* is replaced.
192
+
193
+ ``` cpp
194
+ #define EMPTY
195
+ #define X myfile
196
+ #define Y rsc
197
+ #define Z 42
198
+ #embed <myfile.rsc> prefix(Z)
199
+ #embed EMPTY <X.Y> prefix(Z)
200
+ ```
201
+
202
+ is equivalent to:
203
+
204
+ ``` cpp
205
+ #embed <myfile.rsc> prefix(42)
206
+ #embed <myfile.rsc> prefix(42)
207
+ ```
208
+
209
+ — *end example*]
210
+
211
+ ### Embed parameters <a id="cpp.embed.param">[[cpp.embed.param]]</a>
212
+
213
+ #### limit parameter <a id="cpp.embed.param.limit">[[cpp.embed.param.limit]]</a>
214
+
215
+ An *embed-parameter* of the form `limit (` *pp-balanced-token-seq* `)`
216
+ specifies the maximum possible number of elements in the comma-delimited
217
+ list. It shall appear at most once in the *embed-parameter-seq*. The
218
+ preprocessing token `defined` shall not appear in the
219
+ *pp-balanced-token-seq*.
220
+
221
+ The *pp-balanced-token-seq* is evaluated as a *constant-expression*
222
+ using the rules as described in conditional inclusion [[cpp.cond]], but
223
+ without being processed as in normal text an additional time.
224
+
225
+ [*Example 1*:
226
+
227
+ ``` cpp
228
+ #undef DATA_LIMIT
229
+ #if __has_embed(<data.dat> limit(DATA_LIMIT))
230
+ #endif
231
+ ```
232
+
233
+ is equivalent to:
234
+
235
+ ``` cpp
236
+ #if __has_embed(<data.dat> limit(0))
237
+ #endif
238
+ ```
239
+
240
+ — *end example*]
241
+
242
+ [*Example 2*:
243
+
244
+ ``` cpp
245
+ #embed <data.dat> limit(__has_include("a.h"))
246
+
247
+ #if __has_embed(<data.dat> limit(__has_include("a.h")))
248
+ // ill-formed: __has_include[cpp.cond] cannot appear here
249
+ #endif
250
+ ```
251
+
252
+ — *end example*]
253
+
254
+ The *constant-expression* shall be an integral constant expression whose
255
+ value is greater than or equal to zero. The resource-count
256
+ [[cpp.embed.gen]] becomes implementation-resource-count, if the value of
257
+ the *constant-expression* is greater than implementation-resource-count;
258
+ otherwise, the value of the *constant-expression*.
259
+
260
+ [*Example 3*:
261
+
262
+ ``` cpp
263
+ constexpr unsigned char sound_signature[] = {
264
+ // a hypothetical resource capable of expanding to four or more elements
265
+ #embed <sdk/jump.wav> limit(2+2)
266
+ };
267
+
268
+ static_assert(sizeof(sound_signature) == 4); // OK
269
+ ```
270
+
271
+ — *end example*]
272
+
273
+ #### prefix parameter <a id="cpp.embed.param.prefix">[[cpp.embed.param.prefix]]</a>
274
+
275
+ An *embed-parameter* of the form
276
+
277
+ ``` bnf
278
+ 'prefix (' pp-balanced-token-seqₒₚₜ ')'
279
+ ```
280
+
281
+ shall appear at most once in the *embed-parameter-seq*.
282
+
283
+ If the resource is empty, this *embed-parameter* is ignored. Otherwise,
284
+ the *pp-balanced-token-seq* is placed immediately before the
285
+ comma-delimited list of integral literals.
286
+
287
+ #### suffix parameter <a id="cpp.embed.param.suffix">[[cpp.embed.param.suffix]]</a>
288
+
289
+ An *embed-parameter* of the form
290
+
291
+ ``` bnf
292
+ 'suffix (' pp-balanced-token-seqₒₚₜ ')'
293
+ ```
294
+
295
+ shall appear at most once in the *embed-parameter-seq*.
296
+
297
+ If the resource is empty, this *embed-parameter* is ignored. Otherwise,
298
+ the *pp-balanced-token-seq* is placed immediately after the
299
+ comma-delimited list of the integral constant expressions.
300
+
301
+ [*Example 1*:
302
+
303
+ ``` cpp
304
+ constexpr unsigned char whl[] = {
305
+ #embed "ches.glsl" \
306
+ prefix(0xEF, 0xBB, 0xBF, ) /* a sequence of bytes */ \
307
+ suffix(,)
308
+ 0
309
+ };
310
+ // always null-terminated, contains the sequence if not empty
311
+ constexpr bool is_empty = sizeof(whl) == 1 && whl[0] == '\0';
312
+ constexpr bool is_not_empty = sizeof(whl) >= 4
313
+ && whl[sizeof(whl) - 1] == '\0'
314
+ && whl[0] == '\xEF' && whl[1] == '\xBB' && whl[2] == '\xBF';
315
+ static_assert(is_empty || is_not_empty);
316
+ ```
317
+
318
+ — *end example*]
319
+
320
+ #### `if_empty` parameter <a id="cpp.embed.param.if.empty">[[cpp.embed.param.if.empty]]</a>
321
+
322
+ An embed-parameter of the form
323
+
324
+ ``` bnf
325
+ 'if_empty (' pp-balanced-token-seqₒₚₜ ')'
326
+ ```
327
+
328
+ shall appear at most once in the *embed-parameter-seq*.
329
+
330
+ If the resource is not empty, this *embed-parameter* is ignored.
331
+ Otherwise, the `#embed` directive is replaced by the
332
+ *pp-balanced-token-seq*.
333
+
334
+ [*Example 1*:
335
+
336
+ `limit(0)` affects when a resource is considered empty. Therefore, the
337
+ following program:
338
+
339
+ ``` cpp
340
+ #embed </owo/uwurandom> \
341
+ if_empty(42203) limit(0)
342
+ ```
343
+
344
+ expands to
345
+
346
+ ``` cpp
347
+ 42203
348
+ ```
349
+
350
+ — *end example*]
351
+
352
+ [*Example 2*:
353
+
354
+ This resource is considered empty due to the `limit(0)`
355
+ *embed-parameter*, always, including in `__has_embed` clauses.
356
+
357
+ ``` cpp
358
+ int infinity_zero () {
359
+ #if __has_embed(</owo/uwurandom> limit(0) prefix(some tokens)) == __STDC_EMBED_EMPTY__
360
+ // if </owo/uwurandom> exists, this conditional inclusion branch is taken and the function returns 0.
361
+ return 0;
362
+ #else
363
+ // otherwise, the resource does not exist
364
+ #error "The resource does not exist"
365
+ #endif
366
+ }
367
+ ```
368
+
369
+ — *end example*]
370
+