@@ -432,41 +432,108 @@ std::string kaitai::kstream::bytes_terminate(std::string src, char term, bool in
432
432
// ========================================================================
433
433
434
434
std::string kaitai::kstream::process_xor_one (std::string data, uint8_t key) {
435
+ if (key == 0 )
436
+ return data;
437
+
435
438
size_t len = data.length ();
436
439
std::string result (len, ' ' );
437
440
438
- for (size_t i = 0 ; i < len; i++)
441
+ for (size_t i = 0 ; i < len; i++) {
439
442
result[i] = data[i] ^ key;
443
+ }
440
444
441
445
return result;
442
446
}
443
447
444
448
std::string kaitai::kstream::process_xor_many (std::string data, std::string key) {
445
449
size_t len = data.length ();
446
- size_t kl = key.length ();
450
+ if (len == 1 )
451
+ return process_xor_one (data, key[0 ]);
452
+
447
453
std::string result (len, ' ' );
448
454
449
- size_t ki = 0 ;
455
+ size_t k = 0 ;
456
+ size_t keylen = key.length ();
450
457
for (size_t i = 0 ; i < len; i++) {
451
- result[i] = data[i] ^ key[ki ];
452
- ki ++;
453
- if (ki >= kl )
454
- ki = 0 ;
458
+ result[i] = data[i] ^ key[k ];
459
+ k ++;
460
+ if (k == keylen )
461
+ k = 0 ;
455
462
}
456
463
457
464
return result;
458
465
}
459
466
460
- std::string kaitai::kstream::process_rotate_left (std::string data, int amount) {
467
+ uint8_t precomputedSingleRotations[8 ][256 ];
468
+
469
+ // NOTE: static block of code, https://stackoverflow.com/a/34321324/2375119
470
+ computeSingleRotations {
471
+ for (int amount = 1 ; amount < 8 ; amount++) {
472
+ int anti_amount = 8 - amount;
473
+ for (uint8_t i = 0 ; i < 256 ; i++) {
474
+ precomputedSingleRotations[amount][i] = (uint8_t )((i << amount) | (i >> anti_amount));
475
+ }
476
+ }
477
+ }
478
+
479
+ std::string kaitai::kstream::process_rotate_left (std::string data, int amount, int groupSize = 1 ) {
480
+ if (groupSize < 1 )
481
+ throw std::runtime_error (" process_rotate_left: groupSize must be at least 1" );
482
+
483
+ amount = mod (amount, groupSize * 8 );
484
+ if (amount == 0 )
485
+ return data;
486
+
487
+ int amount_bytes = amount / 8 ;
461
488
size_t len = data.length ();
462
489
std::string result (len, ' ' );
463
490
464
- for (size_t i = 0 ; i < len; i++) {
465
- uint8_t bits = data[i];
466
- result[i] = (bits << amount) | (bits >> (8 - amount));
491
+ if (groupSize == 1 ) {
492
+ uint8_t *translate = &precomputedSingleRotations[amount][0 ];
493
+
494
+ for (size_t i = 0 ; i < len; i++) {
495
+ result[i] = translate[data[i]];
496
+ }
497
+
498
+ return result;
467
499
}
468
500
469
- return result;
501
+ if (len % groupSize != 0 )
502
+ throw std::runtime_error (" process_rotate_left: data length must be a multiple of group size" );
503
+
504
+ if (amount % 8 == 0 ) {
505
+ size_t indices[groupSize];
506
+ for (size_t i = 0 ; i < groupSize; i++) {
507
+ indices[i] = (size_t )((i + amount_bytes) % groupSize);
508
+ }
509
+
510
+ for (size_t i = 0 ; i < len; i += groupSize) {
511
+ for (size_t k = 0 ; k < groupSize; k++) {
512
+ result[i+k] = data[i + indices[k]];
513
+ }
514
+ }
515
+
516
+ return result;
517
+ }
518
+
519
+ {
520
+ int amount1 = amount % 8 ;
521
+ int amount2 = 8 - amount1;
522
+ size_t indices1[groupSize];
523
+ size_t indices2[groupSize];
524
+ for (size_t i = 0 ; i < groupSize; i++) {
525
+ indices1[i] = (size_t )((i + amount_bytes) % groupSize);
526
+ indices2[i] = (size_t )((i + 1 + amount_bytes) % groupSize);
527
+ }
528
+
529
+ for (size_t i = 0 ; i < len; i += groupSize) {
530
+ for (size_t k = 0 ; k < groupSize; k++) {
531
+ result[i+k] = (uint8_t )((data[i + indices1[k]] << amount1) | (data[i + indices2[k]] >> amount2));
532
+ }
533
+ }
534
+
535
+ return result;
536
+ }
470
537
}
471
538
472
539
#ifdef KS_ZLIB
0 commit comments