📄 scripting.cpp
字号:
/*
* Roadnav
* Scripting.cpp
*
* Copyright (c) 2004 - 2006 Richard L. Lynch <rllynch@users.sourceforge.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public License
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
//////////////////////////////////////////////////////////////////////////////
/// \file
///
/// Scripting class
///
//////////////////////////////////////////////////////////////////////////////
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef HAVE_MATH_H
#include <math.h>
#endif
#ifdef _MSC_VER
#pragma warning(disable: 4786)
#endif
#include <wx/wx.h>
#include <wx/tokenzr.h>
#include <wx/wfstream.h>
#include <wx/socket.h>
#include <wx/sckstrm.h>
#include "libroadnav/MapLookup.h"
#include "libroadnav/MapSupport.h"
#include "App.h"
#include "Scripting.h"
#ifdef USE_SCRIPTING
using namespace std;
//////////////////////////////////////////////////////////////////////////////
///
/// \brief Remove and return the front of an STL list
///
//////////////////////////////////////////////////////////////////////////////
wxString PopFrontAndReturn(list<wxString> & lList)
{
wxString strRtn;
strRtn = lList.front();
lList.pop_front();
return strRtn;
}
wxString GetScriptExportFilename()
{
wxString strRtn = g_pConfig->Read(wxT("ScriptingExportScriptFilename"), wxT(""));
return strRtn;
}
bool GetScriptAppendMode()
{
return true;
}
//////////////////////////////////////////////////////////////////////////////
///
/// \brief ScriptStream constructor - initialize all member variables
///
//////////////////////////////////////////////////////////////////////////////
ScriptStream::ScriptStream(wxInputStream * pInputStream, wxOutputStream * pOutputStream, wxSocketBase * pSocket)
{
m_pInputStream = pInputStream;
m_pOutputStream = pOutputStream;
m_pSocket = pSocket;
m_tLastRead = wxDateTime::Now();
}
//////////////////////////////////////////////////////////////////////////////
///
/// \brief ScriptStream destructor - free all memory
///
//////////////////////////////////////////////////////////////////////////////
ScriptStream::~ScriptStream()
{
if (m_pInputStream)
delete m_pInputStream;
m_pInputStream = NULL;
if (m_pOutputStream)
delete m_pOutputStream;
m_pOutputStream = NULL;
if (m_pSocket)
delete m_pSocket;
m_pSocket = NULL;
}
//////////////////////////////////////////////////////////////////////////////
///
/// \brief Scripting constructor - initialize all variables
///
//////////////////////////////////////////////////////////////////////////////
Scripting::Scripting(MapControl * pctlMap)
{
m_pctlMap = pctlMap;
}
//////////////////////////////////////////////////////////////////////////////
///
/// \brief Destructor - free all memory
///
//////////////////////////////////////////////////////////////////////////////
Scripting::~Scripting()
{
vector<ScriptStream *>::iterator i;
// free scripts
m_mtxScripts.Lock();
for (i = m_vScripts.begin(); i != m_vScripts.end(); i++)
{
delete (*i);
}
m_vScripts.clear();
m_mtxScripts.Unlock();
// free servers
DeleteAllTCPServers();
}
//////////////////////////////////////////////////////////////////////////////
///
/// \brief Internal function to add script to list
///
//////////////////////////////////////////////////////////////////////////////
void Scripting::AddScript(wxInputStream * pInputStream, wxOutputStream * pOutputStream, wxSocketBase * pSocket)
{
m_mtxScripts.Lock();
m_vScripts.push_back(new ScriptStream(pInputStream, pOutputStream, pSocket));
m_mtxScripts.Unlock();
}
//////////////////////////////////////////////////////////////////////////////
///
/// \brief Internal function to add server to list
///
//////////////////////////////////////////////////////////////////////////////
void Scripting::AddServer(wxSocketServer * pServer)
{
m_mtxServers.Lock();
m_vServers.push_back(pServer);
m_mtxServers.Unlock();
}
//////////////////////////////////////////////////////////////////////////////
///
/// \brief Processes queued up events - best if run from the main thread
/// of the application, in OnIdle or a timer.
///
//////////////////////////////////////////////////////////////////////////////
void Scripting::PumpScripts()
{
vector<ScriptStream *>::iterator iScript;
m_mtxScripts.Lock();
// iterate through scripts
for (iScript = m_vScripts.begin(); iScript != m_vScripts.end(); iScript++)
{
bool bStreamOkay;
// decide if this script is okay, or if it should be closed
if ((*iScript)->m_pSocket)
bStreamOkay = (*iScript)->m_pSocket->IsConnected();
else
bStreamOkay = !(*iScript)->m_pInputStream->Eof();
if (bStreamOkay)
{
int iCRLFPos;
int iPadding;
if ((*iScript)->m_pSocket)
{
// CanRead() doesn't seem to work correctly on wxSocketInputStream :(
int iCount = 1;
// keep reading, until there is no more data
while (iCount)
{
char szBuffer[1025];
// read, then NULL terminate
(*iScript)->m_pSocket->Read(szBuffer, 1024);
iCount = (*iScript)->m_pSocket->LastCount();
szBuffer[iCount] = 0;
if (iCount)
{
// got something .. append it to input buffer and update last read timestamp
(*iScript)->m_strInputBuffer += wxString(szBuffer, *wxConvCurrent);
(*iScript)->m_tLastRead = wxDateTime::Now();
}
else
{
// one minute of no activity? send a keepalive
if (wxDateTime::Now() - (*iScript)->m_tLastRead > wxTimeSpan(0, 1, 0, 0))
{
(*iScript)->m_pSocket->Write("KEEPALIVE\r\n", 11);
(*iScript)->m_tLastRead = wxDateTime::Now();
}
// make sure everything is okay, otherwise shut down connection
if ((*iScript)->m_pSocket->LastError() != wxSOCKET_WOULDBLOCK && (*iScript)->m_pSocket->LastError() != wxSOCKET_NOERROR)
bStreamOkay = false;
}
} // while (iCount)
}
else // we're not reading from a socket
{
// do a byte by byte read until there's no more data
while ((*iScript)->m_pInputStream->CanRead())
(*iScript)->m_strInputBuffer += (*iScript)->m_pInputStream->GetC();
}
iCRLFPos = 1;
while (iCRLFPos >= 0)
{
// look for CR-LF
iCRLFPos = (*iScript)->m_strInputBuffer.Find(wxT("\r\n"));
iPadding = 2;
// try just LF if CR-LF can't be found
if (iCRLFPos < 0)
{
iCRLFPos = (*iScript)->m_strInputBuffer.Find(wxT('\n'));
iPadding = 1;
}
// try just CR
if (iCRLFPos < 0)
{
iCRLFPos = (*iScript)->m_strInputBuffer.Find(wxT('\r'));
iPadding = 1;
}
// if EOL found
if (iCRLFPos >= 0)
{
list<wxString> vRtn;
// run command
vRtn = ExecuteCommand((*iScript)->m_strInputBuffer.Left(iCRLFPos));
// if output stream available
if ((*iScript)->m_pOutputStream)
{
wxString strOut;
strOut = CompileCommand(vRtn);
// then send it if non-empty
if (strOut.Length())
{
strOut += wxT("\r\n");
(*iScript)->m_pOutputStream->Write(strOut.mb_str(*wxConvCurrent), strOut.Length());
}
}
// remove processed command from buffer
(*iScript)->m_strInputBuffer = (*iScript)->m_strInputBuffer.Mid(iCRLFPos + iPadding);
}
}
}
// something happened .. EOF or socket closed or something .. free up memory and remove from vector
if (!bStreamOkay)
{
// EOF, free up memory
delete (*iScript);
// remove from vector
m_vScripts.erase(iScript);
// exit loop
break;
}
}
m_mtxScripts.Unlock();
}
//////////////////////////////////////////////////////////////////////////////
///
/// \brief Accept connections on any servers running
///
//////////////////////////////////////////////////////////////////////////////
void Scripting::PumpServers()
{
vector<wxSocketServer *>::iterator i;
m_mtxServers.Lock();
for (i = m_vServers.begin(); i != m_vServers.end(); i++)
{
wxSocketBase * pSock;
pSock = (*i)->Accept(false);
if (pSock)
{
// got a new incoming connection
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -