mirror of https://gitee.com/openkylin/qemu.git
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
|
@ -163,9 +163,11 @@ void qemu_put_be32(QEMUFile *f, unsigned int 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_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,
|
||||
int level);
|
||||
int qemu_put_qemu_file(QEMUFile *f_des, QEMUFile *f_src);
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
|
|
@ -433,6 +433,43 @@ size_t qemu_get_buffer(QEMUFile *f, uint8_t *buf, size_t size)
|
|||
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
|
||||
* offset leaves a gap after the previous read/peeked data.
|
||||
|
|
Loading…
Reference in New Issue