Added new parameter parser. Not implemented or tested yet.
This commit is contained in:
parent
f9c953d58f
commit
50a7e5ab99
@ -49,6 +49,7 @@
|
||||
#include "zr/menu"
|
||||
#include "zr/cookies"
|
||||
#include "zr/paramtools"
|
||||
#include "zr/paramparser"
|
||||
#include "zr/models"
|
||||
#include "zr/downloads"
|
||||
#include "zr/overlays"
|
||||
|
531
src/zr/paramparser.inc
Normal file
531
src/zr/paramparser.inc
Normal file
@ -0,0 +1,531 @@
|
||||
/*
|
||||
* ============================================================================
|
||||
*
|
||||
* Zombie:Reloaded
|
||||
*
|
||||
* File: paramparser.inc
|
||||
* Type: Core
|
||||
* Description: Provides functions for parsing single line strings with
|
||||
* flags, and parameters in key=value format.
|
||||
*
|
||||
* Supports quoted strings and escaped characters like "\n"
|
||||
* and "\t".
|
||||
*
|
||||
* Examle raw string:
|
||||
* "type=interval -disabled msg="Title:\n\"Example\"."
|
||||
*
|
||||
* Copyright (C) 2009 Greyscale, Richard Helgeby
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* @section Limit settings.
|
||||
*/
|
||||
#define PARAM_NAME_MAXLEN 64 /** Maximum length of key name or flag name. */
|
||||
#define PARAM_VALUE_MAXLEN 256 /** Maximum length of value string. */
|
||||
/**
|
||||
* @endsection
|
||||
*/
|
||||
|
||||
/**
|
||||
* @section Parsing error codes.
|
||||
*/
|
||||
#define PARAM_ERROR_EMPTY 1 /** Source string is empty. */
|
||||
#define PARAM_ERROR_FULL 2 /** Destination array is full. */
|
||||
#define PARAM_ERROR_UNEXPECTED_KEY 3 /** Unexpected key name. Could not find a equation sign (=) after previous key name. */
|
||||
#define PARAM_ERROR_UNEXPECTED_END 4 /** Unexpected end of source string. */
|
||||
#define PARAM_ERROR_MISSING_QUOTE 5 /** Unexpected end of source string. Missing end quote character. */
|
||||
#define PARAM_ERROR_UNKNOWN 6 /** Unknown error. The parser got a invalid result from a search function it couldn't handle. */
|
||||
/**
|
||||
* @endsection
|
||||
*/
|
||||
|
||||
/**
|
||||
* Modes for what to do and expect when parsing. White space characters between
|
||||
* modes are ignored.
|
||||
*/
|
||||
enum ParamModes
|
||||
{
|
||||
ParamMode_TypeCheck, /** Check if it's a flag or a key. */
|
||||
ParamMode_Flag, /** Expect a flag name (starts with "-"). */
|
||||
ParamMode_Key, /** Expect a key name. */
|
||||
ParamMode_Equal, /** Expect a equation sign. */
|
||||
ParamMode_Value /** Expect a value string. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Structure for storing a key/value pair.
|
||||
*/
|
||||
enum ParamParseResult
|
||||
{
|
||||
bool:Param_IsFlag, /** Specifies whether it's a flag or not. */
|
||||
String:Param_Name[PARAM_NAME_MAXLEN], /** Key or flag name. */
|
||||
String:Param_Value[PARAM_VALUE_MAXLEN] /** Value. Only used if a key. */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**************************************
|
||||
* *
|
||||
* PARAMETER FUNCTIONS *
|
||||
* *
|
||||
**************************************/
|
||||
|
||||
/**
|
||||
* Parses a parameter string in "key=value" format and store the result in a
|
||||
* ParamParseResult array.
|
||||
*
|
||||
* @param buffer A ParamParseResult array to store results.
|
||||
* @param maxlen Maximum number of keys that can be stored (first
|
||||
* dimension of buffer).
|
||||
* @param paramString The source string to parse. String is trimmed before
|
||||
* parsing.
|
||||
* @param err Opional output: Error code if parsing error.
|
||||
* @param errPos Opional output: Position in paramString where the error
|
||||
* occoured.
|
||||
* @return Number of keys parsed.
|
||||
*/
|
||||
stock ParamParseString(buffer[][ParamParseResult], maxlen, String:paramString[], &err = 0, &errPos = -1)
|
||||
{
|
||||
/*
|
||||
* VALIDATION OF INPUT AND BUFFERS
|
||||
*/
|
||||
|
||||
// Trim raw string.
|
||||
TrimString(paramString);
|
||||
|
||||
// Check if raw string is empty.
|
||||
if (strlen(paramString) == 0)
|
||||
{
|
||||
err = PARAM_ERROR_EMPTY;
|
||||
errPos = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Validate specified length of destination buffer.
|
||||
if (maxlen == 0)
|
||||
{
|
||||
err = PARAM_ERROR_FULL;
|
||||
errPos = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* PARSE LOOP
|
||||
*/
|
||||
|
||||
// Get raw string length.
|
||||
new rawlen = sizeof(paramString);
|
||||
|
||||
// Initialize. Expect the start to be a key or a flag.
|
||||
new ParamModes:mode = ParamMode_TypeCheck;
|
||||
|
||||
// Counter for number of parameters parsed.
|
||||
new paramcount;
|
||||
|
||||
// Buffers for temp values.
|
||||
new startpos;
|
||||
new endpos;
|
||||
new bool:quoteon;
|
||||
decl String:value[PARAM_VALUE_MAXLEN];
|
||||
|
||||
// Loop through all characters in the string. Exclude null terminator.
|
||||
for (new strpos = 0; strpos < rawlen - 1; strpos++)
|
||||
{
|
||||
// Check if there's space left in the destination buffer.
|
||||
if (paramcount > maxlen)
|
||||
{
|
||||
// Exit loop. No more parameters can be parsed.
|
||||
err = PARAM_ERROR_FULL;
|
||||
errPos = strpos;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* MODE CHECK
|
||||
*/
|
||||
|
||||
// Check mode for deciding what to do.
|
||||
switch (mode)
|
||||
{
|
||||
case ParamMode_TypeCheck:
|
||||
{
|
||||
// Find start position of first non white space character.
|
||||
startpos = ParamFindStartPos(paramString, strpos);
|
||||
|
||||
// Check if it's a flag type.
|
||||
if (paramString[startpos] == '-')
|
||||
{
|
||||
// It's a flag, change mode.
|
||||
mode = ParamMode_Flag;
|
||||
|
||||
// Update current position.
|
||||
strpos = startpos;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Expect a key name.
|
||||
mode = ParamMode_Key;
|
||||
|
||||
// Update current position. Substract by one to include
|
||||
// the current character in next mode.
|
||||
strpos = startpos - 1;
|
||||
}
|
||||
}
|
||||
case ParamMode_Flag:
|
||||
{
|
||||
// Find stop position (last non white space character).
|
||||
endpos = ParamFindEndPos(paramString, strpos);
|
||||
|
||||
// Extract key name.
|
||||
StrExtract(value, sizeof(value), paramString, strpos, endpos);
|
||||
|
||||
// Copy flag to destination buffer.
|
||||
strcopy(buffer[paramcount][Param_Name], PARAM_NAME_MAXLEN, value);
|
||||
|
||||
// Set flag type.
|
||||
buffer[paramcount][Param_IsFlag] = true;
|
||||
|
||||
// Increment parameter counter.
|
||||
paramcount++;
|
||||
|
||||
// Set next parse mode.
|
||||
mode = ParamMode_TypeCheck;
|
||||
}
|
||||
case ParamMode_Key:
|
||||
{
|
||||
// Find stop position.
|
||||
endpos = ParamFindEndPos(paramString, strpos);
|
||||
|
||||
// Extract key name.
|
||||
StrExtract(value, sizeof(value), paramString, strpos, endpos);
|
||||
|
||||
// Copy key name to destination buffer.
|
||||
strcopy(buffer[paramcount][Param_Name], PARAM_NAME_MAXLEN, value);
|
||||
|
||||
// Make sure flag type is not set.
|
||||
buffer[paramcount][Param_IsFlag] = false;
|
||||
|
||||
// Note: Do not increment parameter counter until the
|
||||
// entire key/value pair is parsed.
|
||||
|
||||
// Set next parse mode. Expect a equation sign.
|
||||
mode = ParamMode_Equal;
|
||||
}
|
||||
case ParamMode_Equal:
|
||||
{
|
||||
// Find start position of first non white space character.
|
||||
startpos = ParamFindStartPos(paramString, strpos);
|
||||
|
||||
// Validate position.
|
||||
if (startpos >= 0)
|
||||
{
|
||||
// Check if it's a equation sign.
|
||||
if (paramString[startpos] == '=')
|
||||
{
|
||||
// Change mode to expect a value at next position.
|
||||
mode = ParamMode_Value;
|
||||
|
||||
// Update current position.
|
||||
strpos = startpos;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Parse error.
|
||||
err = PARAM_ERROR_UNEXPECTED_KEY;
|
||||
errPos = startpos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Parse error.
|
||||
err = PARAM_ERROR_UNEXPECTED_END;
|
||||
errPos = strpos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
case ParamMode_Value:
|
||||
{
|
||||
// Find start position of first non white space character.
|
||||
startpos = ParamFindStartPos(paramString, strpos);
|
||||
|
||||
// Validate start position.
|
||||
if (startpos >= 0)
|
||||
{
|
||||
// Reset quote and escape settings.
|
||||
quoteon = false;
|
||||
|
||||
// Loop through all characters starting from the current
|
||||
// position. Exclude null terminator.
|
||||
for (strpos = startpos; strpos < rawlen - 1; strpos++)
|
||||
{
|
||||
// Check if the current character is a special character.
|
||||
if (paramString[startpos] == '"')
|
||||
{
|
||||
// Toggle quote.
|
||||
quoteon = !quoteon;
|
||||
|
||||
// Check quote state.
|
||||
if (quoteon)
|
||||
{
|
||||
// Quote started, update start position.
|
||||
startpos = strpos + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Quote end, set end position.
|
||||
endpos = strpos - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if it's a white space character or end of the string.
|
||||
else if (!quoteon && (IsCharSpace(paramString[strpos]) || strpos == rawlen - 1))
|
||||
{
|
||||
// End of value reached. Save positions.
|
||||
endpos = strpos - 1;
|
||||
|
||||
// Exit loop.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if quote still haven't ended.
|
||||
if (quoteon)
|
||||
{
|
||||
// Parse error.
|
||||
err = PARAM_ERROR_MISSING_QUOTE;
|
||||
errPos = strpos;
|
||||
break;
|
||||
}
|
||||
|
||||
// Extract value string.
|
||||
StrExtract(value, sizeof(value), paramString, startpos, endpos);
|
||||
|
||||
// Unescape string (converting "\n" to newline, etc.).
|
||||
StrUnescape(value);
|
||||
|
||||
// Copy value string to destination buffer.
|
||||
strcopy(buffer[paramcount][Param_Value], PARAM_VALUE_MAXLEN, value);
|
||||
|
||||
// Make sure flag type is not set.
|
||||
buffer[paramcount][Param_IsFlag] = false;
|
||||
|
||||
// Increment parameter counter.
|
||||
paramcount++;
|
||||
|
||||
// Set next parse mode. Expect a key or a flag.
|
||||
mode = ParamMode_TypeCheck;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Parse error.
|
||||
err = PARAM_ERROR_UNEXPECTED_END;
|
||||
errPos = strpos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return number of parameters parsed.
|
||||
return paramcount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the first key index in a parameter array matching the specified key.
|
||||
*
|
||||
* @param params A ParamParseResult array to search through.
|
||||
* @param maxlen Size of parameter array (first dimension).
|
||||
* @param key Key to find.
|
||||
* @param caseSensitive Specifies whether the search is case sensitive or
|
||||
* not (default).
|
||||
* @return Index of the key if found, -1 otherwise.
|
||||
*/
|
||||
stock ParamFindKey(const params[][ParamParseResult], maxlen, const String:key[], bool:caseSensitive = false)
|
||||
{
|
||||
// Loop through all parameters.
|
||||
for (new index = 0; index < maxlen; index++)
|
||||
{
|
||||
// Check parameter type.
|
||||
if (params[index][Param_IsFlag])
|
||||
{
|
||||
// It's a flag type, skip index.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Match key name.
|
||||
if (StrEqual(params[index][Param_Name], key, caseSensitive))
|
||||
{
|
||||
// Key found, return the key index.
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified flag is set in a parameter array.
|
||||
*
|
||||
* @param params A ParamParseResult array to search through.
|
||||
* @param maxlen Size of parameter array (first dimension).
|
||||
* @param flag Flag to check.
|
||||
* @param caseSensitive Specifies whether the search is case sensitive or
|
||||
* not (default).
|
||||
* @return True flag is found, false otherwise.
|
||||
*/
|
||||
stock bool:ParamHasFlag(const params[][ParamParseResult], maxlen, const String:flag[], bool:caseSensitive = false)
|
||||
{
|
||||
// Loop through all parameters.
|
||||
for (new index = 0; index < maxlen; index++)
|
||||
{
|
||||
// Check parameter type.
|
||||
if (!params[index][Param_IsFlag])
|
||||
{
|
||||
// It's a key type, skip index.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Match flag name.
|
||||
if (StrEqual(params[index][Param_Name], flag, caseSensitive))
|
||||
{
|
||||
// Flag found.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**************************************
|
||||
* *
|
||||
* HELPER FUNCTIONS *
|
||||
* *
|
||||
**************************************/
|
||||
|
||||
/**
|
||||
* Finds the position of the last non white space character from a specified start position.
|
||||
*
|
||||
* @param paramString Raw string search in.
|
||||
* @param startPos Optional. Position to start searching from.
|
||||
* @return Position of the last non white space character, or -1
|
||||
* if failed.
|
||||
*/
|
||||
stock ParamFindEndPos(const String:paramString[], startPos = 0)
|
||||
{
|
||||
new rawlen = sizeof(paramString);
|
||||
|
||||
// Validate string length.
|
||||
if (rawlen == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Loop through all characters from the specified start position.
|
||||
for (new strpos = startPos; strpos < rawlen; strpos++)
|
||||
{
|
||||
// Check if white space or if current position is the last
|
||||
// character before the null terminator.
|
||||
if (IsCharSpace(paramString[strpos]) || strpos == rawlen - 1)
|
||||
{
|
||||
return strpos - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// It should never reach this place. Added to satisfy compiler.
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the first non white space character in a string, starting from the
|
||||
* specified position.
|
||||
*
|
||||
* @param paramString Raw string to search in.
|
||||
* @param startPos Optional. Position to start searching from.
|
||||
* @return Position of first character or -1 if failed.
|
||||
*/
|
||||
stock ParamFindStartPos(const String:paramString[], startPos = 0)
|
||||
{
|
||||
new rawlen = sizeof(paramString);
|
||||
|
||||
// Validate string length.
|
||||
if (rawlen == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Loop through all characters from the specified start position.
|
||||
for (new strpos = startPos; strpos < rawlen; strpos++)
|
||||
{
|
||||
// Check if not white space.
|
||||
if (!IsCharSpace(paramString[strpos]))
|
||||
{
|
||||
return strpos;
|
||||
}
|
||||
}
|
||||
|
||||
// No character found.
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts a area in a string between two positions.
|
||||
*
|
||||
* @param buffer Destination string buffer.
|
||||
* @param maxlen Size of destination buffer.
|
||||
* @param source Source string to extract from.
|
||||
* @param startpos Start position of string to extract.
|
||||
* @param endpos End position of string to extract.
|
||||
* @return Number of cells written.
|
||||
*/
|
||||
stock StrExtract(String:buffer[], maxlen, const String:source[], startpos, endpos)
|
||||
{
|
||||
new len;
|
||||
|
||||
// Calculate string length. Also add space for null terminator.
|
||||
len = endpos - startpos + 1;
|
||||
|
||||
// Validate length.
|
||||
if (len < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Extract string and store it in the buffer.
|
||||
return strcopy(buffer, len, source[startpos]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unescapes a string (replaces "\n" with newlines, etc.).
|
||||
*
|
||||
* @param str String to unescape.
|
||||
*/
|
||||
stock StrUnescape(String:str[])
|
||||
{
|
||||
new len = sizeof(str);
|
||||
|
||||
ReplaceString(str, len, "\\n", "\n");
|
||||
ReplaceString(str, len, "\\r", "\r");
|
||||
ReplaceString(str, len, "\\t", "\t");
|
||||
ReplaceString(str, len, "\\\"", "\"");
|
||||
ReplaceString(str, len, "\\\\", "\\");
|
||||
}
|
Loading…
Reference in New Issue
Block a user