<commit_before>#include "Player.h"
#include "SDL.h"
#include "InputHandler.h"

Player::Player(const LoaderParams* pParams) : SDLGameObject(pParams) { }

void Player::draw()
{
	SDLGameObject::draw();	//we now use SDLGameObject
}

void Player::update()
{
	m_velocity.setX(0);
	m_velocity.setY(0);

	m_acceleration.setX(0);
	m_acceleration.setY(0);

	handleInput();	//adding our function

	m_currentFrame = int(((SDL_GetTicks() / 100) % 6));

	SDLGameObject::update();
}

void Player::clean()
{
	//blank clean() function
}

void Player::handleInput()
{
	if (TheInputHandler::Instance()->joysticksInitialised())
	{
		//for analog sticks of the first joystick
		if ((TheInputHandler::Instance()->xvalue(0, 1) > 0) || (TheInputHandler::Instance()->xvalue(0, 1) < 0))
		{
			//if we are moving the player with analog stick while pressing Y
			//it will get an acceleration of 2 in that direction
			m_velocity.setX((float)1 * TheInputHandler::Instance()->xvalue(0, 1));
			if (TheInputHandler::Instance()->getButtonState(0, 3))	//Button 3(Yellow)
			{
				//give the player some acceleration
				m_acceleration.setX((float)2 * TheInputHandler::Instance()->xvalue(0, 1));
			}
		}

		if ((TheInputHandler::Instance()->yvalue(0, 1) > 0) || (TheInputHandler::Instance()->yvalue(0, 1) < 0))
		{
			m_velocity.setY((float)1 * TheInputHandler::Instance()->yvalue(0, 1));
			if (TheInputHandler::Instance()->getButtonState(0, 3))
			{
				m_acceleration.setY((float)2 * TheInputHandler::Instance()->yvalue(0,1));
			}
		}

		if ((TheInputHandler::Instance()->xvalue(0, 2) > 0) || (TheInputHandler::Instance()->xvalue(0, 2) < 0))
		{
			m_velocity.setX((float)1 * TheInputHandler::Instance()->xvalue(0, 2));
			if (TheInputHandler::Instance()->getButtonState(0, 3))
			{
				m_acceleration.setX((float)2 * TheInputHandler::Instance()->xvalue(0, 1));
			}
		}

		if ((TheInputHandler::Instance()->yvalue(0, 2) > 0) || (TheInputHandler::Instance()->yvalue(0, 2) < 0))
		{
			m_velocity.setY((float)1 * TheInputHandler::Instance()->yvalue(0, 2));
			if (TheInputHandler::Instance()->getButtonState(0, 3))
			{
				m_acceleration.setY((float)2 * TheInputHandler::Instance()->yvalue(0, 1));
			}
		}
		/*	Code as in the book
		//for buttons of the first joystick
		if (TheInputHandler::Instance()->getButtonState(0, 3))	//Button 3(Yellow)
		{
			//give the player some acceleration
			m_acceleration.setX(1);
		}
		*/
	}

	//check for mouse button input
	if (InputHandler::Instance()->getMouseButtonState(LEFT))
	{
		m_acceleration.setX(-3);
	}
	if (InputHandler::Instance()->getMouseButtonState(RIGHT))
	{
		m_acceleration.setX(3);
	}

	//check for mouse motion input

	Vector2D vec = TheInputHandler::Instance()->getMousePosition();

	m_velocity = (vec - m_position) / 100;
}<commit_msg>Disabled the mouse motion feature<commit_after>#include "Player.h"
#include "SDL.h"
#include "InputHandler.h"

Player::Player(const LoaderParams* pParams) : SDLGameObject(pParams) { }

void Player::draw()
{
	SDLGameObject::draw();	//we now use SDLGameObject
}

void Player::update()
{
	m_velocity.setX(0);
	m_velocity.setY(0);

	m_acceleration.setX(0);
	m_acceleration.setY(0);

	handleInput();	//adding our function

	m_currentFrame = int(((SDL_GetTicks() / 100) % 6));

	SDLGameObject::update();
}

void Player::clean()
{
	//blank clean() function
}

void Player::handleInput()
{
	if (TheInputHandler::Instance()->joysticksInitialised())
	{
		//for analog sticks of the first joystick
		if ((TheInputHandler::Instance()->xvalue(0, 1) > 0) || (TheInputHandler::Instance()->xvalue(0, 1) < 0))
		{
			//if we are moving the player with analog stick while pressing Y
			//it will get an acceleration of 2 in that direction
			m_velocity.setX((float)1 * TheInputHandler::Instance()->xvalue(0, 1));
			if (TheInputHandler::Instance()->getButtonState(0, 3))	//Button 3(Yellow)
			{
				//give the player some acceleration
				m_acceleration.setX((float)2 * TheInputHandler::Instance()->xvalue(0, 1));
			}
		}

		if ((TheInputHandler::Instance()->yvalue(0, 1) > 0) || (TheInputHandler::Instance()->yvalue(0, 1) < 0))
		{
			m_velocity.setY((float)1 * TheInputHandler::Instance()->yvalue(0, 1));
			if (TheInputHandler::Instance()->getButtonState(0, 3))
			{
				m_acceleration.setY((float)2 * TheInputHandler::Instance()->yvalue(0,1));
			}
		}

		if ((TheInputHandler::Instance()->xvalue(0, 2) > 0) || (TheInputHandler::Instance()->xvalue(0, 2) < 0))
		{
			m_velocity.setX((float)1 * TheInputHandler::Instance()->xvalue(0, 2));
			if (TheInputHandler::Instance()->getButtonState(0, 3))
			{
				m_acceleration.setX((float)2 * TheInputHandler::Instance()->xvalue(0, 1));
			}
		}

		if ((TheInputHandler::Instance()->yvalue(0, 2) > 0) || (TheInputHandler::Instance()->yvalue(0, 2) < 0))
		{
			m_velocity.setY((float)1 * TheInputHandler::Instance()->yvalue(0, 2));
			if (TheInputHandler::Instance()->getButtonState(0, 3))
			{
				m_acceleration.setY((float)2 * TheInputHandler::Instance()->yvalue(0, 1));
			}
		}
		/*	Code as in the book
		//for buttons of the first joystick
		if (TheInputHandler::Instance()->getButtonState(0, 3))	//Button 3(Yellow)
		{
			//give the player some acceleration
			m_acceleration.setX(1);
		}
		*/
	}

	//check for mouse button input
	if (InputHandler::Instance()->getMouseButtonState(LEFT))
	{
		m_acceleration.setX(-3);
	}
	if (InputHandler::Instance()->getMouseButtonState(RIGHT))
	{
		m_acceleration.setX(3);
	}

	//check for mouse motion input
	//commenting this feature as I don't want player to follow mouse
	//uncomment the following code to enable the feature
	/*

	Vector2D vec = TheInputHandler::Instance()->getMousePosition();

	m_velocity = (vec - m_position) / 100;

	*/
}<|endoftext|>


<commit_before><commit_msg>there's no point to that assign<commit_after><|endoftext|>


<commit_before>
#include "md2qm_observer.h"
#include <votca/csg/nblist.h>
#include <qmnblist.h>

MD2QMObserver::MD2QMObserver()
{}

MD2QMObserver::~MD2QMObserver()
{}

void MD2QMObserver::Initialize(QMTopology &qmtop, Property &opts)
{
    _qmtop = &qmtop;
    _save.Open(qmtop, _out, 'w');
}

void MD2QMObserver::BeginCG(Topology *top, Topology *top_atom)
{
    _qmtop->Initialize(*top);
}

/// evaluate current conformation

void MD2QMObserver::EvalConfiguration(Topology *top, Topology *top_atom)
{
    _qmtop->Update(*top);
    QMNBList &nblist = _qmtop->nblist();

    BeadList list1;
    Topology *toptmp = dynamic_cast<Topology*>(_qmtop);
    list1.Generate(*toptmp, "*");

    nblist.setCutoff(_cutoff);
    nblist.Generate(list1);
    _save.Save();

    print_nbs_to_file(_qmtop->nblist());

}

void MD2QMObserver::EndCG()
{
    _save.Close();
}

void MD2QMObserver::print_nbs_to_file(QMNBList &nblist){
    ofstream out_nbl;
    string out ;
    out = string("nbl_votca_") + lexical_cast<string> (_qmtop->getStep()) + string(".res");
    out_nbl.open(out.c_str());
    if(out_nbl!=0){
        out_nbl << "Neighbours, J(0), J_eff, rate, r_ij, abs(r_ij) [nm]" << endl;
        QMNBList::iterator iter;
        for (iter = nblist.begin(); iter != nblist.end(); ++iter) {
            out_nbl << "(" << (*iter)->first->getId() << "," << (*iter)->second->getId() << "): ";
            out_nbl << 0.0 << " " << 0.0 << " " << 0.0 << " ";
            out_nbl << (*iter)->r().getX() << " " << (*iter)->r().getY() << " " << (*iter)->r().getZ() << " ";
            out_nbl << " " << (*iter)->dist() << endl;
        }
    }
    out_nbl.close();
}

<commit_msg>removed output of res-files, usage of xmlwriter is recommended instead<commit_after>
#include "md2qm_observer.h"
#include <votca/csg/nblist.h>
#include <qmnblist.h>

MD2QMObserver::MD2QMObserver()
{}

MD2QMObserver::~MD2QMObserver()
{}

void MD2QMObserver::Initialize(QMTopology &qmtop, Property &opts)
{
    _qmtop = &qmtop;
    _save.Open(qmtop, _out, 'w');
}

void MD2QMObserver::BeginCG(Topology *top, Topology *top_atom)
{
    _qmtop->Initialize(*top);
}

/// evaluate current conformation

void MD2QMObserver::EvalConfiguration(Topology *top, Topology *top_atom)
{
    _qmtop->Update(*top);
    QMNBList &nblist = _qmtop->nblist();

    BeadList list1;
    Topology *toptmp = dynamic_cast<Topology*>(_qmtop);
    list1.Generate(*toptmp, "*");

    nblist.setCutoff(_cutoff);
    nblist.Generate(list1);
    _save.Save();

// Old stuff is now replaced by output of pairs.xml (xmlwriter calculator)
//
//    print_nbs_to_file(_qmtop->nblist());
}

void MD2QMObserver::EndCG()
{
    _save.Close();
}

// Old stuff is now replaced by output of pairs.xml (xmlwriter calculator)
//
//void MD2QMObserver::print_nbs_to_file(QMNBList &nblist){
//    ofstream out_nbl;
//    string out ;
//    out = string("nbl_votca_") + lexical_cast<string> (_qmtop->getStep()) + string(".res");
//    out_nbl.open(out.c_str());
//    if(out_nbl!=0){
//        out_nbl << "Neighbours, J(0), J_eff, rate, r_ij, abs(r_ij) [nm]" << endl;
//        QMNBList::iterator iter;
//        for (iter = nblist.begin(); iter != nblist.end(); ++iter) {
//            out_nbl << "(" << (*iter)->first->getId() << "," << (*iter)->second->getId() << "): ";
//            out_nbl << 0.0 << " " << 0.0 << " " << 0.0 << " ";
//            out_nbl << (*iter)->r().getX() << " " << (*iter)->r().getY() << " " << (*iter)->r().getZ() << " ";
//            out_nbl << " " << (*iter)->dist() << endl;
//        }
//    }
//    out_nbl.close();
//}

<|endoftext|>


<commit_before>#include "contact_input_bar.hh"
#include <iostream>
#include <regex>
using namespace std;

void ContactInputBar::confirm()
{
	if (!entry_name.validate()) return entry_name.grab_focus();
	if (!entry_phone.validate()) return entry_phone.grab_focus();
	string name = entry_name.get_text();
	string phone = entry_phone.get_text();
	entry_name.reset();
	entry_phone.reset();
	hide();
	_signal_ok.emit(name, phone);
}

void ContactInputBar::cancel()
{
	entry_name.reset();
	entry_phone.reset();
	hide();
	_signal_cancel.emit();
}

ContactInputBar::ContactInputBar()
{
	set_has_subtitle(false);
	pack_start(hbox);
	hbox.show();

	auto context = get_style_context();
	context->add_class("selection-mode");

	hbox.pack_start(btn_ok);
	btn_ok.show();

	pack_end(btn_cancel);
	btn_cancel.show();

	hbox.pack_start(label_name);
	hbox.pack_start(entry_name);
	hbox.pack_start(label_phone);
	hbox.pack_start(entry_phone);
	label_name.show();
	entry_name.show();
	label_phone.show();
	entry_phone.show();

	entry_name.validator([&](const string& s) {
		string name{s};
		name = regex_replace(name, regex{"\\s+"}, "");
		return (name != "");
	});

	entry_phone.validator([&](const string& s) {
		string phone{s};
		if (regex_match(phone, regex{".*\\s"})) return false;
		if (regex_match(phone, regex{"\\s.*"})) return false;
		if (regex_match(phone, regex{".*\\s{2,}.*"})) return false;
		phone = regex_replace(phone, regex{"^\\+"}, "");
		phone = regex_replace(phone, regex{"\\s+"}, "");
		return bool(regex_match(phone, regex{"\\d+"}));
	});

	btn_ok.signal_clicked().connect([&]() {
		confirm();
	});

	btn_cancel.signal_clicked().connect([&]() {
		cancel();
	});

	entry_name.signal_activate().connect([&]() { confirm(); });
	entry_phone.signal_activate().connect([&]() { confirm(); });
	entry_name.signal_cancel().connect([&]() { cancel(); });
	entry_phone.signal_cancel().connect([&]() { cancel(); });
}

void ContactInputBar::show(const string& name)
{
	HeaderBar::show();
	if (name == "") entry_name.grab_focus();
	else {
		entry_name.set_text(name);
		entry_phone.grab_focus();
	}
}

<commit_msg>better validator for name<commit_after>#include "contact_input_bar.hh"
#include <iostream>
#include <regex>
using namespace std;

void ContactInputBar::confirm()
{
	if (!entry_name.validate()) return entry_name.grab_focus();
	if (!entry_phone.validate()) return entry_phone.grab_focus();
	string name = entry_name.get_text();
	string phone = entry_phone.get_text();
	entry_name.reset();
	entry_phone.reset();
	hide();
	_signal_ok.emit(name, phone);
}

void ContactInputBar::cancel()
{
	entry_name.reset();
	entry_phone.reset();
	hide();
	_signal_cancel.emit();
}

ContactInputBar::ContactInputBar()
{
	set_has_subtitle(false);
	pack_start(hbox);
	hbox.show();

	auto context = get_style_context();
	context->add_class("selection-mode");

	hbox.pack_start(btn_ok);
	btn_ok.show();

	pack_end(btn_cancel);
	btn_cancel.show();

	hbox.pack_start(label_name);
	hbox.pack_start(entry_name);
	hbox.pack_start(label_phone);
	hbox.pack_start(entry_phone);
	label_name.show();
	entry_name.show();
	label_phone.show();
	entry_phone.show();

	entry_name.validator([&](const string& s) {
		string name{s};
		if (regex_match(name, regex{"\\s.*"})) return false;		// initial spaces
		if (regex_match(name, regex{".*\\s"})) return false;		// trailing spaces
		if (regex_match(name, regex{".*\\s{2,}.*"})) return false;	// multiple spaces
		return (name != "");
	});

	entry_phone.validator([&](const string& s) {
		string phone{s};
		if (regex_match(phone, regex{"\\s.*"})) return false;		// initial spaces
		if (regex_match(phone, regex{".*\\s"})) return false;		// trailing spaces
		if (regex_match(phone, regex{".*\\s{2,}.*"})) return false;	// multiple spaces
		phone = regex_replace(phone, regex{"^\\+"}, "");
		phone = regex_replace(phone, regex{"\\s+"}, "");
		return bool(regex_match(phone, regex{"\\d+"}));
	});

	btn_ok.signal_clicked().connect([&]() {
		confirm();
	});

	btn_cancel.signal_clicked().connect([&]() {
		cancel();
	});

	entry_name.signal_activate().connect([&]() { confirm(); });
	entry_phone.signal_activate().connect([&]() { confirm(); });
	entry_name.signal_cancel().connect([&]() { cancel(); });
	entry_phone.signal_cancel().connect([&]() { cancel(); });
}

void ContactInputBar::show(const string& name)
{
	HeaderBar::show();
	if (name == "") entry_name.grab_focus();
	else {
		entry_name.set_text(name);
		entry_phone.grab_focus();
	}
}

<|endoftext|>


<commit_before>#include "llvm/ADT/StringMap.h"

#include <string>
#include <vector>

namespace hooks {

/// NUM_KEYS - Calculate the size of a const char* array.
#define NUM_KEYS(Keys) sizeof(Keys) / sizeof(const char*)

// See http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
inline unsigned NextHighestPowerOf2 (unsigned i) {
  i |= i >> 1;
  i |= i >> 2;
  i |= i >> 4;
  i |= i >> 8;
  i |= i >> 16;
  i++;
  return i;
}

typedef std::vector<std::string> StrVec;
typedef llvm::StringMap<const char*> ArgMap;

/// ConvertToMAttrImpl - Common implementation of ConvertMArchToMAttr and
/// ConvertToMAttr. The optional Args parameter contains information about how
/// to transform special-cased values (for example, '-march=armv6' must be
/// forwarded as '-mattr=+v6').
std::string ConvertToMAttrImpl(const StrVec& Opts, const ArgMap* Args = 0) {
  std::string out("-mattr=");
  bool firstIter = true;

  for (StrVec::const_iterator B = Opts.begin(), E = Opts.end(); B!=E; ++B) {
    const std::string& Arg = *B;

    if (firstIter)
      firstIter = false;
    else
      out += ",";

    // Check if the argument is a special case.
    if (Args != 0) {
      ArgMap::const_iterator I = Args->find(Arg);

      if (I != Args->end()) {
        out += '+';
        out += I->getValue();
        continue;
      }
    }

    // Convert 'no-foo' to '-foo'.
    if (Arg.find("no-") == 0 && Arg[3] != 0) {
      out += '-';
      out += Arg.c_str() + 3;
    }
    // Convert 'foo' to '+foo'.
    else {
      out += '+';
      out += Arg;
    }
  }

  return out;
}

// -march values that need to be special-cased.
const char* MArchKeysARM[] = { "armv4t", "armv5t", "armv5te", "armv6",
                               "armv6-m", "armv6t2", "armv7-a", "armv7-m" };
const char* MArchValuesARM[] = { "v4t", "v5t", "v5te", "v6", "v6m", "v6t2",
                                 "v7a", "v7m" };
const unsigned MArchNumKeysARM = NUM_KEYS(MArchKeysARM);
const unsigned MArchMapSize = NextHighestPowerOf2(MArchNumKeysARM);

void FillInArgMap(ArgMap& Args, const char* Keys[],
                  const char* Values[], unsigned NumKeys)
{
  for (unsigned i = 0; i < NumKeys; ++i) {
    // Explicit cast to StringRef here is necessary to pick up the right
    // overload.
    Args.GetOrCreateValue(llvm::StringRef(Keys[i]), Values[i]);
  }
}

/// ConvertMArchToMAttr - Convert -march from the gcc dialect to
/// something llc can understand.
std::string ConvertMArchToMAttr(const StrVec& Opts) {
  static ArgMap MArchMap(MArchMapSize);
  static bool StaticDataInitialized = false;

  if (!StaticDataInitialized) {
    FillInArgMap(MArchMap, MArchKeysARM, MArchValuesARM, MArchNumKeysARM);
    StaticDataInitialized = true;
  }

  return ConvertToMAttrImpl(Opts, &MArchMap);
}

// -mcpu values that need to be special-cased.
const char* MCpuKeysPPC[] = { "G3", "G4", "G5", "powerpc", "powerpc64"};
const char* MCpuValuesPPC[] = { "g3", "g4", "g5", "ppc", "ppc64"};
const unsigned MCpuNumKeysPPC = NUM_KEYS(MCpuKeysPPC);
const unsigned MCpuMapSize = NextHighestPowerOf2(MCpuNumKeysPPC);

/// ConvertMCpu - Convert -mcpu value from the gcc to the llc dialect.
std::string ConvertMCpu(const char* Val) {
  static ArgMap MCpuMap(MCpuMapSize);
  static bool StaticDataInitialized = false;

  if (!StaticDataInitialized) {
    FillInArgMap(MCpuMap, MCpuKeysPPC, MCpuValuesPPC, MCpuNumKeysPPC);
    StaticDataInitialized = true;
  }

  std::string ret = "-mcpu=";
  ArgMap::const_iterator I = MCpuMap.find(Val);
  if (I != MCpuMap.end()) {
    return ret + I->getValue();
  }
  return ret + Val;
}

// -mfpu values that need to be special-cased.
const char* MFpuKeysARM[] = { "vfp", "vfpv3",
                              "vfpv3-fp16", "vfpv3-d16", "vfpv3-d16-fp16",
                              "neon", "neon-fp16" };
const char* MFpuValuesARM[] = { "vfp2", "vfp3",
                                "+vfp3,+fp16", "+vfp3,+d16", "+vfp3,+d16,+fp16",
                                "+neon", "+neon,+neonfp" };
const unsigned MFpuNumKeysARM = NUM_KEYS(MFpuKeysARM);
const unsigned MFpuMapSize = NextHighestPowerOf2(MFpuNumKeysARM);

/// ConvertMFpu - Convert -mfpu value from the gcc to the llc dialect.
std::string ConvertMFpu(const char* Val) {
  static ArgMap MFpuMap(MFpuMapSize);
  static bool StaticDataInitialized = false;

  if (!StaticDataInitialized) {
    FillInArgMap(MFpuMap, MFpuKeysARM, MFpuValuesARM, MFpuNumKeysARM);
    StaticDataInitialized = true;
  }

  std::string ret = "-mattr=";
  ArgMap::const_iterator I = MFpuMap.find(Val);
  if (I != MFpuMap.end()) {
    return ret + I->getValue();
  }
  return ret + '+' + Val;
}

/// ConvertToMAttr - Convert '-mfoo' and '-mno-bar' to '-mattr=+foo,-bar'.
std::string ConvertToMAttr(const StrVec& Opts) {
  return ConvertToMAttrImpl(Opts);
}

}
<commit_msg>llvmc: Support -march arguments that should be forwarded to llc as -mcpu.<commit_after>#include "llvm/ADT/StringMap.h"

#include <string>
#include <vector>

