universe@56: #include "memstream.h" universe@56: #include universe@56: #include universe@56: #include universe@56: universe@56: struct _UcxMemstream { universe@56: void *space; universe@56: size_t pos; universe@56: size_t length; universe@56: _Bool autofree; universe@56: }; universe@56: universe@56: UcxMemstream *ucx_memopen(void* space, size_t length) { universe@56: UcxMemstream *stream = (UcxMemstream*) malloc(sizeof(UcxMemstream)); universe@56: if (stream) { universe@56: if (!space) { universe@56: stream->space = malloc(length); universe@56: if (!stream->space) { universe@56: free(stream); universe@56: return NULL; universe@56: } universe@56: memset(stream->space, 0, length); universe@56: stream->autofree = 1; universe@56: } else { universe@56: stream->space = space; universe@56: stream->autofree = 0; universe@56: } universe@56: stream->length = length; universe@56: universe@56: stream->pos = 0; universe@56: } universe@56: universe@56: return stream; universe@56: } universe@56: universe@56: void ucx_memclose(UcxMemstream *stream) { universe@56: if (stream->autofree) { universe@56: free(stream->space); universe@56: } universe@56: free(stream); universe@56: } universe@56: universe@56: int ucx_memseek(UcxMemstream *stream, long offset, int whence) { universe@56: size_t npos; universe@56: switch (whence) { universe@56: case SEEK_SET: universe@56: npos = 0; universe@56: break; universe@56: case SEEK_CUR: universe@56: npos = stream->pos; universe@56: break; universe@56: case SEEK_END: universe@56: npos = strlen(stream->space); universe@56: break; universe@56: } universe@56: universe@56: npos += offset; universe@56: universe@56: if (npos < 0 || npos > stream->length) { universe@56: return -1; universe@56: } else { universe@56: stream->pos = npos; universe@56: return 0; universe@56: } universe@56: universe@56: } universe@56: universe@56: int ucx_memeof(UcxMemstream *stream) { universe@56: return stream->pos >= stream->length; universe@56: } universe@56: universe@56: int ucx_memoverflow(UcxMemstream *stream) { universe@56: return stream->pos > stream->length; universe@56: } universe@56: universe@56: size_t ucx_memtell(UcxMemstream *stream) { universe@56: return stream->pos; universe@56: } universe@56: universe@56: size_t ucx_memio(void* d, size_t s, size_t n, UcxMemstream *m, _Bool read) { universe@56: size_t len; universe@56: if (m->pos + s*n > m->length) { universe@56: if (ucx_memoverflow(m)) { universe@56: len = 0; universe@56: } else { universe@56: len = m->length - m->pos; universe@56: if (s > 1) len -= len%s; universe@56: } universe@56: } else { universe@56: len = s*n; universe@56: } universe@56: universe@56: if (len == 0) { universe@56: return 0; universe@56: } universe@56: universe@56: if (read) { universe@56: memcpy(d, m->space+m->pos, len); universe@56: } else { universe@56: memcpy(m->space+m->pos, d, len); universe@56: } universe@56: m->pos += len; universe@56: universe@56: return len; universe@56: } universe@56: universe@56: int ucx_memputc(UcxMemstream *stream, int c) { universe@56: if (ucx_memeof(stream)) { universe@56: return EOF; universe@56: } else { universe@56: c &= 0xFF; universe@56: ((char*)(stream->space))[stream->pos] = (char) c; universe@56: stream->pos++; universe@56: return c; universe@56: } universe@56: } universe@56: universe@56: int ucx_memgetc(UcxMemstream *stream) { universe@56: if (ucx_memeof(stream)) { universe@56: return EOF; universe@56: } else { universe@56: int c = ((char*)(stream->space))[stream->pos]; universe@56: stream->pos++; universe@56: return c; universe@56: } universe@56: } universe@56: universe@56: int ucx_memprintf(UcxMemstream *stream, const char* format, ...) { universe@56: va_list v; universe@56: va_start(v, format); universe@56: int r = vsprintf(stream->space+stream->pos, format, v); universe@56: va_end(v); universe@56: universe@56: stream->pos += r; universe@56: universe@56: return r; universe@56: } universe@56: universe@56: int ucx_memscanf(UcxMemstream *stream, const char* format, ...) { universe@56: universe@56: /* TODO: vsscanf returns the number of fields read, universe@56: * we need the number of bytes */ universe@56: universe@56: va_list v; universe@56: va_start(v, format); universe@56: int r = vsscanf(stream->space+stream->pos, format, v); universe@56: va_end(v); universe@56: universe@56: stream->pos += r; universe@56: universe@56: return r; universe@56: }