<commit_before>#include "Settings.h"

#include <Shlwapi.h>

#include "HotkeyActions.h"
#include "Logger.h"
#include "StringUtils.h"

std::wstring Settings::_appDir(L"");

Settings::Settings(std::wstring file) :
_file(file) {
    CLOG(L"Loading settings file [%s]", file.c_str());

    std::string u8FileName = StringUtils::Narrow(file);
    tinyxml2::XMLError result = _xml.LoadFile(u8FileName.c_str());
    if (result != tinyxml2::XMLError::XML_SUCCESS) {
        throw std::runtime_error("Failed to parse XML file");
    }

    _root = _xml.GetDocument()->FirstChildElement("settings");
    if (_root == NULL) {
        throw std::runtime_error("Could not find root XML element");
    }
}

std::wstring Settings::AppDir() {
    if (_appDir.empty()) {
        wchar_t path[MAX_PATH];
        GetModuleFileName(NULL, path, MAX_PATH);
        PathRemoveFileSpec(path);
        _appDir = std::wstring(path);
    }
    return _appDir;
}

std::wstring Settings::SkinName() {
    const char* skinName = _root->FirstChildElement("skin")->GetText();
    if (skinName == NULL) {
        return L"Default";
    } else {
        return StringUtils::Widen(skinName);
    }
}

std::unordered_map<int, int> Settings::Hotkeys() {
    std::unordered_map<int, int> keyMappings;

    tinyxml2::XMLElement *hotkeys = _root->FirstChildElement("hotkeys");
    tinyxml2::XMLElement *hotkey = hotkeys->FirstChildElement("hotkey");

    for (; hotkey != NULL; hotkey = hotkey->NextSiblingElement()) {
        int action = -1;
        hotkey->QueryIntAttribute("action", &action);
        if (action == -1) {
            CLOG(L"No action provided for hotkey; skipping");
            continue;
        }

        int combination = -1;
        hotkey->QueryIntAttribute("combination", &combination);
        if (combination == -1) {
            CLOG(L"No key combination provided for hotkey; skipping");
            continue;
        }

        /* Whew, we made it! */
        CLOG(L"Adding hotkey mapping: %d -> %d", combination, action);
        keyMappings[combination] = action;
    }

    return keyMappings;
}

bool Settings::IsEnabled(std::string elementName) {
    bool val = false;
    _root->FirstChildElement(elementName.c_str())->QueryBoolText(&val);
    return val;
}

std::wstring Settings::GetText(std::string elementName) {
    const char* str = _root->FirstChildElement(elementName.c_str())->GetText();
    if (str == NULL) {
        return NULL;
    } else {
        return StringUtils::Widen(str);
    }
}<commit_msg>Fix invalid pointer bug<commit_after>#include "Settings.h"

#include <Shlwapi.h>

#include "HotkeyActions.h"
#include "Logger.h"
#include "StringUtils.h"

std::wstring Settings::_appDir(L"");

Settings::Settings(std::wstring file) :
_file(file) {
    CLOG(L"Loading settings file [%s]", file.c_str());

    std::string u8FileName = StringUtils::Narrow(file);
    tinyxml2::XMLError result = _xml.LoadFile(u8FileName.c_str());
    if (result != tinyxml2::XMLError::XML_SUCCESS) {
        throw std::runtime_error("Failed to parse XML file");
    }

    _root = _xml.GetDocument()->FirstChildElement("settings");
    if (_root == NULL) {
        throw std::runtime_error("Could not find root XML element");
    }
}

std::wstring Settings::AppDir() {
    if (_appDir.empty()) {
        wchar_t path[MAX_PATH];
        GetModuleFileName(NULL, path, MAX_PATH);
        PathRemoveFileSpec(path);
        _appDir = std::wstring(path);
    }
    return _appDir;
}

std::wstring Settings::SkinName() {
    const char* skinName = _root->FirstChildElement("skin")->GetText();
    if (skinName == NULL) {
        return L"Default";
    } else {
        return StringUtils::Widen(skinName);
    }
}

std::unordered_map<int, int> Settings::Hotkeys() {
    std::unordered_map<int, int> keyMappings;

    tinyxml2::XMLElement *hotkeys = _root->FirstChildElement("hotkeys");
    tinyxml2::XMLElement *hotkey = hotkeys->FirstChildElement("hotkey");

    for (; hotkey != NULL; hotkey = hotkey->NextSiblingElement()) {
        int action = -1;
        hotkey->QueryIntAttribute("action", &action);
        if (action == -1) {
            CLOG(L"No action provided for hotkey; skipping");
            continue;
        }

        int combination = -1;
        hotkey->QueryIntAttribute("combination", &combination);
        if (combination == -1) {
            CLOG(L"No key combination provided for hotkey; skipping");
            continue;
        }

        /* Whew, we made it! */
        CLOG(L"Adding hotkey mapping: %d -> %d", combination, action);
        keyMappings[combination] = action;
    }

    return keyMappings;
}

bool Settings::IsEnabled(std::string elementName) {
    bool val = false;
    _root->FirstChildElement(elementName.c_str())->QueryBoolText(&val);
    return val;
}

std::wstring Settings::GetText(std::string elementName) {
    const char* str = _root->FirstChildElement(elementName.c_str())->GetText();
    if (str == NULL) {
        return L"";
    } else {
        return StringUtils::Widen(str);
    }
}<|endoftext|>


<commit_before>#include "mwm_url.hpp"

#include "../indexer/mercator.hpp"

#include "../coding/uri.hpp"

#include "../base/logging.hpp"
#include "../base/string_utils.hpp"

#include "../std/algorithm.hpp"
#include "../std/bind.hpp"

using namespace url_scheme;

namespace
{

static int const INVALID_LAT_VALUE = -1000;

bool IsInvalidApiPoint(ApiPoint const & p) { return p.m_lat == INVALID_LAT_VALUE; }

}  // unnames namespace

ParsedMapApi::ParsedMapApi():m_id(0)
{}

ParsedMapApi::ParsedMapApi(Uri const & uri):m_id(0)
{
  if (!Parse(uri))
  {
    m_points.clear();
  }
}

bool ParsedMapApi::SetUriAndParse(string const & url)
{
  Clear();
  return Parse(url_scheme::Uri(url));
}

bool ParsedMapApi::IsValid() const
{
  return !m_points.empty();
}

bool ParsedMapApi::Parse(Uri const & uri)
{
  string const & scheme = uri.GetScheme();
  if ((scheme != "mapswithme" && scheme != "mwm") || uri.GetPath() != "map")
    return false;

  uri.ForEachKeyValue(bind(&ParsedMapApi::AddKeyValue, this, _1, _2));
  m_points.erase(remove_if(m_points.begin(), m_points.end(), &IsInvalidApiPoint), m_points.end());

  return true;
}

void ParsedMapApi::AddKeyValue(string const & key, string const & value)
{
  if (key == "backurl")
    m_globalBackUrl = value;
  if (key == "v")
  {
    if (!strings::to_int(value, m_id))
      m_id = 0;
  }
  if (key == "appname")
    m_appTitle = value;
  if (key == "ll")
  {
    m_points.push_back(ApiPoint());
    m_points.back().m_lat = INVALID_LAT_VALUE;

    size_t const firstComma = value.find(',');
    if (firstComma == string::npos)
    {
      LOG(LWARNING, ("Map API: no comma between lat and lon for 'll' key", key, value));
      return;
    }

    if (value.find(',', firstComma + 1) != string::npos)
    {
      LOG(LWARNING, ("Map API: more than one comma in a value for 'll' key", key, value));
      return;
    }

    double lat, lon;
    if (!strings::to_double(value.substr(0, firstComma), lat) ||
        !strings::to_double(value.substr(firstComma + 1), lon))
    {
      LOG(LWARNING, ("Map API: can't parse lat,lon for 'll' key", key, value));
      return;
    }

    if (!MercatorBounds::ValidLat(lat) || !MercatorBounds::ValidLon(lon))
    {
      LOG(LWARNING, ("Map API: incorrect value for lat and/or lon", key, value, lat, lon));
      return;
    }

    m_points.back().m_lat = lat;
    m_points.back().m_lon = lon;
    m_showRect = m2::Add(m_showRect, m2::PointD(lat, lon));
  }
  else if (key == "n")
  {
    if (!m_points.empty())
      m_points.back().m_title = value;
    else
      LOG(LWARNING, ("Map API: Point name with no point. 'll' should come first!"));
  }
  else if (key == "u")
  {
    if (!m_points.empty())
      m_points.back().m_url = value;
    else
      LOG(LWARNING, ("Map API: Point url with no point. 'll' should come first!"));
  }
}

void ParsedMapApi::Clear()
{
  m_points.clear();
  m_globalBackUrl.clear();
  m_appTitle.clear();
  m_id = 0;
  m_showRect = m2::RectD();
}
<commit_msg>[core] Small viewrect bag fix.<commit_after>#include "mwm_url.hpp"

#include "../indexer/mercator.hpp"

#include "../coding/uri.hpp"

#include "../base/logging.hpp"
#include "../base/string_utils.hpp"

#include "../std/algorithm.hpp"
#include "../std/bind.hpp"

using namespace url_scheme;

namespace
{

static int const INVALID_LAT_VALUE = -1000;

bool IsInvalidApiPoint(ApiPoint const & p) { return p.m_lat == INVALID_LAT_VALUE; }

}  // unnames namespace

ParsedMapApi::ParsedMapApi():m_id(0)
{}

ParsedMapApi::ParsedMapApi(Uri const & uri):m_id(0)
{
  if (!Parse(uri))
  {
    m_points.clear();
  }
}

bool ParsedMapApi::SetUriAndParse(string const & url)
{
  Clear();
  return Parse(url_scheme::Uri(url));
}

bool ParsedMapApi::IsValid() const
{
  return !m_points.empty();
}

bool ParsedMapApi::Parse(Uri const & uri)
{
  string const & scheme = uri.GetScheme();
  if ((scheme != "mapswithme" && scheme != "mwm") || uri.GetPath() != "map")
    return false;

  uri.ForEachKeyValue(bind(&ParsedMapApi::AddKeyValue, this, _1, _2));
  m_points.erase(remove_if(m_points.begin(), m_points.end(), &IsInvalidApiPoint), m_points.end());

  return true;
}

void ParsedMapApi::AddKeyValue(string const & key, string const & value)
{
  if (key == "backurl")
    m_globalBackUrl = value;
  if (key == "v")
  {
    if (!strings::to_int(value, m_id))
      m_id = 0;
  }
  if (key == "appname")
    m_appTitle = value;
  if (key == "ll")
  {
    m_points.push_back(ApiPoint());
    m_points.back().m_lat = INVALID_LAT_VALUE;

    size_t const firstComma = value.find(',');
    if (firstComma == string::npos)
    {
      LOG(LWARNING, ("Map API: no comma between lat and lon for 'll' key", key, value));
      return;
    }

    if (value.find(',', firstComma + 1) != string::npos)
    {
      LOG(LWARNING, ("Map API: more than one comma in a value for 'll' key", key, value));
      return;
    }

    double lat, lon;
    if (!strings::to_double(value.substr(0, firstComma), lat) ||
        !strings::to_double(value.substr(firstComma + 1), lon))
    {
      LOG(LWARNING, ("Map API: can't parse lat,lon for 'll' key", key, value));
      return;
    }

    if (!MercatorBounds::ValidLat(lat) || !MercatorBounds::ValidLon(lon))
    {
      LOG(LWARNING, ("Map API: incorrect value for lat and/or lon", key, value, lat, lon));
      return;
    }

    m_points.back().m_lat = lat;
    m_points.back().m_lon = lon;
    m_showRect = m2::Add(m_showRect, m2::PointD(lon, lat));
  }
  else if (key == "n")
  {
    if (!m_points.empty())
      m_points.back().m_title = value;
    else
      LOG(LWARNING, ("Map API: Point name with no point. 'll' should come first!"));
  }
  else if (key == "u")
  {
    if (!m_points.empty())
      m_points.back().m_url = value;
    else
      LOG(LWARNING, ("Map API: Point url with no point. 'll' should come first!"));
  }
}

