예제 #1
0
void CRFLinkBase::ParseData(const char *data, size_t len)
{
	size_t ii=0;
	while (ii<len)
	{
		const unsigned char c = data[ii];
		if (c == 0x0d)
		{
			ii++;
			continue;
		}

		if (c == 0x0a || m_rfbufferpos == sizeof(m_rfbuffer) - 1)
		{
			// discard newline, close string, parse line and clear it.
			if (m_rfbufferpos > 0) m_rfbuffer[m_rfbufferpos] = 0;
			std::string sLine((char*)&m_rfbuffer);
			ParseLine(sLine);
			m_rfbufferpos = 0;
		}
		else
		{
			m_rfbuffer[m_rfbufferpos] = c;
			m_rfbufferpos++;
		}
		ii++;
	}

}
예제 #2
0
파일: savebuff.cpp 프로젝트: Affix/znc
	bool BootStrap(CChan *pChan)
	{
		CString sFile;
		if (DecryptChannel(pChan->GetName(), sFile))
		{
			if (!pChan->GetBuffer().empty())
				return(true); // reloaded a module probably in this case, so just verify we can decrypt the file

			VCString vsLines;
			VCString::iterator it;

			sFile.Split("\n", vsLines);

			for (it = vsLines.begin(); it != vsLines.end(); ++it) {
				CString sLine(*it);
				sLine.Trim();
				pChan->AddBuffer(sLine);
			}
		} else
		{
			m_sPassword = "";
			CUtils::PrintError("[" + GetModName() + ".so] Failed to Decrypt [" + pChan->GetName() + "]");
			return(false);
		}

		return(true);
	}
예제 #3
0
const EvaluateItem& NegotiveEvaluator::get() const
{
    std::string sLine(cLine_);
    boost::trim(sLine);
    item_->userQuery_ = sLine;
    return *item_;
}
예제 #4
0
파일: fileio.cpp 프로젝트: bholtsclaw/uox3
void ReadWorldTagData( std::ifstream &inStream, UString &tag, UString &data )
{
	char temp[4096];
	tag = "o---o";
	data = "o---o";
	while( !inStream.eof() && !inStream.fail() )
	{
		inStream.getline( temp, 4096 );
		UString sLine( temp );
		sLine = sLine.removeComment().stripWhiteSpace();
		if( !sLine.empty() )
		{
			if( sLine != "o---o" )
			{
				if( sLine.sectionCount( "=" ) == 1 )
				{
					tag		= sLine.section( "=", 0, 0 ).stripWhiteSpace();
					data	= sLine.section( "=", 1 ).stripWhiteSpace();
					break;
				}
			}
			else
				break;
		}
	}
}
예제 #5
0
bool 
Matlab_Interface::CMD_read::doCommand( std::string commandLine )
{

  if( 0 == driver )
  {
    std::cout << "ERROR: No valid driver registered with reader." << std::endl;
    return false;
  }

  commandLine.replace( commandLine.find(command), command.size()+1, ""); 

  ifstream inFile(commandLine.c_str());
  if( !inFile )
  {
    std::cout << "ERROR: Could not open file \"" << commandLine << "\"" << std::endl;
    return false;
  }

  Matlab_Interface::CMD_newMacro::is = &inFile;

  char cLine[256];

  while( !inFile.eof() )
  {
    inFile.getline( cLine, 256 );
    std::string sLine(cLine);
    driver->doCommand( sLine );
  }

  Matlab_Interface::CMD_newMacro::is = &(std::cin);

  return true;
}
예제 #6
0
파일: CJSEngine.cpp 프로젝트: Kitiara/UOX3
    CJSEngine::CJSEngine(void)
    {
        runtimeList.resize(0);

        const SI32 DefEngineSize = 0x1000000;

        std::ifstream engineData("engine.dat");
        SI32 engineSize = DefEngineSize;
        if (engineData.is_open())
        {
            char line[1024];
            engineData.getline(line, 1024);
            UString sLine(line);
            sLine = sLine.removeComment().stripWhiteSpace();
            if (!sLine.empty())
                engineSize = UOX_MAX(sLine.toLong(), DefEngineSize);

            engineData.close();
        }
        
        Console.PrintSectionBegin();
        Console << "Starting JavaScript Engine...." << myendl;
        
        runtimeList.push_back(new CJSRuntime(engineSize)); // Default Runtime
        runtimeList.push_back(new CJSRuntime(engineSize)); // Console Runtime

        Console << "JavaScript engine startup complete." << myendl;
        Console.PrintSectionBegin();
    }
