core/smn_string.cpp
author Scott Ehlert <ds@alliedmods.net>
Wed Aug 15 06:19:30 2007 +0000 (2007-08-15)
changeset 1330 ab94316bb52b
parent 1231 17badaf66ce4
child 1360 962ecf7c9d37
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)
dvander@370
     1
/**
ds@653
     2
 * vim: set ts=4 :
ds@1330
     3
 * =============================================================================
dvander@1231
     4
 * SourceMod
dvander@1231
     5
 * Copyright (C) 2004-2007 AlliedModders LLC.  All rights reserved.
ds@1330
     6
 * =============================================================================
dvander@370
     7
 *
ds@1330
     8
 * This program is free software; you can redistribute it and/or modify it under
ds@1330
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330
    10
 * Free Software Foundation.
dvander@1231
    11
 * 
ds@1330
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
ds@1330
    15
 * details.
dvander@1231
    16
 *
ds@1330
    17
 * You should have received a copy of the GNU General Public License along with
ds@1330
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@1231
    19
 *
ds@1330
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
ds@1330
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
ds@1330
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
ds@1330
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330
    27
 * or <http://www.sourcemod.net/license.php>.
dvander@370
    28
 *
dvander@370
    29
 * Version: $Id$
dvander@370
    30
 */
dvander@370
    31
faluco@225
    32
#include <string.h>
dvander@233
    33
#include <stdlib.h>
dvander@233
    34
#include "sm_globals.h"
faluco@230
    35
#include "sm_stringutil.h"
dvander@631
    36
#include "TextParsers.h"
dvander@748
    37
#include <ctype.h>
faluco@225
    38
faluco@225
    39
inline const char *_strstr(const char *str, const char *substr)
faluco@225
    40
{
faluco@225
    41
#ifdef PLATFORM_WINDOWS
faluco@225
    42
	return strstr(str, substr);
dvander@351
    43
#elif defined PLATFORM_LINUX
faluco@225
    44
	return (const char *)strstr(str, substr);
faluco@225
    45
#endif
faluco@225
    46
}
faluco@225
    47
faluco@225
    48
/*********************************************
faluco@225
    49
*                                            *
faluco@225
    50
* STRING MANIPULATION NATIVE IMPLEMENTATIONS *
faluco@225
    51
*                                            *
faluco@225
    52
*********************************************/
faluco@225
    53
faluco@225
    54
static cell_t sm_strlen(IPluginContext *pCtx, const cell_t *params)
faluco@225
    55
{
faluco@225
    56
	char *str;
faluco@225
    57
	pCtx->LocalToString(params[1], &str);
faluco@225
    58
faluco@225
    59
	return strlen(str);
faluco@225
    60
}
faluco@225
    61
faluco@225
    62
static cell_t sm_contain(IPluginContext *pCtx, const cell_t *params)
faluco@225
    63
{
faluco@225
    64
	typedef const char *(*STRSEARCH)(const char *, const char *);
faluco@225
    65
	STRSEARCH func;
faluco@225
    66
	char *str, *substr;
faluco@225
    67
faluco@225
    68
	pCtx->LocalToString(params[1], &str);
faluco@225
    69
	pCtx->LocalToString(params[2], &substr);
faluco@225
    70
faluco@225
    71
	func = (params[3]) ? _strstr : stristr;
faluco@225
    72
	const char *pos = func(str, substr);
faluco@225
    73
	if (pos)
faluco@225
    74
	{
faluco@225
    75
		return (pos - str);
faluco@225
    76
	}
faluco@225
    77
faluco@225
    78
	return -1;
faluco@225
    79
}
faluco@225
    80
dvander@233
    81
static cell_t sm_strcmp(IPluginContext *pCtx, const cell_t *params)
faluco@225
    82
{
faluco@225
    83
	typedef int (*STRCOMPARE)(const char *, const char *);
faluco@225
    84
	STRCOMPARE func;
faluco@225
    85
	char *str1, *str2;
faluco@225
    86
faluco@225
    87
	pCtx->LocalToString(params[1], &str1);
faluco@225
    88
	pCtx->LocalToString(params[2], &str2);
faluco@225
    89
faluco@225
    90
	func = (params[3]) ? strcmp : stricmp;
faluco@225
    91
dvander@233
    92
	return (func(str1, str2));
faluco@225
    93
}
faluco@225
    94
