mirror of
https://codeberg.org/scip/pcp.git
synced 2025-12-17 20:00:58 +01:00
added buffer_new_buf() which makes it possible to back a Buffer with an existing pointer without copying
This commit is contained in:
@@ -74,7 +74,7 @@ typedef struct _pcp_buffer Buffer;
|
|||||||
*/
|
*/
|
||||||
Buffer *buffer_new(size_t blocksize, char *name);
|
Buffer *buffer_new(size_t blocksize, char *name);
|
||||||
|
|
||||||
/** Create a new buffer.
|
/** Create a new string buffer.
|
||||||
|
|
||||||
Create a new buffer, initially alloc'd to a blocksize of 32 bytes and zero-filled.
|
Create a new buffer, initially alloc'd to a blocksize of 32 bytes and zero-filled.
|
||||||
The buffer will be a string buffer. See buffer_get_str().
|
The buffer will be a string buffer. See buffer_get_str().
|
||||||
@@ -85,6 +85,75 @@ Buffer *buffer_new(size_t blocksize, char *name);
|
|||||||
*/
|
*/
|
||||||
Buffer *buffer_new_str(char *name);
|
Buffer *buffer_new_str(char *name);
|
||||||
|
|
||||||
|
|
||||||
|
/** Create a new buffer from existing data.
|
||||||
|
|
||||||
|
Create a new buffer, but don't allocate memory nor copy data.
|
||||||
|
Instead the provided data pointer will be used as internal
|
||||||
|
storage directly.
|
||||||
|
|
||||||
|
This kind of buffer can be used to put the Buffer API into
|
||||||
|
use with existing data from other sources. In most cases you'll
|
||||||
|
use it for reading. However, please be aware, that it can be
|
||||||
|
used for writing as well and in this case the data pointer
|
||||||
|
maybe resized (by calling realloc()).
|
||||||
|
|
||||||
|
When calling buffer_free() on this Buffer, the memory pointed to
|
||||||
|
by the given data pointer will not be free'd and remains accessible.
|
||||||
|
It's the responsibility of the caller to do so.
|
||||||
|
|
||||||
|
Example using mmap(2):
|
||||||
|
@code
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <pcp.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
FILE *RFD;
|
||||||
|
size_t rs;
|
||||||
|
Buffer *rb;
|
||||||
|
byte *chunk;
|
||||||
|
void *r;
|
||||||
|
|
||||||
|
if((RFD = fopen("README", "rb")) == NULL) {
|
||||||
|
fprintf(stderr, "oops, could not open README!\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(RFD, 0, SEEK_END);
|
||||||
|
rs = ftell(RFD);
|
||||||
|
fseek(RFD, 0, SEEK_SET);
|
||||||
|
|
||||||
|
void *r = mmap(NULL, rs, PROT_READ, 0, fileno(RFD), 0);
|
||||||
|
|
||||||
|
*rb = buffer_new_buf("r", r, rs);
|
||||||
|
|
||||||
|
size_t blocksize = 36;
|
||||||
|
void *chunk = malloc(blocksize);
|
||||||
|
|
||||||
|
while(buffer_done(rb) != 1) {
|
||||||
|
if(buffer_left(rb) < blocksize)
|
||||||
|
blocksize = buffer_left(rb);
|
||||||
|
buffer_get_chunk(rb, chunk, blocksize);
|
||||||
|
_dump("chunk", chunk, blocksize); // or do something else with it
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer_free(rb);
|
||||||
|
|
||||||
|
munmap(r, rs);
|
||||||
|
fclose(RFD);
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
\param[in] name A name for the Buffer. Just used for debugging purposes or in error messages.
|
||||||
|
|
||||||
|
\param[in] data The data pointer to use by the buffer.
|
||||||
|
|
||||||
|
\param[in] datasize The size of the data.
|
||||||
|
|
||||||
|
\return Returns a new Buffer object.
|
||||||
|
|
||||||
|
*/
|
||||||
|
Buffer *buffer_new_buf(char *name, void *data, size_t datasize);
|
||||||
|
|
||||||
/* initialize buffer vars */
|
/* initialize buffer vars */
|
||||||
void buffer_init(Buffer *b, size_t blocksize, char *name);
|
void buffer_init(Buffer *b, size_t blocksize, char *name);
|
||||||
|
|
||||||
|
|||||||
@@ -21,13 +21,6 @@
|
|||||||
|
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
|
||||||
Buffer *buffer_new(size_t blocksize, char *name) {
|
|
||||||
Buffer *b = ucmalloc(sizeof(Buffer));
|
|
||||||
b->buf = ucmalloc(blocksize);
|
|
||||||
buffer_init(b, blocksize, name);
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
void buffer_init(Buffer *b, size_t blocksize, char *name) {
|
void buffer_init(Buffer *b, size_t blocksize, char *name) {
|
||||||
b->name = ucmalloc(strlen(name)+1);
|
b->name = ucmalloc(strlen(name)+1);
|
||||||
b->size = blocksize;
|
b->size = blocksize;
|
||||||
@@ -39,23 +32,40 @@ void buffer_init(Buffer *b, size_t blocksize, char *name) {
|
|||||||
memcpy(b->name, name, strlen(name)+1);
|
memcpy(b->name, name, strlen(name)+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Buffer *buffer_new(size_t blocksize, char *name) {
|
||||||
|
Buffer *b = ucmalloc(sizeof(Buffer));
|
||||||
|
b->buf = ucmalloc(blocksize);
|
||||||
|
buffer_init(b, blocksize, name);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
Buffer *buffer_new_str(char *name) {
|
Buffer *buffer_new_str(char *name) {
|
||||||
Buffer *b = buffer_new(256, name);
|
Buffer *b = buffer_new(256, name);
|
||||||
b->isstring = 1;
|
b->isstring = 1;
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Buffer *buffer_new_buf(char *name, void *data, size_t datasize) {
|
||||||
|
Buffer *b = buffer_new(256, name);
|
||||||
|
b->allocated = 0;
|
||||||
|
b->buf = data;
|
||||||
|
b->size = datasize;
|
||||||
|
b->end = datasize;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
void buffer_free(Buffer *b) {
|
void buffer_free(Buffer *b) {
|
||||||
if(b != NULL) {
|
if(b != NULL) {
|
||||||
if(b->allocated == 1) {
|
if(b->allocated == 1) {
|
||||||
|
/* free the underlying data pointer only if we allocated it */
|
||||||
if(b->end > 0) {
|
if(b->end > 0) {
|
||||||
buffer_clear(b);
|
buffer_clear(b);
|
||||||
|
}
|
||||||
free(b->buf);
|
free(b->buf);
|
||||||
}
|
}
|
||||||
free(b);
|
free(b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void buffer_clear(Buffer *b) {
|
void buffer_clear(Buffer *b) {
|
||||||
b->offset = 0;
|
b->offset = 0;
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "buffertest.h"
|
#include "buffertest.h"
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
/* testing basic Buffer api */
|
||||||
Buffer *test = buffer_new(16, "test");
|
Buffer *test = buffer_new(16, "test");
|
||||||
|
|
||||||
byte *a = ucmalloc(32);
|
byte *a = ucmalloc(32);
|
||||||
@@ -52,6 +54,44 @@ int main() {
|
|||||||
|
|
||||||
buffer_free(test);
|
buffer_free(test);
|
||||||
|
|
||||||
|
/* testing pointer backed buffer */
|
||||||
|
FILE *RFD;
|
||||||
|
size_t rs;
|
||||||
|
|
||||||
|
if((RFD = fopen("README", "rb")) == NULL) {
|
||||||
|
fprintf(stderr, "oops, could not open README!\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(RFD, 0, SEEK_END);
|
||||||
|
rs = ftell(RFD);
|
||||||
|
fseek(RFD, 0, SEEK_SET);
|
||||||
|
|
||||||
|
void *r = mmap(NULL, rs, PROT_READ, 0, fileno(RFD), 0);
|
||||||
|
|
||||||
|
//unsigned char *r = urmalloc(256);
|
||||||
|
Buffer *rb = buffer_new_buf("r", r, rs);
|
||||||
|
|
||||||
|
fprintf(stderr, "r: %p rb->buf: %p\n", r, rb->buf);
|
||||||
|
buffer_info(rb);
|
||||||
|
|
||||||
|
size_t blocksize = 36;
|
||||||
|
void *chunk = malloc(blocksize);
|
||||||
|
|
||||||
|
while(buffer_done(rb) != 1) {
|
||||||
|
if(buffer_left(rb) < blocksize)
|
||||||
|
blocksize = buffer_left(rb);
|
||||||
|
buffer_get_chunk(rb, chunk, blocksize);
|
||||||
|
_dump("chunk", chunk, blocksize);
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer_free(rb);
|
||||||
|
|
||||||
|
_dump("r", r, rs); /* should work! */
|
||||||
|
|
||||||
|
munmap(r, rs);
|
||||||
|
fclose(RFD);
|
||||||
|
|
||||||
fatals_ifany();
|
fatals_ifany();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user