<commit_before>#include "quiz.h"

#define TITLE "TEST YOUR KNOWLEDGE!"

extern question questions[3][3][3];

int height, width;

void init_ui()
{
	textcolor(LIGHTGRAY);
	textbackground(BLACK);

	struct text_info info;
	gettextinfo(&info);

	width = (int) info.screenwidth;
	height = (int) info.screenheight;
}

void frame(coord up_left, int f_height, int f_width, int f_sides)
{
	char l_up = (char) 201;
	char l_down = (char) 200;
	char r_up = (char) 187;
	char r_down = (char) 188;
	char bet_ver = (char) 186;
	char bet_hor = (char) 205;

	if(up_left.x == -1)
	{
		coord b(1,1);
		up_left = b;
		f_width = width;
		f_height = height - 1;
	}

	gotoxy(up_left.x, up_left.y);

	cout << l_up;
	for(int i = 0; i < f_width - 2; i++)
	{
		cout << bet_hor;
	}
	cout << r_up;

	if(f_sides)
	{
		for(i = 2; i <= f_height - 1; i++)
		{
			gotoxy(up_left.x, i); cout << bet_ver;
			gotoxy(up_left.x + f_width - 1, i); cout << bet_ver;
		}
	}

	gotoxy(up_left.x, up_left.y + f_height + 1);
	cout << l_down;
	for(i = 0; i < f_width - 2; i++)
	{
		cout << bet_hor;
	}
	cout << r_down;

	gotoxy(up_left.x + 2, up_left.y + 2);
}

void printc(char str[], int ws, int t_color, int b_color)
{
	if(ws == -1)
	{
		gotoxy((width - strlen(str))/2 ,wherey());
	}
	else
	{
		gotoxy(ws + 1, wherey());
	}

	textcolor(t_color);
	textbackground(b_color);
	cprintf("%s", str);
}

/*
 Generates user interface
 Screen_num:
	1: difficulty level
	2: Subject
*/
int generate_ui(int screen_num)
{
	clrscr();
	frame();

	char title[] = TITLE;
	char head[100], op1[100], op2[100], op3[100];
	if(screen_num == 1)
	{
		strcpy(head, "Select difficulty level: ");
		strcpy(op1, "Easy");
		strcpy(op2, "Intermediate");
		strcpy(op3, "Hard");
	}
	else if(screen_num == 2)
	{
		strcpy(head, "Select subject: ");
		strcpy(op1, "Computer Science (C++)");
		strcpy(op2, "General Knowledge");
		strcpy(op3, "English");
	}

	gotoxy(1, (height - 6) / 2);

	printc(title);
	cout << "\n\n";

	int lengths[] = {
					  strlen(head),
					  strlen(op1),
					  strlen(op2),
					  strlen(op3),
					};

	//Determining max length
	int max_len = lengths[0];
	for(int i = 0; i < 4; i++)
	{
		for(int j = i + 1; j < 4; j++)
		{
			if(lengths[j] > max_len)
			{
				max_len = lengths[j];
			}
		}
	}

	int a = (width - max_len) / 2;
	coord b(a - 4,wherey());
	frame(b, 6, max_len + 8, 0);

	printc(head, a);
	cout << '\n';

	coord bullet1(b.x + 2, wherey());

	gotoxy(bullet1.x + 2, bullet1.y); printc(op1, a); cout << '\n';
	gotoxy(bullet1.x + 2, bullet1.y + 1); printc(op2, a); cout << '\n';
	gotoxy(bullet1.x + 2, bullet1.y + 2); printc(op3, a); cout << '\n';

	return select(bullet1, 3);
}

int generate_ui(int lvl, int sub, int q_num)
{
	clrscr();
	frame();

	gotoxy(2,2); cout << "Difficulty: ";
	switch(lvl)
	{
		case 0:
			cout << "Easy";
			break;
		case 1:
			cout << "Intermediate";
			break;
		case 2:
			cout << "Hard";
			break;
	}

	char print[100] = "Subject: ";
	switch(sub)
	{
		case 0:
			strcat(print, "C++");
			break;
		case 1:
			strcat(print, "G.K.");
			break;
		case 2:
			strcat(print, "English");
			break;
	}
	gotoxy(width - strlen(print), 2);
	cout << print;

	char ques[200], options[4][200];

	strcpy(ques, questions[lvl][sub][q_num].q);
	strcpy(options[0], questions[lvl][sub][q_num].options[0]);
	strcpy(options[1], questions[lvl][sub][q_num].options[1]);
	strcpy(options[2], questions[lvl][sub][q_num].options[2]);
	strcpy(options[3], questions[lvl][sub][q_num].options[3]);

	int f_width = (8 * width) / 10;
	int ws = (width - f_width) / 2;

	int lengths[] = {
					 strlen(ques),
					 strlen(options[0]),
					 strlen(options[1]),
					 strlen(options[2]),
					 strlen(options[3])
					};

	int f_height = 2 + lengths[0] / f_width + 1;
	int f_ws = 3;  //Whitespace inside frame for options
	for(int i = 1; i < 5; i++)
	{
		f_height += lengths[i] / (f_width - f_ws) + 1;
	}

	coord u_left(ws + 1, (height - f_height) / 2 + 1);
	frame(u_left, f_height, f_width, 0);

	char printq[] = "Question ";
	gotoxy((width - strlen(printq) - 1) / 2 + 1, 2);
	cout << printq << q_num + 1;

	gotoxy(1, (height - f_height) / 2 - 3);
	printc(TITLE);

	char fstring[200] = "";

	int height_ops[4] = {0,0,0,0};
	int height_ques = wrap(ques, fstring, f_width - f_ws);

	int line_num = 1;
	char line[200];
	int read;
	int chars_read = 0;
	coord ques_coord(u_left.x + 1, u_left.y + 2);

	for(i = 0; i < height_ques; i++)
	{
		sscanf(fstring + chars_read, "%[^\n]%*c%n", line, &read);
		gotoxy(ques_coord.x + 2, ques_coord.y + line_num - 1);
		cout << line;
		line_num++;
		chars_read += read;
	}

	strcpy(fstring, "");

	coord bullet1(ques_coord.x, ques_coord.y + height_ques);

	for(i = 0; i < 4; i++)
	{
		height_ops[i] = wrap(options[i], fstring, f_width - f_ws - 3 - 2);
		read = 0, chars_read = 0;

		int len = strlen(fstring);
		fstring[len] = '\n'; fstring[len+1] = '\0';

		coord op_start(bullet1.x + 2 + 3, bullet1.y); // x: +2 space for bullet, +3 space for option letter

		for(int j = 0; j < i; j++)
		{
			op_start.y += height_ops[j];
		}

		gotoxy(bullet1.x + 2, op_start.y);
		cout << (char) ('A' + i) << ". ";

		for(j = 0; j < height_ops[i]; j++)
		{
			sscanf(fstring + chars_read, "%[^\n]%*c%n", line, &read);
			gotoxy(op_start.x, op_start.y + j);
			line_num++;
			cout << line;
			chars_read += read;
		}

		strcpy(fstring, "");
	}

	int selected_ans = select(bullet1, 4, height_ops) + 1;
	gotoxy(1, (height - f_height) / 2 - 1);
	if(selected_ans == questions[lvl][sub][q_num].correct)
	{
		printc("Correct Answer!!");
		return 1;
	}
	else
	{
		char pr[] = "Incorrect Answer!! Correct answer was ";
		char a[2] = {(char) ('A' + questions[lvl][sub][q_num].correct - 1),'\0'};
		strcat(pr,a);
		printc(pr);
		return 0;
	}

}

int select(coord line1, int num_ops, char bullet)
{
	int height_ops[] = {1,1,1,1,1};
	return select(line1, num_ops, height_ops, bullet);
}

int select(coord line1, int num_ops, int height_ops[], char bullet)
{
	int curr_line = 0;
	gotoxy(line1.x, line1.y); cout << bullet;
	while(1)
	{
		char c = getch();

		if(c == 0)
		{
			c = getch();
			switch(c)
			{
				case 'H':
					curr_line == 0 ? curr_line = num_ops - 1 : curr_line--;
					break;
				case 'P':
					curr_line == num_ops - 1 ? curr_line = 0 : curr_line++;
					break;
			}
		}
		else if(c == 13)
		{
			return curr_line;
		}

		for(int i = 0; i < num_ops; i++)
		{
			coord bullet_pos;

			bullet_pos.x = line1.x;
			bullet_pos.y = line1.y;
			for(int j = 0; j < i; j++)
			{
				bullet_pos.y += height_ops[j];
			}

			gotoxy(bullet_pos.x, bullet_pos.y);

			if(i == curr_line)
			{
				cout << bullet;
			}
			else
			{
				cout << ' ';
			}
		}
	}
}
<commit_msg>Removed cursor from displaying during gameplay<commit_after>#include "quiz.h"

#define TITLE "TEST YOUR KNOWLEDGE!"

extern question questions[3][3][3];

int height, width;

void init_ui()
{
	_setcursortype(_NOCURSOR);
	textcolor(LIGHTGRAY);
	textbackground(BLACK);

	struct text_info info;
	gettextinfo(&info);

	width = (int) info.screenwidth;
	height = (int) info.screenheight;
}

void frame(coord up_left, int f_height, int f_width, int f_sides)
{
	char l_up = (char) 201;
	char l_down = (char) 200;
	char r_up = (char) 187;
	char r_down = (char) 188;
	char bet_ver = (char) 186;
	char bet_hor = (char) 205;

	if(up_left.x == -1)
	{
		coord b(1,1);
		up_left = b;
		f_width = width;
		f_height = height - 1;
	}

	gotoxy(up_left.x, up_left.y);

	cout << l_up;
	for(int i = 0; i < f_width - 2; i++)
	{
		cout << bet_hor;
	}
	cout << r_up;

	if(f_sides)
	{
		for(i = 2; i <= f_height - 1; i++)
		{
			gotoxy(up_left.x, i); cout << bet_ver;
			gotoxy(up_left.x + f_width - 1, i); cout << bet_ver;
		}
	}

	gotoxy(up_left.x, up_left.y + f_height + 1);
	cout << l_down;
	for(i = 0; i < f_width - 2; i++)
	{
		cout << bet_hor;
	}
	cout << r_down;

	gotoxy(up_left.x + 2, up_left.y + 2);
}

void printc(char str[], int ws, int t_color, int b_color)
{
	if(ws == -1)
	{
		gotoxy((width - strlen(str))/2 ,wherey());
	}
	else
	{
		gotoxy(ws + 1, wherey());
	}

	textcolor(t_color);
	textbackground(b_color);
	cprintf("%s", str);
}

/*
 Generates user interface
 Screen_num:
	1: difficulty level
	2: Subject
*/
int generate_ui(int screen_num)
{
	clrscr();
	frame();

	char title[] = TITLE;
	char head[100], op1[100], op2[100], op3[100];
	if(screen_num == 1)
	{
		strcpy(head, "Select difficulty level: ");
		strcpy(op1, "Easy");
		strcpy(op2, "Intermediate");
		strcpy(op3, "Hard");
	}
	else if(screen_num == 2)
	{
		strcpy(head, "Select subject: ");
		strcpy(op1, "Computer Science (C++)");
		strcpy(op2, "General Knowledge");
		strcpy(op3, "English");
	}

	gotoxy(1, (height - 6) / 2);

	printc(title);
	cout << "\n\n";

	int lengths[] = {
					  strlen(head),
					  strlen(op1),
					  strlen(op2),
					  strlen(op3),
					};

	//Determining max length
	int max_len = lengths[0];
	for(int i = 0; i < 4; i++)
	{
		for(int j = i + 1; j < 4; j++)
		{
			if(lengths[j] > max_len)
			{
				max_len = lengths[j];
			}
		}
	}

	int a = (width - max_len) / 2;
	coord b(a - 4,wherey());
	frame(b, 6, max_len + 8, 0);

	printc(head, a);
	cout << '\n';

	coord bullet1(b.x + 2, wherey());

	gotoxy(bullet1.x + 2, bullet1.y); printc(op1, a); cout << '\n';
	gotoxy(bullet1.x + 2, bullet1.y + 1); printc(op2, a); cout << '\n';
	gotoxy(bullet1.x + 2, bullet1.y + 2); printc(op3, a); cout << '\n';

	return select(bullet1, 3);
}