예제 #7
0
파일: RFLink.cpp 프로젝트: clafa/domoticz-1
void CRFLink::readCallback(const char *data, size_t len)
{
	boost::lock_guard<boost::mutex> l(readQueueMutex);
	size_t ii=0;

	while (ii<len)
	{
		const unsigned char c = data[ii];
		if (c == 0x0d)
		{
			ii++;
			continue;
		}

		if (c == 0x0a || m_rfbufferpos == sizeof(m_rfbuffer) - 1)
		{
			// discard newline, close string, parse line and clear it.
			if (m_rfbufferpos > 0) m_rfbuffer[m_rfbufferpos] = 0;
			std::string sLine((char*)&m_rfbuffer);
			ParseLine(sLine);
			m_rfbufferpos = 0;
		}
		else
		{
			m_rfbuffer[m_rfbufferpos] = c;
			m_rfbufferpos++;
		}
		ii++;
	}

}
예제 #8
0
void ImportM3U(const wxString & sM3UPath,wxArrayString & sFiles)
{
    sFiles.Clear();
    wxTextFile f(sM3UPath);
    if(!f.Open(wxConvISO8859_1))
    {
        wxLogError(_("File %s not found."),sM3UPath.c_str());
        return;
    }
    wxFileName fnM3UPath(sM3UPath);
    sFiles.Alloc(f.GetLineCount());
    for (size_t n =0; n < f.GetLineCount();n++)
    {
        wxString sLine(f[n]);
        sLine.Trim();
        if(sLine.IsEmpty())
            continue; // skip empty lines;
        else if(sLine.StartsWith(_T("#")))
            continue;//skip comments
        wxFileName fn(sLine);
        fn.Normalize(wxPATH_NORM_ALL,fnM3UPath.GetPath());
        sFiles.Add(fn.GetFullPath());
    }
    return;
}
예제 #9
0
//--------------------------------------------------------------------------------------------------------------//
void CFrmMain::OnEditCopy() 
{
	CString sLine("");

	POSITION pos = m_wndView.GetFirstSelectedItemPosition();
	if (pos == NULL)
	{
		for(int i = 0; i < m_wndView.GetItemCount(); i++) sLine += MakeItemString(i);
	}
	else
	{
		int nItem;
		while (pos)
		{
			nItem = m_wndView.GetNextSelectedItem(pos);
			sLine += MakeItemString(nItem);
		}
	}
	if (::OpenClipboard(m_wndView) && EmptyClipboard())
	{
		HGLOBAL p = ::GlobalAlloc(GMEM_MOVEABLE, (sLine.GetLength() + 1) * sizeof(TCHAR));
		if (p)
		{
			LPSTR psz = (LPSTR)::GlobalLock(p);
			memcpy(psz, (LPCTSTR)sLine, (sLine.GetLength() + 1) * sizeof(TCHAR));
			GlobalUnlock(p);
			SetClipboardData(CF_OEMTEXT, p);
		}
		CloseClipboard();
	}
}
예제 #10
0
std::vector<std::string> OBJLoader::tokenize(const char* line, const char token, bool skip)
{
	std::string sLine(line);
	std::vector<std::string> tokens;

	int begin = 0;
	int pos = sLine.find_first_of(token, begin);

	while (pos != std::string::npos) {
		std::string newToken;

		if (begin != pos) {
			newToken = sLine.substr(begin, pos - begin);
		} 

		begin = pos + 1;
		tokens.push_back(newToken);

		if (skip) {
			pos = sLine.find_first_not_of(token, begin);
			begin = pos;
		}

		pos = sLine.find_first_of(token, begin);
	}

	if (begin != std::string::npos) {
		std::string newToken = sLine.substr(begin);
		tokens.push_back(newToken);
	}
	return tokens;
}
예제 #11
0
void cfgMgr::readIn( void ) {
	std::string sKey;
	std::string sVal;
	std::string sAppName = getAppName();

/* 
 * There may be a better way to structure this.
 * My concept is to have platform dependent "loop/starter" sections
 * followed by some consistent platform independent "actual work" and
 * then a platform dependent "loop/cleanup" section
 * This way the actual work is consistent across platforms
 */
#if defined(WIN32)
	DWORD idx=0;
	while( getRegOption( sAppName.c_str(),idx++,sKey,sVal ) ) {
#elif defined(MACOS_X_UNIX)
	// where does mac store app cfg info ?
#elif defined(LINUX)
	// is there "standard" code used under linux for /etc/app/*.conf file processing?
	//  i'm thinking like POSIX-type routines?
#else
	//  for now just do basic file i/o
//	std::string scfgFileName = sAppName.c_str() + ".conf";
	std::string scfgFileName(sAppName.c_str());
	scfgFileName.append(".conf");
	FILE* fCfg = fopen( scfgFileName.c_str(), "r" );
	if( fCfg==NULL )
		return;  // bow out early if can't even open config file

	const int MAX_CONF_FILE_LINE_LENGTH = 2048;
	char buf[MAX_CONF_FILE_LINE_LENGTH];
	while( fgets(buf,MAX_CONF_FILE_LINE_LENGTH,fCfg)!=NULL ) {
		//for now, just treat as key=val pair, 1 per line
		if( buf[0]=='#' ) continue;
		if( !strlen(buf) ) continue;

		std::string sLine( buf );
		std::string::size_type pos=sLine.find( "=" );
		if( pos==std::string::npos ) continue;

		sKey = sLine.substr(0,pos);
		sVal = sLine.substr(pos+1);
#endif


			addKeyValPair( sKey.c_str(),sVal.c_str() );


#if defined(WIN32)
	}
#elif defined(MACOS_X_UNIX)
	//
#elif defined(LINUX)
	//
#else
	}
	fclose( fCfg );
#endif
}
예제 #12
0
void
SMTPMessage::SendLine
	(
	const JCharacter* line
	)
{
	JString sLine(line);
	SendLine(sLine);
}
예제 #13
0
void
SMTPMessage::SendLine
	(
	const JString& line
	)
{
	JString sLine(line);
	sLine += "\r";
	itsLink->SendMessage(sLine);
}
예제 #14
0
const EvaluateItem& PositiveEvaluator::get() const
{
    std::string sLine(cLine_);
    std::size_t pos = sLine.find("\t");
    if (std::string::npos != pos)
    {
        item_->userQuery_ = sLine.substr(0, pos);
        item_->correct_ = sLine.substr(pos + 1);
    }
    return *item_;
}
예제 #15
0
//--------------------------------------------------------------------------------
bool CSSQuickMail::Send()
	{
	CSSConfigGeneral config;
	if(config.m_bNoEmail)
		return false;
	CString sTemp;
	sTemp.Format("Server Addr: %s\r\nServer Port: %d\r\n", (LPCTSTR) config.m_sMainIP, config.m_nMainPort);
	CString sLine('-', 40);
	if(m_sMsg.Right(2) != "\r\n")
		m_sMsg += "\r\n";
	m_sMsg += sLine + "\r\n" + sTemp;
	return CQuickMail::Send();
	}
예제 #16
0
//--------------------------------------------------------------------------------
bool CStatus::SetLogFile(LPCTSTR pFilename, CResult* pRes)
	{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

	m_nRefCount++;

	if(m_pFile != NULL)
		{
		m_pFile->Close();
		delete m_pFile;
		m_pFile = NULL;
		}

	bool bRv = true;
	CFileException e;
	m_pFile = new CStdioFile;
	if(m_pFile->Open(pFilename,
			CFile::modeReadWrite|CFile::modeCreate|CFile::modeNoTruncate|
			CFile::shareDenyWrite|CFile::typeText, &e))
		{
		m_pFile->SeekToEnd();

		CString sLine('-', 160);
		CString sTemp;
		sTemp.Format("\n%s\nLog file started: %s\n%s\n%s\n%s\n", (LPCTSTR) sLine,
			(LPCTSTR) CTime::GetCurrentTime().Format("%c"), (LPCTSTR) sLine,
			"Type\tObjName\tFuncName\tThreadId\tMsg\tOS err id\tOS err msg",  (LPCTSTR) sLine);
		m_pFile->WriteString(sTemp);

/*		if(m_pService != NULL)
			if(m_pService->m_bDebug)
				printf("%s", (LPCTSTR) sTemp);
*/
		}
	else
		{
		if(pRes != NULL)
			{
			pRes->SetResultCode(CResult::errOS);
			pRes->SetOSResult(e.m_lOsError);
			}

		delete m_pFile;
		m_pFile = NULL;
		bRv = false;
		}

	return bRv;
	}
예제 #17
0
QString CBuffer::dump() const
{
	QString sHex = toHex();
	QString sAscii = toAscii();
	QString sRet;

	int nOffset = 0;

	sRet = QString("Length: %1 \nOffset      Hex                             ASCII\n------------------------------------------------------\n").arg(m_nLength);

	for( ; nOffset < sAscii.length(); nOffset += 10 )
	{
		QString sLine("0x%1  %2  %3\n");

		sRet += sLine.arg(nOffset, 8, 16, QLatin1Char('0')).arg(sHex.mid(nOffset * 3, 10 * 3), -30, QLatin1Char(' ')).arg(sAscii.mid(nOffset, 10));
	}

	return sRet;
}
예제 #18
0
파일: savebuff.cpp 프로젝트: Affix/znc
	void Replay(const CString & sChan)
	{
		CString sFile;
		PutUser(":***[email protected] PRIVMSG " + sChan + " :Buffer Playback...");
		if (DecryptChannel(sChan, sFile))
		{
			VCString vsLines;
			VCString::iterator it;

			sFile.Split("\n", vsLines);

			for (it = vsLines.begin(); it != vsLines.end(); ++it) {
				CString sLine(*it);
				sLine.Trim();
				PutUser(sLine);
			}
		}
		PutUser(":***[email protected] PRIVMSG " + sChan + " :Playback Complete.");
	}