void ParsedMapApi::Clear()
{
  m_points.clear();
  m_globalBackUrl.clear();
  m_appTitle.clear();
  m_id = 0;
  m_showRect = m2::RectD();
}
<|endoftext|>


<commit_before>#include "mwm_url.hpp"

#include "../indexer/mercator.hpp"

#include "../coding/uri.hpp"

#include "../base/logging.hpp"
#include "../base/string_utils.hpp"

#include "../std/algorithm.hpp"
#include "../std/bind.hpp"

using namespace url_scheme;

namespace
{

static int const INVALID_LAT_VALUE = -1000;

bool IsInvalidApiPoint(ApiPoint const & p) { return p.m_lat == INVALID_LAT_VALUE; }

}  // unnames namespace

ParsedMapApi::ParsedMapApi():m_id(0)
{}

ParsedMapApi::ParsedMapApi(Uri const & uri):m_id(0)
{
  if (!Parse(uri))
  {
    m_points.clear();
  }
}

bool ParsedMapApi::SetUriAndParse(string const & url)
{
  Clear();
  return Parse(url_scheme::Uri(url));
}

bool ParsedMapApi::IsValid() const
{
  return !m_points.empty();
}

bool ParsedMapApi::Parse(Uri const & uri)
{
  string const & scheme = uri.GetScheme();
  if ((scheme != "mapswithme" && scheme != "mwm") || uri.GetPath() != "map")
    return false;

  uri.ForEachKeyValue(bind(&ParsedMapApi::AddKeyValue, this, _1, _2));
  m_points.erase(remove_if(m_points.begin(), m_points.end(), &IsInvalidApiPoint), m_points.end());

  return true;
}

void ParsedMapApi::AddKeyValue(string const & key, string const & value)
{
  if (key == "backurl")
    m_globalBackUrl = value;
  if (key == "v")
  {
    if (!strings::to_int(value, m_id))
      m_id = 0;
  }
  if (key == "appname")
    m_appTitle = value;
  strings::AsciiToLower(key);

  if (key == "ll")
  {
    m_points.push_back(ApiPoint());
    m_points.back().m_lat = INVALID_LAT_VALUE;

    size_t const firstComma = value.find(',');
    if (firstComma == string::npos)
    {
      LOG(LWARNING, ("Map API: no comma between lat and lon for 'll' key", key, value));
      return;
    }

    if (value.find(',', firstComma + 1) != string::npos)
    {
      LOG(LWARNING, ("Map API: more than one comma in a value for 'll' key", key, value));
      return;
    }

    double lat, lon;
    if (!strings::to_double(value.substr(0, firstComma), lat) ||
        !strings::to_double(value.substr(firstComma + 1), lon))
    {
      LOG(LWARNING, ("Map API: can't parse lat,lon for 'll' key", key, value));
      return;
    }

    if (!MercatorBounds::ValidLat(lat) || !MercatorBounds::ValidLon(lon))
    {
      LOG(LWARNING, ("Map API: incorrect value for lat and/or lon", key, value, lat, lon));
      return;
    }

    m_points.back().m_lat = lat;
    m_points.back().m_lon = lon;
    m_showRect = m2::Add(m_showRect, m2::PointD(lon, lat));
  }
  else if (key == "n")
  {
    if (!m_points.empty())
      m_points.back().m_title = value;
    else
      LOG(LWARNING, ("Map API: Point name with no point. 'll' should come first!"));
  }
  else if (key == "u")
  {
    if (!m_points.empty())
      m_points.back().m_url = value;
    else
      LOG(LWARNING, ("Map API: Point url with no point. 'll' should come first!"));
  }
}

void ParsedMapApi::Clear()
{
  m_points.clear();
  m_globalBackUrl.clear();
  m_appTitle.clear();
  m_id = 0;
  m_showRect = m2::RectD();
}
<commit_msg>[api] Fixed "else if"<commit_after>#include "mwm_url.hpp"

#include "../indexer/mercator.hpp"

#include "../coding/uri.hpp"

#include "../base/logging.hpp"
#include "../base/string_utils.hpp"

#include "../std/algorithm.hpp"
#include "../std/bind.hpp"

using namespace url_scheme;

namespace
{

static int const INVALID_LAT_VALUE = -1000;

bool IsInvalidApiPoint(ApiPoint const & p) { return p.m_lat == INVALID_LAT_VALUE; }

}  // unnames namespace

ParsedMapApi::ParsedMapApi():m_id(0)
{}

ParsedMapApi::ParsedMapApi(Uri const & uri):m_id(0)
{
  if (!Parse(uri))
  {
    m_points.clear();
  }
}

bool ParsedMapApi::SetUriAndParse(string const & url)
{
  Clear();
  return Parse(url_scheme::Uri(url));
}

bool ParsedMapApi::IsValid() const
{
  return !m_points.empty();
}

bool ParsedMapApi::Parse(Uri const & uri)
{
  string const & scheme = uri.GetScheme();
  if ((scheme != "mapswithme" && scheme != "mwm") || uri.GetPath() != "map")
    return false;

  uri.ForEachKeyValue(bind(&ParsedMapApi::AddKeyValue, this, _1, _2));
  m_points.erase(remove_if(m_points.begin(), m_points.end(), &IsInvalidApiPoint), m_points.end());

  return true;
}

void ParsedMapApi::AddKeyValue(string const & key, string const & value)
{
  strings::AsciiToLower(key);

  if (key == "ll")
  {
    m_points.push_back(ApiPoint());
    m_points.back().m_lat = INVALID_LAT_VALUE;

    size_t const firstComma = value.find(',');
    if (firstComma == string::npos)
    {
      LOG(LWARNING, ("Map API: no comma between lat and lon for 'll' key", key, value));
      return;
    }

    if (value.find(',', firstComma + 1) != string::npos)
    {
      LOG(LWARNING, ("Map API: more than one comma in a value for 'll' key", key, value));
      return;
    }

    double lat, lon;
    if (!strings::to_double(value.substr(0, firstComma), lat) ||
        !strings::to_double(value.substr(firstComma + 1), lon))
    {
      LOG(LWARNING, ("Map API: can't parse lat,lon for 'll' key", key, value));
      return;
    }

    if (!MercatorBounds::ValidLat(lat) || !MercatorBounds::ValidLon(lon))
    {
      LOG(LWARNING, ("Map API: incorrect value for lat and/or lon", key, value, lat, lon));
      return;
    }

    m_points.back().m_lat = lat;
    m_points.back().m_lon = lon;
    m_showRect = m2::Add(m_showRect, m2::PointD(lon, lat));
  }
  else if (key == "n")
  {
    if (!m_points.empty())
      m_points.back().m_title = value;
    else
      LOG(LWARNING, ("Map API: Point name with no point. 'll' should come first!"));
  }
  else if (key == "u")
  {
    if (!m_points.empty())
      m_points.back().m_url = value;
    else
      LOG(LWARNING, ("Map API: Point url with no point. 'll' should come first!"));
  }
}

void ParsedMapApi::Clear()
{
  m_points.clear();
  else if (key == "backurl")
  {
    m_globalBackUrl = value;
  }
  else if (key == "v")
  {
    if (!strings::to_int(value, m_version))
      m_version = 0;
  }
  else if (key == "appname")
  {
    m_appTitle = value;
  }
  m_globalBackUrl.clear();
  m_appTitle.clear();
  m_id = 0;
  m_showRect = m2::RectD();
}
<|endoftext|>


<commit_before>/*------------------------------------------------------------------------
* (The MIT License)
*
* Copyright (c) 2008-2011 Rhomobile, Inc.
*
* 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.
*
* http://rhomobile.com
*------------------------------------------------------------------------*/

#include "SplashScreen.h"
#include "RhoThread.h"
#include "IRhoClassFactory.h"
#include "RhoConf.h"
#include "Tokenizer.h"

namespace rho {
namespace common {
IMPLEMENT_LOGCLASS(CSplashScreen,"SplashScreen");

void CSplashScreen::start()
{
	if (m_nDelay>0 && m_startTime.toULong() == 0)
        m_startTime = CTimeInterval::getCurrentTime();
}

long CSplashScreen::howLongWaitMs()
{
   if (m_nDelay <= 0) {
       return m_nDelay;
   }
   CTimeInterval endTime = CTimeInterval::getCurrentTime();
   long nTimeElapsed = endTime.minus(m_startTime).toULong();

   long timeToWait = m_nDelay * 1000 - nTimeElapsed;

   return (timeToWait > 0) ? timeToWait : 0;
}

void CSplashScreen::hide()
{
	if (m_nDelay<=0 || m_startTime.toULong() == 0)
		return;
	long nWaitMs = howLongWaitMs();
    m_startTime = CTimeInterval();
	if ( nWaitMs <= 0 )
		return;

    CAutoPtr<IRhoThreadImpl> ptrThread = rho_get_RhoClassFactory()->createThreadImpl();

    ptrThread->sleep(nWaitMs);
}

void CSplashScreen::init()
{
	String strSplash = RHOCONF().getString("splash_screen");

	CTokenizer stringtokenizer(strSplash, ";");
	while (stringtokenizer.hasMoreTokens()) {
		String tok = stringtokenizer.nextToken();
		tok = String_trim(tok);
		if (tok.length() == 0) {
			continue;
		}

		if (tok.find("delay") == 0)
		{
			int nEq = tok.find('=');
			if (nEq>=0)
			{
				String val = tok.substr(nEq+1);
				val = String_trim(val);
				if ( val.length() > 0 )
                    convertFromStringA( val.c_str(), m_nDelay );
			}
		}else if (tok.find("zoom") == 0)
		{
			m_nFlags |= VZOOM | HZOOM;
		}else if ( tok.find("vzoom") == 0)
		{
			m_nFlags |= VZOOM;
		}else if ( tok.find("hzoom") == 0)
		{
			m_nFlags |= HZOOM;
		}else if ( tok.find("center") == 0)
		{
			m_nFlags |= VCENTER | HCENTER;
		}else if ( tok.find("vcenter") == 0)
		{
			m_nFlags |= VCENTER;
		}else if ( tok.find("hcenter") == 0)
		{
			m_nFlags |= HCENTER;
		}

	}
}
}
}
<commit_msg>Update SplashScreen.cpp<commit_after>/*------------------------------------------------------------------------
* (The MIT License)
*
* Copyright (c) 2008-2011 Rhomobile, Inc.
*
* 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.
*
* http://rhomobile.com
*------------------------------------------------------------------------*/

#include "SplashScreen.h"
#include "RhoThread.h"
#include "IRhoClassFactory.h"
#include "RhoConf.h"
#include "Tokenizer.h"

