<commit_before>#include <atlconv.h>
#include <cstdlib>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <stdio.h>
#include <tchar.h>
#include <windows.h>

#include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp>
#include <boost/program_options.hpp>

#include "VoiceroidFactory.h"
#include "Yukari.h"
#include "YukariEx.h"

#define DELIMITERS _T(".B")

using namespace boost::program_options;

// IvV\\
struct Options {
	// ǂݏグ VOICEROID(Yukari, YukariEx)
	std::string target_voiceroid_str;
	// o̓t@CpX
	std::wstring output_file;
	// ̓t@CpX
	std::wstring input_file;
	// ̓t@CR[h UTF8 Ƃď
	bool is_utf8;
	// [h(ĐEۑ܂őҋ@܂)
	bool is_sync_mode;
	// ǂݏグ(Ƃēnꂽꍇ)
	std::wstring echo_text;
	// ǂݏグ𕪊ڈ̃TCY
	size_t split_size;
} typedef Options;

// t@Ce擾
std::wstring getContents(std::wstring filepath, bool is_utf8);

// 񂪃f~^ǂ肷
bool is_delimiter(std::wstring str);

// wstring  string ɕϊ
std::string wstring2string(const std::wstring &src);

// string  wstring ɕϊ
std::wstring string2wstring(const std::string &src);

// UTF8  SJIS ɂĕԂ
std::string utf8toSjis(std::string srcUTF8);

// R}hC
Options parseArgs(int argc, _TCHAR* argv[]);

int _tmain(int argc, _TCHAR* argv[])
{
	setlocale(LC_CTYPE, "");
	std::ios::sync_with_stdio(true);

	// R}hC
	Options options = parseArgs(argc, argv);

	// w肳ꂽɉ
	// R}hCt@Cǂݏグ擾B
	std::wstring wcontents;
	if (options.input_file.compare(_T("")) == 0) {
		// t@Cw肪Ȃ΃R}hC擾
		wcontents = options.echo_text;
	} else {
		// t@Cw肪΃t@Ce擾
		wcontents = getContents(options.input_file, options.is_utf8);
	}

	// ɉĒNgp邩肷
	VoiceroidType voiceroidType;
	if (options.target_voiceroid_str.compare("Yukari") == 0) {
		voiceroidType = VoiceroidType::YUKARI;
	}
	else if (options.target_voiceroid_str.compare("YukariEx") == 0) {
		voiceroidType = VoiceroidType::YUKARI_EX;
	}

	// VOICEROID 쐬
	Voiceroid* voiceroid = VoiceroidFactory::create(voiceroidType);

	// w蕶𒴂Ȃ悤ɕȂǂݏグ邽߂̏B

	std::list<std::wstring> list_string;
	boost::split(list_string, wcontents, boost::is_any_of(DELIMITERS));

	size_t size = 0;
	std::wstringstream ss;

	// ǂݏグ邩t@Cɕۑ邩
	if (options.output_file.length() == 0) {

		BOOST_FOREACH(std::wstring s, list_string) {

			// w蕶𒴂ꍇA
			// ܂łߍł̂ǂݏグB
			// A񂩂璴Ăꍇ͂߂B
			if (size != 0 && size + s.length() > options.split_size) {

				// ǂݏグ
				voiceroid->echo(wstring2string(ss.str()), options.is_sync_mode);

				// ss Zbg
				ss.str(_T(""));
				ss.clear();
				size = 0;
			}

			// TCY𑝂₵ĕ񌋍
			size += s.length();
			ss << s << _T("B");
		}

		// Ō̓ǂݏグ
		voiceroid->echo(wstring2string(ss.str()), options.is_sync_mode);

	} else {

		size_t fileno = 0;

		BOOST_FOREACH(std::wstring s, list_string) {

			// w蕶𒴂ꍇA
			// ܂łߍł̂ǂݏグB
			// A񂩂璴Ăꍇ͂߂B
			if (size != 0 && size + s.length() > options.split_size) {

				// t@Cɕۑ

				// t@Cgݗ
				_TCHAR drive[_MAX_DRIVE];
				_TCHAR dir[_MAX_DIR];
				_TCHAR filename[_MAX_FNAME];
				_TCHAR ext[_MAX_EXT];
				_tsplitpath(options.output_file.c_str(), drive, dir, filename, ext);

				std::wstringstream dest;
				dest << drive << dir << filename << _T("_") << std::setfill(L'0') << std::setw(3) << std::right << fileno << ext;
				voiceroid->save(wstring2string(ss.str()), wstring2string(dest.str()), options.is_sync_mode);

				// ss Zbg
				ss.str(_T(""));
				ss.clear();
				size = 0;

				fileno++;
			}

			// TCY𑝂₵ĕ񌋍
			size += s.length();
			ss << s << _T("B");
		}

		// Ō̕ۑ

		// t@Cgݗ
		_TCHAR drive[_MAX_DRIVE];
		_TCHAR dir[_MAX_DIR];
		_TCHAR filename[_MAX_FNAME];
		_TCHAR ext[_MAX_EXT];
		_tsplitpath(options.output_file.c_str(), drive, dir, filename, ext);

		std::wstringstream dest;
		dest << drive << dir << filename << _T("_") << std::setfill(L'0') << std::setw(3) << std::right << fileno << ext;
		voiceroid->save(wstring2string(ss.str()), wstring2string(dest.str()), options.is_sync_mode);

	}

	delete voiceroid;

	exit(0);
}

