Files
filza27.2/XPF/external/ChOma/src/MemoryStream.c
T

220 lines
6.6 KiB
C

#include "MemoryStream.h"
#include "Util.h"
int memory_stream_read(MemoryStream *stream, uint64_t offset, size_t size, void *outBuf)
{
if (stream->read) {
int ret = stream->read(stream, offset, size, outBuf);
if (ret != size) { return -1; }
return 0;
}
return -1;
}
int memory_stream_write(MemoryStream *stream, uint64_t offset, size_t size, const void *inBuf)
{
if (stream->write) {
int ret = stream->write(stream, offset, size, inBuf);
if (ret != size) { return -1; }
return 0;
}
return -1;
}
int memory_stream_insert(MemoryStream *stream, uint64_t offset, size_t size, const void *inBuf)
{
if (!(stream->flags & MEMORY_STREAM_FLAG_MUTABLE)) goto fail;
size_t streamSize = memory_stream_get_size(stream);
if (memory_stream_expand(stream, 0, size) != 0) goto fail;
if (memory_stream_copy_data(stream, offset, stream, offset + size, streamSize-offset) != 0) goto fail;
if (memory_stream_write(stream, offset, size, inBuf) != 0) goto fail;
return 0;
fail:
printf("Error: memory_stream_insert failed\n");
return -1;
}
int memory_stream_delete(MemoryStream *stream, uint64_t offset, size_t size)
{
if (size == 0) return 0;
if (!(stream->flags & MEMORY_STREAM_FLAG_MUTABLE)) goto fail;
size_t streamSize = memory_stream_get_size(stream);
if (memory_stream_copy_data(stream, offset+size, stream, offset, streamSize-(offset+size)) != 0) goto fail;
if (memory_stream_trim(stream, 0, size) != 0) goto fail;
return 0;
fail:
printf("Error: memory_stream_delete failed\n");
return -1;
}
int memory_stream_read_string(MemoryStream *stream, uint64_t offset, char **outString)
{
size_t size = 0;
char c = 1;
while (c != 0) {
int r = memory_stream_read(stream, offset+size, sizeof(c), &c);
if (r != 0) return r;
size++;
}
*outString = malloc(size+1);
return memory_stream_read(stream, offset, size+1, *outString);
}
int memory_stream_write_string(MemoryStream *stream, uint64_t offset, const char *string)
{
size_t size = strlen(string) + 1;
return memory_stream_write(stream, offset, size, string);
}
size_t memory_stream_get_size(MemoryStream *stream)
{
if (stream->getSize) {
size_t sizeOut;
if (stream->getSize(stream, &sizeOut) == 0) return sizeOut;
}
return MEMORY_STREAM_SIZE_INVALID;
}
uint8_t *memory_stream_get_raw_pointer(MemoryStream *stream)
{
if (stream->getRawPtr) {
return stream->getRawPtr(stream);
}
return NULL;
}
uint32_t memory_stream_get_flags(MemoryStream *stream)
{
return stream->flags;
}
void _memory_stream_clone(MemoryStream *clone, MemoryStream *stream)
{
clone->read = stream->read;
clone->write = stream->write;
clone->getSize = stream->getSize;
clone->getRawPtr = stream->getRawPtr;
clone->trim = stream->trim;
clone->expand = stream->expand;
clone->softclone = stream->softclone;
clone->hardclone = stream->hardclone;
clone->free = stream->free;
}
MemoryStream *memory_stream_softclone(MemoryStream *stream)
{
if (stream->softclone) {
MemoryStream *clone = stream->softclone(stream);
if (clone) {
_memory_stream_clone(clone, stream);
return clone;
}
}
return NULL;
}
MemoryStream *memory_stream_hardclone(MemoryStream *stream)
{
if (stream->hardclone) {
MemoryStream *clone = stream->hardclone(stream);
if (clone) {
_memory_stream_clone(clone, stream);
return clone;
}
}
return NULL;
}
int memory_stream_trim(MemoryStream *stream, size_t trimAtStart, size_t trimAtEnd)
{
if (stream->trim) {
return stream->trim(stream, trimAtStart, trimAtEnd);
}
return -1;
}
int memory_stream_expand(MemoryStream *stream, size_t expandAtStart, size_t expandAtEnd)
{
if (stream->expand) {
return stream->expand(stream, expandAtStart, expandAtEnd);
}
return -1;
}
void memory_stream_free(MemoryStream *stream)
{
if (stream->free) {
stream->free(stream);
}
free(stream);
}
#define COPY_DATA_BUFFER_SIZE 0x4000
int memory_stream_copy_data(MemoryStream *originStream, uint64_t originOffset, MemoryStream *targetStream, uint64_t targetOffset, size_t size)
{
size_t originSize = memory_stream_get_size(originStream);
size_t targetSize = memory_stream_get_size(targetStream);
if (originSize == MEMORY_STREAM_SIZE_INVALID || targetSize == MEMORY_STREAM_SIZE_INVALID) {
printf("Error: memory_stream_copy_data failed, invalid size detected\n");
return -1;
}
if (originOffset + size > originSize) {
printf("Error: memory_stream_copy_data failed, originOffset OOB\n");
return -1;
}
if (targetOffset + size > targetSize && !(memory_stream_get_flags(targetStream) | MEMORY_STREAM_FLAG_AUTO_EXPAND)) {
printf("Error: memory_stream_copy_data failed, targetOffset OOB\n");
return -1;
}
bool backwards = (originStream == targetStream) && (targetOffset > originOffset);
uint8_t buffer[COPY_DATA_BUFFER_SIZE];
for (uint32_t copiedSize = 0; copiedSize < size; copiedSize += COPY_DATA_BUFFER_SIZE) {
uint32_t remainingSize = size - copiedSize;
uint32_t sizeToCopy = COPY_DATA_BUFFER_SIZE;
if (remainingSize < sizeToCopy) {
sizeToCopy = remainingSize;
}
uint64_t readOffset = backwards ? ((originOffset + (size - copiedSize)) - sizeToCopy) : (originOffset + copiedSize);
uint64_t writeOffset = backwards ? ((targetOffset + (size - copiedSize)) - sizeToCopy) : (targetOffset + copiedSize);
int rr = memory_stream_read(originStream, readOffset, sizeToCopy, buffer);
if (rr != 0) {
printf("Error: memory_stream_copy_data failed on memory_stream_read (%d)\n", rr);
return rr;
}
int wr = memory_stream_write(targetStream, writeOffset, sizeToCopy, buffer);
if (wr != 0) {
printf("Error: memory_stream_copy_data failed on memory_stream_write (%d)\n", wr);
return rr;
}
}
return 0;
}
int memory_stream_find_memory(MemoryStream *stream, uint64_t searchStartOffset, uint64_t searchEndOffset, void *bytes, void *mask, size_t nbytes, uint16_t alignment, uint64_t *foundOffsetOut)
{
__block int r = -1;
enumerate_range(searchStartOffset, searchEndOffset, alignment, nbytes, ^bool(uint64_t cur) {
uint8_t buf[nbytes];
memory_stream_read(stream, cur, nbytes, buf);
if (!memcmp_masked(buf, bytes, mask, nbytes)) {
*foundOffsetOut = cur;
r = 0;
return false;
}
return true;
});
return r;
}