develooper Front page | perl.perl6.users | Postings from June 2022

My How To on Buffers

From:
ToddAndMargo via perl6-users
Date:
June 19, 2022 11:03
Subject:
My How To on Buffers
Message ID:
eda589df-6202-61fa-39b1-64115bd760d7@zoho.com
Hi All,

If you were wondering what I was up to, this is it.

This is originally in Open Document Test (.odt) format,
so I do not know how well it will translate to text.
If you want the original document, I will email it
to you.  It is a lot pretties and you can <ctrl><click>
on the Table of Contents to jump to the subject
you want

Thank you for all the help!

-T


Raku: Buffers, How To:

Table of Contents
References:	1
Type Graph:	1
Types of buffers:	2
Simple creation:	2
Presalt with 10 entries of the same thing:	2
Presalt with spec entries:	2
Presalt with swept entries:	2
Counting the number of elements in a buffer:	2
Append Strings (letters) to a buffer:	3
Append numbers to a buffer:	3
Changing elements of a buffer:	3
Copy elements from one buffer to another:	3
copy cell 1 through cell 2 from $x to $y:	4
copy three cells starting at cell 1 from $x to $y:	4
Locate a sub-buffer inside a buffer:	4
String to Buffer:	5
Buffer to String:	5
int/uint to Buf:	5
Num to Buf:	5
Num (square root of three) to Buf:	5
40 digits without the decimal point of the square root of 3:	5

References:
    https://docs.raku.org/type/Buf
    https://docs.raku.org/routine/append
    https://raku.github.io/Documentable/integration-test/type
    https://docs.raku.org/type/Buf#(Blob)_method_subbuf
    https://docs.raku.org/images/type-graph-Buf.svg
    https://docs.raku.org/routine/encode

Type Graph:
   <https://docs.raku.org/images/type-graph-Buf.svg>


Types of buffers:
Note: number refers to the number of bits
     Buf
     buf8     (default)
     buf16
     buf32
     buf64


Simple creation:
Note: buffer indexes start counting from zero
    >my Buf $x;
    (Buf)

    > my $b = buf8.new( 0xAB, 0xAC );
    Buf[uint8]:0x<AB AC>

    > my buf8 $c = buf8.new( 0xAB, 0xAC );
    Buf[uint8]:0x<AB AC>

    > my Buf $d = buf8.new( 0xAB, 0xAC );
    Buf[uint8]:0x<AB AC>


Presalt with 10 entries of the same thing:
    > my Buf $y = Buf.new( 0xFA xx 10);
    Buf:0x<FA FA FA FA FA FA FA FA FA FA>


Presalt with specific entries:
    > my Buf $z = Buf.new( 0xAF, 0xFF, 0x1F );
    Buf:0x<AF FF 1F>


Presalt with swept entries:
    > my buf8 $e = buf8.new(0x5..0x8);
    Buf[uint8]:0x<05 06 07 08>

    > my buf8 $e = buf8.new(0x5A..0x5D);
    Buf[uint8]:0x<5A 5B 5C 5D>


Counting the number of elements in a buffer:
Note: buffer indexes start counting from zero
    > say $y.bytes
    14
    > say $y.elems
    14

Append Strings (letters) to a buffer:
    $y ~= "A".encode.Buf;
    Buf:0x<FA FA FA FA FA FA FA FA FA FA 41>


Append numbers to a buffer:
    > my buf8 $x = buf8.new( 0x41, 0x42, 0x43, 0x44 )
    Buf[unit8]:0x<41 42 43 44>

    > $x.append( 0xDD );
    Buf:0x<41 42 43 44 DD>

    > $x.append( 0xEE..0xF1 );
    Buf:0x<41 42 43 44 DD EE EF F0 F1>

    > $x.append( 0xA1, 0xA3, 0xA5 );
    Buf:0x<41 42 43 44 DD EE EF F0 F1 A1 A3 A5>

    $x ~= buf8.new( 0xBB, 0xBC );
    Buf:0x<41 42 43 44 DD EE EF F0 F1 A1 A3 A5 BB BC>

    > $x.push( 0xDE, 0xDF );
    Buf[uint8]:0x<41 42 43 44 DD EE EF F0 F1 A1 A3 A5 BB BC DE DF>


Changing elements of a buffer:
    > say $y[3].base(0x10)
    FA
    > $y[3] = 0xFB
    251
    > say $y[3].base(16)
    FB


Copy elements from one buffer to another:
Note: buffer indexes start counting from zero
use `subbuf`

copy cell 1 through cell 2 from $x to $y:
 > my Buf $x=Buf.new(0x55, 0x66, 0x77, 0x78);