Options parseArgs(int argc, _TCHAR* argv[]) {
	options_description opt("IvV");
	// R}hC`
	opt.add_options()
		("help,h", "wv\")
		("voiceroid", value<std::string>()->default_value("YukariEx"), "ǂݏグ VOICEROID(Yukari, YukariEx)")
		("output-file,o", wvalue<std::wstring>(), "o̓t@CpX")
		("input-file,i", wvalue<std::wstring>(), "̓t@CpX")
		("utf8,u", "̓t@CR[h UTF8 Ƃď")
		("sync,s", "[h(ĐEۑ܂őҋ@܂)")
		("split-size", value<size_t>()->default_value(20000), "ǂݏグ𕪊ڈ̃TCY");

	// R}hC
	variables_map argmap;
	auto pr = parse_command_line(argc, argv, opt);
	store(pr, argmap);
	notify(argmap);

	// ͌ʎ擾
	Options options;
	options.target_voiceroid_str = argmap["voiceroid"].as<std::string>();

	// o̓t@CpX擾
	// (gpĂo[W boost_program_options ł́A
	//  std::wstring ɑ΂ default_value w肷ƃRpCG[ɂȂ邽߁A
	//  IvV̗L`FbNƑOŎ)
	std::wstring woutput_file;
	if (argmap.count("output-file")) {
		options.output_file = argmap["output-file"].as<std::wstring>();
	} else {
		options.output_file = _T("");
	}

	// ̓t@CpX擾
	// (gpĂo[W boost_program_options ł́A
	//  std::wstring ɑ΂ default_value w肷ƃRpCG[ɂȂ邽߁A
	//  IvV̗L`FbNƑOŎ)
	std::wstring winput_file;
	if (argmap.count("input-file")) {
		options.input_file = argmap["input-file"].as<std::wstring>();
	} else {
		options.input_file = _T("");
	}

	options.is_utf8 = argmap.count("utf8");
	options.is_sync_mode = !argmap["sync"].empty();
	options.echo_text = _T("");
	options.split_size = argmap["split-size"].as<size_t>();

	// IvVȊÕR}hC擾
	for (auto const& str : collect_unrecognized(pr.options, include_positional)) {
		options.echo_text.append(_T(" "));
		options.echo_text.append(str);
	}

	// wv\w肪邩A
	// echo_text, input_file Ƃ̏ꍇAwv\ďI
	if (argmap.count("help") ||
		(options.echo_text.compare(_T("")) == 0
			&& options.input_file.compare(_T("")) == 0)) {
		_TCHAR drive[_MAX_DRIVE];
		_TCHAR dir[_MAX_DIR];
		_TCHAR filename[_MAX_FNAME];
		_TCHAR ext[_MAX_EXT];
		_tsplitpath(argv[0], drive, dir, filename, ext);

		wprintf(_T("Usage: %s%s [options] [text]\n"), filename, ext);

		std::stringstream helpStream;
		helpStream << opt << std::endl;
		printf(helpStream.str().c_str());

		exit(1);
	}

	return options;
}

std::string wstring2string(const std::wstring &src) {
	char *mbs = new char[src.length() * MB_CUR_MAX + 1];
	wcstombs(mbs, src.c_str(), src.length() * MB_CUR_MAX + 1);

	std::string dest = mbs;
	delete[] mbs;

	return dest;
}

std::wstring string2wstring(const std::string &src) {
	wchar_t *wcs = new wchar_t[src.length() + 1];
	mbstowcs(wcs, src.c_str(), src.length() + 1);
	std::wstring dest = wcs;
	delete[] wcs;

	return dest;
}

std::string utf8toSjis(std::string srcUTF8) {
	//Unicode֕ϊ̕񒷂𓾂
	int lenghtUnicode = MultiByteToWideChar(CP_UTF8, 0, srcUTF8.c_str(), srcUTF8.size() + 1, NULL, 0);

	//KvȕUnicodẽobt@m
	wchar_t* bufUnicode = new wchar_t[lenghtUnicode];

	//UTF8Unicode֕ϊ
	MultiByteToWideChar(CP_UTF8, 0, srcUTF8.c_str(), srcUTF8.size() + 1, bufUnicode, lenghtUnicode);

	//ShiftJIS֕ϊ̕񒷂𓾂
	int lengthSJis = WideCharToMultiByte(CP_THREAD_ACP, 0, bufUnicode, -1, NULL, 0, NULL, NULL);

	//KvȕShiftJIS̃obt@m
	char* bufShiftJis = new char[lengthSJis];

	//UnicodeShiftJIS֕ϊ
	WideCharToMultiByte(CP_THREAD_ACP, 0, bufUnicode, lenghtUnicode + 1, bufShiftJis, lengthSJis, NULL, NULL);

	std::string strSJis(bufShiftJis);

	delete bufUnicode;
	delete bufShiftJis;

	return strSJis;
}

// t@Ce擾
std::wstring getContents(std::wstring filepath, bool is_utf8) {
	std::ifstream ifs (filepath);

	// t@CI[v۔
	if (ifs.fail())
	{
		std::cerr << "t@CI[vɎs܂B" << std::endl;
		return NULL;
	}

	// TODO: ꉽĂł[ˁH
	std::istreambuf_iterator<char> it(ifs);
	std::istreambuf_iterator<char> last;
	std::string str (it, last);

	// t@CR[hɉĕϊ
	if (is_utf8) {
		// utf8
		str = utf8toSjis(str);
	}

	return string2wstring(str);
}

bool is_delimiter(std::wstring str) {
	for (wchar_t* it = DELIMITERS; *it; ++it) {
		size_t index = str.find(*it);

		if (index != std::string::npos) {
			return TRUE;
		}
	}

	return FALSE;
}

<commit_msg>繰り返し出てくるマジックナンバーを定数化した。<commit_after>#include <atlconv.h>
#include <cstdlib>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <stdio.h>
#include <tchar.h>
#include <windows.h>

#include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp>
#include <boost/program_options.hpp>

#include "VoiceroidFactory.h"
#include "Yukari.h"
#include "YukariEx.h"

#define INSERT_DELIMITER _T("B")
#define DELIMITERS _T(".B")

#define EMPTY_STR _T("")

using namespace boost::program_options;

// IvV\\
struct Options {
	// ǂݏグ VOICEROID(Yukari, YukariEx)
	std::string target_voiceroid_str;
	// o̓t@CpX
	std::wstring output_file;
	// ̓t@CpX
	std::wstring input_file;
	// ̓t@CR[h UTF8 Ƃď
	bool is_utf8;
	// [h(ĐEۑ܂őҋ@܂)
	bool is_sync_mode;
	// ǂݏグ(Ƃēnꂽꍇ)
	std::wstring echo_text;
	// ǂݏグ𕪊ڈ̃TCY
	size_t split_size;
} typedef Options;

// t@Ce擾
std::wstring getContents(std::wstring filepath, bool is_utf8);

// 񂪃f~^ǂ肷
bool is_delimiter(std::wstring str);

// wstring  string ɕϊ
std::string wstring2string(const std::wstring &src);

// string  wstring ɕϊ
std::wstring string2wstring(const std::string &src);

// UTF8  SJIS ɂĕԂ
std::string utf8toSjis(std::string srcUTF8);

// R}hC
Options parseArgs(int argc, _TCHAR* argv[]);

int _tmain(int argc, _TCHAR* argv[])
{
	setlocale(LC_CTYPE, "");
	std::ios::sync_with_stdio(true);

	// R}hC
	Options options = parseArgs(argc, argv);

	// w肳ꂽɉ
	// R}hCt@Cǂݏグ擾B
	std::wstring wcontents;
	if (options.input_file.compare(EMPTY_STR) == 0) {
		// t@Cw肪Ȃ΃R}hC擾
		wcontents = options.echo_text;
	} else {
		// t@Cw肪΃t@Ce擾
		wcontents = getContents(options.input_file, options.is_utf8);
	}

	// ɉĒNgp邩肷
	VoiceroidType voiceroidType;
	if (options.target_voiceroid_str.compare("Yukari") == 0) {
		voiceroidType = VoiceroidType::YUKARI;
	}
	else if (options.target_voiceroid_str.compare("YukariEx") == 0) {
		voiceroidType = VoiceroidType::YUKARI_EX;
	}

	// VOICEROID 쐬
	Voiceroid* voiceroid = VoiceroidFactory::create(voiceroidType);

	// w蕶𒴂Ȃ悤ɕȂǂݏグ邽߂̏B

	std::list<std::wstring> list_string;
	boost::split(list_string, wcontents, boost::is_any_of(DELIMITERS));

	size_t size = 0;
	std::wstringstream ss;

	// ǂݏグ邩t@Cɕۑ邩
	if (options.output_file.length() == 0) {

		BOOST_FOREACH(std::wstring s, list_string) {

			// w蕶𒴂ꍇA
			// ܂łߍł̂ǂݏグB
			// A񂩂璴Ăꍇ͂߂B
			if (size != 0 && size + s.length() > options.split_size) {

				// ǂݏグ
				voiceroid->echo(wstring2string(ss.str()), options.is_sync_mode);

				// ss Zbg
				ss.str(EMPTY_STR);
				ss.clear();
				size = 0;
			}

			// TCY𑝂₵ĕ񌋍
			size += s.length();
			ss << s << INSERT_DELIMITER;
		}

		// Ō̓ǂݏグ
		voiceroid->echo(wstring2string(ss.str()), options.is_sync_mode);

	} else {

		size_t fileno = 0;

		BOOST_FOREACH(std::wstring s, list_string) {

			// w蕶𒴂ꍇA
			// ܂łߍł̂ǂݏグB
			// A񂩂璴Ăꍇ͂߂B
			if (size != 0 && size + s.length() > options.split_size) {

				// t@Cɕۑ

				// t@Cgݗ
				_TCHAR drive[_MAX_DRIVE];
				_TCHAR dir[_MAX_DIR];
				_TCHAR filename[_MAX_FNAME];
				_TCHAR ext[_MAX_EXT];
				_tsplitpath(options.output_file.c_str(), drive, dir, filename, ext);

				std::wstringstream dest;
				dest << drive << dir << filename << _T("_") << std::setfill(L'0') << std::setw(3) << std::right << fileno << ext;
				voiceroid->save(wstring2string(ss.str()), wstring2string(dest.str()), options.is_sync_mode);

				// ss Zbg
				ss.str(EMPTY_STR);
				ss.clear();
				size = 0;

				fileno++;
			}

			// TCY𑝂₵ĕ񌋍
			size += s.length();
			ss << s << INSERT_DELIMITER;
		}

		// Ō̕ۑ

		// t@Cgݗ
		_TCHAR drive[_MAX_DRIVE];
		_TCHAR dir[_MAX_DIR];
		_TCHAR filename[_MAX_FNAME];
		_TCHAR ext[_MAX_EXT];
		_tsplitpath(options.output_file.c_str(), drive, dir, filename, ext);

		std::wstringstream dest;
		dest << drive << dir << filename << _T("_") << std::setfill(L'0') << std::setw(3) << std::right << fileno << ext;
		voiceroid->save(wstring2string(ss.str()), wstring2string(dest.str()), options.is_sync_mode);

	}

	delete voiceroid;

	exit(0);
}

Options parseArgs(int argc, _TCHAR* argv[]) {
	options_description opt("IvV");
	// R}hC`
	opt.add_options()
		("help,h", "wv\")
		("voiceroid", value<std::string>()->default_value("YukariEx"), "ǂݏグ VOICEROID(Yukari, YukariEx)")
		("output-file,o", wvalue<std::wstring>(), "o̓t@CpX")
		("input-file,i", wvalue<std::wstring>(), "̓t@CpX")
		("utf8,u", "̓t@CR[h UTF8 Ƃď")
		("sync,s", "[h(ĐEۑ܂őҋ@܂)")
		("split-size", value<size_t>()->default_value(20000), "ǂݏグ𕪊ڈ̃TCY");

	// R}hC
	variables_map argmap;
	auto pr = parse_command_line(argc, argv, opt);
	store(pr, argmap);
	notify(argmap);

	// ͌ʎ擾
	Options options;
	options.target_voiceroid_str = argmap["voiceroid"].as<std::string>();

	// o̓t@CpX擾
	// (gpĂo[W boost_program_options ł́A
	//  std::wstring ɑ΂ default_value w肷ƃRpCG[ɂȂ邽߁A
	//  IvV̗L`FbNƑOŎ)
	std::wstring woutput_file;
	if (argmap.count("output-file")) {
		options.output_file = argmap["output-file"].as<std::wstring>();
	} else {
		options.output_file = EMPTY_STR;
	}

	// ̓t@CpX擾
	// (gpĂo[W boost_program_options ł́A
	//  std::wstring ɑ΂ default_value w肷ƃRpCG[ɂȂ邽߁A
	//  IvV̗L`FbNƑOŎ)
	std::wstring winput_file;
	if (argmap.count("input-file")) {
		options.input_file = argmap["input-file"].as<std::wstring>();
	} else {
		options.input_file = EMPTY_STR;
	}

	options.is_utf8 = argmap.count("utf8");
	options.is_sync_mode = !argmap["sync"].empty();
	options.echo_text = EMPTY_STR;
	options.split_size = argmap["split-size"].as<size_t>();

	// IvVȊÕR}hC擾
	for (auto const& str : collect_unrecognized(pr.options, include_positional)) {
		options.echo_text.append(_T(" "));
		options.echo_text.append(str);
	}

	// wv\w肪邩A
	// echo_text, input_file Ƃ̏ꍇAwv\ďI
	if (argmap.count("help") ||
		(options.echo_text.compare(EMPTY_STR) == 0
			&& options.input_file.compare(EMPTY_STR) == 0)) {
		_TCHAR drive[_MAX_DRIVE];
		_TCHAR dir[_MAX_DIR];
		_TCHAR filename[_MAX_FNAME];
		_TCHAR ext[_MAX_EXT];
		_tsplitpath(argv[0], drive, dir, filename, ext);

		wprintf(_T("Usage: %s%s [options] [text]\n"), filename, ext);

		std::stringstream helpStream;
		helpStream << opt << std::endl;
		printf(helpStream.str().c_str());

		exit(1);
	}

	return options;
}

std::string wstring2string(const std::wstring &src) {
	char *mbs = new char[src.length() * MB_CUR_MAX + 1];
	wcstombs(mbs, src.c_str(), src.length() * MB_CUR_MAX + 1);

	std::string dest = mbs;
	delete[] mbs;

	return dest;
}

std::wstring string2wstring(const std::string &src) {
	wchar_t *wcs = new wchar_t[src.length() + 1];
	mbstowcs(wcs, src.c_str(), src.length() + 1);
	std::wstring dest = wcs;
	delete[] wcs;

	return dest;
}

std::string utf8toSjis(std::string srcUTF8) {
	//Unicode֕ϊ̕񒷂𓾂
	int lenghtUnicode = MultiByteToWideChar(CP_UTF8, 0, srcUTF8.c_str(), srcUTF8.size() + 1, NULL, 0);

	//KvȕUnicodẽobt@m
	wchar_t* bufUnicode = new wchar_t[lenghtUnicode];

	//UTF8Unicode֕ϊ
	MultiByteToWideChar(CP_UTF8, 0, srcUTF8.c_str(), srcUTF8.size() + 1, bufUnicode, lenghtUnicode);

	//ShiftJIS֕ϊ̕񒷂𓾂
	int lengthSJis = WideCharToMultiByte(CP_THREAD_ACP, 0, bufUnicode, -1, NULL, 0, NULL, NULL);

	//KvȕShiftJIS̃obt@m
	char* bufShiftJis = new char[lengthSJis];

	//UnicodeShiftJIS֕ϊ
	WideCharToMultiByte(CP_THREAD_ACP, 0, bufUnicode, lenghtUnicode + 1, bufShiftJis, lengthSJis, NULL, NULL);

	std::string strSJis(bufShiftJis);

	delete bufUnicode;
	delete bufShiftJis;

	return strSJis;
}

// t@Ce擾
std::wstring getContents(std::wstring filepath, bool is_utf8) {
	std::ifstream ifs (filepath);

	// t@CI[v۔
	if (ifs.fail())
	{
		std::cerr << "t@CI[vɎs܂B" << std::endl;
		return NULL;
	}

	// TODO: ꉽĂł[ˁH
	std::istreambuf_iterator<char> it(ifs);
	std::istreambuf_iterator<char> last;
	std::string str (it, last);

	// t@CR[hɉĕϊ
	if (is_utf8) {
		// utf8
		str = utf8toSjis(str);
	}

	return string2wstring(str);
}

bool is_delimiter(std::wstring str) {
	for (wchar_t* it = DELIMITERS; *it; ++it) {
		size_t index = str.find(*it);

		if (index != std::string::npos) {
			return TRUE;
		}
	}

	return FALSE;
}

<|endoftext|>


<commit_before>#include"core.hpp"

#include<stdexcept>
#include<sstream>
#include<fcntl.h> // for open FLAGS
#include<unistd.h> // for tty checks
#include<cstring> // for memset
#include<unordered_map> // for cash

ics::Core::Core(const std::string& path, speed_t baudrate)
: fd {open(path.c_str(), O_RDWR | O_NOCTTY)},
  oldTio {}
{
  if (fd < 0)
    throw std::runtime_error {"Cannot open deveice"};
  try {
    if (!isatty(fd))
      throw std::invalid_argument {"Not tty device"};
    if (tcgetattr(fd, &oldTio) < 0)
      throw std::runtime_error {"Cannot setup tty"};
    auto newTio = getTermios();
    if (cfsetispeed(&newTio, baudrate) < 0)
      throw std::runtime_error {"Cannot set baudrate"};
    if (cfsetospeed(&newTio, baudrate) < 0)
      throw std::runtime_error {"Cannot set baudrate"};
    if (tcsetattr(fd, TCSANOW, &newTio) < 0)
      throw std::runtime_error {"Cannot setup tty"};
  } catch (...) {
    close(fd);
    throw;
  }
}

ics::Core::~Core() noexcept {
  if (fd < 0) return;
  tcsetattr(fd, TCSANOW, &oldTio);
  close(fd);
}

ics::Core::Core(Core&& rhs) noexcept
: fd {rhs.fd},
  oldTio {rhs.oldTio}
{
  rhs.fd = -1;
}

ics::Core& ics::Core::operator=(Core&& rhs) noexcept {
  fd = rhs.fd;
  oldTio = rhs.oldTio;
  rhs.fd = -1;
  return *this;
}

std::shared_ptr<ics::Core> ics::Core::getCore(const std::string& path, speed_t baudrate) {
  static std::unordered_map<std::string, std::weak_ptr<Core>> cache;
  auto objPtr = cache[path].lock();
  if (!objPtr) {
    objPtr = std::make_shared<Core>(path, baudrate);
    cache[path] = objPtr;
  }
  return objPtr;
}

void ics::Core::communicate(const std::vector<uint8_t>& tx, std::vector<uint8_t>& rx) {
  write(fd, tx.data(), tx.size()); // send
  for (auto& receive : rx) read(fd, &receive, 1); // receive
// check section
  auto receive = rx.begin();
  for (const auto& send : tx) {
    if (send != *receive) {
      std::stringstream ss;
      ss << "Receive falied:" << receive - rx.begin() << ':' << static_cast<int>(send) << "<->" << static_cast<int>(*receive);
      throw std::runtime_error {ss.str()};
    }
    ++receive;
  }
  if ((tx[0] & 0x7F) != *receive) throw std::runtime_error {"Receive failed: fail make data"};
}

termios ics::Core::getTermios() noexcept {
  termios newTio;
  std::memset(&newTio, 0, sizeof(newTio));
  newTio.c_iflag = 0;
  newTio.c_oflag = 0;
  newTio.c_cflag = CS8 | CREAD | CLOCAL | PARENB;
  newTio.c_lflag = 0;
  newTio.c_cc[VMIN] = 1;
  newTio.c_cc[VTIME] = 1;
  return newTio;
}
<commit_msg>Update error message for readability<commit_after>#include"core.hpp"

#include<stdexcept>
#include<sstream>
#include<fcntl.h> // for open FLAGS
#include<unistd.h> // for tty checks
#include<cstring> // for memset
#include<unordered_map> // for cash

ics::Core::Core(const std::string& path, speed_t baudrate)
: fd {open(path.c_str(), O_RDWR | O_NOCTTY)},
  oldTio {}
{
  if (fd < 0)
    throw std::runtime_error {"Cannot open deveice"};
  try {
    if (!isatty(fd))
      throw std::invalid_argument {"Not tty device"};
    if (tcgetattr(fd, &oldTio) < 0)
      throw std::runtime_error {"Cannot setup tty"};
    auto newTio = getTermios();
    if (cfsetispeed(&newTio, baudrate) < 0)
      throw std::runtime_error {"Cannot set baudrate"};
    if (cfsetospeed(&newTio, baudrate) < 0)
      throw std::runtime_error {"Cannot set baudrate"};
    if (tcsetattr(fd, TCSANOW, &newTio) < 0)
      throw std::runtime_error {"Cannot setup tty"};
  } catch (...) {
    close(fd);
    throw;
  }
}

ics::Core::~Core() noexcept {
  if (fd < 0) return;
  tcsetattr(fd, TCSANOW, &oldTio);
  close(fd);
}

ics::Core::Core(Core&& rhs) noexcept
: fd {rhs.fd},
  oldTio {rhs.oldTio}
{
  rhs.fd = -1;
}

ics::Core& ics::Core::operator=(Core&& rhs) noexcept {
  fd = rhs.fd;
  oldTio = rhs.oldTio;
  rhs.fd = -1;
  return *this;
}

std::shared_ptr<ics::Core> ics::Core::getCore(const std::string& path, speed_t baudrate) {
  static std::unordered_map<std::string, std::weak_ptr<Core>> cache;
  auto objPtr = cache[path].lock();
  if (!objPtr) {
    objPtr = std::make_shared<Core>(path, baudrate);
    cache[path] = objPtr;
  }
  return objPtr;
}

void ics::Core::communicate(const std::vector<uint8_t>& tx, std::vector<uint8_t>& rx) {
  write(fd, tx.data(), tx.size()); // send
  for (auto& receive : rx) read(fd, &receive, 1); // receive
// check section
  auto receive = rx.begin();
  for (const auto& send : tx) {
    if (send != *receive) {
      std::stringstream ss;
      ss << "Receive falied(loopback):" << receive - rx.begin() << ':' << static_cast<int>(send) << "<->" << static_cast<int>(*receive);
      throw std::runtime_error {ss.str()};
    }
    ++receive;
  }
  if ((tx[0] & 0x7F) != *receive) throw std::runtime_error {"Receive failed: invalid target data"};
}

termios ics::Core::getTermios() noexcept {
  termios newTio;
  std::memset(&newTio, 0, sizeof(newTio));
  newTio.c_iflag = 0;
  newTio.c_oflag = 0;
  newTio.c_cflag = CS8 | CREAD | CLOCAL | PARENB;
  newTio.c_lflag = 0;
  newTio.c_cc[VMIN] = 1;
  newTio.c_cc[VTIME] = 1;
  return newTio;
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "bbudf.h"
#include "curl.h"
#include "logger.h"
namespace curl {
	//TODO http://www.openssl.org/docs/crypto/threads.html#DESCRIPTION
	__thread CURL* ch=NULL;
	__thread long curl_response_code=0;
	int curl_global_init_called=0;

	size_t readfunction_blob( char *ptr, size_t size, size_t nmemb, void *userdata){
		unsigned short length,actual_length;
		length=size*nmemb;
		blobcallback* blob=(blobcallback*) userdata;
		int res;
		res=blob->blob_get_segment(blob->blob_handle,(ISC_UCHAR*)ptr,length,&actual_length);
		logger::syslog(0, "xmlreader::readfunction_blob() len=%d,res=%d,actual_length=%d",length,res,actual_length);
		return actual_length;
	}

	size_t writefunction_blob( char *ptr, size_t size, size_t nmemb, void *userdata){
		size_t length=size*nmemb;
		if(length>0){
			blobcallback* outblob=(blobcallback*) userdata;
			outblob->blob_put_segment(outblob->blob_handle, (ISC_UCHAR*) ptr, length);
		}
		return length;
	}
}

FBUDF_API void fn_curl_exec(const char* method,const char* url, const char* sslcert, const char* sslcertpassword,const char* cainfo, const char* headers, blobcallback* datablob, const char* cookies, blobcallback* outblob) {
	curl::curl_response_code=0;
	if (!outblob || !outblob->blob_handle){
		return;
	}
	CURLcode code;
	if(!curl::curl_global_init_called) {
		code=curl_global_init(CURL_GLOBAL_ALL);
		if(code != CURLE_OK){
			logger::blobprinf(outblob,"curl_global_init() failed: %s\n",curl_easy_strerror(code));
			return;
		}
		curl::curl_global_init_called=1;
	}
	CURL* ch;
	if(curl::ch==NULL){
		curl::ch=curl_easy_init();
		if(!curl::ch){
			logger::blobprinf(outblob,"curl_easy_init() failed\n");
			return;
		}
	}
	ch=curl::ch;
	curl_easy_setopt(ch,CURLOPT_NOSIGNAL,1);
	if (strcmp(method,"GET")==0){
		curl_easy_setopt(ch,CURLOPT_HTTPGET,1);
	}else if (strcmp(method,"POST")==0){
		curl_easy_setopt(ch,CURLOPT_POST,1);
	}else if (strcmp(method,"PUT")==0){
		curl_easy_setopt(ch,CURLOPT_PUT,1);
	}else if (strcmp(method,"HEAD")==0){
		curl_easy_setopt(ch,CURLOPT_NOBODY,1);
	}else{
		logger::blobprinf(outblob,"unknown method '%s'",method);
		return;
	}
	curl_easy_setopt(ch,CURLOPT_URL,url);
	curl_easy_setopt(ch,CURLOPT_SSLCERT,sslcert);
	curl_easy_setopt(ch,CURLOPT_SSLCERTPASSWD,sslcertpassword);
	curl_easy_setopt(ch,CURLOPT_CAINFO,cainfo);
	curl_easy_setopt(ch,CURLOPT_WRITEFUNCTION,curl::writefunction_blob);
	curl_easy_setopt(ch,CURLOPT_WRITEDATA,outblob);
	struct curl_slist *slist=NULL;
	if(headers){
#if defined(WIN32)
#else

		char *saveptr;
		char *headersdup=strdup(headers);
		char *token=strtok_r(headersdup, "\n", &saveptr);
		while(token){
			 slist = curl_slist_append(slist, token);
			 token=strtok_r(NULL, "\n", &saveptr);
		}
		free(headersdup);
#endif
	}
	curl_easy_setopt(ch, CURLOPT_HTTPHEADER, slist);
	curl_easy_setopt(ch, CURLOPT_COOKIE, cookies);
	if(datablob && datablob->blob_handle){
		//logger::syslog(0, "setup readfunction_blob(), data length=%d",datablob->blob_total_length);
		curl_easy_setopt(ch,CURLOPT_READFUNCTION,curl::readfunction_blob);
		curl_easy_setopt(ch,CURLOPT_READDATA,datablob);
		curl_easy_setopt(ch,CURLOPT_POSTFIELDSIZE,datablob->blob_total_length);
	}
	code=curl_easy_perform(ch);
	if(slist){
		 curl_slist_free_all(slist);
	}
	if(code != CURLE_OK){
		logger::blobprinf(outblob,"curl_easy_perform() failed: %s\n",curl_easy_strerror(code));
		return;
	}
	curl_easy_getinfo(ch, CURLINFO_RESPONSE_CODE, &curl::curl_response_code);
}
FBUDF_API long fn_curl_get_response_code() {
	return curl::curl_response_code;
}<commit_msg>specify size of PUT with CURLOPT_INFILESIZE<commit_after>#include "stdafx.h"
#include "bbudf.h"
#include "curl.h"
#include "logger.h"
namespace curl {
	//TODO http://www.openssl.org/docs/crypto/threads.html#DESCRIPTION
	__thread CURL* ch=NULL;
	__thread long curl_response_code=0;
	int curl_global_init_called=0;

	size_t readfunction_blob( char *ptr, size_t size, size_t nmemb, void *userdata){
		unsigned short length,actual_length;
		length=size*nmemb;
		blobcallback* blob=(blobcallback*) userdata;
		int res;
		res=blob->blob_get_segment(blob->blob_handle,(ISC_UCHAR*)ptr,length,&actual_length);
		logger::syslog(0, "xmlreader::readfunction_blob() len=%d,res=%d,actual_length=%d",length,res,actual_length);
		return actual_length;
	}

	size_t writefunction_blob( char *ptr, size_t size, size_t nmemb, void *userdata){
		size_t length=size*nmemb;
		if(length>0){
			blobcallback* outblob=(blobcallback*) userdata;
			outblob->blob_put_segment(outblob->blob_handle, (ISC_UCHAR*) ptr, length);
		}
		return length;
	}
}

FBUDF_API void fn_curl_exec(const char* method,const char* url, const char* sslcert, const char* sslcertpassword,const char* cainfo, const char* headers, blobcallback* datablob, const char* cookies, blobcallback* outblob) {
	curl::curl_response_code=0;
	if (!outblob || !outblob->blob_handle){
		return;
	}
	CURLcode code;
	if(!curl::curl_global_init_called) {
		code=curl_global_init(CURL_GLOBAL_ALL);
		if(code != CURLE_OK){
			logger::blobprinf(outblob,"curl_global_init() failed: %s\n",curl_easy_strerror(code));
			return;
		}
		curl::curl_global_init_called=1;
	}
	CURL* ch;
	if(curl::ch==NULL){
		curl::ch=curl_easy_init();
		if(!curl::ch){
			logger::blobprinf(outblob,"curl_easy_init() failed\n");
			return;
		}
	}
	ch=curl::ch;
	curl_easy_setopt(ch,CURLOPT_NOSIGNAL,1);
	if (strcmp(method,"GET")==0){
		curl_easy_setopt(ch,CURLOPT_HTTPGET,1);
	}else if (strcmp(method,"POST")==0){
		curl_easy_setopt(ch,CURLOPT_POST,1);
	}else if (strcmp(method,"PUT")==0){
		curl_easy_setopt(ch,CURLOPT_PUT,1);
	}else if (strcmp(method,"HEAD")==0){
		curl_easy_setopt(ch,CURLOPT_NOBODY,1);
	}else{
		logger::blobprinf(outblob,"unknown method '%s'",method);
		return;
	}
	curl_easy_setopt(ch,CURLOPT_URL,url);
	curl_easy_setopt(ch,CURLOPT_SSLCERT,sslcert);
	curl_easy_setopt(ch,CURLOPT_SSLCERTPASSWD,sslcertpassword);
	curl_easy_setopt(ch,CURLOPT_CAINFO,cainfo);
	curl_easy_setopt(ch,CURLOPT_WRITEFUNCTION,curl::writefunction_blob);
	curl_easy_setopt(ch,CURLOPT_WRITEDATA,outblob);
	struct curl_slist *slist=NULL;
	if(headers){
#if defined(WIN32)
#else

		char *saveptr;
		char *headersdup=strdup(headers);
		char *token=strtok_r(headersdup, "\n", &saveptr);
		while(token){
			 slist = curl_slist_append(slist, token);
			 token=strtok_r(NULL, "\n", &saveptr);
		}
		free(headersdup);
#endif
	}
	curl_easy_setopt(ch, CURLOPT_HTTPHEADER, slist);
	curl_easy_setopt(ch, CURLOPT_COOKIE, cookies);
	if(datablob && datablob->blob_handle){
		//logger::syslog(0, "setup readfunction_blob(), data length=%d",datablob->blob_total_length);
		curl_easy_setopt(ch,CURLOPT_READFUNCTION,curl::readfunction_blob);
		curl_easy_setopt(ch,CURLOPT_READDATA,datablob);
		if (strcmp(method,"PUT")==0) {
			curl_easy_setopt(ch,CURLOPT_INFILESIZE,datablob->blob_total_length);
		}else{
			curl_easy_setopt(ch,CURLOPT_POSTFIELDSIZE,datablob->blob_total_length);
		}
	}
	code=curl_easy_perform(ch);
	if(slist){
		 curl_slist_free_all(slist);
	}
	if(code != CURLE_OK){
		logger::blobprinf(outblob,"curl_easy_perform() failed: %s\n",curl_easy_strerror(code));
		return;
	}
	curl_easy_getinfo(ch, CURLINFO_RESPONSE_CODE, &curl::curl_response_code);
}
FBUDF_API long fn_curl_get_response_code() {
	return curl::curl_response_code;
}<|endoftext|>


<commit_before>#include "drawdevice.h"

#include <QFile>

DrawDevice::DrawDevice(Engine *eng, QWidget *parent) : QWidget(parent)
{
    engine = eng;
    setGeometry(parent->geometry());
    bgm = 0;
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(updateEngine()));
    timer->start(1000/25);
}

DrawDevice::~DrawDevice()
{
    for (std::map<string, QPixmap *>::iterator i = images.begin();
            i != images.end(); ++i)
    {
        delete i->second;
    }
    images.clear();
    if (bgm) delete bgm;
    delete timer;
}

void DrawDevice::initialize()
{
    setMouseTracking(true);
    setFocusPolicy(Qt::StrongFocus);
    std::vector<string> images = engine->getImgNames();
    for (std::vector<string>::iterator i = images.begin();
            i != images.end(); ++i)
        loadImage(*i);
}

bool DrawDevice::loadImage(string filename)
{
    if (QFile::exists(QString::fromStdString(filename)))
    {
        images[filename] = new QPixmap(filename.c_str());
        return true;
    }
    else
    {
        return false;
    }
}

void DrawDevice::quit(int status)
{
    qApp->exit(status);
}

void DrawDevice::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    drawRoom(painter);
}

void DrawDevice::mousePressEvent(QMouseEvent * event)
{
    std::pair<float, float> coord = engine->absToRelCoord(event->x(), event->y());
    engine->click(coord.first, coord.second);
    update();
    updateMusic();
}

void DrawDevice::mouseMoveEvent(QMouseEvent *event)
{
    if (engine->state() == Engine::GAME)
    {
        std::pair<float, float> coord = engine->absToRelCoord(event->x(), event->y());
        Item *item = engine->getRoomsManager()->currentRoom()->itemAt(coord.first,
                                                                    coord.second);
        Area *area = engine->getRoomsManager()->currentRoom()->areaAt(coord.first,
                                                                    coord.second);
        if (item != 0)
            setCursor(Qt::OpenHandCursor);
        else if (area != 0)
            setCursor(Qt::PointingHandCursor);
        else
            setCursor(Qt::ArrowCursor);
    }
    else
        setCursor(Qt::ArrowCursor);
}

void DrawDevice::resizeEvent(QResizeEvent *event)
{
    engine->getRoomsManager()->setRoomSize(event->size().width(), event->size().height());
}

void DrawDevice::updateEngine()
{
    if (engine->update())
        repaint();
}

QPixmap optimizedSetOpacity(QPixmap img, int opacity)
{
    QPixmap temp(img.size());
    temp.fill(Qt::transparent);
    QPainter p(&temp);
    p.setCompositionMode(QPainter::CompositionMode_Source);
    p.drawPixmap(0, 0, img);
    QLinearGradient alpha_gradient(0, 0, img.width(), 0);
    alpha_gradient.setColorAt(0, QColor(255, 255, 255, opacity));
    alpha_gradient.setColorAt(1, QColor(255, 255, 255, opacity));
    p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
    p.setBrush(alpha_gradient);
    p.drawRect(0, 0, temp.width(), temp.height());
    p.end();
    return temp;
}

void DrawDevice::drawImage(QPainter &painter, string name, GuiRect rect, int opacity)
{
    QPixmap img = *images[name];
    QRect r(rect.x, rect.y, rect.w, rect.h);
    painter.drawPixmap(r, optimizedSetOpacity(img, opacity));
}

void DrawDevice::drawText(QPainter &painter, string text, GuiRect rect)
{
    int x = rect.x;
    int y = rect.y + rect.h / 2;
    painter.drawText(x, y, QString::fromUtf8(text.c_str()));
}

void DrawDevice::drawRoom(QPainter &painter)
{
    GuiDataVect dv = engine->getVisibleData();
    for (GuiDataVect::iterator i = dv.begin(); i != dv.end(); ++i)
    {
        GuiData data = (*i);
        engine->relToAbsRect(data.rect);
        if (data.image != "")
            drawImage(painter, data.image, data.rect, data.alpha);
        if (data.text != "")
            drawText(painter, data.text, data.rect);
    }
}

void DrawDevice::updateMusic()
{
    // Background Music
    if (!QSound::isAvailable()) return;
    QString bgm_to_play(engine->getRoomsManager()->currentRoom()->bgm().c_str());
    if (bgm_to_play != "" && bgm_to_play != last_bgm)
    {
        if (bgm) delete bgm;
        bgm = new QSound(bgm_to_play);
        last_bgm = bgm_to_play;
    }
    if (bgm_to_play == "" && bgm) delete bgm;

    // SFX
    std::vector<string> sfx = engine->getSFX();
    for (std::vector<string>::iterator i = sfx.begin(); i != sfx.end(); ++i)
        QSound::play((*i).c_str());
}

<commit_msg>removed QSound::isAvailable() fixes #10<commit_after>#include "drawdevice.h"

#include <QFile>

DrawDevice::DrawDevice(Engine *eng, QWidget *parent) : QWidget(parent)
{
    engine = eng;
    setGeometry(parent->geometry());
    bgm = 0;
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(updateEngine()));
    timer->start(1000/25);
}

