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>