summaryrefslogtreecommitdiff
path: root/libs/endian/doc/buffers.html
blob: 85aae22e5d83ed82df6fd85e57e01072ee4f3543 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
<html>

<head>
<meta http-equiv="Content-Language" content="en-us">
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Endian Buffer Types</title>
<link href="styles.css" rel="stylesheet">
</style>
</head>

<body>


<table border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="100%">
  <tr>
    <td>
<a href="../../../index.html">
<img src="../../../boost.png" alt="Boost logo" align="middle" border="0" width="277" height="86"></a></td>
    <td align="middle">
    <b>
    <font size="6">Endian Buffer Types</font> </b>
    </td>
  </tr>
</table>

<table border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" bgcolor="#D7EEFF" width="100%">
  <tr>
    <td><b>
    <a href="index.html">Endian Home</a>&nbsp;&nbsp;&nbsp;&nbsp;
    <a href="conversion.html">Conversion Functions</a>&nbsp;&nbsp;&nbsp;&nbsp;
    <a href="arithmetic.html">Arithmetic Types</a>&nbsp;&nbsp;&nbsp;&nbsp;
    <a href="buffers.html">Buffer Types</a>&nbsp;&nbsp;&nbsp;&nbsp;
    <a href="choosing_approach.html">Choosing Approach</a></b></td>
  </tr>
</table>

<p></p>

<table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" align="right">
  <tr>
    <td width="100%" bgcolor="#D7EEFF" align="center">
      <i><b>Contents</b></i></td>
  </tr>
  <tr>
    <td width="100%" bgcolor="#E8F5FF">
      <a href="#Introduction">Introduction</a><br>
      <a href="#Example">Example</a><br>
      <a href="#Limitations">Limitations</a><br>
      <a href="#Feature-set">Feature set</a><br>
      <a href="#Types">Enums and typedefs</a><br>
      <a href="#Class_template_endian">Class template <code>endian_buffer</code></a><br>
      &nbsp;&nbsp;&nbsp;
      <a href="#Synopsis">Synopsis</a><br>
      &nbsp;&nbsp;&nbsp; <a href="#Members">Members</a><br>
&nbsp;&nbsp;&nbsp; <a href="#Non-member-functions">Non-Members</a><br>
      <a href="#FAQ">FAQ</a><br>
      <a href="#Design">Design</a><br>
      <a href="#C++0x">C++11</a><br>
      <a href="#Compilation">Compilation</a></td>
  </tr>
  </table>
<h2><a name="Introduction">Introduction</a></h2>
<p>The internal byte order of arithmetic types is traditionally called <b><i>endianness</i></b>. See 
the
<a href="http://en.wikipedia.org/wiki/Endian" name="endianness">Wikipedia</a> for 
a full 
exploration of <b><i>endianness</i></b>, including definitions of <i><b>big 
endian</b></i> and <i><b>little endian</b></i>.</p>
<p>Header <b><code>boost/endian/buffers.hpp</code></b> 
provides <code>endian_buffer</code>, a portable endian integer binary buffer 
class template with control over 
byte order, value type, size, and alignment independent of the platform&#39;s native 
endianness. Typedefs provide easy-to-use names 
for common configurations.</p>
<p>Use cases primarily involve data portability, either via files or network 
connections, but these byte-holders may 
also be used to reduce memory use, file size, or network activity since they 
 
provide binary numeric sizes not otherwise available.</p>
<p dir="ltr">Class <code>endian_buffer</code> is aimed at users who wish 
explicit control over when endianness conversions occur. It also serves as the 
base class for the <code><a href="arithmetic.html">endian_arithmetic</a></code> 
class template, which is aimed at users who wish fully automatic endianness 
conversion and direct support for all normal arithmetic operations.</p>
<h2><a name="Example">Example</a></h2>
<p>The <b><code>example/endian_example.cpp</code></b> program writes a 
binary file containing four-byte, big-endian and little-endian integers:</p>
<blockquote>
  <pre>#include &lt;iostream&gt;
#include &lt;cstdio&gt;
#include &lt;boost/endian/buffers.hpp&gt;  // see <a href="#Synopsis">Synopsis</a> below
#include &lt;boost/static_assert.hpp&gt;

