diff --git a/core/TextParsers.cpp b/core/TextParsers.cpp index 060124f5..9cc6c231 100644 --- a/core/TextParsers.cpp +++ b/core/TextParsers.cpp @@ -79,45 +79,6 @@ unsigned int TextParsers::GetUTF8CharBytes(const char *stream) return _GetUTF8CharBytes(stream); } -/** - * Character streams - */ - -struct CharStream -{ - const char *curpos; -}; - -bool CharStreamReader(void *stream, char *buffer, size_t maxlength, unsigned int *read) -{ - CharStream *srdr = (CharStream *)stream; - - const char *ptr = srdr->curpos; - for (size_t i=0; icurpos; - - srdr->curpos = ptr; - - return true; -} - -SMCError TextParsers::ParseString_SMC(const char *stream, - ITextListener_SMC *smc, - SMCStates *states) -{ - CharStream srdr = { stream }; - - return ParseStream_SMC(&srdr, CharStreamReader, smc, states); -} - /** * File streams */ @@ -189,6 +150,57 @@ SMCError TextParsers::ParseSMCFile(const char *file, return result; } +struct RawStream +{ + const char *stream; + size_t length; + size_t pos; +}; + +bool RawStreamReader(void *stream, char *buffer, size_t maxlength, unsigned int *read) +{ + RawStream *rs = (RawStream *)stream; + + if (rs->pos >= rs->length) + { + return false; + } + + size_t remaining = rs->length - rs->pos; + + /* Use the smaller of the two */ + size_t copy = (remaining > maxlength) ? maxlength : remaining; + + memcpy(buffer, &rs->stream[rs->pos], copy); + rs->pos += copy; + *read = copy; + assert(rs->pos <= rs->length); + + return true; +} + +SMCError TextParsers::ParseSMCStream(const char *stream, + size_t length, + ITextListener_SMC *smc_listener, + SMCStates *states, + char *buffer, + size_t maxsize) +{ + RawStream rs; + SMCError result; + + rs.stream = stream; + rs.length = length; + rs.pos = 0; + + result = ParseStream_SMC(&rs, RawStreamReader, smc_listener, states); + + const char *errstr = GetSMCErrorString(result); + UTIL_Format(buffer, maxsize, "%s", errstr != NULL ? errstr : "Unknown error"); + + return result; +} + /** * Raw parsing of streams with helper functions */ diff --git a/core/TextParsers.h b/core/TextParsers.h index 30e8a781..ca863395 100644 --- a/core/TextParsers.h +++ b/core/TextParsers.h @@ -70,14 +70,18 @@ public: char *buffer, size_t maxsize); + SMCError ParseSMCStream(const char *stream, + size_t length, + ITextListener_SMC *smc_listener, + SMCStates *states, + char *buffer, + size_t maxsize); + unsigned int GetUTF8CharBytes(const char *stream); const char *GetSMCErrorString(SMCError err); bool IsWhitespace(const char *stream); private: - SMCError ParseString_SMC(const char *stream, - ITextListener_SMC *smc, - SMCStates *states); SMCError ParseStream_SMC(void *stream, STREAMREADER srdr, ITextListener_SMC *smc, diff --git a/public/ITextParsers.h b/public/ITextParsers.h index c0ccf6d5..7df0997b 100644 --- a/public/ITextParsers.h +++ b/public/ITextParsers.h @@ -43,7 +43,7 @@ namespace SourceMod { #define SMINTERFACE_TEXTPARSERS_NAME "ITextParsers" - #define SMINTERFACE_TEXTPARSERS_VERSION 3 + #define SMINTERFACE_TEXTPARSERS_VERSION 4 /** * The INI file format is defined as: @@ -399,12 +399,31 @@ namespace SourceMod * @param states Optional pointer to store last known states. * @param buffer Error message buffer. * @param maxsize Maximum size of the error buffer. + * @return Error code. */ virtual SMCError ParseSMCFile(const char *file, ITextListener_SMC *smc_listener, SMCStates *states, char *buffer, size_t maxsize) =0; + + /** + * @brief Parses a raw UTF8 stream as an SMC file. + * + * @param stream Memory containing data. + * @param length Number of bytes in the stream. + * @param smc_listener Event handler for reading file. + * @param states Optional pointer to store last known states. + * @param buffer Error message buffer. + * @param maxsize Maximum size of the error buffer. + * @return Error code. + */ + virtual SMCError ParseSMCStream(const char *stream, + size_t length, + ITextListener_SMC *smc_listener, + SMCStates *states, + char *buffer, + size_t maxsize) =0; }; inline unsigned int _GetUTF8CharBytes(const char *stream)