Fix single header build with updated DN lib
This commit is contained in:
@@ -63,7 +63,7 @@ DN_API void DN_ASYNC_Deinit(DN_ASYNCCore *async)
|
||||
DN_AtomicSetValue32(&async->join_threads, true);
|
||||
DN_OS_SemaphoreIncrement(&async->worker_sem, async->thread_count);
|
||||
for (DN_ForItSize(it, DN_OSThread, async->threads, async->thread_count))
|
||||
DN_OS_ThreadJoin(it.data);
|
||||
DN_OS_ThreadJoin(it.data, DN_TCDeinitArenas_Yes);
|
||||
}
|
||||
|
||||
static bool DN_ASYNC_QueueTask_(DN_ASYNCCore *async, DN_ASYNCTask const *task, DN_U64 wait_time_ms) {
|
||||
|
||||
@@ -128,8 +128,8 @@ DN_API void DN_BinPackStr8FromArena(DN_BinPack *pack, DN_Arena *arena, DN_BinPac
|
||||
if (mode == DN_BinPackMode_Serialise) {
|
||||
DN_Str8BuilderAppendBytesCopy(&pack->writer, string->data, string->size);
|
||||
} else {
|
||||
DN_Str8 src = DN_Str8Slice(pack->read, pack->read_index, string->size);
|
||||
*string = DN_Str8FromStr8Arena(arena, src);
|
||||
DN_Str8 src = DN_Str8Subset(pack->read, pack->read_index, string->size);
|
||||
*string = DN_Str8FromStr8Arena(src, arena);
|
||||
pack->read_index += src.size;
|
||||
}
|
||||
}
|
||||
@@ -140,8 +140,8 @@ DN_API void DN_BinPackStr8FromPool(DN_BinPack *pack, DN_Pool *pool, DN_BinPackMo
|
||||
if (mode == DN_BinPackMode_Serialise) {
|
||||
DN_Str8BuilderAppendBytesCopy(&pack->writer, string->data, string->size);
|
||||
} else {
|
||||
DN_Str8 src = DN_Str8Slice(pack->read, pack->read_index, string->size);
|
||||
*string = DN_Str8FromStr8Pool(pool, src);
|
||||
DN_Str8 src = DN_Str8Subset(pack->read, pack->read_index, string->size);
|
||||
*string = DN_Str8FromStr8Pool(src, pool);
|
||||
pack->read_index += src.size;
|
||||
}
|
||||
}
|
||||
@@ -175,7 +175,7 @@ DN_API void DN_BinPackCArray(DN_BinPack *pack, DN_BinPackMode mode, void *ptr, D
|
||||
if (mode == DN_BinPackMode_Serialise) {
|
||||
DN_Str8BuilderAppendBytesCopy(&pack->writer, ptr, size);
|
||||
} else {
|
||||
DN_Str8 src = DN_Str8Slice(pack->read, pack->read_index, size);
|
||||
DN_Str8 src = DN_Str8Subset(pack->read, pack->read_index, size);
|
||||
DN_Assert(src.size == size);
|
||||
DN_Memcpy(ptr, src.data, DN_Min(src.size, size));
|
||||
pack->read_index += src.size;
|
||||
|
||||
+37
-39
@@ -1,10 +1,8 @@
|
||||
#define DN_CSV_CPP
|
||||
|
||||
#if defined(_CLANGD)
|
||||
#include "dn_csv.h"
|
||||
#endif
|
||||
#include "dn_csv.h"
|
||||
|
||||
static DN_CSVTokeniser DN_CSV_TokeniserInit(DN_Str8 string, char delimiter)
|
||||
DN_CSVTokeniser DN_CSV_TokeniserInit(DN_Str8 string, char delimiter)
|
||||
{
|
||||
DN_CSVTokeniser result = {};
|
||||
result.string = string;
|
||||
@@ -12,13 +10,21 @@ static DN_CSVTokeniser DN_CSV_TokeniserInit(DN_Str8 string, char delimiter)
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool DN_CSV_TokeniserValid(DN_CSVTokeniser *tokeniser)
|
||||
bool DN_CSV_TokeniserValid(DN_CSVTokeniser *tokeniser)
|
||||
{
|
||||
bool result = tokeniser && !tokeniser->bad;
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool DN_CSV_TokeniserNextRow(DN_CSVTokeniser *tokeniser)
|
||||
static void DN_CSV_TokeniserEatNewLines_(DN_CSVTokeniser *tokeniser)
|
||||
{
|
||||
char const *end = tokeniser->string.data + tokeniser->string.size;
|
||||
while (tokeniser->it[0] == '\n' || tokeniser->it[0] == '\r')
|
||||
if (++tokeniser->it == end)
|
||||
break;
|
||||
}
|
||||
|
||||
bool DN_CSV_TokeniserNextRow(DN_CSVTokeniser *tokeniser)
|
||||
{
|
||||
bool result = false;
|
||||
if (DN_CSV_TokeniserValid(tokeniser) && tokeniser->string.size) {
|
||||
@@ -37,7 +43,7 @@ static bool DN_CSV_TokeniserNextRow(DN_CSVTokeniser *tokeniser)
|
||||
return result;
|
||||
}
|
||||
|
||||
static DN_Str8 DN_CSV_TokeniserNextField(DN_CSVTokeniser *tokeniser)
|
||||
DN_Str8 DN_CSV_TokeniserNextField(DN_CSVTokeniser *tokeniser)
|
||||
{
|
||||
DN_Str8 result = {};
|
||||
if (!DN_CSV_TokeniserValid(tokeniser))
|
||||
@@ -52,10 +58,7 @@ static DN_Str8 DN_CSV_TokeniserNextField(DN_CSVTokeniser *tokeniser)
|
||||
char const *string_end = tokeniser->string.data + tokeniser->string.size;
|
||||
if (!tokeniser->it) {
|
||||
tokeniser->it = tokeniser->string.data;
|
||||
// NOTE: Skip any leading new lines
|
||||
while (tokeniser->it[0] == '\n' || tokeniser->it[0] == '\r')
|
||||
if (++tokeniser->it == string_end)
|
||||
break;
|
||||
DN_CSV_TokeniserEatNewLines_(tokeniser); // NOTE: Skip any leading new lines
|
||||
}
|
||||
|
||||
// NOTE: Tokeniser pointing at end, no more valid data to parse.
|
||||
@@ -68,8 +71,8 @@ static DN_Str8 DN_CSV_TokeniserNextField(DN_CSVTokeniser *tokeniser)
|
||||
// 3. '\n' Last field in record, extract everything leading up the the new line.
|
||||
char const *begin = tokeniser->it;
|
||||
while (tokeniser->it != string_end && (tokeniser->it[0] != '"' &&
|
||||
tokeniser->it[0] != tokeniser->delimiter &&
|
||||
tokeniser->it[0] != '\n'))
|
||||
tokeniser->it[0] != tokeniser->delimiter &&
|
||||
tokeniser->it[0] != '\n'))
|
||||
tokeniser->it++;
|
||||
|
||||
bool quoted_field = (tokeniser->it != string_end) && tokeniser->it[0] == '"';
|
||||
@@ -106,8 +109,7 @@ static DN_Str8 DN_CSV_TokeniserNextField(DN_CSVTokeniser *tokeniser)
|
||||
// NOTE: Quoted fields may have whitespace after the closing quote, we skip
|
||||
// until we reach the field terminator.
|
||||
if (quoted_field)
|
||||
while (tokeniser->it != string_end && (tokeniser->it[0] != tokeniser->delimiter &&
|
||||
tokeniser->it[0] != '\n'))
|
||||
while (tokeniser->it != string_end && (tokeniser->it[0] != tokeniser->delimiter && tokeniser->it[0] != '\n'))
|
||||
tokeniser->it++;
|
||||
|
||||
// NOTE: Advance the tokeniser past the field terminator.
|
||||
@@ -120,7 +122,7 @@ static DN_Str8 DN_CSV_TokeniserNextField(DN_CSVTokeniser *tokeniser)
|
||||
return result;
|
||||
}
|
||||
|
||||
static DN_Str8 DN_CSV_TokeniserNextColumn(DN_CSVTokeniser *tokeniser)
|
||||
DN_Str8 DN_CSV_TokeniserNextColumn(DN_CSVTokeniser *tokeniser)
|
||||
{
|
||||
DN_Str8 result = {};
|
||||
if (!DN_CSV_TokeniserValid(tokeniser))
|
||||
@@ -135,14 +137,14 @@ static DN_Str8 DN_CSV_TokeniserNextColumn(DN_CSVTokeniser *tokeniser)
|
||||
return result;
|
||||
}
|
||||
|
||||
static void DN_CSV_TokeniserSkipLine(DN_CSVTokeniser *tokeniser)
|
||||
void DN_CSV_TokeniserSkipLine(DN_CSVTokeniser *tokeniser)
|
||||
{
|
||||
while (DN_CSV_TokeniserValid(tokeniser) && !tokeniser->end_of_line)
|
||||
DN_CSV_TokeniserNextColumn(tokeniser);
|
||||
DN_CSV_TokeniserNextRow(tokeniser);
|
||||
}
|
||||
|
||||
static int DN_CSV_TokeniserNextN(DN_CSVTokeniser *tokeniser, DN_Str8 *fields, int fields_size, bool column_iterator)
|
||||
int DN_CSV_TokeniserNextN(DN_CSVTokeniser *tokeniser, DN_Str8 *fields, int fields_size, bool column_iterator)
|
||||
{
|
||||
if (!DN_CSV_TokeniserValid(tokeniser) || !fields || fields_size <= 0)
|
||||
return 0;
|
||||
@@ -150,34 +152,32 @@ static int DN_CSV_TokeniserNextN(DN_CSVTokeniser *tokeniser, DN_Str8 *fields, in
|
||||
int result = 0;
|
||||
for (; result < fields_size; result++) {
|
||||
fields[result] = column_iterator ? DN_CSV_TokeniserNextColumn(tokeniser) : DN_CSV_TokeniserNextField(tokeniser);
|
||||
if (!DN_CSV_TokeniserValid(tokeniser) || fields[result].size == 0)
|
||||
if (!DN_CSV_TokeniserValid(tokeniser) || !fields[result].data)
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_MSVC_WARNING_PUSH
|
||||
DN_MSVC_WARNING_DISABLE(4505) // 'x': unreferenced function with internal linkage has been removed
|
||||
static int DN_CSV_TokeniserNextColumnN(DN_CSVTokeniser *tokeniser, DN_Str8 *fields, int fields_size)
|
||||
int DN_CSV_TokeniserNextColumnN(DN_CSVTokeniser *tokeniser, DN_Str8 *fields, int fields_size)
|
||||
{
|
||||
int result = DN_CSV_TokeniserNextN(tokeniser, fields, fields_size, true /*column_iterator*/);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int DN_CSV_TokeniserNextFieldN(DN_CSVTokeniser *tokeniser, DN_Str8 *fields, int fields_size)
|
||||
int DN_CSV_TokeniserNextFieldN(DN_CSVTokeniser *tokeniser, DN_Str8 *fields, int fields_size)
|
||||
{
|
||||
int result = DN_CSV_TokeniserNextN(tokeniser, fields, fields_size, false /*column_iterator*/);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void DN_CSV_TokeniserSkipLineN(DN_CSVTokeniser *tokeniser, int count)
|
||||
void DN_CSV_TokeniserSkipLineN(DN_CSVTokeniser *tokeniser, int count)
|
||||
{
|
||||
for (int i = 0; i < count && DN_CSV_TokeniserValid(tokeniser); i++)
|
||||
DN_CSV_TokeniserSkipLine(tokeniser);
|
||||
}
|
||||
|
||||
static void DN_CSV_PackU64(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U64 *value)
|
||||
void DN_CSV_PackU64(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U64 *value)
|
||||
{
|
||||
if (serialise == DN_CSVSerialise_Read) {
|
||||
DN_Str8 csv_value = DN_CSV_TokeniserNextColumn(&pack->read_tokeniser);
|
||||
@@ -189,7 +189,7 @@ static void DN_CSV_PackU64(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U64 *
|
||||
}
|
||||
}
|
||||
|
||||
static void DN_CSV_PackI64(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I64 *value)
|
||||
void DN_CSV_PackI64(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I64 *value)
|
||||
{
|
||||
if (serialise == DN_CSVSerialise_Read) {
|
||||
DN_Str8 csv_value = DN_CSV_TokeniserNextColumn(&pack->read_tokeniser);
|
||||
@@ -201,7 +201,7 @@ static void DN_CSV_PackI64(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I64 *
|
||||
}
|
||||
}
|
||||
|
||||
static void DN_CSV_PackI32(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I32 *value)
|
||||
void DN_CSV_PackI32(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I32 *value)
|
||||
{
|
||||
DN_I64 u64 = *value;
|
||||
DN_CSV_PackI64(pack, serialise, &u64);
|
||||
@@ -209,7 +209,7 @@ static void DN_CSV_PackI32(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I32 *
|
||||
*value = DN_SaturateCastI64ToI32(u64);
|
||||
}
|
||||
|
||||
static void DN_CSV_PackI16(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I16 *value)
|
||||
void DN_CSV_PackI16(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I16 *value)
|
||||
{
|
||||
DN_I64 u64 = *value;
|
||||
DN_CSV_PackI64(pack, serialise, &u64);
|
||||
@@ -217,7 +217,7 @@ static void DN_CSV_PackI16(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I16 *
|
||||
*value = DN_SaturateCastI64ToI16(u64);
|
||||
}
|
||||
|
||||
static void DN_CSV_PackI8(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I8 *value)
|
||||
void DN_CSV_PackI8(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I8 *value)
|
||||
{
|
||||
DN_I64 u64 = *value;
|
||||
DN_CSV_PackI64(pack, serialise, &u64);
|
||||
@@ -225,8 +225,7 @@ static void DN_CSV_PackI8(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I8 *va
|
||||
*value = DN_SaturateCastI64ToI8(u64);
|
||||
}
|
||||
|
||||
|
||||
static void DN_CSV_PackU32(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U32 *value)
|
||||
void DN_CSV_PackU32(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U32 *value)
|
||||
{
|
||||
DN_U64 u64 = *value;
|
||||
DN_CSV_PackU64(pack, serialise, &u64);
|
||||
@@ -234,7 +233,7 @@ static void DN_CSV_PackU32(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U32 *
|
||||
*value = DN_SaturateCastU64ToU32(u64);
|
||||
}
|
||||
|
||||
static void DN_CSV_PackU16(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U16 *value)
|
||||
void DN_CSV_PackU16(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U16 *value)
|
||||
{
|
||||
DN_U64 u64 = *value;
|
||||
DN_CSV_PackU64(pack, serialise, &u64);
|
||||
@@ -242,7 +241,7 @@ static void DN_CSV_PackU16(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U16 *
|
||||
*value = DN_SaturateCastU64ToU16(u64);
|
||||
}
|
||||
|
||||
static void DN_CSV_PackBoolAsU64(DN_CSVPack *pack, DN_CSVSerialise serialise, bool *value)
|
||||
void DN_CSV_PackBoolAsU64(DN_CSVPack *pack, DN_CSVSerialise serialise, bool *value)
|
||||
{
|
||||
DN_U64 u64 = *value;
|
||||
DN_CSV_PackU64(pack, serialise, &u64);
|
||||
@@ -250,17 +249,17 @@ static void DN_CSV_PackBoolAsU64(DN_CSVPack *pack, DN_CSVSerialise serialise, bo
|
||||
*value = u64 ? 1 : 0;
|
||||
}
|
||||
|
||||
static void DN_CSV_PackStr8(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_Str8 *str8, DN_Arena *arena)
|
||||
void DN_CSV_PackStr8(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_Str8 *str8, DN_Arena *arena)
|
||||
{
|
||||
if (serialise == DN_CSVSerialise_Read) {
|
||||
DN_Str8 csv_value = DN_CSV_TokeniserNextColumn(&pack->read_tokeniser);
|
||||
*str8 = DN_Str8FromStr8Arena(arena, csv_value);
|
||||
*str8 = DN_Str8FromStr8Arena(csv_value, arena);
|
||||
} else {
|
||||
DN_Str8BuilderAppendF(&pack->write_builder, "%s%.*s", pack->write_column++ ? "," : "", DN_Str8PrintFmt(*str8));
|
||||
}
|
||||
}
|
||||
|
||||
static void DN_CSV_PackBuffer(DN_CSVPack *pack, DN_CSVSerialise serialise, void *dest, size_t *size)
|
||||
void DN_CSV_PackBuffer(DN_CSVPack *pack, DN_CSVSerialise serialise, void *dest, size_t *size)
|
||||
{
|
||||
if (serialise == DN_CSVSerialise_Read) {
|
||||
DN_Str8 csv_value = DN_CSV_TokeniserNextColumn(&pack->read_tokeniser);
|
||||
@@ -271,14 +270,14 @@ static void DN_CSV_PackBuffer(DN_CSVPack *pack, DN_CSVSerialise serialise, void
|
||||
}
|
||||
}
|
||||
|
||||
static void DN_CSV_PackBufferWithMax(DN_CSVPack *pack, DN_CSVSerialise serialise, void *dest, size_t *size, size_t max)
|
||||
void DN_CSV_PackBufferWithMax(DN_CSVPack *pack, DN_CSVSerialise serialise, void *dest, size_t *size, size_t max)
|
||||
{
|
||||
if (serialise == DN_CSVSerialise_Read)
|
||||
*size = max;
|
||||
DN_CSV_PackBuffer(pack, serialise, dest, size);
|
||||
}
|
||||
|
||||
static bool DN_CSV_PackNewLine(DN_CSVPack *pack, DN_CSVSerialise serialise)
|
||||
bool DN_CSV_PackNewLine(DN_CSVPack *pack, DN_CSVSerialise serialise)
|
||||
{
|
||||
bool result = true;
|
||||
if (serialise == DN_CSVSerialise_Read) {
|
||||
@@ -289,4 +288,3 @@ static bool DN_CSV_PackNewLine(DN_CSVPack *pack, DN_CSVSerialise serialise)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
DN_MSVC_WARNING_POP
|
||||
|
||||
+35
-3
@@ -1,9 +1,18 @@
|
||||
#if !defined(DN_CSV_H)
|
||||
#define DN_CSV_H
|
||||
|
||||
#if defined(_CLANGD)
|
||||
#include "../dn.h"
|
||||
#endif
|
||||
// NOTE: Data structures to create and parse CSV files, supports Python style escaped quotes (e.g.
|
||||
// Using "" to escape quotes inside a quoted string).
|
||||
//
|
||||
// API
|
||||
// DN_CSV_TokeniserNextN: Reads the next N consecutive fields from the parser. If `column_iterator`
|
||||
// is `false` then the read of the N consecutive fields does not proceed past the end of the
|
||||
// current CSV row. If `true` then it reads the next N fields even if reading would progress onto
|
||||
// the next row.
|
||||
|
||||
#if defined(_CLANGD)
|
||||
#include "../dn.h"
|
||||
#endif
|
||||
|
||||
enum DN_CSVSerialise
|
||||
{
|
||||
@@ -27,4 +36,27 @@ struct DN_CSVPack
|
||||
DN_CSVTokeniser read_tokeniser;
|
||||
};
|
||||
|
||||
DN_CSVTokeniser DN_CSV_TokeniserInit (DN_Str8 string, char delimiter);
|
||||
bool DN_CSV_TokeniserValid (DN_CSVTokeniser *tokeniser);
|
||||
bool DN_CSV_TokeniserNextRow (DN_CSVTokeniser *tokeniser);
|
||||
DN_Str8 DN_CSV_TokeniserNextField (DN_CSVTokeniser *tokeniser);
|
||||
DN_Str8 DN_CSV_TokeniserNextColumn (DN_CSVTokeniser *tokeniser);
|
||||
void DN_CSV_TokeniserSkipLine (DN_CSVTokeniser *tokeniser);
|
||||
int DN_CSV_TokeniserNextN (DN_CSVTokeniser *tokeniser, DN_Str8 *fields, int fields_size, bool column_iterator);
|
||||
int DN_CSV_TokeniserNextColumnN(DN_CSVTokeniser *tokeniser, DN_Str8 *fields, int fields_size);
|
||||
int DN_CSV_TokeniserNextFieldN (DN_CSVTokeniser *tokeniser, DN_Str8 *fields, int fields_size);
|
||||
void DN_CSV_TokeniserSkipLineN (DN_CSVTokeniser *tokeniser, int count);
|
||||
void DN_CSV_PackU64 (DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U64 *value);
|
||||
void DN_CSV_PackI64 (DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I64 *value);
|
||||
void DN_CSV_PackI32 (DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I32 *value);
|
||||
void DN_CSV_PackI16 (DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I16 *value);
|
||||
void DN_CSV_PackI8 (DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I8 *value);
|
||||
void DN_CSV_PackU32 (DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U32 *value);
|
||||
void DN_CSV_PackU16 (DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U16 *value);
|
||||
void DN_CSV_PackBoolAsU64 (DN_CSVPack *pack, DN_CSVSerialise serialise, bool *value);
|
||||
void DN_CSV_PackStr8 (DN_CSVPack *pack, DN_CSVSerialise serialise, DN_Str8 *str8, DN_Arena *arena);
|
||||
void DN_CSV_PackBuffer (DN_CSVPack *pack, DN_CSVSerialise serialise, void *dest, size_t *size);
|
||||
void DN_CSV_PackBufferWithMax (DN_CSVPack *pack, DN_CSVSerialise serialise, void *dest, size_t *size, size_t max);
|
||||
bool DN_CSV_PackNewLine (DN_CSVPack *pack, DN_CSVSerialise serialise);
|
||||
|
||||
#endif // !defined(DN_CSV_H)
|
||||
|
||||
@@ -72,7 +72,7 @@ DN_API void DN_JSONBuilder_KeyValue(DN_JSONBuilder *builder, DN_Str8 key, DN_Str
|
||||
DN_API void DN_JSONBuilder_KeyValueFV(DN_JSONBuilder *builder, DN_Str8 key, char const *value_fmt, va_list args)
|
||||
{
|
||||
DN_TCScratch scratch = DN_TCScratchBegin(&builder->string_builder.arena, 1);
|
||||
DN_Str8 value = DN_Str8FromFmtVArena(scratch.arena, value_fmt, args);
|
||||
DN_Str8 value = DN_Str8FromFmtVArena(&scratch.arena, value_fmt, args);
|
||||
DN_JSONBuilder_KeyValue(builder, key, value);
|
||||
DN_TCScratchEnd(&scratch);
|
||||
}
|
||||
|
||||
@@ -41,7 +41,6 @@ struct DN_JSONBuilder
|
||||
};
|
||||
#endif // !defined(DN_NO_JSON_BUIDLER)
|
||||
|
||||
// NOTE: DN_BinarySearch ///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
using DN_BinarySearchLessThanProc = bool(T const &lhs, T const &rhs);
|
||||
|
||||
|
||||
+16
-12
@@ -1,6 +1,8 @@
|
||||
#define DN_NET_CURL_CPP
|
||||
|
||||
#if defined(_CLANGD)
|
||||
#define DN_H_WITH_OS 1
|
||||
#include "../dn.h"
|
||||
#include "dn_net.h"
|
||||
#endif
|
||||
|
||||
@@ -43,7 +45,7 @@ DN_NETRequestHandle DN_NET_HandleFromRequest(DN_NETRequest *request)
|
||||
void DN_NET_EndFinishedRequest_(DN_NETRequest *request)
|
||||
{
|
||||
// NOTE: Deallocate the memory used in the request and reset the string builder
|
||||
DN_ArenaPopTo(&request->arena, request->start_response_arena_pos);
|
||||
DN_ArenaTempEnd(&request->start_response_arena, DN_ArenaReset_Yes);
|
||||
// NOTE: Check that the request is completely detached
|
||||
DN_Assert(request->next == nullptr);
|
||||
}
|
||||
@@ -52,7 +54,8 @@ void DN_NET_BaseInit_(DN_NETCore *net, char *base, DN_U64 base_size)
|
||||
{
|
||||
net->base = base;
|
||||
net->base_size = base_size;
|
||||
net->arena = DN_ArenaFromBuffer(net->base, net->base_size, DN_ArenaFlags_Nil);
|
||||
net->mem = DN_MemListFromBuffer(net->base, net->base_size, DN_MemFlags_Nil);
|
||||
net->arena = DN_ArenaFromMemList(&net->mem);
|
||||
net->completion_sem = DN_OS_SemaphoreInit(0);
|
||||
}
|
||||
|
||||
@@ -61,31 +64,32 @@ DN_NETRequestHandle DN_NET_SetupRequest_(DN_NETRequest *request, DN_Str8 url, DN
|
||||
// NOTE: Setup request
|
||||
DN_Assert(request);
|
||||
if (request) {
|
||||
if (!request->arena.curr)
|
||||
request->arena = DN_ArenaFromVMem(DN_Megabytes(1), DN_Kilobytes(1), DN_ArenaFlags_Nil);
|
||||
if (!request->mem.curr)
|
||||
request->mem = DN_MemListFromVMem(DN_Megabytes(1), DN_Kilobytes(1), DN_MemFlags_Nil);
|
||||
request->arena = DN_ArenaTempBeginFromMemList(&request->mem);
|
||||
request->type = type;
|
||||
request->gen = DN_Max(request->gen + 1, 1);
|
||||
request->url = DN_Str8FromStr8Arena(&request->arena, url);
|
||||
request->method = DN_Str8FromStr8Arena(&request->arena, DN_Str8TrimWhitespaceAround(method));
|
||||
request->url = DN_Str8FromStr8Arena(url, &request->arena);
|
||||
request->method = DN_Str8FromStr8Arena(DN_Str8TrimWhitespaceAround(method), &request->arena);
|
||||
|
||||
if (args) {
|
||||
request->args.flags = args->flags;
|
||||
request->args.username = DN_Str8FromStr8Arena(&request->arena, args->username);
|
||||
request->args.password = DN_Str8FromStr8Arena(&request->arena, args->password);
|
||||
request->args.username = DN_Str8FromStr8Arena(args->username, &request->arena);
|
||||
request->args.password = DN_Str8FromStr8Arena(args->password, &request->arena);
|
||||
if (type == DN_NETRequestType_HTTP)
|
||||
request->args.payload = DN_Str8FromStr8Arena(&request->arena, args->payload);
|
||||
request->args.payload = DN_Str8FromStr8Arena(args->payload, &request->arena);
|
||||
|
||||
request->args.headers = DN_ArenaNewArray(&request->arena, DN_Str8, args->headers_size, DN_ZMem_No);
|
||||
DN_Assert(request->args.headers);
|
||||
if (request->args.headers) {
|
||||
for (DN_ForItSize(it, DN_Str8, args->headers, args->headers_size))
|
||||
request->args.headers[it.index] = DN_Str8FromStr8Arena(&request->arena, *it.data);
|
||||
request->args.headers[it.index] = DN_Str8FromStr8Arena(*it.data, &request->arena);
|
||||
request->args.headers_size = args->headers_size;
|
||||
}
|
||||
}
|
||||
|
||||
request->completion_sem = DN_OS_SemaphoreInit(0);
|
||||
request->start_response_arena_pos = DN_ArenaPos(&request->arena);
|
||||
request->completion_sem = DN_OS_SemaphoreInit(0);
|
||||
request->start_response_arena = DN_ArenaTempBeginFromArena(&request->arena);
|
||||
}
|
||||
|
||||
DN_NETRequestHandle result = DN_NET_HandleFromRequest(request);
|
||||
|
||||
+20
-17
@@ -2,8 +2,8 @@
|
||||
#define DN_NET_H
|
||||
|
||||
#if defined(_CLANGD)
|
||||
#include "../dn_base_inc.h"
|
||||
#include "../dn_os_inc.h"
|
||||
#define DN_H_WITH_OS 1
|
||||
#include "../dn.h"
|
||||
#endif
|
||||
|
||||
enum DN_NETRequestType
|
||||
@@ -74,8 +74,9 @@ struct DN_NETResponse
|
||||
|
||||
struct DN_NETRequest
|
||||
{
|
||||
DN_MemList mem;
|
||||
DN_Arena arena;
|
||||
DN_USize start_response_arena_pos;
|
||||
DN_Arena start_response_arena;
|
||||
DN_NETRequestType type;
|
||||
DN_U64 gen;
|
||||
DN_Str8 url;
|
||||
@@ -88,22 +89,13 @@ struct DN_NETRequest
|
||||
DN_U64 context[2];
|
||||
};
|
||||
|
||||
struct DN_NETCore
|
||||
{
|
||||
char *base;
|
||||
DN_U64 base_size;
|
||||
DN_Arena arena;
|
||||
DN_OSSemaphore completion_sem;
|
||||
void *context;
|
||||
};
|
||||
|
||||
typedef void (DN_NETInitFunc) (DN_NETCore *net, char *base, DN_U64 base_size);
|
||||
typedef void (DN_NETDeinitFunc) (DN_NETCore *net);
|
||||
typedef DN_NETRequestHandle(DN_NETDoHTTPFunc) (DN_NETCore *net, DN_Str8 url, DN_Str8 method, DN_NETDoHTTPArgs const *args);
|
||||
typedef DN_NETRequestHandle(DN_NETDoWSFunc) (DN_NETCore *net, DN_Str8 url);
|
||||
typedef void (DN_NETInitFunc) (struct DN_NETCore *net, char *base, DN_U64 base_size);
|
||||
typedef void (DN_NETDeinitFunc) (struct DN_NETCore *net);
|
||||
typedef DN_NETRequestHandle(DN_NETDoHTTPFunc) (struct DN_NETCore *net, DN_Str8 url, DN_Str8 method, DN_NETDoHTTPArgs const *args);
|
||||
typedef DN_NETRequestHandle(DN_NETDoWSFunc) (struct DN_NETCore *net, DN_Str8 url);
|
||||
typedef void (DN_NETDoWSSendFunc) (DN_NETRequestHandle handle, DN_Str8 data, DN_NETWSSend send);
|
||||
typedef DN_NETResponse (DN_NETWaitForResponseFunc) (DN_NETRequestHandle handle, DN_Arena *arena, DN_U32 timeout_ms);
|
||||
typedef DN_NETResponse (DN_NETWaitForAnyResponseFunc)(DN_NETCore *net, DN_Arena *arena, DN_U32 timeout_ms);
|
||||
typedef DN_NETResponse (DN_NETWaitForAnyResponseFunc)(struct DN_NETCore *net, DN_Arena *arena, DN_U32 timeout_ms);
|
||||
|
||||
struct DN_NETInterface
|
||||
{
|
||||
@@ -116,6 +108,17 @@ struct DN_NETInterface
|
||||
DN_NETWaitForAnyResponseFunc* wait_for_any_response;
|
||||
};
|
||||
|
||||
struct DN_NETCore
|
||||
{
|
||||
char *base;
|
||||
DN_U64 base_size;
|
||||
DN_MemList mem;
|
||||
DN_Arena arena;
|
||||
DN_OSSemaphore completion_sem;
|
||||
void *context;
|
||||
DN_NETInterface api;
|
||||
};
|
||||
|
||||
DN_Str8 DN_NET_Str8FromResponseState(DN_NETResponseState state);
|
||||
DN_NETRequest * DN_NET_RequestFromHandle (DN_NETRequestHandle handle);
|
||||
DN_NETRequestHandle DN_NET_HandleFromRequest (DN_NETRequest *request);
|
||||
|
||||
@@ -129,7 +129,7 @@ static int32_t DN_NET_CurlThreadEntryPoint_(DN_OSThread *thread)
|
||||
DN_Str8 payload = {};
|
||||
for (DN_OS_MutexScope(&curl->ring_mutex)) {
|
||||
DN_Assert(DN_RingHasData(&curl->ring, event.ws_send_size));
|
||||
payload = DN_Str8AllocArena(tmem.arena, event.ws_send_size, DN_ZMem_No);
|
||||
payload = DN_Str8AllocArena(event.ws_send_size, DN_ZMem_No, &tmem.arena);
|
||||
DN_RingRead(&curl->ring, payload.data, payload.size);
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ static int32_t DN_NET_CurlThreadEntryPoint_(DN_OSThread *thread)
|
||||
DN_NETRequest *request = DN_Cast(DN_NETRequest *) event.request.handle;
|
||||
|
||||
// NOTE: Release resources
|
||||
DN_ArenaClear(&request->arena);
|
||||
DN_ArenaTempEnd(&request->arena, DN_ArenaReset_Yes);
|
||||
DN_OS_SemaphoreDeinit(&request->completion_sem);
|
||||
|
||||
curl_multi_remove_handle(curl->thread_curlm, curl_req->handle);
|
||||
@@ -224,7 +224,7 @@ static int32_t DN_NET_CurlThreadEntryPoint_(DN_OSThread *thread)
|
||||
}
|
||||
} else {
|
||||
req->response.error_str8 = DN_Str8FromFmtArena(&req->arena, "Failed to get HTTP response status (CURL %d): %s", msg->data.result, curl_easy_strerror(get_result));
|
||||
req->response.state = DN_NETResponseState_Error;
|
||||
req->response.state = DN_NETResponseState_Error;
|
||||
}
|
||||
} else {
|
||||
DN_USize curl_extended_error_size = DN_CStr8Size(curl_req->error);
|
||||
@@ -302,7 +302,7 @@ static int32_t DN_NET_CurlThreadEntryPoint_(DN_OSThread *thread)
|
||||
|
||||
// NOTE: Allocate and read (we use meta->bytesleft as per comment from initial recv)
|
||||
if (meta->bytesleft) {
|
||||
DN_Str8 buffer = DN_Str8AllocArena(&req->arena, meta->bytesleft, DN_ZMem_No);
|
||||
DN_Str8 buffer = DN_Str8AllocArena(meta->bytesleft, DN_ZMem_No, &req->arena);
|
||||
DN_Assert(buffer.size == DN_Cast(DN_USize)meta->bytesleft);
|
||||
receive_result = curl_ws_recv(curl_req->handle, buffer.data, buffer.size, &buffer.size, &meta);
|
||||
DN_Assert(buffer.size == DN_Cast(DN_USize)meta->len);
|
||||
@@ -353,13 +353,13 @@ static int32_t DN_NET_CurlThreadEntryPoint_(DN_OSThread *thread)
|
||||
DN_USize curl_extended_error_size = DN_CStr8Size(curl_req->error);
|
||||
req->response.state = DN_NETResponseState_Error;
|
||||
req->response.error_str8 = DN_Str8FromFmtArena(&req->arena,
|
||||
"Websocket receive '%.*s' failed (CURL %d): %s%s%s%s",
|
||||
DN_Str8PrintFmt(req->url),
|
||||
receive_result,
|
||||
curl_easy_strerror(receive_result),
|
||||
curl_extended_error_size ? " (" : "",
|
||||
curl_extended_error_size ? curl_req->error : "",
|
||||
curl_extended_error_size ? ")" : "");
|
||||
"Websocket receive '%.*s' failed (CURL %d): %s%s%s%s",
|
||||
DN_Str8PrintFmt(req->url),
|
||||
receive_result,
|
||||
curl_easy_strerror(receive_result),
|
||||
curl_extended_error_size ? " (" : "",
|
||||
curl_extended_error_size ? curl_req->error : "",
|
||||
curl_extended_error_size ? ")" : "");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,10 +394,11 @@ DN_NETInterface DN_NET_CurlInterface()
|
||||
void DN_NET_CurlInit(DN_NETCore *net, char *base, DN_U64 base_size)
|
||||
{
|
||||
DN_NET_BaseInit_(net, base, base_size);
|
||||
DN_NETCurlCore *curl = DN_ArenaNew(&net->arena, DN_NETCurlCore, DN_ZMem_Yes);
|
||||
net->context = curl;
|
||||
DN_NETCurlCore *curl = DN_ArenaNew(&net->arena, DN_NETCurlCore, DN_ZMem_Yes);
|
||||
net->context = curl;
|
||||
net->api = DN_NET_CurlInterface();
|
||||
|
||||
DN_USize arena_bytes_avail = (net->arena.curr->reserve - net->arena.curr->used);
|
||||
DN_USize arena_bytes_avail = (net->arena.mem->curr->reserve - net->arena.mem->curr->used);
|
||||
curl->ring.size = arena_bytes_avail / 2;
|
||||
curl->ring.base = DN_Cast(char *) DN_ArenaAlloc(&net->arena, curl->ring.size, /*align*/ 1, DN_ZMem_Yes);
|
||||
DN_Assert(curl->ring.base);
|
||||
@@ -415,7 +416,7 @@ void DN_NET_CurlDeinit(DN_NETCore *net)
|
||||
DN_NETCurlCore *curl = DN_Cast(DN_NETCurlCore *) net->context;
|
||||
curl->kill_thread = true;
|
||||
curl_multi_wakeup(curl->thread_curlm);
|
||||
DN_OS_ThreadJoin(&curl->thread);
|
||||
DN_OS_ThreadJoin(&curl->thread, DN_TCDeinitArenas_Yes);
|
||||
}
|
||||
|
||||
static DN_NETRequestHandle DN_NET_CurlDoRequest_(DN_NETCore *net, DN_Str8 url, DN_Str8 method, DN_NETDoHTTPArgs const *args, DN_NETRequestType type)
|
||||
@@ -434,11 +435,11 @@ static DN_NETRequestHandle DN_NET_CurlDoRequest_(DN_NETCore *net, DN_Str8 url, D
|
||||
|
||||
// NOTE None in the free list so allocate one
|
||||
if (!req) {
|
||||
DN_U64 arena_pos = DN_ArenaPos(&net->arena);
|
||||
DN_U64 arena_pos = DN_MemListPos(net->arena.mem);
|
||||
req = DN_ArenaNew(&net->arena, DN_NETRequest, DN_ZMem_Yes);
|
||||
DN_NETCurlRequest *curl_req = DN_ArenaNew(&net->arena, DN_NETCurlRequest, DN_ZMem_Yes);
|
||||
if (!req || !curl_req) {
|
||||
DN_ArenaPopTo(&net->arena, arena_pos);
|
||||
DN_MemListPopTo(net->arena.mem, arena_pos);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -453,7 +454,7 @@ static DN_NETRequestHandle DN_NET_CurlDoRequest_(DN_NETCore *net, DN_Str8 url, D
|
||||
result = DN_NET_SetupRequest_(req, url, method, args, type);
|
||||
req->response.request = result;
|
||||
req->context[1] = DN_Cast(DN_UPtr) net;
|
||||
curl_req->str8_builder = DN_Str8BuilderFromArena(&req->arena);
|
||||
curl_req->str8_builder = DN_Str8BuilderFromArena(&req->start_response_arena);
|
||||
}
|
||||
|
||||
// NOTE: Setup the request for curl API
|
||||
@@ -587,8 +588,8 @@ static DN_NETResponse DN_NET_CurlHandleFinishedRequest_(DN_NETCurlCore *curl, DN
|
||||
DN_NETCurlRequest *curl_req = DN_NET_CurlRequestFromRequest_(req);
|
||||
result.body = DN_Str8BuilderBuild(&curl_req->str8_builder, arena);
|
||||
if (result.error_str8.size)
|
||||
result.error_str8 = DN_Str8FromStr8Arena(arena, result.error_str8);
|
||||
curl_req->str8_builder = DN_Str8BuilderFromArena(&req->arena);
|
||||
result.error_str8 = DN_Str8FromStr8Arena(result.error_str8, arena);
|
||||
curl_req->str8_builder = {}; // Clear it out, reinitialised on subsequent do request call
|
||||
}
|
||||
DN_NET_EndFinishedRequest_(req);
|
||||
|
||||
|
||||
+375
-254
File diff suppressed because it is too large
Load Diff
@@ -2,12 +2,14 @@
|
||||
#define DN_NO_WINDOWS_H_REPLACEMENT_HEADER
|
||||
#endif
|
||||
|
||||
#define DN_H_WITH_OS 1
|
||||
#define DN_H_WITH_CORE 1
|
||||
#define DN_H_WITH_HASH 1
|
||||
#define DN_H_WITH_HELPERS 1
|
||||
#define DN_H_WITH_ASYNC 1
|
||||
#define DN_H_WITH_NET 1
|
||||
#define DN_ARENA_TEMP_MEM_UAF_GUARD 1
|
||||
#define DN_ARENA_TEMP_MEM_UAF_TRACE_ON_BY_DEFAULT 0
|
||||
#define DN_H_WITH_OS 1
|
||||
#define DN_H_WITH_CORE 1
|
||||
#define DN_H_WITH_HASH 1
|
||||
#define DN_H_WITH_HELPERS 1
|
||||
#define DN_H_WITH_ASYNC 1
|
||||
#define DN_H_WITH_NET 1
|
||||
#include "../dn.h"
|
||||
#include "../dn.cpp"
|
||||
|
||||
@@ -35,7 +37,7 @@ int main(int, char**)
|
||||
{
|
||||
DN_Core dn = {};
|
||||
DN_Init(&dn, DN_InitFlags_LogAllFeatures | DN_InitFlags_OS | DN_InitFlags_ThreadContext, nullptr);
|
||||
DN_Tests_RunSuite(DN_TestsPrint_Yes);
|
||||
DN_TST_RunSuite(DN_TSTPrint_Yes);
|
||||
return 0;
|
||||
}
|
||||
DN_MSVC_WARNING_POP
|
||||
|
||||
Reference in New Issue
Block a user