[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 4/9] qemu_qsb.diff
From: |
Joel Schopp |
Subject: |
[Qemu-devel] [PATCH 4/9] qemu_qsb.diff |
Date: |
Tue, 12 Mar 2013 22:09:37 -0500 |
This patch adds support functions for operating on in memory sized file buffers.
Signed-off-by: Stefan Berger <address@hidden>
Signed-off-by: Joel Schopp <address@hidden>
---
include/migration/qemu-file.h | 12 +++
include/qemu-common.h | 15 ++++
qemu-file.c | 184 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 211 insertions(+)
diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h
index 728b6e2..de8408a 100644
--- a/include/migration/qemu-file.h
+++ b/include/migration/qemu-file.h
@@ -24,6 +24,8 @@
#ifndef QEMU_FILE_H
#define QEMU_FILE_H 1
+#include <stdint.h>
+
/* This function writes a chunk of data to a file at the given position.
* The pos argument can be ignored if the file is only being used for
* streaming. The handler should try to write all of the data it can.
@@ -58,6 +60,14 @@ typedef struct QEMUFileOps {
QEMUFileGetFD *get_fd;
} QEMUFileOps;
+struct QEMUSizedBuffer {
+ unsigned char *buffer;
+ uint64_t size;
+ uint64_t used;
+};
+
+typedef struct QEMUSizedBuffer QEMUSizedBuffer;
+
QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops);
QEMUFile *qemu_fopen(const char *filename, const char *mode);
QEMUFile *qemu_fdopen(int fd, const char *mode);
@@ -71,6 +81,8 @@ void qemu_put_byte(QEMUFile *f, int v);
int qemu_read_bytes(QEMUFile *f, uint8_t *buf, int size);
int qemu_peek_bytes(QEMUFile *f, uint8_t *buf, int size, size_t offset);
int qemu_write_bytes(QEMUFile *f, const uint8_t *buf, int size);
+QEMUFile *qemu_bufopen(const char *mode, QEMUSizedBuffer *input);
+const QEMUSizedBuffer *qemu_buf_get(QEMUFile *f);
static inline void qemu_put_ubyte(QEMUFile *f, unsigned int v)
{
diff --git a/include/qemu-common.h b/include/qemu-common.h
index 5e13708..de1cdc0 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -442,4 +442,19 @@ int64_t pow2floor(int64_t value);
int uleb128_encode_small(uint8_t *out, uint32_t n);
int uleb128_decode_small(const uint8_t *in, uint32_t *n);
+/* QEMU Sized Buffer */
+#include "include/migration/qemu-file.h"
+QEMUSizedBuffer *qsb_create(const uint8_t *buffer, uint64_t len);
+QEMUSizedBuffer *qsb_clone(const QEMUSizedBuffer *);
+void qsb_free(QEMUSizedBuffer *);
+uint64_t qsb_set_length(QEMUSizedBuffer *qsb, uint64_t length);
+uint64_t qsb_get_length(const QEMUSizedBuffer *qsb);
+const unsigned char *qsb_get_buffer(const QEMUSizedBuffer *, int64_t pos);
+int qsb_write_at(QEMUSizedBuffer *qsb, const uint8_t *buf,
+ int64_t pos, int size);
+int qsb_append_qsb(QEMUSizedBuffer *dest, const QEMUSizedBuffer *src);
+int qsb_append(QEMUSizedBuffer *dest, const uint8_t *buffer, uint64_t len);
+
+
+
#endif
diff --git a/qemu-file.c b/qemu-file.c
index f8a54e7..a1528e5 100644
--- a/qemu-file.c
+++ b/qemu-file.c
@@ -743,3 +743,187 @@ int qemu_write_bytes(QEMUFile *f, const uint8_t *buf, int
size)
return size;
}
+
+
+QEMUSizedBuffer *qsb_create(const uint8_t *buffer, uint64_t len)
+{
+ QEMUSizedBuffer *qsb;
+ uint64_t alloc_len;
+
+ alloc_len = (len > 1024) ? len : 1024;
+
+ qsb = g_new0(QEMUSizedBuffer, 1);
+ if (!qsb) {
+ return NULL;
+ }
+
+ qsb->buffer = g_malloc(alloc_len);
+ if (!qsb->buffer) {
+ g_free(qsb);
+ return NULL;
+ }
+ qsb->size = alloc_len;
+
+ if (buffer) {
+ memcpy(qsb->buffer, buffer, len);
+ qsb->used = len;
+ }
+
+ return qsb;
+}
+
+void qsb_free(QEMUSizedBuffer *qsb)
+{
+ if (!qsb) {
+ return;
+ }
+ g_free(qsb->buffer);
+ g_free(qsb);
+}
+
+uint64_t qsb_get_length(const QEMUSizedBuffer *qsb)
+{
+ return qsb->used;
+}
+
+uint64_t qsb_set_length(QEMUSizedBuffer *qsb, uint64_t new_len)
+{
+ if (new_len <= qsb->size) {
+ qsb->used = new_len;
+ } else {
+ qsb->used = qsb->size;
+ }
+ return qsb->used;
+}
+
+const unsigned char *qsb_get_buffer(const QEMUSizedBuffer *qsb, int64_t pos)
+{
+ if (pos < qsb->used) {
+ return &qsb->buffer[pos];
+ }
+ return NULL;
+}
+
+int qsb_write_at(QEMUSizedBuffer *qsb, const uint8_t *buf,
+ int64_t pos, int size)
+{
+ if (pos + size > qsb->size) {
+ qsb->buffer = g_realloc(qsb->buffer, pos + size + 1024);
+ if (qsb->buffer == NULL) {
+ return -ENOMEM;
+ }
+ qsb->size = pos + size;
+ }
+ memcpy(&qsb->buffer[pos], buf, size);
+ if (pos + size > qsb->used) {
+ qsb->used = pos + size;
+ }
+
+ return size;
+}
+
+int qsb_append_qsb(QEMUSizedBuffer *dest, const QEMUSizedBuffer *src)
+{
+ return qsb_write_at(dest, qsb_get_buffer(src, 0),
+ qsb_get_length(dest), qsb_get_length(src));
+}
+
+int qsb_append(QEMUSizedBuffer *dest, const uint8_t *buf, uint64_t len)
+{
+ return qsb_write_at(dest, buf,
+ qsb_get_length(dest), len);
+}
+
+QEMUSizedBuffer *qsb_clone(const QEMUSizedBuffer *in)
+{
+ return qsb_create(qsb_get_buffer(in, 0),
+ qsb_get_length(in));
+}
+
+typedef struct QEMUBuffer {
+ QEMUSizedBuffer *qsb;
+ QEMUFile *file;
+} QEMUBuffer;
+
+static int buf_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
+{
+ QEMUBuffer *s = opaque;
+ ssize_t len = qsb_get_length(s->qsb) - pos;
+
+ if (len <= 0) {
+ return 0;
+ }
+
+ if (len > size) {
+ len = size;
+ }
+ memcpy(buf, qsb_get_buffer(s->qsb, pos), len);
+
+ return len;
+}
+
+static int buf_put_buffer(void *opaque, const uint8_t *buf,
+ int64_t pos, int size)
+{
+ QEMUBuffer *s = opaque;
+
+ return qsb_write_at(s->qsb, buf, pos, size);
+}
+
+static int buf_close(void *opaque)
+{
+ QEMUBuffer *s = opaque;
+
+ qsb_free(s->qsb);
+
+ g_free(s);
+
+ return 0;
+}
+
+const QEMUSizedBuffer *qemu_buf_get(QEMUFile *f)
+{
+ QEMUBuffer *p;
+
+ qemu_fflush(f);
+
+ p = (QEMUBuffer *)f->opaque;
+
+ return p->qsb;
+}
+
+static const QEMUFileOps buf_read_ops = {
+ .get_buffer = buf_get_buffer,
+ .close = buf_close
+};
+
+static const QEMUFileOps buf_write_ops = {
+ .put_buffer = buf_put_buffer,
+ .close = buf_close
+};
+
+QEMUFile *qemu_bufopen(const char *mode, QEMUSizedBuffer *input)
+{
+ QEMUBuffer *s;
+
+ if (mode == NULL || (mode[0] != 'r' && mode[0] != 'w') || mode[1] != 0) {
+ fprintf(stderr, "qemu_bufopen: Argument validity check failed\n");
+ return NULL;
+ }
+
+ s = g_malloc0(sizeof(QEMUBuffer));
+ if (mode[0] == 'r') {
+ s->qsb = input;
+ }
+
+ if (s->qsb == NULL) {
+ s->qsb = qsb_create(NULL, 0);
+ }
+
+ if (mode[0] == 'r') {
+ s->file = qemu_fopen_ops(s, &buf_read_ops);
+ } else {
+ s->file = qemu_fopen_ops(s, &buf_write_ops);
+ }
+ return s->file;
+}
--
1.7.10.4
- [Qemu-devel] [PATCH 0/9 v2] Implement and test asn1 ber visitors, Joel Schopp, 2013/03/12
- [Qemu-devel] [PATCH 5/9] qapi_sized_buffer, Joel Schopp, 2013/03/12
- [Qemu-devel] [PATCH 3/9] two new file wrappers, Joel Schopp, 2013/03/12
- [Qemu-devel] [PATCH 2/9] qapi_c_arrays.diff, Joel Schopp, 2013/03/12
- [Qemu-devel] [PATCH 9/9] update_maintainers.diff, Joel Schopp, 2013/03/12
- [Qemu-devel] [PATCH 4/9] qemu_qsb.diff,
Joel Schopp <=
- [Qemu-devel] [PATCH 1/9] qemu-file, Joel Schopp, 2013/03/12
- [Qemu-devel] [PATCH 6/9] asn1_output-visitor.diff, Joel Schopp, 2013/03/12
- [Qemu-devel] [PATCH 8/9] asn1_test_visitor_serialization.diff, Joel Schopp, 2013/03/12
- [Qemu-devel] [PATCH 7/9] asn1_input-visitor.diff, Joel Schopp, 2013/03/12