DrawDevice::~DrawDevice()
{
    for (std::map<string, QPixmap *>::iterator i = images.begin();
            i != images.end(); ++i)
    {
        delete i->second;
    }
    images.clear();
    if (bgm) delete bgm;
    delete timer;
}

void DrawDevice::initialize()
{
    setMouseTracking(true);
    setFocusPolicy(Qt::StrongFocus);
    std::vector<string> images = engine->getImgNames();
    for (std::vector<string>::iterator i = images.begin();
            i != images.end(); ++i)
        loadImage(*i);
}

bool DrawDevice::loadImage(string filename)
{
    if (QFile::exists(QString::fromStdString(filename)))
    {
        images[filename] = new QPixmap(filename.c_str());
        return true;
    }
    else
    {
        return false;
    }
}

void DrawDevice::quit(int status)
{
    qApp->exit(status);
}

void DrawDevice::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    drawRoom(painter);
}

void DrawDevice::mousePressEvent(QMouseEvent * event)
{
    std::pair<float, float> coord = engine->absToRelCoord(event->x(), event->y());
    engine->click(coord.first, coord.second);
    update();
    updateMusic();
}

void DrawDevice::mouseMoveEvent(QMouseEvent *event)
{
    if (engine->state() == Engine::GAME)
    {
        std::pair<float, float> coord = engine->absToRelCoord(event->x(), event->y());
        Item *item = engine->getRoomsManager()->currentRoom()->itemAt(coord.first,
                                                                    coord.second);
        Area *area = engine->getRoomsManager()->currentRoom()->areaAt(coord.first,
                                                                    coord.second);
        if (item != 0)
            setCursor(Qt::OpenHandCursor);
        else if (area != 0)
            setCursor(Qt::PointingHandCursor);
        else
            setCursor(Qt::ArrowCursor);
    }
    else
        setCursor(Qt::ArrowCursor);
}

