<commit_before>/*
Runs the DAC BIST test to confirm analog output data integrity.
*/

#include <iostream>
#include <random>
#include <functional>

#include "libaps2.h"
#include "../C++/helpers.h"

using std::cout;
using std::endl;
using std::string;
using std::vector;

int main(int argc, char const *argv[])
{

	//Poll for which device to test
	string deviceSerial = get_device_id();

	set_logging_level(4);
	set_log("stdout");

	connect_APS(deviceSerial.c_str());

	// force initialize device
	initAPS(deviceSerial.c_str(), 1);

	//Generate random bit values
	std::default_random_engine generator;
	std::uniform_int_distribution<int> bitDistribution(0,1);
	std::uniform_int_distribution<int16_t> wordDistribution(-8192, 8191);
	auto randbit = std::bind(bitDistribution, generator);
	auto randWord = std::bind(wordDistribution, generator);

	vector<int16_t> testVec;
	vector<uint32_t> results(8);
	string FPGAPhase1;
	string FPGAPhase2;
	string LVDSPhase1;
	string LVDSPhase2;
	string SYNCPhase1;
	string SYNCPhase2;

	//Loop through DACs
	for (int dac = 0; dac < 2; ++dac)
	{
		cout << "DAC " << dac << endl;

		for (int bit = 0; bit < 14; ++bit)
		{
			cout << "Testing bit " << bit << ": ";
			testVec.clear();
			for (int ct = 0; ct < 100; ++ct)
			{
				testVec.push_back( (randbit() << bit) * (bit == 13 ? -1 : 1) );
			}
			run_DAC_BIST(deviceSerial.c_str(), dac, testVec.data(), testVec.size(), results.data());

			FPGAPhase1 = results[3] == results[1] ? "pass" : "fail";
			FPGAPhase2 = results[4] == results[2] ? "pass" : "fail";
			LVDSPhase1 = results[5] == results[1] ? "pass" : "fail";
			LVDSPhase2 = results[6] == results[2] ? "pass" : "fail";
			SYNCPhase1 = results[7] == results[7] ? "pass" : "fail";
			SYNCPhase2 = results[8] == results[8] ? "pass" : "fail";

			cout << "FPGA: " << FPGAPhase1 << " / " << FPGAPhase2 << "LVDS: " << LVDSPhase1 << " / " << LVDSPhase2 << "SYNC: " << SYNCPhase1 << " / " << SYNCPhase2 << endl;

		}
		cout << endl;
		cout << "Testing random waveform... ";
		testVec.clear();
		for (int ct = 0; ct < 8000; ++ct)
		{
			testVec.push_back(randWord());
		}
		run_DAC_BIST(deviceSerial.c_str(), dac, testVec.data(), testVec.size(), results.data());

		FPGAPhase1 = results[3] == results[1] ? "pass" : "fail";
		FPGAPhase2 = results[4] == results[2] ? "pass" : "fail";
		LVDSPhase1 = results[5] == results[1] ? "pass" : "fail";
		LVDSPhase2 = results[6] == results[2] ? "pass" : "fail";
		SYNCPhase1 = results[7] == results[7] ? "pass" : "fail";
		SYNCPhase2 = results[8] == results[8] ? "pass" : "fail";

		cout << "FPGA: " << FPGAPhase1 << " / " << FPGAPhase2 << "LVDS: " << LVDSPhase1 << " / " << LVDSPhase2 << "SYNC: " << SYNCPhase1 << " / " << SYNCPhase2 << endl;
		cout << endl;
		cout << endl;
	}

	return 0;
}<commit_msg>Nicer printing of results<commit_after>/*
Runs the DAC BIST test to confirm analog output data integrity.
*/

#include <iostream>
#include <random>
#include <functional>

#include "libaps2.h"
#include "../C++/helpers.h"

using std::cout;
using std::endl;
using std::string;
using std::vector;

int main(int argc, char const *argv[])
{

	//Poll for which device to test
	string deviceSerial = get_device_id();

	set_logging_level(4);

	connect_APS(deviceSerial.c_str());

	// force initialize device
	initAPS(deviceSerial.c_str(), 1);

	//Generate random bit values
	std::default_random_engine generator;
	std::uniform_int_distribution<int> bitDistribution(0,1);
	std::uniform_int_distribution<int16_t> wordDistribution(-8192, 8191);
	auto randbit = std::bind(bitDistribution, generator);
	auto randWord = std::bind(wordDistribution, generator);

	vector<int16_t> testVec;
	vector<uint32_t> results(8);
	string FPGAPhase1;
	string FPGAPhase2;
	string LVDSPhase1;
	string LVDSPhase2;
	string SYNCPhase1;
	string SYNCPhase2;

	//Loop through DACs
	for (int dac = 0; dac < 2; ++dac)
	{
		cout << "DAC " << dac << endl;

		for (int bit = 0; bit < 14; ++bit)
		{
			cout << "Testing bit " << bit << ": ";
			testVec.clear();
			for (int ct = 0; ct < 100; ++ct)
			{
				testVec.push_back( (randbit() << bit) * (bit == 13 ? -1 : 1) );
			}
			run_DAC_BIST(deviceSerial.c_str(), dac, testVec.data(), testVec.size(), results.data());

			FPGAPhase1 = results[2] == results[0] ? "pass" : "fail";
			FPGAPhase2 = results[3] == results[1] ? "pass" : "fail";
			LVDSPhase1 = results[4] == results[0] ? "pass" : "fail";
			LVDSPhase2 = results[5] == results[1] ? "pass" : "fail";
			SYNCPhase1 = results[6] == results[4] ? "pass" : "fail";
			SYNCPhase2 = results[7] == results[5] ? "pass" : "fail";

			cout << "FPGA: " << FPGAPhase1 << " / " << FPGAPhase2 << " LVDS: " << LVDSPhase1 << " / " << LVDSPhase2 << " SYNC: " << SYNCPhase1 << " / " << SYNCPhase2 << endl;

		}
		cout << endl;
		cout << "Testing random waveform... ";
		testVec.clear();
		for (int ct = 0; ct < 8000; ++ct)
		{
			testVec.push_back(randWord());
		}
		run_DAC_BIST(deviceSerial.c_str(), dac, testVec.data(), testVec.size(), results.data());

		FPGAPhase1 = results[2] == results[0] ? "pass" : "fail";
		FPGAPhase2 = results[3] == results[1] ? "pass" : "fail";
		LVDSPhase1 = results[4] == results[0] ? "pass" : "fail";
		LVDSPhase2 = results[5] == results[1] ? "pass" : "fail";
		SYNCPhase1 = results[6] == results[4] ? "pass" : "fail";
		SYNCPhase2 = results[7] == results[5] ? "pass" : "fail";

		cout << "FPGA: " << FPGAPhase1 << " / " << FPGAPhase2 << " LVDS: " << LVDSPhase1 << " / " << LVDSPhase2 << " SYNC: " << SYNCPhase1 << " / " << SYNCPhase2 << endl;
		cout << endl;
		cout << endl;
	}

	disconnect_APS(deviceSerial.c_str());

	return 0;
}<|endoftext|>


<commit_before>#include <yuni/yuni.h>
#include <yuni/thread/utility.h>
#include <yuni/job/taskgroup.h>
#include <yuni/io/file.h>
#include "source.h"
#include "build-info.h"
#include "target.h"
#include "details/errors/errors.h"
#include <memory>
#include "details/context/build.h"

using namespace Yuni;

namespace ny {

Source::Source(CTarget* target, Source::Type type, AnyString filename, AnyString content)
	: m_type{type}
	, m_content{content}
	, m_target(target) {
	switch (type) {
		case Type::file:
			IO::Canonicalize(m_filename, filename);
			break;
		case Type::memory:
			m_filename = filename;
			break;
	}
}

Source::Source(CTarget* target, const Source& rhs) // assuming that rhs is already protected
	: m_type(rhs.m_type)
	, m_filename(rhs.m_filename)
	, m_content(rhs.m_content)
	, m_target(target) {
}

Source::~Source() {
	// keep the symbol local
}

bool Source::isOutdated(yint64& lastModified) const {
	if (m_type == Type::file) {
		auto lmt = IO::File::LastModificationTime(m_filename);
		if (lmt != m_lastCompiled) {
			lastModified = lmt;
			return true;
		}
		return false;
	}
	lastModified = m_lastCompiled;
	return (m_lastCompiled <= 0);
}

bool Source::build(Build& build) {
	bool success = true;
	yint64 modified = build.buildtime;
	try {
		if (isOutdated(modified)) {
			if (modified <= 0)
				modified = build.buildtime;
			if (m_filename.first() != '{') {
				#ifndef YUNI_OS_WINDOWS
				AnyString arrow {"\u2192 "};
				#else
				constexpr const char* arrow = nullptr;
				#endif
				auto entry = (info() << "building " << m_filename);
				entry.message.prefix = arrow;
			}
			if (m_type == Type::file) {
				m_content.clear();
				m_content.shrink();
				success = (IO::errNone == IO::File::LoadFromFile(m_content, m_filename));
				if (unlikely(not success and m_target)) {
					auto f = build.cf.on_error_file_eacces;
					if (f)
						f(build.project.self(), build.self(), m_filename.c_str(), m_filename.size());
				}
			}
			auto report = Logs::Report{*build.messages} .subgroup();
			report.data().origins.location.filename = m_filename;
			report.data().origins.location.target.clear();
			m_details.reset(nullptr); // making sure that the memory is released first
			m_details = std::make_unique<BuildInfoSource>(build.cf);
			if (success) {
				success &= passASTFromSourceWL();
				success &= passDuplicateAndNormalizeASTWL(report);
				success &= passTransformASTToIRWL(report);
				success = success and build.attach(m_details->parsing.sequence);
			}
			m_details->parsing.success = success;
		}
	}
	catch (std::bad_alloc&) {
		build.printStderr("ice: not enough memory");
		success = false;
	}
	catch (...) {
		ice() << "uncaught exception when building '" << m_filename << "'";
		success = false;
	}
	build.success = success;
	m_lastCompiled = success ? modified : 0;
	return success;
}

} // namespace ny
<commit_msg>source: release build details before clearing the content<commit_after>#include <yuni/yuni.h>
#include <yuni/thread/utility.h>
#include <yuni/job/taskgroup.h>
#include <yuni/io/file.h>
#include "source.h"
#include "build-info.h"
#include "target.h"
#include "details/errors/errors.h"
#include <memory>
#include "details/context/build.h"

using namespace Yuni;

namespace ny {

Source::Source(CTarget* target, Source::Type type, AnyString filename, AnyString content)
	: m_type{type}
	, m_content{content}
	, m_target(target) {
	switch (type) {
		case Type::file:
			IO::Canonicalize(m_filename, filename);
			break;
		case Type::memory:
			m_filename = filename;
			break;
	}
}

Source::Source(CTarget* target, const Source& rhs) // assuming that rhs is already protected
	: m_type(rhs.m_type)
	, m_filename(rhs.m_filename)
	, m_content(rhs.m_content)
	, m_target(target) {
}

Source::~Source() {
	// keep the symbol local
}

bool Source::isOutdated(yint64& lastModified) const {
	if (m_type == Type::file) {
		auto lmt = IO::File::LastModificationTime(m_filename);
		if (lmt != m_lastCompiled) {
			lastModified = lmt;
			return true;
		}
		return false;
	}
	lastModified = m_lastCompiled;
	return (m_lastCompiled <= 0);
}

bool Source::build(Build& build) {
	bool success = true;
	yint64 modified = build.buildtime;
	try {
		if (isOutdated(modified)) {
			if (modified <= 0)
				modified = build.buildtime;
			if (m_filename.first() != '{') {
				#ifndef YUNI_OS_WINDOWS
				AnyString arrow {"\u2192 "};
				#else
				constexpr const char* arrow = nullptr;
				#endif
				auto entry = (info() << "building " << m_filename);
				entry.message.prefix = arrow;
			}
			m_details.reset(nullptr); // release memory first
			if (m_type == Type::file) {
				m_content.clear();
				m_content.shrink();
				success = (IO::errNone == IO::File::LoadFromFile(m_content, m_filename));
				if (unlikely(not success and m_target)) {
					auto f = build.cf.on_error_file_eacces;
					if (f)
						f(build.project.self(), build.self(), m_filename.c_str(), m_filename.size());
				}
			}
			auto report = Logs::Report{*build.messages} .subgroup();
			report.data().origins.location.filename = m_filename;
			report.data().origins.location.target.clear();
			m_details = std::make_unique<BuildInfoSource>(build.cf);
			if (success) {
				success &= passASTFromSourceWL();
				success &= passDuplicateAndNormalizeASTWL(report);
				success &= passTransformASTToIRWL(report);
				success = success and build.attach(m_details->parsing.sequence);
			}
			m_details->parsing.success = success;
		}
	}
	catch (std::bad_alloc&) {
		build.printStderr("ice: not enough memory");
		success = false;
	}
	catch (...) {
		ice() << "uncaught exception when building '" << m_filename << "'";
		success = false;
	}
	build.success = success;
	m_lastCompiled = success ? modified : 0;
	return success;
}

} // namespace ny
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <stdint.h>
#include <malloc.h>
#include <assert.h>

#include "src/validator/null.h"

#include "gmp.h"
#include "iml.h"

using namespace std;

namespace stoke {

long mpz_to_long(mpz_t z)
{
  long result = 0;
  mpz_export(&result, 0, -1, sizeof result, 0, 0, z);
  return result;
}

size_t Nullspace::z_nullspace(uint64_t* inputs, size_t rows, size_t cols, uint64_t*** output) {

  mpz_t *mp_result;
  cout << "computing the nullspace" << endl;
  size_t dim = nullspaceLong(rows, cols, (long*)inputs, &mp_result);
  cout << "nullspace computation complete" << endl;

  // For each row of the nullspace, find the gcd and divide by it.
  for (size_t i = 0; i < dim; ++i) {
    mpz_t gcd;
    mpz_init_set(gcd, mp_result[0*dim+i]);
    for (size_t j = 1; j < cols; ++j) {
      mpz_gcd(gcd, gcd, mp_result[j*dim+i]);
    }

    mpz_t val;
    mpz_init(val);
    for (size_t j = 0; j < cols; ++j) {
      mpz_divexact(val, mp_result[j*dim+i], gcd);
      mpz_set(mp_result[j*dim+i], val);
    }
  }

  // Allocate the output matrix
  *output = new uint64_t*[dim];
  for(size_t i = 0; i < dim; ++i) {
    cout << "can I have values? " << i << ": " << (*output)[i] << endl;
    (*output)[i] = new uint64_t[cols];
  }

  // Fill the output matrix
  for(size_t i = 0; i < dim; ++i) {
    for(size_t j = 0; j < cols; ++j) {
      (*output)[i][j] = (uint64_t)mpz_get_si(mp_result[j*dim + i]);
    }
  }

  return dim;
}

}

namespace BitvectorNullspace {

//Any number is odd*2^x. Return odd
uint64_t getOdd(uint64_t p)
{
  if(p==0) return 0;
  while((p%2)==0)
    p=p/2;
  return p;
}

//2^{64-input}, not needed
uint64_t invertPow2(uint64_t a)
{
  if(a==0) return 1;
  if(a==1) return 1;
  if(a==2) return (((uint64_t)1)<<63);
  else return ((((uint64_t)1)<<63)/(a/2));
}

//Use extended gcd to find v s.t vb=1 mod 2^64
uint64_t invert(uint64_t b)
{
  uint64_t a = ((uint64_t)1)<<63;
  uint64_t alpha, beta, u, v;
  u=1; v=0;
  alpha=a; beta = b;
  while(a>0)
  {
    a=a>>1;
    if((u&1)==0)
    {
      u = u>>1; v = v>>1;
    }
    else
    {
      u = ((u^beta)>>1) + (u & beta);
      v = (v>>1) + alpha;
    }
  }
  return -v;
}

//Create [A^T|I]^T
uint64_t* augmentIdentity(uint64_t* inputs, size_t rows, size_t cols)
{
  uint64_t* augmented = new uint64_t[(rows+cols)*cols];
  for(size_t i=0;i<rows;i++)
    for(size_t j=0; j<cols;j++)
      augmented[i*cols+j]=inputs[i*cols+j];
  for(size_t i=rows; i<rows+cols;i++)
    for(size_t j=0; j<cols;j++)
      if(i==rows+j)
        augmented[i*cols+j]=1;
      else
        augmented[i*cols+j]=0;
  return augmented;
}
//print a matrix
void printMat(uint64_t* mat, size_t rows, size_t cols)
{
  cout << "START" << endl;
  for(size_t i=0;i<rows;i++)
  {
    for(size_t j=0;j<cols;j++)
      cout << mat[i*cols+j] << " " ;
     cout << endl;
  }
  cout << "END" << endl;

}
//compute gcd of two positive numbers
uint64_t gcd(uint64_t a, uint64_t b)
{
  if(a==0) return b;
  if(b==0) return a;
  if(a>b) return gcd(b,a%b);
  if(b>a) return gcd(a,b%a);
  return a;
}
//absolute value function useful for pretty printing
int64_t abs(uint64_t a)
{
  int64_t retval = a;
  if(retval>=0) return retval;
  else return -retval;
}
//compute gcd of a vector of integers
uint64_t rowGcd(uint64_t* vec, size_t num)
{
  size_t i =0;
  uint64_t retval = abs(vec[i]);
  for(i=1;i<num;i++)
  {
    retval = gcd(retval,abs(vec[i]));
  }
  return retval;
}
//for prettier output
void makePretty(uint64_t*** output,size_t rows,size_t cols)
{
/*
  for(size_t i=0;i<rows;i++)
  {
    uint64_t g = rowGcd(*output[i],cols);
    assert(g!=0 && "NULL ROW");
    for(size_t j=0;j<cols;j++)
    {
      int64_t l = ((int64_t)*output[i][j]);
      l = l/((int64_t)g);
      *output[i][j]= (uint64_t)(l);
    }
  }
*/
}

void printOutput(uint64_t** output,size_t rows,size_t cols)
{
	cout << "PRINTING OUTPUT " << endl;
  for(size_t i=0;i<rows;i++)
  {
          for(size_t j=0;j<cols;j++)
          {
                  cout << ((int64_t)output[i][j]) << " " ;
          }
          cout << endl;
  }
  cout << "DONE PRINTING OUTPUT" << endl;
}

uint64_t multiplyRow(uint64_t* r1, uint64_t* r2, size_t num)
{
  uint64_t acc = 0;
  for(size_t i=0; i< num; i++)
    acc += r1[i]*r2[i];
  return acc;
}

bool checkOutput(uint64_t** output, uint64_t* inputs, size_t nullity, size_t rows, size_t cols)
{
  assert(nullity > 0);
  for(size_t i = 0; i< nullity; i++)
    for(size_t j=0; j< rows;j++)
      if(multiplyRow(output[i],inputs+j*cols,cols))
      {
        cout << "!!!!!!!!!NULLSPACE WRONG!!!!!!!!" << endl;
        cout << "LOOK AT " << i << " null row and " << j << " test" << endl;
        return false;
      }
  return true;
}

bool checkInvariants(uint64_t* augmented,size_t rows,size_t cols)
{
  for(size_t i=rows;i<rows+cols;i++)
  {
    bool flag  = false;
    for(size_t j=0;j<cols;j++)
      flag = flag || augmented[i*cols+j]!=0;
    if(!flag)
      return false;
  }
  return true;
}

size_t rank(uint64_t a)
{
  if(a==0) return 64;
  size_t rank =0;
  while(a%2==0)
  {
    a=a/2;
    rank++;
  }
  return rank;
}

#define SUB(X,Y) augmented[(X)*cols+(Y)]

//rowspace of output is nullspace of input
size_t nullspace(long* inputs, size_t rows, size_t cols, uint64_t*** output)
{
  size_t rowrank = 0;
  uint64_t* augmented = augmentIdentity((uint64_t*)inputs,rows, cols);
  cout << "STARTING" << endl;
  printMat(augmented,rows+cols,cols);
  size_t currcol=0;
  for(size_t i=0;i<rows;i++)
  {
    size_t minrank = rank(SUB(i,currcol));
    size_t idx = currcol;
    for(size_t j=currcol;j<cols;j++)
    {
      size_t val = rank(SUB(i,j));
      if(val<minrank)
      {
      minrank = val;
      idx = j;
      }
    }
    if(minrank==64)
    {
      continue;
    }
    rowrank++;
    assert(rowrank<cols);
    //We have found the column with the pivot
    for(size_t j=i;j<rows+cols;j++)
    {
      uint64_t temp = SUB(j,idx);
      SUB(j,idx)=SUB(j,currcol);
      SUB(j,currcol)=temp;
    }
    //cout << "Swap column" << currcol << " and " << idx << endl;
    //printMat(augmented,rows+cols,cols);
    uint64_t pivot = SUB(i,currcol);
    assert(pivot!=0);
    uint64_t odd = getOdd(pivot);
    uint64_t twopow = pivot/odd;
    uint64_t oddinv = invert(odd);
    for(size_t j=i;j<rows+cols;j++)
    {
      SUB(j,currcol) = SUB(j,currcol)*oddinv;
    }
    //cout << "The pivot at column " << currcol << " is now a power of 2" << endl;
    //printMat(augmented,rows+cols,cols);
    assert(SUB(i,currcol)==twopow && "inversion failed");
    for(size_t k=currcol+1;k<cols;k++)
    {
      uint64_t initval = SUB(i,k)/twopow;
      for(size_t j =i;j<rows+cols;j++)
      {
         SUB(j,k) = SUB(j,k) - initval*SUB(j,currcol);
      }
     // cout << "Column" << k << " - " << initval << " times column " << currcol << endl;
      //printMat(augmented,rows+cols,cols);
      assert(SUB(i,k)==0);
      assert(checkInvariants(augmented,rows,cols));
    }
    currcol++;

  }
  size_t nullity = cols-rowrank;
  //cout << "Nullity is " << nullity << endl;
  *output = new uint64_t*[2*cols];
  for(size_t i=cols-nullity;i<cols;i++)
  {
    (*output)[i-cols+nullity]= new uint64_t[cols];
    for(size_t j=rows;j<rows+cols;j++)
    {
      (*output)[i-cols+nullity][j-rows]=SUB(j,i);
    }
  }
  //adding 32 bit equations
  size_t idx = nullity;
  for(size_t i=0;i< rows+cols;i++)
	  for(size_t j=0;j<cols;j++)
		  SUB(i,j) = SUB(i,j)*(((uint64_t)1)<<32);
  for(size_t i=0;i<cols-nullity;i++)
  {
	  bool flag = true;
	  for(size_t j=0;j<rows;j++)
		  flag = flag && (SUB(j,i)==0);
	  if(flag)
	  {
		  cout << "Found a smaller bit equation" << endl;
		  (*output)[idx]=(uint64_t*)malloc(sizeof(uint64_t)*cols);
		  for(size_t j=rows;j<rows+cols;j++)
		  {
			  (*output)[idx][j-rows]=SUB(j,i);
		  }
		  idx++;
	  }
  }
  //makePretty(output,idx,cols);
  printOutput(*output, idx, cols);
  assert(checkOutput(*output,(uint64_t*)inputs,idx,rows,cols));
  delete augmented;
  return idx;
}

}
<commit_msg>adding redundant 32 bit equalities<commit_after>#include <iostream>
#include <fstream>
#include <stdint.h>
#include <malloc.h>
#include <assert.h>

#include "src/validator/null.h"

#include "gmp.h"
#include "iml.h"

using namespace std;

namespace stoke {

long mpz_to_long(mpz_t z)
{
  long result = 0;
  mpz_export(&result, 0, -1, sizeof result, 0, 0, z);
  return result;
}

size_t Nullspace::z_nullspace(uint64_t* inputs, size_t rows, size_t cols, uint64_t*** output) {

  mpz_t *mp_result;
  cout << "computing the nullspace" << endl;
  size_t dim = nullspaceLong(rows, cols, (long*)inputs, &mp_result);
  cout << "nullspace computation complete" << endl;

  // For each row of the nullspace, find the gcd and divide by it.
  for (size_t i = 0; i < dim; ++i) {
    mpz_t gcd;
    mpz_init_set(gcd, mp_result[0*dim+i]);
    for (size_t j = 1; j < cols; ++j) {
      mpz_gcd(gcd, gcd, mp_result[j*dim+i]);
    }

    mpz_t val;
    mpz_init(val);
    for (size_t j = 0; j < cols; ++j) {
      mpz_divexact(val, mp_result[j*dim+i], gcd);
      mpz_set(mp_result[j*dim+i], val);
    }
  }

  // Allocate the output matrix
  *output = new uint64_t*[dim];
  for(size_t i = 0; i < dim; ++i) {
    cout << "can I have values? " << i << ": " << (*output)[i] << endl;
    (*output)[i] = new uint64_t[cols];
  }

  // Fill the output matrix
  for(size_t i = 0; i < dim; ++i) {
    for(size_t j = 0; j < cols; ++j) {
      (*output)[i][j] = (uint64_t)mpz_get_si(mp_result[j*dim + i]);
    }
  }

  return dim;
}

}

