Skip to content

Instantly share code, notes, and snippets.

@zoffixznet
Created November 1, 2016 18:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zoffixznet/3598d276e2cfdcae3b3761e142797093 to your computer and use it in GitHub Desktop.
Save zoffixznet/3598d276e2cfdcae3b3761e142797093 to your computer and use it in GitHub Desktop.
class IO::Blob { … }
my IO::Blob $io .= new: "moo meow foo";
$io.write: "Foo\nBar\nBer\n";
$io.data.encode.say;
class IO::Blob is IO::Handle {
constant EMPTY = "".encode;
constant LF = "\n".encode;
constant TAB = "\t".encode;
constant SPACE = " ".encode;
has Int $!pos = 0;
has Int $!ins = 1;
has Blob $.data is rw = Buf.new;
has Bool $!is_closed = False;
has Str $.nl is rw = "\n";
has $.path;
multi method gist(IO::Blob:D:) {
$!is_closed
?? "IO::Blob(closed)"
!! "IO::Blob(opened, at ins {$!ins} / pos {$!pos})"
}
multi method perl(IO::Blob:D:) {
"IO::Blob.new(data => {$.data.perl})"
}
multi method new(Blob $data = Buf.new) {
return self.bless(:$data);
}
multi method open(Blob $data = Buf.new) returns IO::Blob {
return self.new($data);
}
multi method new(Str $str) {
return self.new($str.encode);
}
multi method open(Str $str) {
return self.new($str.encode);
}
method get(IO::Blob:D:) returns Str {
return '' if self.eof;
unless (defined $.nl) {
return self.slurp-rest();
}
my $i = $!pos;
my $len = $.data.elems;
loop (; $i < $len; $i++) {
if ($.data.subbuf($i, 1) eq LF) {
$!ins++;
last;
}
}
my $line;
if ($i < $len) {
$line = $.data.subbuf($!pos, $i - $!pos + 1);
$!pos = $i + 1;
} else {
$line = $.data.subbuf($!pos, $i - $!pos);
$!pos = $len;
}
return $line.decode;
}
method getc(IO::Blob:D:) returns Str {
return '' if self.eof;
my $char = $.data.subbuf($!pos++, 1);
# TODO other separator
if ($char eq LF) {
$!ins++;
}
return $char.decode;
}
method lines(IO::Blob:D: $limit = Inf) {
my $line;
my @lines;
loop (my $i = 0; $i < $limit; $i++) {
my $line = self.get;
if (!$line.Bool) {
last;
}
@lines.push($line)
}
return @lines;
}
method word(IO::Blob:D:) returns Str {
if self.eof {
return '';
}
# TODO other separator
my $i = $!pos;
my $len = $.data.elems;
loop (; $i < $len; $i++) {
my $char = $.data.subbuf($i, 1);
if ($char eq TAB || $char eq SPACE) {
last;
} elsif ($char eq LF) {
$!ins++;
last;
}
}
my $buf;
if ($i < $len) {
$buf = $.data.subbuf($!pos, $i - $!pos + 1);
$!pos = $i + 1;
} else {
$buf = $.data.subbuf($!pos, $i - $!pos);
$!pos = $len;
}
return $buf.decode;
}
method words(IO::Blob:D: $count = Inf) {
my $word;
my @words;
loop (my $i = 0; $i < $count; $i++) {
my $word = self.word;
if (!$word.Bool) {
last;
}
@words.push($word)
}
return @words;
}
method print(IO::Blob:D: *@text) returns Bool {
self.write(@text.join.encode);
return True;
}
method read(IO::Blob:D: Int(Cool:D) $bytes) returns Blob {
if self.eof {
return EMPTY;
}
my $read = $.data.subbuf($!pos, $bytes);
$!pos += $read.elems;
# TODO ins
return $read;
}
method write(IO::Blob:D: Blob:D $buf) returns Bool {
my $data = $.data ~ $buf;
$!pos = $data.elems;
$.data = $data;
# TODO ins
return True;
}
method seek(IO::Blob:D: int $offset, SeekType:D $whence = SeekFromBeginning) returns Bool {
my $eofpos = $.data.elems;
# Seek:
given $whence {
when SeekFromBeginning { $!pos = $offset }
when SeekFromCurrent { $!pos += $offset }
when SeekFromEnd { $!pos = $eofpos + $offset }
}
# Fixup
if ($!pos < 0) { $!pos = 0 }
if ($!pos > $eofpos) { $!pos = $eofpos }
return True;
}
method tell(IO::Blob:D:) returns Int {
return $!pos;
}
method ins(IO::Blob:D:) returns Int {
return $!ins;
}
proto method slurp-rest(|) { * }
multi method slurp-rest(IO::Blob:D: :$bin!) returns Buf {
my $buf := Buf.new();
if self.eof {
return $buf;
}
my $read = $.data.subbuf($!pos);
$!pos += $.data.elems;
#TODO ins
return $buf ~ $read;
}
multi method slurp-rest(IO::Blob:D: :$enc = 'utf8') returns Str {
if self.eof {
return "";
}
my $read = $.data.subbuf($!pos).decode($enc);
$!pos = $.data.elems;
#TODO ins
return $read;
}
method eof(IO::Blob:D:) returns Bool {
return $!is_closed || $!pos >= $.data.elems;
}
method close(IO::Blob:D:) {
$.data = Nil;
$!pos = Nil;
$!ins = Nil;
$!is_closed = True;
}
method is-closed(IO::Blob:D:) returns Bool {
return $!is_closed;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment