Skip to content

Instantly share code, notes, and snippets.

@RadAd
Created April 24, 2025 01:03
Show Gist options
  • Save RadAd/3599dc0928c4e285b1339c818390ef3e to your computer and use it in GitHub Desktop.
Save RadAd/3599dc0928c4e285b1339c818390ef3e to your computer and use it in GitHub Desktop.
Memory based file
#include "memfile.h"
#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <io.h>
#include <fcntl.h>
#include <process.h>
typedef struct pipereadthreaddatatag
{
FILE* fr;
mempipecb cb;
void* param;
} pipereadthreaddata;
static unsigned __stdcall pipereadthread(void* pArguments)
{
pipereadthreaddata* data = (pipereadthreaddata*) pArguments ;
char buf[1024];
size_t i;
while (i = fread(buf, sizeof(buf[0]), ARRAYSIZE(buf), data->fr))
data->cb(buf, i, data->param);
free(data);
return 0;
}
static FILE* tofile(_In_ HANDLE hFile, _In_ int flags, _In_z_ LPCTSTR _Mode)
{
const int fd = _open_osfhandle((intptr_t) hFile, flags);
if (fd < 0)
return NULL;
return _tfdopen(fd, _Mode);
}
int fpipe(FILE** pfr, FILE** pfw)
{
const DWORD nSizePipe = 0;
HANDLE hReadPipe, hWritePipe;
if (!CreatePipe(&hReadPipe, &hWritePipe, NULL, nSizePipe))
return EOF;
*pfr = tofile(hReadPipe, _O_RDONLY, _T("r"));
if (!*pfr)
{
CloseHandle(hReadPipe);
CloseHandle(hWritePipe);
return EOF;
}
*pfw = tofile(hWritePipe, _O_WRONLY, _T("w"));
if (!*pfw)
{
fclose(*pfr);
CloseHandle(hWritePipe);
return EOF;
}
return 0;
}
FILE* fmemopipe(HANDLE* phThread, mempipecb cb, void* param)
{
const DWORD nSizePipe = 0;
const unsigned int nStackSizeThread = 0;
FILE* fr, * fw;
if (fpipe(&fr, &fw) != 0)
return NULL;
pipereadthreaddata* data = (pipereadthreaddata*) malloc(sizeof(pipereadthreaddata));
if (!data)
{
fclose(fr);
fclose(fw);
return NULL;
}
data->fr = fr;
data->cb = cb;
data->param = param;
HANDLE hThread = (HANDLE)_beginthreadex(NULL, nStackSizeThread,
pipereadthread, data, 0, NULL);
if (!hThread)
{
free(data);
fclose(fw);
fclose(fr);
return NULL;
}
if (phThread)
*phThread = hThread;
return fw;
}
#pragma once
#include <stdio.h>
#include <windows.h>
typedef void(*mempipecb)(const void* buf, size_t size, void* param);
int fpipe(FILE** pfr, FILE** pfw);
FILE* fmemopipe(HANDLE* phThread, mempipecb cb, void* param);
#include <tchar.h>
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
#include <assert.h>
#include "memfile.h"
#include "radvector.h"
void process(const void* buf, size_t size, void* param)
{
vector* rdbuf = (vector*)param;
VectorAppend(rdbuf, buf, size);
}
int _tmain(const int argc, const TCHAR* const argv[])
{
HANDLE hThread = NULL;
vector readbuf = VectorCreate(1024);
FILE* f = fmemopipe(&hThread, process, &readbuf);
if (f)
{
char buf[] = "hello";
fwrite(buf, sizeof(buf[0]), ARRAYSIZE(buf), f);
fclose(f);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
assert(strcmp(buf, readbuf.buf) == 0);
}
return EXIT_SUCCESS;
}
#pragma once
#include <assert.h>
#include <stdbool.h>
typedef struct vectortag
{
char* buf;
size_t size;
size_t capacity;
} vector;
bool VectorGrow(vector* v, const size_t newcapacity)
{
assert(newcapacity > v->capacity);
char* newbuf = (char*)realloc(v->buf, newcapacity);
if (!newbuf)
return false;
v->buf = newbuf;
v->capacity = newcapacity;
assert(v->capacity >= v->size);
return true;
}
vector VectorCreate(size_t capacity)
{
vector v;
v.buf = NULL;
v.size = 0;
v.capacity = 0;
VectorGrow(&v, capacity);
assert(v.capacity >= v.size);
return v;
}
void VectorFree(vector* v)
{
free(v->buf);
}
bool VectorAppend(vector* v, const char* buf, size_t size)
{
const size_t space = v->capacity - v->size;
if (space < size)
{
if (!VectorGrow(v, v->capacity * 2))
return false;
}
memcpy(v->buf + v->size, buf, size);
v->size += size;
return true;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment