//////////////////////////////////////////////////////////// //~ Formatting types #define DefaultFmtPrecision 6 #define Base16Chars ("0123456789abcdef") Enum(FmtArgKind) { FmtArgKind_None, // Arbitrary magic numbers for argument validation FmtArgKind_Char = 0xf5281df, FmtArgKind_String = 0xa5ffa9a, FmtArgKind_Uint = 0x746f19b, FmtArgKind_Uint2 = 0x83429d9, FmtArgKind_Uint3 = 0x1b4b749, FmtArgKind_Uint4 = 0xf8eb3cf, FmtArgKind_Sint = 0x8603694, FmtArgKind_Sint2 = 0x335a803, FmtArgKind_Sint3 = 0xe5e4ab1, FmtArgKind_Sint4 = 0xe1fd7ad, FmtArgKind_Float = 0x4814143, FmtArgKind_Float2 = 0x4260065, FmtArgKind_Float3 = 0x0d28ab7, FmtArgKind_Float4 = 0x76fe314, FmtArgKind_Hex = 0xa3d0792, FmtArgKind_Ptr = 0xc4519e4, FmtArgKind_Uid = 0xd1cd407, FmtArgKind_Handle = 0xead3bec, FmtArgKind_End = 0xecbc5ae }; Struct(FmtArg) { FmtArgKind kind; u32 p; // Precision u32 z; // Z-fill union { u8 c; String string; Vec4U64 uints; Vec4I64 sints; Vec4F64 floats; void *ptr; Uid uid; u64 handle; } value; }; Struct(FmtArgArray) { u64 count; FmtArg *args; }; //////////////////////////////////////////////////////////// //~ Unicode types Struct(CodepointIter) { u32 codepoint; // Internal String src; u64 pos; }; //////////////////////////////////////////////////////////// //~ Conversion helpers String StringFromBool(Arena *arena, b32 b); String StringFromChar(Arena *arena, char c); String StringFromUint(Arena *arena, u64 n, u64 base, u64 zfill); String StringFromUints(Arena *arena, u64 uints_count, u64 *uints, u64 base, u64 zfill); String StringFromSint(Arena *arena, i64 n, u64 base, u64 zfill); String StringFromFloat(Arena *arena, f64 src, u32 precision); String StringFromPtr(Arena *arena, void *ptr); String StringFromhandle(Arena *arena, u64 v); String StringFromUid(Arena *arena, Uid uid); //////////////////////////////////////////////////////////// //~ String helpers String PushString(Arena *arena, String src); String CopyString(String dst, String src); String RepeatString(Arena *arena, String src, u64 count); String CatString(Arena *arena, String str1, String str2); StringArray SplitString(Arena *arena, String str, String delim); String ReplaceString(Arena *arena, String str, String old_pattern, String new_pattern); String IndentString(Arena *arena, String str, u32 indent); String LowerString(Arena *arena, String str); b32 MatchString(String str1, String str2); b32 StringContains(String str, String substring); b32 StringBeginsWith(String str, String substring); b32 StringEndsWith(String str, String substring); String StringFromArray(Arena *arena, StringArray a); String PathFromString(Arena *arena, String str, u8 path_delimiter); //////////////////////////////////////////////////////////// //~ Trimming helpers String TrimLeft(String s, String pattern); String TrimRight(String s, String pattern); String Trim(String s, String pattern); String TrimWhitespace(String s); //////////////////////////////////////////////////////////// //~ String list helpers StringListNode *PushStringToList(Arena *arena, StringList *l, String s); String StringFromList(Arena *arena, StringList l, String separator); //////////////////////////////////////////////////////////// //~ Formatting #define FMTARG(_kind, ...) ((FmtArg) { .kind = (_kind), .p = DefaultFmtPrecision, __VA_ARGS__ }) #define FmtChar(v, ...) FMTARG(FmtArgKind_Char, .value.c = (v), __VA_ARGS__) #define FmtString(v, ...) FMTARG(FmtArgKind_String, .value.string = (v), __VA_ARGS__) #define FmtUint(v, ...) FMTARG(FmtArgKind_Uint, .value.uints = VEC4U64((v), 0, 0, 0), __VA_ARGS__) #define FmtUint2(v, ...) FMTARG(FmtArgKind_Uint2, .value.uints = VEC4U64((v).x, (v).y, 0, 0), __VA_ARGS__) #define FmtUint3(v, ...) FMTARG(FmtArgKind_Uint3, .value.uints = VEC4U64((v).x, (v).y, (v).z, 0), __VA_ARGS__) #define FmtUint4(v, ...) FMTARG(FmtArgKind_Uint4, .value.uints = VEC4U64((v).x, (v).y, (v).z, (v).w), __VA_ARGS__) #define FmtSint(v, ...) FMTARG(FmtArgKind_Sint, .value.sints = VEC4I64((v), 0, 0, 0), __VA_ARGS__) #define FmtSint2(v, ...) FMTARG(FmtArgKind_Sint2, .value.sints = VEC4I64((v).x, (v).y, 0, 0), __VA_ARGS__) #define FmtSint3(v, ...) FMTARG(FmtArgKind_Sint3, .value.sints = VEC4I64((v).x, (v).y, (v).z, 0), __VA_ARGS__) #define FmtSint4(v, ...) FMTARG(FmtArgKind_Sint4, .value.sints = VEC4I64((v).x, (v).y, (v).z, (v).w), __VA_ARGS__) #define FmtFloat(v, ...) FMTARG(FmtArgKind_Float, .value.floats = VEC4F64((v), 0, 0, 0), __VA_ARGS__) #define FmtFloat2(v, ...) FMTARG(FmtArgKind_Float2, .value.floats = VEC4F64((v).x, (v).y, 0, 0), __VA_ARGS__) #define FmtFloat3(v, ...) FMTARG(FmtArgKind_Float3, .value.floats = VEC4F64((v).x, (v).y, (v).z, 0), __VA_ARGS__) #define FmtFloat4(v, ...) FMTARG(FmtArgKind_Float4, .value.floats = VEC4F64((v).x, (v).y, (v).z, (v).w), __VA_ARGS__) #define FmtHex(v, ...) FMTARG(FmtArgKind_Hex, .value.uints.x = (v), __VA_ARGS__) #define FmtPtr(v, ...) FMTARG(FmtArgKind_Ptr, .value.ptr = (v), __VA_ARGS__) #define FmtHandle(v, ...) FMTARG(FmtArgKind_Handle, .value.handle = (v), __VA_ARGS__) #define FmtUid(v, ...) FMTARG(FmtArgKind_Uid, .value.uid = (v), __VA_ARGS__) #define FmtEnd FMTARG(FmtArgKind_End) // Denotes end of VA list String FormatString(Arena *arena, String fmt, FmtArgArray args); String StringF_(Arena *arena, String fmt, ...); #define StringF(arena, lit, ...) StringF_((arena), Lit(lit), __VA_ARGS__, FmtEnd) FmtArgArray FmtArgsFromVaList(Arena *arena, va_list vl); //////////////////////////////////////////////////////////// //~ Unicode //- Iter CodepointIter InitCodepointIter(String str); b32 NextCodepoint(CodepointIter *iter); //- Decode string String StringFromString16(Arena *arena, String16 str16); String StringFromString32(Arena *arena, String32 str32); //- Encode string String16 String16FromString(Arena *arena, String str8); String32 String32FromString(Arena *arena, String str8); //////////////////////////////////////////////////////////// //~ Base64 u64 Base64LenFromStringLen(u64 len); u64 StringLenFromBase64Len(u64 len); String Base64FromString(Arena *arena, String str); String StringFromBase64(Arena *arena, String str); //////////////////////////////////////////////////////////// //~ Null-terminated strings //- Narrow strings u64 CstrLenNoLimit(char *cstr); u64 CstrLen(char *cstr, u64 limit); char *CstrFromString(Arena *arena, String src); char *CstrFromStringToBuff(String dest_buff, String src); String StringFromCstrNoLimit(char *cstr); String StringFromCstr(char *cstr, u64 limit); //- Wide strings u64 WstrLenNoLimit(wchar_t *wstr); u64 WstrLen(wchar_t *wstr, u64 limit); wchar_t *WstrFromString(Arena *arena, String src); wchar_t *WstrFromString16(Arena *arena, String16 src); String StringFromWstrNoLimit(Arena *arena, wchar_t *wstr); String StringFromWstr(Arena *arena, wchar_t *wstr, u64 limit); String16 String16FromWstrNoLimit(wchar_t *wstr); String16 String16FromWstr(wchar_t *wstr, u64 limit);