using namespace boost::endian;

namespace 
{
  //  This is an extract from a very widely used GIS file format.
  //  Why the designer decided to mix big and little endians in
  //  the same file is not known. But this is a real-world format
  //  and users wishing to write low level code manipulating these
  //  files have to deal with the mixed endianness.

  struct header
  {
    big_int32_<code>buf_</code>t     file_code;
    big_int32_<code>buf_</code>t     file_length;
    little_int32_<code>buf_</code>t  version;
    little_int32_<code>buf_</code>t  shape_type;
  };

  const char* filename = &quot;test.dat&quot;;
}

int main(int, char* [])
{
  header h;

  BOOST_STATIC_ASSERT(sizeof(h) == 16U);  // reality check
  
  h.file_code   = 0x01020304;
  h.file_length = sizeof(header);
  h.version     = 1;
  h.shape_type  = 0x01020304;

  //  Low-level I/O such as POSIX read/write or &lt;cstdio&gt;
  //  fread/fwrite is sometimes used for binary file operations
  //  when ultimate efficiency is important. Such I/O is often
  //  performed in some C++ wrapper class, but to drive home the
  //  point that endian integers are often used in fairly
  //  low-level code that does bulk I/O operations, &lt;cstdio&gt;
  //  fopen/fwrite is used for I/O in this example.

  std::FILE* fi = std::fopen(filename, &quot;wb&quot;);  // MUST BE BINARY
  
  if (!fi)
  {
    std::cout &lt;&lt; &quot;could not open &quot; &lt;&lt; filename &lt;&lt; '\n';
    return 1;
  }

  if (std::fwrite(&amp;h, sizeof(header), 1, fi)!= 1)
  {
    std::cout &lt;&lt; &quot;write failure for &quot; &lt;&lt; filename &lt;&lt; '\n';
    return 1;
  }

  std::fclose(fi);

  std::cout &lt;&lt; &quot;created file &quot; &lt;&lt; filename &lt;&lt; '\n';

  return 0;
}
</pre>
</blockquote>
<p>After compiling and executing <b><code>example/endian_example.cpp</code></b>, 
a hex dump of <code>test.dat</code> shows:</p>
<blockquote>
  <pre>01020304 00000010 01000000 04030201</pre>
</blockquote>
<p>Notice that the first two 32-bit integers are big endian while the second two 
are little endian, even though the machine this was compiled and run on was 
little endian.</p>
<h2><a name="Limitations">Limitations</a></h2>
<p>Requires <code>&lt;climits&gt;</code> <code>CHAR_BIT == 8</code>. If <code>CHAR_BIT</code> 
is some other value, compilation will result in an <code>#error</code>. This 
restriction is in place because the design, implementation, testing, and 
documentation has only considered issues related to 8-bit bytes, and there have 
been no real-world use cases presented for other sizes.</p>
<p>In C++03, <code>endian_buffer</code> does not meet the requirements for POD types 
because it has constructors, private data members, and a base class. This means 
that common use cases are relying on unspecified behavior in that the C++ 
Standard does not guarantee memory layout for non-POD types. This has not been a 
problem in practice since all known C++ compilers  lay out memory as if <code>
endian</code> were a POD type. In C++11, it is possible to specify the 
default constructor as trivial, and private data members and base classes  no longer disqualify a type from being a POD 
type. Thus under C++11, <code>endian_buffer</code> 
will no longer be relying on unspecified behavior.</p>
<h2><a name="Feature-set">Feature set</a></h2>
<ul>
  <li>Big endian| little endian | native endian byte ordering.</li>
  <li>Signed | unsigned</li>
  <li>Unaligned | aligned</li>
  <li>1-8 byte (unaligned) | 1, 2, 4, 8 byte (aligned)</li>
  <li>Choice of  value type</li>
</ul>
<h2>Enums and t<a name="Types">ypedefs</a></h2>
<p>Two scoped enums are provided:</p>
<blockquote>
  <pre>enum class order {big, little, native};

enum class align {no, yes}; </pre>
</blockquote>
<p>One class template is provided:</p>
<blockquote>
  <pre>template &lt;order Order, typename T, std::size_t Nbits,
  align Align = align::no&gt;
