1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2025-01-19 12:07:13 +01:00

Adjust the string explode and implode utilities.

This commit is contained in:
Sandu Liviu Catalin 2016-07-09 14:12:51 +03:00
parent bba09395d0
commit 862c09150f

View File

@ -1060,13 +1060,57 @@ static bool OnlyDelimiter(CSStr str, SQChar chr)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static Array StrExplode(CSStr str, SQChar chr, bool empty) static SQInteger SqStrExplode(HSQUIRRELVM vm)
{ {
const Int32 top = sq_gettop(vm);
// Was the delimiter character specified?
if (top <= 1)
{
return sq_throwerror(vm, _SC("Missing delimiter character"));
}
// Was the boolean empty specified?
else if (top <= 2)
{
return sq_throwerror(vm, _SC("Missing boolean empty"));
}
// Was the string value specified?
else if (top <= 3)
{
return sq_throwerror(vm, _SC("Missing string value"));
}
// Attempt to generate the string value
StackStrF val(vm, 4);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.mRes))
{
return val.mRes; // Propagate the error!
}
// The delimiter character and boolean empty
SQChar delim = 0;
bool empty = 0;
// Attempt to retrieve the remaining arguments from the stack
try
{
delim = Var< SQChar >(vm, 2).value;
empty = Var< bool >(vm, 3).value;
}
catch (const Sqrat::Exception & e)
{
return sq_throwerror(vm, e.Message().c_str());
}
catch (...)
{
return sq_throwerror(vm, _SC("Unable to retrieve arguments"));
}
// Grab the string value to a shorter name
CSStr str = val.mPtr;
// Create an empty array on the stack
sq_newarray(vm, 0);
// See if we actually have something to explode // See if we actually have something to explode
if(!str || *str == '\0') if(!str || *str == '\0')
{ {
// Default to an empty array // Specify that we have an argument on the stack
return Array(DefaultVM::Get(), 0); return 1;
} }
// Don't modify the specified string pointer // Don't modify the specified string pointer
CSStr itr = str, last = str; CSStr itr = str, last = str;
@ -1076,7 +1120,7 @@ static Array StrExplode(CSStr str, SQChar chr, bool empty)
while (*itr != '\0') while (*itr != '\0')
{ {
// Is this our delimiter? // Is this our delimiter?
if (*(itr++) == chr) if (*(itr++) == delim)
{ {
// Are we allowed to include empty elements? // Are we allowed to include empty elements?
if (empty || (itr - last) > 1) if (empty || (itr - last) > 1)
@ -1089,39 +1133,46 @@ static Array StrExplode(CSStr str, SQChar chr, bool empty)
} }
} }
// Were there no delimiters found and can we include empty elements? // Were there no delimiters found and can we include empty elements?
if (num == 0 && !empty && (str[1] == '\0' || OnlyDelimiter(str, chr))) if (num == 0 && !empty && (str[1] == '\0' || OnlyDelimiter(str, delim)))
{ {
// Default to an empty array // Specify that we have an argument on the stack
return Array(DefaultVM::Get(), 0); return 1;
} }
// Have we found any delimiters? // Have we found any delimiters?
else if (num == 0) else if (num == 0)
{ {
// Create an array with just one element
Array arr(DefaultVM::Get(), 1);
// Test against strings with only delimiters // Test against strings with only delimiters
if (str[1] == '\0' || OnlyDelimiter(str, chr)) if (str[1] == '\0' || OnlyDelimiter(str, delim))
{ {
arr.SetValue(0, _SC("")); // Add an empty string sq_pushstring(vm, _SC(""), 0); // Add an empty string
} }
else else
{ {
arr.SetValue(0, str); // Add the whole string sq_pushstring(vm, val.mPtr, val.mLen); // Add the whole string
} }
// Return the resulted array // Append the string on the stack to the array
return arr; const SQRESULT r = sq_arrayappend(vm, -2);
// Check the result
if (SQ_FAILED(r))
{
return r; // Propagate the error
}
// Specify that we have an argument on the stack
return 1;
} }
// Is there anything after the last delimiter? // Is there anything after the last delimiter?
if (itr != last && *last != chr) if (itr != last && *last != delim)
{ {
++num; // Add it to the counter ++num; // Add it to the counter
} }
SQRESULT r = SQ_OK;
// Pre-allocate an array with the number of found delimiters // Pre-allocate an array with the number of found delimiters
Array arr(DefaultVM::Get(), num); r = sq_arrayresize(vm, -1, num);
// Remember the initial stack size // Check the result
StackGuard sg; if (SQ_FAILED(r))
// Push the array object on the stack {
sq_pushobject(DefaultVM::Get(), arr.GetObject()); return r; // Propagate the error
}
// Don't modify the specified string pointer // Don't modify the specified string pointer
itr = str, last = str; itr = str, last = str;
// Reset the counter and use it as the element index // Reset the counter and use it as the element index
@ -1130,38 +1181,48 @@ static Array StrExplode(CSStr str, SQChar chr, bool empty)
while (*itr != '\0') while (*itr != '\0')
{ {
// Is this our delimiter? // Is this our delimiter?
if (*itr++ == chr) if (*itr++ == delim)
{ {
// Are we allowed to include empty elements? // Are we allowed to include empty elements?
if (empty || (itr - last) > 1) if (empty || (itr - last) > 1)
{ {
// Push the element index on the stack and advance to the next one // Push the element index on the stack and advance to the next one
sq_pushinteger(DefaultVM::Get(), num++); sq_pushinteger(vm, num++);
// Push the string portion on the stack // Push the string portion on the stack
sq_pushstring(DefaultVM::Get(), last, itr - last - 1); sq_pushstring(vm, last, itr - last - 1);
// Assign the string onto the // Assign the string onto the
sq_set(DefaultVM::Get(), -3); r = sq_set(vm, -3);
// Check the result
if (SQ_FAILED(r))
{
return r; // Propagate the error
}
} }
// Update the last delimiter position // Update the last delimiter position
last = itr; last = itr;
} }
} }
// Is there anything after the last delimiter? // Is there anything after the last delimiter?
if (itr != last && *last != chr) if (itr != last && *last != delim)
{ {
// Push the element index on the stack // Push the element index on the stack
sq_pushinteger(DefaultVM::Get(), num); sq_pushinteger(vm, num);
// Add the remaining string as an element // Add the remaining string as an element
sq_pushstring(DefaultVM::Get(), last, itr - last); sq_pushstring(vm, last, itr - last);
// Assign the string onto the // Assign the string onto the
sq_set(DefaultVM::Get(), -3); r = sq_set(vm, -3);
// Check the result
if (SQ_FAILED(r))
{
return r; // Propagate the error
}
} }
// Return the resulted array and let the stack guard handle the cleanup // Specify that we have an argument on the stack
return arr; return 1;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static CSStr StrImplode(Array & arr, SQChar chr) static CSStr StrImplode(SQChar chr, Array & arr)
{ {
// Determine array size // Determine array size
const Int32 length = static_cast< Int32 >(arr.Length()); const Int32 length = static_cast< Int32 >(arr.Length());
@ -1236,7 +1297,7 @@ void Register_String(HSQUIRRELVM vm)
Table strns(vm); Table strns(vm);
strns.Func(_SC("FromArray"), &FromArray) strns.Func(_SC("FromArray"), &FromArray)
.Func(_SC("Explode"), &StrExplode) .SquirrelFunc(_SC("Explode"), &SqStrExplode)
.Func(_SC("Implode"), &StrImplode) .Func(_SC("Implode"), &StrImplode)
.SquirrelFunc(_SC("Center"), &SqCenterStr) .SquirrelFunc(_SC("Center"), &SqCenterStr)
.SquirrelFunc(_SC("Left"), &SqLeftStr) .SquirrelFunc(_SC("Left"), &SqLeftStr)