<commit_before>/**
* pty.js
* Copyright (c) 2013, Christopher Jeffrey, Peter Sunde (MIT License)
*
* pty.cc:
*   This file is responsible for starting processes
*   with pseudo-terminal file descriptors.
*/

#include <v8.h>
#include <node.h>
#include <node_buffer.h>
#include <string.h>
#include <stdlib.h>
#include <winpty.h>
#include <Shlwapi.h> // PathCombine
#include <string>
#include <sstream>
#include <iostream>
#include <vector>

using namespace v8;
using namespace std;
using namespace node;

/**
* Misc
*/
extern "C" void init(Handle<Object>);

#define WINPTY_DBG_VARIABLE TEXT("WINPTYDBG")
#define MAX_ENV 65536

/**
* winpty
*/
static std::vector<winpty_t *> ptyHandles;
static volatile LONG ptyCounter;

struct winpty_s {
  winpty_s();
  HANDLE controlPipe;
  HANDLE dataPipe;
};

winpty_s::winpty_s() :
  controlPipe(nullptr),
  dataPipe(nullptr)
{
}

/**
* Helpers
*/

const wchar_t* to_wstring(const String::Utf8Value& str)
{
  const char *bytes = *str;
  unsigned int sizeOfStr = MultiByteToWideChar(CP_ACP, 0, bytes, -1, NULL, 0);
  wchar_t *output = new wchar_t[sizeOfStr];
  MultiByteToWideChar(CP_ACP, 0, bytes, -1, output, sizeOfStr);
  return output;
}

static winpty_t *get_pipe_handle(int handle) {
  for(winpty_t *ptyHandle : ptyHandles) {
    int current = (int)ptyHandle->controlPipe;
    if(current == handle) {
      return ptyHandle;
    }
  }
  return nullptr;
}

static bool remove_pipe_handle(int handle) {
  for(winpty_t *ptyHandle : ptyHandles) {
    if((int)ptyHandle->controlPipe == handle) {
      delete ptyHandle;
      ptyHandle = nullptr;
      return true;
    }
  }
  return false;
}

static bool file_exists(std::wstring filename) {
  return (INVALID_FILE_ATTRIBUTES == ::GetFileAttributesW(filename.c_str()) &&
    ::GetLastError() == ERROR_FILE_NOT_FOUND) == false;
}

// cmd.exe -> C:\Windows\system32\cmd.exe
static std::wstring get_shell_path(std::wstring filename)  {

  if(file_exists(filename)) {
    return nullptr;
  }

  wchar_t buffer_[MAX_ENV];
  int read = ::GetEnvironmentVariableW(L"Path", buffer_, MAX_ENV);
  if(!read) {
    return nullptr;
  }

  std::wstring delimiter = L";";
  size_t pos = 0;
  vector<wstring> paths;
  std::wstring buffer(buffer_);
  while ((pos = buffer.find(delimiter)) != std::wstring::npos) {
    paths.push_back(buffer.substr(0, pos));
    buffer.erase(0, pos + delimiter.length());
  }

  const wchar_t *filename_ = filename.c_str();

  for(wstring path : paths) {
    wchar_t pathCombined[MAX_PATH];
    ::PathCombineW(pathCombined, const_cast<wchar_t*>(path.c_str()), filename_);

    if(pathCombined == NULL) {
      continue;
    }

    if(file_exists(pathCombined)) {
      return std::wstring(pathCombined);
    }

  }

  return nullptr;
}

/*
* PtyOpen
* pty.open(dataPipe, cols, rows)
*
* If you need to debug winpty-agent.exe do the following:
* ======================================================
*
* 1) Install python 2.7
* 2) Install win32pipe
x86) http://sourceforge.net/projects/pywin32/files/pywin32/Build%20218/pywin32-218.win32-py2.7.exe/download
x64) http://sourceforge.net/projects/pywin32/files/pywin32/Build%20218/pywin32-218.win-amd64-py2.7.exe/download
* 3) Start deps/winpty/misc/DebugServer.py (Before you start node)
*
* Then you'll see output from winpty-agent.exe.
*
* Important part:
* ===============
* CreateProcess: success 8896 0 (Windows error code)
*
* Create test.js:
* ===============
*
* var pty = require('./');
*
* var term = pty.fork('cmd.exe', [], {
*   name: 'Windows Shell',
*	  cols: 80,
*	  rows: 30,
*	  cwd: process.env.HOME,
*	  env: process.env,
*	  debug: true
* });
*
* term.on('data', function(data) {
* 	console.log(data);
* });
*
*/

static Handle<Value> PtyOpen(const Arguments& args) {
  HandleScope scope;

  if (args.Length() != 4
    || !args[0]->IsString() // dataPipe
    || !args[1]->IsNumber() // cols
    || !args[2]->IsNumber() // rows
    || !args[3]->IsBoolean()) // debug
  {
    return ThrowException(Exception::Error(
      String::New("Usage: pty.open(dataPipe, cols, rows, debug)")));
  }

  const wchar_t *pipeName = to_wstring(String::Utf8Value(args[0]->ToString()));
  int cols = args[1]->Int32Value();
  int rows = args[2]->Int32Value();
  bool debug = args[3]->ToBoolean()->IsTrue();

  // Enable/disable debugging
  SetEnvironmentVariable(WINPTY_DBG_VARIABLE, debug ? "1" : NULL); // NULL = deletes variable

  // Open a new pty session.
  winpty_t *pc = winpty_open_use_own_datapipe(pipeName, cols, rows);

  // Error occured during startup of agent process.
  assert(pc != nullptr);

  // Save pty struct fpr later use.
  ptyHandles.insert(ptyHandles.end(), pc);

  // Pty object values.
  Local<Object> marshal = Object::New();
  marshal->Set(String::New("pid"), Number::New((int)pc->controlPipe));
  marshal->Set(String::New("pty"), Number::New(InterlockedIncrement(&ptyCounter)));
  marshal->Set(String::New("fd"), Number::New(-1));

  delete pipeName;

  return scope.Close(marshal);

}

/*
* PtyStartProcess
* pty.startProcess(pid, file, env, cwd);
*/

static Handle<Value> PtyStartProcess(const Arguments& args) {
  HandleScope scope;

  if (args.Length() != 5
    || !args[0]->IsNumber() // pid
    || !args[1]->IsString() // file
    || !args[2]->IsString() // cmdline
    || !args[3]->IsArray() // env
    || !args[4]->IsString()) // cwd
  {
    return ThrowException(Exception::Error(
      String::New("Usage: pty.startProcess(pid, file, cmdline, env, cwd)")));
  }

  // Get winpty_t by control pipe handle
  int pid = args[0]->Int32Value();

  winpty_t *pc = get_pipe_handle(pid);
  assert(pc != nullptr);

  const wchar_t *filename = to_wstring(String::Utf8Value(args[1]->ToString()));
  const wchar_t *cmdline = to_wstring(String::Utf8Value(args[2]->ToString()));
  const wchar_t *cwd = to_wstring(String::Utf8Value(args[4]->ToString()));

  // create environment block
  wchar_t *env = NULL;
  const Handle<Array> envValues = Handle<Array>::Cast(args[3]);
  if(!envValues.IsEmpty()) {

    std::wstringstream envBlock;

    for(uint32_t i = 0; i < envValues->Length(); i++) {
      std::wstring envValue(to_wstring(String::Utf8Value(envValues->Get(i)->ToString())));
      envBlock << envValue << L' ';
    }

    std::wstring output = envBlock.str();

    size_t count = output.size();
    env = new wchar_t[count + 2];
    wcsncpy(env, output.c_str(), count);

    wcscat(env, L"\0");
  }

  // use environment 'Path' variable to determine location of
  // the relative path that we have recieved (e.g cmd.exe)
  std::wstring shellpath;
  if(::PathIsRelativeW(filename)) {
    shellpath = get_shell_path(filename);
  } else {
    shellpath = filename;
  }

  if(!file_exists(shellpath)) {
    return ThrowException(Exception::Error(String::New("Unable to load executable, it does not exist.")));
  }

  int result = winpty_start_process(pc, shellpath.c_str(), cmdline, cwd, env);
  delete env;
  assert(0 == result);

  return scope.Close(Undefined());
}

/*
* PtyResize
* pty.resize(pid, cols, rows);
*/
static Handle<Value> PtyResize(const Arguments& args) {
  HandleScope scope;

  if (args.Length() != 3
    || !args[0]->IsNumber() // pid
    || !args[1]->IsNumber() // cols
    || !args[2]->IsNumber()) // rows
  {
    return ThrowException(Exception::Error(String::New("Usage: pty.resize(pid, cols, rows)")));
  }

  int handle = args[0]->Int32Value();
  int cols = args[1]->Int32Value();
  int rows = args[2]->Int32Value();

  winpty_t *pc = get_pipe_handle(handle);

  assert(pc != nullptr);
  assert(0 == winpty_set_size(pc, cols, rows));

  return scope.Close(Undefined());
}

/*
* PtyKill
* pty.kill(pid);
*/
static Handle<Value> PtyKill(const Arguments& args) {
  HandleScope scope;

  if (args.Length() != 1
    || !args[0]->IsNumber()) // pid
  {
    return ThrowException(Exception::Error(String::New("Usage: pty.kill(pid)")));
  }

  int handle = args[0]->Int32Value();

  winpty_t *pc = get_pipe_handle(handle);

  assert(pc != nullptr);
  winpty_exit(pc);
  assert(true == remove_pipe_handle(handle));

  return scope.Close(Undefined());

}

/**
* Init
*/

extern "C" void init(Handle<Object> target) {
  HandleScope scope;
  NODE_SET_METHOD(target, "open", PtyOpen);
  NODE_SET_METHOD(target, "startProcess", PtyStartProcess);
  NODE_SET_METHOD(target, "resize", PtyResize);
  NODE_SET_METHOD(target, "kill", PtyKill);
};

NODE_MODULE(pty, init);
<commit_msg>change to a more descriptive variable name<commit_after>/**
* pty.js
* Copyright (c) 2013, Christopher Jeffrey, Peter Sunde (MIT License)
*
* pty.cc:
*   This file is responsible for starting processes
*   with pseudo-terminal file descriptors.
*/

#include <v8.h>
#include <node.h>
#include <node_buffer.h>
#include <string.h>
#include <stdlib.h>
#include <winpty.h>
#include <Shlwapi.h> // PathCombine
#include <string>
#include <sstream>
#include <iostream>
#include <vector>

using namespace v8;
using namespace std;
using namespace node;

/**
* Misc
*/
extern "C" void init(Handle<Object>);

#define WINPTY_DBG_VARIABLE TEXT("WINPTYDBG")
#define MAX_ENV 65536

/**
* winpty
*/
static std::vector<winpty_t *> ptyHandles;
static volatile LONG ptyCounter;

struct winpty_s {
  winpty_s();
  HANDLE controlPipe;
  HANDLE dataPipe;
};

winpty_s::winpty_s() :
  controlPipe(nullptr),
  dataPipe(nullptr)
{
}

/**
* Helpers
*/

const wchar_t* to_wstring(const String::Utf8Value& str)
{
  const char *bytes = *str;
  unsigned int sizeOfStr = MultiByteToWideChar(CP_ACP, 0, bytes, -1, NULL, 0);
  wchar_t *output = new wchar_t[sizeOfStr];
  MultiByteToWideChar(CP_ACP, 0, bytes, -1, output, sizeOfStr);
  return output;
}