class endian_buffer;
</pre>
</blockquote>
<p>Typedefs, such as <code>big_int32_buf_t</code>, provide convenient naming 
conventions for common use cases:</p>
<blockquote>
<table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="49%">
  <tr>
    <td width="18%" align="center"><b><i>Name</i></b></td>
    <td width="49%" align="center"><b><i>Alignment</i></b></td>
    <td width="10%" align="center"><b><i>Endianness</i></b></td>
    <td width="10%" align="center"><b><i>Sign</i></b></td>
    <td width="15%" align="center"><b><i>Sizes in bits (n)</i></b></td>
  </tr>
  <tr>
    <td width="18%" dir="ltr"><code>big_int</code><b><i>n</i></b><code>_buf_t</code></td>
    <td width="49%" align="center" dir="ltr"><code>no</code></td>
    <td width="10%" align="center" dir="ltr"><code>big</code></td>
    <td width="10%" align="center" dir="ltr">signed</td>
    <td width="15%" dir="ltr">8,16,24,32,40,48,56,64</td>
    </tr>
  <tr>
    <td width="18%" dir="ltr"><code>big_uint</code><i><b>n</b></i><code>_buf_t</code></td>
    <td width="49%" align="center" dir="ltr"><code>no</code></td>
    <td width="10%" align="center" dir="ltr"><code>big</code></td>
    <td width="10%" align="center" dir="ltr">unsigned</td>
    <td width="15%" dir="ltr">8,16,24,32,40,48,56,64</td>
    </tr>
  <tr>
    <td width="18%"><code>little_int</code><i><b>n</b></i><code>_buf_t</code></td>
    <td width="49%" align="center"><code>no</code></td>
    <td width="10%" align="center"><code>little</code></td>
    <td width="10%" align="center">signed</td>
    <td width="15%">8,16,24,32,40,48,56,64</td>
    </tr>
  <tr>
    <td width="18%"><code>little_uint</code><i><b>n</b></i><code>_buf_t</code></td>
    <td width="49%" align="center"><code>no</code></td>
    <td width="10%" align="center"><code>little</code></td>
    <td width="10%" align="center">unsigned</td>
    <td width="15%">8,16,24,32,40,48,56,64</td>
    </tr>
  <tr>
    <td width="18%"><code>native_int</code><i><b>n</b></i><code>_buf_t</code></td>
    <td width="49%" align="center"><code>no</code></td>
    <td width="10%" align="center"><code>native</code></td>
    <td width="10%" align="center">signed</td>
    <td width="15%">8,16,24,32,40,48,56,64</td>
    </tr>
  <tr>
    <td width="18%"><code>native_uint</code><i><b>n</b></i><code>_buf_t</code></td>
    <td width="49%" align="center"><code>no</code></td>
    <td width="10%" align="center"><code>native</code></td>
    <td width="10%" align="center">unsigned</td>
    <td width="15%">8,16,24,32,40,48,56,64</td>
    </tr>
  <tr>
    <td width="18%"><code>big_int</code><i><b>n</b></i><code>_buf_at</code></td>
    <td width="49%" align="center"><code>yes</code></td>
    <td width="10%" align="center"><code>big</code></td>
    <td width="10%" align="center">signed</td>
    <td width="15%">8,16,32,64</td>
  </tr>
  <tr>
    <td width="18%"><code>big_uint</code><i><b>n</b></i><code>_</code><code>buf_at</code></td>
    <td width="49%" align="center"><code>yes</code></td>
    <td width="10%" align="center"><code>big</code></td>
    <td width="10%" align="center">unsigned</td>
    <td width="15%">8,16,32,64</td>
  </tr>
  <tr>
    <td width="18%"><code>little_int</code><i><b>n</b></i><code>_</code><code>buf_at</code></td>
    <td width="49%" align="center"><code>yes</code></td>
    <td width="10%" align="center"><code>little</code></td>
    <td width="10%" align="center">signed</td>
    <td width="15%">8,16,32,64</td>
  </tr>
  <tr>
    <td width="18%"><code>little_uint</code><i><b>n</b></i><code>_</code><code>buf_at</code></td>
    <td width="49%" align="center"><code>yes</code></td>
    <td width="10%" align="center"><code>little</code></td>
    <td width="10%" align="center">unsigned</td>
    <td width="15%">8,16,32,64</td>
  </tr>
