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