diff --git a/rply.c b/rply.c index c4105ef..de382ea 100644 --- a/rply.c +++ b/rply.c @@ -3,6 +3,10 @@ * Diego Nehab, IMPA * http://www.impa.br/~diego/software/rply * + * In-memory read/write of PLY files + * Patryk Kiepas + * https://github.com/quepas + * * This library is distributed under the MIT License. See notice * at the end of this file. * ---------------------------------------------------------------------- */ @@ -15,9 +19,11 @@ #include #include #include +#include #include "rply.h" #include "rplyfile.h" +#include "rplymemory.h" /* ---------------------------------------------------------------------- * Make sure we get our integer types right @@ -192,6 +198,11 @@ typedef t_ply_odriver *p_ply_odriver; * pdata/idata: user data defined with ply_open/ply_create * ---------------------------------------------------------------------- */ typedef struct t_ply_ { + bool in_memory; + const char* load_memory; + char* store_memory; + size_t* store_memory_size; + size_t store_buffer_size; e_ply_io_mode io_mode; e_ply_storage_mode storage_mode; p_ply_element element; @@ -236,6 +247,11 @@ static int ply_write_chunk(p_ply ply, void *anybuffer, size_t size); static int ply_write_chunk_reverse(p_ply ply, void *anybuffer, size_t size); static void ply_reverse(void *anydata, size_t size); +/* ---------------------------------------------------------------------- + * In memory I/O functions + * ---------------------------------------------------------------------- */ +static int ply_store_buffer_in_memory(p_ply ply, char *buffer); + /* ---------------------------------------------------------------------- * String functions * ---------------------------------------------------------------------- */ @@ -313,7 +329,14 @@ static int BREFILL(p_ply ply) { ply->buffer_last = size; ply->buffer_first = ply->buffer_token = 0; /* fill remaining with new data */ - size = fread(ply->buffer+size, 1, BUFFERSIZE-size-1, ply->fp); + if (ply->in_memory) { + size_t to_read = BUFFERSIZE-size-1; + memcpy(ply->buffer+size, ply->load_memory, to_read); + ply->load_memory += to_read; + size = to_read; + } else { + size = fread(ply->buffer+size, 1, BUFFERSIZE-size-1, ply->fp); + } /* increase size to account for new data */ ply->buffer_last += size; /* place sentinel so we can use str* functions with buffer */ @@ -384,6 +407,7 @@ p_ply ply_open_from_file(FILE *fp, p_ply_error_cb error_cb, error_cb(NULL, "Out of memory"); return NULL; } + ply->in_memory = false; ply->idata = idata; ply->pdata = pdata; ply->io_mode = PLY_READ; @@ -393,8 +417,34 @@ p_ply ply_open_from_file(FILE *fp, p_ply_error_cb error_cb, return ply; } +p_ply ply_open_from_memory(const char* buffer, p_ply_error_cb error_cb, long idata, + void *pdata) { + p_ply ply; + if (error_cb == NULL) error_cb = ply_error_cb; + assert(buffer); + if (!ply_type_check()) { + error_cb(ply, "Incompatible type system"); + return NULL; + } + ply = ply_alloc(); + if (!ply) { + error_cb(NULL, "Out of memory"); + return NULL; + } + ply->in_memory = true; + ply->load_memory = buffer; + ply->idata = idata; + ply->pdata = pdata; + ply->io_mode = PLY_READ; + ply->error_cb = error_cb; + return ply; +} + int ply_read_header(p_ply ply) { - assert(ply && ply->fp && ply->io_mode == PLY_READ); + assert(ply && ply->io_mode == PLY_READ); + if (!ply->in_memory) { + assert(ply->fp); + } if (!ply_read_header_magic(ply)) return 0; if (!ply_read_word(ply)) return 0; /* parse file format */ @@ -441,7 +491,10 @@ long ply_set_read_cb(p_ply ply, const char *element_name, int ply_read(p_ply ply) { long i; p_ply_argument argument; - assert(ply && ply->fp && ply->io_mode == PLY_READ); + assert(ply && ply->io_mode == PLY_READ); + if (!ply->in_memory) { + assert(ply->fp); + } argument = &ply->argument; /* for each element type */ for (i = 0; i < ply->nelements; i++) { @@ -486,6 +539,7 @@ p_ply ply_create_to_file(FILE *fp, e_ply_storage_mode storage_mode, error_cb(NULL, "Out of memory"); return NULL; } + ply->in_memory = false; ply->idata = idata; ply->pdata = pdata; ply->io_mode = PLY_WRITE; @@ -501,10 +555,47 @@ p_ply ply_create_to_file(FILE *fp, e_ply_storage_mode storage_mode, return ply; } +p_ply +ply_create_to_memory(char *buffer, size_t buffer_size, size_t *ply_size, e_ply_storage_mode storage_mode, + p_ply_error_cb error_cb, long idata, void *pdata) { + p_ply ply; + if (error_cb == NULL) error_cb = ply_error_cb; + assert(storage_mode <= PLY_DEFAULT); + if (!ply_type_check()) { + error_cb(ply, "Incompatible type system"); + return NULL; + } + ply = ply_alloc(); + if (!ply) { + error_cb(NULL, "Out of memory"); + return NULL; + } + ply->in_memory = true; + ply->store_memory = buffer; + ply->store_memory_size = ply_size; + *(ply->store_memory_size) = 0; + ply->store_buffer_size = buffer_size; + ply->idata = idata; + ply->pdata = pdata; + ply->io_mode = PLY_WRITE; + if (storage_mode == PLY_DEFAULT) storage_mode = ply_arch_endian(); + if (storage_mode == PLY_ASCII) ply->odriver = &ply_odriver_ascii; + else if (storage_mode == ply_arch_endian()) + ply->odriver = &ply_odriver_binary; + else ply->odriver = &ply_odriver_binary_reverse; + ply->storage_mode = storage_mode; + ply->fp = NULL; + ply->own_fp = 0; + ply->error_cb = error_cb; + return ply; +} int ply_add_element(p_ply ply, const char *name, long ninstances) { p_ply_element element = NULL; - assert(ply && ply->fp && ply->io_mode == PLY_WRITE); + assert(ply && ply->io_mode == PLY_WRITE); + if (!ply->in_memory) { + assert(ply->fp); + } assert(name && strlen(name) < WORDSIZE && ninstances >= 0); if (strlen(name) >= WORDSIZE || ninstances < 0) { ply_ferror(ply, "Invalid arguments"); @@ -520,7 +611,10 @@ int ply_add_element(p_ply ply, const char *name, long ninstances) { int ply_add_scalar_property(p_ply ply, const char *name, e_ply_type type) { p_ply_element element = NULL; p_ply_property property = NULL; - assert(ply && ply->fp && ply->io_mode == PLY_WRITE); + assert(ply && ply->io_mode == PLY_WRITE); + if (!ply->in_memory) { + assert(ply->fp); + } assert(name && strlen(name) < WORDSIZE); assert(type < PLY_LIST); if (strlen(name) >= WORDSIZE || type >= PLY_LIST) { @@ -539,7 +633,10 @@ int ply_add_list_property(p_ply ply, const char *name, e_ply_type length_type, e_ply_type value_type) { p_ply_element element = NULL; p_ply_property property = NULL; - assert(ply && ply->fp && ply->io_mode == PLY_WRITE); + assert(ply && ply->io_mode == PLY_WRITE); + if (!ply->in_memory) { + assert(ply->fp); + } assert(name && strlen(name) < WORDSIZE); if (strlen(name) >= WORDSIZE) { ply_ferror(ply, "Invalid arguments"); @@ -599,38 +696,85 @@ int ply_add_obj_info(p_ply ply, const char *obj_info) { int ply_write_header(p_ply ply) { long i, j; - assert(ply && ply->fp && ply->io_mode == PLY_WRITE); + assert(ply && ply->io_mode == PLY_WRITE); + if (!ply->in_memory) { + assert(ply->fp); + } assert(ply->element || ply->nelements == 0); assert(!ply->element || ply->nelements > 0); - if (fprintf(ply->fp, "ply\nformat %s 1.0\n", - ply_storage_mode_list[ply->storage_mode]) <= 0) goto error; - for (i = 0; i < ply->ncomments; i++) - if (fprintf(ply->fp, "comment %s\n", ply->comment + LINESIZE*i) <= 0) - goto error; - for (i = 0; i < ply->nobj_infos; i++) - if (fprintf(ply->fp, "obj_info %s\n", ply->obj_info + LINESIZE*i) <= 0) - goto error; + char buffer[LINESIZE]; + if (ply->in_memory) { + sprintf(buffer, "ply\nformat %s 1.0\n", + ply_storage_mode_list[ply->storage_mode]); + if (ply_store_buffer_in_memory(ply, buffer) == 0) goto error; + } else { + if (fprintf(ply->fp, "ply\nformat %s 1.0\n", + ply_storage_mode_list[ply->storage_mode]) <= 0) goto error; + } + for (i = 0; i < ply->ncomments; i++) { + if (ply->in_memory) { + sprintf(buffer, "comment %s\n", ply->comment + LINESIZE*i); + if (ply_store_buffer_in_memory(ply, buffer) == 0) goto error; + } else { + if (fprintf(ply->fp, "comment %s\n", ply->comment + LINESIZE*i) <= 0) + goto error; + } + } + for (i = 0; i < ply->nobj_infos; i++) { + if (ply->in_memory) { + sprintf(buffer, "obj_info %s\n", ply->obj_info + LINESIZE*i); + if (ply_store_buffer_in_memory(ply, buffer) == 0) goto error; + } else { + if (fprintf(ply->fp, "obj_info %s\n", ply->obj_info + LINESIZE*i) <= 0) + goto error; + } + } for (i = 0; i < ply->nelements; i++) { p_ply_element element = &ply->element[i]; assert(element->property || element->nproperties == 0); assert(!element->property || element->nproperties > 0); - if (fprintf(ply->fp, "element %s %ld\n", element->name, - element->ninstances) <= 0) goto error; + if (ply->in_memory) { + sprintf(buffer, "element %s %ld\n", element->name, + element->ninstances); + if (ply_store_buffer_in_memory(ply, buffer) == 0) goto error; + } else { + if (fprintf(ply->fp, "element %s %ld\n", element->name, + element->ninstances) <= 0) goto error; + } for (j = 0; j < element->nproperties; j++) { p_ply_property property = &element->property[j]; if (property->type == PLY_LIST) { - if (fprintf(ply->fp, "property list %s %s %s\n", + if (ply->in_memory) { + sprintf(buffer, "property list %s %s %s\n", ply_type_list[property->length_type], ply_type_list[property->value_type], - property->name) <= 0) goto error; + property->name); + if (ply_store_buffer_in_memory(ply, buffer) == 0) goto error; + } else { + if (fprintf(ply->fp, "property list %s %s %s\n", + ply_type_list[property->length_type], + ply_type_list[property->value_type], + property->name) <= 0) goto error; + } } else { - if (fprintf(ply->fp, "property %s %s\n", + if (ply->in_memory) { + sprintf(buffer, "property %s %s\n", ply_type_list[property->type], - property->name) <= 0) goto error; + property->name); + if (ply_store_buffer_in_memory(ply, buffer) == 0) goto error; + } else { + if (fprintf(ply->fp, "property %s %s\n", + ply_type_list[property->type], + property->name) <= 0) goto error; + } } } } - return fprintf(ply->fp, "end_header\n") > 0; + if (ply->in_memory) { + return ply_store_buffer_in_memory(ply, "end_header\n") > 0; + } else { + return fprintf(ply->fp, "end_header\n") > 0; + } error: ply_ferror(ply, "Error writing to file"); return 0; @@ -681,8 +825,13 @@ int ply_write(p_ply ply, double value) { } while (ply->welement < ply->nelements && !element->ninstances); } if (ply->storage_mode == PLY_ASCII) { - return (!spaceafter || putc(' ', ply->fp) > 0) && - (!breakafter || putc('\n', ply->fp) > 0); + if (ply->in_memory) { + return (!spaceafter || ply_store_buffer_in_memory(ply, " ") > 0) && + (!breakafter || ply_store_buffer_in_memory(ply, "\n") > 0); + } else { + return (!spaceafter || putc(' ', ply->fp) > 0) && + (!breakafter || putc('\n', ply->fp) > 0); + } } else { return 1; } @@ -690,16 +839,28 @@ int ply_write(p_ply ply, double value) { int ply_close(p_ply ply) { long i; - assert(ply && ply->fp); + assert(ply); + if (!ply->in_memory) { + assert(ply->fp); + } assert(ply->element || ply->nelements == 0); assert(!ply->element || ply->nelements > 0); /* write last chunk to file */ - if (ply->io_mode == PLY_WRITE && - fwrite(ply->buffer, 1, ply->buffer_last, ply->fp) < ply->buffer_last) { - ply_ferror(ply, "Error closing up"); - return 0; + if (ply->io_mode == PLY_WRITE) { + if (ply->in_memory) { + if (ply->buffer_last > 0) { + memcpy(ply->store_memory, ply->buffer, ply->buffer_last); + ply->store_memory += ply->buffer_last; + *(ply->store_memory_size) += ply->buffer_last; + } + } else { + if (fwrite(ply->buffer, 1, ply->buffer_last, ply->fp) < ply->buffer_last) { + ply_ferror(ply, "Error closing up"); + return 0; + } + } } - if (ply->own_fp) fclose(ply->fp); + if (!ply->in_memory && ply->own_fp) fclose(ply->fp); /* free all memory used by handle */ if (ply->element) { for (i = 0; i < ply->nelements; i++) { @@ -955,7 +1116,10 @@ static int ply_check_word(p_ply ply) { static int ply_read_word(p_ply ply) { size_t t = 0; - assert(ply && ply->fp && ply->io_mode == PLY_READ); + assert(ply && ply->io_mode == PLY_READ); + if (!ply->in_memory) { + assert(ply->fp); + } /* skip leading blanks */ while (1) { t = strspn(BFIRST(ply), " \n\r\t"); @@ -1012,7 +1176,10 @@ static int ply_check_line(p_ply ply) { static int ply_read_line(p_ply ply) { const char *end = NULL; - assert(ply && ply->fp && ply->io_mode == PLY_READ); + assert(ply && ply->io_mode == PLY_READ); + if (!ply->in_memory) { + assert(ply->fp); + } /* look for a end of line */ end = strchr(BFIRST(ply), '\n'); /* if we didn't reach the end of the buffer, we are done */ @@ -1048,7 +1215,10 @@ static int ply_read_line(p_ply ply) { static int ply_read_chunk(p_ply ply, void *anybuffer, size_t size) { char *buffer = (char *) anybuffer; size_t i = 0; - assert(ply && ply->fp && ply->io_mode == PLY_READ); + assert(ply && ply->io_mode == PLY_READ); + if (!ply->in_memory) { + assert(ply->fp); + } assert(ply->buffer_first <= ply->buffer_last); while (i < size) { if (ply->buffer_first < ply->buffer_last) { @@ -1057,7 +1227,13 @@ static int ply_read_chunk(p_ply ply, void *anybuffer, size_t size) { i++; } else { ply->buffer_first = 0; - ply->buffer_last = fread(ply->buffer, 1, BUFFERSIZE, ply->fp); + if (ply->in_memory) { + memcpy(ply->buffer, ply->load_memory, BUFFERSIZE); + ply->load_memory += BUFFERSIZE; + ply->buffer_last = BUFFERSIZE; + } else { + ply->buffer_last = fread(ply->buffer, 1, BUFFERSIZE, ply->fp); + } if (ply->buffer_last <= 0) return 0; } } @@ -1067,7 +1243,10 @@ static int ply_read_chunk(p_ply ply, void *anybuffer, size_t size) { static int ply_write_chunk(p_ply ply, void *anybuffer, size_t size) { char *buffer = (char *) anybuffer; size_t i = 0; - assert(ply && ply->fp && ply->io_mode == PLY_WRITE); + assert(ply && ply->io_mode == PLY_WRITE); + if (!ply->in_memory) { + assert(ply->fp); + } assert(ply->buffer_last <= BUFFERSIZE); while (i < size) { if (ply->buffer_last < BUFFERSIZE) { @@ -1076,8 +1255,14 @@ static int ply_write_chunk(p_ply ply, void *anybuffer, size_t size) { i++; } else { ply->buffer_last = 0; - if (fwrite(ply->buffer, 1, BUFFERSIZE, ply->fp) < BUFFERSIZE) - return 0; + if (ply->in_memory) { + memcpy(ply->store_memory, ply->buffer, BUFFERSIZE); + ply->store_memory += BUFFERSIZE; + *(ply->store_memory_size) += BUFFERSIZE; + } else { + if (fwrite(ply->buffer, 1, BUFFERSIZE, ply->fp) < BUFFERSIZE) + return 0; + } } } return 1; @@ -1108,6 +1293,19 @@ static void ply_reverse(void *anydata, size_t size) { } } +static int ply_store_buffer_in_memory(p_ply ply, char *buffer) { + assert(ply && ply->io_mode == PLY_WRITE && ply->store_memory); + size_t length = strlen(buffer); + if (*ply->store_memory_size + length > ply->store_buffer_size) { + ply_ferror(ply, "The store buffer is too small. Use a bigger one!"); + return 0; + } + memcpy(ply->store_memory, buffer, length); + ply->store_memory += length; + *(ply->store_memory_size) += length; + return length > 0; +} + static void ply_init(p_ply ply) { ply->element = NULL; ply->nelements = 0; @@ -1192,7 +1390,10 @@ static p_ply_property ply_grow_property(p_ply ply, p_ply_element element) { } static int ply_read_header_format(p_ply ply) { - assert(ply && ply->fp && ply->io_mode == PLY_READ); + assert(ply && ply->io_mode == PLY_READ); + if (!ply->in_memory) { + assert(ply->fp); + } if (strcmp(BWORD(ply), "format")) return 0; if (!ply_read_word(ply)) return 0; ply->storage_mode = ply_find_string(BWORD(ply), ply_storage_mode_list); @@ -1208,7 +1409,10 @@ static int ply_read_header_format(p_ply ply) { } static int ply_read_header_comment(p_ply ply) { - assert(ply && ply->fp && ply->io_mode == PLY_READ); + assert(ply && ply->io_mode == PLY_READ); + if (!ply->in_memory) { + assert(ply->fp); + } if (strcmp(BWORD(ply), "comment")) return 0; if (!ply_read_line(ply)) return 0; if (!ply_add_comment(ply, BLINE(ply))) return 0; @@ -1217,7 +1421,10 @@ static int ply_read_header_comment(p_ply ply) { } static int ply_read_header_obj_info(p_ply ply) { - assert(ply && ply->fp && ply->io_mode == PLY_READ); + assert(ply && ply->io_mode == PLY_READ); + if (!ply->in_memory) { + assert(ply->fp); + } if (strcmp(BWORD(ply), "obj_info")) return 0; if (!ply_read_line(ply)) return 0; if (!ply_add_obj_info(ply, BLINE(ply))) return 0; @@ -1256,7 +1463,10 @@ static int ply_read_header_property(p_ply ply) { static int ply_read_header_element(p_ply ply) { p_ply_element element = NULL; long dummy; - assert(ply && ply->fp && ply->io_mode == PLY_READ); + assert(ply && ply->io_mode == PLY_READ); + if (!ply->in_memory) { + assert(ply->fp); + } if (strcmp(BWORD(ply), "element")) return 0; /* allocate room for new element */ element = ply_grow_element(ply); @@ -1325,42 +1535,90 @@ static int ply_type_check(void) { * ---------------------------------------------------------------------- */ static int oascii_int8(p_ply ply, double value) { if (value > PLY_INT8_MAX || value < PLY_INT8_MIN) return 0; - return fprintf(ply->fp, "%d", (t_ply_int8) value) > 0; + if (ply->in_memory) { + char buffer[WORDSIZE]; + snprintf(buffer, WORDSIZE, "%d", (t_ply_int8) value); + return ply_store_buffer_in_memory(ply, buffer); + } else { + return fprintf(ply->fp, "%d", (t_ply_int8) value) > 0; + } } static int oascii_uint8(p_ply ply, double value) { if (value > PLY_UINT8_MAX || value < 0) return 0; - return fprintf(ply->fp, "%d", (t_ply_uint8) value) > 0; + if (ply->in_memory) { + char buffer[WORDSIZE]; + snprintf(buffer, WORDSIZE, "%d", (t_ply_uint8) value); + return ply_store_buffer_in_memory(ply, buffer); + } else { + return fprintf(ply->fp, "%d", (t_ply_uint8) value) > 0; + } } static int oascii_int16(p_ply ply, double value) { if (value > PLY_INT16_MAX || value < PLY_INT16_MIN) return 0; - return fprintf(ply->fp, "%d", (t_ply_int16) value) > 0; + if (ply->in_memory) { + char buffer[WORDSIZE]; + snprintf(buffer, WORDSIZE, "%d", (t_ply_int16) value); + return ply_store_buffer_in_memory(ply, buffer); + } else { + return fprintf(ply->fp, "%d", (t_ply_int16) value) > 0; + } } static int oascii_uint16(p_ply ply, double value) { if (value > PLY_UINT16_MAX || value < 0) return 0; - return fprintf(ply->fp, "%d", (t_ply_uint16) value) > 0; + if (ply->in_memory) { + char buffer[WORDSIZE]; + snprintf(buffer, WORDSIZE, "%d", (t_ply_uint16) value); + return ply_store_buffer_in_memory(ply, buffer); + } else { + return fprintf(ply->fp, "%d", (t_ply_uint16) value) > 0; + } } static int oascii_int32(p_ply ply, double value) { if (value > PLY_INT32_MAX || value < PLY_INT32_MIN) return 0; - return fprintf(ply->fp, "%d", (t_ply_int32) value) > 0; + if (ply->in_memory) { + char buffer[WORDSIZE]; + snprintf(buffer, WORDSIZE, "%d", (t_ply_int32) value); + return ply_store_buffer_in_memory(ply, buffer); + } else { + return fprintf(ply->fp, "%d", (t_ply_int32) value) > 0; + } } static int oascii_uint32(p_ply ply, double value) { if (value > PLY_UINT32_MAX || value < 0) return 0; - return fprintf(ply->fp, "%d", (t_ply_uint32) value) > 0; + if (ply->in_memory) { + char buffer[WORDSIZE]; + snprintf(buffer, WORDSIZE, "%d", (t_ply_uint32) value); + return ply_store_buffer_in_memory(ply, buffer); + } else { + return fprintf(ply->fp, "%d", (t_ply_uint32) value) > 0; + } } static int oascii_float32(p_ply ply, double value) { if (value < -FLT_MAX || value > FLT_MAX) return 0; - return fprintf(ply->fp, "%g", (float) value) > 0; + if (ply->in_memory) { + char buffer[WORDSIZE]; + snprintf(buffer, WORDSIZE, "%g", (float) value); + return ply_store_buffer_in_memory(ply, buffer); + } else { + return fprintf(ply->fp, "%g", (float) value) > 0; + } } static int oascii_float64(p_ply ply, double value) { if (value < -DBL_MAX || value > DBL_MAX) return 0; - return fprintf(ply->fp, "%g", value) > 0; + if (ply->in_memory) { + char buffer[WORDSIZE]; + snprintf(buffer, WORDSIZE, "%g", value); + return ply_store_buffer_in_memory(ply, buffer); + } else { + return fprintf(ply->fp, "%g", value) > 0; + } } static int obinary_int8(p_ply ply, double value) { diff --git a/rplymemory.h b/rplymemory.h new file mode 100644 index 0000000..f2c4cb3 --- /dev/null +++ b/rplymemory.h @@ -0,0 +1,73 @@ +#ifndef RPLY_MEMORY_H +#define RPLY_MEMORY_H +/* ---------------------------------------------------------------------- + * RPly library, read/write PLY files + * Diego Nehab, IMPA + * http://www.impa.br/~diego/software/rply + * + * In-memory read/write of PLY files + * Patryk Kiepas + * https://github.com/quepas + * + * This library is distributed under the MIT License. See notice + * at the end of this file. + * ---------------------------------------------------------------------- */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ---------------------------------------------------------------------- + * Opens a PLY file for reading from memory (buffer of const char[]) + * + * buffer : file in the memory for reading + * error_cb : error callback function + * idata,pdata : contextual information available to users + * + * Returns 1 if successful, 0 otherwise + * ---------------------------------------------------------------------- */ +p_ply ply_open_from_memory(const char *buffer, p_ply_error_cb error_cb, long idata, void *pdata); + +/* ---------------------------------------------------------------------- + * Creates new PLY file for writing in memory (to a buffer of char[]) + * + * buffer : memory for storing the file + * buffer_size : size of pre-allocated memory for the buffer + * ply_size : actual size of the PLY file in memory + * storage_mode : file format mode + * error_cb : error callback function + * idata, pdata : contextual information available to users + * + * Returns handle to PLY file if successful, NULL otherwise + * ---------------------------------------------------------------------- */ +p_ply ply_create_to_memory(char *buffer, size_t buffer_size, size_t *ply_size, e_ply_storage_mode storage_mode, p_ply_error_cb error_cb, long idata, void *pdata); + +#ifdef __cplusplus +} +#endif + +#endif /* RPLY_MEMORY_H */ + +/* ---------------------------------------------------------------------- + * Copyright (C) 2003-2015 Diego Nehab. All rights reserved. + * Copyright (C) 2020 Patryk Kiepas + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ---------------------------------------------------------------------- */