<commit_before>#include "QGeoIP.h"

QGeoIP::QGeoIP() {
    this->cityDB = NULL;
    this->ISPDB  = NULL;
}

QGeoIP::~QGeoIP() {
    this->closeDatabases();
}

bool QGeoIP::openDatabases(const QString & cityDBFile, const QString & ISPDBFile) {
    if (!this->open(&this->cityDB, cityDBFile)) {
        qCritical("Could not open city DB, %s.", qPrintable(cityDBFile));
        return false;
    }
    if (!this->open(&this->ISPDB, ISPDBFile)) {
        qCritical("Could not open ISP DB, %s.", qPrintable(ISPDBFile));
        return false;
    }

    return true;
}

void QGeoIP::closeDatabases() {
    this->close(&this->cityDB);
    this->close(&this->ISPDB);
}

/**
 * Resolve an IP address to a QGeoIPRecord, in which the following information
 * is contained:
 * - the country code (ISO-3166-1-alpha2)
 * - the country name
 * - city name
 * - region name
 * - latitude and longitude
 *
 * @return
 *   The corresponding QGeoIPRecord.
 */
QGeoIPRecord QGeoIP::recordByAddr(const QHostAddress & ip) {
    static QString country, city, region, isp, timeZone;
    const char * addr, * regionName, * ispName;

    if (this->isOpen(this->cityDB) && !ip.isNull()) {
        addr = ip.toString().toAscii().constData();

        GeoIPRecord * r;
        if (ip.protocol() == QAbstractSocket::IPv6Protocol)
            r = GeoIP_record_by_addr_v6(this->cityDB, addr);
        else
            r = GeoIP_record_by_addr(this->cityDB, addr);

        // Look up the ISP for this IP address, but only if an ISP DB is open.
        isp = QString::null;
        if (this->isOpen(this->ISPDB)) {
            if (ip.protocol() == QAbstractSocket::IPv6Protocol)
                ispName = GeoIP_org_by_name_v6(this->ISPDB, addr);
            else
                ispName = GeoIP_org_by_name(this->ISPDB, addr);

            if (ispName != NULL) {
                isp = QString::fromUtf8(ispName);
                free((char *) ispName);
            }
        }
        // Since addr really is an alias that points directly the the data
        // stored by the QHostAddress data structure, it doesn't need to be
        // deleted.

        timeZone = QString::fromUtf8(GeoIP_time_zone_by_country_and_region(r->country_code, r->region));

        if (r != NULL) {
            country = QString::fromUtf8(r->country_name);
            city = QString::fromUtf8(r->city);

            regionName = GeoIP_region_name_by_code(r->country_code, r->region);
            if (regionName != NULL) {
                region = QString::fromUtf8(regionName);
                // No free() call required for regionName, since it is actually
                // pointing to a hardcoded string in libGeoIP's C code.
            }

            // Create the result that will be returned to the user.
            QGeoIPRecord result(country, region, city, isp, timeZone, r->latitude, r->longitude, r->country_code, r->continent_code);

            // Delete the GeoIPRecord returned by GeoIP_record_by_addr() from
            // memory now that it is no longer needed.
            GeoIPRecord_delete(r);

            // Return the result we found.
            return result;
        }
    }

    // This function should only be called when at least the City DB is open.
    qWarning("QGeoIP::recordByAddr(): MaxMind City DB is not open.");

    // Satisfy compiler.
    return QGeoIPRecord();
}

//-----------------------------------------------------------------------------------
// Private methods.

/**
 * Open a GeoIP database. If a database is already opened in the current
 * instance, it will be closed before the requested database is opened.
 *
 * @return
 *   true if successful, otherwise false.
 */
bool QGeoIP::open(GeoIP ** db, const QString & fileName) {
    *db = GeoIP_open(fileName.toLocal8Bit().constData(), GEOIP_MMAP_CACHE);
    if (this->isOpen(*db)) {
        GeoIP_set_charset(*db, GEOIP_CHARSET_UTF8);
        return true;
    }
    else
        return false;
}

void QGeoIP::close(GeoIP ** db) {
    if (this->isOpen(*db)) {
        GeoIP_delete(*db);
        *db = NULL;
    }
}

bool QGeoIP::isOpen(GeoIP const * const db) const {
    return db != NULL;
}

#ifdef DEBUG
QDebug operator<<(QDebug dbg, const QGeoIPRecord & record) {
    dbg.nospace() << record.country
                  << " ("
                  << record.countryCode
                  << ", "
                  << record.continentCode
                  << "), "
                  << record.region
                  << ", "
                  << record.city
                  << ", "
                  << record.isp
                  << ", "
                  << record.timeZone
                  << ", ("
                  << record.lat
                  << ","
                  << record.lon
                  << ")";

    return dbg.nospace();
}
#endif
<commit_msg>Fix a bug introduced in commit 2f7fe0cc408d2d41df0a (the commit that fixed the remaining memory leaks), which would cause incorrect results. Strangely, a side-effect of this change is a significant performance improvement: the ±50,000-line test file can now be parsed at about 3,600 lines per second instead of about 1,800 lines per second (on my 2.66 GHz Core 2 Duo). I don't have an explanation for this.<commit_after>#include "QGeoIP.h"

QGeoIP::QGeoIP() {
    this->cityDB = NULL;
    this->ISPDB  = NULL;
}

QGeoIP::~QGeoIP() {
    this->closeDatabases();
}

bool QGeoIP::openDatabases(const QString & cityDBFile, const QString & ISPDBFile) {
    if (!this->open(&this->cityDB, cityDBFile)) {
        qCritical("Could not open city DB, %s.", qPrintable(cityDBFile));
        return false;
    }
    if (!this->open(&this->ISPDB, ISPDBFile)) {
        qCritical("Could not open ISP DB, %s.", qPrintable(ISPDBFile));
        return false;
    }

    return true;
}

void QGeoIP::closeDatabases() {
    this->close(&this->cityDB);
    this->close(&this->ISPDB);
}

/**
 * Resolve an IP address to a QGeoIPRecord, in which the following information
 * is contained:
 * - the country code (ISO-3166-1-alpha2)
 * - the country name
 * - city name
 * - region name
 * - latitude and longitude
 *
 * @return
 *   The corresponding QGeoIPRecord.
 */
QGeoIPRecord QGeoIP::recordByAddr(const QHostAddress & ip) {
    static QString country, city, region, isp, timeZone;
    const char * addr, * regionName, * ispName;

    if (this->isOpen(this->cityDB) && !ip.isNull()) {
        addr = ip.toString().toAscii().constData();

        GeoIPRecord * r;
        if (ip.protocol() == QAbstractSocket::IPv6Protocol)
            r = GeoIP_record_by_addr_v6(this->cityDB, addr);
        else
            r = GeoIP_record_by_addr(this->cityDB, addr);

        // Look up the ISP for this IP address, but only if an ISP DB is open.
        isp = QString::null;
        // Set addr to the same value again, since the GeoIP_record_by_addr()
        // call above may (sometimes) change addr, thereby generating
        // incorrect results.
        // addr = ip.toString().toAscii().constData();
        if (this->isOpen(this->ISPDB)) {
            if (ip.protocol() == QAbstractSocket::IPv6Protocol)
                ispName = GeoIP_org_by_name_v6(this->ISPDB, addr);
            else
                ispName = GeoIP_org_by_name(this->ISPDB, addr);

            if (ispName != NULL) {
                isp = QString::fromUtf8(ispName);
                free((char *) ispName);
            }
        }
        // Since addr really is an alias that points directly the the data
        // stored by the QHostAddress data structure, it doesn't need to be
        // deleted.

        timeZone = QString::fromUtf8(GeoIP_time_zone_by_country_and_region(r->country_code, r->region));

        if (r != NULL) {
            country = QString::fromUtf8(r->country_name);
            city = QString::fromUtf8(r->city);

            regionName = GeoIP_region_name_by_code(r->country_code, r->region);
            if (regionName != NULL) {
                region = QString::fromUtf8(regionName);
                // No free() call required for regionName, since it is actually
                // pointing to a hardcoded string in libGeoIP's C code.
            }

            // Create the result that will be returned to the user.
            QGeoIPRecord result(country, region, city, isp, timeZone, r->latitude, r->longitude, r->country_code, r->continent_code);

            // Delete the GeoIPRecord returned by GeoIP_record_by_addr() from
            // memory now that it is no longer needed.
            GeoIPRecord_delete(r);

            // Return the result we found.
            return result;
        }
    }

    // This function should only be called when at least the City DB is open.
    qWarning("QGeoIP::recordByAddr(): MaxMind City DB is not open.");

    // Satisfy compiler.
    return QGeoIPRecord();
}

//-----------------------------------------------------------------------------------
// Private methods.

/**
 * Open a GeoIP database. If a database is already opened in the current
 * instance, it will be closed before the requested database is opened.
 *
 * @return
 *   true if successful, otherwise false.
 */
bool QGeoIP::open(GeoIP ** db, const QString & fileName) {
    *db = GeoIP_open(fileName.toLocal8Bit().constData(), GEOIP_MMAP_CACHE);
    if (this->isOpen(*db)) {
        GeoIP_set_charset(*db, GEOIP_CHARSET_UTF8);
        return true;
    }
    else
        return false;
}

void QGeoIP::close(GeoIP ** db) {
    if (this->isOpen(*db)) {
        GeoIP_delete(*db);
        *db = NULL;
    }
}

bool QGeoIP::isOpen(GeoIP const * const db) const {
    return db != NULL;
}

#ifdef DEBUG
QDebug operator<<(QDebug dbg, const QGeoIPRecord & record) {
    dbg.nospace() << record.country
                  << " ("
                  << record.countryCode
                  << ", "
                  << record.continentCode
                  << "), "
                  << record.region
                  << ", "
                  << record.city
                  << ", "
                  << record.isp
                  << ", "
                  << record.timeZone
                  << ", ("
                  << record.lat
                  << ","
                  << record.lon
                  << ")";

    return dbg.nospace();
}
#endif
<|endoftext|>


<commit_before>/*
	Copyright (c) 2013, Remi Thebault
	All rights reserved.

	Redistribution and use in source and binary forms, with or without
	modification, are permitted provided that the following conditions are met:
		* Redistributions of source code must retain the above copyright
		  notice, this list of conditions and the following disclaimer.
		* Redistributions in binary form must reproduce the above copyright
		  notice, this list of conditions and the following disclaimer in the
		  documentation and/or other materials provided with the distribution.
		* Neither the name of the <organization> 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 <COPYRIGHT HOLDER> 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.
*/
#include "QtTool.h"
#include "StringUtils.h"
#include "FileUtils.h"

#ifdef _WIN32
#include <Windows.h>
#else
#include <sys/types.h>
#include <sys/stat.h>
#endif

#include <algorithm>
#include <fstream>
#include <sstream>
#include <iostream>
#include <stdexcept>
#include <cstdlib>
#include <cstdio>

using namespace std;