</table>
</blockquote>
<p>The unaligned types do not cause compilers to insert padding bytes in classes 
and structs. This is an important characteristic that can be exploited to minimize wasted space in 
memory, files, and network transmissions. </p>
<p><font color="#FF0000"><b><i><span style="background-color: #FFFFFF">Warning:</span></i></b></font><span style="background-color: #FFFFFF"> 
Code that uses a</span>ligned types is possibly non-portable because alignment 
requirements vary between hardware architectures and because alignment may be 
affected by compiler switches or pragmas. For example, alignment of an 64-bit 
integer may be to a 32-bit boundary on a 32-bit machine and to a 64-bit boundary 
on a 64-bit machine. Furthermore, aligned types 
are only available on architectures with 8, 16, 32, and 64-bit integer types. </p>
<p><i><b>Recommendation:</b></i> Prefer unaligned buffer types.</p>
<p><i><b>Recommendation:</b></i> Protect yourself against alignment ills. For 
example:</p>
<blockquote>
  <pre>static_assert(sizeof(containing_struct) == 12, &quot;sizeof(containing_struct) is wrong&quot;); </pre>
</blockquote>
<p><b><i>Note:</i></b> One-byte big and little buffer types 
have identical layout on all platforms, so they never actually reverse endianness. They are provided to enable generic code, and 
to improve code readability and searchability.</p>
<h2><a name="Class_template_endian">Class template <code>endian</code></a><code>_buffer</code></h2>
<p>An <code>endian_buffer</code> is an integer byte-holder with user-specified <a href="#endianness">
endianness</a>, value type, size, and <a href="#alignment">alignment</a>. The 
usual operations on integers are supplied.</p>
<h3><a name="Synopsis">Synopsis</a></h3>
<pre>namespace boost
{
  namespace endian
  {
    //  C++11 features emulated if not available
   
    enum class <a name="order">order</a>
    {
      big,                             // big-endian
      little,                          // little-endian
      native = <b><i>implementation-defined</i></b>  // same as order::big or order::little<b><i>
    </i></b>};

    enum class <a name="alignment">align</a> {no, yes};            

    template &lt;order Order, class T, std::size_t Nbits,
      align Align = align::no&gt;
    class endian_buffer
    {
    public:
      typedef T value_type;

      <a href="#endian">endian_buffer</a>() noexcept = default;
      explicit <a href="#explicit-endian">endian_buffer</a>(T v) noexcept;

      endian_buffer&amp; <a href="#operator-eq">operator=</a>(T v) noexcept;
      value_type     <a href="#value">value</a>() const noexcept;
      const char*    <a href="#data">data</a>() const noexcept;
    protected:
      <b><i>implementaton-defined</i></b>  endian_value;  // for exposition only
    };
    
    //  stream inserter
    template &lt;class charT, class traits, order Order, class T,
      std::size_t n_bits, align Align&gt;
    std::basic_ostream&lt;charT, traits&gt;&amp;
      <a href="#inserter">operator&lt;&lt;</a>(std::basic_ostream&lt;charT, traits&gt;&amp; os,
        const endian_buffer&lt;Order, T, n_bits, Align&gt;&amp; x);

    //  stream extractor 
    template &lt;class charT, class traits, order Order, class T,
      std::size_t n_bits, align A&gt;
    std::basic_istream&lt;charT, traits&gt;&amp;
      <a href="#extractor">operator&gt;&gt;</a>(std::basic_istream&lt;charT, traits&gt;&amp; is,
        endian_buffer&lt;Order, T, n_bits, Align&gt;&amp; x);

    // typedefs  

    // unaligned big endian signed integer buffers
    typedef endian_buffer&lt;order::big, int_least8_t, 8&gt;        big_int8_buf_t;
    typedef endian_buffer&lt;order::big, int_least16_t, 16&gt;      big_int16_buf_t;
    typedef endian_buffer&lt;order::big, int_least32_t, 24&gt;      big_int24_buf_t;
    typedef endian_buffer&lt;order::big, int_least32_t, 32&gt;      big_int32_buf_t;
    typedef endian_buffer&lt;order::big, int_least64_t, 40&gt;      big_int40_buf_t;
    typedef endian_buffer&lt;order::big, int_least64_t, 48&gt;      big_int48_buf_t;
    typedef endian_buffer&lt;order::big, int_least64_t, 56&gt;      big_int56_buf_t;
    typedef endian_buffer&lt;order::big, int_least64_t, 64&gt;      big_int64_buf_t;
  
    // unaligned big endian unsigned integer buffers
    typedef endian_buffer&lt;order::big, uint_least8_t, 8&gt;       big_uint8_buf_t;
    typedef endian_buffer&lt;order::big, uint_least16_t, 16&gt;     big_uint16_buf_t;
    typedef endian_buffer&lt;order::big, uint_least32_t, 24&gt;     big_uint24_buf_t;
    typedef endian_buffer&lt;order::big, uint_least32_t, 32&gt;     big_uint32_buf_t;
    typedef endian_buffer&lt;order::big, uint_least64_t, 40&gt;     big_uint40_buf_t;
    typedef endian_buffer&lt;order::big, uint_least64_t, 48&gt;     big_uint48_buf_t;
    typedef endian_buffer&lt;order::big, uint_least64_t, 56&gt;     big_uint56_buf_t;
    typedef endian_buffer&lt;order::big, uint_least64_t, 64&gt;     big_uint64_buf_t;
  
    // unaligned little endian signed integer buffers
    typedef endian_buffer&lt;order::little, int_least8_t, 8&gt;     little_int8_buf_t;
    typedef endian_buffer&lt;order::little, int_least16_t, 16&gt;   little_int16_buf_t;
    typedef endian_buffer&lt;order::little, int_least32_t, 24&gt;   little_int24_buf_t;
    typedef endian_buffer&lt;order::little, int_least32_t, 32&gt;   little_int32_buf_t;
    typedef endian_buffer&lt;order::little, int_least64_t, 40&gt;   little_int40_buf_t;
    typedef endian_buffer&lt;order::little, int_least64_t, 48&gt;   little_int48_buf_t;
    typedef endian_buffer&lt;order::little, int_least64_t, 56&gt;   little_int56_buf_t;
    typedef endian_buffer&lt;order::little, int_least64_t, 64&gt;   little_int64_buf_t;
  
    // unaligned little endian unsigned integer buffers
    typedef endian_buffer&lt;order::little, uint_least8_t, 8&gt;    little_uint8_buf_t;
    typedef endian_buffer&lt;order::little, uint_least16_t, 16&gt;  little_uint16_buf_t;
    typedef endian_buffer&lt;order::little, uint_least32_t, 24&gt;  little_uint24_buf_t;
    typedef endian_buffer&lt;order::little, uint_least32_t, 32&gt;  little_uint32_buf_t;
    typedef endian_buffer&lt;order::little, uint_least64_t, 40&gt;  little_uint40_buf_t;
    typedef endian_buffer&lt;order::little, uint_least64_t, 48&gt;  little_uint48_buf_t;
    typedef endian_buffer&lt;order::little, uint_least64_t, 56&gt;  little_uint56_buf_t;
    typedef endian_buffer&lt;order::little, uint_least64_t, 64&gt;  little_uint64_buf_t;
  
    // unaligned native endian signed integer types
    typedef <b><i>implementation-defined</i></b>_int8_buf_t   native_int8_buf_t;
    typedef <b><i>implementation-defined</i></b>_int16_buf_t  native_int16_buf_t;
    typedef <b><i>implementation-defined</i></b>_int24_buf_t  native_int24_buf_t;
    typedef <b><i>implementation-defined</i></b>_int32_buf_t  native_int32_buf_t;
    typedef <b><i>implementation-defined</i></b>_int40_buf_t  native_int40_buf_t;
    typedef <b><i>implementation-defined</i></b>_int48_buf_t  native_int48_buf_t;
    typedef <b><i>implementation-defined</i></b>_int56_buf_t  native_int56_buf_t;
    typedef <b><i>implementation-defined</i></b>_int64_buf_t  native_int64_buf_t;

    // unaligned native endian unsigned integer types
    typedef <b><i>implementation-defined</i></b>_uint8_buf_t   native_uint8_buf_t;
    typedef <b><i>implementation-defined</i></b>_uint16_buf_t  native_uint16_buf_t;
    typedef <b><i>implementation-defined</i></b>_uint24_buf_t  native_uint24_buf_t;
    typedef <b><i>implementation-defined</i></b>_uint32_buf_t  native_uint32_buf_t;
    typedef <b><i>implementation-defined</i></b>_uint40_buf_t  native_uint40_buf_t;
    typedef <b><i>implementation-defined</i></b>_uint48_buf_t  native_uint48_buf_t;
    typedef <b><i>implementation-defined</i></b>_uint56_buf_t  native_uint56_buf_t;
    typedef <b><i>implementation-defined</i></b>_uint64_buf_t  native_uint64_buf_t;
    
    // aligned big endian signed integer buffers
    typedef endian_buffer&lt;order::big, int8_t, 8, align::yes&gt;       big_int8_buf_at;
    typedef endian_buffer&lt;order::big, int16_t, 16, align::yes&gt;     big_int16_buf_at;
    typedef endian_buffer&lt;order::big, int32_t, 32, align::yes&gt;     big_int32_buf_at;
    typedef endian_buffer&lt;order::big, int64_t, 64, align::yes&gt;     big_int64_buf_at;
  
    // aligned big endian unsigned integer buffers
    typedef endian_buffer&lt;order::big, uint8_t, 8, align::yes&gt;      big_uint8_buf_at;
    typedef endian_buffer&lt;order::big, uint16_t, 16, align::yes&gt;    big_uint16_buf_at;
    typedef endian_buffer&lt;order::big, uint32_t, 32, align::yes&gt;    big_uint32_buf_at;
    typedef endian_buffer&lt;order::big, uint64_t, 64, align::yes&gt;    big_uint64_buf_at;
  
    // aligned little endian signed integer buffers
    typedef endian_buffer&lt;order::little, int8_t, 8, align::yes&gt;    little_int8_buf_at;
    typedef endian_buffer&lt;order::little, int16_t, 16, align::yes&gt;  little_int16_buf_at;
    typedef endian_buffer&lt;order::little, int32_t, 32, align::yes&gt;  little_int32_buf_at;
    typedef endian_buffer&lt;order::little, int64_t, 64, align::yes&gt;  little_int64_buf_at;
  
    // aligned little endian unsigned integer buffers
    typedef endian_buffer&lt;order::little, uint8_t, 8, align::yes&gt;   little_uint8_buf_at;
    typedef endian_buffer&lt;order::little, uint16_t, 16, align::yes&gt; little_uint16_buf_at;
    typedef endian_buffer&lt;order::little, uint32_t, 32, align::yes&gt; little_uint32_buf_at;
    typedef endian_buffer&lt;order::little, uint64_t, 64, align::yes&gt; little_uint64_buf_at;

    // aligned native endian typedefs are not provided because
    // &lt;cstdint&gt; types are superior for this use case
  
  } // namespace endian
} // namespace boost</pre>
<p>The <i><b><code>implementation-defined</code></b></i> text in typedefs above is either
<code>big</code> or <code>little</code> according to the native endianness of the 
platform.</p>
<p>The expository data member <code>endian_value</code> stores the current value 
of an <code>endian_value</code> object as a sequence of bytes ordered as 
specified by the <code>Order</code> template parameter.&nbsp; The <i><b><code>
implementation-defined</code></b></i> type of <code>endian_value</code> is a 
type such as <code><span style="font-size: 85%">char[Nbits/CHAR_BIT]</span></code> 
or <code><span style="font-size: 85%">T</span></code> that meets the 
requirements imposed by the <code>Nbits</code> and <code>Align</code> template 
parameters.&nbsp; The <code><span style="font-size: 85%">CHAR_BIT</span></code> 
macro is defined in <code><span style="font-size: 85%">&lt;climits&gt;</span></code>. 
The only value of <code><span style="font-size: 85%">CHAR_BIT</span></code> that 
is required to be supported is 8.</p>
<p>Template parameter <code><span style="font-size: 85%">T</span></code> is 
required to be a standard integer type (C++std, 3.9.1) and <code>
<span style="font-size: 85%">sizeof(T)*CHAR_BIT</span></code> is required to be 
greater or equal to <span style="font-size: 85%"> <code>Nbits</code>.</span></p>
<h3><a name="Members">Members</a></h3>
  <pre><code><a name="endian">endian</a>_buffer() noexcept = default;</code></pre>
