1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/plugins/include/string.inc Sun Jul 06 04:49:55 2008 +0000
1.3 @@ -0,0 +1,557 @@
1.4 +/**
1.5 + * vim: set ts=4 :
1.6 + * =============================================================================
1.7 + * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
1.8 + * =============================================================================
1.9 + *
1.10 + * This file is part of the SourceMod/SourcePawn SDK.
1.11 + *
1.12 + * This program is free software; you can redistribute it and/or modify it under
1.13 + * the terms of the GNU General Public License, version 3.0, as published by the
1.14 + * Free Software Foundation.
1.15 + *
1.16 + * This program is distributed in the hope that it will be useful, but WITHOUT
1.17 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.18 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.19 + * details.
1.20 + *
1.21 + * You should have received a copy of the GNU General Public License along with
1.22 + * this program. If not, see <http://www.gnu.org/licenses/>.
1.23 + *
1.24 + * As a special exception, AlliedModders LLC gives you permission to link the
1.25 + * code of this program (as well as its derivative works) to "Half-Life 2," the
1.26 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.27 + * by the Valve Corporation. You must obey the GNU General Public License in
1.28 + * all respects for all other code used. Additionally, AlliedModders LLC grants
1.29 + * this exception to all derivative works. AlliedModders LLC defines further
1.30 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.31 + * or <http://www.sourcemod.net/license.php>.
1.32 + *
1.33 + * Version: $Id$
1.34 + */
1.35 +
1.36 +#if defined _string_included
1.37 + #endinput
1.38 +#endif
1.39 +#define _string_included
1.40 +
1.41 +/**
1.42 + * @global Unless otherwise noted, all string functions which take in a
1.43 + * writable buffer and maximum length should have the null terminator INCLUDED
1.44 + * in the length. This means that this is valid:
1.45 + * strcopy(string, sizeof(string), ...)
1.46 + */
1.47 +
1.48 +/**
1.49 + * Calculates the length of a string.
1.50 + *
1.51 + * @param str String to check.
1.52 + * @return Number of valid character bytes in the string.
1.53 + */
1.54 +native strlen(const String:str[]);
1.55 +
1.56 +/**
1.57 + * Tests whether a string is found inside another string.
1.58 + *
1.59 + * @param str String to search in.
1.60 + * @param substr Substring to find inside the original string.
1.61 + * @param caseSensitive If true (default), search is case sensitive.
1.62 + * If false, search is case insensitive.
1.63 + * @return -1 on failure (no match found). Any other value
1.64 + * indicates a position in the string where the match starts.
1.65 + */
1.66 +native StrContains(const String:str[], const String:substr[], bool:caseSensitive=true);
1.67 +
1.68 +/**
1.69 + * Compares two strings lexographically.
1.70 + *
1.71 + * @param str1 First string (left).
1.72 + * @param str2 Second string (right).
1.73 + * @param caseSensitive If true (default), comparison is case sensitive.
1.74 + * If false, comparison is case insensitive.
1.75 + * @return -1 if str1 < str2
1.76 + * 0 if str1 == str2
1.77 + * 1 if str1 > str2
1.78 + */
1.79 +native strcmp(const String:str1[], const String:str2[], bool:caseSensitive=true);
1.80 +
1.81 +/**
1.82 + * Compares two strings parts lexographically.
1.83 + *
1.84 + * @param str1 First string (left).
1.85 + * @param str2 Second string (right).
1.86 + * @param num Number of characters to compare.
1.87 + * @param caseSensitive If true (default), comparison is case sensitive.
1.88 + * If false, comparison is case insensitive.
1.89 + * @return -1 if str1 < str2
1.90 + * 0 if str1 == str2
1.91 + * 1 if str1 > str2
1.92 + */
1.93 +native strncmp(const String:str1[], const String:str2[], num, bool:caseSensitive=true);
1.94 +
1.95 +/**
1.96 + * Backwards compatible stock - StrCompare is now strcmp
1.97 + * @deprecated Renamed to strcmp
1.98 + */
1.99 +#pragma deprecated Use strcmp() instead
1.100 +stock StrCompare(const String:str1[], const String:str2[], bool:caseSensitive=true)
1.101 +{
1.102 + return strcmp(str1, str2, caseSensitive);
1.103 +}
1.104 +
1.105 +/**
1.106 + * Returns whether two strings are equal.
1.107 + *
1.108 + * @param str1 First string (left).
1.109 + * @param str2 Second string (right).
1.110 + * @param caseSensitive If true (default), comparison is case sensitive.
1.111 + * If false, comparison is case insensitive.
1.112 + * @return True if equal, false otherwise.
1.113 + */
1.114 +stock bool:StrEqual(const String:str1[], const String:str2[], bool:caseSensitive=true)
1.115 +{
1.116 + return (strcmp(str1, str2, caseSensitive) == 0);
1.117 +}
1.118 +
1.119 +/**
1.120 + * Copies one string to another string.
1.121 + * @note If the destination buffer is too small to hold the source string, the
1.122 + * destination will be truncated.
1.123 + *
1.124 + * @param dest Destination string buffer to copy to.
1.125 + * @param destlen Destination buffer length (includes null terminator).
1.126 + * @param source Source string buffer to copy from.
1.127 + * @return Number of cells written.
1.128 + */
1.129 +native strcopy(String:dest[], destLen, const String:source[]);
1.130 +
1.131 +/**
1.132 + * Backwards compatibility stock - use strcopy
1.133 + * @deprecated Renamed to strcopy
1.134 + */
1.135 +#pragma deprecated Use strcopy() instead
1.136 +stock StrCopy(String:dest[], destLen, const String:source[])
1.137 +{
1.138 + return strcopy(dest, destLen, source);
1.139 +}
1.140 +
1.141 +/**
1.142 + * Formats a string according to the SourceMod format rules (see documentation).
1.143 + *
1.144 + * @param buffer Destination string buffer.
1.145 + * @param maxlength Maximum length of output string buffer.
1.146 + * @param format Formatting rules.
1.147 + * @param ... Variable number of format parameters.
1.148 + * @return Number of cells written.
1.149 + */
1.150 +native Format(String:buffer[], maxlength, const String:format[], any:...);
1.151 +
1.152 +/**
1.153 + * Formats a string according to the SourceMod format rules (see documentation).
1.154 + * @note This is the same as Format(), except none of the input buffers can
1.155 + * overlap the same memory as the output buffer. Since this security
1.156 + * check is removed, it is slightly faster.
1.157 + *
1.158 + * @param buffer Destination string buffer.
1.159 + * @param maxlength Maximum length of output string buffer.
1.160 + * @param format Formatting rules.
1.161 + * @param ... Variable number of format parameters.
1.162 + * @return Number of cells written.
1.163 + */
1.164 +native FormatEx(String:buffer[], maxlength, const String:format[], any:...);
1.165 +
1.166 +/**
1.167 + * Formats a string according to the SourceMod format rules (see documentation).
1.168 + * @note This is the same as Format(), except it grabs parameters from a
1.169 + * parent parameter stack, rather than a local. This is useful for
1.170 + * implementing your own variable argument functions.
1.171 + *
1.172 + * @param buffer Destination string buffer.
1.173 + * @param maxlength Maximum length of output string buffer.
1.174 + * @param format Formatting rules.
1.175 + * @param varpos Argument number which contains the '...' symbol.
1.176 + * Note: Arguments start at 1.
1.177 + * @return Number of bytes written.
1.178 + */
1.179 +native VFormat(String:buffer[], maxlength, const String:format[], varpos);
1.180 +
1.181 +/**
1.182 + * Converts a string to an integer.
1.183 + *
1.184 + * @param str String to convert.
1.185 + * @param nBase Numerical base to use. 10 is default.
1.186 + * @return Integer conversion of string, or 0 on failure.
1.187 + */
1.188 +native StringToInt(const String:str[], nBase=10);
1.189 +
1.190 +/**
1.191 + * Converts a string to an integer with some more options.
1.192 + *
1.193 + * @param str String to convert.
1.194 + * @param result Variable to store the result in.
1.195 + * @param nBase Numerical base to use. 10 is default.
1.196 + * @return Number of characters consumed.
1.197 + */
1.198 +native StringToIntEx(const String:str[], &result, nBase=10);
1.199 +
1.200 +/**
1.201 + * Converts an integer to a string.
1.202 + *
1.203 + * @param num Integer to convert.
1.204 + * @param str Buffer to store string in.
1.205 + * @param maxlength Maximum length of string buffer.
1.206 + * @return Number of cells written to buffer.
1.207 + */
1.208 +native IntToString(num, String:str[], maxlength);
1.209 +
1.210 +/**
1.211 + * Converts a string to a floating point number.
1.212 + *
1.213 + * @param str String to convert to a foat.
1.214 + * @return Floating point result, or 0.0 on error.
1.215 + */
1.216 +native Float:StringToFloat(const String:str[]);
1.217 +
1.218 +/**
1.219 + * Converts a string to a floating point number with some more options.
1.220 + *
1.221 + * @param str String to convert to a foat.
1.222 + * @param result Variable to store result in.
1.223 + * @return Number of characters consumed.
1.224 + */
1.225 +native StringToFloatEx(const String:str[], &Float:result);
1.226 +
1.227 +/**
1.228 + * Converts a floating point number to a string.
1.229 + *
1.230 + * @param num Floating point number to convert.
1.231 + * @param str Buffer to store string in.
1.232 + * @param maxlength Maximum length of string buffer.
1.233 + * @return Number of cells written to buffer.
1.234 + */
1.235 +native FloatToString(Float:num, String:str[], maxlength);
1.236 +
1.237 +/**
1.238 + * Finds the first "argument" in a string; either a set of space
1.239 + * terminated characters, or a fully quoted string. After the
1.240 + * argument is found, whitespace is read until the next portion
1.241 + * of the string is reached. If nothing remains, -1 is returned.
1.242 + * Otherwise, the index to the first character is returned.
1.243 + *
1.244 + * @param source Source input string.
1.245 + * @param arg Stores argument read from string.
1.246 + * @param argLen Maximum length of argument buffer.
1.247 + * @return Index to next piece of string, or -1 if none.
1.248 + */
1.249 +native BreakString(const String:source[], String:arg[], argLen);
1.250 +
1.251 +/**
1.252 + * Backwards compatibility stock - use BreakString
1.253 + * @deprecated Renamed to BreakString.
1.254 + */
1.255 +#pragma deprecated Use BreakString() instead
1.256 +stock StrBreak(const String:source[], String:arg[], argLen)
1.257 +{
1.258 + return BreakString(source, arg, argLen);
1.259 +}
1.260 +
1.261 +/**
1.262 + * Removes whitespace characters from the beginning and end of a string.
1.263 + *
1.264 + * @param str The string to trim.
1.265 + * @return Number of bytes written (UTF-8 safe).
1.266 + */
1.267 +native TrimString(String:str[]);
1.268 +
1.269 +/**
1.270 + * Returns text in a string up until a certain character sequence is reached.
1.271 + *
1.272 + * @param source Source input string.
1.273 + * @param split A string which specifies a search point to break at.
1.274 + * @param part Buffer to store string part.
1.275 + * @param partLen Maximum length of the string part buffer.
1.276 + * @return -1 if no match was found; otherwise, an index into source
1.277 + * marking the first index after the searched text. The
1.278 + * index is always relative to the start of the input string.
1.279 + */
1.280 +native SplitString(const String:source[], const String:split[], String:part[], partLen);
1.281 +
1.282 +/**
1.283 + * Given a string, replaces all occurrences of a search string with a
1.284 + * replacement string.
1.285 + *
1.286 + * @param text String to perform search and replacements on.
1.287 + * @param maxlength Maximum length of the string buffer.
1.288 + * @param search String to search for.
1.289 + * @param replace String to replace the search string with.
1.290 + * @return Number of replacements that were performed.
1.291 + */
1.292 +native ReplaceString(String:text[], maxlength, const String:search[], const String:replace[]);
1.293 +
1.294 +/**
1.295 + * Given a string, replaces the first occurrence of a search string with a
1.296 + * replacement string.
1.297 + *
1.298 + * @param text String to perform search and replacements on.
1.299 + * @param maxlength Maximum length of the string buffer.
1.300 + * @param search String to search for.
1.301 + * @param replace String to replace the search string with.
1.302 + * @param searchLen If higher than -1, its value will be used instead of
1.303 + * a strlen() call on the search parameter.
1.304 + * @param replaceLen If higher than -1, its value will be used instead of
1.305 + * a strlen() call on the replace parameter.
1.306 + * @return Index into the buffer (relative to the start) from where
1.307 + * the last replacement ended, or -1 if no replacements were
1.308 + * made.
1.309 + */
1.310 +native ReplaceStringEx(String:text[], maxlength, const String:search[], const String:replace[], searchLen=-1, replaceLen=-1);
1.311 +
1.312 +/**
1.313 + * Returns the number of bytes a character is using. This is
1.314 + * for multi-byte characters (UTF-8). For normal ASCII characters,
1.315 + * this will return 1.
1.316 + *
1.317 + * @param source Source input string.
1.318 + * @return Number of bytes the current character uses.
1.319 + */
1.320 +native GetCharBytes(const String:source[]);
1.321 +
1.322 +/**
1.323 + * Returns whether a character is an ASCII alphabet character.
1.324 + *
1.325 + * @note Multi-byte characters will always return false.
1.326 + *
1.327 + * @param char Character to test.
1.328 + * @return True if character is alphabetical, otherwise false.
1.329 + */
1.330 +native bool:IsCharAlpha(chr);
1.331 +
1.332 +/**
1.333 + * Returns whether a character is numeric.
1.334 + *
1.335 + * @note Multi-byte characters will always return false.
1.336 + *
1.337 + * @param char Character to test.
1.338 + * @return True if character is numeric, otherwise false.
1.339 + */
1.340 +native bool:IsCharNumeric(chr);
1.341 +
1.342 +/**
1.343 + * Returns whether a character is whitespace.
1.344 + *
1.345 + * @note Multi-byte characters will always return false.
1.346 + *
1.347 + * @param char Character to test.
1.348 + * @return True if character is whitespace, otherwise false.
1.349 + */
1.350 +native bool:IsCharSpace(chr);
1.351 +
1.352 +/**
1.353 + * Returns if a character is multi-byte or not.
1.354 + *
1.355 + * @param char Character to test.
1.356 + * @return 0 for a normal 7-bit ASCII character,
1.357 + * otherwise number of bytes in multi-byte character.
1.358 + */
1.359 +native IsCharMB(chr);
1.360 +
1.361 +/**
1.362 + * Returns whether an alphabetic character is uppercase.
1.363 + *
1.364 + * @note Multi-byte characters will always return false.
1.365 + *
1.366 + * @param char Character to test.
1.367 + * @return True if character is uppercase, otherwise false.
1.368 + */
1.369 +native bool:IsCharUpper(chr);
1.370 +
1.371 +/**
1.372 + * Returns whether an alphabetic character is lowercase.
1.373 + *
1.374 + * @note Multi-byte characters will always return false.
1.375 + *
1.376 + * @param char Character to test.
1.377 + * @return True if character is lowercase, otherwise false.
1.378 + */
1.379 +native bool:IsCharLower(chr);
1.380 +
1.381 +/**
1.382 + * Strips a quote pair off a string if it exists. That is, the following
1.383 + * replace rule is applied once: $"(.*)"^ -> $\1^
1.384 + *
1.385 + * Note that the leading and trailing quotes will only be removed if both
1.386 + * exist. Otherwise, the string is left unmodified. This function should
1.387 + * be considered O(k) (all characters get shifted down).
1.388 + *
1.389 + * @param text String to modify (in place).
1.390 + * @return True if string was modified, false if there was no
1.391 + * set of quotes.
1.392 + */
1.393 +native bool:StripQuotes(String:text[]);
1.394 +
1.395 +/**
1.396 + * Returns an uppercase character to a lowercase character.
1.397 + *
1.398 + * @param chr Characer to convert.
1.399 + * @return Lowercase character on success,
1.400 + * no change on failure.
1.401 + */
1.402 +stock CharToUpper(chr)
1.403 +{
1.404 + if (IsCharLower(chr))
1.405 + {
1.406 + return (chr & ~(1<<5));
1.407 + }
1.408 + return chr;
1.409 +}
1.410 +
1.411 +/**
1.412 + * Returns a lowercase character to an uppercase character.
1.413 + *
1.414 + * @param chr Characer to convert.
1.415 + * @return Uppercase character on success,
1.416 + * no change on failure.
1.417 + */
1.418 +stock CharToLower(chr)
1.419 +{
1.420 + if (IsCharUpper(chr))
1.421 + {
1.422 + return (chr | (1<<5));
1.423 + }
1.424 + return chr;
1.425 +}
1.426 +
1.427 +/**
1.428 + * Finds the first occurrence of a character in a string.
1.429 + *
1.430 + * @param str String.
1.431 + * @param c Character to search for.
1.432 + * @param reverse False (default) to search forward, true to search
1.433 + * backward.
1.434 + * @return The index of the first occurrence of the character
1.435 + * in the string, or -1 if the character was not found.
1.436 + */
1.437 +stock FindCharInString(const String:str[], c, bool:reverse = false)
1.438 +{
1.439 + new i, len
1.440 +
1.441 + len = strlen(str);
1.442 +
1.443 + if (!reverse)
1.444 + {
1.445 + for (i = 0; i < len; i++)
1.446 + {
1.447 + if (str[i] == c)
1.448 + {
1.449 + return i;
1.450 + }
1.451 + }
1.452 + }
1.453 + else
1.454 + {
1.455 + for (i = len - 1; i >= 0; i--)
1.456 + {
1.457 + if (str[i] == c)
1.458 + {
1.459 + return i;
1.460 + }
1.461 + }
1.462 + }
1.463 +
1.464 + return -1;
1.465 +}
1.466 +
1.467 +/**
1.468 + * Concatenates one string onto another.
1.469 + *
1.470 + * @param buffer String to append to.
1.471 + * @param maxlength Maximum length of entire buffer.
1.472 + * @param source Source string to concatenate.
1.473 + * @return Number of bytes written.
1.474 + */
1.475 +stock StrCat(String:buffer[], maxlength, const String:source[])
1.476 +{
1.477 + new len = strlen(buffer);
1.478 + if (len >= maxlength)
1.479 + {
1.480 + return 0;
1.481 + }
1.482 +
1.483 + return Format(buffer[len], maxlength-len, "%s", source);
1.484 +}
1.485 +
1.486 +/**
1.487 + * Breaks a string into pieces and stores each piece into an array of buffers.
1.488 + *
1.489 + * @param text The string to split.
1.490 + * @param split The string to use as a split delimiter.
1.491 + * @param buffers An array of string buffers (2D array).
1.492 + * @param maxStrings Number of string buffers (first dimension size).
1.493 + * @param maxStringLength Maximum length of each string buffer.
1.494 + * @return Number of strings retrieved.
1.495 + */
1.496 +stock ExplodeString(const String:text[], const String:split[], String:buffers[][], maxStrings, maxStringLength)
1.497 +{
1.498 + new reloc_idx, idx, total;
1.499 +
1.500 + if (maxStrings < 1 || split[0] == '\0')
1.501 + {
1.502 + return 0;
1.503 + }
1.504 +
1.505 + while ((idx = SplitString(text[reloc_idx], split, buffers[total], maxStringLength)) != -1)
1.506 + {
1.507 + reloc_idx += idx;
1.508 + if (text[reloc_idx] == '\0')
1.509 + {
1.510 + break;
1.511 + }
1.512 + if (++total >= maxStrings)
1.513 + {
1.514 + return total;
1.515 + }
1.516 + }
1.517 +
1.518 + if (text[reloc_idx] != '\0' && total <= maxStrings - 1)
1.519 + {
1.520 + strcopy(buffers[total++], maxStringLength, text[reloc_idx]);
1.521 + }
1.522 +
1.523 + return total;
1.524 +}
1.525 +
1.526 +/**
1.527 + * Joins an array of strings into one string, with a "join" string inserted in
1.528 + * between each given string. This function complements ExplodeString.
1.529 + *
1.530 + * @param strings An array of strings.
1.531 + * @param numStrings Number of strings in the array.
1.532 + * @param join The join string to insert between each string.
1.533 + * @param buffer Output buffer to write the joined string to.
1.534 + * @param maxLength Maximum length of the output buffer.
1.535 + * @return Number of bytes written to the output buffer.
1.536 + */
1.537 +stock ImplodeStrings(const String:strings[][], numStrings, const String:join[], String:buffer[], maxLength)
1.538 +{
1.539 + new total, length, part_length;
1.540 + new join_length = strlen(join);
1.541 + for (new i=0; i<numStrings; i++)
1.542 + {
1.543 + length = strcopy(buffer[total], maxLength-total, strings[i]);
1.544 + total += length;
1.545 + if (length < part_length)
1.546 + {
1.547 + break;
1.548 + }
1.549 + if (i != numStrings - 1)
1.550 + {
1.551 + length = strcopy(buffer[total], maxLength-total, join);
1.552 + total += length;
1.553 + if (length < join_length)
1.554 + {
1.555 + break;
1.556 + }
1.557 + }
1.558 + }
1.559 + return total;
1.560 +}