⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scripting.cpp

📁 roadnav 内含一个基于wxWindows库的车载导航系统。编译后
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
 *  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 + -