/* File retrieval.
- Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1996-2005 Free Software Foundation, Inc.
This file is part of GNU Wget.
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with Wget; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+along with Wget; if not, write to the Free Software Foundation, Inc.,
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
In addition, as a special exception, the Free Software Foundation
gives permission to link the code of its release of Wget with the
#include "url.h"
#include "recur.h"
#include "ftp.h"
+#include "http.h"
#include "host.h"
#include "connect.h"
#include "hash.h"
return ret;
}
\f
-/* Read a hunk of data from FD, up until a terminator. The terminator
- is whatever the TERMINATOR function determines it to be; for
- example, it can be a line of data, or the head of an HTTP response.
- The function returns the data read allocated with malloc.
-
- In case of error, NULL is returned. In case of EOF and no data
- read, NULL is returned and errno set to 0. In case of EOF with
- data having been read, the data is returned, but it will
- (obviously) not contain the terminator.
+/* Read a hunk of data from FD, up until a terminator. The hunk is
+ limited by whatever the TERMINATOR callback chooses as its
+ terminator. For example, if terminator stops at newline, the hunk
+ will consist of a line of data; if terminator stops at two
+ newlines, it can be used to read the head of an HTTP response.
+ Upon determining the boundary, the function returns the data (up to
+ the terminator) in malloc-allocated storage.
+
+ In case of read error, NULL is returned. In case of EOF and no
+ data read, NULL is returned and errno set to 0. In case of having
+ read some data, but encountering EOF before seeing the terminator,
+ the data that has been read is returned, but it will (obviously)
+ not contain the terminator.
+
+ The TERMINATOR function is called with three arguments: the
+ beginning of the data read so far, the beginning of the current
+ block of peeked-at data, and the length of the current block.
+ Depending on its needs, the function is free to choose whether to
+ analyze all data or just the newly arrived data. If TERMINATOR
+ returns NULL, it means that the terminator has not been seen.
+ Otherwise it should return a pointer to the charactre immediately
+ following the terminator.
The idea is to be able to read a line of input, or otherwise a hunk
of text, such as the head of an HTTP request, without crossing the
boundary, so that the next call to fd_read etc. reads the data
after the hunk. To achieve that, this function does the following:
- 1. Peek at available data.
+ 1. Peek at incoming data.
2. Determine whether the peeked data, along with the previously
read data, includes the terminator.
xfree (hunk);
return NULL;
}
- end = terminator (hunk, tail, pklen);
+ end = terminator (hunk, hunk + tail, pklen);
if (end)
{
/* The data contains the terminator: we'll drain the data up
to the end of the terminator. */
remain = end - (hunk + tail);
+ assert (remain >= 0);
if (remain == 0)
{
/* No more data needs to be read. */
}
static const char *
-line_terminator (const char *hunk, int oldlen, int peeklen)
+line_terminator (const char *start, const char *peeked, int peeklen)
{
- const char *p = memchr (hunk + oldlen, '\n', peeklen);
+ const char *p = memchr (peeked, '\n', peeklen);
if (p)
- /* p+1 because we want the line to include '\n' */
+ /* p+1 because the line must include '\n' */
return p + 1;
return NULL;
}
{
static char res[20];
static const char *rate_names[] = {"B/s", "KB/s", "MB/s", "GB/s" };
- int units = 0;
+ int units;
double dlrate = calc_rate (bytes, msecs, &units);
- sprintf (res, "%.2f %s", dlrate, rate_names[units]);
+ /* Use more digits for smaller numbers (regardless of unit used),
+ e.g. "1022", "247", "12.5", "2.38". */
+ sprintf (res, "%.*f %s",
+ dlrate >= 99.95 ? 0 : dlrate >= 9.995 ? 1 : 2,
+ dlrate, rate_names[units]);
return res;
}