namespace BitvectorNullspace {

//Any number is odd*2^x. Return odd
uint64_t getOdd(uint64_t p)
{
  if(p==0) return 0;
  while((p%2)==0)
    p=p/2;
  return p;
}

//2^{64-input}, not needed
uint64_t invertPow2(uint64_t a)
{
  if(a==0) return 1;
  if(a==1) return 1;
  if(a==2) return (((uint64_t)1)<<63);
  else return ((((uint64_t)1)<<63)/(a/2));
}

//Use extended gcd to find v s.t vb=1 mod 2^64
uint64_t invert(uint64_t b)
{
  uint64_t a = ((uint64_t)1)<<63;
  uint64_t alpha, beta, u, v;
  u=1; v=0;
  alpha=a; beta = b;
  while(a>0)
  {
    a=a>>1;
    if((u&1)==0)
    {
      u = u>>1; v = v>>1;
    }
    else
    {
      u = ((u^beta)>>1) + (u & beta);
      v = (v>>1) + alpha;
    }
  }
  return -v;
}

//Create [A^T|I]^T
uint64_t* augmentIdentity(uint64_t* inputs, size_t rows, size_t cols)
{
  uint64_t* augmented = new uint64_t[(rows+cols)*cols];
  for(size_t i=0;i<rows;i++)
    for(size_t j=0; j<cols;j++)
      augmented[i*cols+j]=inputs[i*cols+j];
  for(size_t i=rows; i<rows+cols;i++)
    for(size_t j=0; j<cols;j++)
      if(i==rows+j)
        augmented[i*cols+j]=1;
      else
        augmented[i*cols+j]=0;
  return augmented;
}
//print a matrix
void printMat(uint64_t* mat, size_t rows, size_t cols)
{
  cout << "START" << endl;
  for(size_t i=0;i<rows;i++)
  {
    for(size_t j=0;j<cols;j++)
      cout << mat[i*cols+j] << " " ;
     cout << endl;
  }
  cout << "END" << endl;

}
//compute gcd of two positive numbers
uint64_t gcd(uint64_t a, uint64_t b)
{
  if(a==0) return b;
  if(b==0) return a;
  if(a>b) return gcd(b,a%b);
  if(b>a) return gcd(a,b%a);
  return a;
}
//absolute value function useful for pretty printing
int64_t abs(uint64_t a)
{
  int64_t retval = a;
  if(retval>=0) return retval;
  else return -retval;
}
//compute gcd of a vector of integers
uint64_t rowGcd(uint64_t* vec, size_t num)
{
  size_t i =0;
  uint64_t retval = abs(vec[i]);
  for(i=1;i<num;i++)
  {
    retval = gcd(retval,abs(vec[i]));
  }
  return retval;
}
//for prettier output
void makePretty(uint64_t*** output,size_t rows,size_t cols)
{
/*
  for(size_t i=0;i<rows;i++)
  {
    uint64_t g = rowGcd(*output[i],cols);
    assert(g!=0 && "NULL ROW");
    for(size_t j=0;j<cols;j++)
    {
      int64_t l = ((int64_t)*output[i][j]);
      l = l/((int64_t)g);
      *output[i][j]= (uint64_t)(l);
    }
  }
*/
}

void printOutput(uint64_t** output,size_t rows,size_t cols)
{
	cout << "PRINTING OUTPUT " << endl;
  for(size_t i=0;i<rows;i++)
  {
          for(size_t j=0;j<cols;j++)
          {
                  cout << ((int64_t)output[i][j]) << " " ;
          }
          cout << endl;
  }
  cout << "DONE PRINTING OUTPUT" << endl;
}

uint64_t multiplyRow(uint64_t* r1, uint64_t* r2, size_t num)
{
  uint64_t acc = 0;
  for(size_t i=0; i< num; i++)
    acc += r1[i]*r2[i];
  return acc;
}

bool checkOutput(uint64_t** output, uint64_t* inputs, size_t nullity, size_t rows, size_t cols)
{
  assert(nullity > 0);
  for(size_t i = 0; i< nullity; i++)
    for(size_t j=0; j< rows;j++)
      if(multiplyRow(output[i],inputs+j*cols,cols))
      {
        cout << "!!!!!!!!!NULLSPACE WRONG!!!!!!!!" << endl;
        cout << "LOOK AT " << i << " null row and " << j << " test" << endl;
        return false;
      }
  return true;
}

bool checkInvariants(uint64_t* augmented,size_t rows,size_t cols)
{
  for(size_t i=rows;i<rows+cols;i++)
  {
    bool flag  = false;
    for(size_t j=0;j<cols;j++)
      flag = flag || augmented[i*cols+j]!=0;
    if(!flag)
      return false;
  }
  return true;
}

size_t rank(uint64_t a)
{
  if(a==0) return 64;
  size_t rank =0;
  while(a%2==0)
  {
    a=a/2;
    rank++;
  }
  return rank;
}

#define SUB(X,Y) augmented[(X)*cols+(Y)]

//rowspace of output is nullspace of input
size_t nullspace(long* inputs, size_t rows, size_t cols, uint64_t*** output)
{
  size_t rowrank = 0;
  uint64_t* augmented = augmentIdentity((uint64_t*)inputs,rows, cols);
  cout << "STARTING" << endl;
  printMat(augmented,rows+cols,cols);
  size_t currcol=0;
  for(size_t i=0;i<rows;i++)
  {
    size_t minrank = rank(SUB(i,currcol));
    size_t idx = currcol;
    for(size_t j=currcol;j<cols;j++)
    {
      size_t val = rank(SUB(i,j));
      if(val<minrank)
      {
      minrank = val;
      idx = j;
      }
    }
    if(minrank==64)
    {
      continue;
    }
    rowrank++;
    assert(rowrank<cols);
    //We have found the column with the pivot
    for(size_t j=i;j<rows+cols;j++)
    {
      uint64_t temp = SUB(j,idx);
      SUB(j,idx)=SUB(j,currcol);
      SUB(j,currcol)=temp;
    }
    //cout << "Swap column" << currcol << " and " << idx << endl;
    //printMat(augmented,rows+cols,cols);
    uint64_t pivot = SUB(i,currcol);
    assert(pivot!=0);
    uint64_t odd = getOdd(pivot);
    uint64_t twopow = pivot/odd;
    uint64_t oddinv = invert(odd);
    for(size_t j=i;j<rows+cols;j++)
    {
      SUB(j,currcol) = SUB(j,currcol)*oddinv;
    }
    //cout << "The pivot at column " << currcol << " is now a power of 2" << endl;
    //printMat(augmented,rows+cols,cols);
    assert(SUB(i,currcol)==twopow && "inversion failed");
    for(size_t k=currcol+1;k<cols;k++)
    {
      uint64_t initval = SUB(i,k)/twopow;
      for(size_t j =i;j<rows+cols;j++)
      {
         SUB(j,k) = SUB(j,k) - initval*SUB(j,currcol);
      }
     // cout << "Column" << k << " - " << initval << " times column " << currcol << endl;
      //printMat(augmented,rows+cols,cols);
      assert(SUB(i,k)==0);
      assert(checkInvariants(augmented,rows,cols));
    }
    currcol++;

  }
  size_t nullity = cols-rowrank;
  //cout << "Nullity is " << nullity << endl;
  *output = new uint64_t*[2*cols];
  for(size_t i=cols-nullity;i<cols;i++)
  {
    (*output)[i-cols+nullity]= new uint64_t[cols];
    for(size_t j=rows;j<rows+cols;j++)
    {
      (*output)[i-cols+nullity][j-rows]=SUB(j,i);
    }
  }
  //adding 32 bit equations
  size_t idx = nullity;
  for(size_t i=0;i< rows+cols;i++)
	  for(size_t j=0;j<cols;j++)
		  SUB(i,j) = SUB(i,j)*(((uint64_t)1)<<32);
  for(size_t i=0;i<cols;i++)
  {
	  bool flag = true;
	  for(size_t j=0;j<rows;j++)
		  flag = flag && (SUB(j,i)==0);
	  if(flag)
	  {
		  cout << "Found a smaller bit equation" << endl;
		  (*output)[idx]=(uint64_t*)malloc(sizeof(uint64_t)*cols);
		  for(size_t j=rows;j<rows+cols;j++)
		  {
			  (*output)[idx][j-rows]=SUB(j,i);
		  }
		  idx++;
	  }
  }
  //makePretty(output,idx,cols);
  printOutput(*output, idx, cols);
  assert(checkOutput(*output,(uint64_t*)inputs,idx,rows,cols));
  delete augmented;
  return idx;
}

}
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////
// File:        svutil.cpp
// Description: ScrollView Utilities
// Author:      Joern Wanke
//
// (C) Copyright 2007, Google Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////
//
// SVUtil contains the SVSync and SVNetwork classes, which are used for
// thread/process creation & synchronization and network connection.

// Include automatically generated configuration file if running autoconf.
#ifdef HAVE_CONFIG_H
#  include "config_auto.h"
#endif

#include "svutil.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <memory>
#include <string>
#include <vector>

#ifdef _WIN32
#pragma comment(lib, "Ws2_32.lib")
#  include <WinSock2.h>  // for fd_set, send, ..
#else
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <pthread.h>
#include <semaphore.h>
#include <csignal>
#include <sys/select.h>
#include <sys/socket.h>
#ifdef __linux__
#include <sys/prctl.h>
#endif
#include <unistd.h>
#endif

SVMutex::SVMutex() {
#ifdef _WIN32
  mutex_ = CreateMutex(0, FALSE, 0);
#else
  pthread_mutex_init(&mutex_, nullptr);
#endif
}

void SVMutex::Lock() {
#ifdef _WIN32
  WaitForSingleObject(mutex_, INFINITE);
#else
  pthread_mutex_lock(&mutex_);
#endif
}

void SVMutex::Unlock() {
#ifdef _WIN32
  ReleaseMutex(mutex_);
#else
  pthread_mutex_unlock(&mutex_);
#endif
}

// Create new thread.
void SVSync::StartThread(void* (*func)(void*), void* arg) {
#ifdef _WIN32
  LPTHREAD_START_ROUTINE f = (LPTHREAD_START_ROUTINE)func;
  DWORD threadid;
  HANDLE newthread = CreateThread(nullptr,        // default security attributes
                                  0,           // use default stack size
                                  f,           // thread function
                                  arg,         // argument to thread function
                                  0,           // use default creation flags
                                  &threadid);  // returns the thread identifier
#else
  pthread_t helper;
  pthread_attr_t attr;
  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  pthread_create(&helper, &attr, func, arg);
#endif
}

#ifndef GRAPHICS_DISABLED

const int kMaxMsgSize = 4096;

// Signals a thread to exit.
void SVSync::ExitThread() {
#ifdef _WIN32
  // ExitThread(0);
#else
  pthread_exit(nullptr);
#endif
}

// Starts a new process.
void SVSync::StartProcess(const char* executable, const char* args) {
  std::string proc;
  proc.append(executable);
  proc.append(" ");
  proc.append(args);
  std::cout << "Starting " << proc << std::endl;
#ifdef _WIN32
  STARTUPINFO start_info;
  PROCESS_INFORMATION proc_info;
  GetStartupInfo(&start_info);
  if (!CreateProcess(nullptr, const_cast<char*>(proc.c_str()), nullptr, nullptr, FALSE,
                CREATE_NO_WINDOW | DETACHED_PROCESS, nullptr, nullptr,
                &start_info, &proc_info))
    return;
#else
  int pid = fork();
  if (pid != 0) {   // The father process returns
  } else {
#ifdef __linux__
    // Make sure the java process terminates on exit, since its
    // broken socket detection seems to be useless.
    prctl(PR_SET_PDEATHSIG, 2, 0, 0, 0);
#endif
    char* mutable_args = strdup(args);
    int argc = 1;
    for (int i = 0; mutable_args[i]; ++i) {
      if (mutable_args[i] == ' ') {
        ++argc;
      }
    }
    std::unique_ptr<char*[]> argv(new char*[argc + 2]);
    argv[0] = strdup(executable);
    argv[1] = mutable_args;
    argc = 2;
    bool inquote = false;
    for (int i = 0; mutable_args[i]; ++i) {
      if (!inquote && mutable_args[i] == ' ') {
        mutable_args[i] = '\0';
        argv[argc++] = mutable_args + i + 1;
      } else if (mutable_args[i] == '"') {
        inquote = !inquote;
        mutable_args[i] = ' ';
      }
    }
    argv[argc] = nullptr;
    execvp(executable, argv.get());
    free(argv[0]);
    free(argv[1]);
  }
#endif
}

SVSemaphore::SVSemaphore() {
#ifdef _WIN32
  semaphore_ = CreateSemaphore(0, 0, 10, 0);
#elif defined(__APPLE__)
  char name[50];
  snprintf(name, sizeof(name), "%ld", random());
  sem_unlink(name);
  semaphore_ = sem_open(name, O_CREAT , S_IWUSR, 0);
  if (semaphore_ == SEM_FAILED) {
    perror("sem_open");
  }
#else
  sem_init(&semaphore_, 0, 0);
#endif
}

void SVSemaphore::Signal() {
#ifdef _WIN32
  ReleaseSemaphore(semaphore_, 1, nullptr);
#elif defined(__APPLE__)
  sem_post(semaphore_);
#else
  sem_post(&semaphore_);
#endif
}

void SVSemaphore::Wait() {
#ifdef _WIN32
  WaitForSingleObject(semaphore_, INFINITE);
#elif defined(__APPLE__)
  sem_wait(semaphore_);
#else
  sem_wait(&semaphore_);
#endif
}

// Place a message in the message buffer (and flush it).
void SVNetwork::Send(const char* msg) {
  mutex_send_.Lock();
  msg_buffer_out_.append(msg);
  mutex_send_.Unlock();
}

// Send the whole buffer.
void SVNetwork::Flush() {
  mutex_send_.Lock();
  while (!msg_buffer_out_.empty()) {
    int i = send(stream_, msg_buffer_out_.c_str(), msg_buffer_out_.length(), 0);
    msg_buffer_out_.erase(0, i);
  }
  mutex_send_.Unlock();
}

// Receive a message from the server.
// This will always return one line of char* (denoted by \n).
char* SVNetwork::Receive() {
  char* result = nullptr;
#if defined(_WIN32) || defined(__CYGWIN__)
  if (has_content) { result = strtok (nullptr, "\n"); }
#else
  if (buffer_ptr_ != nullptr) { result = strtok_r(nullptr, "\n", &buffer_ptr_); }
#endif

  // This means there is something left in the buffer and we return it.
  if (result != nullptr) { return result;
  // Otherwise, we read from the stream_.
  } else {
    buffer_ptr_ = nullptr;
    has_content = false;

    // The timeout length is not really important since we are looping anyway
    // until a new message is delivered.
    struct timeval tv;
    tv.tv_sec = 10;
    tv.tv_usec = 0;

    // Set the flags to return when the stream_ is ready to be read.
    fd_set readfds;
    FD_ZERO(&readfds);
    FD_SET(stream_, &readfds);

    int i = select(stream_+1, &readfds, nullptr, nullptr, &tv);

    // The stream_ died.
    if (i == 0) { return nullptr; }

    // Read the message buffer.
    i = recv(stream_, msg_buffer_in_, kMaxMsgSize, 0);

    // Server quit (0) or error (-1).
    if (i <= 0) { return nullptr; }
    msg_buffer_in_[i] = '\0';
    has_content = true;
#ifdef _WIN32
    return strtok(msg_buffer_in_, "\n");
#else
    // Setup a new string tokenizer.
    return strtok_r(msg_buffer_in_, "\n", &buffer_ptr_);
#endif
  }
}

