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>

Reply via email to