<commit_before>// Plugins.cpp

#include "stdafx.h"
#include "Plugins.h"
#include  "wx/sizer.h"
#include  "wx/menuitem.h"
#include  "wx/checklst.h"
#include <wx/config.h>
#include <wx/confbase.h>
#include <wx/fileconf.h>

enum
{
    ID_BUTTON_ADD,
	ID_BUTTON_EDIT,
	ID_BUTTON_REMOVE,
	ID_BUTTON_PLUGIN_BROWSE,
	ID_LISTBOX_CONTROL
};

BEGIN_EVENT_TABLE( CPluginItemDialog, wxDialog )
EVT_BUTTON( ID_BUTTON_PLUGIN_BROWSE, CPluginItemDialog::OnButtonBrowse )
EVT_BUTTON( wxID_OK, CPluginItemDialog::OnButtonOK )
EVT_BUTTON( wxID_CANCEL, CPluginItemDialog::OnButtonCancel )
END_EVENT_TABLE()

CPluginItemDialog::CPluginItemDialog(wxWindow *parent, const wxString& title, PluginData& pd):wxDialog(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{
	m_pd = &pd;

    m_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);

    // create buttons
    wxButton *button1 = new wxButton(m_panel, wxID_OK);
    wxButton *button2 = new wxButton(m_panel, wxID_CANCEL);

    wxBoxSizer *mainsizer = new wxBoxSizer( wxVERTICAL );

    wxFlexGridSizer *gridsizer = new wxFlexGridSizer(3, 5, 5);
	gridsizer->Add(new wxStaticText(m_panel, wxID_ANY, _("Name")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));
	m_name_text_ctrl = new wxTextCtrl(m_panel, wxID_ANY, pd.name);
	gridsizer->Add(m_name_text_ctrl, wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL).Expand());
	gridsizer->Add(new wxStaticText(m_panel, wxID_ANY, _T("")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));
	gridsizer->Add(new wxStaticText(m_panel, wxID_ANY, _("File Path")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));
	m_path_text_ctrl = new wxTextCtrl(m_panel, wxID_ANY, pd.path, wxDefaultPosition, wxSize(400, 0));
	gridsizer->Add(m_path_text_ctrl, wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL).Expand());
    gridsizer->Add(new wxButton(m_panel, ID_BUTTON_PLUGIN_BROWSE, _T("...")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));

	gridsizer->AddGrowableCol(1, 1);

    wxBoxSizer *bottomsizer = new wxBoxSizer( wxHORIZONTAL );

    bottomsizer->Add( button1, 0, wxALL, 10 );
    bottomsizer->Add( button2, 0, wxALL, 10 );

    mainsizer->Add( gridsizer, wxSizerFlags().Align(wxALIGN_CENTER).Border(wxALL, 10).Expand() );
    mainsizer->Add( bottomsizer, wxSizerFlags().Align(wxALIGN_CENTER) );

    // tell frame to make use of sizer (or constraints, if any)
    m_panel->SetAutoLayout( true );
    m_panel->SetSizer( mainsizer );

#ifndef __WXWINCE__
    // don't allow frame to get smaller than what the sizers tell ye
    mainsizer->SetSizeHints( this );
#endif

    Show(true);
}

void CPluginItemDialog::OnButtonOK(wxCommandEvent& event)
{
	// it must have a name
	if(m_name_text_ctrl->GetValue().Len() == 0)
	{
		wxMessageBox(_("Plugin must have a name!"));
		m_name_text_ctrl->SetFocus();
		return;
	}

	// it must have a file path
	if(m_path_text_ctrl->GetValue().Len() == 0)
	{
		wxMessageBox(_("No file specified!"));
		m_path_text_ctrl->SetFocus();
		return;
	}

	m_pd->name = m_name_text_ctrl->GetValue();
	m_pd->path = m_path_text_ctrl->GetValue();

	EndModal(wxID_OK);
}

void CPluginItemDialog::OnButtonCancel(wxCommandEvent& event)
{
	EndModal(wxID_CANCEL);
}

void CPluginItemDialog::OnButtonBrowse(wxCommandEvent& event)
{
#ifdef WIN32
	wxString ext_str(_T("*.dll"));
#else
	wxString ext_str(_T("*.so"));
#endif
	wxString wildcard_string = wxString(_("shared library files")) + _T(" |") + ext_str;

    wxFileDialog dialog(this, _("Choose shared library file"), wxEmptyString, wxEmptyString, wildcard_string);
    dialog.CentreOnParent();

    if (dialog.ShowModal() == wxID_OK)
    {
		m_path_text_ctrl->SetValue(dialog.GetPath());
    }
}

BEGIN_EVENT_TABLE( CPluginsDialog, wxDialog )
EVT_BUTTON( ID_BUTTON_ADD, CPluginsDialog::OnButtonAdd )
EVT_BUTTON( ID_BUTTON_EDIT, CPluginsDialog::OnButtonEdit )
EVT_UPDATE_UI(ID_BUTTON_EDIT, CPluginsDialog::OnUpdateEdit)
EVT_BUTTON( ID_BUTTON_REMOVE, CPluginsDialog::OnButtonRemove )
EVT_UPDATE_UI(ID_BUTTON_REMOVE, CPluginsDialog::OnUpdateRemove)
EVT_BUTTON( wxID_OK, CPluginsDialog::OnButtonOK )
EVT_BUTTON( wxID_CANCEL, CPluginsDialog::OnButtonCancel )
EVT_LISTBOX_DCLICK(ID_LISTBOX_CONTROL, CPluginsDialog::OnListboxDblClick)
END_EVENT_TABLE()

CPluginsDialog::CPluginsDialog(wxWindow *parent):wxDialog(parent, wxID_ANY, _("HeeksCAD plugin libraries"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{
   // make a panel with some controls
    m_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);

	ReadPluginsList(m_plugins);

    CreateCheckListbox();

    // create buttons
    wxButton *button1 = new wxButton(m_panel, ID_BUTTON_ADD, _("New"));
    wxButton *button2 = new wxButton(m_panel, ID_BUTTON_EDIT, _("Edit"));
    wxButton *button3 = new wxButton(m_panel, ID_BUTTON_REMOVE, _("Delete"));
    wxButton *button4 = new wxButton(m_panel, wxID_OK);
    wxButton *button5 = new wxButton(m_panel, wxID_CANCEL);

    wxBoxSizer *mainsizer = new wxBoxSizer( wxVERTICAL );

    mainsizer->Add( m_pListBox, 1, wxGROW|wxALL, 10 );

    wxBoxSizer *bottomsizer = new wxBoxSizer( wxHORIZONTAL );

    bottomsizer->Add( button1, 0, wxALL, 10 );
    bottomsizer->Add( button2, 0, wxALL, 10 );
    bottomsizer->Add( button3, 0, wxALL, 10 );
    bottomsizer->Add( button4, 0, wxALL, 10 );
    bottomsizer->Add( button5, 0, wxALL, 10 );

    mainsizer->Add( bottomsizer, 0, wxCENTER );

    // tell frame to make use of sizer (or constraints, if any)
    m_panel->SetAutoLayout( true );
    m_panel->SetSizer( mainsizer );

#ifndef __WXWINCE__
    // don't allow frame to get smaller than what the sizers tell ye
    mainsizer->SetSizeHints( this );
#endif

    Show(true);
}

void ReadPluginsList(std::list<PluginData> &plugins)
{
	plugins.clear();

	::wxSetWorkingDirectory(wxGetApp().GetExeFolder());
	wxConfig plugins_config(_T("HeeksCAD"));
	plugins_config.SetPath(_T("/plugins"));

	wxString key;
	long Index;
	wxString str;

	bool entry_found = false;

	entry_found = plugins_config.GetFirstEntry(key, Index);

	while(entry_found)
	{
		plugins_config.Read(key, &str);

		PluginData pd;
		if(str[0] == '#')
		{
			str = str.Mid(1);
			pd.enabled = false;
		}
		else
		{
			pd.enabled = true;
		}

		pd.name = key;
		pd.path = str;

		plugins.push_back(pd);

		entry_found = plugins_config.GetNextEntry(key, Index);
	}
}

void CPluginsDialog::CreateCheckListbox(long flags)
{
    wxString *astrChoices = new wxString[m_plugins.size()];
    unsigned int ui = 0;
	for ( std::list<PluginData>::iterator It = m_plugins.begin(); It != m_plugins.end(); It++, ui++ )
	{
		PluginData &pd = *It;
		astrChoices[ui] = pd.name;
	}

    m_pListBox = new wxCheckListBox
        (
         m_panel,               // parent
         ID_LISTBOX_CONTROL,       // control id
         wxPoint(10, 10),       // listbox poistion
         wxSize(400, 100),      // listbox size
         m_plugins.size(),		// number of strings
         astrChoices,           // array of strings
         flags
        );

    delete [] astrChoices;

    ui = 0;
	for ( std::list<PluginData>::iterator It = m_plugins.begin(); It != m_plugins.end(); It++, ui++ )
	{
		PluginData &pd = *It;
		if(pd.enabled)m_pListBox->Check(ui);
	}
}

void CPluginsDialog::EditSelected(unsigned int selection)
{
	unsigned int ui = 0;
	for ( std::list<PluginData>::iterator It = m_plugins.begin(); It != m_plugins.end(); It++, ui++ )
	{
		if(ui == selection)
		{
			PluginData &pd = *It;
			CPluginItemDialog dlg(this, _("Add New Plugin"), pd);
			if(dlg.ShowModal() == wxID_OK)
			{
				// updata the check list
				delete m_pListBox;
				CreateCheckListbox();
			}
		}
	}
}

void CPluginsDialog::OnButtonAdd(wxCommandEvent& event)
{
	PluginData pd;
	CPluginItemDialog dlg(this, _("Add New Plugin"), pd);
	if(dlg.ShowModal() == wxID_OK)
	{
		// add the new item
		m_plugins.push_back(pd);

		// updata the check list
		delete m_pListBox;
		CreateCheckListbox();
	}
}

void CPluginsDialog::OnButtonEdit(wxCommandEvent& event)
{
	int selection = m_pListBox->GetSelection();

	EditSelected(selection);
}

void CPluginsDialog::OnUpdateEdit( wxUpdateUIEvent& event )
{
	event.Enable(m_pListBox->GetSelection() >= 0);
}

void CPluginsDialog::OnUpdateRemove( wxUpdateUIEvent& event )
{
	event.Enable(m_pListBox->GetSelection() >= 0);
}

void CPluginsDialog::OnButtonRemove(wxCommandEvent& event)
{
	delete m_pListBox;
	CreateCheckListbox();
}

void CPluginsDialog::OnButtonOK(wxCommandEvent& event)
{
	::wxSetWorkingDirectory(wxGetApp().GetExeFolder());

	wxConfig plugins_config(_T("HeeksCAD"));
	plugins_config.SetPath(_T("/plugins"));

	plugins_config.DeleteGroup(_T("plugins"));

	unsigned int ui = 0;
	for ( std::list<PluginData>::iterator It = m_plugins.begin(); It != m_plugins.end(); It++, ui++ )
	{
		PluginData &pd = *It;
		pd.enabled = m_pListBox->IsChecked(ui);
		wxString value = pd.path;
		if(!(pd.enabled))value.Prepend(_T("#"));
		plugins_config.Write(pd.name, value);
	}

	EndModal(wxID_OK);
}

void CPluginsDialog::OnButtonCancel(wxCommandEvent& event)
{
	EndModal(wxID_CANCEL);
}

void CPluginsDialog::OnListboxDblClick(wxCommandEvent& WXUNUSED(event))
{
    int selection = m_pListBox->GetSelection();

	EditSelected(selection);
}
<commit_msg>I made the "Delete" button in the plugins dialog work.<commit_after>// Plugins.cpp

#include "stdafx.h"
#include "Plugins.h"
#include  "wx/sizer.h"
#include  "wx/menuitem.h"
#include  "wx/checklst.h"
#include <wx/config.h>
#include <wx/confbase.h>
#include <wx/fileconf.h>

enum
{
    ID_BUTTON_ADD,
	ID_BUTTON_EDIT,
	ID_BUTTON_REMOVE,
	ID_BUTTON_PLUGIN_BROWSE,
	ID_LISTBOX_CONTROL
};

BEGIN_EVENT_TABLE( CPluginItemDialog, wxDialog )
EVT_BUTTON( ID_BUTTON_PLUGIN_BROWSE, CPluginItemDialog::OnButtonBrowse )
EVT_BUTTON( wxID_OK, CPluginItemDialog::OnButtonOK )
EVT_BUTTON( wxID_CANCEL, CPluginItemDialog::OnButtonCancel )
END_EVENT_TABLE()

CPluginItemDialog::CPluginItemDialog(wxWindow *parent, const wxString& title, PluginData& pd):wxDialog(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{
	m_pd = &pd;

    m_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);

    // create buttons
    wxButton *button1 = new wxButton(m_panel, wxID_OK);
    wxButton *button2 = new wxButton(m_panel, wxID_CANCEL);

    wxBoxSizer *mainsizer = new wxBoxSizer( wxVERTICAL );

    wxFlexGridSizer *gridsizer = new wxFlexGridSizer(3, 5, 5);
	gridsizer->Add(new wxStaticText(m_panel, wxID_ANY, _("Name")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));
	m_name_text_ctrl = new wxTextCtrl(m_panel, wxID_ANY, pd.name);
	gridsizer->Add(m_name_text_ctrl, wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL).Expand());
	gridsizer->Add(new wxStaticText(m_panel, wxID_ANY, _T("")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));
	gridsizer->Add(new wxStaticText(m_panel, wxID_ANY, _("File Path")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));
	m_path_text_ctrl = new wxTextCtrl(m_panel, wxID_ANY, pd.path, wxDefaultPosition, wxSize(400, 0));
	gridsizer->Add(m_path_text_ctrl, wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL).Expand());
    gridsizer->Add(new wxButton(m_panel, ID_BUTTON_PLUGIN_BROWSE, _T("...")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));

	gridsizer->AddGrowableCol(1, 1);

    wxBoxSizer *bottomsizer = new wxBoxSizer( wxHORIZONTAL );

    bottomsizer->Add( button1, 0, wxALL, 10 );
    bottomsizer->Add( button2, 0, wxALL, 10 );

    mainsizer->Add( gridsizer, wxSizerFlags().Align(wxALIGN_CENTER).Border(wxALL, 10).Expand() );
    mainsizer->Add( bottomsizer, wxSizerFlags().Align(wxALIGN_CENTER) );

    // tell frame to make use of sizer (or constraints, if any)
    m_panel->SetAutoLayout( true );
    m_panel->SetSizer( mainsizer );

#ifndef __WXWINCE__
    // don't allow frame to get smaller than what the sizers tell ye
    mainsizer->SetSizeHints( this );
#endif

    Show(true);
}

void CPluginItemDialog::OnButtonOK(wxCommandEvent& event)
{
	// it must have a name
	if(m_name_text_ctrl->GetValue().Len() == 0)
	{
		wxMessageBox(_("Plugin must have a name!"));
		m_name_text_ctrl->SetFocus();
		return;
	}

	// it must have a file path
	if(m_path_text_ctrl->GetValue().Len() == 0)
	{
		wxMessageBox(_("No file specified!"));
		m_path_text_ctrl->SetFocus();
		return;
	}

	m_pd->name = m_name_text_ctrl->GetValue();
	m_pd->path = m_path_text_ctrl->GetValue();

	EndModal(wxID_OK);
}

void CPluginItemDialog::OnButtonCancel(wxCommandEvent& event)
{
	EndModal(wxID_CANCEL);
}

void CPluginItemDialog::OnButtonBrowse(wxCommandEvent& event)
{
#ifdef WIN32
	wxString ext_str(_T("*.dll"));
#else
	wxString ext_str(_T("*.so"));
#endif
	wxString wildcard_string = wxString(_("shared library files")) + _T(" |") + ext_str;

    wxFileDialog dialog(this, _("Choose shared library file"), wxEmptyString, wxEmptyString, wildcard_string);
    dialog.CentreOnParent();

    if (dialog.ShowModal() == wxID_OK)
    {
		m_path_text_ctrl->SetValue(dialog.GetPath());
    }
}

BEGIN_EVENT_TABLE( CPluginsDialog, wxDialog )
EVT_BUTTON( ID_BUTTON_ADD, CPluginsDialog::OnButtonAdd )
EVT_BUTTON( ID_BUTTON_EDIT, CPluginsDialog::OnButtonEdit )
EVT_UPDATE_UI(ID_BUTTON_EDIT, CPluginsDialog::OnUpdateEdit)
EVT_BUTTON( ID_BUTTON_REMOVE, CPluginsDialog::OnButtonRemove )
EVT_UPDATE_UI(ID_BUTTON_REMOVE, CPluginsDialog::OnUpdateRemove)
EVT_BUTTON( wxID_OK, CPluginsDialog::OnButtonOK )
EVT_BUTTON( wxID_CANCEL, CPluginsDialog::OnButtonCancel )
EVT_LISTBOX_DCLICK(ID_LISTBOX_CONTROL, CPluginsDialog::OnListboxDblClick)
END_EVENT_TABLE()

