jaakko_m has asked for the wisdom of the Perl Monks concerning the following question:

Hi, This is my first post to Perlmonks, so please let me know if I've posted this in the wrong place and failed to search the proper category for info before posting. I have been asked to port some Java code to Perl, but am not clear on how to do this exactly. Hoping someone a bit more familiar with Java may be able to point me in the right direction? The method takes a 128-bit hex string and manipulates it, but I am not quite clear on how this would translate to Perl. Sample Java code I'd like to port to Perl:
private byte[] getBytes(String hexText) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); StringTokenizer stToken = new StringTokenizer(hexText, "-", false); while (stToken.hasMoreTokens()) { String token = stToken.nextToken(); int i = Integer.parseInt(token, 16); if (token.length() > 2) { byte b = (byte) (i >>> 8); baos.write(b); } baos.write((byte) i); } return baos.toByteArray(); }

Replies are listed 'Best First'.
Re: Port Java code to Perl help
by toolic (Bishop) on Apr 14, 2012 at 01:18 UTC
    Since I wouldn't know Java from Coffee, and you didn't tell me what the code should do, I'm gonna pretend it takes a string of 128 characters and returns an array of 64 2-character strings:
    use warnings; use strict; use Data::Dumper; my $str = 'deadbeef'; my @bytes = $str =~ /../g; print Dumper(\@bytes); __END__ $VAR1 = [ 'de', 'ad', 'be', 'ef' ];

    If you are interested in learning Perl, here are some free-sources (I just made that up, I think):

Re: Port Java code to Perl help
by davido (Cardinal) on Apr 14, 2012 at 00:59 UTC

    Welcome to the Monastery!

    While I'm sure someone proficient in Java is surely reading your post by now, it would help those of us such as myself (who have been fortunate enough to keep our distance from Java) if you could explain what it does. I have some ideas, but I would enjoy thinking about how to implement it in Perl a lot more if I was sure what it does.


    Dave

Re: Port Java code to Perl help
by mbethke (Hermit) on Apr 14, 2012 at 07:43 UTC

    Assuming you get a maximum of four hex digits in a number between dashes (otherwise the semantics of the Java version would be rather obscure too), I'd say:

    sub get_bytes { return join '', map { length($_) > 2 ? pack('C', hex substr($_,0,-2)) : pack('C', he +x $_) } split /-/, $_[0]; }

    It splits the string on dashes, the resulting list gets mapped to characters depending on the length of the number (I leave off the last two hex digits rather than doing a logical right shift because pack returns a string) and then joined back together with no separator to yield the byte string.

    Maybe someone can come up with a clever pack pattern that does it all, I'm not quite the expert there.

      As pack 'H' is working from left to right on the passed string, you can simply say pack 'H2' (two hex characters make up one byte):

      sub get_bytes { return join '', map { pack('H2', $_) } split /-/, $_[0]; } print get_bytes('66-6f-6f00-62ff-61-72');

      This would print "foobar", because the lower bytes 00 and ff are being ignored.

Re: Port Java code to Perl help
by BrowserUk (Patriarch) on Apr 14, 2012 at 08:31 UTC

    Perhaps:

    sub dashedHexToBytes{ join'', map pack( 'H*', $_ ),split'-', $_[0] };;
    print dashedHexToBytes( '3f-ff0c-1234-af12' );;
    ? ♀↕4»↕
    

    Or

    sub dashedHexToBytes{ local $_ = shift; tr[-][]; return pack( 'h*', $_ ); };;
    print dashedHexToBytes( '0123-4567-89ab-cdef-0123-4567-89ab-cdef' );;
    ►2MeÎÿ║═Ý▀►2MeÎÿ║═Ý☼
    

    Note: In both examples, you may need to switch from 'H*' to 'h*' or vice versa depending on the endianess of the originating system and that of the receiving system.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

    The start of some sanity?

      This solution did the trick, got the result into a binary exactly as we needed! Thanks so much and sorry for the delay in getting my response back up here.
      sub dashedHexToBytes{ join'', map pack( 'H*', $_ ),split'-', $_[0] };
      Best! Jaakko
Re: Port Java code to Perl help
by halfcountplus (Hermit) on Apr 14, 2012 at 13:56 UTC
    If you want a fairly literal translation:
    #!/usr/bin/perl use strict; use warnings FATAL => qw(all); sub getBytes { # split string into tokens my @tokens = split '-', (shift); # map array of hex tokens to array of bytes my @bytearray = map ( pack('C', hex2byte($_)), # see below @tokens ); return \@bytearray; } sub hex2byte { my $b = hex(shift); # deal with oversize values $b >>= 1 while ($b > 255); return $b; } # try my $arrayref = getBytes('5e-ff-adad-23'); # check foreach (@{$arrayref}) { print unpack ('C', $_)."\n"; }