Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Re: Align string on a 32-bit boundary with padding

by johngg (Canon)
on Aug 18, 2022 at 09:51 UTC ( #11146219=note: print w/replies, xml ) Need Help??


in reply to Align string on a 32-bit boundary with padding

Use pack with the Z template.

Update: An example.

johngg@aleatico:~$ perl -Mstrict -Mwarnings -E ' my $str = q{example.me}; my $length = length $str; my $padTo = 4; my $rem = $length % $padTo; my $padLen = $length + ( $rem ? $padTo - $rem : 0 ); print pack qq{Z$padLen}, $str;' | hexdump -C 00000000 65 78 61 6d 70 6c 65 2e 6d 65 00 00 |example.m +e..| 0000000c

Update 2: Don't use this, if the string is already aligned to a 32-bit boundary the Z template will overwrite the last character with a NULL is it seems to always produce a C-style NULL-terminated string.

Update 3: Removed the strike-through! The solution is to only pad with pack when necessary but it does begin to look messy.

johngg@aleatico:~$ perl -Mstrict -Mwarnings -E ' my $str = q{myexample.me}; my $length = length $str; my $padTo = 4; my $rem = $length % $padTo; print $rem ? pack( qq{Z@{ [ $length + $padTo - $rem ] }}, $str ) : $str;' | hexdump -C 00000000 6d 79 65 78 61 6d 70 6c 65 2e 6d 65 |myexample +.me| 0000000c

Cheers,

JohnGG

Replies are listed 'Best First'.
Re^2: Align string on a 32-bit boundary with padding
by BillKSmith (Monsignor) on Aug 18, 2022 at 16:13 UTC
    I took your suggestion as a challenge. Here is the best I could do. It probably is not what you had in mind.
    use strict; use warnings; use Test::More tests=>1; my $Origin_Host_CER="example.me"; my $required = "6578616d706c652e6d650000"; my $length = 4*int((length($Origin_Host_CER)+3)/4); my $result = unpack('H*', pack("Z$length", $Origin_Host_CER)); is($result, $required, 'AVP String');
    Bill
Re^2: Align string on a 32-bit boundary with padding
by BillKSmith (Monsignor) on Aug 20, 2022 at 20:50 UTC
    After studying your updates, private messages, and documentation for 'pack', I was able to fix my previous code by packing one extra (arbitrary) character, and not unpacking it. However, I noticed that the 'pack' was overkill. I could concatenate three extra nulls to the end of the original ASCII string and unpack as much as necessary. The length ($l) has to be twice what it was before because now I am unpacking two hex characters for every one ASCII character that I had been packing.
    use strict; use warnings; use Test::More tests=>4; my @examples = ( [qw( example. 6578616d706c652e )], [qw( example.1 6578616d706c652e31000000)], [qw( example.12 6578616d706c652e31320000)], [qw( example.123 6578616d706c652e31323300)], ); foreach my $example(@examples) { my ($Origin_Host_CER, $required) = @$example; my $l = 8*int((length($Origin_Host_CER)+3)/4); my $result = unpack("H$l", $Origin_Host_CER . "\x00" x 3); is($result, $required, $Origin_Host_CER); }

    RESULTS

    1..4 ok 1 - example. ok 2 - example.1 ok 3 - example.12 ok 4 - example.123
    Bill
Re^2: Align string on a 32-bit boundary with padding
by NERDVANA (Hermit) on Aug 20, 2022 at 14:35 UTC
    There's really no need for pack when you can just add  ("\0" x $n) to the original string.
      ... add ("\0" x $n) to the original string.

      Shouldn't that be ("\0" x ($n-1)) if $n is the boundary width in bytes?

      Win8 Strawberry 5.8.9.5 (32) Sat 08/20/2022 15:46:20 C:\@Work\Perl\monks >perl use strict; use warnings; use bytes; use Data::Dump qw(pp); use constant BYTE_BOUND => 4; use constant PAD => "\0" x (BYTE_BOUND-1); my $s = 'TheRainInSpainFalls'; while (length $s) { my $p = $s . PAD; $p = bytes::substr $p, 0, bytes::length($p) - bytes::length($p)%BY +TE_BOUND; printf "%4s - %-28s \n", bytes::length($p), pp($p); chop $s; } ^Z 20 - "TheRainInSpainFalls\0" 20 - "TheRainInSpainFall\0\0" 20 - "TheRainInSpainFal\0\0\0" 16 - "TheRainInSpainFa" 16 - "TheRainInSpainF\0" 16 - "TheRainInSpain\0\0" 16 - "TheRainInSpai\0\0\0" 12 - "TheRainInSpa" 12 - "TheRainInSp\0" 12 - "TheRainInS\0\0" 12 - "TheRainIn\0\0\0" 8 - "TheRainI" 8 - "TheRain\0" 8 - "TheRai\0\0" 8 - "TheRa\0\0\0" 4 - "TheR" 4 - "The\0" 4 - "Th\0\0" 4 - "T\0\0\0"


      Give a man a fish:  <%-{-{-{-<

        $n was whatever you are adding to the string from your other math. My only point was that appending a short string of "\0" is faster and less to look at than using unpack to split the string on every byte and then re-join them.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11146219]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (4)
As of 2023-02-06 00:54 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    I prefer not to run the latest version of Perl because:







    Results (33 votes). Check out past polls.

    Notices?