dvander@680
    95
static cell_t sm_strncmp(IPluginContext *pCtx, const cell_t *params)
dvander@680
    96
{
dvander@680
    97
	char *str1, *str2;
dvander@680
    98
dvander@680
    99
	pCtx->LocalToString(params[1], &str1);
dvander@680
   100
	pCtx->LocalToString(params[2], &str2);
dvander@680
   101
	
dvander@680
   102
	if  (params[4])
dvander@680
   103
	{
dvander@680
   104
		return strncmp(str1, str2, (size_t)params[3]);
dvander@680
   105
	} else {
dvander@680
   106
		return strncasecmp(str1, str2, (size_t)params[3]);
dvander@680
   107
	}
dvander@680
   108
}
dvander@680
   109
faluco@225
   110
static cell_t sm_strcopy(IPluginContext *pCtx, const cell_t *params)
faluco@225
   111
{
faluco@230
   112
	char *dest, *src;
faluco@225
   113
faluco@225
   114
	pCtx->LocalToString(params[1], &dest);
faluco@225
   115
	pCtx->LocalToString(params[3], &src);
faluco@225
   116
faluco@230
   117
	return strncopy(dest, src, params[2]);
faluco@225
   118
}
faluco@226
   119
dvander@233
   120
static cell_t sm_strconvint(IPluginContext *pCtx, const cell_t *params)
faluco@226
   121
{
dvander@233
   122
	char *str, *dummy;
faluco@226
   123
	pCtx->LocalToString(params[1], &str);
faluco@226
   124
dvander@233
   125
	return static_cast<cell_t>(strtol(str, &dummy, params[2]));
faluco@226
   126
}
faluco@226
   127
dvander@1072
   128
static cell_t StringToIntEx(IPluginContext *pCtx, const cell_t *params)
dvander@1072
   129
{
dvander@1072
   130
	char *str, *dummy = NULL;
dvander@1072
   131
	cell_t *addr;
dvander@1072
   132
	pCtx->LocalToString(params[1], &str);
dvander@1072
   133
	pCtx->LocalToPhysAddr(params[2], &addr);
dvander@1072
   134
dvander@1072
   135
	*addr = static_cast<cell_t>(strtol(str, &dummy, params[3]));
dvander@1072
   136
dvander@1072
   137
	return dummy - str;
dvander@1072
   138
}
dvander@1072
   139
faluco@226
   140
static cell_t sm_numtostr(IPluginContext *pCtx, const cell_t *params)
faluco@226
   141
{
faluco@226
   142
	char *str;
faluco@226
   143
	pCtx->LocalToString(params[2], &str);
faluco@274
   144
	size_t res = UTIL_Format(str, params[3], "%d", params[1]);
faluco@226
   145
faluco@274
   146
	return static_cast<cell_t>(res);
faluco@226
   147
}
faluco@226
   148
faluco@226
   149
static cell_t sm_strtofloat(IPluginContext *pCtx, const cell_t *params)
faluco@226
   150
{
dvander@233
   151
	char *str, *dummy;
faluco@226
   152
	pCtx->LocalToString(params[1], &str);
faluco@226
   153
dvander@233
   154
	float val = (float)strtod(str, &dummy);
dvander@233
   155
dvander@233
   156
	return sp_ftoc(val);
faluco@226
   157
}
faluco@226
   158
dvander@1072
   159
static cell_t StringToFloatEx(IPluginContext *pCtx, const cell_t *params)
dvander@1072
   160
{
dvander@1072
   161
	char *str, *dummy = NULL;
dvander@1072
   162
	cell_t *addr;
dvander@1072
   163
	pCtx->LocalToString(params[1], &str);
dvander@1072
   164
	pCtx->LocalToPhysAddr(params[2], &addr);
dvander@1072
   165
dvander@1072
   166
	float val = (float)strtod(str, &dummy);
dvander@1072
   167
dvander@1072
   168
	*addr = sp_ftoc(val);
dvander@1072
   169
dvander@1072
   170
	return dummy - str;
dvander@1072
   171
}
dvander@1072
   172