<blockquote>
<p><i>Effects:</i> Constructs an uninitialized object of type <code>endian_buffer&lt;Order, T, 
Nbits, Align&gt;</code>.</p>
</blockquote>
<pre><code>explicit <a name="explicit-endian">endian</a>_buffer(T v) noexcept;</code></pre>
<blockquote>
<p><i>Effects:</i> Constructs an object of type <code>endian_buffer&lt;Order, T, 
Nbits, Align&gt;</code>.</p>
<p><i>Postcondition:</i> <code>value() == v &amp; mask</code>, where <code>mask</code> 
is a constant of type <code>value_type</code> with <code>Nbits</code> low-order 
bits set to one.</p>
<p><i>Remarks:</i> If <code>Align</code> is <code>align::yes</code> then 
endianness conversion, if required, is performed by <code>
boost::endian::endian_reverse</code>.</p>
</blockquote>
<pre><code>endian_buffer&amp; <a name="operator-eq">operator=</a>(T v) noexcept;</code></pre>
<blockquote>
  <p><i>Postcondition:</i> <code>value() == v &amp; mask</code>, where <code>mask</code> 
  is a constant of type <code>value_type</code> with <code>Nbits</code> 
  low-order bits set to one.</p>
  <p><i>Returns:</i> <code>*this</code>.</p>
