ostream-buffer.c revision a067446575cf5ce63f4a64fa0eb4aac16e591e89
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2002-2016 Dovecot authors, see the included COPYING file */
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen#include "lib.h"
345648b341f228bd7f0b89f8aa3ecb9c470d817eTimo Sirainen#include "buffer.h"
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen#include "ostream-private.h"
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen
5a2cb3d097a2d9a9e930af997e7bf3400a8d840dTimo Sirainenstruct buffer_ostream {
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen struct ostream_private ostream;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen buffer_t *buf;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen bool seeked;
97c339398f1aba6f315b55a9b6ee6b020e33bea4Timo Sirainen};
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
16f46efe0e090fe6975acf012a61a160f4787985Andrey Paninstatic int o_stream_buffer_seek(struct ostream_private *stream, uoff_t offset)
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen{
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen struct buffer_ostream *bstream = (struct buffer_ostream *)stream;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen bstream->seeked = TRUE;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen stream->ostream.offset = offset;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen return 1;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen}
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainenstatic int
25757faf029c369a8318349dafe952e2358df1d8Timo Siraineno_stream_buffer_write_at(struct ostream_private *stream,
16f46efe0e090fe6975acf012a61a160f4787985Andrey Panin const void *data, size_t size, uoff_t offset)
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen{
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen struct buffer_ostream *bstream = (struct buffer_ostream *)stream;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen buffer_write(bstream->buf, offset, data, size);
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen return 0;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen}
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainenstatic ssize_t
25757faf029c369a8318349dafe952e2358df1d8Timo Siraineno_stream_buffer_sendv(struct ostream_private *stream,
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen const struct const_iovec *iov, unsigned int iov_count)
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen{
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen struct buffer_ostream *bstream = (struct buffer_ostream *)stream;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen size_t left, n, offset;
7242e1ce7803b83bc82e239ef111b47c1c72dd4bAndrey Panin ssize_t ret = 0;
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen unsigned int i;
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen offset = bstream->seeked ? stream->ostream.offset : bstream->buf->used;
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen
c57776c06ec99ba9b0dafdbf9475ea72ea8ca134Timo Sirainen for (i = 0; i < iov_count; i++) {
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen left = bstream->ostream.max_buffer_size -
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen stream->ostream.offset;
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen n = I_MIN(left, iov[i].iov_len);
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen buffer_write(bstream->buf, offset, iov[i].iov_base, n);
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen stream->ostream.offset += n; offset += n;
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen ret += n;
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen if (n != iov[i].iov_len)
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen break;
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen }
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen return ret;
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen}
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainenstruct ostream *o_stream_create_buffer(buffer_t *buf)
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen{
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen struct buffer_ostream *bstream;
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen struct ostream *output;
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen bstream = i_new(struct buffer_ostream, 1);
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen /* we don't set buffer as blocking, because if max_buffer_size is
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen changed it can get truncated. this is used in various places in
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen unit tests. */
1ddec6312bc6882aeb17d4d46d19cbca1723b68bTimo Sirainen bstream->ostream.max_buffer_size = (size_t)-1;
1ddec6312bc6882aeb17d4d46d19cbca1723b68bTimo Sirainen bstream->ostream.seek = o_stream_buffer_seek;
1ddec6312bc6882aeb17d4d46d19cbca1723b68bTimo Sirainen bstream->ostream.sendv = o_stream_buffer_sendv;
1ddec6312bc6882aeb17d4d46d19cbca1723b68bTimo Sirainen bstream->ostream.write_at = o_stream_buffer_write_at;
1ddec6312bc6882aeb17d4d46d19cbca1723b68bTimo Sirainen
1ddec6312bc6882aeb17d4d46d19cbca1723b68bTimo Sirainen bstream->buf = buf;
1ddec6312bc6882aeb17d4d46d19cbca1723b68bTimo Sirainen output = o_stream_create(&bstream->ostream, NULL, -1);
1ddec6312bc6882aeb17d4d46d19cbca1723b68bTimo Sirainen o_stream_set_name(output, "(buffer)");
1ddec6312bc6882aeb17d4d46d19cbca1723b68bTimo Sirainen return output;
1ddec6312bc6882aeb17d4d46d19cbca1723b68bTimo Sirainen}
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen