renamed mm_api, I don't like short names!
finished and tested the INI parser and its API --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40150
This commit is contained in:
parent
13775b11b6
commit
f19fbac013
286
core/CTextParsers.cpp
Normal file
286
core/CTextParsers.cpp
Normal file
@ -0,0 +1,286 @@
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "CTextParsers.h"
|
||||
|
||||
CTextParsers g_TextParse;
|
||||
|
||||
static int g_ini_chartable1[255] = {0};
|
||||
|
||||
CTextParsers::CTextParsers()
|
||||
{
|
||||
g_ini_chartable1['_'] = 1;
|
||||
g_ini_chartable1['-'] = 1;
|
||||
g_ini_chartable1[','] = 1;
|
||||
g_ini_chartable1['+'] = 1;
|
||||
g_ini_chartable1['.'] = 1;
|
||||
g_ini_chartable1['$'] = 1;
|
||||
g_ini_chartable1['?'] = 1;
|
||||
g_ini_chartable1['/'] = 1;
|
||||
}
|
||||
|
||||
bool CTextParsers::ParseFile_SMC(const char *file, ITextListener_SMC *smc_listener, unsigned int *line, unsigned int *col)
|
||||
{
|
||||
/* :TODO: Implement this */
|
||||
if (line)
|
||||
{
|
||||
*line = 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CTextParsers::ParseFile_INI(const char *file, ITextListener_INI *ini_listener, unsigned int *line, unsigned int *col)
|
||||
{
|
||||
FILE *fp = fopen(file, "rt");
|
||||
unsigned int curline = 0;
|
||||
unsigned int curtok;
|
||||
size_t len;
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
if (line)
|
||||
{
|
||||
*line = 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
char buffer[2048];
|
||||
char *ptr, *save_ptr;
|
||||
bool in_quote;
|
||||
while (!feof(fp))
|
||||
{
|
||||
curline++;
|
||||
curtok = 0;
|
||||
buffer[0] = '\0';
|
||||
if (fgets(buffer, sizeof(buffer), fp) == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Preprocess the string before anything */
|
||||
ptr = buffer;
|
||||
|
||||
/* First strip beginning whitespace */
|
||||
while ((*ptr != '\0') && isspace(*ptr))
|
||||
{
|
||||
ptr++;
|
||||
}
|
||||
|
||||
len = strlen(ptr);
|
||||
|
||||
if (!len)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Now search for comment characters */
|
||||
in_quote = false;
|
||||
save_ptr = ptr;
|
||||
for (size_t i=0; i<len; i++,ptr++)
|
||||
{
|
||||
if (!in_quote)
|
||||
{
|
||||
switch (*ptr)
|
||||
{
|
||||
case '"':
|
||||
{
|
||||
in_quote = true;
|
||||
break;
|
||||
}
|
||||
case ';':
|
||||
{
|
||||
/* Stop the loop */
|
||||
len = i;
|
||||
/* Terminate the string here */
|
||||
*ptr = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (*ptr == '"')
|
||||
{
|
||||
in_quote = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!len)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ptr = save_ptr;
|
||||
|
||||
/* Lastly, strip ending whitespace off */
|
||||
for (size_t i=len-1; i>=0 && i<len; i--)
|
||||
{
|
||||
if (isspace(ptr[i]))
|
||||
{
|
||||
ptr[i] = '\0';
|
||||
len--;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!len)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ini_listener->ReadINI_RawLine(ptr, &curtok))
|
||||
{
|
||||
goto event_failed;
|
||||
}
|
||||
|
||||
if (*ptr == '[')
|
||||
{
|
||||
bool invalid_tokens = false;
|
||||
bool got_bracket = false;
|
||||
bool extra_tokens = false;
|
||||
char c;
|
||||
|
||||
for (size_t i=1; i<len; i++)
|
||||
{
|
||||
c = ptr[i];
|
||||
if (!isalnum(c) && !g_ini_chartable1[c])
|
||||
{
|
||||
/* First check - is this a bracket? */
|
||||
if (c == ']')
|
||||
{
|
||||
/* Yes! */
|
||||
got_bracket = true;
|
||||
/* If this isn't the last character... */
|
||||
if (i != len - 1)
|
||||
{
|
||||
extra_tokens = true;
|
||||
}
|
||||
/* terminate */
|
||||
ptr[i] = '\0';
|
||||
break;
|
||||
} else {
|
||||
/* n...No! Continue copying. */
|
||||
invalid_tokens = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Tell the handler */
|
||||
if (!ini_listener->ReadINI_NewSection(&ptr[1], invalid_tokens, got_bracket, extra_tokens, &curtok))
|
||||
{
|
||||
goto event_failed;
|
||||
}
|
||||
} else {
|
||||
char *key_ptr = ptr;
|
||||
char *val_ptr = NULL;
|
||||
char c;
|
||||
size_t first_space = 0;
|
||||
bool invalid_tokens = false;
|
||||
bool equal_token = false;
|
||||
bool quotes = false;
|
||||
|
||||
for (size_t i=0; i<len; i++)
|
||||
{
|
||||
c = ptr[i];
|
||||
/* is this an invalid char? */
|
||||
if (!isalnum(c) && !g_ini_chartable1[c])
|
||||
{
|
||||
if (isspace(c))
|
||||
{
|
||||
/* if it's a space, keep track of the last space */
|
||||
if (!first_space)
|
||||
{
|
||||
first_space = i;
|
||||
}
|
||||
} else {
|
||||
if (c == '=')
|
||||
{
|
||||
/* if it's an equal sign, we're done with the key */
|
||||
if (first_space)
|
||||
{
|
||||
/* remove excess whitespace */
|
||||
key_ptr[first_space] = '\0';
|
||||
} else {
|
||||
/* remove the equal sign */
|
||||
key_ptr[i] = '\0';
|
||||
}
|
||||
if (ptr[++i] != '\0')
|
||||
{
|
||||
/* If this isn't the end, set next pointer */
|
||||
val_ptr = &ptr[i];
|
||||
}
|
||||
equal_token = true;
|
||||
break;
|
||||
} else {
|
||||
/* Mark that we got something invalid! */
|
||||
invalid_tokens = true;
|
||||
first_space = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we need to parse the value, if any */
|
||||
if (val_ptr)
|
||||
{
|
||||
/* eat up spaces! there shouldn't be any h*/
|
||||
while ((*val_ptr != '\0') && isspace(*val_ptr))
|
||||
{
|
||||
val_ptr++;
|
||||
}
|
||||
if (*val_ptr == '\0')
|
||||
{
|
||||
val_ptr = NULL;
|
||||
goto skip_value;
|
||||
}
|
||||
/* Do we have an initial quote? If so, the parsing rules change! */
|
||||
if (*val_ptr == '"' && *val_ptr != '\0')
|
||||
{
|
||||
len = strlen(val_ptr);
|
||||
if (val_ptr[len-1] == '"')
|
||||
{
|
||||
/* Strip quotes! */
|
||||
val_ptr[--len] = '\0';
|
||||
val_ptr++;
|
||||
quotes = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
skip_value:
|
||||
/* We're done! */
|
||||
curtok = val_ptr - buffer;
|
||||
if (!ini_listener->ReadINI_KeyValue(key_ptr, val_ptr, invalid_tokens, equal_token, quotes, &curtok))
|
||||
{
|
||||
curtok = 0;
|
||||
goto event_failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (line)
|
||||
{
|
||||
*line = curline;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return true;
|
||||
|
||||
event_failed:
|
||||
if (line)
|
||||
{
|
||||
*line = curline;
|
||||
}
|
||||
|
||||
if (col)
|
||||
{
|
||||
*col = curtok;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return false;
|
||||
}
|
27
core/CTextParsers.h
Normal file
27
core/CTextParsers.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef _INCLUDE_SOURCEMOD_TEXTPARSERS_H_
|
||||
#define _INCLUDE_SOURCEMOD_TEXTPARSERS_H_
|
||||
|
||||
#include "interfaces/ITextParsers.h"
|
||||
|
||||
using namespace SourceMod;
|
||||
|
||||
class CTextParsers : public ITextParsers
|
||||
{
|
||||
|
||||
public:
|
||||
CTextParsers();
|
||||
public:
|
||||
virtual bool ParseFile_INI(const char *file,
|
||||
ITextListener_INI *ini_listener,
|
||||
unsigned int *line,
|
||||
unsigned int *col);
|
||||
|
||||
virtual bool ParseFile_SMC(const char *file,
|
||||
ITextListener_SMC *smc_listener,
|
||||
unsigned int *line,
|
||||
unsigned int *col);
|
||||
};
|
||||
|
||||
extern CTextParsers g_TextParse;
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_TEXTPARSERS_H_
|
@ -1,5 +1,5 @@
|
||||
#ifndef _INCLUDE_SOURCEMOD_TEXTPARSERS_H_
|
||||
#define _INCLUDE_SOURCEMOD_TEXTPARSERS_H_
|
||||
#ifndef _INCLUDE_SOURCEMOD_TEXTPARSERS_INTERFACE_H_
|
||||
#define _INCLUDE_SOURCEMOD_TEXTPARSERS_INTERFACE_H_
|
||||
|
||||
#include <IShareSys.h>
|
||||
|
||||
@ -50,9 +50,18 @@ namespace SourceMod
|
||||
* @brief Called when a new section is encountered in an INI file.
|
||||
*
|
||||
* @param section Name of section in between the [ and ] characters.
|
||||
* @param invalid_tokens True if invalid tokens were detected in the name.
|
||||
* @param close_bracket True if a closing bracket was detected, false otherwise.
|
||||
* @param extra_tokens True if extra tokens were detected on the line.
|
||||
* @param curtok Contains current token in the line where the section name starts.
|
||||
* You can add to this offset when failing to point to a token.
|
||||
* @return True to keep parsing, false otherwise.
|
||||
*/
|
||||
virtual bool ReadINI_NewSection(const char *section)
|
||||
virtual bool ReadINI_NewSection(const char *section,
|
||||
bool invalid_tokens,
|
||||
bool close_bracket,
|
||||
bool extra_tokens,
|
||||
unsigned int *curtok)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -61,11 +70,32 @@ namespace SourceMod
|
||||
* @brief Called when encountering a key/value pair in an INI file.
|
||||
*
|
||||
* @param key Name of key.
|
||||
* @param value Name of value.
|
||||
* @param value String containing value (with quotes stripped, if any).
|
||||
* @param invalid_tokens Whether or not the key contained invalid tokens.
|
||||
* @param equal_token There was an '=' sign present (in case the value is missing).
|
||||
* @param quotes Whether value was enclosed in quotes.
|
||||
* @param curtoken Contains the token index of the start of the value string.
|
||||
* This can be changed when returning false.
|
||||
* @return True to keep parsing, false otherwise.
|
||||
*/
|
||||
virtual bool ReadINI_KeyValue(const char *key, const char *value, bool quotes)
|
||||
virtual bool ReadINI_KeyValue(const char *key,
|
||||
const char *value,
|
||||
bool invalid_tokens,
|
||||
bool equal_token,
|
||||
bool quotes,
|
||||
unsigned int *curtok)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called after a line has been preprocessed, if it has text.
|
||||
*
|
||||
* @param line Contents of line.
|
||||
* @param curtok Pointer to optionally store failed position in string.
|
||||
* @return True to keep parsing, false otherwise.
|
||||
*/
|
||||
virtual bool ReadINI_RawLine(const char *line, unsigned int *cutok)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -163,8 +193,20 @@ namespace SourceMod
|
||||
}
|
||||
};
|
||||
|
||||
#define SMINTERFACE_TEXTPARSERS_NAME "ITextParsers"
|
||||
#define SMINTERFACE_TEXTPARSERS_VERSION 1
|
||||
|
||||
class ITextParsers : public SMInterface
|
||||
{
|
||||
public:
|
||||
virtual const char *GetInterfaceName()
|
||||
{
|
||||
return SMINTERFACE_TEXTPARSERS_NAME;
|
||||
}
|
||||
virtual unsigned int GetInterfaceVersion()
|
||||
{
|
||||
return SMINTERFACE_TEXTPARSERS_VERSION;
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* @brief Parses an INI-format file.
|
||||
@ -199,4 +241,4 @@ namespace SourceMod
|
||||
};
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_TEXTPARSERS_H_
|
||||
#endif //_INCLUDE_SOURCEMOD_TEXTPARSERS_INTERFACE_H_
|
||||
|
@ -179,7 +179,11 @@
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\mm_api.cpp"
|
||||
RelativePath="..\CTextParsers.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sourcemm_api.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
@ -189,7 +193,7 @@
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\mm_api.h"
|
||||
RelativePath="..\CTextParsers.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
@ -200,6 +204,10 @@
|
||||
RelativePath="..\sm_version.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sourcemm_api.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
|
@ -1,16 +1,24 @@
|
||||
#include <oslink.h>
|
||||
#include "mm_api.h"
|
||||
#include "sourcemm_api.h"
|
||||
#include "sm_version.h"
|
||||
#include "systems/LibrarySys.h"
|
||||
#include "CTextParsers.h"
|
||||
|
||||
SourceMod_Core g_SourceMod;
|
||||
|
||||
PLUGIN_EXPOSE(SourceMod, g_SourceMod);
|
||||
|
||||
class Test : public ITextListener_INI
|
||||
{
|
||||
public:
|
||||
};
|
||||
|
||||
bool SourceMod_Core::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late)
|
||||
{
|
||||
PLUGIN_SAVEVARS();
|
||||
|
||||
Test test;
|
||||
bool result = g_TextParse.ParseFile_INI("c:\\gaben.ini", &test, NULL, NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ private:
|
||||
LibraryHandle m_lib;
|
||||
};
|
||||
|
||||
class LibrarySystem
|
||||
class LibrarySystem : public ILibrarySys
|
||||
{
|
||||
public:
|
||||
virtual ILibrary *OpenLibrary(const char *path, char *error, size_t err_max);
|
||||
|
Loading…
Reference in New Issue
Block a user