namespace rho {
namespace common {
IMPLEMENT_LOGCLASS(CSplashScreen,"SplashScreen");

void CSplashScreen::start()
{
	if (m_nDelay>0 && m_startTime.toULong() == 0)
        m_startTime = CTimeInterval::getCurrentTime();
}

long CSplashScreen::howLongWaitMs()
{
   if (m_nDelay <= 0) {
       return m_nDelay;
   }
   CTimeInterval endTime = CTimeInterval::getCurrentTime();
   long nTimeElapsed = endTime.minus(m_startTime).toULong();

   long timeToWait = m_nDelay * 1000 - nTimeElapsed;

   return (timeToWait > 0) ? timeToWait : 0;
}

void CSplashScreen::setDuration(long lDuration)
{
	m_nDelay = (long)(lDuration/1000);
}

void CSplashScreen::hide()
{
	if (m_nDelay<=0 || m_startTime.toULong() == 0)
		return;
	long nWaitMs = howLongWaitMs();
    m_startTime = CTimeInterval();
	if ( nWaitMs <= 0 )
		return;

    CAutoPtr<IRhoThreadImpl> ptrThread = rho_get_RhoClassFactory()->createThreadImpl();

    ptrThread->sleep(nWaitMs);
}

void CSplashScreen::init()
{
	String strSplash = RHOCONF().getString("splash_screen");

	CTokenizer stringtokenizer(strSplash, ";");
	while (stringtokenizer.hasMoreTokens()) {
		String tok = stringtokenizer.nextToken();
		tok = String_trim(tok);
		if (tok.length() == 0) {
			continue;
		}

		if (tok.find("delay") == 0)
		{
			int nEq = tok.find('=');
			if (nEq>=0)
			{
				String val = tok.substr(nEq+1);
				val = String_trim(val);
				if ( val.length() > 0 )
                    convertFromStringA( val.c_str(), m_nDelay );
			}
		}else if (tok.find("zoom") == 0)
		{
			m_nFlags |= VZOOM | HZOOM;
		}else if ( tok.find("vzoom") == 0)
		{
			m_nFlags |= VZOOM;
		}else if ( tok.find("hzoom") == 0)
		{
			m_nFlags |= HZOOM;
		}else if ( tok.find("center") == 0)
		{
			m_nFlags |= VCENTER | HCENTER;
		}else if ( tok.find("vcenter") == 0)
		{
			m_nFlags |= VCENTER;
		}else if ( tok.find("hcenter") == 0)
		{
			m_nFlags |= HCENTER;
		}

	}
}
}
}
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>

#include <iostream>
#include <iterator>
#include <cstdlib>
#include <cassert>
#include <cmath>

#include <gsl/gsl_math.h>
#include <gsl/gsl_combination.h>

#include "dataset.hh"

using std::cout;
using std::cerr;
using std::ofstream;

MSZDataSet::MSZDataSet(double **matrix, size_t nrows, size_t ncols, size_t outputs)
  : matrix(matrix), nrows(nrows), rfeatures(ncols - outputs), ncols(ncols), outputs(outputs) {}

MSZDataSet::~MSZDataSet() {

  // Please God, do not let this Seg Fault!

  // Clean up matrix by deleting each line.
  for(size_t row = 0; row < nrows; row++)
    delete[] matrix[row];

  delete[] matrix;

}

void MSZDataSet::dumpPlotFiles(const vector<string> &labels, const string &prefix) const {

  if(labels.size() != ncols) {
    cerr << "Warning: Trying to dump plot files but labels vector is too small.\n";
    cerr << "Labels has size " << labels.size() << " but we have " << ncols << " columns.\n";
    return;
  }

  // Dump the files for plotting features against output
  for(size_t out = 0; out < outputs; out++) {
    for(size_t feature = outputs; feature < ncols; feature++) {
      ofstream file;
      file.open((prefix + "_" + labels[out] + "_" + labels[feature] + ".dat").c_str());

      file << "# This file is generated by MatSATZilla\n"
	   << "# It should be used with gnuplot to plot\n"
	   << "# the feature " << labels[feature] << " against\n"
	   << "# the output " << labels[out] << "\n"
	   << "#\n"
	// Outputting timestamp could be nice.
	//<< "# Timestamp: " <<
	   << "#\n"
	   << "# " << labels[feature] << "\t\t" << labels[out] << "\n";

      // For each instance
      for(size_t i = 0; i < nrows; i++)
	file << matrix[i][feature] << "\t\t" << matrix[i][out] << "\n";

      file.close();
    }
  }

  // Dump the files for plotting features against themselves
  for(size_t f1 = outputs; f1 < ncols-1; f1++) {
    for(size_t f2 = f1+1; f2 < ncols; f2++) {
      assert(f1 != f2); // Shouldn't be plotting same features
      assert(labels[f1] != labels[f2]); // There shouldn't be two labels with the same name
      ofstream file;
      file.open((prefix + "_" + labels[f1] + "_" + labels[f2] + ".dat").c_str());

      file << "# This file is generated by MatSATZilla\n"
	   << "# It should be used with gnuplot to plot\n"
	   << "# the feature " << labels[f2] << " against\n"
	   << "# the feature " << labels[f1] << "\n"
	   << "#\n"
	// Outputting timestamp could be nice.
	//<< "# Timestamp: " <<
	   << "#\n"
	   << "# " << labels[f2] << "\t\t" << labels[f1] << "\n";

      // For each instance
      for(size_t i = 0; i < nrows; i++)
	file << matrix[i][f2] << "\t\t" << matrix[i][f1] << "\n";

      file.close();
    }
  }
}

void MSZDataSet::printSolverStats(size_t timeout, const vector<string> &slabels) {

  if(slabels.size() != outputs) {
    cerr << "printSolverStats: You're passing in " << slabels.size() << " solver labels but there are " << outputs << " outputs in dataset.\n";
    return;
  }

  vector<size_t> nbTimeouts(outputs, 0);
  vector<size_t> nbOtherErrors(outputs, 0);

  for(size_t s = 0; s < outputs; s++) {
    for(size_t i = 0; i < nrows; i++) {
      if(matrix[i][s] == timeout)
	nbTimeouts[s]++;
      else if(matrix[i][s] == 2*timeout)
	nbOtherErrors[s]++;
    }
  }

  for(size_t s = 0; s < outputs; s++) {
    cout << "Solver: " << slabels[s] << "\n"
	 << "\t\tTimeouts: " << nbTimeouts[s] << " (" << (((double)(nbTimeouts[s])) / nrows)*100.0 << ")\n"
	 << "\t\tOther Errors: " << nbOtherErrors[s] << " (" << (((double)(nbOtherErrors[s])) / nrows)*100.0 << ")\n"
	 << "\t\tUsable Instances: " << nrows - nbTimeouts[s] - nbOtherErrors[s] << " (" << (((double)(nrows - nbTimeouts[s] - nbOtherErrors[s])) / nrows)*100.0 << ")\n";
  }

}

void MSZDataSet::dumpPlotFiles(char **labels, size_t len, char *prefix) const {

  vector<string> vec(len);

  for(size_t i = 0; i < len; i++)
    vec[i] = string(labels[i]);

  dumpPlotFiles(vec, string(prefix));
}

double MSZDataSet::getOutputValue(size_t row, size_t col) const {
  assert(row < nrows);
  assert(col < outputs);

  return matrix[row][col];
}

double MSZDataSet::getFeatureValue(size_t row, size_t col) const {
  assert(row < nrows);
  assert(col < ncols - outputs);

  return matrix[row][col+outputs];
}

void MSZDataSet::standardize() {

  cout << "Standardizing features ...";

  static bool stdDone = false;

  if(!stdDone) {
    for(size_t c = outputs; c < ncols; c++) {

      // Compute column mean and compute column variance.
      double mean = 0.0;
      for(size_t r = 0; r < nrows; r++)
	mean += matrix[r][c];
      mean /= nrows;

      // Compute column standard deviation.
      double sdv = 0.0;
      for(size_t r = 0; r < nrows; r++)
	sdv += gsl_pow_2(matrix[r][c] - mean);
      sdv /= nrows;

      for(size_t r = 0; r < nrows; r++)
	matrix[r][c] = (matrix[r][c] - mean) / sdv;

    }

  }
  stdDone = true;

  cout << "DONE\n";

}

void MSZDataSet::removeFeatures(const vector<size_t> &keepVec) {
  // We need to remove the feature indexes in vec from the current data.

  cout << "Pruning features from dataset: ";

  // Create the indices to remove
  vector<size_t> vec;
  for(size_t i = outputs; i < ncols; i++)
    if(find(keepVec.begin(), keepVec.end(), i-outputs) == keepVec.end())
      vec.push_back(i);

  if(vec.size() == 0) {
    cout << "NONE\n";
    return;
  } else {
    copy(vec.begin(), vec.end(), std::ostream_iterator<size_t>(cout, " "));
    cout << std::endl;
  }

  // Let's setup all the variables
  size_t currRawFeatures = rfeatures;
  size_t currCols = ncols;
  for(size_t i = 0; i < vec.size(); i++) {
    ncols--;
    if(vec[i] < currRawFeatures)
      rfeatures--;
  }

  // Now we need to recreate matrix.
  // KILL ME
  double **newMatrix = (double**)malloc(nrows * sizeof(*newMatrix));
  for(size_t r = 0; r < nrows; r++)
    newMatrix[r] = (double*)malloc(ncols * sizeof(**newMatrix));

  // Copy every column to the new matrix except those listed in vec.
  size_t destc = 0;
  for(size_t origc = 0; origc < currCols; origc++) {
    if(find(vec.begin(), vec.end(), origc) != vec.end())
      continue;
    assert(destc < ncols);
    for(size_t r = 0; r < nrows; r++)
      newMatrix[r][destc] = matrix[r][origc];
    destc++;
  }

  // free previous matrix
  for(size_t r = 0; r < nrows; r++)
    free(matrix[r]);
  free(matrix);

  matrix = newMatrix;
}

void MSZDataSet::standardizeOutputs() {

  cout << "Standardizing outputs... ";

  static bool stdDone = false;

  if(!stdDone) {
    for(size_t c = 0; c < outputs; c++)
      for(size_t r = 0; r < nrows; r++)
	matrix[r][c] = log(matrix[r][c]);
  }

  stdDone = true;

  cout <<  "DONE\n";

}

void MSZDataSet::expand(size_t n) {
  vector<size_t> pvec(ncols - outputs);
  for(size_t i = 0; i < pvec.size(); i++)
    pvec[i] = i;

  expandOnPartition(n, pvec);
}

void MSZDataSet::expand(size_t n, const vector<vector<size_t> > &pvec) {
  for(size_t i = 0; i < pvec.size(); i++)
    expandOnPartition(n, pvec[i]);
}