bool QtTool::needsToRun(const std::string& inFile, const std::string& outFile)
{
#ifdef _WIN32
	HANDLE hInFile = CreateFile(inFile.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL,
	                            OPEN_EXISTING, 0, NULL);
	HANDLE hOutFile = CreateFile(outFile.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL,
	                             OPEN_EXISTING, 0, NULL);

	if(hInFile == INVALID_HANDLE_VALUE) {
		return false;
	}
	if(hOutFile == INVALID_HANDLE_VALUE) {
		return true;
	}

	FILETIME lstInMod, lstOutMod;
	GetFileTime(hInFile, NULL, NULL, &lstInMod);
	GetFileTime(hOutFile, NULL, NULL, &lstOutMod);

	CloseHandle(hInFile);
	CloseHandle(hOutFile);

	return CompareFileTime(&lstInMod, &lstOutMod) == 1;
#else
	struct stat stIn;
	struct stat stOut;
	stat(inFile.c_str(), &stIn);
	stat(outFile.c_str(), &stOut);
	return stIn.st_mtime > stOut.st_mtime;
#endif
}

bool QtTool::runIfNeeded(const std::string& inFile, const std::string& outFile)
{
	if (needsToRun(inFile, outFile)) {

		ostringstream cmd;
		cmd << exePath_;
		if (cmdOpts_.size() > 0) {
			cmd << " " << cmdOpts_;
		}
		cmd << " -o " << outFile << " " << inFile;

#ifdef _WIN32
		const size_t bufSize = 512;
		char buf [bufSize];

		STARTUPINFO si;
		PROCESS_INFORMATION pi;

		ZeroMemory(&pi, sizeof(pi));
		ZeroMemory(&si, sizeof(si));
		si.cb = sizeof(si);
		si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
		si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
		si.hStdInput = NULL;
		si.dwFlags |= STARTF_USESTDHANDLES;

		string cmdOpts = cmd.str();
		for(size_t i=0; i<cmdOpts.size(); ++i) {
			buf[i] = cmdOpts[i];
			if (i == bufSize-1) break;
		}
		size_t i = min(size_t(bufSize-1), cmdOpts.size());
		buf[i] = '\0';

		// Start the child process.
		if( !CreateProcess(
		            NULL,			// module name
		            buf,	        // Command line
		            NULL,           // Process handle not inheritable
		            NULL,           // Thread handle not inheritable
		            TRUE,           // Set handle inheritance to TRUE
		            0,              // No creation flags
		            NULL,           // Use parent's environment block
		            NULL,           // Use parent's starting directory
		            &si,            // Pointer to STARTUPINFO structure
		            &pi )           // Pointer to PROCESS_INFORMATION structure
		  ) {
			cerr << "CreateProcess err " << GetLastError() << "\n";
			throw runtime_error("cannot start process");
		}
		WaitForSingleObject(pi.hProcess, INFINITE);

		if (!CloseHandle(pi.hProcess)) {
			cerr << "close handle process\n";
		}
		if (!CloseHandle(pi.hThread)) {
			cerr << "close handle thread\n";
		}

#else

		FILE *handle = popen(cmd.str().c_str(), "r");

		if (handle == NULL) {
			throw runtime_error("cannot start process");
		}

		char buf[64];
		size_t readn;
		while ((readn = fread(buf, 1, sizeof(buf), handle)) > 0) {
			fwrite(buf, 1, readn, stdout);
		}

		pclose(handle);

#endif

		return true;
	}
	return false;
}

string QtMocTool::exePath(const string& qtBinPath)
{
#ifdef _WIN32
	return qtBinPath + "moc.exe";
#else
	return qtBinPath + "moc";
#endif // _WIN32
}

bool QtMocTool::isFileInput(const string& inFile)
{
	if (!su::endsWith(inFile, string(".h")) &&
	        !su::endsWith(inFile, string(".hpp")) &&
	        !su::endsWith(inFile, string(".hh")) &&
	        !su::endsWith(inFile, string(".hxx"))) {
		return false;
	}

	ifstream in (inFile);
	if (!in) return false;

	string line;
	bool found = false;
	const string q_object = "Q_OBJECT";
	while(getline(in, line)) {
		if(line.find(q_object) != string::npos) {
			found = true;
			break;
		}
	}
	in.close();
	return found;
}

std::string QtMocTool::getOutFilename (const string& inFileName)
{
	string base;
	string ext;
	tie(base, ext) = fu::splitExt(inFileName);

	ostringstream oss;
	oss << "mo_" << base << ".cc";
	return oss.str();
}

string QtUicTool::exePath(const string& qtBinPath)
{
#ifdef _WIN32
	return qtBinPath + "uic.exe";
#else
	return qtBinPath + "uic";
#endif // _WIN32
}

bool QtUicTool::isFileInput(const string& inFile)
{
	if (!su::endsWith(inFile, string(".ui"))) {
		return false;
	}
	return true;
}

string QtUicTool::getOutFilename (const string& inFileName)
{
	string base;
	string ext;
	tie(base, ext) = fu::splitExt(inFileName);

	ostringstream oss;
	oss << "ui_" << base << ".h";
	return oss.str();
}

string QtRccTool::exePath(const string& qtBinPath)
{
#ifdef _WIN32
	return qtBinPath + "rcc.exe";
#else
	return qtBinPath + "rcc";
#endif // _WIN32
}

bool QtRccTool::isFileInput(const string& inFile)
{
	if (!su::endsWith(inFile, string(".qrc"))) {
		return false;
	}
	return true;
}

string QtRccTool::getOutFilename (const string& inFileName)
{
	string base;
	string ext;
	tie(base, ext) = fu::splitExt(inFileName);

	ostringstream oss;
	oss << "rc_" << base << ".cc";
	return oss.str();
}

bool QtRccTool::needsToRun(const std::string& inFile, const std::string& outFile)
{
	if (QtTool::needsToRun(inFile, outFile)) {
		return true;
	}
	bool run = false;

	string baseDir = fu::parentDir(inFile);

	ifstream in (inFile);
	string line;
	while(getline(in, line)) {
		size_t pos = line.find("<file>");
		if (pos != string::npos) {
			line = line.substr(pos + 6);
			pos = line.find("</file>");
			if (pos != string::npos) {
				string fn = line.substr(0, pos);
				if (fn.size() > 0) {
					string resFile = baseDir + fn;
					run = QtTool::needsToRun(resFile, outFile);
					if (run) break;
				}
			}
		}
	}
	in.close();

	return run;
}

<commit_msg>testing existence of files prior to compare timestamps<commit_after>/*
	Copyright (c) 2013, Remi Thebault
	All rights reserved.

	Redistribution and use in source and binary forms, with or without
	modification, are permitted provided that the following conditions are met:
		* Redistributions of source code must retain the above copyright
		  notice, this list of conditions and the following disclaimer.
		* Redistributions in binary form must reproduce the above copyright
		  notice, this list of conditions and the following disclaimer in the
		  documentation and/or other materials provided with the distribution.
		* Neither the name of the <organization> 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 <COPYRIGHT HOLDER> 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.
*/
#include "QtTool.h"
#include "StringUtils.h"
#include "FileUtils.h"

#ifdef _WIN32
#include <Windows.h>
#else
#include <sys/types.h>
#include <sys/stat.h>
#endif

#include <algorithm>
#include <fstream>
#include <sstream>
#include <iostream>
#include <stdexcept>
#include <cstdlib>
#include <cstdio>

using namespace std;

bool QtTool::needsToRun(const std::string& inFile, const std::string& outFile)
{
	if (!fu::isFile(inFile)) {
		return false;
	}
	if (!fu::isFile(outFile)) {
		return true;
	}
#ifdef _WIN32
	HANDLE hInFile = CreateFile(inFile.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL,
	                            OPEN_EXISTING, 0, NULL);
	HANDLE hOutFile = CreateFile(outFile.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL,
	                             OPEN_EXISTING, 0, NULL);

	if(hInFile == INVALID_HANDLE_VALUE) {
		return false;
	}
	if(hOutFile == INVALID_HANDLE_VALUE) {
		return true;
	}

	FILETIME lstInMod, lstOutMod;
	GetFileTime(hInFile, NULL, NULL, &lstInMod);
	GetFileTime(hOutFile, NULL, NULL, &lstOutMod);

	CloseHandle(hInFile);
	CloseHandle(hOutFile);

	return CompareFileTime(&lstInMod, &lstOutMod) == 1;
#else
	struct stat stIn;
	struct stat stOut;
	stat(inFile.c_str(), &stIn);
	stat(outFile.c_str(), &stOut);
	return stIn.st_mtime > stOut.st_mtime;
#endif
}

bool QtTool::runIfNeeded(const std::string& inFile, const std::string& outFile)
{
	if (needsToRun(inFile, outFile)) {

		ostringstream cmd;
		cmd << exePath_;
		if (cmdOpts_.size() > 0) {
			cmd << " " << cmdOpts_;
		}
		cmd << " -o " << outFile << " " << inFile;

#ifdef _WIN32
		const size_t bufSize = 512;
		char buf [bufSize];

		STARTUPINFO si;
		PROCESS_INFORMATION pi;

		ZeroMemory(&pi, sizeof(pi));
		ZeroMemory(&si, sizeof(si));
		si.cb = sizeof(si);
		si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
		si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
		si.hStdInput = NULL;
		si.dwFlags |= STARTF_USESTDHANDLES;

		string cmdOpts = cmd.str();
		for(size_t i=0; i<cmdOpts.size(); ++i) {
			buf[i] = cmdOpts[i];
			if (i == bufSize-1) break;
		}
		size_t i = min(size_t(bufSize-1), cmdOpts.size());
		buf[i] = '\0';

		// Start the child process.
		if( !CreateProcess(
		            NULL,			// module name
		            buf,	        // Command line
		            NULL,           // Process handle not inheritable
		            NULL,           // Thread handle not inheritable
		            TRUE,           // Set handle inheritance to TRUE
		            0,              // No creation flags
		            NULL,           // Use parent's environment block
		            NULL,           // Use parent's starting directory
		            &si,            // Pointer to STARTUPINFO structure
		            &pi )           // Pointer to PROCESS_INFORMATION structure
		  ) {
			cerr << "CreateProcess err " << GetLastError() << "\n";
			throw runtime_error("cannot start process");
		}
		WaitForSingleObject(pi.hProcess, INFINITE);

		if (!CloseHandle(pi.hProcess)) {
			cerr << "close handle process\n";
		}
		if (!CloseHandle(pi.hThread)) {
			cerr << "close handle thread\n";
		}

#else

		FILE *handle = popen(cmd.str().c_str(), "r");

		if (handle == NULL) {
			throw runtime_error("cannot start process");
		}

		char buf[64];
		size_t readn;
		while ((readn = fread(buf, 1, sizeof(buf), handle)) > 0) {
			fwrite(buf, 1, readn, stdout);
		}

		pclose(handle);

#endif

		return true;
	}
	return false;
}

string QtMocTool::exePath(const string& qtBinPath)
{
#ifdef _WIN32
	return qtBinPath + "moc.exe";
#else
	return qtBinPath + "moc";
#endif // _WIN32
}

bool QtMocTool::isFileInput(const string& inFile)
{
	if (!su::endsWith(inFile, string(".h")) &&
	        !su::endsWith(inFile, string(".hpp")) &&
	        !su::endsWith(inFile, string(".hh")) &&
	        !su::endsWith(inFile, string(".hxx"))) {
		return false;
	}

	ifstream in (inFile);
	if (!in) return false;

	string line;
	bool found = false;
	const string q_object = "Q_OBJECT";
	while(getline(in, line)) {
		if(line.find(q_object) != string::npos) {
			found = true;
			break;
		}
	}
	in.close();
	return found;
}

std::string QtMocTool::getOutFilename (const string& inFileName)
{
	string base;
	string ext;
	tie(base, ext) = fu::splitExt(inFileName);

	ostringstream oss;
	oss << "mo_" << base << ".cc";
	return oss.str();
}

string QtUicTool::exePath(const string& qtBinPath)
{
#ifdef _WIN32
	return qtBinPath + "uic.exe";
#else
	return qtBinPath + "uic";
#endif // _WIN32
}

bool QtUicTool::isFileInput(const string& inFile)
{
	if (!su::endsWith(inFile, string(".ui"))) {
		return false;
	}
	return true;
}

string QtUicTool::getOutFilename (const string& inFileName)
{
	string base;
	string ext;
	tie(base, ext) = fu::splitExt(inFileName);

	ostringstream oss;
	oss << "ui_" << base << ".h";
	return oss.str();
}

string QtRccTool::exePath(const string& qtBinPath)
{
#ifdef _WIN32
	return qtBinPath + "rcc.exe";
#else
	return qtBinPath + "rcc";
#endif // _WIN32
}

bool QtRccTool::isFileInput(const string& inFile)
{
	if (!su::endsWith(inFile, string(".qrc"))) {
		return false;
	}
	return true;
}

string QtRccTool::getOutFilename (const string& inFileName)
{
	string base;
	string ext;
	tie(base, ext) = fu::splitExt(inFileName);

	ostringstream oss;
	oss << "rc_" << base << ".cc";
	return oss.str();
}

bool QtRccTool::needsToRun(const std::string& inFile, const std::string& outFile)
{
	if (QtTool::needsToRun(inFile, outFile)) {
		return true;
	}
	bool run = false;

	string baseDir = fu::parentDir(inFile);

	ifstream in (inFile);
	string line;
	while(getline(in, line)) {
		size_t pos = line.find("<file>");
		if (pos != string::npos) {
			line = line.substr(pos + 6);
			pos = line.find("</file>");
			if (pos != string::npos) {
				string fn = line.substr(0, pos);
				if (fn.size() > 0) {
					string resFile = baseDir + fn;
					run = QtTool::needsToRun(resFile, outFile);
					if (run) break;
				}
			}
		}
	}
	in.close();

	return run;
}

<|endoftext|>


<commit_before><commit_msg>`typedef struct TextStruct`: added new field: `font2D_parent`.<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: includes.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-20 02:24:44 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include "includes.hxx"

#include "dumputils.hxx"

#include "codemaker/dependencies.hxx"
#include "codemaker/global.hxx"
#include "codemaker/typemanager.hxx"
#include "codemaker/unotype.hxx"

#include "osl/diagnose.h"
#include "rtl/string.hxx"
#include "rtl/ustring.hxx"
#include "sal/types.h"

#include <vector>

using codemaker::cppumaker::Includes;

Includes::Includes(
    TypeManager const & manager, codemaker::Dependencies const & dependencies,
    bool hpp):
    m_manager(manager), m_map(dependencies.getMap()), m_hpp(hpp),
    m_includeAny(dependencies.hasAnyDependency()), m_includeReference(false),
    m_includeSequence(dependencies.hasSequenceDependency()),
    m_includeType(dependencies.hasTypeDependency()),
    m_includeCppuMacrosHxx(false), m_includeCppuUnotypeHxx(false),
    m_includeOslDoublecheckedlockingH(false), m_includeOslMutexHxx(false),
    m_includeRtlStrbufHxx(false), m_includeRtlStringH(false),
    m_includeRtlTextencH(false), m_includeRtlUstrbufHxx(false),
    m_includeRtlUstringH(false),
    m_includeRtlUstringHxx(dependencies.hasStringDependency()),
    m_includeSalTypesH(
        dependencies.hasBooleanDependency() || dependencies.hasByteDependency()
        || dependencies.hasShortDependency()
        || dependencies.hasUnsignedShortDependency()
        || dependencies.hasLongDependency()
        || dependencies.hasUnsignedShortDependency()
        || dependencies.hasHyperDependency()
        || dependencies.hasUnsignedHyperDependency()
        || dependencies.hasCharDependency()),
    m_includeTypelibTypeclassH(false),
    m_includeTypelibTypedescriptionH(false)
{}

Includes::~Includes()
{}

void Includes::add(rtl::OString const & registryType) {
    sal_Int32 rank;
    std::vector< rtl::OString > args;
    rtl::OString type(
        codemaker::UnoType::decompose(registryType, &rank, &args));
    if (rank > 0) {
        m_includeSequence = true;
    }
    switch (codemaker::UnoType::getSort(type)) {
    case codemaker::UnoType::SORT_VOID:
        OSL_ASSERT(args.empty());
        OSL_ASSERT(false);
        break;

    case codemaker::UnoType::SORT_BOOLEAN:
    case codemaker::UnoType::SORT_BYTE:
    case codemaker::UnoType::SORT_SHORT:
    case codemaker::UnoType::SORT_UNSIGNED_SHORT:
    case codemaker::UnoType::SORT_LONG:
    case codemaker::UnoType::SORT_UNSIGNED_LONG:
    case codemaker::UnoType::SORT_HYPER:
    case codemaker::UnoType::SORT_UNSIGNED_HYPER:
    case codemaker::UnoType::SORT_CHAR:
        OSL_ASSERT(args.empty());
        m_includeSalTypesH = true;
        break;

    case codemaker::UnoType::SORT_FLOAT:
    case codemaker::UnoType::SORT_DOUBLE:
        OSL_ASSERT(args.empty());
        break;

    case codemaker::UnoType::SORT_STRING:
        OSL_ASSERT(args.empty());
        m_includeRtlUstringHxx = true;
        break;

    case codemaker::UnoType::SORT_TYPE:
        OSL_ASSERT(args.empty());
        m_includeType = true;
        break;

    case codemaker::UnoType::SORT_ANY:
        OSL_ASSERT(args.empty());
        m_includeAny = true;
        break;

    case codemaker::UnoType::SORT_COMPLEX:
        m_map.insert(
            codemaker::Dependencies::Map::value_type(
                type, codemaker::Dependencies::KIND_NO_BASE));
        {for (std::vector< rtl::OString >::iterator i(args.begin());
              i != args.end(); ++i)
        {
            add(*i);
        }}
        break;

    default:
        OSL_ASSERT(false);
        break;
    }
}

namespace {

void dumpEmptyLineBeforeFirst(FileStream & out, bool * first) {
    OSL_ASSERT(first != 0);
    if (*first) {
        out << "\n";
        *first = false;
    }
}

}

void Includes::dump(FileStream & out, rtl::OString const * companionHdl) {
    OSL_ASSERT(companionHdl == 0 || m_hpp);
    if (!m_includeReference) {
        for (codemaker::Dependencies::Map::iterator i(m_map.begin());
             i != m_map.end(); ++i)
        {
            if (isInterfaceType(i->first)) {
                m_includeReference = true;
                break;
            }
        }
    }
    out << "#ifndef _SAL_CONFIG_H_\n#include \"sal/config.h\"\n#endif\n";
    if (companionHdl) {
        out << "\n";
        dumpInclude(out, *companionHdl, false);
    }
    bool first = true;
    for (codemaker::Dependencies::Map::iterator i(m_map.begin());
         i != m_map.end(); ++i)
    {
        dumpEmptyLineBeforeFirst(out, &first);
        if (m_hpp || i->second == codemaker::Dependencies::KIND_BASE
            || !isInterfaceType(i->first))
        {
            dumpInclude(out, i->first, m_hpp);
        } else {
            bool ns = dumpNamespaceOpen(out, i->first, false);
            if (ns) {
                out << " ";
            }
            out << "class ";
            dumpTypeIdentifier(out, i->first);
            out << ";";
            if (ns) {
                out << " ";
            }
            dumpNamespaceClose(out, i->first, false);
            out << "\n";
        }
    }
    static char const * hxxExtension[2] = { "h", "hxx" };
    static char const * hxxExtensionUpper[2] = { "H", "HXX" };
    if (m_includeAny) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << "#ifndef _COM_SUN_STAR_UNO_ANY_" << hxxExtensionUpper[m_hpp]
            << "_\n#include \"com/sun/star/uno/Any." << hxxExtension[m_hpp]
            << "\"\n#endif\n";
    }
    if (m_includeReference) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << "#ifndef _COM_SUN_STAR_UNO_REFERENCE_"
            << hxxExtensionUpper[m_hpp]
            << "_\n#include \"com/sun/star/uno/Reference."
            << hxxExtension[m_hpp] << "\"\n#endif\n";
    }
    if (m_includeSequence) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << "#ifndef _COM_SUN_STAR_UNO_SEQUENCE_" << hxxExtensionUpper[m_hpp]
            << "_\n#include \"com/sun/star/uno/Sequence." << hxxExtension[m_hpp]
            << "\"\n#endif\n";
    }
    if (m_includeType) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << "#ifndef _COM_SUN_STAR_UNO_TYPE_" << hxxExtensionUpper[m_hpp]
            << "_\n#include \"com/sun/star/uno/Type." << hxxExtension[m_hpp]
            << "\"\n#endif\n";
    }
    if (m_includeCppuMacrosHxx) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << ("#ifndef _CPPU_MACROS_HXX_\n"
                "#include \"cppu/macros.hxx\"\n#endif\n");
    }
    if (m_includeCppuUnotypeHxx) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << ("#ifndef INCLUDED_CPPU_UNOTYPE_HXX\n"
                "#include \"cppu/unotype.hxx\"\n#endif\n");
    }
    if (m_includeOslDoublecheckedlockingH) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << ("#ifndef INCLUDED_OSL_DOUBLECHECKEDLOCKING_H\n"
                "#include \"osl/doublecheckedlocking.h\"\n#endif\n");
    }
    if (m_includeOslMutexHxx) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << "#ifndef _OSL_MUTEX_HXX_\n#include \"osl/mutex.hxx\"\n#endif\n";
    }
    if (m_includeRtlStrbufHxx) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << ("#ifndef _RTL_STRBUF_HXX_\n"
                "#include \"rtl/strbuf.hxx\"\n#endif\n");
    }
    if (m_includeRtlStringH) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << "#ifndef _RTL_STRING_H_\n#include \"rtl/string.h\"\n#endif\n";
    }
    if (m_includeRtlTextencH) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << "#ifndef _RTL_TEXTENC_H\n#include \"rtl/textenc.h\"\n#endif\n";
    }
    if (m_includeRtlUstrbufHxx) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << ("#ifndef _RTL_USTRBUF_HXX_\n"
                "#include \"rtl/ustrbuf.hxx\"\n#endif\n");
    }
    if (m_includeRtlUstringH) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << "#ifndef _RTL_USTRING_H_\n#include \"rtl/ustring.h\"\n#endif\n";
    }
    if (m_includeRtlUstringHxx) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << ("#ifndef _RTL_USTRING_HXX_\n"
                "#include \"rtl/ustring.hxx\"\n#endif\n");
    }
    if (m_includeSalTypesH) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << "#ifndef _SAL_TYPES_H_\n#include \"sal/types.h\"\n#endif\n";
    }
    if (m_includeTypelibTypeclassH) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << ("#ifndef _TYPELIB_TYPECLASS_H_\n"
                "#include \"typelib/typeclass.h\"\n#endif\n");
    }
    if (m_includeTypelibTypedescriptionH) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << ("#ifndef _TYPELIB_TYPEDESCRIPTION_H_\n"
                "#include \"typelib/typedescription.h\"\n#endif\n");
    }
}

