]> git.tdb.fi Git - libs/core.git/blob - source/io/eventreader.cpp
Some fixes for eof handling in Memory
[libs/core.git] / source / io / eventreader.cpp
1 #ifdef WIN32
2 #include <windows.h>
3 #endif
4 #include <algorithm>
5 #include <msp/core/systemerror.h>
6 #include "eventreader.h"
7 #include "handle_private.h"
8
9 using namespace std;
10
11 namespace Msp {
12 namespace IO {
13
14 struct EventReader::Private
15 {
16 #ifdef WIN32
17         OVERLAPPED *overlapped;
18         Handle event;
19         unsigned buf_size;
20         char *buffer;
21         unsigned buf_avail;
22         char *buf_next;
23 #endif
24 };
25
26
27 EventReader::EventReader(Handle &h, unsigned size):
28         handle(h),
29         priv(0)
30 {
31 #ifdef WIN32
32         priv = new Private;
33
34         priv->overlapped = 0;
35         *priv->event = CreateEvent(0, true, false, 0);
36         priv->buf_size = size;
37         priv->buffer = new char[priv->buf_size];
38         priv->buf_avail = 0;
39         priv->buf_next = priv->buffer;
40 #else
41         (void)size;
42 #endif
43 }
44
45 EventReader::~EventReader()
46 {
47 #ifdef WIN32
48         CloseHandle(*priv->event);
49         delete priv->overlapped;
50         delete[] priv->buffer;
51 #endif
52         delete priv;
53 }
54
55 const Handle &EventReader::get_event()
56 {
57 #ifdef WIN32
58         start();
59         return priv->event;
60 #else
61         return handle;
62 #endif
63 }
64
65 void EventReader::start()
66 {
67 #ifdef WIN32
68         if(priv->buf_avail || priv->overlapped)
69                 return;
70
71         priv->overlapped = new OVERLAPPED;
72         memset(priv->overlapped, 0, sizeof(OVERLAPPED));
73         priv->overlapped->hEvent = *priv->event;
74
75         DWORD ret;
76         priv->buf_next = priv->buffer;
77         if(!ReadFile(*handle, priv->buffer, priv->buf_size, &ret, priv->overlapped))
78         {
79                 unsigned err = GetLastError();
80                 if(err!=ERROR_IO_PENDING)
81                         throw system_error("ReadFile");
82         }
83         else
84         {
85                 priv->buf_avail = ret;
86                 delete priv->overlapped;
87                 priv->overlapped = 0;
88                 SetEvent(*priv->event);
89         }
90 #endif
91 }
92
93 void EventReader::wait()
94 {
95 #ifdef WIN32
96         if(!priv->overlapped)
97                 return;
98
99         DWORD ret;
100         if(!GetOverlappedResult(*handle, priv->overlapped, &ret, true))
101                 throw system_error("GetOverlappedResult");
102         else
103         {
104                 priv->buf_avail = ret;
105                 delete priv->overlapped;
106                 priv->overlapped = 0;
107         }
108 #endif
109 }
110
111 unsigned EventReader::read(char *buf, unsigned len)
112 {
113 #ifdef WIN32
114         if(!priv->buf_avail)
115         {
116                 // No data in buffer, try to get some
117                 start();
118                 wait();
119         }
120
121         len = min(len, priv->buf_avail);
122         memcpy(buf, priv->buf_next, len);
123         priv->buf_next += len;
124         priv->buf_avail -= len;
125
126         if(!priv->buf_avail)
127         {
128                 ResetEvent(*priv->event);
129                 start();
130         }
131
132         return len;
133 #else
134         return sys_read(handle, buf, len);
135 #endif
136 }
137
138 } // namespace IO
139 } // namespace Msp