CPluginsDialog::CPluginsDialog(wxWindow *parent):wxDialog(parent, wxID_ANY, _("HeeksCAD plugin libraries"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{
   // make a panel with some controls
    m_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);

	ReadPluginsList(m_plugins);

    CreateCheckListbox();

    // create buttons
    wxButton *button1 = new wxButton(m_panel, ID_BUTTON_ADD, _("New"));
    wxButton *button2 = new wxButton(m_panel, ID_BUTTON_EDIT, _("Edit"));
    wxButton *button3 = new wxButton(m_panel, ID_BUTTON_REMOVE, _("Delete"));
    wxButton *button4 = new wxButton(m_panel, wxID_OK);
    wxButton *button5 = new wxButton(m_panel, wxID_CANCEL);

    wxBoxSizer *mainsizer = new wxBoxSizer( wxVERTICAL );

    mainsizer->Add( m_pListBox, 1, wxGROW|wxALL, 10 );

    wxBoxSizer *bottomsizer = new wxBoxSizer( wxHORIZONTAL );

    bottomsizer->Add( button1, 0, wxALL, 10 );
    bottomsizer->Add( button2, 0, wxALL, 10 );
    bottomsizer->Add( button3, 0, wxALL, 10 );
    bottomsizer->Add( button4, 0, wxALL, 10 );
    bottomsizer->Add( button5, 0, wxALL, 10 );

    mainsizer->Add( bottomsizer, 0, wxCENTER );

    // tell frame to make use of sizer (or constraints, if any)
    m_panel->SetAutoLayout( true );
    m_panel->SetSizer( mainsizer );

#ifndef __WXWINCE__
    // don't allow frame to get smaller than what the sizers tell ye
    mainsizer->SetSizeHints( this );
#endif

    Show(true);
}

void ReadPluginsList(std::list<PluginData> &plugins)
{
	plugins.clear();

	::wxSetWorkingDirectory(wxGetApp().GetExeFolder());
	wxConfig plugins_config(_T("HeeksCAD"));
	plugins_config.SetPath(_T("/plugins"));

	wxString key;
	long Index;
	wxString str;

	bool entry_found = false;

	entry_found = plugins_config.GetFirstEntry(key, Index);

	while(entry_found)
	{
		plugins_config.Read(key, &str);

		PluginData pd;
		if(str[0] == '#')
		{
			str = str.Mid(1);
			pd.enabled = false;
		}
		else
		{
			pd.enabled = true;
		}

		pd.name = key;
		pd.path = str;

		plugins.push_back(pd);

		entry_found = plugins_config.GetNextEntry(key, Index);
	}
}

void CPluginsDialog::CreateCheckListbox(long flags)
{
    wxString *astrChoices = new wxString[m_plugins.size()];
    unsigned int ui = 0;
	for ( std::list<PluginData>::iterator It = m_plugins.begin(); It != m_plugins.end(); It++, ui++ )
	{
		PluginData &pd = *It;
		astrChoices[ui] = pd.name;
	}

    m_pListBox = new wxCheckListBox
        (
         m_panel,               // parent
         ID_LISTBOX_CONTROL,       // control id
         wxPoint(10, 10),       // listbox poistion
         wxSize(400, 100),      // listbox size
         m_plugins.size(),		// number of strings
         astrChoices,           // array of strings
         flags
        );

    delete [] astrChoices;

    ui = 0;
	for ( std::list<PluginData>::iterator It = m_plugins.begin(); It != m_plugins.end(); It++, ui++ )
	{
		PluginData &pd = *It;
		if(pd.enabled)m_pListBox->Check(ui);
	}
}

void CPluginsDialog::EditSelected(unsigned int selection)
{
	unsigned int ui = 0;
	for ( std::list<PluginData>::iterator It = m_plugins.begin(); It != m_plugins.end(); It++, ui++ )
	{
		if(ui == selection)
		{
			PluginData &pd = *It;
			CPluginItemDialog dlg(this, _("Add New Plugin"), pd);
			if(dlg.ShowModal() == wxID_OK)
			{
				// updata the check list
				delete m_pListBox;
				CreateCheckListbox();
			}
		}
	}
}

void CPluginsDialog::OnButtonAdd(wxCommandEvent& event)
{
	PluginData pd;
	CPluginItemDialog dlg(this, _("Add New Plugin"), pd);
	if(dlg.ShowModal() == wxID_OK)
	{
		// add the new item
		m_plugins.push_back(pd);

		// updata the check list
		delete m_pListBox;
		CreateCheckListbox();
	}
}

void CPluginsDialog::OnButtonEdit(wxCommandEvent& event)
{
	unsigned int selection = m_pListBox->GetSelection();

	EditSelected(selection);
}

void CPluginsDialog::OnUpdateEdit( wxUpdateUIEvent& event )
{
	event.Enable(m_pListBox->GetSelection() >= 0);
}

void CPluginsDialog::OnUpdateRemove( wxUpdateUIEvent& event )
{
	event.Enable(m_pListBox->GetSelection() >= 0);
}

void CPluginsDialog::OnButtonRemove(wxCommandEvent& event)
{
	unsigned int selection = m_pListBox->GetSelection();
	unsigned int ui = 0;
	for ( std::list<PluginData>::iterator It = m_plugins.begin(); It != m_plugins.end(); It++, ui++ )
	{
		if(ui == selection)
		{
			m_plugins.erase(It);
			// updata the check list
			delete m_pListBox;
			CreateCheckListbox();
			break;
		}
	}
}

void CPluginsDialog::OnButtonOK(wxCommandEvent& event)
{
	::wxSetWorkingDirectory(wxGetApp().GetExeFolder());

	wxConfig plugins_config(_T("HeeksCAD"));
	plugins_config.SetPath(_T("/plugins"));

	plugins_config.DeleteGroup(_T("plugins"));

	unsigned int ui = 0;
	for ( std::list<PluginData>::iterator It = m_plugins.begin(); It != m_plugins.end(); It++, ui++ )
	{
		PluginData &pd = *It;
		pd.enabled = m_pListBox->IsChecked(ui);
		wxString value = pd.path;
		if(!(pd.enabled))value.Prepend(_T("#"));
		plugins_config.Write(pd.name, value);
	}

	EndModal(wxID_OK);
}

void CPluginsDialog::OnButtonCancel(wxCommandEvent& event)
{
	EndModal(wxID_CANCEL);
}

void CPluginsDialog::OnListboxDblClick(wxCommandEvent& WXUNUSED(event))
{
    int selection = m_pListBox->GetSelection();

	EditSelected(selection);
}
<|endoftext|>


<commit_before>// SciTE - Scintilla based Text Editor
// PropSet.cxx - a java style properties file module
// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

// Maintain a dictionary of properties

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>

#include "Platform.h"

#include "PropSet.h"

bool EqualCaseInsensitive(const char *a, const char *b) {
#if PLAT_GTK
	return 0 == strcasecmp(a, b);
#elif PLAT_WIN
	return 0 == stricmp(a, b);
#elif PLAT_WX
	return 0 == wxStricmp(a, b);
#endif
}

// Get a line of input. If end of line escaped with '\\' then continue reading.
static bool GetFullLine(const char *&fpc, int &lenData, char *s, int len) {
	bool continuation = true;
	s[0] = '\0';
	while ((len > 1) && lenData > 0) {
		char ch = *fpc;
		fpc++;
		lenData--;
		if ((ch == '\r') || (ch == '\n')) {
			if (!continuation) {
				if ((lenData > 0) && (ch == '\r') && ((*fpc) == '\n')) {
					// munch the second half of a crlf
					fpc++;
					lenData--;
				}
				*s = '\0';
				return true;
			}
		} else if ((ch == '\\') && (lenData > 0) && ((*fpc == '\r') || (*fpc == '\n'))) {
			continuation = true;
		} else {
			continuation = false;
			*s++ = ch;
			*s = '\0';
			len--;
		}
	}
	return false;
}

PropSet::PropSet() {
	superPS = 0;
	size = 10;
	used = 0;
	vals = new char * [size];
}

PropSet::~PropSet() {
	superPS = 0;
	Clear();
	delete []vals;
}

void PropSet::EnsureCanAddEntry() {
	if (used >= size - 2) {
		int newsize = size + 10;
		char **newvals = new char * [newsize];

		for (int i = 0; i < used; i++) {
			newvals[i] = vals[i];
		}
		delete []vals;
		vals = newvals;
		size = newsize;
	}
}

void PropSet::Set(const char *key, const char *val) {
	EnsureCanAddEntry();
	for (int i = 0; i < used; i += 2) {
		if (0 == strcmp(vals[i], key)) {
			// Replace current value
			delete [](vals[i + 1]);
			vals[i + 1] = StringDup(val);
			return;
		}
	}
	// Not found
	vals[used++] = StringDup(key);
	vals[used++] = StringDup(val);
}

void PropSet::Set(char *keyval) {
    while (isspace(*keyval))
        keyval++;
	char *eqat = strchr(keyval, '=');
	if (eqat) {
		*eqat = '\0';
		Set(keyval, eqat + 1);
		*eqat = '=';
	}
}

SString PropSet::Get(const char *key) {
	for (int i = 0; i < used; i += 2) {
		if (0 == strcmp(vals[i], key)) {
			return vals[i + 1];
		}
	}
	if (superPS) {
		// Failed here, so try in base property set
		return superPS->Get(key);
	} else {
		return "";
	}
}

int PropSet::GetInt(const char *key, int defaultValue) {
	SString val = Get(key);
	if (val.length())
		return val.value();
	else
		return defaultValue;
}

bool isprefix(const char *target, const char *prefix) {
	while (*target && *prefix) {
		if (*target != *prefix)
			return false;
		target++;
		prefix++;
	}
	if (*prefix)
		return false;
	else
		return true;
}

bool issuffix(const char *target, const char *suffix) {
	int lentarget = strlen(target);
	int lensuffix = strlen(suffix);
	if (lensuffix > lentarget)
		return false;
	for (int i = lensuffix - 1; i >= 0; i--) {
		if (target[i + lentarget - lensuffix] != suffix[i])
			return false;
	}
	return true;
}

SString PropSet::GetWild(const char *keybase, const char *filename) {
	for (int i = 0; i < used; i += 2) {
		if (isprefix(vals[i], keybase)) {
			char *orgkeyfile = vals[i] + strlen(keybase);
			char *keyfile = NULL;

			if (strstr(orgkeyfile, "$(") == orgkeyfile) {
				char *cpendvar = strchr(orgkeyfile, ')');
				if (cpendvar) {
					*cpendvar = '\0';
					SString s = Get(orgkeyfile + 2);
					*cpendvar= ')';
					keyfile = strdup(s.c_str());
				}
			}
			char *keyptr = keyfile;

			if (keyfile == NULL)
				keyfile = orgkeyfile;

			for (; ; ) {
				char *del = strchr(keyfile, ';');
				if (del == NULL)
					del = keyfile + strlen(keyfile);
				char delchr = *del;
				*del = '\0';
				if (*keyfile == '*') {
					if (issuffix(filename, keyfile + 1)) {
						*del = delchr;
						free(keyptr);
						return vals[i + 1];
					}
				} else if (0 == strcmp(keyfile, filename)) {
					*del = delchr;
					free(keyptr);
					return vals[i + 1];
				}
				if (delchr == '\0')
					break;
				*del = delchr;
				keyfile = del + 1;
			}
			free(keyptr);

			if (0 == strcmp(vals[i], keybase)) {
				return vals[i + 1];
			}
		}
	}
	if (superPS) {
		// Failed here, so try in base property set
		return superPS->GetWild(keybase, filename);
	} else {
		return "";
	}
}

SString PropSet::GetNewExpand(const char *keybase, const char *filename) {
	char *base = StringDup(GetWild(keybase, filename).c_str());
	char *cpvar = strstr(base, "$(");
	while (cpvar) {
		char *cpendvar = strchr(cpvar, ')');
		if (cpendvar) {
			int lenvar = cpendvar - cpvar - 2;  	// Subtract the $()
			char *var = new char[lenvar + 1];
			strncpy(var, cpvar + 2, lenvar);
			var[lenvar] = '\0';
			SString val = GetWild(var, filename);
			int newlenbase = strlen(base) + val.length() - lenvar;
			char *newbase = new char[newlenbase];
			strncpy(newbase, base, cpvar - base);
			strcpy(newbase + (cpvar - base), val.c_str());
			strcpy(newbase + (cpvar - base) + val.length(), cpendvar + 1);
			delete []var;
			delete []base;
			base = newbase;
		}
		cpvar = strstr(base, "$(");
	}
	SString sret = base;
	delete []base;
	return sret;
}

void PropSet::Clear() {
	for (int i = 0; i < used; i++) {
		delete [](vals[i]);
		vals[i] = 0;
	}
	used = 0;
}

void PropSet::ReadFromMemory(const char *data, int len, const char *directoryForImports) {
	const char *pd = data;
	char linebuf[60000];
	bool ifIsTrue = true;
	while (len > 0) {
		GetFullLine(pd, len, linebuf, sizeof(linebuf));
		if (isalpha(linebuf[0]))    // If clause ends with first non-indented line
			ifIsTrue = true;
		if (isprefix(linebuf, "if ")) {
			const char *expr = linebuf + strlen("if") + 1;
			ifIsTrue = GetInt(expr);
		} else if (isprefix(linebuf, "import ") && directoryForImports) {
			char importPath[MAX_PATH];
			strcpy(importPath, directoryForImports);
			strcat(importPath, linebuf + strlen("import") + 1);
			strcat(importPath, ".properties");
            Read(importPath,directoryForImports);
		} else if (isalpha(linebuf[0])) {
			Set(linebuf);
		} else if (isspace(linebuf[0]) && ifIsTrue) {
			Set(linebuf);
		}
	}
}

void PropSet::Read(const char *filename, const char *directoryForImports) {
	char propsData[60000];
	FILE *rcfile = fopen(filename, "rb");
	if (rcfile) {
		int lenFile = fread(propsData, 1, sizeof(propsData), rcfile);
		fclose(rcfile);
		ReadFromMemory(propsData, lenFile, directoryForImports);
	} else {
		//printf("Could not open <%s>\n", filename);
	}
}

static bool iswordsep(char ch, bool onlyLineEnds) {
	if (!isspace(ch))
		return false;
	if (!onlyLineEnds)
		return true;
	return ch == '\r' || ch == '\n';
}

// Creates an array that points into each word in the string and puts \0 terminators
// after each word.
static char **ArrayFromWordList(char *wordlist, bool onlyLineEnds = false) {
	char prev = '\n';
	int words = 0;
	for (int j = 0; wordlist[j]; j++) {
		if (!iswordsep(wordlist[j], onlyLineEnds) && iswordsep(prev, onlyLineEnds))
			words++;
		prev = wordlist[j];
	}
	char **keywords = new char * [words + 1];
	if (keywords) {
		words = 0;
		prev = '\0';
		int len = strlen(wordlist);
		for (int k = 0; k < len; k++) {
			if (!iswordsep(wordlist[k], onlyLineEnds)) {
				if (!prev) {
					keywords[words] = &wordlist[k];
					words++;
				}
			} else {
				wordlist[k] = '\0';
			}
			prev = wordlist[k];
		}
		keywords[words] = &wordlist[len];
	}
	return keywords;
}

void WordList::Clear() {
	if (words) {
		delete []words;
		delete []list;
	}
	words = 0;
	list = 0;
	len = 0;
}

void WordList::Set(const char *s) {
	len = 0;
	list = StringDup(s);
	words = ArrayFromWordList(list, onlyLineEnds);
}

char *WordList::Allocate(int size) {
	list = new char[size + 1];
	list[size] = '\0';
	return list;
}

void WordList::SetFromAllocated() {
	len = 0;
	words = ArrayFromWordList(list, onlyLineEnds);
}

// Shell sort based upon public domain C implementation by Raymond Gardner 1991
// Used here because of problems with mingw qsort.
static void SortWordList(char **words, unsigned int len) {
	unsigned int gap = len / 2;

	while (gap > 0) {
		unsigned int i = gap;
		while (i < len) {
			unsigned int j = i;
			char **a = words + j;
			do {
				j -= gap;
				char **b = a;
				a -= gap;
				if (strcmp(*a, *b) > 0) {
					char *tmp = *a;
					*a = *b;
					*b = tmp;
				} else {
					break;
				}
			} while (j >= gap);
			i++;
		}
		gap = gap / 2;
	}
}

bool WordList::InList(const char *s) {
	if (0 == words)
		return false;
	if (len == 0) {
		for (int i = 0; words[i][0]; i++)
			len++;
		SortWordList(words, len);
		for (unsigned int k = 0; k < (sizeof(starts) / sizeof(starts[0])); k++)
			starts[k] = -1;
		for (int l = len - 1; l >= 0; l--) {
			unsigned char indexChar = words[l][0];
			starts[indexChar] = l;
		}
	}
	unsigned char firstChar = s[0];
	int j = starts[firstChar];
	if (j >= 0) {
		while (words[j][0] == firstChar) {
			if (s[1] == words[j][1]) {
				const char *a = words[j] + 1;
				const char *b = s + 1;
				while (*a && *a == *b) {
					a++;
					b++;
				}
				if (!*a && !*b)
					return true;
			}
			j++;
		}
	}
	return false;
}
<commit_msg>Changed MAX_PATH to 1024 to make GTK+ version compile.<commit_after>// SciTE - Scintilla based Text Editor
// PropSet.cxx - a java style properties file module
// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

// Maintain a dictionary of properties

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>

#include "Platform.h"

#include "PropSet.h"

bool EqualCaseInsensitive(const char *a, const char *b) {
#if PLAT_GTK
	return 0 == strcasecmp(a, b);
#elif PLAT_WIN
	return 0 == stricmp(a, b);
#elif PLAT_WX
	return 0 == wxStricmp(a, b);
#endif
}

// Get a line of input. If end of line escaped with '\\' then continue reading.
static bool GetFullLine(const char *&fpc, int &lenData, char *s, int len) {
	bool continuation = true;
	s[0] = '\0';
	while ((len > 1) && lenData > 0) {
		char ch = *fpc;
		fpc++;
		lenData--;
		if ((ch == '\r') || (ch == '\n')) {
			if (!continuation) {
				if ((lenData > 0) && (ch == '\r') && ((*fpc) == '\n')) {
					// munch the second half of a crlf
					fpc++;
					lenData--;
				}
				*s = '\0';
				return true;
			}
		} else if ((ch == '\\') && (lenData > 0) && ((*fpc == '\r') || (*fpc == '\n'))) {
			continuation = true;
		} else {
			continuation = false;
			*s++ = ch;
			*s = '\0';
			len--;
		}
	}
	return false;
}

PropSet::PropSet() {
	superPS = 0;
	size = 10;
	used = 0;
	vals = new char * [size];
}

PropSet::~PropSet() {
	superPS = 0;
	Clear();
	delete []vals;
}

void PropSet::EnsureCanAddEntry() {
	if (used >= size - 2) {
		int newsize = size + 10;
		char **newvals = new char * [newsize];

		for (int i = 0; i < used; i++) {
			newvals[i] = vals[i];
		}
		delete []vals;
		vals = newvals;
		size = newsize;
	}
}

void PropSet::Set(const char *key, const char *val) {
	EnsureCanAddEntry();
	for (int i = 0; i < used; i += 2) {
		if (0 == strcmp(vals[i], key)) {
			// Replace current value
			delete [](vals[i + 1]);
			vals[i + 1] = StringDup(val);
			return;
		}
	}
	// Not found
	vals[used++] = StringDup(key);
	vals[used++] = StringDup(val);
}

void PropSet::Set(char *keyval) {
    while (isspace(*keyval))
        keyval++;
	char *eqat = strchr(keyval, '=');
	if (eqat) {
		*eqat = '\0';
		Set(keyval, eqat + 1);
		*eqat = '=';
	}
}

SString PropSet::Get(const char *key) {
	for (int i = 0; i < used; i += 2) {
		if (0 == strcmp(vals[i], key)) {
			return vals[i + 1];
		}
	}
	if (superPS) {
		// Failed here, so try in base property set
		return superPS->Get(key);
	} else {
		return "";
	}
}

int PropSet::GetInt(const char *key, int defaultValue) {
	SString val = Get(key);
	if (val.length())
		return val.value();
	else
		return defaultValue;
}

bool isprefix(const char *target, const char *prefix) {
	while (*target && *prefix) {
		if (*target != *prefix)
			return false;
		target++;
		prefix++;
	}
	if (*prefix)
		return false;
	else
		return true;
}

bool issuffix(const char *target, const char *suffix) {
	int lentarget = strlen(target);
	int lensuffix = strlen(suffix);
	if (lensuffix > lentarget)
		return false;
	for (int i = lensuffix - 1; i >= 0; i--) {
		if (target[i + lentarget - lensuffix] != suffix[i])
			return false;
	}
	return true;
}

SString PropSet::GetWild(const char *keybase, const char *filename) {
	for (int i = 0; i < used; i += 2) {
		if (isprefix(vals[i], keybase)) {
			char *orgkeyfile = vals[i] + strlen(keybase);
			char *keyfile = NULL;

			if (strstr(orgkeyfile, "$(") == orgkeyfile) {
				char *cpendvar = strchr(orgkeyfile, ')');
				if (cpendvar) {
					*cpendvar = '\0';
					SString s = Get(orgkeyfile + 2);
					*cpendvar= ')';
					keyfile = strdup(s.c_str());
				}
			}
			char *keyptr = keyfile;

			if (keyfile == NULL)
				keyfile = orgkeyfile;

			for (; ; ) {
				char *del = strchr(keyfile, ';');
				if (del == NULL)
					del = keyfile + strlen(keyfile);
				char delchr = *del;
				*del = '\0';
				if (*keyfile == '*') {
					if (issuffix(filename, keyfile + 1)) {
						*del = delchr;
						free(keyptr);
						return vals[i + 1];
					}
				} else if (0 == strcmp(keyfile, filename)) {
					*del = delchr;
					free(keyptr);
					return vals[i + 1];
				}
				if (delchr == '\0')
					break;
				*del = delchr;
				keyfile = del + 1;
			}
			free(keyptr);

			if (0 == strcmp(vals[i], keybase)) {
				return vals[i + 1];
			}
		}
	}
	if (superPS) {
		// Failed here, so try in base property set
		return superPS->GetWild(keybase, filename);
	} else {
		return "";
	}
}

SString PropSet::GetNewExpand(const char *keybase, const char *filename) {
	char *base = StringDup(GetWild(keybase, filename).c_str());
	char *cpvar = strstr(base, "$(");
	while (cpvar) {
		char *cpendvar = strchr(cpvar, ')');
		if (cpendvar) {
			int lenvar = cpendvar - cpvar - 2;  	// Subtract the $()
			char *var = new char[lenvar + 1];
			strncpy(var, cpvar + 2, lenvar);
			var[lenvar] = '\0';
			SString val = GetWild(var, filename);
			int newlenbase = strlen(base) + val.length() - lenvar;
			char *newbase = new char[newlenbase];
			strncpy(newbase, base, cpvar - base);
			strcpy(newbase + (cpvar - base), val.c_str());
			strcpy(newbase + (cpvar - base) + val.length(), cpendvar + 1);
			delete []var;
			delete []base;
			base = newbase;
		}
		cpvar = strstr(base, "$(");
	}
	SString sret = base;
	delete []base;
	return sret;
}

void PropSet::Clear() {
	for (int i = 0; i < used; i++) {
		delete [](vals[i]);
		vals[i] = 0;
	}
	used = 0;
}

void PropSet::ReadFromMemory(const char *data, int len, const char *directoryForImports) {
	const char *pd = data;
	char linebuf[60000];
	bool ifIsTrue = true;
	while (len > 0) {
		GetFullLine(pd, len, linebuf, sizeof(linebuf));
		if (isalpha(linebuf[0]))    // If clause ends with first non-indented line
			ifIsTrue = true;
		if (isprefix(linebuf, "if ")) {
			const char *expr = linebuf + strlen("if") + 1;
			ifIsTrue = GetInt(expr);
		} else if (isprefix(linebuf, "import ") && directoryForImports) {
			char importPath[1024];
			strcpy(importPath, directoryForImports);
			strcat(importPath, linebuf + strlen("import") + 1);
			strcat(importPath, ".properties");
            		Read(importPath,directoryForImports);
		} else if (isalpha(linebuf[0])) {
			Set(linebuf);
		} else if (isspace(linebuf[0]) && ifIsTrue) {
			Set(linebuf);
		}
	}
}

void PropSet::Read(const char *filename, const char *directoryForImports) {
	char propsData[60000];
	FILE *rcfile = fopen(filename, "rb");
	if (rcfile) {
		int lenFile = fread(propsData, 1, sizeof(propsData), rcfile);
		fclose(rcfile);
		ReadFromMemory(propsData, lenFile, directoryForImports);
	} else {
		//printf("Could not open <%s>\n", filename);
	}
}

static bool iswordsep(char ch, bool onlyLineEnds) {
	if (!isspace(ch))
		return false;
	if (!onlyLineEnds)
		return true;
	return ch == '\r' || ch == '\n';
}

// Creates an array that points into each word in the string and puts \0 terminators
// after each word.
static char **ArrayFromWordList(char *wordlist, bool onlyLineEnds = false) {
	char prev = '\n';
	int words = 0;
	for (int j = 0; wordlist[j]; j++) {
		if (!iswordsep(wordlist[j], onlyLineEnds) && iswordsep(prev, onlyLineEnds))
			words++;
		prev = wordlist[j];
	}
	char **keywords = new char * [words + 1];
	if (keywords) {
		words = 0;
		prev = '\0';
		int len = strlen(wordlist);
		for (int k = 0; k < len; k++) {
			if (!iswordsep(wordlist[k], onlyLineEnds)) {
				if (!prev) {
					keywords[words] = &wordlist[k];
					words++;
				}
			} else {
				wordlist[k] = '\0';
			}
			prev = wordlist[k];
		}
		keywords[words] = &wordlist[len];
	}
	return keywords;
}

void WordList::Clear() {
	if (words) {
		delete []words;
		delete []list;
	}
	words = 0;
	list = 0;
	len = 0;
}

void WordList::Set(const char *s) {
	len = 0;
	list = StringDup(s);
	words = ArrayFromWordList(list, onlyLineEnds);
}

char *WordList::Allocate(int size) {
	list = new char[size + 1];
	list[size] = '\0';
	return list;
}

void WordList::SetFromAllocated() {
	len = 0;
	words = ArrayFromWordList(list, onlyLineEnds);
}

// Shell sort based upon public domain C implementation by Raymond Gardner 1991
// Used here because of problems with mingw qsort.
static void SortWordList(char **words, unsigned int len) {
	unsigned int gap = len / 2;

	while (gap > 0) {
		unsigned int i = gap;
		while (i < len) {
			unsigned int j = i;
			char **a = words + j;
			do {
				j -= gap;
				char **b = a;
				a -= gap;
				if (strcmp(*a, *b) > 0) {
					char *tmp = *a;
					*a = *b;
					*b = tmp;
				} else {
					break;
				}
			} while (j >= gap);
			i++;
		}
		gap = gap / 2;
	}
}

bool WordList::InList(const char *s) {
	if (0 == words)
		return false;
	if (len == 0) {
		for (int i = 0; words[i][0]; i++)
			len++;
		SortWordList(words, len);
		for (unsigned int k = 0; k < (sizeof(starts) / sizeof(starts[0])); k++)
			starts[k] = -1;
		for (int l = len - 1; l >= 0; l--) {
			unsigned char indexChar = words[l][0];
			starts[indexChar] = l;
		}
	}
	unsigned char firstChar = s[0];
	int j = starts[firstChar];
	if (j >= 0) {
		while (words[j][0] == firstChar) {
			if (s[1] == words[j][1]) {
				const char *a = words[j] + 1;
				const char *b = s + 1;
				while (*a && *a == *b) {
					a++;
					b++;
				}
				if (!*a && !*b)
					return true;
			}
			j++;
		}
	}
	return false;
}
<|endoftext|>


<commit_before>// Copyright 2014 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <fstream>
#include <iomanip>
#include <limits>
#include <ctime>

#include <ArgumentList.hpp>
#include <Observation.hpp>
#include <InitializeOpenCL.hpp>
#include <Kernel.hpp>
#include <utils.hpp>
#include <SNR.hpp>

typedef float dataType;
std::string typeName("float");

int main(int argc, char *argv[]) {
  bool printCode = false;
  bool printResults = false;
  bool dSNR = false;
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
	long long unsigned int wrongSamples = 0;
	AstroData::Observation observation;
  PulsarSearch::snrDedispersedConf dConf;
  PulsarSearch::snrFoldedConf fConf;

	try {
    isa::utils::ArgumentList args(argc, argv);
    printCode = args.getSwitch("-print_code");
    printResults = args.getSwitch("-print_res");
    dSNR = args.getSwitch("-dedispersed");
    bool fSNR = args.getSwitch("-folded");
    if ( (dSNR && fSNR) || (!dSNR && ! fSNR) ) {
      throw std::exception();
    }
		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
    observation.setPadding(args.getSwitchArgument< unsigned int >("-padding"));
    if ( fSNR ) {
      fConf.setNrDMsPerBlock(args.getSwitchArgument< unsigned int >("-db"));
      fConf.setNrDMsPerThread(args.getSwitchArgument< unsigned int >("-dt"));
      fConf.setNrPeriodsPerBlock(args.getSwitchArgument< unsigned int >("-pb"));
      fConf.setNrPeriodsPerThread(args.getSwitchArgument< unsigned int >("-pt"));
    } else {
      dConf.setNrDMsPerBlock(args.getSwitchArgument< unsigned int >("-db"));
      dConf.setNrDMsPerThread(args.getSwitchArgument< unsigned int >("-dt"));
      observation.setNrSamplesPerSecond(args.getSwitchArgument< unsigned int >("-samples"));
    }
		observation.setDMRange(args.getSwitchArgument< unsigned int >("-dms"), 0.0, 0.0);
    if ( fSNR ) {
      observation.setPeriodRange(args.getSwitchArgument< unsigned int >("-periods"), 0, 0);
      observation.setNrBins(args.getSwitchArgument< unsigned int >("-bins"));
    }
	} catch  ( isa::utils::SwitchNotFound &err ) {
    std::cerr << err.what() << std::endl;
    return 1;
  } catch ( std::exception &err ) {
    std::cerr << "Usage: " << argv[0] << " [-dedispersed | -folded] [-print_code] [-print_res] -opencl_platform ... -opencl_device ... -padding ... -db ... -dt ... -dms ..." << std::endl;
    std::cerr << "\t -dedispersed -samples ..." << std::endl;
    std::cerr << "\t -folded -pb ... -pt ... -periods .... -bins ..." << std::endl;
		return 1;
	}

	// Initialize OpenCL
	cl::Context * clContext = new cl::Context();
	std::vector< cl::Platform > * clPlatforms = new std::vector< cl::Platform >();
	std::vector< cl::Device > * clDevices = new std::vector< cl::Device >();
	std::vector< std::vector< cl::CommandQueue > > * clQueues = new std::vector< std::vector < cl::CommandQueue > >();

  isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, clContext, clDevices, clQueues);

	// Allocate memory
  std::vector< dataType > foldedData, snrs, snrs_c;
  std::vector< dataType > transposedData, maxS, meanS, varianceS, maxS_c, meanS_c, varianceS_c;
  cl::Buffer foldedData_d, snrs_d;
  cl::Buffer transposedData_d, maxS_d, meanS_d, varianceS_d;
  if ( dSNR ) {
    transposedData.resize(observation.getNrSamplesPerSecond() * observation.getNrPaddedDMs());
    maxS.resize(observation.getNrPaddedDMs());
    meanS.resize(observation.getNrPaddedDMs());
    varianceS.resize(observation.getNrPaddedDMs());
    maxS_c.resize(observation.getNrPaddedDMs());
    meanS_c.resize(observation.getNrPaddedDMs());
    varianceS_c.resize(observation.getNrPaddedDMs());
  } else {
    foldedData.resize(observation.getNrBins() * observation.getNrPeriods() * observation.getNrPaddedDMs());
    snrs.resize(observation.getNrPeriods() * observation.getNrPaddedDMs());
    snrs_c.resize(observation.getNrPeriods() * observation.getNrPaddedDMs());
  }
  try {
    if ( dSNR ) {
      transposedData_d = cl::Buffer(*clContext, CL_MEM_READ_WRITE, transposedData.size() * sizeof(dataType), 0, 0);
      maxS_d = cl::Buffer(*clContext, CL_MEM_READ_WRITE, maxS.size() * sizeof(dataType), 0, 0);
      meanS_d = cl::Buffer(*clContext, CL_MEM_READ_WRITE, meanS.size() * sizeof(dataType), 0, 0);
      varianceS_d = cl::Buffer(*clContext, CL_MEM_READ_WRITE, varianceS.size() * sizeof(dataType), 0, 0);
    } else {
      foldedData_d = cl::Buffer(*clContext, CL_MEM_READ_WRITE, foldedData.size() * sizeof(dataType), 0, 0);
      snrs_d = cl::Buffer(*clContext, CL_MEM_WRITE_ONLY, snrs.size() * sizeof(dataType), 0, 0);
    }
  } catch ( cl::Error &err ) {
    std::cerr << "OpenCL error allocating memory: " << isa::utils::toString< cl_int >(err.err()) << "." << std::endl;
    return 1;
  }

	srand(time(0));
  if ( dSNR ) {
    for ( unsigned int sample = 0; sample < observation.getNrSamplesPerSecond(); sample++ ) {
      for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm++ ) {
        transposedData[(sample * observation.getNrPaddedDMs()) + dm] = static_cast< dataType >(rand() % 10);
      }
    }
    std::fill(maxS.begin(), maxS.end(), static_cast< dataType >(0));
    std::fill(meanS.begin(), meanS.end(), static_cast< dataType >(0));
    std::fill(varianceS.begin(), varianceS.end(), static_cast< dataType >(0));
    std::fill(maxS_c.begin(), maxS_c.end(), static_cast< dataType >(0));
    std::fill(meanS_c.begin(), meanS_c.end(), static_cast< dataType >(0));
    std::fill(varianceS_c.begin(), varianceS_c.end(), static_cast< dataType >(0));
  } else {
    for ( unsigned int bin = 0; bin < observation.getNrBins(); bin++ ) {
      for ( unsigned int period = 0; period < observation.getNrPeriods(); period++ ) {
        for ( unsigned int DM = 0; DM < observation.getNrDMs(); DM++ ) {
          foldedData[(bin * observation.getNrPeriods() * observation.getNrPaddedDMs()) + (period * observation.getNrPaddedDMs()) + DM] = static_cast< dataType >(rand() % 10);
        }
      }
    }
    std::fill(snrs.begin(), snrs.end(), static_cast< dataType >(0));
    std::fill(snrs_c.begin(), snrs_c.end(), static_cast< dataType >(0));
  }

  // Copy data structures to device
  try {
    if ( dSNR ) {
      clQueues->at(clDeviceID)[0].enqueueWriteBuffer(transposedData_d, CL_FALSE, 0, transposedData.size() * sizeof(dataType), reinterpret_cast< void * >(transposedData.data()));
      clQueues->at(clDeviceID)[0].enqueueWriteBuffer(maxS_d, CL_FALSE, 0, maxS.size() * sizeof(dataType), reinterpret_cast< void * >(maxS.data()));
      clQueues->at(clDeviceID)[0].enqueueWriteBuffer(meanS_d, CL_FALSE, 0, meanS.size() * sizeof(dataType), reinterpret_cast< void * >(meanS.data()));
      clQueues->at(clDeviceID)[0].enqueueWriteBuffer(varianceS_d, CL_FALSE, 0, varianceS.size() * sizeof(dataType), reinterpret_cast< void * >(varianceS.data()));
    } else {
      clQueues->at(clDeviceID)[0].enqueueWriteBuffer(foldedData_d, CL_FALSE, 0, foldedData.size() * sizeof(dataType), reinterpret_cast< void * >(foldedData.data()));
      clQueues->at(clDeviceID)[0].enqueueWriteBuffer(snrs_d, CL_FALSE, 0, snrs.size() * sizeof(dataType), reinterpret_cast< void * >(snrs.data()));
    }
  } catch ( cl::Error &err ) {
    std::cerr << "OpenCL error H2D transfer: " << isa::utils::toString< cl_int >(err.err()) << "." << std::endl;
    return 1;
  }

  // Generate kernel
  cl::Kernel * kernel;
  std::string * code;
  if ( dSNR ) {
    code = PulsarSearch::getSNRDedispersedOpenCL(dConf, typeName, observation);
  } else {
    code = PulsarSearch::getSNRFoldedOpenCL(fConf, typeName, observation);
  }
  if ( printCode ) {
    std::cout << *code << std::endl;
  }

  try {
    if ( dSNR ) {
      kernel = isa::OpenCL::compile("snrDedispersed", *code, "-cl-mad-enable -Werror", *clContext, clDevices->at(clDeviceID));
    } else {
      kernel = isa::OpenCL::compile("snrFolded", *code, "-cl-mad-enable -Werror", *clContext, clDevices->at(clDeviceID));
    }
  } catch ( isa::OpenCL::OpenCLError &err ) {
    std::cerr << err.what() << std::endl;
    return 1;
  }

  // Run OpenCL kernel and CPU control
  try {
    unsigned int nrThreads = 0;
    cl::NDRange global;
    cl::NDRange local;

    if ( dSNR ) {
      if ( (observation.getNrDMs() % (dConf.getNrDMsPerBlock() * dConf.getNrDMsPerThread())) == 0 ) {
        nrThreads = observation.getNrDMs() / dConf.getNrDMsPerThread();
      } else {
        nrThreads = observation.getNrPaddedDMs() / dConf.getNrDMsPerThread();
      }
      global = cl::NDRange(nrThreads);
      local = cl::NDRange(dConf.getNrDMsPerBlock());

      kernel->setArg(0, 0);
      kernel->setArg(1, transposedData_d);
      kernel->setArg(2, maxS_d);
      kernel->setArg(3, meanS_d);
      kernel->setArg(4, varianceS_d);
    } else {
      if ( (observation.getNrDMs() % (fConf.getNrDMsPerBlock() * fConf.getNrDMsPerThread())) == 0 ) {
        nrThreads = observation.getNrDMs() / fConf.getNrDMsPerThread();
      } else {
        nrThreads = observation.getNrPaddedDMs() / fConf.getNrDMsPerThread();
      }
      global = cl::NDRange(nrThreads, observation.getNrPeriods() / fConf.getNrPeriodsPerThread());
      local = cl::NDRange(fConf.getNrDMsPerBlock(), fConf.getNrPeriodsPerBlock());

      kernel->setArg(0, foldedData_d);
      kernel->setArg(1, snrs_d);
    }

    clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, 0);
    if ( dSNR ) {
      PulsarSearch::snrDedispersed(0, observation, transposedData, maxS_c, meanS_c, varianceS_c);
      clQueues->at(clDeviceID)[0].enqueueReadBuffer(maxS_d, CL_TRUE, 0, maxS.size() * sizeof(dataType), reinterpret_cast< void * >(maxS.data()));
      clQueues->at(clDeviceID)[0].enqueueReadBuffer(meanS_d, CL_TRUE, 0, meanS.size() * sizeof(dataType), reinterpret_cast< void * >(meanS.data()));
      clQueues->at(clDeviceID)[0].enqueueReadBuffer(varianceS_d, CL_TRUE, 0, varianceS.size() * sizeof(dataType), reinterpret_cast< void * >(varianceS.data()));
    } else {
      PulsarSearch::snrFolded(observation, foldedData, snrs_c);
      clQueues->at(clDeviceID)[0].enqueueReadBuffer(snrs_d, CL_TRUE, 0, snrs.size() * sizeof(dataType), reinterpret_cast< void * >(snrs.data()));
    }
  } catch ( cl::Error &err ) {
    std::cerr << "OpenCL error: " << isa::utils::toString< cl_int >(err.err()) << "." << std::endl;
    return 1;
  }

  if ( dSNR) {
    for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm++ ) {
      dataType snr = (maxS[dm] - meanS[dm]) / std::sqrt(varianceS[dm] / (observation.getNrSamplesPerSecond() - 1));
      dataType snr_c = (maxS_c[dm] - meanS_c[dm]) / std::sqrt(varianceS_c[dm] / (observation.getNrSamplesPerSecond() - 1));
      if ( ! isa::utils::same(snr, snr_c) ) {
        wrongSamples++;
        if ( printResults ) {
          std::cout << "**" << snr << " != " << snr_c << "** ";
        }
      } else if (printResults ) {
        std::cout << snr << " ";
      }
    }
    if ( printResults ) {
      std::cout << std::endl;
    }
  } else {
    for ( unsigned int period = 0; period < observation.getNrPeriods(); period++ ) {
      for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm++ ) {
        if ( ! isa::utils::same(snrs_c[(period * observation.getNrPaddedDMs()) + dm], snrs[(period * observation.getNrPaddedDMs()) + dm]) ) {
          wrongSamples++;
          if ( printResults ) {
            std::cout << "**" << snrs[(period * observation.getNrPaddedDMs()) + dm] << " != " << snrs_c[(period * observation.getNrPaddedDMs()) + dm] << "** ";
          }
        } else if ( printResults ) {
          std::cout << snrs[(period * observation.getNrPaddedDMs()) + dm] << "  ";
        }
      }
      if ( printResults ) {
        std::cout << std::endl;
      }
    }
  }

  if ( wrongSamples > 0 ) {
    if ( dSNR ) {
      std::cout << "Wrong samples: " << wrongSamples << " (" << (wrongSamples * 100.0) / static_cast< long long unsigned int >(observation.getNrDMs()) << "%)." << std::endl;
    } else {
      std::cout << "Wrong samples: " << wrongSamples << " (" << (wrongSamples * 100.0) / (static_cast< long long unsigned int >(observation.getNrDMs()) * observation.getNrPeriods()) << "%)." << std::endl;
    }
  } else {
    std::cout << "TEST PASSED." << std::endl;
  }

	return 0;
}