예제 #19
0
void CATDbgHelper::ReadMapFile( const string sMapFileName )
{
	LOG_FUNC_ENTRY("CATDbgHelper::ReadMapFile");
	try {
		ifstream in( sMapFileName.c_str() );
		if ( ! in.good() )
		{
			in.close();
			return;
		}
		char cLine[MAX_LINE_LENGTH];
		do {
			in.getline( cLine, MAX_LINE_LENGTH );
			// Search pattern for 'image ro' symbols is ".text"
			string sLine( cLine );
			if ( sLine.find( ".text" ) != string::npos )
			{
				MAP_FUNC_INFO symbol;
				// Pickup symbol attributes
				// Address
				string sAddress = CATBase::GetStringUntilNextSpace( sLine, true );
				symbol.iAddress = CATBase::_httoi( sAddress.c_str() );
				// Lenght
				string sLength = CATBase::GetStringUntilNextSpace( sLine, true );
				symbol.iFuncLength = CATBase::_httoi( sLength.c_str() );
				// Name
				size_t iStart = sLine.find_first_of( '(' );
				size_t iEnd = sLine.find_last_of( ')' );
				if ( iStart != string::npos && iEnd != string::npos )
				{
					symbol.sMangledName = sLine.substr( iStart+1, iEnd-iStart-1 );
					// Add symbol to vector
					m_vMapFileFuncList.push_back( symbol );
				}
			}
		} while ( in.good() );
		in.close();
		m_bMap = true;
	} catch (...) {
		m_bMap = false;
		LOG_STRING("DbgHelp: Error reading map file.");
	}
}
예제 #20
0
파일: savebuff.cpp 프로젝트: Affix/znc
	virtual void OnModCommand(const CString& sCmdLine)
	{
		CString sCommand = sCmdLine.Token(0);
		CString sArgs    = sCmdLine.Token(1, true);

		if (sCommand.Equals("setpass"))
		{
			PutModule("Password set to [" + sArgs + "]");
			m_sPassword = CBlowfish::MD5(sArgs);

		} else if (sCommand.Equals("dumpbuff"))
		{
			CString sFile;
			if (DecryptChannel(sArgs, sFile))
			{
				VCString vsLines;
				VCString::iterator it;

				sFile.Split("\n", vsLines);

				for (it = vsLines.begin(); it != vsLines.end(); ++it) {
					CString sLine(*it);
					sLine.Trim();
					PutModule("[" + sLine + "]");
				}
			}
			PutModule("//!-- EOF " + sArgs);
		} else if (sCommand.Equals("replay"))
		{
			Replay(sArgs);
			PutModule("Replayed " + sArgs);

		} else if (sCommand.Equals("save"))
		{
			SaveBufferToDisk();
			PutModule("Done.");
		} else
			PutModule("Unknown command [" + sCommand + "]");
	}
예제 #21
0
	bool BootStrap()
	{
		CString sFile;
		if (DecryptMessages(sFile))
		{
			VCString vsLines;
			VCString::iterator it;

			sFile.Split("\n", vsLines);

			for (it = vsLines.begin(); it != vsLines.end(); ++it) {
				CString sLine(*it);
				sLine.Trim();
				AddMessage(sLine);
			}
		} else {
			m_sPassword = "";
			CUtils::PrintError("[" + GetModName() + ".so] Failed to Decrypt Messages");
			return(false);
		}

		return(true);
	}
예제 #22
0
void object::test<8>
()
{
    geos::geom::PrecisionModel pm(1e+13);
    geos::geom::GeometryFactory::Ptr factory = geos::geom::GeometryFactory::create(&pm);
    geos::io::WKBReader reader(*factory);

    // POINT located between 3rd and 4th vertex of LINESTRING
    // POINT(-23.1094689600055080 50.5195368635957180)
    std::string point("01010000009a266328061c37c0e21a172f80424940");
    // LINESTRING(-23.122057005539 50.5201976774794,-23.1153476966995 50.5133404815199,-23.1094689600055150 50.5223376452201340,-23.1094689600055010 50.5169177629559480,-23.0961967920942 50.5330464848094,-23.0887991006034 50.5258515213185,-23.0852302622362 50.5264582238409)
    std::string
    line("0102000000070000009909bf203f1f37c05c1d66d6954249404afe386d871d37c0a7eb1124b54149409c266328061c37c056d8bff5db42494098266328061c37c0034f7b5c2a42494060065c5aa01837c08ac001de3a4449408401b189bb1637c0b04e471a4f43494014ef84a6d11537c0b20dabfb62434940");
    std::stringstream sPoint(point);
    geom2_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sPoint));
    std::stringstream sLine(line);
    geom1_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sLine));

    prepGeom1_ = GEOSPrepare(geom1_);
    ensure(nullptr != prepGeom1_);
    int ret = GEOSPreparedIntersects(prepGeom1_, geom2_);
    ensure_equals(ret, 1);
}
예제 #23
0
void CCommandLineDisplay::Paint (CG32bitImage &Dest)

//	Paint
//
//	Paint display

	{
	Update();

	//	Paint the cursor

	m_Buffer.Fill(m_rcCursor.left + 1, 
			m_rcCursor.top, 
			RectWidth(m_rcCursor) - 1, 
			RectHeight(m_rcCursor),
			(((m_iCounter % 30) < 20) ? INPUT_COLOR : BACK_COLOR));

	//	Redraw character under cursor
	if ((m_iCounter % 30) >= 20 && m_iCursorPos < m_sInput.GetLength())
		{
		CString sLine(m_sInput.GetASCIIZPointer() + m_iCursorPos, 1);
		m_Buffer.DrawText(m_rcCursor.left, m_rcCursor.top, m_pFonts->Console, INPUT_COLOR, sLine);
		}

	//	Blt

	Dest.Blt(0,
			0,
			RectWidth(m_rcRect),
			RectHeight(m_rcRect),
			200,
			m_Buffer,
			m_rcRect.left,
			m_rcRect.top);

	m_iCounter++;
	}