void Includes::dumpInclude(
    FileStream & out, rtl::OString const & registryType, bool hpp,
    rtl::OString const & suffix)
{
    static char const * extension[2] = { "hdl", "hpp" };
    static char const * extensionUpper[2] = { "HDL", "HPP" };
    out << "#ifndef _" << registryType.replace('/', '_').toAsciiUpperCase();
    if (suffix.getLength() > 0) {
        out << "_" << suffix.toAsciiUpperCase();
    }
    out << "_" <<  extensionUpper[hpp] << "_\n#include \""
        << registryType;
    if (suffix.getLength() > 0) {
        out << "/" << suffix;
    }
    out << "." << extension[hpp] << "\"\n#endif\n";
}

bool Includes::isInterfaceType(rtl::OString const & registryType) const {
    return m_manager.getTypeClass(registryType) == RT_TYPE_INTERFACE;
}
<commit_msg>INTEGRATION: CWS pchfix02 (1.6.8); FILE MERGED 2006/09/01 17:19:22 kaib 1.6.8.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: includes.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 03:37:21 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_codemaker.hxx"

#include "includes.hxx"

#include "dumputils.hxx"

#include "codemaker/dependencies.hxx"
#include "codemaker/global.hxx"
#include "codemaker/typemanager.hxx"
#include "codemaker/unotype.hxx"

#include "osl/diagnose.h"
#include "rtl/string.hxx"
#include "rtl/ustring.hxx"
#include "sal/types.h"

#include <vector>

using codemaker::cppumaker::Includes;

Includes::Includes(
    TypeManager const & manager, codemaker::Dependencies const & dependencies,
    bool hpp):
    m_manager(manager), m_map(dependencies.getMap()), m_hpp(hpp),
    m_includeAny(dependencies.hasAnyDependency()), m_includeReference(false),
    m_includeSequence(dependencies.hasSequenceDependency()),
    m_includeType(dependencies.hasTypeDependency()),
    m_includeCppuMacrosHxx(false), m_includeCppuUnotypeHxx(false),
    m_includeOslDoublecheckedlockingH(false), m_includeOslMutexHxx(false),
    m_includeRtlStrbufHxx(false), m_includeRtlStringH(false),
    m_includeRtlTextencH(false), m_includeRtlUstrbufHxx(false),
    m_includeRtlUstringH(false),
    m_includeRtlUstringHxx(dependencies.hasStringDependency()),
    m_includeSalTypesH(
        dependencies.hasBooleanDependency() || dependencies.hasByteDependency()
        || dependencies.hasShortDependency()
        || dependencies.hasUnsignedShortDependency()
        || dependencies.hasLongDependency()
        || dependencies.hasUnsignedShortDependency()
        || dependencies.hasHyperDependency()
        || dependencies.hasUnsignedHyperDependency()
        || dependencies.hasCharDependency()),
    m_includeTypelibTypeclassH(false),
    m_includeTypelibTypedescriptionH(false)
{}

Includes::~Includes()
{}

void Includes::add(rtl::OString const & registryType) {
    sal_Int32 rank;
    std::vector< rtl::OString > args;
    rtl::OString type(
        codemaker::UnoType::decompose(registryType, &rank, &args));
    if (rank > 0) {
        m_includeSequence = true;
    }
    switch (codemaker::UnoType::getSort(type)) {
    case codemaker::UnoType::SORT_VOID:
        OSL_ASSERT(args.empty());
        OSL_ASSERT(false);
        break;

    case codemaker::UnoType::SORT_BOOLEAN:
    case codemaker::UnoType::SORT_BYTE:
    case codemaker::UnoType::SORT_SHORT:
    case codemaker::UnoType::SORT_UNSIGNED_SHORT:
    case codemaker::UnoType::SORT_LONG:
    case codemaker::UnoType::SORT_UNSIGNED_LONG:
    case codemaker::UnoType::SORT_HYPER:
    case codemaker::UnoType::SORT_UNSIGNED_HYPER:
    case codemaker::UnoType::SORT_CHAR:
        OSL_ASSERT(args.empty());
        m_includeSalTypesH = true;
        break;

    case codemaker::UnoType::SORT_FLOAT:
    case codemaker::UnoType::SORT_DOUBLE:
        OSL_ASSERT(args.empty());
        break;

    case codemaker::UnoType::SORT_STRING:
        OSL_ASSERT(args.empty());
        m_includeRtlUstringHxx = true;
        break;

    case codemaker::UnoType::SORT_TYPE:
        OSL_ASSERT(args.empty());
        m_includeType = true;
        break;

    case codemaker::UnoType::SORT_ANY:
        OSL_ASSERT(args.empty());
        m_includeAny = true;
        break;

    case codemaker::UnoType::SORT_COMPLEX:
        m_map.insert(
            codemaker::Dependencies::Map::value_type(
                type, codemaker::Dependencies::KIND_NO_BASE));
        {for (std::vector< rtl::OString >::iterator i(args.begin());
              i != args.end(); ++i)
        {
            add(*i);
        }}
        break;

    default:
        OSL_ASSERT(false);
        break;
    }
}

namespace {

void dumpEmptyLineBeforeFirst(FileStream & out, bool * first) {
    OSL_ASSERT(first != 0);
    if (*first) {
        out << "\n";
        *first = false;
    }
}

}

void Includes::dump(FileStream & out, rtl::OString const * companionHdl) {
    OSL_ASSERT(companionHdl == 0 || m_hpp);
    if (!m_includeReference) {
        for (codemaker::Dependencies::Map::iterator i(m_map.begin());
             i != m_map.end(); ++i)
        {
            if (isInterfaceType(i->first)) {
                m_includeReference = true;
                break;
            }
        }
    }
    out << "#ifndef _SAL_CONFIG_H_\n#include \"sal/config.h\"\n#endif\n";
    if (companionHdl) {
        out << "\n";
        dumpInclude(out, *companionHdl, false);
    }
    bool first = true;
    for (codemaker::Dependencies::Map::iterator i(m_map.begin());
         i != m_map.end(); ++i)
    {
        dumpEmptyLineBeforeFirst(out, &first);
        if (m_hpp || i->second == codemaker::Dependencies::KIND_BASE
            || !isInterfaceType(i->first))
        {
            dumpInclude(out, i->first, m_hpp);
        } else {
            bool ns = dumpNamespaceOpen(out, i->first, false);
            if (ns) {
                out << " ";
            }
            out << "class ";
            dumpTypeIdentifier(out, i->first);
            out << ";";
            if (ns) {
                out << " ";
            }
            dumpNamespaceClose(out, i->first, false);
            out << "\n";
        }
    }
    static char const * hxxExtension[2] = { "h", "hxx" };
    static char const * hxxExtensionUpper[2] = { "H", "HXX" };
    if (m_includeAny) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << "#ifndef _COM_SUN_STAR_UNO_ANY_" << hxxExtensionUpper[m_hpp]
            << "_\n#include \"com/sun/star/uno/Any." << hxxExtension[m_hpp]
            << "\"\n#endif\n";
    }
    if (m_includeReference) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << "#ifndef _COM_SUN_STAR_UNO_REFERENCE_"
            << hxxExtensionUpper[m_hpp]
            << "_\n#include \"com/sun/star/uno/Reference."
            << hxxExtension[m_hpp] << "\"\n#endif\n";
    }
    if (m_includeSequence) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << "#ifndef _COM_SUN_STAR_UNO_SEQUENCE_" << hxxExtensionUpper[m_hpp]
            << "_\n#include \"com/sun/star/uno/Sequence." << hxxExtension[m_hpp]
            << "\"\n#endif\n";
    }
    if (m_includeType) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << "#ifndef _COM_SUN_STAR_UNO_TYPE_" << hxxExtensionUpper[m_hpp]
            << "_\n#include \"com/sun/star/uno/Type." << hxxExtension[m_hpp]
            << "\"\n#endif\n";
    }
    if (m_includeCppuMacrosHxx) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << ("#ifndef _CPPU_MACROS_HXX_\n"
                "#include \"cppu/macros.hxx\"\n#endif\n");
    }
    if (m_includeCppuUnotypeHxx) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << ("#ifndef INCLUDED_CPPU_UNOTYPE_HXX\n"
                "#include \"cppu/unotype.hxx\"\n#endif\n");
    }
    if (m_includeOslDoublecheckedlockingH) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << ("#ifndef INCLUDED_OSL_DOUBLECHECKEDLOCKING_H\n"
                "#include \"osl/doublecheckedlocking.h\"\n#endif\n");
    }
    if (m_includeOslMutexHxx) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << "#ifndef _OSL_MUTEX_HXX_\n#include \"osl/mutex.hxx\"\n#endif\n";
    }
    if (m_includeRtlStrbufHxx) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << ("#ifndef _RTL_STRBUF_HXX_\n"
                "#include \"rtl/strbuf.hxx\"\n#endif\n");
    }
    if (m_includeRtlStringH) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << "#ifndef _RTL_STRING_H_\n#include \"rtl/string.h\"\n#endif\n";
    }
    if (m_includeRtlTextencH) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << "#ifndef _RTL_TEXTENC_H\n#include \"rtl/textenc.h\"\n#endif\n";
    }
    if (m_includeRtlUstrbufHxx) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << ("#ifndef _RTL_USTRBUF_HXX_\n"
                "#include \"rtl/ustrbuf.hxx\"\n#endif\n");
    }
    if (m_includeRtlUstringH) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << "#ifndef _RTL_USTRING_H_\n#include \"rtl/ustring.h\"\n#endif\n";
    }
    if (m_includeRtlUstringHxx) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << ("#ifndef _RTL_USTRING_HXX_\n"
                "#include \"rtl/ustring.hxx\"\n#endif\n");
    }
    if (m_includeSalTypesH) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << "#ifndef _SAL_TYPES_H_\n#include \"sal/types.h\"\n#endif\n";
    }
    if (m_includeTypelibTypeclassH) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << ("#ifndef _TYPELIB_TYPECLASS_H_\n"
                "#include \"typelib/typeclass.h\"\n#endif\n");
    }
    if (m_includeTypelibTypedescriptionH) {
        dumpEmptyLineBeforeFirst(out, &first);
        out << ("#ifndef _TYPELIB_TYPEDESCRIPTION_H_\n"
                "#include \"typelib/typedescription.h\"\n#endif\n");
    }
}

