Rewrite the buffering on position change.
[remoteglot] / Engine.pm
1 #! /usr/bin/perl
2 use strict;
3 use warnings;
4 use IPC::Open2;
5
6 package Engine;
7
8 sub open {
9         my ($class, $cmdline, $tag, $cb) = @_;
10
11         my ($uciread, $uciwrite);
12         my $pid = IPC::Open2::open2($uciread, $uciwrite, $cmdline);
13
14         my $ev = AnyEvent::Handle->new(
15                 fh => $uciread,
16                 on_error => sub {
17                         my ($handle, $fatal, $msg) = @_;
18                         die "Error in reading from the UCI engine: $msg";
19                 }
20         );
21         my $engine = {
22                 pid => $pid,
23                 read => $uciread,
24                 readbuf => '',
25                 write => $uciwrite,
26                 info => {},
27                 ids => {},
28                 tag => $tag,
29                 ev => $ev,
30                 cb => $cb,
31                 seen_uciok => 0,
32                 stopping => 0,
33         };
34
35         print $uciwrite "uci\n";
36         $ev->push_read(line => sub { $engine->_anyevent_handle_line(@_) });
37         return bless $engine;
38 }
39
40 sub print {
41         my ($engine, $msg) = @_;
42         print { $engine->{'write'} } "$msg\n";
43 }
44
45 sub _anyevent_handle_line {
46         my ($engine, $handle, $line) = @_;
47
48         if (!$engine->{'seen_uciok'}) {
49                 # Gobble up lines until we see uciok.
50                 if ($line =~ /^id (\S+) (.*?)\s*$/) {
51                         $engine->{'id'}->{$1} = $2;
52                 } elsif ($line =~ /^uciok$/) {
53                         $engine->{'seen_uciok'} = 1;
54                 }
55         } else {
56                 $engine->{'cb'}($engine, $line);
57         }
58         $engine->{'ev'}->push_read(line => sub { $engine->_anyevent_handle_line(@_) });
59 }
60
61 1;