/* ========================================================================= zchunk - work with memory chunks ------------------------------------------------------------------------- Copyright (c) 1991-2013 iMatix Corporation Copyright other contributors as noted in the AUTHORS file. This file is part of CZMQ, the high-level C binding for 0MQ: http://czmq.zeromq.org. This is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTA- BILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see http://www.gnu.org/licenses/. =========================================================================*/ /* @header The zchunk class works with variable sized blobs. Not as efficient as ØMQ's messages but they do less weirdness and so are easier to understand. The chunk class has methods to read and write chunks from disk. @discuss @end */ #include "../include/czmq.h" // Structure of our class struct _zchunk_t { size_t size; // Current size of data part size_t max_size; // Maximum allocated size byte *data; // Data part follows here }; // -------------------------------------------------------------------------- // Constructor zchunk_t * zchunk_new (const void *data, size_t size) { zchunk_t *self = (zchunk_t *) zmalloc (sizeof (zchunk_t) + size); if (self) { self->max_size = size; self->data = (byte *) self + sizeof (zchunk_t); if (data) { self->size = size; memcpy (self->data, data, size); } else self->size = 0; } return self; } // -------------------------------------------------------------------------- // Destroy a chunk void zchunk_destroy (zchunk_t **self_p) { assert (self_p); if (*self_p) { zchunk_t *self = *self_p; // If data was reallocated independently, free it independently if (self->data != (byte *) self + sizeof (zchunk_t)) free (self->data); free (self); *self_p = NULL; } } // -------------------------------------------------------------------------- // Resizes chunk max_size as requested; chunk_cur size is set to zero void zchunk_resize (zchunk_t *self, size_t size) { // If data was reallocated independently, free it independently if (self->data != (byte *) self + sizeof (zchunk_t)) free (self->data); self->data = (byte *) zmalloc (size); self->max_size = size; self->size = 0; } // -------------------------------------------------------------------------- // Set chunk data from user-supplied data; truncate if too large // Returns actual size of chunk size_t zchunk_set (zchunk_t *self, const void *data, size_t size) { assert (self); if (size > self->max_size) size = self->max_size; memcpy (self->data, data, size); self->size = size; return size; } // -------------------------------------------------------------------------- // Fill chunk data from user-supplied octet // Returns actual size of chunk size_t zchunk_fill (zchunk_t *self, byte filler, size_t size) { assert (self); if (size > self->max_size) size = self->max_size; memset (self->data, filler, size); self->size = size; return size; } // -------------------------------------------------------------------------- // Return chunk cur size size_t zchunk_size (zchunk_t *self) { assert (self); return self->size; } // -------------------------------------------------------------------------- // Return chunk max size size_t zchunk_max_size (zchunk_t *self) { assert (self); return self->max_size; } // -------------------------------------------------------------------------- // Return chunk data byte * zchunk_data (zchunk_t *self) { assert (self); return self->data; } // -------------------------------------------------------------------------- // Read chunk from an open file descriptor zchunk_t * zchunk_read (FILE *handle, size_t bytes) { zchunk_t *self = zchunk_new (NULL, bytes); self->size = fread (self->data, 1, bytes, handle); return self; } // -------------------------------------------------------------------------- // Write chunk to an open file descriptor int zchunk_write (zchunk_t *self, FILE *handle) { size_t items = fwrite (self->data, 1, self->size, handle); int rc = (items < self->size)? -1: 0; return rc; } // -------------------------------------------------------------------------- // Self test of this class int zchunk_test (bool verbose) { printf (" * zchunk: "); // @selftest zchunk_t *chunk = zchunk_new ("1234567890", 10); assert (chunk); assert (zchunk_size (chunk) == 10); assert (memcmp (zchunk_data (chunk), "1234567890", 10) == 0); zchunk_destroy (&chunk); // @end printf ("OK\n"); return 0; }