int generate_ui(int lvl, int sub, int q_num)
{
	clrscr();
	frame();

	gotoxy(2,2); cout << "Difficulty: ";
	switch(lvl)
	{
		case 0:
			cout << "Easy";
			break;
		case 1:
			cout << "Intermediate";
			break;
		case 2:
			cout << "Hard";
			break;
	}

	char print[100] = "Subject: ";
	switch(sub)
	{
		case 0:
			strcat(print, "C++");
			break;
		case 1:
			strcat(print, "G.K.");
			break;
		case 2:
			strcat(print, "English");
			break;
	}
	gotoxy(width - strlen(print), 2);
	cout << print;

	char ques[200], options[4][200];

	strcpy(ques, questions[lvl][sub][q_num].q);
	strcpy(options[0], questions[lvl][sub][q_num].options[0]);
	strcpy(options[1], questions[lvl][sub][q_num].options[1]);
	strcpy(options[2], questions[lvl][sub][q_num].options[2]);
	strcpy(options[3], questions[lvl][sub][q_num].options[3]);

	int f_width = (8 * width) / 10;
	int ws = (width - f_width) / 2;

	int lengths[] = {
					 strlen(ques),
					 strlen(options[0]),
					 strlen(options[1]),
					 strlen(options[2]),
					 strlen(options[3])
					};

	int f_height = 2 + lengths[0] / f_width + 1;
	int f_ws = 3;  //Whitespace inside frame for options
	for(int i = 1; i < 5; i++)
	{
		f_height += lengths[i] / (f_width - f_ws) + 1;
	}

	coord u_left(ws + 1, (height - f_height) / 2 + 1);
	frame(u_left, f_height, f_width, 0);

	char printq[] = "Question ";
	gotoxy((width - strlen(printq) - 1) / 2 + 1, 2);
	cout << printq << q_num + 1;

	gotoxy(1, (height - f_height) / 2 - 3);
	printc(TITLE);

	char fstring[200] = "";

	int height_ops[4] = {0,0,0,0};
	int height_ques = wrap(ques, fstring, f_width - f_ws);

	int line_num = 1;
	char line[200];
	int read;
	int chars_read = 0;
	coord ques_coord(u_left.x + 1, u_left.y + 2);

	for(i = 0; i < height_ques; i++)
	{
		sscanf(fstring + chars_read, "%[^\n]%*c%n", line, &read);
		gotoxy(ques_coord.x + 2, ques_coord.y + line_num - 1);
		cout << line;
		line_num++;
		chars_read += read;
	}

	strcpy(fstring, "");

	coord bullet1(ques_coord.x, ques_coord.y + height_ques);

	for(i = 0; i < 4; i++)
	{
		height_ops[i] = wrap(options[i], fstring, f_width - f_ws - 3 - 2);
		read = 0, chars_read = 0;

		int len = strlen(fstring);
		fstring[len] = '\n'; fstring[len+1] = '\0';

		coord op_start(bullet1.x + 2 + 3, bullet1.y); // x: +2 space for bullet, +3 space for option letter

		for(int j = 0; j < i; j++)
		{
			op_start.y += height_ops[j];
		}

		gotoxy(bullet1.x + 2, op_start.y);
		cout << (char) ('A' + i) << ". ";

		for(j = 0; j < height_ops[i]; j++)
		{
			sscanf(fstring + chars_read, "%[^\n]%*c%n", line, &read);
			gotoxy(op_start.x, op_start.y + j);
			line_num++;
			cout << line;
			chars_read += read;
		}

		strcpy(fstring, "");
	}

	int selected_ans = select(bullet1, 4, height_ops) + 1;
	gotoxy(1, (height - f_height) / 2 - 1);
	if(selected_ans == questions[lvl][sub][q_num].correct)
	{
		printc("Correct Answer!!");
		return 1;
	}
	else
	{
		char pr[] = "Incorrect Answer!! Correct answer was ";
		char a[2] = {(char) ('A' + questions[lvl][sub][q_num].correct - 1),'\0'};
		strcat(pr,a);
		printc(pr);
		return 0;
	}

}

int select(coord line1, int num_ops, char bullet)
{
	int height_ops[] = {1,1,1,1,1};
	return select(line1, num_ops, height_ops, bullet);
}

int select(coord line1, int num_ops, int height_ops[], char bullet)
{
	int curr_line = 0;
	gotoxy(line1.x, line1.y); cout << bullet;
	while(1)
	{
		char c = getch();

		if(c == 0)
		{
			c = getch();
			switch(c)
			{
				case 'H':
					curr_line == 0 ? curr_line = num_ops - 1 : curr_line--;
					break;
				case 'P':
					curr_line == num_ops - 1 ? curr_line = 0 : curr_line++;
					break;
			}
		}
		else if(c == 13)
		{
			return curr_line;
		}

		for(int i = 0; i < num_ops; i++)
		{
			coord bullet_pos;

			bullet_pos.x = line1.x;
			bullet_pos.y = line1.y;
			for(int j = 0; j < i; j++)
			{
				bullet_pos.y += height_ops[j];
			}

			gotoxy(bullet_pos.x, bullet_pos.y);

			if(i == curr_line)
			{
				cout << bullet;
			}
			else
			{
				cout << ' ';
			}
		}
	}
}
<|endoftext|>


<commit_before>#if !defined(_P0_)

template <typename T, typename U> class P0 {
public:
  typedef SimpleVector<T> Vec;
  typedef SimpleVector<U> VecU;
  typedef SimpleMatrix<T> Mat;
  typedef SimpleMatrix<U> MatU;
  inline P0(const int& range, const int& shrink = 4);
  inline ~P0();
  inline void nextNoreturn(const T& in);
  inline T next(const T& in);
private:
  Vec pred;
  const MatU& seed(const int& size, const bool& idft);
  const Mat&  diff(const int& size, const bool& integrate);
  const Vec&  nextTaylor(const int& size);
  const Vec&  nextDeepTaylor(const int& size, const int& shrink);
  const T& Pi() const;
  const U& J()  const;
  Vec buf;
};

template <typename T, typename U> P0<T,U>::P0(const int& range, const int& shrink) {
  assert(1 < range && 0 < shrink);
  buf.resize(range);
  for(int i = 0; i < buf.size(); i ++)
    buf[i] = T(0);
  const auto& pred0(nextDeepTaylor(range * shrink, shrink));
  pred.resize(range);
  for(int i = 0; i < pred.size(); i ++)
    pred[i] = T(0);
  for(int i = 0; i < pred0.size(); i ++)
    pred[i / shrink] += pred0[i];
  pred /= T(shrink);
}

template <typename T, typename U> P0<T,U>::~P0() {
  ;
}

template <typename T, typename U> inline void P0<T,U>::nextNoreturn(const T& in) {
  for(int i = 1; i < buf.size(); i ++)
    buf[i - 1] = buf[i];
  buf[buf.size() - 1] = in;
  return;
}

template <typename T, typename U> inline T P0<T,U>::next(const T& in) {
  nextNoreturn(in);
  return pred.dot(buf);
}

template <typename T, typename U> const T& P0<T,U>::Pi() const {
  const static auto pi(atan2(T(1), T(1)) * T(4));
  return pi;
}

template <typename T, typename U> const U& P0<T,U>::J() const {
  const static auto i(sqrt(U(T(- 1))));
  return i;
}

template <typename T, typename U> const typename P0<T,U>::MatU& P0<T,U>::seed(const int& size, const bool& f_idft) {
  assert(0 < size);
  static vector<MatU> dft;
  static vector<MatU> idft;
  if(dft.size() <= size)
    dft.resize(size + 1, MatU());
  if(idft.size() <= size)
    idft.resize(size + 1, MatU());
  if((!f_idft) &&  dft[size].rows() == size &&  dft[size].cols() == size)
    return dft[size];
  if(  f_idft  && idft[size].rows() == size && idft[size].cols() == size)
    return idft[size];
  dft[ size].resize(size, size);
  idft[size].resize(size, size);
  auto& edft( dft[size]);
  auto& eidft(idft[size]);
  for(int i = 0; i < edft.rows(); i ++)
    for(int j = 0; j < edft.cols(); j ++) {
      const auto theta(- T(2) * Pi() * T(i) * T(j) / T(edft.rows()));
      edft(i, j)  = U(cos(  theta), sin(  theta));
      eidft(i, j) = U(cos(- theta), sin(- theta)) / U(T(size));
    }
  if(f_idft)
    return eidft;
  return edft;
}

template <typename T, typename U> const typename P0<T,U>::Mat& P0<T,U>::diff(const int& size, const bool& integrate) {
  assert(0 < size);
  static vector<Mat> D;
  static vector<Mat> I;
  if(D.size() <= size)
    D.resize(size + 1, Mat());
  if(I.size() <= size)
    I.resize(size + 1, Mat());
  if((!integrate) && D[size].rows() == size && D[size].cols() == size)
    return D[size];
  if(  integrate  && I[size].rows() == size && I[size].cols() == size)
    return I[size];
  D[size].resize(size, size);
  I[size].resize(size, size);
  auto& d(D[size]);
  auto& i(I[size]);
  auto  DD(seed(size, false));
  DD.row(0) *= U(T(0));
  auto  II(DD);
  T nd(0);
  T ni(0);
  for(int i = 1; i < DD.rows(); i ++) {
    const auto phase(- J() * T(2) * Pi() * T(i) / T(DD.rows()));
    const auto phase2(U(T(1)) / phase);
    DD.row(i) *= phase;
    II.row(i) /= phase;
    nd += abs(phase)  * abs(phase);
    ni += abs(phase2) * abs(phase2);
  }
  d = (seed(size, true) * DD).template real<T>() * sqrt(sqrt(T(DD.rows() - 1) / (nd * ni)));
  i = (seed(size, true) * II).template real<T>() * sqrt(sqrt(T(II.rows() - 1) / (nd * ni)));
  if(integrate)
    return i;
  return d;
}

template <typename T, typename U> const typename P0<T,U>::Vec& P0<T,U>::nextTaylor(const int& size) {
  assert(0 < size);
  static vector<Vec> ntayl;
  if(ntayl.size() <= size)
    ntayl.resize(size + 1, Vec());
  if(ntayl[size].size() == size)
    return ntayl[size];
  ntayl[size].resize(size);
        auto& v(ntayl[size]);
  const auto& D(diff(size, false));
        auto  dd(D.row(D.rows() - 1));
  for(int i = 0; i < v.size() - 1; i ++)
    v[i] = T(0);
  v[v.size() - 1] = T(1);
  for(int i = 2; 0 <= i; i ++) {
    const auto bv(v);
    v += dd;
    if(bv == v)
      break;
    dd = (D * dd) / T(i);
  }
  return v;
}

template <typename T, typename U> const typename P0<T,U>::Vec& P0<T,U>::nextDeepTaylor(const int& size, const int& shrink) {
  assert(0 < size);
  static vector<Vec> dtayl;
  if(dtayl.size() <= size)
    dtayl.resize(size + 1, Vec());
  if(dtayl[size].size() == size)
    return dtayl[size];
  auto& p(dtayl[size]);
  p = nextTaylor(size);
  for(int i = shrink + 1; i < p.size(); i ++) {
    const auto& q(nextTaylor(i));
    for(int j = 0; j < q.size(); j ++)
      p[p.size() + j - q.size()] += q[j];
  }
  return p /= T(p.size() - 1);
}

#define _P0_
#endif

<commit_msg>p0 shrink fix.<commit_after>#if !defined(_P0_)

template <typename T, typename U> class P0 {
public:
  typedef SimpleVector<T> Vec;
  typedef SimpleVector<U> VecU;
  typedef SimpleMatrix<T> Mat;
  typedef SimpleMatrix<U> MatU;
  inline P0(const int& range, const int& shrink = 4);
  inline ~P0();
  inline void nextNoreturn(const T& in);
  inline T next(const T& in);
private:
  Vec pred;
  const MatU& seed(const int& size, const bool& idft);
  const Mat&  diff(const int& size, const bool& integrate);
  const Vec&  nextTaylor(const int& size);
  const Vec&  nextDeepTaylor(const int& size);
  const T& Pi() const;
  const U& J()  const;
  Vec buf;
};

template <typename T, typename U> P0<T,U>::P0(const int& range, const int& shrink) {
  assert(1 < range && 0 < shrink);
  buf.resize(range);
  for(int i = 0; i < buf.size(); i ++)
    buf[i] = T(0);
  const auto& pred0(nextDeepTaylor(range * shrink));
  pred.resize(range);
  for(int i = 0; i < pred.size(); i ++)
    pred[i] = T(0);
  for(int i = 0; i < pred0.size(); i ++)
    pred[i / shrink] += pred0[i];
  pred /= T(shrink);
}

template <typename T, typename U> P0<T,U>::~P0() {
  ;
}

template <typename T, typename U> inline void P0<T,U>::nextNoreturn(const T& in) {
  for(int i = 1; i < buf.size(); i ++)
    buf[i - 1] = buf[i];
  buf[buf.size() - 1] = in;
  return;
}

template <typename T, typename U> inline T P0<T,U>::next(const T& in) {
  nextNoreturn(in);
  return pred.dot(buf);
}

template <typename T, typename U> const T& P0<T,U>::Pi() const {
  const static auto pi(atan2(T(1), T(1)) * T(4));
  return pi;
}

template <typename T, typename U> const U& P0<T,U>::J() const {
  const static auto i(sqrt(U(T(- 1))));
  return i;
}

template <typename T, typename U> const typename P0<T,U>::MatU& P0<T,U>::seed(const int& size, const bool& f_idft) {
  assert(0 < size);
  static vector<MatU> dft;
  static vector<MatU> idft;
  if(dft.size() <= size)
    dft.resize(size + 1, MatU());
  if(idft.size() <= size)
    idft.resize(size + 1, MatU());
  if((!f_idft) &&  dft[size].rows() == size &&  dft[size].cols() == size)
    return dft[size];
  if(  f_idft  && idft[size].rows() == size && idft[size].cols() == size)
    return idft[size];
  dft[ size].resize(size, size);
  idft[size].resize(size, size);
  auto& edft( dft[size]);
  auto& eidft(idft[size]);
  for(int i = 0; i < edft.rows(); i ++)
    for(int j = 0; j < edft.cols(); j ++) {
      const auto theta(- T(2) * Pi() * T(i) * T(j) / T(edft.rows()));
      edft(i, j)  = U(cos(  theta), sin(  theta));
      eidft(i, j) = U(cos(- theta), sin(- theta)) / U(T(size));
    }
  if(f_idft)
    return eidft;
  return edft;
}