Buf:0x<55 66 77 78>

 > my Buf $y=$x.subbuf( 1..2 );
Buf:0x<66 77>

copy three cells starting at cell 1 from $x to $y:
 > my Buf $x=Buf.new(0x55, 0x66, 0x77, 0x78);
Buf:0x<55 66 77 78>

 > my Buf $y=$x.subbuf( 1, 3 );
Buf:0x<66 77 78>


Locate a sub-buffer inside a buffer:
On 2/5/19 7:55 AM, Brad Gilbert wrote:
     `index` is an NQP op, which means in this case that it is written
     in C (assuming you are using MoarVM)

I rewrote it using knowledge of the internals to be a bit faster:

     sub blob-index ( Blob:D $buffer, Blob:D $needle, UInt:D $init = 0 
--> Int ) {
         use nqp;
         my int $needle-width = $needle.elems;
         my int $elems = $buffer.elems;

         if $elems < $needle-width + $init {
             fail 'needle is larger than the buffer'
         }

         my uint $from = $init;
         my uint $to   = $from + $needle-width - 1;

         loop ( ; $to < $elems ; ++$from,++$to ) {
             return $from if $needle eq nqp::slice($buffer,$from,$to)
             # eq is safe since they are two Blobs/Bufs
         }
         return Nil
     }

It's faster mainly because it doesn't use an iterator.

String to Buffer:
    > Buf.new("abc".encode)
    Buf:0x<61 62 63>

    say "abc".encode.Buf;
    Buf:0x<61 62 63>

    > my Buf $x;
    (Buf)
    > $x = "AB".encode.Buf;
    Buf:0x<41 42>
    $x ~= "CD".encode.Buf
    Buf:0x<41 42 43 44>

Buffer to String:
    > say Buf.new(97,98,99).decode
    abc

int/uint to Buf:
    > Buf.new(1414.Str.encode)
    Buf:0x<31 34 31 34>

Num to Buf:
    > Buf.new(2.1414.Str.encode)
    Buf:0x<32 2E 31 34 31 34>

Num (square root of three) to Buf:
 >  Buf.new(3.sqrt.Str.encode)
Buf:0x<31 2E 37 33 32 30 35 30 38 30 37 35 36 38 38 37 37 32>

40 digits without the decimal point of the square root of 3:
Reference: https://rosettacode.org/wiki/Integer_roots#Raku

sub integer_root ( Int $p where * >= 2, Int $n --> Int ) {
    my Int $d = $p - 1;
    my $guess = 10**($n.chars div $p);
    my $iterator = { ( $d * $^x   +   $n div ($^x ** $d) ) div $p };
    my $endpoint = {      $^x      ** $p <= $n
                     and ($^x + 1) ** $p >  $n };
    min (+$guess, $iterator ... $endpoint)[*-1, *-2];
}

 >  Buf.new(integer_root( 2, 3 * 100 ** 39 ).Str.encode)
Buf:0x<31 37 33 32 30 35 30 38 30 37 35 36 38 38 37 37 32 39 33 35 32 37 
34 34 36 33 34 31 35 30 35 38 37 32 33 36 36 39 34 32>
 >

Hexadecimal string to Buffer:

Quick example:
 > my Str $x = '0x84 0x73 0x77 0x84 0x79 0x87 0x84 0x68 0x73'

 > my buf8 $y = buf8.new($x.match(/(<xdigit> ** 2)/, 
:g)».Str».parse-base(16));
Buf[uint8]:0x<84 73 77 84 79 87 84 68 73>


More in depth:

 > use BigRoot;
Nil

 >  BigRoot.precision = 10;
10

 > my $BigNum  = BigRoot.newton's-sqrt: 11
3.3166247904

 > my Str $MyCypher  = sprintf $BigNum.base(16);
3.510E527FE

 > $MyCypher ~~ s/ '.' //;
「.」

 > $MyCypher ~~ s:g/ (..) /0x$0, /;
(「3」
  0 => 「3」 「51」
  0 => 「51」 「0E」
  0 => 「0E」 「52」
  0 => 「52」 「7F」
  0 => 「7F」)

 > $MyCypher ~~ s/ (.*) $(Q[,]) /$0/;
「0x3, 0x51, 0x0E, 0x52, 0x7F,」
  0 => 「0x3, 0x51, 0x0E, 0x52, 0x7F」

 > my buf8 $MyCypherBuf = buf8.new($MyCypher.match(/(<xdigit> ** 2)/, 
:g)».Str».parse-base(16));
Buf[uint8]:0x<51 0E 52 7F>




nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About