static winpty_t *get_pipe_handle(int handle) {
  for(winpty_t *ptyHandle : ptyHandles) {
    int current = (int)ptyHandle->controlPipe;
    if(current == handle) {
      return ptyHandle;
    }
  }
  return nullptr;
}

static bool remove_pipe_handle(int handle) {
  for(winpty_t *ptyHandle : ptyHandles) {
    if((int)ptyHandle->controlPipe == handle) {
      delete ptyHandle;
      ptyHandle = nullptr;
      return true;
    }
  }
  return false;
}

static bool file_exists(std::wstring filename) {
  return (INVALID_FILE_ATTRIBUTES == ::GetFileAttributesW(filename.c_str()) &&
    ::GetLastError() == ERROR_FILE_NOT_FOUND) == false;
}

// cmd.exe -> C:\Windows\system32\cmd.exe
static std::wstring get_shell_path(std::wstring filename)  {

  if(file_exists(filename)) {
    return nullptr;
  }

  wchar_t buffer_[MAX_ENV];
  int read = ::GetEnvironmentVariableW(L"Path", buffer_, MAX_ENV);
  if(!read) {
    return nullptr;
  }

  std::wstring delimiter = L";";
  size_t pos = 0;
  vector<wstring> paths;
  std::wstring buffer(buffer_);
  while ((pos = buffer.find(delimiter)) != std::wstring::npos) {
    paths.push_back(buffer.substr(0, pos));
    buffer.erase(0, pos + delimiter.length());
  }

  const wchar_t *filename_ = filename.c_str();

  for(wstring path : paths) {
    wchar_t searchPath[MAX_PATH];
    ::PathCombineW(searchPath, const_cast<wchar_t*>(path.c_str()), filename_);

    if(searchPath == NULL) {
      continue;
    }

    if(file_exists(searchPath)) {
      return std::wstring(searchPath);
    }

  }

  return nullptr;
}

/*
* PtyOpen
* pty.open(dataPipe, cols, rows)
*
* If you need to debug winpty-agent.exe do the following:
* ======================================================
*
* 1) Install python 2.7
* 2) Install win32pipe
x86) http://sourceforge.net/projects/pywin32/files/pywin32/Build%20218/pywin32-218.win32-py2.7.exe/download
x64) http://sourceforge.net/projects/pywin32/files/pywin32/Build%20218/pywin32-218.win-amd64-py2.7.exe/download
* 3) Start deps/winpty/misc/DebugServer.py (Before you start node)
*
* Then you'll see output from winpty-agent.exe.
*
* Important part:
* ===============
* CreateProcess: success 8896 0 (Windows error code)
*
* Create test.js:
* ===============
*
* var pty = require('./');
*
* var term = pty.fork('cmd.exe', [], {
*   name: 'Windows Shell',
*	  cols: 80,
*	  rows: 30,
*	  cwd: process.env.HOME,
*	  env: process.env,
*	  debug: true
* });
*
* term.on('data', function(data) {
* 	console.log(data);
* });
*
*/

static Handle<Value> PtyOpen(const Arguments& args) {
  HandleScope scope;

  if (args.Length() != 4
    || !args[0]->IsString() // dataPipe
    || !args[1]->IsNumber() // cols
    || !args[2]->IsNumber() // rows
    || !args[3]->IsBoolean()) // debug
  {
    return ThrowException(Exception::Error(
      String::New("Usage: pty.open(dataPipe, cols, rows, debug)")));
  }

  const wchar_t *pipeName = to_wstring(String::Utf8Value(args[0]->ToString()));
  int cols = args[1]->Int32Value();
  int rows = args[2]->Int32Value();
  bool debug = args[3]->ToBoolean()->IsTrue();

  // Enable/disable debugging
  SetEnvironmentVariable(WINPTY_DBG_VARIABLE, debug ? "1" : NULL); // NULL = deletes variable

  // Open a new pty session.
  winpty_t *pc = winpty_open_use_own_datapipe(pipeName, cols, rows);

  // Error occured during startup of agent process.
  assert(pc != nullptr);

  // Save pty struct fpr later use.
  ptyHandles.insert(ptyHandles.end(), pc);

  // Pty object values.
  Local<Object> marshal = Object::New();
  marshal->Set(String::New("pid"), Number::New((int)pc->controlPipe));
  marshal->Set(String::New("pty"), Number::New(InterlockedIncrement(&ptyCounter)));
  marshal->Set(String::New("fd"), Number::New(-1));

  delete pipeName;

  return scope.Close(marshal);

}

/*
* PtyStartProcess
* pty.startProcess(pid, file, env, cwd);
*/

static Handle<Value> PtyStartProcess(const Arguments& args) {
  HandleScope scope;

  if (args.Length() != 5
    || !args[0]->IsNumber() // pid
    || !args[1]->IsString() // file
    || !args[2]->IsString() // cmdline
    || !args[3]->IsArray() // env
    || !args[4]->IsString()) // cwd
  {
    return ThrowException(Exception::Error(
      String::New("Usage: pty.startProcess(pid, file, cmdline, env, cwd)")));
  }

  // Get winpty_t by control pipe handle
  int pid = args[0]->Int32Value();

  winpty_t *pc = get_pipe_handle(pid);
  assert(pc != nullptr);

  const wchar_t *filename = to_wstring(String::Utf8Value(args[1]->ToString()));
  const wchar_t *cmdline = to_wstring(String::Utf8Value(args[2]->ToString()));
  const wchar_t *cwd = to_wstring(String::Utf8Value(args[4]->ToString()));

  // create environment block
  wchar_t *env = NULL;
  const Handle<Array> envValues = Handle<Array>::Cast(args[3]);
  if(!envValues.IsEmpty()) {

    std::wstringstream envBlock;

    for(uint32_t i = 0; i < envValues->Length(); i++) {
      std::wstring envValue(to_wstring(String::Utf8Value(envValues->Get(i)->ToString())));
      envBlock << envValue << L' ';
    }

    std::wstring output = envBlock.str();

    size_t count = output.size();
    env = new wchar_t[count + 2];
    wcsncpy(env, output.c_str(), count);

    wcscat(env, L"\0");
  }

  // use environment 'Path' variable to determine location of
  // the relative path that we have recieved (e.g cmd.exe)
  std::wstring shellpath;
  if(::PathIsRelativeW(filename)) {
    shellpath = get_shell_path(filename);
  } else {
    shellpath = filename;
  }

  if(!file_exists(shellpath)) {
    return ThrowException(Exception::Error(String::New("Unable to load executable, it does not exist.")));
  }

  int result = winpty_start_process(pc, shellpath.c_str(), cmdline, cwd, env);
  delete env;
  assert(0 == result);

  return scope.Close(Undefined());
}

/*
* PtyResize
* pty.resize(pid, cols, rows);
*/
static Handle<Value> PtyResize(const Arguments& args) {
  HandleScope scope;

  if (args.Length() != 3
    || !args[0]->IsNumber() // pid
    || !args[1]->IsNumber() // cols
    || !args[2]->IsNumber()) // rows
  {
    return ThrowException(Exception::Error(String::New("Usage: pty.resize(pid, cols, rows)")));
  }

  int handle = args[0]->Int32Value();
  int cols = args[1]->Int32Value();
  int rows = args[2]->Int32Value();

  winpty_t *pc = get_pipe_handle(handle);

  assert(pc != nullptr);
  assert(0 == winpty_set_size(pc, cols, rows));

  return scope.Close(Undefined());
}

/*
* PtyKill
* pty.kill(pid);
*/
static Handle<Value> PtyKill(const Arguments& args) {
  HandleScope scope;

  if (args.Length() != 1
    || !args[0]->IsNumber()) // pid
  {
    return ThrowException(Exception::Error(String::New("Usage: pty.kill(pid)")));
  }

  int handle = args[0]->Int32Value();

  winpty_t *pc = get_pipe_handle(handle);

  assert(pc != nullptr);
  winpty_exit(pc);
  assert(true == remove_pipe_handle(handle));

  return scope.Close(Undefined());

}

/**
* Init
*/

extern "C" void init(Handle<Object> target) {
  HandleScope scope;
  NODE_SET_METHOD(target, "open", PtyOpen);
  NODE_SET_METHOD(target, "startProcess", PtyStartProcess);
  NODE_SET_METHOD(target, "resize", PtyResize);
  NODE_SET_METHOD(target, "kill", PtyKill);
};

NODE_MODULE(pty, init);
<|endoftext|>