void Includes::dumpInclude(
    FileStream & out, rtl::OString const & registryType, bool hpp,
    rtl::OString const & suffix)
{
    static char const * extension[2] = { "hdl", "hpp" };
    static char const * extensionUpper[2] = { "HDL", "HPP" };
    out << "#ifndef _" << registryType.replace('/', '_').toAsciiUpperCase();
    if (suffix.getLength() > 0) {
        out << "_" << suffix.toAsciiUpperCase();
    }
    out << "_" <<  extensionUpper[hpp] << "_\n#include \""
        << registryType;
    if (suffix.getLength() > 0) {
        out << "/" << suffix;
    }
    out << "." << extension[hpp] << "\"\n#endif\n";
}

bool Includes::isInterfaceType(rtl::OString const & registryType) const {
    return m_manager.getTypeClass(registryType) == RT_TYPE_INTERFACE;
}
<|endoftext|>


<commit_before>/// @author Andrew Hundt <athundt@gmail.com>

#ifndef _VREP_VF_CONTROLLER_
#define _VREP_VF_CONTROLLER_

#include <string>
#include <tuple>
#include <boost/format.hpp>
#include <Eigen/Core>
#include <Eigen/Geometry>

#include <sawConstraintController/mtsVFController.h>

#include "grl/cisst/GrlVFController.hpp"
#include "grl/vrep/Vrep.hpp"
#include "grl/vrep/VrepRobotArmDriver.hpp"
#include "grl/vrep/Eigen.hpp"

#include <boost/lexical_cast.hpp>
#include <boost/range/algorithm/copy.hpp>

namespace grl {

/// This handles a whole vrep path object
class DesiredKinematicsPath {

    enum  VrepVFControllerParamsIndex {
        DesiredKinematicsObjectName
    };

    typedef std::tuple<
            std::string // DesiredKinematicsObjectName
        > VrepVFControllerParams;

    void construct()
    {

    }

    Eigen::Affine3d getDesiredPose(){

    }
};

/// This handles a specific vrep pose
class DesiredKinematicsObject {

    enum  VrepVFControllerParamsIndex {
        DesiredKinematicsObjectName
    };

    std::tuple<
            std::string // DesiredKinematicsObjectName
        > Params;

    void construct()
    {

    }

    Eigen::Affine3d getDesiredPose(){

    }
};

/// @todo verify Robotiiwa is the correct base, and RobotMillTipTarget is the right target, because if the transform doesn't match the one in the jacobian the algorithm will break
//template<typename DesiredKinematics = DesiredKinematicsObject>
class VrepInverseKinematicsController : public grl::InverseKinematicsController
{
public:
    typedef InverseKinematicsController parent_type;

    //using parent_type::currentKinematicsStateP_;
    //using parent_type::parent_type::InitializeKinematicsState;

    enum  VrepVFControllerParamsIndex {
        DesiredKinematicsObjectName,
        IKGroupName
    };

    typedef std::tuple<
             std::string // DesiredKinematicsObjectName
            ,std::string // IKGroupName
        > Params;

    static Params defaultParams()
    {
       return std::make_tuple("RobotMillTipTarget","IK_Group1_iiwa");
    }

    /// @todo need to call parent constructor:
        /*! Constructor
    */
    VrepInverseKinematicsController(size_t num_joints = 7, mtsVFBase::CONTROLLERMODE cm = mtsVFBase::CONTROLLERMODE::JPOS):
     InverseKinematicsController(num_joints,cm)
    {
    }

    void construct(Params params = defaultParams()){
        // get kinematics group name
        // get number of joints
        VrepRobotArmDriverP_ = std::make_shared<vrep::VrepRobotArmDriver>();
        VrepRobotArmDriverP_->construct();

        ikGroupHandle_ = simGetIkGroupHandle(std::get<IKGroupName>(params).c_str());
        simSetExplicitHandling(ikGroupHandle_,1); // enable explicit handling for the ik

        this->currentKinematicsStateP_->Name = std::get<IKGroupName>(params);

        this->desiredKinematicsStateP_->Name = std::get<DesiredKinematicsObjectName>(params);

        /// @todo set desiredKinematicsStateP name, INITIALIZE ALL MEMBER OBJECTS, & SET NAMES
        //
        positionLimitsName = std::get<IKGroupName>(params)+"_PositionLimits";
        this->jointPositionLimitsVFP_->Name = positionLimitsName;

        velocityLimitsName = std::get<IKGroupName>(params)+"_VelocityLimits";
        this->jointVelocityLimitsVFP_->Name = velocityLimitsName;

//            /// This will hold the Jacobian
//    std::unique_ptr<prmKinematicsState> currentKinematicsStateP_;
//
//    /// This will hold the xyz position and the rotation of where I want to go
//    std::unique_ptr<prmKinematicsState> desiredKinematicsStateP_;
//
//    // want to follow a goal position
//    /// @todo will want to use an addVFFollow member function once it is added in
//    std::unique_ptr<mtsVFDataBase> followVFP_;
//
//    /// need velocity limits for the joints
//    std::unique_ptr<mtsVFDataJointLimits> jointVelocityLimitsVFP_;
//    /// joints cannot go to certain position
//    std::unique_ptr<mtsVFDataJointLimits> jointPositionLimitsVFP_;

        /// @todo verify object lifetimes
        //parent_type::parent_type::InitializeKinematicsState(this->currentKinematicsStateP_)

            // for each virtual fixture need names and number of rows

        /// @todo read objective rows from vrep

        // Initialize Variables for update
        //jointHandles_ = VrepRobotArmDriverP_->getJointHandles();
        //int numJoints =jointHandles_.size();

#ifdef HANDLE_ROTATION
        /// @todo objectiveRows seems to currently be a 3 vector, may eventually want a rotation and translation, perhaps with quaternion rotation
        followVFP_->ObjectiveRows = 6;
#else
        followVFP_->ObjectiveRows = 3;
#endif
        // set the names once for each object, only once
        followVFP_->KinNames.push_back(currentKinematicsStateP_->Name);
        followVFP_->KinNames.push_back(desiredKinematicsStateP_->Name);

        AddVFFollowPath(*followVFP_);

        /// @todo set vrep explicit handling of IK here, plus unset in destructor of this object
    }

    /// check out sawConstraintController
    void updateKinematics(){

        // Initialize Variables for update
        jointHandles_ = VrepRobotArmDriverP_->getJointHandles();
        int numJoints =jointHandles_.size();
        std::vector<float> ikCalculatedJointValues(numJoints,0);
        VrepRobotArmDriverP_->getState(currentArmState_);

        /// @todo get target position, probably relative to base
        const auto& handleParams = VrepRobotArmDriverP_->getVrepHandleParams();

        auto target = std::get<vrep::VrepRobotArmDriver::RobotTargetName>(handleParams);
        auto tip = std::get<vrep::VrepRobotArmDriver::RobotTipName>(handleParams);

        // save the current tip to target transform
        Eigen::Affine3d tipToTarget =getObjectTransform( target,tip);

        // set the current transform to the identity so simCheckIkGroup won't fail
        // @see http://www.forum.coppeliarobotics.com/viewtopic.php?f=9&t=3967
        // for details about this issue.
        setObjectTransform( target,tip,Eigen::Affine3d::Identity());

        // debug:
        // std::cout << "TipToTargetTransform:\n" << tipToTarget.matrix() << "\n";

        /// Run inverse kinematics, but all we really want is the jacobian
        /// @todo find version that only returns jacobian
        /// @see http://www.coppeliarobotics.com/helpFiles/en/apiFunctions.htm#simCheckIkGroup
        auto ikcalcResult =
        simCheckIkGroup(ikGroupHandle_
                       ,numJoints
                       ,&jointHandles_[0]
                       ,&ikCalculatedJointValues[0]
                       ,NULL /// @todo do we need to use these options?
                       );
        /// @see http://www.coppeliarobotics.com/helpFiles/en/apiConstants.htm#ikCalculationResults
        if(ikcalcResult!=sim_ikresult_success && ikcalcResult != sim_ikresult_not_performed)
        {
            BOOST_LOG_TRIVIAL(error) << "VrepInverseKinematicsController: didn't run inverse kinematics";
            return;
        }

        setObjectTransform( target,tip,tipToTarget);

        // Get the Jacobian
        int jacobianSize[2];
        float* jacobian=simGetIkGroupMatrix(ikGroupHandle_,0,jacobianSize);
        /// @todo FIX HACK jacobianSize include orientation component, should be 7x6 instead of 7x3

#ifndef HANDLE_ROTATION
        jacobianSize[1] = 3;
#endif

        /// The row/column major order is swapped between cisst and VREP!
        this->currentKinematicsStateP_->Jacobian.SetSize(jacobianSize[1],jacobianSize[0]);

        // Transfer the Jacobian to cisst

        // jacobianSize[0] represents the row count of the Jacobian
        // (i.e. the number of equations or the number of joints involved
        // in the IK resolution of the given kinematic chain)
        // Joints appear from tip to base.

        // jacobianSize[1] represents the column count of the Jacobian
        // (i.e. the number of constraints, e.g. x,y,z,alpha,beta,gamma,jointDependency)

        // The Jacobian data is ordered row-wise, i.e.:
        // [row0,col0],[row1,col0],..,[rowN,col0],[row0,col1],[row1,col1],etc.

        std::string str;
        str+="\n";
        for (int i=0;i<jacobianSize[0];i++)
        {
            for (int j=0;j<jacobianSize[1];j++)
            {
                str+=boost::str(boost::format("%.1e") % jacobian[static_cast<int>(j*jacobianSize[0]+i)]);
                if (j<jacobianSize[1]-1)
                    str+=", ";
                float currentValue = jacobian[static_cast<int>(j*jacobianSize[0]+i)];

                /// The row/column major order is swapped between cisst and VREP!
                this->currentKinematicsStateP_->Jacobian[j][jacobianSize[0]-i-1] = currentValue;
            }
            str+="\n";
        }
        BOOST_LOG_TRIVIAL(trace) << str;

        ///////////////////////////////////////////////////////////
        /// @todo Set Current Joint State

        // currentKinematicsStateP_->JointState = ...
        // prmJointState* JointState;

        ///////////////////////////////////////////////////////////
        // Copy Joint Interval, the range of motion for each joint

        // lower limits
        auto & llim = std::get<vrep::VrepRobotArmDriver::JointLowerPositionLimit>(currentArmState_);
        std::vector<double> llimits(llim.begin(),llim.end());
        jointPositionLimitsVFP_->LowerLimits = vctDoubleVec(llimits.size(),&llimits[0]);

        // upper limits
        auto & ulim = std::get<vrep::VrepRobotArmDriver::JointUpperPositionLimit>(currentArmState_);
        std::vector<double> ulimits(ulim.begin(),ulim.end());
        jointPositionLimitsVFP_->UpperLimits = vctDoubleVec(ulimits.size(),&ulimits[0]);

        Eigen::Affine3d currentEndEffectorPose =
        getObjectTransform(
                             std::get<vrep::VrepRobotArmDriver::RobotTipName>(handleParams)
                            ,std::get<vrep::VrepRobotArmDriver::RobotTargetBaseName>(handleParams)
                          );
        auto  currentEigenT = currentEndEffectorPose.translation();
        auto& currentCisstT = currentKinematicsStateP_->Frame.Translation();
        currentCisstT[0] = currentEigenT(0);
        currentCisstT[1] = currentEigenT(1);
        currentCisstT[2] = currentEigenT(2);
#ifdef HANDLE_ROTATION
        Eigen::Map<Eigen::Matrix<double,3,3,Eigen::RowMajor>> ccr(currentKinematicsStateP_->Frame.Rotation().Pointer());
        ccr = currentEndEffectorPose.rotation();
#endif // HANDLE_ROTATION
        /// @todo set rotation component of current position

        Eigen::Affine3d desiredEndEffectorPose =
        getObjectTransform(
                             std::get<vrep::VrepRobotArmDriver::RobotTargetName>(handleParams)
                            ,std::get<vrep::VrepRobotArmDriver::RobotTargetBaseName>(handleParams)
                          );
        auto  desiredEigenT = desiredEndEffectorPose.translation();
        auto& desiredCisstT = desiredKinematicsStateP_->Frame.Translation();
        desiredCisstT[0] = desiredEigenT(0);
        desiredCisstT[1] = desiredEigenT(1);
        desiredCisstT[2] = desiredEigenT(2);
#ifdef HANDLE_ROTATION
        Eigen::Map<Eigen::Matrix<double,3,3,Eigen::RowMajor>> dcr(desiredKinematicsStateP_->Frame.Rotation().Pointer());
        dcr = desiredEndEffectorPose.rotation();
#endif // HANDLE_ROTATION
        /// @todo set rotation component of desired position

        // for debugging, the translation between the current and desired position in cartesian coordinates
        auto inputDesired_dx = desiredCisstT - currentCisstT;

        SetKinematics(*currentKinematicsStateP_);  // replaced by name of object
        // fill these out in the desiredKinematicsStateP_
        //RotationType RotationMember; // vcRot3
        //TranslationType TranslationMember; // vct3

        SetKinematics(*desiredKinematicsStateP_); // replaced by name of object
        // call setKinematics with the new kinematics
        // sawconstraintcontroller has kinematicsState
        // set the jacobian here

        //////////////////////
        /// @todo move code below here back under run_one updateKinematics() call

       /// @todo need to provide tick time in double seconds and get from vrep API call
       UpdateOptimizer(0.01);

       vctDoubleVec jointAngles_dt;
       auto returncode = Solve(jointAngles_dt);

       /// @todo check the return code, if it doesn't have a result, use the VREP version as a fallback and report an error.
       if(returncode != nmrConstraintOptimizer::NMR_OK) BOOST_THROW_EXCEPTION(std::runtime_error("VrepInverseKinematicsController: constrained optimization error, please investigate"));

       /// @todo: rethink where/when/how to send command for the joint angles. Return to LUA? Set Directly? Distribute via vrep send message command?
        //std::string str;
        str = "";
       for (std::size_t i=0 ; i < jointHandles_.size() ; i++)
       {
          float currentAngle;
          auto ret = simGetJointPosition(jointHandles_[i],&currentAngle);
          BOOST_VERIFY(ret!=-1);
          float futureAngle = currentAngle + jointAngles_dt[i];
          //simSetJointTargetPosition(jointHandles_[i],jointAngles_dt[i]);
          //simSetJointTargetPosition(jointHandles_[i],futureAngle);
          simSetJointPosition(jointHandles_[i],futureAngle);
                str+=boost::lexical_cast<std::string>(jointAngles_dt[i]);
                if (i<jointHandles_.size()-1)
                    str+=", ";
       }
        BOOST_LOG_TRIVIAL(trace) << "jointAngles_dt: "<< str;

        auto optimizerCalculated_dx = this->currentKinematicsStateP_->Jacobian * jointAngles_dt;

        BOOST_LOG_TRIVIAL(trace) << "desired dx: " << inputDesired_dx << " optimizer Calculated dx: " << optimizerCalculated_dx;
    }

