| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- // Kustom
- #include "SDK/amx/amx.h"
- #include "sscanf.h"
- #include "utils.h"
- #include "data.h"
- #include "specifiers.h"
- #include <stdio.h>
- extern logprintf_t
- logprintf;
- extern int
- gOptions;
- bool
- DoK(AMX * amx, char ** defaults, char ** input, cell * cptr, bool optional)
- {
- // First, get the type of the array.
- char *
- type = GetMultiType(defaults);
- if (!type)
- {
- return false;
- }
- if (optional)
- {
- // Optional parameters - just collect the data for
- // now and use it later.
- char *
- opts = 0;
- if (**defaults == '(')
- {
- ++(*defaults);
- SkipWhitespace(defaults);
- // Got the start of the values.
- opts = *defaults;
- // Skip the defaults for now, we don't know the length yet.
- bool
- escape = false;
- while (**defaults && (escape || **defaults != ')'))
- {
- if (**defaults == '\\')
- {
- escape = !escape;
- }
- else
- {
- escape = false;
- }
- ++(*defaults);
- }
- if (**defaults)
- {
- if (opts == *defaults)
- {
- // No defaults found.
- logprintf("sscanf warning: Empty default values.");
- opts = 0;
- }
- // Found a valid end. Make it null for
- // later array getting (easy to detect a
- // null end and we'll never need to
- // backtrack to here in the specifiers).
- **defaults = '\0';
- ++(*defaults);
- }
- else
- {
- logprintf("sscanf warning: Unclosed default value.");
- }
- /*if (optional)
- {
- // Optional parameters are always separated by commans, not
- // whatever the coder may choose.
- TempDelimiter(",)");
- // We need to copy the old save value for optional parts. If
- // we don't and save gets set to false in the middle of the
- // enum then when the code is called for a second time for the
- // real values then save will already be false and they won't
- // get saved.
- switch (DoEnumValues(type, &opts, cptr, true))
- {
- case SSCANF_TRUE_RETURN:
- break;
- case SSCANF_CONT_RETURN:
- logprintf("sscanf error: Insufficient default values.");
- // FALLTHROUGH
- default:
- RestoreDelimiter();
- return false;
- }
- RestoreDelimiter();
- }*/
- }
- else
- {
- logprintf("sscanf warning: No default value found.");
- }
- if (!input || IsStringEnd(**input))
- {
- if (cptr)
- {
- if (opts)
- {
- if (gOptions & 16)
- {
- char
- func[32];
- int
- idx;
- sprintf(func, "sscanf_%s", type);
- if (amx_FindPublic(amx, func, &idx))
- {
- logprintf("sscanf warning: Could not find function SSCANF:%s.", type);
- }
- else
- {
- cell
- ret,
- addr;
- amx_PushString(amx, &addr, 0, opts, 0, 0);
- amx_Exec(amx, &ret, idx);
- amx_Release(amx, addr);
- *cptr = ret;
- return true;
- }
- }
- else
- {
- *cptr = (cell)GetNumber(&opts);
- return true;
- }
- }
- *cptr = 0;
- }
- return true;
- }
- }
- else if (!input || IsStringEnd(**input))
- {
- return false;
- }
- char
- func[32];
- int
- idx;
- sprintf(func, "sscanf_%s", type);
- if (amx_FindPublic(amx, func, &idx))
- {
- logprintf("sscanf warning: Could not find function SSCANF:%s.", type);
- }
- else
- {
- char
- * string = *input,
- * outp = string,
- * start = string;
- if (IsDefaultDelimiter())
- {
- while (!IsWhitespace(*string))
- {
- if (*string == '\\')
- {
- if (IsEnd(*(string + 1)))
- {
- ++string;
- break;
- }
- if (*(string + 1) == '\\' || IsWhitespace(*(string + 1)))
- {
- ++string;
- }
- }
- if (outp != string)
- {
- *outp = *string;
- }
- ++outp;
- ++string;
- }
- }
- else
- {
- // Just a single word. Note that if your delimiter is a backslash
- // you can't escape it - this is not a bug, just don't try use it as
- // a delimiter and still expect to be able to use it in a string. I
- // suppose that technically you could see this as a bug, but I
- // choose to call it an undesirable feature (no-one has complained).
- while (!IsEnd(*string) && !IsDelimiter(*string))
- {
- if (*string == '\\')
- {
- if (IsEnd(*(string + 1)))
- {
- ++string;
- break;
- }
- // Escape spaces, backspace and delimiters - this code
- // is context independent so you can use a string with
- // or without a delimiter and can still escape spaces.
- if (*(string + 1) == '\\' || IsSpacer(*(string + 1)))
- {
- ++string;
- }
- }
- if (outp != string)
- {
- *outp = *string;
- }
- ++outp;
- ++string;
- }
- }
- if (!IsEnd(*string))
- {
- // Skip the final character.
- *input = string + 1;
- }
- else
- {
- // Save the return.
- *input = string;
- }
- // Add a null terminator.
- *outp = '\0';
- cell
- ret,
- addr;
- amx_PushString(amx, &addr, 0, start, 0, 0);
- amx_Exec(amx, &ret, idx);
- amx_Release(amx, addr);
- if (cptr) *cptr = ret;
- }
- return true;
- }
|