<commit_msg>Updated the test.<commit_after>// Copyright 2014 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <fstream>
#include <iomanip>
#include <limits>
#include <ctime>

#include <ArgumentList.hpp>
#include <Observation.hpp>
#include <InitializeOpenCL.hpp>
#include <Kernel.hpp>
#include <utils.hpp>
#include <SNR.hpp>
#include <Stats.hpp>

typedef float dataType;
std::string typeName("float");

int main(int argc, char *argv[]) {
  bool printCode = false;
  bool printResults = false;
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
	long long unsigned int wrongSamples = 0;
	AstroData::Observation observation;
  PulsarSearch::snrDedispersedConf dConf;

	try {
    isa::utils::ArgumentList args(argc, argv);
    printCode = args.getSwitch("-print_code");
    printResults = args.getSwitch("-print_res");
		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
    observation.setPadding(args.getSwitchArgument< unsigned int >("-padding"));
    dConf.setNrDMsPerBlock(args.getSwitchArgument< unsigned int >("-sb"));
    observation.setNrSamplesPerSecond(args.getSwitchArgument< unsigned int >("-samples"));
		observation.setDMRange(args.getSwitchArgument< unsigned int >("-dms"), 0.0, 0.0);
	} catch  ( isa::utils::SwitchNotFound &err ) {
    std::cerr << err.what() << std::endl;
    return 1;
  } catch ( std::exception &err ) {
    std::cerr << "Usage: " << argv[0] << " [-print_code] [-print_res] -opencl_platform ... -opencl_device ... -padding ... -sb ... -dms ... -samples ..." << std::endl;
		return 1;
	}

	// Initialize OpenCL
	cl::Context * clContext = new cl::Context();
	std::vector< cl::Platform > * clPlatforms = new std::vector< cl::Platform >();
	std::vector< cl::Device > * clDevices = new std::vector< cl::Device >();
	std::vector< std::vector< cl::CommandQueue > > * clQueues = new std::vector< std::vector < cl::CommandQueue > >();

  isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, clContext, clDevices, clQueues);

	// Allocate memory
  std::vector< dataType > dedispersedData, snrData;
  cl::Buffer dedispersedData_d, snrData_d;
  dedispersedData.resize(observation.getNrDMs() * observation.getNrSamplesPerPaddedSecond());
  snrData.resize(observation.getNrPaddedDMs());
  try {
    dedispersedData_d = cl::Buffer(*clContext, CL_MEM_READ_WRITE, dedispersedData.size() * sizeof(dataType), 0, 0);
    snrData_d = cl::Buffer(*clContext, CL_MEM_WRITE_ONLY, snrData.size() * sizeof(float), 0, 0);
  } catch ( cl::Error &err ) {
    std::cerr << "OpenCL error allocating memory: " << isa::utils::toString< cl_int >(err.err()) << "." << std::endl;
    return 1;
  }

	srand(time(0));
  for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm++ ) {
    for ( unsigned int sample = 0; sample < observation.getNrSamplesPerSecond(); sample++ ) {
      dedispersedData[(dm * observation.getNrSamplesPerPaddedSecond()) + sample] = static_cast< dataType >(rand() % 10);
    }
  }
  std::fill(snrData.begin(), snrData.end(), 0.0f);

  // Copy data structures to device
  try {
    clQueues->at(clDeviceID)[0].enqueueWriteBuffer(dedispersedData_d, CL_FALSE, 0, dedispersedData.size() * sizeof(dataType), reinterpret_cast< void * >(dedispersedData.data()));
    clQueues->at(clDeviceID)[0].enqueueWriteBuffer(snrData_d, CL_FALSE, 0, snrData.size() * sizeof(float), reinterpret_cast< void * >(snrData.data()));
  } catch ( cl::Error &err ) {
    std::cerr << "OpenCL error H2D transfer: " << isa::utils::toString< cl_int >(err.err()) << "." << std::endl;
    return 1;
  }

  // Generate kernel
  cl::Kernel * kernel;
  std::string * code;
  code = PulsarSearch::getSNRDedispersedOpenCL(dConf, typeName, observation);
  if ( printCode ) {
    std::cout << *code << std::endl;
  }

  try {
    kernel = isa::OpenCL::compile("snrDedispersed", *code, "-cl-mad-enable -Werror", *clContext, clDevices->at(clDeviceID));
  } catch ( isa::OpenCL::OpenCLError &err ) {
    std::cerr << err.what() << std::endl;
    return 1;
  }

  // Run OpenCL kernel and CPU control
  try {
    std::vector< isa::utils::Stats< dataType > > control(observation.getNrDMs());
    cl::NDRange global;
    cl::NDRange local;

    global = cl::NDRange(dConf.getNrSamplesPerBlock(), observation.getNrDMs());
    local = cl::NDRange(dConf.getNrDMsPerBlock(), 1);

    kernel->setArg(0, dedispersedData_d);
    kernel->setArg(2, snrData_d);

    clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, 0);
    clQueues->at(clDeviceID)[0].enqueueReadBuffer(snrData_d, CL_TRUE, 0, snrData.size() * sizeof(float), reinterpret_cast< void * >(snrData.data()));
    for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm++ ) {
      control[dm] = isa::utils::Stats< dataType >();

      for ( unsigned int sample = 0; sample < observation.getNrSamplesPerSecond(); sample++ ) {
        control[dm].addElement(dedispersedData[(dm * observation.getNrSamplesPerPaddedSecond()) + sample]);
      }
    }
  } catch ( cl::Error &err ) {
    std::cerr << "OpenCL error: " << isa::utils::toString< cl_int >(err.err()) << "." << std::endl;
    return 1;
  }

  for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm++ ) {
    if ( ! isa::utils::same(snrData[dm], (control[dm].getMax() - control[dm].getMean()) / control[dm].getStandardDeviation()) ) {
      wrongSamples++;
      if ( printResults ) {
        std::cout << "**" << snrData[dm] << " != " << (control[dm].getMax() - control[dm].getMean()) / control[dm].getStandardDeviation() << "** ";
      }
    } else if (printResults ) {
      std::cout << snr << " ";
    }
  }
  if ( printResults ) {
    std::cout << std::endl;
  }

  if ( wrongSamples > 0 ) {
    std::cout << "Wrong samples: " << wrongSamples << " (" << (wrongSamples * 100.0) / static_cast< long long unsigned int >(observation.getNrDMs()) << "%)." << std::endl;
  } else {
    std::cout << "TEST PASSED." << std::endl;
  }

	return 0;
}

