in reply to Add 1 to an arbitrary-length binary string

found advice suggesting casting strings to unsigned longs and incrementing and then casing back. Unfortunately these are arbitrary length strings and so I have no guarantee that this will be enough space

Sounds like a good opportunity to make use of perl's Math::BigInt module:
use strict; use warnings; use Math::BigInt; my $string = '12349' x 10; my $x = Math::BigInt->new($string); print $x, "\n"; # $x is a Math::BigInt object $x++; print "$x", "\n"; # "$x" is a string __END__ Outputs: 12349123491234912349123491234912349123491234912349 12349123491234912349123491234912349123491234912350
Cheers,
Rob

Replies are listed 'Best First'.
Re^2: Add 1 to an arbitrary-length binary string
by einhverfr (Friar) on Nov 15, 2023 at 12:23 UTC

    Is there any way to turn a string of arbitrary length text into an arbitrary BigInt and back? A big part of the problem is that the prefix could be "/Some/Arbitrarily/long/string"

    Edit: I found Base::Math::Convert but it looks really poorly maintained so I am hoping there is something a little better.

    Worst case scenario, I could build the logic into the module I am building, but hoping to avoid that.

      Is there any way to turn a string of arbitrary length text into an arbitrary BigInt and back?

      Not that I know of - though I don't usually use Math::BigInt.
      Is it guaranteed that the "arbitrary length text" will contain only valid base 64 characters ?

      Math::GMPz (plug) will certainly handle such text, even if it contains invalid base 64 characters - though Math::GMPz isn't included in perl, and depends upon the gmp C library:
      use strict; use warnings; use Math::GMPz qw(:mpz); my ($order, $size, $endian, $nails) = (1, 1, 0, 0); my $s = 'Som3/Arbitr@ri!y/long/string'; my $z = Math::GMPz->new(); Rmpz_import($z, length($s), $order, $size, $endian, $nails, $s); print $z, "\n"; $z++; print "$z\n"; my $incremented_s = Rmpz_export( $order, $size, $endian, $nails, $z); print "$s\n"; print "$incremented_s\n"; # Next retrieve original string: $z--; my $orig_s = Rmpz_export( $order, $size, $endian, $nails, $z); print "$orig_s\n"; __END__ Outputs: 8786758437493627904416651010636024986357833879283932790893327248999 8786758437493627904416651010636024986357833879283932790893327249000 Som3/Arbitr@ri!y/long/string Som3/Arbitr@ri!y/long/strinh Som3/Arbitr@ri!y/long/string
      But perhaps someone else can provide a solution that better suits your needs.

      Cheers,
      Rob.
        This indeed does look correct. Thanks!

      I don't understand what is "one bit larger than the given key". Isn't it

      "/Some/Arbitrarily/long/string" # the key "0Some/Arbitrarily/long/string" # incremented

      ? i.e. next ASCII character, unless for "\xff", then put "\0" and carry over?