<commit_before>/* gobby - A GTKmm driven libobby client
 * Copyright (C) 2005 0x539 dev group
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this program; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <stdexcept>
#include <gtkmm/main.h>
#include <gtkmm/messagedialog.h>
#include <libobby/client_buffer.hpp>
#include <libobby/host_buffer.hpp>
#include "createdialog.hpp"
#include "joindialog.hpp"
#include "window.hpp"

Gobby::Window::Window()
 : Gtk::Window(Gtk::WINDOW_TOPLEVEL),
   m_config(Glib::get_home_dir() + "/.gobby/config.xml"), m_buffer(NULL),
   m_running(false), m_login_failed(false)
{
	m_header.session_create_event().connect(
		sigc::mem_fun(*this, &Window::on_session_create) );
	m_header.session_join_event().connect(
		sigc::mem_fun(*this, &Window::on_session_join) );
	m_header.session_quit_event().connect(
		sigc::mem_fun(*this, &Window::on_session_quit) );
	m_header.quit_event().connect(
		sigc::mem_fun(*this, &Window::on_quit) );

	m_chat.chat_event().connect(
		sigc::mem_fun(*this, &Window::on_chat) );

	m_frame_chat.set_shadow_type(Gtk::SHADOW_IN);
	m_frame_list.set_shadow_type(Gtk::SHADOW_IN);
	m_frame_text.set_shadow_type(Gtk::SHADOW_IN);

	m_frame_chat.add(m_chat);
	m_frame_list.add(m_userlist);
	m_frame_text.add(m_folder);

	m_subpaned.pack1(m_frame_text, true, false);
	m_subpaned.pack2(m_frame_list, true, false);

	m_mainpaned.set_border_width(10);
	m_mainpaned.pack1(m_subpaned, true, false);
	m_mainpaned.pack2(m_frame_chat, true, false);

	m_mainbox.pack_start(m_header, Gtk::PACK_SHRINK);
	m_mainbox.pack_start(m_mainpaned, Gtk::PACK_EXPAND_WIDGET);

	add(m_mainbox);

	set_title("Gobby");
	set_default_size(640, 480);
}

Gobby::Window::~Window()
{
	on_session_quit();
}

void Gobby::Window::on_session_create() try
{
	CreateDialog dlg(*this, m_config);
	if(dlg.run() == Gtk::RESPONSE_OK)
	{
		unsigned int port = dlg.get_port();
		Glib::ustring name = dlg.get_name();
		Gdk::Color color = dlg.get_color();

		unsigned int red = color.get_red() * 255 / 65535;
		unsigned int green = color.get_green() * 255 / 65535;
		unsigned int blue = color.get_blue() * 255 / 65535;

		// Create new buffer
		obby::host_buffer* buffer = new obby::host_buffer(
			port, name, red, green, blue);

		// Delete existing buffer, take new one
		delete m_buffer;
		m_buffer = buffer;

		m_buffer->user_join_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_user_join) );
		m_buffer->user_part_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_user_part) );
		m_buffer->insert_document_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_document_insert));
		m_buffer->remove_document_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_document_remove));

		m_buffer->message_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_chat) );
		m_buffer->server_message_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_server_chat) );

		if(!m_timer_conn.connected() )
			m_timer_conn = Glib::signal_timeout().connect(
				sigc::mem_fun(*this, &Window::on_timer), 400);

		// Running
		m_running = true;

		// Delegate start of obby session
		m_header.obby_start();
		m_folder.obby_start();
		m_userlist.obby_start();
		m_chat.obby_start();

		// Let the local user join
		on_obby_user_join(buffer->get_self() );
	}
	else
	{
		if(m_timer_conn.connected() )
			m_timer_conn.disconnect();

		// Delete existing buffer, if any
		delete m_buffer;
		m_buffer = NULL;
	}
}
catch(Glib::Exception& e)
{
	display_error(e.what() );
	on_session_create();
}
catch(std::exception& e)
{
	display_error(e.what() );
	on_session_create();
}

void Gobby::Window::on_session_join() try
{
	JoinDialog dlg(*this, m_config);
	if(dlg.run() == Gtk::RESPONSE_OK)
	{
		Glib::ustring host = dlg.get_host();
		unsigned int port = dlg.get_port();
		Glib::ustring name = dlg.get_name();
		Gdk::Color color = dlg.get_color();

		unsigned int red = color.get_red() * 255 / 65535;
		unsigned int green = color.get_green() * 255 / 65535;
		unsigned int blue = color.get_blue() * 255 / 65535;

		// TODO: Keep existing connection if host and port did not
		// change
		obby::client_buffer* buffer = new obby::client_buffer(
			host, port);
		delete m_buffer;
		m_buffer = buffer;

		buffer->login_failed_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_login_failed) );
		buffer->close_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_close) );
		buffer->sync_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_sync) );

		m_buffer->user_join_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_user_join) );
		m_buffer->user_part_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_user_part) );
		m_buffer->insert_document_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_document_insert));
		m_buffer->remove_document_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_document_remove));

		if(!m_timer_conn.connected() )
			m_timer_conn = Glib::signal_timeout().connect(
				sigc::mem_fun(*this, &Window::on_timer), 400);

		buffer->login(name, red, green, blue);
	}
	else
	{
		if(m_timer_conn.connected() )
			m_timer_conn.disconnect();

		delete m_buffer;
		m_buffer = NULL;
	}
}
catch(Glib::Exception& e)
{
	display_error(e.what());
	on_session_join();
}
catch(std::exception& e)
{
	display_error(e.what());
	on_session_join();
}

void Gobby::Window::on_session_quit()
{
	if(m_buffer)
	{
		if(m_running)
		{
			m_header.obby_end();
			m_folder.obby_end();
			m_userlist.obby_end();
			m_chat.obby_end();

			m_running = false;
		}

		if(m_timer_conn.connected() )
			m_timer_conn.disconnect();

		delete m_buffer;
		m_buffer = NULL;
	}
}

void Gobby::Window::on_quit()
{
	on_session_quit();
	Gtk::Main::quit();
}

void Gobby::Window::on_chat(const Glib::ustring& message) {
	if (m_running)
		m_buffer->send_message(message);
	else
		throw std::runtime_error("tried to send chat message while not connected");
}

void Gobby::Window::on_obby_login_failed(const std::string& reason)
{
	// Remove timer connection, we do not need any timer calls while
	// displaying dialogs
	m_timer_conn.disconnect();
	display_error(reason);

	// We can not call on_session_join right here. In the callstack, there
	// is a call to the timer (which emitted the login_failed signal through
	// obby::buffer::select). on_session_join destroys this buffer, but it
	// still remains in the callstack. The program will crash if it regains
	// control.
	// TODO: A good solution would be to disable the name and port field
	// in the dialog now, because we are already connected to a server. Only
	// the login fields (name & color) will be editable. That ensures that
	// we need not to create a new buffer but just resend a login request.
	m_login_failed = true;
}

void Gobby::Window::on_obby_close()
{
	display_error("Connection lost");
	on_session_quit();
}

void Gobby::Window::on_obby_sync()
{
	// Send documents to components
	obby::buffer::document_iterator iter = m_buffer->document_begin();
	for(iter; iter != m_buffer->document_end(); ++ iter)
		on_obby_document_insert(*iter);
}

void Gobby::Window::on_obby_chat(obby::user& user, const Glib::ustring& message)
{
	m_chat.obby_message(user, message);
}

void Gobby::Window::on_obby_server_chat(const Glib::ustring& message)
{
	m_chat.obby_server_message(message);
}

bool Gobby::Window::on_timer()
{
	m_buffer->select(0);

	// See comment in Window::on_obby_login_failed
	if(m_login_failed)
	{
		on_session_join();
		m_login_failed = false;
	}

	return true;
}

void Gobby::Window::on_obby_user_join(obby::user& user)
{
	// TODO: Something like is_client to prevent dynamic_cast?
	obby::client_buffer* buf = dynamic_cast<obby::client_buffer*>(m_buffer);
	if(buf)
	{
		if(&buf->get_self() == &user)
		{
			// Login was sucessful, let the fun begin
			m_header.obby_start();
			m_folder.obby_start();
			m_userlist.obby_start();
			m_chat.obby_start();

			m_running = true;
		}
	}

	// Tell user join to components
	m_header.obby_user_join(user);
	m_folder.obby_user_join(user);
	m_userlist.obby_user_join(user);
	m_chat.obby_user_join(user);
}

void Gobby::Window::on_obby_user_part(obby::user& user)
{
	// Tell user part to components
	m_header.obby_user_part(user);
	m_folder.obby_user_part(user);
	m_userlist.obby_user_part(user);
	m_chat.obby_user_part(user);
}

void Gobby::Window::on_obby_document_insert(obby::document& document)
{
	m_header.obby_document_insert(document);
	m_folder.obby_document_insert(document);
	m_userlist.obby_document_insert(document);
	m_chat.obby_document_insert(document);
}

void Gobby::Window::on_obby_document_remove(obby::document& document)
{
	m_header.obby_document_remove(document);
	m_folder.obby_document_remove(document);
	m_userlist.obby_document_remove(document);
	m_chat.obby_document_remove(document);
}

void Gobby::Window::display_error(const Glib::ustring& message)
{
	Gtk::MessageDialog dlg(*this, message, false, Gtk::MESSAGE_ERROR,
	                       Gtk::BUTTONS_OK, true);
	dlg.run();
}

<commit_msg>[project @ Fixed window to also connect chat signals on join]<commit_after>/* gobby - A GTKmm driven libobby client
 * Copyright (C) 2005 0x539 dev group
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this program; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <stdexcept>
#include <gtkmm/main.h>
#include <gtkmm/messagedialog.h>
#include <libobby/client_buffer.hpp>
#include <libobby/host_buffer.hpp>
#include "createdialog.hpp"
#include "joindialog.hpp"
#include "window.hpp"

Gobby::Window::Window()
 : Gtk::Window(Gtk::WINDOW_TOPLEVEL),
   m_config(Glib::get_home_dir() + "/.gobby/config.xml"), m_buffer(NULL),
   m_running(false), m_login_failed(false)
{
	m_header.session_create_event().connect(
		sigc::mem_fun(*this, &Window::on_session_create) );
	m_header.session_join_event().connect(
		sigc::mem_fun(*this, &Window::on_session_join) );
	m_header.session_quit_event().connect(
		sigc::mem_fun(*this, &Window::on_session_quit) );
	m_header.quit_event().connect(
		sigc::mem_fun(*this, &Window::on_quit) );

	m_chat.chat_event().connect(
		sigc::mem_fun(*this, &Window::on_chat) );

	m_frame_chat.set_shadow_type(Gtk::SHADOW_IN);
	m_frame_list.set_shadow_type(Gtk::SHADOW_IN);
	m_frame_text.set_shadow_type(Gtk::SHADOW_IN);

	m_frame_chat.add(m_chat);
	m_frame_list.add(m_userlist);
	m_frame_text.add(m_folder);

	m_subpaned.pack1(m_frame_text, true, false);
	m_subpaned.pack2(m_frame_list, true, false);

	m_mainpaned.set_border_width(10);
	m_mainpaned.pack1(m_subpaned, true, false);
	m_mainpaned.pack2(m_frame_chat, true, false);

	m_mainbox.pack_start(m_header, Gtk::PACK_SHRINK);
	m_mainbox.pack_start(m_mainpaned, Gtk::PACK_EXPAND_WIDGET);

	add(m_mainbox);

	set_title("Gobby");
	set_default_size(640, 480);
}

Gobby::Window::~Window()
{
	on_session_quit();
}

void Gobby::Window::on_session_create() try
{
	CreateDialog dlg(*this, m_config);
	if(dlg.run() == Gtk::RESPONSE_OK)
	{
		unsigned int port = dlg.get_port();
		Glib::ustring name = dlg.get_name();
		Gdk::Color color = dlg.get_color();

		unsigned int red = color.get_red() * 255 / 65535;
		unsigned int green = color.get_green() * 255 / 65535;
		unsigned int blue = color.get_blue() * 255 / 65535;

		// Create new buffer
		obby::host_buffer* buffer = new obby::host_buffer(
			port, name, red, green, blue);

		// Delete existing buffer, take new one
		delete m_buffer;
		m_buffer = buffer;

		m_buffer->user_join_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_user_join) );
		m_buffer->user_part_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_user_part) );
		m_buffer->insert_document_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_document_insert));
		m_buffer->remove_document_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_document_remove));

		m_buffer->message_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_chat) );
		m_buffer->server_message_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_server_chat) );

		if(!m_timer_conn.connected() )
			m_timer_conn = Glib::signal_timeout().connect(
				sigc::mem_fun(*this, &Window::on_timer), 400);

		// Running
		m_running = true;

		// Delegate start of obby session
		m_header.obby_start();
		m_folder.obby_start();
		m_userlist.obby_start();
		m_chat.obby_start();

		// Let the local user join
		on_obby_user_join(buffer->get_self() );
	}
	else
	{
		if(m_timer_conn.connected() )
			m_timer_conn.disconnect();

		// Delete existing buffer, if any
		delete m_buffer;
		m_buffer = NULL;
	}
}
catch(Glib::Exception& e)
{
	display_error(e.what() );
	on_session_create();
}
catch(std::exception& e)
{
	display_error(e.what() );
	on_session_create();
}

void Gobby::Window::on_session_join() try
{
	JoinDialog dlg(*this, m_config);
	if(dlg.run() == Gtk::RESPONSE_OK)
	{
		Glib::ustring host = dlg.get_host();
		unsigned int port = dlg.get_port();
		Glib::ustring name = dlg.get_name();
		Gdk::Color color = dlg.get_color();

		unsigned int red = color.get_red() * 255 / 65535;
		unsigned int green = color.get_green() * 255 / 65535;
		unsigned int blue = color.get_blue() * 255 / 65535;

		// TODO: Keep existing connection if host and port did not
		// change
		obby::client_buffer* buffer = new obby::client_buffer(
			host, port);
		delete m_buffer;
		m_buffer = buffer;

		buffer->login_failed_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_login_failed) );
		buffer->close_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_close) );
		buffer->sync_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_sync) );

		m_buffer->user_join_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_user_join) );
		m_buffer->user_part_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_user_part) );
		m_buffer->insert_document_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_document_insert));
		m_buffer->remove_document_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_document_remove));

		m_buffer->message_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_chat) );
		m_buffer->server_message_event().connect(
			sigc::mem_fun(*this, &Window::on_obby_server_chat) );

		if(!m_timer_conn.connected() )
			m_timer_conn = Glib::signal_timeout().connect(
				sigc::mem_fun(*this, &Window::on_timer), 400);

		buffer->login(name, red, green, blue);
	}
	else
	{
		if(m_timer_conn.connected() )
			m_timer_conn.disconnect();

		delete m_buffer;
		m_buffer = NULL;
	}
}
catch(Glib::Exception& e)
{
	display_error(e.what());
	on_session_join();
}
catch(std::exception& e)
{
	display_error(e.what());
	on_session_join();
}

void Gobby::Window::on_session_quit()
{
	if(m_buffer)
	{
		if(m_running)
		{
			m_header.obby_end();
			m_folder.obby_end();
			m_userlist.obby_end();
			m_chat.obby_end();

			m_running = false;
		}

		if(m_timer_conn.connected() )
			m_timer_conn.disconnect();

		delete m_buffer;
		m_buffer = NULL;
	}
}

void Gobby::Window::on_quit()
{
	on_session_quit();
	Gtk::Main::quit();
}

void Gobby::Window::on_chat(const Glib::ustring& message) {
	if (m_running)
		m_buffer->send_message(message);
	else
		throw std::runtime_error("tried to send chat message while not connected");
}

void Gobby::Window::on_obby_login_failed(const std::string& reason)
{
	// Remove timer connection, we do not need any timer calls while
	// displaying dialogs
	m_timer_conn.disconnect();
	display_error(reason);

	// We can not call on_session_join right here. In the callstack, there
	// is a call to the timer (which emitted the login_failed signal through
	// obby::buffer::select). on_session_join destroys this buffer, but it
	// still remains in the callstack. The program will crash if it regains
	// control.
	// TODO: A good solution would be to disable the name and port field
	// in the dialog now, because we are already connected to a server. Only
	// the login fields (name & color) will be editable. That ensures that
	// we need not to create a new buffer but just resend a login request.
	m_login_failed = true;
}

void Gobby::Window::on_obby_close()
{
	display_error("Connection lost");
	on_session_quit();
}

void Gobby::Window::on_obby_sync()
{
	// Send documents to components
	obby::buffer::document_iterator iter = m_buffer->document_begin();
	for(iter; iter != m_buffer->document_end(); ++ iter)
		on_obby_document_insert(*iter);
}

void Gobby::Window::on_obby_chat(obby::user& user, const Glib::ustring& message)
{
	m_chat.obby_message(user, message);
}

void Gobby::Window::on_obby_server_chat(const Glib::ustring& message)
{
	m_chat.obby_server_message(message);
}

bool Gobby::Window::on_timer()
{
	m_buffer->select(0);

	// See comment in Window::on_obby_login_failed
	if(m_login_failed)
	{
		on_session_join();
		m_login_failed = false;
	}

	return true;
}

void Gobby::Window::on_obby_user_join(obby::user& user)
{
	// TODO: Something like is_client to prevent dynamic_cast?
	obby::client_buffer* buf = dynamic_cast<obby::client_buffer*>(m_buffer);
	if(buf)
	{
		if(&buf->get_self() == &user)
		{
			// Login was sucessful, let the fun begin
			m_header.obby_start();
			m_folder.obby_start();
			m_userlist.obby_start();
			m_chat.obby_start();

			m_running = true;
		}
	}

	// Tell user join to components
	m_header.obby_user_join(user);
	m_folder.obby_user_join(user);
	m_userlist.obby_user_join(user);
	m_chat.obby_user_join(user);
}

void Gobby::Window::on_obby_user_part(obby::user& user)
{
	// Tell user part to components
	m_header.obby_user_part(user);
	m_folder.obby_user_part(user);
	m_userlist.obby_user_part(user);
	m_chat.obby_user_part(user);
}

void Gobby::Window::on_obby_document_insert(obby::document& document)
{
	m_header.obby_document_insert(document);
	m_folder.obby_document_insert(document);
	m_userlist.obby_document_insert(document);
	m_chat.obby_document_insert(document);
}

void Gobby::Window::on_obby_document_remove(obby::document& document)
{
	m_header.obby_document_remove(document);
	m_folder.obby_document_remove(document);
	m_userlist.obby_document_remove(document);
	m_chat.obby_document_remove(document);
}

void Gobby::Window::display_error(const Glib::ustring& message)
{
	Gtk::MessageDialog dlg(*this, message, false, Gtk::MESSAGE_ERROR,
	                       Gtk::BUTTONS_OK, true);
	dlg.run();
}

<|endoftext|>


<commit_before>#include "worker.hpp"

using namespace headers;

static bool IPv4HdrVerification(ipv4* ipv4_hdr, uint16_t f_len){
	// Do header verification (rfc 1812)
	// Step 1
	if(f_len < 20){
		return false;
	}

	// Step 2
	if(IPv4HdrChecksum(ipv4_hdr) != ipv4_hdr->checksum){
		logDebug("IPv4 verification failed");
		return false;
	}

	// Step 3
	if(ipv4_hdr->version() != 4){
		return false;
	}

	// Step 4
	if(ipv4_hdr->ihl() < 5){
		return false;
	}

	// Step 5
	if(ntohs(ipv4_hdr->total_length) < ipv4_hdr->ihl()*4){
		return false;
	}

	// Check for TTL > 1
	if(ipv4_hdr->ttl <= 1){
		return false;
	}

	return true;
};

void Worker::process(){
	// TODO
	// ICMP STUFF

#define WORKER_BULK_SIZE 64
	frame f[WORKER_BULK_SIZE];

	while(1){
		size_t numFrames = ingressQ->try_dequeue_bulk(f, WORKER_BULK_SIZE);
		if(!numFrames){
			return;
		}

		for(size_t i=0; i<numFrames; i++){
			logDebug("Worker::process Processing packet now\n");

			// Cast all the things
			ether* ether_hdr = reinterpret_cast<ether*>(f[i].buf_ptr);
			ipv4* ipv4_hdr = reinterpret_cast<ipv4*>(f[i].buf_ptr + sizeof(ether));

			//Interface& interface = interfaces->at(f.iface & frame::IFACE_ID);
			shared_ptr<Interface> iface_ptr;
			for(auto iface : interfaces){
				if(iface->netmapIndex == (f[i].iface & frame::IFACE_ID)){
					iface_ptr = iface;
					break;
				}
			}
			if(iface_ptr == nullptr){
				fatal("Worker::process something went wrong: netmap interface not found in netlink context");
			}

			if(ether_hdr->ethertype == htons(0x0800)){
				if(!IPv4HdrVerification(ipv4_hdr, f[i].len)){
					logDebug("Worker::process Discarding frame - Header verification failed");
					f[i].iface = frame::IFACE_DISCARD;
				} else {
					// Check if the packet is targeted at the router
					if(count(iface_ptr->IPs.begin(), iface_ptr->IPs.end(), ipv4_hdr->d_ip)){
						logDebug("Worker::process Frame is destined at the host");
						f[i].iface |= frame::IFACE_HOST;
						continue;
					}

					// From here on, all checks were successful
					ipv4_hdr->ttl--;
					ipv4_hdr->checksum++;

					// Route the packet
					nh_index index = cur_lpm->route(ntohl(ipv4_hdr->d_ip));
					logDebug("Worker::process nh_index: " + int2strHex(index));

					// Check if the index is invalid
					if(index == RoutingTable::route::NH_INVALID){
						fatal("Worker::process next hop is invalid");
					} else {
						logDebug("Worker::process frame will use next hop " + int2strHex(index));
					}

					// Look up the next hop
					ARPTable::nextHop nh;
					if(!(index & RoutingTable::route::NH_DIRECTLY_CONNECTED)){
						nh = cur_arp_table->nextHops[index];
					} else {
						//nh = cur_arp_table->directlyConnected.at(ntohl(ipv4_hdr->d_ip));
						auto it = cur_arp_table->directlyConnected.find(ntohl(ipv4_hdr->d_ip));
						if(it != cur_arp_table->directlyConnected.end()){
							nh = it->second;
						} else {
							nh.mac = ARPTable::nextHop::invalidMac;
							nh.netmapInterface = index ^ RoutingTable::route::NH_DIRECTLY_CONNECTED;
						}
					}

					// Is the next hop valid?
					if(!nh){
						// Let the manager handle this
						logDebug("Worker::process There is no MAC for this IP ("
								+ ip_to_str(htonl(ipv4_hdr->d_ip)) + ")");
						logDebug("Worker::process Interface for ARP: " + int2str(nh.netmapInterface));
						if(nh.netmapInterface == uint16_t_max){
							abort();
						}
						f[i].iface = nh.netmapInterface;
						f[i].iface |= frame::IFACE_NOMAC;
					} else {
						// Set MAC addresses
						logDebug("Worker::process There is nothing special about this frame");
						ether_hdr->d_mac = nh.mac;
						ether_hdr->s_mac = iface_ptr->mac;
						f[i].iface = nh.netmapInterface;
					}
					egressQ->try_enqueue(f[i]);
				}
			} else if(ether_hdr->ethertype == htons(0x0806)){
				logDebug("Worker::process This frame contains some kind of ARP payload");
				f[i].iface |= frame::IFACE_ARP;
				egressQ->try_enqueue(f[i]);
			} else {
				// This router currently doesn't support L3 Protocol $foo
				std::stringstream stream;
				stream << std::hex << htons(ether_hdr->ethertype);
				logDebug("Worker::process L3 protocol is currently not supported, given: "
						+ stream.str());
				f[i].iface = frame::IFACE_DISCARD;
				egressQ->try_enqueue(f[i]);
			}
		}
	}
};

void Worker::printAndClearStats(){
	stringstream sstream;
	sstream << "Worker " << workerId << ": ";
	sstream << "Avg. batch size: " << statsNumFrames / statsNumBatches << " ";
	sstream << "#Frames: " << statsNumFrames << " ";
	sstream << "#Batches: " << statsNumBatches << " ";
	sstream << "#Bytes: " << statsNumBytes << endl;

	statsNumFrames = 0;
	statsNumBatches = 0;
	statsNumBytes = 0;

	logInfo(sstream.str());
};
<commit_msg>fix floating point exception<commit_after>#include "worker.hpp"

using namespace headers;

static bool IPv4HdrVerification(ipv4* ipv4_hdr, uint16_t f_len){
	// Do header verification (rfc 1812)
	// Step 1
	if(f_len < 20){
		return false;
	}

	// Step 2
	if(IPv4HdrChecksum(ipv4_hdr) != ipv4_hdr->checksum){
		logDebug("IPv4 verification failed");
		return false;
	}

	// Step 3
	if(ipv4_hdr->version() != 4){
		return false;
	}

	// Step 4
	if(ipv4_hdr->ihl() < 5){
		return false;
	}

	// Step 5
	if(ntohs(ipv4_hdr->total_length) < ipv4_hdr->ihl()*4){
		return false;
	}

	// Check for TTL > 1
	if(ipv4_hdr->ttl <= 1){
		return false;
	}

	return true;
};

void Worker::process(){
	// TODO
	// ICMP STUFF

#define WORKER_BULK_SIZE 64
	frame f[WORKER_BULK_SIZE];

	while(1){
		size_t numFrames = ingressQ->try_dequeue_bulk(f, WORKER_BULK_SIZE);
		if(!numFrames){
			return;
		}

		for(size_t i=0; i<numFrames; i++){
			logDebug("Worker::process Processing packet now\n");

			// Cast all the things
			ether* ether_hdr = reinterpret_cast<ether*>(f[i].buf_ptr);
			ipv4* ipv4_hdr = reinterpret_cast<ipv4*>(f[i].buf_ptr + sizeof(ether));

			//Interface& interface = interfaces->at(f.iface & frame::IFACE_ID);
			shared_ptr<Interface> iface_ptr;
			for(auto iface : interfaces){
				if(iface->netmapIndex == (f[i].iface & frame::IFACE_ID)){
					iface_ptr = iface;
					break;
				}
			}
			if(iface_ptr == nullptr){
				fatal("Worker::process something went wrong: netmap interface not found in netlink context");
			}

			if(ether_hdr->ethertype == htons(0x0800)){
				if(!IPv4HdrVerification(ipv4_hdr, f[i].len)){
					logDebug("Worker::process Discarding frame - Header verification failed");
					f[i].iface = frame::IFACE_DISCARD;
				} else {
					// Check if the packet is targeted at the router
					if(count(iface_ptr->IPs.begin(), iface_ptr->IPs.end(), ipv4_hdr->d_ip)){
						logDebug("Worker::process Frame is destined at the host");
						f[i].iface |= frame::IFACE_HOST;
						continue;
					}

					// From here on, all checks were successful
					ipv4_hdr->ttl--;
					ipv4_hdr->checksum++;

					// Route the packet
					nh_index index = cur_lpm->route(ntohl(ipv4_hdr->d_ip));
					logDebug("Worker::process nh_index: " + int2strHex(index));

					// Check if the index is invalid
					if(index == RoutingTable::route::NH_INVALID){
						fatal("Worker::process next hop is invalid");
					} else {
						logDebug("Worker::process frame will use next hop " + int2strHex(index));
					}

					// Look up the next hop
					ARPTable::nextHop nh;
					if(!(index & RoutingTable::route::NH_DIRECTLY_CONNECTED)){
						nh = cur_arp_table->nextHops[index];
					} else {
						//nh = cur_arp_table->directlyConnected.at(ntohl(ipv4_hdr->d_ip));
						auto it = cur_arp_table->directlyConnected.find(ntohl(ipv4_hdr->d_ip));
						if(it != cur_arp_table->directlyConnected.end()){
							nh = it->second;
						} else {
							nh.mac = ARPTable::nextHop::invalidMac;
							nh.netmapInterface = index ^ RoutingTable::route::NH_DIRECTLY_CONNECTED;
						}
					}

					// Is the next hop valid?
					if(!nh){
						// Let the manager handle this
						logDebug("Worker::process There is no MAC for this IP ("
								+ ip_to_str(htonl(ipv4_hdr->d_ip)) + ")");
						logDebug("Worker::process Interface for ARP: " + int2str(nh.netmapInterface));
						if(nh.netmapInterface == uint16_t_max){
							abort();
						}
						f[i].iface = nh.netmapInterface;
						f[i].iface |= frame::IFACE_NOMAC;
					} else {
						// Set MAC addresses
						logDebug("Worker::process There is nothing special about this frame");
						ether_hdr->d_mac = nh.mac;
						ether_hdr->s_mac = iface_ptr->mac;
						f[i].iface = nh.netmapInterface;
					}
					egressQ->try_enqueue(f[i]);
				}
			} else if(ether_hdr->ethertype == htons(0x0806)){
				logDebug("Worker::process This frame contains some kind of ARP payload");
				f[i].iface |= frame::IFACE_ARP;
				egressQ->try_enqueue(f[i]);
			} else {
				// This router currently doesn't support L3 Protocol $foo
				std::stringstream stream;
				stream << std::hex << htons(ether_hdr->ethertype);
				logDebug("Worker::process L3 protocol is currently not supported, given: "
						+ stream.str());
				f[i].iface = frame::IFACE_DISCARD;
				egressQ->try_enqueue(f[i]);
			}
		}
	}
};

void Worker::printAndClearStats(){
	stringstream sstream;
	sstream << "Worker " << workerId << ": ";
	if((statsNumFrames > 0) && (statsNumBatches > 0)){
		sstream << "Avg. batch size: " << statsNumFrames / statsNumBatches << " ";
	} else {
		sstream << "Avg. batch size: - ";
	}
	sstream << "#Frames: " << statsNumFrames << " ";
	sstream << "#Batches: " << statsNumBatches << " ";
	sstream << "#Bytes: " << statsNumBytes << endl;

	statsNumFrames = 0;
	statsNumBatches = 0;
	statsNumBytes = 0;

	logInfo(sstream.str());
};
<|endoftext|>


<commit_before>#include <cctype>

#include "config.h"
#include "zs_case.hh"

#if HAVE_STRCASECMP
# include <strings.h>
int zs_strcasecmp(const char* s1, const char* s2){
  return strcasecmp(s1, s2);
}
#else
int zs_strcasecmp(const char* s1, const char* s2){
  for(; *s1 && *s2; s1++, s2++){
    auto c1 = std::tolower(*s1);
    auto c2 = std::tolower(*s2);
    if(c1 != c2){
      return c1 - c2;
    }
  }

  return std::tolower(*s1) - std::tolower(*s2);
}
#endif // !defined HAVE_STRCASECMP

int zs_charcasecmp(char c1, char c2){
  char s1[2] = {c1, '\0'};
  char s2[2] = {c2, '\0'};
  return zs_strcasecmp(s1, s2);
}
<commit_msg>trivial refactoring<commit_after>#include <cctype>

#include "config.h"
#include "zs_case.hh"

#if HAVE_STRCASECMP
# include <strings.h>
#endif

int zs_strcasecmp(const char* s1, const char* s2){
#if HAVE_STRCASECMP
  return strcasecmp(s1, s2);
#else
  for(; *s1 && *s2; s1++, s2++){
    auto c1 = std::tolower(*s1);
    auto c2 = std::tolower(*s2);
    if(c1 != c2){
      return c1 - c2;
    }
  }
  return std::tolower(*s1) - std::tolower(*s2);
#endif // HAVE_STRCASECMP
}

int zs_charcasecmp(char c1, char c2){
  char s1[2] = {c1, '\0'};
  char s2[2] = {c2, '\0'};
  return zs_strcasecmp(s1, s2);
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <list>
#include <typeinfo>
#include <ctype.h>

#define PRINT_LINE (std::cout << "line: " << __LINE__ << std::endl)

enum TokenType{
  TOKEN_BRACKET_OPEN,
  TOKEN_BRACKET_CLOSE,
  TOKEN_SYMBOL,
  TOKEN_STRING,
  TOKEN_NIL,
};

class Token {
public:
  TokenType type;
  std::string value;

  Token(TokenType atype) : type(atype), value(std::string()) {
  }

  Token(TokenType atype, std::string avalue) : type(atype), value(avalue) {
  }

  std::string str() {
    std::stringstream ss;
    ss << "Token(" << type << ", " << value << ")";
    return ss.str();
  }
};

namespace Lisp {
  class Expression;
}

// memory allocated exprs
std::list<Lisp::Expression*> objects;

namespace Lisp {
  class Expression {
  public:
    Expression() {
      objects.push_back(this);
    }
    virtual ~Expression() {}

    virtual std::string lisp_str() = 0;
  };

  class CallFunction : public Expression {
  public:
    std::string name;
    std::vector<Expression*> args;

    CallFunction(std::string aname, std::vector<Expression*> &aargs) : name(aname), args(aargs) {}

    std::string lisp_str() {
      std::stringstream ss;
      ss << "(" << name << " ";
      for(Expression* arg : args) {
        ss << arg->lisp_str() << " ";
      }
      ss << ")";
      return ss.str();
    }
  };

  class String : public Expression {
  public:
    std::string value;

    String(std::string &avalue) : value(avalue) {}

    std::string lisp_str() { return '"' + value + '"'; }
  };

  class List : public Expression {
  public:
    std::vector<Expression*> values;

    List(std::vector<Expression*> &avalues) : values(avalues) {}

    std::string lisp_str() {
      std::stringstream ss;
      ss << "(";
      for(Expression* value : values) {
        ss << value->lisp_str() << " ";
      }
      ss << ")";
      return ss.str();
    }
  };

  // TODO: RubyみたくExpression*に埋め込みたい
  class Nil : public Expression {
  public:
    Nil() {}

    std::string lisp_str() { return "nil"; }
  };

  class Parser {
  public:
    std::vector<Expression*> parse(const std::string &code) {
      tokens = tokenize(code);

      /*for(auto tok : tokens) {
        std::cout << tok->str() << std::endl;
      }*/

      std::vector<Expression*> exprs;
      while(!tokens.empty()) {
        exprs.push_back(parse_expr());
      }
      return exprs;
    }

  private:
    std::list<Token*> tokens;

    inline Token* cur_token() {
      return tokens.empty() ? nullptr : tokens.front();
    }

    void consume_token() {
      auto ctoken = cur_token();
      if(ctoken) delete ctoken;

      if(!tokens.empty()) tokens.pop_front();
    }

    Expression* parse_call_fun() {
      consume_token();
      if(cur_token()->type != TOKEN_SYMBOL) {
        //TODO: raise an error
      }
      std::string name;
      name = cur_token()->value;

      consume_token();
      std::vector<Expression*> args;
      for(; !tokens.empty() && cur_token()->type != TOKEN_BRACKET_CLOSE ; consume_token()) {
        args.push_back(parse_expr());
      }

      consume_token();

      return new CallFunction(name, args);
    }

    Expression* parse_expr() {
      switch(cur_token()->type) {
        case TOKEN_BRACKET_OPEN:
          return parse_call_fun();
        case TOKEN_STRING:
          return new String(cur_token()->value);
        case TOKEN_NIL:
          return new Nil();
        default:
          //TODO: raise an error
          return nullptr;
      }
    }

    bool is_symbol(char c) {
      return isalnum(c) && isalpha(c);
    }

    std::list<Token*> tokenize(const std::string &code) {
      std::list<Token*> tokens;

      for(size_t i = 0 ; i < code.size() - 1 ; i++) { //TODO: -1を修正(EOFっぽい?)
        char ch = code[i];
        if(ch == '(')
          tokens.push_back(new Token(TOKEN_BRACKET_OPEN));
        else if(ch == ')')
          tokens.push_back(new Token(TOKEN_BRACKET_CLOSE));
        else if(ch == '"') { // string
          i++;

          size_t token_len = 0;
          while(code[i + token_len] != '"') {
            token_len++;
            if(i + token_len >= code.size()) {
              //TODO: raise an error
            }
          }
          tokens.push_back(new Token(TOKEN_STRING, code.substr(i, token_len)));
          i += token_len;
        }
        else if(ch == ' ' || ch == '\n')
          ;//skip
        else { // symbol
          size_t token_len = 0;
          while(is_symbol(code[i + token_len])) {
            token_len++;
            if(i + token_len >= code.size()) {
              //TODO: raise an error
            }
          }

          std::string token_val = code.substr(i, token_len);
          TokenType token_type;
          if(token_val == "nil")
            token_type = TOKEN_NIL;
          else
            token_type = TOKEN_SYMBOL;

          if(token_type == TOKEN_SYMBOL)
            tokens.push_back(new Token(TOKEN_SYMBOL, token_val));
          else
            tokens.push_back(new Token(token_type));

          i += token_len - 1;
        }
      }

      return tokens;
    }
  };

  class Evaluator {
  public:
    static Expression* evaluate(Expression* expr) {
      const std::type_info& id = typeid(*expr);
      if(id == typeid(CallFunction)) {
        auto call_fun = (CallFunction*)expr;
        auto name = call_fun->name;
        if(name == "print") {
          for(auto arg : call_fun->args) {
            std::cout << ((String*)arg)->value;
          }
          return new Nil();
        }
        else if(name == "inspect") {
          std::cout << (call_fun->args[0])->lisp_str() << std::endl;
          return new Nil();
        }
        else if(name == "list") {
          return new List(call_fun->args);
        }
      }

      //TODO: raise an error
      return nullptr;
    }
  };
}