<|endoftext|>


<commit_before>#include <stdio.h>
#include "Scanner.h"

Scanner::Scanner()
{
	printf("I'm Scanner!\r\b");
}
<commit_msg>something changes in Scanner.cpp<commit_after>#include <stdio.h>
#include "Scanner.h"

Scanner::Scanner()
{
	printf("I'm Scanner!\r\n");
}
<|endoftext|>


<commit_before>#ifndef THREADX_HPP
#define THREADX_HPP

#include "utilx.hpp"

namespace socketx{

    /********** Semaphore ************/
    class semaphore{
        private:
            std::mutex mut;
            std::condition_variable cv;
            ssize_t count;
        public:
            semaphore(ssize_t c);
            void P();
            void V();
    };

    /********* Thread safe queue *********/
    template<typename T>
    class squeue{
        private:
            mutable std::mutex mut;
            std::queue<std::shared_ptr<T>> data_queue;
            std::condition_variable cond;
        public:
            squeue()=default;
            void wait_pop(T &value);
            bool try_pop(T &value);
            std::shared_ptr<T> wait_pop();
            std::shared_ptr<T> try_pop();
            void push(T value);
            bool empty() const;
    };

    template<typename T>
    void squeue<T>::wait_pop(T &value){
        std::unique_lock<std::mutex> lk(mut);
        cond.wait(lk,[this]{return !data_queue.empty();});
        value = std::move(*data_queue.front());
        data_queue.pop();
    }

