Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions core/logic/smn_string.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,25 @@ static cell_t StringToInt64(IPluginContext *pCtx, const cell_t *params)
return dummy - str;
}

static cell_t StringToI64(IPluginContext *pCtx, const cell_t *params)
{
cell_t* out;
if (int err = pCtx->LocalToPhysAddr(params[1], &out); err != SP_ERROR_NONE)
return pCtx->ThrowNativeErrorEx(err, "Could not read argument (error %d)", err);

char *str, *dummy = nullptr;
if (int err = pCtx->LocalToString(params[2], &str); err != SP_ERROR_NONE)
return pCtx->ThrowNativeErrorEx(err, "Invalid str (error %d)", err);

cell_t *consumed;
if (int err = pCtx->LocalToPhysAddr(params[4], &consumed); err != SP_ERROR_NONE)
return pCtx->ThrowNativeErrorEx(err, "Invalid nConsumed (error %d)", err);

*reinterpret_cast<int64_t*>(out) = strtoll(str, &dummy, params[3]);
*consumed = dummy - str;
return 0;
}

static cell_t sm_numtostr(IPluginContext *pCtx, const cell_t *params)
{
char *str;
Expand Down Expand Up @@ -636,6 +655,7 @@ REGISTER_NATIVES(basicStrings)
{"StringToInt", sm_strconvint},
{"StringToIntEx", StringToIntEx},
{"StringToInt64", StringToInt64},
{"StringToI64", StringToI64},
{"StringToFloat", sm_strtofloat},
{"StringToFloatEx", StringToFloatEx},
{"StripQuotes", StripQuotes},
Expand Down
18 changes: 18 additions & 0 deletions plugins/include/string.inc
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ native int StringToIntEx(const char[] str, int &result, int nBase=10);
/**
* Converts a string to a 64-bit integer.
*
* @note If the value is outside the range of representable values,
* If the value is positive, this function will return INT64_MAX.
* If the value is negative, this function will return INT64_MIN.
*
* @param str String to convert.
* @param result Array to store the upper and lower
* 32-bits of the 64-bit integer.
Expand All @@ -212,6 +216,20 @@ native int StringToIntEx(const char[] str, int &result, int nBase=10);
*/
native int StringToInt64(const char[] str, int result[2], int nBase=10);

/**
* Converts a string to an int64 type value.
*
* @note If the value is outside the range of representable values,
* If the value is positive, this function will return INT64_MAX.
* If the value is negative, this function will return INT64_MIN.
*
* @param str String to convert.
* @param nBase Numerical base to use. 10 is default.
* @param nConsumed Number of characters consumed.
* @return int64 conversion of string, or 0 on failure.
*/
native int64 StringToI64(const char[] str, int nBase=10, int &nConsumed=0);

/**
* Converts an integer to a string.
*
Expand Down
14 changes: 14 additions & 0 deletions plugins/include/testing.inc
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,17 @@ stock void AssertStrArrayEq(const char[] text, const char[][] value, const char[
}
PrintToServer("[%d] %s: '%s' arrays are equal OK", TestNumber, TestContext, text);
}

stock void AssertInt64Eq(const char[] text, int64 value, int64 expected)
{
TestNumber++;
if (value == expected)
{
PrintToServer("[%d] %s: %s == %ld OK", TestNumber, TestContext, text, expected);
}
else
{
PrintToServer("[%d] %s FAIL: %s should be %ld, got %ld", TestNumber, TestContext, text, expected, value);
ThrowError("test %d (%s in %s) failed", TestNumber, text, TestContext);
}
}
144 changes: 144 additions & 0 deletions plugins/testsuite/mock/test_string.sp
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
#pragma semicolon 1
#pragma newdecls required

#include <sourcemod>
#include <testing>


public void OnPluginStart()
{
Test_StringToI64();
}


void Test_StringToI64()
{
SetTestContext("Test StringToI64");

AssertInt64Eq("DEC 0", StringToI64("0"), 0);
AssertInt64Eq("DEC 1234567", StringToI64("1234567"), 1234567);
AssertInt64Eq("DEC 1234567654321", StringToI64("1234567654321"), 1234567654321);
AssertInt64Eq("DEC 9223372036854775807", StringToI64("9223372036854775807"), 9223372036854775807);
AssertInt64Eq("DEC -1234567", StringToI64("-1234567"), -1234567);
AssertInt64Eq("DEC -1234567654321", StringToI64("-1234567654321"), -1234567654321);
AssertInt64Eq("DEC -9223372036854775807", StringToI64("-9223372036854775807"), -9223372036854775807);

int nConsumed;

// nConsumed
AssertInt64Eq(
"result 0",
StringToI64("0", .nConsumed=nConsumed),
0);
AssertEq("nConsumed 0", nConsumed, 1);

AssertInt64Eq(
"result 1234567",
StringToI64("1234567", .nConsumed=nConsumed),
1234567);
AssertEq("nConsumed 1234567", nConsumed, 7);

AssertInt64Eq(
"result 1234567654321",
StringToI64("1234567654321", .nConsumed=nConsumed),
1234567654321);
AssertEq("nConsumed 1234567654321", nConsumed, 13);

AssertInt64Eq(
"result 9223372036854775807",
StringToI64("9223372036854775807", .nConsumed=nConsumed),
9223372036854775807);
AssertEq("nConsumed 9223372036854775807", nConsumed, 19);

AssertInt64Eq(
"result -1234567",
StringToI64("-1234567", .nConsumed=nConsumed),
-1234567);
AssertEq("nConsumed -1234567", nConsumed, 8);

AssertInt64Eq(
"result -1234567654321",
StringToI64("-1234567654321", .nConsumed=nConsumed),
-1234567654321);
AssertEq("nConsumed -1234567654321", nConsumed, 14);

AssertInt64Eq(
"result -9223372036854775807",
StringToI64("-9223372036854775807", .nConsumed=nConsumed),
-9223372036854775807);
AssertEq("nConsumed -9223372036854775807", nConsumed, 20);

// Special nBase
AssertInt64Eq(
"result 10001111101110001111101110110101110110001",
StringToI64("10001111101110001111101110110101110110001", 2, nConsumed),
1234567654321);
AssertEq("nConsumed 10001111101110001111101110110101110110001", nConsumed, 41);

AssertInt64Eq(
"result 21756175665661",
StringToI64("21756175665661", 8, nConsumed),
1234567654321);
AssertEq("nConsumed 21756175665661", nConsumed, 14);

AssertInt64Eq(
"result 11F71F76BB1",
StringToI64("11F71F76BB1", 16, nConsumed),
1234567654321);
AssertEq("nConsumed 11F71F76BB1", nConsumed, 11);

// Other
AssertInt64Eq(
"result a1b2c3d4e5f6g7",
StringToI64("a1b2c3d4e5f6g7", .nConsumed=nConsumed),
0);
AssertEq("nConsumed a1b2c3d4e5f6g7", nConsumed, 0);

AssertInt64Eq(
"result 0b10101",
StringToI64("0b10101", .nConsumed=nConsumed),
0);
AssertEq("nConsumed 0b10101", nConsumed, 1);

AssertInt64Eq(
"result 1_234_567",
StringToI64("1_234_567", .nConsumed=nConsumed),
1);
AssertEq("nConsumed 1_234_567", nConsumed, 1);

AssertInt64Eq(
"result 9223372036854775807",
StringToI64("9223372036854775807", .nConsumed=nConsumed),
9223372036854775807);
AssertEq("nConsumed 9223372036854775807", nConsumed, 19);

AssertInt64Eq(
"result 9223372036854775808",
StringToI64("9223372036854775807", .nConsumed=nConsumed),
9223372036854775807);
AssertEq("nConsumed 9223372036854775808", nConsumed, 19);

AssertInt64Eq(
"result 92233720368547758070",
StringToI64("9223372036854775807", .nConsumed=nConsumed),
9223372036854775807);
AssertEq("nConsumed 92233720368547758070", nConsumed, 19);

AssertInt64Eq(
"result -9223372036854775808",
StringToI64("-9223372036854775808", .nConsumed=nConsumed),
-9223372036854775807-1);
AssertEq("nConsumed -9223372036854775808", nConsumed, 20);

AssertInt64Eq(
"result -9223372036854775809",
StringToI64("-9223372036854775808", .nConsumed=nConsumed),
-9223372036854775807-1);
AssertEq("nConsumed -9223372036854775809", nConsumed, 20);

AssertInt64Eq(
"result -92233720368547758080",
StringToI64("-9223372036854775808", .nConsumed=nConsumed),
-9223372036854775807-1);
AssertEq("nConsumed -92233720368547758080", nConsumed, 20);
}
Loading