int main() {
  using namespace std;

  string code;
  //code.reserve(1024);

  char ch;
  while((ch = cin.get()) != std::char_traits<char>::eof()) {
    code.push_back(ch);
  }

  Lisp::Parser parser;
  auto exprs = parser.parse(code);

  for(size_t i = 0 ; i < exprs.size() ; i++) {
    exprs[i] = Lisp::Evaluator::evaluate(exprs[i]);
  }

  // fake GC
  for(auto expr : objects) {
    delete expr;
  }

  return 0;
}
<commit_msg>再帰的な評価に対応<commit_after>#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <list>
#include <typeinfo>
#include <ctype.h>

#define PRINT_LINE (std::cout << "line: " << __LINE__ << std::endl)

enum TokenType{
  TOKEN_BRACKET_OPEN,
  TOKEN_BRACKET_CLOSE,
  TOKEN_SYMBOL,
  TOKEN_STRING,
  TOKEN_NIL,
};

class Token {
public:
  TokenType type;
  std::string value;

  Token(TokenType atype) : type(atype), value(std::string()) {
  }

  Token(TokenType atype, std::string avalue) : type(atype), value(avalue) {
  }

  std::string str() {
    std::stringstream ss;
    ss << "Token(" << type << ", " << value << ")";
    return ss.str();
  }
};