void DrawDevice::resizeEvent(QResizeEvent *event)
{
    engine->getRoomsManager()->setRoomSize(event->size().width(), event->size().height());
}

void DrawDevice::updateEngine()
{
    if (engine->update())
        repaint();
}

QPixmap optimizedSetOpacity(QPixmap img, int opacity)
{
    QPixmap temp(img.size());
    temp.fill(Qt::transparent);
    QPainter p(&temp);
    p.setCompositionMode(QPainter::CompositionMode_Source);
    p.drawPixmap(0, 0, img);
    QLinearGradient alpha_gradient(0, 0, img.width(), 0);
    alpha_gradient.setColorAt(0, QColor(255, 255, 255, opacity));
    alpha_gradient.setColorAt(1, QColor(255, 255, 255, opacity));
    p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
    p.setBrush(alpha_gradient);
    p.drawRect(0, 0, temp.width(), temp.height());
    p.end();
    return temp;
}

void DrawDevice::drawImage(QPainter &painter, string name, GuiRect rect, int opacity)
{
    QPixmap img = *images[name];
    QRect r(rect.x, rect.y, rect.w, rect.h);
    painter.drawPixmap(r, optimizedSetOpacity(img, opacity));
}

void DrawDevice::drawText(QPainter &painter, string text, GuiRect rect)
{
    int x = rect.x;
    int y = rect.y + rect.h / 2;
    painter.drawText(x, y, QString::fromUtf8(text.c_str()));
}