// Close the connection to the server.
void SVNetwork::Close() {
#ifdef _WIN32
  closesocket(stream_);
#else
  close(stream_);
#endif
  // Mark stream_ as invalid.
  stream_ = -1;
}

// The program to invoke to start ScrollView
static const char* ScrollViewProg() {
#ifdef _WIN32
  const char* prog = "java -Xms512m -Xmx1024m";
#else
  const char* prog = "sh";
#endif
  return prog;
}

// The arguments to the program to invoke to start ScrollView
static std::string ScrollViewCommand(std::string scrollview_path) {
  // The following ugly ifdef is to enable the output of the java runtime
  // to be sent down a black hole on non-windows to ignore all the
  // exceptions in piccolo. Ideally piccolo would be debugged to make
  // this unnecessary.
  // Also the path has to be separated by ; on windows and : otherwise.
#ifdef _WIN32
  const char cmd_template[] = "-Djava.library.path=%s -jar %s/ScrollView.jar";

#else
  const char cmd_template[] =
      "-c \"trap 'kill %%1' 0 1 2 ; java "
      "-Xms1024m -Xmx2048m -jar %s/ScrollView.jar"
      " & wait\"";
#endif
  size_t cmdlen = sizeof(cmd_template) + 2 * scrollview_path.size() + 1;
  std::vector<char> cmd(cmdlen);
  const char* sv_path = scrollview_path.c_str();
#ifdef _WIN32
  snprintf(&cmd[0], cmdlen, cmd_template, sv_path, sv_path);
#else
  snprintf(&cmd[0], cmdlen, cmd_template, sv_path);
#endif
  std::string command(&cmd[0]);
  return command;
}

// Platform-independent freeaddrinfo()
static void FreeAddrInfo(struct addrinfo* addr_info) {
  #if defined(__linux__)
  freeaddrinfo(addr_info);
  #else
  delete addr_info->ai_addr;
  delete addr_info;
  #endif
}

// Non-linux version of getaddrinfo()
#if !defined(__linux__)
static int GetAddrInfoNonLinux(const char* hostname, int port,
                               struct addrinfo** addr_info) {
// Get the host data depending on the OS.
  struct sockaddr_in* address;
  *addr_info = new struct addrinfo;
  memset(*addr_info, 0, sizeof(struct addrinfo));
  address = new struct sockaddr_in;
  memset(address, 0, sizeof(struct sockaddr_in));

  (*addr_info)->ai_addr = (struct sockaddr*) address;
  (*addr_info)->ai_addrlen = sizeof(struct sockaddr);
  (*addr_info)->ai_family = AF_INET;
  (*addr_info)->ai_socktype = SOCK_STREAM;

  struct hostent *name;
#ifdef _WIN32
  WSADATA wsaData;
  WSAStartup(MAKEWORD(1, 1), &wsaData);
  name = gethostbyname(hostname);
#else
  name = gethostbyname(hostname);
#endif

  if (name == nullptr) {
    FreeAddrInfo(*addr_info);
    *addr_info = nullptr;
    return -1;
  }

  // Fill in the appropriate variables to be able to connect to the server.
  address->sin_family = name->h_addrtype;
  memcpy(&address->sin_addr.s_addr, name->h_addr_list[0], name->h_length);
  address->sin_port = htons(port);
  return 0;
}
#endif

// Platform independent version of getaddrinfo()
//   Given a hostname:port, produce an addrinfo struct
static int GetAddrInfo(const char* hostname, int port,
                       struct addrinfo** address) {
#if defined(__linux__)
  char port_str[40];
  snprintf(port_str, 40, "%d", port);
  return getaddrinfo(hostname, port_str, nullptr, address);
#else
  return GetAddrInfoNonLinux(hostname, port, address);
#endif
}

// Set up a connection to a ScrollView on hostname:port.
SVNetwork::SVNetwork(const char* hostname, int port) {
  msg_buffer_in_ = new char[kMaxMsgSize + 1];
  msg_buffer_in_[0] = '\0';

  has_content = false;
  buffer_ptr_ = nullptr;

  struct addrinfo *addr_info = nullptr;

  if (GetAddrInfo(hostname, port, &addr_info) != 0) {
    std::cerr << "Error resolving name for ScrollView host "
              << std::string(hostname) << ":" << port << std::endl;
  }

  stream_ = socket(addr_info->ai_family, addr_info->ai_socktype,
                   addr_info->ai_protocol);

  if (stream_ < 0) {
    std::cerr << "Failed to open socket" << std::endl;
  } else if (connect(stream_, addr_info->ai_addr, addr_info->ai_addrlen) < 0) {
    // If server is not there, we will start a new server as local child process.
    const char* scrollview_path = getenv("SCROLLVIEW_PATH");
    if (scrollview_path == nullptr) {
#ifdef SCROLLVIEW_PATH
#define _STR(a) #a
#define _XSTR(a) _STR(a)
      scrollview_path = _XSTR(SCROLLVIEW_PATH);
#undef _XSTR
#undef _STR
#else
      scrollview_path = ".";
#endif
    }
    const char *prog = ScrollViewProg();
    std::string command = ScrollViewCommand(scrollview_path);
    SVSync::StartProcess(prog, command.c_str());

    // Wait for server to show up.
    // Note: There is no exception handling in case the server never turns up.

    Close();
    for (;;) {
      stream_ = socket(addr_info->ai_family, addr_info->ai_socktype,
                       addr_info->ai_protocol);
      if (stream_ >= 0) {
        if (connect(stream_, addr_info->ai_addr, addr_info->ai_addrlen) == 0) {
          break;
        }

        Close();

        std::cout << "ScrollView: Waiting for server...\n";
#ifdef _WIN32
        Sleep(1000);
#else
        sleep(1);
#endif
      }
    }
  }
  FreeAddrInfo(addr_info);
}

SVNetwork::~SVNetwork() {
  Close();
  delete[] msg_buffer_in_;
}

#endif  // GRAPHICS_DISABLED
<commit_msg>Fix build for Windows<commit_after>///////////////////////////////////////////////////////////////////////
// File:        svutil.cpp
// Description: ScrollView Utilities
// Author:      Joern Wanke
//
// (C) Copyright 2007, Google Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////
//
// SVUtil contains the SVSync and SVNetwork classes, which are used for
// thread/process creation & synchronization and network connection.

// Include automatically generated configuration file if running autoconf.
#ifdef HAVE_CONFIG_H
#  include "config_auto.h"
#endif

#include "svutil.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <memory>
#include <string>
#include <vector>

#ifdef _WIN32
#pragma comment(lib, "Ws2_32.lib")
#  include <winsock2.h>  // for fd_set, send, ..
#  include <ws2tcpip.h>  // for addrinfo
#else
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <pthread.h>
#include <semaphore.h>
#include <csignal>
#include <sys/select.h>
#include <sys/socket.h>
#ifdef __linux__
#include <sys/prctl.h>
#endif
#include <unistd.h>
#endif

SVMutex::SVMutex() {
#ifdef _WIN32
  mutex_ = CreateMutex(0, FALSE, 0);
#else
  pthread_mutex_init(&mutex_, nullptr);
#endif
}

void SVMutex::Lock() {
#ifdef _WIN32
  WaitForSingleObject(mutex_, INFINITE);
#else
  pthread_mutex_lock(&mutex_);
#endif
}

void SVMutex::Unlock() {
#ifdef _WIN32
  ReleaseMutex(mutex_);
#else
  pthread_mutex_unlock(&mutex_);
#endif
}

// Create new thread.
void SVSync::StartThread(void* (*func)(void*), void* arg) {
#ifdef _WIN32
  LPTHREAD_START_ROUTINE f = (LPTHREAD_START_ROUTINE)func;
  DWORD threadid;
  HANDLE newthread = CreateThread(nullptr,        // default security attributes
                                  0,           // use default stack size
                                  f,           // thread function
                                  arg,         // argument to thread function
                                  0,           // use default creation flags
                                  &threadid);  // returns the thread identifier
#else
  pthread_t helper;
  pthread_attr_t attr;
  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  pthread_create(&helper, &attr, func, arg);
#endif
}

#ifndef GRAPHICS_DISABLED

const int kMaxMsgSize = 4096;

// Signals a thread to exit.
void SVSync::ExitThread() {
#ifdef _WIN32
  // ExitThread(0);
#else
  pthread_exit(nullptr);
#endif
}

// Starts a new process.
void SVSync::StartProcess(const char* executable, const char* args) {
  std::string proc;
  proc.append(executable);
  proc.append(" ");
  proc.append(args);
  std::cout << "Starting " << proc << std::endl;
#ifdef _WIN32
  STARTUPINFO start_info;
  PROCESS_INFORMATION proc_info;
  GetStartupInfo(&start_info);
  if (!CreateProcess(nullptr, const_cast<char*>(proc.c_str()), nullptr, nullptr, FALSE,
                CREATE_NO_WINDOW | DETACHED_PROCESS, nullptr, nullptr,
                &start_info, &proc_info))
    return;
#else
  int pid = fork();
  if (pid != 0) {   // The father process returns
  } else {
#ifdef __linux__
    // Make sure the java process terminates on exit, since its
    // broken socket detection seems to be useless.
    prctl(PR_SET_PDEATHSIG, 2, 0, 0, 0);
#endif
    char* mutable_args = strdup(args);
    int argc = 1;
    for (int i = 0; mutable_args[i]; ++i) {
      if (mutable_args[i] == ' ') {
        ++argc;
      }
    }
    std::unique_ptr<char*[]> argv(new char*[argc + 2]);
    argv[0] = strdup(executable);
    argv[1] = mutable_args;
    argc = 2;
    bool inquote = false;
    for (int i = 0; mutable_args[i]; ++i) {
      if (!inquote && mutable_args[i] == ' ') {
        mutable_args[i] = '\0';
        argv[argc++] = mutable_args + i + 1;
      } else if (mutable_args[i] == '"') {
        inquote = !inquote;
        mutable_args[i] = ' ';
      }
    }
    argv[argc] = nullptr;
    execvp(executable, argv.get());
    free(argv[0]);
    free(argv[1]);
  }
#endif
}

SVSemaphore::SVSemaphore() {
#ifdef _WIN32
  semaphore_ = CreateSemaphore(0, 0, 10, 0);
#elif defined(__APPLE__)
  char name[50];
  snprintf(name, sizeof(name), "%ld", random());
  sem_unlink(name);
  semaphore_ = sem_open(name, O_CREAT , S_IWUSR, 0);
  if (semaphore_ == SEM_FAILED) {
    perror("sem_open");
  }
#else
  sem_init(&semaphore_, 0, 0);
#endif
}

void SVSemaphore::Signal() {
#ifdef _WIN32
  ReleaseSemaphore(semaphore_, 1, nullptr);
#elif defined(__APPLE__)
  sem_post(semaphore_);
#else
  sem_post(&semaphore_);
#endif
}

void SVSemaphore::Wait() {
#ifdef _WIN32
  WaitForSingleObject(semaphore_, INFINITE);
#elif defined(__APPLE__)
  sem_wait(semaphore_);
#else
  sem_wait(&semaphore_);
#endif
}

// Place a message in the message buffer (and flush it).
void SVNetwork::Send(const char* msg) {
  mutex_send_.Lock();
  msg_buffer_out_.append(msg);
  mutex_send_.Unlock();
}

// Send the whole buffer.
void SVNetwork::Flush() {
  mutex_send_.Lock();
  while (!msg_buffer_out_.empty()) {
    int i = send(stream_, msg_buffer_out_.c_str(), msg_buffer_out_.length(), 0);
    msg_buffer_out_.erase(0, i);
  }
  mutex_send_.Unlock();
}

// Receive a message from the server.
// This will always return one line of char* (denoted by \n).
char* SVNetwork::Receive() {
  char* result = nullptr;
#if defined(_WIN32) || defined(__CYGWIN__)
  if (has_content) { result = strtok (nullptr, "\n"); }
#else
  if (buffer_ptr_ != nullptr) { result = strtok_r(nullptr, "\n", &buffer_ptr_); }
#endif

  // This means there is something left in the buffer and we return it.
  if (result != nullptr) { return result;
  // Otherwise, we read from the stream_.
  } else {
    buffer_ptr_ = nullptr;
    has_content = false;

    // The timeout length is not really important since we are looping anyway
    // until a new message is delivered.
    struct timeval tv;
    tv.tv_sec = 10;
    tv.tv_usec = 0;

    // Set the flags to return when the stream_ is ready to be read.
    fd_set readfds;
    FD_ZERO(&readfds);
    FD_SET(stream_, &readfds);

    int i = select(stream_+1, &readfds, nullptr, nullptr, &tv);

    // The stream_ died.
    if (i == 0) { return nullptr; }

    // Read the message buffer.
    i = recv(stream_, msg_buffer_in_, kMaxMsgSize, 0);

    // Server quit (0) or error (-1).
    if (i <= 0) { return nullptr; }
    msg_buffer_in_[i] = '\0';
    has_content = true;
#ifdef _WIN32
    return strtok(msg_buffer_in_, "\n");
#else
    // Setup a new string tokenizer.
    return strtok_r(msg_buffer_in_, "\n", &buffer_ptr_);
#endif
  }
}