namespace Lisp {
  class Expression;
}

// memory allocated exprs
std::list<Lisp::Expression*> objects;

namespace Lisp {
  class Expression {
  public:
    Expression() {
      objects.push_back(this);
    }
    virtual ~Expression() {}

    virtual std::string lisp_str() = 0;
  };

  class CallFunction : public Expression {
  public:
    std::string name;
    std::vector<Expression*> args;

    CallFunction(std::string aname, std::vector<Expression*> &aargs) : name(aname), args(aargs) {}

    std::string lisp_str() {
      std::stringstream ss;
      ss << "(" << name << " ";
      for(Expression* arg : args) {
        ss << arg->lisp_str() << " ";
      }
      ss << ")";
      return ss.str();
    }
  };

  class String : public Expression {
  public:
    std::string value;

    String(std::string &avalue) : value(avalue) {}

    std::string lisp_str() { return '"' + value + '"'; }
  };

  class List : public Expression {
  public:
    std::vector<Expression*> values;

    List(std::vector<Expression*> &avalues) : values(avalues) {}

    std::string lisp_str() {
      std::stringstream ss;
      ss << "(";
      for(Expression* value : values) {
        ss << value->lisp_str() << " ";
      }
      ss << ")";
      return ss.str();
    }
  };

  // TODO: RubyみたくExpression*に埋め込みたい
  class Nil : public Expression {
  public:
    Nil() {}

