/*****************************************************************************\ * Copyright (c) 2004 Mark Aylett * * * * 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. * \*****************************************************************************/ static const char rcsid[] = "$Id: mar_seq_c.c,v 1.5 2004/12/14 13:09:23 marayl Exp $"; #include "mar_seq_c.h" #include "mar_debug_c.h" #include "mar_format_c.h" #include "mar_mfile_c.h" #include #include #include #if !defined(WIN32) #include #else /* WIN32 */ #include "mar_windows_c.h" #endif /* WIN32 */ typedef const struct mar_impl { int (*free_)(mar_seq_t); void* (*resize_)(mar_seq_t, size_t, size_t); int (*sync_)(mar_seq_t); void* (*addr_)(mar_seq_t); size_t (*size_)(mar_seq_t); void* (*tail_)(mar_seq_t); } * mar_impl_t; struct mar_seq { size_t offset_, len_; mar_impl_t impl_; }; typedef struct mar_memseq { struct mar_seq seq_; void* addr_; size_t len_; }* mar_memseq_t; typedef struct mar_mfileseq { struct mar_seq seq_; mar_mfile_t mfile_; }* mar_mfileseq_t; static int mar_dofreemem(mar_seq_t seq) { mar_memseq_t memseq = (mar_memseq_t)seq; if (memseq->addr_) free(memseq->addr_); free(memseq); return 0; } static void* mar_doresizemem(mar_seq_t seq, size_t size, size_t tail) { mar_memseq_t memseq = (mar_memseq_t)seq; void* addr; if (!memseq->addr_) { if (!(addr = calloc(size, 1))) return NULL; memseq->addr_ = addr; memseq->len_ = size; } else if (size > memseq->len_) { if (!(addr = realloc(memseq->addr_, size))) return NULL; bzero((mar_byte_t*)addr + memseq->len_, size - memseq->len_); memmove((mar_byte_t*)addr + (size - tail), (mar_byte_t*)addr + (memseq->len_ - tail), tail); memseq->addr_ = addr; memseq->len_ = size; } else if (size < memseq->len_) { memmove((mar_byte_t*)memseq->addr_ + (size - tail), (mar_byte_t*)memseq->addr_ + (memseq->len_ - tail), tail); memseq->len_ = size; } return memseq->addr_; } static int mar_dosyncmem(mar_seq_t seq) { return 0; } static void* mar_domemaddr(mar_seq_t seq) { mar_memseq_t memseq = (mar_memseq_t)seq; return memseq->addr_; } static size_t mar_domemsize(mar_seq_t seq) { mar_memseq_t memseq = (mar_memseq_t)seq; return memseq->len_; } static void* mar_domemtail(mar_seq_t seq) { mar_memseq_t memseq = (mar_memseq_t)seq; return (mar_byte_t*)memseq + sizeof(struct mar_memseq); } static const struct mar_impl memimpl = { mar_dofreemem, mar_doresizemem, mar_dosyncmem, mar_domemaddr, mar_domemsize, mar_domemtail }; static int mar_dofreemfile(mar_seq_t seq) { mar_mfileseq_t mfileseq = (mar_mfileseq_t)seq; return mar_closemfile_(mfileseq->mfile_); } static void* mar_doresizemfile(mar_seq_t seq, size_t size, size_t tail) { mar_mfileseq_t mfileseq = (mar_mfileseq_t)seq; size_t len = mar_mfilesize_(mfileseq->mfile_); void* addr; if (size > len) { if (!(addr = mar_mapmfile_(mfileseq->mfile_, size))) return NULL; memmove((mar_byte_t*)addr + (size - tail), (mar_byte_t*)addr + (len - tail), tail); return addr; } addr = mar_mfileaddr_(mfileseq->mfile_); if (size < len) { memmove((mar_byte_t*)addr + (size - tail), (mar_byte_t*)addr + (len - tail), tail); if (-1 == mar_truncatemfile_(mfileseq->mfile_, size)) return NULL; } return addr; } static int mar_dosyncmfile(mar_seq_t seq) { mar_mfileseq_t mfileseq = (mar_mfileseq_t)seq; return mar_syncmfile_(mfileseq->mfile_); } static void* mar_domfileaddr(mar_seq_t seq) { mar_mfileseq_t mfileseq = (mar_mfileseq_t)seq; return mar_mfileaddr_(mfileseq->mfile_); } static size_t mar_domfilesize(mar_seq_t seq) { mar_mfileseq_t mfileseq = (mar_mfileseq_t)seq; return mar_mfilesize_(mfileseq->mfile_); } static void* mar_domfiletail(mar_seq_t seq) { mar_mfileseq_t mfileseq = (mar_mfileseq_t)seq; return (mar_byte_t*)mar_mfiletail_(mfileseq->mfile_) + sizeof(struct mar_mfileseq); } static const struct mar_impl mfileimpl = { mar_dofreemfile, mar_doresizemfile, mar_dosyncmfile, mar_domfileaddr, mar_domfilesize, mar_domfiletail }; MAR_EXTERN int mar_freeseq_(mar_seq_t seq) { return (*seq->impl_->free_)(seq); } MAR_EXTERN int mar_copyseq_(mar_seq_t dst, mar_seq_t src) { size_t size = mar_seqsize_(src); void* addr; if (-1 == mar_setregion_(src, 0, size)) return -1; if (-1 == mar_setregion_(dst, 0, mar_seqsize_(dst))) return -1; if (!(addr = mar_resizeseq_(dst, size))) return -1; memcpy(addr, mar_seqaddr_(src), size); return 0; } MAR_EXTERN mar_seq_t mar_createseq_(size_t tail) { mar_memseq_t memseq; if (!(memseq = (mar_memseq_t)malloc(sizeof(struct mar_memseq) + tail))) return NULL; memseq->seq_.offset_ = 0; memseq->seq_.len_ = 0; memseq->seq_.impl_ = &memimpl; memseq->addr_ = NULL; memseq->len_ = 0; return (mar_seq_t)memseq; } MAR_EXTERN mar_seq_t mar_openseq_(const char* path, int flags, mode_t mode, size_t tail) { size_t size; mar_mfileseq_t mfileseq; mar_mfile_t mfile = mar_openmfile_(path, flags, mode, sizeof(struct mar_mfileseq) + tail); if (!mfile) return NULL; size = mar_mfileresvd_(mfile); if (size && !mar_mapmfile_(mfile, size)) goto fail; mfileseq = (mar_mfileseq_t)mar_mfiletail_(mfile); mfileseq->seq_.offset_ = 0; mfileseq->seq_.len_ = 0; mfileseq->seq_.impl_ = &mfileimpl; mfileseq->mfile_ = mfile; return (mar_seq_t)mfileseq; fail: mar_closemfile_(mfile); return NULL; } MAR_EXTERN void* mar_resizeseq_(mar_seq_t seq, size_t size) { void* addr; size_t total, tail; total = (*seq->impl_->size_)(seq); tail = total - (seq->offset_ + seq->len_); total += (size - seq->len_); if (!(addr = (*seq->impl_->resize_)(seq, total, tail))) return NULL; seq->len_ = size; return (mar_byte_t*)addr + seq->offset_; } MAR_EXTERN int mar_setregion_(mar_seq_t seq, size_t offset, size_t len) { size_t total = (*seq->impl_->size_)(seq); if (total < (offset + len)) { MAR_DEBUG_MSG("Failed to set region:" " Sequence overrun\n"); errno = EINVAL; return -1; } seq->offset_ = offset; seq->len_ = len; return 0; } MAR_EXTERN int mar_syncseq_(mar_seq_t seq) { return (*seq->impl_->sync_)(seq); } MAR_EXTERN void* mar_seqaddr_(mar_seq_t seq) { return (mar_byte_t*)(*seq->impl_->addr_)(seq) + seq->offset_; } MAR_EXTERN size_t mar_seqsize_(mar_seq_t seq) { return (*seq->impl_->size_)(seq); } MAR_EXTERN void* mar_seqtail_(mar_seq_t seq) { return (*seq->impl_->tail_)(seq); }