faluco@226
   173
static cell_t sm_floattostr(IPluginContext *pCtx, const cell_t *params)
faluco@226
   174
{
faluco@226
   175
	char *str;
faluco@226
   176
	pCtx->LocalToString(params[2], &str);
faluco@274
   177
	size_t res = UTIL_Format(str, params[3], "%f", sp_ctof(params[1]));
faluco@226
   178
faluco@274
   179
	return static_cast<cell_t>(res);
faluco@226
   180
}
dvander@233
   181
faluco@236
   182
static cell_t sm_formatex(IPluginContext *pCtx, const cell_t *params)
faluco@236
   183
{
faluco@236
   184
	char *buf, *fmt;
faluco@236
   185
	size_t res;
faluco@236
   186
	int arg = 4;
faluco@236
   187
faluco@236
   188
	pCtx->LocalToString(params[1], &buf);
faluco@236
   189
	pCtx->LocalToString(params[3], &fmt);
faluco@236
   190
	res = atcprintf(buf, static_cast<size_t>(params[2]), fmt, pCtx, params, &arg);
faluco@236
   191
faluco@236
   192
	return static_cast<cell_t>(res);
faluco@236
   193
}
faluco@236
   194
faluco@236
   195
static char g_formatbuf[2048];
faluco@236
   196
static cell_t sm_format(IPluginContext *pCtx, const cell_t *params)
faluco@236
   197
{
faluco@236
   198
	char *buf, *fmt, *destbuf;
faluco@236
   199
	cell_t start_addr, end_addr, maxparam;
faluco@236
   200
	size_t res, maxlen;
faluco@236
   201
	int arg = 4;
faluco@236
   202
	bool copy = false;
faluco@236
   203
faluco@236
   204
	pCtx->LocalToString(params[1], &destbuf);
faluco@236
   205
	pCtx->LocalToString(params[3], &fmt);
faluco@236
   206
faluco@236
   207
	maxlen = static_cast<size_t>(params[2]);
faluco@236
   208
	start_addr = params[1];
faluco@236
   209
	end_addr = params[1] + maxlen;
faluco@236
   210
	maxparam = params[0];
faluco@236
   211
faluco@236
   212
	for (cell_t i=3; i<=maxparam; i++)
faluco@236
   213
	{
faluco@236
   214
		if ((params[i] >= start_addr) && (params[i] <= end_addr))
faluco@236
   215
		{
faluco@236
   216
			copy = true;
faluco@236
   217
			break;
faluco@236
   218
		}
faluco@236
   219
	}
faluco@236
   220
	buf = (copy) ? g_formatbuf : destbuf;
faluco@236
   221
	res = atcprintf(buf, maxlen, fmt, pCtx, params, &arg);
faluco@236
   222
faluco@236
   223
	if (copy)
faluco@236
   224
	{
faluco@236
   225
		memcpy(destbuf, g_formatbuf, res+1);
faluco@236
   226
	}
faluco@236
   227
faluco@236
   228
	return static_cast<cell_t>(res);
faluco@236
   229
}
faluco@236
   230
dvander@411
   231