    std::string lisp_str() { return "nil"; }
  };

  class Parser {
  public:
    std::vector<Expression*> parse(const std::string &code) {
      tokens = tokenize(code);

      /*for(auto tok : tokens) {
        std::cout << tok->str() << std::endl;
      }*/

      std::vector<Expression*> exprs;
      while(!tokens.empty()) {
        exprs.push_back(parse_expr());
      }
      return exprs;
    }

  private:
    std::list<Token*> tokens;

    inline Token* cur_token() {
      return tokens.empty() ? nullptr : tokens.front();
    }

    void consume_token() {
      auto ctoken = cur_token();
      if(ctoken) delete ctoken;

      if(!tokens.empty()) tokens.pop_front();
    }

    Expression* parse_call_fun() {
      consume_token();
      if(cur_token()->type != TOKEN_SYMBOL) {
        //TODO: raise an error
      }
      std::string name;
      name = cur_token()->value;

      consume_token();
      std::vector<Expression*> args;
      for(; !tokens.empty() && cur_token()->type != TOKEN_BRACKET_CLOSE ; consume_token()) {
        args.push_back(parse_expr());
      }

      consume_token();

      return new CallFunction(name, args);
    }

    Expression* parse_expr() {
      switch(cur_token()->type) {
        case TOKEN_BRACKET_OPEN:
          return parse_call_fun();
        case TOKEN_STRING:
          return new String(cur_token()->value);
        case TOKEN_NIL:
          return new Nil();
        default:
          //TODO: raise an error
          return nullptr;
      }
    }

    bool is_symbol(char c) {
      return isalnum(c) && isalpha(c);
    }

    std::list<Token*> tokenize(const std::string &code) {
      std::list<Token*> tokens;

      for(size_t i = 0 ; i < code.size() - 1 ; i++) { //TODO: -1を修正(EOFっぽい?)
        char ch = code[i];
        if(ch == '(')
          tokens.push_back(new Token(TOKEN_BRACKET_OPEN));
        else if(ch == ')')
          tokens.push_back(new Token(TOKEN_BRACKET_CLOSE));
        else if(ch == '"') { // string
          i++;

          size_t token_len = 0;
          while(code[i + token_len] != '"') {
            token_len++;
            if(i + token_len >= code.size()) {
              //TODO: raise an error
            }
          }
          tokens.push_back(new Token(TOKEN_STRING, code.substr(i, token_len)));
          i += token_len;
        }
        else if(ch == ' ' || ch == '\n')
          ;//skip
        else { // symbol
          size_t token_len = 0;
          while(is_symbol(code[i + token_len])) {
            token_len++;
            if(i + token_len >= code.size()) {
              //TODO: raise an error
            }
          }

          std::string token_val = code.substr(i, token_len);
          TokenType token_type;
          if(token_val == "nil")
            token_type = TOKEN_NIL;
          else
            token_type = TOKEN_SYMBOL;

          if(token_type == TOKEN_SYMBOL)
            tokens.push_back(new Token(TOKEN_SYMBOL, token_val));
          else
            tokens.push_back(new Token(token_type));

          i += token_len - 1;
        }
      }

      return tokens;
    }
  };

  class Evaluator {
  public:
    static Expression* evaluate(Expression* expr) {
      const std::type_info& id = typeid(*expr);
      if(id == typeid(CallFunction)) {
        auto call_fun = (CallFunction*)expr;
        auto name = call_fun->name;
        if(name == "print") {
          std::cout << (evaluate(call_fun->args[0]))->lisp_str() << std::endl;
          return new Nil();
        }
        else if(name == "list") {
          auto args = call_fun->args;
          for(size_t i = 0 ; i < args.size() ; i++) {
            args[i] = evaluate(args[i]);
          }
          return new List(args);
        }
      }

      return expr;
    }
  };
}

int main() {
  using namespace std;

  string code;
  //code.reserve(1024);

  char ch;
  while((ch = cin.get()) != std::char_traits<char>::eof()) {
    code.push_back(ch);
  }

  Lisp::Parser parser;
  auto exprs = parser.parse(code);

  for(size_t i = 0 ; i < exprs.size() ; i++) {
    exprs[i] = Lisp::Evaluator::evaluate(exprs[i]);
  }

  // fake GC
  for(auto expr : objects) {
    delete expr;
  }

  return 0;
}
<|endoftext|>


<commit_before>/* BSD 3-Clause License:
 * Copyright (c) 2018, bitsofcotton.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 *
 *    Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 *    Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation or other materials provided with the distribution.
 *    Neither the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#if !defined(_LWORD_)

#include "corpus.hh"

using std::vector;
using std::map;
using std::lower_bound;
using std::sort;
using std::unique;
using std::cerr;
using std::endl;
using std::flush;
using std::max;
using std::min;

template <typename T> class word_t {
public:
  T   str;
  int count;
  word_t() {
    str   = T();
    count = 0;
  }
  ~word_t() {
  }
  word_t(const word_t<T>& other) {
    *this = other;
  }
  word_t& operator = (const word_t<T>& other) {
    str    = other.str;
    count  = other.count;
    return *this;
  }
  bool operator < (const word_t<T>& x1) const {
    return (count < x1.count) || (count == x1.count && str < x1.str);
  }
};

template <typename T> class gram_t {
public:
  T           str;
  vector<int> ptr0;
  vector<int> ptr1;
  gram_t() {
    this->str  = T();
    this->ptr0 = vector<int>();
    this->ptr1 = vector<int>();
  }
  ~gram_t() {
    ;
  }
  gram_t(const gram_t<T>& x) {
    *this = x;
  }
  gram_t& operator = (const gram_t<T>& x) {
    str  = x.str;
    ptr0 = x.ptr0;
    ptr1 = x.ptr1;
    return *this;
  }
  bool operator < (const gram_t<T>& x1) const {
    return str < x1.str;
  }
};

template <typename T, typename U> class lword {
public:
  lword();
  ~lword();
  void init(const int& loop, const int& mthresh, const int& Mthresh);

  const vector<word_t<U> >& compute(const U& input);
private:
  vector<T>                   dict0;
  vector<vector<gram_t<U> > > dicts;
  vector<word_t<U> >          words;

  int mthresh;
  int Mthresh;

  void makeBigram(const U& input);
  void constructNwords();

  bool       isin(const U& key);
  gram_t<U>& find(const U& key);
  void       assign(const gram_t<U>& val);
};

template <typename T, typename U> lword<T, U>::lword() {
  init(60, 2, 2);
}

template <typename T, typename U> lword<T, U>::~lword() {
  // already freed in another places.
  ;
}

template <typename T, typename U> void lword<T, U>::init(const int& loop, const int& mthresh, const int& Mthresh) {
  this->mthresh = mthresh;
  this->Mthresh = Mthresh;
/*
  this->dict0   = vector<T>();
  this->dicts   = vector<vector<gram_t<U> > >();
*/
  this->dicts.resize(loop, vector<gram_t<U> >());
//  this->words   = vector<word_t<U> >();
  return;
}

template <typename T, typename U> bool lword<T, U>::isin(const U& key) {
  assert(key.size() < dicts.size());
  const vector<gram_t<U> >& dict(dicts[key.size()]);
  gram_t<U> key0;
  key0.str = key;
  auto p(lower_bound(dict.begin(), dict.end(), key0));
  return dict.begin() <= p && p < dict.end() && p->str == key;
}

template <typename T, typename U> gram_t<U>& lword<T, U>::find(const U& key) {
  static gram_t<U> dummy;
  assert(key.size() < dicts.size());
  vector<gram_t<U> >& dict(dicts[key.size()]);
  gram_t<U> key0;
  key0.str = key;
  auto p(lower_bound(dict.begin(), dict.end(), key0));
  if(p < dict.begin() || dict.end() <= p || p->str != key) {
    assert(0 && "slipping find.");
    return dummy;
  }
  return *p;
}

template <typename T, typename U> void lword<T, U>::assign(const gram_t<U>& val) {
  assert(val.str.size() < dicts.size());
  vector<gram_t<U> >& dict(dicts[val.str.size()]);
  auto p(lower_bound(dict.begin(), dict.end(), val));
  if(val.ptr0.size()) {
    // delete duplicates:
    gram_t<U> work;
    work.str = val.str;
    // XXX can spped up with sorting.
    for(int i = 0; i < val.ptr0.size(); i ++) {
      bool flag(false);
      for(int j = 0; j < work.ptr0.size(); j ++)
        if(work.ptr0[j] == val.ptr0[i] &&
           work.ptr1[j] == val.ptr1[i]) {
          flag = true;
          break;
        }
      if(flag)
        continue;
      work.ptr0.push_back(val.ptr0[i]);
      work.ptr1.push_back(val.ptr1[i]);
    }
    sort(work.ptr0.begin(), work.ptr0.end());
    sort(work.ptr1.begin(), work.ptr1.end());
    if(p < dict.begin() || dict.end() <= p || p->str != work.str) {
      dict.push_back(work);
      sort(dict.begin(), dict.end());
    } else
      *p = work;
  } else if(dict.begin() <= p && p < dict.end() && p->str == val.str)
    dict.erase(p);
  return;
}