// Close the connection to the server.
void SVNetwork::Close() {
#ifdef _WIN32
  closesocket(stream_);
#else
  close(stream_);
#endif
  // Mark stream_ as invalid.
  stream_ = -1;
}

// The program to invoke to start ScrollView
static const char* ScrollViewProg() {
#ifdef _WIN32
  const char* prog = "java -Xms512m -Xmx1024m";
#else
  const char* prog = "sh";
#endif
  return prog;
}

// The arguments to the program to invoke to start ScrollView
static std::string ScrollViewCommand(std::string scrollview_path) {
  // The following ugly ifdef is to enable the output of the java runtime
  // to be sent down a black hole on non-windows to ignore all the
  // exceptions in piccolo. Ideally piccolo would be debugged to make
  // this unnecessary.
  // Also the path has to be separated by ; on windows and : otherwise.
#ifdef _WIN32
  const char cmd_template[] = "-Djava.library.path=%s -jar %s/ScrollView.jar";

#else
  const char cmd_template[] =
      "-c \"trap 'kill %%1' 0 1 2 ; java "
      "-Xms1024m -Xmx2048m -jar %s/ScrollView.jar"
      " & wait\"";
#endif
  size_t cmdlen = sizeof(cmd_template) + 2 * scrollview_path.size() + 1;
  std::vector<char> cmd(cmdlen);
  const char* sv_path = scrollview_path.c_str();
#ifdef _WIN32
  snprintf(&cmd[0], cmdlen, cmd_template, sv_path, sv_path);
#else
  snprintf(&cmd[0], cmdlen, cmd_template, sv_path);
#endif
  std::string command(&cmd[0]);
  return command;
}

// Platform-independent freeaddrinfo()
static void TessFreeAddrInfo(struct addrinfo* addr_info) {
  #if defined(__linux__)
  freeaddrinfo(addr_info);
  #else
  delete addr_info->ai_addr;
  delete addr_info;
  #endif
}

// Non-linux version of getaddrinfo()
#if !defined(__linux__)
static int GetAddrInfoNonLinux(const char* hostname, int port,
                               struct addrinfo** addr_info) {
// Get the host data depending on the OS.
  struct sockaddr_in* address;
  *addr_info = new struct addrinfo;
  memset(*addr_info, 0, sizeof(struct addrinfo));
  address = new struct sockaddr_in;
  memset(address, 0, sizeof(struct sockaddr_in));

  (*addr_info)->ai_addr = (struct sockaddr*) address;
  (*addr_info)->ai_addrlen = sizeof(struct sockaddr);
  (*addr_info)->ai_family = AF_INET;
  (*addr_info)->ai_socktype = SOCK_STREAM;

  struct hostent *name;
#ifdef _WIN32
  WSADATA wsaData;
  WSAStartup(MAKEWORD(1, 1), &wsaData);
  name = gethostbyname(hostname);
#else
  name = gethostbyname(hostname);
#endif

  if (name == nullptr) {
    TessFreeAddrInfo(*addr_info);
    *addr_info = nullptr;
    return -1;
  }

  // Fill in the appropriate variables to be able to connect to the server.
  address->sin_family = name->h_addrtype;
  memcpy(&address->sin_addr.s_addr, name->h_addr_list[0], name->h_length);
  address->sin_port = htons(port);
  return 0;
}
#endif

// Platform independent version of getaddrinfo()
//   Given a hostname:port, produce an addrinfo struct
static int GetAddrInfo(const char* hostname, int port,
                       struct addrinfo** address) {
#if defined(__linux__)
  char port_str[40];
  snprintf(port_str, 40, "%d", port);
  return getaddrinfo(hostname, port_str, nullptr, address);
#else
  return GetAddrInfoNonLinux(hostname, port, address);
#endif
}

// Set up a connection to a ScrollView on hostname:port.
SVNetwork::SVNetwork(const char* hostname, int port) {
  msg_buffer_in_ = new char[kMaxMsgSize + 1];
  msg_buffer_in_[0] = '\0';

  has_content = false;
  buffer_ptr_ = nullptr;

  struct addrinfo *addr_info = nullptr;

  if (GetAddrInfo(hostname, port, &addr_info) != 0) {
    std::cerr << "Error resolving name for ScrollView host "
              << std::string(hostname) << ":" << port << std::endl;
  }

  stream_ = socket(addr_info->ai_family, addr_info->ai_socktype,
                   addr_info->ai_protocol);

  if (stream_ < 0) {
    std::cerr << "Failed to open socket" << std::endl;
  } else if (connect(stream_, addr_info->ai_addr, addr_info->ai_addrlen) < 0) {
    // If server is not there, we will start a new server as local child process.
    const char* scrollview_path = getenv("SCROLLVIEW_PATH");
    if (scrollview_path == nullptr) {
#ifdef SCROLLVIEW_PATH
#define _STR(a) #a
#define _XSTR(a) _STR(a)
      scrollview_path = _XSTR(SCROLLVIEW_PATH);
#undef _XSTR
#undef _STR
#else
      scrollview_path = ".";
#endif
    }
    const char *prog = ScrollViewProg();
    std::string command = ScrollViewCommand(scrollview_path);
    SVSync::StartProcess(prog, command.c_str());

    // Wait for server to show up.
    // Note: There is no exception handling in case the server never turns up.

    Close();
    for (;;) {
      stream_ = socket(addr_info->ai_family, addr_info->ai_socktype,
                       addr_info->ai_protocol);
      if (stream_ >= 0) {
        if (connect(stream_, addr_info->ai_addr, addr_info->ai_addrlen) == 0) {
          break;
        }

        Close();

        std::cout << "ScrollView: Waiting for server...\n";
#ifdef _WIN32
        Sleep(1000);
#else
        sleep(1);
#endif
      }
    }
  }
  TessFreeAddrInfo(addr_info);
}

SVNetwork::~SVNetwork() {
  Close();
  delete[] msg_buffer_in_;
}

#endif  // GRAPHICS_DISABLED
<|endoftext|>


<commit_before>/*
 * ty, a collection of GUI and command-line tools to manage Teensy devices
 *
 * Distributed under the MIT license (see LICENSE.txt or http://opensource.org/licenses/MIT)
 * Copyright (c) 2015 Niels Martignène <niels.martignene@gmail.com>
 */

#include <QDesktopServices>
#include <QFileDialog>
#include <QScrollBar>
#include <QToolButton>
#include <QUrl>

#include "ty.h"
#include "about_dialog.hh"
#include "board_widget.hh"
#include "commands.hh"
#include "main_window.hh"
#include "tyqt.hh"

using namespace std;

MainWindow::MainWindow(Manager *manager, QWidget *parent)
    : QMainWindow(parent), manager_(manager)
{
    setupUi(this);
    refreshBoardsInfo();

    connect(actionQuit, &QAction::triggered, TyQt::instance(), &TyQt::quit);

    boardList->setModel(manager);
    boardList->setItemDelegate(new BoardItemDelegate(manager));
    connect(boardList->selectionModel(), &QItemSelectionModel::selectionChanged, this, &MainWindow::selectionChanged);
    connect(manager, &Manager::boardAdded, this, &MainWindow::setBoardDefaults);

    monitorText->setWordWrapMode(QTextOption::WrapAnywhere);
    connect(monitorText, &QPlainTextEdit::textChanged, this, &MainWindow::monitorTextChanged);
    connect(monitorText, &QPlainTextEdit::updateRequest, this, &MainWindow::monitorTextScrolled);

    logText->setMaximumBlockCount(1000);

    for (auto &board: *manager)
        setBoardDefaults(board.get());
}

QString MainWindow::makeFirmwareFilter()
{
    QString exts;
    for (auto format = tyb_firmware_formats; format->name; format++)
        exts += QString("*%1 ").arg(format->ext);
    exts.chop(1);

    return tr("Binary Files (%1);;All Files (*)").arg(exts);
}

void MainWindow::setBoardDefaults(Board *board)
{
    board->setProperty("resetAfter", true);

    if (!boardList->currentIndex().isValid() && manager_->boardCount())
        boardList->setCurrentIndex(manager_->index(0, 0));
}

void MainWindow::selectionChanged(const QItemSelection &newsel, const QItemSelection &previous)
{
    TY_UNUSED(newsel);
    TY_UNUSED(previous);

    monitorText->setDocument(nullptr);
    if (current_board_) {
        current_board_->disconnect(this);
        current_board_ = nullptr;
    }

    selected_boards_.clear();
    auto selected = boardList->selectionModel()->selection();
    for (auto &idx: selected.indexes())
        selected_boards_.push_back(manager_->board(idx.row()));

    if (selected_boards_.size() == 1) {
        current_board_ = selected_boards_.front();

        firmwarePath->setText(current_board_->firmware());
        resetAfterUpload->setChecked(current_board_->property("resetAfter").toBool());
        clearOnReset->setChecked(current_board_->clearOnReset());

        monitor_autoscroll_ = true;
        monitor_cursor_ = QTextCursor();
        monitorText->setDocument(&current_board_->serialDocument());
        monitorText->moveCursor(QTextCursor::End);
        monitorText->verticalScrollBar()->setValue(monitorText->verticalScrollBar()->maximum());

        connect(current_board_.get(), &Board::boardChanged, this, &MainWindow::refreshBoardsInfo);
        connect(current_board_.get(), &Board::propertyChanged, this, &MainWindow::updatePropertyField);
    } else {
        firmwarePath->clear();
    }

    refreshBoardsInfo();
}

void MainWindow::refreshBoardsInfo()
{
    if (current_board_) {
        setWindowTitle(QString("TyQt - %1 - %2")
                       .arg(current_board_->modelName())
                       .arg(current_board_->tag()));

        infoTab->setEnabled(true);
        modelText->setText(current_board_->modelName());
        locationText->setText(current_board_->location());
        serialText->setText(QString::number(current_board_->serialNumber()));

        interfaceTree->clear();
        for (auto iface: current_board_->interfaces()) {
            auto item = new QTreeWidgetItem(QStringList{iface.desc, iface.path});
            item->setToolTip(1, iface.path);

            new QTreeWidgetItem(item, QStringList{tr("capabilities"),
                                Board::makeCapabilityList(current_board_->capabilities()).join(", ")});
            new QTreeWidgetItem(item, QStringList{tr("location"),
                                QString("%1:%2").arg(current_board_->location(), QString::number(iface.number))});

            interfaceTree->addTopLevelItem(item);
        }

        monitorTab->setEnabled(true);
        monitorEdit->setEnabled(current_board_->isSerialAvailable());
        actionClearMonitor->setEnabled(true);
        uploadTab->setEnabled(true);
    } else {
        setWindowTitle("TyQt");

        infoTab->setEnabled(false);
        modelText->clear();
        locationText->clear();
        serialText->clear();
        interfaceTree->clear();

        monitorTab->setEnabled(false);
        actionClearMonitor->setEnabled(false);
        uploadTab->setEnabled(false);
    }

    bool upload = false, reset = false, reboot = false;
    for (auto &board: selected_boards_) {
        upload |= board->isUploadAvailable();
        reset |= board->isResetAvailable();
        reboot |= board->isRebootAvailable();
    }
    actionUpload->setEnabled(upload);
    actionUploadNew->setEnabled(upload);
    actionReset->setEnabled(reset);
    actionReboot->setEnabled(reboot);
}

void MainWindow::updatePropertyField(const QByteArray &name, const QVariant &value)
{
    if (name == "firmware") {
        firmwarePath->setText(value.toString());
    } else if (name == "resetAfter") {
        resetAfterUpload->setChecked(value.toBool());
    } else if (name == "clearOnReset") {
        clearOnReset->setChecked(value.toBool());
    }
}

void MainWindow::monitorTextChanged()
{
    if (monitor_autoscroll_) {
        monitorText->verticalScrollBar()->setValue(monitorText->verticalScrollBar()->maximum());
    } else {
        QTextCursor old_cursor = monitorText->textCursor();

        monitorText->setTextCursor(monitor_cursor_);
        monitorText->ensureCursorVisible();

        int position = monitorText->verticalScrollBar()->value();

        monitorText->setTextCursor(old_cursor);
        monitorText->verticalScrollBar()->setValue(position);
    }
}

void MainWindow::monitorTextScrolled(const QRect &rect, int dy)
{
    TY_UNUSED(rect);

    if (!dy)
        return;

    QScrollBar *vbar = monitorText->verticalScrollBar();

    monitor_autoscroll_ = vbar->value() >= vbar->maximum() - 1;
    monitor_cursor_ = monitorText->cursorForPosition(QPoint(0, 0));
}

void MainWindow::clearMonitor()
{
    monitor_cursor_ = QTextCursor();
    monitorText->clear();
}

void MainWindow::showErrorMessage(const QString &msg)
{
    statusBar()->showMessage(msg, SHOW_ERROR_TIMEOUT);
    logText->appendPlainText(msg);
}

void MainWindow::on_firmwarePath_editingFinished()
{
    if (!current_board_)
        return;

    if (!firmwarePath->text().isEmpty()) {
        QString firmware = QFileInfo(firmwarePath->text()).canonicalFilePath();
        if (firmware.isEmpty()) {
            tyQt->reportError(tr("Path '%1' is not valid").arg(firmwarePath->text()));
            return;
        }

        current_board_->setFirmware(firmware);
    } else {
        current_board_->setFirmware("");
    }
}

void MainWindow::on_resetAfterUpload_toggled(bool checked)
{
    if (!current_board_)
        return;

    current_board_->setProperty("resetAfter", checked);
}

void MainWindow::on_actionNewWindow_triggered()
{
    tyQt->openMainWindow();
}

