You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
296 lines
7.3 KiB
C
296 lines
7.3 KiB
C
#ifndef SHARED_H
|
|
#define SHARED_H
|
|
|
|
#define ZeroStruct(Struct) ZeroSize(&Struct, sizeof(Struct))
|
|
inline void ZeroSize(void* Ptr, size_t Size) {
|
|
u8* Byte = (u8*)Ptr;
|
|
// todo(jax): @Speed: Check performance of the two code blocks
|
|
#if 0
|
|
for (size_t i = 0; i < Size; ++i) {
|
|
*Byte++ = 0;
|
|
}
|
|
#else
|
|
while (Size--) {
|
|
*Byte++ = 0;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#define CopyArray(Dest, Source, Count) MemoryCopy((Dest), (Source), (Count)*sizeof(*(Source)))
|
|
inline void* MemoryCopy(void* _Dest, void* _Source, size_t Size) {
|
|
#if 0
|
|
return memcpy(_Dest, _Source, Size);
|
|
#else //NO CRT VERSION HERE!
|
|
if (_Source == 0) {
|
|
ZeroSize(_Dest, Size);
|
|
return _Dest;
|
|
}
|
|
|
|
u8* Source = (u8*)_Source;
|
|
u8* Dest = (u8*)_Dest;
|
|
|
|
while (Size--) {
|
|
*Dest++ = *Source++;
|
|
}
|
|
|
|
return _Dest;
|
|
#endif
|
|
}
|
|
|
|
inline u8* Advance(string* String, umm Count) {
|
|
u8 *Result = 0;
|
|
|
|
if(String->Count >= Count) {
|
|
Result = String->Data;
|
|
String->Data += Count;
|
|
String->Count -= Count;
|
|
} else {
|
|
String->Data += String->Count;
|
|
String->Count = 0;
|
|
}
|
|
|
|
return(Result);
|
|
}
|
|
|
|
inline b32 IsSpacing(char C) {
|
|
b32 Result = ((C == ' ') || (C == '\t') || (C == '\v') ||(C == '\f'));
|
|
return(Result);
|
|
}
|
|
|
|
inline b32 IsEndOfLine(char Value) {
|
|
b32 Result = ((Value == '\n') || (Value == '\r'));
|
|
return Result;
|
|
}
|
|
|
|
inline b32 IsWhitespace(char Value, bool IncludeEOL = false) {
|
|
b32 Result = ((Value == ' ') || (Value == '\t') || (Value == '\v') || (Value == '\f') || ( IncludeEOL ? IsEndOfLine(Value) : 1));
|
|
return Result;
|
|
}
|
|
|
|
inline b32 IsAlphabetical(char Value) {
|
|
b32 Result = (((Value >= 'a') && (Value <= 'z')) || ((Value >= 'A') && (Value <= 'Z')));
|
|
return Result;
|
|
}
|
|
|
|
inline b32 IsNumeric(char Value) {
|
|
b32 Result = ((Value >= '0') && (Value <= '9'));
|
|
return Result;
|
|
}
|
|
|
|
inline char* GetNextLine(char** Contents) {
|
|
char* Text = *Contents;
|
|
if (!*Text) {
|
|
return nullptr;
|
|
}
|
|
|
|
char* Line = Text;
|
|
while (*Text && (*Text != '\n') && (*Text != '\r')) {
|
|
++Text;
|
|
}
|
|
|
|
char* End = Text;
|
|
++End;
|
|
if (*Text == '\r') {
|
|
if (*End == '\n') {
|
|
++End;
|
|
}
|
|
|
|
*Text = '\0';
|
|
}
|
|
|
|
*Contents = End;
|
|
|
|
return Line;
|
|
}
|
|
|
|
inline int StringLength(char* String) {
|
|
int Count = 0;
|
|
while (*String++) {
|
|
++Count;
|
|
}
|
|
return Count;
|
|
}
|
|
|
|
inline string make_string(char* String) {
|
|
string Result = {};
|
|
Result.Data = (u8*)String;
|
|
Result.Count = StringLength(String);
|
|
|
|
return Result;
|
|
}
|
|
|
|
inline char* Substring(char* Source, char* String) {
|
|
while (*Source) {
|
|
char *Begin = Source;
|
|
char *Pattern = String;
|
|
|
|
// If first character of sub string match, check for whole string
|
|
while (*Source && *Pattern && *Source == *Pattern) {
|
|
Source++;
|
|
Pattern++;
|
|
}
|
|
|
|
// If complete sub string match, return starting address
|
|
if (!*Pattern)
|
|
return Begin;
|
|
|
|
Source = Begin + 1;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
// note: _Char is expected to be an ASCII character
|
|
inline char* FindFirstChar(char* String, int _Char) {
|
|
char Char = (char)_Char;
|
|
while (*String != Char) {
|
|
if (!*String++) {
|
|
return NULL;
|
|
}
|
|
}
|
|
return (char*)String;
|
|
}
|
|
|
|
// todo(jax): Consider using while loops for Append and StringCopy?? Query performance benefit.
|
|
|
|
inline char* Append(char* Dest, size_t DestSize, char* Source) {
|
|
// todo(jax): Do we need to terminate annd or allocate needed memory?
|
|
Dest = (char*)malloc(DestSize + (1 + StringLength(Source) * sizeof(char)));
|
|
MemoryCopy(Dest + StringLength(Dest), Source, DestSize + 1);
|
|
return Dest;
|
|
}
|
|
|
|
inline char* StringCopy(char* String) {
|
|
char* Result = (char*)malloc(sizeof(char) * (StringLength(String) + 1));
|
|
MemoryCopy(Result, String, sizeof(char) * (StringLength(String) + 1));
|
|
|
|
return Result;
|
|
}
|
|
|
|
inline bool StringsMatch(char* A, char* B) {
|
|
while (*A && *B) {
|
|
if (*A != *B){
|
|
return false;
|
|
}
|
|
|
|
++A;
|
|
++B;
|
|
}
|
|
|
|
if (*A != *B){
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
inline void CatStrings(size_t SourceACount, char* SourceA, size_t SourceBCount, char* SourceB, size_t DestCount, char* Dest) {
|
|
// todo(jax): Bounds check the Destination. This code is risky!
|
|
for (int Index = 0; Index < SourceACount; ++Index) {
|
|
*Dest++ = *SourceA++;
|
|
}
|
|
|
|
for (int Index = 0; Index < SourceBCount; ++Index) {
|
|
*Dest++ = *SourceB++;
|
|
}
|
|
|
|
*Dest++ = 0;
|
|
}
|
|
|
|
//
|
|
// NOT REALLY SURE IF WE WANT TO USE THE FOLLOWING CODE!
|
|
//
|
|
|
|
#if 1
|
|
void __cdecl __va_start(va_list*, ...);
|
|
#define _crt_va_start(ap, x) ((void)(__va_start(&ap, x)))
|
|
#define _crt_va_arg(ap, t) \
|
|
((sizeof(t) > sizeof(__int64) || (sizeof(t) & (sizeof(t) - 1)) != 0) \
|
|
? **(t**)((ap += sizeof(__int64)) - sizeof(__int64)) \
|
|
: *(t* )((ap += sizeof(__int64)) - sizeof(__int64)))
|
|
#define _crt_va_end(ap) ((void)(ap = (va_list)0))
|
|
#else
|
|
#define _crt_va_start(ap, v) va_start(ap, v)
|
|
#define _crt_va_arg(ap, t) va_arg(ap, t)
|
|
#define _crt_va_end(ap) va_end(ap)
|
|
#endif
|
|
|
|
inline int32 StringToI32_(char** AtInit) {
|
|
int32 Result = {};
|
|
|
|
char* At = *AtInit;
|
|
while ((*At >= '0') && (*At <= '9')) {
|
|
Result *= 10;
|
|
Result += (*At - '0');
|
|
++At;
|
|
}
|
|
|
|
*AtInit = At;
|
|
|
|
return Result;
|
|
}
|
|
|
|
inline int32 StringToI32(char* At) {
|
|
char* Ignored = At;
|
|
int32 Result = StringToI32_(&Ignored);
|
|
return Result;
|
|
}
|
|
|
|
struct format_dest;
|
|
|
|
void OutChar(format_dest* Dest, char Value);
|
|
void OutChars(format_dest* Dest, char* Value);
|
|
|
|
void U64ToASCII(format_dest* Dest, u64 Value, u32 Base, char* Digits);
|
|
void F64ToASCII(format_dest* Dest, f64 Value, u32 Precision);
|
|
|
|
// note(jax): This function serves as a replacement to `stdio.h` sprintf()
|
|
API_EXPORT umm FormatArgList(umm DestSize, char* DestInit, char* Format, va_list ArgList);
|
|
inline umm Format(umm DestSize, char* Dest, char* Format, ...) {
|
|
va_list ArgList;
|
|
_crt_va_start(ArgList, Format);
|
|
umm Result = FormatArgList(DestSize, Dest, Format, ArgList);
|
|
_crt_va_end(ArgList);
|
|
|
|
return Result;
|
|
}
|
|
|
|
inline int _crt_sprintf(char* Buffer, size_t Count, char* Format, ...) {
|
|
int Result;
|
|
|
|
va_list ArgList;
|
|
__crt_va_start(ArgList, Format);
|
|
Result = _vsprintf_s_l(Buffer, Count, Format, NULL, ArgList);
|
|
__crt_va_end(ArgList);
|
|
|
|
return Result;
|
|
}
|
|
|
|
inline umm ae_sprintf(char* Dest, char* Format, ...) {
|
|
va_list ArgList;
|
|
_crt_va_start(ArgList, Format);
|
|
umm Result = FormatArgList(sizeof(Dest), Dest, Format, ArgList);
|
|
_crt_va_end(ArgList);
|
|
|
|
return Result;
|
|
}
|
|
|
|
inline umm ae_sprintf(char* Dest, char* Format, va_list ArgList) {
|
|
umm Result = FormatArgList(sizeof(Dest), Dest, Format, ArgList);
|
|
|
|
return Result;
|
|
}
|
|
|
|
inline umm ae_printf(char* Format, ...) {
|
|
char Buffer[1024];
|
|
|
|
va_list ArgList;
|
|
_crt_va_start(ArgList, Format);
|
|
umm Result = FormatArgList(1024, Buffer, Format, ArgList);
|
|
_crt_va_end(ArgList);
|
|
|
|
fwrite(Buffer, sizeof(char), StringLength(Buffer), stdout);
|
|
fflush(stdout);
|
|
return Result;
|
|
}
|
|
|
|
#endif |