    template<typename T>
    bool squeue<T>::try_pop(T &value){
        std::lock_guard<std::mutex> lk(mut);
        if(data_queue.empty())
            return false;
        value = std::move(*data_queue.front());
        data_queue.pop();
        return true;
    }

    template<typename T>
    std::shared_ptr<T> squeue<T>::wait_pop(){
        std::unique_lock<std::mutex> lk(mut);
        cond.wait(lk,[this]{return !data_queue.empty();});
        std::shared_ptr<T> res = data_queue.front();
        data_queue.pop();
        return res;
    }

    template<typename T>
    std::shared_ptr<T> squeue<T>::try_pop(){
        std::lock_guard<std::mutex> lk(mut);
        if(data_queue.empty())
            return std::shared_ptr<T>();
        std::shared_ptr<T> res = data_queue.front();
        data_queue.pop();
        return res;
    }

    template<typename T>
    void squeue<T>::push(T value){
        std::shared_ptr<T> data = std::make_shared<T>(std::move(value));
        std::lock_guard<std::mutex> lk(mut);
        data_queue.push(data);
        cond.notify_one();
    }

    template<typename T>
    bool squeue<T>::empty() const{
        std::lock_guard<std::mutex> lk(mut);
        return data_queue.empty();
    }

    /********* Circular queue **********/
    template<typename T>
    class cirqueue{
        private:
            size_t num;
            size_t front;
            size_t rear;
            semaphore *slots;
            semaphore *items;
            semaphore *mut;
            std::vector<std::shared_ptr<T>> data;
        public:
            cirqueue(size_t n=0);
            void wait_pop(T &value);
            void wait_push(T value);
            bool empty();
    };

    template<typename T>
    cirqueue<T>::cirqueue(size_t n){
        num = n;
        front = rear = 0;
        slots = new semaphore(num);
        items = new semaphore(0);
        mut = new semaphore(num);
        data = std::vector<std::shared_ptr<T>>(num);
    }

    template<typename T>
    void cirqueue<T>::wait_pop(T &value){
        items->P();
        mut->P();
        value = *data[front++%num];
        mut->V();
        slots->V();
    }

    template<typename T>
    void cirqueue<T>::wait_push(T value){
        slots->P();
        mut->P();
        data[rear++%num] = std::make_shared<T>(value);
        mut->V();
        items->V();
    }

    template<typename T>
    bool cirqueue<T>::empty(){
        mut->P();
        bool ret = data.empty();
        mut->V();
        return ret;
    }

    /********* Thread pool ************/
    class ThreadPool{
        private:
            std::vector<std::thread> workers;
            socketx::squeue<std::function<void()>> tasks;
            size_t thread_num;
            std::atomic<bool> done;
            std::atomic<int> idleThreadNum;

            /*Get a task from tasks queue*/
            void worker();
        public:
            ThreadPool(size_t num=std::thread::hardware_concurrency());
            virtual ~ThreadPool();

            int getThreadNum(){
                return thread_num;
            }
            int getIdelThreadNum(){
                return idleThreadNum;
            }

            void addThread();
            /*Submit a task f to tasks queue, then wait for the return value.*/
            template<typename F>
            auto submit(F f) -> std::future<typename std::result_of<F()>::type>;
    };

    template<typename F>
    auto ThreadPool::submit(F f) -> std::future<typename std::result_of<F()>::type>{
        using return_type = typename std::result_of<F()>::type;

        /*Since packaged_task is non-copyable, we cannot pass it to std::function<>.
        * Instead, making a shared_ptr point to it and invoking it by a lambda function.
        */
        auto task = std::make_shared<std::packaged_task<return_type()>>(std::move(f));
        std::function<void()> func = [task]{(*task)();};
        tasks.push(func);

        std::future<return_type> res = task->get_future();
        return res;
    }
}

#endif<commit_msg>fix bugs<commit_after>#ifndef THREADX_HPP
#define THREADX_HPP

#include "utilx.hpp"

namespace socketx{

    /********** Semaphore ************/
    class semaphore{
        private:
            std::mutex mut;
            std::condition_variable cv;
            ssize_t count;
        public:
            semaphore(ssize_t c);
            void P();
            void V();
    };

    /********* Thread safe queue *********/
    template<typename T>
    class squeue{
        private:
            mutable std::mutex mut;
            std::queue<std::shared_ptr<T>> data_queue;
            std::condition_variable cond;
        public:
            squeue()=default;
            void wait_pop(T &value);
            bool try_pop(T &value);
            std::shared_ptr<T> wait_pop();
            std::shared_ptr<T> try_pop();
            void push(T value);
            bool empty() const;
    };

    template<typename T>
    void squeue<T>::wait_pop(T &value){
        std::unique_lock<std::mutex> lk(mut);
        cond.wait(lk,[this]{return !data_queue.empty();});
        value = std::move(*data_queue.front());
        data_queue.pop();
    }

    template<typename T>
    bool squeue<T>::try_pop(T &value){
        std::lock_guard<std::mutex> lk(mut);
        if(data_queue.empty())
            return false;
        value = std::move(*data_queue.front());
        data_queue.pop();
        return true;
    }

    template<typename T>
    std::shared_ptr<T> squeue<T>::wait_pop(){
        std::unique_lock<std::mutex> lk(mut);
        cond.wait(lk,[this]{return !data_queue.empty();});
        std::shared_ptr<T> res = data_queue.front();
        data_queue.pop();
        return res;
    }

    template<typename T>
    std::shared_ptr<T> squeue<T>::try_pop(){
        std::lock_guard<std::mutex> lk(mut);
        if(data_queue.empty())
            return std::shared_ptr<T>();
        std::shared_ptr<T> res = data_queue.front();
        data_queue.pop();
        return res;
    }

    template<typename T>
    void squeue<T>::push(T value){
        std::shared_ptr<T> data = std::make_shared<T>(std::move(value));
        std::lock_guard<std::mutex> lk(mut);
        data_queue.push(data);
        cond.notify_one();
    }

    template<typename T>
    bool squeue<T>::empty() const{
        std::lock_guard<std::mutex> lk(mut);
        return data_queue.empty();
    }

