plugins/include/string.inc
branchrefac-jit
changeset 2168 c24a6fa957db
     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 +}