@@ -432,41 +432,108 @@ std::string kaitai::kstream::bytes_terminate(std::string src, char term, bool in
432432// ========================================================================
433433
434434std::string kaitai::kstream::process_xor_one (std::string data, uint8_t key) {
435+ if (key == 0 )
436+ return data;
437+
435438 size_t len = data.length ();
436439 std::string result (len, ' ' );
437440
438- for (size_t i = 0 ; i < len; i++)
441+ for (size_t i = 0 ; i < len; i++) {
439442 result[i] = data[i] ^ key;
443+ }
440444
441445 return result;
442446}
443447
444448std::string kaitai::kstream::process_xor_many (std::string data, std::string key) {
445449 size_t len = data.length ();
446- size_t kl = key.length ();
450+ if (len == 1 )
451+ return process_xor_one (data, key[0 ]);
452+
447453 std::string result (len, ' ' );
448454
449- size_t ki = 0 ;
455+ size_t k = 0 ;
456+ size_t keylen = key.length ();
450457 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 ;
455462 }
456463
457464 return result;
458465}
459466
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 ;
461488 size_t len = data.length ();
462489 std::string result (len, ' ' );
463490
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;
467499 }
468500
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+ }
470537}
471538
472539#ifdef KS_ZLIB
0 commit comments