@@ -432,41 +432,104 @@ 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 ();
446450 size_t kl = key.length ();
451+ if (len == 1 )
452+ return process_xor_one (data, key[0 ]);
453+
447454 std::string result (len, ' ' );
448455
449- size_t ki = 0 ;
450456 for (size_t i = 0 ; i < len; i++) {
451- result[i] = data[i] ^ key[ki];
452- ki++;
453- if (ki >= kl)
454- ki = 0 ;
457+ result[i] = data[i] ^ key[i % kl];
455458 }
456459
457460 return result;
458461}
459462
460- std::string kaitai::kstream::process_rotate_left (std::string data, int amount) {
463+ uint8_t precomputedSingleRotations[8 ][256 ];
464+
465+ // NOTE: code based on StackOverflow answer at https://stackoverflow.com/a/34321324/2375119
466+ computeSingleRotations {
467+ for (int amount = 1 ; amount < 8 ; amount++) {
468+ int anti_amount = 8 - amount;
469+ for (uint8_t i = 0 ; i < 256 ; i++) {
470+ precomputedSingleRotations[amount][i] = (uint8_t )((i << amount) | (i >> anti_amount));
471+ }
472+ }
473+ }
474+
475+ std::string kaitai::kstream::process_rotate_left (std::string data, int amount, int groupSize = 1 ) {
476+ if (groupSize < 1 )
477+ throw std::runtime_error (" process_rotate_left: groupSize must be at least 1" );
478+
479+ amount = mod (amount, groupSize * 8 );
480+ if (amount == 0 )
481+ return data;
482+
483+ int amount_bytes = amount / 8 ;
461484 size_t len = data.length ();
462485 std::string result (len, ' ' );
463486
464- for (size_t i = 0 ; i < len; i++) {
465- uint8_t bits = data[i];
466- result[i] = (bits << amount) | (bits >> (8 - amount));
487+ if (groupSize == 1 ) {
488+ uint8_t *translate = &precomputedSingleRotations[amount][0 ];
489+
490+ for (size_t i = 0 ; i < len; i++) {
491+ result[i] = translate[data[i]];
492+ }
493+
494+ return result;
467495 }
468496
469- return result;
497+ if (len % groupSize != 0 )
498+ throw std::runtime_error (" process_rotate_left: data length must be a multiple of group size" );
499+
500+ if (amount % 8 == 0 ) {
501+ size_t indices[groupSize];
502+ for (size_t i = 0 ; i < groupSize; i++) {
503+ indices[i] = (size_t )((i + amount_bytes) % groupSize);
504+ }
505+
506+ for (size_t i = 0 ; i < len; i += groupSize) {
507+ for (size_t k = 0 ; k < groupSize; k++) {
508+ result[i+k] = data[i + indices[k]];
509+ }
510+ }
511+
512+ return result;
513+ }
514+
515+ {
516+ int amount1 = amount % 8 ;
517+ int amount2 = 8 - amount1;
518+ size_t indices1[groupSize];
519+ size_t indices2[groupSize];
520+ for (size_t i = 0 ; i < groupSize; i++) {
521+ indices1[i] = (size_t )((i + amount_bytes) % groupSize);
522+ indices2[i] = (size_t )((i + 1 + amount_bytes) % groupSize);
523+ }
524+
525+ for (size_t i = 0 ; i < len; i += groupSize) {
526+ for (size_t k = 0 ; k < groupSize; k++) {
527+ result[i+k] = (uint8_t )((data[i + indices1[k]] << amount1) | (data[i + indices2[k]] >> amount2));
528+ }
529+ }
530+
531+ return result;
532+ }
470533}
471534
472535#ifdef KS_ZLIB
0 commit comments