    /********* Circular queue **********/
    template<typename T>
    class cirqueue{
        private:
            size_t num;
            size_t front;
            size_t rear;
            semaphore *slots;
            semaphore *items;
            semaphore *mut;
            std::vector<std::shared_ptr<T>> data;
        public:
            cirqueue(size_t n=0);
            void wait_pop(T &value);
            void wait_push(T value);
            bool empty();
    };

    template<typename T>
    cirqueue<T>::cirqueue(size_t n){
        num = n;
        front = rear = 0;
        slots = new semaphore(num);
        items = new semaphore(0);
        mut = new semaphore(num);
        data = std::vector<std::shared_ptr<T>>(num);
    }

    template<typename T>
    void cirqueue<T>::wait_pop(T &value){
        items->P();
        mut->P();
        value = *data[front++%num];
        mut->V();
        slots->V();
    }

    template<typename T>
    void cirqueue<T>::wait_push(T value){
        slots->P();
        mut->P();
        data[rear++%num] = std::make_shared<T>(value);
        mut->V();
        items->V();
    }

    template<typename T>
    bool cirqueue<T>::empty(){
        mut->P();
        bool ret = data.empty();
        mut->V();
        return ret;
    }

    /********* Thread pool ************/
    class ThreadPool{
        private:
            std::vector<std::thread> workers;
            socketx::squeue<std::function<void()>> tasks;
            size_t thread_num;
            std::atomic<bool> done;
            std::atomic<int> idleThreadNum;

            /*Get a task from tasks queue*/
            void worker();
        public:
            ThreadPool(size_t num=std::thread::hardware_concurrency());
            virtual ~ThreadPool();

            int getThreadNum(){
                return thread_num;
            }
            int getIdleThreadNum(){
                return idleThreadNum;
            }

            void addThread();
            /*Submit a task f to tasks queue, then wait for the return value.*/
            template<typename F>
            auto submit(F f) -> std::future<typename std::result_of<F()>::type>;
    };

    template<typename F>
    auto ThreadPool::submit(F f) -> std::future<typename std::result_of<F()>::type>{
        using return_type = typename std::result_of<F()>::type;

        /*Since packaged_task is non-copyable, we cannot pass it to std::function<>.
        * Instead, making a shared_ptr point to it and invoking it by a lambda function.
        */
        auto task = std::make_shared<std::packaged_task<return_type()>>(std::move(f));
        std::function<void()> func = [task]{(*task)();};
        tasks.push(func);

        std::future<return_type> res = task->get_future();
        return res;
    }
}

#endif<|endoftext|>


<commit_before>// Copyright 2014, Chris Pearce & Yun Sing Koh
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "TidList.h"
#include "debug.h"
#include "utils.h"

using namespace std;

void TidList::Set(int aTid, bool aValue) {
  int vidx = aTid / TIDLIST_SIZE;
  int chunkIdx = TidToChunkIdx(aTid);
  unsigned chunk = GetChunk(vidx, chunkIdx);

  int bitNum = TidToChunkBitNum(aTid);
  switch (aValue) {
    case true: {
      chunk |= (1 << bitNum);
      break;
    }
    case false: {
      chunk &= (~0 - (1 << bitNum));
      break;
    }
  }
  //v->at(chunkIdx) = chunk;
  SetChunk(vidx, chunkIdx, chunk);

  ASSERT(Get(aTid) == aValue);
}

unsigned TidList::SetChunk(int aVecIdx, int aChunkIdx, unsigned aVal) {
  if (aVecIdx >= mChunks.size()) {
    mChunks.resize(aVecIdx + 1);
  }
  if (mChunks[aVecIdx] == 0) {
    mChunks[aVecIdx] = new vector<unsigned>();
  }
  vector<unsigned>* v = mChunks[aVecIdx];
  if (v->size() <= aChunkIdx) {
    v->resize(aChunkIdx + 1);
  }

  v->at(aChunkIdx) = aVal;

  return aVal;
}

bool TidList::Get(int aTid) const {
  int vidx = aTid / TIDLIST_SIZE;
  if (mChunks[vidx] == 0) {
    return false;
  }
  unsigned chunk = mChunks[vidx]->at(TidToChunkIdx(aTid));

  int bitNum = TidToChunkBitNum(aTid);
  return (chunk & (1 << bitNum)) != 0;
}

unsigned TidList::GetChunk(int aVecId, int aChunkId) const {
  if (aVecId >= mChunks.size() ||
      mChunks[aVecId] == 0 ||
      mChunks[aVecId]->size() <= aChunkId) {
    return 0;
  }

  return mChunks.at(aVecId)->at(aChunkId);
}

void TidList::Test() {
  TidList tl;
  tl.Set(123, true);
  ASSERT(tl.Get(123) == true);
  tl.Set(123, false);
  ASSERT(tl.Get(123) == false);

  tl.Set(31, true);
  tl.Set(32, true);
  tl.Set(33, true);
  ASSERT(tl.Get(31));
  ASSERT(tl.Get(32));
  ASSERT(tl.Get(33));

  tl.Set(31, false);
  ASSERT(!tl.Get(31));
  ASSERT(tl.Get(32));
  ASSERT(tl.Get(33));

  tl.Set(32, false);
  ASSERT(!tl.Get(31));
  ASSERT(!tl.Get(32));
  ASSERT(tl.Get(33));

  tl.Set(33, false);
  ASSERT(!tl.Get(31));
  ASSERT(!tl.Get(32));
  ASSERT(!tl.Get(33));

}

<commit_msg>Silence warning about boolean in switch statement.<commit_after>// Copyright 2014, Chris Pearce & Yun Sing Koh
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "TidList.h"
#include "debug.h"
#include "utils.h"

using namespace std;

void TidList::Set(int aTid, bool aValue) {
  int vidx = aTid / TIDLIST_SIZE;
  int chunkIdx = TidToChunkIdx(aTid);
  unsigned chunk = GetChunk(vidx, chunkIdx);

  int bitNum = TidToChunkBitNum(aTid);
  if (aValue) {
    chunk |= (1 << bitNum);
  } else {
    chunk &= (~0 - (1 << bitNum));
  }
  //v->at(chunkIdx) = chunk;
  SetChunk(vidx, chunkIdx, chunk);

  ASSERT(Get(aTid) == aValue);
}

unsigned TidList::SetChunk(int aVecIdx, int aChunkIdx, unsigned aVal) {
  if (aVecIdx >= mChunks.size()) {
    mChunks.resize(aVecIdx + 1);
  }
  if (mChunks[aVecIdx] == 0) {
    mChunks[aVecIdx] = new vector<unsigned>();
  }
  vector<unsigned>* v = mChunks[aVecIdx];
  if (v->size() <= aChunkIdx) {
    v->resize(aChunkIdx + 1);
  }

  v->at(aChunkIdx) = aVal;

  return aVal;
}

bool TidList::Get(int aTid) const {
  int vidx = aTid / TIDLIST_SIZE;
  if (mChunks[vidx] == 0) {
    return false;
  }
  unsigned chunk = mChunks[vidx]->at(TidToChunkIdx(aTid));

  int bitNum = TidToChunkBitNum(aTid);
  return (chunk & (1 << bitNum)) != 0;
}

unsigned TidList::GetChunk(int aVecId, int aChunkId) const {
  if (aVecId >= mChunks.size() ||
      mChunks[aVecId] == 0 ||
      mChunks[aVecId]->size() <= aChunkId) {
    return 0;
  }

  return mChunks.at(aVecId)->at(aChunkId);
}

void TidList::Test() {
  TidList tl;
  tl.Set(123, true);
  ASSERT(tl.Get(123) == true);
  tl.Set(123, false);
  ASSERT(tl.Get(123) == false);

  tl.Set(31, true);
  tl.Set(32, true);
  tl.Set(33, true);
  ASSERT(tl.Get(31));
  ASSERT(tl.Get(32));
  ASSERT(tl.Get(33));

  tl.Set(31, false);
  ASSERT(!tl.Get(31));
  ASSERT(tl.Get(32));
  ASSERT(tl.Get(33));

  tl.Set(32, false);
  ASSERT(!tl.Get(31));
  ASSERT(!tl.Get(32));
  ASSERT(tl.Get(33));

  tl.Set(33, false);
  ASSERT(!tl.Get(31));
  ASSERT(!tl.Get(32));
  ASSERT(!tl.Get(33));

}

<|endoftext|>


<commit_before>/*
 * Actuator.cc
 *
 *      Author: Lunatic
 */

#include <cstring>
#include <cstdlib>

#include "actuator.h"
#include "lexer.h"
#include "alarm.h"