static cell_t sm_vformat(IPluginContext *pContext, const cell_t *params)
dvander@411
   232
{
dvander@411
   233
	int vargPos = static_cast<int>(params[4]);
dvander@411
   234
dvander@411
   235
	/* Get the parent parameter array */
dvander@411
   236
	sp_context_t *ctx = pContext->GetContext();
dvander@411
   237
	cell_t *local_params = (cell_t *)(ctx->memory + ctx->frm + (2 * sizeof(cell_t)));
dvander@411
   238
dvander@411
   239
	cell_t max = local_params[0];
dvander@411
   240
	if (vargPos > (int)max + 1)
dvander@411
   241
	{
dvander@411
   242
		return pContext->ThrowNativeError("Argument index is invalid: %d", vargPos);
dvander@411
   243
	}
dvander@411
   244
dvander@411
   245
	cell_t addr_start = params[1];
dvander@411
   246
	cell_t addr_end = addr_start + params[2];
dvander@411
   247
	bool copy = false;
dvander@411
   248
	for (int i=vargPos; i<=max; i++)
dvander@411
   249
	{
dvander@411
   250
		/* Does this clip bounds? */
dvander@411
   251
		if ((local_params[i] >= addr_start)
dvander@411
   252
			&& (local_params[i] <= addr_end))
dvander@411
   253
		{
dvander@411
   254
			copy = true;
dvander@411
   255
			break;
dvander@411
   256
		}
dvander@411
   257
	}
dvander@411
   258
dvander@411
   259
	/* Get destination info */
dvander@411
   260
	char *format, *destination;
dvander@411
   261
	size_t maxlen = static_cast<size_t>(params[2]);
dvander@411
   262
dvander@411
   263
	if (copy)
dvander@411
   264
	{
dvander@411
   265
		destination = g_formatbuf;
dvander@411
   266
	} else {
dvander@411
   267
		pContext->LocalToString(params[1], &destination);
dvander@411
   268
	}
dvander@411
   269
dvander@411
   270
	pContext->LocalToString(params[3], &format);
dvander@411
   271
dvander@411
   272
	size_t total = atcprintf(destination, maxlen, format, pContext, local_params, &vargPos);
dvander@411
   273
dvander@411
   274
	/* Perform copy-on-write if we need to */
dvander@411
   275
	if (copy)
dvander@411
   276
	{
dvander@411
   277
		pContext->StringToLocal(params[1], maxlen, g_formatbuf);
dvander@411
   278
	}
dvander@411
   279
dvander@411
   280
	return total;
dvander@411
   281
}
dvander@411
   282
dvander@631
   283
/* :TODO: make this UTF8 safe */
ds@830
   284
static cell_t BreakString(IPluginContext *pContext, const cell_t *params)
dvander@631
   285
{
dvander@631
   286
	const char *input;
dvander@631
   287
	char *out;
dvander@631
   288
	size_t outMax;
dvander@631
   289
dvander@631
   290
	/* Get parameters */
dvander@631
   291
	pContext->LocalToString(params[1], (char **)&input);
dvander@631
   292
	pContext->LocalToString(params[2], &out);
dvander@631
   293
	outMax = params[3];
dvander@631
   294
dvander@631
   295
	const char *inptr = input;
dvander@631
   296
	/* Eat up whitespace */
dvander@631
   297
	while (*inptr != '\0' && IsWhitespace(inptr))
dvander@631
   298
	{
dvander@631
   299
		inptr++;
dvander@631
   300
	}
dvander@631
   301
dvander@631
   302
	if (*inptr == '\0')
dvander@631
   303
	{
dvander@631
   304
		if (outMax)
dvander@631
   305
		{
dvander@631
   306
			*out = '\0';
dvander@631
   307
		}
dvander@631
   308
		return -1;
dvander@631
   309
	}
dvander@631
   310
dvander@631
   311
	const char *start, *end = NULL;
dvander@631
   312
dvander@631
   313
	bool quoted = (*inptr == '"');
dvander@631
   314
	if (quoted)
dvander@631
   315
	{
dvander@631
   316
		inptr++;
dvander@631
   317
		start = inptr;
dvander@631
   318
		/* Read input until we reach a quote. */
dvander@631
   319
		while (*inptr != '\0' && *inptr != '"')
dvander@631
   320
		{
dvander@631
   321
			/* Update the end point, increment the stream. */
dvander@631
   322
			end = inptr++;
dvander@631
   323
		}
dvander@631
   324
		/* Read one more token if we reached an end quote */
dvander@631
   325
		if (*inptr == '"')
dvander@631
   326
		{
dvander@631
   327
			inptr++;
dvander@631
   328
		}
dvander@631
   329
	} else {
dvander@631
   330
		start = inptr;
dvander@631
   331
		/* Read input until we reach a space */
dvander@631
   332
		while (*inptr != '\0' && !IsWhitespace(inptr))
dvander@631
   333
		{
dvander@631
   334
			/* Update the end point, increment the stream. */
dvander@631
   335
			end = inptr++;
dvander@631
   336
		}
dvander@631
   337
	}
dvander@631
   338
dvander@631
   339
	/* Copy the string we found, if necessary */
dvander@631
   340
	if (end == NULL)
dvander@631
   341
	{
dvander@631
   342
		if (outMax)
dvander@631
   343
		{
dvander@631
   344
			*out = '\0';
dvander@631
   345
		}
dvander@631
   346
	} else if (outMax) {
dvander@631
   347
		char *outptr = out;
dvander@631
   348
		outMax--;
dvander@631
   349
		for (const char *ptr=start;
dvander@631
   350
			(ptr <= end) && ((unsigned)(outptr - out) < (outMax));
dvander@631
   351
			ptr++, outptr++)
dvander@631
   352
			{
dvander@631
   353
			*outptr = *ptr;
dvander@631
   354
		}
dvander@631
   355
		*outptr = '\0';
dvander@631
   356
	}
dvander@631
   357
dvander@631
   358
	/* Consume more of the string until we reach non-whitespace */
dvander@631
   359
	while (*inptr != '\0' && IsWhitespace(inptr))
dvander@631
   360
	{
dvander@631
   361
		inptr++;
dvander@631
   362
	}
dvander@631
   363
dvander@631
   364
	if (*inptr == '\0')
dvander@631
   365
	{
dvander@631
   366
		return -1;
dvander@631
   367
	}
dvander@631
   368
dvander@631
   369
	return inptr - input;
dvander@631
   370
}
dvander@631
   371
