vn/code/vn_string.h

374 lines
7.7 KiB
C
Raw Normal View History

2023-06-17 17:00:55 +00:00
/* date = May 7th 2023 9:01 pm */
#ifndef VN_STRING_H
#define VN_STRING_H
inline b32 IsWhitespace(char C)
{
2023-06-19 17:12:26 +00:00
b32 Result = ((C == ' ') ||
(C == '\n') ||
(C == '\t') ||
(C == '\r'));
return(Result);
2023-06-17 17:00:55 +00:00
}
2023-06-19 17:12:26 +00:00
inline b32 IsDigit(char C)
2023-06-17 17:00:55 +00:00
{
2023-06-19 17:12:26 +00:00
b32 Result = ((C >= '0') && (C <= '9'));
return(Result);
2023-06-17 17:00:55 +00:00
}
2023-06-19 17:12:26 +00:00
inline b32 IsLetter(char C)
2023-06-17 17:00:55 +00:00
{
2023-06-19 17:12:26 +00:00
b32 Result = ((C >= 'A') && (C <= 'Z')) || ((C >= 'a') && (C <= 'z'));
return(Result);
}
inline s64 StringLength(char *String)
{
s64 Result = 0;
while(*String++)
{
++Result;
}
return(Result);
2023-06-17 17:00:55 +00:00
}
inline string MakeStringFromCString(char *Data)
{
2023-06-19 17:12:26 +00:00
string Result = {StringLength(Data), (u8 *)Data};
return(Result);
2023-06-17 17:00:55 +00:00
}
2023-06-19 17:12:26 +00:00
inline u64 HashString(string String)
2023-06-17 17:00:55 +00:00
{
2023-06-19 17:12:26 +00:00
u64 Result = 5731;
2023-06-17 17:00:55 +00:00
for(s64 Index = 0;
2023-06-19 17:12:26 +00:00
Index < String.Count;
2023-06-17 17:00:55 +00:00
++Index)
{
2023-06-19 17:12:26 +00:00
Result += String.Data[Index];
Result ^= Result << 13;
Result ^= Result >> 7;
Result ^= Result << 17;
2023-06-17 17:00:55 +00:00
}
2023-06-19 17:12:26 +00:00
return(Result);
}
inline b32 AreEqual(string A, string B)
{
b32 Result = false;
if(A.Count == B.Count)
{
Result = true;
for(s64 Index = 0;
Index < A.Count;
++Index)
{
if(A.Data[Index] != B.Data[Index])
{
Result = false;
break;
}
}
}
return(Result);
2023-06-18 12:18:34 +00:00
}
inline s64 FirstIndexOf(string String, char Char)
{
2023-06-19 17:12:26 +00:00
s64 Result = -1;
for(s64 Index = 0;
Index < String.Count;
++Index)
2023-06-18 12:18:34 +00:00
{
2023-06-19 17:12:26 +00:00
if(String.Data[Index] == Char)
{
Result = Index;
break;
}
2023-06-18 12:18:34 +00:00
}
2023-06-19 17:12:26 +00:00
return(Result);
2023-06-17 17:00:55 +00:00
}
inline s64 LastIndexOf(string String, char Char)
{
2023-06-19 17:12:26 +00:00
s64 Result = -1;
for(s64 Index = String.Count-1;
Index >= 0;
--Index)
2023-06-18 12:18:34 +00:00
{
2023-06-19 17:12:26 +00:00
if(String.Data[Index] == Char)
{
Result = Index;
break;
}
2023-06-18 12:18:34 +00:00
}
2023-06-19 17:12:26 +00:00
return(Result);
2023-06-17 17:00:55 +00:00
}
2023-06-18 12:18:34 +00:00
inline s64 LastIndexOf(string String, string Substring)
2023-06-17 17:00:55 +00:00
{
2023-06-19 17:12:26 +00:00
s64 Result = -1;
if(String.Count >= Substring.Count)
{
for(s64 Index = String.Count-Substring.Count;
Index >= 0;
--Index)
{
string ToCheck = MakeString((char *)String.Data + Index, Substring.Count);
if(AreEqual(ToCheck, Substring))
{
Result = Index;
break;
}
}
}
return(Result);
}
static s64 ConvertStringToS64(string String)
{
s64 Result = 0;
b32 IsNegative = false;
s64 Index = 0;
if(String.Data[Index] == '-')
{
IsNegative = true;
++Index;
}
for(;Index < String.Count; ++Index)
{
u8 Char = String.Data[Index];
Assert(IsDigit(Char));
Result = Result*10 + (Char-'0');
}
if(IsNegative)
{
Result = -Result;
}
return(Result);
}
static string ConvertS64ToString(s64 Value, memory_arena *Arena)
{
b32 IsNegative = (Value < 0);
if(IsNegative)
{
Value = -Value;
}
s64 DigitCount = (s64)Floor(Log(Max(Value, 1)) / Log(10)) + 1;
s64 TotalBufferCount = DigitCount + IsNegative;
string String = {TotalBufferCount, PushArray(Arena, u8, TotalBufferCount + 1)};
String.Data[TotalBufferCount] = 0;
if(IsNegative)
{
String.Data[0] = '-';
}
for(s64 Index = 0;
Index < DigitCount;
++Index)
2023-06-17 17:00:55 +00:00
{
2023-06-19 17:12:26 +00:00
String.Data[TotalBufferCount - 1 - Index] = '0' + (Value % 10);
Value /= 10;
2023-06-17 17:00:55 +00:00
}
2023-06-19 17:12:26 +00:00
return(String);
}
static string Substring(string String, range_s64 Range)
{
string Result = MakeString((char *)String.Data + Range.Min, DimOfRange(Range));
return(Result);
}
static string Prefix(string String, s64 Count)
{
range_s64 Range = RangeS64(0, Count);
string Result = Substring(String, Range);
return(Result);
}
static string Suffix(string String, s64 Count)
{
range_s64 Range = RangeS64(String.Count - Count, String.Count);
string Result = Substring(String, Range);
return(Result);
2023-06-17 17:00:55 +00:00
}
static s64 UTF8FromCodepoint(u8 *Out, u32 Codepoint)
{
2023-06-19 17:12:26 +00:00
s64 Length = 0;
if(Codepoint <= 0x7F)
{
Out[0] = (u8)Codepoint;
Length = 1;
}
else if(Codepoint <= 0x7FF)
{
Out[0] = (0x3 << 6) | ((Codepoint >> 6) & 0x1F);
Out[1] = 0x80 | ( Codepoint & 0x3F);
Length = 2;
}
else if(Codepoint <= 0xFFFF)
{
Out[0] = (0x7 << 5) | ((Codepoint >> 12) & 0x0F);
Out[1] = 0x80 | ((Codepoint >> 6) & 0x3F);
Out[2] = 0x80 | ( Codepoint & 0x3F);
Length = 3;
}
else if(Codepoint <= 0x10FFFF)
{
Out[0] = (0xF << 4) | ((Codepoint >> 12) & 0x07);
Out[1] = 0x80 | ((Codepoint >> 12) & 0x3F);
Out[2] = 0x80 | ((Codepoint >> 6) & 0x3F);
Out[3] = 0x80 | ( Codepoint & 0x3F);
Length = 4;
}
else
{
Out[0] = '?';
Length = 1;
}
return(Length);
2023-06-17 17:00:55 +00:00
}
inline s64 GetCodepointSize(u32 Codepoint)
{
2023-06-19 17:12:26 +00:00
s64 Result = 0;
if(Codepoint <= 0x7F)
{
Result = 1;
}
else if(Codepoint <= 0x7FF)
{
Result = 2;
}
else if(Codepoint <= 0xFFFF)
{
Result = 3;
}
else if(Codepoint <= 0x10FFFF)
{
Result = 4;
}
else
{
Result = 1;
}
return(Result);
2023-06-17 17:00:55 +00:00
}
// sixten(TODO): Remove this forward decl.
inline string PushCString(struct memory_arena *Arena, char *CString);
inline string StringFromCodepoint(struct memory_arena *Arena, u32 Codepoint)
{
2023-06-19 17:12:26 +00:00
char Buffer[5] = {};
UTF8FromCodepoint((u8 *)Buffer, Codepoint);
string Result = PushCString(Arena, Buffer);
return(Result);
2023-06-17 17:00:55 +00:00
}
struct utf8_iterator
{
2023-06-19 17:12:26 +00:00
string Data;
s64 Index;
u32 Codepoint;
2023-06-17 17:00:55 +00:00
};
inline void Advance(utf8_iterator *Iter)
{
2023-06-19 17:12:26 +00:00
u8 *At = Iter->Data.Data + Iter->Index;
if(Iter->Index < Iter->Data.Count)
2023-06-17 17:00:55 +00:00
{
2023-06-19 17:12:26 +00:00
if((At[0] & 0x80) == 0x00)
{
Iter->Codepoint = (At[0] & 0x7F);
Iter->Index += 1;
}
else if((At[0] & 0xE0) == 0xC0)
{
Iter->Codepoint = ((At[0] & 0x1F) << 6)|(At[1] & 0x3F);
Iter->Index += 2;
}
else if((At[0] & 0xF0) == 0xE0)
{
Iter->Codepoint = ((At[0] & 0x0F) << 12)|((At[1] & 0x3F) << 6)|(At[2] & 0x3F);
Iter->Index += 3;
}
else if((Iter->Data.Data[Iter->Index] & 0xF8) == 0xF0)
{
Iter->Codepoint = ((At[0] & 0x0F) << 18)|((At[1] & 0x3F) << 12)|((At[2] & 0x3F) << 6)|(At[3] & 0x3F);
Iter->Index += 4;
}
2023-06-17 17:00:55 +00:00
}
2023-06-19 17:12:26 +00:00
else
2023-06-18 12:18:34 +00:00
{
2023-06-19 17:12:26 +00:00
Iter->Codepoint = 0;
2023-06-18 12:18:34 +00:00
}
2023-06-17 17:00:55 +00:00
}
inline utf8_iterator IterateUTF8String(string String)
{
2023-06-19 17:12:26 +00:00
utf8_iterator Iter = {};
Iter.Data = String;
Advance(&Iter);
return(Iter);
}
static void AppendString(string_list *List, string String, memory_arena *Arena)
{
string_node *Node = PushStruct(Arena, string_node);
Node->String = String;
List->TotalCount += String.Count;
DLLInsertLast(List->First, List->Last, Node);
}
static string JoinStringList(string_list *List, memory_arena *Arena)
{
u8 *Buffer = PushArray(Arena, u8, List->TotalCount + 1);
Buffer[List->TotalCount] = 0;
s64 GlobalIndex = 0;
for(string_node *Node = List->First;
Node != 0;
Node = Node->Next)
{
string String = Node->String;
for(s64 Index = 0;
Index < String.Count;
++Index)
{
Buffer[GlobalIndex++] = String.Data[Index];
}
}
string Result = MakeString((char *)Buffer, List->TotalCount);
return(Result);
2023-06-17 17:00:55 +00:00
}
#endif //VN_STRING_H