template <typename T, typename U> const typename P0<T,U>::Mat& P0<T,U>::diff(const int& size, const bool& integrate) {
  assert(0 < size);
  static vector<Mat> D;
  static vector<Mat> I;
  if(D.size() <= size)
    D.resize(size + 1, Mat());
  if(I.size() <= size)
    I.resize(size + 1, Mat());
  if((!integrate) && D[size].rows() == size && D[size].cols() == size)
    return D[size];
  if(  integrate  && I[size].rows() == size && I[size].cols() == size)
    return I[size];
  D[size].resize(size, size);
  I[size].resize(size, size);
  auto& d(D[size]);
  auto& i(I[size]);
  auto  DD(seed(size, false));
  DD.row(0) *= U(T(0));
  auto  II(DD);
  T nd(0);
  T ni(0);
  for(int i = 1; i < DD.rows(); i ++) {
    const auto phase(- J() * T(2) * Pi() * T(i) / T(DD.rows()));
    const auto phase2(U(T(1)) / phase);
    DD.row(i) *= phase;
    II.row(i) /= phase;
    nd += abs(phase)  * abs(phase);
    ni += abs(phase2) * abs(phase2);
  }
  d = (seed(size, true) * DD).template real<T>() * sqrt(sqrt(T(DD.rows() - 1) / (nd * ni)));
  i = (seed(size, true) * II).template real<T>() * sqrt(sqrt(T(II.rows() - 1) / (nd * ni)));
  if(integrate)
    return i;
  return d;
}

template <typename T, typename U> const typename P0<T,U>::Vec& P0<T,U>::nextTaylor(const int& size) {
  assert(0 < size);
  static vector<Vec> ntayl;
  if(ntayl.size() <= size)
    ntayl.resize(size + 1, Vec());
  if(ntayl[size].size() == size)
    return ntayl[size];
  ntayl[size].resize(size);
        auto& v(ntayl[size]);
  const auto& D(diff(size, false));
        auto  dd(D.row(D.rows() - 1));
  for(int i = 0; i < v.size() - 1; i ++)
    v[i] = T(0);
  v[v.size() - 1] = T(1);
  for(int i = 2; 0 <= i; i ++) {
    const auto bv(v);
    v += dd;
    if(bv == v)
      break;
    dd = (D * dd) / T(i);
  }
  return v;
}

template <typename T, typename U> const typename P0<T,U>::Vec& P0<T,U>::nextDeepTaylor(const int& size) {
  assert(0 < size);
  static vector<Vec> dtayl;
  if(dtayl.size() <= size)
    dtayl.resize(size + 1, Vec());
  if(dtayl[size].size() == size)
    return dtayl[size];
  auto& p(dtayl[size]);
  p = nextTaylor(size);
  p[p.size() - 1] += T(1);
  for(int i = 2; i < p.size(); i ++) {
    const auto& q(nextTaylor(i));
    for(int j = 0; j < q.size(); j ++)
      p[p.size() + j - q.size()] += q[j];
  }
  return p /= T(p.size());
}

#define _P0_
#endif

<|endoftext|>


<commit_before>#include "types.h"
#include "amd64.h"
#include "mmu.h"
#include "cpu.hh"
#include "kernel.hh"
#include "bits.hh"
#include "spinlock.h"
#include "kalloc.h"
#include "queue.h"
#include "condvar.h"
#include "proc.hh"
#include "vm.hh"
#include "gc.hh"
#include "crange.hh"
#include "cpputil.hh"

enum { vm_debug = 0 };

/*
 * vmnode
 */

vmnode::vmnode(u64 npg, vmntype ntype)
  : npages(npg), ref(0), type(ntype), ip(0), offset(0), sz(0)
{
  if (npg > NELEM(page))
    panic("vmnode too big\n");
  memset(page, 0, sizeof(page));
  if (type == EAGER)
    assert(allocpg() == 0);
}

vmnode::~vmnode()
{
  for(u64 i = 0; i < npages; i++) {
    if (page[i]) {
      kfree(page[i]);
      page[i] = 0;
    }
  }
  if (ip) {
    iput(ip);
    ip = 0;
  }
}

void
vmnode::decref()
{
  if(--ref == 0)
    delete this;
}

int
vmnode::allocpg()
{
  for(u64 i = 0; i < npages; i++) {
    if((page[i] = kalloc()) == 0)
      return -1;
    memset((char *) page[i], 0, PGSIZE);
  }
  return 0;
}

vmnode *
vmnode::copy()
{
  vmnode *c = new vmnode(npages, type);
  if(c != 0) {
    c->type = type;
    if (type == ONDEMAND) {
      c->ip = idup(ip);
      c->offset = offset;
      c->sz = c->sz;
    }
    if (page[0]) {   // If the first page is present, all of them are present
      if (c->allocpg() < 0) {
	cprintf("vmn_copy: out of memory\n");
	delete c;
	return 0;
      }
      for(u64 i = 0; i < npages; i++) {
	memmove(c->page[i], page[i], PGSIZE);
      }
    }
  }
  return c;
}

int
vmnode::demand_load()
{
  for (u64 i = 0; i < sz; i += PGSIZE) {
    char *p = page[i / PGSIZE];
    s64 n;
    if (sz - i < PGSIZE)
      n = sz - i;
    else
      n = PGSIZE;
    if (readi(ip, p, offset+i, n) != n)
      return -1;
  }
  return 0;
}

int
vmnode::load(inode *iparg, u64 offarg, u64 szarg)
{
  ip = iparg;
  offset = offarg;
  sz = szarg;

  if (type == ONDEMAND)
    return 0;
  return demand_load();
}

/*
 * vma
 */

vma::vma()
  : rcu_freed("vma"), vma_start(0), vma_end(0), va_type(PRIVATE), n(0)
{
  snprintf(lockname, sizeof(lockname), "vma:%p", this);
  initlock(&lock, lockname, LOCKSTAT_VM);
}

vma::~vma()
{
  if(n)
    n->decref();
  destroylock(&lock);
}

/*
 * vmap
 */

vmap::vmap()
  : cr(10)
{
  snprintf(lockname, sizeof(lockname), "vmap:%p", this);
  initlock(&lock, lockname, LOCKSTAT_VM);

  ref = 1;
  alloc = 0;
  kshared = 0;

  pml4 = setupkvm();
  if (pml4 == 0) {
    cprintf("vmap_alloc: setupkvm out of memory\n");
    goto err0;
  }

  kshared = (char*) ksalloc(slab_kshared);
  if (kshared == NULL) {
    cprintf("vmap::vmap: kshared out of memory\n");
    goto err1;
  }

  if (setupkshared(pml4, kshared)) {
    cprintf("vmap::vmap: setupkshared out of memory\n");
    goto err2;
  }

  return;

 err2:
  ksfree(slab_kshared, kshared);
 err1:
  freevm(pml4);
 err0:
  destroylock(&lock);
}

vmap::~vmap()
{
  if (kshared)
    ksfree(slab_kshared, kshared);
  if (pml4)
    freevm(pml4);
  alloc = 0;
  destroylock(&lock);
}

void
vmap::decref()
{
  if (--ref == 0)
    delete this;
}

vmap*
vmap::copy(int share)
{
  vmap *nm = new vmap();
  if(nm == 0)
    return 0;

  scoped_acquire sa(&lock);
  for (range *r: cr) {
    struct vma *e = (struct vma *) r->value;
    struct vma *ne = new vma();
    if (ne == 0)
      goto err;

    ne->vma_start = e->vma_start;
    ne->vma_end = e->vma_end;
    if (share) {
      ne->n = e->n;
      ne->va_type = COW;

      scoped_acquire sae(&e->lock);
      e->va_type = COW;
      updatepages(pml4, e->vma_start, e->vma_end, [](atomic<pme_t>* p) {
          for (;;) {
            pme_t v = p->load();
            if (!(v & PTE_P) || !(v & PTE_U) || !(v & PTE_W) ||
                cmpxch(p, v, PTE_ADDR(v) | PTE_P | PTE_U | PTE_COW))
              break;
          }
        });
    } else {
      ne->n = e->n->copy();
      ne->va_type = e->va_type;
    }

    if (ne->n == 0)
      goto err;

    ne->n->ref++;
    auto span = nm->cr.search_lock(ne->vma_start, ne->vma_end - ne->vma_start);
    for (auto x __attribute__((unused)): span)
      assert(0);  /* span must be empty */
    span.replace(new range(&nm->cr, ne->vma_start, ne->vma_end - ne->vma_start, ne, 0));
  }

  if (share)
    lcr3(v2p(pml4));  // Reload hardware page table

  return nm;

 err:
  delete nm;
  return 0;
}

// Does any vma overlap start..start+len?
// If yes, return the vma pointer.
// If no, return 0.
// This code can't handle regions at the very end
// of the address space, e.g. 0xffffffff..0x0
// We key vma's by their end address.
vma *
vmap::lookup(uptr start, uptr len)
{
  if (start + len < start)
    panic("vmap::lookup bad len");

  range *r = cr.search(start, len);
  if (r != 0) {
    vma *e = (struct vma *) (r->value);
    if (e->vma_end <= e->vma_start)
      panic("malformed va");
    if (e->vma_start < start+len && e->vma_end > start)
      return e;
  }

  return 0;
}

int
vmap::insert(vmnode *n, uptr vma_start)
{
  vma *e;

  {
    // new scope to release the search lock before tlbflush
    u64 len = n->npages * PGSIZE;
    auto span = cr.search_lock(vma_start, len);
    for (auto r: span) {
      cprintf("vmap::insert: overlap 0x%lx @ 0x%lx\n", r->size, r->key);
      return -1;
    }

    // XXX handle overlaps

    e = new vma();
    if (e == 0) {
      cprintf("vmap::insert: out of vmas\n");
      return -1;
    }

    e->vma_start = vma_start;
    e->vma_end = vma_start + len;
    e->n = n;
    n->ref++;
    span.replace(new range(&cr, vma_start, len, e, 0));
  }

  updatepages(pml4, e->vma_start, e->vma_end, [](atomic<pme_t> *p) {
      for (;;) {
        pme_t v = p->load();
        if (v & PTE_LOCK)
          continue;
        if (cmpxch(p, v, (pme_t) 0))
          break;
      }
    });
  tlbflush();
  return 0;
}

int
vmap::remove(uptr vma_start, uptr len)
{
  {
    // new scope to release the search lock before tlbflush
    uptr vma_end = vma_start + len;

    auto span = cr.search_lock(vma_start, len);
    for (auto r: span) {
      if (r->key < vma_start || r->key + r->size > vma_end) {
        cprintf("vmap::remove: partial unmap not supported\n");
        return -1;
      }
    }

    // XXX handle partial unmap

    span.replace(0);
  }

  updatepages(pml4, vma_start, vma_start + len, [](atomic<pme_t> *p) {
      for (;;) {
        pme_t v = p->load();
        if (v & PTE_LOCK)
          continue;
        if (cmpxch(p, v, (pme_t) 0))
          break;
      }
    });
  tlbflush();
  return 0;
}

/*
 * pagefault handling code on vmap
 */

vma *
vmap::pagefault_ondemand(uptr va, vma *m, scoped_acquire *mlock)
{
  if (m->n->allocpg() < 0)
    panic("pagefault: couldn't allocate pages");
  mlock->release();
  if (m->n->demand_load() < 0)
    panic("pagefault: couldn't load");
  m = lookup(va, 1);
  if (!m)
    panic("pagefault_ondemand");
  mlock->acquire(&m->lock); // re-acquire lock on m
  return m;
}

int
vmap::pagefault_wcow(vma *m)
{
  // Always make a copy of n, even if this process has the only ref,
  // because other processes may change ref count while this process
  // is handling wcow.
  struct vmnode *n = m->n;
  struct vmnode *c = m->n->copy();
  if (c == 0) {
    cprintf("pagefault_wcow: out of mem\n");
    return -1;
  }
  c->ref = 1;
  m->va_type = PRIVATE;
  m->n = c;

  // Update the hardware page tables to reflect the change to the vma
  updatepages(pml4, m->vma_start, m->vma_end, [](atomic<pme_t> *p) {
      for (;;) {
        pme_t v = p->load();
        if (!(v & PTE_P) || cmpxch(p, v, v & ~PTE_P))
          break;
      }
    });

  // drop my ref to vmnode
  n->decref();
  return 0;
}

int
vmap::pagefault(uptr va, u32 err)
{
  bool needflush = false;
  atomic<pme_t> *pte = walkpgdir(pml4, va, 1);

 retry:
  pme_t ptev = pte->load();

  // optimize checks of args to syscals
  if ((ptev & (PTE_P|PTE_U|PTE_W)) == (PTE_P|PTE_U|PTE_W)) {
    // XXX using pagefault() as a security check in syscalls is prone to races
    return 0;
  }

  if (ptev & PTE_LOCK) {
    // locked, might as well wait for the other pagefaulting core..
    goto retry;
  }

  scoped_gc_epoch gc;
  vma *m = lookup(va, 1);
  if (m == 0)
    return -1;

  scoped_acquire mlock(&m->lock);
  u64 npg = (PGROUNDDOWN(va) - m->vma_start) / PGSIZE;

  if (m->n && m->n->type == ONDEMAND && m->n->page[npg] == 0)
    m = pagefault_ondemand(va, m, &mlock);

  if (vm_debug)
    cprintf("pagefault: err 0x%x va 0x%lx type %d ref %lu pid %d\n",
            err, va, m->va_type, m->n->ref.load(), myproc()->pid);

  if (m->va_type == COW && (err & FEC_WR)) {
    if (pagefault_wcow(m) < 0)
      return -1;
    needflush = true;
  }

  if (!cmpxch(pte, ptev, ptev | PTE_LOCK))
    goto retry;

  // XXX check if vma has been deleted, and if so, unlock & goto retry

  if (m->va_type == COW) {
    *pte = v2p(m->n->page[npg]) | PTE_P | PTE_U | PTE_COW;
  } else {
    assert(m->n->ref == 1);
    *pte = v2p(m->n->page[npg]) | PTE_P | PTE_U | PTE_W;
  }

  mlock.release();
  if (needflush)
    tlbflush();
  return 1;
}

int
pagefault(struct vmap *vmap, uptr va, u32 err)
{
  return vmap->pagefault(va, err);
}