namespace hooks {

/// NUM_KEYS - Calculate the size of a const char* array.
#define NUM_KEYS(Keys) sizeof(Keys) / sizeof(const char*)

// See http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
inline unsigned NextHighestPowerOf2 (unsigned i) {
  i |= i >> 1;
  i |= i >> 2;
  i |= i >> 4;
  i |= i >> 8;
  i |= i >> 16;
  i++;
  return i;
}

typedef std::vector<std::string> StrVec;
typedef llvm::StringMap<const char*> ArgMap;

/// ConvertToMAttrImpl - Common implementation of ConvertMArchToMAttr and
/// ConvertToMAttr. The optional Args parameter contains information about how
/// to transform special-cased values (for example, '-march=armv6' must be
/// forwarded as '-mattr=+v6').
std::string ConvertToMAttrImpl(const StrVec& Opts,
                               const ArgMap* Args = 0,
                               const ArgMap* MCpuArgs = 0) {
  std::string mattr("-mattr=");
  std::string mcpu("-mcpu=");
  bool mattrTouched = false;
  bool mcpuTouched = false;
  bool firstIter = true;

  for (StrVec::const_iterator B = Opts.begin(), E = Opts.end(); B!=E; ++B) {
    const std::string& Arg = *B;

    if (firstIter)
      firstIter = false;
    else
      mattr += ",";

    // Check if the argument is a special case.
    if (Args != 0) {
      ArgMap::const_iterator I = Args->find(Arg);

      if (I != Args->end()) {
        mattr += '+';
        mattr += I->getValue();
        continue;
      }
    }

    // Check if the argument should be forwarded to -mcpu instead of -mattr.
    if (MCpuArgs != 0 && !mcpuTouched) {
      ArgMap::const_iterator I = MCpuArgs->find(Arg);

      if (I != MCpuArgs->end()) {
        mcpuTouched = true;
        mcpu += I->getValue();
        continue;
      }
    }

    // Convert 'no-foo' to '-foo'.
    if (Arg.find("no-") == 0 && Arg[3] != 0) {
      mattr += '-';
      mattr += Arg.c_str() + 3;
    }
    // Convert 'foo' to '+foo'.
    else {
      mattr += '+';
      mattr += Arg;
    }
  }

  std::string out;
  if (mattrTouched)
    out += mattr;
  if (mcpuTouched)
    out += (mattrTouched ? " " : "") + mcpu;

  return out;
}

// -march values that need to be special-cased.
const char* MArchKeysARM[] = { "armv4t", "armv5t", "armv5te", "armv6",
                               "armv6-m", "armv6t2", "armv7-a", "armv7-m" };
const char* MArchValuesARM[] = { "v4t", "v5t", "v5te", "v6", "v6m", "v6t2",
                                 "v7a", "v7m" };
const unsigned MArchNumKeysARM = NUM_KEYS(MArchKeysARM);
const unsigned MArchMapSize = NextHighestPowerOf2(MArchNumKeysARM);

// -march values that should be forwarded as -mcpu
const char* MArchMCpuKeysARM[] = { "iwmmxt", "ep9312" };
const char* MArchMCpuValuesARM[] = { "iwmmxt", "ep9312"};
const unsigned MArchMCpuNumKeysARM = NUM_KEYS(MArchMCpuKeysARM);
const unsigned MArchMCpuMapSize = NextHighestPowerOf2(MArchMCpuNumKeysARM);

void FillInArgMap(ArgMap& Args, const char* Keys[],
                  const char* Values[], unsigned NumKeys)
{
  for (unsigned i = 0; i < NumKeys; ++i) {
    // Explicit cast to StringRef here is necessary to pick up the right
    // overload.
    Args.GetOrCreateValue(llvm::StringRef(Keys[i]), Values[i]);
  }
}

/// ConvertMArchToMAttr - Convert -march from the gcc dialect to
/// something llc can understand.
std::string ConvertMArchToMAttr(const StrVec& Opts) {
  static ArgMap MArchMap(MArchMapSize);
  static ArgMap MArchMCpuMap(MArchMapSize);
  static bool StaticDataInitialized = false;

  if (!StaticDataInitialized) {
    FillInArgMap(MArchMap, MArchKeysARM, MArchValuesARM, MArchNumKeysARM);
    FillInArgMap(MArchMCpuMap, MArchMCpuKeysARM,
                 MArchMCpuValuesARM, MArchMCpuNumKeysARM);
    StaticDataInitialized = true;
  }

  return ConvertToMAttrImpl(Opts, &MArchMap, &MArchMCpuMap);
}

// -mcpu values that need to be special-cased.
const char* MCpuKeysPPC[] = { "G3", "G4", "G5", "powerpc", "powerpc64"};
const char* MCpuValuesPPC[] = { "g3", "g4", "g5", "ppc", "ppc64"};
const unsigned MCpuNumKeysPPC = NUM_KEYS(MCpuKeysPPC);
const unsigned MCpuMapSize = NextHighestPowerOf2(MCpuNumKeysPPC);

/// ConvertMCpu - Convert -mcpu value from the gcc to the llc dialect.
std::string ConvertMCpu(const char* Val) {
  static ArgMap MCpuMap(MCpuMapSize);
  static bool StaticDataInitialized = false;

  if (!StaticDataInitialized) {
    FillInArgMap(MCpuMap, MCpuKeysPPC, MCpuValuesPPC, MCpuNumKeysPPC);
    StaticDataInitialized = true;
  }

  std::string ret = "-mcpu=";
  ArgMap::const_iterator I = MCpuMap.find(Val);
  if (I != MCpuMap.end()) {
    return ret + I->getValue();
  }
  return ret + Val;
}

// -mfpu values that need to be special-cased.
const char* MFpuKeysARM[] = { "vfp", "vfpv3",
                              "vfpv3-fp16", "vfpv3-d16", "vfpv3-d16-fp16",
                              "neon", "neon-fp16" };
const char* MFpuValuesARM[] = { "vfp2", "vfp3",
                                "+vfp3,+fp16", "+vfp3,+d16", "+vfp3,+d16,+fp16",
                                "+neon", "+neon,+neonfp" };
const unsigned MFpuNumKeysARM = NUM_KEYS(MFpuKeysARM);
const unsigned MFpuMapSize = NextHighestPowerOf2(MFpuNumKeysARM);

/// ConvertMFpu - Convert -mfpu value from the gcc to the llc dialect.
std::string ConvertMFpu(const char* Val) {
  static ArgMap MFpuMap(MFpuMapSize);
  static bool StaticDataInitialized = false;

  if (!StaticDataInitialized) {
    FillInArgMap(MFpuMap, MFpuKeysARM, MFpuValuesARM, MFpuNumKeysARM);
    StaticDataInitialized = true;
  }

  std::string ret = "-mattr=";
  ArgMap::const_iterator I = MFpuMap.find(Val);
  if (I != MFpuMap.end()) {
    return ret + I->getValue();
  }
  return ret + '+' + Val;
}

/// ConvertToMAttr - Convert '-mfoo' and '-mno-bar' to '-mattr=+foo,-bar'.
std::string ConvertToMAttr(const StrVec& Opts) {
  return ConvertToMAttrImpl(Opts);
}

}
<|endoftext|>


<commit_before>// Copyright (c) 2000-2019, Heiko Bauke
// 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 and/or other materials provided
//     with the distribution.
//
//   * Neither the name of the copyright holder nor 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 HOLDERS 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 TRNG_GENERATE_CANONICAL_HPP)

#define TRNG_GENERATE_CANONICAL_HPP

#include <type_traits>
#include <trng/cuda.hpp>
#include <trng/limits.hpp>
#include <trng/math.hpp>
#include <trng/utility.hpp>

namespace trng {

  template<typename result_type, typename R>
  TRNG_CUDA_ENABLE result_type generate_canonical(R &);

  namespace detail {

    template<typename result_type, typename R>
    TRNG_CUDA_ENABLE inline
        typename std::enable_if<math::numeric_limits<result_type>::is_iec559, result_type>::type
        generate_canonical_impl(R &r, result_type) {
      return utility::uniformoo<result_type>(r);
    }

    template<typename result_type, typename R>
    TRNG_CUDA_ENABLE inline
        typename std::enable_if<math::numeric_limits<result_type>::is_integer,
                                result_type>::type
        generate_canonical_impl(R &r, result_type) {
      return static_cast<result_type>(
          math::floor(utility::uniformco<double>(r) *
                      (static_cast<double>(R::max) - static_cast<double>(R::min) + 1.0)));
    }

  }  // namespace detail

  template<typename result_type, typename R>
  TRNG_CUDA_ENABLE result_type generate_canonical(R &g) {
    return detail::generate_canonical_impl(g, result_type());
  }

}  // namespace trng

#endif
<commit_msg>minor clean-up for portability<commit_after>// Copyright (c) 2000-2019, Heiko Bauke
// 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 and/or other materials provided
//     with the distribution.
//
//   * Neither the name of the copyright holder nor 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 HOLDERS 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 TRNG_GENERATE_CANONICAL_HPP)

#define TRNG_GENERATE_CANONICAL_HPP

#include <type_traits>
#include <trng/cuda.hpp>
#include <trng/limits.hpp>
#include <trng/math.hpp>
#include <trng/utility.hpp>

namespace trng {

  template<typename result_type, typename R>
  TRNG_CUDA_ENABLE result_type generate_canonical(R &);

  namespace detail {

    template<typename result_type, typename R>
    TRNG_CUDA_ENABLE inline
        typename std::enable_if<std::is_floating_point<result_type>::value, result_type>::type
        generate_canonical_impl(R &r, result_type) {
      return utility::uniformoo<result_type>(r);
    }

    template<typename result_type, typename R>
    TRNG_CUDA_ENABLE inline
        typename std::enable_if<math::numeric_limits<result_type>::is_integer,
                                result_type>::type
        generate_canonical_impl(R &r, result_type) {
      return static_cast<result_type>(
          math::floor(utility::uniformco<double>(r) *
                      (static_cast<double>(R::max) - static_cast<double>(R::min) + 1.0)));
    }

  }  // namespace detail

  template<typename result_type, typename R>
  TRNG_CUDA_ENABLE result_type generate_canonical(R &g) {
    return detail::generate_canonical_impl(g, result_type());
  }

}  // namespace trng

#endif
<|endoftext|>


<commit_before>//
// Tests for haplotype score functions
//

#include "catch.hpp"
#include "haplotypes.hpp"

namespace unittest {
using namespace std;

xg::XG::ThreadMapping make_xg_mapping(int64_t node_id) {
  xg::XG::ThreadMapping to_return;
  to_return.node_id = node_id;
  to_return.is_reverse = false;
  return to_return;
}

//TODO test paths that aren't in the index

TEST_CASE("We can score haplotypes using gPBWT", "[haplo-score][xg]") {
  //     / [3] \   / [6] \         ###################
  //  [1]       [4]-------[7]      # baby test graph #
  //    \\ [2] /   \ [5] /         ###################
  //    \__[8]
  string graph_json = R"(
  {"node":[{"id":1,"sequence":"GATT"},
  {"id":2,"sequence":"ACA"},
  {"id":3,"sequence":"TT"},
  {"id":4,"sequence":"ACA"},
  {"id":5,"sequence":"TTAG"},
  {"id":6,"sequence":"GG"},
  {"id":7,"sequence":"ATTACA"},
  {"id":8,"sequence":"AAAA"}],
  "edge":[{"to":2,"from":1},
  {"to":3,"from":1},
  {"to":4,"from":2},
  {"to":4,"from":3},
  {"to":5,"from":4},
  {"to":6,"from":4},
  {"to":7,"from":4},
  {"to":7,"from":5},
  {"to":7,"from":6}
  ]}
  )";

  vector<xg::XG::ThreadMapping> tm = {
    make_xg_mapping(1), // dummy for 1-based indexing
    make_xg_mapping(1),
    make_xg_mapping(2),
    make_xg_mapping(3),
    make_xg_mapping(4),
    make_xg_mapping(5),
    make_xg_mapping(6),
    make_xg_mapping(7),
    make_xg_mapping(8)
  };

  vector<xg::XG::ThreadMapping> t1_2_4_5_7 = {tm[1], tm[2], tm[4], tm[5], tm[7]};
  vector<xg::XG::ThreadMapping> t1_3_4_5_7 = {tm[1], tm[3], tm[4], tm[5], tm[7]};
  vector<xg::XG::ThreadMapping> t1_2_4_6_7 = {tm[1], tm[2], tm[4], tm[6], tm[7]};
  vector<xg::XG::ThreadMapping> t1_3_4_6_7 = {tm[1], tm[3], tm[4], tm[6], tm[7]};
  vector<xg::XG::ThreadMapping> t1_2_4_d_7 = {tm[1], tm[2], tm[4], tm[7]};
  vector<xg::XG::ThreadMapping> t1_3_4_d_7 = {tm[1], tm[3], tm[4], tm[7]};

  vector<xg::XG::ThreadMapping> query = {tm[1], tm[2], tm[4]};

  vector<vector<xg::XG::ThreadMapping> > haplotypes_to_add = {
    t1_2_4_5_7,
    t1_2_4_5_7,
    t1_2_4_5_7,
    t1_2_4_5_7,
    t1_2_4_5_7,
    t1_3_4_5_7,
    t1_3_4_5_7,
    t1_2_4_5_7,
    t1_2_4_d_7,
    t1_2_4_d_7,
    t1_3_4_6_7,
    t1_3_4_6_7
  };

  vector<string> haplotype_names = {
    "t0",
    "t1",
    "t2",
    "t3",
    "t4",
    "t5",
    "t6",
    "t7",
    "t8",
    "t9",
    "t10",
    "t11"
  };

  // Load the JSON
  vg::Graph proto_graph;
  json2pb(proto_graph, graph_json.c_str(), graph_json.size());
  // Build the xg index
  xg::XG xg_index(proto_graph);
  xg_index.insert_threads_into_dag(haplotypes_to_add, haplotype_names);
  haplotypes_to_add.clear();
  // build a score-penalty memo: recombination penalty 9, population size 12
  haplo::haploMath::RRMemo memo(9, 12);

  // initial node
  haplo::hDP_graph_accessor ga1(xg_index, tm[1], memo);
  haplo::haplo_DP_column hdpc(ga1);
  REQUIRE(hdpc.get_sizes()[0] == 12);
  REQUIRE(hdpc.current_sum() <= 0);
  double last_sum = hdpc.current_sum();

  // second node
  haplo::hDP_graph_accessor ga12(xg_index, tm[1], tm[2], memo);
  hdpc.extend(ga12);
  REQUIRE(hdpc.get_sizes().size() == 1);
  REQUIRE(hdpc.current_sum() < last_sum);
  REQUIRE(hdpc.get_sizes()[0] == 8);
  last_sum = hdpc.current_sum();

