plugins/include/string.inc
author Scott Ehlert <ds@alliedmods.net>
Wed Aug 15 06:19:30 2007 +0000 (2007-08-15)
changeset 1330 ab94316bb52b
parent 1268 9360f5ea2289
child 1652 eacd2002cda8
permissions -rw-r--r--
Updated license headers on virtually all files with extremely minor changes in the name of some sort of strange consistency.
All plugin and include file headers also have been changed to say about GPL3 instead of GPL2.

(This day shall henceforth be known as the Eighty Column Massacre of '07)
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
     5  * =============================================================================
     6  *
     7  * This file is part of the SourceMod/SourcePawn SDK.
     8  *
     9  * This program is free software; you can redistribute it and/or modify it under
    10  * the terms of the GNU General Public License, version 3.0, as published by the
    11  * Free Software Foundation.
    12  * 
    13  * This program is distributed in the hope that it will be useful, but WITHOUT
    14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    15  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    16  * details.
    17  *
    18  * You should have received a copy of the GNU General Public License along with
    19  * this program.  If not, see <http://www.gnu.org/licenses/>.
    20  *
    21  * As a special exception, AlliedModders LLC gives you permission to link the
    22  * code of this program (as well as its derivative works) to "Half-Life 2," the
    23  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    24  * by the Valve Corporation.  You must obey the GNU General Public License in
    25  * all respects for all other code used.  Additionally, AlliedModders LLC grants
    26  * this exception to all derivative works.  AlliedModders LLC defines further
    27  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    28  * or <http://www.sourcemod.net/license.php>.
    29  *
    30  * Version: $Id$
    31  */
    32  
    33 #if defined _string_included
    34  #endinput
    35 #endif
    36 #define _string_included
    37 
    38 /**
    39  * @global Unless otherwise noted, all string functions which take in a 
    40  * writable buffer and maximum length should have the null terminator INCLUDED
    41  * in the length.  This means that this is valid: 
    42  * strcopy(string, sizeof(string), ...)
    43  */
    44  
    45 /**
    46  * Calculates the length of a string.
    47  *
    48  * @param str			String to check.
    49  * @return				Length of string, in cells (NOT characters).
    50  */
    51 native strlen(const String:str[]);
    52 
    53 /**
    54  * Tests whether a string is found inside another string.
    55  *
    56  * @param str			String to search in.
    57  * @param substr		Substring to find inside the original string.
    58  * @param caseSensitive	If true (default), search is case sensitive.
    59  *						If false, search is case insensitive.
    60  * @return				-1 on failure (no match found). Any other value
    61  *						indicates a position in the string where the match starts.
    62  */
    63 native StrContains(const String:str[], const String:substr[], bool:caseSensitive=true);
    64 
    65 /**
    66  * Compares two strings lexographically.
    67  *
    68  * @param str1			First string (left).
    69  * @param str2			Second string (right).
    70  * @param caseSensitive	If true (default), comparison is case sensitive.
    71  *						If false, comparison is case insensitive.
    72  * @return				-1 if str1 < str2
    73  *						0 if str1 == str2
    74  *						1 if str1 > str2
    75  */
    76 native strcmp(const String:str1[], const String:str2[], bool:caseSensitive=true);
    77 
    78 /**
    79  * Compares two strings parts lexographically.
    80  *
    81  * @param str1			First string (left).
    82  * @param str2			Second string (right).
    83  * @param num			Number of characters to compare.
    84  * @param caseSensitive	If true (default), comparison is case sensitive.
    85  *						If false, comparison is case insensitive.
    86  * @return				-1 if str1 < str2
    87  *						0 if str1 == str2
    88  *						1 if str1 > str2
    89  */
    90 native strncmp(const String:str1[], const String:str2[], num, bool:caseSensitive=true);
    91 
    92 /**
    93  * Backwards compatible stock - StrCompare is now strcmp
    94  * @deprecated		Renamed to strcmp
    95  */
    96 #pragma deprecated Use strcmp() instead
    97 stock StrCompare(const String:str1[], const String:str2[], bool:caseSensitive=true)
    98 {
    99 	return strcmp(str1, str2, caseSensitive);
   100 }
   101 
   102 /**
   103  * Returns whether two strings are equal.
   104  *
   105  * @param str1			First string (left).
   106  * @param str2			Second string (right).
   107  * @param caseSensitive	If true (default), comparison is case sensitive.
   108  * 						If false, comparison is case insensitive.
   109  * @return				True if equal, false otherwise.
   110  */
   111 stock bool:StrEqual(const String:str1[], const String:str2[], bool:caseSensitive=true)
   112 {
   113 	return (strcmp(str1, str2, caseSensitive) == 0);
   114 }
   115 
   116 /**
   117  * Copies one string to another string.
   118  * @note If the destination buffer is too small to hold the source string, the 
   119  *       destination will be truncated.
   120  *
   121  * @param dest			Destination string buffer to copy to.
   122  * @param destlen		Destination buffer length (includes null terminator).
   123  * @param source		Source string buffer to copy from.
   124  * @return				Number of cells written.
   125  */
   126 native strcopy(String:dest[], destLen, const String:source[]);
   127 
   128 /**
   129  * Backwards compatibility stock - use strcopy
   130  * @deprecated			Renamed to strcopy
   131  */
   132 #pragma deprecated Use strcopy() instead
   133 stock StrCopy(String:dest[], destLen, const String:source[])
   134 {
   135 	return strcopy(dest, destLen, source);
   136 }
   137 
   138 /**
   139  * Formats a string according to the SourceMod format rules (see documentation).
   140  *
   141  * @param buffer		Destination string buffer.
   142  * @param maxlength		Maximum length of output string buffer.
   143  * @param format		Formatting rules.
   144  * @param ...			Variable number of format parameters.
   145  * @return				Number of cells written.
   146  */
   147 native Format(String:buffer[], maxlength, const String:format[], any:...);
   148 
   149 /**
   150  * Formats a string according to the SourceMod format rules (see documentation).
   151  * @note This is the same as Format(), except none of the input buffers can 
   152  *       overlap the same memory as the output buffer.  Since this security 
   153  *       check is removed, it is slightly faster.
   154  *
   155  * @param buffer		Destination string buffer.
   156  * @param maxlength		Maximum length of output string buffer.
   157  * @param format		Formatting rules.
   158  * @param ...			Variable number of format parameters.
   159  * @return				Number of cells written.
   160  */
   161 native FormatEx(String:buffer[], maxlength, const String:format[], any:...);
   162 
   163 /**
   164  * Formats a string according to the SourceMod format rules (see documentation).
   165  * @note This is the same as Format(), except it grabs parameters from a 
   166  *       parent parameter stack, rather than a local.  This is useful for 
   167  *       implementing your own variable argument functions.
   168  *
   169  * @param buffer		Destination string buffer.
   170  * @param maxlength		Maximum length of output string buffer.
   171  * @param format		Formatting rules.
   172  * @param varpos		Argument number which contains the '...' symbol.
   173  *						Note: Arguments start at 1.
   174  * @return 				Number of bytes written.
   175  */
   176 native VFormat(String:buffer[], maxlength, const String:format[], varpos);
   177 
   178 /**
   179  * Converts a string to an integer.
   180  *
   181  * @param str			String to convert.
   182  * @param nBase			Numerical base to use.  10 is default.
   183  * @return				Integer conversion of string, or 0 on failure.
   184  */
   185 native StringToInt(const String:str[], nBase=10);
   186 
   187 /**
   188  * Converts a string to an integer with some more options.
   189  *
   190  * @param str			String to convert.
   191  * @param result		Variable to store the result in.
   192  * @param nBase			Numerical base to use.  10 is default.
   193  * @return				Number of characters consumed.
   194  */
   195 native StringToIntEx(const String:str[], &result, nBase=10);
   196 
   197 /**
   198  * Converts an integer to a string.
   199  *
   200  * @param num			Integer to convert.
   201  * @param str			Buffer to store string in.
   202  * @param maxlength		Maximum length of string buffer.
   203  * @return				Number of cells written to buffer.
   204  */
   205 native IntToString(num, String:str[], maxlength);
   206 
   207 /** 
   208  * Converts a string to a floating point number.
   209  *
   210  * @param str			String to convert to a foat.
   211  * @return				Floating point result, or 0.0 on error.
   212  */
   213 native Float:StringToFloat(const String:str[]);
   214 
   215 /** 
   216  * Converts a string to a floating point number with some more options.
   217  *
   218  * @param str			String to convert to a foat.
   219  * @param result		Variable to store result in.
   220  * @return				Number of characters consumed.
   221  */
   222 native StringToFloatEx(const String:str[], &Float:result);
   223 
   224 /**
   225  * Converts a floating point number to a string.
   226  *
   227  * @param num			Floating point number to convert.
   228  * @param str			Buffer to store string in.
   229  * @param maxlength		Maximum length of string buffer.
   230  * @return				Number of cells written to buffer.
   231  */
   232 native FloatToString(Float:num, String:str[], maxlength);
   233 
   234 /**
   235  * Finds the first "argument" in a string; either a set of space
   236  * terminated characters, or a fully quoted string.  After the 
   237  * argument is found, whitespace is read until the next portion
   238  * of the string is reached.  If nothing remains, -1 is returned.
   239  * Otherwise, the index to the first character is returned.
   240  *
   241  * @param source		Source input string.
   242  * @param arg			Stores argument read from string.
   243  * @param argLen		Maximum length of argument buffer.
   244  * @return				Index to next piece of string, or -1 if none.
   245  */
   246 native BreakString(const String:source[], String:arg[], argLen);
   247 
   248 /**
   249  * Backwards compatibility stock - use BreakString
   250  * @deprecated			Renamed to BreakString.
   251  */
   252 #pragma deprecated Use BreakString() instead
   253 stock StrBreak(const String:source[], String:arg[], argLen)
   254 {
   255 	return BreakString(source, arg, argLen);
   256 }
   257 
   258 /**
   259  * Removes whitespace characters from the beginning and end of a string.
   260  *
   261  * @param str			The string to trim.
   262  * @return				Number of bytes written (UTF-8 safe).
   263  */
   264 native TrimString(String:str[]);
   265 
   266 /**
   267  * Returns text in a string up until a certain character sequence is reached.
   268  *
   269  * @param source		Source input string.
   270  * @param split			A string which specifies a search point to break at.
   271  * @param part			Buffer to store string part.
   272  * @param partLen		Maximum length of the string part buffer.
   273  * @return				-1 if no match was found; otherwise, an index into source
   274  *						marking the first index after the searched text.  The
   275  *						index is always relative to the start of the input string.
   276  */
   277 native SplitString(const String:source[], const String:split[], String:part[], partLen);
   278 
   279 /**
   280  * Given a string, replaces all occurrences of a search string with a 
   281  * replacement string.
   282  *
   283  * @param text			String to perform search and replacements on.
   284  * @param maxlength		Maximum length of the string buffer.
   285  * @param search		String to search for.
   286  * @param replace		String to replace the search string with.
   287  * @return				Number of replacements that were performed.
   288  */
   289 native ReplaceString(String:text[], maxlength, const String:search[], const String:replace[]);
   290 
   291 /**
   292  * Given a string, replaces the first occurrence of a search string with a 
   293  * replacement string.
   294  *
   295  * @param text			String to perform search and replacements on.
   296  * @param maxlength		Maximum length of the string buffer.
   297  * @param search		String to search for.
   298  * @param replace		String to replace the search string with.
   299  * @param searchLen		If higher than -1, its value will be used instead of
   300  *						a strlen() call on the search parameter.
   301  * @param replaceLen	If higher than -1, its value will be used instead of
   302  *						a strlen() call on the replace parameter.
   303  * @return				Index into the buffer (relative to the start) from where
   304  *						the last replacement ended, or -1 if no replacements were
   305  *						made.
   306  */
   307 native ReplaceStringEx(String:text[], maxlength, const String:search[], const String:replace[], searchLen=-1, replaceLen=-1);
   308 
   309 /** 
   310  * Returns the number of bytes a character is using.  This is
   311  * for multi-byte characters (UTF-8).  For normal ASCII characters,
   312  * this will return 1.
   313  *
   314  * @param source		Source input string.
   315  * @return				Number of bytes the current character uses.
   316  */
   317 native GetCharBytes(const String:source[]);
   318 
   319 /**
   320  * Returns whether a character is an ASCII alphabet character.
   321  *
   322  * @note Multi-byte characters will always return false.
   323  *
   324  * @param char			Character to test.
   325  * @return				True if character is alphabetical, otherwise false.
   326  */
   327 native bool:IsCharAlpha(chr);
   328 
   329 /**
   330  * Returns whether a character is numeric.
   331  *
   332  * @note Multi-byte characters will always return false.
   333  *
   334  * @param char			Character to test.
   335  * @return				True if character is numeric, otherwise false.
   336  */
   337 native bool:IsCharNumeric(chr);
   338 
   339 /**
   340  * Returns whether a character is whitespace.
   341  *
   342  * @note Multi-byte characters will always return false.
   343  *
   344  * @param char			Character to test.
   345  * @return				True if character is whitespace, otherwise false.
   346  */
   347 native bool:IsCharSpace(chr);
   348 
   349 /**
   350  * Returns if a character is multi-byte or not.
   351  *
   352  * @param char			Character to test.
   353  * @return				0 for a normal 7-bit ASCII character,
   354  *						otherwise number of bytes in multi-byte character.
   355  */
   356 native IsCharMB(chr);
   357 
   358 /**
   359  * Returns whether an alphabetic character is uppercase.
   360  *
   361  * @note Multi-byte characters will always return false.
   362  *
   363  * @param char			Character to test.
   364  * @return				True if character is uppercase, otherwise false.
   365  */
   366 native bool:IsCharUpper(chr);
   367 
   368 /**
   369  * Returns whether an alphabetic character is lowercase.
   370  *
   371  * @note Multi-byte characters will always return false.
   372  *
   373  * @param char			Character to test.
   374  * @return				True if character is lowercase, otherwise false.
   375  */
   376 native bool:IsCharLower(chr);
   377 
   378 /**
   379  * Returns an uppercase character to a lowercase character.
   380  *
   381  * @param chr			Characer to convert.
   382  * @return				Lowercase character on success, 
   383  *						no change on failure.
   384  */
   385 stock CharToUpper(chr)
   386 {
   387 	if (IsCharLower(chr))
   388 	{
   389 		return (chr & ~(1<<5));
   390 	}
   391 	return chr;
   392 }
   393 
   394 /**
   395  * Returns a lowercase character to an uppercase character.
   396  *
   397  * @param chr			Characer to convert.
   398  * @return				Uppercase character on success, 
   399  *						no change on failure.
   400  */
   401 stock CharToLower(chr)
   402 {
   403 	if (IsCharUpper(chr))
   404 	{
   405 		return (chr | (1<<5));
   406 	}
   407 	return chr;
   408 }
   409 
   410 /**
   411  * Concatenates one string onto another.
   412  *
   413  * @param buffer		String to append to.
   414  * @param maxlength		Maximum length of entire buffer.
   415  * @param source		Source string to concatenate.
   416  * @return				Number of bytes written.
   417  */
   418 stock StrCat(String:buffer[], maxlength, const String:source[])
   419 {
   420 	new len = strlen(buffer);
   421 	if (len >= maxlength)
   422 	{
   423 		return 0;
   424 	}
   425 	
   426 	return Format(buffer[len], maxlength-len, "%s", source);
   427 }
   428 
   429 /**
   430  * Breaks a string into pieces and stores each piece into an array of buffers.
   431  *
   432  * @param text				The string to split.
   433  * @param split				The string to use as a split delimiter.
   434  * @param buffers			An array of string buffers (2D array).
   435  * @param maxStrings		Number of string buffers (first dimension size).
   436  * @param maxStringLength	Maximum length of each string buffer.
   437  * @return					Number of strings retrieved.
   438  */
   439 stock ExplodeString(const String:text[], const String:split[], String:buffers[][], maxStrings, maxStringLength)
   440 {
   441 	new reloc_idx, idx, total;
   442 	
   443 	if (maxStrings < 1 || split[0] == '\0')
   444 	{
   445 		return 0;
   446 	}
   447 	
   448 	while ((idx = SplitString(text[reloc_idx], split, buffers[total], maxStringLength)) != -1)
   449 	{
   450 		reloc_idx += idx;
   451 		if (text[reloc_idx] == '\0')
   452 		{
   453 			break;
   454 		}
   455 		if (++total >= maxStrings)
   456 		{
   457 			return total;
   458 		}
   459 	}
   460 	
   461 	if (text[reloc_idx] != '\0' && total <= maxStrings - 1)
   462 	{
   463 		strcopy(buffers[total++], maxStringLength, text[reloc_idx]);
   464 	}
   465 	
   466 	return total;
   467 }
   468 
   469 /**
   470  * Joins an array of strings into one string, with a "join" string inserted in
   471  * between each given string.  This function complements ExplodeString.
   472  *
   473  * @param strings		An array of strings.
   474  * @param numStrings	Number of strings in the array.
   475  * @param join			The join string to insert between each string.
   476  * @param buffer		Output buffer to write the joined string to.
   477  * @param maxLength		Maximum length of the output buffer.
   478  * @return				Number of bytes written to the output buffer.
   479  */
   480 stock ImplodeStrings(const String:strings[][], numStrings, const String:join[], String:buffer[], maxLength)
   481 {
   482 	new total, length, part_length;
   483 	new join_length = strlen(join);
   484 	for (new i=0; i<numStrings; i++)
   485 	{
   486 		length = strcopy(buffer[total], maxLength-total, strings[i]);
   487 		total += length;
   488 		if (length < part_length)
   489 		{
   490 			break;
   491 		}
   492 		if (i != numStrings - 1)
   493 		{
   494 			length = strcopy(buffer[total], maxLength-total, join);
   495 			total += length;
   496 			if (length < join_length)
   497 			{
   498 				break;
   499 			}
   500 		}
   501 	}
   502 	return total;
   503 }