    /// may not need this it is in the base class
    /// blocking call, call in separate thread, just allocates memory
    void run_one(){
       updateKinematics();

    }

    /// may not need this it is in the base class
    /// this will have output
    /// blocking call, call in separate thread, just allocates memory
    /// this runs the actual optimization algorithm
    void solve(){

    }

    std::vector<int> jointHandles_; ///< @todo move this item back into VrepRobotArmDriver
    int ikGroupHandle_;
    std::shared_ptr<vrep::VrepRobotArmDriver> VrepRobotArmDriverP_;
    vrep::VrepRobotArmDriver::State currentArmState_;
    std::string positionLimitsName;
    std::string velocityLimitsName;
};

} // namespace grl

#endif<commit_msg>vrep VFController.hpp eigen cisst rotation conversion now in ColMajor format<commit_after>/// @author Andrew Hundt <athundt@gmail.com>

#ifndef _VREP_VF_CONTROLLER_
#define _VREP_VF_CONTROLLER_

#include <string>
#include <tuple>
#include <boost/format.hpp>
#include <Eigen/Core>
#include <Eigen/Geometry>

#include <sawConstraintController/mtsVFController.h>

#include "grl/cisst/GrlVFController.hpp"
#include "grl/vrep/Vrep.hpp"
#include "grl/vrep/VrepRobotArmDriver.hpp"
#include "grl/vrep/Eigen.hpp"

#include <boost/lexical_cast.hpp>
#include <boost/range/algorithm/copy.hpp>

namespace grl {

/// This handles a whole vrep path object
class DesiredKinematicsPath {

    enum  VrepVFControllerParamsIndex {
        DesiredKinematicsObjectName
    };

    typedef std::tuple<
            std::string // DesiredKinematicsObjectName
        > VrepVFControllerParams;

    void construct()
    {

    }

    Eigen::Affine3d getDesiredPose(){

    }
};

/// This handles a specific vrep pose
class DesiredKinematicsObject {

    enum  VrepVFControllerParamsIndex {
        DesiredKinematicsObjectName
    };

    std::tuple<
            std::string // DesiredKinematicsObjectName
        > Params;

    void construct()
    {

    }

    Eigen::Affine3d getDesiredPose(){

    }
};

/// @todo verify Robotiiwa is the correct base, and RobotMillTipTarget is the right target, because if the transform doesn't match the one in the jacobian the algorithm will break
//template<typename DesiredKinematics = DesiredKinematicsObject>
class VrepInverseKinematicsController : public grl::InverseKinematicsController
{
public:
    typedef InverseKinematicsController parent_type;

    //using parent_type::currentKinematicsStateP_;
    //using parent_type::parent_type::InitializeKinematicsState;

    enum  VrepVFControllerParamsIndex {
        DesiredKinematicsObjectName,
        IKGroupName
    };

    typedef std::tuple<
             std::string // DesiredKinematicsObjectName
            ,std::string // IKGroupName
        > Params;

    static Params defaultParams()
    {
       return std::make_tuple("RobotMillTipTarget","IK_Group1_iiwa");
    }

    /// @todo need to call parent constructor:
        /*! Constructor
    */
    VrepInverseKinematicsController(size_t num_joints = 7, mtsVFBase::CONTROLLERMODE cm = mtsVFBase::CONTROLLERMODE::JPOS):
     InverseKinematicsController(num_joints,cm)
    {
    }

    void construct(Params params = defaultParams()){
        // get kinematics group name
        // get number of joints
        VrepRobotArmDriverP_ = std::make_shared<vrep::VrepRobotArmDriver>();
        VrepRobotArmDriverP_->construct();

        ikGroupHandle_ = simGetIkGroupHandle(std::get<IKGroupName>(params).c_str());
        simSetExplicitHandling(ikGroupHandle_,1); // enable explicit handling for the ik

        this->currentKinematicsStateP_->Name = std::get<IKGroupName>(params);

        this->desiredKinematicsStateP_->Name = std::get<DesiredKinematicsObjectName>(params);

        /// @todo set desiredKinematicsStateP name, INITIALIZE ALL MEMBER OBJECTS, & SET NAMES
        //
        positionLimitsName = std::get<IKGroupName>(params)+"_PositionLimits";
        this->jointPositionLimitsVFP_->Name = positionLimitsName;

        velocityLimitsName = std::get<IKGroupName>(params)+"_VelocityLimits";
        this->jointVelocityLimitsVFP_->Name = velocityLimitsName;

//            /// This will hold the Jacobian
//    std::unique_ptr<prmKinematicsState> currentKinematicsStateP_;
//
//    /// This will hold the xyz position and the rotation of where I want to go
//    std::unique_ptr<prmKinematicsState> desiredKinematicsStateP_;
//
//    // want to follow a goal position
//    /// @todo will want to use an addVFFollow member function once it is added in
//    std::unique_ptr<mtsVFDataBase> followVFP_;
//
//    /// need velocity limits for the joints
//    std::unique_ptr<mtsVFDataJointLimits> jointVelocityLimitsVFP_;
//    /// joints cannot go to certain position
//    std::unique_ptr<mtsVFDataJointLimits> jointPositionLimitsVFP_;

        /// @todo verify object lifetimes
        //parent_type::parent_type::InitializeKinematicsState(this->currentKinematicsStateP_)

            // for each virtual fixture need names and number of rows

        /// @todo read objective rows from vrep

        // Initialize Variables for update
        //jointHandles_ = VrepRobotArmDriverP_->getJointHandles();
        //int numJoints =jointHandles_.size();

#ifdef HANDLE_ROTATION
        /// @todo objectiveRows seems to currently be a 3 vector, may eventually want a rotation and translation, perhaps with quaternion rotation
        followVFP_->ObjectiveRows = 6;
#else
        followVFP_->ObjectiveRows = 3;
#endif
        // set the names once for each object, only once
        followVFP_->KinNames.push_back(currentKinematicsStateP_->Name);
        followVFP_->KinNames.push_back(desiredKinematicsStateP_->Name);

        AddVFFollowPath(*followVFP_);

        /// @todo set vrep explicit handling of IK here, plus unset in destructor of this object
    }