void MSZDataSet::expandOnPartition(size_t k, const vector<size_t> &pvec) {

  // expansion is quadratic at the minimum and
  // and be bigger than partition size.
  assert(k > 2 && k <= pvec.size());

  // Standardize features
  standardize();

  // Reallocate the data.
  // If we have N features, then, to expand to a order-K polynomial
  // we are adding
  // n + (n !) / (k! (n-k!))
  size_t num = 1;
  for(size_t i = 0; i < k; i++) num *= rfeatures - i; // for big k hell breaks loose
  size_t den = 1;
  for(size_t i = k; i > 0; i--) den *= i;
  size_t nNewF = rfeatures;
  nNewF += num / den;
  ncols += nNewF; // Update number of columns

  // Now, we need to realloc all the structure
  for(size_t r = 0; r < nrows; r++) {
    matrix[r] = (double*)realloc(matrix[r], sizeof(**matrix) * (nNewF + ncols));
    if(matrix[r] == 0) {
      cerr << "Bad news... while trying to allocate memory...\n";
      exit(EXIT_FAILURE);
    }
  }

  // Compute the cross products
  // To do this we compute all the indices combinations and use them
  // to compute the cross product on columns defined in pvec.
  size_t currColumn = rfeatures + outputs;
  const size_t n = pvec.size();
  gsl_combination * c;
  c = gsl_combination_calloc (n, k);
  size_t *ind = new size_t [k];

  // Compute cross product for initial configuration
  // Now using the very nice combination structure from GSL.
  // Up to rev. 121, we used custom combination generator.
  do {
    for(size_t i = 0; i < k; i++)
      ind[i] = gsl_combination_get(c, i);

    // Compute cross product in current configuration
    for(size_t r = 0; r < nrows; r++) {
      matrix[r][currColumn] = computeCrossProduct(r, ind, k, pvec);
    }
    currColumn++;
  } while(gsl_combination_next (c) == GSL_SUCCESS);
  gsl_combination_free (c);
  delete ind;

  // Compute Powers
  for(size_t i = 0; i < pvec.size(); i++) {
    for(size_t r = 0; r < nrows; r++) {
      // Compute powers for pvec[i] feature
      matrix[r][currColumn] = gsl_pow_int(matrix[r][pvec[i]], k);
    }
  }

}

double MSZDataSet::computeCrossProduct(size_t r, size_t *ind, size_t k, const vector<size_t> &vec) {
  double cp = 1.0; // Cross-product
  for(size_t i = 0; i < k; i++)
   cp *= matrix[r][vec[ind[i]]];
  return cp;
}

/////////////////////////////////////////
/////////////////////////////////////////
//
// API Entrace Function for Data Set creation
//
/////////////////////////////////////////
/////////////////////////////////////////

MSZDataSet *createDataSet(double** matrix, size_t nrows, size_t ncols, size_t outputs) {
  assert(nrows > 0);
  assert(ncols > 0);
  assert(matrix != 0);
  assert(outputs > 0);
  assert(nrows >= ncols - outputs);

#ifndef NDEBUG
  for(size_t r = 0; r < nrows; r++)
    assert(matrix[r] != 0);
#endif // NDEBUG

  // The call!
  MSZDataSet *ds = new MSZDataSet(matrix, nrows, ncols, outputs);
  if(!ds) {
    cerr << "Error: Allocation of Dataset\n";
    exit(EXIT_FAILURE);
  }

  return ds;
}
<commit_msg>Replaced mallocs by new.<commit_after>#include <iostream>
#include <fstream>

#include <iostream>
#include <iterator>
#include <cstdlib>
#include <cassert>
#include <cmath>

#include <gsl/gsl_math.h>
#include <gsl/gsl_combination.h>

#include "dataset.hh"

using std::cout;
using std::cerr;
using std::ofstream;

MSZDataSet::MSZDataSet(double **matrix, size_t nrows, size_t ncols, size_t outputs)
  : matrix(matrix), nrows(nrows), rfeatures(ncols - outputs), ncols(ncols), outputs(outputs) {}

MSZDataSet::~MSZDataSet() {

  // Please God, do not let this Seg Fault!

  // Clean up matrix by deleting each line.
  for(size_t row = 0; row < nrows; row++)
    delete[] matrix[row];

  delete[] matrix;

}

void MSZDataSet::dumpPlotFiles(const vector<string> &labels, const string &prefix) const {

  if(labels.size() != ncols) {
    cerr << "Warning: Trying to dump plot files but labels vector is too small.\n";
    cerr << "Labels has size " << labels.size() << " but we have " << ncols << " columns.\n";
    return;
  }

  // Dump the files for plotting features against output
  for(size_t out = 0; out < outputs; out++) {
    for(size_t feature = outputs; feature < ncols; feature++) {
      ofstream file;
      file.open((prefix + "_" + labels[out] + "_" + labels[feature] + ".dat").c_str());

      file << "# This file is generated by MatSATZilla\n"
	   << "# It should be used with gnuplot to plot\n"
	   << "# the feature " << labels[feature] << " against\n"
	   << "# the output " << labels[out] << "\n"
	   << "#\n"
	// Outputting timestamp could be nice.
	//<< "# Timestamp: " <<
	   << "#\n"
	   << "# " << labels[feature] << "\t\t" << labels[out] << "\n";

      // For each instance
      for(size_t i = 0; i < nrows; i++)
	file << matrix[i][feature] << "\t\t" << matrix[i][out] << "\n";

      file.close();
    }
  }

  // Dump the files for plotting features against themselves
  for(size_t f1 = outputs; f1 < ncols-1; f1++) {
    for(size_t f2 = f1+1; f2 < ncols; f2++) {
      assert(f1 != f2); // Shouldn't be plotting same features
      assert(labels[f1] != labels[f2]); // There shouldn't be two labels with the same name
      ofstream file;
      file.open((prefix + "_" + labels[f1] + "_" + labels[f2] + ".dat").c_str());

      file << "# This file is generated by MatSATZilla\n"
	   << "# It should be used with gnuplot to plot\n"
	   << "# the feature " << labels[f2] << " against\n"
	   << "# the feature " << labels[f1] << "\n"
	   << "#\n"
	// Outputting timestamp could be nice.
	//<< "# Timestamp: " <<
	   << "#\n"
	   << "# " << labels[f2] << "\t\t" << labels[f1] << "\n";

      // For each instance
      for(size_t i = 0; i < nrows; i++)
	file << matrix[i][f2] << "\t\t" << matrix[i][f1] << "\n";

      file.close();
    }
  }
}

void MSZDataSet::printSolverStats(size_t timeout, const vector<string> &slabels) {

  if(slabels.size() != outputs) {
    cerr << "printSolverStats: You're passing in " << slabels.size() << " solver labels but there are " << outputs << " outputs in dataset.\n";
    return;
  }

  vector<size_t> nbTimeouts(outputs, 0);
  vector<size_t> nbOtherErrors(outputs, 0);

  for(size_t s = 0; s < outputs; s++) {
    for(size_t i = 0; i < nrows; i++) {
      if(matrix[i][s] == timeout)
	nbTimeouts[s]++;
      else if(matrix[i][s] == 2*timeout)
	nbOtherErrors[s]++;
    }
  }

  for(size_t s = 0; s < outputs; s++) {
    cout << "Solver: " << slabels[s] << "\n"
	 << "\t\tTimeouts: " << nbTimeouts[s] << " (" << (((double)(nbTimeouts[s])) / nrows)*100.0 << ")\n"
	 << "\t\tOther Errors: " << nbOtherErrors[s] << " (" << (((double)(nbOtherErrors[s])) / nrows)*100.0 << ")\n"
	 << "\t\tUsable Instances: " << nrows - nbTimeouts[s] - nbOtherErrors[s] << " (" << (((double)(nrows - nbTimeouts[s] - nbOtherErrors[s])) / nrows)*100.0 << ")\n";
  }

}

void MSZDataSet::dumpPlotFiles(char **labels, size_t len, char *prefix) const {

  vector<string> vec(len);

  for(size_t i = 0; i < len; i++)
    vec[i] = string(labels[i]);

  dumpPlotFiles(vec, string(prefix));
}

double MSZDataSet::getOutputValue(size_t row, size_t col) const {
  assert(row < nrows);
  assert(col < outputs);

  return matrix[row][col];
}

double MSZDataSet::getFeatureValue(size_t row, size_t col) const {
  assert(row < nrows);
  assert(col < ncols - outputs);

  return matrix[row][col+outputs];
}

void MSZDataSet::standardize() {

  cout << "Standardizing features ...";

  static bool stdDone = false;

  if(!stdDone) {
    for(size_t c = outputs; c < ncols; c++) {

      // Compute column mean and compute column variance.
      double mean = 0.0;
      for(size_t r = 0; r < nrows; r++)
	mean += matrix[r][c];
      mean /= nrows;

      // Compute column standard deviation.
      double sdv = 0.0;
      for(size_t r = 0; r < nrows; r++)
	sdv += gsl_pow_2(matrix[r][c] - mean);
      sdv /= nrows;

      for(size_t r = 0; r < nrows; r++)
	matrix[r][c] = (matrix[r][c] - mean) / sdv;

    }

  }
  stdDone = true;

  cout << "DONE\n";

}

void MSZDataSet::removeFeatures(const vector<size_t> &keepVec) {
  // We need to remove the feature indexes in vec from the current data.

  cout << "Pruning features from dataset: ";

  // Create the indices to remove
  vector<size_t> vec;
  for(size_t i = outputs; i < ncols; i++)
    if(find(keepVec.begin(), keepVec.end(), i-outputs) == keepVec.end())
      vec.push_back(i);

  if(vec.size() == 0) {
    cout << "NONE\n";
    return;
  } else {
    copy(vec.begin(), vec.end(), std::ostream_iterator<size_t>(cout, " "));
    cout << std::endl;
  }

  // Let's setup all the variables
  size_t currRawFeatures = rfeatures;
  size_t currCols = ncols;
  for(size_t i = 0; i < vec.size(); i++) {
    ncols--;
    if(vec[i] < currRawFeatures)
      rfeatures--;
  }

  // Now we need to recreate matrix.
  // KILL ME
  double **newMatrix = new double** [nrows];
  for(size_t r = 0; r < nrows; r++)
    newMatrix[r] = new double* [ncols];

  // Copy every column to the new matrix except those listed in vec.
  size_t destc = 0;
  for(size_t origc = 0; origc < currCols; origc++) {
    if(find(vec.begin(), vec.end(), origc) != vec.end())
      continue;
    assert(destc < ncols);
    for(size_t r = 0; r < nrows; r++)
      newMatrix[r][destc] = matrix[r][origc];
    destc++;
  }

  // free previous matrix
  for(size_t r = 0; r < nrows; r++)
    free(matrix[r]);
  free(matrix);

  matrix = newMatrix;
}

void MSZDataSet::standardizeOutputs() {

  cout << "Standardizing outputs... ";

  static bool stdDone = false;

  if(!stdDone) {
    for(size_t c = 0; c < outputs; c++)
      for(size_t r = 0; r < nrows; r++)
	matrix[r][c] = log(matrix[r][c]);
  }

  stdDone = true;

  cout <<  "DONE\n";

}

void MSZDataSet::expand(size_t n) {
  vector<size_t> pvec(ncols - outputs);
  for(size_t i = 0; i < pvec.size(); i++)
    pvec[i] = i;

  expandOnPartition(n, pvec);
}

void MSZDataSet::expand(size_t n, const vector<vector<size_t> > &pvec) {
  for(size_t i = 0; i < pvec.size(); i++)
    expandOnPartition(n, pvec[i]);
}

