parent
eab4b33a9a
commit
dd15ad3295
@ -0,0 +1,31 @@
|
||||
#ifndef _FSVEC_H
|
||||
#define _FSVEC_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#define restrict __restrict__
|
||||
#endif
|
||||
|
||||
// A simple file-backed back inserter
|
||||
typedef struct {
|
||||
FILE* backing;
|
||||
size_t len;
|
||||
} fvec_t;
|
||||
|
||||
int fvec_new(fvec_t* restrict obj, const char* path);
|
||||
void fvec_close(fvec_t* restrict obj);
|
||||
|
||||
int fvec_pop_end(fvec_t* restrict obj, size_t sz);
|
||||
void fvec_push_whole_buffer(fvec_t* restrict obj, const void* _buffer, size_t sz);
|
||||
int fvec_get_whole_buffer(const fvec_t* restrict obj, void* _buffer, size_t _sz);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#undef restrict
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FSVEC_H */
|
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <random>
|
||||
#include <string>
|
||||
|
||||
struct uuid //not to spec but idc
|
||||
{
|
||||
const static constexpr int SIZE=16;
|
||||
inline static uuid generate()
|
||||
{
|
||||
using namespace std;
|
||||
static thread_local random_device dev;
|
||||
static thread_local mt19937 rng(dev());
|
||||
uniform_int_distribution<int> dist(0, 15);
|
||||
constexpr const char hex[] = "0123456789abcdef";
|
||||
uuid id;
|
||||
for(int i=0;i<SIZE;i++) id.str[i] = hex[dist(rng)];
|
||||
id.str[SIZE] =0;
|
||||
return id;
|
||||
}
|
||||
inline operator const char*() const { return &str[0]; }
|
||||
inline operator const std::array<char, SIZE+1>&() const { return str; }
|
||||
|
||||
inline std::string to_string() const
|
||||
{
|
||||
return std::string(&str[0]);
|
||||
}
|
||||
private:
|
||||
inline uuid(){}
|
||||
std::array<char, SIZE+1> str;
|
||||
};
|
@ -0,0 +1,67 @@
|
||||
#include <unistd.h>
|
||||
#include <fsvec.h>
|
||||
#include <panic.h>
|
||||
|
||||
int fvec_new(fvec_t* restrict obj, const char* path)
|
||||
{
|
||||
obj->backing = fopen(path, "wb");
|
||||
if(!obj->backing) {
|
||||
perror("fvec_new(): Failed to open file");
|
||||
return 0;
|
||||
}
|
||||
obj->len=0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void fvec_close(fvec_t* restrict obj)
|
||||
{
|
||||
if(obj->backing) fclose(obj->backing);
|
||||
obj->backing=NULL;
|
||||
obj->len=0;
|
||||
}
|
||||
|
||||
int fvec_pop_end(fvec_t* restrict obj, size_t sz)
|
||||
{
|
||||
if(!obj->len) return 0;
|
||||
|
||||
if(ftruncate(fileno(obj->backing), (obj->len-=sz))<0) {
|
||||
perror("Failed to pop buffer");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void fvec_push_whole_buffer(fvec_t* restrict obj, const void* _buffer, size_t sz)
|
||||
{
|
||||
size_t w= 0;
|
||||
size_t c;
|
||||
const unsigned char* buffer = _buffer;
|
||||
while ( w<sz && (c=fwrite(buffer+w, 1, sz-w, obj->backing))>0 ) w+=c;
|
||||
if(w!=sz) {
|
||||
perror("Corrupted buffer state, aborting");
|
||||
panic("Cannot continue");
|
||||
}
|
||||
obj->len += sz;
|
||||
}
|
||||
int fvec_get_whole_buffer(const fvec_t* restrict obj, void* _buffer, size_t _sz)
|
||||
{
|
||||
ssize_t sz = (ssize_t)_sz;
|
||||
if(_sz != (size_t)sz) panic("Buffer size %lu too large", _sz);
|
||||
|
||||
if(obj->len<(size_t)sz) return 0;
|
||||
if(fseek(obj->backing, -sz, SEEK_END)<0) {
|
||||
perror("fvec_get_whole_buffer() failed to seek");
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t w=0;
|
||||
ssize_t c;
|
||||
unsigned char* buffer = _buffer;
|
||||
while ( w<_sz && (c=fread(buffer+w, 1, sz-w, obj->backing))>0 ) w+=c;
|
||||
if (w!=_sz) {
|
||||
perror("Corrupted buffer state, aborting");
|
||||
panic("Cannot continue");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
@ -1,57 +1,73 @@
|
||||
#include <filesystem>
|
||||
|
||||
#include <fsvec.hpp>
|
||||
#include <uuid.hpp>
|
||||
#include <fsvec.h>
|
||||
|
||||
#define FB file_back_buffer
|
||||
using std::size_t;
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
/// A temporary file name
|
||||
struct temp_file
|
||||
{
|
||||
inline temp_file()
|
||||
{
|
||||
// Create random new file
|
||||
}
|
||||
inline temp_file(const temp_file& c) = delete;
|
||||
inline temp_file(temp_file&& m) : name(m.name) { m.name= nullptr; }
|
||||
|
||||
inline temp_file(temp_file&& m) : name(std::move(m.name)) {}
|
||||
inline temp_file() : name(uuid::generate().to_string()){}
|
||||
inline temp_file(const char* name) : name(name) {}
|
||||
inline ~temp_file()
|
||||
inline temp_file(std::string&& name) : name(name) {}
|
||||
|
||||
inline ~temp_file() = default;
|
||||
|
||||
inline const fs::path& full_path() const
|
||||
{
|
||||
if(name) name = nullptr;
|
||||
if(_full_path.empty())
|
||||
_full_path = fs::canonical( fs::temp_directory_path() / name );
|
||||
return _full_path;
|
||||
}
|
||||
inline const std::string& base_name() const { return name; }
|
||||
|
||||
private:
|
||||
const char* name;
|
||||
inline const fs::path* operator->() const { return &full_path(); }
|
||||
private:
|
||||
std::string name;
|
||||
mutable fs::path _full_path;
|
||||
};
|
||||
|
||||
struct FB::impl
|
||||
{
|
||||
size_t cap;
|
||||
temp_file file;
|
||||
|
||||
fvec_t backing;
|
||||
|
||||
inline ~impl()
|
||||
{
|
||||
fvec_close(&backing);
|
||||
}
|
||||
};
|
||||
|
||||
FB::FB(size_t cap) : inner(std::make_unique<FB::impl>())
|
||||
{
|
||||
// Set cap
|
||||
inner->cap = cap;
|
||||
// Open `inner->file`
|
||||
// Create then open `inner->file`
|
||||
if(!fvec_new(&inner->backing, inner->file->c_str())) panic("Failed to open backing for temp file buffer");
|
||||
|
||||
}
|
||||
FB::FB() : FB(DEFAULT_CAP){}
|
||||
|
||||
void FB::push_buf(byte* buf, size_t len)
|
||||
{
|
||||
|
||||
fvec_push_whole_buffer(&inner->backing, (void*)buf, len);
|
||||
}
|
||||
|
||||
FB::byte* FB::back(size_t len)
|
||||
bool FB::back(byte* buf, size_t len) const
|
||||
{
|
||||
return nullptr;
|
||||
return !!fvec_get_whole_buffer(&inner->backing, (void*)buf, len);
|
||||
}
|
||||
|
||||
const FB::byte* FB::back(size_t len) const
|
||||
bool FB::pop_n(size_t len)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void FB::pop_n(size_t len)
|
||||
{
|
||||
|
||||
return !!fvec_pop_end(&inner->backing, len);
|
||||
}
|
||||
|
Loading…
Reference in new issue