    /// check out sawConstraintController
    void updateKinematics(){

        // Initialize Variables for update
        jointHandles_ = VrepRobotArmDriverP_->getJointHandles();
        int numJoints =jointHandles_.size();
        std::vector<float> ikCalculatedJointValues(numJoints,0);
        VrepRobotArmDriverP_->getState(currentArmState_);

        /// @todo get target position, probably relative to base
        const auto& handleParams = VrepRobotArmDriverP_->getVrepHandleParams();

        auto target = std::get<vrep::VrepRobotArmDriver::RobotTargetName>(handleParams);
        auto tip = std::get<vrep::VrepRobotArmDriver::RobotTipName>(handleParams);

        // save the current tip to target transform
        Eigen::Affine3d tipToTarget =getObjectTransform( target,tip);

        // set the current transform to the identity so simCheckIkGroup won't fail
        // @see http://www.forum.coppeliarobotics.com/viewtopic.php?f=9&t=3967
        // for details about this issue.
        setObjectTransform( target,tip,Eigen::Affine3d::Identity());

        // debug:
        // std::cout << "TipToTargetTransform:\n" << tipToTarget.matrix() << "\n";

        /// Run inverse kinematics, but all we really want is the jacobian
        /// @todo find version that only returns jacobian
        /// @see http://www.coppeliarobotics.com/helpFiles/en/apiFunctions.htm#simCheckIkGroup
        auto ikcalcResult =
        simCheckIkGroup(ikGroupHandle_
                       ,numJoints
                       ,&jointHandles_[0]
                       ,&ikCalculatedJointValues[0]
                       ,NULL /// @todo do we need to use these options?
                       );
        /// @see http://www.coppeliarobotics.com/helpFiles/en/apiConstants.htm#ikCalculationResults
        if(ikcalcResult!=sim_ikresult_success && ikcalcResult != sim_ikresult_not_performed)
        {
            BOOST_LOG_TRIVIAL(error) << "VrepInverseKinematicsController: didn't run inverse kinematics";
            return;
        }

        setObjectTransform( target,tip,tipToTarget);

        // Get the Jacobian
        int jacobianSize[2];
        float* jacobian=simGetIkGroupMatrix(ikGroupHandle_,0,jacobianSize);
        /// @todo FIX HACK jacobianSize include orientation component, should be 7x6 instead of 7x3

#ifndef HANDLE_ROTATION
        jacobianSize[1] = 3;
#endif

        /// The row/column major order is swapped between cisst and VREP!
        this->currentKinematicsStateP_->Jacobian.SetSize(jacobianSize[1],jacobianSize[0]);

        // Transfer the Jacobian to cisst

        // jacobianSize[0] represents the row count of the Jacobian
        // (i.e. the number of equations or the number of joints involved
        // in the IK resolution of the given kinematic chain)
        // Joints appear from tip to base.

        // jacobianSize[1] represents the column count of the Jacobian
        // (i.e. the number of constraints, e.g. x,y,z,alpha,beta,gamma,jointDependency)

        // The Jacobian data is ordered row-wise, i.e.:
        // [row0,col0],[row1,col0],..,[rowN,col0],[row0,col1],[row1,col1],etc.

        std::string str;
        str+="\n";
        for (int i=0;i<jacobianSize[0];i++)
        {
            for (int j=0;j<jacobianSize[1];j++)
            {
                str+=boost::str(boost::format("%.1e") % jacobian[static_cast<int>(j*jacobianSize[0]+i)]);
                if (j<jacobianSize[1]-1)
                    str+=", ";
                float currentValue = jacobian[static_cast<int>(j*jacobianSize[0]+i)];

                /// The row/column major order is swapped between cisst and VREP!
                this->currentKinematicsStateP_->Jacobian[j][jacobianSize[0]-i-1] = currentValue;
            }
            str+="\n";
        }
        BOOST_LOG_TRIVIAL(trace) << str;

        ///////////////////////////////////////////////////////////
        /// @todo Set Current Joint State

        // currentKinematicsStateP_->JointState = ...
        // prmJointState* JointState;

        ///////////////////////////////////////////////////////////
        // Copy Joint Interval, the range of motion for each joint

        // lower limits
        auto & llim = std::get<vrep::VrepRobotArmDriver::JointLowerPositionLimit>(currentArmState_);
        std::vector<double> llimits(llim.begin(),llim.end());
        jointPositionLimitsVFP_->LowerLimits = vctDoubleVec(llimits.size(),&llimits[0]);

        // upper limits
        auto & ulim = std::get<vrep::VrepRobotArmDriver::JointUpperPositionLimit>(currentArmState_);
        std::vector<double> ulimits(ulim.begin(),ulim.end());
        jointPositionLimitsVFP_->UpperLimits = vctDoubleVec(ulimits.size(),&ulimits[0]);

        Eigen::Affine3d currentEndEffectorPose =
        getObjectTransform(
                             std::get<vrep::VrepRobotArmDriver::RobotTipName>(handleParams)
                            ,std::get<vrep::VrepRobotArmDriver::RobotTargetBaseName>(handleParams)
                          );
        auto  currentEigenT = currentEndEffectorPose.translation();
        auto& currentCisstT = currentKinematicsStateP_->Frame.Translation();
        currentCisstT[0] = currentEigenT(0);
        currentCisstT[1] = currentEigenT(1);
        currentCisstT[2] = currentEigenT(2);
#ifdef HANDLE_ROTATION
        Eigen::Map<Eigen::Matrix<double,3,3,Eigen::ColMajor>> ccr(currentKinematicsStateP_->Frame.Rotation().Pointer());
        ccr = currentEndEffectorPose.rotation();
#endif // HANDLE_ROTATION
        /// @todo set rotation component of current position

        Eigen::Affine3d desiredEndEffectorPose =
        getObjectTransform(
                             std::get<vrep::VrepRobotArmDriver::RobotTargetName>(handleParams)
                            ,std::get<vrep::VrepRobotArmDriver::RobotTargetBaseName>(handleParams)
                          );
        auto  desiredEigenT = desiredEndEffectorPose.translation();
        auto& desiredCisstT = desiredKinematicsStateP_->Frame.Translation();
        desiredCisstT[0] = desiredEigenT(0);
        desiredCisstT[1] = desiredEigenT(1);
        desiredCisstT[2] = desiredEigenT(2);
#ifdef HANDLE_ROTATION
        Eigen::Map<Eigen::Matrix<double,3,3,Eigen::ColMajor>> dcr(desiredKinematicsStateP_->Frame.Rotation().Pointer());
        dcr = desiredEndEffectorPose.rotation();
#endif // HANDLE_ROTATION
        /// @todo set rotation component of desired position

        // for debugging, the translation between the current and desired position in cartesian coordinates
        auto inputDesired_dx = desiredCisstT - currentCisstT;

        SetKinematics(*currentKinematicsStateP_);  // replaced by name of object
        // fill these out in the desiredKinematicsStateP_
        //RotationType RotationMember; // vcRot3
        //TranslationType TranslationMember; // vct3

        SetKinematics(*desiredKinematicsStateP_); // replaced by name of object
        // call setKinematics with the new kinematics
        // sawconstraintcontroller has kinematicsState
        // set the jacobian here

        //////////////////////
        /// @todo move code below here back under run_one updateKinematics() call

       /// @todo need to provide tick time in double seconds and get from vrep API call
       UpdateOptimizer(0.01);

       vctDoubleVec jointAngles_dt;
       auto returncode = Solve(jointAngles_dt);

       /// @todo check the return code, if it doesn't have a result, use the VREP version as a fallback and report an error.
       if(returncode != nmrConstraintOptimizer::NMR_OK) BOOST_THROW_EXCEPTION(std::runtime_error("VrepInverseKinematicsController: constrained optimization error, please investigate"));

       /// @todo: rethink where/when/how to send command for the joint angles. Return to LUA? Set Directly? Distribute via vrep send message command?
        //std::string str;
        str = "";
       for (std::size_t i=0 ; i < jointHandles_.size() ; i++)
       {
          float currentAngle;
          auto ret = simGetJointPosition(jointHandles_[i],&currentAngle);
          BOOST_VERIFY(ret!=-1);
          float futureAngle = currentAngle + jointAngles_dt[i];
          //simSetJointTargetPosition(jointHandles_[i],jointAngles_dt[i]);
          //simSetJointTargetPosition(jointHandles_[i],futureAngle);
          simSetJointPosition(jointHandles_[i],futureAngle);
                str+=boost::lexical_cast<std::string>(jointAngles_dt[i]);
                if (i<jointHandles_.size()-1)
                    str+=", ";
       }
        BOOST_LOG_TRIVIAL(trace) << "jointAngles_dt: "<< str;

        auto optimizerCalculated_dx = this->currentKinematicsStateP_->Jacobian * jointAngles_dt;

        BOOST_LOG_TRIVIAL(trace) << "desired dx: " << inputDesired_dx << " optimizer Calculated dx: " << optimizerCalculated_dx;
    }

    /// may not need this it is in the base class
    /// blocking call, call in separate thread, just allocates memory
    void run_one(){
       updateKinematics();

    }

    /// may not need this it is in the base class
    /// this will have output
    /// blocking call, call in separate thread, just allocates memory
    /// this runs the actual optimization algorithm
    void solve(){

    }

    std::vector<int> jointHandles_; ///< @todo move this item back into VrepRobotArmDriver
    int ikGroupHandle_;
    std::shared_ptr<vrep::VrepRobotArmDriver> VrepRobotArmDriverP_;
    vrep::VrepRobotArmDriver::State currentArmState_;
    std::string positionLimitsName;
    std::string velocityLimitsName;
};

} // namespace grl

#endif<|endoftext|>


<commit_before>#pragma once
#include <Eigen/Geometry>
#include "mtao/types.h"
#include "mtao/colvector_loop.hpp"

namespace mtao { namespace geometry {
    template <typename T, int D>
        auto bounding_box(const mtao::ColVectors<T,D>& V) {
            Eigen::AlignedBox<T,D> bb;
            bb.extend(V.rowwise().minCoeff());
            bb.extend(V.rowwise().maxCoeff());
            return bb;
        }
    template <typename T, int D>
        auto bounding_box_slow(const mtao::ColVectors<T,D>& V) {
            Eigen::AlignedBox<T,D> bb;
            bb.extend(V.rowwise().minCoeff());
            bb.extend(V.rowwise().maxCoeff());
            for(auto&& p: colvector_loop(V)) {
                bb.extend(p);
            }

            return bb;
        }
}}
<commit_msg>name change in bbox<commit_after>#pragma once
#include <Eigen/Geometry>
#include "mtao/types.hpp"
#include "mtao/colvector_loop.hpp"

namespace mtao { namespace geometry {
    template <typename T, int D> using BBox = Eigen::AlignedBox<T,D>;
    template <typename T, int D>
        auto bounding_box(const mtao::ColVectors<T,D>& V) {
            BBox<T,D> bb;
            bb.extend(V.rowwise().minCoeff());
            bb.extend(V.rowwise().maxCoeff());
            return bb;
        }
    template <typename T, int D>
        auto bounding_box_slow(const mtao::ColVectors<T,D>& V) {
            BBox<T,D> bb;
            bb.extend(V.rowwise().minCoeff());
            bb.extend(V.rowwise().maxCoeff());
            for(auto&& p: colvector_loop(V)) {
                bb.extend(p);
            }

            return bb;
        }
}}
<|endoftext|>


<commit_before>/*
 * NetworkServer.hpp
 *
 *  Created on: 07.04.2016
 *      Author: Marc Hartung
 */

#ifndef INCLUDE_NETWORK_IMPL_NETWORKSERVER_HPP_
#define INCLUDE_NETWORK_IMPL_NETWORKSERVER_HPP_

#include "NetworkMember.hpp"

namespace NetOff
{

    class NetworkServer : public NetworkMember
    {
     public:
        NetworkServer();

        NetworkServer(const NetworkServer &) = delete;
        NetworkServer& operator=(const NetworkServer &) = delete;

        virtual ~NetworkServer();

        bool initialize(const int & port);

        void deinitialize() override;

        virtual char getChar() const
        {
            return 'S';
        }

