* file: small wrap over winapi for windows and stdio for posix
 * fs: small wrapper over stat
 * slice: slice macro type
modified:
 * str and strview are now slices
This commit is contained in:
snarmph 2021-10-06 00:13:10 +02:00
parent bb5cce33f0
commit c4d1ffe539
15 changed files with 451 additions and 88 deletions

View file

@ -7,6 +7,8 @@ add_library(Colla STATIC
str.c
coroutine.c
os.c
fs.c
file.c
)
IF (WIN32)

View file

@ -6,6 +6,7 @@ extern "C" {
#include <stdbool.h> // bool
#include <string.h> // memset
#include "tracelog.h" // fatal
// heavily inspired by https://gist.github.com/Enichan/5f01140530ff0133fde19c9549a2a973
@ -86,6 +87,11 @@ bool coIsDead(coroutine_t co);
#define coroutine(...) \
if(!self.init) { \
if(COVAR->co.state != 0) { \
fatal("coroutine not initialized in %s:%d,\n" \
"did you forget to do '= {0};'?", \
__FILE__, __LINE__); \
} \
memset(&self, 0, sizeof(self)); \
self.init = true; \
} \

160
file.c Normal file
View file

@ -0,0 +1,160 @@
#include "file.h"
#include "tracelog.h"
#ifdef _WIN32
#define VC_EXTRALEAN
#include <windows.h>
static DWORD _toWin32Access(int mode) {
switch(mode) {
case FILE_READ: return GENERIC_READ;
case FILE_WRITE: return GENERIC_WRITE;
case FILE_BOTH: return GENERIC_READ | GENERIC_WRITE;
default: fatal("unrecognized mode: %d", mode); return 0;
}
}
static DWORD _toWin32Creation(int mode) {
switch(mode) {
case FILE_READ: return OPEN_EXISTING;
case FILE_WRITE: return OPEN_ALWAYS;
case FILE_BOTH: return OPEN_ALWAYS;
default: fatal("unrecognized mode: %d", mode); return 0;
}
}
file_t fileOpen(const char *fname, int mode) {
return (file_t) {
.handle = CreateFile(fname,
_toWin32Access(mode),
0,
NULL,
_toWin32Creation(mode),
FILE_ATTRIBUTE_NORMAL,
NULL)
};
}
void fileClose(file_t *ctx) {
if(ctx->handle) {
CloseHandle((HANDLE)ctx->handle);
ctx->handle = NULL;
}
}
bool fileIsValid(file_t *ctx) {
return ctx->handle != INVALID_HANDLE_VALUE;
}
bool filePutc(file_t *ctx, char c) {
return fileWrite(ctx, &c, 1) == 1;
}
bool filePuts(file_t *ctx, const char *str) {
size_t len = strlen(str);
return fileWrite(ctx, str, len) == len;
}
bool filePutstr(file_t *ctx, str_t str) {
return fileWrite(ctx, str.buf, str.len) == str.len;
}
bool filePutview(file_t *ctx, strview_t view) {
return fileWrite(ctx, view.buf, view.len) == view.len;
}
size_t fileRead(file_t *ctx, void *buf, size_t len) {
DWORD bytes_read = 0;
BOOL result = ReadFile((HANDLE)ctx->handle, buf, (DWORD)len, &bytes_read, NULL);
return result == TRUE ? (size_t)bytes_read : 0;
}
size_t fileWrite(file_t *ctx, const void *buf, size_t len) {
DWORD bytes_read = 0;
BOOL result = WriteFile((HANDLE)ctx->handle, buf, (DWORD)len, &bytes_read, NULL);
return result == TRUE ? (size_t)bytes_read : 0;
}
bool fileSeekEnd(file_t *ctx) {
return SetFilePointerEx((HANDLE)ctx->handle, (LARGE_INTEGER){0}, NULL, FILE_END) == TRUE;
}
void fileRewind(file_t *ctx) {
SetFilePointerEx((HANDLE)ctx->handle, (LARGE_INTEGER){0}, NULL, FILE_BEGIN);
}
uint64_t fileTell(file_t *ctx) {
LARGE_INTEGER tell;
BOOL result = SetFilePointerEx((HANDLE)ctx->handle, (LARGE_INTEGER){0}, &tell, FILE_CURRENT);
return result == TRUE ? (uint64_t)tell.QuadPart : 0;
}
#else
#include <stdio.h>
#include <errno.h>
#include <string.h>
const char *_toStdioMode(int mode) {
switch(mode) {
case FILE_READ: return "rb";
case FILE_BOTH: return "r+b";
case FILE_WRITE: return "wb";
default: fatal("mode not recognized: %d", mode); return "";
}
}
file_t fileOpen(const char *fname, int mode) {
return (file_t) {
.handle = (void*) fopen(fname, _toStdioMode(mode)),
};
}
void fileClose(file_t *ctx) {
if(ctx->handle) {
fclose((FILE*)ctx->handle);
ctx->handle = NULL;
}
}
bool fileIsValid(file_t *ctx) {
info("handle: %p", ctx->handle);
return ctx->handle != NULL;
}
bool filePutc(file_t *ctx, char c) {
return fputc(c, (FILE*)ctx->handle) == c;
}
bool filePuts(file_t *ctx, const char *str) {
return fputs(str, (FILE*)ctx->handle) != EOF;
}
bool filePutstr(file_t *ctx, str_t str) {
return fileWrite(ctx, str.buf, str.len) == str.len;
}
bool filePutview(file_t *ctx, strview_t view) {
return fileWrite(ctx, view.buf, view.len) == view.len;
}
size_t fileRead(file_t *ctx, void *buf, size_t len) {
return fread(buf, 1, len, (FILE*)ctx->handle);
}
size_t fileWrite(file_t *ctx, const void *buf, size_t len) {
return fwrite(buf, 1, len, (FILE*)ctx->handle);
}
bool fileSeekEnd(file_t *ctx) {
return fseek((FILE*)ctx->handle, 0, SEEK_END) == 0;
}
void fileRewind(file_t *ctx) {
rewind((FILE*)ctx->handle);
}
uint64_t fileTell(file_t *ctx) {
return (uint64_t)ftell((FILE*)ctx->handle);
}
#endif

31
file.h Normal file
View file

@ -0,0 +1,31 @@
#pragma once
#include <stdint.h>
#include "str.h"
#include "strview.h"
enum {
FILE_READ, FILE_WRITE, FILE_BOTH
};
typedef struct {
void *handle;
} file_t;
file_t fileOpen(const char *fname, int mode);
void fileClose(file_t *ctx);
bool fileIsValid(file_t *ctx);
bool filePutc(file_t *ctx, char c);
bool filePuts(file_t *ctx, const char *str);
bool filePutstr(file_t *ctx, str_t str);
bool filePutview(file_t *ctx, strview_t view);
size_t fileRead(file_t *ctx, void *buf, size_t len);
size_t fileWrite(file_t *ctx, const void *buf, size_t len);
bool fileSeekEnd(file_t *ctx);
void fileRewind(file_t *ctx);
uint64_t fileTell(file_t *ctx);

121
fs.c Normal file
View file

@ -0,0 +1,121 @@
#include "fs.h"
#include <time.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include "tracelog.h"
#ifdef _WIN32
#define VC_EXTRALEAN
#include <windows.h>
#include <sys/stat.h>
static int _modeToType(unsigned int mode) {
switch(mode & _S_IFMT) {
case _S_IFDIR: return FS_MODE_DIR;
case _S_IFCHR: return FS_MODE_CHARACTER_DEVICE;
case _S_IFREG: return FS_MODE_FILE;
case _S_IFIFO: return FS_MODE_FIFO;
default: return FS_MODE_UKNOWN;
}
}
fs_stat_t fsStat(file_t fp) {
TCHAR path[MAX_PATH];
DWORD pathlen = GetFinalPathNameByHandle(
(HANDLE)fp.handle,
path,
MAX_PATH,
0);
struct stat statbuf;
int res = stat(path, &statbuf);
if(res == 0) {
return (fs_stat_t) {
.type = _modeToType(statbuf.st_mode),
.size = statbuf.st_size,
.last_access = statbuf.st_atime,
.last_modif = statbuf.st_mtime
};
}
else {
return (fs_stat_t) { 0 };
}
}
fs_time_t fsAsTime(int64_t timer) {
struct tm t;
errno_t error = localtime_s(&t, &timer);
if(error == 0) {
return (fs_time_t) {
.year = t.tm_year + 1900,
.month = t.tm_mon + 1,
.day = t.tm_mday,
.hour = t.tm_hour,
.minutes = t.tm_min,
.seconds = t.tm_sec,
.daylight_saving = t.tm_isdst > 0
};
}
else {
char buf[128];
strerror_s(buf, sizeof(buf), error);
err("%s", buf);
return (fs_time_t) { 0 };
}
}
#else
#include <sys/stat.h>
static int _modeToType(unsigned int mode) {
switch(mode & __S_IFMT) {
case __S_IFDIR: return FS_MODE_DIR;
case __S_IFCHR: return FS_MODE_CHARACTER_DEVICE;
case __S_IFREG: return FS_MODE_FILE;
case __S_IFIFO: return FS_MODE_FIFO;
default: return FS_MODE_UKNOWN;
}
}
fs_stat_t fsStat(file_t fp) {
int fd = fileno((FILE*)fp.handle);
struct stat statbuf;
int res = fstat(fd, &statbuf);
if(res == 0) {
return (fs_stat_t) {
.type = _modeToType(statbuf.st_mode),
.size = statbuf.st_size,
.last_access = statbuf.st_atime,
.last_modif = statbuf.st_mtime
};
}
else {
return (fs_stat_t) { 0 };
}
}
fs_time_t fsAsTime(int64_t timer) {
struct tm *t = localtime(&timer);
if(t) {
return (fs_time_t) {
.year = t->tm_year + 1900,
.month = t->tm_mon + 1,
.day = t->tm_mday,
.hour = t->tm_hour,
.minutes = t->tm_min,
.seconds = t->tm_sec,
.daylight_saving = t->tm_isdst > 0
};
}
else {
err("%s", strerror(errno));
return (fs_time_t) { 0 };
}
}
#endif

34
fs.h Normal file
View file

@ -0,0 +1,34 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "file.h"
enum {
FS_MODE_FILE,
FS_MODE_DIR,
FS_MODE_CHARACTER_DEVICE,
FS_MODE_FIFO,
FS_MODE_UKNOWN,
};
typedef struct {
int type;
uint64_t size;
int64_t last_access;
int64_t last_modif;
} fs_stat_t;
typedef struct {
int year;
int month;
int day;
int hour;
int minutes;
int seconds;
bool daylight_saving;
} fs_time_t;
fs_stat_t fsStat(file_t fp);
fs_time_t fsAsTime(int64_t time);

2
http.c
View file

@ -225,7 +225,7 @@ void resParseFields(http_response_t *ctx, str_istream_t *in) {
}
istrSkip(in, 2); // skip \r\n
} while(line.size > 2);
} while(line.len > 2);
}
// == HTTP CLIENT =============================================================

