summaryrefslogtreecommitdiff
path: root/src/mt/mread.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/mt/mread.cc')
-rw-r--r--src/mt/mread.cc135
1 files changed, 135 insertions, 0 deletions
diff --git a/src/mt/mread.cc b/src/mt/mread.cc
new file mode 100644
index 0000000..da5a966
--- /dev/null
+++ b/src/mt/mread.cc
@@ -0,0 +1,135 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mt/mread.h>
21#include <mt/split.h>
22#include <poll.h>
23#include <signal.h>
24#include <errno.h>
25
26const int MSEC=4000;
27const int RETRY=3;
28const int TIMEOUT=2;
29
30//////////////////////////////////////////////////////////////////////////
31
32mread::mread() : fd(-1),buf()
33{
34}
35
36mread::mread(int f) : fd(f),buf()
37{
38}
39
40//////////////////////////////////////////////////////////////////////////
41
42void mread::clear()
43{
44 buf.clear();
45}
46
47int mread::poll()
48{
49 pollfd pfd={fd,POLLIN,0};
50 return ::poll(&pfd,1,MSEC);
51}
52
53int mread::read(char* s,int n)
54{
55 if(buf.empty()) {
56 int m=::read(fd,s,n);
57 for(int i=0;i<RETRY&&m<0&&errno==EAGAIN&&poll()>=0;i++) m=::read(fd,s,n);
58 if(m<0&&n) *s=0;
59 return m;
60 }
61 else {
62 if(n>buf.size()) n=buf.size();
63 memcpy(s,buf.data(),n);
64 buf.erase(0,n);
65 return n;
66 }
67}
68
69void mread::putback(const sref& s)
70{
71 if(s.nempty()) buf.insert(0,s);
72}
73
74//////////////////////////////////////////////////////////////////////////
75
76int mread::readx(char* s,int n)
77{
78 int tries=0,acc=0;
79 while(acc<n) {
80 int m=read(s+acc,n-acc);
81 if(m<0) return -1;
82 else if(m==0) {
83 if(poll()<0) return -1;
84 if(tries++>=TIMEOUT) return acc;
85 }
86 else {
87 acc+=m;
88 tries=0;
89 }
90 }
91 return acc;
92}
93
94//////////////////////////////////////////////////////////////////////////
95
96int mread::readln(char* s,int n)
97{
98 int tries=0,acc=0;
99 while(acc<n) {
100 int m=read(s+acc,n-acc);
101 if(m<0) return -1;
102 else if(m==0) {
103 if(poll()<0) return -1;
104 if(tries++>=TIMEOUT) return acc?-1:0;
105 }
106 else {
107 int p=sref(s+acc,m).find('\n')+1;
108 if(p>0) { acc+=p; putback(sref(s+acc,m-p)); return acc; }
109 else { acc+=m; tries=0; }
110 }
111 }
112 return acc;
113}
114
115int mread::readpara(char* s,int n)
116{
117 int tries=0,acc=0;
118 while(acc<n) {
119 int m=read(s+acc,n-acc);
120 if(m<0) return -1;
121 else if(m==0) {
122 if(poll()<0) return -1;
123 if(tries++>=TIMEOUT) return acc?-1:0;
124 }
125 else {
126 int found=0;
127 sref first,rest(s+acc,m);
128 while(Splitln(first,rest)) if(first.empty()) { found=1; break; }
129 if(found) { acc=rest.begin()-s; putback(rest); return acc; }
130 else { acc+=m; tries=0; }
131 }
132 }
133 return acc;
134}
135