http and lots of formats
This commit is contained in:
1
appleauth/auth.cpp
Normal file
1
appleauth/auth.cpp
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
74
appleauth/build.cpp
Normal file
74
appleauth/build.cpp
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
#include "helper.h"
|
||||||
|
#include "c.h"
|
||||||
|
#include "ld.h"
|
||||||
|
#include "tier1/utlstring.h"
|
||||||
|
#include "tier1/commandline.h"
|
||||||
|
|
||||||
|
ADD_DEPENDENCY_BUILD_FILE(tier0, "../tier0/build.cpp")
|
||||||
|
ADD_DEPENDENCY_BUILD_FILE(tier1, "../tier1/build.cpp")
|
||||||
|
ADD_DEPENDENCY_BUILD_FILE(tier2, "../tier2/build.cpp")
|
||||||
|
ADD_DEPENDENCY_BUILD_FILE(http, "../http/build.cpp")
|
||||||
|
|
||||||
|
DECLARE_BUILD_STAGE(appleauth)
|
||||||
|
{
|
||||||
|
CProject_t compileProject = {};
|
||||||
|
LinkProject_t ldProject = {};
|
||||||
|
|
||||||
|
compileProject.m_szName = "appleauth";
|
||||||
|
compileProject.files = {
|
||||||
|
"auth.cpp"
|
||||||
|
};
|
||||||
|
compileProject.includeDirectories = {"../public"};
|
||||||
|
compileProject.bFPIC = true;
|
||||||
|
ldProject = ccompiler->Compile(&compileProject);
|
||||||
|
ldProject.objects.AppendTail({GET_PROJECT_LIBRARY(tier1, "tier1")});
|
||||||
|
ldProject.objects.AppendTail({GET_PROJECT_LIBRARY(tier2, "tier2")});
|
||||||
|
ldProject.linkType = ELINK_DYNAMIC_LIBRARY;
|
||||||
|
|
||||||
|
CUtlString szOutputProject = linker->Link(&ldProject);
|
||||||
|
|
||||||
|
ADD_OUTPUT_OBJECT("appleauth", szOutputProject)
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
DECLARE_BUILD_STAGE(appleauth_test)
|
||||||
|
{
|
||||||
|
|
||||||
|
CProject_t compileProject = {};
|
||||||
|
LinkProject_t ldProject = {};
|
||||||
|
|
||||||
|
filesystem2->MakeDirectory("build");
|
||||||
|
filesystem2->CopyFile("build",GET_PROJECT_LIBRARY(funnyhttp, "funnyhttp"));
|
||||||
|
filesystem2->CopyFile("build",GET_PROJECT_LIBRARY(appleauth, "appleauth"));
|
||||||
|
filesystem2->CopyFile("build",GET_PROJECT_LIBRARY(tier0, "tier0"));
|
||||||
|
|
||||||
|
compileProject.m_szName = "appleauth";
|
||||||
|
compileProject.files = {
|
||||||
|
"test.cpp"
|
||||||
|
};
|
||||||
|
compileProject.includeDirectories = {"../public"};
|
||||||
|
compileProject.bFPIC = true;
|
||||||
|
ldProject = ccompiler->Compile(&compileProject);
|
||||||
|
ldProject.libraryObjects = {
|
||||||
|
GET_PROJECT_LIBRARY(tier1, "tier1"),
|
||||||
|
GET_PROJECT_LIBRARY(tier2, "tier2"),
|
||||||
|
};
|
||||||
|
ldProject.libraries = {
|
||||||
|
"tier0",
|
||||||
|
};
|
||||||
|
ldProject.libraryDirectories = {
|
||||||
|
"build",
|
||||||
|
};
|
||||||
|
ldProject.linkType = ELINK_EXECUTABLE;
|
||||||
|
CUtlString szOutputDir = linker->Link(&ldProject);
|
||||||
|
|
||||||
|
filesystem2->CopyFile("build",szOutputDir);
|
||||||
|
|
||||||
|
|
||||||
|
CUtlVector<CUtlString> args = {};
|
||||||
|
runner->Run("build/appleauth", args);
|
||||||
|
runner->Wait();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
ADD_DEPENDENCY_BUILD_FILE(tier0, "../tier0/build.cpp");
|
ADD_DEPENDENCY_BUILD_FILE(tier0, "../tier0/build.cpp");
|
||||||
ADD_DEPENDENCY_BUILD_FILE(tier1, "../tier1/build.cpp");
|
ADD_DEPENDENCY_BUILD_FILE(tier1, "../tier1/build.cpp");
|
||||||
ADD_DEPENDENCY_BUILD_FILE(tier2, "../tier2/build.cpp");
|
ADD_DEPENDENCY_BUILD_FILE(tier2, "../tier2/build.cpp");
|
||||||
ADD_DEPENDENCY_BUILD_FILE(apple, "apple/build.cpp");
|
ADD_DEPENDENCY_BUILD_FILE(appleauth, "../appleauth/build.cpp");
|
||||||
|
|
||||||
|
|
||||||
CUtlVector<CUtlString> g_fpcFiles = {
|
CUtlVector<CUtlString> g_fpcFiles = {
|
||||||
@@ -139,14 +139,9 @@ DECLARE_BUILD_STAGE(install)
|
|||||||
CUtlString szTier0 = GET_PROJECT_LIBRARY(tier0, "tier0");
|
CUtlString szTier0 = GET_PROJECT_LIBRARY(tier0, "tier0");
|
||||||
CUtlString szTier1 = GET_PROJECT_LIBRARY(tier1, "tier1");
|
CUtlString szTier1 = GET_PROJECT_LIBRARY(tier1, "tier1");
|
||||||
CUtlString szTier2 = GET_PROJECT_LIBRARY(tier2, "tier2");
|
CUtlString szTier2 = GET_PROJECT_LIBRARY(tier2, "tier2");
|
||||||
CUtlString xtool = GET_PROJECT_LIBRARY(xtool_cpp, "xtool");
|
|
||||||
|
|
||||||
filesystem2->CopyFile("build/fpc_temp", szExe);
|
filesystem2->CopyFile("build/fpc_temp", szExe);
|
||||||
filesystem2->CopyFile("build/libfpc_temp.so", szLibFpc);
|
filesystem2->CopyFile("build/libfpc_temp.so", szLibFpc);
|
||||||
if (xtool)
|
|
||||||
{
|
|
||||||
filesystem2->CopyFile("build", xtool);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
filesystem2->CopyFile("build/libtier1.a", szTier1);
|
filesystem2->CopyFile("build/libtier1.a", szTier1);
|
||||||
|
|||||||
@@ -82,6 +82,14 @@ CUtlString ILinker::Link( LinkProject_t *pProject )
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (auto object: pProject->libraryObjects)
|
||||||
|
{
|
||||||
|
if (filesystem2->ShouldRecompile(object,szOutputFile))
|
||||||
|
{
|
||||||
|
shouldRecompile = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!shouldRecompile)
|
if (!shouldRecompile)
|
||||||
goto compiled;
|
goto compiled;
|
||||||
|
|
||||||
|
|||||||
@@ -35,42 +35,3 @@ DECLARE_BUILD_STAGE(funnyhttp)
|
|||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
DECLARE_BUILD_STAGE(test)
|
|
||||||
{
|
|
||||||
|
|
||||||
CProject_t compileProject = {};
|
|
||||||
LinkProject_t ldProject = {};
|
|
||||||
|
|
||||||
filesystem2->MakeDirectory("build");
|
|
||||||
filesystem2->CopyFile("build",GET_PROJECT_LIBRARY(funnyhttp, "funnyhttp"));
|
|
||||||
filesystem2->CopyFile("build",GET_PROJECT_LIBRARY(tier0, "tier0"));
|
|
||||||
|
|
||||||
compileProject.m_szName = "funnyhttptest";
|
|
||||||
compileProject.files = {
|
|
||||||
"test.cpp"
|
|
||||||
};
|
|
||||||
compileProject.includeDirectories = {"../public"};
|
|
||||||
compileProject.bFPIC = true;
|
|
||||||
ldProject = ccompiler->Compile(&compileProject);
|
|
||||||
ldProject.libraryObjects = {
|
|
||||||
GET_PROJECT_LIBRARY(tier1, "tier1"),
|
|
||||||
GET_PROJECT_LIBRARY(tier2, "tier2"),
|
|
||||||
};
|
|
||||||
ldProject.libraries = {
|
|
||||||
"tier0",
|
|
||||||
};
|
|
||||||
ldProject.libraryDirectories = {
|
|
||||||
"build",
|
|
||||||
};
|
|
||||||
ldProject.linkType = ELINK_EXECUTABLE;
|
|
||||||
CUtlString szOutputDir = linker->Link(&ldProject);
|
|
||||||
|
|
||||||
filesystem2->CopyFile("build",szOutputDir);
|
|
||||||
|
|
||||||
|
|
||||||
CUtlVector<CUtlString> args = {};
|
|
||||||
runner->Run("build/funnyhttptest", args);
|
|
||||||
runner->Wait();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
|
|||||||
446
http/client.cpp
446
http/client.cpp
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
#include "http/http.h"
|
#include "http/http.h"
|
||||||
#include "tier1/interface.h"
|
#include "tier1/interface.h"
|
||||||
#include "tier1/utlstring.h"
|
#include "tier1/utlstring.h"
|
||||||
@@ -6,18 +7,34 @@
|
|||||||
#include "fcntl.h"
|
#include "fcntl.h"
|
||||||
#include "openssl/ssl.h"
|
#include "openssl/ssl.h"
|
||||||
#include "openssl/err.h"
|
#include "openssl/err.h"
|
||||||
|
#include "arpa/inet.h"
|
||||||
|
|
||||||
abstract_class CHTTPClient: public IHTTPClient
|
abstract_class CHTTPClient: public IHTTPClient
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void Post( const char *szResource, HTTPHeader_t *pHeader, uint32_t uDataSize, const char *data ) override;
|
void ConnectToServer();
|
||||||
|
void CloseConnection();
|
||||||
|
|
||||||
|
virtual void Post( const char *szResource, HTTPHeader_t *pHeader, uint32_t uDataSize, const void *data ) override;
|
||||||
virtual void Get( const char *szResource, HTTPHeader_t *pHeader ) override;
|
virtual void Get( const char *szResource, HTTPHeader_t *pHeader ) override;
|
||||||
virtual HTTPResponse_t GetResponse() override;
|
virtual HTTPResponse_t GetResponse() override;
|
||||||
|
|
||||||
HTTPResponse_t ParseResponse( const char *szMessage );
|
virtual bool WebSocket_Connect( const char *szResource ) override;
|
||||||
|
virtual void WebSocket_Close( void ) override;
|
||||||
|
virtual void WebSocket_SendText( const char *szData ) override;
|
||||||
|
virtual CUtlString WebSocket_RecvText() override;
|
||||||
|
virtual void WebSocket_SendBinary( size_t uSize, const void *pData ) override;
|
||||||
|
virtual WebSocketPacket_t WebSocket_RecvBinary() override;
|
||||||
|
|
||||||
|
ssize_t Write( void *pData, ssize_t uSize );
|
||||||
|
ssize_t Read( void *pData, ssize_t uSize );
|
||||||
|
|
||||||
|
HTTPResponse_t ParseResponse( const char *szMessage, uint32_t uDataSize );
|
||||||
const char *GetVersion();
|
const char *GetVersion();
|
||||||
|
HTTPHeaderParam_t ParseHeaderParams( const char *szHeaderLine );
|
||||||
|
|
||||||
const char *m_szHostName;
|
const char *m_szHostName;
|
||||||
|
uint16_t m_uPort;
|
||||||
bool m_bIsSecure;
|
bool m_bIsSecure;
|
||||||
SSL *m_pSSL;
|
SSL *m_pSSL;
|
||||||
SSL_CTX *m_pSSLCtx;
|
SSL_CTX *m_pSSLCtx;
|
||||||
@@ -25,9 +42,37 @@ public:
|
|||||||
int m_iFileDescriptor;
|
int m_iFileDescriptor;
|
||||||
};
|
};
|
||||||
|
|
||||||
void CHTTPClient::Post( const char *szResource, HTTPHeader_t *pHeader, uint32_t uDataSize, const char *data )
|
void CHTTPClient::Post( const char *szResource, HTTPHeader_t *pHeader, uint32_t uDataSize, const void *data )
|
||||||
{
|
{
|
||||||
|
if (pHeader == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ConnectToServer();
|
||||||
|
|
||||||
|
CUtlString szMessage = CUtlString(
|
||||||
|
"POST %s HTTP/%s\r\n",
|
||||||
|
szResource, GetVersion());
|
||||||
|
CUtlString szHeader = CUtlString(
|
||||||
|
"Host: %s\r\n"
|
||||||
|
"Content-Length: %u\r\n",
|
||||||
|
m_szHostName,
|
||||||
|
uDataSize
|
||||||
|
);
|
||||||
|
|
||||||
|
CUtlString szCombined;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for ( i = 0; i < pHeader->m_nParamCount; i++ )
|
||||||
|
{
|
||||||
|
szHeader.AppendTail(CUtlString("%s: %s\r\n", pHeader->m_params[i].m_szParamName.GetString(), pHeader->m_params[i].m_szValue.GetString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
szCombined = szMessage;
|
||||||
|
szCombined.AppendTail(szHeader);
|
||||||
|
szCombined.AppendTail("\r\n");
|
||||||
|
|
||||||
|
Write(szCombined.GetString(), szCombined.GetLenght());
|
||||||
|
Write((void*)data, uDataSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHTTPClient::Get( const char *szResource, HTTPHeader_t *pHeader )
|
void CHTTPClient::Get( const char *szResource, HTTPHeader_t *pHeader )
|
||||||
@@ -35,6 +80,8 @@ void CHTTPClient::Get( const char *szResource, HTTPHeader_t *pHeader )
|
|||||||
if (pHeader == NULL)
|
if (pHeader == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
ConnectToServer();
|
||||||
|
|
||||||
CUtlString szMessage = CUtlString(
|
CUtlString szMessage = CUtlString(
|
||||||
"GET %s HTTP/%s\r\n",
|
"GET %s HTTP/%s\r\n",
|
||||||
szResource, GetVersion());
|
szResource, GetVersion());
|
||||||
@@ -48,53 +95,54 @@ void CHTTPClient::Get( const char *szResource, HTTPHeader_t *pHeader )
|
|||||||
|
|
||||||
for ( i = 0; i < pHeader->m_nParamCount; i++ )
|
for ( i = 0; i < pHeader->m_nParamCount; i++ )
|
||||||
{
|
{
|
||||||
szHeader.AppendTail(CUtlString("%s: %s\r\n", pHeader->m_params[i].m_szParamName, pHeader->m_params[i].m_szValue));
|
szHeader.AppendTail(CUtlString("%s: %s\r\n", pHeader->m_params[i].m_szParamName.GetString(), pHeader->m_params[i].m_szValue.GetString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
szCombined = szMessage;
|
szCombined = szMessage;
|
||||||
szCombined.AppendTail(szHeader);
|
szCombined.AppendTail(szHeader);
|
||||||
szCombined.AppendTail("\r\n");
|
szCombined.AppendTail("\r\n");
|
||||||
|
|
||||||
if (m_bIsSecure)
|
Write(szCombined.GetString(), szCombined.GetLenght());
|
||||||
SSL_write(m_pSSL, szCombined.GetString(), szCombined.GetLenght());
|
|
||||||
else
|
|
||||||
write(m_iFileDescriptor, szCombined.GetString(), szCombined.GetLenght());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HTTPResponse_t CHTTPClient::GetResponse()
|
HTTPResponse_t CHTTPClient::GetResponse()
|
||||||
{
|
{
|
||||||
CUtlResizableBuffer<char> szCharBuffer(0);
|
CUtlResizableBuffer<char> szCharBuffer(0);
|
||||||
char response[4096];
|
char response[4096] = {};
|
||||||
int n;
|
int n;
|
||||||
int nPreviousSize = 0;
|
int nPreviousSize = 0;
|
||||||
|
|
||||||
if (m_bIsSecure)
|
readSocket:
|
||||||
|
|
||||||
|
n = Read(response, sizeof(response));
|
||||||
|
if (n == -1)
|
||||||
|
goto responseDone;
|
||||||
|
|
||||||
|
|
||||||
|
szCharBuffer.Resize(nPreviousSize+n);
|
||||||
|
V_memcpy((char*)szCharBuffer.GetMemory()+nPreviousSize, response, n);
|
||||||
|
nPreviousSize += n;
|
||||||
|
V_printf("%s\n",response);
|
||||||
|
|
||||||
|
// HTTP 1.0 reacts either to socket being closed or Content-Lenght
|
||||||
|
// HTTP 1.1 has Transfer-Encoding: chunked, which we need to respect
|
||||||
|
// Still some response codes may not include a body
|
||||||
|
if ( n > 0 )
|
||||||
{
|
{
|
||||||
secureRead:
|
HTTPResponse_t r = ParseResponse(szCharBuffer, szCharBuffer.GetSize());
|
||||||
n = SSL_read(m_pSSL, response, sizeof(response));
|
if (r.m_bIsComplete)
|
||||||
szCharBuffer.Resize(nPreviousSize+n);
|
goto responseDone;
|
||||||
V_memcpy((char*)szCharBuffer.GetMemory()+nPreviousSize, response, n);
|
|
||||||
nPreviousSize += n;
|
|
||||||
if (SSL_pending(m_pSSL)>0)
|
|
||||||
goto secureRead;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
httpRead:
|
|
||||||
n = read(m_iFileDescriptor, response, sizeof(response));
|
|
||||||
V_printf("%i\n",n);
|
|
||||||
szCharBuffer.Resize(nPreviousSize+n+1);
|
|
||||||
szCharBuffer[nPreviousSize+n] = 0;
|
|
||||||
V_memcpy((char*)szCharBuffer.GetMemory()+nPreviousSize, response, n);
|
|
||||||
nPreviousSize += n;
|
|
||||||
goto httpRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// these do not provide body
|
||||||
|
}
|
||||||
|
// there is some data so go and read back again
|
||||||
|
goto readSocket;
|
||||||
|
responseDone:
|
||||||
|
|
||||||
szCharBuffer.Resize(n+1);
|
return ParseResponse(szCharBuffer, szCharBuffer.GetSize());
|
||||||
return ParseResponse(szCharBuffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HTTPResponse_t CHTTPClient::ParseResponse( const char *szMessage )
|
HTTPResponse_t CHTTPClient::ParseResponse( const char *szMessage, uint32_t uDataSize )
|
||||||
{
|
{
|
||||||
char cPreviousCharacter = 0;
|
char cPreviousCharacter = 0;
|
||||||
char cCurrentCharacter = 0;
|
char cCurrentCharacter = 0;
|
||||||
@@ -115,12 +163,18 @@ HTTPResponse_t CHTTPClient::ParseResponse( const char *szMessage )
|
|||||||
if (bIsMessage)
|
if (bIsMessage)
|
||||||
{
|
{
|
||||||
uint32_t uResult = 0;
|
uint32_t uResult = 0;
|
||||||
V_sscanf(szBuffer, "HTTP/1.1 %i", &uResult);
|
while (szBuffer[0] != ' ')
|
||||||
|
szBuffer.RemoveHead(1);
|
||||||
|
while (szBuffer[0] == ' ')
|
||||||
|
szBuffer.RemoveHead(1);
|
||||||
|
V_sscanf(szBuffer, "%i", &uResult);
|
||||||
response.m_uCode = uResult;
|
response.m_uCode = uResult;
|
||||||
}
|
}
|
||||||
|
if (szBuffer == "")
|
||||||
|
break;
|
||||||
|
if (!bIsMessage)
|
||||||
|
headers.AppendTail(ParseHeaderParams(szBuffer));
|
||||||
bIsMessage = false;
|
bIsMessage = false;
|
||||||
if (szBuffer == "")
|
|
||||||
break;
|
|
||||||
szBuffer = "";
|
szBuffer = "";
|
||||||
cPreviousCharacter = 0;
|
cPreviousCharacter = 0;
|
||||||
cCurrentCharacter = *pcCurrentCharacter++;
|
cCurrentCharacter = *pcCurrentCharacter++;
|
||||||
@@ -133,12 +187,73 @@ HTTPResponse_t CHTTPClient::ParseResponse( const char *szMessage )
|
|||||||
|
|
||||||
cPreviousCharacter = cCurrentCharacter;
|
cPreviousCharacter = cCurrentCharacter;
|
||||||
};
|
};
|
||||||
|
switch (response.m_uCode)
|
||||||
|
{
|
||||||
|
case 100:
|
||||||
|
case 101:
|
||||||
|
case 204:
|
||||||
|
case 205:
|
||||||
|
case 304:
|
||||||
|
response.m_bIsComplete = true;
|
||||||
|
return response;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bParseInChunks = false;
|
||||||
|
uint64_t uBodySize;
|
||||||
|
// check content lenght
|
||||||
|
for ( int i = 0; i < response.m_params.GetSize(); i++ )
|
||||||
|
{
|
||||||
|
if ( !V_stricmp( response.m_params[i].m_szParamName, "Content-Length" ) )
|
||||||
|
{
|
||||||
|
uBodySize = atoll(response.m_params[i].m_szValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
if ( !V_stricmp( response.m_params[i].m_szParamName, "Transfer-Encoding" ) )
|
||||||
|
{
|
||||||
|
if ( !V_stricmp( response.m_params[i].m_szValue, "Chunked" ) )
|
||||||
|
{
|
||||||
|
bParseInChunks = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
pcCurrentCharacter++;
|
pcCurrentCharacter++;
|
||||||
uint32_t nDataLen = V_strlen(pcCurrentCharacter);
|
if ( !bParseInChunks )
|
||||||
data = CUtlBuffer<char>(nDataLen+1);
|
{
|
||||||
V_strcpy(data.GetMemory(), pcCurrentCharacter);
|
uint32_t nDataLen = uDataSize-(pcCurrentCharacter-szMessage);
|
||||||
data[nDataLen] = 0;
|
data = CUtlBuffer<char>(nDataLen+1);
|
||||||
response.m_message = data;
|
V_memcpy(data.GetMemory(), pcCurrentCharacter, nDataLen);
|
||||||
|
data[nDataLen] = 0;
|
||||||
|
response.m_params = CUtlBuffer<HTTPHeaderParam_t>(headers.GetSize());
|
||||||
|
for (int i = 0; i < headers.GetSize(); i++ )
|
||||||
|
{
|
||||||
|
response.m_params[i] = headers[i];
|
||||||
|
}
|
||||||
|
response.m_message = data;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
szBuffer = "";
|
||||||
|
while (*pcCurrentCharacter)
|
||||||
|
{
|
||||||
|
|
||||||
|
cCurrentCharacter = *pcCurrentCharacter;
|
||||||
|
if ( cPreviousCharacter == '\r')
|
||||||
|
{
|
||||||
|
if ( cCurrentCharacter == '\n')
|
||||||
|
{
|
||||||
|
uint32_t uChunkSize;
|
||||||
|
uChunkSize = strtol(szBuffer, NULL, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cPreviousCharacter != 0)
|
||||||
|
szBuffer.AppendTail(cPreviousCharacter);
|
||||||
|
pcCurrentCharacter++;
|
||||||
|
|
||||||
|
cPreviousCharacter = cCurrentCharacter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
@@ -148,57 +263,76 @@ const char *CHTTPClient::GetVersion()
|
|||||||
|
|
||||||
return "1.1";
|
return "1.1";
|
||||||
}
|
}
|
||||||
abstract_class CHTTPClientManager: public IHTTPClientManager
|
HTTPHeaderParam_t CHTTPClient::ParseHeaderParams( const char *szHeaderLine )
|
||||||
{
|
{
|
||||||
public:
|
const char *psz = szHeaderLine;
|
||||||
CHTTPClientManager();
|
CUtlString szName;
|
||||||
virtual IHTTPClient *Connect( const char *szUrl, bool bSecure ) override;
|
CUtlString szValue;
|
||||||
virtual void Disconnect( IHTTPClient *szConnection ) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
IHTTPClient *CHTTPClientManager::Connect( const char *szUrl, bool bSecure )
|
int stage = 0;
|
||||||
|
while (*psz)
|
||||||
|
{
|
||||||
|
if (stage == 0)
|
||||||
|
{
|
||||||
|
if (*psz == ':')
|
||||||
|
stage = 1;
|
||||||
|
else
|
||||||
|
szName.AppendTail(*psz);
|
||||||
|
} else if (stage == 1)
|
||||||
|
{
|
||||||
|
if (*psz != ' ')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
psz++;
|
||||||
|
}
|
||||||
|
szValue = psz;
|
||||||
|
return {szName, szValue};
|
||||||
|
}
|
||||||
|
void CHTTPClient::ConnectToServer()
|
||||||
{
|
{
|
||||||
struct hostent *pServerHostName = NULL;
|
struct hostent *pServerHostName = NULL;
|
||||||
struct sockaddr_in serverAddress;
|
struct sockaddr_in serverAddress;
|
||||||
int fd = 0;
|
int fd = 0;
|
||||||
int err;
|
int err;
|
||||||
CHTTPClient *pClient;
|
|
||||||
SSL_CTX *ctx;
|
SSL_CTX *ctx;
|
||||||
SSL *ssl;
|
SSL *ssl;
|
||||||
|
|
||||||
pServerHostName = gethostbyname(szUrl);
|
if (V_strcmp(m_szHostName, "localhost"))
|
||||||
if (!pServerHostName)
|
{
|
||||||
return NULL;
|
pServerHostName = gethostbyname(m_szHostName);
|
||||||
|
if (!pServerHostName)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
fd = socket(AF_INET, SOCK_STREAM, 0);
|
fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if ( fd < 0 )
|
if ( fd < 0 )
|
||||||
return NULL;
|
return;
|
||||||
|
|
||||||
V_memset(&serverAddress, 0, sizeof(serverAddress));
|
V_memset(&serverAddress, 0, sizeof(serverAddress));
|
||||||
serverAddress.sin_family = AF_INET;
|
serverAddress.sin_family = AF_INET;
|
||||||
V_memcpy(&serverAddress.sin_addr.s_addr, pServerHostName->h_addr, pServerHostName->h_length);
|
if (!V_strcmp(m_szHostName, "localhost"))
|
||||||
|
inet_pton(AF_INET, "127.0.0.1", &serverAddress.sin_addr);
|
||||||
|
else
|
||||||
|
V_memcpy(&serverAddress.sin_addr.s_addr, pServerHostName->h_addr, pServerHostName->h_length);
|
||||||
|
|
||||||
// https
|
// https
|
||||||
if ( bSecure )
|
serverAddress.sin_port = htons(m_uPort);
|
||||||
serverAddress.sin_port = htons(443);
|
|
||||||
else
|
|
||||||
serverAddress.sin_port = htons(80);
|
|
||||||
|
|
||||||
err = connect(fd, (struct sockaddr *)&serverAddress, sizeof(serverAddress));
|
err = connect(fd, (struct sockaddr *)&serverAddress, sizeof(serverAddress));
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return NULL;
|
return;
|
||||||
|
|
||||||
if (bSecure)
|
if (m_bIsSecure)
|
||||||
{
|
{
|
||||||
ctx = SSL_CTX_new(TLS_client_method());
|
ctx = SSL_CTX_new(TLS_client_method());
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return NULL;
|
return;
|
||||||
ssl =SSL_new(ctx);
|
ssl =SSL_new(ctx);
|
||||||
if (!ssl)
|
if (!ssl)
|
||||||
return NULL;
|
return;
|
||||||
|
|
||||||
SSL_set_fd(ssl, fd);
|
SSL_set_fd(ssl, fd);
|
||||||
SSL_set_tlsext_host_name(ssl, szUrl);
|
SSL_set_tlsext_host_name(ssl, m_szHostName);
|
||||||
|
|
||||||
int r = SSL_connect(ssl);
|
int r = SSL_connect(ssl);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
@@ -206,19 +340,192 @@ IHTTPClient *CHTTPClientManager::Connect( const char *szUrl, bool bSecure )
|
|||||||
ERR_print_errors_fp(stdout);
|
ERR_print_errors_fp(stdout);
|
||||||
SSL_free(ssl);
|
SSL_free(ssl);
|
||||||
SSL_CTX_free(ctx);
|
SSL_CTX_free(ctx);
|
||||||
return NULL;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pClient = new CHTTPClient();
|
m_iFileDescriptor = fd;
|
||||||
pClient->m_iFileDescriptor = fd;
|
if (m_bIsSecure)
|
||||||
pClient->m_szHostName = szUrl;
|
|
||||||
if (bSecure)
|
|
||||||
{
|
{
|
||||||
pClient->m_bIsSecure = bSecure;
|
m_pSSL = ssl;
|
||||||
pClient->m_pSSL = ssl;
|
m_pSSLCtx = ctx;
|
||||||
pClient->m_pSSLCtx = ctx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHTTPClient::CloseConnection()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
bool CHTTPClient::WebSocket_Connect( const char *szResource )
|
||||||
|
{
|
||||||
|
HTTPResponse_t stResponse;
|
||||||
|
HTTPHeaderParam_t params[] = {
|
||||||
|
{"Upgrade", "websocket"},
|
||||||
|
{"Connection", "Upgrade"},
|
||||||
|
{"Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ=="},
|
||||||
|
{"Sec-WebSocket-Protocol", "chat, superchat"},
|
||||||
|
{"Sec-WebSocket-Version", "13"},
|
||||||
|
};
|
||||||
|
HTTPHeader_t stHeader = {
|
||||||
|
sizeof(params)/sizeof(params[0]),
|
||||||
|
params
|
||||||
|
};
|
||||||
|
Get(szResource, &stHeader);
|
||||||
|
stResponse = GetResponse();
|
||||||
|
// According to spec 101 is a good sign
|
||||||
|
if (stResponse.m_uCode == 101)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CHTTPClient::WebSocket_Close( void )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
enum EWebSocketOp
|
||||||
|
{
|
||||||
|
WEBSOCKET_CONTINUE = 0,
|
||||||
|
WEBSOCKET_TEXT = 1,
|
||||||
|
WEBSOCKET_BINARY = 2,
|
||||||
|
WEBSOCKET_CLOSE = 8,
|
||||||
|
WEBSOCKET_PING = 9,
|
||||||
|
WEBSOCKET_PONG = 10,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WebSocketFrame_t
|
||||||
|
{
|
||||||
|
EWebSocketOp nOpCode: 4;
|
||||||
|
uint8_t nReserved: 3;
|
||||||
|
uint8_t bFin: 1;
|
||||||
|
uint8_t nPayloadLenght: 7;
|
||||||
|
uint8_t bMasked: 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
void CHTTPClient::WebSocket_SendText( const char *szData )
|
||||||
|
{
|
||||||
|
size_t uLen;
|
||||||
|
WebSocketFrame_t stFrame;
|
||||||
|
uLen = V_strlen(szData);
|
||||||
|
stFrame = (WebSocketFrame_t){
|
||||||
|
.nOpCode = WEBSOCKET_TEXT,
|
||||||
|
.bFin = 1,
|
||||||
|
.bMasked = 1,
|
||||||
|
};
|
||||||
|
// im too lazy to mask it
|
||||||
|
int iMask = 0;
|
||||||
|
|
||||||
|
if ( uLen <= 125 )
|
||||||
|
{
|
||||||
|
stFrame.nPayloadLenght = uLen;
|
||||||
|
Write(&stFrame, 2);
|
||||||
|
Write(&iMask, 4);
|
||||||
|
}
|
||||||
|
else if ( uLen <= 65535 )
|
||||||
|
{
|
||||||
|
stFrame.nPayloadLenght = 126;
|
||||||
|
Write(&stFrame, 2);
|
||||||
|
uint16_t uLenN = htons(uLen);
|
||||||
|
Write(&uLenN, 2);
|
||||||
|
Write(&iMask, 4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stFrame.nPayloadLenght = 127;
|
||||||
|
Write(&stFrame, 2);
|
||||||
|
Write(&iMask, 4);
|
||||||
|
Write(&uLen, 8);
|
||||||
|
}
|
||||||
|
Write((void*)szData, uLen);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlString CHTTPClient::WebSocket_RecvText()
|
||||||
|
{
|
||||||
|
WebSocketFrame_t stFrame;
|
||||||
|
size_t uLen = 0;
|
||||||
|
CUtlBuffer<char> szText;
|
||||||
|
Read(&stFrame, 2);
|
||||||
|
if (stFrame.nPayloadLenght == 126)
|
||||||
|
{
|
||||||
|
Read(&uLen, 2);
|
||||||
|
} else if (stFrame.nPayloadLenght == 127)
|
||||||
|
{
|
||||||
|
Read(&uLen, 8);
|
||||||
|
} else {
|
||||||
|
uLen = stFrame.nPayloadLenght;
|
||||||
|
}
|
||||||
|
szText = CUtlBuffer<char>(uLen+1);
|
||||||
|
Read(szText, uLen);
|
||||||
|
szText[uLen] = 0;
|
||||||
|
return szText.GetMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHTTPClient::WebSocket_SendBinary( size_t uSize, const void *pData )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
WebSocketPacket_t CHTTPClient::WebSocket_RecvBinary()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ssize_t CHTTPClient::Write( void *pData, ssize_t uSize )
|
||||||
|
{
|
||||||
|
if (m_bIsSecure)
|
||||||
|
return SSL_write(m_pSSL, pData, uSize);
|
||||||
|
else
|
||||||
|
return write(m_iFileDescriptor, pData, uSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t CHTTPClient::Read( void *pData, ssize_t uSize )
|
||||||
|
{
|
||||||
|
ssize_t n;
|
||||||
|
if ( m_bIsSecure )
|
||||||
|
{
|
||||||
|
n = SSL_read(m_pSSL, pData, uSize);
|
||||||
|
if (n == 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
n = read(m_iFileDescriptor, pData, uSize);
|
||||||
|
if (n == -1)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
abstract_class CHTTPClientManager: public IHTTPClientManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CHTTPClientManager();
|
||||||
|
virtual IHTTPClient *Connect( const char *szUrl, bool bSecure, uint16_t *pPort ) override;
|
||||||
|
virtual void Disconnect( IHTTPClient *szConnection ) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
IHTTPClient *CHTTPClientManager::Connect( const char *szUrl, bool bSecure, uint16_t *pPort )
|
||||||
|
{
|
||||||
|
CHTTPClient *pClient;
|
||||||
|
pClient = new CHTTPClient();
|
||||||
|
if (pPort)
|
||||||
|
pClient->m_uPort = *pPort;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (bSecure)
|
||||||
|
pClient->m_uPort = 443;
|
||||||
|
else
|
||||||
|
pClient->m_uPort = 80;
|
||||||
|
}
|
||||||
|
pClient->m_szHostName = szUrl;
|
||||||
|
pClient->m_bIsSecure = bSecure;
|
||||||
return pClient;
|
return pClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,3 +545,4 @@ CHTTPClientManager::CHTTPClientManager()
|
|||||||
|
|
||||||
CHTTPClientManager s_HttpClientManager;
|
CHTTPClientManager s_HttpClientManager;
|
||||||
EXPOSE_INTERFACE_GLOBALVAR(IHTTPClientManager, CHTTPClientManager, HTTP_CLIENT_INTERFACE_VERSION, s_HttpClientManager);
|
EXPOSE_INTERFACE_GLOBALVAR(IHTTPClientManager, CHTTPClientManager, HTTP_CLIENT_INTERFACE_VERSION, s_HttpClientManager);
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ int main()
|
|||||||
g_pHttpClientMgr = (IHTTPClientManager*)pHttpFactory(HTTP_CLIENT_INTERFACE_VERSION, NULL);
|
g_pHttpClientMgr = (IHTTPClientManager*)pHttpFactory(HTTP_CLIENT_INTERFACE_VERSION, NULL);
|
||||||
if ( !g_pHttpClientMgr )
|
if ( !g_pHttpClientMgr )
|
||||||
return 0;
|
return 0;
|
||||||
IHTTPClient *pClient = g_pHttpClientMgr->Connect("ani.sidestore.io", true);
|
IHTTPClient *pClient = g_pHttpClientMgr->Connect("www.example.com", true, NULL);
|
||||||
printf("%p\n",pClient);
|
printf("%p\n",pClient);
|
||||||
if ( pClient == NULL )
|
if ( pClient == NULL )
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
16
public/appleauth/iauth.h
Normal file
16
public/appleauth/iauth.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#ifndef APPLE_AUTH_H
|
||||||
|
#define APPLE_AUTH_H
|
||||||
|
|
||||||
|
#include "tier0/platform.h"
|
||||||
|
#include "tier2/iappsystem.h"
|
||||||
|
|
||||||
|
abstract_class IAppleAuth: public IAppSystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void SubmitLoginData( const char *szEmail, const char *szPassword ) = 0;
|
||||||
|
virtual void Submit2FA( const char *szCode ) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
IAppleAuth *AppleAuth();
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -3,11 +3,12 @@
|
|||||||
|
|
||||||
#include "tier0/platform.h"
|
#include "tier0/platform.h"
|
||||||
#include "tier1/utlvector.h"
|
#include "tier1/utlvector.h"
|
||||||
|
#include "tier1/utlstring.h"
|
||||||
|
|
||||||
struct HTTPHeaderParam_t
|
struct HTTPHeaderParam_t
|
||||||
{
|
{
|
||||||
const char *m_szParamName;
|
CUtlString m_szParamName;
|
||||||
const char *m_szValue;
|
CUtlString m_szValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HTTPHeader_t
|
struct HTTPHeader_t
|
||||||
@@ -21,21 +22,35 @@ struct HTTPResponse_t
|
|||||||
CUtlBuffer<HTTPHeaderParam_t> m_params;
|
CUtlBuffer<HTTPHeaderParam_t> m_params;
|
||||||
CUtlBuffer<char> m_message;
|
CUtlBuffer<char> m_message;
|
||||||
uint32_t m_uCode;
|
uint32_t m_uCode;
|
||||||
bool bIsValid;
|
bool m_bIsComplete;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WebSocketPacket_t
|
||||||
|
{
|
||||||
|
size_t m_uSize;
|
||||||
|
void *m_pData;
|
||||||
};
|
};
|
||||||
|
|
||||||
abstract_class IHTTPClient
|
abstract_class IHTTPClient
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void Post( const char *szResource, HTTPHeader_t *pHeader, uint32_t uDataSize, const char *data ) = 0;
|
virtual void Post( const char *szResource, HTTPHeader_t *pHeader, uint32_t uDataSize, const void *data ) = 0;
|
||||||
virtual void Get( const char *szResource, HTTPHeader_t *pHeader ) = 0;
|
virtual void Get( const char *szResource, HTTPHeader_t *pHeader ) = 0;
|
||||||
|
|
||||||
|
virtual bool WebSocket_Connect( const char *szResource ) = 0;
|
||||||
|
virtual void WebSocket_Close( void ) = 0;
|
||||||
|
virtual void WebSocket_SendText( const char *szData ) = 0;
|
||||||
|
virtual CUtlString WebSocket_RecvText() = 0;
|
||||||
|
virtual void WebSocket_SendBinary( size_t uSize, const void *pData ) = 0;
|
||||||
|
virtual WebSocketPacket_t WebSocket_RecvBinary() = 0;
|
||||||
|
|
||||||
virtual HTTPResponse_t GetResponse() = 0;
|
virtual HTTPResponse_t GetResponse() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
abstract_class IHTTPClientManager
|
abstract_class IHTTPClientManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual IHTTPClient *Connect( const char *szUrl, bool bSecure ) = 0;
|
virtual IHTTPClient *Connect( const char *szUrl, bool bSecure, uint16_t *pPort ) = 0;
|
||||||
virtual void Disconnect( IHTTPClient *pClient ) = 0;
|
virtual void Disconnect( IHTTPClient *pClient ) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,23 @@
|
|||||||
#define POSIX
|
#define POSIX
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SWAP16(x) (uint16_t)((((x) >> 8) & 0x00FF) | \
|
||||||
|
(((x) << 8) & 0xFF00))
|
||||||
|
|
||||||
|
#define SWAP32(x) (uint32_t)((((x) >> 24) & 0x000000FF) | \
|
||||||
|
(((x) >> 8) & 0x0000FF00) | \
|
||||||
|
(((x) << 8) & 0x00FF0000) | \
|
||||||
|
(((x) << 24) & 0xFF000000))
|
||||||
|
|
||||||
|
#define SWAP64(x) ((uint64_t)( \
|
||||||
|
(((x) >> 56) & 0x00000000000000FFULL) | \
|
||||||
|
(((x) >> 40) & 0x000000000000FF00ULL) | \
|
||||||
|
(((x) >> 24) & 0x0000000000FF0000ULL) | \
|
||||||
|
(((x) >> 8) & 0x00000000FF000000ULL) | \
|
||||||
|
(((x) << 8) & 0x000000FF00000000ULL) | \
|
||||||
|
(((x) << 24) & 0x0000FF0000000000ULL) | \
|
||||||
|
(((x) << 40) & 0x00FF000000000000ULL) | \
|
||||||
|
(((x) << 56) & 0xFF00000000000000ULL) ))
|
||||||
|
|
||||||
#define abstract_class class
|
#define abstract_class class
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
#ifndef TIER2_JSON_H
|
||||||
|
#define TIER2_JSON_H
|
||||||
|
|
||||||
|
#include "tier0/platform.h"
|
||||||
|
|
||||||
|
class IJSONObject;
|
||||||
|
class IJSONArray;
|
||||||
|
class IJSONValue;
|
||||||
|
|
||||||
|
enum EJSONParameterType
|
||||||
|
{
|
||||||
|
JSON_PARAMETER_NULL,
|
||||||
|
JSON_PARAMETER_STRING,
|
||||||
|
JSON_PARAMETER_NUMBER,
|
||||||
|
JSON_PARAMETER_BOOLEAN,
|
||||||
|
JSON_PARAMETER_ARRAY,
|
||||||
|
JSON_PARAMETER_OBJECT,
|
||||||
|
};
|
||||||
|
|
||||||
|
abstract_class IJSONArray
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual uint32_t GetCount() = 0;
|
||||||
|
virtual IJSONObject *GetParameter( uint32_t i ) = 0;
|
||||||
|
|
||||||
|
virtual void SetArray( uint32_t uCount, IJSONValue *pValue ) = 0;
|
||||||
|
|
||||||
|
virtual void CopyTo( IJSONArray *pObject ) = 0;
|
||||||
|
virtual void Free() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
abstract_class IJSONValue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual EJSONParameterType GetType( void ) = 0;
|
||||||
|
virtual const char *GetStringValue() = 0;
|
||||||
|
virtual float GetNumberValue() = 0;
|
||||||
|
virtual bool GetBooleanValue() = 0;
|
||||||
|
virtual IJSONArray *GetArray() = 0;
|
||||||
|
virtual IJSONObject *GetObject() = 0;
|
||||||
|
|
||||||
|
virtual void MakeNULL() = 0;
|
||||||
|
virtual void SetStringValue( const char *szString ) = 0;
|
||||||
|
virtual void SetNumberValue( float fValue ) = 0;
|
||||||
|
virtual void SetBooleanValue( bool bValue ) = 0;
|
||||||
|
virtual void SetArrayValue( IJSONArray *pValue ) = 0;
|
||||||
|
virtual void SetObjectValue( IJSONObject *pValue ) = 0;
|
||||||
|
|
||||||
|
virtual void CopyTo( IJSONValue *pObject ) = 0;
|
||||||
|
virtual void Free() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
abstract_class IJSONObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual IJSONValue *GetValue( const char *szName ) = 0;
|
||||||
|
virtual void SetValue( const char *szName, IJSONValue *pValue ) = 0;
|
||||||
|
|
||||||
|
virtual void CopyTo( IJSONObject *pObject ) = 0;
|
||||||
|
virtual void Free() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
abstract_class IJSONManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual IJSONObject *CreateObject( ) = 0;
|
||||||
|
virtual void FreeObject( IJSONObject *pObject ) = 0;
|
||||||
|
virtual IJSONArray *CreateArray( ) = 0;
|
||||||
|
virtual void FreeArray( IJSONArray *pArray ) = 0;
|
||||||
|
virtual IJSONValue *CreateValue( ) = 0;
|
||||||
|
virtual void FreeValue( IJSONValue *pValue ) = 0;
|
||||||
|
|
||||||
|
virtual IJSONObject *ReadString( const char *szString ) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
IJSONManager *JSONManager();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
13
public/tier2/fileformats/plist.h
Normal file
13
public/tier2/fileformats/plist.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#ifndef TIER2_PLIST_H
|
||||||
|
#define TIER2_PLIST_H
|
||||||
|
|
||||||
|
#include "tier2/fileformats/json.h"
|
||||||
|
|
||||||
|
abstract_class IPropertyListManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual IJSONObject *ReadString( const char *psz ) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
IPropertyListManager *PropertyListManager();
|
||||||
|
#endif
|
||||||
69
public/tier2/fileformats/xml.h
Normal file
69
public/tier2/fileformats/xml.h
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
#ifndef TIER2_XML_H
|
||||||
|
#define TIER2_XML_H
|
||||||
|
|
||||||
|
#include "tier0/platform.h"
|
||||||
|
#include "tier1/utlstring.h"
|
||||||
|
|
||||||
|
struct XMLParam_t
|
||||||
|
{
|
||||||
|
CUtlString m_szName;
|
||||||
|
CUtlString m_szValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EXMLObjectType
|
||||||
|
{
|
||||||
|
XML_OBJECT_ELEMENT,
|
||||||
|
XML_OBJECT_TEXT,
|
||||||
|
XML_OBJECT_COMMENT,
|
||||||
|
XML_OBJECT_CDATA,
|
||||||
|
XML_OBJECT_PROCESSING_INSTRUCTION,
|
||||||
|
XML_OBJECT_DOCUMENT_TYPE,
|
||||||
|
};
|
||||||
|
|
||||||
|
abstract_class IXMLObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual EXMLObjectType GetType() = 0;
|
||||||
|
virtual const char *GetValue() = 0;
|
||||||
|
virtual void SetType( EXMLObjectType eType ) = 0;
|
||||||
|
virtual void SetValue( const char *psz ) = 0;
|
||||||
|
|
||||||
|
virtual CUtlVector<XMLParam_t> &GetParams() = 0;
|
||||||
|
|
||||||
|
virtual CUtlVector<IXMLObject*> &GetChildren() = 0;
|
||||||
|
|
||||||
|
virtual void Free() = 0;
|
||||||
|
|
||||||
|
inline IXMLObject *FindFirstTag( const char *szName )
|
||||||
|
{
|
||||||
|
for ( auto &c: GetChildren() )
|
||||||
|
{
|
||||||
|
if ( c->GetType() != XML_OBJECT_ELEMENT ) continue;
|
||||||
|
if ( V_strcmp(c->GetValue(), szName) ) continue;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct XMLFile_t
|
||||||
|
{
|
||||||
|
IXMLObject *m_pRoot;
|
||||||
|
CUtlString m_szRootObjectName;
|
||||||
|
CUtlString m_szFPI;
|
||||||
|
CUtlString m_szURI;
|
||||||
|
};
|
||||||
|
|
||||||
|
abstract_class IXMLManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual XMLFile_t ReadString( const char *szData ) = 0;
|
||||||
|
virtual CUtlString WriteString( IXMLObject *pObject ) = 0;
|
||||||
|
|
||||||
|
virtual IXMLObject *CreateObject() = 0;
|
||||||
|
virtual void FreeObject( IXMLObject *pObject ) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
IXMLManager *XMLManager();
|
||||||
|
|
||||||
|
#endif
|
||||||
21
public/tier2/tokenizer.h
Normal file
21
public/tier2/tokenizer.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#ifndef TIER2_TOKENIZER_H
|
||||||
|
#define TIER2_TOKENIZER_H
|
||||||
|
#include "tier0/platform.h"
|
||||||
|
#include "tier1/utlstring.h"
|
||||||
|
#include "tier1/utlvector.h"
|
||||||
|
|
||||||
|
struct Token_t
|
||||||
|
{
|
||||||
|
CUtlString m_szValue;
|
||||||
|
bool m_bIsQuoted;
|
||||||
|
|
||||||
|
uint32_t m_iLine;
|
||||||
|
uint32_t m_iCharacter;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef bool( *fnIsAlphabetSymbol )( char c );
|
||||||
|
CUtlVector<Token_t> Tokenize( const char *szString );
|
||||||
|
CUtlVector<Token_t> Tokenize( const char *szString, fnIsAlphabetSymbol pfnIsAlphabetSymbol );
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -7,6 +7,9 @@
|
|||||||
CUtlVector<CUtlString> tier2_CompiledFiles = {
|
CUtlVector<CUtlString> tier2_CompiledFiles = {
|
||||||
"fileformats/ini.cpp",
|
"fileformats/ini.cpp",
|
||||||
"fileformats/json.cpp",
|
"fileformats/json.cpp",
|
||||||
|
"fileformats/xml.cpp",
|
||||||
|
"fileformats/plist.cpp",
|
||||||
|
"tokenizer.cpp",
|
||||||
"filesystem.cpp",
|
"filesystem.cpp",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -142,8 +142,10 @@ IINIFile *CINIManager::ReadString( const char *psz )
|
|||||||
|
|
||||||
if (bIsQuoted)
|
if (bIsQuoted)
|
||||||
{
|
{
|
||||||
|
// text within ""
|
||||||
if (bIsSlash)
|
if (bIsSlash)
|
||||||
{
|
{
|
||||||
|
// reading \n \t etc.
|
||||||
bIsSlash = false;
|
bIsSlash = false;
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
@@ -157,8 +159,9 @@ IINIFile *CINIManager::ReadString( const char *psz )
|
|||||||
szStringValue.AppendTail('\n');
|
szStringValue.AppendTail('\n');
|
||||||
continue;
|
continue;
|
||||||
case 't':
|
case 't':
|
||||||
szStringValue.AppendTail('\n');
|
szStringValue.AppendTail('\t');
|
||||||
continue;
|
continue;
|
||||||
|
// allow for strings to go to next line with by ending with backward slash
|
||||||
case '\n':
|
case '\n':
|
||||||
szStringValue.AppendTail('\n');
|
szStringValue.AppendTail('\n');
|
||||||
continue;
|
continue;
|
||||||
@@ -167,16 +170,22 @@ IINIFile *CINIManager::ReadString( const char *psz )
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// react to special symbols witin a string
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// enables reading \n \t etc.
|
||||||
case '\\':
|
case '\\':
|
||||||
bIsSlash = true;
|
bIsSlash = true;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case '\n':
|
case '\n':
|
||||||
|
// newline
|
||||||
|
// we do want to end it to prevent parsing errors
|
||||||
|
// and there is no standart
|
||||||
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);
|
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 '"':
|
case '"':
|
||||||
|
// end string
|
||||||
bIsQuoted = false;
|
bIsQuoted = false;
|
||||||
if (szStringValue == 0)
|
if (szStringValue == 0)
|
||||||
continue;
|
continue;
|
||||||
@@ -190,6 +199,7 @@ IINIFile *CINIManager::ReadString( const char *psz )
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
// " makes it use a string
|
||||||
if (c == '"')
|
if (c == '"')
|
||||||
{
|
{
|
||||||
bIsQuoted = true;
|
bIsQuoted = true;
|
||||||
@@ -210,6 +220,9 @@ IINIFile *CINIManager::ReadString( const char *psz )
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// tokenize
|
||||||
|
// shitty tokenize
|
||||||
|
// must be reworked
|
||||||
for ( int i = 0; i < tokens.GetSize(); i++ )
|
for ( int i = 0; i < tokens.GetSize(); i++ )
|
||||||
{
|
{
|
||||||
if (tokens[i] == "]")
|
if (tokens[i] == "]")
|
||||||
|
|||||||
@@ -0,0 +1,401 @@
|
|||||||
|
#include "tier2/fileformats/json.h"
|
||||||
|
#include "tier2/tokenizer.h"
|
||||||
|
|
||||||
|
abstract_class CJSONArray: public IJSONArray
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual uint32_t GetCount() override;
|
||||||
|
virtual IJSONObject *GetParameter( uint32_t i ) override;
|
||||||
|
|
||||||
|
virtual void SetArray( uint32_t uCount, IJSONValue *pValue ) override;
|
||||||
|
|
||||||
|
virtual void CopyTo( IJSONArray *pObject ) override;
|
||||||
|
virtual void Free() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t CJSONArray::GetCount()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
IJSONObject *CJSONArray::GetParameter( uint32_t i )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CJSONArray::SetArray( uint32_t uCount, IJSONValue *pValue )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CJSONArray::CopyTo( IJSONArray *pObject )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CJSONArray::Free()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract_class CJSONValue: public IJSONValue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual EJSONParameterType GetType( void ) override;
|
||||||
|
virtual const char *GetStringValue() override;
|
||||||
|
virtual float GetNumberValue() override;
|
||||||
|
virtual bool GetBooleanValue() override;
|
||||||
|
virtual IJSONArray *GetArray() override;
|
||||||
|
virtual IJSONObject *GetObject() override;
|
||||||
|
|
||||||
|
virtual void MakeNULL() override;
|
||||||
|
virtual void SetStringValue( const char *szString ) override;
|
||||||
|
virtual void SetNumberValue( float fValue ) override;
|
||||||
|
virtual void SetBooleanValue( bool bValue ) override;
|
||||||
|
virtual void SetArrayValue( IJSONArray *pValue ) override;
|
||||||
|
virtual void SetObjectValue( IJSONObject *pValue ) override;
|
||||||
|
|
||||||
|
virtual void CopyTo( IJSONValue *pObject ) override;
|
||||||
|
virtual void Free() override;
|
||||||
|
|
||||||
|
EJSONParameterType m_eType;
|
||||||
|
CUtlString m_szString;
|
||||||
|
float m_fValue;
|
||||||
|
bool m_bValue;
|
||||||
|
IJSONArray *m_pArray;
|
||||||
|
IJSONObject *m_pObject;
|
||||||
|
};
|
||||||
|
|
||||||
|
EJSONParameterType CJSONValue::GetType( void )
|
||||||
|
{
|
||||||
|
return m_eType;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * CJSONValue::GetStringValue()
|
||||||
|
{
|
||||||
|
return m_szString;
|
||||||
|
}
|
||||||
|
|
||||||
|
float CJSONValue::GetNumberValue()
|
||||||
|
{
|
||||||
|
return m_fValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CJSONValue::GetBooleanValue()
|
||||||
|
{
|
||||||
|
return m_fValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
IJSONArray *CJSONValue::GetArray()
|
||||||
|
{
|
||||||
|
return m_pArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
IJSONObject *CJSONValue::GetObject()
|
||||||
|
{
|
||||||
|
return m_pObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CJSONValue::MakeNULL()
|
||||||
|
{
|
||||||
|
if ( GetType() == JSON_PARAMETER_OBJECT )
|
||||||
|
{
|
||||||
|
JSONManager()->FreeObject(m_pObject);
|
||||||
|
m_pObject = NULL;
|
||||||
|
}
|
||||||
|
if ( GetType() == JSON_PARAMETER_ARRAY )
|
||||||
|
{
|
||||||
|
|
||||||
|
JSONManager()->FreeArray(m_pArray);
|
||||||
|
m_pArray = NULL;
|
||||||
|
}
|
||||||
|
if ( GetType() == JSON_PARAMETER_STRING )
|
||||||
|
m_szString = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CJSONValue::SetStringValue( const char *szString )
|
||||||
|
{
|
||||||
|
MakeNULL();
|
||||||
|
m_szString = szString;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CJSONValue::SetNumberValue( float fValue )
|
||||||
|
{
|
||||||
|
MakeNULL();
|
||||||
|
m_fValue = fValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CJSONValue::SetBooleanValue( bool bValue )
|
||||||
|
{
|
||||||
|
MakeNULL();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CJSONValue::SetArrayValue( IJSONArray *pValue )
|
||||||
|
{
|
||||||
|
MakeNULL();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CJSONValue::SetObjectValue( IJSONObject *pValue )
|
||||||
|
{
|
||||||
|
MakeNULL();
|
||||||
|
m_pObject = pValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CJSONValue::CopyTo( IJSONValue *pObject )
|
||||||
|
{
|
||||||
|
MakeNULL();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CJSONValue::Free()
|
||||||
|
{
|
||||||
|
MakeNULL();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
abstract_class CJSONObject: public IJSONObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual IJSONValue *GetValue( const char *szName ) override;
|
||||||
|
virtual void SetValue( const char *szName, IJSONValue *pValue ) override;
|
||||||
|
|
||||||
|
virtual void CopyTo( IJSONObject *pObject ) override;
|
||||||
|
virtual void Free() override;
|
||||||
|
|
||||||
|
struct JSONObjectParam_t
|
||||||
|
{
|
||||||
|
CUtlString m_szName;
|
||||||
|
IJSONValue *m_pValue;
|
||||||
|
};
|
||||||
|
CUtlVector<JSONObjectParam_t> m_params;
|
||||||
|
};
|
||||||
|
|
||||||
|
IJSONValue *CJSONObject::GetValue( const char *szName )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
JSONObjectParam_t *pParam;
|
||||||
|
for ( i = 0; i < m_params.GetSize(); i++ )
|
||||||
|
{
|
||||||
|
if ( m_params[i].m_szName != szName )
|
||||||
|
continue;
|
||||||
|
return m_params[i].m_pValue;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CJSONObject::SetValue( const char *szName, IJSONValue *pValue )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
JSONObjectParam_t *pParam;
|
||||||
|
for ( i = 0; i < m_params.GetSize(); i++ )
|
||||||
|
{
|
||||||
|
if ( m_params[i].m_szName != szName )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
|
||||||
|
// Scary
|
||||||
|
if ( pValue == NULL )
|
||||||
|
m_params.RemoveAt(i);
|
||||||
|
else
|
||||||
|
m_params[i].m_pValue = pValue;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( pValue == NULL )
|
||||||
|
return;
|
||||||
|
m_params.AppendTail({szName, pValue});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CJSONObject::CopyTo( IJSONObject *pObject )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CJSONObject::Free()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract_class CJSONManager: public IJSONManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual IJSONObject *CreateObject( ) override;
|
||||||
|
virtual void FreeObject( IJSONObject *pObject ) override;
|
||||||
|
virtual IJSONArray *CreateArray( ) override;
|
||||||
|
virtual void FreeArray( IJSONArray *pArray ) override;
|
||||||
|
virtual IJSONValue *CreateValue( ) override;
|
||||||
|
virtual void FreeValue( IJSONValue *pValue ) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool ExpectedToken( Token_t &token, const char *szValue );
|
||||||
|
static CUtlString GetQuotedToken( Token_t &token );
|
||||||
|
IJSONObject *ParseObject( Token_t *&pToken, const Token_t *pEnding );
|
||||||
|
IJSONArray *ParseArray( Token_t *&pToken, const Token_t *pEnding );
|
||||||
|
IJSONValue *ParseValue( Token_t *&pToken, const Token_t *pEnding );
|
||||||
|
virtual IJSONObject *ReadString( const char *szString ) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
IJSONObject *CJSONManager::CreateObject( )
|
||||||
|
{
|
||||||
|
return new CJSONObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CJSONManager::FreeObject( IJSONObject *pObject )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
IJSONArray *CJSONManager::CreateArray( )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CJSONManager::FreeArray( IJSONArray *pArray )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
IJSONValue *CJSONManager::CreateValue( )
|
||||||
|
{
|
||||||
|
return new CJSONValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CJSONManager::FreeValue( IJSONValue *pValue )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#define NEXT_TOKEN() \
|
||||||
|
pToken++; \
|
||||||
|
if (pToken == pEnding) \
|
||||||
|
goto eof \
|
||||||
|
|
||||||
|
bool CJSONManager::ExpectedToken( Token_t &token, const char *szValue )
|
||||||
|
{
|
||||||
|
if ( token.m_szValue == szValue && !token.m_bIsQuoted )
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
CUtlString CJSONManager::GetQuotedToken( Token_t &token )
|
||||||
|
{
|
||||||
|
if ( token.m_bIsQuoted )
|
||||||
|
return token.m_szValue;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
IJSONObject *CJSONManager::ParseObject( Token_t *&pToken, const Token_t *pEnding )
|
||||||
|
{
|
||||||
|
IJSONObject *pObject;
|
||||||
|
CUtlString szParamName;
|
||||||
|
IJSONValue *pValue;
|
||||||
|
|
||||||
|
if ( !ExpectedToken(*(pToken), "{") )
|
||||||
|
return NULL;
|
||||||
|
NEXT_TOKEN();
|
||||||
|
pObject = CreateObject();
|
||||||
|
|
||||||
|
// object might be empty
|
||||||
|
if ( ExpectedToken(*pToken, "}") )
|
||||||
|
{
|
||||||
|
NEXT_TOKEN();
|
||||||
|
return pObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
szParamName = NULL;
|
||||||
|
pValue = NULL;
|
||||||
|
if ( GetQuotedToken(*pToken) == NULL )
|
||||||
|
goto not_quoted;
|
||||||
|
|
||||||
|
szParamName = pToken->m_szValue;
|
||||||
|
NEXT_TOKEN();
|
||||||
|
|
||||||
|
if ( !ExpectedToken(*pToken, ":") )
|
||||||
|
goto not_colon;
|
||||||
|
NEXT_TOKEN();
|
||||||
|
|
||||||
|
pValue = ParseValue(pToken, pEnding);
|
||||||
|
pObject->SetValue(szParamName, pValue);
|
||||||
|
|
||||||
|
if ( !ExpectedToken(*pToken, ",") )
|
||||||
|
{
|
||||||
|
if ( !ExpectedToken(*pToken, "}") )
|
||||||
|
{
|
||||||
|
goto not_comma;
|
||||||
|
}
|
||||||
|
return pObject;
|
||||||
|
}
|
||||||
|
NEXT_TOKEN();
|
||||||
|
}
|
||||||
|
return pObject;
|
||||||
|
not_comma:
|
||||||
|
V_printf("%i: comma (,) or } was expected but got %s\n", pToken->m_iLine, pToken->m_szValue.GetString());
|
||||||
|
return NULL;
|
||||||
|
not_colon:
|
||||||
|
V_printf("%i: colon (:)was expected but got %s\n", pToken->m_iLine, pToken->m_szValue.GetString());
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
not_quoted:
|
||||||
|
V_printf("%s was not quoted\n", szParamName.GetString());
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
eof:
|
||||||
|
V_printf("EOF\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
IJSONArray *CJSONManager::ParseArray( Token_t *&pToken, const Token_t *pEnding )
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
eof:
|
||||||
|
V_printf("EOF\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
IJSONValue *CJSONManager::ParseValue( Token_t *&pToken, const Token_t *pEnding )
|
||||||
|
{
|
||||||
|
IJSONObject *pObject = ParseObject(pToken, pEnding);
|
||||||
|
IJSONArray *pArray = NULL;
|
||||||
|
IJSONValue *pValue = CreateValue();
|
||||||
|
if (pObject)
|
||||||
|
{
|
||||||
|
pValue->SetObjectValue(pObject);
|
||||||
|
return pValue;
|
||||||
|
}
|
||||||
|
if ( GetQuotedToken(*pToken) != NULL )
|
||||||
|
{
|
||||||
|
pValue->SetStringValue(pToken->m_szValue);
|
||||||
|
NEXT_TOKEN();
|
||||||
|
return pValue;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
eof:
|
||||||
|
V_printf("EOF\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IJSONObject *CJSONManager::ReadString( const char *psz )
|
||||||
|
{
|
||||||
|
CUtlVector<Token_t> tokens;
|
||||||
|
CUtlVector<char> stack;
|
||||||
|
IJSONObject *pGlobalObject = NULL;
|
||||||
|
|
||||||
|
tokens = Tokenize(psz);
|
||||||
|
Token_t *pCurrentToken = tokens.GetData();
|
||||||
|
pGlobalObject = ParseObject(pCurrentToken, tokens.end().m_pCurrent);
|
||||||
|
|
||||||
|
return pGlobalObject;
|
||||||
|
};
|
||||||
|
|
||||||
|
IJSONManager *JSONManager()
|
||||||
|
{
|
||||||
|
static CJSONManager mgr;
|
||||||
|
return &mgr;
|
||||||
|
}
|
||||||
|
|||||||
69
tier2/fileformats/plist.cpp
Normal file
69
tier2/fileformats/plist.cpp
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
#include "tier2/fileformats/xml.h"
|
||||||
|
#include "tier2/fileformats/plist.h"
|
||||||
|
|
||||||
|
class CPropertyListManager: public IPropertyListManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IJSONObject *ReadDict( IXMLObject *pDict );
|
||||||
|
virtual IJSONObject *ReadString( const char *psz ) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
IJSONObject *CPropertyListManager::ReadString( const char *psz )
|
||||||
|
{
|
||||||
|
XMLFile_t file = XMLManager()->ReadString(psz);
|
||||||
|
IJSONObject *pObject;
|
||||||
|
|
||||||
|
IXMLObject *pList = file.m_pRoot->FindFirstTag(file.m_szRootObjectName);
|
||||||
|
if (pList == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
IXMLObject *pDict = pList->FindFirstTag("dict");
|
||||||
|
if (pDict == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
|
||||||
|
pObject = ReadDict(pDict);
|
||||||
|
return pObject;
|
||||||
|
}
|
||||||
|
IJSONObject *CPropertyListManager::ReadDict( IXMLObject *pDict )
|
||||||
|
{
|
||||||
|
CUtlString szKeyToCreate = NULL;
|
||||||
|
IJSONObject *pObject = JSONManager()->CreateObject();
|
||||||
|
for ( auto &c: pDict->GetChildren() )
|
||||||
|
{
|
||||||
|
if (c->GetType() != XML_OBJECT_ELEMENT)
|
||||||
|
continue;
|
||||||
|
if ( !V_strcmp(c->GetValue(), "key"))
|
||||||
|
{
|
||||||
|
szKeyToCreate = c->GetChildren()[0]->GetValue();
|
||||||
|
}
|
||||||
|
if ( !V_strcmp(c->GetValue(), "string"))
|
||||||
|
{
|
||||||
|
if ( szKeyToCreate == NULL )
|
||||||
|
continue;
|
||||||
|
IJSONValue *pVal = JSONManager()->CreateValue();
|
||||||
|
if (c->GetChildren().GetSize()>0)
|
||||||
|
pVal->SetStringValue(c->GetChildren()[0]->GetValue());
|
||||||
|
else
|
||||||
|
pVal->SetStringValue("");
|
||||||
|
pObject->SetValue(szKeyToCreate, pVal);
|
||||||
|
szKeyToCreate = NULL;
|
||||||
|
}
|
||||||
|
if ( !V_strcmp(c->GetValue(), "dict"))
|
||||||
|
{
|
||||||
|
if ( szKeyToCreate == NULL )
|
||||||
|
continue;
|
||||||
|
IJSONValue *pVal = JSONManager()->CreateValue();
|
||||||
|
pVal->SetObjectValue(ReadDict(c));
|
||||||
|
pObject->SetValue(szKeyToCreate, pVal);
|
||||||
|
szKeyToCreate = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPropertyListManager *PropertyListManager()
|
||||||
|
{
|
||||||
|
static CPropertyListManager mgr = {};
|
||||||
|
return &mgr;
|
||||||
|
}
|
||||||
420
tier2/fileformats/xml.cpp
Normal file
420
tier2/fileformats/xml.cpp
Normal file
@@ -0,0 +1,420 @@
|
|||||||
|
#include "tier2/fileformats/xml.h"
|
||||||
|
#include "tier2/tokenizer.h"
|
||||||
|
|
||||||
|
class CXMLObject: public IXMLObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual EXMLObjectType GetType() override;
|
||||||
|
virtual const char *GetValue() override;
|
||||||
|
virtual void SetType( EXMLObjectType eType ) override;
|
||||||
|
virtual void SetValue( const char *psz ) override;
|
||||||
|
virtual CUtlVector<IXMLObject*> &GetChildren() override;
|
||||||
|
virtual CUtlVector<XMLParam_t> &GetParams() override;
|
||||||
|
virtual void Free() override;
|
||||||
|
|
||||||
|
EXMLObjectType m_eType;
|
||||||
|
CUtlString m_szValue;
|
||||||
|
CUtlVector<IXMLObject*> m_children;
|
||||||
|
CUtlVector<XMLParam_t> m_params;
|
||||||
|
};
|
||||||
|
|
||||||
|
EXMLObjectType CXMLObject::GetType()
|
||||||
|
{
|
||||||
|
return m_eType;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *CXMLObject::GetValue()
|
||||||
|
{
|
||||||
|
return m_szValue.GetString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CXMLObject::SetType( EXMLObjectType eType )
|
||||||
|
{
|
||||||
|
m_eType = eType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CXMLObject::SetValue( const char *psz )
|
||||||
|
{
|
||||||
|
m_szValue = psz;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CUtlVector<IXMLObject*> &CXMLObject::GetChildren()
|
||||||
|
{
|
||||||
|
return m_children;
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlVector<XMLParam_t> &CXMLObject::GetParams()
|
||||||
|
{
|
||||||
|
return m_params;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CXMLObject::Free()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class CXMLManager: public IXMLManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual XMLFile_t ReadString( const char *szData ) override;
|
||||||
|
virtual CUtlString WriteString( IXMLObject *pObject ) override;
|
||||||
|
|
||||||
|
virtual IXMLObject *CreateObject() override;
|
||||||
|
virtual void FreeObject( IXMLObject *pObject ) override;
|
||||||
|
|
||||||
|
IXMLObject *ReadTagParams( CUtlString szTag );
|
||||||
|
XMLFile_t ReadDoctype( const char *szData );
|
||||||
|
|
||||||
|
bool BIsValidAtStart( char c );
|
||||||
|
bool BIsValidAtMid( char c );
|
||||||
|
void SkipWhiteSpaces( const char *&psz );
|
||||||
|
};
|
||||||
|
|
||||||
|
static char XML_TAG[] = "<";
|
||||||
|
static char XML_TAG_END[] = ">";
|
||||||
|
static char XML_SELF_CLOSE_END[] = "/>";
|
||||||
|
static char XML_CLOSE_TAG[] = "</";
|
||||||
|
static char XML_DOCTYPE[] = "<!DOCTYPE";
|
||||||
|
static char XML_PREPROCESSOR_BEGIN[] = "<?";
|
||||||
|
static char XML_PREPROCESSOR_END[] = "?>";
|
||||||
|
|
||||||
|
XMLFile_t CXMLManager::ReadString( const char *szString )
|
||||||
|
{
|
||||||
|
CUtlString szTagStack = {};
|
||||||
|
CUtlString szRootObjectName;
|
||||||
|
IXMLObject *pRootObject = CreateObject();
|
||||||
|
IXMLObject *pLastObject = pRootObject;
|
||||||
|
CUtlVector<IXMLObject*> stack = {pRootObject};
|
||||||
|
|
||||||
|
enum EXMLParsingMode
|
||||||
|
{
|
||||||
|
XML_PARSING_MODE_TEXT,
|
||||||
|
XML_PARSING_MODE_PREPROCESS_TAG,
|
||||||
|
XML_PARSING_MODE_TAG,
|
||||||
|
XML_PARSING_MODE_CLOSE_TAG,
|
||||||
|
XML_PARSING_MODE_DOCTYPE,
|
||||||
|
XML_PARSING_MODE_COMMENT,
|
||||||
|
} eMode = XML_PARSING_MODE_TEXT;
|
||||||
|
|
||||||
|
const char *psz = szString;
|
||||||
|
CUtlString szTag = "";
|
||||||
|
CUtlString szText = "";
|
||||||
|
XMLFile_t stFile = {};
|
||||||
|
while (*psz)
|
||||||
|
{
|
||||||
|
switch (eMode)
|
||||||
|
{
|
||||||
|
case XML_PARSING_MODE_TEXT:
|
||||||
|
if (!V_strncmp(XML_DOCTYPE, psz, sizeof(XML_DOCTYPE)-1))
|
||||||
|
{
|
||||||
|
psz+=sizeof(XML_DOCTYPE)-1;
|
||||||
|
szTag = NULL;
|
||||||
|
|
||||||
|
eMode = XML_PARSING_MODE_DOCTYPE;
|
||||||
|
if (szText != NULL)
|
||||||
|
{
|
||||||
|
IXMLObject *pText = CreateObject();
|
||||||
|
pText->SetType(XML_OBJECT_TEXT);
|
||||||
|
pText->SetValue(szText);
|
||||||
|
pLastObject->GetChildren().AppendTail(pText);
|
||||||
|
szText = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!V_strncmp(XML_PREPROCESSOR_BEGIN, psz, sizeof(XML_PREPROCESSOR_BEGIN)-1))
|
||||||
|
{
|
||||||
|
psz+=sizeof(XML_PREPROCESSOR_BEGIN)-1;
|
||||||
|
szTag = NULL;
|
||||||
|
|
||||||
|
eMode = XML_PARSING_MODE_PREPROCESS_TAG;
|
||||||
|
if (szText != NULL)
|
||||||
|
{
|
||||||
|
IXMLObject *pText = CreateObject();
|
||||||
|
pText->SetType(XML_OBJECT_TEXT);
|
||||||
|
pText->SetValue(szText);
|
||||||
|
pLastObject->GetChildren().AppendTail(pText);
|
||||||
|
szText = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!V_strncmp(XML_CLOSE_TAG, psz, sizeof(XML_CLOSE_TAG)-1))
|
||||||
|
{
|
||||||
|
psz+=sizeof(XML_CLOSE_TAG)-1;
|
||||||
|
szTag = NULL;
|
||||||
|
|
||||||
|
eMode = XML_PARSING_MODE_CLOSE_TAG;
|
||||||
|
if (szText != NULL)
|
||||||
|
{
|
||||||
|
IXMLObject *pText = CreateObject();
|
||||||
|
pText->SetType(XML_OBJECT_TEXT);
|
||||||
|
pText->SetValue(szText);
|
||||||
|
pLastObject->GetChildren().AppendTail(pText);
|
||||||
|
szText = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!V_strncmp(XML_TAG, psz, sizeof(XML_TAG)-1))
|
||||||
|
{
|
||||||
|
psz+=sizeof(XML_TAG)-1;
|
||||||
|
szTag = NULL;
|
||||||
|
|
||||||
|
eMode = XML_PARSING_MODE_TAG;
|
||||||
|
if (szText != NULL)
|
||||||
|
{
|
||||||
|
IXMLObject *pText = CreateObject();
|
||||||
|
pText->SetType(XML_OBJECT_TEXT);
|
||||||
|
pText->SetValue(szText);
|
||||||
|
pLastObject->GetChildren().AppendTail(pText);
|
||||||
|
szText = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
szText.AppendTail(*psz);
|
||||||
|
psz++;
|
||||||
|
break;
|
||||||
|
case XML_PARSING_MODE_PREPROCESS_TAG:
|
||||||
|
if (!V_strncmp(XML_PREPROCESSOR_END, psz, sizeof(XML_PREPROCESSOR_END)-1))
|
||||||
|
{
|
||||||
|
psz+=sizeof(XML_PREPROCESSOR_END)-1;
|
||||||
|
eMode = XML_PARSING_MODE_TEXT;
|
||||||
|
V_printf("preprocess: %s\n", szTag.GetString());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
szTag.AppendTail(*psz);
|
||||||
|
psz++;
|
||||||
|
break;
|
||||||
|
case XML_PARSING_MODE_TAG:
|
||||||
|
if (!V_strncmp(XML_SELF_CLOSE_END, psz, sizeof(XML_SELF_CLOSE_END)-1))
|
||||||
|
{
|
||||||
|
psz+=sizeof(XML_SELF_CLOSE_END)-1;
|
||||||
|
eMode = XML_PARSING_MODE_TEXT;
|
||||||
|
IXMLObject *pObject = ReadTagParams(szTag);
|
||||||
|
pLastObject->GetChildren().AppendTail(pObject);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!V_strncmp(XML_TAG_END, psz, sizeof(XML_TAG_END)-1))
|
||||||
|
{
|
||||||
|
psz+=sizeof(XML_TAG_END)-1;
|
||||||
|
eMode = XML_PARSING_MODE_TEXT;
|
||||||
|
IXMLObject *pObject = ReadTagParams(szTag);
|
||||||
|
stack.AppendTail(pObject);
|
||||||
|
pLastObject->GetChildren().AppendTail(pObject);
|
||||||
|
pLastObject = pObject;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
szTag.AppendTail(*psz);
|
||||||
|
psz++;
|
||||||
|
break;
|
||||||
|
case XML_PARSING_MODE_CLOSE_TAG:
|
||||||
|
if (!V_strncmp(XML_TAG_END, psz, sizeof(XML_TAG_END)-1))
|
||||||
|
{
|
||||||
|
psz+=sizeof(XML_TAG_END)-1;
|
||||||
|
eMode = XML_PARSING_MODE_TEXT;
|
||||||
|
|
||||||
|
|
||||||
|
if (!V_strcmp(pLastObject->GetValue(), szTag))
|
||||||
|
{
|
||||||
|
stack.RemoveTail();
|
||||||
|
pLastObject = stack[stack.GetSize()-1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
V_printf("\"%s\" != \"%s\"\n",pLastObject->GetValue(), szTag.GetString());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
szTag.AppendTail(*psz);
|
||||||
|
psz++;
|
||||||
|
break;
|
||||||
|
case XML_PARSING_MODE_DOCTYPE:
|
||||||
|
if (!V_strncmp(XML_TAG_END, psz, sizeof(XML_TAG_END)-1))
|
||||||
|
{
|
||||||
|
psz+=sizeof(XML_TAG_END)-1;
|
||||||
|
eMode = XML_PARSING_MODE_TEXT;
|
||||||
|
|
||||||
|
stFile = ReadDoctype(szTag);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
szTag.AppendTail(*psz);
|
||||||
|
psz++;
|
||||||
|
break;
|
||||||
|
case XML_PARSING_MODE_COMMENT:
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
stFile.m_pRoot = pRootObject;
|
||||||
|
return stFile;
|
||||||
|
}
|
||||||
|
CUtlString CXMLManager::WriteString( IXMLObject *pObject )
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
IXMLObject *CXMLManager::ReadTagParams( CUtlString szTag )
|
||||||
|
{
|
||||||
|
const char *psz = szTag;
|
||||||
|
CUtlVector<XMLParam_t> params;
|
||||||
|
CUtlString szTagName = NULL;
|
||||||
|
CUtlString szParamName = NULL;
|
||||||
|
IXMLObject *pObject = CreateObject();
|
||||||
|
// Read tag name
|
||||||
|
if (!BIsValidAtStart(*psz))
|
||||||
|
{
|
||||||
|
V_printf("tag must start with letter or _");
|
||||||
|
FreeObject(pObject);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
szTagName.AppendTail(*psz++);
|
||||||
|
while (BIsValidAtMid(*psz))
|
||||||
|
{
|
||||||
|
szTagName.AppendTail(*psz);
|
||||||
|
psz++;
|
||||||
|
}
|
||||||
|
pObject->SetType(XML_OBJECT_ELEMENT);
|
||||||
|
pObject->SetValue(szTagName);
|
||||||
|
|
||||||
|
while (*psz)
|
||||||
|
{
|
||||||
|
while (V_isspace(*psz))
|
||||||
|
{
|
||||||
|
psz++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (*psz && (!V_isalpha(*psz) || *psz == '_'))
|
||||||
|
{
|
||||||
|
V_printf("parameter must start with letter or _\n");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
while (*psz && (*psz != ' ' || *psz != '='))
|
||||||
|
{
|
||||||
|
psz++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
while (V_isspace(*psz))
|
||||||
|
{
|
||||||
|
psz++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
szParamName.AppendTail(*psz);
|
||||||
|
};
|
||||||
|
return pObject;
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool XMLGetWordSymbol( char c )
|
||||||
|
{
|
||||||
|
if (V_isalnum(c))
|
||||||
|
return true;
|
||||||
|
switch(c)
|
||||||
|
{
|
||||||
|
case ':':
|
||||||
|
return true;
|
||||||
|
case '.':
|
||||||
|
return true;
|
||||||
|
case '_':
|
||||||
|
return true;
|
||||||
|
case '-':
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
XMLFile_t CXMLManager::ReadDoctype( const char *szData )
|
||||||
|
{
|
||||||
|
const char *psz = szData;
|
||||||
|
XMLFile_t stFile = {};
|
||||||
|
CUtlString dtdType = NULL;
|
||||||
|
CUtlVector<Token_t> tokens;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if (!V_isspace(*psz))
|
||||||
|
return stFile;
|
||||||
|
|
||||||
|
SkipWhiteSpaces(psz);
|
||||||
|
|
||||||
|
tokens = Tokenize(psz, XMLGetWordSymbol);
|
||||||
|
if ( tokens.GetSize() < i + 1 )
|
||||||
|
return stFile;
|
||||||
|
if ( tokens[i].m_bIsQuoted )
|
||||||
|
return stFile;
|
||||||
|
|
||||||
|
stFile.m_szRootObjectName = tokens[i++].m_szValue;
|
||||||
|
|
||||||
|
// parse ddt
|
||||||
|
if ( tokens.GetSize() < i + 1 )
|
||||||
|
return stFile;
|
||||||
|
|
||||||
|
if ( tokens[i].m_szValue == "PUBLIC" && !tokens[i].m_bIsQuoted )
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
if ( tokens.GetSize() < i + 2 )
|
||||||
|
return stFile;
|
||||||
|
if (!tokens[i].m_bIsQuoted || !tokens[i+1].m_bIsQuoted)
|
||||||
|
return stFile;
|
||||||
|
stFile.m_szFPI = tokens[i++].m_szValue;
|
||||||
|
stFile.m_szURI = tokens[i++].m_szValue;
|
||||||
|
} else if ( tokens[i].m_szValue == "SYSTEM" && !tokens[i].m_bIsQuoted )
|
||||||
|
{
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// read root element
|
||||||
|
return stFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CXMLManager::BIsValidAtStart( char c )
|
||||||
|
{
|
||||||
|
if (V_isalpha(c))
|
||||||
|
return true;
|
||||||
|
if (c == '_')
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CXMLManager::BIsValidAtMid( char c )
|
||||||
|
{
|
||||||
|
if (V_isalnum(c))
|
||||||
|
return true;
|
||||||
|
if (c == '_')
|
||||||
|
return true;
|
||||||
|
if (c == '-')
|
||||||
|
return true;
|
||||||
|
if (c == '.')
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void CXMLManager::SkipWhiteSpaces( const char *&psz )
|
||||||
|
{
|
||||||
|
while (V_isspace(*psz))
|
||||||
|
{
|
||||||
|
psz++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IXMLObject *CXMLManager::CreateObject()
|
||||||
|
{
|
||||||
|
return new CXMLObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CXMLManager::FreeObject( IXMLObject *pObject )
|
||||||
|
{
|
||||||
|
pObject->Free();
|
||||||
|
delete (CXMLObject*)pObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IXMLManager *XMLManager()
|
||||||
|
{
|
||||||
|
static CXMLManager mgr;
|
||||||
|
return &mgr;
|
||||||
|
};
|
||||||
124
tier2/tokenizer.cpp
Normal file
124
tier2/tokenizer.cpp
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
#include "tier2/tokenizer.h"
|
||||||
|
|
||||||
|
static bool IsWordSymbol( char c )
|
||||||
|
{
|
||||||
|
if (V_isalnum(c))
|
||||||
|
return true;
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case '_':
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlVector<Token_t> Tokenize( const char *psz )
|
||||||
|
{
|
||||||
|
return Tokenize(psz, IsWordSymbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlVector<Token_t> Tokenize( const char *psz, fnIsAlphabetSymbol fnIsAlphabetSymbol )
|
||||||
|
{
|
||||||
|
CUtlVector<Token_t> tokens = {};
|
||||||
|
size_t i = 0;
|
||||||
|
char c;
|
||||||
|
uint32_t nCurrentLine = 0;
|
||||||
|
uint32_t nCurrentCharacter = 0;
|
||||||
|
bool bIsQuoted = false;
|
||||||
|
bool bIsSlash = false;
|
||||||
|
CUtlString szStringValue;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
c = psz[i];
|
||||||
|
i++;
|
||||||
|
if (c == '\0')
|
||||||
|
break;
|
||||||
|
if (c == '\n')
|
||||||
|
{
|
||||||
|
nCurrentCharacter = 0;
|
||||||
|
nCurrentLine++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (bIsQuoted)
|
||||||
|
{
|
||||||
|
// text within ""
|
||||||
|
if (bIsSlash)
|
||||||
|
{
|
||||||
|
// reading \n \t etc.
|
||||||
|
bIsSlash = false;
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case '\\':
|
||||||
|
szStringValue.AppendTail('\\');
|
||||||
|
continue;
|
||||||
|
case '"':
|
||||||
|
szStringValue.AppendTail('"');
|
||||||
|
continue;
|
||||||
|
case 'n':
|
||||||
|
szStringValue.AppendTail('\n');
|
||||||
|
continue;
|
||||||
|
case 't':
|
||||||
|
szStringValue.AppendTail('\t');
|
||||||
|
continue;
|
||||||
|
// allow for strings to go to next line with by ending with backward slash
|
||||||
|
case '\n':
|
||||||
|
szStringValue.AppendTail('\n');
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
szStringValue.AppendTail(c);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// react to special symbols witin a string
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
|
||||||
|
// enables reading \n \t etc.
|
||||||
|
case '\\':
|
||||||
|
bIsSlash = true;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case '\n':
|
||||||
|
// newline
|
||||||
|
// we do want to end it to prevent parsing errors
|
||||||
|
// and there is no standart
|
||||||
|
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 '"':
|
||||||
|
// end string
|
||||||
|
bIsQuoted = false;
|
||||||
|
if (szStringValue == 0)
|
||||||
|
continue;
|
||||||
|
tokens.AppendTail({szStringValue, true, nCurrentLine});
|
||||||
|
szStringValue = 0;
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
szStringValue.AppendTail(c);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// " makes it use a string
|
||||||
|
if (c == '"')
|
||||||
|
{
|
||||||
|
bIsQuoted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fnIsAlphabetSymbol(c))
|
||||||
|
{
|
||||||
|
szStringValue.AppendTail(c);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
if (szStringValue != 0)
|
||||||
|
tokens.AppendTail({szStringValue, false, nCurrentLine});
|
||||||
|
szStringValue = 0;
|
||||||
|
if (V_isgraph(c) && c != '"')
|
||||||
|
tokens.AppendTail({CUtlString("%c", c), false, nCurrentLine});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return tokens;
|
||||||
|
};
|
||||||
0
tier2/uuid.cpp
Normal file
0
tier2/uuid.cpp
Normal file
Reference in New Issue
Block a user