template <typename T, typename U> const vector<word_t<U> >& lword<T, U>::compute(const U& input) {
  makeBigram(input);
  constructNwords();
  for(auto itr = dicts.begin(); itr != dicts.end(); ++ itr)
    for(auto itr2 = itr->begin(); itr2 != itr->end(); ++ itr2) {
      word_t<U> work;
      work.count = itr2->ptr0.size();
      if(!work.count)
        continue;
      work.str   = itr2->str;
      bool flag(false);
      for(int i = 0; i < words.size(); i ++)
        if(work.str == words[i].str) {
          flag = true;
          break;
        }
      if(flag) continue;
      words.push_back(work);
    }
  sort(words.begin(), words.end());
  return words;
}

template <typename T, typename U> void lword<T, U>::makeBigram(const U& input) {
  map<U, vector<int> > mapw;
  for(int i = 1; i < input.size(); i ++) {
    U work;
    work += T(input[i - 1]);
    work += T(input[i]);
    mapw[work].push_back(i);
    if(!binary_search(dict0.begin(), dict0.end(), input[i])) {
      dict0.push_back(input[i]);
      sort(dict0.begin(), dict0.end());
    }
  }
  for(auto itr = mapw.begin(); itr != mapw.end(); ++ itr) {
    gram_t<U> work;
    work.str = itr->first;
    for(auto itr2 = itr->second.begin(); itr2 != itr->second.end(); ++ itr2) {
      work.ptr0.push_back(*itr2 - 1);
      work.ptr1.push_back(*itr2);
    }
    assign(work);
  }
  return;
}

template <typename T, typename U> void lword<T, U>::constructNwords() {
  int i;
  for(i = 2; i < dicts.size(); i ++) {
    cerr << i << flush;
    map<U, vector<int> > map0;
    map<U, vector<int> > map1;
    map<U, vector<int> > dmap;
    for(auto itr = dicts[i].begin(); itr != dicts[i].end(); ++ itr) {
      cerr << "." << flush;
      const gram_t<U>& idxkey(*itr);
      for(auto itr2 = dict0.begin(); itr2 != dict0.end(); ++ itr2) {
        U key2;
        for(int j = 1; j < idxkey.str.size(); j ++)
          key2 += idxkey.str[j];
        key2 += T(*itr2);
        if(!isin(key2))
          continue;
        const gram_t<U>& idxkey2(find(key2));
        U workkey(idxkey.str);
        workkey += *itr2;
        if(isin(workkey))
          continue;
        vector<int> idxwork[4];
        for(int j = 0; j < 4; j ++)
          idxwork[j] = vector<int>();
        int tt = 0;
        int ss = 0;
        while(tt < idxkey2.ptr0.size() && ss < idxkey.ptr0.size()) {
          if(idxkey2.ptr1[tt] == idxkey.ptr1[ss] + 1) {
            idxwork[0].push_back(idxkey.ptr0[ss]);
            idxwork[1].push_back(idxkey2.ptr1[tt]);
            idxwork[2].push_back(ss);
            idxwork[3].push_back(tt);
            ss ++;
            tt ++;
          } else if(idxkey2.ptr1[tt] > idxkey.ptr1[ss])
            ss ++;
          else
            tt ++;
        }
        if(idxwork[0].size() < Mthresh)
          continue;
        const int diff(min( idxkey.ptr0.size(), idxkey2.ptr0.size()) - idxwork[0].size());
        const int diffM(max(idxkey.ptr0.size(), idxkey2.ptr0.size()) - idxwork[0].size());
        if(diff < 0 || mthresh < diffM)
          continue;
        map0[workkey].insert(map0[workkey].end(), idxwork[0].begin(), idxwork[0].end());
        map1[workkey].insert(map1[workkey].end(), idxwork[1].begin(), idxwork[1].end());
        dmap[idxkey.str].insert(dmap[idxkey.str].end(), idxwork[2].begin(), idxwork[2].end());
        dmap[key2].insert(dmap[key2].end(), idxwork[3].begin(), idxwork[3].end());
      }
    }
    // delete this stage garbage.
    for(auto itr = dmap.begin(); itr != dmap.end(); ++ itr) {
      sort(itr->second.begin(), itr->second.end());
      const gram_t<U>& before(find(itr->first));
            gram_t<U>  after(before);
      after.ptr0 = vector<int>();
      after.ptr1 = vector<int>();
      for(int j = 0; j < before.ptr1.size(); j ++)
        if(!binary_search(itr->second.begin(), itr->second.end(), j)) {
          after.ptr0.push_back(before.ptr0[j]);
          after.ptr1.push_back(before.ptr1[j]);
        }
      assign(after);
    }
    // construct next stage.
    for(auto itr = map0.begin(); itr != map0.end(); ++ itr) {
      gram_t<U> work;
      work.str  = itr->first;
      work.ptr0 = itr->second;
      work.ptr1 = map1[itr->first];
      assign(work);
    }
    cerr << endl;
  }
  return;
}

// some functions.
template <typename T> vector<T> cutText(const T& input, const vector<T>& eliminate0, const vector<T>& delimiter0, const bool& f_sort = false) {
  vector<T> delimiter(delimiter0);
  vector<T> eliminate(eliminate0);
  sort(delimiter.begin(), delimiter.end());
  sort(eliminate.begin(), eliminate.end());
  delimiter.erase(unique(delimiter.begin(), delimiter.end()), delimiter.end());
  eliminate.erase(unique(eliminate.begin(), eliminate.end()), eliminate.end());
  vector<T> result;
  T         workbuf;
  for(int i = 0; i < input.size(); i ++) {
    workbuf += input[i];
    for(int j = 0; j < delimiter.size(); j ++)
      if(workbuf.size() >= delimiter[j].size() &&
         workbuf.substr(workbuf.size() - delimiter[j].size(), delimiter[j].size()) == delimiter[j]) {
        if(workbuf.size() - delimiter[j].size())
          result.push_back(workbuf.substr(0, workbuf.size() - delimiter[j].size()));
        workbuf = T();
        goto next;
      }
    for(int j = 0; j < eliminate.size(); j ++)
      if(workbuf.size() >= eliminate[j].size() &&
        workbuf.substr(workbuf.size() - eliminate[j].size(), eliminate[j].size()) == eliminate[j]) {
        workbuf = workbuf.substr(0, workbuf.size() - eliminate[j].size());
        break;
      }
   next:
    ;
  }
  if(workbuf.size())
    result.push_back(workbuf);
  if(f_sort)
    sort(result.begin(), result.end());
  return result;
}

template <typename T, typename U> Eigen::Matrix<T, Eigen::Dynamic, 1> countWords(const U& orig, const vector<U>& words) {
  Eigen::Matrix<T, Eigen::Dynamic, 1> result(words.size());
  for(int i = 0; i < result.size(); i ++)
    result[i] = T(0);
  for(int i = 0; i < orig.size(); i ++) {
    const U work(orig.substr(i, orig.size() - i - 1));
    for(int j = 0; j < words.size(); j ++)
      if(equalStrClip<U>(work, words[j]) && work.size() >= words[j].size())
        result[j] = T(1);
  }
  return result;
}

template <typename T, typename U> vector<int> pseudoWordsBalance(const vector<U>& orig, const vector<U>& words0, int nloop = - 1) {
  cerr << "pseudoWordsBalance : " << orig.size() << ", " << words0.size() << flush;
  vector<U> words(words0);
  sort(words.begin(), words.end());
  words.erase(unique(words.begin(), words.end()), words.end());

  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> result(words.size(), orig.size());
  for(int i = 0; i < orig.size(); i ++)
    result.col(i) = countWords<T, U>(orig[i], words);

  vector<int> vres;
  if(nloop <= 0)
    nloop = result.cols();

  for(int i = 0; i < min(int(result.cols()), nloop); i ++) {
    vector<pair<T, int> > scores;
    for(int j = 0; j < result.cols(); j ++)
      scores.push_back(make_pair(- result.col(j).dot(result.col(j)), j));
    sort(scores.begin(), scores.end());
    if(scores[0].first == T(0))
      break;
    const int& idx(scores[0].second);
    vres.push_back(idx);
    for(int k = 0; k < result.rows(); k ++)
      if(result(k, idx) != T(0))
        result.row(k) *= T(0);
    T sum(0);
    for(int j = 0; j < result.rows(); j ++)
      sum += result.row(j).dot(result.row(j));
    cerr << ":" << sum << flush;
  }
  cerr << endl;
  return vres;
}

#define _LWORD_
#endif

<commit_msg>Delete lword.hh<commit_after><|endoftext|>


<commit_before>#include <QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}
<commit_msg>Set org name and app name<commit_after>#include <QApplication>
#include "mainwindow.h"

const QString APP_ORGNAME = "PepperNote";
const QString APP_APPNAME = "PepperNote";

int main(int argc, char *argv[])
{
    QCoreApplication::setOrganizationName(APP_ORGNAME);
    QCoreApplication::setApplicationName(APP_APPNAME);

    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}
<|endoftext|>


<commit_before>37730beb-ad58-11e7-9920-ac87a332f658<commit_msg>updated some files<commit_after>37dc0840-ad58-11e7-b0c1-ac87a332f658<|endoftext|>


<commit_before>/*
    Copyright (C) 2015 Jolla Ltd.
    Contact: Aaron McCarthy <aaron.mccarthy@jollamobile.com>

    This file is part of geoclue-hybris.

    Geoclue-hybris is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License.
*/

#include <QtCore/QCoreApplication>
#include <QtCore/QLoggingCategory>
#include <QtDBus/QDBusConnection>

#include "hybrisprovider.h"

#include <locationsettings.h>

#include <unistd.h>
#include <sys/types.h>
#include <grp.h>
#include <errno.h>