namespace Script {

bool Env::contains(const std::string& name) {
	return vars.find(name) != vars.end();
}
std::string Env::get(const std::string& name) {
	return vars.find(name)->second;
}
void Env::put(const std::string& name, const std::string& value) {
	vars[name] = value;
}

//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

Actuator::Actuator(Parser& _parser) :
		parser(_parser) {
}

Actuator::~Actuator() {
}

void Actuator::load() {
	while (parser.has_next()) {
		Instruction inst;
		parser.next(inst);
		if (inst.type == kLabel) {
			std::map<std::string, size_t>::iterator it = labels.find(inst.name);
			if (it == labels.end())
				labels[inst.name] = insts.size();
		} else
			insts.push_back(inst);
	}

}

/*
 * 将Token转换为Instruction{type, name, params}
 *

void Actuator::load(const std::string& script_code) {
	Lexer lexer(script_code);
	std::vector<Token> tokens;
	while (!lexer.finish()) {
		Log::info("新的一行");

		Instruction inst;
		tokens.clear();

		for (;;) {
			Token token;
			int stat = lexer.next_token(token);
			if (stat >= 0)
				break;
			Log::info(token.to_str());
			tokens.push_back(token);
		}

		if (tokens.empty())
			continue;
		if (tokens[0].type != kName) {
			error("语法错误load", tokens[0].pos);
		}

		inst.name = tokens[0].token;
		inst.pos = tokens[0].pos;

		if (tokens.size() == 1) {
			inst.type = kInstruction;
		} else if (tokens[1].type == kColon) {
			inst.type = kLabel;
		} else { //处理指令参数
			inst.type = kInstruction;
			for (size_t i = 1; i < tokens.size(); ++i) {
				switch (tokens[i].type) {
				case kInt:
				case kReal:
				case kString:
				case kName:
				case KCmp:
					inst.params.push_back(tokens[i]);
					break;
				default:
					Log::error("%zu", i);
					Log::error(tokens[i].to_str());
					error("参数不符合要求！", tokens[i].pos);
				}
			}
		}

		if (inst.type == kLabel) {
			std::map<std::string, size_t>::iterator it = labels.find(inst.name);
			if (it == labels.end())
				labels[inst.name] = insts.size();
		} else
			insts.push_back(inst);

	}
	Log::info("加载完毕！");
}
*/

/*
 * 如果是变量 存在则直接取出 否则报错 ？不太妥当
 * 其他直接返回
 *
 */
std::string get_val_or_var(Env& env, Token& token) {
	if (token.type == kName) { //处理变量
		if (env.contains(token.token)) {
			return env.get(token.token);
		} else
			error("变量未定义" + token.token, token.pos); //？不太妥当
	}
	return token.token;
}

bool is_real(const std::string& number) {
	return std::string::npos != number.find('.');
}

bool is_int(const std::string& number) {
	return !is_real(number);
}

long long str2int(const std::string& val) {
//char *err = NULL;
//long long retval = std::strtoll(val.c_str(), &err, 10);
//if (*err == '\0')
//return retval;

//忽略错误
	return std::strtoll(val.c_str(), NULL, 10);
}

long double str2double(const std::string& val) {
//char *err = NULL;
//long double retval = std::strtold(val.c_str(), &err);
//if (*err == '\0')
//return retval;
//else
//
//error!
//return 0.0;
	return std::strtold(val.c_str(), NULL);

}
//3.3333

bool is_zero(const std::string& vfloat) {
	bool left = true, right = true;
	size_t start = 0, pos = vfloat.find('.');

	if (pos == std::string::npos)
		pos = vfloat.size();

	while (start < pos) {
		if (vfloat[start++] != '0') {
			left = false;
		}
	}
	while (++pos < vfloat.size()) {
		if (vfloat[pos] != '0') {
			right = false;
		}
	}
	return left && right;

}

std::string eval(const std::string& cmd, const std::string& arg1,
		const std::string& arg2, const Position& pos) {

#define EVAL(RES, X, Y, OP)                          \
	do {                                             \
		if(is_real(X) || is_real(Y)) {               \
			RES << (str2double(X) OP str2double(Y)); \
		} else {                                     \
			RES << (str2int(X) OP str2int(Y));       \
		}                                            \
	}while(0)                                        \

	std::stringstream ss;
	if (cmd == "add") { // +
		EVAL(ss, arg1, arg2, +);
	} else if (cmd == "min") { //-
		EVAL(ss, arg1, arg2, -);
	} else if (cmd == "mul") { // *
		EVAL(ss, arg1, arg2, *);
	} else if (cmd == "div") { // /
		if (is_zero(arg2)) {
			error("除数不能为0！", pos);
		}
		EVAL(ss, arg1, arg2, /);
	}
	return ss.str();

#undef EVAL
}

/*
 *
 * 依次处理指令
 * exit
 * goto
 * mov
 * ...
 *
 *
 *
 */
void Actuator::run(Env& env) {
	for (size_t idx = 0; idx < insts.size(); /*++idx*/) {
		Instruction& pc = insts[idx]; //模拟PC寄存器
		Log::debug("正在执行的指令： %s", pc.to_str().c_str());

		if (pc.name == "exit") {
			if (pc.params.empty())
				break;
			else
				error("exit不能有参数", pc.pos);
		} else if (pc.name == "goto") {
			if (pc.params.size() == 1 && pc.params[0].type == kName) {
				//处理指令跳转
				std::map<std::string, size_t>::iterator it = labels.find(
						pc.params[0].token);
				if (it == labels.end()) {
					error("找不到带跳转位置", pc.pos);
				} else {
					idx = it->second; //更新到下一条指令
					continue;
				}
			} else {
				error("goto语句后面必须带有一个跳转Label", pc.pos);
			}
		} else if (pc.name == "mov") {
			if (pc.params.size() == 2 && pc.params[0].type == kName) {
				std::string val = get_val_or_var(env, pc.params[1]);
				env.put(pc.params[0].token, val);
			} else {
				error("set语句必须是一个变量和一个对象参数", pc.pos);
			}
		} else if (pc.name == "add" || pc.name == "min" || pc.name == "mul"
				|| pc.name == "div") {
			//add a b 1 => a = b + 1
			if (pc.params.size() == 3 && pc.params[0].type == kName) {
				//把param1和param2求值 把结果放入param0为key结果为value的环境map中
				std::string arg1 = get_val_or_var(env, pc.params[1]);
				std::string arg2 = get_val_or_var(env, pc.params[2]);
				env.put(pc.params[0].token, eval(pc.name, arg1, arg2, pc.params[2].pos));
			} else {
				error(pc.name + "命令需要一个变量和两个参数", pc.pos);
			}
		} else if (pc.name == "if") { //if value1 [opcode value2] goto label
			bool jmp = false;
			if (pc.params.size() == 5 && pc.params[1].type == KCmp) { //if val goto label
				std::string left = get_val_or_var(env, pc.params[0]);
				std::string right = get_val_or_var(env, pc.params[2]);

				if (pc.params[1].token == "==") {
					jmp = left == right;
				} else if (pc.params[1].token == "!=") {
					jmp = left != right;
				} else if (pc.params[1].token == "<") {
					jmp = str2double(left) < str2double(right);
				} else if (pc.params[1].token == ">") {
					jmp = str2double(left) > str2double(right);
				} else if (pc.params[1].token == "<=") {
					jmp = str2double(left) <= str2double(right);
				} else if (pc.params[1].token == ">=") {
					jmp = str2double(left) < str2double(right);
				}

				if (jmp && pc.params[3].type == kName
						&& pc.params[3].token == "goto"
						&& pc.params[4].type == kName) {
					//处理指令跳转
					std::map<std::string, size_t>::iterator it = labels.find(
							pc.params[4].token);
					if (it == labels.end()) {
						error("找不到带跳转位置", pc.params[4].pos);
					} else {
						idx = it->second; //更新到下一条指令
						continue;
					}
				} else if (jmp) {
					error("goto语句后面必须带有一个跳转Label", pc.params[4].pos);
				}
			}
		} else if (pc.name == "print") {

			for (std::vector<Token>::iterator it = pc.params.begin();
					it != pc.params.end(); ++it) {
				if (it->type == kName) {
					if (env.contains(it->token)) {
						std::cout << env.get(it->token);
					} else
						error("变量未定义！", it->pos);
				} else
					std::cout << it->token;
				std::cout << std::endl;
			}
		} else if (pc.name == "read") {

			for (std::vector<Token>::iterator it = pc.params.begin();
					it != pc.params.end(); ++it) {
				if (it->type != kName) {
					error("必须是变量！", it->pos);
				}
				std::string temp;
				std::cin >> temp;
				env.put(it->token, temp);
			}
		} else {
			error("无法识别的指令", pc.pos);
		}
		idx++;
	}

}

} /* namespace Script */
<commit_msg>废弃函数load(code)<commit_after>/*
 * Actuator.cc
 *
 *      Author: Lunatic
 */

#include <cstring>
#include <cstdlib>

#include "actuator.h"
#include "lexer.h"
#include "alarm.h"

namespace Script {

bool Env::contains(const std::string& name) {
	return vars.find(name) != vars.end();
}
std::string Env::get(const std::string& name) {
	return vars.find(name)->second;
}
void Env::put(const std::string& name, const std::string& value) {
	vars[name] = value;
}

//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

Actuator::Actuator(Parser& _parser) :
		parser(_parser) {
}

Actuator::~Actuator() {
}

void Actuator::load() {
	while (parser.has_next()) {
		Instruction inst;
		parser.next(inst);
		if (inst.type == kLabel) {
			std::map<std::string, size_t>::iterator it = labels.find(inst.name);
			if (it == labels.end())
				labels[inst.name] = insts.size();
		} else
			insts.push_back(inst);
	}

}

/*
 * 如果是变量 存在则直接取出 否则报错 ？不太妥当
 * 其他直接返回
 *
 */
std::string get_val_or_var(Env& env, Token& token) {
	if (token.type == kName) { //处理变量
		if (env.contains(token.token)) {
			return env.get(token.token);
		} else
			error("变量未定义" + token.token, token.pos); //？不太妥当
	}
	return token.token;
}

bool is_real(const std::string& number) {
	return std::string::npos != number.find('.');
}

bool is_int(const std::string& number) {
	return !is_real(number);
}

long long str2int(const std::string& val) {
//char *err = NULL;
//long long retval = std::strtoll(val.c_str(), &err, 10);
//if (*err == '\0')
//return retval;

//忽略错误
	return std::strtoll(val.c_str(), NULL, 10);
}

long double str2double(const std::string& val) {
//char *err = NULL;
//long double retval = std::strtold(val.c_str(), &err);
//if (*err == '\0')
//return retval;
//else
//
//error!
//return 0.0;
	return std::strtold(val.c_str(), NULL);

}
//3.3333

bool is_zero(const std::string& vfloat) {
	bool left = true, right = true;
	size_t start = 0, pos = vfloat.find('.');

	if (pos == std::string::npos)
		pos = vfloat.size();

	while (start < pos) {
		if (vfloat[start++] != '0') {
			left = false;
		}
	}
	while (++pos < vfloat.size()) {
		if (vfloat[pos] != '0') {
			right = false;
		}
	}
	return left && right;

}

std::string eval(const std::string& cmd, const std::string& arg1,
		const std::string& arg2, const Position& pos) {

#define EVAL(RES, X, Y, OP)                          \
	do {                                             \
		if(is_real(X) || is_real(Y)) {               \
			RES << (str2double(X) OP str2double(Y)); \
		} else {                                     \
			RES << (str2int(X) OP str2int(Y));       \
		}                                            \
	}while(0)                                        \

	std::stringstream ss;
	if (cmd == "add") { // +
		EVAL(ss, arg1, arg2, +);
	} else if (cmd == "min") { //-
		EVAL(ss, arg1, arg2, -);
	} else if (cmd == "mul") { // *
		EVAL(ss, arg1, arg2, *);
	} else if (cmd == "div") { // /
		if (is_zero(arg2)) {
			error("除数不能为0！", pos);
		}
		EVAL(ss, arg1, arg2, /);
	}
	return ss.str();

#undef EVAL
}

/*
 *
 * 依次处理指令
 * exit
 * goto
 * mov
 * ...
 *
 *
 *
 */
void Actuator::run(Env& env) {
	for (size_t idx = 0; idx < insts.size(); /*++idx*/) {
		Instruction& pc = insts[idx]; //模拟PC寄存器
		Log::debug("正在执行的指令： %s", pc.to_str().c_str());

		if (pc.name == "exit") {
			if (pc.params.empty())
				break;
			else
				error("exit不能有参数", pc.pos);
		} else if (pc.name == "goto") {
			if (pc.params.size() == 1 && pc.params[0].type == kName) {
				//处理指令跳转
				std::map<std::string, size_t>::iterator it = labels.find(
						pc.params[0].token);
				if (it == labels.end()) {
					error("找不到带跳转位置", pc.pos);
				} else {
					idx = it->second; //更新到下一条指令
					continue;
				}
			} else {
				error("goto语句后面必须带有一个跳转Label", pc.pos);
			}
		} else if (pc.name == "mov") {
			if (pc.params.size() == 2 && pc.params[0].type == kName) {
				std::string val = get_val_or_var(env, pc.params[1]);
				env.put(pc.params[0].token, val);
			} else {
				error("set语句必须是一个变量和一个对象参数", pc.pos);
			}
		} else if (pc.name == "add" || pc.name == "min" || pc.name == "mul"
				|| pc.name == "div") {
			//add a b 1 => a = b + 1
			if (pc.params.size() == 3 && pc.params[0].type == kName) {
				//把param1和param2求值 把结果放入param0为key结果为value的环境map中
				std::string arg1 = get_val_or_var(env, pc.params[1]);
				std::string arg2 = get_val_or_var(env, pc.params[2]);
				env.put(pc.params[0].token, eval(pc.name, arg1, arg2, pc.params[2].pos));
			} else {
				error(pc.name + "命令需要一个变量和两个参数", pc.pos);
			}
		} else if (pc.name == "if") { //if value1 [opcode value2] goto label
			bool jmp = false;
			if (pc.params.size() == 5 && pc.params[1].type == KCmp) { //if val goto label
				std::string left = get_val_or_var(env, pc.params[0]);
				std::string right = get_val_or_var(env, pc.params[2]);

				if (pc.params[1].token == "==") {
					jmp = left == right;
				} else if (pc.params[1].token == "!=") {
					jmp = left != right;
				} else if (pc.params[1].token == "<") {
					jmp = str2double(left) < str2double(right);
				} else if (pc.params[1].token == ">") {
					jmp = str2double(left) > str2double(right);
				} else if (pc.params[1].token == "<=") {
					jmp = str2double(left) <= str2double(right);
				} else if (pc.params[1].token == ">=") {
					jmp = str2double(left) < str2double(right);
				}

				if (jmp && pc.params[3].type == kName
						&& pc.params[3].token == "goto"
						&& pc.params[4].type == kName) {
					//处理指令跳转
					std::map<std::string, size_t>::iterator it = labels.find(
							pc.params[4].token);
					if (it == labels.end()) {
						error("找不到带跳转位置", pc.params[4].pos);
					} else {
						idx = it->second; //更新到下一条指令
						continue;
					}
				} else if (jmp) {
					error("goto语句后面必须带有一个跳转Label", pc.params[4].pos);
				}
			}
		} else if (pc.name == "print") {

			for (std::vector<Token>::iterator it = pc.params.begin();
					it != pc.params.end(); ++it) {
				if (it->type == kName) {
					if (env.contains(it->token)) {
						std::cout << env.get(it->token);
					} else
						error("变量未定义！", it->pos);
				} else
					std::cout << it->token;
				std::cout << std::endl;
			}
		} else if (pc.name == "read") {

			for (std::vector<Token>::iterator it = pc.params.begin();
					it != pc.params.end(); ++it) {
				if (it->type != kName) {
					error("必须是变量！", it->pos);
				}
				std::string temp;
				std::cin >> temp;
				env.put(it->token, temp);
			}
		} else {
			error("无法识别的指令", pc.pos);
		}
		idx++;
	}

}

} /* namespace Script */
<|endoftext|>