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