void MSZDataSet::expandOnPartition(size_t k, const vector<size_t> &pvec) {

  // expansion is quadratic at the minimum and
  // and be bigger than partition size.
  assert(k >= 2 && k <= pvec.size());

  // Standardize features
  standardize();

  // Reallocate the data.
  // If we have N features, then, to expand to a order-K polynomial
  // we are adding
  // n + (n !) / (k! (n-k!))
  size_t num = 1;
  for(size_t i = 0; i < k; i++) num *= rfeatures - i; // for big k hell breaks loose
  size_t den = 1;
  for(size_t i = k; i > 0; i--) den *= i;
  size_t nNewF = rfeatures;
  nNewF += num / den;
  ncols += nNewF; // Update number of columns

  // Now, we need to realloc all the structure
  for(size_t r = 0; r < nrows; r++) {
    matrix[r] = (double*)realloc(matrix[r], sizeof(**matrix) * (nNewF + ncols));
    if(matrix[r] == 0) {
      cerr << "Bad news... while trying to allocate memory...\n";
      exit(EXIT_FAILURE);
    }
  }

  // Compute the cross products
  // To do this we compute all the indices combinations and use them
  // to compute the cross product on columns defined in pvec.
  size_t currColumn = rfeatures + outputs;
  const size_t n = pvec.size();
  gsl_combination * c;
  c = gsl_combination_calloc (n, k);
  size_t *ind = new size_t [k];

  // Compute cross product for initial configuration
  // Now using the very nice combination structure from GSL.
  // Up to rev. 121, we used custom combination generator.
  do {
    for(size_t i = 0; i < k; i++)
      ind[i] = gsl_combination_get(c, i);

    // Compute cross product in current configuration
    for(size_t r = 0; r < nrows; r++) {
      matrix[r][currColumn] = computeCrossProduct(r, ind, k, pvec);
    }
    currColumn++;
  } while(gsl_combination_next (c) == GSL_SUCCESS);
  gsl_combination_free (c);
  delete ind;

  // Compute Powers
  for(size_t i = 0; i < pvec.size(); i++) {
    for(size_t r = 0; r < nrows; r++) {
      // Compute powers for pvec[i] feature
      matrix[r][currColumn] = gsl_pow_int(matrix[r][pvec[i]], k);
    }
  }

}

double MSZDataSet::computeCrossProduct(size_t r, size_t *ind, size_t k, const vector<size_t> &vec) {
  double cp = 1.0; // Cross-product
  for(size_t i = 0; i < k; i++)
   cp *= matrix[r][vec[ind[i]]];
  return cp;
}

/////////////////////////////////////////
/////////////////////////////////////////
//
// API Entrace Function for Data Set creation
//
/////////////////////////////////////////
/////////////////////////////////////////

MSZDataSet *createDataSet(double** matrix, size_t nrows, size_t ncols, size_t outputs) {
  assert(nrows > 0);
  assert(ncols > 0);
  assert(matrix != 0);
  assert(outputs > 0);
  assert(nrows >= ncols - outputs);

#ifndef NDEBUG
  for(size_t r = 0; r < nrows; r++)
    assert(matrix[r] != 0);
#endif // NDEBUG

  // The call!
  MSZDataSet *ds = new MSZDataSet(matrix, nrows, ncols, outputs);
  if(!ds) {
    cerr << "Error: Allocation of Dataset\n";
    exit(EXIT_FAILURE);
  }

  return ds;
}
<|endoftext|>


<commit_before>/**
 * \file dcs/testbed/base_sensor.hpp
 *
 * \brief Collect observations.
 *
 * \author Marco Guazzone (marco.guazzone@gmail.com)
 *
 *

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

#ifndef DCS_TESTBED_BASE_SENSOR_HPP
#define DCS_TESTBED_BASE_SENSOR_HPP

#include <dcs/testbed/sensor_observation.hpp>
#include <vector>

namespace dcs { namespace testbed {

template <typename TraitsT>
class base_sensor
{
	public: typedef TraitsT traits_type;
	public: typedef sensor_observation<traits_type> observation_type;

	public: void sense()
	{
		do_sense();
	}

	public: bool has_observations() const
	{
		return do_has_observations();
	}

	public: ::std::vector<observation_type> observations() const
	{
		return do_observations();
	}

	private: virtual void do_sense() = 0;

	private: virtual void do_reset() = 0;

	private: virtual bool do_has_observations() const = 0;

	private: virtual ::std::vector<observation_type> do_observations() const = 0;
}; // base_sensor

}} // Namespace dcs::testbed

#endif // DCS_TESTBED_BASE_SENSOR_HPP
<commit_msg>Improved doc<commit_after>/**
 * \file dcs/testbed/base_sensor.hpp
 *
 * \brief Class to model sensors for collecting observations.
 *
 * \author Marco Guazzone (marco.guazzone@gmail.com)
 *
 *

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

#ifndef DCS_TESTBED_BASE_SENSOR_HPP
#define DCS_TESTBED_BASE_SENSOR_HPP

#include <dcs/testbed/sensor_observation.hpp>
#include <vector>

namespace dcs { namespace testbed {

/**
 * \file dcs/testbed/base_sensor.hpp
 *
 * \brief Class to model sensors for collecting observations.
 *
 * \tparam TraitsT traits type.
 *
 * \author Marco Guazzone (marco.guazzone@gmail.com)
 */
template <typename TraitsT>
class base_sensor
{
	public: typedef TraitsT traits_type;
	public: typedef sensor_observation<traits_type> observation_type;

	/// Collect next available observations
	public: void sense()
	{
		do_sense();
	}

	/// Tells if some observations have been collected and are available to be consumed
	public: bool has_observations() const
	{
		return do_has_observations();
	}

	/// Returns the last collected observations
	public: ::std::vector<observation_type> observations() const
	{
		return do_observations();
	}

	/// Reset the state of this sensor
	public: void reset()
	{
		do_reset();
	}

	private: virtual void do_sense() = 0;

	private: virtual void do_reset() = 0;

	private: virtual bool do_has_observations() const = 0;

	private: virtual ::std::vector<observation_type> do_observations() const = 0;
}; // base_sensor

}} // Namespace dcs::testbed

#endif // DCS_TESTBED_BASE_SENSOR_HPP
<|endoftext|>


<commit_before>#ifndef INCLUDE_AL_FILE_HPP
#define INCLUDE_AL_FILE_HPP

/*	Allocore --
	Multimedia / virtual environment application class library

	Copyright (C) 2009. AlloSphere Research Group, Media Arts & Technology, UCSB.
	Copyright (C) 2006-2008. The Regents of the University of California (REGENTS).
	All Rights Reserved.

	Permission to use, copy, modify, distribute, and distribute modified versions
	of this software and its documentation without fee and without a signed
	licensing agreement, is hereby granted, provided that the above copyright
	notice, the list of contributors, this paragraph and the following two paragraphs
	appear in all copies, modifications, and distributions.

	IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
	SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
	OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
	BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

	REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
	THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
	PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
	HEREUNDER IS PROVIDED "AS IS". REGENTS HAS  NO OBLIGATION TO PROVIDE
	MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

	File description:
	Utilities for file management

	File author(s):
	Graham Wakefield, 2010, grrrwaaa@gmail.com
	Lance Putnam, 2010, putnam.lance@gmail.com
*/

#include <limits.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string>
#include <sys/stat.h>
#include <list>

#include "allocore/system/al_Config.h"

#ifdef AL_WIN32
	#define AL_FILE_DELIMITER		'\\'
	#define AL_FILE_DELIMITER_STR	"\\"
#else
	#define AL_FILE_DELIMITER		'/'
	#define AL_FILE_DELIMITER_STR	"/"
#endif

#define AL_PATH_MAX (4096)

namespace al{

// Strips a qualified path to a file (src) into a path to the containing folder (dst)
//void path2dir(char* dst, const char* src);

/// A pair of path (folder/directory) and file name
class FilePath {
public:
	FilePath(){}

	/// @param[in] file			File name without directory
	/// @param[in] path			Directory of file
	FilePath(const std::string& file, const std::string& path)
	:	mPath(path), mFile(file) {}

	/// @param[in] fullpath		Full path to file (directory + file name)
	explicit FilePath(std::string fullpath);

	/// Get file name without directory
	const std::string& file() const { return mFile; }

	/// Get path (directory) of file
	const std::string& path() const { return mPath; }

	/// Get file with directory
	std::string filepath() const { return path()+file(); }

	/// Returns whether file part is valid
	bool valid() const { return file()!=""; }

	/// Set file name without directory
	FilePath& file(const std::string& v) { mFile=v; return *this; }

	/// Set path (directory) of file
	FilePath& path(const std::string& v) { mPath=v; return *this; }

protected:
	std::string mPath;
	std::string mFile;
};

/// A handy way to manage several possible search paths
class SearchPaths {
public:
	typedef std::pair<std::string, bool> searchpath;
	typedef std::list<searchpath> searchpathlist;
	typedef std::list<searchpath>::iterator iterator;

	SearchPaths() {}
	SearchPaths(std::string file) {
		FilePath fp(file);
		addAppPaths(fp.path());
	}
	SearchPaths(int argc, char * const argv[], bool recursive=true) { addAppPaths(argc,argv,recursive); }
	SearchPaths(const SearchPaths& cpy)
	:	mSearchPaths(cpy.mSearchPaths),
		mAppPath(cpy.mAppPath)
	{}
	~SearchPaths() {}

	/// find a file in the searchpaths
	FilePath find(const std::string& filename) ;

	/// add a path to search in; recursive searching is optional
	void addSearchPath(const std::string& path, bool recursive = true);
	void addRelativePath(std::string rel, bool recursive=true) {
		addSearchPath(appPath() + rel, recursive);
	}

	/// adds best estimate of application launch paths (cwd etc.)
	/// can pass in argv from the main() function if desired.
	void addAppPaths(int argc, char * const argv[], bool recursive = true);
	void addAppPaths(int argc, const char ** argv, bool recursive = true);
	void addAppPaths(std::string path, bool recursive = true);
	void addAppPaths(bool recursive = true);

	const std::string& appPath() const { return mAppPath; }

	void print();

	iterator begin() { return mSearchPaths.begin(); }
	iterator end() { return mSearchPaths.end(); }

protected:
	std::list<searchpath> mSearchPaths;
	std::string mAppPath;
};

/// File
class File{
public:

	/// @param[in] path		path of file
	/// @param[in] mode		i/o mode w, r, wb, rb
	/// @param[in] open		whether to open the file
	File(const std::string& path, const std::string& mode="r", bool open=false);
	File(const FilePath& path, const std::string& mode="r", bool open=false);

	~File();

	void close();	///< Close file
	bool open();	///< Open file with specified i/o mode

	File& mode(const std::string& v){ mMode=v; return *this; }
	File& path(const std::string& v){ mPath=v; return *this; }

	/// Write memory elements to file
	int write(const std::string& v){ return write(v.data(), 1, v.length()); }
	int write(const void * v, int itemSizeInBytes, int items=1){
		int itemsWritten = fwrite(v, itemSizeInBytes, items, mFP);
		mSizeBytes += itemsWritten * itemSizeInBytes;
		return itemsWritten;
	}

	/// Read memory elements from file
	int read(void * v, int size, int items=1){ return fread(v, size, items, mFP); }

	/// Quick and dirty write memory to file
	static int write(const std::string& path, const void * v, int size, int items=1);

	/// Returns character string of file contents (read mode only)
	const char * readAll();

	/// Returns whether file is open
	bool opened() const { return 0 != mFP; }

	/// Returns file i/o mode string
	const std::string& mode() const { return mMode; }

	/// Returns path string
	const std::string& path() const { return mPath; }

	/// Returns size, in bytes, of file contents
	int size() const { return mSizeBytes; }

	/// Return modification time of file (or 0 on failure) as number of seconds since 00:00:00 january 1, 1970 UTC
	al_sec modified() const;

	/// Return last access time of file (or 0 on failure) as number of seconds since 00:00:00 january 1, 1970 UTC
	al_sec accessed() const;