int main(int argc, char *argv[])
{
    uid_t realUid;
    uid_t effectiveUid;
    uid_t savedUid;

#if QT_VERSION >= QT_VERSION_CHECK(5, 3, 0)
    QCoreApplication::setSetuidAllowed(true);
#endif
    QLoggingCategory::setFilterRules(QStringLiteral("geoclue.provider.hybris.debug=false\n"
                                                    "geoclue.provider.hybris.nmea.debug=false\n"
                                                    "geoclue.provider.hybris.position.debug=false"));
    QCoreApplication a(argc, argv);

    int result = getresuid(&realUid, &effectiveUid, &savedUid);
    if (result == -1)
        qFatal("Failed to get process uids, %s", strerror(errno));

    gid_t supplementaryGroups[NGROUPS_MAX];
    int numberGroups = getgroups(NGROUPS_MAX, supplementaryGroups);
    if (numberGroups == -1)
        qFatal("Failed to get supplementary groups, %s", strerror(errno));

    if (numberGroups + 1 > NGROUPS_MAX)
        qFatal("Too many supplementary groups");

    group *group = getgrnam("gps");
    if (!group)
        qFatal("Failed to get id of gps group, %s", strerror(errno));

    supplementaryGroups[numberGroups++] = group->gr_gid;

#if GEOCLUE_ANDROID_GPS_INTERFACE == 2
    group = getgrnam("net_raw");
    if (group) {
        if (numberGroups + 1 > NGROUPS_MAX)
            qWarning("Too many supplementary groups, can't add net_raw");
        else
            supplementaryGroups[numberGroups++] = group->gr_gid;
    }
#endif

    numberGroups = setgroups(numberGroups, supplementaryGroups);
    if (numberGroups == -1)
        qFatal("Failed to set supplementary groups, %s", strerror(errno));

#if GEOCLUE_ANDROID_GPS_INTERFACE != 2
    // Drop privileges.
    result = setuid(realUid);
    if (result == -1)
        qFatal("Failed to set process uid to %d, %s", realUid, strerror(errno));
#endif

    QDBusConnection session = QDBusConnection::sessionBus();
    LocationSettings settings;
    HybrisProvider provider;
    provider.setLocationSettings(&settings);
    if (!session.registerObject(QStringLiteral("/org/freedesktop/Geoclue/Providers/Hybris"), &provider))
        qFatal("Failed to register object /org/freedesktop/Geoclue/Providers/Hybris");
    if (!session.registerService(QStringLiteral("org.freedesktop.Geoclue.Providers.Hybris")))
        qFatal("Failed to register service org.freedesktop.Geoclue.Providers.Hybris");

    return a.exec();
}
<commit_msg>[geoclue-provider-hybris] fix permissions with Android 7 based devices. JB#40615<commit_after>/*
    Copyright (C) 2015 Jolla Ltd.
    Contact: Aaron McCarthy <aaron.mccarthy@jollamobile.com>

    This file is part of geoclue-hybris.

    Geoclue-hybris is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License.
*/

#include <QtCore/QCoreApplication>
#include <QtCore/QLoggingCategory>
#include <QtDBus/QDBusConnection>

#include "hybrisprovider.h"

#include <locationsettings.h>

#include <unistd.h>
#include <sys/types.h>
#include <grp.h>
#include <errno.h>

int main(int argc, char *argv[])
{
    uid_t realUid;
    uid_t effectiveUid;
    uid_t savedUid;

#if QT_VERSION >= QT_VERSION_CHECK(5, 3, 0)
    QCoreApplication::setSetuidAllowed(true);
#endif
    QLoggingCategory::setFilterRules(QStringLiteral("geoclue.provider.hybris.debug=false\n"
                                                    "geoclue.provider.hybris.nmea.debug=false\n"
                                                    "geoclue.provider.hybris.position.debug=false"));
    QCoreApplication a(argc, argv);

    int result = getresuid(&realUid, &effectiveUid, &savedUid);
    if (result == -1)
        qFatal("Failed to get process uids, %s", strerror(errno));

    gid_t supplementaryGroups[NGROUPS_MAX];
    int numberGroups = getgroups(NGROUPS_MAX, supplementaryGroups);
    if (numberGroups == -1)
        qFatal("Failed to get supplementary groups, %s", strerror(errno));

    if (numberGroups + 1 > NGROUPS_MAX)
        qFatal("Too many supplementary groups");

    group *group = getgrnam("gps");
    if (!group)
        qFatal("Failed to get id of gps group, %s", strerror(errno));

    supplementaryGroups[numberGroups++] = group->gr_gid;

#if GEOCLUE_ANDROID_GPS_INTERFACE >= 2
    group = getgrnam("net_raw");
    if (group) {
        if (numberGroups + 1 > NGROUPS_MAX)
            qWarning("Too many supplementary groups, can't add net_raw");
        else
            supplementaryGroups[numberGroups++] = group->gr_gid;
    }
#endif

    numberGroups = setgroups(numberGroups, supplementaryGroups);
    if (numberGroups == -1)
        qFatal("Failed to set supplementary groups, %s", strerror(errno));

#if GEOCLUE_ANDROID_GPS_INTERFACE == 1
    // Drop privileges.
    result = setuid(realUid);
    if (result == -1)
        qFatal("Failed to set process uid to %d, %s", realUid, strerror(errno));
#endif

    QDBusConnection session = QDBusConnection::sessionBus();
    LocationSettings settings;
    HybrisProvider provider;
    provider.setLocationSettings(&settings);
    if (!session.registerObject(QStringLiteral("/org/freedesktop/Geoclue/Providers/Hybris"), &provider))
        qFatal("Failed to register object /org/freedesktop/Geoclue/Providers/Hybris");
    if (!session.registerService(QStringLiteral("org.freedesktop.Geoclue.Providers.Hybris")))
        qFatal("Failed to register service org.freedesktop.Geoclue.Providers.Hybris");

    return a.exec();
}
<|endoftext|>


<commit_before>7978812b-2749-11e6-b3c1-e0f84713e7b8<commit_msg>Deal with it<commit_after>79871668-2749-11e6-8f6c-e0f84713e7b8<|endoftext|>


<commit_before>295e332b-2748-11e6-b5e6-e0f84713e7b8<commit_msg>update testing<commit_after>296db819-2748-11e6-b1fe-e0f84713e7b8<|endoftext|>


<commit_before>#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <map>

void parse_data(std::ifstream &instream_data, std::vector <std::vector <std::string> >& vec_data,
	std::map<std::string, std::vector <std::vector <std::string> > >& map_data){
	int count=0;
	while (instream_data){
		std::string s;
	    if (!getline( instream_data, s )){
	    	break;
	    }
	    std::istringstream ss( s );
	    std::vector <std::string> record;
	    while (ss){
	      std::string s;
	      if (!getline( ss, s, ',' )){
	      	break;
	      }
	      record.push_back( s );
	    }
	    vec_data.push_back(record);
	    std::string full_name= vec_data[count][1];
	    std::string modified_name="";
	    int x=0;
	    while(x<full_name.size()){
	    	if(full_name[x]!='\\'){
	    		modified_name.push_back(full_name[x]);
	    	}else{
	    		modified_name.pop_back();
	    		break;
	    	}
	    	x++;
	    }
		map_data.insert(std::make_pair(modified_name, vec_data));
		count++;
	}
}

int main(){
	std::vector <std::vector <std::string> > data;
	std::map<std::string, std::vector <std::vector <std::string> > > map_player_salary;

	std::vector <std::vector <std::string> > pitcher_data;
	std::map<std::string, std::vector <std::vector <std::string> > > map_pitcher_player;

	std::vector <std::vector <std::string> > batter_data;
	std::map<std::string, std::vector <std::vector <std::string> > > map_batter_player;

	std::ifstream infile( "2017_MLB_Player_Salary_Info.md" );
	std::ifstream infile_pitcher( "2017_MLB_Pitcher_Info.md" );
	std::ifstream infile_batter( "2017_MLB_Batter_Info.md" );

	//parse_data for salary info
	parse_data(infile, data, map_player_salary);

	//test if player salary data works
	// for(int x=0; x<data.size(); x++){
	// 	if((data[x][21])!=""){
	// 		std::cout<<"Name: "<< data[x][1]<<" Salary: "<< data[x][21]<<std::endl;
	// 	}
	// }

	std::cout<<data.size()<<std::endl;
	if(map_player_salary.find("Zack Greinke")!=map_player_salary.end()){

		std::cout<< map_player_salary.find("Zack Greinke")->first<<std::endl;

		// std::cout<<"Jason Heyward's Salary: "<<map_player_salary.find("Jason Heyward")->second[3][21]<<std::endl;
		// std::cout<<"map works!!"<<std::endl;
	}

	// //parse data for pitcher info
	// parse_data(infile_pitcher, pitcher_data, map_pitcher_player);

	// // test if pitcher player data works
	// // for(int x=0; x<pitcher_data.size(); x++){
	// // 	if((pitcher_data[x][1])!="Name"){
	// // 		std::cout<<"Name: "<< pitcher_data[x][1]<<" ERA: "<< pitcher_data[x][8]<<std::endl;
	// // 	}
	// // }
	// if(map_pitcher_player.find("Tim Adleman")!=map_pitcher_player.end()){
	// 	std::cout<<"Tim Adleman's ERA: "<<map_pitcher_player.find("Tim Adleman")->second[1][8]<<std::endl;
	// 	// std::cout<<"Fernando Abad's ERA: "<<map_pitcher_player.find("Fernando Abad")->second[1][1]<<std::endl;
	// 	std::cout<<"map works!!"<<std::endl;
	// }

	// //parse data for batter info
	// parse_data(infile_batter, batter_data, map_batter_player);

	// //test if pitcher player data works
	// // for(int x=0; x<batter_data.size(); x++){
	// // 	if((batter_data[x][1])!="Name"){
	// // 		std::cout<<"Name: "<< batter_data[x][1]<<" BA: "<< batter_data[x][18]<<std::endl;
	// // 	}
	// // }
	// if(map_batter_player.find("Ryan Zimmerman")!=map_batter_player.end()){
	// 	std::cout<<"Ryan Zimmerman's BA: "<< map_batter_player.find("Ryan Zimmerman")->second[1][7]<<std::endl;
	// 	std::cout<<"map works!!"<<std::endl;
	// }

	return 0;
}
<commit_msg>Finished map container with correct structure<commit_after>#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <map>

void parse_data(std::ifstream &instream_data,std::map<std::string, std::vector <std::string> > & map_data){

	int count=0;
	while (instream_data){
		std::string s;
	    if (!getline( instream_data, s )){
	    	break;
	    }
	    std::istringstream ss( s );
	    std::vector <std::string> record;
	    while (ss){
	      std::string s;
	      if (!getline( ss, s, ',' )){
	      	break;
	      }
	      record.push_back( s );
	    }

	    std::string full_name= record[1];
	    std::string modified_name="";

	    int x=0;
	    while(x<full_name.size()){
	    	if(full_name[x]!='\\'){
	    		modified_name.push_back(full_name[x]);
	    	}else{
	    		modified_name.pop_back();
	    		break;
	    	}
	    	x++;
	    }
		map_data.insert(std::make_pair(modified_name, record));
		count++;
	}
}

int main(){
	std::map<std::string, std::vector <std::string> >  map_salary;
	std::map<std::string, std::vector <std::string> >  map_pitcher_player;
	std::map<std::string, std::vector <std::string> >  map_batter_player;

	std::ifstream infile( "2017_MLB_Player_Salary_Info.md" );
	std::ifstream infile_pitcher( "2017_MLB_Pitcher_Info.md" );
	std::ifstream infile_batter( "2017_MLB_Batter_Info.md" );

	//parse_data for salary info
	parse_data(infile, map_salary);
	if(map_salary.find("Yoenis Cespedes")!=map_salary.end()){
		std::cout<< "Yoenis Cespedes's Salary: "<< map_salary.find("Yoenis Cespedes")->second[21]<<std::endl;
	}

	//parse data for pitcher info
	parse_data(infile_pitcher, map_pitcher_player);
	if(map_pitcher_player.find("Tim Adleman")!=map_pitcher_player.end()){
		std::cout<<"Tim Adleman's ERA: "<<map_pitcher_player.find("Tim Adleman")->second[8]<<std::endl;
	}

	//parse data for batter info
	parse_data(infile_batter, map_batter_player);
	if(map_batter_player.find("Ryan Zimmerman")!=map_batter_player.end()){
		std::cout<<"Ryan Zimmerman's BA: "<< map_batter_player.find("Ryan Zimmerman")->second[18]<<std::endl;
		// std::cout<<"map works!!"<<std::endl;
	}

	return 0;
}
<|endoftext|>