  // third node
  haplo::hDP_graph_accessor ga24(xg_index, tm[2], tm[4], memo);
  hdpc.extend(ga24);
  REQUIRE(hdpc.get_sizes().size() == 2);
  REQUIRE(hdpc.get_sizes()[0] == 4);
  REQUIRE(hdpc.get_sizes()[1] == 8);
  REQUIRE(hdpc.current_sum() > last_sum);

  last_sum = hdpc.current_sum();

  pair<double, bool> result_from_thread = haplo::haplo_DP::score(query, xg_index, memo);
  REQUIRE(result_from_thread.second);
  REQUIRE(fabs(result_from_thread.first - last_sum) < 0.000001);

  // recognize nonexistent edge

  haplo::hDP_graph_accessor ga14(xg_index, tm[1], tm[4], memo);
  REQUIRE(!ga14.has_edge());

  vector<xg::XG::ThreadMapping> missing_edge = {tm[1], tm[4]};
  REQUIRE(haplo::haplo_DP::score(missing_edge, xg_index, memo).second);

  vector<xg::XG::ThreadMapping> empty_node = {tm[1], tm[8]};
  REQUIRE(!(haplo::haplo_DP::score(empty_node, xg_index, memo).second));
}

TEST_CASE("We can score haplotypes using GBWT", "[haplo-score][gbwt]") {
  gbwt::DynamicGBWT* gbwt_index = new gbwt::DynamicGBWT;

  vector<gbwt::node_type> tm = {
    gbwt::Node::encode(1, false), // dummy for 1-based indexing
    gbwt::Node::encode(1, false),
    gbwt::Node::encode(2, false),
    gbwt::Node::encode(3, false),
    gbwt::Node::encode(4, false),
    gbwt::Node::encode(5, false),
    gbwt::Node::encode(6, false),
    gbwt::Node::encode(7, false),
    gbwt::Node::encode(8, false),
  };

  vector<gbwt::node_type> t1_2_4_5_7 = {tm[1], tm[2], tm[4], tm[5], tm[7], gbwt::ENDMARKER};
  vector<gbwt::node_type> t1_3_4_5_7 = {tm[1], tm[3], tm[4], tm[5], tm[7], gbwt::ENDMARKER};
  vector<gbwt::node_type> t1_2_4_6_7 = {tm[1], tm[2], tm[4], tm[6], tm[7], gbwt::ENDMARKER};
  vector<gbwt::node_type> t1_3_4_6_7 = {tm[1], tm[3], tm[4], tm[6], tm[7], gbwt::ENDMARKER};
  vector<gbwt::node_type> t1_2_4_d_7 = {tm[1], tm[2], tm[4], tm[7], gbwt::ENDMARKER};
  vector<gbwt::node_type> t1_3_4_d_7 = {tm[1], tm[3], tm[4], tm[7], gbwt::ENDMARKER};

  vector<vector<gbwt::node_type> > haplotypes_to_add = {
    t1_2_4_5_7,
    t1_2_4_5_7,
    t1_2_4_5_7,
    t1_2_4_5_7,
    t1_2_4_5_7,
    t1_3_4_5_7,
    t1_3_4_5_7,
    t1_2_4_5_7,
    t1_2_4_d_7,
    t1_2_4_d_7,
    t1_3_4_6_7,
    t1_3_4_6_7
  };

  vector<size_t> node_lengths = {
    0, // dummy for 1-based indexing
    4,
    3,
    2,
    3,
    4,
    2,
    6,
    3
  };

  for(size_t i = 0; i < haplotypes_to_add.size(); i++) {
    gbwt_index->insert(haplotypes_to_add[i]);
  }

  REQUIRE(gbwt_index->nodeSize(tm[1]) == 12);
  REQUIRE(gbwt_index->nodeSize(tm[2]) == 8);
  REQUIRE(gbwt_index->nodeSize(tm[1]) == 12);

  haplo::haploMath::RRMemo memo(9, 12);

  // initial node
  haplo::hDP_gbwt_graph_accessor<gbwt::DynamicGBWT> ga1(*gbwt_index, tm[1], node_lengths[1], memo);
  haplo::haplo_DP_column hdpc(ga1);
  REQUIRE(hdpc.get_sizes()[0] == 12);
  REQUIRE(hdpc.current_sum() <= 0);
  double last_sum = hdpc.current_sum();

  // second node
  haplo::hDP_gbwt_graph_accessor<gbwt::DynamicGBWT> ga12(*gbwt_index, tm[1], tm[2], node_lengths[2], memo);
  hdpc.extend(ga12);
  REQUIRE(hdpc.get_sizes().size() == 1);
  REQUIRE(hdpc.current_sum() < last_sum);
  REQUIRE(hdpc.get_sizes()[0] == 8);
  last_sum = hdpc.current_sum();

  // third node
  haplo::hDP_gbwt_graph_accessor<gbwt::DynamicGBWT> ga24(*gbwt_index, tm[2], tm[4], node_lengths[4], memo);
  hdpc.extend(ga24);
  REQUIRE(hdpc.get_sizes().size() == 2);
  REQUIRE(hdpc.get_sizes()[0] == 4);
  REQUIRE(hdpc.get_sizes()[1] == 8);
  REQUIRE(hdpc.current_sum() > last_sum);

  last_sum = hdpc.current_sum();

  vector<gbwt::node_type> query_nodes = {tm[1], tm[2], tm[4]};
  vector<size_t> query_node_lengths = {node_lengths[1], node_lengths[2], node_lengths[4]};
  haplo::gbwt_thread_t query(query_nodes, query_node_lengths);

  pair<double, bool> result_from_thread = haplo::haplo_DP::score(query, *gbwt_index, memo);
  REQUIRE(fabs(result_from_thread.first - last_sum) < 0.000001);

  // recognize nonexistent edge
  haplo::hDP_gbwt_graph_accessor<gbwt::DynamicGBWT> ga14(*gbwt_index, tm[1], tm[4], 3, memo);
  REQUIRE(!ga14.has_edge());

  query_nodes = {tm[1], tm[4]};
  query_node_lengths = {node_lengths[1], node_lengths[4]};
  haplo::gbwt_thread_t missing_edge(query_nodes, query_node_lengths);

  REQUIRE(haplo::haplo_DP::score(missing_edge, *gbwt_index, memo).second);

  query_nodes = {tm[1], tm[8]};
  query_node_lengths = {node_lengths[1], node_lengths[8]};
  haplo::gbwt_thread_t empty_node(query_nodes, query_node_lengths);
  REQUIRE(!(haplo::haplo_DP::score(empty_node, *gbwt_index, memo).second));
  delete gbwt_index;
}
}<commit_msg>Silent GBWT construction in tests<commit_after>//
// Tests for haplotype score functions
//

#include "catch.hpp"
#include "haplotypes.hpp"

namespace unittest {
using namespace std;

xg::XG::ThreadMapping make_xg_mapping(int64_t node_id) {
  xg::XG::ThreadMapping to_return;
  to_return.node_id = node_id;
  to_return.is_reverse = false;
  return to_return;
}

//TODO test paths that aren't in the index

TEST_CASE("We can score haplotypes using gPBWT", "[haplo-score][xg]") {
  //     / [3] \   / [6] \         ###################
  //  [1]       [4]-------[7]      # baby test graph #
  //    \\ [2] /   \ [5] /         ###################
  //    \__[8]
  string graph_json = R"(
  {"node":[{"id":1,"sequence":"GATT"},
  {"id":2,"sequence":"ACA"},
  {"id":3,"sequence":"TT"},
  {"id":4,"sequence":"ACA"},
  {"id":5,"sequence":"TTAG"},
  {"id":6,"sequence":"GG"},
  {"id":7,"sequence":"ATTACA"},
  {"id":8,"sequence":"AAAA"}],
  "edge":[{"to":2,"from":1},
  {"to":3,"from":1},
  {"to":4,"from":2},
  {"to":4,"from":3},
  {"to":5,"from":4},
  {"to":6,"from":4},
  {"to":7,"from":4},
  {"to":7,"from":5},
  {"to":7,"from":6}
  ]}
  )";

  vector<xg::XG::ThreadMapping> tm = {
    make_xg_mapping(1), // dummy for 1-based indexing
    make_xg_mapping(1),
    make_xg_mapping(2),
    make_xg_mapping(3),
    make_xg_mapping(4),
    make_xg_mapping(5),
    make_xg_mapping(6),
    make_xg_mapping(7),
    make_xg_mapping(8)
  };

  vector<xg::XG::ThreadMapping> t1_2_4_5_7 = {tm[1], tm[2], tm[4], tm[5], tm[7]};
  vector<xg::XG::ThreadMapping> t1_3_4_5_7 = {tm[1], tm[3], tm[4], tm[5], tm[7]};
  vector<xg::XG::ThreadMapping> t1_2_4_6_7 = {tm[1], tm[2], tm[4], tm[6], tm[7]};
  vector<xg::XG::ThreadMapping> t1_3_4_6_7 = {tm[1], tm[3], tm[4], tm[6], tm[7]};
  vector<xg::XG::ThreadMapping> t1_2_4_d_7 = {tm[1], tm[2], tm[4], tm[7]};
  vector<xg::XG::ThreadMapping> t1_3_4_d_7 = {tm[1], tm[3], tm[4], tm[7]};

  vector<xg::XG::ThreadMapping> query = {tm[1], tm[2], tm[4]};

  vector<vector<xg::XG::ThreadMapping> > haplotypes_to_add = {
    t1_2_4_5_7,
    t1_2_4_5_7,
    t1_2_4_5_7,
    t1_2_4_5_7,
    t1_2_4_5_7,
    t1_3_4_5_7,
    t1_3_4_5_7,
    t1_2_4_5_7,
    t1_2_4_d_7,
    t1_2_4_d_7,
    t1_3_4_6_7,
    t1_3_4_6_7
  };

  vector<string> haplotype_names = {
    "t0",
    "t1",
    "t2",
    "t3",
    "t4",
    "t5",
    "t6",
    "t7",
    "t8",
    "t9",
    "t10",
    "t11"
  };

  // Load the JSON
  vg::Graph proto_graph;
  json2pb(proto_graph, graph_json.c_str(), graph_json.size());
  // Build the xg index
  xg::XG xg_index(proto_graph);
  xg_index.insert_threads_into_dag(haplotypes_to_add, haplotype_names);
  haplotypes_to_add.clear();
  // build a score-penalty memo: recombination penalty 9, population size 12
  haplo::haploMath::RRMemo memo(9, 12);

  // initial node
  haplo::hDP_graph_accessor ga1(xg_index, tm[1], memo);
  haplo::haplo_DP_column hdpc(ga1);
  REQUIRE(hdpc.get_sizes()[0] == 12);
  REQUIRE(hdpc.current_sum() <= 0);
  double last_sum = hdpc.current_sum();

  // second node
  haplo::hDP_graph_accessor ga12(xg_index, tm[1], tm[2], memo);
  hdpc.extend(ga12);
  REQUIRE(hdpc.get_sizes().size() == 1);
  REQUIRE(hdpc.current_sum() < last_sum);
  REQUIRE(hdpc.get_sizes()[0] == 8);
  last_sum = hdpc.current_sum();

  // third node
  haplo::hDP_graph_accessor ga24(xg_index, tm[2], tm[4], memo);
  hdpc.extend(ga24);
  REQUIRE(hdpc.get_sizes().size() == 2);
  REQUIRE(hdpc.get_sizes()[0] == 4);
  REQUIRE(hdpc.get_sizes()[1] == 8);
  REQUIRE(hdpc.current_sum() > last_sum);

  last_sum = hdpc.current_sum();

  pair<double, bool> result_from_thread = haplo::haplo_DP::score(query, xg_index, memo);
  REQUIRE(result_from_thread.second);
  REQUIRE(fabs(result_from_thread.first - last_sum) < 0.000001);

  // recognize nonexistent edge

  haplo::hDP_graph_accessor ga14(xg_index, tm[1], tm[4], memo);
  REQUIRE(!ga14.has_edge());

  vector<xg::XG::ThreadMapping> missing_edge = {tm[1], tm[4]};
  REQUIRE(haplo::haplo_DP::score(missing_edge, xg_index, memo).second);

  vector<xg::XG::ThreadMapping> empty_node = {tm[1], tm[8]};
  REQUIRE(!(haplo::haplo_DP::score(empty_node, xg_index, memo).second));
}

