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