1 /** 2 * Load/Store Operators 3 * 4 * Copyright: 5 * (C) 1999-2007 Jack Lloyd 6 * (C) 2014-2015 Etienne Cimon 7 * 2007 Yves Jerschow 8 * 9 * License: 10 * Botan is released under the Simplified BSD License (see LICENSE.md) 11 */ 12 module botan.utils.loadstor; 13 14 import botan.utils.types; 15 import botan.utils.bswap; 16 import botan.utils.get_byte; 17 import std.bitmanip; 18 19 20 /** 21 * Make a ushort from two bytes 22 * Params: 23 * i0 = the first ubyte 24 * i1 = the second ubyte 25 * Returns: i0 || i1 26 */ 27 ushort make_ushort(ubyte i0, ubyte i1) 28 { 29 return ((cast(ushort)(i0) << 8) | i1); 30 } 31 32 /** 33 * Make a uint from four bytes 34 * Params: 35 * i0 = the first ubyte 36 * i1 = the second ubyte 37 * i2 = the third ubyte 38 * i3 = the fourth ubyte 39 * Returns: i0 || i1 || i2 || i3 40 */ 41 uint make_uint(ubyte i0, ubyte i1, ubyte i2, ubyte i3) 42 { 43 return ((cast(uint)(i0) << 24) | 44 (cast(uint)(i1) << 16) | 45 (cast(uint)(i2) << 8) | 46 (cast(uint)(i3))); 47 } 48 49 /** 50 * Make a ulong from eight bytes 51 * Params: 52 * i0 = the first ubyte 53 * i1 = the second ubyte 54 * i2 = the third ubyte 55 * i3 = the fourth ubyte 56 * i4 = the fifth ubyte 57 * i5 = the sixth ubyte 58 * i6 = the seventh ubyte 59 * i7 = the eighth ubyte 60 * Returns: i0 || i1 || i2 || i3 || i4 || i5 || i6 || i7 61 */ 62 ulong make_ulong(ubyte i0, ubyte i1, ubyte i2, ubyte i3, 63 ubyte i4, ubyte i5, ubyte i6, ubyte i7) 64 { 65 return ((cast(ulong)(i0) << 56) | 66 (cast(ulong)(i1) << 48) | 67 (cast(ulong)(i2) << 40) | 68 (cast(ulong)(i3) << 32) | 69 (cast(ulong)(i4) << 24) | 70 (cast(ulong)(i5) << 16) | 71 (cast(ulong)(i6) << 8) | 72 (cast(ulong)(i7))); 73 } 74 75 /** 76 * Load a big-endian word 77 * Params: 78 * input = a pointer to some bytes 79 * off = an offset into the array 80 * Returns: off'th T of in, as a big-endian value 81 */ 82 T loadBigEndian(T)(const(ubyte)* input, size_t off) 83 { 84 input += off * T.sizeof; 85 T output = 0; 86 for (size_t i = 0; i != T.sizeof; ++i) 87 output = (output << 8) | input[i]; 88 return output; 89 } 90 91 /** 92 * Load a little-endian word 93 * Params: 94 * input = a pointer to some bytes 95 * off = an offset into the array 96 * Returns: off'th T of in, as a litte-endian value 97 */ 98 T loadLittleEndian(T)(const(ubyte)* input, size_t off) 99 { 100 input += off * T.sizeof; 101 T output = 0; 102 for (size_t i = 0; i != T.sizeof; ++i) 103 output = (output << 8) | input[T.sizeof-1-i]; 104 return output; 105 } 106 107 /** 108 * Load a big-endian ushort 109 * Params: 110 * input = a pointer to some bytes 111 * off = an offset into the array 112 * Returns: off'th ushort of in, as a big-endian value 113 */ 114 ushort loadBigEndian(T : ushort)(const(ubyte)* input, size_t off) 115 { 116 return *cast(ushort*) nativeToBigEndian!ushort(*( (cast(const ushort*) input) + off)); 117 } 118 119 /** 120 * Load a little-endian ushort 121 * Params: 122 * input = a pointer to some bytes 123 * off = an offset into the array 124 * Returns: off'th ushort of in, as a little-endian value 125 */ 126 ushort loadLittleEndian(T : ushort)(const(ubyte)* input, size_t off) 127 { 128 return *cast(ushort*) nativeToLittleEndian!ushort(*((cast(const ushort*) input) + off)); 129 } 130 131 /** 132 * Load a big-endian uint 133 * Params: 134 * input = a pointer to some bytes 135 * off = an offset into the array 136 * Returns: off'th uint of in, as a big-endian value 137 */ 138 uint loadBigEndian(T : uint)(const(ubyte)* input, size_t off) 139 { 140 return *cast(uint*) nativeToBigEndian!uint(*((cast(const uint*) input) + off)); 141 } 142 143 /** 144 * Load a little-endian uint 145 * Params: 146 * input = a pointer to some bytes 147 * off = an offset into the array 148 * Returns: off'th uint of in, as a little-endian value 149 */ 150 151 uint loadLittleEndian(T : uint)(const(ubyte)* input, size_t off) 152 { 153 return *cast(uint*) nativeToLittleEndian!uint(*( (cast(const uint*) input) + off)); 154 } 155 156 /** 157 * Load a big-endian ulong 158 * Params: 159 * input = a pointer to some bytes 160 * off = an offset into the array 161 * Returns: off'th ulong of in, as a big-endian value 162 */ 163 ulong loadBigEndian(T : ulong)(const(ubyte)* input, size_t off) 164 { 165 return *cast(ulong*) nativeToBigEndian!ulong(*( (cast(const ulong*) input) + off)); 166 167 } 168 169 /** 170 * Load a little-endian ulong 171 * Params: 172 * input = a pointer to some bytes 173 * off = an offset into the array 174 * Returns: off'th ulong of in, as a little-endian value 175 */ 176 ulong loadLittleEndian(T : ulong)(const(ubyte)* input, size_t off) 177 { 178 return *cast(ulong*) nativeToLittleEndian!ulong(*( (cast(const ulong*) input) + off)); 179 } 180 181 /** 182 * Load two little-endian words 183 * Params: 184 * input = a pointer to some bytes 185 * x0 = where the first word will be written 186 * x1 = where the second word will be written 187 */ 188 void loadLittleEndian(T)(const(ubyte)* input, ref T x0, ref T x1) 189 { 190 x0 = loadLittleEndian!T(input, 0); 191 x1 = loadLittleEndian!T(input, 1); 192 } 193 194 /** 195 * Load four little-endian words 196 * Params: 197 * input = a pointer to some bytes 198 * x0 = where the first word will be written 199 * x1 = where the second word will be written 200 * x2 = where the third word will be written 201 * x3 = where the fourth word will be written 202 */ 203 void loadLittleEndian(T)(const(ubyte)* input, 204 ref T x0, ref T x1, ref T x2, ref T x3) 205 { 206 x0 = loadLittleEndian!T(input, 0); 207 x1 = loadLittleEndian!T(input, 1); 208 x2 = loadLittleEndian!T(input, 2); 209 x3 = loadLittleEndian!T(input, 3); 210 } 211 212 /** 213 * Load eight little-endian words 214 * Params: 215 * input = a pointer to some bytes 216 * x0 = where the first word will be written 217 * x1 = where the second word will be written 218 * x2 = where the third word will be written 219 * x3 = where the fourth word will be written 220 * x4 = where the fifth word will be written 221 * x5 = where the sixth word will be written 222 * x6 = where the seventh word will be written 223 * x7 = where the eighth word will be written 224 */ 225 void loadLittleEndian(T)(const(ubyte)* input, 226 ref T x0, ref T x1, ref T x2, ref T x3, 227 ref T x4, ref T x5, ref T x6, ref T x7) 228 { 229 x0 = loadLittleEndian!T(input, 0); 230 x1 = loadLittleEndian!T(input, 1); 231 x2 = loadLittleEndian!T(input, 2); 232 x3 = loadLittleEndian!T(input, 3); 233 x4 = loadLittleEndian!T(input, 4); 234 x5 = loadLittleEndian!T(input, 5); 235 x6 = loadLittleEndian!T(input, 6); 236 x7 = loadLittleEndian!T(input, 7); 237 } 238 239 /** 240 * Load a variable number of little-endian words 241 * Params: 242 * output = the output array of words 243 * input = the input array of bytes 244 * count = how many words are in in 245 */ 246 void loadLittleEndian(T)(T* output, const(ubyte)* input, size_t count) 247 { 248 foreach (size_t i; 0 .. count) 249 output[i] = loadLittleEndian!T(input, i); 250 } 251 252 /** 253 * Load two big-endian words 254 * Params: 255 * input = a pointer to some bytes 256 * x0 = where the first word will be written 257 * x1 = where the second word will be written 258 */ 259 void loadBigEndian(T)(const(ubyte)* input, ref T x0, ref T x1) 260 { 261 x0 = loadBigEndian!T(input, 0); 262 x1 = loadBigEndian!T(input, 1); 263 } 264 265 /** 266 * Load four big-endian words 267 * Params: 268 * input = a pointer to some bytes 269 * x0 = where the first word will be written 270 * x1 = where the second word will be written 271 * x2 = where the third word will be written 272 * x3 = where the fourth word will be written 273 */ 274 void loadBigEndian(T)(const(ubyte)* input, ref T x0, ref T x1, ref T x2, ref T x3) 275 { 276 x0 = loadBigEndian!T(input, 0); 277 x1 = loadBigEndian!T(input, 1); 278 x2 = loadBigEndian!T(input, 2); 279 x3 = loadBigEndian!T(input, 3); 280 } 281 282 /** 283 * Load eight big-endian words 284 * Params: 285 * input = a pointer to some bytes 286 * x0 = where the first word will be written 287 * x1 = where the second word will be written 288 * x2 = where the third word will be written 289 * x3 = where the fourth word will be written 290 * x4 = where the fifth word will be written 291 * x5 = where the sixth word will be written 292 * x6 = where the seventh word will be written 293 * x7 = where the eighth word will be written 294 */ 295 void loadBigEndian(T)(const(ubyte)* input, 296 ref T x0, ref T x1, ref T x2, ref T x3, 297 ref T x4, ref T x5, ref T x6, ref T x7) 298 { 299 x0 = loadBigEndian!T(input, 0); 300 x1 = loadBigEndian!T(input, 1); 301 x2 = loadBigEndian!T(input, 2); 302 x3 = loadBigEndian!T(input, 3); 303 x4 = loadBigEndian!T(input, 4); 304 x5 = loadBigEndian!T(input, 5); 305 x6 = loadBigEndian!T(input, 6); 306 x7 = loadBigEndian!T(input, 7); 307 } 308 309 /** 310 * Load a variable number of big-endian words 311 * Params: 312 * output = the output array of words 313 * input = the input array of bytes 314 * count = how many words are in in 315 */ 316 void loadBigEndian(T)(T* output, const(ubyte)* input, size_t count) 317 { 318 foreach (size_t i; 0 .. count) 319 output[i] = loadBigEndian!T(input, i); 320 } 321 322 /** 323 * Store a big-endian ushort 324 * Params: 325 * input = the input ushort 326 * output = the ubyte array to write to 327 */ 328 void storeBigEndian(ushort input, ubyte[2]* output) 329 { 330 *cast(ushort*) output = bigEndianToNative!ushort(*cast(ubyte[2]*) &input); 331 332 } 333 334 /** 335 * Store a little-endian ushort 336 * Params: 337 * input = the input ushort 338 * output = the ubyte array to write to 339 */ 340 void storeLittleEndian(ushort input, ubyte[2]* output) 341 { 342 *cast(ushort*) output = littleEndianToNative!ushort(*cast(ubyte[2]*) &input); 343 344 } 345 346 /** 347 * Store a big-endian uint 348 * Params: 349 * input = the input uint 350 * output = the ubyte array to write to 351 */ 352 void storeBigEndian(uint input, ubyte[4]* output) 353 { 354 *cast(uint*) output = bigEndianToNative!uint(*cast(ubyte[4]*) &input); 355 356 } 357 358 /** 359 * Store a little-endian uint 360 * Params: 361 * input = the input uint 362 * output = the ubyte array to write to 363 */ 364 void storeLittleEndian(uint input, ubyte[4]* output) 365 { 366 *cast(uint*) output = littleEndianToNative!uint(*cast(ubyte[4]*) &input); 367 368 } 369 370 /** 371 * Store a big-endian ulong 372 * Params: 373 * input = the input ulong 374 * output = the ubyte array to write to 375 */ 376 void storeBigEndian(ulong input, ubyte[8]* output) 377 { 378 *cast(ulong*) output = bigEndianToNative!ulong(*cast(ubyte[8]*) &input); 379 } 380 381 /** 382 * Store a little-endian ulong 383 * Params: 384 * input = the input ulong 385 * output = the ubyte array to write to 386 */ 387 void storeLittleEndian(in ulong input, ubyte[8]* output) 388 { 389 *cast(ulong*) output = littleEndianToNative!ulong(*cast(ubyte[8]*) &input); 390 } 391 392 /** 393 * Store a little-endian ulong 394 * Params: 395 * input = the input ulong 396 * output = the ubyte array to write to 397 */ 398 void storeLittleEndian(T)(in T input, ubyte* output) 399 { 400 storeLittleEndian(cast(T) input, cast(ubyte[T.sizeof]*) output); 401 } 402 403 /** 404 * Store a big-endian ulong 405 * Params: 406 * input = the input ulong 407 * output = the ubyte array to write to 408 */ 409 void storeBigEndian(T)(in T input, ubyte* output) 410 { 411 storeBigEndian(cast(T) input, cast(ubyte[T.sizeof]*) output); 412 } 413 414 /** 415 * Store two little-endian words 416 * Params: 417 * output = the output ubyte array 418 * x0 = the first word 419 * x1 = the second word 420 */ 421 void storeLittleEndian(T)(ubyte* output, T x0, T x1) 422 { 423 storeLittleEndian(x0, output + (0 * T.sizeof)); 424 storeLittleEndian(x1, output + (1 * T.sizeof)); 425 } 426 427 /** 428 * Store two big-endian words 429 * Params: 430 * output = the output ubyte array 431 * x0 = the first word 432 * x1 = the second word 433 */ 434 void storeBigEndian(T)(ubyte* output, T x0, T x1) 435 { 436 storeBigEndian(x0, output + (0 * T.sizeof)); 437 storeBigEndian(x1, output + (1 * T.sizeof)); 438 } 439 440 /** 441 * Store four little-endian words 442 * Params: 443 * output = the output ubyte array 444 * x0 = the first word 445 * x1 = the second word 446 * x2 = the third word 447 * x3 = the fourth word 448 */ 449 void storeLittleEndian(T)(ubyte* output, T x0, T x1, T x2, T x3) 450 { 451 storeLittleEndian(x0, output + (0 * T.sizeof)); 452 storeLittleEndian(x1, output + (1 * T.sizeof)); 453 storeLittleEndian(x2, output + (2 * T.sizeof)); 454 storeLittleEndian(x3, output + (3 * T.sizeof)); 455 } 456 457 /** 458 * Store four big-endian words 459 * Params: 460 * output = the output ubyte array 461 * x0 = the first word 462 * x1 = the second word 463 * x2 = the third word 464 * x3 = the fourth word 465 */ 466 void storeBigEndian(T)(ref ubyte* output, T x0, T x1, T x2, T x3) 467 { 468 storeBigEndian(x0, output + (0 * T.sizeof)); 469 storeBigEndian(x1, output + (1 * T.sizeof)); 470 storeBigEndian(x2, output + (2 * T.sizeof)); 471 storeBigEndian(x3, output + (3 * T.sizeof)); 472 } 473 474 /** 475 * Store eight little-endian words 476 * Params: 477 * output = the output ubyte array 478 * x0 = the first word 479 * x1 = the second word 480 * x2 = the third word 481 * x3 = the fourth word 482 * x4 = the fifth word 483 * x5 = the sixth word 484 * x6 = the seventh word 485 * x7 = the eighth word 486 */ 487 void storeLittleEndian(T)(ubyte* output, T x0, T x1, T x2, T x3, 488 T x4, T x5, T x6, T x7) 489 { 490 storeLittleEndian(x0, output + (0 * T.sizeof)); 491 storeLittleEndian(x1, output + (1 * T.sizeof)); 492 storeLittleEndian(x2, output + (2 * T.sizeof)); 493 storeLittleEndian(x3, output + (3 * T.sizeof)); 494 storeLittleEndian(x4, output + (4 * T.sizeof)); 495 storeLittleEndian(x5, output + (5 * T.sizeof)); 496 storeLittleEndian(x6, output + (6 * T.sizeof)); 497 storeLittleEndian(x7, output + (7 * T.sizeof)); 498 } 499 500 /** 501 * Store eight big-endian words 502 * Params: 503 * output = the output ubyte array 504 * x0 = the first word 505 * x1 = the second word 506 * x2 = the third word 507 * x3 = the fourth word 508 * x4 = the fifth word 509 * x5 = the sixth word 510 * x6 = the seventh word 511 * x7 = the eighth word 512 */ 513 void storeBigEndian(T)(ubyte* output, T x0, T x1, T x2, T x3, 514 T x4, T x5, T x6, T x7) 515 { 516 storeBigEndian(x0, output + (0 * T.sizeof)); 517 storeBigEndian(x1, output + (1 * T.sizeof)); 518 storeBigEndian(x2, output + (2 * T.sizeof)); 519 storeBigEndian(x3, output + (3 * T.sizeof)); 520 storeBigEndian(x4, output + (4 * T.sizeof)); 521 storeBigEndian(x5, output + (5 * T.sizeof)); 522 storeBigEndian(x6, output + (6 * T.sizeof)); 523 storeBigEndian(x7, output + (7 * T.sizeof)); 524 }