5
slice.h Normal file
View file

@ -0,0 +1,5 @@
#pragma once
#include <stddef.h> // size_t
#define slice_t(type) struct { type buf; size_t len; }

View file

@ -2,11 +2,8 @@
#include <stdio.h>
#undef INVALID_SOCKET
#undef SOCKET_ERROR
#if SOCK_WINDOWS
#include <winsock2.h>
#include <ws2tcpip.h>
static bool _win_skInit();
static bool _win_skCleanup();
@ -72,7 +69,9 @@ bool skClose(socket_t sock) {
bool skBind(socket_t sock, const char *ip, uint16_t port) {
struct sockaddr_in addr;
addr.sin_family = AF_INET;
// TODO use inet_pton instead
addr.sin_addr.s_addr = inet_addr(ip);
addr.sin_port = htons(port);
return skBindPro(sock, (struct sockaddr *) &addr, sizeof(addr));
@ -101,6 +100,7 @@ socket_t skAcceptPro(socket_t sock, struct sockaddr *addr, socket_len_t *addrlen
}
bool skConnect(socket_t sock, const char *server, unsigned short server_port) {
// TODO use getaddrinfo insetad
struct hostent *host = gethostbyname(server);
// if gethostbyname fails, inet_addr will also fail and return an easier to debug error
const char *address = server;

View file

@ -19,8 +19,6 @@ struct sockaddr;
#include <winsock2.h>
typedef SOCKET socket_t;
typedef int socket_len_t;
#define INVALID_SOCKET (socket_t)(~0)
#define SOCKET_ERROR (-1)
#elif SOCK_POSIX
#include <sys/socket.h>
typedef int socket_t;

14
str.c
View file

@ -16,7 +16,7 @@ str_t strInitStr(const char *cstr) {
}
str_t strInitView(strview_t view) {
return strInitBuf(view.buf, view.size);
return strInitBuf(view.buf, view.len);
}
str_t strInitBuf(const char *buf, size_t len) {
@ -48,7 +48,7 @@ str_t strDup(str_t ctx) {
strview_t strGetView(str_t *ctx) {
return (strview_t) {
.buf = ctx->buf,
.size = ctx->len
.len = ctx->len
};
}
@ -77,7 +77,7 @@ void strAppendStr(str_t *ctx, str_t str) {
}
void strAppendView(str_t *ctx, strview_t view) {
strAppendBuf(ctx, view.buf, view.size);
strAppendBuf(ctx, view.buf, view.len);
}
void strAppendBuf(str_t *ctx, const char *buf, size_t len) {
@ -130,7 +130,7 @@ strview_t strSubview(str_t *ctx, size_t pos, size_t len) {
if(len == SIZE_MAX || (pos + len) > ctx->len) len = ctx->len - pos;
return (strview_t) {
.buf = ctx->buf + pos,
.size = len
.len = len
};
}
@ -169,7 +169,7 @@ void strTest(void) {
{
s = strInitStr("hello world");
strview_t view = strGetView(&s);
printf("\"%.*s\" %zu\n", (int)view.size, view.buf, view.size);
printf("\"%.*s\" %zu\n", (int)view.len, view.buf, view.len);
strFree(&s);
}
debug("== testing begin/end ============");
@ -255,9 +255,9 @@ void strTest(void) {
printf("-- view\n");
strview_t v = strSubview(&s, 0, 5);
printf("0..5: \"%.*s\"\n", (int)v.size, v.buf);
printf("0..5: \"%.*s\"\n", (int)v.len, v.buf);
v = strSubview(&s, 5, SIZE_MAX);
printf("6..SIZE_MAX: \"%.*s\"\n", (int)v.size, v.buf);
printf("6..SIZE_MAX: \"%.*s\"\n", (int)v.len, v.buf);
strFree(&s);
}

12
str.h
View file

@ -4,15 +4,17 @@
extern "C" {
#endif
#include <stddef.h>
#include "slice.h"
#include "strview.h"
#define STR_TESTING
typedef struct {
char *buf;
size_t len;
} str_t;
// typedef struct {
// char *buf;
// size_t len;
// } str_t;
typedef slice_t(char *) str_t;
str_t strInit(void);
str_t strInitStr(const char *cstr);

View file

@ -504,10 +504,10 @@ void ostrAppenddouble(str_ostream_t *ctx, double val) {
}
void ostrAppendview(str_ostream_t *ctx, strview_t view) {
if((ctx->allocated - ctx->size) < view.size) {
_ostrRealloc(ctx, view.size + 1);
if((ctx->allocated - ctx->size) < view.len) {
_ostrRealloc(ctx, view.len + 1);
}
memcpy(ctx->buf + ctx->size, view.buf, view.size);
ctx->size += view.size;
memcpy(ctx->buf + ctx->size, view.buf, view.len);
ctx->size += view.len;
ctx->buf[ctx->size] = '\0';
}

100
strview.c
View file

@ -20,7 +20,7 @@ strview_t strvInit(const char *cstr) {
strview_t strvInitLen(const char *buf, size_t size) {
strview_t view;
view.buf = buf;
view.size = size;
view.len = size;
return view;
}
@ -29,7 +29,7 @@ char strvFront(strview_t ctx) {
}
char strvBack(strview_t ctx) {
return ctx.buf[ctx.size - 1];
return ctx.buf[ctx.len - 1];
}
const char *strvBegin(strview_t *ctx) {
@ -37,31 +37,31 @@ const char *strvBegin(strview_t *ctx) {
}
const char *strvEnd(strview_t *ctx) {
return ctx->buf + ctx->size;
return ctx->buf + ctx->len;
}
bool strvIsEmpty(strview_t ctx) {
return ctx.size == 0;
return ctx.len == 0;
}
void strvRemovePrefix(strview_t *ctx, size_t n) {
ctx->buf += n;
ctx->size -= n;
ctx->len -= n;
}
void strvRemoveSuffix(strview_t *ctx, size_t n) {
ctx->size -= n;
ctx->len -= n;
}
size_t strvCopy(strview_t ctx, char **buf) {
*buf = malloc(ctx.size + 1);
memcpy(*buf, ctx.buf, ctx.size);
(*buf)[ctx.size] = '\0';
return ctx.size;
*buf = malloc(ctx.len + 1);
memcpy(*buf, ctx.buf, ctx.len);
(*buf)[ctx.len] = '\0';
return ctx.len;
}
size_t strvCopyN(strview_t ctx, char **buf, size_t count, size_t from) {
size_t sz = ctx.size + 1 - from;
size_t sz = ctx.len + 1 - from;
count = min(count, sz);
*buf = malloc(count + 1);
memcpy(*buf, ctx.buf + from, count);
@ -70,7 +70,7 @@ size_t strvCopyN(strview_t ctx, char **buf, size_t count, size_t from) {
}
size_t strvCopyBuf(strview_t ctx, char *buf, size_t len, size_t from) {
size_t sz = ctx.size + 1 - from;
size_t sz = ctx.len + 1 - from;
len = min(len, sz);
memcpy(buf, ctx.buf + from, len);
buf[len - 1] = '\0';
@ -78,21 +78,21 @@ size_t strvCopyBuf(strview_t ctx, char *buf, size_t len, size_t from) {
}
strview_t strvSubstr(strview_t ctx, size_t from, size_t len) {
if(from > ctx.size) from = ctx.size - len;
size_t sz = ctx.size - from;
if(from > ctx.len) from = ctx.len - len;
size_t sz = ctx.len - from;
return strvInitLen(ctx.buf + from, min(len, sz));
}
int strvCompare(strview_t ctx, strview_t other) {
if(ctx.size < other.size) return -1;
if(ctx.size > other.size) return 1;
return memcmp(ctx.buf, other.buf, ctx.size);
if(ctx.len < other.len) return -1;
if(ctx.len > other.len) return 1;
return memcmp(ctx.buf, other.buf, ctx.len);
}
int strvICompare(strview_t ctx, strview_t other) {
if(ctx.size < other.size) return -1;
if(ctx.size > other.size) return 1;
for(size_t i = 0; i < ctx.size; ++i) {
if(ctx.len < other.len) return -1;
if(ctx.len > other.len) return 1;
for(size_t i = 0; i < ctx.len; ++i) {
char a = tolower(ctx.buf[i]);
char b = tolower(other.buf[i]);
if(a != b) return a - b;
@ -105,8 +105,8 @@ bool strvStartsWith(strview_t ctx, char c) {
}
bool strvStartsWithView(strview_t ctx, strview_t view) {
if(ctx.size < view.size) return false;
return memcmp(ctx.buf, view.buf, view.size) == 0;
if(ctx.len < view.len) return false;
return memcmp(ctx.buf, view.buf, view.len) == 0;
}
bool strvEndsWith(strview_t ctx, char c) {
@ -114,45 +114,45 @@ bool strvEndsWith(strview_t ctx, char c) {
}
bool strvEndsWithView(strview_t ctx, strview_t view) {
if(ctx.size < view.size) return false;
return memcmp(ctx.buf + ctx.size - view.size, view.buf, view.size) == 0;
if(ctx.len < view.len) return false;
return memcmp(ctx.buf + ctx.len - view.len, view.buf, view.len) == 0;
}
bool strvContains(strview_t ctx, char c) {
for(size_t i = 0; i < ctx.size; ++i) {
for(size_t i = 0; i < ctx.len; ++i) {
if(ctx.buf[i] == c) return true;
}
return false;
}
bool strvContainsView(strview_t ctx, strview_t view) {
if(ctx.size < view.size) return false;
size_t end = ctx.size - view.size;
if(ctx.len < view.len) return false;
size_t end = ctx.len - view.len;
for(size_t i = 0; i < end; ++i) {
if(memcmp(ctx.buf + i, view.buf, view.size) == 0) return true;
if(memcmp(ctx.buf + i, view.buf, view.len) == 0) return true;
}
return false;
}
size_t strvFind(strview_t ctx, char c, size_t from) {
for(size_t i = from; i < ctx.size; ++i) {
for(size_t i = from; i < ctx.len; ++i) {
if(ctx.buf[i] == c) return i;
}
return SIZE_MAX;
}
size_t strvFindView(strview_t ctx, strview_t view, size_t from) {
if(ctx.size < view.size) return SIZE_MAX;
size_t end = ctx.size - view.size;
if(ctx.len < view.len) return SIZE_MAX;
size_t end = ctx.len - view.len;
for(size_t i = from; i < end; ++i) {
if(memcmp(ctx.buf + i, view.buf, view.size) == 0) return i;
if(memcmp(ctx.buf + i, view.buf, view.len) == 0) return i;
}
return SIZE_MAX;
}
size_t strvRFind(strview_t ctx, char c, size_t from) {
if(from >= ctx.size) {
from = ctx.size - 1;
if(from >= ctx.len) {
from = ctx.len - 1;
}
const char *buf = ctx.buf + from;
@ -164,23 +164,23 @@ size_t strvRFind(strview_t ctx, char c, size_t from) {
}
size_t strvRFindView(strview_t ctx, strview_t view, size_t from) {
from = min(from, ctx.size);
from = min(from, ctx.len);
if(view.size > ctx.size) {
from -= view.size;
if(view.len > ctx.len) {
from -= view.len;
}
const char *buf = ctx.buf + from;
for(; buf >= ctx.buf; --buf) {
if(memcmp(buf, view.buf, view.size) == 0) return (buf - ctx.buf);
if(memcmp(buf, view.buf, view.len) == 0) return (buf - ctx.buf);
}
return SIZE_MAX;
}
size_t strvFindFirstOf(strview_t ctx, strview_t view, size_t from) {
if(ctx.size < view.size) return SIZE_MAX;
for(size_t i = from; i < ctx.size; ++i) {
for(size_t j = 0; j < view.size; ++j) {
if(ctx.len < view.len) return SIZE_MAX;
for(size_t i = from; i < ctx.len; ++i) {
for(size_t j = 0; j < view.len; ++j) {
if(ctx.buf[i] == view.buf[j]) return i;
}
}
@ -188,13 +188,13 @@ size_t strvFindFirstOf(strview_t ctx, strview_t view, size_t from) {
}
size_t strvFindLastOf(strview_t ctx, strview_t view, size_t from) {
if(from >= ctx.size) {
from = ctx.size - 1;
if(from >= ctx.len) {
from = ctx.len - 1;
}
const char *buf = ctx.buf + from;
for(; buf >= ctx.buf; --buf) {
for(size_t j = 0; j < view.size; ++j) {
for(size_t j = 0; j < view.len; ++j) {
if(*buf == view.buf[j]) return (buf - ctx.buf);
}
}
@ -203,7 +203,7 @@ size_t strvFindLastOf(strview_t ctx, strview_t view, size_t from) {
}
size_t strvFindFirstNot(strview_t ctx, char c, size_t from) {
size_t end = ctx.size - 1;
size_t end = ctx.len - 1;
for(size_t i = from; i < end; ++i) {
if(ctx.buf[i] != c) return i;
}
@ -211,7 +211,7 @@ size_t strvFindFirstNot(strview_t ctx, char c, size_t from) {
}
size_t strvFindFirstNotOf(strview_t ctx, strview_t view, size_t from) {
for(size_t i = from; i < ctx.size; ++i) {
for(size_t i = from; i < ctx.len; ++i) {
if(!strvContains(view, ctx.buf[i])) {
return i;
}
@ -220,8 +220,8 @@ size_t strvFindFirstNotOf(strview_t ctx, strview_t view, size_t from) {
}
size_t strvFindLastNot(strview_t ctx, char c, size_t from) {
if(from >= ctx.size) {
from = ctx.size - 1;
if(from >= ctx.len) {
from = ctx.len - 1;
}
const char *buf = ctx.buf + from;
@ -235,8 +235,8 @@ size_t strvFindLastNot(strview_t ctx, char c, size_t from) {
}
size_t strvFindLastNotOf(strview_t ctx, strview_t view, size_t from) {
if(from >= ctx.size) {
from = ctx.size - 1;
if(from >= ctx.len) {
from = ctx.len - 1;
}
const char *buf = ctx.buf + from;

View file

@ -9,12 +9,16 @@ extern "C" {
#include <stddef.h>
#include <limits.h>
#include "slice.h"
#define STRV_NOT_FOUND SIZE_MAX
typedef struct {
const char *buf;
size_t size;
} strview_t;
// typedef struct {
// const char *buf;
// size_t size;
// } strview_t;
typedef slice_t(const char *) strview_t;
strview_t strvInit(const char *cstr);
strview_t strvInitLen(const char *buf, size_t size);