dvander@748
   372
static cell_t GetCharBytes(IPluginContext *pContext, const cell_t *params)
dvander@748
   373
{
dvander@748
   374
	char *str;
dvander@748
   375
	pContext->LocalToString(params[1], &str);
dvander@748
   376
dvander@748
   377
	return _GetUTF8CharBytes(str);
dvander@748
   378
};
dvander@748
   379
dvander@748
   380
static cell_t IsCharAlpha(IPluginContext *pContext, const cell_t *params)
dvander@748
   381
{
dvander@748
   382
	char chr = params[1];
dvander@748
   383
dvander@748
   384
	if (_GetUTF8CharBytes(&chr) != 1)
dvander@748
   385
	{
dvander@748
   386
		return 0;
dvander@748
   387
	}
dvander@748
   388
dvander@748
   389
	return isalpha(chr);
dvander@748
   390
}
dvander@748
   391
dvander@748
   392
static cell_t IsCharNumeric(IPluginContext *pContext, const cell_t *params)
dvander@748
   393
{
dvander@748
   394
	char chr = params[1];
dvander@748
   395
dvander@748
   396
	if (_GetUTF8CharBytes(&chr) != 1)
dvander@748
   397
	{
dvander@748
   398
		return 0;
dvander@748
   399
	}
dvander@748
   400
dvander@748
   401
	return isdigit(chr);
dvander@748
   402
}
dvander@748
   403
dvander@748
   404
static cell_t IsCharSpace(IPluginContext *pContext, const cell_t *params)
dvander@748
   405
{
dvander@748
   406
	char chr = params[1];
dvander@748
   407
dvander@748
   408
	if (_GetUTF8CharBytes(&chr) != 1)
dvander@748
   409
	{
dvander@748
   410
		return 0;
dvander@748
   411
	}
dvander@748
   412
dvander@748
   413
	return isspace(chr);
dvander@748
   414
}
dvander@748
   415
dvander@748
   416
static cell_t IsCharMB(IPluginContext *pContext, const cell_t *params)
dvander@748
   417
{
dvander@748
   418
	char chr = params[1];
dvander@748
   419
dvander@748
   420
	unsigned int bytes = _GetUTF8CharBytes(&chr);
dvander@748
   421
	if (bytes == 1)
dvander@748
   422
	{
dvander@748
   423
		return 0;
dvander@748
   424
	}
dvander@748
   425
dvander@748
   426
	return bytes;
dvander@748
   427
}
dvander@748
   428
ds@830
   429
