mirror of
https://github.com/Karaka-Management/cOMS.git
synced 2026-01-10 19:08:39 +00:00
update
This commit is contained in:
parent
dc9f37b726
commit
20770b42a4
|
|
@ -19,11 +19,11 @@
|
|||
|
||||
uint64 cpu_info_features() {
|
||||
uint64 feature_bitfield = 0;
|
||||
int32 cpuInfo[4] = {0};
|
||||
uint32 cpu_info[4] = {0};
|
||||
|
||||
compiler_cpuid(cpuInfo, 0x00000001);
|
||||
uint32 ecx = (uint32) cpuInfo[2];
|
||||
uint32 edx = (uint32) cpuInfo[3];
|
||||
compiler_cpuid(cpu_info, 0x00000001);
|
||||
uint32 ecx = (uint32) cpu_info[2];
|
||||
uint32 edx = (uint32) cpu_info[3];
|
||||
|
||||
// Map ECX features
|
||||
if (ecx & (1 << 0)) feature_bitfield |= CPU_FEATURE_SSE3;
|
||||
|
|
@ -54,9 +54,9 @@ uint64 cpu_info_features() {
|
|||
if (edx & (1 << 25)) feature_bitfield |= CPU_FEATURE_SSE;
|
||||
if (edx & (1 << 26)) feature_bitfield |= CPU_FEATURE_SSE2;
|
||||
|
||||
compiler_cpuid(cpuInfo, 0x00000007);
|
||||
uint32 ebx = (uint32) cpuInfo[1];
|
||||
uint32 ecx7 = (uint32) cpuInfo[2];
|
||||
compiler_cpuid(cpu_info, 0x00000007);
|
||||
uint32 ebx = (uint32) cpu_info[1];
|
||||
uint32 ecx7 = (uint32) cpu_info[2];
|
||||
|
||||
// Map EBX features
|
||||
if (ebx & (1 << 3)) feature_bitfield |= CPU_FEATURE_BMI1;
|
||||
|
|
@ -76,9 +76,9 @@ uint64 cpu_info_features() {
|
|||
// Map ECX features
|
||||
if (ecx7 & (1 << 0)) feature_bitfield |= CPU_FEATURE_PREFETCHWT1;
|
||||
|
||||
compiler_cpuid(cpuInfo, 0x80000001);
|
||||
uint32 ecx81 = (uint32) cpuInfo[2];
|
||||
uint32 edx81 = (uint32) cpuInfo[3];
|
||||
compiler_cpuid(cpu_info, 0x80000001);
|
||||
uint32 ecx81 = (uint32) cpu_info[2];
|
||||
uint32 edx81 = (uint32) cpu_info[3];
|
||||
|
||||
// Map ECX extended features
|
||||
if (ecx81 & (1 << 0)) feature_bitfield |= CPU_FEATURE_LAHF;
|
||||
|
|
@ -108,8 +108,8 @@ void cpu_info_cache(byte level, CpuCacheInfo* cache) {
|
|||
cache->sets = 0;
|
||||
cache->line_size = 0;
|
||||
|
||||
int32 regs[4];
|
||||
compiler_cpuid(regs, (0x04 << 8) | level);
|
||||
uint32 regs[4];
|
||||
compiler_cpuid(regs, 0x04, level);
|
||||
eax = regs[0];
|
||||
ebx = regs[1];
|
||||
ecx = regs[2];
|
||||
|
|
@ -123,7 +123,7 @@ void cpu_info_cache(byte level, CpuCacheInfo* cache) {
|
|||
|
||||
cache->ways = (byte) ((ebx >> 22) & 0x3FF) + 1;
|
||||
cache->partitions = (byte) ((ebx >> 12) & 0x3FF) + 1;
|
||||
cache->line_size = (uint16) (ebx & 0xFFF) + 1;
|
||||
cache->line_size = OMS_MAX((uint16) (ebx & 0xFFF) + 1, 64);
|
||||
cache->sets = ecx + 1;
|
||||
cache->size = cache->ways * cache->partitions * cache->line_size * cache->sets;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,20 +86,28 @@ int32 compiler_find_first_bit_l2r(uint32 mask) noexcept {
|
|||
|
||||
/*
|
||||
#include <cpuid.h>
|
||||
|
||||
static inline
|
||||
void cpuid(int32 cpuInfo[4], int32 function_id) {
|
||||
__cpuid(function_id, cpuInfo[0], cpuInfo[1], cpuInfo[2], cpuInfo[3]);
|
||||
inline
|
||||
void compiler_cpuid(uint32 cpu_info[4], int32 function_id) {
|
||||
__cpuid(function_id, cpu_info[0], cpu_info[1], cpu_info[2], cpu_info[3]);
|
||||
}
|
||||
*/
|
||||
|
||||
inline
|
||||
void compiler_cpuid(int32 cpuInfo[4], int32 function_id) noexcept {
|
||||
void compiler_cpuid(uint32 cpu_info[4], int32 function_id) noexcept {
|
||||
asm volatile(
|
||||
"cpuid"
|
||||
: "=a" (cpuInfo[0]), "=b" (cpuInfo[1]), "=c" (cpuInfo[2]), "=d" (cpuInfo[3])
|
||||
: "=a" (cpu_info[0]), "=b" (cpu_info[1]), "=c" (cpu_info[2]), "=d" (cpu_info[3])
|
||||
: "a" (function_id)
|
||||
);
|
||||
}
|
||||
|
||||
inline
|
||||
void compiler_cpuid(uint32 cpu_info[4], int32 function_id, int32 level) noexcept {
|
||||
asm volatile(
|
||||
"cpuid"
|
||||
: "=a" (cpu_info[0]), "=b" (cpu_info[1]), "=c" (cpu_info[2]), "=d" (cpu_info[3])
|
||||
: "a" (function_id), "c" (level)
|
||||
);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -79,8 +79,9 @@ int32 compiler_find_first_bit_l2r(uint32 mask) noexcept {
|
|||
}
|
||||
|
||||
inline
|
||||
void compiler_cpuid(int32 cpuInfo[4], int32 function_id) noexcept {
|
||||
__cpuidex(cpuInfo, function_id, 0);
|
||||
void compiler_cpuid(uint32 cpu_info[4], int32 function_id, int32 level = 0) noexcept {
|
||||
__cpuidex(cpu_info, function_id, level);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -10,7 +10,12 @@
|
|||
#define COMS_DATABASE_SQLITE_H
|
||||
|
||||
#include "../../stdlib/Types.h"
|
||||
#include "../../EngineDependencies/sqlite/src/sqlite3.h"
|
||||
|
||||
#if _WIN32
|
||||
#include "../../EngineDependencies/sqlite/src/sqlite3.h"
|
||||
#else
|
||||
#include <sqlite3.h>
|
||||
#endif
|
||||
|
||||
inline
|
||||
int32 db_open_sqlite(DatabaseConnection* con)
|
||||
|
|
|
|||
|
|
@ -58,11 +58,11 @@ size_t base64_decode(const char* encoded_data, byte* data, size_t encoded_length
|
|||
size_t output_length = encoded_length / 4 * 3;
|
||||
int32 padding = 0;
|
||||
|
||||
if (data[encoded_length - 1] == '=') {
|
||||
if (encoded_data[encoded_length - 1] == '=') {
|
||||
--output_length;
|
||||
++padding;
|
||||
|
||||
if (data[encoded_length - 2] == '=') {
|
||||
if (encoded_data[encoded_length - 2] == '=') {
|
||||
--output_length;
|
||||
++padding;
|
||||
}
|
||||
|
|
@ -88,9 +88,8 @@ size_t base64_decode(const char* encoded_data, byte* data, size_t encoded_length
|
|||
uint32 sextet_a = BASE64_LOOKUP[(byte) encoded_data[i]];
|
||||
uint32 sextet_b = BASE64_LOOKUP[(byte) encoded_data[i + 1]];
|
||||
uint32 sextet_c = (padding > 1) ? 0 : BASE64_LOOKUP[(byte) encoded_data[i + 2]];
|
||||
uint32 sextet_d = 0;
|
||||
|
||||
uint32 triple = (sextet_a << 18) | (sextet_b << 12) | (sextet_c << 6) | sextet_d;
|
||||
uint32 triple = (sextet_a << 18) | (sextet_b << 12) | (sextet_c << 6);
|
||||
|
||||
data[j + 1] = (triple >> 16) & 0xFF;
|
||||
if (padding == 1) {
|
||||
|
|
|
|||
|
|
@ -255,9 +255,8 @@ size_t base64_decode_simd(const char* encoded_data, byte* data, size_t encoded_l
|
|||
uint32 sextet_a = BASE64_LOOKUP[(byte) encoded_data[i]];
|
||||
uint32 sextet_b = BASE64_LOOKUP[(byte) encoded_data[i + 1]];
|
||||
uint32 sextet_c = (padding > 1) ? 0 : BASE64_LOOKUP[(byte) encoded_data[i + 2]];
|
||||
uint32 sextet_d = 0;
|
||||
|
||||
uint32 triple = (sextet_a << 18) | (sextet_b << 12) | (sextet_c << 6) | sextet_d;
|
||||
uint32 triple = (sextet_a << 18) | (sextet_b << 12) | (sextet_c << 6);
|
||||
|
||||
data[j] = (triple >> 16) & 0xFF;
|
||||
if (padding == 1) {
|
||||
|
|
|
|||
|
|
@ -389,9 +389,8 @@ size_t base64_decode_simd(const char* encoded_data, byte* data, size_t encoded_l
|
|||
uint32 sextet_a = BASE64_LOOKUP[(byte) encoded_data[i]];
|
||||
uint32 sextet_b = BASE64_LOOKUP[(byte) encoded_data[i + 1]];
|
||||
uint32 sextet_c = (padding > 1) ? 0 : BASE64_LOOKUP[(byte) encoded_data[i + 2]];
|
||||
uint32 sextet_d = 0;
|
||||
|
||||
uint32 triple = (sextet_a << 18) | (sextet_b << 12) | (sextet_c << 6) | sextet_d;
|
||||
uint32 triple = (sextet_a << 18) | (sextet_b << 12) | (sextet_c << 6);
|
||||
|
||||
data[j] = (triple >> 16) & 0xFF;
|
||||
if (padding == 1) {
|
||||
|
|
|
|||
|
|
@ -190,9 +190,9 @@ void html_template_cache_load_all(HtmlTemplateCache* cache, const char* basedir,
|
|||
LOG_1("Loaded all html templates with %n in cache size", {{LOG_DATA_INT32, &cache->cache_pos}});
|
||||
}
|
||||
|
||||
HtmlTemplateASTNode* html_template_cache_get(HtmlTemplateCache* cache, const char* key)
|
||||
HtmlTemplateASTNode* html_template_cache_get(const HtmlTemplateCache* cache, const char* key)
|
||||
{
|
||||
PerfectHashEntryInt32* entry = (PerfectHashEntryInt32 *) perfect_hashmap_get_entry(&cache->hm, key);
|
||||
const PerfectHashEntryInt32* entry = (PerfectHashEntryInt32 *) perfect_hashmap_get_entry(&cache->hm, key);
|
||||
if (!entry) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ HtmlTemplateToken html_template_token_next(const char** input, HtmlTemplateConte
|
|||
} else if (context_flag == HTML_TEMPLATE_CONTEXT_FLAG_HTML) {
|
||||
// We might be in html mode or template mode
|
||||
// Depending on the mode we must handle chars differently
|
||||
if ((**input == '<' && **input == '?')) {
|
||||
if ((**input == '<' && (*input)[1] == '?')) {
|
||||
token.type = TOKEN_CODE_START;
|
||||
token.length = 2;
|
||||
|
||||
|
|
@ -101,7 +101,7 @@ HtmlTemplateToken html_template_token_next(const char** input, HtmlTemplateConte
|
|||
token.type = TOKEN_HTML;
|
||||
|
||||
// Move input along until EOF or template code is found
|
||||
while (**input != '\0' && (**input != '<' || **input != '?')) {
|
||||
while (**input != '\0' && (**input != '<' || (*input)[1] != '?')) {
|
||||
++(*input);
|
||||
++token.length;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ struct HtmlTemplateASTNode {
|
|||
};
|
||||
};
|
||||
|
||||
HtmlTemplateASTNode* html_template_node_create(HtmlTemplateNodeType type, HtmlTemplateToken* token, byte** memory) {
|
||||
HtmlTemplateASTNode* html_template_node_create(HtmlTemplateNodeType type, const HtmlTemplateToken* token, byte** memory) {
|
||||
*memory = (byte *) ROUND_TO_NEAREST((uintptr_t) *memory, 32);
|
||||
HtmlTemplateASTNode* node = (HtmlTemplateASTNode *) *memory;
|
||||
*memory = (byte *) ROUND_TO_NEAREST((uintptr_t) (*memory + sizeof(HtmlTemplateASTNode)), 32);
|
||||
|
|
@ -232,7 +232,13 @@ HtmlTemplateASTNode* html_template_parse_for(const char** input, HtmlTemplateTok
|
|||
return forNode;
|
||||
}
|
||||
|
||||
HtmlTemplateASTNode* html_template_html_parse(const char** input, HtmlTemplateToken* token_current, HtmlTemplateContextStack* context_stack, HtmlTemplateContextFlag context_flag, byte** memory) {
|
||||
HtmlTemplateASTNode* html_template_html_parse(
|
||||
const char** input,
|
||||
HtmlTemplateToken* token_current,
|
||||
HtmlTemplateContextStack* context_stack,
|
||||
HtmlTemplateContextFlag context_flag,
|
||||
byte** memory
|
||||
) {
|
||||
HtmlTemplateASTNode* html = html_template_node_create(NODE_RAW, token_current, memory);
|
||||
|
||||
*token_current = html_template_token_next(input, context_flag); // Consume html
|
||||
|
|
@ -243,18 +249,47 @@ HtmlTemplateASTNode* html_template_html_parse(const char** input, HtmlTemplateTo
|
|||
return html;
|
||||
}
|
||||
|
||||
HtmlTemplateASTNode* html_template_statement_parse(const char** input, HtmlTemplateToken* token_current, HtmlTemplateContextStack* context_stack, HtmlTemplateContextFlag context_flag, byte** memory) {
|
||||
if (token_current->type == TOKEN_HTML) {
|
||||
return html_template_html_parse(input, token_current, context_stack, context_flag, memory);
|
||||
} else if (token_current->type == TOKEN_ASSIGN) {
|
||||
return html_template_assignment_parse(input, token_current, context_flag, memory);
|
||||
} else if (token_current->type == TOKEN_IF) {
|
||||
return html_template_parse_if(input, token_current, context_stack, context_flag, memory);
|
||||
} else if (token_current->type == TOKEN_FOR) {
|
||||
return html_template_parse_for(input, token_current, context_stack, context_flag, memory);
|
||||
} else {
|
||||
ASSERT_SIMPLE(false);
|
||||
exit(1);
|
||||
HtmlTemplateASTNode* html_template_code_parse(
|
||||
const char** input,
|
||||
HtmlTemplateToken* token_current,
|
||||
HtmlTemplateContextStack* context_stack,
|
||||
HtmlTemplateContextFlag context_flag,
|
||||
byte** memory
|
||||
) {
|
||||
HtmlTemplateASTNode* code = html_template_node_create(NODE_RAW, token_current, memory);
|
||||
|
||||
*token_current = html_template_token_next(input, context_flag); // Consume code
|
||||
if (token_current->type != TOKEN_EOF) {
|
||||
code->right = html_template_statement_parse(input, token_current, context_stack, context_flag, memory);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
HtmlTemplateASTNode* html_template_statement_parse(
|
||||
const char** input,
|
||||
HtmlTemplateToken* token_current,
|
||||
HtmlTemplateContextStack* context_stack,
|
||||
HtmlTemplateContextFlag context_flag,
|
||||
byte** memory
|
||||
) {
|
||||
switch(token_current->type) {
|
||||
case TOKEN_HTML: {
|
||||
return html_template_html_parse(input, token_current, context_stack, context_flag, memory);
|
||||
};
|
||||
case TOKEN_ASSIGN: {
|
||||
return html_template_assignment_parse(input, token_current, context_flag, memory);
|
||||
};
|
||||
case TOKEN_IF: {
|
||||
return html_template_parse_if(input, token_current, context_stack, context_flag, memory);
|
||||
};
|
||||
case TOKEN_FOR: {
|
||||
return html_template_parse_for(input, token_current, context_stack, context_flag, memory);
|
||||
};
|
||||
case TOKEN_CODE_START: {
|
||||
return html_template_code_parse(input, token_current, context_stack, context_flag, memory);
|
||||
};
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ void parse_multipart_data(const char *body, const char *boundary) {
|
|||
while (*part == '\r' || *part == '\n') part++;
|
||||
|
||||
// Parse part headers and content
|
||||
char *headers_end = strstr(part, "\r\n\r\n");
|
||||
char* headers_end = strstr(part, "\r\n\r\n");
|
||||
if (headers_end) {
|
||||
*headers_end = '\0'; // Terminate headers
|
||||
char *content = headers_end + 4; // Skip "\r\n\r\n"
|
||||
|
|
|
|||
|
|
@ -34,16 +34,15 @@ struct DebugMemory {
|
|||
uintptr_t start;
|
||||
uint64 size;
|
||||
|
||||
uint64 action_idx;
|
||||
alignas(4) atomic_32 uint32 action_idx;
|
||||
alignas(4) atomic_32 uint32 reserve_action_idx;
|
||||
DebugMemoryRange last_action[DEBUG_MEMORY_RANGE_MAX];
|
||||
|
||||
uint64 reserve_action_idx;
|
||||
DebugMemoryRange reserve_action[DEBUG_MEMORY_RANGE_RES_MAX];
|
||||
};
|
||||
|
||||
struct DebugMemoryContainer {
|
||||
uint64 memory_size;
|
||||
uint64 memory_element_idx;
|
||||
uint32 memory_size;
|
||||
uint32 memory_element_idx;
|
||||
DebugMemory* memory_stats;
|
||||
};
|
||||
static DebugMemoryContainer* _dmc = NULL;
|
||||
|
|
@ -72,7 +71,7 @@ DebugMemory* debug_memory_find(uintptr_t start) noexcept
|
|||
|
||||
void debug_memory_init(uintptr_t start, uint64 size) noexcept
|
||||
{
|
||||
if (!start || !_dmc) {
|
||||
if (!start || !_dmc || (_dmc->memory_size && !_dmc->memory_stats)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -82,15 +81,19 @@ void debug_memory_init(uintptr_t start, uint64 size) noexcept
|
|||
}
|
||||
|
||||
if (_dmc->memory_size <= _dmc->memory_element_idx) {
|
||||
DebugMemory* old = _dmc->memory_stats;
|
||||
|
||||
_dmc->memory_size += 3;
|
||||
_dmc->memory_stats = (DebugMemory *) calloc(_dmc->memory_size, sizeof(DebugMemory));
|
||||
|
||||
if (old) {
|
||||
memcpy(_dmc->memory_stats, old, (_dmc->memory_size - 3) * sizeof(DebugMemory));
|
||||
free(old);
|
||||
const uint64 new_size = _dmc->memory_size + 3;
|
||||
DebugMemory* new_stats = (DebugMemory *) calloc(new_size, sizeof(DebugMemory));
|
||||
if (!new_stats) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_dmc->memory_stats) {
|
||||
memcpy(new_stats, _dmc->memory_stats, _dmc->memory_size * sizeof(DebugMemory));
|
||||
free(_dmc->memory_stats);
|
||||
}
|
||||
|
||||
_dmc->memory_stats = new_stats;
|
||||
_dmc->memory_size = new_size;
|
||||
}
|
||||
|
||||
DebugMemory* debug_mem = &_dmc->memory_stats[_dmc->memory_element_idx];
|
||||
|
|
@ -112,7 +115,7 @@ void debug_memory_log(uintptr_t start, uint64 size, int32 type, const char* func
|
|||
return;
|
||||
}
|
||||
|
||||
uint64 idx = atomic_fetch_add_relaxed(&mem->action_idx, 1);
|
||||
uint32 idx = atomic_fetch_add_relaxed(&mem->action_idx, 1);
|
||||
if (idx >= ARRAY_COUNT(mem->last_action)) {
|
||||
atomic_set_release(&mem->action_idx, 1);
|
||||
idx %= ARRAY_COUNT(mem->last_action);
|
||||
|
|
@ -144,7 +147,7 @@ void debug_memory_reserve(uintptr_t start, uint64 size, int32 type, const char*
|
|||
return;
|
||||
}
|
||||
|
||||
uint64 idx = atomic_fetch_add_relaxed(&mem->reserve_action_idx, 1);
|
||||
uint32 idx = atomic_fetch_add_relaxed(&mem->reserve_action_idx, 1);
|
||||
if (idx >= ARRAY_COUNT(mem->reserve_action)) {
|
||||
atomic_set_release(&mem->reserve_action_idx, 1);
|
||||
idx %= ARRAY_COUNT(mem->reserve_action);
|
||||
|
|
@ -191,7 +194,7 @@ void debug_memory_reset() noexcept
|
|||
// We remove debug information that are "older" than 1GHz
|
||||
uint64 time = intrin_timestamp_counter() - 1 * GHZ;
|
||||
|
||||
for (uint64 i = 0; i < _dmc->memory_element_idx; ++i) {
|
||||
for (uint32 i = 0; i < _dmc->memory_element_idx; ++i) {
|
||||
for (int32 j = 0; j < DEBUG_MEMORY_RANGE_MAX; ++j) {
|
||||
if (_dmc->memory_stats[i].last_action[j].time < time) {
|
||||
memset(&_dmc->memory_stats[i].last_action[j], 0, sizeof(DebugMemoryRange));
|
||||
|
|
|
|||
|
|
@ -403,7 +403,7 @@ int64 chunk_load(ChunkMemory* buf, const byte* data)
|
|||
data += sizeof(buf->alignment);
|
||||
|
||||
memcpy(buf->memory, data, buf->size);
|
||||
data += buf->size;
|
||||
//data += buf->size;
|
||||
|
||||
buf->free = (uint64 *) (buf->memory + buf->count * buf->chunk_size);
|
||||
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ void queue_free(Queue* queue) noexcept
|
|||
}
|
||||
|
||||
inline
|
||||
bool queue_is_empty(Queue* queue) noexcept {
|
||||
bool queue_is_empty(const Queue* queue) noexcept {
|
||||
return queue->head == queue->tail;
|
||||
}
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ void queue_enqueue_unique(Queue* queue, const byte* data) noexcept
|
|||
}
|
||||
|
||||
inline
|
||||
byte* queue_enqueue(Queue* queue, byte* data) noexcept
|
||||
byte* queue_enqueue(Queue* queue, const byte* data) noexcept
|
||||
{
|
||||
byte* mem = ring_get_memory_nomove((RingMemory *) queue, queue->element_size, queue->alignment);
|
||||
memcpy(mem, data, queue->element_size);
|
||||
|
|
@ -117,7 +117,7 @@ byte* queue_enqueue(Queue* queue, byte* data) noexcept
|
|||
}
|
||||
|
||||
inline
|
||||
byte* queue_enqueue_safe(Queue* queue, byte* data) noexcept
|
||||
byte* queue_enqueue_safe(Queue* queue, const byte* data) noexcept
|
||||
{
|
||||
if(queue_is_full(queue)) {
|
||||
return NULL;
|
||||
|
|
@ -132,7 +132,7 @@ byte* queue_enqueue_safe(Queue* queue, byte* data) noexcept
|
|||
|
||||
// WARNING: Only useful for single producer single consumer
|
||||
inline
|
||||
byte* queue_enqueue_wait_atomic(Queue* queue, byte* data) noexcept
|
||||
byte* queue_enqueue_wait_atomic(Queue* queue, const byte* data) noexcept
|
||||
{
|
||||
while (!ring_commit_safe_atomic((RingMemory *) queue, queue->alignment)) {}
|
||||
|
||||
|
|
@ -145,7 +145,7 @@ byte* queue_enqueue_wait_atomic(Queue* queue, byte* data) noexcept
|
|||
|
||||
// WARNING: Only useful for single producer single consumer
|
||||
inline
|
||||
byte* queue_enqueue_safe_atomic(Queue* queue, byte* data) noexcept
|
||||
byte* queue_enqueue_safe_atomic(Queue* queue, const byte* data) noexcept
|
||||
{
|
||||
if (!ring_commit_safe_atomic((RingMemory *) queue, queue->alignment)) {
|
||||
return NULL;
|
||||
|
|
@ -221,7 +221,7 @@ byte* queue_dequeue_keep(Queue* queue) noexcept
|
|||
}
|
||||
|
||||
inline
|
||||
byte* queue_dequeue_start(Queue* queue) noexcept
|
||||
byte* queue_dequeue_start(const Queue* queue) noexcept
|
||||
{
|
||||
return queue->tail;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ void thrd_chunk_set_unset(uint32 element, atomic_64 uint64* state) {
|
|||
} while (!atomic_compare_exchange_strong_release(target, &old_value, new_value));
|
||||
}
|
||||
|
||||
int32 thrd_chunk_get_unset(ThreadedChunkMemory* buf, atomic_64 uint64* state, int32 start_index = 0) {
|
||||
int32 thrd_chunk_get_unset(const ThreadedChunkMemory* buf, atomic_64 uint64* state, int32 start_index = 0) {
|
||||
if ((uint32) start_index >= buf->count) {
|
||||
start_index = 0;
|
||||
}
|
||||
|
|
@ -253,9 +253,6 @@ void thrd_chunk_free_elements(ThreadedChunkMemory* buf, uint64 element, uint32 e
|
|||
return;
|
||||
}
|
||||
|
||||
alignas(8) atomic_64 uint64* target;
|
||||
uint64 old_value, new_value;
|
||||
|
||||
while (element_count > 0) {
|
||||
// Calculate the number of bits we can clear in the current 64-bit block
|
||||
uint32 bits_in_current_block = OMS_MIN(64 - bit_index, element_count);
|
||||
|
|
@ -263,7 +260,8 @@ void thrd_chunk_free_elements(ThreadedChunkMemory* buf, uint64 element, uint32 e
|
|||
// Create a mask to clear the bits
|
||||
uint64 mask = ((1ULL << bits_in_current_block) - 1) << bit_index;
|
||||
|
||||
target = &buf->free[free_index];
|
||||
uint64 old_value, new_value;
|
||||
alignas(8) atomic_64 uint64* target = &buf->free[free_index];
|
||||
|
||||
do {
|
||||
old_value = atomic_get_relaxed(target);
|
||||
|
|
@ -286,7 +284,7 @@ void thrd_chunk_free_elements(ThreadedChunkMemory* buf, uint64 element, uint32 e
|
|||
inline
|
||||
int32 thrd_chunk_resize(ThreadedChunkMemory* buf, int32 element_id, uint32 elements_old, uint32 elements_new) noexcept
|
||||
{
|
||||
byte* data = thrd_chunk_get_element(buf, element_id);
|
||||
const byte* data = thrd_chunk_get_element(buf, element_id);
|
||||
|
||||
int32 chunk_id = thrd_chunk_reserve(buf, elements_new);
|
||||
byte* data_new = thrd_chunk_get_element(buf, chunk_id);
|
||||
|
|
|
|||
|
|
@ -310,7 +310,7 @@ void thrd_queue_dequeue_end_wait(ThreadedQueue* queue) noexcept
|
|||
|
||||
// Semaphore Lock
|
||||
inline
|
||||
void thrd_queue_enqueue_coms_sem_wait(ThreadedQueue* queue, const byte* data) noexcept
|
||||
void thrd_queue_enqueue_sem_wait(ThreadedQueue* queue, const byte* data) noexcept
|
||||
{
|
||||
coms_sem_wait(&queue->empty);
|
||||
mutex_lock(&queue->mutex);
|
||||
|
|
@ -341,7 +341,7 @@ bool thrd_queue_enqueue_semimedwait(ThreadedQueue* queue, const byte* data, uint
|
|||
}
|
||||
|
||||
inline
|
||||
byte* thrd_queue_enqueue_start_coms_sem_wait(ThreadedQueue* queue) noexcept
|
||||
byte* thrd_queue_enqueue_start_sem_wait(ThreadedQueue* queue) noexcept
|
||||
{
|
||||
coms_sem_wait(&queue->empty);
|
||||
mutex_lock(&queue->mutex);
|
||||
|
|
@ -350,14 +350,14 @@ byte* thrd_queue_enqueue_start_coms_sem_wait(ThreadedQueue* queue) noexcept
|
|||
}
|
||||
|
||||
inline
|
||||
void thrd_queue_enqueue_end_coms_sem_wait(ThreadedQueue* queue) noexcept
|
||||
void thrd_queue_enqueue_end_sem_wait(ThreadedQueue* queue) noexcept
|
||||
{
|
||||
mutex_unlock(&queue->mutex);
|
||||
coms_sem_post(&queue->full);
|
||||
}
|
||||
|
||||
inline
|
||||
byte* thrd_queue_dequeue_coms_sem_wait(ThreadedQueue* queue, byte* data) noexcept
|
||||
byte* thrd_queue_dequeue_sem_wait(ThreadedQueue* queue, byte* data) noexcept
|
||||
{
|
||||
coms_sem_wait(&queue->full);
|
||||
mutex_lock(&queue->mutex);
|
||||
|
|
@ -388,7 +388,7 @@ bool thrd_queue_dequeue_semimedwait(ThreadedQueue* queue, byte* data, uint64 wai
|
|||
}
|
||||
|
||||
inline
|
||||
byte* thrd_queue_dequeue_start_coms_sem_wait(ThreadedQueue* queue) noexcept
|
||||
byte* thrd_queue_dequeue_start_sem_wait(ThreadedQueue* queue) noexcept
|
||||
{
|
||||
coms_sem_wait(&queue->full);
|
||||
mutex_lock(&queue->mutex);
|
||||
|
|
@ -397,7 +397,7 @@ byte* thrd_queue_dequeue_start_coms_sem_wait(ThreadedQueue* queue) noexcept
|
|||
}
|
||||
|
||||
inline
|
||||
void thrd_queue_dequeue_end_coms_sem_wait(ThreadedQueue* queue) noexcept
|
||||
void thrd_queue_dequeue_end_sem_wait(ThreadedQueue* queue) noexcept
|
||||
{
|
||||
ring_move_pointer((RingMemory *) queue, &queue->tail, queue->element_size, queue->alignment);
|
||||
|
||||
|
|
|
|||
|
|
@ -48,8 +48,7 @@ bool library_load(Library* lib)
|
|||
// @question we might want RTLD_NOW?
|
||||
lib->handle = dlopen(dst, RTLD_LAZY);
|
||||
if (!lib->handle) {
|
||||
const char* error = dlerror();
|
||||
LOG_1(error);
|
||||
LOG_1(dlerror());
|
||||
|
||||
lib->is_valid = false;
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -128,6 +128,13 @@ int32 network_info_get(NetworkInfo* info) {
|
|||
}
|
||||
|
||||
void cpu_info_get(CpuInfo* info) {
|
||||
info->features = cpu_info_features();
|
||||
|
||||
cpu_info_cache(1, &info->cache[0]);
|
||||
cpu_info_cache(2, &info->cache[1]);
|
||||
cpu_info_cache(3, &info->cache[2]);
|
||||
cpu_info_cache(4, &info->cache[3]);
|
||||
|
||||
FileHandle fp = file_read_handle("/proc/cpuinfo");
|
||||
char line[256];
|
||||
char internal_buffer[512];
|
||||
|
|
|
|||
|
|
@ -159,8 +159,9 @@ bool socket_server_websocket_create(SocketConnection* con) {
|
|||
con->sd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
|
||||
|
||||
int32 flags;
|
||||
if ((flags = fcntl(con->sd, F_GETFL, 0)) < 0 ||
|
||||
fcntl(con->sd, F_SETFL, flags | O_NONBLOCK) < 0) {
|
||||
if ((flags = fcntl(con->sd, F_GETFL, 0)) < 0
|
||||
|| fcntl(con->sd, F_SETFL, flags | O_NONBLOCK) < 0
|
||||
) {
|
||||
close(con->sd);
|
||||
con->sd = 0;
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -348,7 +348,7 @@ void hashmap_insert(HashMap* hm, const char* key, const char* value) noexcept {
|
|||
*target = (uint16) (element + 1);
|
||||
}
|
||||
|
||||
HashEntry* hashmap_insert(HashMap* hm, const char* key, byte* value) noexcept {
|
||||
HashEntry* hashmap_insert(HashMap* hm, const char* key, const byte* value) noexcept {
|
||||
uint64 index = hash_djb2(key) % hm->buf.count;
|
||||
|
||||
int32 element = chunk_reserve(&hm->buf, 1);
|
||||
|
|
@ -656,7 +656,7 @@ void hashmap_insert(HashMap* hm, int32 key, const char* value) noexcept {
|
|||
*target = (uint16) (element + 1);
|
||||
}
|
||||
|
||||
void hashmap_insert(HashMap* hm, int32 key, byte* value) noexcept {
|
||||
void hashmap_insert(HashMap* hm, int32 key, const byte* value) noexcept {
|
||||
uint64 index = ((uint32) key) % hm->buf.count;
|
||||
|
||||
int32 element = chunk_reserve(&hm->buf, 1);
|
||||
|
|
|
|||
|
|
@ -270,7 +270,7 @@ void perfect_hashmap_insert(PerfectHashMap* hm, const char* key, const char* val
|
|||
}
|
||||
|
||||
inline
|
||||
void perfect_hashmap_insert(PerfectHashMap* hm, const char* key, byte* value) {
|
||||
void perfect_hashmap_insert(PerfectHashMap* hm, const char* key, const byte* value) {
|
||||
int32 index = hm->hash_function(key, hm->hash_seed) % hm->map_count;
|
||||
PerfectHashEntryStr* entry = (PerfectHashEntryStr *) (hm->hash_entries + hm->entry_size * index);
|
||||
|
||||
|
|
@ -376,7 +376,7 @@ bool perfect_hashmap_from_hashmap(PerfectHashMap* phm, const HashMap* hm, int32
|
|||
} chunk_iterate_end;
|
||||
|
||||
// Check if we can turn it into a perfect hash map
|
||||
PerfectHashMap* is_perfect = perfect_hashmap_prepare(phm, (const char**) keys, key_index, seed_tries, ring);
|
||||
const PerfectHashMap* is_perfect = perfect_hashmap_prepare(phm, (const char**) keys, key_index, seed_tries, ring);
|
||||
if (!is_perfect) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -384,7 +384,7 @@ bool perfect_hashmap_from_hashmap(PerfectHashMap* phm, const HashMap* hm, int32
|
|||
// Fill perfect hash map
|
||||
chunk_id = 0;
|
||||
chunk_iterate_start(&hm->buf, chunk_id) {
|
||||
HashEntry* entry = (HashEntry *) chunk_get_element((ChunkMemory *) &hm->buf, chunk_id);
|
||||
const HashEntry* entry = (const HashEntry *) chunk_get_element((ChunkMemory *) &hm->buf, chunk_id);
|
||||
perfect_hashmap_insert(phm, entry->key, entry->value);
|
||||
} chunk_iterate_end;
|
||||
|
||||
|
|
|
|||
|
|
@ -419,7 +419,7 @@ uint16 float_to_f16(float f) {
|
|||
return f16_bits;
|
||||
}
|
||||
|
||||
float f16_to_float(f16 f) {
|
||||
f32 f16_to_float(f16 f) {
|
||||
uint32_t sign = (f & HALF_FLOAT_SIGN_MASK) << 16;
|
||||
int32_t exponent = (f & HALF_FLOAT_EXP_MASK) >> HALF_FLOAT_EXP_SHIFT;
|
||||
uint32_t fraction = (f & HALF_FLOAT_FRAC_MASK) << (FLOAT32_EXP_SHIFT - HALF_FLOAT_EXP_SHIFT);
|
||||
|
|
@ -441,7 +441,7 @@ float f16_to_float(f16 f) {
|
|||
|
||||
uint32_t f_bits = sign | (exponent << FLOAT32_EXP_SHIFT) | fraction;
|
||||
|
||||
return *((float *) &f_bits);
|
||||
return BITCAST(f_bits, f32);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -39,21 +39,21 @@ void system_info_render(char* buf, const SystemInfo* info) {
|
|||
"\n"
|
||||
"CPU:\n"
|
||||
"==============\n"
|
||||
"Hardware\n" "Vendor: %s\n" "Brand: %s\n" "Model: %d\n" "Family: %d\n" "Mhz: %d\n" "Core Count: %d\n" "Page Size: %d\n"
|
||||
"Hardware\n" "Vendor: %s\n" "Brand: %s\n" "Model: %d\n" "Family: %d\n" "Mhz: %d\n" "Core Count: %d\n" "Page Size: %u\n"
|
||||
"\n"
|
||||
"Cache:\n"
|
||||
"L1: Size %d Line %d\n"
|
||||
"L2: Size %d Line %d\n"
|
||||
"L3: Size %d Line %d\n"
|
||||
"L4: Size %d Line %d\n"
|
||||
"L1: Size %u Line %u\n"
|
||||
"L2: Size %u Line %u\n"
|
||||
"L3: Size %u Line %u\n"
|
||||
"L4: Size %u Line %u\n"
|
||||
"\n"
|
||||
"Features: %ld\n"
|
||||
"Features: %lld\n"
|
||||
"\n"
|
||||
"GPU:\n"
|
||||
"==============\n"
|
||||
"Name: %s\n" "VRAM: %d\n"
|
||||
"Name: %s\n" "VRAM: %d\n"
|
||||
"Name: %s\n" "VRAM: %d\n"
|
||||
"Name: %s\n" "VRAM: %u\n"
|
||||
"Name: %s\n" "VRAM: %u\n"
|
||||
"Name: %s\n" "VRAM: %u\n"
|
||||
"\n"
|
||||
"Display:\n"
|
||||
"==============\n"
|
||||
|
|
@ -66,7 +66,7 @@ void system_info_render(char* buf, const SystemInfo* info) {
|
|||
"\n"
|
||||
"RAM:\n"
|
||||
"==============\n"
|
||||
"Memory: %d MB",
|
||||
"Memory: %u MB",
|
||||
info->os.vendor, info->os.name, info->os.major, info->os.minor,
|
||||
info->mainboard.name, info->mainboard.serial_number,
|
||||
info->network[0].slot, info->network[0].mac[0], info->network[0].mac[1], info->network[0].mac[2], info->network[0].mac[3], info->network[0].mac[4], info->network[0].mac[5], info->network[0].mac[6], info->network[0].mac[7],
|
||||
|
|
@ -74,11 +74,11 @@ void system_info_render(char* buf, const SystemInfo* info) {
|
|||
info->network_count < 3 ? "" : info->network[2].slot, info->network_count < 3 ? 0 : info->network[2].mac[0], info->network_count < 3 ? 0 : info->network[2].mac[1], info->network_count < 3 ? 0 : info->network[2].mac[2], info->network_count < 3 ? 0 : info->network[2].mac[3], info->network_count < 3 ? 0 : info->network[2].mac[4], info->network_count < 3 ? 0 : info->network[2].mac[5], info->network_count < 3 ? 0 : info->network[2].mac[6], info->network_count < 3 ? 0 : info->network[2].mac[7],
|
||||
info->network_count < 4 ? "" : info->network[3].slot, info->network_count < 4 ? 0 : info->network[3].mac[0], info->network_count < 4 ? 0 : info->network[3].mac[1], info->network_count < 4 ? 0 : info->network[3].mac[2], info->network_count < 4 ? 0 : info->network[3].mac[3], info->network_count < 4 ? 0 : info->network[3].mac[4], info->network_count < 4 ? 0 : info->network[3].mac[5], info->network_count < 4 ? 0 : info->network[3].mac[6], info->network_count < 4 ? 0 : info->network[3].mac[7],
|
||||
info->cpu.vendor, info->cpu.brand, info->cpu.model, info->cpu.family, info->cpu.mhz, info->cpu.core_count, info->cpu.page_size,
|
||||
info->cpu.cache[0].size, info->cpu.cache[0].line_size,
|
||||
info->cpu.cache[1].size, info->cpu.cache[1].line_size,
|
||||
info->cpu.cache[2].size, info->cpu.cache[2].line_size,
|
||||
info->cpu.cache[3].size, info->cpu.cache[3].line_size,
|
||||
info->cpu.features,
|
||||
info->cpu.cache[0].size, (uint32) info->cpu.cache[0].line_size,
|
||||
info->cpu.cache[1].size, (uint32) info->cpu.cache[1].line_size,
|
||||
info->cpu.cache[2].size, (uint32) info->cpu.cache[2].line_size,
|
||||
info->cpu.cache[3].size, (uint32) info->cpu.cache[3].line_size,
|
||||
(long long) info->cpu.features,
|
||||
info->gpu[0].name, info->gpu[0].vram,
|
||||
info->gpu_count < 2 ? "" : info->gpu[1].name, info->gpu_count < 2 ? 0 : info->gpu[1].vram,
|
||||
info->gpu_count < 3 ? "" : info->gpu[2].name, info->gpu_count < 3 ? 0 : info->gpu[2].vram,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
#define HAS_ZERO(x) (((x) - ((size_t)-1 / 0xFF)) & ~(x) & (((size_t)-1 / 0xFF) * (0xFF / 2 + 1)))
|
||||
#define HAS_CHAR(x, c) (HAS_ZERO((x) ^ (((size_t)-1 / 0xFF) * (c))))
|
||||
|
||||
inline constexpr
|
||||
inline
|
||||
size_t str_length(const char* str) noexcept {
|
||||
const char* ptr = str;
|
||||
|
||||
|
|
@ -300,11 +300,10 @@ int32 utf8_decode(const uint32 codepoint, char* __restrict out) noexcept {
|
|||
inline
|
||||
int32 utf8_str_length(const char* in) noexcept {
|
||||
int32 length = 0;
|
||||
int32 bytes;
|
||||
uint32 codepoint;
|
||||
|
||||
while (*in) {
|
||||
bytes = utf8_decode(in, &codepoint);
|
||||
int32 bytes = utf8_decode(in, &codepoint);
|
||||
if (bytes < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -332,11 +331,10 @@ void string_to_utf8(const uint32* in, char* out) noexcept {
|
|||
inline
|
||||
int32 utf8_get_char_at(const char* in, int32 index) noexcept {
|
||||
int32 i = 0;
|
||||
int32 bytes_consumed;
|
||||
uint32 codepoint;
|
||||
|
||||
while (*in) {
|
||||
bytes_consumed = utf8_decode(in, &codepoint);
|
||||
int32 bytes_consumed = utf8_decode(in, &codepoint);
|
||||
if (bytes_consumed < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -358,7 +356,7 @@ void wchar_to_char(wchar_t* str) noexcept
|
|||
char* src = (char*) str;
|
||||
char* dest = src;
|
||||
|
||||
while (*src != '\0' && src[1] != '\0') {
|
||||
while (*src != '\0' || src[1] != '\0') {
|
||||
if (*src != '\0') {
|
||||
*dest++ = *src;
|
||||
}
|
||||
|
|
@ -372,7 +370,7 @@ void wchar_to_char(wchar_t* str) noexcept
|
|||
inline
|
||||
void wchar_to_char(const char* __restrict str, char* __restrict dest) noexcept
|
||||
{
|
||||
while (*str != '\0' && str[1] != '\0') {
|
||||
while (*str != '\0' || str[1] != '\0') {
|
||||
if (*str != '\0') {
|
||||
*dest++ = (char) *str;
|
||||
}
|
||||
|
|
@ -1535,7 +1533,7 @@ void str_pad_right(const char* input, char* output, char pad, size_t len) noexce
|
|||
}
|
||||
}
|
||||
|
||||
inline constexpr
|
||||
inline
|
||||
void str_pad_left(const char* input, char* output, char pad, size_t len) noexcept {
|
||||
size_t input_len = str_length(input);
|
||||
|
||||
|
|
@ -1696,11 +1694,11 @@ void sprintf_fast(char* __restrict buffer, const char* __restrict format, ...) n
|
|||
va_start(args, format);
|
||||
|
||||
while (*format) {
|
||||
if (*format != '%') {
|
||||
*buffer++ = *format;
|
||||
} else if (*format == '\\' && *(format + 1) == '%') {
|
||||
if (*format == '\\' && format[1] == '%') {
|
||||
++format;
|
||||
*buffer++ = *format;
|
||||
} else if (*format != '%') {
|
||||
*buffer++ = *format;
|
||||
} else {
|
||||
++format;
|
||||
|
||||
|
|
@ -1771,15 +1769,14 @@ void sprintf_fast(char* __restrict buffer, int32 buffer_length, const char* __re
|
|||
|
||||
// We start at 1 since we need 1 char for '\0'
|
||||
int32 length = 1;
|
||||
int32 offset;
|
||||
|
||||
while (*format && length < buffer_length) {
|
||||
offset = 1;
|
||||
if (*format != '%') {
|
||||
*buffer++ = *format;
|
||||
} else if (*format == '\\' && *(format + 1) == '%') {
|
||||
int32 offset = 1;
|
||||
if (*format == '\\' && format[1] == '%') {
|
||||
++format;
|
||||
*buffer++ = *format;
|
||||
} else if (*format != '%') {
|
||||
*buffer++ = *format;
|
||||
} else {
|
||||
++format;
|
||||
|
||||
|
|
@ -1855,11 +1852,11 @@ void sprintf_fast_iter(char* buffer, const char* format, ...) noexcept {
|
|||
int32 count_index = 0;
|
||||
|
||||
while (*format) {
|
||||
if (*format != '%' || count_index >= 1) {
|
||||
*buffer++ = *format;
|
||||
} else if (*format == '\\' && *(format + 1) == '%') {
|
||||
if (*format == '\\' && format[1] == '%') {
|
||||
++format;
|
||||
*buffer++ = *format;
|
||||
} else if (*format != '%' || count_index >= 1) {
|
||||
*buffer++ = *format;
|
||||
} else {
|
||||
++count_index;
|
||||
++format;
|
||||
|
|
|
|||
|
|
@ -10,8 +10,14 @@
|
|||
#define COMS_UTILS_TEST_UTILS_H
|
||||
|
||||
#if DEBUG
|
||||
#define ASSERT_SIMPLE(a) if (!(a)) { *(volatile int *)0 = 0; }
|
||||
#define ASSERT_SIMPLE_CONST(a) if constexpr (!(a)) { *(volatile int *)0 = 0; }
|
||||
#define ASSERT_SIMPLE(a) if (!(a)) { \
|
||||
/* cppcheck-suppress nullPointer */ \
|
||||
*(volatile int *)0 = 0; \
|
||||
}
|
||||
#define ASSERT_SIMPLE_CONST(a) if constexpr (!(a)) { \
|
||||
/* cppcheck-suppress nullPointer */ \
|
||||
*(volatile int *)0 = 0; \
|
||||
}
|
||||
#else
|
||||
#define ASSERT_SIMPLE(a) ((void)0)
|
||||
#define ASSERT_SIMPLE_CONST(a) ((void)0)
|
||||
|
|
|
|||
|
|
@ -14,11 +14,15 @@
|
|||
#include "../utils/StringUtils.h"
|
||||
#include "../compiler/CompilerUtils.h"
|
||||
|
||||
#ifdef __linux__
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if ARM
|
||||
#if ARM_NEON
|
||||
#include "../architecture/arm/utils/neon/Utils.h"
|
||||
#include "../architecture/arm/neon/utils/Utils.h"
|
||||
#else
|
||||
#include "../architecture/arm/utils/sve/Utils.h"
|
||||
#include "../architecture/arm/sve/utils/Utils.h"
|
||||
#endif
|
||||
#else
|
||||
#include "../architecture/x86/simd/utils/Utils.h"
|
||||
|
|
@ -37,15 +41,17 @@ bool is_equal(const byte* __restrict region1, const byte* __restrict region2, ui
|
|||
|
||||
inline
|
||||
void str_output(const char* __restrict str, ...) {
|
||||
char buffer[1024];
|
||||
if (str_find(str, '%')) {
|
||||
va_list args;
|
||||
char buffer[1024];
|
||||
va_start(args, str);
|
||||
sprintf_fast(buffer, 1024, str, args);
|
||||
va_end(args);
|
||||
|
||||
str = buffer;
|
||||
}
|
||||
|
||||
#if _WIN32
|
||||
#ifdef _WIN32
|
||||
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
WriteFile(hStdout, str, str_length(str), NULL, NULL);
|
||||
else
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user