// Copy len bytes from p to user address va in vmap.
// Most useful when vmap is not the current page table.
int
vmap::copyout(uptr va, void *p, u64 len)
{
  char *buf = (char*)p;
  while(len > 0){
    uptr va0 = (uptr)PGROUNDDOWN(va);
    scoped_gc_epoch gc;
    vma *vma = lookup(va, 1);
    if(vma == 0)
      return -1;

    acquire(&vma->lock);
    uptr pn = (va0 - vma->vma_start) / PGSIZE;
    char *p0 = vma->n->page[pn];
    if(p0 == 0)
      panic("copyout: missing page");
    uptr n = PGSIZE - (va - va0);
    if(n > len)
      n = len;
    memmove(p0 + (va - va0), buf, n);
    len -= n;
    buf += n;
    va = va0 + PGSIZE;
    release(&vma->lock);
  }
  return 0;
}
<commit_msg>minor<commit_after>#include "types.h"
#include "amd64.h"
#include "mmu.h"
#include "cpu.hh"
#include "kernel.hh"
#include "bits.hh"
#include "spinlock.h"
#include "kalloc.h"
#include "queue.h"
#include "condvar.h"
#include "proc.hh"
#include "vm.hh"
#include "gc.hh"
#include "crange.hh"
#include "cpputil.hh"

enum { vm_debug = 0 };

/*
 * vmnode
 */

vmnode::vmnode(u64 npg, vmntype ntype)
  : npages(npg), ref(0), type(ntype), ip(0), offset(0), sz(0)
{
  if (npg > NELEM(page))
    panic("vmnode too big\n");
  memset(page, 0, sizeof(page));
  if (type == EAGER)
    assert(allocpg() == 0);
}

vmnode::~vmnode()
{
  for(u64 i = 0; i < npages; i++) {
    if (page[i]) {
      kfree(page[i]);
      page[i] = 0;
    }
  }
  if (ip) {
    iput(ip);
    ip = 0;
  }
}

void
vmnode::decref()
{
  if(--ref == 0)
    delete this;
}

int
vmnode::allocpg()
{
  for(u64 i = 0; i < npages; i++) {
    if((page[i] = kalloc()) == 0)
      return -1;
    memset((char *) page[i], 0, PGSIZE);
  }
  return 0;
}

vmnode *
vmnode::copy()
{
  vmnode *c = new vmnode(npages, type);
  if(c != 0) {
    c->type = type;
    if (type == ONDEMAND) {
      c->ip = idup(ip);
      c->offset = offset;
      c->sz = c->sz;
    }
    if (page[0]) {   // If the first page is present, all of them are present
      if (c->allocpg() < 0) {
	cprintf("vmn_copy: out of memory\n");
	delete c;
	return 0;
      }
      for(u64 i = 0; i < npages; i++) {
	memmove(c->page[i], page[i], PGSIZE);
      }
    }
  }
  return c;
}

int
vmnode::demand_load()
{
  for (u64 i = 0; i < sz; i += PGSIZE) {
    char *p = page[i / PGSIZE];
    s64 n;
    if (sz - i < PGSIZE)
      n = sz - i;
    else
      n = PGSIZE;
    if (readi(ip, p, offset+i, n) != n)
      return -1;
  }
  return 0;
}

int
vmnode::load(inode *iparg, u64 offarg, u64 szarg)
{
  ip = iparg;
  offset = offarg;
  sz = szarg;

  if (type == ONDEMAND)
    return 0;
  return demand_load();
}

/*
 * vma
 */

vma::vma()
  : rcu_freed("vma"), vma_start(0), vma_end(0), va_type(PRIVATE), n(0)
{
  snprintf(lockname, sizeof(lockname), "vma:%p", this);
  initlock(&lock, lockname, LOCKSTAT_VM);
}

vma::~vma()
{
  if(n)
    n->decref();
  destroylock(&lock);
}

/*
 * vmap
 */

vmap::vmap()
  : cr(10)
{
  snprintf(lockname, sizeof(lockname), "vmap:%p", this);
  initlock(&lock, lockname, LOCKSTAT_VM);

  ref = 1;
  alloc = 0;
  kshared = 0;

  pml4 = setupkvm();
  if (pml4 == 0) {
    cprintf("vmap_alloc: setupkvm out of memory\n");
    goto err0;
  }

  kshared = (char*) ksalloc(slab_kshared);
  if (kshared == NULL) {
    cprintf("vmap::vmap: kshared out of memory\n");
    goto err1;
  }

  if (setupkshared(pml4, kshared)) {
    cprintf("vmap::vmap: setupkshared out of memory\n");
    goto err2;
  }

  return;

 err2:
  ksfree(slab_kshared, kshared);
 err1:
  freevm(pml4);
 err0:
  destroylock(&lock);
}

vmap::~vmap()
{
  if (kshared)
    ksfree(slab_kshared, kshared);
  if (pml4)
    freevm(pml4);
  alloc = 0;
  destroylock(&lock);
}

void
vmap::decref()
{
  if (--ref == 0)
    delete this;
}

vmap*
vmap::copy(int share)
{
  vmap *nm = new vmap();
  if(nm == 0)
    return 0;

  scoped_acquire sa(&lock);
  for (range *r: cr) {
    struct vma *ne = new vma();
    if (ne == 0)
      goto err;

    struct vma *e = (struct vma *) r->value;
    scoped_acquire sae(&e->lock);

    ne->vma_start = e->vma_start;
    ne->vma_end = e->vma_end;
    if (share) {
      ne->n = e->n;
      ne->va_type = COW;
      e->va_type = COW;
      updatepages(pml4, e->vma_start, e->vma_end, [](atomic<pme_t>* p) {
          for (;;) {
            pme_t v = p->load();
            if (!(v & PTE_P) || !(v & PTE_U) || !(v & PTE_W) ||
                cmpxch(p, v, PTE_ADDR(v) | PTE_P | PTE_U | PTE_COW))
              break;
          }
        });
    } else {
      ne->n = e->n->copy();
      ne->va_type = e->va_type;
    }

    if (ne->n == 0)
      goto err;

    ne->n->ref++;
    auto span = nm->cr.search_lock(ne->vma_start, ne->vma_end - ne->vma_start);
    for (auto x __attribute__((unused)): span)
      assert(0);  /* span must be empty */
    span.replace(new range(&nm->cr, ne->vma_start, ne->vma_end - ne->vma_start, ne, 0));
  }

  if (share) {
    // XXX should really be tlbflush(), but callers hold some locks..
    lcr3(rcr3());  // Reload hardware page table
  }

  return nm;

 err:
  delete nm;
  return 0;
}

// Does any vma overlap start..start+len?
// If yes, return the vma pointer.
// If no, return 0.
// This code can't handle regions at the very end
// of the address space, e.g. 0xffffffff..0x0
// We key vma's by their end address.
vma *
vmap::lookup(uptr start, uptr len)
{
  if (start + len < start)
    panic("vmap::lookup bad len");

  range *r = cr.search(start, len);
  if (r != 0) {
    vma *e = (struct vma *) (r->value);
    if (e->vma_end <= e->vma_start)
      panic("malformed va");
    if (e->vma_start < start+len && e->vma_end > start)
      return e;
  }

  return 0;
}

int
vmap::insert(vmnode *n, uptr vma_start)
{
  vma *e;

  {
    // new scope to release the search lock before tlbflush
    u64 len = n->npages * PGSIZE;
    auto span = cr.search_lock(vma_start, len);
    for (auto r: span) {
      cprintf("vmap::insert: overlap 0x%lx @ 0x%lx\n", r->size, r->key);
      return -1;
    }

    // XXX handle overlaps

    e = new vma();
    if (e == 0) {
      cprintf("vmap::insert: out of vmas\n");
      return -1;
    }

    e->vma_start = vma_start;
    e->vma_end = vma_start + len;
    e->n = n;
    n->ref++;
    span.replace(new range(&cr, vma_start, len, e, 0));
  }

  updatepages(pml4, e->vma_start, e->vma_end, [](atomic<pme_t> *p) {
      for (;;) {
        pme_t v = p->load();
        if (v & PTE_LOCK)
          continue;
        if (cmpxch(p, v, (pme_t) 0))
          break;
      }
    });
  tlbflush();
  return 0;
}

int
vmap::remove(uptr vma_start, uptr len)
{
  {
    // new scope to release the search lock before tlbflush
    uptr vma_end = vma_start + len;

    auto span = cr.search_lock(vma_start, len);
    for (auto r: span) {
      if (r->key < vma_start || r->key + r->size > vma_end) {
        cprintf("vmap::remove: partial unmap not supported\n");
        return -1;
      }
    }

    // XXX handle partial unmap

    span.replace(0);
  }

  updatepages(pml4, vma_start, vma_start + len, [](atomic<pme_t> *p) {
      for (;;) {
        pme_t v = p->load();
        if (v & PTE_LOCK)
          continue;
        if (cmpxch(p, v, (pme_t) 0))
          break;
      }
    });
  tlbflush();
  return 0;
}

/*
 * pagefault handling code on vmap
 */

vma *
vmap::pagefault_ondemand(uptr va, vma *m, scoped_acquire *mlock)
{
  if (m->n->allocpg() < 0)
    panic("pagefault: couldn't allocate pages");
  mlock->release();
  if (m->n->demand_load() < 0)
    panic("pagefault: couldn't load");
  m = lookup(va, 1);
  if (!m)
    panic("pagefault_ondemand");
  mlock->acquire(&m->lock); // re-acquire lock on m
  return m;
}

int
vmap::pagefault_wcow(vma *m)
{
  // Always make a copy of n, even if this process has the only ref,
  // because other processes may change ref count while this process
  // is handling wcow.
  struct vmnode *n = m->n;
  struct vmnode *c = m->n->copy();
  if (c == 0) {
    cprintf("pagefault_wcow: out of mem\n");
    return -1;
  }
  c->ref = 1;
  m->va_type = PRIVATE;
  m->n = c;

  // Update the hardware page tables to reflect the change to the vma
  updatepages(pml4, m->vma_start, m->vma_end, [](atomic<pme_t> *p) {
      for (;;) {
        pme_t v = p->load();
        if (!(v & PTE_P) || cmpxch(p, v, v & ~PTE_P))
          break;
      }
    });

  // drop my ref to vmnode
  n->decref();
  return 0;
}

int
vmap::pagefault(uptr va, u32 err)
{
  bool needflush = false;
  atomic<pme_t> *pte = walkpgdir(pml4, va, 1);

 retry:
  pme_t ptev = pte->load();

  // optimize checks of args to syscals
  if ((ptev & (PTE_P|PTE_U|PTE_W)) == (PTE_P|PTE_U|PTE_W)) {
    // XXX using pagefault() as a security check in syscalls is prone to races
    return 0;
  }

  if (ptev & PTE_LOCK) {
    // locked, might as well wait for the other pagefaulting core..
    goto retry;
  }

  scoped_gc_epoch gc;
  vma *m = lookup(va, 1);
  if (m == 0)
    return -1;

  scoped_acquire mlock(&m->lock);
  u64 npg = (PGROUNDDOWN(va) - m->vma_start) / PGSIZE;

  if (m->n && m->n->type == ONDEMAND && m->n->page[npg] == 0)
    m = pagefault_ondemand(va, m, &mlock);

  if (vm_debug)
    cprintf("pagefault: err 0x%x va 0x%lx type %d ref %lu pid %d\n",
            err, va, m->va_type, m->n->ref.load(), myproc()->pid);

  if (m->va_type == COW && (err & FEC_WR)) {
    if (pagefault_wcow(m) < 0)
      return -1;
    needflush = true;
  }

  if (!cmpxch(pte, ptev, ptev | PTE_LOCK))
    goto retry;

  // XXX check if vma has been deleted, and if so, unlock & goto retry

  if (m->va_type == COW) {
    *pte = v2p(m->n->page[npg]) | PTE_P | PTE_U | PTE_COW;
  } else {
    assert(m->n->ref == 1);
    *pte = v2p(m->n->page[npg]) | PTE_P | PTE_U | PTE_W;
  }

  mlock.release();
  if (needflush)
    tlbflush();
  return 1;
}

int
pagefault(struct vmap *vmap, uptr va, u32 err)
{
  return vmap->pagefault(va, err);
}

