mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-19 16:12:40 -06:00
Add qemu_get_buffer_in_place to avoid copies some of the time
qemu_get_buffer always copies the data it reads to a users buffer, however in many cases the file buffer inside qemu_file could be given back to the caller, avoiding the copy. This isn't always possible depending on the size and alignment of the data. Thus 'qemu_get_buffer_in_place' either copies the data to a supplied buffer or updates a pointer to the internal buffer if convenient. Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com> Reviewed-by: Juan Quintela <quintela@redhat.com> Signed-off-by: Juan Quintela <quintela@redhat.com>
This commit is contained in:
parent
42e2aa5637
commit
9504fb510c
2 changed files with 39 additions and 0 deletions
|
@ -163,9 +163,11 @@ void qemu_put_be32(QEMUFile *f, unsigned int v);
|
||||||
void qemu_put_be64(QEMUFile *f, uint64_t v);
|
void qemu_put_be64(QEMUFile *f, uint64_t v);
|
||||||
size_t qemu_peek_buffer(QEMUFile *f, uint8_t **buf, size_t size, size_t offset);
|
size_t qemu_peek_buffer(QEMUFile *f, uint8_t **buf, size_t size, size_t offset);
|
||||||
size_t qemu_get_buffer(QEMUFile *f, uint8_t *buf, size_t size);
|
size_t qemu_get_buffer(QEMUFile *f, uint8_t *buf, size_t size);
|
||||||
|
size_t qemu_get_buffer_in_place(QEMUFile *f, uint8_t **buf, size_t size);
|
||||||
ssize_t qemu_put_compression_data(QEMUFile *f, const uint8_t *p, size_t size,
|
ssize_t qemu_put_compression_data(QEMUFile *f, const uint8_t *p, size_t size,
|
||||||
int level);
|
int level);
|
||||||
int qemu_put_qemu_file(QEMUFile *f_des, QEMUFile *f_src);
|
int qemu_put_qemu_file(QEMUFile *f_des, QEMUFile *f_src);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note that you can only peek continuous bytes from where the current pointer
|
* Note that you can only peek continuous bytes from where the current pointer
|
||||||
* is; you aren't guaranteed to be able to peak to +n bytes unless you've
|
* is; you aren't guaranteed to be able to peak to +n bytes unless you've
|
||||||
|
|
|
@ -433,6 +433,43 @@ size_t qemu_get_buffer(QEMUFile *f, uint8_t *buf, size_t size)
|
||||||
return done;
|
return done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read 'size' bytes of data from the file.
|
||||||
|
* 'size' can be larger than the internal buffer.
|
||||||
|
*
|
||||||
|
* The data:
|
||||||
|
* may be held on an internal buffer (in which case *buf is updated
|
||||||
|
* to point to it) that is valid until the next qemu_file operation.
|
||||||
|
* OR
|
||||||
|
* will be copied to the *buf that was passed in.
|
||||||
|
*
|
||||||
|
* The code tries to avoid the copy if possible.
|
||||||
|
*
|
||||||
|
* It will return size bytes unless there was an error, in which case it will
|
||||||
|
* return as many as it managed to read (assuming blocking fd's which
|
||||||
|
* all current QEMUFile are)
|
||||||
|
*
|
||||||
|
* Note: Since **buf may get changed, the caller should take care to
|
||||||
|
* keep a pointer to the original buffer if it needs to deallocate it.
|
||||||
|
*/
|
||||||
|
size_t qemu_get_buffer_in_place(QEMUFile *f, uint8_t **buf, size_t size)
|
||||||
|
{
|
||||||
|
if (size < IO_BUF_SIZE) {
|
||||||
|
size_t res;
|
||||||
|
uint8_t *src;
|
||||||
|
|
||||||
|
res = qemu_peek_buffer(f, &src, size, 0);
|
||||||
|
|
||||||
|
if (res == size) {
|
||||||
|
qemu_file_skip(f, res);
|
||||||
|
*buf = src;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return qemu_get_buffer(f, *buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Peeks a single byte from the buffer; this isn't guaranteed to work if
|
* Peeks a single byte from the buffer; this isn't guaranteed to work if
|
||||||
* offset leaves a gap after the previous read/peeked data.
|
* offset leaves a gap after the previous read/peeked data.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue