Add new variants of strbreak, which is too broken to use.

This commit is contained in:
David Anderson
2014-02-09 23:40:45 -08:00
parent 4125796569
commit aa46469878
4 changed files with 460 additions and 24 deletions

View File

@ -1,3 +1,4 @@
// vim: set ts=4 sw=4 tw=99 sts=4 noet ft=c:
/* Strings manipulation
*
* by the AMX Mod X Development Team
@ -223,16 +224,6 @@ native strtok(const text[], Left[], leftLen, Right[], rightLen, token=' ', trimS
*/
native strtok2(const text[], left[], const llen, right[], const rlen, const token = ' ', const trim = 0);
/* Gets parameters from text one at a time
It breaks a string into the first parameter and the rest of the parameters
(A left side and right side of the string)
Example: to split text: "^"This is^" the best year",
strbreak(text, arg1, len1, arg2, len2)
arg1="This is", arg2=the best year
This is more useful than parse() because you can keep breaking
any number of arguments */
native strbreak(const text[], Left[], leftLen, Right[], rightLen);
/* Strips spaces from the beginning and end of a string. */
native trim(text[]);
@ -277,6 +268,58 @@ stock bool:is_str_num(const sString[])
return sString[i] == 0 && i != 0;
}
// Warning: this function is deprecated as it does not work properly. Use
// argparse() or argbreak().
native strbreak(const text[], Left[], leftLen, Right[], rightLen);
/**
* Parses an argument string to find the first argument. You can use this to
* replace strbreak().
*
* You can use argparse() to break a string into all of its arguments:
* new arg[N], pos;
* while (true) {
* pos = argparse(string, pos, arg, sizeof(arg) - 1);
* if (pos == -1)
* break;
* }
*
* All initial whitespace is removed. Remaining characters are read until an
* argument separator is encountered. A separator is any whitespace not inside
* a double-quotation pair (i.e. "x b" is one argument). If only one quotation
* mark appears, argparse() acts as if one existed at the end of the string.
* Quotation marks are never written back, and do not act as separators. For
* example, "a""b""c" will return "abc". An empty quote pair ("") will count
* as an argument containing no characters.
*
* argparse() will write an empty string to argbuffer if no argument is found.
*
* @param text String to tokenize.
* @param pos Position to start parsing from.
* @param argbuffer Buffer to store first argument.
* @param maxlen Size of the buffer.
* @return If no argument was found, -1 is returned. Otherwise,
* the index to the next position to parse from is
* returned. This might be the very end of the string.
*/
native argparse(const text[], pos, argbuffer[], maxlen);
/* Emulates strbreak() using argparse(). */
stock argbreak(const text[], left[], leftlen, right[], rightlen)
{
new pos = argparse(text, 0, left, leftlen);
if (pos == -1)
return -1;
new textlen = strlen(text);
while (pos < textlen && isspace(text[pos]))
pos++;
copy(right, rightlen, text[pos]);
return pos;
}
/* It is basically strbreak but you have a delimiter that is more than one character in length.
You pass the Input string, the Left output, the max length of the left output,
the right output , the max right length, and then the delimiter string.

View File

@ -0,0 +1,339 @@
// vim: set ts=4 sw=4 tw=99 sts=4 noet ft=c:
#include <amxmodx>
#include <amxmisc>
#pragma ctrlchar '\'
public plugin_init()
{
register_plugin("strbreak tests", "1.0", "BAILOPAN");
register_concmd("test_strbreak", "test_strbreak", 0, "admin");
register_concmd("test_argparse", "test_argparse", 0, "admin");
}
new TestCount = 0;
new FailCount = 0;
test_reset()
{
TestCount = 0;
FailCount = 0;
}
test_numequal(a, b)
{
TestCount++;
if (a == b) {
server_print("[%d] PASS /%d/ == /%d/", TestCount, a, b);
} else {
server_print("[%d] FAIL /%d/ == /%d/", TestCount, a, b);
FailCount++;
}
}
test_equal(a[], b[])
{
TestCount++;
if (equal(a, b)) {
server_print("[%d] PASS /%s/ == /%s/", TestCount, a, b);
} else {
server_print("[%d] FAIL /%s/ == /%s/", TestCount, a, b);
FailCount++;
}
}
public test_strbreak(id)
{
test_reset();
new left[8], right[8];
// Test sort of normal behavior for strbreak().
strbreak("a b c", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "a");
test_equal(right, "b c");
strbreak("a", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "a");
test_equal(right, "");
strbreak("a\"", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "a\"");
test_equal(right, "");
strbreak("\"a\" yy", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "a");
test_equal(right, "yy");
strbreak("\"a x", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "\"a x");
test_equal(right, "");
strbreak("a b c", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "a");
test_equal(right, "b c");
strbreak("\"a\" b c", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "a");
test_equal(right, "b c");
strbreak("a \"b c\"", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "a");
test_equal(right, "\"b c\"");
strbreak("a q\"b c\"", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "a");
test_equal(right, "q\"b c\"");
strbreak("q \"b c\"", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "q");
test_equal(right, "\"b c\"");
strbreak("q \"b c", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "q");
test_equal(right, "\"b c");
// strbreak() functionality starts degrading here, but we test this to
// preserve bug-for-bug compatibility.
strbreak("q\"b c\"", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "\"b c");
test_equal(right, "\"");
strbreak("\"a \"a \"b c", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "a \"");
test_equal(right, "\"b c");
strbreak("\"a \"a b c", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "a \"");
test_equal(right, "b c");
strbreak("\"a\"a b c", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "a\"");
test_equal(right, "b c");
strbreak("\"a\" x", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "a\"");
test_equal(right, "x");
strbreak("\"a\"", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "a");
test_equal(right, "\"");
strbreak("\"a\"b", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "\"a\"b");
test_equal(right, "");
strbreak("q\" b c", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "q\" b c");
test_equal(right, "");
// Test truncation.
strbreak("123456789A 123456789ABCDE", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "1234567");
test_equal(right, "1234567");
strbreak("12345 123456789ABCDE", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "12345");
test_equal(right, "1234567");
strbreak("\"12345\" 123456789ABCDE", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "12345");
test_equal(right, "1234567");
strbreak("\"123456789A\" 123456789ABCDE", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "1234567");
test_equal(right, "1234567");
strbreak("\"123456789A\" 1234", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "1234567");
test_equal(right, "1234");
strbreak("\"123456789A\" 1234", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "1234567");
test_equal(right, "1234");
strbreak("123456789A 1234", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "1234567");
test_equal(right, "1234");
strbreak("123456789A 123456778923", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "1234567");
test_equal(right, "1234567");
// Bonkers - left-hand makes no sense. Does whitespace count toward the buffer?!
strbreak(" 123456789A 123456778923", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "12345");
test_equal(right, "1234567");
strbreak(" \"123456789A\" 1234", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "");
test_equal(right, "1234");
strbreak(" \"123456789A\" 1234", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "12");
test_equal(right, "1234");
new text_cmd[7], cheater[64];
strbreak(" a ", text_cmd, 1, cheater, 31);
test_equal(text_cmd, "");
test_equal(cheater, "");
server_print("%d/%d passed", TestCount - FailCount, TestCount);
}
public test_argparse(id)
{
test_reset();
new left[8], right[8];
// Tests for behavior that we expect to work.
argbreak("a b c", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "a");
test_equal(right, "b c");
argbreak("a", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "a");
test_equal(right, "");
argbreak("a\"", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "a");
test_equal(right, "");
argbreak("\"a\" yy", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "a");
test_equal(right, "yy");
argbreak("\"a x", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "a x");
test_equal(right, "");
argbreak("a b c", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "a");
test_equal(right, "b c");
argbreak("\"a\" b c", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "a");
test_equal(right, "b c");
argbreak("a \"b c\"", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "a");
test_equal(right, "\"b c\"");
argbreak("a q\"b c\"", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "a");
test_equal(right, "q\"b c\"");
argbreak("q \"b c\"", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "q");
test_equal(right, "\"b c\"");
argbreak("q \"b c", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "q");
test_equal(right, "\"b c");
argbreak("q\"b c\"", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "qb c");
test_equal(right, "");
argbreak("\"a \"a \"b c", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "a a");
test_equal(right, "\"b c");
argbreak("\"a \"a b c", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "a a");
test_equal(right, "b c");
argbreak("\"a\"a b c", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "aa");
test_equal(right, "b c");
argbreak("\"a\" x", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "a");
test_equal(right, "x");
argbreak("\"a\"", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "a");
test_equal(right, "");
argbreak("\"a\"b", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "ab");
test_equal(right, "");
argbreak("q\" b c", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "q b c");
test_equal(right, "");
// Test truncation.
argbreak("123456789A 123456789ABCDE", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "1234567");
test_equal(right, "1234567");
argbreak("12345 123456789ABCDE", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "12345");
test_equal(right, "1234567");
argbreak("\"12345\" 123456789ABCDE", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "12345");
test_equal(right, "1234567");
argbreak("\"123456789A\" 123456789ABCDE", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "1234567");
test_equal(right, "1234567");
argbreak("\"123456789A\" 1234", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "1234567");
test_equal(right, "1234");
argbreak("\"123456789A\" 1234", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "1234567");
test_equal(right, "1234");
argbreak("123456789A 1234", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "1234567");
test_equal(right, "1234");
argbreak("123456789A 123456778923", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "1234567");
test_equal(right, "1234567");
argbreak(" 123456789A 123456778923", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "1234567");
test_equal(right, "1234567");
argbreak(" \"123456789A\" 1234", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "1234567");
test_equal(right, "1234");
argbreak(" \"123456789A\" 1234", left, sizeof(left) - 1, right, sizeof(right) - 1);
test_equal(left, "1234567");
test_equal(right, "1234");
new text_cmd[7], cheater[64];
argbreak(" a ", text_cmd, 1, cheater, 31);
test_equal(text_cmd, "a");
test_equal(cheater, "");
// Test no-finds.
new pos = argparse(" \t\n \t", 0, left, sizeof(left));
test_numequal(pos, -1);
test_equal(left, "");
// Loop for good measure.
new argv[4][10], argc = 0;
new text[] = "a \"b\" cd\"e\" \t f\" ";
pos = 0;
while (argc < 4) {
pos = argparse(text, pos, argv[argc++], 10 - 1);
if (pos == -1)
break;
}
test_numequal(argc, 4);
test_equal(argv[0], "a");
test_equal(argv[1], "b");
test_equal(argv[2], "cde");
test_equal(argv[3], "f ");
server_print("%d/%d passed", TestCount - FailCount, TestCount);
}