// Copy len bytes from p to user address va in vmap.
// Most useful when vmap is not the current page table.
int
vmap::copyout(uptr va, void *p, u64 len)
{
  char *buf = (char*)p;
  while(len > 0){
    uptr va0 = (uptr)PGROUNDDOWN(va);
    scoped_gc_epoch gc;
    vma *vma = lookup(va, 1);
    if(vma == 0)
      return -1;

    acquire(&vma->lock);
    uptr pn = (va0 - vma->vma_start) / PGSIZE;
    char *p0 = vma->n->page[pn];
    if(p0 == 0)
      panic("copyout: missing page");
    uptr n = PGSIZE - (va - va0);
    if(n > len)
      n = len;
    memmove(p0 + (va - va0), buf, n);
    len -= n;
    buf += n;
    va = va0 + PGSIZE;
    release(&vma->lock);
  }
  return 0;
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2009 Yahoo! Inc.  All rights reserved.  The copyrights
embodied in the content of this file are licensed under the BSD
(revised) open source license
 */

#include <math.h>
#include <iostream>
#include <fstream>
#include <float.h>
#include <pthread.h>
#include <time.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "parse_regressor.h"
#include "parse_example.h"
#include "parse_args.h"
#include "gd.h"
#include "noop.h"
#include "vw.h"
#include "simple_label.h"
#include "sender.h"
#include "delay_ring.h"
#include "message_relay.h"

gd_vars* vw(int argc, char *argv[])
{
  size_t numpasses;
  float eta_decay;
  ofstream final_regressor;
  string final_regressor_name;

  parser* p = new_parser(&simple_label);
  regressor regressor1;

  gd_vars *vars = (gd_vars*) malloc(sizeof(gd_vars));

  po::options_description desc("VW options");

  po::variables_map vm = parse_args(argc, argv, desc, *vars, eta_decay,
				    numpasses, regressor1, p,
				    final_regressor_name);

  if (!global.quiet)
    {
      const char * header_fmt = "%-10s %-10s %8s %8s %10s %8s %8s\n";
      fprintf(stderr, header_fmt,
	      "average", "since", "example", "example",
	      "current", "current", "current");
      fprintf(stderr, header_fmt,
	      "loss", "last", "counter", "weight", "label", "predict", "features");
      cerr.precision(5);
    }

  size_t num_threads = global.num_threads();
  gd_thread_params t = {vars, num_threads, regressor1, &final_regressor_name};

  for (; numpasses > 0; numpasses--) {
    start_parser(num_threads, p);
    initialize_delay_ring();

    if (global.unique_id == 0 && global.local_prediction > 0)
      setup_relay();

    if (vm.count("sendto"))
      {
	setup_send();
	destroy_send();
      }
    else if (vm.count("noop"))
      {
	start_noop();
	end_noop();
      }
    else
      {
	setup_gd(t);
	destroy_gd();
      }

    if (global.unique_id == 0 && global.local_prediction > 0)
      destroy_relay();

    destroy_delay_ring();
    end_parser(p);
    vars->eta *= eta_decay;
    reset_source(global.num_bits, p);
  }

  if (final_regressor_name  != "")
    {
      final_regressor.open(final_regressor_name.c_str());
      dump_regressor(final_regressor, regressor1);
    }
  finalize_regressor(final_regressor,regressor1);
  finalize_source(p);
  global.pairs.~vector();
  free(p);

  return vars;
}
<commit_msg>remove invalid delete<commit_after>/*
Copyright (c) 2009 Yahoo! Inc.  All rights reserved.  The copyrights
embodied in the content of this file are licensed under the BSD
(revised) open source license
 */

#include <math.h>
#include <iostream>
#include <fstream>
#include <float.h>
#include <pthread.h>
#include <time.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "parse_regressor.h"
#include "parse_example.h"
#include "parse_args.h"
#include "gd.h"
#include "noop.h"
#include "vw.h"
#include "simple_label.h"
#include "sender.h"
#include "delay_ring.h"
#include "message_relay.h"

gd_vars* vw(int argc, char *argv[])
{
  size_t numpasses;
  float eta_decay;
  ofstream final_regressor;
  string final_regressor_name;

  parser* p = new_parser(&simple_label);
  regressor regressor1;

  gd_vars *vars = (gd_vars*) malloc(sizeof(gd_vars));

  po::options_description desc("VW options");

  po::variables_map vm = parse_args(argc, argv, desc, *vars, eta_decay,
				    numpasses, regressor1, p,
				    final_regressor_name);

  if (!global.quiet)
    {
      const char * header_fmt = "%-10s %-10s %8s %8s %10s %8s %8s\n";
      fprintf(stderr, header_fmt,
	      "average", "since", "example", "example",
	      "current", "current", "current");
      fprintf(stderr, header_fmt,
	      "loss", "last", "counter", "weight", "label", "predict", "features");
      cerr.precision(5);
    }

  size_t num_threads = global.num_threads();
  gd_thread_params t = {vars, num_threads, regressor1, &final_regressor_name};

  for (; numpasses > 0; numpasses--) {
    start_parser(num_threads, p);
    initialize_delay_ring();

    if (global.unique_id == 0 && global.local_prediction > 0)
      setup_relay();

    if (vm.count("sendto"))
      {
	setup_send();
	destroy_send();
      }
    else if (vm.count("noop"))
      {
	start_noop();
	end_noop();
      }
    else
      {
	setup_gd(t);
	destroy_gd();
      }

    if (global.unique_id == 0 && global.local_prediction > 0)
      destroy_relay();

    destroy_delay_ring();
    end_parser(p);
    vars->eta *= eta_decay;
    reset_source(global.num_bits, p);
  }

  if (final_regressor_name  != "")
    {
      final_regressor.open(final_regressor_name.c_str());
      dump_regressor(final_regressor, regressor1);
    }
  finalize_regressor(final_regressor,regressor1);
  finalize_source(p);
  free(p);

  return vars;
}
<|endoftext|>


<commit_before>/* Copyright 2013 Paulo Roberto Urio <paulourio@gmail.com> */
#include "./ant.h"

#include <opencv2/core/core.hpp>

#include <cassert>

#include "./random.h"

struct Move {
	Move(cv::Point2i point, double probability) :
			point(point), probability(probability) {
	}

	cv::Point2i point;
	double probability;
};

namespace acs {

static const double kAlpha = 2.5;
static const double kBeta = 2.0;

Ant::Ant(cv::Point2i position, const cv::Mat& image, const cv::Mat& pheromone,
		Random* random, double imax) :
				pos_(position),
				image_(image),
				pheromone_(pheromone),
				random_(random),
				memory_(random_, image.cols),
				imax_(imax) {
}

Ant::Ant(const Ant& ant) :
				pos_(ant.pos_),
				image_(ant.image_),
				pheromone_(ant.pheromone_),
				random_(ant.random_),
				memory_(ant.random_, ant.image_.cols),
				imax_(ant.imax_) {
}

void Ant::move() {
	for (int step = 0; step < 70; ++step){
	double total = 0.0;
	std::vector<Move> moves;

	/* Add in |moves| all possible moves */
	moves.reserve(8);
	for (int i = -1; i < +2; ++i) {
		for (int j = -1; j < +2; ++j) {
			if (i == 0 && j == 0)
				continue;
			cv::Point2i new_point(pos_.x + j, pos_.y + i);
			if (!IsValidPoint(new_point))
				continue;
			if (memory_.contains(new_point))
				continue;
			double p = Probability(new_point);
			if (std::isfinite(p) && p > 0.0) {
				total += p;
				moves.push_back(Move(new_point, p));
			}
		}
	}
	if (moves.empty()) {
		int x = random_->next() * image_.cols;
		int y = random_->next() * image_.rows;
		memory_.clear();
		set_pos(cv::Point2i(x, y));
		return;
	}
	/* Normalize all |moves| probabilities */
	for (auto& m : moves)
		m.probability /= total;
	/* Pick one move */
	double choice = random_->next();
	auto move = moves.begin();
	while (move != moves.end()) {
		choice -= move->probability;
		if (choice <= 0.0) {
			set_pos(move->point);
			return;
		}
		++move;
	}
	set_pos(moves.back().point);}
}

void Ant::set_pos(cv::Point2i position) {
	pos_ = position;
	memory_.push(pos_);
}

double Ant::Probability(cv::Point2i p) const {
	if (!IsValidPoint(p))
		return 0.0;
	double phero = std::pow(pheromone_.at<double>(p), kAlpha);
	double heuristic = std::pow(HeuristicInformation(p), kBeta);
	double ret = phero * heuristic;
	if (std::isinf(ret))
		return 0.1e-10;
	return ret;
}

double Ant::HeuristicInformation(cv::Point2i p) const {
	double m = Variation(p, -1, -1, +1, +1);

	m = std::max(m, Variation(p, -1, +1, +1, -1));
	m = std::max(m, Variation(p, 0, +1, 0, -1));
	m = std::max(m, Variation(p, -1, 0, +1, 0));

	// m = std::max(m, Variation(p, -2, -1, +2, +1));
	// m = std::max(m, Variation(p, -2, +1, +2, -1));
	// m = std::max(m, Variation(p, -1, -2, +1, +2));
	// m = std::max(m, Variation(p, +1, -2, -1, +2));

	double ret = m / imax_;
	if (std::isinf(ret))
		return 0.1e-10;
	assert(ret <= 1.0);
	return ret;
}

double Ant::ShadowedPixel(const cv::Point2i& p) const {
	if (!IsValidPoint(p))
		return 0.0;
	uchar pixel = image_.at<uchar>(p);
	return static_cast<double>(pixel);
}

double Ant::Variation(const cv::Point2i& p, int x1, int y1, int x2,
		int y2) const {
	cv::Point2i p1(p.x + x1, p.y + y1);
	cv::Point2i p2(p.x + x2, p.y + y2);
	return std::abs(ShadowedPixel(p1) - ShadowedPixel(p2));
}

bool Ant::IsValidPoint(const cv::Point2i& p) const {
	return (0 <= p.y && p.y < image_.rows && 0 <= p.x && p.x < image_.cols);
}

}  // namespace acs

<commit_msg>Preparando apra apresentação<commit_after>/* Copyright 2013 Paulo Roberto Urio <paulourio@gmail.com> */
#include "./ant.h"

#include <opencv2/core/core.hpp>

#include <cassert>

#include "./random.h"

struct Move {
	Move(cv::Point2i point, double probability) :
			point(point), probability(probability) {
	}

	cv::Point2i point;
	double probability;
};

namespace acs {

static const double kAlpha = 2.5;
static const double kBeta = 2.0;

Ant::Ant(cv::Point2i position, const cv::Mat& image, const cv::Mat& pheromone,
		Random* random, double imax) :
				pos_(position),
				image_(image),
				pheromone_(pheromone),
				random_(random),
				memory_(random_, image.cols),
				imax_(imax) {
}

Ant::Ant(const Ant& ant) :
				pos_(ant.pos_),
				image_(ant.image_),
				pheromone_(ant.pheromone_),
				random_(ant.random_),
				memory_(ant.random_, ant.image_.cols),
				imax_(ant.imax_) {
}

void Ant::move() {
	for (int step = 0; step < 1; ++step){
	double total = 0.0;
	std::vector<Move> moves;

	/* Add in |moves| all possible moves */
	moves.reserve(8);
	for (int i = -1; i < +2; ++i) {
		for (int j = -1; j < +2; ++j) {
			if (i == 0 && j == 0)
				continue;
			cv::Point2i new_point(pos_.x + j, pos_.y + i);
			if (!IsValidPoint(new_point))
				continue;
			if (memory_.contains(new_point))
				continue;
			double p = Probability(new_point);
			if (std::isfinite(p) && p > 0.0) {
				total += p;
				moves.push_back(Move(new_point, p));
			}
		}
	}
	if (moves.empty()) {
		int x = random_->next() * image_.cols;
		int y = random_->next() * image_.rows;
		memory_.clear();
		set_pos(cv::Point2i(x, y));
		return;
	}
	/* Normalize all |moves| probabilities */
	for (auto& m : moves)
		m.probability /= total;
	/* Pick one move */
	double choice = random_->next();
	auto move = moves.begin();
	while (move != moves.end()) {
		choice -= move->probability;
		if (choice <= 0.0) {
			set_pos(move->point);
			return;
		}
		++move;
	}
	set_pos(moves.back().point);}
}

void Ant::set_pos(cv::Point2i position) {
	pos_ = position;
	memory_.push(pos_);
}

double Ant::Probability(cv::Point2i p) const {
	if (!IsValidPoint(p))
		return 0.0;
	double phero = std::pow(pheromone_.at<double>(p), kAlpha);
	double heuristic = std::pow(HeuristicInformation(p), kBeta);
	double ret = phero * heuristic;
	if (std::isinf(ret))
		return 0.1e-10;
	return ret;
}

double Ant::HeuristicInformation(cv::Point2i p) const {
	double m = Variation(p, -1, -1, +1, +1);

	m = std::max(m, Variation(p, -1, +1, +1, -1));
	m = std::max(m, Variation(p, 0, +1, 0, -1));
	m = std::max(m, Variation(p, -1, 0, +1, 0));

	// m = std::max(m, Variation(p, -2, -1, +2, +1));
	// m = std::max(m, Variation(p, -2, +1, +2, -1));
	// m = std::max(m, Variation(p, -1, -2, +1, +2));
	// m = std::max(m, Variation(p, +1, -2, -1, +2));

	double ret = m / imax_;
	if (std::isinf(ret))
		return 0.1e-10;
	assert(ret <= 1.0);
	return ret;
}

double Ant::ShadowedPixel(const cv::Point2i& p) const {
	if (!IsValidPoint(p))
		return 0.0;
	uchar pixel = image_.at<uchar>(p);
	return static_cast<double>(pixel);
}

double Ant::Variation(const cv::Point2i& p, int x1, int y1, int x2,
		int y2) const {
	cv::Point2i p1(p.x + x1, p.y + y1);
	cv::Point2i p2(p.x + x2, p.y + y2);
	return std::abs(ShadowedPixel(p1) - ShadowedPixel(p2));
}

bool Ant::IsValidPoint(const cv::Point2i& p) const {
	return (0 <= p.y && p.y < image_.rows && 0 <= p.x && p.x < image_.cols);
}

}  // namespace acs

<|endoftext|>


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

// Tests Google Mock's output in various scenarios.  This ensures that
// Google Mock's messages are readable and useful.

#include "gmock/gmock.h"

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

#include "gtest/gtest.h"

// Silence C4100 (unreferenced formal parameter) for MSVC
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable:4100)
#endif

using testing::_;
using testing::AnyNumber;
using testing::Ge;
using testing::InSequence;
using testing::NaggyMock;
using testing::Ref;
using testing::Return;
using testing::Sequence;
using testing::Value;

class MockFoo {
 public:
  MockFoo() {}

  MOCK_METHOD3(Bar, char(const std::string& s, int i, double x));
  MOCK_METHOD2(Bar2, bool(int x, int y));
  MOCK_METHOD2(Bar3, void(int x, int y));

 private:
  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFoo);
};

class GMockOutputTest : public testing::Test {
 protected:
  NaggyMock<MockFoo> foo_;
};