	/// Return creation time of file (or 0 on failure) as number of seconds since 00:00:00 january 1, 1970 UTC
	al_sec created() const;

	/// Return size file (or 0 on failure)
	size_t sizeFile() const;

	/// Return space used on disk of file (or 0 on failure)
	size_t storage() const;

	FILE * filePointer() { return mFP; }

	/// Ensure path ends with the proper delimiter
	static std::string conformPath(const std::string& src);

	/// Convert relative paths to absolute paths
	static std::string absolutePath(const std::string& src);

	/// Extracts the directory-part of file name.

	/// The directory-part of the file name is everything up through (and
	/// including) the last slash in it. If the file name contains no slash,
	/// the directory part is the string ‘./’. E.g., /usr/bin/man -> /usr/bin/.
	static std::string directory(const std::string& src);

	/// Returns whether a file or directory exists
	static bool exists(const std::string& path);

	/// Returns whether a file in a directory exists
	static bool exists(const std::string& name, const std::string& path){
		return exists(path+name);
	}

	/// Search for file or directory back from current directory

	/// @param[out] prefixPath	If the file is found, this contains a series of
	///							"../" that can be prefixed to 'matchPath' to get
	///							its actual location.
	/// @param[in]  matchPath	File or directory to search for
	/// @param[in]  maxDepth	Maximum number of directories to search back
	/// \returns whether the file or directory was found
	static bool searchBack(std::string& prefixPath, const std::string& matchPath, int maxDepth=6);

	/// Search for file or directory back from current directory

	/// @param[in,out] path		Input is a file or directory to search for.
	///							If the file is found, the output contains a series of
	///							"../" prefixed to the input. Otherwise, the input
	///							path is not modified.
	/// @param[in]  maxDepth	Maximum number of directories to search back
	/// \returns whether the file or directory was found
	static bool searchBack(std::string& path, int maxDepth=6){
		std::string prefix = "";
		bool r = searchBack(prefix, path);
		if(r) path = prefix + path;
		return r;
	}

	static al_sec modified(std::string path) { File f(path); return f.modified(); }
	static al_sec accessed(std::string path) { File f(path); return f.accessed(); }
	static al_sec created(std::string path) { File f(path); return f.created(); }
	static size_t sizeFile(std::string path) { File f(path); return f.sizeFile(); }
	static size_t storage(std::string path) { File f(path); return f.storage(); }

protected:
	class Impl; Impl * mImpl;

	std::string mPath;
	std::string mMode;
	char * mContent;
	int mSizeBytes;
	FILE * mFP;

	void freeContent();
	void allocContent(int n);
	void getSize();
};

//// INLINE IMPLEMENTATION ////

inline std::string File::conformPath(const std::string& src) {
	std::string path(src);
	// paths should end with a delimiter:
	if (path[path.size()-1] != AL_FILE_DELIMITER) {
		path += AL_FILE_DELIMITER;
	}
	return path;
}

inline std::string File::absolutePath(const std::string& src) {
	char temp[PATH_MAX];
	char * result = realpath(src.c_str(), temp);
	return result ? result : "";
}

inline std::string File::directory(const std::string& src){
	size_t pos = src.find_last_of(AL_FILE_DELIMITER);
	if(std::string::npos != pos){
		return src.substr(0, pos+1);
	}
	return "."AL_FILE_DELIMITER_STR;
}

inline bool File::exists(const std::string& path){
	struct stat s;
	return ::stat(path.c_str(), &s) == 0;
}

inline bool File::searchBack(std::string& prefixPath, const std::string& matchPath, int maxDepth){
	int i=0;
	prefixPath="";

	for(; i<maxDepth; ++i){
		if(File::exists(prefixPath + matchPath)) break;
		prefixPath = ".."AL_FILE_DELIMITER_STR + prefixPath;
	}
	return i<maxDepth;
}

inline void SearchPaths::addAppPaths(std::string path, bool recursive) {
	std::string filepath = File::directory(path);
	mAppPath = filepath;
	addSearchPath(filepath, recursive);
}

inline void SearchPaths::addAppPaths(int argc, const char ** argv, bool recursive) {
	addAppPaths(recursive);
	if (argc > 0) {
		addAppPaths(File::directory(argv[0]), recursive);
	}
}

inline void SearchPaths::addAppPaths(int argc, char * const argv[], bool recursive) {
	addAppPaths(recursive);
	if (argc > 0) {
		addAppPaths(File::directory(argv[0]), recursive);
	}
}

inline void SearchPaths::addAppPaths(bool recursive) {
	char cwd[4096];
	if(getcwd(cwd, sizeof(cwd))){
		mAppPath = std::string(cwd) + "/";
		addSearchPath(mAppPath, recursive);
	}
}

inline void SearchPaths::addSearchPath(const std::string& src, bool recursive) {
	std::string path=File::conformPath(src);

	// check for duplicates
	std::list<searchpath>::iterator iter = mSearchPaths.begin();
	while (iter != mSearchPaths.end()) {
		//printf("path %s\n", iter->first.c_str());
		if (path == iter->first) {
			return;
		}
		iter++;
	}
//	printf("adding path %s\n", path.data());
	mSearchPaths.push_front(searchpath(path, recursive));
}

inline void SearchPaths::print() {
	printf("SearchPath %p appPath: %s\n", this, appPath().c_str());
	std::list<searchpath>::iterator it = mSearchPaths.begin();
	while (it != mSearchPaths.end()) {
		SearchPaths::searchpath sp = (*it++);
		printf("SearchPath %p path: %s (recursive: %d)\n", this, sp.first.c_str(), sp.second);
	}
}

} // al::

#endif

<commit_msg>Move File class to top<commit_after>#ifndef INCLUDE_AL_FILE_HPP
#define INCLUDE_AL_FILE_HPP

/*	Allocore --
	Multimedia / virtual environment application class library

	Copyright (C) 2009. AlloSphere Research Group, Media Arts & Technology, UCSB.
	Copyright (C) 2006-2008. The Regents of the University of California (REGENTS).
	All Rights Reserved.

	Permission to use, copy, modify, distribute, and distribute modified versions
	of this software and its documentation without fee and without a signed
	licensing agreement, is hereby granted, provided that the above copyright
	notice, the list of contributors, this paragraph and the following two paragraphs
	appear in all copies, modifications, and distributions.

	IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
	SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
	OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
	BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

	REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
	THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
	PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
	HEREUNDER IS PROVIDED "AS IS". REGENTS HAS  NO OBLIGATION TO PROVIDE
	MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

	File description:
	Utilities for file management

	File author(s):
	Graham Wakefield, 2010, grrrwaaa@gmail.com
	Lance Putnam, 2010, putnam.lance@gmail.com
*/

#include <limits.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string>
#include <sys/stat.h>
#include <list>

#include "allocore/system/al_Config.h"

#ifdef AL_WIN32
	#define AL_FILE_DELIMITER		'\\'
	#define AL_FILE_DELIMITER_STR	"\\"
#else
	#define AL_FILE_DELIMITER		'/'
	#define AL_FILE_DELIMITER_STR	"/"
#endif

#define AL_PATH_MAX (4096)

namespace al{

class FilePath;

/// File
class File{
public:

	/// @param[in] path		path of file
	/// @param[in] mode		i/o mode w, r, wb, rb
	/// @param[in] open		whether to open the file
	File(const std::string& path, const std::string& mode="r", bool open=false);
	File(const FilePath& path, const std::string& mode="r", bool open=false);

	~File();

	void close();	///< Close file
	bool open();	///< Open file with specified i/o mode

	File& mode(const std::string& v){ mMode=v; return *this; }
	File& path(const std::string& v){ mPath=v; return *this; }

	/// Write memory elements to file
	int write(const std::string& v){ return write(v.data(), 1, v.length()); }
	int write(const void * v, int itemSizeInBytes, int items=1){
		int itemsWritten = fwrite(v, itemSizeInBytes, items, mFP);
		mSizeBytes += itemsWritten * itemSizeInBytes;
		return itemsWritten;
	}

	/// Read memory elements from file
	int read(void * v, int size, int items=1){ return fread(v, size, items, mFP); }

	/// Quick and dirty write memory to file
	static int write(const std::string& path, const void * v, int size, int items=1);

	/// Returns character string of file contents (read mode only)
	const char * readAll();

	/// Returns whether file is open
	bool opened() const { return 0 != mFP; }

	/// Returns file i/o mode string
	const std::string& mode() const { return mMode; }

	/// Returns path string
	const std::string& path() const { return mPath; }

	/// Returns size, in bytes, of file contents
	int size() const { return mSizeBytes; }

	/// Return modification time of file (or 0 on failure) as number of seconds since 00:00:00 january 1, 1970 UTC
	al_sec modified() const;

	/// Return last access time of file (or 0 on failure) as number of seconds since 00:00:00 january 1, 1970 UTC
	al_sec accessed() const;

	/// Return creation time of file (or 0 on failure) as number of seconds since 00:00:00 january 1, 1970 UTC
	al_sec created() const;

	/// Return size file (or 0 on failure)
	size_t sizeFile() const;

	/// Return space used on disk of file (or 0 on failure)
	size_t storage() const;

	FILE * filePointer() { return mFP; }

	/// Ensure path ends with the proper delimiter
	static std::string conformPath(const std::string& src);

	/// Convert relative paths to absolute paths
	static std::string absolutePath(const std::string& src);

	/// Extracts the directory-part of file name.

	/// The directory-part of the file name is everything up through (and
	/// including) the last slash in it. If the file name contains no slash,
	/// the directory part is the string ‘./’. E.g., /usr/bin/man -> /usr/bin/.
	static std::string directory(const std::string& src);

	/// Returns whether a file or directory exists
	static bool exists(const std::string& path);

	/// Returns whether a file in a directory exists
	static bool exists(const std::string& name, const std::string& path){
		return exists(path+name);
	}

	/// Search for file or directory back from current directory

	/// @param[out] prefixPath	If the file is found, this contains a series of
	///							"../" that can be prefixed to 'matchPath' to get
	///							its actual location.
	/// @param[in]  matchPath	File or directory to search for
	/// @param[in]  maxDepth	Maximum number of directories to search back
	/// \returns whether the file or directory was found
	static bool searchBack(std::string& prefixPath, const std::string& matchPath, int maxDepth=6);

	/// Search for file or directory back from current directory

	/// @param[in,out] path		Input is a file or directory to search for.
	///							If the file is found, the output contains a series of
	///							"../" prefixed to the input. Otherwise, the input
	///							path is not modified.
	/// @param[in]  maxDepth	Maximum number of directories to search back
	/// \returns whether the file or directory was found
	static bool searchBack(std::string& path, int maxDepth=6){
		std::string prefix = "";
		bool r = searchBack(prefix, path);
		if(r) path = prefix + path;
		return r;
	}

	static al_sec modified(std::string path) { File f(path); return f.modified(); }
	static al_sec accessed(std::string path) { File f(path); return f.accessed(); }
	static al_sec created(std::string path) { File f(path); return f.created(); }
	static size_t sizeFile(std::string path) { File f(path); return f.sizeFile(); }
	static size_t storage(std::string path) { File f(path); return f.storage(); }

protected:
	class Impl; Impl * mImpl;

	std::string mPath;
	std::string mMode;
	char * mContent;
	int mSizeBytes;
	FILE * mFP;

	void freeContent();
	void allocContent(int n);
	void getSize();
};

/// A pair of path (folder/directory) and file name
class FilePath {
public:
	FilePath(){}