TEST_CASE("We can score haplotypes using GBWT", "[haplo-score][gbwt]") {

  gbwt::Verbosity::set(gbwt::Verbosity::SILENT);
  gbwt::DynamicGBWT* gbwt_index = new gbwt::DynamicGBWT;

  vector<gbwt::node_type> tm = {
    gbwt::Node::encode(1, false), // dummy for 1-based indexing
    gbwt::Node::encode(1, false),
    gbwt::Node::encode(2, false),
    gbwt::Node::encode(3, false),
    gbwt::Node::encode(4, false),
    gbwt::Node::encode(5, false),
    gbwt::Node::encode(6, false),
    gbwt::Node::encode(7, false),
    gbwt::Node::encode(8, false),
  };

  vector<gbwt::node_type> t1_2_4_5_7 = {tm[1], tm[2], tm[4], tm[5], tm[7], gbwt::ENDMARKER};
  vector<gbwt::node_type> t1_3_4_5_7 = {tm[1], tm[3], tm[4], tm[5], tm[7], gbwt::ENDMARKER};
  vector<gbwt::node_type> t1_2_4_6_7 = {tm[1], tm[2], tm[4], tm[6], tm[7], gbwt::ENDMARKER};
  vector<gbwt::node_type> t1_3_4_6_7 = {tm[1], tm[3], tm[4], tm[6], tm[7], gbwt::ENDMARKER};
  vector<gbwt::node_type> t1_2_4_d_7 = {tm[1], tm[2], tm[4], tm[7], gbwt::ENDMARKER};
  vector<gbwt::node_type> t1_3_4_d_7 = {tm[1], tm[3], tm[4], tm[7], gbwt::ENDMARKER};

  vector<vector<gbwt::node_type> > haplotypes_to_add = {
    t1_2_4_5_7,
    t1_2_4_5_7,
    t1_2_4_5_7,
    t1_2_4_5_7,
    t1_2_4_5_7,
    t1_3_4_5_7,
    t1_3_4_5_7,
    t1_2_4_5_7,
    t1_2_4_d_7,
    t1_2_4_d_7,
    t1_3_4_6_7,
    t1_3_4_6_7
  };

  vector<size_t> node_lengths = {
    0, // dummy for 1-based indexing
    4,
    3,
    2,
    3,
    4,
    2,
    6,
    3
  };

  for(size_t i = 0; i < haplotypes_to_add.size(); i++) {
    gbwt_index->insert(haplotypes_to_add[i]);
  }

  REQUIRE(gbwt_index->nodeSize(tm[1]) == 12);
  REQUIRE(gbwt_index->nodeSize(tm[2]) == 8);
  REQUIRE(gbwt_index->nodeSize(tm[1]) == 12);

  haplo::haploMath::RRMemo memo(9, 12);

  // initial node
  haplo::hDP_gbwt_graph_accessor<gbwt::DynamicGBWT> ga1(*gbwt_index, tm[1], node_lengths[1], memo);
  haplo::haplo_DP_column hdpc(ga1);
  REQUIRE(hdpc.get_sizes()[0] == 12);
  REQUIRE(hdpc.current_sum() <= 0);
  double last_sum = hdpc.current_sum();

  // second node
  haplo::hDP_gbwt_graph_accessor<gbwt::DynamicGBWT> ga12(*gbwt_index, tm[1], tm[2], node_lengths[2], memo);
  hdpc.extend(ga12);
  REQUIRE(hdpc.get_sizes().size() == 1);
  REQUIRE(hdpc.current_sum() < last_sum);
  REQUIRE(hdpc.get_sizes()[0] == 8);
  last_sum = hdpc.current_sum();

  // third node
  haplo::hDP_gbwt_graph_accessor<gbwt::DynamicGBWT> ga24(*gbwt_index, tm[2], tm[4], node_lengths[4], memo);
  hdpc.extend(ga24);
  REQUIRE(hdpc.get_sizes().size() == 2);
  REQUIRE(hdpc.get_sizes()[0] == 4);
  REQUIRE(hdpc.get_sizes()[1] == 8);
  REQUIRE(hdpc.current_sum() > last_sum);

  last_sum = hdpc.current_sum();

  vector<gbwt::node_type> query_nodes = {tm[1], tm[2], tm[4]};
  vector<size_t> query_node_lengths = {node_lengths[1], node_lengths[2], node_lengths[4]};
  haplo::gbwt_thread_t query(query_nodes, query_node_lengths);

  pair<double, bool> result_from_thread = haplo::haplo_DP::score(query, *gbwt_index, memo);
  REQUIRE(fabs(result_from_thread.first - last_sum) < 0.000001);

  // recognize nonexistent edge
  haplo::hDP_gbwt_graph_accessor<gbwt::DynamicGBWT> ga14(*gbwt_index, tm[1], tm[4], 3, memo);
  REQUIRE(!ga14.has_edge());

  query_nodes = {tm[1], tm[4]};
  query_node_lengths = {node_lengths[1], node_lengths[4]};
  haplo::gbwt_thread_t missing_edge(query_nodes, query_node_lengths);

  REQUIRE(haplo::haplo_DP::score(missing_edge, *gbwt_index, memo).second);

  query_nodes = {tm[1], tm[8]};
  query_node_lengths = {node_lengths[1], node_lengths[8]};
  haplo::gbwt_thread_t empty_node(query_nodes, query_node_lengths);
  REQUIRE(!(haplo::haplo_DP::score(empty_node, *gbwt_index, memo).second));
  delete gbwt_index;
}
}<|endoftext|>