TEST_F(GMockOutputTest, ExpectedCall) {
  testing::GMOCK_FLAG(verbose) = "info";

  EXPECT_CALL(foo_, Bar2(0, _));
  foo_.Bar2(0, 0);  // Expected call

  testing::GMOCK_FLAG(verbose) = "warning";
}

TEST_F(GMockOutputTest, ExpectedCallToVoidFunction) {
  testing::GMOCK_FLAG(verbose) = "info";

  EXPECT_CALL(foo_, Bar3(0, _));
  foo_.Bar3(0, 0);  // Expected call

  testing::GMOCK_FLAG(verbose) = "warning";
}

TEST_F(GMockOutputTest, ExplicitActionsRunOut) {
  EXPECT_CALL(foo_, Bar2(_, _))
      .Times(2)
      .WillOnce(Return(false));
  foo_.Bar2(2, 2);
  foo_.Bar2(1, 1);  // Explicit actions in EXPECT_CALL run out.
}

TEST_F(GMockOutputTest, UnexpectedCall) {
  EXPECT_CALL(foo_, Bar2(0, _));

  foo_.Bar2(1, 0);  // Unexpected call
  foo_.Bar2(0, 0);  // Expected call
}

TEST_F(GMockOutputTest, UnexpectedCallToVoidFunction) {
  EXPECT_CALL(foo_, Bar3(0, _));

  foo_.Bar3(1, 0);  // Unexpected call
  foo_.Bar3(0, 0);  // Expected call
}

TEST_F(GMockOutputTest, ExcessiveCall) {
  EXPECT_CALL(foo_, Bar2(0, _));

  foo_.Bar2(0, 0);  // Expected call
  foo_.Bar2(0, 1);  // Excessive call
}

TEST_F(GMockOutputTest, ExcessiveCallToVoidFunction) {
  EXPECT_CALL(foo_, Bar3(0, _));

  foo_.Bar3(0, 0);  // Expected call
  foo_.Bar3(0, 1);  // Excessive call
}

TEST_F(GMockOutputTest, UninterestingCall) {
  foo_.Bar2(0, 1);  // Uninteresting call
}

TEST_F(GMockOutputTest, UninterestingCallToVoidFunction) {
  foo_.Bar3(0, 1);  // Uninteresting call
}

TEST_F(GMockOutputTest, RetiredExpectation) {
  EXPECT_CALL(foo_, Bar2(_, _))
      .RetiresOnSaturation();
  EXPECT_CALL(foo_, Bar2(0, 0));

  foo_.Bar2(1, 1);
  foo_.Bar2(1, 1);  // Matches a retired expectation
  foo_.Bar2(0, 0);
}

TEST_F(GMockOutputTest, UnsatisfiedPrerequisite) {
  {
    InSequence s;
    EXPECT_CALL(foo_, Bar(_, 0, _));
    EXPECT_CALL(foo_, Bar2(0, 0));
    EXPECT_CALL(foo_, Bar2(1, _));
  }

  foo_.Bar2(1, 0);  // Has one immediate unsatisfied pre-requisite
  foo_.Bar("Hi", 0, 0);
  foo_.Bar2(0, 0);
  foo_.Bar2(1, 0);
}

TEST_F(GMockOutputTest, UnsatisfiedPrerequisites) {
  Sequence s1, s2;

  EXPECT_CALL(foo_, Bar(_, 0, _))
      .InSequence(s1);
  EXPECT_CALL(foo_, Bar2(0, 0))
      .InSequence(s2);
  EXPECT_CALL(foo_, Bar2(1, _))
      .InSequence(s1, s2);

  foo_.Bar2(1, 0);  // Has two immediate unsatisfied pre-requisites
  foo_.Bar("Hi", 0, 0);
  foo_.Bar2(0, 0);
  foo_.Bar2(1, 0);
}

TEST_F(GMockOutputTest, UnsatisfiedWith) {
  EXPECT_CALL(foo_, Bar2(_, _)).With(Ge());
}

TEST_F(GMockOutputTest, UnsatisfiedExpectation) {
  EXPECT_CALL(foo_, Bar(_, _, _));
  EXPECT_CALL(foo_, Bar2(0, _))
      .Times(2);

  foo_.Bar2(0, 1);
}

TEST_F(GMockOutputTest, MismatchArguments) {
  const std::string s = "Hi";
  EXPECT_CALL(foo_, Bar(Ref(s), _, Ge(0)));

  foo_.Bar("Ho", 0, -0.1);  // Mismatch arguments
  foo_.Bar(s, 0, 0);
}

TEST_F(GMockOutputTest, MismatchWith) {
  EXPECT_CALL(foo_, Bar2(Ge(2), Ge(1)))
      .With(Ge());

  foo_.Bar2(2, 3);  // Mismatch With()
  foo_.Bar2(2, 1);
}

TEST_F(GMockOutputTest, MismatchArgumentsAndWith) {
  EXPECT_CALL(foo_, Bar2(Ge(2), Ge(1)))
      .With(Ge());

  foo_.Bar2(1, 3);  // Mismatch arguments and mismatch With()
  foo_.Bar2(2, 1);
}

TEST_F(GMockOutputTest, UnexpectedCallWithDefaultAction) {
  ON_CALL(foo_, Bar2(_, _))
      .WillByDefault(Return(true));   // Default action #1
  ON_CALL(foo_, Bar2(1, _))
      .WillByDefault(Return(false));  // Default action #2

  EXPECT_CALL(foo_, Bar2(2, 2));
  foo_.Bar2(1, 0);  // Unexpected call, takes default action #2.
  foo_.Bar2(0, 0);  // Unexpected call, takes default action #1.
  foo_.Bar2(2, 2);  // Expected call.
}

TEST_F(GMockOutputTest, ExcessiveCallWithDefaultAction) {
  ON_CALL(foo_, Bar2(_, _))
      .WillByDefault(Return(true));   // Default action #1
  ON_CALL(foo_, Bar2(1, _))
      .WillByDefault(Return(false));  // Default action #2

  EXPECT_CALL(foo_, Bar2(2, 2));
  EXPECT_CALL(foo_, Bar2(1, 1));

  foo_.Bar2(2, 2);  // Expected call.
  foo_.Bar2(2, 2);  // Excessive call, takes default action #1.
  foo_.Bar2(1, 1);  // Expected call.
  foo_.Bar2(1, 1);  // Excessive call, takes default action #2.
}

TEST_F(GMockOutputTest, UninterestingCallWithDefaultAction) {
  ON_CALL(foo_, Bar2(_, _))
      .WillByDefault(Return(true));   // Default action #1
  ON_CALL(foo_, Bar2(1, _))
      .WillByDefault(Return(false));  // Default action #2

  foo_.Bar2(2, 2);  // Uninteresting call, takes default action #1.
  foo_.Bar2(1, 1);  // Uninteresting call, takes default action #2.
}

TEST_F(GMockOutputTest, ExplicitActionsRunOutWithDefaultAction) {
  ON_CALL(foo_, Bar2(_, _))
      .WillByDefault(Return(true));   // Default action #1

  EXPECT_CALL(foo_, Bar2(_, _))
      .Times(2)
      .WillOnce(Return(false));
  foo_.Bar2(2, 2);
  foo_.Bar2(1, 1);  // Explicit actions in EXPECT_CALL run out.
}

TEST_F(GMockOutputTest, CatchesLeakedMocks) {
  MockFoo* foo1 = new MockFoo;
  MockFoo* foo2 = new MockFoo;

  // Invokes ON_CALL on foo1.
  ON_CALL(*foo1, Bar(_, _, _)).WillByDefault(Return('a'));

  // Invokes EXPECT_CALL on foo2.
  EXPECT_CALL(*foo2, Bar2(_, _));
  EXPECT_CALL(*foo2, Bar2(1, _));
  EXPECT_CALL(*foo2, Bar3(_, _)).Times(AnyNumber());
  foo2->Bar2(2, 1);
  foo2->Bar2(1, 1);

  // Both foo1 and foo2 are deliberately leaked.
}

MATCHER_P2(IsPair, first, second, "") {
  return Value(arg.first, first) && Value(arg.second, second);
}

TEST_F(GMockOutputTest, PrintsMatcher) {
  const testing::Matcher<int> m1 = Ge(48);
  EXPECT_THAT((std::pair<int, bool>(42, true)), IsPair(m1, true));
}

void TestCatchesLeakedMocksInAdHocTests() {
  MockFoo* foo = new MockFoo;

  // Invokes EXPECT_CALL on foo.
  EXPECT_CALL(*foo, Bar2(_, _));
  foo->Bar2(2, 1);

  // foo is deliberately leaked.
}

int main(int argc, char **argv) {
  testing::InitGoogleMock(&argc, argv);
  // Ensures that the tests pass no matter what value of
  // --gmock_catch_leaked_mocks and --gmock_verbose the user specifies.
  testing::GMOCK_FLAG(catch_leaked_mocks) = true;
  testing::GMOCK_FLAG(verbose) = "warning";

  TestCatchesLeakedMocksInAdHocTests();
  return RUN_ALL_TESTS();
}

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

// Tests Google Mock's output in various scenarios.  This ensures that
// Google Mock's messages are readable and useful.

#include "gmock/gmock.h"

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

#include "gtest/gtest.h"

// Silence C4100 (unreferenced formal parameter) for MSVC
#ifdef _MSC_VER
# if _MSC_VER <= 1900
#  pragma warning(push)
#  pragma warning(disable:4100)
# endif
#endif

using testing::_;
using testing::AnyNumber;
using testing::Ge;
using testing::InSequence;
using testing::NaggyMock;
using testing::Ref;
using testing::Return;
using testing::Sequence;
using testing::Value;

class MockFoo {
 public:
  MockFoo() {}

  MOCK_METHOD3(Bar, char(const std::string& s, int i, double x));
  MOCK_METHOD2(Bar2, bool(int x, int y));
  MOCK_METHOD2(Bar3, void(int x, int y));

 private:
  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFoo);
};

class GMockOutputTest : public testing::Test {
 protected:
  NaggyMock<MockFoo> foo_;
};

TEST_F(GMockOutputTest, ExpectedCall) {
  testing::GMOCK_FLAG(verbose) = "info";

  EXPECT_CALL(foo_, Bar2(0, _));
  foo_.Bar2(0, 0);  // Expected call

  testing::GMOCK_FLAG(verbose) = "warning";
}

TEST_F(GMockOutputTest, ExpectedCallToVoidFunction) {
  testing::GMOCK_FLAG(verbose) = "info";

  EXPECT_CALL(foo_, Bar3(0, _));
  foo_.Bar3(0, 0);  // Expected call

  testing::GMOCK_FLAG(verbose) = "warning";
}

TEST_F(GMockOutputTest, ExplicitActionsRunOut) {
  EXPECT_CALL(foo_, Bar2(_, _))
      .Times(2)
      .WillOnce(Return(false));
  foo_.Bar2(2, 2);
  foo_.Bar2(1, 1);  // Explicit actions in EXPECT_CALL run out.
}

TEST_F(GMockOutputTest, UnexpectedCall) {
  EXPECT_CALL(foo_, Bar2(0, _));

  foo_.Bar2(1, 0);  // Unexpected call
  foo_.Bar2(0, 0);  // Expected call
}

TEST_F(GMockOutputTest, UnexpectedCallToVoidFunction) {
  EXPECT_CALL(foo_, Bar3(0, _));

  foo_.Bar3(1, 0);  // Unexpected call
  foo_.Bar3(0, 0);  // Expected call
}

TEST_F(GMockOutputTest, ExcessiveCall) {
  EXPECT_CALL(foo_, Bar2(0, _));

  foo_.Bar2(0, 0);  // Expected call
  foo_.Bar2(0, 1);  // Excessive call
}

TEST_F(GMockOutputTest, ExcessiveCallToVoidFunction) {
  EXPECT_CALL(foo_, Bar3(0, _));

  foo_.Bar3(0, 0);  // Expected call
  foo_.Bar3(0, 1);  // Excessive call
}

TEST_F(GMockOutputTest, UninterestingCall) {
  foo_.Bar2(0, 1);  // Uninteresting call
}

TEST_F(GMockOutputTest, UninterestingCallToVoidFunction) {
  foo_.Bar3(0, 1);  // Uninteresting call
}

TEST_F(GMockOutputTest, RetiredExpectation) {
  EXPECT_CALL(foo_, Bar2(_, _))
      .RetiresOnSaturation();
  EXPECT_CALL(foo_, Bar2(0, 0));

  foo_.Bar2(1, 1);
  foo_.Bar2(1, 1);  // Matches a retired expectation
  foo_.Bar2(0, 0);
}

TEST_F(GMockOutputTest, UnsatisfiedPrerequisite) {
  {
    InSequence s;
    EXPECT_CALL(foo_, Bar(_, 0, _));
    EXPECT_CALL(foo_, Bar2(0, 0));
    EXPECT_CALL(foo_, Bar2(1, _));
  }

  foo_.Bar2(1, 0);  // Has one immediate unsatisfied pre-requisite
  foo_.Bar("Hi", 0, 0);
  foo_.Bar2(0, 0);
  foo_.Bar2(1, 0);
}

TEST_F(GMockOutputTest, UnsatisfiedPrerequisites) {
  Sequence s1, s2;

  EXPECT_CALL(foo_, Bar(_, 0, _))
      .InSequence(s1);
  EXPECT_CALL(foo_, Bar2(0, 0))
      .InSequence(s2);
  EXPECT_CALL(foo_, Bar2(1, _))
      .InSequence(s1, s2);

  foo_.Bar2(1, 0);  // Has two immediate unsatisfied pre-requisites
  foo_.Bar("Hi", 0, 0);
  foo_.Bar2(0, 0);
  foo_.Bar2(1, 0);
}

