diff options
Diffstat (limited to 'sourcemod/scripting/include/gamechaos/strings.inc')
| -rw-r--r-- | sourcemod/scripting/include/gamechaos/strings.inc | 367 |
1 files changed, 367 insertions, 0 deletions
diff --git a/sourcemod/scripting/include/gamechaos/strings.inc b/sourcemod/scripting/include/gamechaos/strings.inc new file mode 100644 index 0000000..8ffcb60 --- /dev/null +++ b/sourcemod/scripting/include/gamechaos/strings.inc @@ -0,0 +1,367 @@ + +#if defined _gamechaos_stocks_strings_included + #endinput +#endif +#define _gamechaos_stocks_strings_included + +// these are used for functions that return strings. +// you can change these if they're too small/big. +#define GC_FIXED_BUFFER_SIZE_SMALL 64 +#define GC_FIXED_BUFFER_SIZE_LARGE 4096 + +/** + * Puts the values from a string of integers into an array + * + * @param string + * @param separator + * @param array + * @param arraysize + */ +stock void GCSeparateIntsFromString(const char[] string, const char[] separator, int[] array, int arraysize) +{ + char[][] explodedbuffer = new char[arraysize][32]; + + ExplodeString(string, separator, explodedbuffer, arraysize, 32); + + for (int i; i < arraysize; i++) + { + array[i] = StringToInt(explodedbuffer[i]); + } +} + +/** + * Prints a message to all admins in the chat area. + * + * @param format Formatting rules. + * @param ... Variable number of format parameters. + */ +stock void GCPrintToChatAdmins(const char[] format, any ...) +{ + char buffer[256]; + + for (int i = 1; i <= MaxClients; i++) + { + if (GCIsValidClient(i)) + { + AdminId id = GetUserAdmin(i); + if (!GetAdminFlag(id, Admin_Generic)) + { + continue; + } + SetGlobalTransTarget(i); + VFormat(buffer, sizeof(buffer), format, 2); + PrintToChat(i, "%s", buffer); + } + } +} + +/** + * Removes trailings zeroes from a string. Also removes the decimal point if it can. + * + * @param buffer Buffer to trim. + * @return Whether anything was removed. + */ +stock bool GCRemoveTrailing0s(char[] buffer) +{ + bool removed; + int maxlen = strlen(buffer); + + if (maxlen == 0) + { + return removed; + } + + for (int i = maxlen - 1; i > 0 && (buffer[i] == '0' || buffer[i] == '.' || buffer[i] == 0); i--) + { + if (buffer[i] == 0) + { + continue; + } + if (buffer[i] == '.') + { + buffer[i] = 0; + removed = true; + break; + } + buffer[i] = 0; + removed = true; + } + return removed; +} + +/** + * Formats time by HHMMSS. Uses ticks for the time. + * + * @param timeInTicks Time in ticks. + * @param tickRate Tickrate. + * @param formattedTime String to use for formatting. + * @param size String size. + */ +stock void GCFormatTickTimeHHMMSS(int timeInTicks, float tickRate, char[] formattedTime, int size) +{ + if (timeInTicks <= 0) + { + FormatEx(formattedTime, size, "-00:00:00"); + return; + } + + int time = RoundFloat(float(timeInTicks) / tickRate * 100.0); // centiseconds + int iHours = time / 360000; + int iMinutes = time / 6000 - iHours * 6000; + int iSeconds = (time - iHours * 360000 - iMinutes * 6000) / 100; + int iCentiSeconds = time % 100; + + if (iHours != 0) + { + FormatEx(formattedTime, size, "%02i:", iHours); + } + if (iMinutes != 0) + { + Format(formattedTime, size, "%s%02i:", formattedTime, iMinutes); + } + + Format(formattedTime, size, "%s%02i.%02i", formattedTime, iSeconds, iCentiSeconds); +} + +/** + * Formats time by HHMMSS. Uses seconds. + * + * @param seconds Time in seconds. + * @param formattedTime String to use for formatting. + * @param size String size. + * @param decimals Amount of decimals to use for the fractional part. + */ +stock void GCFormatTimeHHMMSS(float seconds, char[] formattedTime, int size, int decimals) +{ + int iFlooredTime = RoundToFloor(seconds); + int iHours = iFlooredTime / 3600; + int iMinutes = iFlooredTime / 60 - iHours * 60; + int iSeconds = iFlooredTime - iHours * 3600 - iMinutes * 60; + int iFraction = RoundToFloor(FloatFraction(seconds) * Pow(10.0, float(decimals))); + + if (iHours != 0) + { + FormatEx(formattedTime, size, "%02i:", iHours); + } + if (iMinutes != 0) + { + Format(formattedTime, size, "%s%02i:", formattedTime, iMinutes); + } + char szFraction[32]; + FormatEx(szFraction, sizeof(szFraction), "%i", iFraction); + + int iTest = strlen(szFraction); + for (int i; i < decimals - iTest; i++) + { + Format(szFraction, sizeof(szFraction), "%s%s", "0", szFraction); + } + + Format(formattedTime, size, "%s%02i.%s", formattedTime, iSeconds, szFraction); +} + +/** + * Encodes and appends a number onto the end of a UTF-8 string. + * + * @param string String to append to. + * @param strsize String size. + * @param number Unicode codepoint to encode. + */ +stock void GCEncodeUtf8(char[] string, char strsize, int number) +{ + // UTF-8 octet sequence (only change digits marked with x) + /* + Char. number range | UTF-8 octet sequence + (hexadecimal) | (binary) + --------------------+--------------------------------------------- + 0000 0000-0000 007F | 0xxxxxxx + 0000 0080-0000 07FF | 110xxxxx 10xxxxxx + 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx + 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + // byte 4 | byte 3 | byte 2 | byte 1*/ + + //char encodedChar = 0b_11110000_10000000_10000000_10000000; + + int zeropos = strlen(string); + + if (zeropos >= strsize - 1) // need one byte for null terminator + { + return; + } + + if (number < 0) + { + //PrintToServer("ERROR: Encode() - Can't encode negative numbers"); + return; + } + + if (number >= 0x110_000) + { + //PrintToServer("ERROR: Encode() - Number is too big to encode"); + return; + } + + // 1 byte + if (number < 0x80) + { + string[zeropos] = number; + string[zeropos + 1] = '\0'; + } + // 2 bytes + else if (number < 0x800) + { + // can't encode if we don't have enough room + if (zeropos + 2 >= strsize) + { + return; + } + + string[zeropos] = 0b_1100_0000 | (number >> 6); // don't need to mask out bits over 0x7FF + string[zeropos + 1] = 0b_1000_0000 | (number & 0b_0011_1111); + + string[zeropos + 2] = '\0'; + } + // 3 bytes + else if (number < 0x10_000) + { + // can't encode if we don't have enough room + if (zeropos + 3 >= strsize) + { + return; + } + + string[zeropos] = 0b_1110_0000 | (number >> 12); // don't need to mask out bits over 0xFFFF + string[zeropos + 1] = 0b_1000_0000 | ((number >> 6) & 0b_0011_1111); + string[zeropos + 2] = 0b_1000_0000 | (number & 0b_0011_1111); + + string[zeropos + 3] = '\0'; + } + // 4 bytes + else if (number < 0x110_000) + { + // can't encode if we don't have enough room + if (zeropos + 4 >= strsize) + { + return; + } + + string[zeropos] = 0b_1111_0000 | (number >> 18); // don't need to mask out bits over 0x10FFFF + string[zeropos + 1] = 0b_1000_0000 | ((number >> 12) & 0b_0011_1111); + string[zeropos + 2] = 0b_1000_0000 | ((number >> 6) & 0b_0011_1111); + string[zeropos + 3] = 0b_1000_0000 | (number & 0b_0011_1111); + + string[zeropos + 4] = '\0'; + } +} + +// decode a UTF-8 string into an array of unicode codepoints +/** + * Decodes a UTF-8 string into an array of unicode codepoints. + * + * @param string String to decode. + * @param strsize String size. + * @param codepoints Array to use to store the codepoints. + * @param cplength Array length. + */ +stock void GCDecodeUtf8(char[] string, int strsize, int[] codepoints, int cplength) +{ + int charindex; + int cpindex; + + while (charindex < strsize && cpindex < cplength) + { + if (string[charindex] == '\0') + { + break; + } + + int bytes = GetCharBytes(string[charindex]); + + switch (bytes) + { + case 1: + { + codepoints[cpindex] = string[charindex]; + } + case 2: + { + codepoints[cpindex] = (string[charindex++] & 0b_0001_1111) << 6; // byte 2 + codepoints[cpindex] |= string[charindex] & 0b_0011_1111; // byte 1 + } + case 3: + { + codepoints[cpindex] = (string[charindex++] & 0b_0000_1111) << 12; // byte 3 + codepoints[cpindex] |= (string[charindex++] & 0b_0011_1111) << 6; // byte 2 + codepoints[cpindex] |= string[charindex] & 0b_0011_1111; // byte 1 + } + case 4: + { + codepoints[cpindex] = (string[charindex++] & 0b_0000_0111) << 18; // byte 4 + codepoints[cpindex] |= (string[charindex++] & 0b_0011_1111) << 12; // byte 3 + codepoints[cpindex] |= (string[charindex++] & 0b_0011_1111) << 6; // byte 2 + codepoints[cpindex] |= string[charindex] & 0b_0011_1111; // byte 1 + } + } + + charindex++; + cpindex++; + } +} + +/** + * Converts an integer to a string. + * Same as IntToString, but it returns the string. + * + * @param num Integer to convert. + * @return String of the number. + */ +stock char[] GCIntToStringRet(int num) +{ + char string[GC_FIXED_BUFFER_SIZE_SMALL]; + IntToString(num, string, sizeof string); + return string; +} + + /** + * Converts a floating point number to a string. + * Same as FloatToString, but it returns the string. + * + * @param num Floating point number to convert. + * @return String of the number. + */ +stock char[] GCFloatToStringRet(float num) +{ + char string[GC_FIXED_BUFFER_SIZE_SMALL]; + FloatToString(num, string, sizeof string); + return string; +} + +/** + * Formats a string according to the SourceMod format rules (see documentation). + * Same as Format, except it returns the formatted string. + * + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @return Formatted string. + */ +stock char[] GCFormatReturn(const char[] format, any ...) +{ + char string[GC_FIXED_BUFFER_SIZE_LARGE]; + VFormat(string, sizeof string, format, 2); + return string; +} + +/** + * Removes whitespace characters from the beginning and end of a string. + * Same as TrimString, except it returns the formatted string and + * it doesn't modify the passed string. + * + * @param str The string to trim. + * @return Number of bytes written (UTF-8 safe). + */ +stock char[] GCTrimStringReturn(char[] str) +{ + char string[GC_FIXED_BUFFER_SIZE_LARGE]; + strcopy(string, sizeof string, str); + TrimString(string); + return string; +}
\ No newline at end of file |