<p><i>Remarks:</i> If <code>Align</code> is <code>align::yes</code> then 
endianness conversion, if required, is performed by <code>
boost::endian::endian_reverse</code>.</p>
</blockquote>
<pre>value_type <a name="value">value</a>()<code> const noexcept;</code></pre>
<blockquote>
<p><i>Returns:</i> <code>endian_value</code>, converted to <code>value_type</code>, 
if required, and having the endianness of the native platform.</p>
<p><i>Remarks:</i> If <code>Align</code> is <code>align::yes</code> then 
endianness conversion, if required, is performed by <code>
boost::endian::endian_reverse</code>.</p>
</blockquote>
<pre><code>const char* <a name="data">data</a>() const noexcept;</code></pre>
<blockquote>
<p><i>Returns:</i> A pointer to the first byte of <code>endian_value</code>.</p>
</blockquote>
<h3><a name="Non-member-functions">Non-member functions</a></h3>
<pre>template &lt;class charT, class traits, order Order, class T,
  std::size_t n_bits, align Align&gt;
std::basic_ostream&lt;charT, traits&gt;&amp; <a name="inserter">operator&lt;&lt;</a>(std::basic_ostream&lt;charT, traits&gt;&amp; os,
  const endian_buffer&lt;Order, T, n_bits, Align&gt;&amp; x);
