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_
|
#ifndef _INCLUDE_SOURCEMOD_TEXTPARSERS_INTERFACE_H_
|
||||||
#define _INCLUDE_SOURCEMOD_TEXTPARSERS_H_
|
#define _INCLUDE_SOURCEMOD_TEXTPARSERS_INTERFACE_H_
|
||||||
|
|
||||||
#include <IShareSys.h>
|
#include <IShareSys.h>
|
||||||
|
|
||||||
@ -50,9 +50,18 @@ namespace SourceMod
|
|||||||
* @brief Called when a new section is encountered in an INI file.
|
* @brief Called when a new section is encountered in an INI file.
|
||||||
*
|
*
|
||||||
* @param section Name of section in between the [ and ] characters.
|
* @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.
|
* @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;
|
return true;
|
||||||
}
|
}
|
||||||
@ -61,11 +70,32 @@ namespace SourceMod
|
|||||||
* @brief Called when encountering a key/value pair in an INI file.
|
* @brief Called when encountering a key/value pair in an INI file.
|
||||||
*
|
*
|
||||||
* @param key Name of key.
|
* @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 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.
|
* @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;
|
return true;
|
||||||
}
|
}
|
||||||
@ -163,8 +193,20 @@ namespace SourceMod
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define SMINTERFACE_TEXTPARSERS_NAME "ITextParsers"
|
||||||
|
#define SMINTERFACE_TEXTPARSERS_VERSION 1
|
||||||
|
|
||||||
class ITextParsers : public SMInterface
|
class ITextParsers : public SMInterface
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
virtual const char *GetInterfaceName()
|
||||||
|
{
|
||||||
|
return SMINTERFACE_TEXTPARSERS_NAME;
|
||||||
|
}
|
||||||
|
virtual unsigned int GetInterfaceVersion()
|
||||||
|
{
|
||||||
|
return SMINTERFACE_TEXTPARSERS_VERSION;
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Parses an INI-format file.
|
* @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}"
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||||
>
|
>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\mm_api.cpp"
|
RelativePath="..\CTextParsers.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sourcemm_api.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
@ -189,7 +193,7 @@
|
|||||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||||
>
|
>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\mm_api.h"
|
RelativePath="..\CTextParsers.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
@ -200,6 +204,10 @@
|
|||||||
RelativePath="..\sm_version.h"
|
RelativePath="..\sm_version.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sourcemm_api.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Resource Files"
|
Name="Resource Files"
|
||||||
|
@ -1,16 +1,24 @@
|
|||||||
#include <oslink.h>
|
#include <oslink.h>
|
||||||
#include "mm_api.h"
|
#include "sourcemm_api.h"
|
||||||
#include "sm_version.h"
|
#include "sm_version.h"
|
||||||
#include "systems/LibrarySys.h"
|
#include "CTextParsers.h"
|
||||||
|
|
||||||
SourceMod_Core g_SourceMod;
|
SourceMod_Core g_SourceMod;
|
||||||
|
|
||||||
PLUGIN_EXPOSE(SourceMod, 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)
|
bool SourceMod_Core::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late)
|
||||||
{
|
{
|
||||||
PLUGIN_SAVEVARS();
|
PLUGIN_SAVEVARS();
|
||||||
|
|
||||||
|
Test test;
|
||||||
|
bool result = g_TextParse.ParseFile_INI("c:\\gaben.ini", &test, NULL, NULL);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -48,7 +48,7 @@ private:
|
|||||||
LibraryHandle m_lib;
|
LibraryHandle m_lib;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LibrarySystem
|
class LibrarySystem : public ILibrarySys
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ILibrary *OpenLibrary(const char *path, char *error, size_t err_max);
|
virtual ILibrary *OpenLibrary(const char *path, char *error, size_t err_max);
|
||||||
|
Loading…
Reference in New Issue
Block a user