1 /*
2 Copyright (c) by respective owners including Yahoo!, Microsoft, and
3 individual contributors. All rights reserved.  Released under a BSD (revised)
4 license as described in the file LICENSE.
5  */
6 #include "io_buf.h"
7 #ifdef WIN32
8 #include <winsock2.h>
9 #endif
10 
buf_read(io_buf & i,char * & pointer,size_t n)11 size_t buf_read(io_buf &i, char* &pointer, size_t n)
12 {//return a pointer to the next n bytes.  n must be smaller than the maximum size.
13   if (i.space.end + n <= i.endloaded)
14     {
15       pointer = i.space.end;
16       i.space.end += n;
17       return n;
18     }
19   else // out of bytes, so refill.
20     {
21       if (i.space.end != i.space.begin) //There exists room to shift.
22 	{ // Out of buffer so swap to beginning.
23 	  size_t left = i.endloaded - i.space.end;
24 	  memmove(i.space.begin, i.space.end, left);
25 	  i.space.end = i.space.begin;
26 	  i.endloaded = i.space.begin+left;
27 	}
28       if (i.fill(i.files[i.current]) > 0)
29 	return buf_read(i,pointer,n);// more bytes are read.
30       else if (++i.current < i.files.size())
31 	return buf_read(i,pointer,n);// No more bytes, so go to next file and try again.
32       else
33 	{//no more bytes to read, return all that we have left.
34 	  pointer = i.space.end;
35 	  i.space.end = i.endloaded;
36 	  return i.endloaded - pointer;
37 	}
38     }
39 }
40 
isbinary(io_buf & i)41 bool isbinary(io_buf &i) {
42   if (i.endloaded == i.space.end)
43     if (i.fill(i.files[i.current]) <= 0)
44       return false;
45 
46   bool ret = (*i.space.end == 0);
47   if (ret)
48     i.space.end++;
49 
50   return ret;
51 }
52 
readto(io_buf & i,char * & pointer,char terminal)53 size_t readto(io_buf &i, char* &pointer, char terminal)
54 {//Return a pointer to the bytes before the terminal.  Must be less than the buffer size.
55   pointer = i.space.end;
56   while (pointer < i.endloaded && *pointer != terminal)
57     pointer++;
58   if (pointer != i.endloaded)
59     {
60       size_t n = pointer - i.space.end;
61       i.space.end = pointer+1;
62       pointer -= n;
63       return n+1;
64     }
65   else
66     {
67       if (i.endloaded == i.space.end_array)
68 	{
69 	  size_t left = i.endloaded - i.space.end;
70 	  memmove(i.space.begin, i.space.end, left);
71 	  i.space.end = i.space.begin;
72 	  i.endloaded = i.space.begin+left;
73 	  pointer = i.endloaded;
74 	}
75       if (i.current < i.files.size() && i.fill(i.files[i.current]) > 0)// more bytes are read.
76 	return readto(i,pointer,terminal);
77       else if (++i.current < i.files.size())  //no more bytes, so go to next file.
78 	return readto(i,pointer,terminal);
79       else //no more bytes to read, return everything we have.
80 	{
81 	  size_t n = pointer - i.space.end;
82 	  i.space.end = pointer;
83 	  pointer -= n;
84 	  return n;
85 	}
86     }
87 }
88 
buf_write(io_buf & o,char * & pointer,size_t n)89 void buf_write(io_buf &o, char* &pointer, size_t n)
90 {//return a pointer to the next n bytes to write into.
91   if (o.space.end + n <= o.space.end_array)
92     {
93       pointer = o.space.end;
94       o.space.end += n;
95     }
96   else // Time to dump the file
97     {
98       if (o.space.end != o.space.begin)
99 	o.flush();
100       else // Array is short, so increase size.
101 	{
102 	  o.space.resize(2*(o.space.end_array - o.space.begin));
103 	  o.endloaded = o.space.begin;
104 	}
105       buf_write (o, pointer,n);
106     }
107 }
108 
is_socket(int f)109 bool io_buf::is_socket(int f)
110 { // this appears to work in practice, but could probably be done in a cleaner fashion
111   const int _nhandle = 32;
112   return f >= _nhandle;
113 }
114 
read_file_or_socket(int f,void * buf,size_t nbytes)115 ssize_t io_buf::read_file_or_socket(int f, void* buf, size_t nbytes) {
116 #ifdef _WIN32
117   if (is_socket(f))
118     return recv(f, reinterpret_cast<char*>(buf), static_cast<int>(nbytes), 0);
119   else
120     return _read(f, buf, (unsigned int)nbytes);
121 #else
122   return read(f, buf, (unsigned int)nbytes);
123 #endif
124 }
125 
write_file_or_socket(int f,const void * buf,size_t nbytes)126 ssize_t io_buf::write_file_or_socket(int f, const void* buf, size_t nbytes)
127 {
128 #ifdef _WIN32
129   if (is_socket(f))
130     return send(f, reinterpret_cast<const char*>(buf), static_cast<int>(nbytes), 0);
131   else
132     return _write(f, buf, (unsigned int)nbytes);
133 #else
134   return write(f, buf, (unsigned int)nbytes);
135 #endif
136 }
137 
close_file_or_socket(int f)138 void io_buf::close_file_or_socket(int f)
139 {
140 #ifdef _WIN32
141   if (io_buf::is_socket(f))
142     closesocket(f);
143   else
144     _close(f);
145 #else
146   close(f);
147 #endif
148 }
149