</pre>
<blockquote>
  <p><i>Returns:</i> <code>os &lt;&lt; x.value()</code>.</p>
</blockquote>
<pre>template &lt;class charT, class traits, order Order, class T,
  std::size_t n_bits, align A&gt;
std::basic_istream&lt;charT, traits&gt;&amp; <a name="extractor">operator&gt;&gt;</a>(std::basic_istream&lt;charT, traits&gt;&amp; is,
  endian_buffer&lt;Order, T, n_bits, Align&gt;&amp; x);
</pre>
<blockquote>
  <p><i>Effects: </i>As if:</p>
  <blockquote>
    <pre>T i;
if (is &gt;&gt; i)
  x = i;
</pre>
  </blockquote>
  <p><i>Returns:</i> <code>is</code>.</p>
</blockquote>
<h2><a name="FAQ">FAQ</a></h2>

<p>See the <a href="index.html#FAQ">Endian home page</a> FAQ for a library-wide 
FAQ.</p>

<p><b>Why not just use Boost.Serialization?</b> Serialization involves a 
conversion for every object involved in I/O. Endian integers require no 
conversion or copying. They are already in the desired format for binary I/O. 
Thus they can be read or written in bulk.</p>
<p><b>Are endian types PODs?</b> Yes for C++11. No for C++03, although several
<a href="#Compilation">macros</a> are available to force PODness in all cases.</p>
<p><b>What are the implications of endian integer types not being PODs with C++03 
compilers?</b> They 
can't be used in unions. Also, compilers aren't required to align or lay 
out storage in portable ways, although this potential problem hasn't prevented 
use of Boost.Endian with 
real compilers.</p>
<p><b>What good is <i>native </i>endianness?</b> It  provides alignment and 
size guarantees not available from the built-in types. It eases generic 
programming.</p>
<p><b>Why bother with the aligned endian types?</b> Aligned integer operations 
may be faster (as much as 10 to 20 times faster) if the endianness and alignment of 
the type matches the endianness and alignment requirements of the machine. The code, 
however, is 
likely to be somewhat less portable than with the unaligned types.</p>
<p><b>Why provide the arithmetic operations?</b> Providing a full set of operations reduces program 
clutter and makes code both easier to write and to read. Consider 
incrementing a variable in a record. It is very convenient to write:</p>
<pre wrap>    ++record.foo;</pre>
<p wrap>Rather than:</p>
<pre wrap>    int temp(record.foo);
    ++temp;
    record.foo = temp;</pre>