static cell_t IsCharUpper(IPluginContext *pContext, const cell_t *params)
dvander@748
   430
{
dvander@748
   431
	char chr = params[1];
dvander@748
   432
dvander@748
   433
	if (_GetUTF8CharBytes(&chr) != 1)
dvander@748
   434
	{
dvander@748
   435
		return 0;
dvander@748
   436
	}
dvander@748
   437
dvander@748
   438
	return isupper(chr);
dvander@748
   439
}
dvander@748
   440
ds@830
   441
static cell_t IsCharLower(IPluginContext *pContext, const cell_t *params)
dvander@748
   442
{
dvander@748
   443
	char chr = params[1];
dvander@748
   444
dvander@748
   445
	if (_GetUTF8CharBytes(&chr) != 1)
dvander@748
   446
	{
dvander@748
   447
		return 0;
dvander@748
   448
	}
dvander@748
   449
dvander@748
   450
	return islower(chr);
dvander@748
   451
}
dvander@748
   452
dvander@833
   453
static cell_t ReplaceString(IPluginContext *pContext, const cell_t *params)
dvander@833
   454
{
dvander@833
   455
	char *text, *search, *replace;
dvander@833
   456
	size_t maxlength;
dvander@833
   457
	
dvander@833
   458
	pContext->LocalToString(params[1], &text);
dvander@833
   459
	pContext->LocalToString(params[3], &search);
dvander@833
   460
	pContext->LocalToString(params[4], &replace);
dvander@833
   461
	maxlength = (size_t)params[2];
dvander@833
   462
dvander@833
   463
dvander@833
   464
	return  UTIL_ReplaceAll(text, maxlength, search, replace);
dvander@833
   465
}
dvander@833
   466
dvander@833
   467
static cell_t ReplaceStringEx(IPluginContext *pContext, const cell_t *params)
dvander@833
   468
{
dvander@833
   469
	char *text, *search, *replace;
dvander@833
   470
	size_t maxlength;
dvander@833
   471
dvander@833
   472
	pContext->LocalToString(params[1], &text);
dvander@833
   473
	pContext->LocalToString(params[3], &search);
dvander@833
   474
	pContext->LocalToString(params[4], &replace);
dvander@833
   475
	maxlength = (size_t)params[2];
dvander@833
   476
dvander@833
   477
	size_t searchLen = (params[5] == -1) ? strlen(search) : (size_t)params[5];
dvander@833
   478
	size_t replaceLen = (params[6] == -1) ? strlen(replace) : (size_t)params[6];
dvander@833
   479
dvander@833
   480
	char *ptr = UTIL_ReplaceEx(text, maxlength, search, searchLen, replace, replaceLen);
dvander@833
   481
dvander@833
   482
	if (ptr == NULL)
dvander@833
   483
	{
dvander@833
   484
		return -1;
dvander@833
   485
	}
dvander@833
   486
dvander@833
   487
	return ptr - text;
dvander@833
   488
}
dvander@833
   489
ds@830
   490
static cell_t TrimString(IPluginContext *pContext, const cell_t *params)
ds@830
   491
{
ds@830
   492
	char *str;
ds@830
   493
	pContext->LocalToString(params[1], &str);
ds@830
   494
ds@830
   495
	size_t chars = strlen(str);
ds@830
   496
ds@830
   497
	if (chars == 0)
ds@830
   498
	{
ds@830
   499
		return 0;
ds@830
   500
	}
ds@830
   501
ds@830
   502
	char *end = str + chars - 1;
ds@830
   503
ds@830
   504
	/* Iterate backwards through string until we reach first non-whitespace char */
ds@830
   505
	while (end >= str && IsWhitespace(end))
ds@830
   506
	{
ds@830
   507
		end--;
ds@830
   508
	}
ds@830
   509
ds@830
   510
	/* Replace first whitespace char (at the end) with null terminator */
ds@830
   511
	*(end + 1) = '\0';
ds@830
   512
ds@830
   513
	/* Iterate forwards through string until first non-whitespace char is reached */
ds@830
   514
	while (IsWhitespace(str))
ds@830
   515
	{
ds@830
   516
		str++;
ds@830
   517
	}
ds@830
   518
ds@830
   519
	size_t bytes;
ds@830
   520
	pContext->StringToLocalUTF8(params[1], chars + 1, str, &bytes);
ds@830
   521
ds@830
   522
	return bytes;
ds@830
   523
}
ds@830
   524