<commit_before>/******************************************************************************\
* File:          svn.cpp
* Purpose:       Implementation of wxExSVN class
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
*
* Copyright (c) 1998-2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <wx/extension/svn.h>
#include <wx/extension/app.h> // for wxExApp
#include <wx/extension/configdialog.h>
#include <wx/extension/defs.h>
#include <wx/extension/stc.h>

#if wxUSE_GUI

wxExSTCEntryDialog* wxExSVN::m_STCEntryDialog = NULL;

wxExSVN::wxExSVN(int command_id, const wxString& fullpath)
  : m_Type(GetType(command_id))
  , m_FullPath(fullpath)
{
  Initialize();
}

wxExSVN::wxExSVN(wxExSVNType type, const wxString& fullpath)
  : m_Type(type)
  , m_FullPath(fullpath)
{
  Initialize();
}

wxStandardID wxExSVN::Execute(wxWindow* parent)
{
  const wxString svn_flags_name = wxString::Format("svn/flags%d", m_Type);
  const wxString svn_flags_contents = wxExApp::GetConfig(svn_flags_name);

  if (parent != NULL)
  {
    std::vector<wxExConfigItem> v;

    if (m_Type == SVN_COMMIT)
    {
      v.push_back(wxExConfigItem(
        _("Revision comment"),
        CONFIG_COMBOBOX,
        wxEmptyString,
        true)); // required
    }

    if (m_FullPath.empty() && m_Type != SVN_HELP)
    {
      v.push_back(wxExConfigItem(
        _("Base folder"),
        CONFIG_COMBOBOXDIR,
        wxEmptyString,
        true)); // required
    }

    // SVN_UPDATE and SVN_HELP have no flags to ask for.
    if (m_Type != SVN_UPDATE && m_Type != SVN_HELP)
    {
      wxExApp::SetConfig(_("Flags"), svn_flags_contents);
      v.push_back(wxExConfigItem(_("Flags")));
    }

    // Instead, SVN_HELP has an extra subcommand.
    if (m_Type == SVN_HELP)
    {
      v.push_back(wxExConfigItem(_("Subcommand")));
    }

    if (wxExConfigDialog(parent,
      wxExApp::GetConfig(),
      v,
      m_Caption).ShowModal() == wxID_CANCEL)
    {
      m_ReturnCode = wxID_CANCEL;
      return m_ReturnCode;
    }
  }

  const wxString cwd = wxGetCwd();

  wxString file;

  if (m_FullPath.empty())
  {
    wxSetWorkingDirectory(wxExApp::GetConfig(_("Base folder")));
  }
  else
  {
    file = " \"" + m_FullPath + "\"";
  }

  wxString comment;

  if (m_Type == SVN_COMMIT)
  {
    comment = " -m \"" + wxExApp::GetConfig(_("Revision comment")) + "\"";
  }

  wxString flags;
  wxString subcommand;

  if (m_Type == SVN_HELP)
  {
    subcommand = wxExApp::GetConfig(_("Subcommand"));

    if (!subcommand.empty())
    {
      subcommand = " " + subcommand;
    }
  }
  else
  {
    flags = wxExApp::GetConfig(_("Flags"));

    wxExApp::SetConfig(svn_flags_name, flags);

    m_CommandWithFlags = m_Command + " " + flags;

    if (!flags.empty())
    {
      flags += " ";
    }
  }

  const wxString command =
    "svn " + flags + m_Command + subcommand + comment + file;

  wxArrayString output;
  wxArrayString errors;
  m_Output.clear();

  if (wxExecute(
    command,
    output,
    errors) == -1)
  {
    m_ReturnCode = wxID_ABORT;
    return m_ReturnCode;
  }

  wxExApp::Log(command);

  if (m_FullPath.empty())
  {
    wxSetWorkingDirectory(cwd);
  }

  // First output the errors.
  for (size_t i = 0; i < errors.GetCount(); i++)
  {
    m_Output += errors[i] + "\n";
  }

  // Then the normal output, will be empty if there are errors.
  for (size_t j = 0; j < output.GetCount(); j++)
  {
    m_Output += output[j] + "\n";
  }

  return wxID_OK;
}

wxStandardID wxExSVN::ExecuteAndShowOutput(wxWindow* parent)
{
  Execute(parent);
  ShowOutput(parent);
  return m_ReturnCode;
}

wxExSVNType wxExSVN::GetType(int command_id) const
{
  switch (command_id)
  {
    case ID_EDIT_SVN_BLAME: return SVN_BLAME; break;
    case ID_EDIT_SVN_CAT: return SVN_CAT; break;
    case ID_EDIT_SVN_COMMIT: return SVN_COMMIT; break;
    case ID_EDIT_SVN_DIFF: return SVN_DIFF; break;
    case ID_EDIT_SVN_HELP: return SVN_HELP; break;
    case ID_EDIT_SVN_INFO: return SVN_INFO; break;
    case ID_EDIT_SVN_LOG: return SVN_LOG; break;
    case ID_EDIT_SVN_REVERT: return SVN_REVERT; break;
    case ID_EDIT_SVN_STAT: return SVN_STAT; break;
    case ID_EDIT_SVN_UPDATE: return SVN_UPDATE; break;
    default:
      wxFAIL;
      return SVN_STAT;
      break;
  }
}

void wxExSVN::Initialize()
{
  switch (m_Type)
  {
    case SVN_BLAME:  m_Caption = "SVN Blame"; break;
    case SVN_CAT:    m_Caption = "SVN Cat"; break;
    case SVN_COMMIT: m_Caption = "SVN Commit"; break;
    case SVN_DIFF:   m_Caption = "SVN Diff"; break;
    case SVN_HELP:   m_Caption = "SVN Help"; break;
    case SVN_INFO:   m_Caption = "SVN Info"; break;
    case SVN_LOG:    m_Caption = "SVN Log"; break;
    case SVN_REVERT: m_Caption = "SVN Revert"; break;
    case SVN_STAT:   m_Caption = "SVN Stat"; break;
    case SVN_UPDATE: m_Caption = "SVN Update"; break;
    default:
      wxFAIL;
      break;
  }

  m_Command = m_Caption.AfterFirst(' ').Lower();

  // Currently no flags, as no command was executed.
  m_CommandWithFlags = m_Command;

  m_Output.clear();
  m_ReturnCode = wxID_NONE;

  wxASSERT(wxExApp::GetConfig() != NULL);
}

void wxExSVN::ShowOutput(wxWindow* parent) const
{
  if (m_ReturnCode != wxID_OK)
  {
    return;
  }

  const wxString caption = m_Caption +
    (!m_FullPath.empty() ? " " + wxFileName(m_FullPath).GetFullName(): wxString(wxEmptyString));

  // Create a dialog for contents.
  if (m_STCEntryDialog == NULL)
  {
    m_STCEntryDialog = new wxExSTCEntryDialog(
      parent,
      caption,
      m_Output,
      wxEmptyString,
      wxOK,
      wxID_ANY,
      wxDefaultPosition, wxSize(575, 250));
  }
  else
  {
    m_STCEntryDialog->SetText(m_Output);
    m_STCEntryDialog->SetTitle(caption);

    // Reset a previous lexer.
    if (!m_STCEntryDialog->GetLexer().empty())
    {
      m_STCEntryDialog->SetLexer(wxEmptyString);
    }
  }

  // Add a lexer if we specified a path, asked for cat or blame
  // and there were no errors, and there is a lexer.
  if (
    !m_FullPath.empty() &&
    (m_Type == SVN_CAT || m_Type == SVN_BLAME) &&
     m_ReturnCode == 0)
  {
    const wxExFileName fn(m_FullPath);

    if (!fn.GetLexer().GetScintillaLexer().empty())
    {
      m_STCEntryDialog->SetLexer(fn.GetLexer().GetScintillaLexer());
    }
  }

  m_STCEntryDialog->Show();
}

#endif
<commit_msg>fill the output in case of error<commit_after>/******************************************************************************\
* File:          svn.cpp
* Purpose:       Implementation of wxExSVN class
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
*
* Copyright (c) 1998-2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <wx/extension/svn.h>
#include <wx/extension/app.h> // for wxExApp
#include <wx/extension/configdialog.h>
#include <wx/extension/defs.h>
#include <wx/extension/stc.h>

#if wxUSE_GUI

wxExSTCEntryDialog* wxExSVN::m_STCEntryDialog = NULL;

wxExSVN::wxExSVN(int command_id, const wxString& fullpath)
  : m_Type(GetType(command_id))
  , m_FullPath(fullpath)
{
  Initialize();
}

wxExSVN::wxExSVN(wxExSVNType type, const wxString& fullpath)
  : m_Type(type)
  , m_FullPath(fullpath)
{
  Initialize();
}

wxStandardID wxExSVN::Execute(wxWindow* parent)
{
  const wxString svn_flags_name = wxString::Format("svn/flags%d", m_Type);
  const wxString svn_flags_contents = wxExApp::GetConfig(svn_flags_name);

  if (parent != NULL)
  {
    std::vector<wxExConfigItem> v;

    if (m_Type == SVN_COMMIT)
    {
      v.push_back(wxExConfigItem(
        _("Revision comment"),
        CONFIG_COMBOBOX,
        wxEmptyString,
        true)); // required
    }

    if (m_FullPath.empty() && m_Type != SVN_HELP)
    {
      v.push_back(wxExConfigItem(
        _("Base folder"),
        CONFIG_COMBOBOXDIR,
        wxEmptyString,
        true)); // required
    }

    // SVN_UPDATE and SVN_HELP have no flags to ask for.
    if (m_Type != SVN_UPDATE && m_Type != SVN_HELP)
    {
      wxExApp::SetConfig(_("Flags"), svn_flags_contents);
      v.push_back(wxExConfigItem(_("Flags")));
    }

    // Instead, SVN_HELP has an extra subcommand.
    if (m_Type == SVN_HELP)
    {
      v.push_back(wxExConfigItem(_("Subcommand")));
    }

    m_ReturnCode = (wxStandardID)wxExConfigDialog(parent,
      wxExApp::GetConfig(),
      v,
      m_Caption).ShowModal();

    if (m_ReturnCode == wxID_CANCEL)
    {
      return m_ReturnCode;
    }
  }

  const wxString cwd = wxGetCwd();

  wxString file;

  if (m_FullPath.empty())
  {
    wxSetWorkingDirectory(wxExApp::GetConfig(_("Base folder")));
  }
  else
  {
    file = " \"" + m_FullPath + "\"";
  }

  wxString comment;

  if (m_Type == SVN_COMMIT)
  {
    comment = " -m \"" + wxExApp::GetConfig(_("Revision comment")) + "\"";
  }

  wxString flags;
  wxString subcommand;

  if (m_Type == SVN_HELP)
  {
    subcommand = wxExApp::GetConfig(_("Subcommand"));

    if (!subcommand.empty())
    {
      subcommand = " " + subcommand;
    }
  }
  else
  {
    flags = wxExApp::GetConfig(_("Flags"));

    wxExApp::SetConfig(svn_flags_name, flags);

    m_CommandWithFlags = m_Command + " " + flags;

    if (!flags.empty())
    {
      flags += " ";
    }
  }

  const wxString command =
    "svn " + flags + m_Command + subcommand + comment + file;

  wxArrayString output;
  wxArrayString errors;
  m_Output.clear();

  if (wxExecute(
    command,
    output,
    errors) == -1)
  {
    if (m_Output.empty())
    {
      m_Output = "Could not execute: " + command;
    }

    m_ReturnCode = wxID_ABORT;
    return m_ReturnCode;
  }

  wxExApp::Log(command);

  if (m_FullPath.empty())
  {
    wxSetWorkingDirectory(cwd);
  }

  // First output the errors.
  for (size_t i = 0; i < errors.GetCount(); i++)
  {
    m_Output += errors[i] + "\n";
  }

  // Then the normal output, will be empty if there are errors.
  for (size_t j = 0; j < output.GetCount(); j++)
  {
    m_Output += output[j] + "\n";
  }

  return wxID_OK;
}

wxStandardID wxExSVN::ExecuteAndShowOutput(wxWindow* parent)
{
  Execute(parent);
  ShowOutput(parent);
  return m_ReturnCode;
}

wxExSVNType wxExSVN::GetType(int command_id) const
{
  switch (command_id)
  {
    case ID_EDIT_SVN_BLAME: return SVN_BLAME; break;
    case ID_EDIT_SVN_CAT: return SVN_CAT; break;
    case ID_EDIT_SVN_COMMIT: return SVN_COMMIT; break;
    case ID_EDIT_SVN_DIFF: return SVN_DIFF; break;
    case ID_EDIT_SVN_HELP: return SVN_HELP; break;
    case ID_EDIT_SVN_INFO: return SVN_INFO; break;
    case ID_EDIT_SVN_LOG: return SVN_LOG; break;
    case ID_EDIT_SVN_REVERT: return SVN_REVERT; break;
    case ID_EDIT_SVN_STAT: return SVN_STAT; break;
    case ID_EDIT_SVN_UPDATE: return SVN_UPDATE; break;
    default:
      wxFAIL;
      return SVN_STAT;
      break;
  }
}

void wxExSVN::Initialize()
{
  switch (m_Type)
  {
    case SVN_BLAME:  m_Caption = "SVN Blame"; break;
    case SVN_CAT:    m_Caption = "SVN Cat"; break;
    case SVN_COMMIT: m_Caption = "SVN Commit"; break;
    case SVN_DIFF:   m_Caption = "SVN Diff"; break;
    case SVN_HELP:   m_Caption = "SVN Help"; break;
    case SVN_INFO:   m_Caption = "SVN Info"; break;
    case SVN_LOG:    m_Caption = "SVN Log"; break;
    case SVN_REVERT: m_Caption = "SVN Revert"; break;
    case SVN_STAT:   m_Caption = "SVN Stat"; break;
    case SVN_UPDATE: m_Caption = "SVN Update"; break;
    default:
      wxFAIL;
      break;
  }

  m_Command = m_Caption.AfterFirst(' ').Lower();

  // Currently no flags, as no command was executed.
  m_CommandWithFlags = m_Command;

  m_Output.clear();
  m_ReturnCode = wxID_NONE;

  wxASSERT(wxExApp::GetConfig() != NULL);
}

void wxExSVN::ShowOutput(wxWindow* parent) const
{
  switch (m_ReturnCode)
  {
    case wxID_CANCEL:
      break;

    case wxID_ABORT:
      wxMessageBox(m_Output);
      break;

    case wxID_OK:
    {
      const wxString caption = m_Caption +
        (!m_FullPath.empty() ? " " + wxFileName(m_FullPath).GetFullName(): wxString(wxEmptyString));

      // Create a dialog for contents.
      if (m_STCEntryDialog == NULL)
      {
        m_STCEntryDialog = new wxExSTCEntryDialog(
          parent,
          caption,
          m_Output,
          wxEmptyString,
          wxOK,
          wxID_ANY,
          wxDefaultPosition, wxSize(575, 250));
      }
      else
      {
        m_STCEntryDialog->SetText(m_Output);
        m_STCEntryDialog->SetTitle(caption);

        // Reset a previous lexer.
        if (!m_STCEntryDialog->GetLexer().empty())
        {
          m_STCEntryDialog->SetLexer(wxEmptyString);
        }
      }

      // Add a lexer if we specified a path, asked for cat or blame
      // and there is a lexer.
      if (
        !m_FullPath.empty() &&
        (m_Type == SVN_CAT || m_Type == SVN_BLAME))
      {
        const wxExFileName fn(m_FullPath);

        if (!fn.GetLexer().GetScintillaLexer().empty())
        {
          m_STCEntryDialog->SetLexer(fn.GetLexer().GetScintillaLexer());
        }
      }

      m_STCEntryDialog->Show();
    }
    break;

    default:
      wxFAIL;
      break;
  }
}

#endif
<|endoftext|>


<commit_before>/*
 The MIT License (MIT)

 Copyright (c) 2015 winlin

 Permission is hereby granted, free of charge, to any person obtaining a copy of
 this software and associated documentation files (the "Software"), to deal in
 the Software without restriction, including without limitation the rights to
 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 the Software, and to permit persons to whom the Software is furnished to do so,
 subject to the following conditions:

 The above copyright notice and this permission notice shall be included in all
 copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include <dlp_core.hpp>

#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <netdb.h>
#include <arpa/inet.h>

#include <map>
using namespace std;

#include <st.h>

// nginx also set to 512
#define SERVER_LISTEN_BACKLOG 512

DlpProcessTitle* dlp_process_title = new DlpProcessTitle();

bool st_initilaized = false;
int dlp_master_id = getpid();
std::map<st_thread_t, int> cache;

int dlp_generate_id()
{
    if (!st_initilaized) {
        return 0;
    }

    static int id = 100;

    int gid = id++;
    cache[st_thread_self()] = gid;
    return gid;
}

int dlp_get_id()
{
    if (st_initilaized) {
        return cache[st_thread_self()];
    }
    return 0;
}

vector<int> dlp_list_to_ints(string str_list)
{
    vector<int> ints;

    std::string p = str_list;
    dlp_verbose("parse string list: %s", p.c_str());

    size_t pos = string::npos;
    while ((pos = p.find(",")) != string::npos) {
        std::string value = p.substr(0, pos);
        if (!value.empty()) {
            dlp_verbose("int value: %s", value.c_str());
            ints.push_back(::atoi(value.c_str()));
        }
        p = p.substr(pos + 1);
    }

    if (!p.empty()) {
        dlp_verbose("int value: %s", p.c_str());
        ints.push_back(::atoi(p.c_str()));
    }

    dlp_verbose("string list parsed.");

    return ints;
}

int dlp_listen_tcp(int port, int& fd)
{
    int ret = ERROR_SUCCESS;

    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        ret = ERROR_SOCKET_LISTEN;
        dlp_error("create linux socket error. port=%d, ret=%d", port, ret);
        return ret;
    }
    dlp_verbose("create linux socket success. port=%d, fd=%d", port, fd);

    int reuse_socket = 1;
    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_socket, sizeof(int)) == -1) {
        ret = ERROR_SOCKET_LISTEN;
        dlp_error("setsockopt reuse-addr error. port=%d, ret=%d", port, ret);
        return ret;
    }
    dlp_verbose("setsockopt reuse-addr success. port=%d, fd=%d", port, fd);

    sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = INADDR_ANY;
    //addr.sin_addr.s_addr = inet_addr("0.0.0.0");
    if (bind(fd, (const sockaddr*)&addr, sizeof(sockaddr_in)) == -1) {
        ret = ERROR_SOCKET_LISTEN;
        dlp_error("bind socket error. port=%d, ret=%d", port, ret);
        return ret;
    }
    dlp_verbose("bind socket success. port=%d, fd=%d", port, fd);

    if (::listen(fd, SERVER_LISTEN_BACKLOG) == -1) {
        ret = ERROR_SOCKET_LISTEN;
        dlp_error("listen socket error. port=%d, ret=%d", port, ret);
        return ret;
    }
    dlp_verbose("listen socket success. port=%d, fd=%d", port, fd);

    return ret;
}

int dlp_st_init()
{
    int ret = ERROR_SUCCESS;

    // Select the best event system available on the OS. In Linux this is
    // epoll(). On BSD it will be kqueue.
    if (st_set_eventsys(ST_EVENTSYS_ALT) == -1) {
        ret = ERROR_ST_INITIALIZE;
        dlp_error("st_set_eventsys use %s failed. ret=%d", st_get_eventsys_name(), ret);
        return ret;
    }
    dlp_trace("st_set_eventsys to %s", st_get_eventsys_name());

    if(st_init() != 0){
        ret = ERROR_ST_INITIALIZE;
        dlp_error("st_init failed. ret=%d", ret);
        return ret;
    }
    dlp_trace("st_init success, use %s", st_get_eventsys_name());

    st_initilaized = true;
    dlp_generate_id();
    dlp_trace("st main thread, cid=%d", dlp_get_id());

    return ret;
}

string dlp_get_peer_ip(int fd)
{
    std::string ip;

    // discovery client information
    sockaddr_in addr;
    socklen_t addrlen = sizeof(addr);
    if (getpeername(fd, (sockaddr*)&addr, &addrlen) == -1) {
        return ip;
    }
    dlp_verbose("get peer name success.");

    // ip v4 or v6
    char buf[INET6_ADDRSTRLEN];
    memset(buf, 0, sizeof(buf));

    if ((inet_ntop(addr.sin_family, &addr.sin_addr, buf, sizeof(buf))) == NULL) {
        return ip;
    }
    dlp_verbose("get peer ip of client ip=%s, fd=%d", buf, fd);

    ip = buf;

    dlp_verbose("get peer ip success. ip=%s, fd=%d", ip.c_str(), fd);

    return ip;
}

void dlp_close_stfd(st_netfd_t& stfd)
{
    if (stfd) {
        int fd = st_netfd_fileno(stfd);
        st_netfd_close(stfd);
        stfd = NULL;

        // st does not close it sometimes,
        // close it manually.
        close(fd);
    }
}

string dlp_dns_resolve(string host)
{
    if (inet_addr(host.c_str()) != INADDR_NONE) {
        return host;
    }

    hostent* answer = gethostbyname(host.c_str());
    if (answer == NULL) {
        return "";
    }

    char ipv4[16];
    memset(ipv4, 0, sizeof(ipv4));
    if (answer->h_length > 0) {
        inet_ntop(AF_INET, answer->h_addr_list[0], ipv4, sizeof(ipv4));
    }

    return ipv4;
}

int dlp_socket_connect(string server, int port, st_utime_t timeout, st_netfd_t* pstfd)
{
    int ret = ERROR_SUCCESS;

    *pstfd = NULL;
    st_netfd_t stfd = NULL;
    sockaddr_in addr;

    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if(sock == -1){
        ret = ERROR_ST_SOCKET;
        dlp_error("create socket error. ret=%d", ret);
        return ret;
    }

    dlp_assert(!stfd);
    stfd = st_netfd_open_socket(sock);
    if(stfd == NULL){
        ret = ERROR_ST_SOCKET;
        dlp_error("st_netfd_open_socket failed. ret=%d", ret);
        return ret;
    }

    // connect to server.
    std::string ip = dlp_dns_resolve(server);
    if (ip.empty()) {
        ret = ERROR_ST_SOCKET;
        dlp_error("dns resolve server error, ip empty. ret=%d", ret);
        goto failed;
    }

    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = inet_addr(ip.c_str());

    if (st_connect(stfd, (const struct sockaddr*)&addr, sizeof(sockaddr_in), timeout) == -1){
        ret = ERROR_ST_SOCKET;
        dlp_error("connect to server error. ip=%s, port=%d, ret=%d", ip.c_str(), port, ret);
        goto failed;
    }
    dlp_info("connect ok. server=%s, ip=%s, port=%d", server.c_str(), ip.c_str(), port);

    *pstfd = stfd;
    return ret;

failed:
    if (stfd) {
        dlp_close_stfd(stfd);
    }
    return ret;
}

DlpStSocket::DlpStSocket(st_netfd_t client_stfd)
{
    stfd = client_stfd;
    send_timeout = recv_timeout = ST_UTIME_NO_TIMEOUT;
    recv_bytes = send_bytes = 0;
}

DlpStSocket::~DlpStSocket()
{
}

bool DlpStSocket::is_never_timeout(int64_t timeout_us)
{
    return timeout_us == (int64_t)ST_UTIME_NO_TIMEOUT;
}

void DlpStSocket::set_recv_timeout(int64_t timeout_us)
{
    recv_timeout = timeout_us;
}

int64_t DlpStSocket::get_recv_timeout()
{
    return recv_timeout;
}

void DlpStSocket::set_send_timeout(int64_t timeout_us)
{
    send_timeout = timeout_us;
}

int64_t DlpStSocket::get_send_timeout()
{
    return send_timeout;
}

int64_t DlpStSocket::get_recv_bytes()
{
    return recv_bytes;
}

int64_t DlpStSocket::get_send_bytes()
{
    return send_bytes;
}

int DlpStSocket::read(void* buf, size_t size, ssize_t* nread)
{
    int ret = ERROR_SUCCESS;

    ssize_t nb_read = st_read(stfd, buf, size, recv_timeout);
    if (nread) {
        *nread = nb_read;
    }

    // On success a non-negative integer indicating the number of bytes actually read is returned
    // (a value of 0 means the network connection is closed or end of file is reached).
    // Otherwise, a value of -1 is returned and errno is set to indicate the error.
    if (nb_read <= 0) {
        // @see https://github.com/simple-rtmp-server/srs/issues/200
        if (nb_read < 0 && errno == ETIME) {
            return ERROR_SOCKET_TIMEOUT;
        }

        if (nb_read == 0) {
            errno = ECONNRESET;
        }

        return ERROR_SOCKET_READ;
    }

    recv_bytes += nb_read;

    return ret;
}

int DlpStSocket::read_fully(void* buf, size_t size, ssize_t* nread)
{
    int ret = ERROR_SUCCESS;

    ssize_t nb_read = st_read_fully(stfd, buf, size, recv_timeout);
    if (nread) {
        *nread = nb_read;
    }

    // On success a non-negative integer indicating the number of bytes actually read is returned
    // (a value less than nbyte means the network connection is closed or end of file is reached)
    // Otherwise, a value of -1 is returned and errno is set to indicate the error.
    if (nb_read != (ssize_t)size) {
        // @see https://github.com/simple-rtmp-server/srs/issues/200
        if (nb_read < 0 && errno == ETIME) {
            return ERROR_SOCKET_TIMEOUT;
        }

        if (nb_read >= 0) {
            errno = ECONNRESET;
        }

        return ERROR_SOCKET_READ_FULLY;
    }

    recv_bytes += nb_read;

    return ret;
}

int DlpStSocket::write(void* buf, size_t size, ssize_t* nwrite)
{
    int ret = ERROR_SUCCESS;

    ssize_t nb_write = st_write(stfd, buf, size, send_timeout);
    if (nwrite) {
        *nwrite = nb_write;
    }

    // On success a non-negative integer equal to nbyte is returned.
    // Otherwise, a value of -1 is returned and errno is set to indicate the error.
    if (nb_write <= 0) {
        // @see https://github.com/simple-rtmp-server/srs/issues/200
        if (nb_write < 0 && errno == ETIME) {
            return ERROR_SOCKET_TIMEOUT;
        }

        return ERROR_SOCKET_WRITE;
    }

    send_bytes += nb_write;

    return ret;
}

int DlpStSocket::writev(const iovec *iov, int iov_size, ssize_t* nwrite)
{
    int ret = ERROR_SUCCESS;

    ssize_t nb_write = st_writev(stfd, iov, iov_size, send_timeout);
    if (nwrite) {
        *nwrite = nb_write;
    }

    // On success a non-negative integer equal to nbyte is returned.
    // Otherwise, a value of -1 is returned and errno is set to indicate the error.
    if (nb_write <= 0) {
        // @see https://github.com/simple-rtmp-server/srs/issues/200
        if (nb_write < 0 && errno == ETIME) {
            return ERROR_SOCKET_TIMEOUT;
        }

        return ERROR_SOCKET_WRITE;
    }

    send_bytes += nb_write;

    return ret;
}

DlpProcessTitle::DlpProcessTitle()
{
    argc = 0;
    argv = NULL;
}

DlpProcessTitle::~DlpProcessTitle()
{
}

void DlpProcessTitle::set_argcv(int c, char** v)
{
    argc = c;
    argv = v;

    argv_length.clear();
    for (int i = 0; i < argc; i++) {
        char* p = argv[i];
        int nb_p = (int)strlen(p);

        if (nb_p <= 0) {
            continue;
        }

        argv_length.push_back(nb_p);
    }
}

void DlpProcessTitle::set_title(const char* title)
{
    const char* start = title;
    const char* end = start + strlen(title);
    const char* pos = start;

    for (int i = 0; i < argc; i++) {
        char* p = argv[i];
        int nb_p = argv_length.at(i);
        memset(p, 0, nb_p);
    }

    for (int i = 0; i < argc && pos < end; i++) {
        char* p = argv[i];
        int nb_p = argv_length.at(i);

        int nwrite = snprintf(p, nb_p, "%s", pos);
        pos += nwrite;
    }
}

<commit_msg>refine the process title.<commit_after>/*
 The MIT License (MIT)

 Copyright (c) 2015 winlin

 Permission is hereby granted, free of charge, to any person obtaining a copy of
 this software and associated documentation files (the "Software"), to deal in
 the Software without restriction, including without limitation the rights to
 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 the Software, and to permit persons to whom the Software is furnished to do so,
 subject to the following conditions:

 The above copyright notice and this permission notice shall be included in all
 copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include <dlp_core.hpp>

#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <netdb.h>
#include <arpa/inet.h>

#include <map>
using namespace std;

#include <st.h>

// nginx also set to 512
#define SERVER_LISTEN_BACKLOG 512

DlpProcessTitle* dlp_process_title = new DlpProcessTitle();

bool st_initilaized = false;
int dlp_master_id = getpid();
std::map<st_thread_t, int> cache;

int dlp_generate_id()
{
    if (!st_initilaized) {
        return 0;
    }

    static int id = 100;

    int gid = id++;
    cache[st_thread_self()] = gid;
    return gid;
}

int dlp_get_id()
{
    if (st_initilaized) {
        return cache[st_thread_self()];
    }
    return 0;
}

vector<int> dlp_list_to_ints(string str_list)
{
    vector<int> ints;

    std::string p = str_list;
    dlp_verbose("parse string list: %s", p.c_str());

    size_t pos = string::npos;
    while ((pos = p.find(",")) != string::npos) {
        std::string value = p.substr(0, pos);
        if (!value.empty()) {
            dlp_verbose("int value: %s", value.c_str());
            ints.push_back(::atoi(value.c_str()));
        }
        p = p.substr(pos + 1);
    }

    if (!p.empty()) {
        dlp_verbose("int value: %s", p.c_str());
        ints.push_back(::atoi(p.c_str()));
    }

    dlp_verbose("string list parsed.");

    return ints;
}

int dlp_listen_tcp(int port, int& fd)
{
    int ret = ERROR_SUCCESS;

    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        ret = ERROR_SOCKET_LISTEN;
        dlp_error("create linux socket error. port=%d, ret=%d", port, ret);
        return ret;
    }
    dlp_verbose("create linux socket success. port=%d, fd=%d", port, fd);

    int reuse_socket = 1;
    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_socket, sizeof(int)) == -1) {
        ret = ERROR_SOCKET_LISTEN;
        dlp_error("setsockopt reuse-addr error. port=%d, ret=%d", port, ret);
        return ret;
    }
    dlp_verbose("setsockopt reuse-addr success. port=%d, fd=%d", port, fd);

    sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = INADDR_ANY;
    //addr.sin_addr.s_addr = inet_addr("0.0.0.0");
    if (bind(fd, (const sockaddr*)&addr, sizeof(sockaddr_in)) == -1) {
        ret = ERROR_SOCKET_LISTEN;
        dlp_error("bind socket error. port=%d, ret=%d", port, ret);
        return ret;
    }
    dlp_verbose("bind socket success. port=%d, fd=%d", port, fd);

    if (::listen(fd, SERVER_LISTEN_BACKLOG) == -1) {
        ret = ERROR_SOCKET_LISTEN;
        dlp_error("listen socket error. port=%d, ret=%d", port, ret);
        return ret;
    }
    dlp_verbose("listen socket success. port=%d, fd=%d", port, fd);

    return ret;
}

int dlp_st_init()
{
    int ret = ERROR_SUCCESS;

    // Select the best event system available on the OS. In Linux this is
    // epoll(). On BSD it will be kqueue.
    if (st_set_eventsys(ST_EVENTSYS_ALT) == -1) {
        ret = ERROR_ST_INITIALIZE;
        dlp_error("st_set_eventsys use %s failed. ret=%d", st_get_eventsys_name(), ret);
        return ret;
    }
    dlp_trace("st_set_eventsys to %s", st_get_eventsys_name());

    if(st_init() != 0){
        ret = ERROR_ST_INITIALIZE;
        dlp_error("st_init failed. ret=%d", ret);
        return ret;
    }
    dlp_trace("st_init success, use %s", st_get_eventsys_name());

    st_initilaized = true;
    dlp_generate_id();
    dlp_trace("st main thread, cid=%d", dlp_get_id());

    return ret;
}

string dlp_get_peer_ip(int fd)
{
    std::string ip;

    // discovery client information
    sockaddr_in addr;
    socklen_t addrlen = sizeof(addr);
    if (getpeername(fd, (sockaddr*)&addr, &addrlen) == -1) {
        return ip;
    }
    dlp_verbose("get peer name success.");

    // ip v4 or v6
    char buf[INET6_ADDRSTRLEN];
    memset(buf, 0, sizeof(buf));

    if ((inet_ntop(addr.sin_family, &addr.sin_addr, buf, sizeof(buf))) == NULL) {
        return ip;
    }
    dlp_verbose("get peer ip of client ip=%s, fd=%d", buf, fd);

    ip = buf;

    dlp_verbose("get peer ip success. ip=%s, fd=%d", ip.c_str(), fd);

    return ip;
}

void dlp_close_stfd(st_netfd_t& stfd)
{
    if (stfd) {
        int fd = st_netfd_fileno(stfd);
        st_netfd_close(stfd);
        stfd = NULL;

        // st does not close it sometimes,
        // close it manually.
        close(fd);
    }
}

string dlp_dns_resolve(string host)
{
    if (inet_addr(host.c_str()) != INADDR_NONE) {
        return host;
    }

    hostent* answer = gethostbyname(host.c_str());
    if (answer == NULL) {
        return "";
    }

    char ipv4[16];
    memset(ipv4, 0, sizeof(ipv4));
    if (answer->h_length > 0) {
        inet_ntop(AF_INET, answer->h_addr_list[0], ipv4, sizeof(ipv4));
    }

    return ipv4;
}

int dlp_socket_connect(string server, int port, st_utime_t timeout, st_netfd_t* pstfd)
{
    int ret = ERROR_SUCCESS;

    *pstfd = NULL;
    st_netfd_t stfd = NULL;
    sockaddr_in addr;

    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if(sock == -1){
        ret = ERROR_ST_SOCKET;
        dlp_error("create socket error. ret=%d", ret);
        return ret;
    }

    dlp_assert(!stfd);
    stfd = st_netfd_open_socket(sock);
    if(stfd == NULL){
        ret = ERROR_ST_SOCKET;
        dlp_error("st_netfd_open_socket failed. ret=%d", ret);
        return ret;
    }

    // connect to server.
    std::string ip = dlp_dns_resolve(server);
    if (ip.empty()) {
        ret = ERROR_ST_SOCKET;
        dlp_error("dns resolve server error, ip empty. ret=%d", ret);
        goto failed;
    }

    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = inet_addr(ip.c_str());

    if (st_connect(stfd, (const struct sockaddr*)&addr, sizeof(sockaddr_in), timeout) == -1){
        ret = ERROR_ST_SOCKET;
        dlp_error("connect to server error. ip=%s, port=%d, ret=%d", ip.c_str(), port, ret);
        goto failed;
    }
    dlp_info("connect ok. server=%s, ip=%s, port=%d", server.c_str(), ip.c_str(), port);

    *pstfd = stfd;
    return ret;

failed:
    if (stfd) {
        dlp_close_stfd(stfd);
    }
    return ret;
}

DlpStSocket::DlpStSocket(st_netfd_t client_stfd)
{
    stfd = client_stfd;
    send_timeout = recv_timeout = ST_UTIME_NO_TIMEOUT;
    recv_bytes = send_bytes = 0;
}

DlpStSocket::~DlpStSocket()
{
}

bool DlpStSocket::is_never_timeout(int64_t timeout_us)
{
    return timeout_us == (int64_t)ST_UTIME_NO_TIMEOUT;
}

void DlpStSocket::set_recv_timeout(int64_t timeout_us)
{
    recv_timeout = timeout_us;
}

int64_t DlpStSocket::get_recv_timeout()
{
    return recv_timeout;
}

void DlpStSocket::set_send_timeout(int64_t timeout_us)
{
    send_timeout = timeout_us;
}

int64_t DlpStSocket::get_send_timeout()
{
    return send_timeout;
}

int64_t DlpStSocket::get_recv_bytes()
{
    return recv_bytes;
}

int64_t DlpStSocket::get_send_bytes()
{
    return send_bytes;
}

int DlpStSocket::read(void* buf, size_t size, ssize_t* nread)
{
    int ret = ERROR_SUCCESS;

    ssize_t nb_read = st_read(stfd, buf, size, recv_timeout);
    if (nread) {
        *nread = nb_read;
    }

    // On success a non-negative integer indicating the number of bytes actually read is returned
    // (a value of 0 means the network connection is closed or end of file is reached).
    // Otherwise, a value of -1 is returned and errno is set to indicate the error.
    if (nb_read <= 0) {
        // @see https://github.com/simple-rtmp-server/srs/issues/200
        if (nb_read < 0 && errno == ETIME) {
            return ERROR_SOCKET_TIMEOUT;
        }

        if (nb_read == 0) {
            errno = ECONNRESET;
        }

        return ERROR_SOCKET_READ;
    }

    recv_bytes += nb_read;

    return ret;
}

int DlpStSocket::read_fully(void* buf, size_t size, ssize_t* nread)
{
    int ret = ERROR_SUCCESS;

    ssize_t nb_read = st_read_fully(stfd, buf, size, recv_timeout);
    if (nread) {
        *nread = nb_read;
    }

    // On success a non-negative integer indicating the number of bytes actually read is returned
    // (a value less than nbyte means the network connection is closed or end of file is reached)
    // Otherwise, a value of -1 is returned and errno is set to indicate the error.
    if (nb_read != (ssize_t)size) {
        // @see https://github.com/simple-rtmp-server/srs/issues/200
        if (nb_read < 0 && errno == ETIME) {
            return ERROR_SOCKET_TIMEOUT;
        }

        if (nb_read >= 0) {
            errno = ECONNRESET;
        }

        return ERROR_SOCKET_READ_FULLY;
    }

    recv_bytes += nb_read;

    return ret;
}

int DlpStSocket::write(void* buf, size_t size, ssize_t* nwrite)
{
    int ret = ERROR_SUCCESS;

    ssize_t nb_write = st_write(stfd, buf, size, send_timeout);
    if (nwrite) {
        *nwrite = nb_write;
    }

    // On success a non-negative integer equal to nbyte is returned.
    // Otherwise, a value of -1 is returned and errno is set to indicate the error.
    if (nb_write <= 0) {
        // @see https://github.com/simple-rtmp-server/srs/issues/200
        if (nb_write < 0 && errno == ETIME) {
            return ERROR_SOCKET_TIMEOUT;
        }

        return ERROR_SOCKET_WRITE;
    }

    send_bytes += nb_write;

    return ret;
}

int DlpStSocket::writev(const iovec *iov, int iov_size, ssize_t* nwrite)
{
    int ret = ERROR_SUCCESS;

    ssize_t nb_write = st_writev(stfd, iov, iov_size, send_timeout);
    if (nwrite) {
        *nwrite = nb_write;
    }

    // On success a non-negative integer equal to nbyte is returned.
    // Otherwise, a value of -1 is returned and errno is set to indicate the error.
    if (nb_write <= 0) {
        // @see https://github.com/simple-rtmp-server/srs/issues/200
        if (nb_write < 0 && errno == ETIME) {
            return ERROR_SOCKET_TIMEOUT;
        }

        return ERROR_SOCKET_WRITE;
    }

    send_bytes += nb_write;

    return ret;
}

DlpProcessTitle::DlpProcessTitle()
{
    argc = 0;
    argv = NULL;
}

DlpProcessTitle::~DlpProcessTitle()
{
}

void DlpProcessTitle::set_argcv(int c, char** v)
{
    argc = c;
    argv = v;

    argv_length.clear();
    for (int i = 0; i < argc; i++) {
        char* p = argv[i];
        int nb_p = (int)strlen(p);

        if (nb_p <= 0) {
            continue;
        }

        // the size of argv should plus the last 0.
        argv_length.push_back(nb_p + 1);
    }
}

void DlpProcessTitle::set_title(const char* title)
{
    const char* start = title;
    const char* end = start + strlen(title);
    const char* pos = start;

    for (int i = 0; i < argc; i++) {
        char* p = argv[i];
        int nb_p = argv_length.at(i);
        memset(p, 0, nb_p);
    }

    for (int i = 0; i < argc && pos < end; i++) {
        char* p = argv[i];
        int nb_p = argv_length.at(i);

        snprintf(p, nb_p, "%s", pos);
        pos += nb_p - 1;
    }
}

<|endoftext|>


<commit_before>void surfaces() {
   //Draw 2-Dim functions
   // To see the output of this macro, click begin_html here end_html
   //Author: Rene Brun

   TCanvas 8c1 = new TCanvas("c1","Surfaces Drawing Options",200,10,700,900);
   c1->SetFillColor(42);
   gStyle->SetFrameFillColor(42);
   title = new TPaveText(.2,0.96,.8,.995);
   title->SetFillColor(33);
   title->AddText("Examples of Surface options");
   title->Draw();

   pad1 = new TPad("pad1","Gouraud shading",0.03,0.50,0.98,0.95,21);
   pad2 = new TPad("pad2","Color mesh",0.03,0.02,0.98,0.48,21);
   pad1->Draw();
   pad2->Draw();
   //
   // We generate a 2-D function
   TF2 *f2 = new TF2("f2","x**2 + y**2 - x**3 -8*x*y**4",-1,1.2,-1.5,1.5);
   f2->SetContour(48);
   f2->SetFillColor(45);

   // Draw this function in pad1 with Gouraud shading option
   pad1->cd();
   pad1->SetPhi(-80);
   pad1->SetLogz();
   f2->Draw("surf4");

   // Draw this function in pad2 with color mesh option
   pad2->cd();
   pad2->SetTheta(25);
   pad2->SetPhi(-110);
   pad2->SetLogz();
   f2->Draw("surf1");

   //add axis titles. The titles are set on the intermediate
   //histogram used for visualisation. We must force this histogram
   //to be created, then force the redrawing of the two pads
   pad2->Update();
   f2->GetHistogram()->GetXaxis()->SetTitle("x title");
   f2->GetHistogram()->GetYaxis()->SetTitle("y title");
   f2->GetHistogram()->GetXaxis()->SetTitleOffset(1.4);
   f2->GetHistogram()->GetYaxis()->SetTitleOffset(1.4);
   pad1->Modified();
   pad2->Modified();
}
<commit_msg>- Fix a typo: "8" was written instead of "*" in the TCanvas declaration.<commit_after>void surfaces() {
   //Draw 2-Dim functions
   // To see the output of this macro, click begin_html here end_html
   //Author: Rene Brun

   TCanvas *c1 = new TCanvas("c1","Surfaces Drawing Options",200,10,700,900);
   c1->SetFillColor(42);
   gStyle->SetFrameFillColor(42);
   title = new TPaveText(.2,0.96,.8,.995);
   title->SetFillColor(33);
   title->AddText("Examples of Surface options");
   title->Draw();

   pad1 = new TPad("pad1","Gouraud shading",0.03,0.50,0.98,0.95,21);
   pad2 = new TPad("pad2","Color mesh",0.03,0.02,0.98,0.48,21);
   pad1->Draw();
   pad2->Draw();
   //
   // We generate a 2-D function
   TF2 *f2 = new TF2("f2","x**2 + y**2 - x**3 -8*x*y**4",-1,1.2,-1.5,1.5);
   f2->SetContour(48);
   f2->SetFillColor(45);

   // Draw this function in pad1 with Gouraud shading option
   pad1->cd();
   pad1->SetPhi(-80);
   pad1->SetLogz();
   f2->Draw("surf4");

   // Draw this function in pad2 with color mesh option
   pad2->cd();
   pad2->SetTheta(25);
   pad2->SetPhi(-110);
   pad2->SetLogz();
   f2->Draw("surf1");

   //add axis titles. The titles are set on the intermediate
   //histogram used for visualisation. We must force this histogram
   //to be created, then force the redrawing of the two pads
   pad2->Update();
   f2->GetHistogram()->GetXaxis()->SetTitle("x title");
   f2->GetHistogram()->GetYaxis()->SetTitle("y title");
   f2->GetHistogram()->GetXaxis()->SetTitleOffset(1.4);
   f2->GetHistogram()->GetYaxis()->SetTitleOffset(1.4);
   pad1->Modified();
   pad2->Modified();
}
<|endoftext|>