Botan  1.10.9
loadstor.h
Go to the documentation of this file.
1 /*
2 * Load/Store Operators
3 * (C) 1999-2007 Jack Lloyd
4 * 2007 Yves Jerschow
5 *
6 * Distributed under the terms of the Botan license
7 */
8 
9 #ifndef BOTAN_LOAD_STORE_H__
10 #define BOTAN_LOAD_STORE_H__
11 
12 #include <botan/types.h>
13 #include <botan/bswap.h>
14 #include <botan/get_byte.h>
15 #include <cstring>
16 
17 #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
18 
19 #if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
20 
21 #define BOTAN_ENDIAN_N2B(x) (x)
22 #define BOTAN_ENDIAN_B2N(x) (x)
23 
24 #define BOTAN_ENDIAN_N2L(x) reverse_bytes(x)
25 #define BOTAN_ENDIAN_L2N(x) reverse_bytes(x)
26 
27 #elif defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
28 
29 #define BOTAN_ENDIAN_N2L(x) (x)
30 #define BOTAN_ENDIAN_L2N(x) (x)
31 
32 #define BOTAN_ENDIAN_N2B(x) reverse_bytes(x)
33 #define BOTAN_ENDIAN_B2N(x) reverse_bytes(x)
34 
35 #endif
36 
37 #endif
38 
39 namespace Botan {
40 
41 /**
42 * Make a u16bit from two bytes
43 * @param i0 the first byte
44 * @param i1 the second byte
45 * @return i0 || i1
46 */
47 inline u16bit make_u16bit(byte i0, byte i1)
48  {
49  return ((static_cast<u16bit>(i0) << 8) | i1);
50  }
51 
52 /**
53 * Make a u32bit from four bytes
54 * @param i0 the first byte
55 * @param i1 the second byte
56 * @param i2 the third byte
57 * @param i3 the fourth byte
58 * @return i0 || i1 || i2 || i3
59 */
60 inline u32bit make_u32bit(byte i0, byte i1, byte i2, byte i3)
61  {
62  return ((static_cast<u32bit>(i0) << 24) |
63  (static_cast<u32bit>(i1) << 16) |
64  (static_cast<u32bit>(i2) << 8) |
65  (static_cast<u32bit>(i3)));
66  }
67 
68 /**
69 * Make a u32bit from eight bytes
70 * @param i0 the first byte
71 * @param i1 the second byte
72 * @param i2 the third byte
73 * @param i3 the fourth byte
74 * @param i4 the fifth byte
75 * @param i5 the sixth byte
76 * @param i6 the seventh byte
77 * @param i7 the eighth byte
78 * @return i0 || i1 || i2 || i3 || i4 || i5 || i6 || i7
79 */
80 inline u64bit make_u64bit(byte i0, byte i1, byte i2, byte i3,
81  byte i4, byte i5, byte i6, byte i7)
82  {
83  return ((static_cast<u64bit>(i0) << 56) |
84  (static_cast<u64bit>(i1) << 48) |
85  (static_cast<u64bit>(i2) << 40) |
86  (static_cast<u64bit>(i3) << 32) |
87  (static_cast<u64bit>(i4) << 24) |
88  (static_cast<u64bit>(i5) << 16) |
89  (static_cast<u64bit>(i6) << 8) |
90  (static_cast<u64bit>(i7)));
91  }
92 
93 /**
94 * Load a big-endian word
95 * @param in a pointer to some bytes
96 * @param off an offset into the array
97 * @return off'th T of in, as a big-endian value
98 */
99 template<typename T>
100 inline T load_be(const byte in[], size_t off)
101  {
102  in += off * sizeof(T);
103  T out = 0;
104  for(size_t i = 0; i != sizeof(T); ++i)
105  out = (out << 8) | in[i];
106  return out;
107  }
108 
109 /**
110 * Load a little-endian word
111 * @param in a pointer to some bytes
112 * @param off an offset into the array
113 * @return off'th T of in, as a litte-endian value
114 */
115 template<typename T>
116 inline T load_le(const byte in[], size_t off)
117  {
118  in += off * sizeof(T);
119  T out = 0;
120  for(size_t i = 0; i != sizeof(T); ++i)
121  out = (out << 8) | in[sizeof(T)-1-i];
122  return out;
123  }
124 
125 /**
126 * Load a big-endian u16bit
127 * @param in a pointer to some bytes
128 * @param off an offset into the array
129 * @return off'th u16bit of in, as a big-endian value
130 */
131 template<>
132 inline u16bit load_be<u16bit>(const byte in[], size_t off)
133  {
134 #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
135  return BOTAN_ENDIAN_N2B(*(reinterpret_cast<const u16bit*>(in) + off));
136 #else
137  in += off * sizeof(u16bit);
138  return make_u16bit(in[0], in[1]);
139 #endif
140  }
141 
142 /**
143 * Load a little-endian u16bit
144 * @param in a pointer to some bytes
145 * @param off an offset into the array
146 * @return off'th u16bit of in, as a little-endian value
147 */
148 template<>
149 inline u16bit load_le<u16bit>(const byte in[], size_t off)
150  {
151 #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
152  return BOTAN_ENDIAN_N2L(*(reinterpret_cast<const u16bit*>(in) + off));
153 #else
154  in += off * sizeof(u16bit);
155  return make_u16bit(in[1], in[0]);
156 #endif
157  }
158 
159 /**
160 * Load a big-endian u32bit
161 * @param in a pointer to some bytes
162 * @param off an offset into the array
163 * @return off'th u32bit of in, as a big-endian value
164 */
165 template<>
166 inline u32bit load_be<u32bit>(const byte in[], size_t off)
167  {
168 #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
169  return BOTAN_ENDIAN_N2B(*(reinterpret_cast<const u32bit*>(in) + off));
170 #else
171  in += off * sizeof(u32bit);
172  return make_u32bit(in[0], in[1], in[2], in[3]);
173 #endif
174  }
175 
176 /**
177 * Load a little-endian u32bit
178 * @param in a pointer to some bytes
179 * @param off an offset into the array
180 * @return off'th u32bit of in, as a little-endian value
181 */
182 template<>
183 inline u32bit load_le<u32bit>(const byte in[], size_t off)
184  {
185 #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
186  return BOTAN_ENDIAN_N2L(*(reinterpret_cast<const u32bit*>(in) + off));
187 #else
188  in += off * sizeof(u32bit);
189  return make_u32bit(in[3], in[2], in[1], in[0]);
190 #endif
191  }
192 
193 /**
194 * Load a big-endian u64bit
195 * @param in a pointer to some bytes
196 * @param off an offset into the array
197 * @return off'th u64bit of in, as a big-endian value
198 */
199 template<>
200 inline u64bit load_be<u64bit>(const byte in[], size_t off)
201  {
202 #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
203  return BOTAN_ENDIAN_N2B(*(reinterpret_cast<const u64bit*>(in) + off));
204 #else
205  in += off * sizeof(u64bit);
206  return make_u64bit(in[0], in[1], in[2], in[3],
207  in[4], in[5], in[6], in[7]);
208 #endif
209  }
210 
211 /**
212 * Load a little-endian u64bit
213 * @param in a pointer to some bytes
214 * @param off an offset into the array
215 * @return off'th u64bit of in, as a little-endian value
216 */
217 template<>
218 inline u64bit load_le<u64bit>(const byte in[], size_t off)
219  {
220 #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
221  return BOTAN_ENDIAN_N2L(*(reinterpret_cast<const u64bit*>(in) + off));
222 #else
223  in += off * sizeof(u64bit);
224  return make_u64bit(in[7], in[6], in[5], in[4],
225  in[3], in[2], in[1], in[0]);
226 #endif
227  }
228 
229 /**
230 * Load two little-endian words
231 * @param in a pointer to some bytes
232 * @param x0 where the first word will be written
233 * @param x1 where the second word will be written
234 */
235 template<typename T>
236 inline void load_le(const byte in[], T& x0, T& x1)
237  {
238  x0 = load_le<T>(in, 0);
239  x1 = load_le<T>(in, 1);
240  }
241 
242 /**
243 * Load four little-endian words
244 * @param in a pointer to some bytes
245 * @param x0 where the first word will be written
246 * @param x1 where the second word will be written
247 * @param x2 where the third word will be written
248 * @param x3 where the fourth word will be written
249 */
250 template<typename T>
251 inline void load_le(const byte in[],
252  T& x0, T& x1, T& x2, T& x3)
253  {
254  x0 = load_le<T>(in, 0);
255  x1 = load_le<T>(in, 1);
256  x2 = load_le<T>(in, 2);
257  x3 = load_le<T>(in, 3);
258  }
259 
260 /**
261 * Load eight little-endian words
262 * @param in a pointer to some bytes
263 * @param x0 where the first word will be written
264 * @param x1 where the second word will be written
265 * @param x2 where the third word will be written
266 * @param x3 where the fourth word will be written
267 * @param x4 where the fifth word will be written
268 * @param x5 where the sixth word will be written
269 * @param x6 where the seventh word will be written
270 * @param x7 where the eighth word will be written
271 */
272 template<typename T>
273 inline void load_le(const byte in[],
274  T& x0, T& x1, T& x2, T& x3,
275  T& x4, T& x5, T& x6, T& x7)
276  {
277  x0 = load_le<T>(in, 0);
278  x1 = load_le<T>(in, 1);
279  x2 = load_le<T>(in, 2);
280  x3 = load_le<T>(in, 3);
281  x4 = load_le<T>(in, 4);
282  x5 = load_le<T>(in, 5);
283  x6 = load_le<T>(in, 6);
284  x7 = load_le<T>(in, 7);
285  }
286 
287 /**
288 * Load a variable number of little-endian words
289 * @param out the output array of words
290 * @param in the input array of bytes
291 * @param count how many words are in in
292 */
293 template<typename T>
294 inline void load_le(T out[],
295  const byte in[],
296  size_t count)
297  {
298 #if defined(BOTAN_TARGET_CPU_HAS_KNOWN_ENDIANNESS)
299  std::memcpy(out, in, sizeof(T)*count);
300 
301 #if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
302  const size_t blocks = count - (count % 4);
303  const size_t left = count - blocks;
304 
305  for(size_t i = 0; i != blocks; i += 4)
306  bswap_4(out + i);
307 
308  for(size_t i = 0; i != left; ++i)
309  out[blocks+i] = reverse_bytes(out[blocks+i]);
310 #endif
311 
312 #else
313  for(size_t i = 0; i != count; ++i)
314  out[i] = load_le<T>(in, i);
315 #endif
316  }
317 
318 /**
319 * Load two big-endian words
320 * @param in a pointer to some bytes
321 * @param x0 where the first word will be written
322 * @param x1 where the second word will be written
323 */
324 template<typename T>
325 inline void load_be(const byte in[], T& x0, T& x1)
326  {
327  x0 = load_be<T>(in, 0);
328  x1 = load_be<T>(in, 1);
329  }
330 
331 /**
332 * Load four big-endian words
333 * @param in a pointer to some bytes
334 * @param x0 where the first word will be written
335 * @param x1 where the second word will be written
336 * @param x2 where the third word will be written
337 * @param x3 where the fourth word will be written
338 */
339 template<typename T>
340 inline void load_be(const byte in[],
341  T& x0, T& x1, T& x2, T& x3)
342  {
343  x0 = load_be<T>(in, 0);
344  x1 = load_be<T>(in, 1);
345  x2 = load_be<T>(in, 2);
346  x3 = load_be<T>(in, 3);
347  }
348 
349 /**
350 * Load eight big-endian words
351 * @param in a pointer to some bytes
352 * @param x0 where the first word will be written
353 * @param x1 where the second word will be written
354 * @param x2 where the third word will be written
355 * @param x3 where the fourth word will be written
356 * @param x4 where the fifth word will be written
357 * @param x5 where the sixth word will be written
358 * @param x6 where the seventh word will be written
359 * @param x7 where the eighth word will be written
360 */
361 template<typename T>
362 inline void load_be(const byte in[],
363  T& x0, T& x1, T& x2, T& x3,
364  T& x4, T& x5, T& x6, T& x7)
365  {
366  x0 = load_be<T>(in, 0);
367  x1 = load_be<T>(in, 1);
368  x2 = load_be<T>(in, 2);
369  x3 = load_be<T>(in, 3);
370  x4 = load_be<T>(in, 4);
371  x5 = load_be<T>(in, 5);
372  x6 = load_be<T>(in, 6);
373  x7 = load_be<T>(in, 7);
374  }
375 
376 /**
377 * Load a variable number of big-endian words
378 * @param out the output array of words
379 * @param in the input array of bytes
380 * @param count how many words are in in
381 */
382 template<typename T>
383 inline void load_be(T out[],
384  const byte in[],
385  size_t count)
386  {
387 #if defined(BOTAN_TARGET_CPU_HAS_KNOWN_ENDIANNESS)
388  std::memcpy(out, in, sizeof(T)*count);
389 
390 #if defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
391  const size_t blocks = count - (count % 4);
392  const size_t left = count - blocks;
393 
394  for(size_t i = 0; i != blocks; i += 4)
395  bswap_4(out + i);
396 
397  for(size_t i = 0; i != left; ++i)
398  out[blocks+i] = reverse_bytes(out[blocks+i]);
399 #endif
400 
401 #else
402  for(size_t i = 0; i != count; ++i)
403  out[i] = load_be<T>(in, i);
404 #endif
405  }
406 
407 /**
408 * Store a big-endian u16bit
409 * @param in the input u16bit
410 * @param out the byte array to write to
411 */
412 inline void store_be(u16bit in, byte out[2])
413  {
414 #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
415  *reinterpret_cast<u16bit*>(out) = BOTAN_ENDIAN_B2N(in);
416 #else
417  out[0] = get_byte(0, in);
418  out[1] = get_byte(1, in);
419 #endif
420  }
421 
422 /**
423 * Store a little-endian u16bit
424 * @param in the input u16bit
425 * @param out the byte array to write to
426 */
427 inline void store_le(u16bit in, byte out[2])
428  {
429 #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
430  *reinterpret_cast<u16bit*>(out) = BOTAN_ENDIAN_L2N(in);
431 #else
432  out[0] = get_byte(1, in);
433  out[1] = get_byte(0, in);
434 #endif
435  }
436 
437 /**
438 * Store a big-endian u32bit
439 * @param in the input u32bit
440 * @param out the byte array to write to
441 */
442 inline void store_be(u32bit in, byte out[4])
443  {
444 #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
445  *reinterpret_cast<u32bit*>(out) = BOTAN_ENDIAN_B2N(in);
446 #else
447  out[0] = get_byte(0, in);
448  out[1] = get_byte(1, in);
449  out[2] = get_byte(2, in);
450  out[3] = get_byte(3, in);
451 #endif
452  }
453 
454 /**
455 * Store a little-endian u32bit
456 * @param in the input u32bit
457 * @param out the byte array to write to
458 */
459 inline void store_le(u32bit in, byte out[4])
460  {
461 #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
462  *reinterpret_cast<u32bit*>(out) = BOTAN_ENDIAN_L2N(in);
463 #else
464  out[0] = get_byte(3, in);
465  out[1] = get_byte(2, in);
466  out[2] = get_byte(1, in);
467  out[3] = get_byte(0, in);
468 #endif
469  }
470 
471 /**
472 * Store a big-endian u64bit
473 * @param in the input u64bit
474 * @param out the byte array to write to
475 */
476 inline void store_be(u64bit in, byte out[8])
477  {
478 #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
479  *reinterpret_cast<u64bit*>(out) = BOTAN_ENDIAN_B2N(in);
480 #else
481  out[0] = get_byte(0, in);
482  out[1] = get_byte(1, in);
483  out[2] = get_byte(2, in);
484  out[3] = get_byte(3, in);
485  out[4] = get_byte(4, in);
486  out[5] = get_byte(5, in);
487  out[6] = get_byte(6, in);
488  out[7] = get_byte(7, in);
489 #endif
490  }
491 
492 /**
493 * Store a little-endian u64bit
494 * @param in the input u64bit
495 * @param out the byte array to write to
496 */
497 inline void store_le(u64bit in, byte out[8])
498  {
499 #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
500  *reinterpret_cast<u64bit*>(out) = BOTAN_ENDIAN_L2N(in);
501 #else
502  out[0] = get_byte(7, in);
503  out[1] = get_byte(6, in);
504  out[2] = get_byte(5, in);
505  out[3] = get_byte(4, in);
506  out[4] = get_byte(3, in);
507  out[5] = get_byte(2, in);
508  out[6] = get_byte(1, in);
509  out[7] = get_byte(0, in);
510 #endif
511  }
512 
513 /**
514 * Store two little-endian words
515 * @param out the output byte array
516 * @param x0 the first word
517 * @param x1 the second word
518 */
519 template<typename T>
520 inline void store_le(byte out[], T x0, T x1)
521  {
522  store_le(x0, out + (0 * sizeof(T)));
523  store_le(x1, out + (1 * sizeof(T)));
524  }
525 
526 /**
527 * Store two big-endian words
528 * @param out the output byte array
529 * @param x0 the first word
530 * @param x1 the second word
531 */
532 template<typename T>
533 inline void store_be(byte out[], T x0, T x1)
534  {
535  store_be(x0, out + (0 * sizeof(T)));
536  store_be(x1, out + (1 * sizeof(T)));
537  }
538 
539 /**
540 * Store four little-endian words
541 * @param out the output byte array
542 * @param x0 the first word
543 * @param x1 the second word
544 * @param x2 the third word
545 * @param x3 the fourth word
546 */
547 template<typename T>
548 inline void store_le(byte out[], T x0, T x1, T x2, T x3)
549  {
550  store_le(x0, out + (0 * sizeof(T)));
551  store_le(x1, out + (1 * sizeof(T)));
552  store_le(x2, out + (2 * sizeof(T)));
553  store_le(x3, out + (3 * sizeof(T)));
554  }
555 
556 /**
557 * Store four big-endian words
558 * @param out the output byte array
559 * @param x0 the first word
560 * @param x1 the second word
561 * @param x2 the third word
562 * @param x3 the fourth word
563 */
564 template<typename T>
565 inline void store_be(byte out[], T x0, T x1, T x2, T x3)
566  {
567  store_be(x0, out + (0 * sizeof(T)));
568  store_be(x1, out + (1 * sizeof(T)));
569  store_be(x2, out + (2 * sizeof(T)));
570  store_be(x3, out + (3 * sizeof(T)));
571  }
572 
573 /**
574 * Store eight little-endian words
575 * @param out the output byte array
576 * @param x0 the first word
577 * @param x1 the second word
578 * @param x2 the third word
579 * @param x3 the fourth word
580 * @param x4 the fifth word
581 * @param x5 the sixth word
582 * @param x6 the seventh word
583 * @param x7 the eighth word
584 */
585 template<typename T>
586 inline void store_le(byte out[], T x0, T x1, T x2, T x3,
587  T x4, T x5, T x6, T x7)
588  {
589  store_le(x0, out + (0 * sizeof(T)));
590  store_le(x1, out + (1 * sizeof(T)));
591  store_le(x2, out + (2 * sizeof(T)));
592  store_le(x3, out + (3 * sizeof(T)));
593  store_le(x4, out + (4 * sizeof(T)));
594  store_le(x5, out + (5 * sizeof(T)));
595  store_le(x6, out + (6 * sizeof(T)));
596  store_le(x7, out + (7 * sizeof(T)));
597  }
598 
599 /**
600 * Store eight big-endian words
601 * @param out the output byte array
602 * @param x0 the first word
603 * @param x1 the second word
604 * @param x2 the third word
605 * @param x3 the fourth word
606 * @param x4 the fifth word
607 * @param x5 the sixth word
608 * @param x6 the seventh word
609 * @param x7 the eighth word
610 */
611 template<typename T>
612 inline void store_be(byte out[], T x0, T x1, T x2, T x3,
613  T x4, T x5, T x6, T x7)
614  {
615  store_be(x0, out + (0 * sizeof(T)));
616  store_be(x1, out + (1 * sizeof(T)));
617  store_be(x2, out + (2 * sizeof(T)));
618  store_be(x3, out + (3 * sizeof(T)));
619  store_be(x4, out + (4 * sizeof(T)));
620  store_be(x5, out + (5 * sizeof(T)));
621  store_be(x6, out + (6 * sizeof(T)));
622  store_be(x7, out + (7 * sizeof(T)));
623  }
624 
625 }
626 
627 #endif
T load_be(const byte in[], size_t off)
Definition: loadstor.h:100
T load_le(const byte in[], size_t off)
Definition: loadstor.h:116
void store_le(u16bit in, byte out[2])
Definition: loadstor.h:427
byte get_byte(size_t byte_num, T input)
Definition: get_byte.h:21
unsigned char byte
Definition: types.h:22
unsigned long long u64bit
Definition: types.h:49
u16bit load_be< u16bit >(const byte in[], size_t off)
Definition: loadstor.h:132
u32bit load_le< u32bit >(const byte in[], size_t off)
Definition: loadstor.h:183
unsigned short u16bit
Definition: types.h:27
void bswap_4(T x[4])
Definition: bswap.h:112
u32bit load_be< u32bit >(const byte in[], size_t off)
Definition: loadstor.h:166
u16bit load_le< u16bit >(const byte in[], size_t off)
Definition: loadstor.h:149
u64bit load_be< u64bit >(const byte in[], size_t off)
Definition: loadstor.h:200
void store_be(u16bit in, byte out[2])
Definition: loadstor.h:412
u16bit make_u16bit(byte i0, byte i1)
Definition: loadstor.h:47
u64bit make_u64bit(byte i0, byte i1, byte i2, byte i3, byte i4, byte i5, byte i6, byte i7)
Definition: loadstor.h:80
u32bit make_u32bit(byte i0, byte i1, byte i2, byte i3)
Definition: loadstor.h:60
unsigned int u32bit
Definition: types.h:32
u64bit load_le< u64bit >(const byte in[], size_t off)
Definition: loadstor.h:218
u16bit reverse_bytes(u16bit val)
Definition: bswap.h:24