void MainWindow::on_actionUpload_triggered()
{
    if (current_board_ && current_board_->firmware().isEmpty()) {
        on_actionUploadNew_triggered();
        return;
    }

    unsigned int uploaded = 0;
    for (auto &board: selected_boards_) {
        if (!board->firmware().isEmpty()) {
            board->upload({Firmware::load(board->firmware())},
                          board->property("resetAfter").toBool()).start();
            uploaded++;
        }
    }
    if (!uploaded)
        tyQt->reportError("No board has a set firmware, try using 'Upload New Firmware'");
}

void MainWindow::on_actionUploadNew_triggered()
{
    auto filenames = QFileDialog::getOpenFileNames(this, tr("Open Firmwares"), "",
                                                   makeFirmwareFilter());
    if (filenames.isEmpty())
        return;

    vector<shared_ptr<Firmware>> fws;
    fws.reserve(filenames.count());
    for (auto filename: filenames)
        fws.push_back(Firmware::load(filename));

    for (auto &board: selected_boards_)
        board->upload(fws, board->property("resetAfter").toBool()).start();
}

void MainWindow::on_actionReset_triggered()
{
    for (auto &board: selected_boards_)
        board->reset().start();
}

void MainWindow::on_actionReboot_triggered()
{
    for (auto &board: selected_boards_)
        board->reboot().start();
}

void MainWindow::on_monitorEdit_returnPressed()
{
    if (!current_board_)
        return;

    QString s = monitorEdit->text();
    monitorEdit->clear();

    switch (newlineComboBox->currentIndex()) {
    case 1:
        s += '\n';
        break;
    case 2:
        s += '\r';
        break;
    case 3:
        s += "\r\n";
        break;

    default:
        break;
    }

    if (echo->isChecked())
        current_board_->appendToSerialDocument(s);

    current_board_->sendSerial(s.toUtf8());
}

void MainWindow::on_clearOnReset_toggled(bool checked)
{
    if (!current_board_)
        return;

    current_board_->setClearOnReset(checked);
}

void MainWindow::on_actionMinimalInterface_toggled(bool checked)
{
    toolBar->setVisible(!checked);
    boardList->setVisible(!checked);
    statusbar->setVisible(!checked);
}

void MainWindow::on_actionClearMonitor_triggered()
{
    clearMonitor();
}

void MainWindow::on_firmwareBrowseButton_clicked()
{
    auto filename = QFileDialog::getOpenFileName(this, tr("Open Firmware"), "",
                                                 makeFirmwareFilter());
    if (filename.isEmpty())
        return;

    firmwarePath->setText(filename);
    emit firmwarePath->editingFinished();
}

void MainWindow::on_monitorText_customContextMenuRequested(const QPoint &pos)
{
    QMenu *menu = monitorText->createStandardContextMenu();

    menu->addAction(actionClearMonitor);
    menu->exec(monitorText->viewport()->mapToGlobal(pos));
}

void MainWindow::on_logText_customContextMenuRequested(const QPoint &pos)
{
    QMenu *menu = logText->createStandardContextMenu();

    menu->addAction(tr("Clear"), logText, SLOT(clear()));
    menu->exec(logText->viewport()->mapToGlobal(pos));
}

void MainWindow::on_actionWebsite_triggered()
{
    QDesktopServices::openUrl(QUrl("https://github.com/Koromix/ty/"));
}

void MainWindow::on_actionReportBug_triggered()
{
    QDesktopServices::openUrl(QUrl("https://github.com/Koromix/ty/issues"));
}

void MainWindow::on_actionAbout_triggered()
{
    AboutDialog(this).exec();
}
<commit_msg>Avoid duplicate selected boards in TyQt<commit_after>/*
 * ty, a collection of GUI and command-line tools to manage Teensy devices
 *
 * Distributed under the MIT license (see LICENSE.txt or http://opensource.org/licenses/MIT)
 * Copyright (c) 2015 Niels Martignène <niels.martignene@gmail.com>
 */

#include <QDesktopServices>
#include <QFileDialog>
#include <QScrollBar>
#include <QToolButton>
#include <QUrl>

#include "ty.h"
#include "about_dialog.hh"
#include "board_widget.hh"
#include "commands.hh"
#include "main_window.hh"
#include "tyqt.hh"

using namespace std;

MainWindow::MainWindow(Manager *manager, QWidget *parent)
    : QMainWindow(parent), manager_(manager)
{
    setupUi(this);
    refreshBoardsInfo();

    connect(actionQuit, &QAction::triggered, TyQt::instance(), &TyQt::quit);

    boardList->setModel(manager);
    boardList->setItemDelegate(new BoardItemDelegate(manager));
    connect(boardList->selectionModel(), &QItemSelectionModel::selectionChanged, this, &MainWindow::selectionChanged);
    connect(manager, &Manager::boardAdded, this, &MainWindow::setBoardDefaults);

    monitorText->setWordWrapMode(QTextOption::WrapAnywhere);
    connect(monitorText, &QPlainTextEdit::textChanged, this, &MainWindow::monitorTextChanged);
    connect(monitorText, &QPlainTextEdit::updateRequest, this, &MainWindow::monitorTextScrolled);

    logText->setMaximumBlockCount(1000);

    for (auto &board: *manager)
        setBoardDefaults(board.get());
}

QString MainWindow::makeFirmwareFilter()
{
    QString exts;
    for (auto format = tyb_firmware_formats; format->name; format++)
        exts += QString("*%1 ").arg(format->ext);
    exts.chop(1);

    return tr("Binary Files (%1);;All Files (*)").arg(exts);
}

void MainWindow::setBoardDefaults(Board *board)
{
    board->setProperty("resetAfter", true);

    if (!boardList->currentIndex().isValid() && manager_->boardCount())
        boardList->setCurrentIndex(manager_->index(0, 0));
}

void MainWindow::selectionChanged(const QItemSelection &newsel, const QItemSelection &previous)
{
    TY_UNUSED(newsel);
    TY_UNUSED(previous);

    monitorText->setDocument(nullptr);
    if (current_board_) {
        current_board_->disconnect(this);
        current_board_ = nullptr;
    }

    selected_boards_.clear();
    auto selected = boardList->selectionModel()->selectedIndexes();
    for (auto &idx: selected) {
        if (idx.column() == 0)
            selected_boards_.push_back(manager_->board(idx.row()));
    }

    if (selected_boards_.size() == 1) {
        current_board_ = selected_boards_.front();

        firmwarePath->setText(current_board_->firmware());
        resetAfterUpload->setChecked(current_board_->property("resetAfter").toBool());
        clearOnReset->setChecked(current_board_->clearOnReset());

        monitor_autoscroll_ = true;
        monitor_cursor_ = QTextCursor();
        monitorText->setDocument(&current_board_->serialDocument());
        monitorText->moveCursor(QTextCursor::End);
        monitorText->verticalScrollBar()->setValue(monitorText->verticalScrollBar()->maximum());

        connect(current_board_.get(), &Board::boardChanged, this, &MainWindow::refreshBoardsInfo);
        connect(current_board_.get(), &Board::propertyChanged, this, &MainWindow::updatePropertyField);
    } else {
        firmwarePath->clear();
    }

    refreshBoardsInfo();
}

void MainWindow::refreshBoardsInfo()
{
    if (current_board_) {
        setWindowTitle(QString("TyQt - %1 - %2")
                       .arg(current_board_->modelName())
                       .arg(current_board_->tag()));

        infoTab->setEnabled(true);
        modelText->setText(current_board_->modelName());
        locationText->setText(current_board_->location());
        serialText->setText(QString::number(current_board_->serialNumber()));

        interfaceTree->clear();
        for (auto iface: current_board_->interfaces()) {
            auto item = new QTreeWidgetItem(QStringList{iface.desc, iface.path});
            item->setToolTip(1, iface.path);

            new QTreeWidgetItem(item, QStringList{tr("capabilities"),
                                Board::makeCapabilityList(current_board_->capabilities()).join(", ")});
            new QTreeWidgetItem(item, QStringList{tr("location"),
                                QString("%1:%2").arg(current_board_->location(), QString::number(iface.number))});

            interfaceTree->addTopLevelItem(item);
        }

        monitorTab->setEnabled(true);
        monitorEdit->setEnabled(current_board_->isSerialAvailable());
        actionClearMonitor->setEnabled(true);
        uploadTab->setEnabled(true);
    } else {
        setWindowTitle("TyQt");

        infoTab->setEnabled(false);
        modelText->clear();
        locationText->clear();
        serialText->clear();
        interfaceTree->clear();

        monitorTab->setEnabled(false);
        actionClearMonitor->setEnabled(false);
        uploadTab->setEnabled(false);
    }

    bool upload = false, reset = false, reboot = false;
    for (auto &board: selected_boards_) {
        upload |= board->isUploadAvailable();
        reset |= board->isResetAvailable();
        reboot |= board->isRebootAvailable();
    }
    actionUpload->setEnabled(upload);
    actionUploadNew->setEnabled(upload);
    actionReset->setEnabled(reset);
    actionReboot->setEnabled(reboot);
}

void MainWindow::updatePropertyField(const QByteArray &name, const QVariant &value)
{
    if (name == "firmware") {
        firmwarePath->setText(value.toString());
    } else if (name == "resetAfter") {
        resetAfterUpload->setChecked(value.toBool());
    } else if (name == "clearOnReset") {
        clearOnReset->setChecked(value.toBool());
    }
}

void MainWindow::monitorTextChanged()
{
    if (monitor_autoscroll_) {
        monitorText->verticalScrollBar()->setValue(monitorText->verticalScrollBar()->maximum());
    } else {
        QTextCursor old_cursor = monitorText->textCursor();

        monitorText->setTextCursor(monitor_cursor_);
        monitorText->ensureCursorVisible();

        int position = monitorText->verticalScrollBar()->value();

        monitorText->setTextCursor(old_cursor);
        monitorText->verticalScrollBar()->setValue(position);
    }
}

void MainWindow::monitorTextScrolled(const QRect &rect, int dy)
{
    TY_UNUSED(rect);

    if (!dy)
        return;

    QScrollBar *vbar = monitorText->verticalScrollBar();

    monitor_autoscroll_ = vbar->value() >= vbar->maximum() - 1;
    monitor_cursor_ = monitorText->cursorForPosition(QPoint(0, 0));
}

void MainWindow::clearMonitor()
{
    monitor_cursor_ = QTextCursor();
    monitorText->clear();
}

void MainWindow::showErrorMessage(const QString &msg)
{
    statusBar()->showMessage(msg, SHOW_ERROR_TIMEOUT);
    logText->appendPlainText(msg);
}

void MainWindow::on_firmwarePath_editingFinished()
{
    if (!current_board_)
        return;

    if (!firmwarePath->text().isEmpty()) {
        QString firmware = QFileInfo(firmwarePath->text()).canonicalFilePath();
        if (firmware.isEmpty()) {
            tyQt->reportError(tr("Path '%1' is not valid").arg(firmwarePath->text()));
            return;
        }

        current_board_->setFirmware(firmware);
    } else {
        current_board_->setFirmware("");
    }
}

void MainWindow::on_resetAfterUpload_toggled(bool checked)
{
    if (!current_board_)
        return;

    current_board_->setProperty("resetAfter", checked);
}

void MainWindow::on_actionNewWindow_triggered()
{
    tyQt->openMainWindow();
}

void MainWindow::on_actionUpload_triggered()
{
    if (current_board_ && current_board_->firmware().isEmpty()) {
        on_actionUploadNew_triggered();
        return;
    }

    unsigned int uploaded = 0;
    for (auto &board: selected_boards_) {
        if (!board->firmware().isEmpty()) {
            board->upload({Firmware::load(board->firmware())},
                          board->property("resetAfter").toBool()).start();
            uploaded++;
        }
    }
    if (!uploaded)
        tyQt->reportError("No board has a set firmware, try using 'Upload New Firmware'");
}

void MainWindow::on_actionUploadNew_triggered()
{
    auto filenames = QFileDialog::getOpenFileNames(this, tr("Open Firmwares"), "",
                                                   makeFirmwareFilter());
    if (filenames.isEmpty())
        return;

    vector<shared_ptr<Firmware>> fws;
    fws.reserve(filenames.count());
    for (auto filename: filenames)
        fws.push_back(Firmware::load(filename));

    for (auto &board: selected_boards_)
        board->upload(fws, board->property("resetAfter").toBool()).start();
}

void MainWindow::on_actionReset_triggered()
{
    for (auto &board: selected_boards_)
        board->reset().start();
}

void MainWindow::on_actionReboot_triggered()
{
    for (auto &board: selected_boards_)
        board->reboot().start();
}

void MainWindow::on_monitorEdit_returnPressed()
{
    if (!current_board_)
        return;

    QString s = monitorEdit->text();
    monitorEdit->clear();

    switch (newlineComboBox->currentIndex()) {
    case 1:
        s += '\n';
        break;
    case 2:
        s += '\r';
        break;
    case 3:
        s += "\r\n";
        break;

    default:
        break;
    }

    if (echo->isChecked())
        current_board_->appendToSerialDocument(s);

    current_board_->sendSerial(s.toUtf8());
}

void MainWindow::on_clearOnReset_toggled(bool checked)
{
    if (!current_board_)
        return;

    current_board_->setClearOnReset(checked);
}

void MainWindow::on_actionMinimalInterface_toggled(bool checked)
{
    toolBar->setVisible(!checked);
    boardList->setVisible(!checked);
    statusbar->setVisible(!checked);
}

void MainWindow::on_actionClearMonitor_triggered()
{
    clearMonitor();
}

void MainWindow::on_firmwareBrowseButton_clicked()
{
    auto filename = QFileDialog::getOpenFileName(this, tr("Open Firmware"), "",
                                                 makeFirmwareFilter());
    if (filename.isEmpty())
        return;

    firmwarePath->setText(filename);
    emit firmwarePath->editingFinished();
}

void MainWindow::on_monitorText_customContextMenuRequested(const QPoint &pos)
{
    QMenu *menu = monitorText->createStandardContextMenu();

    menu->addAction(actionClearMonitor);
    menu->exec(monitorText->viewport()->mapToGlobal(pos));
}

void MainWindow::on_logText_customContextMenuRequested(const QPoint &pos)
{
    QMenu *menu = logText->createStandardContextMenu();

    menu->addAction(tr("Clear"), logText, SLOT(clear()));
    menu->exec(logText->viewport()->mapToGlobal(pos));
}

void MainWindow::on_actionWebsite_triggered()
{
    QDesktopServices::openUrl(QUrl("https://github.com/Koromix/ty/"));
}

void MainWindow::on_actionReportBug_triggered()
{
    QDesktopServices::openUrl(QUrl("https://github.com/Koromix/ty/issues"));
}

void MainWindow::on_actionAbout_triggered()
{
    AboutDialog(this).exec();
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/views/painter.h"

#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/gfx/insets.h"
#include "ui/gfx/nine_image_painter.h"
#include "ui/gfx/point.h"
#include "ui/gfx/rect.h"
#include "ui/views/view.h"

namespace views {

namespace {

// DashedFocusPainter ----------------------------------------------------------

class DashedFocusPainter : public Painter {
 public:
  explicit DashedFocusPainter(const gfx::Insets& insets);
  virtual ~DashedFocusPainter();

  // Painter:
  virtual gfx::Size GetMinimumSize() const OVERRIDE;
  virtual void Paint(gfx::Canvas* canvas, const gfx::Size& size) OVERRIDE;

 private:
  const gfx::Insets insets_;

  DISALLOW_COPY_AND_ASSIGN(DashedFocusPainter);
};

DashedFocusPainter::DashedFocusPainter(const gfx::Insets& insets)
    : insets_(insets) {
}

DashedFocusPainter::~DashedFocusPainter() {
}

gfx::Size DashedFocusPainter::GetMinimumSize() const {
  return gfx::Size();
}

void DashedFocusPainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) {
  gfx::Rect rect(size);
  rect.Inset(insets_);
  canvas->DrawFocusRect(rect);
}

// SolidFocusPainter -----------------------------------------------------------

class SolidFocusPainter : public Painter {
 public:
  SolidFocusPainter(SkColor color, const gfx::Insets& insets);
  virtual ~SolidFocusPainter();

  // Painter:
  virtual gfx::Size GetMinimumSize() const OVERRIDE;
  virtual void Paint(gfx::Canvas* canvas, const gfx::Size& size) OVERRIDE;

 private:
  const SkColor color_;
  const gfx::Insets insets_;

  DISALLOW_COPY_AND_ASSIGN(SolidFocusPainter);
};

SolidFocusPainter::SolidFocusPainter(SkColor color,
                                     const gfx::Insets& insets)
    : color_(color),
      insets_(insets) {
}

SolidFocusPainter::~SolidFocusPainter() {
}

gfx::Size SolidFocusPainter::GetMinimumSize() const {
  return gfx::Size();
}

void SolidFocusPainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) {
  gfx::Rect rect(size);
  rect.Inset(insets_);
  canvas->DrawSolidFocusRect(rect, color_);
}

// GradientPainter ------------------------------------------------------------

class GradientPainter : public Painter {
 public:
  GradientPainter(bool horizontal,
                  SkColor* colors,
                  SkScalar* pos,
                  size_t count);
  virtual ~GradientPainter();

  // Painter:
  virtual gfx::Size GetMinimumSize() const OVERRIDE;
  virtual void Paint(gfx::Canvas* canvas, const gfx::Size& size) OVERRIDE;

 private:
  // If |horizontal_| is true then the gradient is painted horizontally.
  bool horizontal_;
  // The gradient colors.
  scoped_ptr<SkColor[]> colors_;
  // The relative positions of the corresponding gradient colors.
  scoped_ptr<SkScalar[]> pos_;
  // The number of elements in |colors_| and |pos_|.
  size_t count_;

  DISALLOW_COPY_AND_ASSIGN(GradientPainter);
};

GradientPainter::GradientPainter(bool horizontal,
                                 SkColor* colors,
                                 SkScalar* pos,
                                 size_t count)
    : horizontal_(horizontal),
      colors_(new SkColor[count]),
      pos_(new SkScalar[count]),
      count_(count) {
  for (size_t i = 0; i < count_; ++i) {
    pos_[i] = pos[i];
    colors_[i] = colors[i];
  }
}

GradientPainter::~GradientPainter() {
}

gfx::Size GradientPainter::GetMinimumSize() const {
  return gfx::Size();
}

void GradientPainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) {
  SkPaint paint;
  SkPoint p[2];
  p[0].iset(0, 0);
  if (horizontal_)
    p[1].iset(size.width(), 0);
  else
    p[1].iset(0, size.height());

  skia::RefPtr<SkShader> s = skia::AdoptRef(SkGradientShader::CreateLinear(
      p, colors_.get(), pos_.get(), count_, SkShader::kClamp_TileMode));
  paint.setStyle(SkPaint::kFill_Style);
  paint.setShader(s.get());

  canvas->sk_canvas()->drawRectCoords(SkIntToScalar(0), SkIntToScalar(0),
                                      SkIntToScalar(size.width()),
                                      SkIntToScalar(size.height()), paint);
}

// ImagePainter ---------------------------------------------------------------

// ImagePainter stores and paints nine images as a scalable grid.
class VIEWS_EXPORT ImagePainter : public Painter {
 public:
  // Constructs an ImagePainter with the specified image resource ids.
  // See CreateImageGridPainter()'s comment regarding image ID count and order.
  explicit ImagePainter(const int image_ids[]);

  // Constructs an ImagePainter with the specified image and insets.
  ImagePainter(const gfx::ImageSkia& image, const gfx::Insets& insets);

  virtual ~ImagePainter();

  // Painter:
  virtual gfx::Size GetMinimumSize() const OVERRIDE;
  virtual void Paint(gfx::Canvas* canvas, const gfx::Size& size) OVERRIDE;

 private:
  scoped_ptr<gfx::NineImagePainter> nine_painter_;

  DISALLOW_COPY_AND_ASSIGN(ImagePainter);
};

ImagePainter::ImagePainter(const int image_ids[])
    : nine_painter_(ui::CreateNineImagePainter(image_ids)) {
}

ImagePainter::ImagePainter(const gfx::ImageSkia& image,
                           const gfx::Insets& insets)
    : nine_painter_(new gfx::NineImagePainter(image, insets)) {
}

ImagePainter::~ImagePainter() {
}

gfx::Size ImagePainter::GetMinimumSize() const {
  return nine_painter_->GetMinimumSize();
}

void ImagePainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) {
  nine_painter_->Paint(canvas, gfx::Rect(size));
}

}  // namespace

// Painter --------------------------------------------------------------------

Painter::Painter() {
}

Painter::~Painter() {
}

// static
void Painter::PaintPainterAt(gfx::Canvas* canvas,
                             Painter* painter,
                             const gfx::Rect& rect) {
  DCHECK(canvas && painter);
  canvas->Save();
  canvas->Translate(rect.OffsetFromOrigin());
  painter->Paint(canvas, rect.size());
  canvas->Restore();
}

// static
void Painter::PaintFocusPainter(View* view,
                                gfx::Canvas* canvas,
                                Painter* focus_painter) {
  if (focus_painter && view->HasFocus())
    PaintPainterAt(canvas, focus_painter, view->GetLocalBounds());
}

// static
Painter* Painter::CreateHorizontalGradient(SkColor c1, SkColor c2) {
  SkColor colors[2];
  colors[0] = c1;
  colors[1] = c2;
  SkScalar pos[] = {0, 1};
  return new GradientPainter(true, colors, pos, 2);
}

// static
Painter* Painter::CreateVerticalGradient(SkColor c1, SkColor c2) {
  SkColor colors[2];
  colors[0] = c1;
  colors[1] = c2;
  SkScalar pos[] = {0, 1};
  return new GradientPainter(false, colors, pos, 2);
}

// static
Painter* Painter::CreateVerticalMultiColorGradient(SkColor* colors,
                                                   SkScalar* pos,
                                                   size_t count) {
  return new GradientPainter(false, colors, pos, count);
}

// static
Painter* Painter::CreateImagePainter(const gfx::ImageSkia& image,
                                     const gfx::Insets& insets) {
  return new ImagePainter(image, insets);
}

// static
Painter* Painter::CreateImageGridPainter(const int image_ids[]) {
  return new ImagePainter(image_ids);
}

// static
scoped_ptr<Painter> Painter::CreateDashedFocusPainter() {
  return scoped_ptr<Painter>(new DashedFocusPainter(gfx::Insets())).Pass();
}

// static
scoped_ptr<Painter> Painter::CreateDashedFocusPainterWithInsets(
    const gfx::Insets& insets) {
  return scoped_ptr<Painter>(new DashedFocusPainter(insets)).Pass();
}

// static
scoped_ptr<Painter> Painter::CreateSolidFocusPainter(
    SkColor color,
    const gfx::Insets& insets) {
  return scoped_ptr<Painter>(new SolidFocusPainter(color, insets)).Pass();
}

// HorizontalPainter ----------------------------------------------------------

HorizontalPainter::HorizontalPainter(const int image_resource_names[]) {
  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
  for (int i = 0; i < 3; ++i)
    images_[i] = rb.GetImageNamed(image_resource_names[i]).ToImageSkia();
  DCHECK_EQ(images_[LEFT]->height(), images_[CENTER]->height());
  DCHECK_EQ(images_[LEFT]->height(), images_[RIGHT]->height());
}

HorizontalPainter::~HorizontalPainter() {
}

gfx::Size HorizontalPainter::GetMinimumSize() const {
  return gfx::Size(
      images_[LEFT]->width() + images_[CENTER]->width() +
          images_[RIGHT]->width(), images_[LEFT]->height());
}

void HorizontalPainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) {
  if (size.width() < GetMinimumSize().width())
    return;  // No room to paint.

  canvas->DrawImageInt(*images_[LEFT], 0, 0);
  canvas->DrawImageInt(*images_[RIGHT], size.width() - images_[RIGHT]->width(),
                       0);
  canvas->TileImageInt(
      *images_[CENTER], images_[LEFT]->width(), 0,
      size.width() - images_[LEFT]->width() - images_[RIGHT]->width(),
      images_[LEFT]->height());
}

}  // namespace views
<commit_msg>win: Don't VIEWS_EXPORT ImagePainter.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/views/painter.h"

#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/gfx/insets.h"
#include "ui/gfx/nine_image_painter.h"
#include "ui/gfx/point.h"
#include "ui/gfx/rect.h"
#include "ui/views/view.h"

namespace views {

namespace {

// DashedFocusPainter ----------------------------------------------------------

class DashedFocusPainter : public Painter {
 public:
  explicit DashedFocusPainter(const gfx::Insets& insets);
  virtual ~DashedFocusPainter();

  // Painter:
  virtual gfx::Size GetMinimumSize() const OVERRIDE;
  virtual void Paint(gfx::Canvas* canvas, const gfx::Size& size) OVERRIDE;

 private:
  const gfx::Insets insets_;

  DISALLOW_COPY_AND_ASSIGN(DashedFocusPainter);
};

DashedFocusPainter::DashedFocusPainter(const gfx::Insets& insets)
    : insets_(insets) {
}

DashedFocusPainter::~DashedFocusPainter() {
}

gfx::Size DashedFocusPainter::GetMinimumSize() const {
  return gfx::Size();
}

void DashedFocusPainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) {
  gfx::Rect rect(size);
  rect.Inset(insets_);
  canvas->DrawFocusRect(rect);
}

// SolidFocusPainter -----------------------------------------------------------

class SolidFocusPainter : public Painter {
 public:
  SolidFocusPainter(SkColor color, const gfx::Insets& insets);
  virtual ~SolidFocusPainter();

  // Painter:
  virtual gfx::Size GetMinimumSize() const OVERRIDE;
  virtual void Paint(gfx::Canvas* canvas, const gfx::Size& size) OVERRIDE;

 private:
  const SkColor color_;
  const gfx::Insets insets_;

  DISALLOW_COPY_AND_ASSIGN(SolidFocusPainter);
};

SolidFocusPainter::SolidFocusPainter(SkColor color,
                                     const gfx::Insets& insets)
    : color_(color),
      insets_(insets) {
}

SolidFocusPainter::~SolidFocusPainter() {
}

gfx::Size SolidFocusPainter::GetMinimumSize() const {
  return gfx::Size();
}

void SolidFocusPainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) {
  gfx::Rect rect(size);
  rect.Inset(insets_);
  canvas->DrawSolidFocusRect(rect, color_);
}

// GradientPainter ------------------------------------------------------------

class GradientPainter : public Painter {
 public:
  GradientPainter(bool horizontal,
                  SkColor* colors,
                  SkScalar* pos,
                  size_t count);
  virtual ~GradientPainter();

  // Painter:
  virtual gfx::Size GetMinimumSize() const OVERRIDE;
  virtual void Paint(gfx::Canvas* canvas, const gfx::Size& size) OVERRIDE;

 private:
  // If |horizontal_| is true then the gradient is painted horizontally.
  bool horizontal_;
  // The gradient colors.
  scoped_ptr<SkColor[]> colors_;
  // The relative positions of the corresponding gradient colors.
  scoped_ptr<SkScalar[]> pos_;
  // The number of elements in |colors_| and |pos_|.
  size_t count_;

  DISALLOW_COPY_AND_ASSIGN(GradientPainter);
};

GradientPainter::GradientPainter(bool horizontal,
                                 SkColor* colors,
                                 SkScalar* pos,
                                 size_t count)
    : horizontal_(horizontal),
      colors_(new SkColor[count]),
      pos_(new SkScalar[count]),
      count_(count) {
  for (size_t i = 0; i < count_; ++i) {
    pos_[i] = pos[i];
    colors_[i] = colors[i];
  }
}

GradientPainter::~GradientPainter() {
}

gfx::Size GradientPainter::GetMinimumSize() const {
  return gfx::Size();
}

void GradientPainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) {
  SkPaint paint;
  SkPoint p[2];
  p[0].iset(0, 0);
  if (horizontal_)
    p[1].iset(size.width(), 0);
  else
    p[1].iset(0, size.height());

  skia::RefPtr<SkShader> s = skia::AdoptRef(SkGradientShader::CreateLinear(
      p, colors_.get(), pos_.get(), count_, SkShader::kClamp_TileMode));
  paint.setStyle(SkPaint::kFill_Style);
  paint.setShader(s.get());

  canvas->sk_canvas()->drawRectCoords(SkIntToScalar(0), SkIntToScalar(0),
                                      SkIntToScalar(size.width()),
                                      SkIntToScalar(size.height()), paint);
}

// ImagePainter ---------------------------------------------------------------

// ImagePainter stores and paints nine images as a scalable grid.
class ImagePainter : public Painter {
 public:
  // Constructs an ImagePainter with the specified image resource ids.
  // See CreateImageGridPainter()'s comment regarding image ID count and order.
  explicit ImagePainter(const int image_ids[]);

  // Constructs an ImagePainter with the specified image and insets.
  ImagePainter(const gfx::ImageSkia& image, const gfx::Insets& insets);

  virtual ~ImagePainter();

  // Painter:
  virtual gfx::Size GetMinimumSize() const OVERRIDE;
  virtual void Paint(gfx::Canvas* canvas, const gfx::Size& size) OVERRIDE;

 private:
  scoped_ptr<gfx::NineImagePainter> nine_painter_;

  DISALLOW_COPY_AND_ASSIGN(ImagePainter);
};

ImagePainter::ImagePainter(const int image_ids[])
    : nine_painter_(ui::CreateNineImagePainter(image_ids)) {
}

ImagePainter::ImagePainter(const gfx::ImageSkia& image,
                           const gfx::Insets& insets)
    : nine_painter_(new gfx::NineImagePainter(image, insets)) {
}

ImagePainter::~ImagePainter() {
}

gfx::Size ImagePainter::GetMinimumSize() const {
  return nine_painter_->GetMinimumSize();
}

void ImagePainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) {
  nine_painter_->Paint(canvas, gfx::Rect(size));
}

}  // namespace

// Painter --------------------------------------------------------------------

Painter::Painter() {
}

Painter::~Painter() {
}

// static
void Painter::PaintPainterAt(gfx::Canvas* canvas,
                             Painter* painter,
                             const gfx::Rect& rect) {
  DCHECK(canvas && painter);
  canvas->Save();
  canvas->Translate(rect.OffsetFromOrigin());
  painter->Paint(canvas, rect.size());
  canvas->Restore();
}

// static
void Painter::PaintFocusPainter(View* view,
                                gfx::Canvas* canvas,
                                Painter* focus_painter) {
  if (focus_painter && view->HasFocus())
    PaintPainterAt(canvas, focus_painter, view->GetLocalBounds());
}

// static
Painter* Painter::CreateHorizontalGradient(SkColor c1, SkColor c2) {
  SkColor colors[2];
  colors[0] = c1;
  colors[1] = c2;
  SkScalar pos[] = {0, 1};
  return new GradientPainter(true, colors, pos, 2);
}

// static
Painter* Painter::CreateVerticalGradient(SkColor c1, SkColor c2) {
  SkColor colors[2];
  colors[0] = c1;
  colors[1] = c2;
  SkScalar pos[] = {0, 1};
  return new GradientPainter(false, colors, pos, 2);
}

// static
Painter* Painter::CreateVerticalMultiColorGradient(SkColor* colors,
                                                   SkScalar* pos,
                                                   size_t count) {
  return new GradientPainter(false, colors, pos, count);
}

// static
Painter* Painter::CreateImagePainter(const gfx::ImageSkia& image,
                                     const gfx::Insets& insets) {
  return new ImagePainter(image, insets);
}

// static
Painter* Painter::CreateImageGridPainter(const int image_ids[]) {
  return new ImagePainter(image_ids);
}

// static
scoped_ptr<Painter> Painter::CreateDashedFocusPainter() {
  return scoped_ptr<Painter>(new DashedFocusPainter(gfx::Insets())).Pass();
}

// static
scoped_ptr<Painter> Painter::CreateDashedFocusPainterWithInsets(
    const gfx::Insets& insets) {
  return scoped_ptr<Painter>(new DashedFocusPainter(insets)).Pass();
}

// static
scoped_ptr<Painter> Painter::CreateSolidFocusPainter(
    SkColor color,
    const gfx::Insets& insets) {
  return scoped_ptr<Painter>(new SolidFocusPainter(color, insets)).Pass();
}

// HorizontalPainter ----------------------------------------------------------

HorizontalPainter::HorizontalPainter(const int image_resource_names[]) {
  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
  for (int i = 0; i < 3; ++i)
    images_[i] = rb.GetImageNamed(image_resource_names[i]).ToImageSkia();
  DCHECK_EQ(images_[LEFT]->height(), images_[CENTER]->height());
  DCHECK_EQ(images_[LEFT]->height(), images_[RIGHT]->height());
}

HorizontalPainter::~HorizontalPainter() {
}

gfx::Size HorizontalPainter::GetMinimumSize() const {
  return gfx::Size(
      images_[LEFT]->width() + images_[CENTER]->width() +
          images_[RIGHT]->width(), images_[LEFT]->height());
}

void HorizontalPainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) {
  if (size.width() < GetMinimumSize().width())
    return;  // No room to paint.

  canvas->DrawImageInt(*images_[LEFT], 0, 0);
  canvas->DrawImageInt(*images_[RIGHT], size.width() - images_[RIGHT]->width(),
                       0);
  canvas->TileImageInt(
      *images_[CENTER], images_[LEFT]->width(), 0,
      size.width() - images_[LEFT]->width() - images_[RIGHT]->width(),
      images_[LEFT]->height());
}

}  // namespace views
<|endoftext|>


<commit_before>#include <iostream>
#include <sstream>

#include <apply_init_wave.h>
#include <param_reader.h>
#include <utility.h>
#include <xyz_reader.h>
#include <xyz_writer.h>
#include <wave_simulator_2d.h>

using namespace aasoni;
using namespace std;

namespace {

    bool parseArguments(std::string *paramFile,
                        std::string *outFilePrefix,
                        int argc, char *argv[])
    {
        if (argc < 5)
        {
            cout << "Usage is -p <param_file> -o <out_prefix>" << endl;
            return false;
        }
        else
        {
            for (size_t i = 1; i < argc; ++i)
            {
                if (string(argv[i]) == "-p")
                {
                    *paramFile = argv[i+1];
                    ++i;
                }
                else if (string(argv[i]) == "-o")
                {
                    *outFilePrefix = argv[i+1];
                    ++i;
                }
                else
                {
                    cout << "Not enough or invalid arguments." << endl;
                    return false;
                }
            }
            return true;
        }
    }

} //anonymous namespace

int main(int argc, char *argv[] )
{
    //get command line arguments
    std::string paramFile, outFilePrefix;
    if(!parseArguments(&paramFile, &outFilePrefix, argc, argv))
        return 0;

    //read parameter file
    ParamReader paramReader(paramFile);

    //get data file info
    string fileName = paramReader.getDataFileName();
    size_t xLength = paramReader.getXLength();
    size_t yLength = paramReader.getYLength();

    //read data
    VEC latitude, longitude;
    MAT bathymetry;
    XYZ_Reader reader;
    if(!reader.readFile(&latitude, &longitude, &bathymetry, xLength, yLength, fileName))
    {
        cout << "Unable to read data" << endl;
        return 1;
    }

    //convert data to surface
    MAT height = bathymetry;
    bathymetryToHeight(&height);

    //   ADD WAVE TO SURFACE
    //read wave data
    double amplitude = paramReader.getWaveAmplitude();
    double xPos = paramReader.getWaveX();
    double yPos = paramReader.getWaveY();
    double xSigma = paramReader.getWaveSigmaX();
    double ySigma = paramReader.getWaveSigmaY();
    double c = paramReader.getWaveC();
    MAT wave = height;

    ApplyInitWave applyWave(amplitude, xPos, yPos, xSigma, ySigma, c);
    applyWave(&latitude, &longitude, &wave);

    //write initial wave
    MAT output;
    XYZ_Writer writer;
    heightAndBathymetryToSurface(&output, bathymetry, wave);
    writer.writeToFile(latitude,longitude,output,"data/surface.xyz");

    //Simulate propagation
    size_t steps = paramReader.getSimulationSteps();
    double deltaX = paramReader.getDeltaX();
    double deltaY = paramReader.getDeltaY();
    double deltaT = paramReader.getDeltaT();
    WaveSimulator2D simulator(steps, deltaX, deltaY, deltaT, wave, &wave);

    size_t iter = 0;
    string outputFilename;
    while(simulator.next())
    {
        if(iter % 10 == 1)
            cout << "completed " << iter << " iterations." << endl;
        ++iter;
        ostringstream os;
        os << outFilePrefix << "_" << iter << ".xyz";
        outputFilename = os.str();

        //write output
        heightAndBathymetryToSurface(&output, bathymetry, wave);
        writer.writeToFile(latitude,longitude,output,outputFilename);
    }

}
<commit_msg>Fixed error messagee<commit_after>#include <iostream>
#include <sstream>

#include <apply_init_wave.h>
#include <param_reader.h>
#include <utility.h>
#include <xyz_reader.h>
#include <xyz_writer.h>
#include <wave_simulator_2d.h>

using namespace aasoni;
using namespace std;

namespace {

    bool parseArguments(std::string *paramFile,
                        std::string *outFilePrefix,
                        int argc, char *argv[])
    {
        if (argc < 5)
        {
            cout << "Usage is -p <param_file> -o <out_prefix>" << endl;
            return false;
        }
        else
        {
            for (size_t i = 1; i < argc; ++i)
            {
                if (string(argv[i]) == "-p")
                {
                    *paramFile = argv[i+1];
                    ++i;
                }
                else if (string(argv[i]) == "-o")
                {
                    *outFilePrefix = argv[i+1];
                    ++i;
                }
                else
                {
                    cout << "Not enough or invalid arguments." << endl;
                    return false;
                }
            }
            return true;
        }
    }

} //anonymous namespace

int main(int argc, char *argv[] )
{
    //get command line arguments
    std::string paramFile, outFilePrefix;
    if(!parseArguments(&paramFile, &outFilePrefix, argc, argv))
        return 0;

    //read parameter file
    ParamReader paramReader(paramFile);

    //get data file info
    string fileName = paramReader.getDataFileName();
    size_t xLength = paramReader.getXLength();
    size_t yLength = paramReader.getYLength();

    //read data
    VEC latitude, longitude;
    MAT bathymetry;
    XYZ_Reader reader;
    if(!reader.readFile(&latitude, &longitude, &bathymetry, xLength, yLength, fileName))
    {
        cout << "Unable to read data: " << fileName << endl;
        return 1;
    }

    //convert data to surface
    MAT height = bathymetry;
    bathymetryToHeight(&height);

    //   ADD WAVE TO SURFACE
    //read wave data
    double amplitude = paramReader.getWaveAmplitude();
    double xPos = paramReader.getWaveX();
    double yPos = paramReader.getWaveY();
    double xSigma = paramReader.getWaveSigmaX();
    double ySigma = paramReader.getWaveSigmaY();
    double c = paramReader.getWaveC();
    MAT wave = height;

    ApplyInitWave applyWave(amplitude, xPos, yPos, xSigma, ySigma, c);
    applyWave(&latitude, &longitude, &wave);

    //write initial wave
    MAT output;
    XYZ_Writer writer;
    heightAndBathymetryToSurface(&output, bathymetry, wave);
    writer.writeToFile(latitude,longitude,output,"data/surface.xyz");

    //Simulate propagation
    size_t steps = paramReader.getSimulationSteps();
    double deltaX = paramReader.getDeltaX();
    double deltaY = paramReader.getDeltaY();
    double deltaT = paramReader.getDeltaT();
    WaveSimulator2D simulator(steps, deltaX, deltaY, deltaT, wave, &wave);

    size_t iter = 0;
    string outputFilename;
    while(simulator.next())
    {
        if(iter % 10 == 1)
            cout << "completed " << iter << " iterations." << endl;
        ++iter;
        ostringstream os;
        os << outFilePrefix << "_" << iter << ".xyz";
        outputFilename = os.str();

        //write output
        heightAndBathymetryToSurface(&output, bathymetry, wave);
        writer.writeToFile(latitude,longitude,output,outputFilename);
    }

}
<|endoftext|>