dvander@834
   525
static cell_t SplitString(IPluginContext *pContext, const cell_t *params)
dvander@834
   526
{
dvander@834
   527
	char *text, *split;
dvander@834
   528
	
dvander@834
   529
	pContext->LocalToString(params[1], &text);
dvander@834
   530
	pContext->LocalToString(params[2], &split);
dvander@834
   531
dvander@834
   532
	size_t maxLen = (size_t)params[4];
dvander@834
   533
	size_t textLen = strlen(text);
dvander@834
   534
	size_t splitLen = strlen(split);
dvander@834
   535
dvander@834
   536
	if (splitLen > textLen)
dvander@834
   537
	{
dvander@834
   538
		return -1;
dvander@834
   539
	}
dvander@834
   540
dvander@834
   541
	for (size_t i=0; i<textLen - splitLen; i++)
dvander@834
   542
	{
dvander@834
   543
		if (strncmp(&text[i], split, splitLen) == 0)
dvander@834
   544
		{
dvander@834
   545
			/* Split hereeeee */
dvander@834
   546
			if (i >= maxLen)
dvander@834
   547
			{
dvander@834
   548
				pContext->StringToLocalUTF8(params[3], maxLen, text, NULL);
dvander@834
   549
			} else {
dvander@834
   550
				pContext->StringToLocalUTF8(params[3], i+1, text, NULL);
dvander@834
   551
			}
dvander@834
   552
			return (cell_t)(i + splitLen);
dvander@834
   553
		}
dvander@834
   554
	}
dvander@834
   555
dvander@834
   556
	return -1;
dvander@834
   557
}
dvander@834
   558
dvander@631
   559
REGISTER_NATIVES(basicStrings)
dvander@233
   560
{
dvander@833
   561
	{"BreakString",			BreakString},
dvander@833
   562
	{"FloatToString",		sm_floattostr},
dvander@833
   563
	{"Format",				sm_format},
dvander@833
   564
	{"FormatEx",			sm_formatex},
dvander@748
   565
	{"GetCharBytes",		GetCharBytes},
dvander@748
   566
	{"IntToString",			sm_numtostr},
dvander@748
   567
	{"IsCharAlpha",			IsCharAlpha},
dvander@748
   568
	{"IsCharLower",			IsCharLower},
dvander@748
   569
	{"IsCharMB",			IsCharMB},
dvander@748
   570
	{"IsCharNumeric",		IsCharNumeric},
dvander@748
   571
	{"IsCharSpace",			IsCharSpace},
dvander@748
   572
	{"IsCharUpper",			IsCharUpper},
dvander@833
   573
	{"ReplaceString",		ReplaceString},
dvander@833
   574
	{"ReplaceStringEx",		ReplaceStringEx},
dvander@834
   575
	{"SplitString",			SplitString},
dvander@233
   576
	{"strlen",				sm_strlen},
ds@830
   577
	{"StrBreak",			BreakString},		/* Backwards compat shim */
dvander@233
   578
	{"StrContains",			sm_contain},
dvander@681
   579
	{"strcmp",				sm_strcmp},
dvander@681
   580
	{"StrCompare",			sm_strcmp},			/* Backwards compat shim */
dvander@681
   581
	{"strncmp",				sm_strncmp},
dvander@681
   582
	{"strcopy",				sm_strcopy},
dvander@681
   583
	{"StrCopy",				sm_strcopy},		/* Backwards compat shim */
dvander@233
   584
	{"StringToInt",			sm_strconvint},
dvander@1072
   585
	{"StringToIntEx",		StringToIntEx},
dvander@233
   586
	{"StringToFloat",		sm_strtofloat},
dvander@1072
   587
	{"StringToFloatEx",		StringToFloatEx},
dvander@833
   588
	{"TrimString",			TrimString},
dvander@411
   589
	{"VFormat",				sm_vformat},
dvander@233
   590
	{NULL,					NULL},
dvander@233
   591
};