Botan 1.10.17
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
39namespace 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*/
47inline 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*/
60inline 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*/
80inline 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*/
99template<typename T>
100inline 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*/
115template<typename T>
116inline 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*/
131template<>
132inline 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*/
148template<>
149inline 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*/
165template<>
166inline 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*/
182template<>
183inline 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*/
199template<>
200inline 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*/
217template<>
218inline 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*/
235template<typename T>
236inline 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*/
250template<typename T>
251inline 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*/
272template<typename T>
273inline 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*/
293template<typename T>
294inline 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*/
324template<typename T>
325inline 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*/
339template<typename T>
340inline 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*/
361template<typename T>
362inline 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*/
382template<typename T>
383inline 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*/
412inline 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*/
427inline 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*/
442inline 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*/
459inline 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*/
476inline 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*/
497inline 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*/
519template<typename T>
520inline 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*/
532template<typename T>
533inline 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*/
547template<typename T>
548inline 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*/
564template<typename T>
565inline 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*/
585template<typename T>
586inline 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*/
611template<typename T>
612inline 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
u16bit reverse_bytes(u16bit val)
Definition bswap.h:24
byte get_byte(size_t byte_num, T input)
Definition get_byte.h:21
T load_be(const byte in[], size_t off)
Definition loadstor.h:100
u64bit make_u64bit(byte i0, byte i1, byte i2, byte i3, byte i4, byte i5, byte i6, byte i7)
Definition loadstor.h:80
void bswap_4(T x[4])
Definition bswap.h:112
unsigned long long u64bit
Definition types.h:49
u32bit make_u32bit(byte i0, byte i1, byte i2, byte i3)
Definition loadstor.h:60
T load_le(const byte in[], size_t off)
Definition loadstor.h:116
u16bit make_u16bit(byte i0, byte i1)
Definition loadstor.h:47
unsigned int u32bit
Definition types.h:32
unsigned short u16bit
Definition types.h:27
void store_be(u16bit in, byte out[2])
Definition loadstor.h:412
void store_le(u16bit in, byte out[2])
Definition loadstor.h:427