예제 #24
0
//加载文件,读取相应的数据
bool CCardCfg::LoadFile(string sFile)
{
	if (m_sFile == sFile)
		return false;

	m_sFile = sFile;

	ReleaseAll();

	char buffer[256];
	memset(buffer,0,256);
	string sLine;//读取的行

	//char fileName[256];
	//memset(fileName,0,256);
	//int iSize = sFile.size();
	//strcpy_s(fileName,sFile.c_str());//使用头文件#include <string.h>

	ifstream  fs;
	fs.open(sFile);
	if(!fs)
	{
		std::cout << "打开文件失败!";
		return false;
	}

	CCard* newCard = 0;//新卡
	bool bCardValid = false;//卡数据有效

	while(!fs.eof())
	{
		memset(buffer,0,256);
		fs.getline(buffer,256);//读取一行
		string sLine(buffer);
		int iSize = sLine.size();
		if(0 == iSize)
			continue;

		if('/' == sLine[0])
			continue;
		else if(';' == sLine[0])
		{	
			bCardValid = false;//某类卡数据结束,卡无效
			newCard = 0;//卡结束
		}
		else if(':' == sLine[0])
		{
			//:A,区域交换功率控制卡(A),,,,,,,,,,,,,,,,,
			vector<string> lines = CXxwCppPub::SplitStrByChar(sLine,',');//以,分割字符串
			int nCount = lines.size();
			if(nCount >= 2)
			{
				bCardValid = true;
				newCard = new CCard;
				string sName = lines.at(0);
				sName = CXxwCppPub::TrimLeft(sName,':');
				sName = CXxwCppPub::TrimRight(sName);
				newCard->m_sName = sName;
				newCard->m_sComment = lines.at(1);
				//如果已有该key,删除对应的value,防止内存泄露
				//因为配置文件中在不同的地方有相同的卡名的情况,目前这种情况不知道该怎么处理
				map<string,CCard*>::iterator pos = m_allCardsCfg.find(sName);
				if (pos != m_allCardsCfg.end())
				{
					CCard* pCard = pos->second;
					if (pCard)
					{
						delete pCard;
						pCard = 0;
					}
				}
				m_allCardsCfg[sName] = newCard;
			}
		}
		else if(bCardValid && newCard)
		{
			//1,1,A1,1,1,=,A,卡,区域交换功率卡,,,,,CARD,,,,,
			vector<string> lines = CXxwCppPub::SplitStrByChar(sLine,',');//以,分割字符串
			int nCount = lines.size();
			if(nCount >= 15)
			{
				CCardField *newField = new CCardField;
				newField->nStart = atoi(lines.at(0).c_str());
				newField->nEnd = atoi(lines.at(1).c_str());
				newField->sFormat = lines.at(2);
				newField->bKey = atoi(lines.at(3).c_str());
				newField->nBlank = atoi(lines.at(4).c_str());
				newField->sComp = lines.at(5);
				newField->sKey = lines.at(6);
				newField->sComment = lines.at(7);
				newField->sCaption = lines.at(8);
				newField->sDefaultValue = lines.at(9);
				newField->sMinValue = lines.at(10);
				newField->sMaxValue = lines.at(11);
				newField->lFlag = atol(lines.at(12).c_str());
				newField->sKeyName = lines.at(13);
				newField->sValueList = lines.at(14);
				newCard->m_allFields.push_back(newField);
			}
		}
	}

	fs.close();//关闭文件

	return true;
}
예제 #25
0
파일: Chan.cpp 프로젝트: jimloco/znc
void CChan::SendBuffer(CClient* pClient) {
	if (m_pNetwork && m_pNetwork->IsUserAttached()) {
		const vector<CString>& vsBuffer = GetBuffer();

		// in the event that pClient is NULL, need to send this to all clients for the user
		// I'm presuming here that pClient is listed inside vClients thus vClients at this
		// point can't be empty.
		//
		// This loop has to be cycled twice to maintain the existing behavior which is
		// 1. OnChanBufferStarting
		// 2. OnChanBufferPlayLine
		// 3. ClearBuffer() if not keeping the buffer
		// 4. OnChanBufferEnding
		//
		// With the exception of ClearBuffer(), this needs to happen per client, and
		// if pClient is not NULL, the loops break after the first iteration.
		//
		// Rework this if you like ...
		if (vsBuffer.size()) {
			const vector<CClient*> & vClients = m_pNetwork->GetClients();
			for (size_t uClient = 0; uClient < vClients.size(); ++uClient) {

				CClient * pUseClient = ( pClient ? pClient : vClients[uClient] );
				bool bSkipStatusMsg = false;
				NETWORKMODULECALL(OnChanBufferStarting(*this, *pUseClient), m_pNetwork->GetUser(), m_pNetwork, NULL, bSkipStatusMsg = true);

				if (!bSkipStatusMsg) {
					m_pNetwork->PutUser(":***[email protected] PRIVMSG " + GetName() + " :Buffer Playback...", pUseClient);
				}

				for (unsigned int a = 0; a < vsBuffer.size(); a++) {
					CString sLine(vsBuffer[a]);
					NETWORKMODULECALL(OnChanBufferPlayLine(*this, *pUseClient, sLine), m_pNetwork->GetUser(), m_pNetwork, NULL, continue);
					m_pNetwork->PutUser(sLine, pUseClient);
				}

				if (pClient)
					break;

			}

			if (!KeepBuffer()) {
				ClearBuffer();
			}

			for ( size_t uClient = 0; uClient < vClients.size(); ++uClient) {

				CClient * pUseClient = ( pClient ? pClient : vClients[uClient] );
				bool bSkipStatusMsg = false;
				NETWORKMODULECALL(OnChanBufferEnding(*this, *pUseClient), m_pNetwork->GetUser(), m_pNetwork, NULL, bSkipStatusMsg = true);

				if (!bSkipStatusMsg) {
					m_pNetwork->PutUser(":***[email protected] PRIVMSG " + GetName() + " :Playback Complete.", pUseClient);
				}

				if (pClient)
					break;
			}

		}
	}
}
예제 #26
0
void Meteostick::ParseLine()
{
	if (m_bufferpos < 1)
		return;
	std::string sLine((char*)&m_buffer);

	std::vector<std::string> results;
	StringSplit(sLine, " ", results);
	if (results.size() < 1)
		return; //invalid data

	switch (m_state)
	{
	case MSTATE_INIT:
		if (sLine.find("# MeteoStick Version") == 0) {
			_log.Log(LOG_STATUS, sLine.c_str());
			return;
		}
		if (results[0] == "?")
		{
			//Turn off filters
			write("f0\n");
			m_state = MSTATE_FILTERS;
		}
		return;
	case MSTATE_FILTERS:
		//Set output to 'computer values'
		write("o1\n");
		m_state = MSTATE_VALUES;
		return;
	case MSTATE_VALUES:
#ifdef USE_868_Mhz
		//Set listen frequency to 868Mhz
		write("m1\n");
#else
		//Set listen frequency to 915Mhz
		write("m0\n");
#endif
		m_state = MSTATE_DATA;
		return;
	}

	if (m_state != MSTATE_DATA)
		return;

	if (results.size() < 3)
		return;

	unsigned char rCode = results[0][0];
	if (rCode == '#')
		return;

//#ifdef _DEBUG
	_log.Log(LOG_NORM, sLine.c_str());
//#endif

	switch (rCode)
	{
	case 'B':
		//temperature in Celsius, pressure in hPa
		if (results.size() >= 3)
		{
			float temp = static_cast<float>(atof(results[1].c_str()));
			float baro = static_cast<float>(atof(results[2].c_str()));

			SendTempBaroSensor(0, temp, baro, "Meteostick Temp+Baro");
		}
		break;
	case 'W':
		//current wind speed in m / s, wind direction in degrees
		if (results.size() >= 5)
		{
			unsigned char ID = (unsigned char)atoi(results[1].c_str());
			if (m_LastOutsideTemp[ID%MAX_IDS] != 12345)
			{
				float speed = static_cast<float>(atof(results[2].c_str()));
				int direction = static_cast<int>(atoi(results[3].c_str()));
				SendWindSensor(ID, m_LastOutsideTemp[ID%MAX_IDS], speed, direction, "Wind");
			}
		}
		break;
	case 'T':
		//temperature in degree Celsius, humidity in percent
		if (results.size() >= 5)
		{
			unsigned char ID = (unsigned char)atoi(results[1].c_str());
			float temp = static_cast<float>(atof(results[2].c_str()));
			int hum = static_cast<int>(atoi(results[3].c_str()));

			SendTempHumSensor(ID, temp, hum, "Outside Temp+Hum");
			m_LastOutsideTemp[ID%MAX_IDS] = temp;
			m_LastOutsideHum[ID%MAX_IDS] = hum;
		}
		break;
	case 'R':
		//Rain
		//counter value (value 0 - 255), ticks, 1 tick = 0.2mm or 0.01in
		//it only has a small counter, so we should make the total counter ourselfses
		if (results.size() >= 4)
		{
			unsigned char ID = (unsigned char)atoi(results[1].c_str());
			int raincntr = atoi(results[2].c_str());
			float Rainmm = 0;
			if (m_LastRainValue[ID%MAX_IDS] != -1)
			{
				int cntr_diff = (raincntr - m_LastRainValue[ID%MAX_IDS])&255;
				Rainmm = float(cntr_diff);
#ifdef RAIN_IN_MM
				//one tick is one mm
				Rainmm*=0.2f; //convert to mm;
#else
				//one tick is 0.01 inch, we need to convert this also to mm
				//Rainmm *= 0.01f; //convert to inch
				//Rainmm *= 25.4f; //convert to mm
				//or directly
				Rainmm *= 0.254;
#endif
			}
			m_LastRainValue[ID%MAX_IDS] = raincntr;

			if (m_ActRainCounter[ID%MAX_IDS] == -1)
			{
				//Get Last stored Rain counter
				float rcounter=GetRainSensorCounter(ID);
				m_ActRainCounter[ID%MAX_IDS] = rcounter;
			}
			m_ActRainCounter[ID%MAX_IDS] += Rainmm;

			SendRainSensor(ID, m_ActRainCounter[ID%MAX_IDS], "Rain");
		}
		break;
	case 'S':
		//solar radiation, solar radiation in W / qm
		if (results.size() >= 4)
		{
			unsigned char ID = (unsigned char)atoi(results[1].c_str());
			float Radiation = static_cast<float>(atof(results[2].c_str()));
			SendSolarRadiationSensor(ID, Radiation, "Solar Radiation");
		}
		break;
	case 'U':
		//UV index
		if (results.size() >= 4)
		{
			unsigned char ID = (unsigned char)atoi(results[1].c_str());
			float UV = static_cast<float>(atof(results[2].c_str()));
			SendUVSensor(ID, UV, "UV");
		}
		break;
	case 'L':
		//wetness data of a leaf station
		//channel number (1 - 4), leaf wetness (0-15)
		if (results.size() >= 5)
		{
			unsigned char ID = (unsigned char)atoi(results[1].c_str());
			unsigned char Channel = (unsigned char)atoi(results[2].c_str());
			unsigned char Wetness = (unsigned char)atoi(results[3].c_str());
			SendLeafWetnessRainSensor(ID, Channel, Wetness, "Leaf Wetness");
		}
		break;
	case 'M':
		//soil moisture of a soil station
		//channel number (1 - 4), Soil moisture in cbar(0 - 200)
		if (results.size() >= 5)
		{
			unsigned char ID = (unsigned char)atoi(results[1].c_str());
			unsigned char Channel = (unsigned char)atoi(results[2].c_str());
			unsigned char Moisture = (unsigned char)atoi(results[3].c_str());
			SendSoilMoistureSensor(ID, Channel, Moisture, "Soil Moisture");
		}
		break;
	case 'O':
		//soil / leaf temperature of a soil / leaf station
		//channel number (1 - 4), soil / leaf temperature in degrees Celsius
		if (results.size() >= 5)
		{
			unsigned char ID = (unsigned char)atoi(results[1].c_str());
			unsigned char Channel = (unsigned char)atoi(results[2].c_str());
			float temp = static_cast<float>(atof(results[3].c_str()));
			unsigned char finalID = (ID * 10) + Channel;
			SendTempSensor(finalID, temp, "Soil/Leaf Temp");
		}
		break;
	case 'P':
		//solar panel power in(0 - 100)
		if (results.size() >= 4)
		{
			unsigned char ID = (unsigned char)atoi(results[1].c_str());
			float Percentage = static_cast<float>(atof(results[2].c_str()));
			SendPercentage(ID, Percentage, "power of solar panel");
		}
		break;
	default:
		_log.Log(LOG_STATUS, "Unknown Type: %c", rCode);
		break;
	}

}
예제 #27
0
파일: OTGWBase.cpp 프로젝트: ZaaaV/domoticz
void OTGWBase::ParseLine()
{
	if (m_bufferpos<2)
		return;
	std::string sLine((char*)&m_buffer);

	std::vector<std::string> results;
	StringSplit(sLine,",",results);
	if (results.size()==25)
	{
		//status report
		//0    Status (MsgID=0) - Printed as two 8-bit bitfields
		//1    Control setpoint (MsgID=1) - Printed as a floating point value
		//2    Remote parameter flags (MsgID= 6) - Printed as two 8-bit bitfields
		//3    Maximum relative modulation level (MsgID=14) - Printed as a floating point value
		//4    Boiler capacity and modulation limits (MsgID=15) - Printed as two bytes
		//5    Room Setpoint (MsgID=16) - Printed as a floating point value
		//6    Relative modulation level (MsgID=17) - Printed as a floating point value
		//7    CH water pressure (MsgID=18) - Printed as a floating point value
		//8    Room temperature (MsgID=24) - Printed as a floating point value
		//9    Boiler water temperature (MsgID=25) - Printed as a floating point value
		//10    DHW temperature (MsgID=26) - Printed as a floating point value
		//11    Outside temperature (MsgID=27) - Printed as a floating point value
		//12    Return water temperature (MsgID=28) - Printed as a floating point value
		//13    DHW setpoint boundaries (MsgID=48) - Printed as two bytes
		//14    Max CH setpoint boundaries (MsgID=49) - Printed as two bytes
		//15    DHW setpoint (MsgID=56) - Printed as a floating point value
		//16    Max CH water setpoint (MsgID=57) - Printed as a floating point value
		//17    Burner starts (MsgID=116) - Printed as a decimal value
		//18    CH pump starts (MsgID=117) - Printed as a decimal value
		//19    DHW pump/valve starts (MsgID=118) - Printed as a decimal value
		//20    DHW burner starts (MsgID=119) - Printed as a decimal value
		//21    Burner operation hours (MsgID=120) - Printed as a decimal value
		//22    CH pump operation hours (MsgID=121) - Printed as a decimal value
		//23    DHW pump/valve operation hours (MsgID=122) - Printed as a decimal value
		//24    DHW burner operation hours (MsgID=123) - Printed as a decimal value 
		_tOTGWStatus _status;
		int idx=0;

		_status.MsgID=results[idx++];
		if (_status.MsgID.size()==17)
		{
			bool bCH_enabled=(_status.MsgID[7]=='1');										UpdateSwitch(101,bCH_enabled,"CH_enabled");
			bool bDHW_enabled=(_status.MsgID[6]=='1');										UpdateSwitch(102,bDHW_enabled,"DHW_enabled");
			bool bCooling_enable=(_status.MsgID[5]=='1');									UpdateSwitch(103,bCooling_enable,"Cooling_enable");
			bool bOTC_active=(_status.MsgID[4]=='1');										UpdateSwitch(104,bOTC_active,"OTC_active");
			bool bCH2_enabled=(_status.MsgID[3]=='1');										UpdateSwitch(105,bCH2_enabled,"CH2_enabled");

			bool bFault_indication=(_status.MsgID[9+7]=='1');								UpdateSwitch(110,bFault_indication,"Fault_indication");
			bool bCH_active=(_status.MsgID[9+6]=='1');										UpdateSwitch(111,bCH_active,"CH_active");
			bool bDHW_active=(_status.MsgID[9+5]=='1');										UpdateSwitch(112,bDHW_active,"DHW_active");
			bool bFlameOn=(_status.MsgID[9+4]=='1');										UpdateSwitch(113,bFlameOn,"FlameOn");
			bool bCooling_Mode_Active=(_status.MsgID[9+3]=='1');							UpdateSwitch(114,bCooling_Mode_Active,"Cooling_Mode_Active");
			bool bCH2_Active=(_status.MsgID[9+2]=='1');										UpdateSwitch(115,bCH2_Active,"CH2_Active");
			bool bDiagnosticEvent=(_status.MsgID[9+1]=='1');								UpdateSwitch(116,bDiagnosticEvent,"DiagnosticEvent");
		}
		
		_status.Control_setpoint=(float)atof(results[idx++].c_str());						UpdateTempSensor(idx-1,_status.Control_setpoint,"Control Setpoint");
		_status.Remote_parameter_flags=results[idx++];
		_status.Maximum_relative_modulation_level=(float)atof(results[idx++].c_str());
		_status.Boiler_capacity_and_modulation_limits=results[idx++];
		_status.Room_Setpoint=(float)atof(results[idx++].c_str());							UpdateSetPointSensor(idx-1,_status.Room_Setpoint,"Room Setpoint");
		_status.Relative_modulation_level=(float)atof(results[idx++].c_str());
		_status.CH_water_pressure=(float)atof(results[idx++].c_str());
		if (_status.CH_water_pressure!=0)
		{
			UpdatePressureSensor(idx-1,_status.CH_water_pressure,"CH Water Pressure");
		}

		_status.Room_temperature=(float)atof(results[idx++].c_str());						UpdateTempSensor(idx-1,_status.Room_temperature,"Room Temperature");
		_status.Boiler_water_temperature=(float)atof(results[idx++].c_str());				UpdateTempSensor(idx-1,_status.Boiler_water_temperature,"Boiler Water Temperature");
		_status.DHW_temperature=(float)atof(results[idx++].c_str());						UpdateTempSensor(idx-1,_status.DHW_temperature,"DHW Temperature");
		_status.Outside_temperature=(float)atof(results[idx++].c_str());					UpdateTempSensor(idx-1,_status.Outside_temperature,"Outside Temperature");
		_status.Return_water_temperature=(float)atof(results[idx++].c_str());				UpdateTempSensor(idx-1,_status.Return_water_temperature,"Return Water Temperature");
		_status.DHW_setpoint_boundaries=results[idx++];
		_status.Max_CH_setpoint_boundaries=results[idx++];
		_status.DHW_setpoint=(float)atof(results[idx++].c_str());							UpdateSetPointSensor(idx-1,_status.DHW_setpoint,"DHW Setpoint");
		_status.Max_CH_water_setpoint=(float)atof(results[idx++].c_str());					UpdateSetPointSensor(idx-1,_status.Max_CH_water_setpoint,"Max_CH Water Setpoint");
		_status.Burner_starts=atol(results[idx++].c_str());
		_status.CH_pump_starts=atol(results[idx++].c_str());
		_status.DHW_pump_valve_starts=atol(results[idx++].c_str());
		_status.DHW_burner_starts=atol(results[idx++].c_str());
		_status.Burner_operation_hours=atol(results[idx++].c_str());
		_status.CH_pump_operation_hours=atol(results[idx++].c_str());
		_status.DHW_pump_valve_operation_hours=atol(results[idx++].c_str());
		_status.DHW_burner_operation_hours=atol(results[idx++].c_str());
		return;
	}
	else
	{
		if (sLine=="SE")
		{
			_log.Log(LOG_ERROR,"OTGW: Error received!");
		}
		else
		{
			if (
				(sLine.find("OT")==std::string::npos)&&
				(sLine.find("PS")==std::string::npos)
				)
			{
				//Dont report OT/PS feedback
				_log.Log(LOG_STATUS,"OTGW: %s",sLine.c_str());
			}
		}
	}

}
예제 #28
0
void S0MeterBase::ParseLine()
{
	if (m_bufferpos<2)
		return;
	std::string sLine((char*)&m_buffer);

	std::vector<std::string> results;
	StringSplit(sLine,":",results);
	if (results.size()<1)
		return; //invalid data

	if (results[0][0]=='/') {
		//Meter restart
		//m_bMeterRestart=true;
		//Software Version

		std::string MeterID=results[0].substr(1);
		std::string SoftwareVersion=results[1];
		_log.Log(LOG_STATUS,"S0 Meter: ID: %s, Version: %s",MeterID.c_str(),SoftwareVersion.c_str());
		return;
	}
	if (results.size()<4)
	{
		_log.Log(LOG_ERROR,"S0 Meter: Invalid Data received! %s",sLine.c_str());
		return;
	}
	int totmeters=(results.size()-4)/3;
	if (totmeters>max_s0_meters)
		totmeters=max_s0_meters;
	//ID:0001:I:99:M1:123:456:M2:234:567 = ID(1)/Pulse Interval(3)/M1Actual(5)/M1Total(7)/M2Actual(8)/M2Total(9)
	//std::string MeterID=results[1];
	double s0_pulse_interval=atof(results[3].c_str());

	int roffset = 4;
	if (results[0] == "ID")
	{
		for (int ii = 0; ii < totmeters; ii++)
		{
			m_meters[ii].m_PacketsSinceLastPulseChange++;

			double s0_pulse = atof(results[roffset + 1].c_str());

			unsigned long LastTotalPulses = m_meters[ii].total_pulses;
			m_meters[ii].total_pulses = (unsigned long)atol(results[roffset + 2].c_str());
			if (m_meters[ii].total_pulses < LastTotalPulses)
			{
				//counter has looped
				m_meters[ii].m_counter_start += (LastTotalPulses + m_meters[ii].total_pulses);
				m_meters[ii].first_total_pulses_received = m_meters[ii].total_pulses;
			}

			if (s0_pulse != 0)
			{
				double pph = ((double)m_meters[ii].m_pulse_per_unit) / 1000; // Pulses per (watt) hour
				double ActualUsage = ((3600.0 / double(m_meters[ii].m_PacketsSinceLastPulseChange*s0_pulse_interval) / pph) * s0_pulse);
				m_meters[ii].m_PacketsSinceLastPulseChange = 0;

				m_meters[ii].m_last_values[m_meters[ii].m_value_buffer_write_pos] = ActualUsage;
				m_meters[ii].m_value_buffer_write_pos = (m_meters[ii].m_value_buffer_write_pos + 1) % 5;

				if (m_meters[ii].m_value_buffer_total < 5)
					m_meters[ii].m_value_buffer_total++;

				//Calculate Average
				double vTotal = 0;
				for (int iBuf = 0; iBuf < m_meters[ii].m_value_buffer_total; iBuf++)
					vTotal += m_meters[ii].m_last_values[iBuf];
				m_meters[ii].m_CurrentUsage = vTotal / double(m_meters[ii].m_value_buffer_total);
#ifdef _DEBUG
				_log.Log(LOG_STATUS, "S0 Meter: M%d, Watt: %.3f", ii + 1, m_meters[ii].m_CurrentUsage);
#endif
			}
			else
			{
				if (m_meters[ii].m_PacketsSinceLastPulseChange > 5 * 6)
				{
					//No pulses received for a long time, consider no usage
					m_meters[ii].m_PacketsSinceLastPulseChange = 0;
					m_meters[ii].m_last_values[0] = 0;
					m_meters[ii].m_value_buffer_total = 0;
					m_meters[ii].m_value_buffer_write_pos = 0;
					m_meters[ii].m_CurrentUsage = 0;
				}
			}

			if ((m_meters[ii].total_pulses != 0) || (m_meters[ii].m_firstTime))
			{
				m_meters[ii].m_firstTime = false;
				if (m_meters[ii].first_total_pulses_received == 0)
					m_meters[ii].first_total_pulses_received = m_meters[ii].total_pulses;

				double counter_value = m_meters[ii].m_counter_start + (((double)(m_meters[ii].total_pulses - m_meters[ii].first_total_pulses_received) / ((double)m_meters[ii].m_pulse_per_unit)));
				m_meters[ii].m_current_counter = counter_value;
				SendMeter(ii + 1, m_meters[ii].m_CurrentUsage / 1000.0f, counter_value);
			}

			roffset += 3;
		}
	}
	else if(results[0] == "EID")
	{
		roffset = 2;
		for (int ii = 0; ii < totmeters; ii++)
		{
			double s0_counter = atof(results[roffset + 1].c_str());
			if (s0_counter != 0)
			{
				if (m_meters[ii].m_firstTime)
				{
					m_meters[ii].m_current_counter = s0_counter;
					m_meters[ii].m_firstTime = false;
				}
				if (s0_counter < m_meters[ii].m_current_counter)
				{
					//counter has looped
					m_meters[ii].m_counter_start += m_meters[ii].m_current_counter;
				}
				m_meters[ii].m_current_counter = s0_counter;
				m_meters[ii].m_CurrentUsage = atof(results[roffset + 2].c_str());

				double counter_value = m_meters[ii].m_counter_start + s0_counter;
				SendMeter(ii + 1, m_meters[ii].m_CurrentUsage / 1000.0f, m_meters[ii].m_current_counter);
			}

			roffset += 3;
		}
	}
}
예제 #29
0
bool CSimpleMesh::LoadMaterials(CString szFileName) {
	TArray<CString> m_oTextureNames;

	FILE *file = fopen(szFileName, "rt");
	if (!file)
		return false;

	char szLine[MAX_LINE_LEN];
	CString *ppsTokens;
	int iNumTokens;
	int iNumMaterials = 0;
	while (fgets(szLine, MAX_LINE_LEN, file)) {
		CString sLine(szLine);
		sLine.ToUpper();

		if (sLine.StartsWith("NEWMTL")) {
			CMaterial oMaterial;
			m_oMaterials.Append(oMaterial);

			sLine.Tokenize(&ppsTokens, &iNumTokens, sDelimiters);
			m_oMaterialNames.Append(ppsTokens[1]);
			SAFE_DELETE_ARRAY(ppsTokens);
			iNumMaterials++;

			//m_oTextureNames.Append(NULL);
			m_oMaterialsTextureIndex.Append(NO_TEXTURE);
		} else if (sLine.StartsWith("KA")) {
			sLine.Tokenize(&ppsTokens, &iNumTokens, sDelimiters);
			CMaterial *oMaterial = &m_oMaterials[m_oMaterials.GetSize() - 1];
			CColor *poColor = oMaterial->GetAmbientColor();
			poColor->red = ppsTokens[1].ToFloat();
			poColor->green = ppsTokens[2].ToFloat();
			poColor->blue = ppsTokens[3].ToFloat();

			SAFE_DELETE_ARRAY(ppsTokens);
		} else if (sLine.StartsWith("KD")) {
			sLine.Tokenize(&ppsTokens, &iNumTokens, sDelimiters);
			CMaterial *oMaterial = &m_oMaterials[m_oMaterials.GetSize() - 1];
			CColor *poColor = oMaterial->GetDiffuseColor();
			poColor->red = ppsTokens[1].ToFloat();
			poColor->green = ppsTokens[2].ToFloat();
			poColor->blue = ppsTokens[3].ToFloat();

			SAFE_DELETE_ARRAY(ppsTokens);
		} else if (sLine.StartsWith("KS")) {
			sLine.Tokenize(&ppsTokens, &iNumTokens, sDelimiters);
			CMaterial *oMaterial = &m_oMaterials[m_oMaterials.GetSize() - 1];
			CColor *poColor = oMaterial->GetSpecularColor();
			poColor->red = ppsTokens[1].ToFloat();
			poColor->green = ppsTokens[2].ToFloat();
			poColor->blue = ppsTokens[3].ToFloat();

			SAFE_DELETE_ARRAY(ppsTokens);
		} else if (sLine.StartsWith("NS")) {
			sLine.Tokenize(&ppsTokens, &iNumTokens, sDelimiters);
			CMaterial *oMaterial = &m_oMaterials[m_oMaterials.GetSize() - 1];

			oMaterial->SetPower(ppsTokens[1].ToFloat());

			SAFE_DELETE_ARRAY(ppsTokens);
		} else if (sLine.StartsWith("MAP_KD") || sLine.StartsWith("MAP_KA")) {
			sLine.Tokenize(&ppsTokens, &iNumTokens, sDelimiters);
			CString sTextureName(ppsTokens[1].StartsWith(".\\") ? ppsTokens[1].GetBuffer() + 2 : ppsTokens[1]);

			int index = m_oTextureNames.Find(sTextureName);

			if (index == -1) {
				m_oTextureNames.Append(sTextureName);
				m_oMaterialsTextureIndex[m_oMaterials.GetSize() - 1] = m_oTextureNames.GetSize() - 1;
			} else {
				m_oMaterialsTextureIndex[m_oMaterials.GetSize() - 1] = index;
			}

			SAFE_DELETE_ARRAY(ppsTokens);
		}
	}

	fclose(file);

	for (int i = 0; i < m_oTextureNames.GetSize(); i++)
		m_oTextures.Append(new CTexture(m_poDisplayDevice, m_oTextureNames[i].GetBuffer()));

	return true;
}
예제 #30
0
bool CSimpleMesh::LoadFromObjFile(char *szFileName) {
	TArray<VECTOR3Df> m_oVertexArray;
	TArray<VECTOR3Df> m_oNormalArray;
	TArray<VECTOR2Df> m_oTextureCoordArray;

	m_oMaterials.RemoveAll();
	m_oMaterialNames.RemoveAll();

	m_oSubsetsStartIndex.RemoveAll();
	m_oSubsetsMaterialIndex.RemoveAll();

	FreeTexureArray();
	m_oMaterialsTextureIndex.RemoveAll();

	TArray<FACE_STRUCT> oFaceBuffer;

#ifdef USE_HASHTABLE_FOR_VERTEX_SEARCH
	THashTable<FACE_STRUCT> oFaceHash(NUM_KEYS, FACE_STRUCT::GetKey);
#endif //USE_HASHTABLE_FOR_VERTEX_SEARCH

	TArray<unsigned short> oIndexBuffer;

	DELETE_OBJECT(m_poVB);
	DELETE_OBJECT(m_poIB);

	FILE *file = fopen(szFileName, "rt");
	if (!file)
		return false;

	char szLine[MAX_LINE_LEN];
	CString *ppsTokens;
	int iNumTokens;
	int iNumIndexes = 0;

	while (fgets(szLine, MAX_LINE_LEN, file)) {
		CString sLine(szLine);
		sLine.ToUpper();

		sLine.Tokenize(&ppsTokens, &iNumTokens, sDelimiters);

		if (iNumTokens == 0)
			continue;

		if (ppsTokens[0].Equals("MTLLIB")) {
			LoadMaterials(ppsTokens[1]);
		} else if (ppsTokens[0].Equals("VN")) {
			m_oNormalArray.Append(VECTOR3Df(ppsTokens[1].ToFloat(), ppsTokens[2].ToFloat(), ppsTokens[3].ToFloat()));
		} else if (ppsTokens[0].Equals("VT")) {
			m_oTextureCoordArray.Append(VECTOR2Df(ppsTokens[1].ToFloat(), ppsTokens[2].ToFloat()));
		} else if (ppsTokens[0].Equals("V")) {
			m_oVertexArray.Append(VECTOR3Df(ppsTokens[1].ToFloat(), ppsTokens[2].ToFloat(), ppsTokens[3].ToFloat()));
		} else if (ppsTokens[0].Equals("USEMTL")) {
			int iMaterialIndex = m_oMaterialNames.Find(ppsTokens[1]);
			m_oSubsetsMaterialIndex.Append(iMaterialIndex);
			m_oSubsetsStartIndex.Append(oIndexBuffer.GetSize());
		} else if (ppsTokens[0].Equals("F")) {
			struct FACE_STRUCT face;

			for (int i = 0; i < 3; i++) {
				face.iVertexIndex = ppsTokens[i * 3 + 1].ToInt() - 1;
				face.iTextureIndex = ppsTokens[i * 3 + 2].ToInt() - 1;
				face.iNormalIndex = ppsTokens[i * 3 + 3].ToInt() - 1;

#ifndef USE_HASHTABLE_FOR_VERTEX_SEARCH
				int index = oFaceBuffer.Find(face);
				if (index == -1) {
					oIndexBuffer.Append(oFaceBuffer.GetSize());
					oFaceBuffer.Append(face);
				} else {
					oIndexBuffer.Append(index);
				} 
#else
				FACE_STRUCT *found = oFaceHash.Find(face);
				if (found) {
					int index = found->iIndex;

					oIndexBuffer.Append(index);
				} else {
					face.iIndex = iNumIndexes++;
					oFaceHash.Insert(face);

					oIndexBuffer.Append(oFaceBuffer.GetSize());
					oFaceBuffer.Append(face);
				} 
#endif //USE_HASHTABLE_FOR_VERTEX_SEARCH
			}
		}

		SAFE_DELETE_ARRAY(ppsTokens);
	}


	m_oSubsetsStartIndex.Append(oIndexBuffer.GetSize());

	fclose(file);

	m_poIB = new CIndexBuffer(oIndexBuffer.GetSize());
	memcpy(m_poIB->GetIndexBuffer(), &oIndexBuffer[0], oIndexBuffer.GetSize() * sizeof(unsigned short));

	m_bHasTextures = m_oTextures.GetSize() > 0;
	m_bHasMaterials = m_oMaterials.GetSize() > 0;
	int iFormat = VERTEXFORMAT_XYZ | VERTEXFORMAT_NORMAL | (m_bHasTextures ? VERTEXFORMAT_TEXTURE : 0);

	m_poVB = new CVertexBuffer(iFormat, oFaceBuffer.GetSize());
	int iIndex = 0, iNumVertex = oFaceBuffer.GetSize();
	for (int i = 0; i < iNumVertex; i++) {
		float *pVertex = (float *)m_poVB->GetVertexAtIndex(i);

		memcpy(pVertex, &m_oVertexArray[oFaceBuffer[i].iVertexIndex], 3 * sizeof(float));
		memcpy(pVertex + 3, &m_oNormalArray[oFaceBuffer[i].iNormalIndex], 3 * sizeof(float));

		if (m_bHasTextures) 
			memcpy(pVertex + 6, &m_oTextureCoordArray[oFaceBuffer[i].iTextureIndex], 2 * sizeof(float));
	}

	return true;
}