#include "tier2/fileformats/ini.h" #include "tier0/platform.h" #include "tier1/utlstring.h" #include "tier1/utlvector.h" #include "tier0/lib.h" enum ESectionType { SECTIONTYPE_String, SECTIONTYPE_Boolean, SECTIONTYPE_Float, }; struct SectionData_t { ESectionType m_eSectionType; CUtlString m_szKey; bool m_bData; float m_fData; CUtlString m_szData; }; abstract_class CINISection: public IINISection { public: virtual bool GetBoolValue( const char *szKeyName ) override; virtual int GetIntValue( const char *szKeyName ) override; virtual const char *GetStringValue( const char *szKeyName ) override; virtual CUtlString GetUTLStringValue( const char *szKeyName ) override; CUtlVector m_values; CUtlString m_szSectionName; }; bool CINISection::GetBoolValue( const char *szKeyName ) { } int CINISection::GetIntValue( const char *szKeyName ) { } const char *CINISection::GetStringValue( const char *szKeyName ) { return 0; } CUtlString CINISection::GetUTLStringValue( const char *szKeyName ) { } class CINIFile: public IINIFile { public: virtual IINISection *GetSection( const char *szSectionName ) override; CUtlVector m_sections; }; IINISection *CINIFile::GetSection( const char *szSectionName ) { for ( auto §ion: m_sections ) { if ( section->m_szSectionName == szSectionName ) return (IINISection*)§ion; } return 0; } class CINIManager: public IINIManager { public: virtual IINIFile *ReadString( const char *psz ) override; bool IsWordSymbol( char c ); CUtlVector TokenizeString(); }; IINIFile *CINIManager::ReadString( const char *psz ) { CINIFile *pFile = 0; CINIFile file = {}; bool bIsQuoted; bool bIsSlash; bool bIsVarName; bool bIsVarValue; bool bIsSectionName; CINISection currentSection; SectionData_t currentSectionData; size_t i = 0; char c; CUtlString szStringValue; CUtlVector tokens; uint32_t nCurrentLine = 0; while (true) { c = psz[i]; i++; if (c == '\0') break; if (c == '\n') nCurrentLine++; if (bIsQuoted) { if (bIsSlash) { bIsSlash = false; switch (c) { case '\\': szStringValue.AppendTail('\\'); continue; case '"': szStringValue.AppendTail('"'); continue; case 'n': szStringValue.AppendTail('\n'); continue; case 't': szStringValue.AppendTail('\n'); continue; case '\n': szStringValue.AppendTail('\n'); continue; default: szStringValue.AppendTail(c); continue; } } else { switch (c) { case '\\': bIsSlash = true; continue; case '\n': V_printf("line %i: new line was found but the string wasn't finished, did you forget to place \" in the end of the line?\n", nCurrentLine); case '"': bIsQuoted = false; if (szStringValue == 0) continue; tokens.AppendTail(szStringValue); szStringValue = 0; continue; default: szStringValue.AppendTail(c); continue; } } } else { if (c == '"') { bIsQuoted = true; } if (IsWordSymbol(c)) { szStringValue.AppendTail(c); continue; } else { if (szStringValue != 0) tokens.AppendTail(szStringValue); szStringValue = 0; if (V_isgraph(c) && c != '"') tokens.AppendTail(CUtlString("%c", c)); } } }; currentSectionData.m_eSectionType = SECTIONTYPE_String; for ( int i = 0; i < tokens.GetSize(); i++ ) { if (tokens[i] == "]") { V_printf("Error: unexpected ]\n"); return 0; } if (tokens[i] == "[") { i++; if (i>=tokens.GetSize()) { V_printf("Error: Trailing section start\n"); return 0; } currentSection = {}; currentSection.m_szSectionName = tokens[i]; V_printf("[%s]\n",currentSection.m_szSectionName.GetString()); i++; if (i>=tokens.GetSize()) { V_printf("Error: Trailing section name\n"); return 0; } if (tokens[i] != "]") { V_printf("Error: expected ]\n"); return 0; } continue; } if (tokens[i] == "=") { V_printf("Error: expected key\n"); return 0; } currentSectionData = {}; currentSectionData.m_szKey = tokens[i]; i++; if (i>=tokens.GetSize()) { V_printf("Error: trailing key\n"); return 0; } if (tokens[i] != "=") { V_printf("Error: expected =\n"); return 0; } i++; if (i>=tokens.GetSize()) { V_printf("Error: expected value\n"); return 0; } currentSectionData.m_szData = tokens[i]; currentSection.m_values.AppendTail(currentSectionData); } pFile = new CINIFile; *pFile = file; return (IINIFile*)pFile; } bool CINIManager::IsWordSymbol( char c ) { if (V_isalnum(c)) return true; switch (c) { case '-': case '_': case '.': return true; default: return false; } } CUtlVector TokenizeString(); IINIManager *INIManager() { static CINIManager manager; return &manager; }