	/// @param[in] file			File name without directory
	/// @param[in] path			Directory of file
	FilePath(const std::string& file, const std::string& path)
	:	mPath(path), mFile(file) {}

	/// @param[in] fullpath		Full path to file (directory + file name)
	explicit FilePath(std::string fullpath);

	/// Get file name without directory
	const std::string& file() const { return mFile; }

	/// Get path (directory) of file
	const std::string& path() const { return mPath; }

	/// Get file with directory
	std::string filepath() const { return path()+file(); }

	/// Returns whether file part is valid
	bool valid() const { return file()!=""; }

	/// Set file name without directory
	FilePath& file(const std::string& v) { mFile=v; return *this; }

	/// Set path (directory) of file
	FilePath& path(const std::string& v) { mPath=v; return *this; }

protected:
	std::string mPath;
	std::string mFile;
};

/// A handy way to manage several possible search paths
class SearchPaths {
public:
	typedef std::pair<std::string, bool> searchpath;
	typedef std::list<searchpath> searchpathlist;
	typedef std::list<searchpath>::iterator iterator;

	SearchPaths() {}
	SearchPaths(std::string file) {
		FilePath fp(file);
		addAppPaths(fp.path());
	}
	SearchPaths(int argc, char * const argv[], bool recursive=true) { addAppPaths(argc,argv,recursive); }
	SearchPaths(const SearchPaths& cpy)
	:	mSearchPaths(cpy.mSearchPaths),
		mAppPath(cpy.mAppPath)
	{}
	~SearchPaths() {}

	/// find a file in the searchpaths
	FilePath find(const std::string& filename) ;

	/// add a path to search in; recursive searching is optional
	void addSearchPath(const std::string& path, bool recursive = true);
	void addRelativePath(std::string rel, bool recursive=true) {
		addSearchPath(appPath() + rel, recursive);
	}

	/// adds best estimate of application launch paths (cwd etc.)
	/// can pass in argv from the main() function if desired.
	void addAppPaths(int argc, char * const argv[], bool recursive = true);
	void addAppPaths(int argc, const char ** argv, bool recursive = true);
	void addAppPaths(std::string path, bool recursive = true);
	void addAppPaths(bool recursive = true);

	const std::string& appPath() const { return mAppPath; }

	void print();

	iterator begin() { return mSearchPaths.begin(); }
	iterator end() { return mSearchPaths.end(); }

protected:
	std::list<searchpath> mSearchPaths;
	std::string mAppPath;
};

//// INLINE IMPLEMENTATION ////

inline std::string File::conformPath(const std::string& src) {
	std::string path(src);
	// paths should end with a delimiter:
	if (path[path.size()-1] != AL_FILE_DELIMITER) {
		path += AL_FILE_DELIMITER;
	}
	return path;
}

inline std::string File::absolutePath(const std::string& src) {
	char temp[PATH_MAX];
	char * result = realpath(src.c_str(), temp);
	return result ? result : "";
}

inline std::string File::directory(const std::string& src){
	size_t pos = src.find_last_of(AL_FILE_DELIMITER);
	if(std::string::npos != pos){
		return src.substr(0, pos+1);
	}
	return "."AL_FILE_DELIMITER_STR;
}

inline bool File::exists(const std::string& path){
	struct stat s;
	return ::stat(path.c_str(), &s) == 0;
}

inline bool File::searchBack(std::string& prefixPath, const std::string& matchPath, int maxDepth){
	int i=0;
	prefixPath="";

	for(; i<maxDepth; ++i){
		if(File::exists(prefixPath + matchPath)) break;
		prefixPath = ".."AL_FILE_DELIMITER_STR + prefixPath;
	}
	return i<maxDepth;
}

inline void SearchPaths::addAppPaths(std::string path, bool recursive) {
	std::string filepath = File::directory(path);
	mAppPath = filepath;
	addSearchPath(filepath, recursive);
}

inline void SearchPaths::addAppPaths(int argc, const char ** argv, bool recursive) {
	addAppPaths(recursive);
	if (argc > 0) {
		addAppPaths(File::directory(argv[0]), recursive);
	}
}

inline void SearchPaths::addAppPaths(int argc, char * const argv[], bool recursive) {
	addAppPaths(recursive);
	if (argc > 0) {
		addAppPaths(File::directory(argv[0]), recursive);
	}
}

inline void SearchPaths::addAppPaths(bool recursive) {
	char cwd[4096];
	if(getcwd(cwd, sizeof(cwd))){
		mAppPath = std::string(cwd) + "/";
		addSearchPath(mAppPath, recursive);
	}
}

inline void SearchPaths::addSearchPath(const std::string& src, bool recursive) {
	std::string path=File::conformPath(src);

	// check for duplicates
	std::list<searchpath>::iterator iter = mSearchPaths.begin();
	while (iter != mSearchPaths.end()) {
		//printf("path %s\n", iter->first.c_str());
		if (path == iter->first) {
			return;
		}
		iter++;
	}
//	printf("adding path %s\n", path.data());
	mSearchPaths.push_front(searchpath(path, recursive));
}

inline void SearchPaths::print() {
	printf("SearchPath %p appPath: %s\n", this, appPath().c_str());
	std::list<searchpath>::iterator it = mSearchPaths.begin();
	while (it != mSearchPaths.end()) {
		SearchPaths::searchpath sp = (*it++);
		printf("SearchPath %p path: %s (recursive: %d)\n", this, sp.first.c_str(), sp.second);
	}
}

} // al::

#endif

<|endoftext|>


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

#ifndef __ros1_bridge__factory__hpp__
#define __ros1_bridge__factory__hpp__

#include <functional>

// include ROS 1 message event
#include <ros/message.h>

#include <ros1_bridge/factory_interface.hpp>

namespace ros1_bridge
{

template<typename ROS1_T, typename ROS2_T>
class Factory : public FactoryInterface
{
public:
  ros::Publisher
  create_ros1_publisher(
    ros::NodeHandle node,
    const std::string & topic_name,
    size_t queue_size)
  {
    return node.advertise<ROS1_T>(topic_name, queue_size);
  }

  rclcpp::publisher::Publisher::SharedPtr
  create_ros2_publisher(
    rclcpp::node::Node::SharedPtr node,
    const std::string & topic_name,
    size_t queue_size)
  {
    rmw_qos_profile_t custom_qos_profile = rmw_qos_profile_default;
    custom_qos_profile.depth = queue_size;
    return node->create_publisher<ROS2_T>(topic_name, custom_qos_profile);
  }

  ros::Subscriber
  create_ros1_subscriber(
    ros::NodeHandle node,
    const std::string & topic_name,
    size_t queue_size,
    rclcpp::publisher::Publisher::SharedPtr ros2_pub)
  {
    // workaround for https://github.com/ros/roscpp_core/issues/22 to get the connection header
    ros::SubscribeOptions ops;
    ops.topic = topic_name;
    ops.queue_size = queue_size;
    ops.md5sum = ros::message_traits::md5sum<ROS1_T>();
    ops.datatype = ros::message_traits::datatype<ROS1_T>();
    ops.helper = ros::SubscriptionCallbackHelperPtr(
      new ros::SubscriptionCallbackHelperT<const ros::MessageEvent<ROS1_T const>&>(
        boost::bind(&Factory<ROS1_T, ROS2_T>::ros1_callback, _1, ros2_pub)
      )
    );
    return node.subscribe(ops);
  }

  rclcpp::subscription::SubscriptionBase::SharedPtr
  create_ros2_subscriber(
    rclcpp::node::Node::SharedPtr node,
    const std::string & topic_name,
    size_t queue_size,
    ros::Publisher ros1_pub)
  {
    rmw_qos_profile_t custom_qos_profile = rmw_qos_profile_default;
    custom_qos_profile.depth = queue_size;
    // TODO(wjwwood): use a lambda until create_subscription supports std/boost::bind.
    auto callback = [this, ros1_pub](const typename ROS2_T::SharedPtr msg) {
      return this->ros2_callback(msg, ros1_pub);
    };
    return node->create_subscription<ROS2_T>(
      topic_name, custom_qos_profile, callback, nullptr, true);
  }

protected:

  static
  void ros1_callback(
    const ros::MessageEvent<ROS1_T const> & ros1_msg_event,
    rclcpp::publisher::Publisher::SharedPtr ros2_pub
    )
  {
    const boost::shared_ptr<ros::M_string> & connection_header = ros1_msg_event.getConnectionHeaderPtr();
    if (!connection_header) {
      printf("  dropping message without connection header\n");
      return;
    }

    std::string key = "callerid";
    if (connection_header->find(key) != connection_header->end()) {
      if (connection_header->at(key) == "/ros_bridge") {
        return;
      }
    }

    const boost::shared_ptr<ROS1_T const> & ros1_msg = ros1_msg_event.getConstMessage();

    auto ros2_msg = std::make_shared<ROS2_T>();
    convert_1_to_2(*ros1_msg, *ros2_msg);
    printf("  Passing message from ROS 1 to ROS 2\n");
    ros2_pub->publish(ros2_msg);
  }

  static
  void ros2_callback(
    typename ROS2_T::SharedPtr ros2_msg,
    ros::Publisher ros1_pub
    )
  {
    ROS1_T ros1_msg;
    convert_2_to_1(*ros2_msg, ros1_msg);
    printf("  Passing message from ROS 2 to ROS 1\n");
    ros1_pub.publish(ros1_msg);
  }

// since convert functions call each other for sub messages they must be public
public:

  // defined outside of the class
  static
  void
  convert_1_to_2(
    const ROS1_T & ros1_msg,
    ROS2_T & ros2_msg);
  static
  void
  convert_2_to_1(
    const ROS2_T & ros2_msg,
    ROS1_T & ros1_msg);
};

}  // namespace ros1_bridge

#endif // __ros1_bridge__factory__hpp__
<commit_msg>use sensor profile since messages might be large which is not implemented in all rmw impl for reliable qos<commit_after>// Copyright 2015 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef __ros1_bridge__factory__hpp__
#define __ros1_bridge__factory__hpp__

#include <functional>

// include ROS 1 message event
#include <ros/message.h>

#include <ros1_bridge/factory_interface.hpp>

namespace ros1_bridge
{

template<typename ROS1_T, typename ROS2_T>
class Factory : public FactoryInterface
{
public:
  ros::Publisher
  create_ros1_publisher(
    ros::NodeHandle node,
    const std::string & topic_name,
    size_t queue_size)
  {
    return node.advertise<ROS1_T>(topic_name, queue_size);
  }

  rclcpp::publisher::Publisher::SharedPtr
  create_ros2_publisher(
    rclcpp::node::Node::SharedPtr node,
    const std::string & topic_name,
    size_t queue_size)
  {
    rmw_qos_profile_t custom_qos_profile = rmw_qos_profile_sensor_data;
    custom_qos_profile.depth = queue_size;
    return node->create_publisher<ROS2_T>(topic_name, custom_qos_profile);
  }

  ros::Subscriber
  create_ros1_subscriber(
    ros::NodeHandle node,
    const std::string & topic_name,
    size_t queue_size,
    rclcpp::publisher::Publisher::SharedPtr ros2_pub)
  {
    // workaround for https://github.com/ros/roscpp_core/issues/22 to get the connection header
    ros::SubscribeOptions ops;
    ops.topic = topic_name;
    ops.queue_size = queue_size;
    ops.md5sum = ros::message_traits::md5sum<ROS1_T>();
    ops.datatype = ros::message_traits::datatype<ROS1_T>();
    ops.helper = ros::SubscriptionCallbackHelperPtr(
      new ros::SubscriptionCallbackHelperT<const ros::MessageEvent<ROS1_T const>&>(
        boost::bind(&Factory<ROS1_T, ROS2_T>::ros1_callback, _1, ros2_pub)
      )
    );
    return node.subscribe(ops);
  }

