Skip to content

Commit

Permalink
Initial implementation of Blob.readint / Buf.writeint
Browse files Browse the repository at this point in the history
As more or less described in
  https://gist.github.com/jnthn/1e865a06d213d89d9aa6352908858a57

This commit implements:

  Endian: native-endian little-endian big-endian

  Blob.read-int8  read-int16  read-int32  read-int64
       read-uint8 read-uint16 read-uint32 read-uint64
                              read-num32  read-num64

  Buf.write-int8  write-int16  write-int32  write-int64
      write-uint8 write-uint16 write-uint32 write-uint64
                               write-num32  write-num64

Each of these methods take a native integer offset as the first parameter,
and an endian indicator (of the Endian enum) as the last positional parameter
(which is different from the design where multiple named variables were used).

The "write-xxx" methods take the appropriate value as the second parameter.

    my $b = Blob.new(1,2,3,4);        # assuming on little-endian system
    say $b.read-int16(1);             # 770 because 3*256 + 2
    say $b.read-int16(1,big-endian);  # 515 because 2*256 + 3
  • Loading branch information
lizmat committed Dec 11, 2018
1 parent a759f9d commit 4f14d71
Showing 1 changed file with 143 additions and 0 deletions.
143 changes: 143 additions & 0 deletions src/core/Buf.pm6
Expand Up @@ -6,6 +6,23 @@ my class X::Cannot::Empty { ... }
my class X::Cannot::Lazy { ... }
my class X::Experimental { ... }

# these constants temporary until they are available as nqp::const::FOO
constant BINARY_ENDIAN_NATIVE = 0;
constant BINARY_ENDIAN_LITTLE = 1;
constant BINARY_ENDIAN_BIG = 2;

constant BINARY_SIZE_8_BIT = 0;
constant BINARY_SIZE_16_BIT = 4;
constant BINARY_SIZE_32_BIT = 8;
constant BINARY_SIZE_64_BIT = 12;

# externalize the endian indicators
enum Endian (
native-endian => BINARY_ENDIAN_NATIVE,
little-endian => BINARY_ENDIAN_LITTLE,
big-endian => BINARY_ENDIAN_BIG,
);

my role Blob[::T = uint8] does Positional[T] does Stringy is repr('VMArray') is array_type(T) {
X::NYI.new(
feature => "{$?CLASS.^name.comb(/^ \w+ /)}s with native {T.^name}"
Expand Down Expand Up @@ -111,6 +128,70 @@ my role Blob[::T = uint8] does Positional[T] does Stringy is repr('VMArray') is
)
}

# for simplicity's sake, these are not multis
method read-int8(
int $offset, Endian $endian = native-endian --> int
) is raw {
nqp::readint(self,$offset,
nqp::bitor_i(BINARY_SIZE_8_BIT,$endian))
}
method read-int16(
int $offset, Endian $endian = native-endian --> int
) is raw {
nqp::readint(self,$offset,
nqp::bitor_i(BINARY_SIZE_16_BIT,$endian))
}
method read-int32(
int $offset, Endian $endian = native-endian --> int
) is raw {
nqp::readint(self,$offset,
nqp::bitor_i(BINARY_SIZE_32_BIT,$endian))
}
method read-int64(
int $offset, Endian $endian = native-endian --> int
) is raw {
nqp::readint(self,$offset,
nqp::bitor_i(BINARY_SIZE_64_BIT,$endian))
}

method read-uint8(
int $offset, Endian $endian = native-endian --> uint
) is raw {
nqp::readuint(self,$offset,
nqp::bitor_i(BINARY_SIZE_8_BIT,$endian))
}
method read-uint16(
int $offset, Endian $endian = native-endian --> uint
) is raw {
nqp::readuint(self,$offset,
nqp::bitor_i(BINARY_SIZE_16_BIT,$endian))
}
method read-uint32(
int $offset, Endian $endian = native-endian --> uint
) is raw {
nqp::readuint(self,$offset,
nqp::bitor_i(BINARY_SIZE_32_BIT,$endian))
}
method read-uint64(
int $offset, Endian $endian = native-endian --> uint
) is raw {
nqp::readuint(self,$offset,
nqp::bitor_i(BINARY_SIZE_64_BIT,$endian))
}

method read-num32(
int $offset, Endian $endian = native-endian --> num
) is raw {
nqp::readnum(self,$offset,
nqp::bitor_i(BINARY_SIZE_32_BIT,$endian))
}
method read-num64(
int $offset, Endian $endian = native-endian --> num
) is raw {
nqp::readnum(self,$offset,
nqp::bitor_i(BINARY_SIZE_64_BIT,$endian))
}

multi method Bool(Blob:D:) { nqp::hllbool(nqp::elems(self)) }
method Capture(Blob:D:) { self.List.Capture }

Expand Down Expand Up @@ -550,6 +631,68 @@ my role Buf[::T = uint8] does Blob[T] is repr('VMArray') is array_type(T) {
!! self!push-list("initializ",nqp::setelems(self,0),iterable);
}

# for simplicity's sake, these are not multis
method write-int8(
int $offset, int $value, Endian $endian = native-endian --> Nil
) is raw {
nqp::writeint(self,$offset,$value,
nqp::bitor_i(BINARY_SIZE_8_BIT,$endian))
}
method write-int16(
int $offset, int $value, Endian $endian = native-endian --> Nil
) is raw {
nqp::writeint(self,$offset,$value,
nqp::bitor_i(BINARY_SIZE_16_BIT,$endian))
}
method write-int32(
int $offset, int $value, Endian $endian = native-endian --> Nil
) is raw {
nqp::writeint(self,$offset,$value,
nqp::bitor_i(BINARY_SIZE_32_BIT,$endian))
}
method write-int64(
int $offset, int $value, Endian $endian = native-endian --> Nil
) is raw {
nqp::writeint(self,$offset,$value,
nqp::bitor_i(BINARY_SIZE_64_BIT,$endian))
}
method write-uint8(
int $offset, uint8 $value, Endian $endian = native-endian --> Nil
) is raw {
nqp::writeuint(self,$offset,$value,
nqp::bitor_i(BINARY_SIZE_8_BIT,$endian))
}
method write-uint16(
int $offset, uint16 $value, Endian $endian = native-endian --> Nil
) is raw {
nqp::writeuint(self,$offset,$value,
nqp::bitor_i(BINARY_SIZE_16_BIT,$endian))
}
method write-uint32(
int $offset, uint32 $value, Endian $endian = native-endian --> Nil
) is raw {
nqp::writeuint(self,$offset,$value,
nqp::bitor_i(BINARY_SIZE_32_BIT,$endian))
}
method write-uint64(
int $offset, uint64 $value, Endian $endian = native-endian --> Nil
) is raw {
nqp::writeuint(self,$offset,$value,
nqp::bitor_i(BINARY_SIZE_64_BIT,$endian))
}
method write-num32(
int $offset, num32 $value, Endian $endian = native-endian --> Nil
) is raw {
nqp::writenum(self,$offset,$value,
nqp::bitor_i(BINARY_SIZE_32_BIT,$endian))
}
method write-num64(
int $offset, num64 $value, Endian $endian = native-endian --> Nil
) is raw {
nqp::writenum(self,$offset,$value,
nqp::bitor_i(BINARY_SIZE_64_BIT,$endian))
}

multi method list(Buf:D:) {
Seq.new(class :: does Rakudo::Iterator::Blobby {
method pull-one() is raw {
Expand Down

0 comments on commit 4f14d71

Please sign in to comment.