Changeset: a005b45fe545 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=a005b45fe545
Modified Files:
common/stream/stream.c
Branch: default
Log Message:
Merge with Jan2014 branch.
diffs (truncated from 507 to 300 lines):
diff --git a/common/stream/stream.c b/common/stream/stream.c
--- a/common/stream/stream.c
+++ b/common/stream/stream.c
@@ -149,9 +149,9 @@ struct stream {
} stream_data;
int errnr;
ssize_t (*read) (stream *s, void *buf, size_t elmsize, size_t cnt);
- ssize_t (*readline) (stream *s, void *buf, size_t maxcnt);
ssize_t (*write) (stream *s, const void *buf, size_t elmsize, size_t
cnt);
void (*close) (stream *s);
+ void (*clrerr) (stream *s);
char *(*error) (stream *s);
void (*destroy) (stream *s);
int (*flush) (stream *s);
@@ -159,6 +159,11 @@ struct stream {
int (*fgetpos) (stream *s, lng *p);
int (*fsetpos) (stream *s, lng p);
void (*update_timeout) (stream *s);
+ /* in case read() read a non-integral number of elements we
+ * save the last partial element here (only used in
+ * socket_read() */
+ void *buf;
+ size_t len;
};
int
@@ -198,30 +203,61 @@ mnstr_read(stream *s, void *buf, size_t
return (*s->read) (s, buf, elmsize, cnt);
}
-/* Read one line (seperated by \n) of atmost maxcnt characters from
+/* Read one line (seperated by \n) of at most maxcnt-1 characters from
* the stream. Returns the number of characters actually read,
- * includes the trailing \n */
+ * includes the trailing \n; terminated by a NULL byte. */
ssize_t
mnstr_readline(stream *s, void *buf, size_t maxcnt)
{
+ char *b = buf, *start = buf;
+
#ifdef STREAM_DEBUG
printf("readline %s " SZFMT "\n", s->name ? s->name : "<unnamed>",
maxcnt);
#endif
assert(s->access == ST_READ);
if (s->errnr)
return -1;
- if (!s->readline) {
- size_t len = 0;
- char *b = buf, *start = buf;
- while ((*s->read) (s, start, 1, 1) > 0 && len < maxcnt) {
- if (*start++ == '\n')
- break;
+ if (maxcnt == 0)
+ return 0;
+ if (maxcnt == 1) {
+ *start = 0;
+ return 0;
+ }
+ for (;;) {
+ switch ((*s->read)(s, start, 1, 1)) {
+ case 1:
+ /* successfully read a character,
+ * check whether it is the line
+ * separator and whether we have space
+ * left for more */
+ if (*start++ == '\n' || --maxcnt == 1) {
+ *start = 0;
+#if 0
+ if (s->type == ST_ASCII &&
+ start[-1] == '\n' &&
+ start > b + 1 &&
+ start[-2] == '\r') {
+ /* convert CR-LF to just LF */
+ start[-2] = start[-1];
+ start--;
+ }
+#endif
+ return (ssize_t) (start - b);
+ }
+ break;
+ case -1:
+ /* error: if we didn't read anything yet,
+ * return the error, otherwise return what we
+ * have */
+ if (start == b)
+ return -1;
+ /* fall through */
+ case 0:
+ /* end of file: return what we have */
+ *start = 0;
+ return (ssize_t) (start - b);
}
- if (s->errnr)
- return -1;
- return (ssize_t) (start - b);
- } else
- return (*s->readline) (s, buf, maxcnt);
+ }
}
/* Write cnt elements of size elmsize to the stream. Returns the
@@ -361,8 +397,11 @@ mnstr_errnr(stream *s)
void
mnstr_clearerr(stream *s)
{
- if (s != NULL)
+ if (s != NULL) {
s->errnr = MNSTR_NO__ERROR;
+ if (s->clrerr)
+ (*s->clrerr) (s);
+ }
}
int
@@ -442,6 +481,8 @@ get_extention(const char *file)
static void
destroy(stream *s)
{
+ if (s->buf)
+ free(s->buf);
free(s->name);
free(s);
}
@@ -481,9 +522,9 @@ create_stream(const char *name)
s->errnr = MNSTR_NO__ERROR;
s->stream_data.p = NULL;
s->read = NULL;
- s->readline = NULL;
s->write = NULL;
s->close = NULL;
+ s->clrerr = NULL;
s->error = error;
s->destroy = destroy;
s->flush = NULL;
@@ -492,6 +533,8 @@ create_stream(const char *name)
s->fsetpos = NULL;
s->timeout = 0;
s->update_timeout = NULL;
+ s->buf = NULL;
+ s->len = 0;
#ifdef STREAM_DEBUG
printf("create_stream %s -> " PTRFMT "\n", name ? name : "<unnamed>",
PTRFMTCAST s);
#endif
@@ -508,8 +551,9 @@ file_read(stream *s, void *buf, size_t e
size_t rc = 0;
if (!feof(fp)) {
- rc = fread(buf, elmsize, cnt, fp);
- if (ferror(fp)) {
+ if (ferror(fp) ||
+ ((rc = fread(buf, elmsize, cnt, fp)) == 0 &&
+ ferror(fp))) {
s->errnr = MNSTR_READ_ERROR;
return -1;
}
@@ -549,6 +593,14 @@ file_close(stream *s)
s->stream_data.p = NULL;
}
+static void
+file_clrerr(stream *s)
+{
+ FILE *fp = (FILE *) s->stream_data.p;
+
+ clearerr(fp);
+}
+
static int
file_flush(stream *s)
{
@@ -645,9 +697,9 @@ open_stream(const char *filename, const
if ((fp = fopen(filename, flags)) == NULL)
s->errnr = MNSTR_OPEN_ERROR;
s->read = file_read;
- s->readline = NULL;
s->write = file_write;
s->close = file_close;
+ s->clrerr = file_clrerr;
s->flush = file_flush;
s->fsync = file_fsync;
s->fgetpos = file_fgetpos;
@@ -1463,65 +1515,55 @@ socket_write(stream *s, const void *buf,
if (nr > 0)
res += nr;
}
+ if ((size_t) res >= elmsize)
+ return (ssize_t) (res / elmsize);
if (nr < 0) {
s->errnr = MNSTR_WRITE_ERROR;
return -1;
}
- if (res > 0)
- return (ssize_t) (res / elmsize);
- s->errnr = MNSTR_WRITE_ERROR;
- return -1;
+ return 0;
}
static ssize_t
socket_read(stream *s, void *buf, size_t elmsize, size_t cnt)
{
- ssize_t nr = 0, res = 0, size = (ssize_t) (elmsize * cnt);
-
- if (!s || s->errnr)
+ ssize_t nr = 0, size = (ssize_t) (elmsize * cnt);
+
+ if (!s || s->errnr || size == 0)
return -1;
- errno = 0;
- while (res < size &&
- (
+ assert((s->buf == NULL) == (s->len == 0));
+ if (s->buf) {
+ assert((size_t) size > s->len);
+ memcpy(buf, s->buf, s->len);
+ }
+
#ifdef NATIVE_WIN32
- /* recv works on int, make sure the argument fits */
- ((nr = recv(s->stream_data.s, (void *) ((char *) buf + res),
- (int) min(size - res, 1 << 16), 0)) > 0)
+ if (size > INT_MAX)
+ size = elmsize * (INT_MAX / elmsize);
+ nr = recv(s->stream_data.s, (char *) buf + s->len, (int) (size -
s->len), 0);
#else
- ((nr = read(s->stream_data.s, (void *) ((char *) buf + res),
- size - res)) > 0)
+ nr = read(s->stream_data.s, (char *) buf + s->len, size - s->len);
#endif
- || (s->timeout == 0
- && (errno == EAGAIN || errno == EWOULDBLOCK))
- || errno == EINTR)
- ) {
- errno = 0;
- if (nr > 0)
- res += nr;
- }
- if (nr < 0) {
+ if (nr == -1) {
s->errnr = MNSTR_READ_ERROR;
return -1;
}
- return (ssize_t) (res / elmsize);
-}
-
-/* Read one line (seperated by \n) of at most maxcnt characters from the
- * stream. Returns the number of characters actually read, includes the
- * trailing \n. */
-static ssize_t
-socket_readline(stream *s, void *buf, size_t maxcnt)
-{
- char *b = buf, *start = buf, *end = start + maxcnt;
-
- while (socket_read(s, start, 1, 1) > 0 && start < end) {
- if (*start++ == '\n')
- break;
+ if (nr == 0)
+ return 0; /* end of file */
+ if (s->buf) {
+ nr += s->len;
+ free(s->buf);
+ s->buf = NULL;
+ s->len = 0;
}
- if (s->errnr)
- return -1;
- return (ssize_t) (start - b);
+ if (elmsize > 1 && (cnt = nr % elmsize) != 0) {
+ s->buf = malloc(cnt);
+ memcpy(s->buf, (char *) buf + nr - cnt, cnt);
+ s->len = cnt;
+ nr -= cnt;
+ }
+ return (ssize_t) (nr / elmsize);
}
static void
@@ -1547,6 +1589,10 @@ socket_close(stream *s)
}
}
s->stream_data.s = INVALID_SOCKET;
+ if (s->buf)
+ free(s->buf);
+ s->buf = NULL;
+ s->len = 0;
}
static void
@@ -1571,10 +1617,8 @@ socket_open(SOCKET sock, const char *nam
if ((s = create_stream(name)) == NULL)
return NULL;
s->read = socket_read;
- s->readline = socket_readline;
s->write = socket_write;
s->close = socket_close;
- s->flush = NULL;
s->stream_data.s = sock;
s->update_timeout = socket_update_timeout;
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list