TEST_F(GMockOutputTest, UnsatisfiedWith) {
  EXPECT_CALL(foo_, Bar2(_, _)).With(Ge());
}

TEST_F(GMockOutputTest, UnsatisfiedExpectation) {
  EXPECT_CALL(foo_, Bar(_, _, _));
  EXPECT_CALL(foo_, Bar2(0, _))
      .Times(2);

  foo_.Bar2(0, 1);
}

TEST_F(GMockOutputTest, MismatchArguments) {
  const std::string s = "Hi";
  EXPECT_CALL(foo_, Bar(Ref(s), _, Ge(0)));

  foo_.Bar("Ho", 0, -0.1);  // Mismatch arguments
  foo_.Bar(s, 0, 0);
}

TEST_F(GMockOutputTest, MismatchWith) {
  EXPECT_CALL(foo_, Bar2(Ge(2), Ge(1)))
      .With(Ge());

  foo_.Bar2(2, 3);  // Mismatch With()
  foo_.Bar2(2, 1);
}

TEST_F(GMockOutputTest, MismatchArgumentsAndWith) {
  EXPECT_CALL(foo_, Bar2(Ge(2), Ge(1)))
      .With(Ge());

  foo_.Bar2(1, 3);  // Mismatch arguments and mismatch With()
  foo_.Bar2(2, 1);
}

TEST_F(GMockOutputTest, UnexpectedCallWithDefaultAction) {
  ON_CALL(foo_, Bar2(_, _))
      .WillByDefault(Return(true));   // Default action #1
  ON_CALL(foo_, Bar2(1, _))
      .WillByDefault(Return(false));  // Default action #2

  EXPECT_CALL(foo_, Bar2(2, 2));
  foo_.Bar2(1, 0);  // Unexpected call, takes default action #2.
  foo_.Bar2(0, 0);  // Unexpected call, takes default action #1.
  foo_.Bar2(2, 2);  // Expected call.
}

TEST_F(GMockOutputTest, ExcessiveCallWithDefaultAction) {
  ON_CALL(foo_, Bar2(_, _))
      .WillByDefault(Return(true));   // Default action #1
  ON_CALL(foo_, Bar2(1, _))
      .WillByDefault(Return(false));  // Default action #2

  EXPECT_CALL(foo_, Bar2(2, 2));
  EXPECT_CALL(foo_, Bar2(1, 1));

  foo_.Bar2(2, 2);  // Expected call.
  foo_.Bar2(2, 2);  // Excessive call, takes default action #1.
  foo_.Bar2(1, 1);  // Expected call.
  foo_.Bar2(1, 1);  // Excessive call, takes default action #2.
}

TEST_F(GMockOutputTest, UninterestingCallWithDefaultAction) {
  ON_CALL(foo_, Bar2(_, _))
      .WillByDefault(Return(true));   // Default action #1
  ON_CALL(foo_, Bar2(1, _))
      .WillByDefault(Return(false));  // Default action #2

  foo_.Bar2(2, 2);  // Uninteresting call, takes default action #1.
  foo_.Bar2(1, 1);  // Uninteresting call, takes default action #2.
}

TEST_F(GMockOutputTest, ExplicitActionsRunOutWithDefaultAction) {
  ON_CALL(foo_, Bar2(_, _))
      .WillByDefault(Return(true));   // Default action #1

  EXPECT_CALL(foo_, Bar2(_, _))
      .Times(2)
      .WillOnce(Return(false));
  foo_.Bar2(2, 2);
  foo_.Bar2(1, 1);  // Explicit actions in EXPECT_CALL run out.
}

TEST_F(GMockOutputTest, CatchesLeakedMocks) {
  MockFoo* foo1 = new MockFoo;
  MockFoo* foo2 = new MockFoo;

  // Invokes ON_CALL on foo1.
  ON_CALL(*foo1, Bar(_, _, _)).WillByDefault(Return('a'));

  // Invokes EXPECT_CALL on foo2.
  EXPECT_CALL(*foo2, Bar2(_, _));
  EXPECT_CALL(*foo2, Bar2(1, _));
  EXPECT_CALL(*foo2, Bar3(_, _)).Times(AnyNumber());
  foo2->Bar2(2, 1);
  foo2->Bar2(1, 1);

  // Both foo1 and foo2 are deliberately leaked.
}

MATCHER_P2(IsPair, first, second, "") {
  return Value(arg.first, first) && Value(arg.second, second);
}

TEST_F(GMockOutputTest, PrintsMatcher) {
  const testing::Matcher<int> m1 = Ge(48);
  EXPECT_THAT((std::pair<int, bool>(42, true)), IsPair(m1, true));
}

void TestCatchesLeakedMocksInAdHocTests() {
  MockFoo* foo = new MockFoo;

  // Invokes EXPECT_CALL on foo.
  EXPECT_CALL(*foo, Bar2(_, _));
  foo->Bar2(2, 1);

  // foo is deliberately leaked.
}

int main(int argc, char **argv) {
  testing::InitGoogleMock(&argc, argv);
  // Ensures that the tests pass no matter what value of
  // --gmock_catch_leaked_mocks and --gmock_verbose the user specifies.
  testing::GMOCK_FLAG(catch_leaked_mocks) = true;
  testing::GMOCK_FLAG(verbose) = "warning";

  TestCatchesLeakedMocksInAdHocTests();
  return RUN_ALL_TESTS();
}

#ifdef _MSC_VER
# if _MSC_VER <= 1900
#  pragma warning(pop)
# endif
#endif
<|endoftext|>


<commit_before>#include "configure.hpp"
#include "parsers/md_parser.hpp"
#include "display_drivers/ncurses_display_driver.hpp"
#include "display_drivers/plaintext_display_driver.hpp"
#include "display_drivers/latex_display_driver.hpp"
#include "display_drivers/html_display_driver.hpp"
#include "display_drivers/troff_display_driver.hpp"
#include "display_drivers/ansi_display_driver.hpp"
#include "display_drivers/md_display_driver.hpp"
#include "display_drivers/rst_display_driver.hpp"

#include "options.hpp"

#include <iostream>
#include <locale.h>
#include <cassert>

using namespace std;

int main(int argc, char ** argv) {
	setlocale(LC_ALL, "");

	MdlOptions op(argc, argv);
	Parser *parser(new MdParser(op.input_file()));
	DisplayDriver *driver(nullptr);
	ofstream output_file;

	string driver_string(op.display_driver());
	if (driver_string == "plain") {
		driver = new PlainTextDisplayDriver();
	} else if (driver_string == "ncurses") {
		driver = new NcursesDisplayDriver();
	} else if (driver_string == "latex") {
		driver = new LaTeXDisplayDriver(true);
	} else if (driver_string == "html") {
		driver = new HtmlDisplayDriver(true);
	} else if (driver_string == "troff") {
		driver = new TroffDisplayDriver(true);
	} else if (driver_string == "ansi") {
		driver = new AnsiDisplayDriver();
	} else if (driver_string == "md") {
		driver = new MdDisplayDriver();
	} else if (driver_string == "rst") {
		driver = new RstDisplayDriver();
	}

	assert(driver);
	assert(parser);

	/*
	 * This code section is not used since there is only one parser at the moment.
	 *
	if (vm.count("input-parser")) {
		// Select parser
	} else {
		// Default: MD
	}*/

	if (!op.output_file().empty()) {
		output_file.open(op.output_file());
		driver->display(parser->get_document(), output_file);
		output_file.close();
	} else {
		driver->display(parser->get_document());
	}

	delete driver;
	delete parser;

	return 0;
}
<commit_msg>Remove useless includes<commit_after>#include "configure.hpp"
#include "parsers/md_parser.hpp"
#include "display_drivers/ncurses_display_driver.hpp"
#include "display_drivers/plaintext_display_driver.hpp"
#include "display_drivers/latex_display_driver.hpp"
#include "display_drivers/html_display_driver.hpp"
#include "display_drivers/troff_display_driver.hpp"
#include "display_drivers/ansi_display_driver.hpp"
#include "display_drivers/md_display_driver.hpp"
#include "display_drivers/rst_display_driver.hpp"

#include "options.hpp"

#include <cassert>

using namespace std;

int main(int argc, char ** argv) {
	setlocale(LC_ALL, "");

	MdlOptions op(argc, argv);
	Parser *parser(new MdParser(op.input_file()));
	DisplayDriver *driver(nullptr);
	ofstream output_file;

	string driver_string(op.display_driver());
	if (driver_string == "plain") {
		driver = new PlainTextDisplayDriver();
	} else if (driver_string == "ncurses") {
		driver = new NcursesDisplayDriver();
	} else if (driver_string == "latex") {
		driver = new LaTeXDisplayDriver(true);
	} else if (driver_string == "html") {
		driver = new HtmlDisplayDriver(true);
	} else if (driver_string == "troff") {
		driver = new TroffDisplayDriver(true);
	} else if (driver_string == "ansi") {
		driver = new AnsiDisplayDriver();
	} else if (driver_string == "md") {
		driver = new MdDisplayDriver();
	} else if (driver_string == "rst") {
		driver = new RstDisplayDriver();
	}

	assert(driver);
	assert(parser);

	/*
	 * This code section is not used since there is only one parser at the moment.
	 *
	if (vm.count("input-parser")) {
		// Select parser
	} else {
		// Default: MD
	}*/

	if (!op.output_file().empty()) {
		output_file.open(op.output_file());
		driver->display(parser->get_document(), output_file);
		output_file.close();
	} else {
		driver->display(parser->get_document());
	}

	delete driver;
	delete parser;

	return 0;
}
<|endoftext|>


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

#include <direct.h>
#include <shlobj.h>
#include <stringapiset.h>

#include <iostream>
#include <string>

#include "app/src/log.h"
#include "database/src/desktop/util_desktop.h"

namespace firebase {
namespace database {
namespace internal {

// Split a string based on specified character delimiter into constituent parts
static std::vector<std::string> split_string(const std::string& s,
                                             const char delimiter='/') {
  size_t pos = 0;
  // This index is used as the starting index to search the delimiters from.
  size_t delimiter_search_start = 0;
  // Skip any leading delimiters
  while(s[delimiter_search_start] == delimiter) {
    delimiter_search_start++;
  }

  std::vector<std::string> split_parts;
  size_t len = s.size();
  // Cant proceed if input string consists of just delimiters
  if (pos >= len) {
    return split_parts;
  }

  while( (pos = s.find(delimiter, delimiter_search_start)) != std::string::npos) {
    split_parts.push_back(s.substr(delimiter_search_start, pos-delimiter_search_start));

    while(s[pos] == delimiter && pos<len) {
      pos++;
      delimiter_search_start = pos;
    }
  }

  // If the input string doesn't end with a delimiter we need to push the last
  // token into our return vector
  if (delimiter_search_start != len)
    split_parts.push_back(s.substr(delimiter_search_start, len-delimiter_search_start));

  return split_parts;
}

static std::string utf8_encode(const std::wstring& wstr) {
  if (wstr.empty()) return std::string();
  int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(),
                                        NULL, 0, NULL, NULL);
  std::string strTo(size_needed, 0);
  WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0],
                      size_needed, NULL, NULL);
  return strTo;
}

std::string GetAppDataPath(const char* app_name, bool should_create) {
  wchar_t* pwstr = nullptr;
  HRESULT result = SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &pwstr);
  if (result != S_OK) {
    return "";
  }
  std::wstring wstr(pwstr);
  CoTaskMemFree(static_cast<void*>(pwstr));
  std::string path = utf8_encode(wstr);
  if (path == "") return "";
  if (should_create) {
    // App name might contain path separators. Split it to get list of subdirs
    std::vector<std::string> app_name_parts = split_string(app_name, '/');
    if(app_name_parts.empty()) return "";
    std::string dir_path = path;
    // Recursively create the entire tree of directories
    for (std::vector<std::string>::const_iterator it = app_name_parts.begin();
                                            it != app_name_parts.end(); it++) {
          dir_path = dir_path + "\\" + *it;
          retval = _mkdir(dir_path.c_str());
          if (retval != 0 && errno != EEXIST) return "";
    }
  }
  return path + "\\" + app_name;
}

}  // namespace internal
}  // namespace database
}  // namespace firebase
<commit_msg>declaring retval variable<commit_after>// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <direct.h>
#include <shlobj.h>
#include <stringapiset.h>

#include <iostream>
#include <string>

#include "app/src/log.h"
#include "database/src/desktop/util_desktop.h"

namespace firebase {
namespace database {
namespace internal {

// Split a string based on specified character delimiter into constituent parts
static std::vector<std::string> split_string(const std::string& s,
                                             const char delimiter='/') {
  size_t pos = 0;
  // This index is used as the starting index to search the delimiters from.
  size_t delimiter_search_start = 0;
  // Skip any leading delimiters
  while(s[delimiter_search_start] == delimiter) {
    delimiter_search_start++;
  }

  std::vector<std::string> split_parts;
  size_t len = s.size();
  // Cant proceed if input string consists of just delimiters
  if (pos >= len) {
    return split_parts;
  }

  while( (pos = s.find(delimiter, delimiter_search_start)) != std::string::npos) {
    split_parts.push_back(s.substr(delimiter_search_start, pos-delimiter_search_start));

    while(s[pos] == delimiter && pos<len) {
      pos++;
      delimiter_search_start = pos;
    }
  }

  // If the input string doesn't end with a delimiter we need to push the last
  // token into our return vector
  if (delimiter_search_start != len)
    split_parts.push_back(s.substr(delimiter_search_start, len-delimiter_search_start));

  return split_parts;
}

static std::string utf8_encode(const std::wstring& wstr) {
  if (wstr.empty()) return std::string();
  int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(),
                                        NULL, 0, NULL, NULL);
  std::string strTo(size_needed, 0);
  WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0],
                      size_needed, NULL, NULL);
  return strTo;
}

