Commit 96cfdb5e 96cfdb5e8ef877b1f8773e426061ef4d3442997e by Sergey Poznyakoff

Make sure stream->offset points to the position in stream corresponding to the start of the buffer.

* libmailutils/stream/stream.c (_stream_fill_buffer): Keep
track of the current offset.
(mu_stream_seek): avoid unnecessary seeks.
(_stream_skip_input_bytes): Call _stream_flush_buffer before
_stream_fill_buffer.
(_stream_write_unbuffered): Do not modify current offset.
(mu_stream_read,mu_stream_write): For unbuffered streams,
modify current offset after invoking the corresponding I/O
call.
(_stream_scandelim): Call _stream_flush_buffer before
_stream_fill_buffer.
1 parent 78e57f7e
...@@ -110,7 +110,6 @@ _stream_fill_buffer (struct _mu_stream *stream) ...@@ -110,7 +110,6 @@ _stream_fill_buffer (struct _mu_stream *stream)
110 int rc = 0; 110 int rc = 0;
111 char c; 111 char c;
112 112
113 stream->offset += stream->level;
114 switch (stream->buftype) 113 switch (stream->buftype)
115 { 114 {
116 case mu_buffer_none: 115 case mu_buffer_none:
...@@ -127,7 +126,8 @@ _stream_fill_buffer (struct _mu_stream *stream) ...@@ -127,7 +126,8 @@ _stream_fill_buffer (struct _mu_stream *stream)
127 for (n = 0; 126 for (n = 0;
128 n < stream->bufsize 127 n < stream->bufsize
129 && (rc = _stream_read_unbuffered (stream, 128 && (rc = _stream_read_unbuffered (stream,
130 &c, 1, 0, &rdn)) == 0;) 129 &c, 1,
130 0, &rdn)) == 0;)
131 { 131 {
132 if (rdn == 0) 132 if (rdn == 0)
133 { 133 {
...@@ -143,7 +143,6 @@ _stream_fill_buffer (struct _mu_stream *stream) ...@@ -143,7 +143,6 @@ _stream_fill_buffer (struct _mu_stream *stream)
143 } 143 }
144 if (rc == 0) 144 if (rc == 0)
145 { 145 {
146 stream->offset -= stream->level;
147 stream->pos = 0; 146 stream->pos = 0;
148 _stream_event (stream, _MU_STR_EVENT_FILLBUF, 147 _stream_event (stream, _MU_STR_EVENT_FILLBUF,
149 stream->level, _stream_curp (stream)); 148 stream->level, _stream_curp (stream));
...@@ -193,7 +192,8 @@ _stream_flush_buffer (struct _mu_stream *stream, int flags) ...@@ -193,7 +192,8 @@ _stream_flush_buffer (struct _mu_stream *stream, int flags)
193 192
194 case mu_buffer_full: 193 case mu_buffer_full:
195 if ((rc = _stream_write_unbuffered (stream, stream->buffer, 194 if ((rc = _stream_write_unbuffered (stream, stream->buffer,
196 stream->level, 1, NULL))) 195 stream->level,
196 1, NULL)))
197 return rc; 197 return rc;
198 _stream_event (stream, _MU_STR_EVENT_FLUSHBUF, 198 _stream_event (stream, _MU_STR_EVENT_FLUSHBUF,
199 stream->level, stream->buffer); 199 stream->level, stream->buffer);
...@@ -208,7 +208,8 @@ _stream_flush_buffer (struct _mu_stream *stream, int flags) ...@@ -208,7 +208,8 @@ _stream_flush_buffer (struct _mu_stream *stream, int flags)
208 end = memchr (start, '\n', wrsize)) 208 end = memchr (start, '\n', wrsize))
209 { 209 {
210 size_t size = end - start + 1; 210 size_t size = end - start + 1;
211 rc = _stream_write_unbuffered (stream, start, size, 1, NULL); 211 rc = _stream_write_unbuffered (stream, start, size,
212 1, NULL);
212 if (rc) 213 if (rc)
213 return rc; 214 return rc;
214 _stream_event (stream, _MU_STR_EVENT_FLUSHBUF, 215 _stream_event (stream, _MU_STR_EVENT_FLUSHBUF,
...@@ -231,18 +232,26 @@ _stream_flush_buffer (struct _mu_stream *stream, int flags) ...@@ -231,18 +232,26 @@ _stream_flush_buffer (struct _mu_stream *stream, int flags)
231 wrsize, stream->buffer); 232 wrsize, stream->buffer);
232 wrsize = 0; 233 wrsize = 0;
233 } 234 }
234 if (wrsize) 235 if (!(flags & _MU_STR_FLUSH_KEEP))
235 memmove (stream->buffer, start, wrsize); 236 {
236 else 237 if (wrsize)
237 _stream_clrflag (stream, _MU_STR_DIRTY); 238 memmove (stream->buffer, start, wrsize);
238 stream->level = stream->pos = wrsize; 239 else
239 return 0; 240 _stream_clrflag (stream, _MU_STR_DIRTY);
241 stream->offset += stream->level - wrsize;
242 stream->level = stream->pos = wrsize;
243 return 0;
244 }
240 } 245 }
241 _stream_clrflag (stream, _MU_STR_DIRTY); 246 _stream_clrflag (stream, _MU_STR_DIRTY);
242 } 247 }
243 248
244 if (!(flags & _MU_STR_FLUSH_KEEP)) 249 if (!(flags & _MU_STR_FLUSH_KEEP))
245 stream->pos = stream->level = 0; 250 {
251 stream->offset += stream->level;
252 stream->pos = stream->level = 0;
253 }
254
246 return 0; 255 return 0;
247 } 256 }
248 257
...@@ -413,19 +422,21 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence, ...@@ -413,19 +422,21 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence,
413 return mu_stream_seterr (stream, EINVAL, 1); 422 return mu_stream_seterr (stream, EINVAL, 1);
414 } 423 }
415 424
416 if (stream->buftype == mu_buffer_none ? 425 if (!(stream->buftype == mu_buffer_none ?
417 (offset != stream->offset) 426 (offset == stream->offset)
418 : (stream->level == 0 427 : (stream->offset <= offset &&
419 || offset < stream->offset 428 offset < stream->offset + stream->level)))
420 || offset > stream->offset + stream->level))
421 { 429 {
422 if ((rc = _stream_flush_buffer (stream, _MU_STR_FLUSH_ALL))) 430 if ((rc = _stream_flush_buffer (stream, _MU_STR_FLUSH_ALL)))
423 return rc; 431 return rc;
424 rc = stream->seek (stream, offset, &stream->offset); 432 if (stream->offset != offset)
425 if (rc == ESPIPE) 433 {
426 return rc; 434 rc = stream->seek (stream, offset, &stream->offset);
427 if (rc) 435 if (rc == ESPIPE)
428 return mu_stream_seterr (stream, rc, 1); 436 return rc;
437 if (rc)
438 return mu_stream_seterr (stream, rc, 1);
439 }
429 _mu_stream_cleareof (stream); 440 _mu_stream_cleareof (stream);
430 } 441 }
431 else if (stream->buftype != mu_buffer_none) 442 else if (stream->buftype != mu_buffer_none)
...@@ -476,10 +487,10 @@ _stream_skip_input_bytes (mu_stream_t stream, mu_off_t count, mu_off_t *pres) ...@@ -476,10 +487,10 @@ _stream_skip_input_bytes (mu_stream_t stream, mu_off_t count, mu_off_t *pres)
476 { 487 {
477 for (pos = 0;;) 488 for (pos = 0;;)
478 { 489 {
479 if ((rc = _stream_flush_buffer (stream, _MU_STR_FLUSH_ALL)))
480 return rc;
481 if (stream->pos == stream->level) 490 if (stream->pos == stream->level)
482 { 491 {
492 if ((rc = _stream_flush_buffer (stream, _MU_STR_FLUSH_ALL)))
493 return rc;
483 rc = _stream_fill_buffer (stream); 494 rc = _stream_fill_buffer (stream);
484 if (rc) 495 if (rc)
485 break; 496 break;
...@@ -585,44 +596,42 @@ _stream_read_unbuffered (mu_stream_t stream, void *buf, size_t size, ...@@ -585,44 +596,42 @@ _stream_read_unbuffered (mu_stream_t stream, void *buf, size_t size,
585 return 0; 596 return 0;
586 } 597 }
587 598
588 if (full_read) 599 if (full_read)
589 { 600 {
590 size_t rdbytes; 601 size_t rdbytes;
591 602
592 nread = 0; 603 nread = 0;
593 while (size > 0 604 while (size > 0
594 && (rc = stream->read (stream, buf, size, &rdbytes)) == 0) 605 && (rc = stream->read (stream, buf, size, &rdbytes)) == 0)
595 { 606 {
596 if (rdbytes == 0) 607 if (rdbytes == 0)
597 { 608 {
598 _stream_setflag (stream, _MU_STR_EOF);
599 break;
600 }
601 buf += rdbytes;
602 nread += rdbytes;
603 size -= rdbytes;
604 stream->bytes_in += rdbytes;
605
606 }
607 if (size && rc)
608 rc = mu_stream_seterr (stream, rc, 0);
609 }
610 else
611 {
612 rc = stream->read (stream, buf, size, &nread);
613 if (rc == 0)
614 {
615 if (nread == 0)
616 _stream_setflag (stream, _MU_STR_EOF); 609 _stream_setflag (stream, _MU_STR_EOF);
617 stream->bytes_in += nread; 610 break;
618 } 611 }
619 mu_stream_seterr (stream, rc, rc != 0); 612 buf += rdbytes;
620 } 613 nread += rdbytes;
621 stream->offset += nread; 614 size -= rdbytes;
622 if (pnread) 615 stream->bytes_in += rdbytes;
623 *pnread = nread; 616 }
624 617 if (size && rc)
625 return rc; 618 rc = mu_stream_seterr (stream, rc, 0);
619 }
620 else
621 {
622 rc = stream->read (stream, buf, size, &nread);
623 if (rc == 0)
624 {
625 if (nread == 0)
626 _stream_setflag (stream, _MU_STR_EOF);
627 stream->bytes_in += nread;
628 }
629 mu_stream_seterr (stream, rc, rc != 0);
630 }
631 if (pnread)
632 *pnread = nread;
633
634 return rc;
626 } 635 }
627 636
628 static int 637 static int
...@@ -657,7 +666,7 @@ _stream_write_unbuffered (mu_stream_t stream, ...@@ -657,7 +666,7 @@ _stream_write_unbuffered (mu_stream_t stream,
657 nwritten = 0; 666 nwritten = 0;
658 while (size > 0 667 while (size > 0
659 && (rc = stream->write (stream, bufp, size, &wrbytes)) 668 && (rc = stream->write (stream, bufp, size, &wrbytes))
660 == 0) 669 == 0)
661 { 670 {
662 if (wrbytes == 0) 671 if (wrbytes == 0)
663 { 672 {
...@@ -677,7 +686,6 @@ _stream_write_unbuffered (mu_stream_t stream, ...@@ -677,7 +686,6 @@ _stream_write_unbuffered (mu_stream_t stream,
677 stream->bytes_out += nwritten; 686 stream->bytes_out += nwritten;
678 } 687 }
679 _stream_setflag (stream, _MU_STR_WRT); 688 _stream_setflag (stream, _MU_STR_WRT);
680 stream->offset += nwritten;
681 if (pnwritten) 689 if (pnwritten)
682 *pnwritten = nwritten; 690 *pnwritten = nwritten;
683 mu_stream_seterr (stream, rc, rc != 0); 691 mu_stream_seterr (stream, rc, rc != 0);
...@@ -695,7 +703,14 @@ mu_stream_read (mu_stream_t stream, void *buf, size_t size, size_t *pread) ...@@ -695,7 +703,14 @@ mu_stream_read (mu_stream_t stream, void *buf, size_t size, size_t *pread)
695 } 703 }
696 704
697 if (stream->buftype == mu_buffer_none) 705 if (stream->buftype == mu_buffer_none)
698 return _stream_read_unbuffered (stream, buf, size, !pread, pread); 706 {
707 size_t nread = 0;
708 int rc = _stream_read_unbuffered (stream, buf, size, !pread, &nread);
709 stream->offset += nread;
710 if (pread)
711 *pread = nread;
712 return rc;
713 }
699 else 714 else
700 { 715 {
701 char *bufp = buf; 716 char *bufp = buf;
...@@ -712,6 +727,12 @@ mu_stream_read (mu_stream_t stream, void *buf, size_t size, size_t *pread) ...@@ -712,6 +727,12 @@ mu_stream_read (mu_stream_t stream, void *buf, size_t size, size_t *pread)
712 727
713 if (stream->pos == stream->level) 728 if (stream->pos == stream->level)
714 { 729 {
730 if ((rc = _stream_flush_buffer (stream, _MU_STR_FLUSH_ALL)))
731 {
732 if (nbytes)
733 break;
734 return rc;
735 }
715 if ((rc = _stream_fill_buffer (stream))) 736 if ((rc = _stream_fill_buffer (stream)))
716 { 737 {
717 if (nbytes) 738 if (nbytes)
...@@ -757,6 +778,8 @@ _stream_scandelim (mu_stream_t stream, char *buf, size_t size, int delim, ...@@ -757,6 +778,8 @@ _stream_scandelim (mu_stream_t stream, char *buf, size_t size, int delim,
757 778
758 if (stream->pos == stream->level) 779 if (stream->pos == stream->level)
759 { 780 {
781 if ((rc = _stream_flush_buffer (stream, _MU_STR_FLUSH_ALL)))
782 break;
760 if ((rc = _stream_fill_buffer (stream)) || stream->level == 0) 783 if ((rc = _stream_fill_buffer (stream)) || stream->level == 0)
761 break; 784 break;
762 } 785 }
...@@ -959,8 +982,14 @@ mu_stream_write (mu_stream_t stream, const void *buf, size_t size, ...@@ -959,8 +982,14 @@ mu_stream_write (mu_stream_t stream, const void *buf, size_t size,
959 } 982 }
960 983
961 if (stream->buftype == mu_buffer_none) 984 if (stream->buftype == mu_buffer_none)
962 rc = _stream_write_unbuffered (stream, buf, size, 985 {
963 !pnwritten, pnwritten); 986 size_t nwritten;
987 rc = _stream_write_unbuffered (stream, buf, size,
988 !pnwritten, &nwritten);
989 stream->offset += nwritten;
990 if (pnwritten)
991 *pnwritten = nwritten;
992 }
964 else 993 else
965 { 994 {
966 size_t nbytes = 0; 995 size_t nbytes = 0;
......