void DrawDevice::drawRoom(QPainter &painter)
{
    GuiDataVect dv = engine->getVisibleData();
    for (GuiDataVect::iterator i = dv.begin(); i != dv.end(); ++i)
    {
        GuiData data = (*i);
        engine->relToAbsRect(data.rect);
        if (data.image != "")
            drawImage(painter, data.image, data.rect, data.alpha);
        if (data.text != "")
            drawText(painter, data.text, data.rect);
    }
}

void DrawDevice::updateMusic()
{
    // Background Music
    QString bgm_to_play(engine->getRoomsManager()->currentRoom()->bgm().c_str());
    if (bgm_to_play != "" && bgm_to_play != last_bgm)
    {
        if (bgm) delete bgm;
        bgm = new QSound(bgm_to_play);
        last_bgm = bgm_to_play;
    }
    if (bgm_to_play == "" && bgm) delete bgm;

    // SFX
    std::vector<string> sfx = engine->getSFX();
    for (std::vector<string>::iterator i = sfx.begin(); i != sfx.end(); ++i)
        QSound::play((*i).c_str());
}

<|endoftext|>


<commit_before>/*
Copyright (c) 2013 Daniele Bartolini, Michele Rossi
Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto

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

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

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

#include <cstring>
#include <inttypes.h>

#include "Allocator.h"
#include "Filesystem.h"
#include "StringUtils.h"
#include "JSONParser.h"
#include "SpriteResource.h"
#include "StringUtils.h"
#include "Array.h"
#include "Config.h"
#include "ReaderWriter.h"
#include <cfloat>

namespace crown
{
namespace sprite_resource
{

struct SpriteFrame
{
	StringId32 name;
	Vector4 region;		// [x0, y0, x1, y1]
	Vector2 scale;		// [Sx, Sy]
	Vector2 offset;		// [Ox, Oy]
};

//-----------------------------------------------------------------------------
void parse_frame(JSONElement e, SpriteFrame& frame)
{
	frame.name   = e.key("name"  ).to_string_id();
	frame.region = e.key("region").to_vector4();
	frame.offset = e.key("offset").to_vector2();
	frame.scale  = e.key("scale" ).to_vector2();
}

//-----------------------------------------------------------------------------
void parse_animation(JSONElement e, SpriteAnimation& anim)
{
	anim.name = e.key("name").to_string_id();
	anim.time = e.key("time").to_float();
	anim.num_frames = 0;
	anim.start_frame = 0;
}

//-----------------------------------------------------------------------------
void compile(Filesystem& fs, const char* resource_path, File* out_file)
{
	File* file = fs.open(resource_path, FOM_READ);
	JSONParser json(*file);
	fs.close(file);

	JSONElement root = json.root();

	// Read width/height
	const float width  = root.key("width" ).to_float();
	const float height = root.key("height").to_float();
	const uint32_t num_frames = root.key("frames").size();
	const uint32_t num_animations = root.key("animations").size();

	BinaryWriter bw(*out_file);

	Array<float> vertices(default_allocator());
	Array<uint16_t> indices(default_allocator());
	uint32_t num_idx = 0;
	for (uint32_t i = 0; i < num_frames; i++)
	{
		JSONElement e(root.key("frames")[i]);

		SpriteFrame frame;
		parse_frame(e, frame);

		const SpriteFrame& fd = frame;

		// Compute uv coords
		const float u0 = fd.region.x / width;
		const float v0 = fd.region.y / height;
		const float u1 = (fd.region.x + fd.region.z) / width;
		const float v1 = (fd.region.y + fd.region.w) / height;

		// Compute positions
		const float w = fd.region.z / CE_PIXELS_PER_METER;
		const float h = fd.region.w / CE_PIXELS_PER_METER;

		const float x0 = fd.scale.x * (-w * 0.5) + fd.offset.x;
		const float y0 = fd.scale.y * (-h * 0.5) + fd.offset.y;
		const float x1 = fd.scale.x * ( w * 0.5) + fd.offset.x;
		const float y1 = fd.scale.y * ( h * 0.5) + fd.offset.y;

		array::push_back(vertices, x0); array::push_back(vertices, y0); // position
		array::push_back(vertices, u0); array::push_back(vertices, v0); // uv

		array::push_back(vertices, x1); array::push_back(vertices, y0); // position
		array::push_back(vertices, u1); array::push_back(vertices, v0); // uv

		array::push_back(vertices, x1); array::push_back(vertices, y1); // position
		array::push_back(vertices, u1); array::push_back(vertices, v1); // uv

		array::push_back(vertices, x0); array::push_back(vertices, y1); // position
		array::push_back(vertices, u0); array::push_back(vertices, v1); // uv

		array::push_back(indices, uint16_t(num_idx)); array::push_back(indices, uint16_t(num_idx + 1)); array::push_back(indices, uint16_t(num_idx + 2));
		array::push_back(indices, uint16_t(num_idx)); array::push_back(indices, uint16_t(num_idx + 2)); array::push_back(indices, uint16_t(num_idx + 3));
		num_idx += 4;
	}

	const uint32_t num_vertices = array::size(vertices) / 4; // 4 components per vertex
	const uint32_t num_indices = array::size(indices);

	// Write animations
	Array<SpriteAnimation> animations(default_allocator());
	Array<uint32_t> frames(default_allocator());

	for (uint32_t i = 0; i < num_animations; i++)
	{
		JSONElement e(root.key("animations")[i]);

		SpriteAnimation anim;
		parse_animation(e, anim);

		// Read frames
		const uint32_t num_frames = e.key("frames").size();

		anim.num_frames = num_frames;
		anim.start_frame = array::size(frames); // Relative offset

		for (uint32_t ff = 0; ff < num_frames; ff++)
			array::push_back(frames, (uint32_t) e.key("frames")[ff].to_int());

		array::push_back(animations, anim);
	}

	// Write header
	bw.write(uint32_t(0)); // vb
	bw.write(uint32_t(0)); // ib
	bw.write(num_animations); uint32_t offt = sizeof(SpriteHeader);
	bw.write(offt);
	bw.write(num_vertices); offt += sizeof(SpriteAnimation) * array::size(animations) + sizeof(uint32_t) * array::size(frames);
	bw.write(offt);
	bw.write(num_indices); offt += sizeof(float) * array::size(vertices);
	bw.write(offt);

	if (array::size(animations))
		bw.write(array::begin(animations), sizeof(SpriteAnimation) * array::size(animations));

	if (array::size(frames))
		bw.write(array::begin(frames), sizeof(uint32_t) * array::size(frames));

	if (array::size(vertices))
		bw.write(array::begin(vertices), sizeof(float) * array::size(vertices));

	if (array::size(indices))
		bw.write(array::begin(indices), sizeof(uint16_t) * array::size(indices));
}

} // namespace sprite_resource
} // namespace crown
<commit_msg>Add missing headers<commit_after>/*
Copyright (c) 2013 Daniele Bartolini, Michele Rossi
Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto

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

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

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

#include <cstring>
#include <inttypes.h>

#include "Allocator.h"
#include "Filesystem.h"
#include "StringUtils.h"
#include "JSONParser.h"
#include "SpriteResource.h"
#include "StringUtils.h"
#include "Array.h"
#include "Config.h"
#include "ReaderWriter.h"
#include "Vector3.h"
#include "Vector4.h"
#include <cfloat>

namespace crown
{
namespace sprite_resource
{

struct SpriteFrame
{
	StringId32 name;
	Vector4 region;		// [x0, y0, x1, y1]
	Vector2 scale;		// [Sx, Sy]
	Vector2 offset;		// [Ox, Oy]
};

//-----------------------------------------------------------------------------
void parse_frame(JSONElement e, SpriteFrame& frame)
{
	frame.name   = e.key("name"  ).to_string_id();
	frame.region = e.key("region").to_vector4();
	frame.offset = e.key("offset").to_vector2();
	frame.scale  = e.key("scale" ).to_vector2();
}

//-----------------------------------------------------------------------------
void parse_animation(JSONElement e, SpriteAnimation& anim)
{
	anim.name = e.key("name").to_string_id();
	anim.time = e.key("time").to_float();
	anim.num_frames = 0;
	anim.start_frame = 0;
}

//-----------------------------------------------------------------------------
void compile(Filesystem& fs, const char* resource_path, File* out_file)
{
	File* file = fs.open(resource_path, FOM_READ);
	JSONParser json(*file);
	fs.close(file);

	JSONElement root = json.root();

	// Read width/height
	const float width  = root.key("width" ).to_float();
	const float height = root.key("height").to_float();
	const uint32_t num_frames = root.key("frames").size();
	const uint32_t num_animations = root.key("animations").size();

	BinaryWriter bw(*out_file);

	Array<float> vertices(default_allocator());
	Array<uint16_t> indices(default_allocator());
	uint32_t num_idx = 0;
	for (uint32_t i = 0; i < num_frames; i++)
	{
		JSONElement e(root.key("frames")[i]);

		SpriteFrame frame;
		parse_frame(e, frame);

		const SpriteFrame& fd = frame;

		// Compute uv coords
		const float u0 = fd.region.x / width;
		const float v0 = fd.region.y / height;
		const float u1 = (fd.region.x + fd.region.z) / width;
		const float v1 = (fd.region.y + fd.region.w) / height;

		// Compute positions
		const float w = fd.region.z / CE_PIXELS_PER_METER;
		const float h = fd.region.w / CE_PIXELS_PER_METER;

		const float x0 = fd.scale.x * (-w * 0.5) + fd.offset.x;
		const float y0 = fd.scale.y * (-h * 0.5) + fd.offset.y;
		const float x1 = fd.scale.x * ( w * 0.5) + fd.offset.x;
		const float y1 = fd.scale.y * ( h * 0.5) + fd.offset.y;

		array::push_back(vertices, x0); array::push_back(vertices, y0); // position
		array::push_back(vertices, u0); array::push_back(vertices, v0); // uv

		array::push_back(vertices, x1); array::push_back(vertices, y0); // position
		array::push_back(vertices, u1); array::push_back(vertices, v0); // uv

		array::push_back(vertices, x1); array::push_back(vertices, y1); // position
		array::push_back(vertices, u1); array::push_back(vertices, v1); // uv

		array::push_back(vertices, x0); array::push_back(vertices, y1); // position
		array::push_back(vertices, u0); array::push_back(vertices, v1); // uv

		array::push_back(indices, uint16_t(num_idx)); array::push_back(indices, uint16_t(num_idx + 1)); array::push_back(indices, uint16_t(num_idx + 2));
		array::push_back(indices, uint16_t(num_idx)); array::push_back(indices, uint16_t(num_idx + 2)); array::push_back(indices, uint16_t(num_idx + 3));
		num_idx += 4;
	}

	const uint32_t num_vertices = array::size(vertices) / 4; // 4 components per vertex
	const uint32_t num_indices = array::size(indices);

	// Write animations
	Array<SpriteAnimation> animations(default_allocator());
	Array<uint32_t> frames(default_allocator());

	for (uint32_t i = 0; i < num_animations; i++)
	{
		JSONElement e(root.key("animations")[i]);

		SpriteAnimation anim;
		parse_animation(e, anim);

		// Read frames
		const uint32_t num_frames = e.key("frames").size();

		anim.num_frames = num_frames;
		anim.start_frame = array::size(frames); // Relative offset

		for (uint32_t ff = 0; ff < num_frames; ff++)
			array::push_back(frames, (uint32_t) e.key("frames")[ff].to_int());

		array::push_back(animations, anim);
	}

	// Write header
	bw.write(uint32_t(0)); // vb
	bw.write(uint32_t(0)); // ib
	bw.write(num_animations); uint32_t offt = sizeof(SpriteHeader);
	bw.write(offt);
	bw.write(num_vertices); offt += sizeof(SpriteAnimation) * array::size(animations) + sizeof(uint32_t) * array::size(frames);
	bw.write(offt);
	bw.write(num_indices); offt += sizeof(float) * array::size(vertices);
	bw.write(offt);

	if (array::size(animations))
		bw.write(array::begin(animations), sizeof(SpriteAnimation) * array::size(animations));

	if (array::size(frames))
		bw.write(array::begin(frames), sizeof(uint32_t) * array::size(frames));

	if (array::size(vertices))
		bw.write(array::begin(vertices), sizeof(float) * array::size(vertices));

	if (array::size(indices))
		bw.write(array::begin(indices), sizeof(uint16_t) * array::size(indices));
}

} // namespace sprite_resource
} // namespace crown
<|endoftext|>


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

#include "chrome/browser/autofill/autofill_ie_toolbar_import_win.h"

#include "base/basictypes.h"
#include "base/string16.h"
#include "base/win/registry.h"
#include "chrome/browser/autofill/autofill_profile.h"
#include "chrome/browser/autofill/credit_card.h"
#include "chrome/browser/autofill/crypto/rc4_decryptor.h"
#include "chrome/browser/autofill/field_types.h"
#include "chrome/browser/autofill/personal_data_manager.h"
#include "chrome/browser/sync/util/data_encryption.h"

using base::win::RegKey;

// Forward declaration. This function is not in unnamed namespace as it
// is referenced in the unittest.
bool ImportCurrentUserProfiles(std::vector<AutoFillProfile>* profiles,
                               std::vector<CreditCard>* credit_cards);
namespace {

const wchar_t* const kProfileKey =
    L"Software\\Google\\Google Toolbar\\4.0\\Autofill\\Profiles";
const wchar_t* const kCreditCardKey =
    L"Software\\Google\\Google Toolbar\\4.0\\Autofill\\Credit Cards";
const wchar_t* const kPasswordHashValue = L"password_hash";
const wchar_t* const kSaltValue = L"salt";

// This is RC4 decryption for Toolbar credit card data. This is necessary
// because it is not standard, so Crypto api cannot be used.
std::wstring DecryptCCNumber(const std::wstring& data) {
  const wchar_t* kEmptyKey =
    L"\x3605\xCEE5\xCE49\x44F7\xCF4E\xF6CC\x604B\xFCBE\xC70A\x08FD";
  const size_t kMacLen = 10;

  if (data.length() <= kMacLen)
    return std::wstring();

  RC4Decryptor rc4_algorithm(kEmptyKey);
  return rc4_algorithm.Run(data.substr(kMacLen));
}

bool IsEmptySalt(std::wstring const& salt) {
  // Empty salt in IE Toolbar is \x1\x2...\x14
  if (salt.length() != 20)
    return false;
  for (size_t i = 0; i < salt.length(); ++i) {
    if (salt[i] != i + 1)
      return false;
  }
  return true;
}

string16 ReadAndDecryptValue(RegKey* key, const wchar_t* value_name) {
  DWORD data_type = REG_BINARY;
  DWORD data_size = 0;
  if (!key->ReadValue(value_name, NULL, &data_size, &data_type) ||
      !data_size || data_type != REG_BINARY)
    return string16();
  std::vector<uint8> data;
  data.resize(data_size);
  if (key->ReadValue(value_name, &(data[0]), &data_size, &data_type)) {
    std::string out_data;
    if (DecryptData(data, &out_data)) {
      // The actual data is in UTF16 already.
      if (!(out_data.size() & 1) && (out_data.size() > 2) &&
          !out_data[out_data.size() - 1] && !out_data[out_data.size() - 2]) {
        return string16(
            reinterpret_cast<const wchar_t *>(out_data.c_str()));
      }
    }
  }
  return string16();
}

struct {
  AutoFillFieldType field_type;
  const wchar_t *reg_value_name;
} profile_reg_values[] = {
  { NAME_FIRST,                    L"name_first" },
  { NAME_MIDDLE,                   L"name_middle" },
  { NAME_LAST,                     L"name_last" },
  { NAME_SUFFIX,                   L"name_suffix" },
  { EMAIL_ADDRESS,                 L"email" },
  { COMPANY_NAME,                  L"company_name" },
  { PHONE_HOME_NUMBER,             L"phone_home_number" },
  { PHONE_HOME_CITY_CODE,          L"phone_home_city_code" },
  { PHONE_HOME_COUNTRY_CODE,       L"phone_home_country_code" },
  { PHONE_FAX_NUMBER,              L"phone_fax_number" },
  { PHONE_FAX_CITY_CODE,           L"phone_fax_city_code" },
  { PHONE_FAX_COUNTRY_CODE,        L"phone_fax_country_code" },
  { ADDRESS_HOME_LINE1,            L"address_home_line1" },
  { ADDRESS_HOME_LINE2,            L"address_home_line2" },
  { ADDRESS_HOME_CITY,             L"address_home_city" },
  { ADDRESS_HOME_STATE,            L"address_home_state" },
  { ADDRESS_HOME_ZIP,              L"address_home_zip" },
  { ADDRESS_HOME_COUNTRY,          L"address_home_country" },
  { ADDRESS_BILLING_LINE1,         L"address_billing_line1" },
  { ADDRESS_BILLING_LINE2,         L"address_billing_line2" },
  { ADDRESS_BILLING_CITY,          L"address_billing_city" },
  { ADDRESS_BILLING_STATE,         L"address_billing_state" },
  { ADDRESS_BILLING_ZIP,           L"address_billing_zip" },
  { ADDRESS_BILLING_COUNTRY,       L"address_billing_country" },
  { CREDIT_CARD_NAME,              L"credit_card_name" },
  { CREDIT_CARD_NUMBER,            L"credit_card_number" },
  { CREDIT_CARD_EXP_MONTH,         L"credit_card_exp_month" },
  { CREDIT_CARD_EXP_4_DIGIT_YEAR,  L"credit_card_exp_4_digit_year" },
  { CREDIT_CARD_TYPE,              L"credit_card_type" },
  // We do not import verification code.
};

typedef std::map<std::wstring, AutoFillFieldType> RegToFieldMap;

bool ImportSingleProfile(FormGroup* profile,
                         RegKey* key,
                         const RegToFieldMap& reg_to_field ) {
  DCHECK(profile != NULL);
  if (!key->Valid())
    return false;

  bool has_non_empty_fields = false;

  for (uint32 value_index = 0; value_index < key->ValueCount(); ++value_index) {
    std::wstring value_name;
    if (!key->ReadName(value_index, &value_name))
      continue;
    RegToFieldMap::const_iterator it = reg_to_field.find(value_name);
    if (it == reg_to_field.end())
      continue;  // This field is not imported.
    string16 field_value = ReadAndDecryptValue(key, value_name.c_str());
    if (!field_value.empty()) {
      has_non_empty_fields = true;
      if (it->second == CREDIT_CARD_NUMBER) {
        field_value = DecryptCCNumber(field_value);
      }
      profile->SetInfo(AutoFillType(it->second), field_value);
    }
  }
  return has_non_empty_fields;
}

// Imports profiles from the IE toolbar and stores them. Asynchronous
// if PersonalDataManager has not been loaded yet. Deletes itself on completion.
class AutoFillImporter : public PersonalDataManager::Observer {
 public:
  explicit AutoFillImporter(PersonalDataManager* personal_data_manager)
    : personal_data_manager_(personal_data_manager) {
      personal_data_manager_->SetObserver(this);
  }

  bool ImportProfiles() {
    if (!ImportCurrentUserProfiles(&profiles_, &credit_cards_)) {
      delete this;
      return false;
    }
    if (personal_data_manager_->IsDataLoaded())
      OnPersonalDataLoaded();
    return true;
  }

  // PersonalDataManager::Observer methods:
  virtual void OnPersonalDataLoaded() {
    if (!profiles_.empty())
      personal_data_manager_->SetProfiles(&profiles_);
    if (!credit_cards_.empty())
      personal_data_manager_->SetCreditCards(&credit_cards_);
    delete this;
  }

 private:
  ~AutoFillImporter() {
    personal_data_manager_->RemoveObserver(this);
  }

  PersonalDataManager* personal_data_manager_;
  std::vector<AutoFillProfile> profiles_;
  std::vector<CreditCard> credit_cards_;
};

}  // namespace

// Imports AutoFill profiles and credit cards from IE Toolbar if present and not
// password protected. Returns true if data is successfully retrieved. False if
// there is no data, data is password protected or error occurred.
bool ImportCurrentUserProfiles(std::vector<AutoFillProfile>* profiles,
                               std::vector<CreditCard>* credit_cards) {
  DCHECK(profiles);
  DCHECK(credit_cards);

  // Create a map of possible fields for a quick access.
  RegToFieldMap reg_to_field;
  for (size_t i = 0; i < arraysize(profile_reg_values); ++i) {
    reg_to_field[std::wstring(profile_reg_values[i].reg_value_name)] =
        profile_reg_values[i].field_type;
  }

  base::win::RegistryKeyIterator iterator_profiles(HKEY_CURRENT_USER,
                                                   kProfileKey);
  for (; iterator_profiles.Valid(); ++iterator_profiles) {
    std::wstring key_name(kProfileKey);
    key_name.append(L"\\");
    key_name.append(iterator_profiles.Name());
    RegKey key(HKEY_CURRENT_USER, key_name.c_str(), KEY_READ);
    AutoFillProfile profile;
    if (ImportSingleProfile(&profile, &key, reg_to_field)) {
      // Combine phones into whole phone #.
      string16 phone;
      phone = profile.GetFieldText(AutoFillType(PHONE_HOME_COUNTRY_CODE));
      phone.append(profile.GetFieldText(AutoFillType(PHONE_HOME_CITY_CODE)));
      phone.append(profile.GetFieldText(AutoFillType(PHONE_HOME_NUMBER)));
      profile.SetInfo(AutoFillType(PHONE_HOME_WHOLE_NUMBER), phone);
      phone = profile.GetFieldText(AutoFillType(PHONE_FAX_COUNTRY_CODE));
      phone.append(profile.GetFieldText(AutoFillType(PHONE_FAX_CITY_CODE)));
      phone.append(profile.GetFieldText(AutoFillType(PHONE_FAX_NUMBER)));
      profile.SetInfo(AutoFillType(PHONE_FAX_WHOLE_NUMBER), phone);
      profiles->push_back(profile);
    }
  }
  string16 password_hash;
  string16 salt;
  RegKey cc_key(HKEY_CURRENT_USER, kCreditCardKey, KEY_READ);
  if (cc_key.Valid()) {
    password_hash = ReadAndDecryptValue(&cc_key, kPasswordHashValue);
    salt = ReadAndDecryptValue(&cc_key, kSaltValue);
  }

  // We import CC profiles only if they are not password protected.
  if (password_hash.empty() && IsEmptySalt(salt)) {
    base::win::RegistryKeyIterator iterator_cc(HKEY_CURRENT_USER,
                                               kCreditCardKey);
    for (; iterator_cc.Valid(); ++iterator_cc) {
      std::wstring key_name(kCreditCardKey);
      key_name.append(L"\\");
      key_name.append(iterator_cc.Name());
      RegKey key(HKEY_CURRENT_USER, key_name.c_str(), KEY_READ);
      CreditCard credit_card;
      if (ImportSingleProfile(&credit_card, &key, reg_to_field)) {
        string16 cc_number = credit_card.GetFieldText(
            AutoFillType(CREDIT_CARD_NUMBER));
        if (!cc_number.empty())
          credit_cards->push_back(credit_card);
      }
    }
  }
  return (profiles->size() + credit_cards->size()) > 0;
}

bool ImportAutofillDataWin(PersonalDataManager* pdm) {
  AutoFillImporter *importer = new AutoFillImporter(pdm);
  // importer will self delete.
  return importer->ImportProfiles();
}

<commit_msg>Fix for bug 68588" crash occurs if the first run when mode is incognito BUG=68588 TEST=Should not crash in described circumstances Review URL: http://codereview.chromium.org/6134002<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/autofill/autofill_ie_toolbar_import_win.h"

#include "base/basictypes.h"
#include "base/string16.h"
#include "base/win/registry.h"
#include "chrome/browser/autofill/autofill_profile.h"
#include "chrome/browser/autofill/credit_card.h"
#include "chrome/browser/autofill/crypto/rc4_decryptor.h"
#include "chrome/browser/autofill/field_types.h"
#include "chrome/browser/autofill/personal_data_manager.h"
#include "chrome/browser/sync/util/data_encryption.h"

using base::win::RegKey;

// Forward declaration. This function is not in unnamed namespace as it
// is referenced in the unittest.
bool ImportCurrentUserProfiles(std::vector<AutoFillProfile>* profiles,
                               std::vector<CreditCard>* credit_cards);
namespace {

const wchar_t* const kProfileKey =
    L"Software\\Google\\Google Toolbar\\4.0\\Autofill\\Profiles";
const wchar_t* const kCreditCardKey =
    L"Software\\Google\\Google Toolbar\\4.0\\Autofill\\Credit Cards";
const wchar_t* const kPasswordHashValue = L"password_hash";
const wchar_t* const kSaltValue = L"salt";

// This is RC4 decryption for Toolbar credit card data. This is necessary
// because it is not standard, so Crypto api cannot be used.
std::wstring DecryptCCNumber(const std::wstring& data) {
  const wchar_t* kEmptyKey =
    L"\x3605\xCEE5\xCE49\x44F7\xCF4E\xF6CC\x604B\xFCBE\xC70A\x08FD";
  const size_t kMacLen = 10;

  if (data.length() <= kMacLen)
    return std::wstring();

  RC4Decryptor rc4_algorithm(kEmptyKey);
  return rc4_algorithm.Run(data.substr(kMacLen));
}

bool IsEmptySalt(std::wstring const& salt) {
  // Empty salt in IE Toolbar is \x1\x2...\x14
  if (salt.length() != 20)
    return false;
  for (size_t i = 0; i < salt.length(); ++i) {
    if (salt[i] != i + 1)
      return false;
  }
  return true;
}

string16 ReadAndDecryptValue(RegKey* key, const wchar_t* value_name) {
  DWORD data_type = REG_BINARY;
  DWORD data_size = 0;
  if (!key->ReadValue(value_name, NULL, &data_size, &data_type) ||
      !data_size || data_type != REG_BINARY)
    return string16();
  std::vector<uint8> data;
  data.resize(data_size);
  if (key->ReadValue(value_name, &(data[0]), &data_size, &data_type)) {
    std::string out_data;
    if (DecryptData(data, &out_data)) {
      // The actual data is in UTF16 already.
      if (!(out_data.size() & 1) && (out_data.size() > 2) &&
          !out_data[out_data.size() - 1] && !out_data[out_data.size() - 2]) {
        return string16(
            reinterpret_cast<const wchar_t *>(out_data.c_str()));
      }
    }
  }
  return string16();
}

struct {
  AutoFillFieldType field_type;
  const wchar_t *reg_value_name;
} profile_reg_values[] = {
  { NAME_FIRST,                    L"name_first" },
  { NAME_MIDDLE,                   L"name_middle" },
  { NAME_LAST,                     L"name_last" },
  { NAME_SUFFIX,                   L"name_suffix" },
  { EMAIL_ADDRESS,                 L"email" },
  { COMPANY_NAME,                  L"company_name" },
  { PHONE_HOME_NUMBER,             L"phone_home_number" },
  { PHONE_HOME_CITY_CODE,          L"phone_home_city_code" },
  { PHONE_HOME_COUNTRY_CODE,       L"phone_home_country_code" },
  { PHONE_FAX_NUMBER,              L"phone_fax_number" },
  { PHONE_FAX_CITY_CODE,           L"phone_fax_city_code" },
  { PHONE_FAX_COUNTRY_CODE,        L"phone_fax_country_code" },
  { ADDRESS_HOME_LINE1,            L"address_home_line1" },
  { ADDRESS_HOME_LINE2,            L"address_home_line2" },
  { ADDRESS_HOME_CITY,             L"address_home_city" },
  { ADDRESS_HOME_STATE,            L"address_home_state" },
  { ADDRESS_HOME_ZIP,              L"address_home_zip" },
  { ADDRESS_HOME_COUNTRY,          L"address_home_country" },
  { ADDRESS_BILLING_LINE1,         L"address_billing_line1" },
  { ADDRESS_BILLING_LINE2,         L"address_billing_line2" },
  { ADDRESS_BILLING_CITY,          L"address_billing_city" },
  { ADDRESS_BILLING_STATE,         L"address_billing_state" },
  { ADDRESS_BILLING_ZIP,           L"address_billing_zip" },
  { ADDRESS_BILLING_COUNTRY,       L"address_billing_country" },
  { CREDIT_CARD_NAME,              L"credit_card_name" },
  { CREDIT_CARD_NUMBER,            L"credit_card_number" },
  { CREDIT_CARD_EXP_MONTH,         L"credit_card_exp_month" },
  { CREDIT_CARD_EXP_4_DIGIT_YEAR,  L"credit_card_exp_4_digit_year" },
  { CREDIT_CARD_TYPE,              L"credit_card_type" },
  // We do not import verification code.
};

typedef std::map<std::wstring, AutoFillFieldType> RegToFieldMap;

bool ImportSingleProfile(FormGroup* profile,
                         RegKey* key,
                         const RegToFieldMap& reg_to_field ) {
  DCHECK(profile != NULL);
  if (!key->Valid())
    return false;

  bool has_non_empty_fields = false;

  for (uint32 value_index = 0; value_index < key->ValueCount(); ++value_index) {
    std::wstring value_name;
    if (!key->ReadName(value_index, &value_name))
      continue;
    RegToFieldMap::const_iterator it = reg_to_field.find(value_name);
    if (it == reg_to_field.end())
      continue;  // This field is not imported.
    string16 field_value = ReadAndDecryptValue(key, value_name.c_str());
    if (!field_value.empty()) {
      has_non_empty_fields = true;
      if (it->second == CREDIT_CARD_NUMBER) {
        field_value = DecryptCCNumber(field_value);
      }
      profile->SetInfo(AutoFillType(it->second), field_value);
    }
  }
  return has_non_empty_fields;
}

// Imports profiles from the IE toolbar and stores them. Asynchronous
// if PersonalDataManager has not been loaded yet. Deletes itself on completion.
class AutoFillImporter : public PersonalDataManager::Observer {
 public:
  explicit AutoFillImporter(PersonalDataManager* personal_data_manager)
    : personal_data_manager_(personal_data_manager) {
      personal_data_manager_->SetObserver(this);
  }

  bool ImportProfiles() {
    if (!ImportCurrentUserProfiles(&profiles_, &credit_cards_)) {
      delete this;
      return false;
    }
    if (personal_data_manager_->IsDataLoaded())
      OnPersonalDataLoaded();
    return true;
  }

  // PersonalDataManager::Observer methods:
  virtual void OnPersonalDataLoaded() {
    if (!profiles_.empty())
      personal_data_manager_->SetProfiles(&profiles_);
    if (!credit_cards_.empty())
      personal_data_manager_->SetCreditCards(&credit_cards_);
    delete this;
  }

 private:
  ~AutoFillImporter() {
    personal_data_manager_->RemoveObserver(this);
  }

  PersonalDataManager* personal_data_manager_;
  std::vector<AutoFillProfile> profiles_;
  std::vector<CreditCard> credit_cards_;
};

}  // namespace

// Imports AutoFill profiles and credit cards from IE Toolbar if present and not
// password protected. Returns true if data is successfully retrieved. False if
// there is no data, data is password protected or error occurred.
bool ImportCurrentUserProfiles(std::vector<AutoFillProfile>* profiles,
                               std::vector<CreditCard>* credit_cards) {
  DCHECK(profiles);
  DCHECK(credit_cards);

  // Create a map of possible fields for a quick access.
  RegToFieldMap reg_to_field;
  for (size_t i = 0; i < arraysize(profile_reg_values); ++i) {
    reg_to_field[std::wstring(profile_reg_values[i].reg_value_name)] =
        profile_reg_values[i].field_type;
  }

  base::win::RegistryKeyIterator iterator_profiles(HKEY_CURRENT_USER,
                                                   kProfileKey);
  for (; iterator_profiles.Valid(); ++iterator_profiles) {
    std::wstring key_name(kProfileKey);
    key_name.append(L"\\");
    key_name.append(iterator_profiles.Name());
    RegKey key(HKEY_CURRENT_USER, key_name.c_str(), KEY_READ);
    AutoFillProfile profile;
    if (ImportSingleProfile(&profile, &key, reg_to_field)) {
      // Combine phones into whole phone #.
      string16 phone;
      phone = profile.GetFieldText(AutoFillType(PHONE_HOME_COUNTRY_CODE));
      phone.append(profile.GetFieldText(AutoFillType(PHONE_HOME_CITY_CODE)));
      phone.append(profile.GetFieldText(AutoFillType(PHONE_HOME_NUMBER)));
      profile.SetInfo(AutoFillType(PHONE_HOME_WHOLE_NUMBER), phone);
      phone = profile.GetFieldText(AutoFillType(PHONE_FAX_COUNTRY_CODE));
      phone.append(profile.GetFieldText(AutoFillType(PHONE_FAX_CITY_CODE)));
      phone.append(profile.GetFieldText(AutoFillType(PHONE_FAX_NUMBER)));
      profile.SetInfo(AutoFillType(PHONE_FAX_WHOLE_NUMBER), phone);
      profiles->push_back(profile);
    }
  }
  string16 password_hash;
  string16 salt;
  RegKey cc_key(HKEY_CURRENT_USER, kCreditCardKey, KEY_READ);
  if (cc_key.Valid()) {
    password_hash = ReadAndDecryptValue(&cc_key, kPasswordHashValue);
    salt = ReadAndDecryptValue(&cc_key, kSaltValue);
  }

  // We import CC profiles only if they are not password protected.
  if (password_hash.empty() && IsEmptySalt(salt)) {
    base::win::RegistryKeyIterator iterator_cc(HKEY_CURRENT_USER,
                                               kCreditCardKey);
    for (; iterator_cc.Valid(); ++iterator_cc) {
      std::wstring key_name(kCreditCardKey);
      key_name.append(L"\\");
      key_name.append(iterator_cc.Name());
      RegKey key(HKEY_CURRENT_USER, key_name.c_str(), KEY_READ);
      CreditCard credit_card;
      if (ImportSingleProfile(&credit_card, &key, reg_to_field)) {
        string16 cc_number = credit_card.GetFieldText(
            AutoFillType(CREDIT_CARD_NUMBER));
        if (!cc_number.empty())
          credit_cards->push_back(credit_card);
      }
    }
  }
  return (profiles->size() + credit_cards->size()) > 0;
}

bool ImportAutofillDataWin(PersonalDataManager* pdm) {
  // In incognito mode we do not have PDM - and we should not import anything.
  if (!pdm)
    return false;
  AutoFillImporter *importer = new AutoFillImporter(pdm);
  // importer will self delete.
  return importer->ImportProfiles();
}

<|endoftext|>


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

#include "chrome/browser/chromeos/browser_notification_observers.h"

#include <string>

#include "base/file_util.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/chromeos/boot_times_loader.h"
#include "chrome/browser/chromeos/login/authentication_notification_details.h"
#include "chrome/common/notification_service.h"

namespace chromeos {

InitialTabNotificationObserver::InitialTabNotificationObserver() {
  registrar_.Add(this, NotificationType::LOAD_START,
                 NotificationService::AllSources());
}

InitialTabNotificationObserver::~InitialTabNotificationObserver() {
}

void InitialTabNotificationObserver::Observe(
    NotificationType type,
    const NotificationSource& source,
    const NotificationDetails& details) {
  // Only log for first tab to render.  Make sure this is only done once.
  if (type == NotificationType::LOAD_START && num_tabs_.GetNext() == 0) {
    // Post difference between first tab and login succeess time as login time.
    UMA_HISTOGRAM_TIMES("BootTime.Login",
                        base::Time::NowFromSystemTime() - login_success_time_);
    // Post chrome first render stat.
    BootTimesLoader::RecordCurrentStats("chrome-first-render");
    registrar_.Remove(this, NotificationType::LOAD_START,
                      NotificationService::AllSources());
  }
}

LogLoginSuccessObserver::LogLoginSuccessObserver() {
  registrar_.Add(this, NotificationType::LOGIN_AUTHENTICATION,
                 NotificationService::AllSources());
}

LogLoginSuccessObserver::~LogLoginSuccessObserver() {
}

void LogLoginSuccessObserver::Observe(NotificationType type,
                                   const NotificationSource& source,
                                   const NotificationDetails& details) {
  DCHECK(type == NotificationType::LOGIN_AUTHENTICATION);
  Details<AuthenticationNotificationDetails> auth_details(details);
  if (auth_details->success()) {
    InitialTabNotificationObserver::Get()->SetLoginSuccessTime();
    BootTimesLoader::RecordCurrentStats("login-successful");
    registrar_.Remove(this, NotificationType::LOGIN_AUTHENTICATION,
                      NotificationService::AllSources());
  }
}

}  // namespace chromeos
<commit_msg>Chrome ARM build fix.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/browser_notification_observers.h"

#include <string>

#include "base/file_util.h"
#include "base/histogram.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/chromeos/boot_times_loader.h"
#include "chrome/browser/chromeos/login/authentication_notification_details.h"
#include "chrome/common/notification_service.h"

namespace chromeos {

InitialTabNotificationObserver::InitialTabNotificationObserver() {
  registrar_.Add(this, NotificationType::LOAD_START,
                 NotificationService::AllSources());
}

InitialTabNotificationObserver::~InitialTabNotificationObserver() {
}

void InitialTabNotificationObserver::Observe(
    NotificationType type,
    const NotificationSource& source,
    const NotificationDetails& details) {
  // Only log for first tab to render.  Make sure this is only done once.
  if (type == NotificationType::LOAD_START && num_tabs_.GetNext() == 0) {
    // Post difference between first tab and login succeess time as login time.
    UMA_HISTOGRAM_TIMES("BootTime.Login",
                        base::Time::NowFromSystemTime() - login_success_time_);
    // Post chrome first render stat.
    BootTimesLoader::RecordCurrentStats("chrome-first-render");
    registrar_.Remove(this, NotificationType::LOAD_START,
                      NotificationService::AllSources());
  }
}

LogLoginSuccessObserver::LogLoginSuccessObserver() {
  registrar_.Add(this, NotificationType::LOGIN_AUTHENTICATION,
                 NotificationService::AllSources());
}

LogLoginSuccessObserver::~LogLoginSuccessObserver() {
}

void LogLoginSuccessObserver::Observe(NotificationType type,
                                   const NotificationSource& source,
                                   const NotificationDetails& details) {
  DCHECK(type == NotificationType::LOGIN_AUTHENTICATION);
  Details<AuthenticationNotificationDetails> auth_details(details);
  if (auth_details->success()) {
    InitialTabNotificationObserver::Get()->SetLoginSuccessTime();
    BootTimesLoader::RecordCurrentStats("login-successful");
    registrar_.Remove(this, NotificationType::LOGIN_AUTHENTICATION,
                      NotificationService::AllSources());
  }
}

}  // namespace chromeos
<|endoftext|>