std::string GetAppDataPath(const char* app_name, bool should_create) {
  wchar_t* pwstr = nullptr;
  HRESULT result = SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &pwstr);
  if (result != S_OK) {
    return "";
  }
  std::wstring wstr(pwstr);
  CoTaskMemFree(static_cast<void*>(pwstr));
  std::string path = utf8_encode(wstr);
  if (path == "") return "";
  if (should_create) {
    // App name might contain path separators. Split it to get list of subdirs
    std::vector<std::string> app_name_parts = split_string(app_name, '/');
    if(app_name_parts.empty()) return "";
    std::string dir_path = path;
    // Recursively create the entire tree of directories
    for (std::vector<std::string>::const_iterator it = app_name_parts.begin();
                                            it != app_name_parts.end(); it++) {
          dir_path = dir_path + "\\" + *it;
          int retval = _mkdir(dir_path.c_str());
          if (retval != 0 && errno != EEXIST) return "";
    }
  }
  return path + "\\" + app_name;
}

}  // namespace internal
}  // namespace database
}  // namespace firebase
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
 * SPI Master library for arduino.
 *
 * This file is free software; you can redistribute it and/or modify
 * it under the terms of either the GNU General Public License version 2
 * or the GNU Lesser General Public License version 2.1, both as
 * published by the Free Software Foundation.
 */

#include "SPI.h"
#include "wiring_private.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_mcspi.h"
#include "inc/hw_gpio.h"
#include "driverlib/rom_map.h"
#include "driverlib/spi.h"
#include "driverlib/gpio.h"
#include "driverlib/prcm.h"
#include "driverlib/pin.h"

#define SSIBASE g_ulSSIBase[SSIModule]
#define NOT_ACTIVE 0xA

static const unsigned long g_ulSSIBase[] = {
	GSPI_BASE
};

//*****************************************************************************
//
// The list of SSI peripherals.
//
//*****************************************************************************
static const unsigned long g_ulSSIPeriph[] = {
	PRCM_GSPI
};

//*****************************************************************************
//
// The list of SSI gpio configurations.
//
//*****************************************************************************
static const unsigned long g_ulSSIPins[][4] = {
	{PIN_05 /* SCLK */, PIN_08 /* SS */, PIN_06 /* MISO */, PIN_07 /* MOSI */}
};

static const unsigned long g_ulSSIPinModes[][4] = {
	{PIN_MODE_7 /* SCLK */, PIN_MODE_7 /* SS */, PIN_MODE_7 /* MISO */, PIN_MODE_7 /* MOSI */}
};

SPIClass::SPIClass(void) {
	SSIModule = NOT_ACTIVE;
	SSIBitOrder = MSBFIRST;
}

SPIClass::SPIClass(uint8_t module) {
	SSIModule = module;
	SSIBitOrder = MSBFIRST;
}

void SPIClass::begin() {
	unsigned long initialData = 0;

	if(SSIModule == NOT_ACTIVE) {
		SSIModule = BOOST_PACK_SPI;
	}

	MAP_PRCMPeripheralClkEnable(PRCM_GSPI, PRCM_RUN_MODE_CLK);

	/* Configure pins as SPI */
	MAP_PinTypeSPI(g_ulSSIPins[SSIModule][0], g_ulSSIPinModes[SSIModule][0]);
	/* Leave the CS pin under software control */
//	MAP_PinTypeSPI(g_ulSSIPins[SSIModule][1], g_ulSSIPinModes[SSIModule][1]);
	MAP_PinTypeSPI(g_ulSSIPins[SSIModule][2], g_ulSSIPinModes[SSIModule][2]);
	MAP_PinTypeSPI(g_ulSSIPins[SSIModule][3], g_ulSSIPinModes[SSIModule][3]);

	MAP_PRCMPeripheralReset(PRCM_GSPI);
	MAP_SPIReset(SSIBASE);

	/* 4 MHz clock, MODE 0, 3 PIN with CS under S/W control */
	MAP_SPIConfigSetExpClk(SSIBASE,MAP_PRCMPeripheralClockGet(PRCM_GSPI),
				4000000, SPI_MODE_MASTER, SPI_MODE0,
				(SPI_HW_CTRL_CS |
				SPI_3PIN_MODE |
				SPI_TURBO_OFF |
				SPI_CS_ACTIVELOW |
				SPI_WL_8));

	MAP_SPIEnable(SSIBASE);
}

void SPIClass::end()
{
	MAP_SPIDisable(SSIBASE);
}

void SPIClass::setBitOrder(uint8_t ssPin, uint8_t bitOrder)
{
	SSIBitOrder = bitOrder;
}

void SPIClass::setBitOrder(uint8_t bitOrder)
{
	SSIBitOrder = bitOrder;
}

void SPIClass::setDataMode(uint8_t mode)
{
	HWREG(SSIBASE + MCSPI_O_CH0CONF) &= ~SPI_MODE_MASK;
	HWREG(SSIBASE + MCSPI_O_CH0CONF) |= mode;
}

void SPIClass::setClockDivider(uint8_t divider)
{
	/* The least significant four bits of the divider is used fo configure
	 * CLKD in MCSPI_CHCONF next eight least significant bits are used to
	 * configure the EXTCLK in MCSPI_CHCTRL.
	 * Note that the peripheral clock is set to 40 MHz vs System Clock @ 80 MHz */

	uint16_t _divider = ((MAP_PRCMPeripheralClockGet(PRCM_GSPI) / (MAX_BITRATE / divider))  - 1);

	HWREG(SSIBASE + MCSPI_O_CH0CONF) &= ~SPI_CLKD_MASK;
	HWREG(SSIBASE + MCSPI_O_CH0CONF) |= ((_divider & 0x0000000F) << 2);

	HWREG(SSIBASE + MCSPI_O_CH0CTRL) &= ~SPI_EXTCLK_MASK;
	HWREG(SSIBASE + MCSPI_O_CH0CTRL) |= ((_divider & 0x00000FF0) << 4);
	SPIEnable(SSIBASE);
}

uint8_t SPIClass::transfer(uint8_t data)
{
	uint32_t rxtxData;
	uint8_t rxData;

	if(SSIBitOrder == LSBFIRST) {
		rxtxData = data;
		asm("rbit %0, %1" : "=r" (rxtxData) : "r" (rxtxData));	// reverse order of 32 bits
		asm("rev %0, %1" : "=r" (rxtxData) : "r" (rxtxData));	// reverse order of bytes to get original bits into lowest byte
		data = (uint8_t) rxtxData;
	}

	MAP_SPITransfer(SSIBASE, &data, &rxData, 1, 0);

	if(SSIBitOrder == LSBFIRST) {
		rxtxData = rxData;
		asm("rbit %0, %1" : "=r" (rxtxData) : "r" (rxtxData));	// reverse order of 32 bits
		asm("rev %0, %1" : "=r" (rxtxData) : "r" (rxtxData));	// reverse order of bytes to get original bits into lowest byte
		rxData = (uint8_t) rxtxData;
	}

	return (uint8_t) rxData;
}

/* Only one module available in the CC3200
 * But we leave it in here in case there will
 * be variants with more modules in the future */
void SPIClass::setModule(uint8_t module) {
	SSIModule = module;
	begin();
}

SPIClass SPI;
<commit_msg>Enable SPI peripheral clock before poking registers<commit_after>/*
 * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
 * SPI Master library for arduino.
 *
 * This file is free software; you can redistribute it and/or modify
 * it under the terms of either the GNU General Public License version 2
 * or the GNU Lesser General Public License version 2.1, both as
 * published by the Free Software Foundation.
 */

#include "SPI.h"
#include "wiring_private.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_mcspi.h"
#include "inc/hw_gpio.h"
#include "driverlib/rom_map.h"
#include "driverlib/spi.h"
#include "driverlib/gpio.h"
#include "driverlib/prcm.h"
#include "driverlib/pin.h"

#define SSIBASE g_ulSSIBase[SSIModule]
#define NOT_ACTIVE 0xA

static const unsigned long g_ulSSIBase[] = {
	GSPI_BASE
};

//*****************************************************************************
//
// The list of SSI peripherals.
//
//*****************************************************************************
static const unsigned long g_ulSSIPeriph[] = {
	PRCM_GSPI
};

//*****************************************************************************
//
// The list of SSI gpio configurations.
//
//*****************************************************************************
static const unsigned long g_ulSSIPins[][4] = {
	{PIN_05 /* SCLK */, PIN_08 /* SS */, PIN_06 /* MISO */, PIN_07 /* MOSI */}
};

static const unsigned long g_ulSSIPinModes[][4] = {
	{PIN_MODE_7 /* SCLK */, PIN_MODE_7 /* SS */, PIN_MODE_7 /* MISO */, PIN_MODE_7 /* MOSI */}
};

SPIClass::SPIClass(void) {
	SSIModule = BOOST_PACK_SPI;
	SSIBitOrder = MSBFIRST;
}

SPIClass::SPIClass(uint8_t module) {
	SSIModule = module;
	SSIBitOrder = MSBFIRST;
}

void SPIClass::begin() {
	unsigned long initialData = 0;

	if(SSIModule == NOT_ACTIVE) {
		SSIModule = BOOST_PACK_SPI;
	}

	MAP_PRCMPeripheralClkEnable(PRCM_GSPI, PRCM_RUN_MODE_CLK);

	/* Configure pins as SPI */
	MAP_PinTypeSPI(g_ulSSIPins[SSIModule][0], g_ulSSIPinModes[SSIModule][0]);
	/* Leave the CS pin under software control */
//	MAP_PinTypeSPI(g_ulSSIPins[SSIModule][1], g_ulSSIPinModes[SSIModule][1]);
	MAP_PinTypeSPI(g_ulSSIPins[SSIModule][2], g_ulSSIPinModes[SSIModule][2]);
	MAP_PinTypeSPI(g_ulSSIPins[SSIModule][3], g_ulSSIPinModes[SSIModule][3]);

	MAP_PRCMPeripheralReset(PRCM_GSPI);
	MAP_SPIReset(SSIBASE);

	/* 4 MHz clock, MODE 0, 3 PIN with CS under S/W control */
	MAP_SPIConfigSetExpClk(SSIBASE,MAP_PRCMPeripheralClockGet(PRCM_GSPI),
				4000000, SPI_MODE_MASTER, SPI_MODE0,
				(SPI_HW_CTRL_CS |
				SPI_3PIN_MODE |
				SPI_TURBO_OFF |
				SPI_CS_ACTIVELOW |
				SPI_WL_8));

	MAP_SPIEnable(SSIBASE);
}

void SPIClass::end()
{
	MAP_SPIDisable(SSIBASE);
}

void SPIClass::setBitOrder(uint8_t ssPin, uint8_t bitOrder)
{
	SSIBitOrder = bitOrder;
}

void SPIClass::setBitOrder(uint8_t bitOrder)
{
	SSIBitOrder = bitOrder;
}

void SPIClass::setDataMode(uint8_t mode)
{
	MAP_PRCMPeripheralClkEnable(PRCM_GSPI, PRCM_RUN_MODE_CLK);
	HWREG(SSIBASE + MCSPI_O_CH0CONF) &= ~SPI_MODE_MASK;
	HWREG(SSIBASE + MCSPI_O_CH0CONF) |= mode;
}

void SPIClass::setClockDivider(uint8_t divider)
{
	/* The least significant four bits of the divider is used fo configure
	 * CLKD in MCSPI_CHCONF next eight least significant bits are used to
	 * configure the EXTCLK in MCSPI_CHCTRL.
	 * Note that the peripheral clock is set to 40 MHz vs System Clock @ 80 MHz */
	MAP_PRCMPeripheralClkEnable(PRCM_GSPI, PRCM_RUN_MODE_CLK);

	uint16_t _divider = ((MAP_PRCMPeripheralClockGet(PRCM_GSPI) / (MAX_BITRATE / divider))  - 1);

	HWREG(SSIBASE + MCSPI_O_CH0CONF) &= ~SPI_CLKD_MASK;
	HWREG(SSIBASE + MCSPI_O_CH0CONF) |= ((_divider & 0x0000000F) << 2);

	HWREG(SSIBASE + MCSPI_O_CH0CTRL) &= ~SPI_EXTCLK_MASK;
	HWREG(SSIBASE + MCSPI_O_CH0CTRL) |= ((_divider & 0x00000FF0) << 4);
	SPIEnable(SSIBASE);
}

uint8_t SPIClass::transfer(uint8_t data)
{
	uint32_t rxtxData;
	uint8_t rxData;

	if(SSIBitOrder == LSBFIRST) {
		rxtxData = data;
		asm("rbit %0, %1" : "=r" (rxtxData) : "r" (rxtxData));	// reverse order of 32 bits
		asm("rev %0, %1" : "=r" (rxtxData) : "r" (rxtxData));	// reverse order of bytes to get original bits into lowest byte
		data = (uint8_t) rxtxData;
	}

	MAP_SPITransfer(SSIBASE, &data, &rxData, 1, 0);

	if(SSIBitOrder == LSBFIRST) {
		rxtxData = rxData;
		asm("rbit %0, %1" : "=r" (rxtxData) : "r" (rxtxData));	// reverse order of 32 bits
		asm("rev %0, %1" : "=r" (rxtxData) : "r" (rxtxData));	// reverse order of bytes to get original bits into lowest byte
		rxData = (uint8_t) rxtxData;
	}

	return (uint8_t) rxData;
}

/* Only one module available in the CC3200
 * But we leave it in here in case there will
 * be variants with more modules in the future */
void SPIClass::setModule(uint8_t module) {
	SSIModule = module;
	begin();
}

SPIClass SPI(0);
<|endoftext|>