  rclcpp::subscription::SubscriptionBase::SharedPtr
  create_ros2_subscriber(
    rclcpp::node::Node::SharedPtr node,
    const std::string & topic_name,
    size_t queue_size,
    ros::Publisher ros1_pub)
  {
    rmw_qos_profile_t custom_qos_profile = rmw_qos_profile_sensor_data;
    custom_qos_profile.depth = queue_size;
    // TODO(wjwwood): use a lambda until create_subscription supports std/boost::bind.
    auto callback = [this, ros1_pub](const typename ROS2_T::SharedPtr msg) {
      return this->ros2_callback(msg, ros1_pub);
    };
    return node->create_subscription<ROS2_T>(
      topic_name, custom_qos_profile, callback, nullptr, true);
  }

protected:

  static
  void ros1_callback(
    const ros::MessageEvent<ROS1_T const> & ros1_msg_event,
    rclcpp::publisher::Publisher::SharedPtr ros2_pub
    )
  {
    const boost::shared_ptr<ros::M_string> & connection_header = ros1_msg_event.getConnectionHeaderPtr();
    if (!connection_header) {
      printf("  dropping message without connection header\n");
      return;
    }

    std::string key = "callerid";
    if (connection_header->find(key) != connection_header->end()) {
      if (connection_header->at(key) == "/ros_bridge") {
        return;
      }
    }

    const boost::shared_ptr<ROS1_T const> & ros1_msg = ros1_msg_event.getConstMessage();

    auto ros2_msg = std::make_shared<ROS2_T>();
    convert_1_to_2(*ros1_msg, *ros2_msg);
    printf("  Passing message from ROS 1 to ROS 2\n");
    ros2_pub->publish(ros2_msg);
  }

  static
  void ros2_callback(
    typename ROS2_T::SharedPtr ros2_msg,
    ros::Publisher ros1_pub
    )
  {
    ROS1_T ros1_msg;
    convert_2_to_1(*ros2_msg, ros1_msg);
    printf("  Passing message from ROS 2 to ROS 1\n");
    ros1_pub.publish(ros1_msg);
  }

// since convert functions call each other for sub messages they must be public
public:

  // defined outside of the class
  static
  void
  convert_1_to_2(
    const ROS1_T & ros1_msg,
    ROS2_T & ros2_msg);
  static
  void
  convert_2_to_1(
    const ROS2_T & ros2_msg,
    ROS1_T & ros1_msg);
};

}  // namespace ros1_bridge

#endif // __ros1_bridge__factory__hpp__
<|endoftext|>


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

#ifndef __ros1_bridge__factory__hpp__
#define __ros1_bridge__factory__hpp__

#include <functional>

// include ROS 1 message event
#include <ros/message.h>

#include <ros1_bridge/factory_interface.hpp>

namespace ros1_bridge
{

template<typename ROS1_T, typename ROS2_T>
class Factory : public FactoryInterface
{
public:
  ros::Publisher
  create_ros1_publisher(
    ros::NodeHandle node,
    const std::string & topic_name,
    size_t queue_size)
  {
    return node.advertise<ROS1_T>(topic_name, queue_size);
  }

  rclcpp::publisher::Publisher::SharedPtr
  create_ros2_publisher(
    rclcpp::node::Node::SharedPtr node,
    const std::string & topic_name,
    size_t queue_size)
  {
    rmw_qos_profile_t custom_qos_profile = rmw_qos_profile_default;
    custom_qos_profile.depth = queue_size;
    return node->create_publisher<ROS2_T>(topic_name, custom_qos_profile);
  }

  ros::Subscriber
  create_ros1_subscriber(
    ros::NodeHandle node,
    const std::string & topic_name,
    size_t queue_size,
    rclcpp::publisher::Publisher::SharedPtr ros2_pub)
  {
    // workaround for https://github.com/ros/roscpp_core/issues/22 to get the connection header
    ros::SubscribeOptions ops;
    ops.topic = topic_name;
    ops.queue_size = queue_size;
    ops.md5sum = ros::message_traits::md5sum<ROS1_T>();
    ops.datatype = ros::message_traits::datatype<ROS1_T>();
    ops.helper = ros::SubscriptionCallbackHelperPtr(
      new ros::SubscriptionCallbackHelperT<const ros::MessageEvent<ROS1_T const>&>(
        boost::bind(&Factory<ROS1_T, ROS2_T>::ros1_callback, _1, ros2_pub)
      )
    );
    return node.subscribe(ops);
  }

  rclcpp::subscription::SubscriptionBase::SharedPtr
  create_ros2_subscriber(
    rclcpp::node::Node::SharedPtr node,
    const std::string & topic_name,
    size_t queue_size,
    ros::Publisher ros1_pub)
  {
    rmw_qos_profile_t custom_qos_profile = rmw_qos_profile_default;
    custom_qos_profile.depth = queue_size;
    auto callback = [this, ros1_pub](const typename ROS2_T::SharedPtr msg) {
      return this->ros2_callback(msg, ros1_pub);
    };
    return node->create_subscription<ROS2_T>(
      topic_name, custom_qos_profile, callback, nullptr, true);
  }

protected:

  static
  void ros1_callback(
    const ros::MessageEvent<ROS1_T const> & ros1_msg_event,
    rclcpp::publisher::Publisher::SharedPtr ros2_pub
    )
  {
    const boost::shared_ptr<ros::M_string> & connection_header = ros1_msg_event.getConnectionHeaderPtr();
    if (!connection_header) {
      printf("  dropping message without connection header\n");
      return;
    }

    std::string key = "callerid";
    if (connection_header->find(key) != connection_header->end()) {
      if (connection_header->at(key) == "/ros_bridge") {
        return;
      }
    }

    const boost::shared_ptr<ROS1_T const> & ros1_msg = ros1_msg_event.getConstMessage();

    auto ros2_msg = std::make_shared<ROS2_T>();
    convert_1_to_2(*ros1_msg, *ros2_msg);
    printf("  Passing message from ROS 1 to ROS 2\n");
    ros2_pub->publish(ros2_msg);
  }

  static
  void ros2_callback(
    typename ROS2_T::SharedPtr ros2_msg,
    ros::Publisher ros1_pub
    )
  {
    ROS1_T ros1_msg;
    convert_2_to_1(*ros2_msg, ros1_msg);
    printf("  Passing message from ROS 2 to ROS 1\n");
    ros1_pub.publish(ros1_msg);
  }

// since convert functions call each other for sub messages they must be public
public:

  // defined outside of the class
  static
  void
  convert_1_to_2(
    const ROS1_T & ros1_msg,
    ROS2_T & ros2_msg);
  static
  void
  convert_2_to_1(
    const ROS2_T & ros2_msg,
    ROS1_T & ros1_msg);
};

}  // namespace ros1_bridge

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

#ifndef __ros1_bridge__factory__hpp__
#define __ros1_bridge__factory__hpp__

#include <functional>

// include ROS 1 message event
#include <ros/message.h>

#include <ros1_bridge/factory_interface.hpp>

namespace ros1_bridge
{

template<typename ROS1_T, typename ROS2_T>
class Factory : public FactoryInterface
{
public:
  ros::Publisher
  create_ros1_publisher(
    ros::NodeHandle node,
    const std::string & topic_name,
    size_t queue_size)
  {
    return node.advertise<ROS1_T>(topic_name, queue_size);
  }

  rclcpp::publisher::Publisher::SharedPtr
  create_ros2_publisher(
    rclcpp::node::Node::SharedPtr node,
    const std::string & topic_name,
    size_t queue_size)
  {
    rmw_qos_profile_t custom_qos_profile = rmw_qos_profile_default;
    custom_qos_profile.depth = queue_size;
    return node->create_publisher<ROS2_T>(topic_name, custom_qos_profile);
  }

  ros::Subscriber
  create_ros1_subscriber(
    ros::NodeHandle node,
    const std::string & topic_name,
    size_t queue_size,
    rclcpp::publisher::Publisher::SharedPtr ros2_pub)
  {
    // workaround for https://github.com/ros/roscpp_core/issues/22 to get the connection header
    ros::SubscribeOptions ops;
    ops.topic = topic_name;
    ops.queue_size = queue_size;
    ops.md5sum = ros::message_traits::md5sum<ROS1_T>();
    ops.datatype = ros::message_traits::datatype<ROS1_T>();
    ops.helper = ros::SubscriptionCallbackHelperPtr(
      new ros::SubscriptionCallbackHelperT<const ros::MessageEvent<ROS1_T const>&>(
        boost::bind(&Factory<ROS1_T, ROS2_T>::ros1_callback, _1, ros2_pub)
      )
    );
    return node.subscribe(ops);
  }

  rclcpp::subscription::SubscriptionBase::SharedPtr
  create_ros2_subscriber(
    rclcpp::node::Node::SharedPtr node,
    const std::string & topic_name,
    size_t queue_size,
    ros::Publisher ros1_pub)
  {
    rmw_qos_profile_t custom_qos_profile = rmw_qos_profile_default;
    custom_qos_profile.depth = queue_size;
    // TODO(wjwwood): use a lambda until create_subscription supports std/boost::bind.
    auto callback = [this, ros1_pub](const typename ROS2_T::SharedPtr msg) {
      return this->ros2_callback(msg, ros1_pub);
    };
    return node->create_subscription<ROS2_T>(
      topic_name, custom_qos_profile, callback, nullptr, true);
  }

protected:

  static
  void ros1_callback(
    const ros::MessageEvent<ROS1_T const> & ros1_msg_event,
    rclcpp::publisher::Publisher::SharedPtr ros2_pub
    )
  {
    const boost::shared_ptr<ros::M_string> & connection_header = ros1_msg_event.getConnectionHeaderPtr();
    if (!connection_header) {
      printf("  dropping message without connection header\n");
      return;
    }

    std::string key = "callerid";
    if (connection_header->find(key) != connection_header->end()) {
      if (connection_header->at(key) == "/ros_bridge") {
        return;
      }
    }

    const boost::shared_ptr<ROS1_T const> & ros1_msg = ros1_msg_event.getConstMessage();

    auto ros2_msg = std::make_shared<ROS2_T>();
    convert_1_to_2(*ros1_msg, *ros2_msg);
    printf("  Passing message from ROS 1 to ROS 2\n");
    ros2_pub->publish(ros2_msg);
  }

  static
  void ros2_callback(
    typename ROS2_T::SharedPtr ros2_msg,
    ros::Publisher ros1_pub
    )
  {
    ROS1_T ros1_msg;
    convert_2_to_1(*ros2_msg, ros1_msg);
    printf("  Passing message from ROS 2 to ROS 1\n");
    ros1_pub.publish(ros1_msg);
  }

// since convert functions call each other for sub messages they must be public
public:

  // defined outside of the class
  static
  void
  convert_1_to_2(
    const ROS1_T & ros1_msg,
    ROS2_T & ros2_msg);
  static
  void
  convert_2_to_1(
    const ROS2_T & ros2_msg,
    ROS1_T & ros1_msg);
};

}  // namespace ros1_bridge

#endif // __ros1_bridge__factory__hpp__
<|endoftext|>