     private:
        TCPsocket _tcpsock;

    };

} /* namespace NetOff */

#endif /* INCLUDE_NETWORK_IMPL_NETWORKSERVER_HPP_ */
<commit_msg>Add override keyword to function<commit_after>/*
 * NetworkServer.hpp
 *
 *  Created on: 07.04.2016
 *      Author: Marc Hartung
 */

#ifndef INCLUDE_NETWORK_IMPL_NETWORKSERVER_HPP_
#define INCLUDE_NETWORK_IMPL_NETWORKSERVER_HPP_

#include "NetworkMember.hpp"

namespace NetOff
{

    class NetworkServer : public NetworkMember
    {
     public:
        NetworkServer();

        NetworkServer(const NetworkServer &) = delete;
        NetworkServer& operator=(const NetworkServer &) = delete;

        virtual ~NetworkServer();

        bool initialize(const int & port);

        void deinitialize() override;

        virtual char getChar() const override
        {
            return 'S';
        }

     private:
        TCPsocket _tcpsock;

    };

} /* namespace NetOff */

#endif /* INCLUDE_NETWORK_IMPL_NETWORKSERVER_HPP_ */
<|endoftext|>


<commit_before>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#ifndef NIX_ENTITY_WITH_SOURCES_H
#define NIX_ENTITY_WITH_SOURCES_H

#include <nix/base/EntityWithMetadata.hpp>
#include <nix/Source.hpp>

namespace nix {
namespace base {

/**
 * @brief Base class for entities that can be associated with one or more sources.
 *
 * In order to describe the provenance of data some entities of the NIX data model can
 * be associated with {@link nix::Source} entities. This class serves as a base class for
 * those.
 */
template <typename T>
class EntityWithSources : public base::EntityWithMetadata<T> {

public:

    /**
     * @brief Constructor that creates a null entity.
     */
    EntityWithSources()
        : EntityWithMetadata<T>()
    {
    }

    /**
     * @brief Constructor that creates a new entity from a shared pointer to
     * an implementation instance.
     */
    EntityWithSources(const std::shared_ptr<T> &p_impl)
        : EntityWithMetadata<T>(p_impl)
    {
    }

    /**
     * @brief Constructor with move semantics that creates a new entity from a
     * shared pointer to an implementation instance.
     */
    EntityWithSources(std::shared_ptr<T> &&ptr)
        : EntityWithMetadata<T>(std::move(ptr))
    {
    }

    /**
     * @brief Get the number of sources associated with this entity.
     *
     * @return The number sources.
     */
    ndsize_t sourceCount() const {
        return EntityWithMetadata<T>::backend()->sourceCount();
    }

    /**
     * @brief Checks if a specific source is associated with this entity.
     *
     * @param id      The source id to check.
     *
     * @return True if the source is associated with this entity, false otherwise.
     */
    bool hasSource(const std::string &id) const {
        return EntityWithMetadata<T>::backend()->hasSource(id);
    }

    /**
     * @brief Checks if a specific source is associated with this entity.
     *
     * @param source    The source to check.
     *
     * @return True if the source is associated with this entity, false otherwise.
     */
    bool hasSource(const Source &source) const {
        return EntityWithMetadata<T>::backend()->hasSource(source.id());
    }

    /**
     * @brief Returns an associated source identified by its id.
     *
     * @param id        The id of the associated source.
     */
    Source getSource(const std::string &id) const {
        return EntityWithMetadata<T>::backend()->getSource(id);
    }

    /**
     * @brief Retrieves an associated source identified by its index.
     *
     * @param index        The index of the associated source.
     *
     * @return The source with the given id. If it doesn't exist an exception
     *         will be thrown.
     */
    Source getSource(const size_t index) const {
        return EntityWithMetadata<T>::backend()->getSource(index);
    }

    /**
     * @brief Get all sources associated with this entity.
     *
     * The parameter filter can be used to filter sources by various
     * criteria. By default a filter that accepts all sources is used.
     *
     * @param filter    A filter function.
     *
     * @return All associated sources that match the given filter as a vector
     */
    std::vector<Source> sources(util::Filter<Source>::type filter = util::AcceptAll<Source>()) const
    {
        auto f = [this] (size_t i) { return getSource(i); };
        return nix::base::ImplContainer<T>::template getEntities<nix::Source, decltype(f)>(f,sourceCount(),filter);
    }

    /**
     * @brief Set all sources associations for this entity.
     *
     * All previously existing associations will be overwritten.
     *
     * @param sources A vector with all sources.
     */
    virtual void sources(const std::vector<Source> &sources) {
        EntityWithMetadata<T>::backend()->sources(sources);
    }

    /**
     * @brief Associate a new source with the entity.
     *
     * If a source with the given id already is associated with the
     * entity, the call will have no effect.
     *
     * @param id      The id of the source.
     */
    void addSource(const std::string &id) {
        EntityWithMetadata<T>::backend()->addSource(id);
    }

    /**
     * @brief Associate a new source with the entity.
     *
     * Calling this method will have no effect if the source is already associated to this entity.
     *
     * @param source    The source to add.
     */
    void addSource(const Source &source) {
        EntityWithMetadata<T>::backend()->addSource(source.id());
    }

    /**
     * @brief Remove a source from the list of associated sources.
     *
     * This method just removes the association between the entity and the source.
     * The source itself will not be deleted from the file.
     *
     * @param id      The id of the source to remove.
     *
     * @return True if the source was removed, false otherwise.
     */
    bool removeSource(const std::string &id) {
        return EntityWithMetadata<T>::backend()->removeSource(id);
    }

    /**
     * @brief Remove a source from the list of associated sources.
     *
     * This method just removes the association between the entity and the source.
     * The source itself will not be deleted from the file.
     *
     * @param source    The source to remove.
     *
     * @return True if the source was removed, false otherwise.
     */
    bool removeSource(const Source &source) {
        return EntityWithMetadata<T>::backend()->removeSource(source.id());
    }

    /**
     * Destructor
     */
    virtual ~EntityWithSources() {}

};

} // namespace base
} // namespace nix

#endif // NIX_ENTITY_WITH_SOURCES_H
<commit_msg>[Sources] add try catch check for possibility of invalid files<commit_after>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#ifndef NIX_ENTITY_WITH_SOURCES_H
#define NIX_ENTITY_WITH_SOURCES_H

#include <nix/base/EntityWithMetadata.hpp>
#include <nix/Source.hpp>

namespace nix {
namespace base {

/**
 * @brief Base class for entities that can be associated with one or more sources.
 *
 * In order to describe the provenance of data some entities of the NIX data model can
 * be associated with {@link nix::Source} entities. This class serves as a base class for
 * those.
 */
template <typename T>
class EntityWithSources : public base::EntityWithMetadata<T> {

public:

    /**
     * @brief Constructor that creates a null entity.
     */
    EntityWithSources()
        : EntityWithMetadata<T>()
    {
    }

    /**
     * @brief Constructor that creates a new entity from a shared pointer to
     * an implementation instance.
     */
    EntityWithSources(const std::shared_ptr<T> &p_impl)
        : EntityWithMetadata<T>(p_impl)
    {
    }

    /**
     * @brief Constructor with move semantics that creates a new entity from a
     * shared pointer to an implementation instance.
     */
    EntityWithSources(std::shared_ptr<T> &&ptr)
        : EntityWithMetadata<T>(std::move(ptr))
    {
    }

    /**
     * @brief Get the number of sources associated with this entity.
     *
     * @return The number sources.
     */
    ndsize_t sourceCount() const {
        return EntityWithMetadata<T>::backend()->sourceCount();
    }

    /**
     * @brief Checks if a specific source is associated with this entity.
     *
     * @param id      The source id to check.
     *
     * @return True if the source is associated with this entity, false otherwise.
     */
    bool hasSource(const std::string &id) const {
        return EntityWithMetadata<T>::backend()->hasSource(id);
    }

    /**
     * @brief Checks if a specific source is associated with this entity.
     *
     * @param source    The source to check.
     *
     * @return True if the source is associated with this entity, false otherwise.
     */
    bool hasSource(const Source &source) const {
        std::string id;
        try {
            id = source.id();
        } catch (...) {
            return false;
        }
        return EntityWithMetadata<T>::backend()->hasSource(id);
    }

    /**
     * @brief Returns an associated source identified by its id.
     *
     * @param id        The id of the associated source.
     */
    Source getSource(const std::string &id) const {
        return EntityWithMetadata<T>::backend()->getSource(id);
    }

    /**
     * @brief Retrieves an associated source identified by its index.
     *
     * @param index        The index of the associated source.
     *
     * @return The source with the given id. If it doesn't exist an exception
     *         will be thrown.
     */
    Source getSource(const size_t index) const {
        return EntityWithMetadata<T>::backend()->getSource(index);
    }

    /**
     * @brief Get all sources associated with this entity.
     *
     * The parameter filter can be used to filter sources by various
     * criteria. By default a filter that accepts all sources is used.
     *
     * @param filter    A filter function.
     *
     * @return All associated sources that match the given filter as a vector
     */
    std::vector<Source> sources(util::Filter<Source>::type filter = util::AcceptAll<Source>()) const
    {
        auto f = [this] (size_t i) { return getSource(i); };
        return nix::base::ImplContainer<T>::template getEntities<nix::Source, decltype(f)>(f,sourceCount(),filter);
    }

    /**
     * @brief Set all sources associations for this entity.
     *
     * All previously existing associations will be overwritten.
     *
     * @param sources A vector with all sources.
     */
    virtual void sources(const std::vector<Source> &sources) {
        EntityWithMetadata<T>::backend()->sources(sources);
    }

    /**
     * @brief Associate a new source with the entity.
     *
     * If a source with the given id already is associated with the
     * entity, the call will have no effect.
     *
     * @param id      The id of the source.
     */
    void addSource(const std::string &id) {
        EntityWithMetadata<T>::backend()->addSource(id);
    }

    /**
     * @brief Associate a new source with the entity.
     *
     * Calling this method will have no effect if the source is already associated to this entity.
     *
     * @param source    The source to add.
     */
    void addSource(const Source &source) {
        EntityWithMetadata<T>::backend()->addSource(source.id());
    }

    /**
     * @brief Remove a source from the list of associated sources.
     *
     * This method just removes the association between the entity and the source.
     * The source itself will not be deleted from the file.
     *
     * @param id      The id of the source to remove.
     *
     * @return True if the source was removed, false otherwise.
     */
    bool removeSource(const std::string &id) {
        return EntityWithMetadata<T>::backend()->removeSource(id);
    }

    /**
     * @brief Remove a source from the list of associated sources.
     *
     * This method just removes the association between the entity and the source.
     * The source itself will not be deleted from the file.
     *
     * @param source    The source to remove.
     *
     * @return True if the source was removed, false otherwise.
     */
    bool removeSource(const Source &source) {
        return EntityWithMetadata<T>::backend()->removeSource(source.id());
    }

    /**
     * Destructor
     */
    virtual ~EntityWithSources() {}

};

} // namespace base
} // namespace nix

#endif // NIX_ENTITY_WITH_SOURCES_H
<|endoftext|>