<h2><a name="Design">Design</a> considerations for Boost.Endian buffers</h2>
<ul>
  <li>Must be suitable for I/O - in other words, must be memcpyable.</li>
  <li>Must provide exactly the size and internal byte ordering specified.</li>
  <li>Must work correctly when the internal integer representation has more bits 
  that the sum of the bits in the external byte representation. Sign extension 
  must work correctly when the internal integer representation type has more 
  bits than the sum of the bits in the external bytes. For example, using 
  a 64-bit integer internally to represent 40-bit (5 byte) numbers must work for 
  both positive and negative values.</li>
  <li>Must work correctly (including using the same defined external 
  representation) regardless of whether a compiler treats char as signed or 
  unsigned.</li>
  <li>Unaligned types must not cause compilers to insert padding bytes.</li>
  <li>The implementation should supply optimizations with great care. Experience has shown that optimizations of endian 
  integers often become pessimizations when changing 
  machines or compilers. Pessimizations can also happen when changing compiler switches, 
  compiler versions, or CPU models of the same architecture.</li>
</ul>
<h2><a name="C++0x">C++11</a></h2>
<p>The availability of the C++11
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm">
Defaulted Functions</a> feature is detected automatically, and will be used if 
present to ensure that objects of <code>class endian_buffer</code> are trivial, and 
thus PODs.</p>
<h2><a name="Compilation">Compilation</a></h2>
<p>Boost.Endian is implemented entirely within headers, with no need to link to 
any Boost object libraries.</p>
<p>Several macros allow user control over features:</p>
<ul>
  <li>BOOST_ENDIAN_NO_CTORS causes <code>class endian_buffer</code> to have no 
  constructors. The intended use is for compiling user code that must be 
  portable between compilers regardless of C++11
  <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm">
  Defaulted Functions</a> support. Use of constructors will always fail, <br>
&nbsp;</li>
  <li>BOOST_ENDIAN_FORCE_PODNESS causes BOOST_ENDIAN_NO_CTORS to be defined if 
  the compiler does not support C++11
  <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm">
  Defaulted Functions</a>. This is ensures that objects of <code>class endian_buffer</code> 
  are PODs, and so can be used in C++03 unions. 
  In C++11, <code>class endian_buffer</code> objects are PODs, even though they have 
  constructors, so can always be used in unions.</li>
</ul>
<hr>
<p>Last revised:
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->25 March, 2015<!--webbot bot="Timestamp" endspan i-checksum="28920" --></p>
<p>© Copyright Beman Dawes, 2006-2009, 2013</p>
<p>Distributed under the Boost Software License, Version 1.0. See
<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/ LICENSE_1_0.txt</a></p>

</body>

</html>