<commit_before>#include "CurlClient.h"

#include "BasicAuth.h"

#include <cstdio>
#include <cstring>
#include <cassert>
#include <cctype>
#include <iostream>
#include <pthread.h>

using namespace std;

#include <curl/curl.h>

class CurlClient : public HTTPClient {
 public:
  CurlClient(const std::string & _interface, const std::string & _user_agent, bool _enable_cookies = true, bool _enable_keepalive = true)
    : HTTPClient(_user_agent, _enable_cookies, _enable_keepalive),
      interface_name(_interface)
  {

  }
  CurlClient(const CurlClient & other) : HTTPClient(other),
					 interface_name(other.interface_name)
  {

  }

  ~CurlClient() {
    if (curl) curl_easy_cleanup(curl);
  }

  HTTPResponse request(const HTTPRequest & req, const Authorization & auth) override;

  void clearCookies() override;

 protected:
  bool initialize();

 private:
  bool handleProgress(double dltotal, double dlnow, double ultotal, double ulnow);

  static size_t write_data_func(void * buffer, size_t size, size_t nmemb, void *userp);
  static size_t headers_func(void * buffer, size_t size, size_t nmemb, void *userp);
  static int progress_func(void *  clientp, double dltotal, double dlnow, double ultotal, double ulnow);

  std::string interface_name;
  CURL * curl = 0;
};

bool
CurlClient::initialize() {
  if (curl) {
    curl_easy_reset(curl);
    data_out.clear();
    data_out.shrink_to_fit();
  } else {
    curl = curl_easy_init();
  }

  assert(curl);

  if (curl) {
#ifndef WIN32
    if (!interface_name.empty()) {
      int r = curl_easy_setopt(curl, CURLOPT_INTERFACE, interface_name.c_str());
      assert(r != CURLE_INTERFACE_FAILED);
    }
#endif
    curl_easy_setopt(curl, CURLOPT_USERAGENT, user_agent.c_str());
    curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data_func);
    curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_func);
    curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, headers_func);
    curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, this);
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30);
    curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
    curl_easy_setopt(curl, CURLOPT_DNS_CACHE_TIMEOUT, 600);
    // curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
    if (!enable_keepalive) {
      curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1);
      curl_easy_setopt(curl, CURLOPT_FORBID_REUSE, 1);
    }
    if (!cookie_jar.empty()) {
      curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookie_jar.c_str());
      curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookie_jar.c_str());
    } else if (enable_cookies) {
      curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "");
    }
    // curl_easy_setopt(curl, CURLOPT_MAXCONNECTS, 10);

  }

  return curl != 0;
}

HTTPResponse
CurlClient::request(const HTTPRequest & req, const Authorization & auth) {
  if (req.getURI().empty()) {
    return HTTPResponse(0, "empty URI");
  }
  if (!initialize()) {
    return HTTPResponse(0, "Unable to initialize client");
  }

  // string ascii_uri = encodeIDN(uri);
  // if (ascii_uri.empty()) {
  //   cerr << "failed to convert url " << uri << endl;
  //   assert(0);
  // }

  struct curl_slist * headers = 0;
  if (req.getType() == HTTPRequest::POST) {
    data_out = req.getContent();

    if (!req.getContentType().empty()) {
      string h = "Content-type: ";
      h += req.getContentType();
      headers = curl_slist_append(headers, h.c_str());
    }
  } else {
    data_out.clear();
  }

  const BasicAuth * basic = dynamic_cast<const BasicAuth *>(&auth);
  if (basic) {
    string s = basic->getUsername();
    s += ':';
    s += basic->getPassword();
    curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
    curl_easy_setopt(curl, CURLOPT_USERPWD, s.c_str());
  } else {
    string auth_header = auth.createHeader();
    if (!auth_header.empty()) {
      string s = auth.getHeaderName();
      s += ": ";
      s += auth_header;
      headers = curl_slist_append(headers, s.c_str());
    }
  }

  for (auto & hd : req.getHeaders()) {
    string s = hd.first;
    s += ": ";
    s += hd.second;
    headers = curl_slist_append(headers, s.c_str());
  }

  HTTPResponse response;
  response.setCallback(callback);

  if (req.getType() == HTTPRequest::POST) {
    curl_easy_setopt(curl, CURLOPT_POST, 1);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data_out.data());
    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, data_out.size());
  } else {
    curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
  }
  curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, req.getFollowLocation());
  curl_easy_setopt(curl, CURLOPT_URL, req.getURI().c_str());
  curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
  curl_easy_setopt(curl, CURLOPT_TIMEOUT, req.getTimeout());
  curl_easy_setopt(curl, CURLOPT_HEADERDATA, &response);
  curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
  if (!cookie_jar.empty()) {
    curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookie_jar.c_str());
    curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookie_jar.c_str());
  }

  CURLcode res = curl_easy_perform(curl);
  if (res == 0) {
    unsigned long a = 0;
    if (curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &a) == CURLE_OK) {
      response.setResultCode(a);
    }
    if (!req.getFollowLocation()) {
      char * ptr = 0;
      curl_easy_getinfo(curl, CURLINFO_REDIRECT_URL, &ptr);
      if (ptr) {
	response.setRedirectUrl(ptr);
      }
    }
  } else {
    response.setErrorText(curl_easy_strerror(res));
  }

  if (headers) {
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, 0);
    curl_slist_free_all(headers);
  }

  return response;
}

bool
CurlClient::handleProgress(double dltotal, double dlnow, double ultotal, double ulnow) {
  if (callback) {
    return callback->onIdle(true);
  }
  return true;
}

size_t
CurlClient::write_data_func(void * buffer, size_t size, size_t nmemb, void * userp) {
  size_t s = size * nmemb;
#if 0
  CurlClient * client = static_cast<CurlClient *>(userp);
  assert(client);
  if (client->addToData((int)s, (char *)buffer)) {
    return s;
  } else {
    return 0;
  }
#else
  // Content-Type: multipart/x-mixed-replace; boundary=myboundary

  HTTPResponse * response = static_cast<HTTPResponse *>(userp);
  assert(response);
  if (response->getCallback()) {
    if (response->getCallback()->handleChunk(s, (const char *)buffer)) {
      return s;
    } else {
      return 0;
    }
  } else {
    response->appendContent(string((const char *)buffer, s));
    return s;
  }
#endif
}

// bool
// CurlClient::addToData(size_t len, const char * data) {
//   if (callback) {
//     return callback->handleChunk(len, data);
//   } else {
//     data_in += string(data, len);
//     return true;
//   }
// }

size_t
CurlClient::headers_func(void * buffer, size_t size, size_t nmemb, void *userp) {
  HTTPResponse * response = static_cast<HTTPResponse *>(userp);

  int result = 0;
  if (buffer) {
    string s((const char*)buffer, size * nmemb);
    int pos1 = 0;
    for ( ; pos1 < s.size() && s[pos1] != ':'; pos1++) { }
    int pos2 = s[pos1] == ':' ? pos1 + 1 : pos1;
    for (; pos2 < s.size() && isspace(s[pos2]); pos2++) { }
    int pos3 = s.size();
    for (; pos3 > 0 && isspace(s[pos3 - 1]); pos3--) { }
    std::string key = s.substr(0, pos1);
    std::string value = s.substr(pos2, pos3 - pos2);

    // cerr << "got header: " << key << " " << value << endl;

    if (response->getCallback()) {
      response->getCallback()->handleHeader(key, value);
    } else {
      response->addHeader(key, value);
    }
    result = size * nmemb;
  }
  return result;
}

int
CurlClient::progress_func(void * clientp, double dltotal, double dlnow, double ultotal, double ulnow) {
  CurlClient * client = static_cast<CurlClient *>(clientp);
  assert(client);
  if (!client->handleProgress(dltotal, dlnow, ultotal, ulnow)) {
    return 1;
  } else {
    return 0;
  }
}

#ifndef __APPLE__
static pthread_mutex_t *lockarray;

#include <openssl/crypto.h>

static void lock_callback(int mode, int type, const char *file, int line) {
  (void)file;
  (void)line;
  if (mode & CRYPTO_LOCK) {
    pthread_mutex_lock(&(lockarray[type]));
  } else {
    pthread_mutex_unlock(&(lockarray[type]));
  }
}

static unsigned long thread_id(void) {
  unsigned long ret;

#ifdef WIN32
  ret = (unsigned long)(pthread_self().p);
#else
  ret=(unsigned long)pthread_self();
#endif
  return(ret);
}

static void init_locks(void) {
  int i;

  lockarray=(pthread_mutex_t *)OPENSSL_malloc(CRYPTO_num_locks() *
					      sizeof(pthread_mutex_t));
  for (i=0; i<CRYPTO_num_locks(); i++) {
    pthread_mutex_init(&(lockarray[i]),NULL);
  }

  CRYPTO_set_id_callback((unsigned long (*)())thread_id);
  CRYPTO_set_locking_callback(lock_callback); // (void (*)())lock_callback);
}

static void kill_locks(void)
{
  int i;

  CRYPTO_set_locking_callback(NULL);
  for (i=0; i<CRYPTO_num_locks(); i++)
    pthread_mutex_destroy(&(lockarray[i]));

  OPENSSL_free(lockarray);
}
#endif

#if 0
#include <gcrypt.h>
#include <errno.h>
#include <gnutls/gnutls.h>

GCRY_THREAD_OPTION_PTHREAD_IMPL;
#endif

void
CurlClient::clearCookies() {
  if (curl) {
    curl_easy_setopt(curl, CURLOPT_URL, "ALL");
  }
}

std::shared_ptr<HTTPClient>
CurlClientFactory::createClient(const std::string & _user_agent, bool _enable_cookies, bool _enable_keepalive) {
  return std::make_shared<CurlClient>("", _user_agent, _enable_cookies, _enable_keepalive);
}

void
CurlClientFactory::globalInit() {
#ifndef __APPLE__
#if 0
  gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
  gnutls_global_init();
#else
  init_locks();
#endif
#endif

  curl_global_init(CURL_GLOBAL_DEFAULT);

#if 0
  thread_setup();
#endif
#if 0
  gnutls_global_init();
#endif
}

void
CurlClientFactory::globalCleanup() {
  curl_global_cleanup();
#ifndef __APPLE__
  kill_locks();
#endif
}
<commit_msg>refactor, don't use data_out<commit_after>#include "CurlClient.h"

#include "BasicAuth.h"

#include <cstdio>
#include <cstring>
#include <cassert>
#include <cctype>
#include <iostream>
#include <pthread.h>

using namespace std;

#include <curl/curl.h>

class CurlClient : public HTTPClient {
 public:
  CurlClient(const std::string & _interface, const std::string & _user_agent, bool _enable_cookies = true, bool _enable_keepalive = true)
    : HTTPClient(_user_agent, _enable_cookies, _enable_keepalive),
      interface_name(_interface)
  {

  }
  CurlClient(const CurlClient & other) : HTTPClient(other),
					 interface_name(other.interface_name)
  {

  }

  ~CurlClient() {
    if (curl) curl_easy_cleanup(curl);
  }

  HTTPResponse request(const HTTPRequest & req, const Authorization & auth) override {
    if (req.getURI().empty()) {
      return HTTPResponse(0, "empty URI");
    }
    if (!initialize()) {
      return HTTPResponse(0, "Unable to initialize client");
    }

    // string ascii_uri = encodeIDN(uri);
    // if (ascii_uri.empty()) {
    //   cerr << "failed to convert url " << uri << endl;
    //   assert(0);
    // }

    struct curl_slist * headers = 0;
    if (req.getType() == HTTPRequest::POST) {
      if (!req.getContentType().empty()) {
	string h = "Content-type: ";
	h += req.getContentType();
	headers = curl_slist_append(headers, h.c_str());
      }
    }

    const BasicAuth * basic = dynamic_cast<const BasicAuth *>(&auth);
    if (basic) {
      string s = basic->getUsername();
      s += ':';
      s += basic->getPassword();
      curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
      curl_easy_setopt(curl, CURLOPT_USERPWD, s.c_str());
    } else {
      string auth_header = auth.createHeader();
      if (!auth_header.empty()) {
	string s = auth.getHeaderName();
	s += ": ";
	s += auth_header;
	headers = curl_slist_append(headers, s.c_str());
      }
    }

    for (auto & hd : req.getHeaders()) {
      string s = hd.first;
      s += ": ";
      s += hd.second;
      headers = curl_slist_append(headers, s.c_str());
    }

    HTTPResponse response;
    response.setCallback(callback);

    if (req.getType() == HTTPRequest::POST) {
      curl_easy_setopt(curl, CURLOPT_POST, 1);
      curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, req.getContent().size());
      curl_easy_setopt(curl, CURLOPT_POSTFIELDS, req.getContent().data());
    } else {
      curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
    }
    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, req.getFollowLocation());
    curl_easy_setopt(curl, CURLOPT_URL, req.getURI().c_str());
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, req.getTimeout());
    curl_easy_setopt(curl, CURLOPT_HEADERDATA, &response);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
    if (!cookie_jar.empty()) {
      curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookie_jar.c_str());
      curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookie_jar.c_str());
    }

    CURLcode res = curl_easy_perform(curl);
    if (res == 0) {
      unsigned long a = 0;
      if (curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &a) == CURLE_OK) {
	response.setResultCode(a);
      }
      if (!req.getFollowLocation()) {
	char * ptr = 0;
	curl_easy_getinfo(curl, CURLINFO_REDIRECT_URL, &ptr);
	if (ptr) {
	  response.setRedirectUrl(ptr);
	}
      }
    } else {
      response.setErrorText(curl_easy_strerror(res));
    }

    if (headers) {
      curl_easy_setopt(curl, CURLOPT_HTTPHEADER, 0);
      curl_slist_free_all(headers);
    }

    return response;
  }

  void clearCookies() override {
    if (curl) {
      curl_easy_setopt(curl, CURLOPT_URL, "ALL"); // what does this do?
    }
  }

 protected:
  bool initialize() {
    if (curl) {
      curl_easy_reset(curl);
    } else {
      curl = curl_easy_init();
    }

    assert(curl);

    if (curl) {
#ifndef WIN32
      if (!interface_name.empty()) {
	int r = curl_easy_setopt(curl, CURLOPT_INTERFACE, interface_name.c_str());
	assert(r != CURLE_INTERFACE_FAILED);
      }
#endif
      curl_easy_setopt(curl, CURLOPT_USERAGENT, user_agent.c_str());
      curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
      curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data_func);
      curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_func);
      curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, headers_func);
      curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, this);
      curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
      curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30);
      curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
      curl_easy_setopt(curl, CURLOPT_DNS_CACHE_TIMEOUT, 600);
      // curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
      if (!enable_keepalive) {
	curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1);
	curl_easy_setopt(curl, CURLOPT_FORBID_REUSE, 1);
	// curl_easy_setopt(curl, CURLOPT_MAXCONNECTS, 10);
      }
      if (!cookie_jar.empty()) {
	curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookie_jar.c_str());
	curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookie_jar.c_str());
      } else if (enable_cookies) {
	curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "");
      }
    }

    return curl != 0;
  }

 private:
  bool handleProgress(double dltotal, double dlnow, double ultotal, double ulnow) {
    if (callback) {
      return callback->onIdle(true);
    }
    return true;
  }

  static size_t write_data_func(void * buffer, size_t size, size_t nmemb, void *userp);
  static size_t headers_func(void * buffer, size_t size, size_t nmemb, void *userp);
  static int progress_func(void *  clientp, double dltotal, double dlnow, double ultotal, double ulnow);

  std::string interface_name;
  CURL * curl = 0;
};

size_t
CurlClient::write_data_func(void * buffer, size_t size, size_t nmemb, void * userp) {
  size_t s = size * nmemb;
  // Content-Type: multipart/x-mixed-replace; boundary=myboundary

  HTTPResponse * response = static_cast<HTTPResponse *>(userp);
  assert(response);
  if (response->getCallback()) {
    if (response->getCallback()->handleChunk(s, (const char *)buffer)) {
      return s;
    } else {
      return 0;
    }
  } else {
    response->appendContent(string((const char *)buffer, s));
    return s;
  }
}

size_t
CurlClient::headers_func(void * buffer, size_t size, size_t nmemb, void *userp) {
  HTTPResponse * response = static_cast<HTTPResponse *>(userp);

  int result = 0;
  if (buffer) {
    string s((const char*)buffer, size * nmemb);
    int pos1 = 0;
    for ( ; pos1 < s.size() && s[pos1] != ':'; pos1++) { }
    int pos2 = s[pos1] == ':' ? pos1 + 1 : pos1;
    for (; pos2 < s.size() && isspace(s[pos2]); pos2++) { }
    int pos3 = s.size();
    for (; pos3 > 0 && isspace(s[pos3 - 1]); pos3--) { }
    std::string key = s.substr(0, pos1);
    std::string value = s.substr(pos2, pos3 - pos2);

    // cerr << "got header: " << key << " " << value << endl;

    if (response->getCallback()) {
      response->getCallback()->handleHeader(key, value);
    } else {
      response->addHeader(key, value);
    }
    result = size * nmemb;
  }
  return result;
}

int
CurlClient::progress_func(void * clientp, double dltotal, double dlnow, double ultotal, double ulnow) {
  CurlClient * client = static_cast<CurlClient *>(clientp);
  assert(client);
  if (!client->handleProgress(dltotal, dlnow, ultotal, ulnow)) {
    return 1;
  } else {
    return 0;
  }
}

#ifndef __APPLE__
static pthread_mutex_t *lockarray;

#include <openssl/crypto.h>

static void lock_callback(int mode, int type, const char *file, int line) {
  (void)file;
  (void)line;
  if (mode & CRYPTO_LOCK) {
    pthread_mutex_lock(&(lockarray[type]));
  } else {
    pthread_mutex_unlock(&(lockarray[type]));
  }
}

static unsigned long thread_id(void) {
  unsigned long ret;

#ifdef WIN32
  ret = (unsigned long)(pthread_self().p);
#else
  ret=(unsigned long)pthread_self();
#endif
  return(ret);
}

static void init_locks(void) {
  int i;

  lockarray=(pthread_mutex_t *)OPENSSL_malloc(CRYPTO_num_locks() *
					      sizeof(pthread_mutex_t));
  for (i=0; i<CRYPTO_num_locks(); i++) {
    pthread_mutex_init(&(lockarray[i]),NULL);
  }

  CRYPTO_set_id_callback((unsigned long (*)())thread_id);
  CRYPTO_set_locking_callback(lock_callback); // (void (*)())lock_callback);
}

static void kill_locks(void)
{
  int i;

  CRYPTO_set_locking_callback(NULL);
  for (i=0; i<CRYPTO_num_locks(); i++)
    pthread_mutex_destroy(&(lockarray[i]));

  OPENSSL_free(lockarray);
}
#endif

#if 0
#include <gcrypt.h>
#include <errno.h>
#include <gnutls/gnutls.h>

GCRY_THREAD_OPTION_PTHREAD_IMPL;
#endif

std::shared_ptr<HTTPClient>
CurlClientFactory::createClient(const std::string & _user_agent, bool _enable_cookies, bool _enable_keepalive) {
  return std::make_shared<CurlClient>("", _user_agent, _enable_cookies, _enable_keepalive);
}

void
CurlClientFactory::globalInit() {
#ifndef __APPLE__
#if 0
  gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
  gnutls_global_init();
#else
  init_locks();
#endif
#endif

  curl_global_init(CURL_GLOBAL_DEFAULT);

#if 0
  thread_setup();
#endif
#if 0
  gnutls_global_init();
#endif
}

void
CurlClientFactory::globalCleanup() {
  curl_global_cleanup();
#ifndef __APPLE__
  kill_locks();
#endif
}
<|endoftext|>


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

#include "DeviceInfo.h"

#include <cstring>
#include <string>

using namespace tcam;

DeviceInfo::DeviceInfo (const struct tcam_device_info& device_desc)
    : device(device_desc)
{}

DeviceInfo::DeviceInfo ()
{
    device.type = TCAM_DEVICE_TYPE_UNKNOWN;

    memset(device.identifier, 0, sizeof(device.identifier));
    memset(device.name, 0, sizeof(device.name));
    memset(device.serial_number, 0, sizeof(device.serial_number));
}

DeviceInfo::DeviceInfo (const DeviceInfo& other)
{
    this->device = other.device;
}

DeviceInfo& DeviceInfo::operator= (const DeviceInfo& other)
{
    this->device = other.device;
    return *this;
}

struct tcam_device_info DeviceInfo::get_info () const
{
    return device;
}

std::string DeviceInfo::get_name () const
{
    return device.name;
}

std::string DeviceInfo::get_serial () const
{
    return device.serial_number;
}

std::string DeviceInfo::get_identifier () const
{
    return device.identifier;
}

enum TCAM_DEVICE_TYPE DeviceInfo::get_device_type () const
{
    return device.type;
}

std::string DeviceInfo::get_device_type_as_string () const
{
    switch (device.type)
    {
        case TCAM_DEVICE_TYPE_V4L2:
            return "V4L2";
        case TCAM_DEVICE_TYPE_ARAVIS:
            return "Aravis";
        case TCAM_DEVICE_TYPE_LIBUSB:
            return "LibUsb";
        default:
            return "Unknown";
    }
}
<commit_msg>srcs: Make device type strings lower case<commit_after>/*
 * Copyright 2014 The Imaging Source Europe GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "DeviceInfo.h"

#include <cstring>
#include <string>

using namespace tcam;

DeviceInfo::DeviceInfo (const struct tcam_device_info& device_desc)
    : device(device_desc)
{}

DeviceInfo::DeviceInfo ()
{
    device.type = TCAM_DEVICE_TYPE_UNKNOWN;

    memset(device.identifier, 0, sizeof(device.identifier));
    memset(device.name, 0, sizeof(device.name));
    memset(device.serial_number, 0, sizeof(device.serial_number));
}

DeviceInfo::DeviceInfo (const DeviceInfo& other)
{
    this->device = other.device;
}

DeviceInfo& DeviceInfo::operator= (const DeviceInfo& other)
{
    this->device = other.device;
    return *this;
}

struct tcam_device_info DeviceInfo::get_info () const
{
    return device;
}

std::string DeviceInfo::get_name () const
{
    return device.name;
}

std::string DeviceInfo::get_serial () const
{
    return device.serial_number;
}

std::string DeviceInfo::get_identifier () const
{
    return device.identifier;
}

enum TCAM_DEVICE_TYPE DeviceInfo::get_device_type () const
{
    return device.type;
}

std::string DeviceInfo::get_device_type_as_string () const
{
    switch (device.type)
    {
        case TCAM_DEVICE_TYPE_V4L2:
            return "v4l2";
        case TCAM_DEVICE_TYPE_ARAVIS:
            return "aravis";
        case TCAM_DEVICE_TYPE_LIBUSB:
            return "libusb";
        default:
            return "unknown";
    }
}
<|endoftext|>


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

#ifdef __unix__
  #include <cxxabi.h>
#endif

#include "LIEF/exception.hpp"

#include "LIEF/visitors/Hash.hpp"

#include "LIEF/ELF/Symbol.hpp"
#include "LIEF/ELF/EnumToString.hpp"

namespace LIEF {
namespace ELF {

Symbol::Symbol(void) :
  type_{ELF_SYMBOL_TYPES::STT_NOTYPE},
  binding_{SYMBOL_BINDINGS::STB_LOCAL},
  other_{0},
  shndx_{0},
  value_{0},
  size_{0},
  symbol_version_{nullptr}
{}

Symbol::~Symbol(void) = default;

Symbol& Symbol::operator=(Symbol other) {
  this->swap(other);
  return *this;
}

Symbol::Symbol(const Symbol& other) : LIEF::Symbol{other},
  type_{other.type_},
  binding_{other.binding_},
  other_{other.other_},
  shndx_{other.shndx_},
  value_{other.value_},
  size_{other.size_},
  symbol_version_{nullptr}
{}

void Symbol::swap(Symbol& other) {
  std::swap(this->name_,           other.name_);
  std::swap(this->type_,           other.type_);
  std::swap(this->binding_,        other.binding_);
  std::swap(this->other_,          other.other_);
  std::swap(this->shndx_,          other.shndx_);
  std::swap(this->value_,          other.value_);
  std::swap(this->size_,           other.size_);
  std::swap(this->symbol_version_, other.symbol_version_);
}

Symbol::Symbol(const Elf32_Sym* header) :
  LIEF::Symbol{},
  type_{static_cast<ELF_SYMBOL_TYPES>(header->st_info & 0x0f)},
  binding_{static_cast<SYMBOL_BINDINGS>(header->st_info >> 4)},
  other_{header->st_other},
  shndx_{header->st_shndx},
  value_{header->st_value},
  size_{header->st_size},
  symbol_version_{nullptr}
{}

Symbol::Symbol(const Elf64_Sym* header) :
  LIEF::Symbol{},
  type_{static_cast<ELF_SYMBOL_TYPES>(header->st_info & 0x0f)},
  binding_{static_cast<SYMBOL_BINDINGS>(header->st_info >> 4)},
  other_{header->st_other},
  shndx_{header->st_shndx},
  value_{header->st_value},
  size_{header->st_size},
  symbol_version_{nullptr}
{}

Symbol::Symbol(std::string name, ELF_SYMBOL_TYPES type, SYMBOL_BINDINGS binding,
    uint8_t other, uint16_t shndx,
    uint64_t value, uint64_t size) :
  LIEF::Symbol{name},
  type_{type},
  binding_{binding},
  other_{other},
  shndx_{shndx},
  value_{value},
  size_{size},
  symbol_version_{nullptr}
{}

ELF_SYMBOL_TYPES Symbol::type(void) const {
  return this->type_;
}

SYMBOL_BINDINGS Symbol::binding(void) const {
  return this->binding_;
}

uint8_t Symbol::information(void) const {
  return static_cast<uint8_t>((static_cast<uint8_t>(this->binding_) << 4) | (static_cast<uint8_t>(this->type_) & 0x0f));
}

uint8_t Symbol::other(void) const {
  return this->other_;
}

uint16_t Symbol::section_idx(void) const {
  return this->shndx();
}

Section& Symbol::section(void) {
  if (this->section_ == nullptr) {
    throw not_found("No section associated with this symbol");
  } else {
    return *this->section_;
  }
}

uint64_t Symbol::value(void) const {
  return this->value_;
}

uint64_t Symbol::size(void) const {
  return this->size_;
}

uint16_t Symbol::shndx(void) const {
  return this->shndx_;
}

bool Symbol::has_version(void) const {
  return this->symbol_version_ != nullptr;
}

const SymbolVersion& Symbol::symbol_version(void) const {
  if (this->symbol_version_ != nullptr) {
    return *this->symbol_version_;
  } else {
    throw not_found("There is no symbol version associated with this symbol");
  }
}

SymbolVersion& Symbol::symbol_version(void) {
  return const_cast<SymbolVersion&>(static_cast<const Symbol*>(this)->symbol_version());
}

void Symbol::type(ELF_SYMBOL_TYPES type) {
  this->type_ = type;
}

void Symbol::binding(SYMBOL_BINDINGS binding) {
  this->binding_ = binding;
}

void Symbol::other(uint8_t other) {
  this->other_ = other;
}

void Symbol::value(uint64_t value) {
  this->value_ = value;
}

void Symbol::size(uint64_t size) {
  this->size_ = size;
}

void Symbol::shndx(uint16_t idx) {
  this->shndx_ = idx;
}

void Symbol::information(uint8_t info) {
  this->binding_ = static_cast<SYMBOL_BINDINGS>(info >> 4);
  this->type_    = static_cast<ELF_SYMBOL_TYPES>(info & 0x0f);
}

std::string Symbol::demangled_name(void) const {
#if defined(__unix__)
  int status;
  const std::string& name = this->name().c_str();
  auto realname = abi::__cxa_demangle(name.c_str(), 0, 0, &status);

  if (status == 0) {
    return realname;
  } else {
    return name;
  }
#else
  throw not_supported("Can't demangle name");
#endif
}

bool Symbol::is_exported(void) const {
  return ((this->binding() == SYMBOL_BINDINGS::STB_GLOBAL or
        this->binding() == SYMBOL_BINDINGS::STB_WEAK) and
        this->shndx() != SYMBOL_SECTION_INDEX::SHN_UNDEF);
}

void Symbol::set_exported(bool flag) {
  if (flag) {
    this->shndx(1);
    this->binding(SYMBOL_BINDINGS::STB_GLOBAL);
  } else {
    this->shndx(SYMBOL_SECTION_INDEX::SHN_UNDEF);
    this->binding(SYMBOL_BINDINGS::STB_LOCAL);
  }
}

bool Symbol::is_imported(void) const {
  return this->shndx() == SYMBOL_SECTION_INDEX::SHN_UNDEF;
}

void Symbol::set_imported(bool flag) {
  if (flag) {
    this->shndx(SYMBOL_SECTION_INDEX::SHN_UNDEF);
  } else {
    this->shndx(1);
  }
}

void Symbol::accept(Visitor& visitor) const {

  LIEF::Symbol::accept(visitor);

  visitor.visit(this->type());
  visitor.visit(this->binding());
  visitor.visit(this->information());
  visitor.visit(this->other());
  visitor.visit(this->section_idx());
  visitor.visit(this->value());
  visitor.visit(this->size());

  if(this->has_version()) {
    visitor(this->symbol_version());
  }
}

bool Symbol::operator==(const Symbol& rhs) const {
  size_t hash_lhs = Hash::hash(*this);
  size_t hash_rhs = Hash::hash(rhs);
  return hash_lhs == hash_rhs;
}

bool Symbol::operator!=(const Symbol& rhs) const {
  return not (*this == rhs);
}

std::ostream& operator<<(std::ostream& os, const Symbol& entry) {

  std::string name;
  try {
    name = entry.demangled_name();
  } catch (const not_supported&) {
    name = entry.name();
  }
  os << std::hex;
  os << std::left
     << std::setw(30) << name
     << std::setw(10) << to_string(entry.type())
     << std::setw(10) << to_string(entry.binding())
     << std::setw(10) << entry.value()
     << std::setw(10) << entry.size();

  if (entry.has_version()) {
    os << std::setw(10) << entry.symbol_version();
  }

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

#ifdef __unix__
  #include <cxxabi.h>
#endif

#include "LIEF/exception.hpp"

#include "LIEF/visitors/Hash.hpp"

#include "LIEF/ELF/Symbol.hpp"
#include "LIEF/ELF/EnumToString.hpp"

namespace LIEF {
namespace ELF {

Symbol::Symbol(void) :
  type_{ELF_SYMBOL_TYPES::STT_NOTYPE},
  binding_{SYMBOL_BINDINGS::STB_LOCAL},
  other_{0},
  shndx_{0},
  value_{0},
  size_{0},
  symbol_version_{nullptr}
{}

Symbol::~Symbol(void) = default;

Symbol& Symbol::operator=(Symbol other) {
  this->swap(other);
  return *this;
}

Symbol::Symbol(const Symbol& other) : LIEF::Symbol{other},
  type_{other.type_},
  binding_{other.binding_},
  other_{other.other_},
  shndx_{other.shndx_},
  value_{other.value_},
  size_{other.size_},
  symbol_version_{nullptr}
{}

void Symbol::swap(Symbol& other) {
  std::swap(this->name_,           other.name_);
  std::swap(this->type_,           other.type_);
  std::swap(this->binding_,        other.binding_);
  std::swap(this->other_,          other.other_);
  std::swap(this->shndx_,          other.shndx_);
  std::swap(this->value_,          other.value_);
  std::swap(this->size_,           other.size_);
  std::swap(this->symbol_version_, other.symbol_version_);
}

Symbol::Symbol(const Elf32_Sym* header) :
  LIEF::Symbol{},
  type_{static_cast<ELF_SYMBOL_TYPES>(header->st_info & 0x0f)},
  binding_{static_cast<SYMBOL_BINDINGS>(header->st_info >> 4)},
  other_{header->st_other},
  shndx_{header->st_shndx},
  value_{header->st_value},
  size_{header->st_size},
  symbol_version_{nullptr}
{}

Symbol::Symbol(const Elf64_Sym* header) :
  LIEF::Symbol{},
  type_{static_cast<ELF_SYMBOL_TYPES>(header->st_info & 0x0f)},
  binding_{static_cast<SYMBOL_BINDINGS>(header->st_info >> 4)},
  other_{header->st_other},
  shndx_{header->st_shndx},
  value_{header->st_value},
  size_{header->st_size},
  symbol_version_{nullptr}
{}

Symbol::Symbol(std::string name, ELF_SYMBOL_TYPES type, SYMBOL_BINDINGS binding,
    uint8_t other, uint16_t shndx,
    uint64_t value, uint64_t size) :
  LIEF::Symbol{name},
  type_{type},
  binding_{binding},
  other_{other},
  shndx_{shndx},
  value_{value},
  size_{size},
  symbol_version_{nullptr}
{}

ELF_SYMBOL_TYPES Symbol::type(void) const {
  return this->type_;
}

SYMBOL_BINDINGS Symbol::binding(void) const {
  return this->binding_;
}

uint8_t Symbol::information(void) const {
  return static_cast<uint8_t>((static_cast<uint8_t>(this->binding_) << 4) | (static_cast<uint8_t>(this->type_) & 0x0f));
}

uint8_t Symbol::other(void) const {
  return this->other_;
}

uint16_t Symbol::section_idx(void) const {
  return this->shndx();
}

Section& Symbol::section(void) {
  if (this->section_ == nullptr) {
    throw not_found("No section associated with this symbol");
  } else {
    return *this->section_;
  }
}

uint64_t Symbol::value(void) const {
  return this->value_;
}

uint64_t Symbol::size(void) const {
  return this->size_;
}

uint16_t Symbol::shndx(void) const {
  return this->shndx_;
}

bool Symbol::has_version(void) const {
  return this->symbol_version_ != nullptr;
}

const SymbolVersion& Symbol::symbol_version(void) const {
  if (this->symbol_version_ != nullptr) {
    return *this->symbol_version_;
  } else {
    throw not_found("There is no symbol version associated with this symbol");
  }
}

SymbolVersion& Symbol::symbol_version(void) {
  return const_cast<SymbolVersion&>(static_cast<const Symbol*>(this)->symbol_version());
}

void Symbol::type(ELF_SYMBOL_TYPES type) {
  this->type_ = type;
}

void Symbol::binding(SYMBOL_BINDINGS binding) {
  this->binding_ = binding;
}

void Symbol::other(uint8_t other) {
  this->other_ = other;
}

void Symbol::value(uint64_t value) {
  this->value_ = value;
}

void Symbol::size(uint64_t size) {
  this->size_ = size;
}

void Symbol::shndx(uint16_t idx) {
  this->shndx_ = idx;
}

void Symbol::information(uint8_t info) {
  this->binding_ = static_cast<SYMBOL_BINDINGS>(info >> 4);
  this->type_    = static_cast<ELF_SYMBOL_TYPES>(info & 0x0f);
}

std::string Symbol::demangled_name(void) const {
#if defined(__unix__)
  int status;
  const std::string& name = this->name().c_str();
  auto realname = abi::__cxa_demangle(name.c_str(), 0, 0, &status);

  if (status == 0) {
    return realname;
  } else {
    return name;
  }
#else
  throw not_supported("Can't demangle name");
#endif
}

bool Symbol::is_exported(void) const {
  bool is_exported = this->shndx() != SYMBOL_SECTION_INDEX::SHN_UNDEF;
  is_exported = is_exported and this->value() != 0;
  is_exported = is_exported and (this->binding() == SYMBOL_BINDINGS::STB_GLOBAL or
                                 this->binding() == SYMBOL_BINDINGS::STB_WEAK);
  is_exported = is_exported and (this->type() == ELF_SYMBOL_TYPES::STT_FUNC or
                                 this->type() == ELF_SYMBOL_TYPES::STT_GNU_IFUNC or
                                 this->type() == ELF_SYMBOL_TYPES::STT_OBJECT);
  return is_exported;
}

void Symbol::set_exported(bool flag) {
  if (flag) {
    this->shndx(1);
    this->binding(SYMBOL_BINDINGS::STB_GLOBAL);
  } else {
    this->shndx(SYMBOL_SECTION_INDEX::SHN_UNDEF);
    this->binding(SYMBOL_BINDINGS::STB_LOCAL);
  }
}

bool Symbol::is_imported(void) const {
  bool is_imported = this->shndx() == SYMBOL_SECTION_INDEX::SHN_UNDEF;
  is_imported = is_imported and this->value() == 0;
  is_imported = is_imported and this->name().size() > 0;
  is_imported = is_imported and (this->binding() == SYMBOL_BINDINGS::STB_GLOBAL or
                                 this->binding() == SYMBOL_BINDINGS::STB_WEAK);
  is_imported = is_imported and (this->type() == ELF_SYMBOL_TYPES::STT_FUNC or
                                 this->type() == ELF_SYMBOL_TYPES::STT_GNU_IFUNC or
                                 this->type() == ELF_SYMBOL_TYPES::STT_OBJECT);
  return is_imported;
}

void Symbol::set_imported(bool flag) {
  if (flag) {
    this->shndx(SYMBOL_SECTION_INDEX::SHN_UNDEF);
  } else {
    this->shndx(1);
  }
}

void Symbol::accept(Visitor& visitor) const {

  LIEF::Symbol::accept(visitor);

  visitor.visit(this->type());
  visitor.visit(this->binding());
  visitor.visit(this->information());
  visitor.visit(this->other());
  visitor.visit(this->section_idx());
  visitor.visit(this->value());
  visitor.visit(this->size());

  if(this->has_version()) {
    visitor(this->symbol_version());
  }
}

bool Symbol::operator==(const Symbol& rhs) const {
  size_t hash_lhs = Hash::hash(*this);
  size_t hash_rhs = Hash::hash(rhs);
  return hash_lhs == hash_rhs;
}

bool Symbol::operator!=(const Symbol& rhs) const {
  return not (*this == rhs);
}

std::ostream& operator<<(std::ostream& os, const Symbol& entry) {

  std::string name;
  try {
    name = entry.demangled_name();
  } catch (const not_supported&) {
    name = entry.name();
  }
  os << std::hex;
  os << std::left
     << std::setw(30) << name
     << std::setw(10) << to_string(entry.type())
     << std::setw(10) << to_string(entry.binding())
     << std::setw(10) << entry.value()
     << std::setw(10) << entry.size();

  if (entry.has_version()) {
    os << std::setw(10) << entry.symbol_version();
  }

  return os;
}
}
}
<|endoftext|>


<commit_before>//===--------------------- DispatchStage.cpp --------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
///
/// This file models the dispatch component of an instruction pipeline.
///
/// The DispatchStage is responsible for updating instruction dependencies
/// and communicating to the simulated instruction scheduler that an instruction
/// is ready to be scheduled for execution.
///
//===----------------------------------------------------------------------===//

#include "DispatchStage.h"
#include "Backend.h"
#include "HWEventListener.h"
#include "Scheduler.h"
#include "llvm/Support/Debug.h"

using namespace llvm;

#define DEBUG_TYPE "llvm-mca"

namespace mca {

void DispatchStage::notifyInstructionDispatched(const InstRef &IR,
                                                ArrayRef<unsigned> UsedRegs) {
  LLVM_DEBUG(dbgs() << "[E] Instruction Dispatched: " << IR << '\n');
  Owner->notifyInstructionEvent(HWInstructionDispatchedEvent(IR, UsedRegs));
}

bool DispatchStage::checkPRF(const InstRef &IR) {
  SmallVector<unsigned, 4> RegDefs;
  for (const std::unique_ptr<WriteState> &RegDef :
       IR.getInstruction()->getDefs())
    RegDefs.emplace_back(RegDef->getRegisterID());

  const unsigned RegisterMask = PRF.isAvailable(RegDefs);
  // A mask with all zeroes means: register files are available.
  if (RegisterMask) {
    Owner->notifyStallEvent(HWStallEvent(HWStallEvent::RegisterFileStall, IR));
    return false;
  }

  return true;
}

bool DispatchStage::checkRCU(const InstRef &IR) {
  const unsigned NumMicroOps = IR.getInstruction()->getDesc().NumMicroOps;
  if (RCU.isAvailable(NumMicroOps))
    return true;
  Owner->notifyStallEvent(
      HWStallEvent(HWStallEvent::RetireControlUnitStall, IR));
  return false;
}

bool DispatchStage::checkScheduler(const InstRef &IR) {
  HWStallEvent::GenericEventType Event;
  const bool Ready = SC.canBeDispatched(IR, Event);
  if (!Ready)
    Owner->notifyStallEvent(HWStallEvent(Event, IR));
  return Ready;
}

void DispatchStage::updateRAWDependencies(ReadState &RS,
                                          const MCSubtargetInfo &STI) {
  SmallVector<WriteState *, 4> DependentWrites;

  collectWrites(DependentWrites, RS.getRegisterID());
  RS.setDependentWrites(DependentWrites.size());
  LLVM_DEBUG(dbgs() << "Found " << DependentWrites.size()
                    << " dependent writes\n");
  // We know that this read depends on all the writes in DependentWrites.
  // For each write, check if we have ReadAdvance information, and use it
  // to figure out in how many cycles this read becomes available.
  const ReadDescriptor &RD = RS.getDescriptor();
  if (!RD.HasReadAdvanceEntries) {
    for (WriteState *WS : DependentWrites)
      WS->addUser(&RS, /* ReadAdvance */ 0);
    return;
  }

  const MCSchedModel &SM = STI.getSchedModel();
  const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
  for (WriteState *WS : DependentWrites) {
    unsigned WriteResID = WS->getWriteResourceID();
    int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
    WS->addUser(&RS, ReadAdvance);
  }
  // Prepare the set for another round.
  DependentWrites.clear();
}

void DispatchStage::dispatch(InstRef IR) {
  assert(!CarryOver && "Cannot dispatch another instruction!");
  Instruction &IS = *IR.getInstruction();
  const InstrDesc &Desc = IS.getDesc();
  const unsigned NumMicroOps = Desc.NumMicroOps;
  if (NumMicroOps > DispatchWidth) {
    assert(AvailableEntries == DispatchWidth);
    AvailableEntries = 0;
    CarryOver = NumMicroOps - DispatchWidth;
  } else {
    assert(AvailableEntries >= NumMicroOps);
    AvailableEntries -= NumMicroOps;
  }

  // A dependency-breaking instruction doesn't have to wait on the register
  // input operands, and it is often optimized at register renaming stage.
  // Update RAW dependencies if this instruction is not a dependency-breaking
  // instruction. A dependency-breaking instruction is a zero-latency
  // instruction that doesn't consume hardware resources.
  // An example of dependency-breaking instruction on X86 is a zero-idiom XOR.
  if (!Desc.isZeroLatency())
    for (std::unique_ptr<ReadState> &RS : IS.getUses())
      updateRAWDependencies(*RS, STI);

  // By default, a dependency-breaking zero-latency instruction is expected to
  // be optimized at register renaming stage. That means, no physical register
  // is allocated to the instruction.
  SmallVector<unsigned, 4> RegisterFiles(PRF.getNumRegisterFiles());
  for (std::unique_ptr<WriteState> &WS : IS.getDefs())
    PRF.addRegisterWrite(*WS, RegisterFiles, !Desc.isZeroLatency());

  // Reserve slots in the RCU, and notify the instruction that it has been
  // dispatched to the schedulers for execution.
  IS.dispatch(RCU.reserveSlot(IR, NumMicroOps));

  // Notify listeners of the "instruction dispatched" event.
  notifyInstructionDispatched(IR, RegisterFiles);
}

void DispatchStage::preExecute(const InstRef &IR) {
  AvailableEntries = CarryOver >= DispatchWidth ? 0 : DispatchWidth - CarryOver;
  CarryOver = CarryOver >= DispatchWidth ? CarryOver - DispatchWidth : 0U;
}

bool DispatchStage::execute(InstRef &IR) {
  const InstrDesc &Desc = IR.getInstruction()->getDesc();
  if (!isAvailable(Desc.NumMicroOps) || !canDispatch(IR))
    return false;
  dispatch(IR);
  return true;
}

#ifndef NDEBUG
void DispatchStage::dump() const {
  PRF.dump();
  RCU.dump();
}
#endif
} // namespace mca
<commit_msg>[llvm-mca] Remove redundant call. NFC<commit_after>//===--------------------- DispatchStage.cpp --------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
///
/// This file models the dispatch component of an instruction pipeline.
///
/// The DispatchStage is responsible for updating instruction dependencies
/// and communicating to the simulated instruction scheduler that an instruction
/// is ready to be scheduled for execution.
///
//===----------------------------------------------------------------------===//

#include "DispatchStage.h"
#include "Backend.h"
#include "HWEventListener.h"
#include "Scheduler.h"
#include "llvm/Support/Debug.h"

using namespace llvm;

#define DEBUG_TYPE "llvm-mca"

namespace mca {

void DispatchStage::notifyInstructionDispatched(const InstRef &IR,
                                                ArrayRef<unsigned> UsedRegs) {
  LLVM_DEBUG(dbgs() << "[E] Instruction Dispatched: " << IR << '\n');
  Owner->notifyInstructionEvent(HWInstructionDispatchedEvent(IR, UsedRegs));
}

bool DispatchStage::checkPRF(const InstRef &IR) {
  SmallVector<unsigned, 4> RegDefs;
  for (const std::unique_ptr<WriteState> &RegDef :
       IR.getInstruction()->getDefs())
    RegDefs.emplace_back(RegDef->getRegisterID());

  const unsigned RegisterMask = PRF.isAvailable(RegDefs);
  // A mask with all zeroes means: register files are available.
  if (RegisterMask) {
    Owner->notifyStallEvent(HWStallEvent(HWStallEvent::RegisterFileStall, IR));
    return false;
  }

  return true;
}

bool DispatchStage::checkRCU(const InstRef &IR) {
  const unsigned NumMicroOps = IR.getInstruction()->getDesc().NumMicroOps;
  if (RCU.isAvailable(NumMicroOps))
    return true;
  Owner->notifyStallEvent(
      HWStallEvent(HWStallEvent::RetireControlUnitStall, IR));
  return false;
}

bool DispatchStage::checkScheduler(const InstRef &IR) {
  HWStallEvent::GenericEventType Event;
  const bool Ready = SC.canBeDispatched(IR, Event);
  if (!Ready)
    Owner->notifyStallEvent(HWStallEvent(Event, IR));
  return Ready;
}

void DispatchStage::updateRAWDependencies(ReadState &RS,
                                          const MCSubtargetInfo &STI) {
  SmallVector<WriteState *, 4> DependentWrites;

  collectWrites(DependentWrites, RS.getRegisterID());
  RS.setDependentWrites(DependentWrites.size());
  LLVM_DEBUG(dbgs() << "Found " << DependentWrites.size()
                    << " dependent writes\n");
  // We know that this read depends on all the writes in DependentWrites.
  // For each write, check if we have ReadAdvance information, and use it
  // to figure out in how many cycles this read becomes available.
  const ReadDescriptor &RD = RS.getDescriptor();
  if (!RD.HasReadAdvanceEntries) {
    for (WriteState *WS : DependentWrites)
      WS->addUser(&RS, /* ReadAdvance */ 0);
    return;
  }

  const MCSchedModel &SM = STI.getSchedModel();
  const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
  for (WriteState *WS : DependentWrites) {
    unsigned WriteResID = WS->getWriteResourceID();
    int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
    WS->addUser(&RS, ReadAdvance);
  }
}

void DispatchStage::dispatch(InstRef IR) {
  assert(!CarryOver && "Cannot dispatch another instruction!");
  Instruction &IS = *IR.getInstruction();
  const InstrDesc &Desc = IS.getDesc();
  const unsigned NumMicroOps = Desc.NumMicroOps;
  if (NumMicroOps > DispatchWidth) {
    assert(AvailableEntries == DispatchWidth);
    AvailableEntries = 0;
    CarryOver = NumMicroOps - DispatchWidth;
  } else {
    assert(AvailableEntries >= NumMicroOps);
    AvailableEntries -= NumMicroOps;
  }

  // A dependency-breaking instruction doesn't have to wait on the register
  // input operands, and it is often optimized at register renaming stage.
  // Update RAW dependencies if this instruction is not a dependency-breaking
  // instruction. A dependency-breaking instruction is a zero-latency
  // instruction that doesn't consume hardware resources.
  // An example of dependency-breaking instruction on X86 is a zero-idiom XOR.
  if (!Desc.isZeroLatency())
    for (std::unique_ptr<ReadState> &RS : IS.getUses())
      updateRAWDependencies(*RS, STI);

  // By default, a dependency-breaking zero-latency instruction is expected to
  // be optimized at register renaming stage. That means, no physical register
  // is allocated to the instruction.
  SmallVector<unsigned, 4> RegisterFiles(PRF.getNumRegisterFiles());
  for (std::unique_ptr<WriteState> &WS : IS.getDefs())
    PRF.addRegisterWrite(*WS, RegisterFiles, !Desc.isZeroLatency());

  // Reserve slots in the RCU, and notify the instruction that it has been
  // dispatched to the schedulers for execution.
  IS.dispatch(RCU.reserveSlot(IR, NumMicroOps));

  // Notify listeners of the "instruction dispatched" event.
  notifyInstructionDispatched(IR, RegisterFiles);
}

void DispatchStage::preExecute(const InstRef &IR) {
  AvailableEntries = CarryOver >= DispatchWidth ? 0 : DispatchWidth - CarryOver;
  CarryOver = CarryOver >= DispatchWidth ? CarryOver - DispatchWidth : 0U;
}

bool DispatchStage::execute(InstRef &IR) {
  const InstrDesc &Desc = IR.getInstruction()->getDesc();
  if (!isAvailable(Desc.NumMicroOps) || !canDispatch(IR))
    return false;
  dispatch(IR);
  return true;
}

#ifndef NDEBUG
void DispatchStage::dump() const {
  PRF.dump();
  RCU.dump();
}
#endif
} // namespace mca
<|endoftext|>


<commit_before>#include <algorithm>

#include "Zenderer/Zenderer.hpp"

using namespace zen;

// Here's some perfect sample XML.
static const char* SAMPLE_XML[] = {
    "<entity type=\"QUAD\" name=\"generic\">",
        "<position x=\"100\" y=\"200\">",
        "</ >",
        "<texture>",
            "Tester.tga",
        "</ >",
        "<shader type=\"both\">",
            "<vshader>",
                "Tester.vs",
            "</ >",
            "<fshader>",
                "Tester.fs",
            "</ >",
        "</ >",
    "</ >"
};

#if defined(ZEN_API) && !defined(_DEBUG) && !defined(ZENDERER_EXPORTS)
  #pragma comment(lib, "Zenderer.lib")
#endif // ZEN_API

// Windowed version for release builds.
#ifndef _DEBUG
  int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPInst,
                     LPSTR lpCmdLine, int nShowCmd)
#else
  int main(int argc, char* argv[])
#endif // _DEBUG
{
    Init();

    asset::CAssetManager Manager; Manager.Init();
    gfx::CWindow Window(800, 600, "Hello, Zenderer.");

    Window.AttachAssetManager(Manager);
    Window.Init();

    sfx::CSound2D Sound;
    //Sound.LoadFromFile("Crackle.wav");

    color4f_t Teal(0.0, 1.0, 1.0, 1.0);

    gfxcore::CTexture* T = Manager.Create<gfxcore::CTexture>(
        string_t("sample.png"));

    gfxcore::CVertexArray Vao;
    gfxcore::DrawBatch D;

    gfxcore::index_t i[] = {0, 1, 3, 3, 1, 2};

    D.Vertices  = new gfxcore::vertex_t[4];
    D.vcount    = 4;
    D.Indices   = i;
    D.icount    = 6;

    D.Vertices[0].position = math::vector_t(0, 0);
    D.Vertices[1].position = math::vector_t(T->GetWidth(), 0);
    D.Vertices[2].position = math::vector_t(T->GetWidth(), T->GetHeight());
    D.Vertices[3].position = math::vector_t(0, T->GetHeight());

    D.Vertices[0].tc = math::vector_t(1.0, 0.0);
    D.Vertices[1].tc = math::vector_t(1.0, 1.0);
    D.Vertices[2].tc = math::vector_t(0.0, 1.0);
    D.Vertices[3].tc = math::vector_t(0.0, 0.0);

    D.Vertices[0].color =
    D.Vertices[1].color =
    D.Vertices[2].color =
    D.Vertices[3].color = color4f_t(1, 1, 1, 1);

    Vao.Init();
    Vao.AddData(D);
    Vao.Offload();

    D.Vertices[0].position = math::vector_t(0, 0);
    D.Vertices[1].position = math::vector_t(800, 0);
    D.Vertices[2].position = math::vector_t(800, 600);
    D.Vertices[3].position = math::vector_t(0, 600);

    gfxcore::CVertexArray FS;
    FS.Init();
    FS.AddData(D);
    FS.Offload();

    D.Indices = nullptr;
    delete[] D.Vertices;
    D.vcount = D.icount = 0;

    gfx::CQuad Q(32, 32);
    Q.Create().Move(math::vector_t(100, 100));
    Q.SetColor(color4f_t(1));

    Window.ToggleVSYNC();
    util::CTimer Timer(60);

    gfxcore::CRenderer::EnableAlphaBlending();

    gfx::CLight L(Manager, gfx::LightType::ZEN_POINT, Window.GetHeight());
    L.Init();
    L.Enable();
    L.SetBrightness(0.5);
    L.SetColor(1.0, 1.0, 1.0);
    L.SetPosition(200, 100);
    L.Disable();

    gfx::CRenderTarget RT(800, 600);
    RT.Init();

    double x, y;

    while(Window.IsOpen())
    {
        Timer.Start();

        // Handle events
        glfwPollEvents();
        glfwGetCursorPos(Window.GetWindow(), &x, &y);

        // Game logic
        Sound.Update();

        RT.Bind();
        RT.Clear();
        T->Bind();
        gfxcore::CRenderer::GetDefaultEffect().Enable();
        gfxcore::CRenderer::GetDefaultEffect().SetParameter(
            "mv", math::matrix4x4_t::GetIdentityMatrix());
        Vao.Draw();
        gfxcore::CRenderer::GetDefaultEffect().Disable();
        T->Unbind();
        RT.Unbind();

        // Rendering
        Window.Clear(Teal);

        GL(glBindTexture(GL_TEXTURE_2D, RT.GetTexture()));
        gfxcore::CRenderer::GetDefaultEffect().Enable();
        gfxcore::CRenderer::GetDefaultEffect().SetParameter(
            "mv", math::matrix4x4_t::GetIdentityMatrix());
        FS.Draw();
        gfxcore::CRenderer::GetDefaultEffect().Disable();
        GL(glBindTexture(GL_TEXTURE_2D, 0));

        T->Bind();
        gfxcore::CRenderer::GetDefaultEffect().Enable();
        Vao.Draw();
        gfxcore::CRenderer::GetDefaultEffect().Disable();
        T->Unbind();

        Q.Move(x, y);
        Q.Draw();

        Window.Update();

        // Finalize
        Timer.Delay();
    }

    Vao.Destroy();

    Quit();

    return 0;
}
<commit_msg>FBO render test passed<commit_after>#include <algorithm>

#include "Zenderer/Zenderer.hpp"

using namespace zen;

// Here's some perfect sample XML.
static const char* SAMPLE_XML[] = {
    "<entity type=\"QUAD\" name=\"generic\">",
        "<position x=\"100\" y=\"200\">",
        "</ >",
        "<texture>",
            "Tester.tga",
        "</ >",
        "<shader type=\"both\">",
            "<vshader>",
                "Tester.vs",
            "</ >",
            "<fshader>",
                "Tester.fs",
            "</ >",
        "</ >",
    "</ >"
};

#if defined(ZEN_API) && !defined(_DEBUG) && !defined(ZENDERER_EXPORTS)
  #pragma comment(lib, "Zenderer.lib")
#endif // ZEN_API

// Windowed version for release builds.
#ifndef _DEBUG
  int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPInst,
                     LPSTR lpCmdLine, int nShowCmd)
#else
  int main(int argc, char* argv[])
#endif // _DEBUG
{
    Init();

    asset::CAssetManager Manager; Manager.Init();
    gfx::CWindow Window(800, 600, "Hello, Zenderer.");

    Window.AttachAssetManager(Manager);
    Window.Init();

    sfx::CSound2D Sound;
    //Sound.LoadFromFile("Crackle.wav");

    color4f_t Teal(0.0, 1.0, 1.0, 1.0);

    gfxcore::CTexture* T = Manager.Create<gfxcore::CTexture>(
        string_t("sample.png"));

    gfxcore::CVertexArray Vao;
    gfxcore::DrawBatch D;

    gfxcore::index_t i[] = {0, 1, 3, 3, 1, 2};

    D.Vertices  = new gfxcore::vertex_t[4];
    D.vcount    = 4;
    D.Indices   = i;
    D.icount    = 6;

    D.Vertices[0].position = math::vector_t(0, 0);
    D.Vertices[1].position = math::vector_t(T->GetWidth(), 0);
    D.Vertices[2].position = math::vector_t(T->GetWidth(), T->GetHeight());
    D.Vertices[3].position = math::vector_t(0, T->GetHeight());

    D.Vertices[0].tc = math::vector_t(0.0, 1.0);
    D.Vertices[1].tc = math::vector_t(1.0, 1.0);
    D.Vertices[2].tc = math::vector_t(1.0, 0.0);
    D.Vertices[3].tc = math::vector_t(0.0, 0.0);

    D.Vertices[0].color =
    D.Vertices[1].color =
    D.Vertices[2].color =
    D.Vertices[3].color = color4f_t(1, 1, 1, 1);

    Vao.Init();
    Vao.AddData(D);
    Vao.Offload();

    D.Vertices[0].position = math::vector_t(0, 0);
    D.Vertices[1].position = math::vector_t(800, 0);
    D.Vertices[2].position = math::vector_t(800, 600);
    D.Vertices[3].position = math::vector_t(0, 600);

    gfxcore::CVertexArray FS;
    FS.Init();
    FS.AddData(D);
    FS.Offload();

    D.Indices = nullptr;
    delete[] D.Vertices;
    D.vcount = D.icount = 0;

    gfx::CQuad Q(32, 32);
    Q.Create();
    Q.SetColor(color4f_t(1));

    Window.ToggleVSYNC();
    util::CTimer Timer(60);

    gfxcore::CRenderer::EnableAlphaBlending();

    gfx::CLight L(Manager, gfx::LightType::ZEN_POINT, Window.GetHeight());
    L.Init();
    L.Enable();
    L.SetBrightness(0.5);
    L.SetColor(1.0, 1.0, 1.0);
    L.SetPosition(200, 100);
    L.Disable();

    gfx::CRenderTarget RT(800, 600);
    RT.Init();

    double x, y;

    while(Window.IsOpen())
    {
        Timer.Start();

        // Handle events
        glfwPollEvents();
        glfwGetCursorPos(Window.GetWindow(), &x, &y);

        // Game logic
        Sound.Update();

        RT.Bind();
        RT.Clear();
        T->Bind();
        gfxcore::CRenderer::GetDefaultEffect().Enable();
        gfxcore::CRenderer::GetDefaultEffect().SetParameter(
            "proj", gfxcore::CRenderer::GetProjectionMatrix());
        gfxcore::CRenderer::GetDefaultEffect().SetParameter(
            "mv", math::matrix4x4_t::GetIdentityMatrix());
        Vao.Draw();
        gfxcore::CRenderer::GetDefaultEffect().Disable();
        T->Unbind();
        RT.Unbind();

        // Rendering
        Window.Clear(Teal);

        GL(glBindTexture(GL_TEXTURE_2D, RT.GetTexture()));
        gfxcore::CRenderer::GetDefaultEffect().Enable();
        FS.Draw();
        gfxcore::CRenderer::GetDefaultEffect().Disable();
        GL(glBindTexture(GL_TEXTURE_2D, 0));

        T->Bind();
        gfxcore::CRenderer::GetDefaultEffect().Enable();
        math::matrix4x4_t MV = math::matrix4x4_t::GetIdentityMatrix();
        MV[0][3] = 100.0;
        MV[1][3] = 100.0;
        gfxcore::CRenderer::GetDefaultEffect().SetParameter("mv", MV);
        Vao.Draw();
        gfxcore::CRenderer::GetDefaultEffect().Disable();
        T->Unbind();

        Q.Move(x, y);
        Q.Draw();

        Window.Update();

        // Finalize
        Timer.Delay();
    }

    Vao.Destroy();

    Quit();

    return 0;
}
<|endoftext|>


<commit_before>/*
 * FileSystem.cpp
 *
 *  Created on: Jun 20, 2014
 *      Author: Pimenta
 */

// this
#include "FileSystem.hpp"

// standard
#include <cstdlib>

using namespace std;
using namespace helpers;

FileSystem::Folder FileSystem::rootFolder;
uint32_t FileSystem::nextID;
uint32_t FileSystem::localIP;
set<uint32_t> FileSystem::storedFiles;

FileSystem::File::File() : id(nextID++), size(0), peer1(localIP), peer2(0) {
  char tmp[25];
  sprintf(tmp, "www/files/%08x", id);
  rename("www/files/tmp", tmp);
  FILE* fp = fopen(tmp, "rb");
  if (fp) {
    fseek(fp, 0, SEEK_END);
    size = ftell(fp);
  }
  fclose(fp);
}

void FileSystem::File::serialize(ByteQueue& data) {
  data.push((const void*)this, 16).push(author);
}

void FileSystem::File::deserialize(ByteQueue& data) {
  data.pop((void*)this, 16);
  author = data.pop<string>();
}

ByteQueue FileSystem::File::read() {
  ByteQueue data;
  if (storedFiles.find(id) != storedFiles.end()) { // if the file is stored here
    data.resize(size);
    char tmp[25];
    sprintf(tmp, "www/files/%08x", id);
    FILE* fp = fopen(tmp, "rb");
    fread(data.ptr(), size, 1, fp);
    fclose(fp);
  }
  return data;
}

void FileSystem::File::erase() {
  char tmp[25];
  sprintf(tmp, "www/files/%08x", id);
  remove(tmp);
}

uint32_t FileSystem::Folder::getTotalFolders() {
  uint32_t total = subfolders.size();
  for (auto& kv : subfolders)
    total += kv.second.getTotalFolders();
  return total;
}

uint32_t FileSystem::Folder::getTotalFiles() {
  uint32_t total = 0;
  for (auto& kv : subfolders)
    total += kv.second.getTotalFiles();
  return total + files.size();
}

uint64_t FileSystem::Folder::getTotalSize() {
  int total = 0;
  for (auto& kv : subfolders)
    total += kv.second.getTotalSize();
  for (auto& kv : files)
    total += kv.second.size;
  return total;
}

FileSystem::Folder* FileSystem::Folder::findFolder(const string& subPath, Folder** parent) {
  if (!parsePath(subPath)) { // if the path is invalid
    if (parent) // if the parent folder was requested
      *parent = nullptr;
    return nullptr;
  }
  return findFolder_(subPath, parent);
}

FileSystem::File* FileSystem::Folder::findFile(const string& subPath, Folder** parent) {
  if (!parsePath(subPath)) { // if the path is invalid
    if (parent) // if the parent folder was requested
      *parent = nullptr;
    return nullptr;
  }
  return findFile_(subPath, parent);
}

FileSystem::Folder* FileSystem::Folder::findFirstBottomUp(const string& subPath, string& foundPath) {
  if (!parsePath(subPath)) { // if the path is invalid
    foundPath = "";
    return nullptr;
  }
  Folder* folder = findFirstBottomUp_(subPath, foundPath);
  // removing duplicated '/'
  if (foundPath.size() > 2 && foundPath[0] == '/' && foundPath[1] == '/')
    foundPath = foundPath.substr(1, foundPath.size());
  return folder;
}

void FileSystem::Folder::serialize(ByteQueue& data) {
  data.push(uint32_t(subfolders.size()));
  for (auto& kv : subfolders) {
    data.push(kv.first);
    kv.second.serialize(data);
  }
  data.push(uint32_t(files.size()));
  for (auto& kv : files) {
    data.push(kv.first);
    kv.second.serialize(data);
  }
}

void FileSystem::Folder::deserialize(ByteQueue& data) {
  uint32_t subf_size = data.pop<uint32_t>();
  for (uint32_t i = 0; i < subf_size; i++) {
    string key = data.pop<string>();
    subfolders[key].deserialize(data);
  }
  uint32_t files_size = data.pop<uint32_t>();
  for (uint32_t i = 0; i < files_size; i++) {
    string key = data.pop<string>();
    files[key].deserialize(data);
  }
}

void FileSystem::Folder::eraseFiles() {
  for (auto& kv : subfolders)
    kv.second.eraseFiles();
  for (auto& kv : files)
    kv.second.erase();
}

FileSystem::Folder* FileSystem::Folder::findFolder_(const string& subPath, Folder** parent) {
  pair<string, string> brokenPath = extractFirst(subPath, '/');
  if (brokenPath.second == "") { // if subPath is a folder name
    if (parent) // if the parent folder was requested
      *parent = this;
    auto folder = subfolders.find(brokenPath.first);
    if (folder == subfolders.end()) // if the folder was not found
      return nullptr;
    return &folder->second;
  }
  auto parentFolder = subfolders.find(brokenPath.first);
  if (parentFolder == subfolders.end()) { // if a parent folder was not found
    if (parent) // if the parent folder was requested
      *parent = nullptr;
    return nullptr;
  }
  // recursive call
  return parentFolder->second.findFolder_(brokenPath.second, parent);
}

FileSystem::File* FileSystem::Folder::findFile_(const string& subPath, Folder** parent) {
  pair<string, string> brokenPath = extractFirst(subPath, '/');
  if (brokenPath.second == "") { // if supPath is a file name
    if (parent) // if the parent folder was requested
      *parent = this;
    auto file = files.find(brokenPath.first);
    if (file == files.end()) // if the file was not found
      return nullptr;
    return &file->second;
  }
  auto parentFolder = subfolders.find(brokenPath.first);
  if (parentFolder == subfolders.end()) { // if a parent folder was not found
    if (parent) // if the parent folder was requested
      *parent = nullptr;
    return nullptr;
  }
  // recursive call
  return parentFolder->second.findFile_(brokenPath.second, parent);
}

FileSystem::Folder* FileSystem::Folder::findFirstBottomUp_(const string& subPath, string& foundPath) {
  pair<string, string> brokenPath = extractFirst(subPath, '/');
  if (brokenPath.second == "") { // if subPath is a folder name
    auto folder = subfolders.find(brokenPath.first);
    if (folder == subfolders.end()) // if the folder was not found
      return this;
    foundPath += brokenPath.first;
    return &folder->second;
  }
  auto parentFolder = subfolders.find(brokenPath.first);
  if (parentFolder == subfolders.end()) // if a parent folder was not found
    return this;
  foundPath += brokenPath.first;
  // recursive call
  return parentFolder->second.findFirstBottomUp_(brokenPath.second, foundPath);
}

void FileSystem::init(uint32_t localIP) {
  rootFolder.subfolders.clear();
  rootFolder.files.clear();
  FileSystem::localIP = localIP;
  nextID = 1;
  storedFiles.clear();
#ifdef _WIN32
  system("rmdir /Q /S www\\files");
  system("mkdir www\\files");
#else
  system("rm -rf www/files");
  system("mkdir www/files");
#endif
}

ByteQueue FileSystem::serialize() {
  ByteQueue data;
  rootFolder.serialize(data);
  return data;
}

void FileSystem::deserialize(ByteQueue& data) {
  rootFolder.deserialize(data);
}

bool FileSystem::parseName(const string& name) {
  static set<char> allowedChars;
  static StaticInitializer staticInitializar([&]() {
    for (char c = '0'; c <= '9'; c++)
      allowedChars.insert(c);
    for (char c = 'a'; c <= 'z'; c++)
      allowedChars.insert(c);
    for (char c = 'A'; c <= 'Z'; c++)
      allowedChars.insert(c);
    allowedChars.insert('_');
    allowedChars.insert('-');
    allowedChars.insert('+');
    allowedChars.insert('.');
  });
  if (!name.size()) // if the name is empty
    return false;
  for (int i = 0; i < int(name.size()); i++) { // check if all chars are allowed
    if (allowedChars.find(name[i]) == allowedChars.end())
      return false;
  }
  return true;
}

bool FileSystem::parsePath(const string& path) {
  if (!path.size()) // if the path is empty
    return false;
  list<string> atoms = explode(path, '/');
  string reassembledPath;
  for (auto& folder : atoms) { // reassemble the exploded path
    if (!parseName(folder)) // if there is an invalid folder name
      return false;
    reassembledPath += '/';
    reassembledPath += folder;
  }
  return reassembledPath == path;
}

FileSystem::Folder* FileSystem::createFolder(const string& fullPath) {
  Folder* parent;
  Folder* folder = rootFolder.findFolder(fullPath, &parent);
  if (!parent || folder) // if parent folder was not found or the folder exist
    return nullptr;
  pair<string, string> brokenPath = extractLast(fullPath, '/');
  return &parent->subfolders[brokenPath.second];
}

FileSystem::Folder* FileSystem::retrieveFolder(const string& fullPath, string& foundPath) {
  foundPath = "/";
  if (fullPath == "/") // returning root folder
    return &rootFolder;
  return rootFolder.findFirstBottomUp(fullPath, foundPath);
}

FileSystem::Folder* FileSystem::updateFolder(const string& fullPath, const string& newName) {
  if (!parseName(newName)) // if the new name is invalid
    return nullptr;
  Folder* parent;
  Folder* folder = rootFolder.findFolder(fullPath, &parent);
  if (!parent || !folder) // if parent or folder doesn't exist
    return nullptr;
  string newNameWithSlash = string("/") + newName;
  // if the new folder already exist
  if (parent->subfolders.find(newNameWithSlash) != parent->subfolders.end())
    return nullptr;
  Folder* newFolder = &parent->subfolders[newNameWithSlash];
  newFolder->subfolders = folder->subfolders;
  newFolder->files = folder->files;
  pair<string, string> brokenPath = extractLast(fullPath, '/');
  parent->subfolders.erase(brokenPath.second);
  return newFolder;
}

bool FileSystem::deleteFolder(const string& fullPath) {
  Folder* parent;
  Folder* folder = rootFolder.findFolder(fullPath, &parent);
  if (!parent || !folder) // if parent of folder doesn't exist
    return false;
  folder->eraseFiles();
  pair<string, string> brokenPath = extractLast(fullPath, '/');
  parent->subfolders.erase(brokenPath.second);
  return true;
}

FileSystem::File* FileSystem::createFile(const string& fullPath, const string& author) {
  Folder* parent;
  File* file = rootFolder.findFile(fullPath, &parent);
  if (!parent || file) { // if parent folder was not found or the file exist
    remove("www/files/tmp");
    return nullptr;
  }
  pair<string, string> brokenPath = extractLast(fullPath, '/');
  file = &parent->files[brokenPath.second];
  file->author = author;
  storedFiles.insert(file->id);
  return file;
}

FileSystem::File* FileSystem::createFile(const string& fullPath, ByteQueue& info) {
  Folder* parent;
  File* file = rootFolder.findFile(fullPath, &parent);
  if (!parent || file) // if parent folder was not found or the file exist
    return nullptr;
  pair<string, string> brokenPath = extractLast(fullPath, '/');
  file = &parent->files[brokenPath.second];
  file->deserialize(info);
  return file;
}

FileSystem::File* FileSystem::retrieveFile(const string& fullPath) {
  return rootFolder.findFile(fullPath);
}

FileSystem::File* FileSystem::updateFile(const string& fullPath, const string& newName) {
  if (!parseName(newName)) // if the new name is invalid
    return nullptr;
  Folder* parent;
  File* file = rootFolder.findFile(fullPath, &parent);
  if (!parent || !file) // if the parent folder or the file don't exist
    return nullptr;
  string newNameWithSlash = string("/") + newName;
  // if the new file already exist
  if (parent->files.find(newNameWithSlash) != parent->files.end())
    return nullptr;
  File* newFile = &parent->files[newNameWithSlash];
  *newFile = *file;
  pair<string, string> brokenPath = extractLast(fullPath, '/');
  parent->files.erase(brokenPath.second);
  return newFile;
}

bool FileSystem::deleteFile(const string& fullPath) {
  Folder* parent;
  File* file = rootFolder.findFile(fullPath, &parent);
  if (!parent || !file) // if the parent folder or the file don't exist
    return false;
  file->erase();
  pair<string, string> brokenPath = extractLast(fullPath, '/');
  parent->files.erase(brokenPath.second);
  return true;
}

uint32_t FileSystem::getTotalFolders() {
  return rootFolder.getTotalFolders();
}

uint32_t FileSystem::getTotalFiles() {
  return rootFolder.getTotalFiles();
}

uint64_t FileSystem::getTotalSize() {
  return rootFolder.getTotalSize();
}

ByteQueue FileSystem::readFile(FILE* fp) {
  fseek(fp, 0, SEEK_END);
  size_t size = ftell(fp);
  fseek(fp, 0, SEEK_SET);
  ByteQueue data(size);
  fread(data.ptr(), size, 1, fp);
  return data;
}
<commit_msg>Fixing bug on file sync<commit_after>/*
 * FileSystem.cpp
 *
 *  Created on: Jun 20, 2014
 *      Author: Pimenta
 */

// this
#include "FileSystem.hpp"

// standard
#include <cstdlib>

using namespace std;
using namespace helpers;

FileSystem::Folder FileSystem::rootFolder;
uint32_t FileSystem::nextID;
uint32_t FileSystem::localIP;
set<uint32_t> FileSystem::storedFiles;

FileSystem::File::File() : id(nextID++), size(0), peer1(localIP), peer2(0) {
  char tmp[25];
  sprintf(tmp, "www/files/%08x", id);
  rename("www/files/tmp", tmp);
  FILE* fp = fopen(tmp, "rb");
  if (fp) {
    fseek(fp, 0, SEEK_END);
    size = ftell(fp);
    fclose(fp);
  }
}

void FileSystem::File::serialize(ByteQueue& data) {
  data.push((const void*)this, 16).push(author);
}

void FileSystem::File::deserialize(ByteQueue& data) {
  data.pop((void*)this, 16);
  author = data.pop<string>();
}

ByteQueue FileSystem::File::read() {
  ByteQueue data;
  if (storedFiles.find(id) != storedFiles.end()) { // if the file is stored here
    data.resize(size);
    char tmp[25];
    sprintf(tmp, "www/files/%08x", id);
    FILE* fp = fopen(tmp, "rb");
    fread(data.ptr(), size, 1, fp);
    fclose(fp);
  }
  return data;
}

void FileSystem::File::erase() {
  char tmp[25];
  sprintf(tmp, "www/files/%08x", id);
  remove(tmp);
}

uint32_t FileSystem::Folder::getTotalFolders() {
  uint32_t total = subfolders.size();
  for (auto& kv : subfolders)
    total += kv.second.getTotalFolders();
  return total;
}

uint32_t FileSystem::Folder::getTotalFiles() {
  uint32_t total = 0;
  for (auto& kv : subfolders)
    total += kv.second.getTotalFiles();
  return total + files.size();
}

uint64_t FileSystem::Folder::getTotalSize() {
  int total = 0;
  for (auto& kv : subfolders)
    total += kv.second.getTotalSize();
  for (auto& kv : files)
    total += kv.second.size;
  return total;
}

FileSystem::Folder* FileSystem::Folder::findFolder(const string& subPath, Folder** parent) {
  if (!parsePath(subPath)) { // if the path is invalid
    if (parent) // if the parent folder was requested
      *parent = nullptr;
    return nullptr;
  }
  return findFolder_(subPath, parent);
}

FileSystem::File* FileSystem::Folder::findFile(const string& subPath, Folder** parent) {
  if (!parsePath(subPath)) { // if the path is invalid
    if (parent) // if the parent folder was requested
      *parent = nullptr;
    return nullptr;
  }
  return findFile_(subPath, parent);
}

FileSystem::Folder* FileSystem::Folder::findFirstBottomUp(const string& subPath, string& foundPath) {
  if (!parsePath(subPath)) { // if the path is invalid
    foundPath = "";
    return nullptr;
  }
  Folder* folder = findFirstBottomUp_(subPath, foundPath);
  // removing duplicated '/'
  if (foundPath.size() > 2 && foundPath[0] == '/' && foundPath[1] == '/')
    foundPath = foundPath.substr(1, foundPath.size());
  return folder;
}

void FileSystem::Folder::serialize(ByteQueue& data) {
  data.push(uint32_t(subfolders.size()));
  for (auto& kv : subfolders) {
    data.push(kv.first);
    kv.second.serialize(data);
  }
  data.push(uint32_t(files.size()));
  for (auto& kv : files) {
    data.push(kv.first);
    kv.second.serialize(data);
  }
}

void FileSystem::Folder::deserialize(ByteQueue& data) {
  uint32_t subf_size = data.pop<uint32_t>();
  for (uint32_t i = 0; i < subf_size; i++) {
    string key = data.pop<string>();
    subfolders[key].deserialize(data);
  }
  uint32_t files_size = data.pop<uint32_t>();
  for (uint32_t i = 0; i < files_size; i++) {
    string key = data.pop<string>();
    files[key].deserialize(data);
  }
}

void FileSystem::Folder::eraseFiles() {
  for (auto& kv : subfolders)
    kv.second.eraseFiles();
  for (auto& kv : files)
    kv.second.erase();
}

FileSystem::Folder* FileSystem::Folder::findFolder_(const string& subPath, Folder** parent) {
  pair<string, string> brokenPath = extractFirst(subPath, '/');
  if (brokenPath.second == "") { // if subPath is a folder name
    if (parent) // if the parent folder was requested
      *parent = this;
    auto folder = subfolders.find(brokenPath.first);
    if (folder == subfolders.end()) // if the folder was not found
      return nullptr;
    return &folder->second;
  }
  auto parentFolder = subfolders.find(brokenPath.first);
  if (parentFolder == subfolders.end()) { // if a parent folder was not found
    if (parent) // if the parent folder was requested
      *parent = nullptr;
    return nullptr;
  }
  // recursive call
  return parentFolder->second.findFolder_(brokenPath.second, parent);
}

FileSystem::File* FileSystem::Folder::findFile_(const string& subPath, Folder** parent) {
  pair<string, string> brokenPath = extractFirst(subPath, '/');
  if (brokenPath.second == "") { // if supPath is a file name
    if (parent) // if the parent folder was requested
      *parent = this;
    auto file = files.find(brokenPath.first);
    if (file == files.end()) // if the file was not found
      return nullptr;
    return &file->second;
  }
  auto parentFolder = subfolders.find(brokenPath.first);
  if (parentFolder == subfolders.end()) { // if a parent folder was not found
    if (parent) // if the parent folder was requested
      *parent = nullptr;
    return nullptr;
  }
  // recursive call
  return parentFolder->second.findFile_(brokenPath.second, parent);
}

FileSystem::Folder* FileSystem::Folder::findFirstBottomUp_(const string& subPath, string& foundPath) {
  pair<string, string> brokenPath = extractFirst(subPath, '/');
  if (brokenPath.second == "") { // if subPath is a folder name
    auto folder = subfolders.find(brokenPath.first);
    if (folder == subfolders.end()) // if the folder was not found
      return this;
    foundPath += brokenPath.first;
    return &folder->second;
  }
  auto parentFolder = subfolders.find(brokenPath.first);
  if (parentFolder == subfolders.end()) // if a parent folder was not found
    return this;
  foundPath += brokenPath.first;
  // recursive call
  return parentFolder->second.findFirstBottomUp_(brokenPath.second, foundPath);
}

void FileSystem::init(uint32_t localIP) {
  rootFolder.subfolders.clear();
  rootFolder.files.clear();
  FileSystem::localIP = localIP;
  nextID = 1;
  storedFiles.clear();
#ifdef _WIN32
  system("rmdir /Q /S www\\files");
  system("mkdir www\\files");
#else
  system("rm -rf www/files");
  system("mkdir www/files");
#endif
}

ByteQueue FileSystem::serialize() {
  ByteQueue data;
  rootFolder.serialize(data);
  return data;
}

void FileSystem::deserialize(ByteQueue& data) {
  rootFolder.deserialize(data);
}

bool FileSystem::parseName(const string& name) {
  static set<char> allowedChars;
  static StaticInitializer staticInitializar([&]() {
    for (char c = '0'; c <= '9'; c++)
      allowedChars.insert(c);
    for (char c = 'a'; c <= 'z'; c++)
      allowedChars.insert(c);
    for (char c = 'A'; c <= 'Z'; c++)
      allowedChars.insert(c);
    allowedChars.insert('_');
    allowedChars.insert('-');
    allowedChars.insert('+');
    allowedChars.insert('.');
  });
  if (!name.size()) // if the name is empty
    return false;
  for (int i = 0; i < int(name.size()); i++) { // check if all chars are allowed
    if (allowedChars.find(name[i]) == allowedChars.end())
      return false;
  }
  return true;
}

bool FileSystem::parsePath(const string& path) {
  if (!path.size()) // if the path is empty
    return false;
  list<string> atoms = explode(path, '/');
  string reassembledPath;
  for (auto& folder : atoms) { // reassemble the exploded path
    if (!parseName(folder)) // if there is an invalid folder name
      return false;
    reassembledPath += '/';
    reassembledPath += folder;
  }
  return reassembledPath == path;
}

FileSystem::Folder* FileSystem::createFolder(const string& fullPath) {
  Folder* parent;
  Folder* folder = rootFolder.findFolder(fullPath, &parent);
  if (!parent || folder) // if parent folder was not found or the folder exist
    return nullptr;
  pair<string, string> brokenPath = extractLast(fullPath, '/');
  return &parent->subfolders[brokenPath.second];
}

FileSystem::Folder* FileSystem::retrieveFolder(const string& fullPath, string& foundPath) {
  foundPath = "/";
  if (fullPath == "/") // returning root folder
    return &rootFolder;
  return rootFolder.findFirstBottomUp(fullPath, foundPath);
}

FileSystem::Folder* FileSystem::updateFolder(const string& fullPath, const string& newName) {
  if (!parseName(newName)) // if the new name is invalid
    return nullptr;
  Folder* parent;
  Folder* folder = rootFolder.findFolder(fullPath, &parent);
  if (!parent || !folder) // if parent or folder doesn't exist
    return nullptr;
  string newNameWithSlash = string("/") + newName;
  // if the new folder already exist
  if (parent->subfolders.find(newNameWithSlash) != parent->subfolders.end())
    return nullptr;
  Folder* newFolder = &parent->subfolders[newNameWithSlash];
  newFolder->subfolders = folder->subfolders;
  newFolder->files = folder->files;
  pair<string, string> brokenPath = extractLast(fullPath, '/');
  parent->subfolders.erase(brokenPath.second);
  return newFolder;
}

bool FileSystem::deleteFolder(const string& fullPath) {
  Folder* parent;
  Folder* folder = rootFolder.findFolder(fullPath, &parent);
  if (!parent || !folder) // if parent of folder doesn't exist
    return false;
  folder->eraseFiles();
  pair<string, string> brokenPath = extractLast(fullPath, '/');
  parent->subfolders.erase(brokenPath.second);
  return true;
}

FileSystem::File* FileSystem::createFile(const string& fullPath, const string& author) {
  Folder* parent;
  File* file = rootFolder.findFile(fullPath, &parent);
  if (!parent || file) { // if parent folder was not found or the file exist
    remove("www/files/tmp");
    return nullptr;
  }
  pair<string, string> brokenPath = extractLast(fullPath, '/');
  file = &parent->files[brokenPath.second];
  file->author = author;
  storedFiles.insert(file->id);
  return file;
}

FileSystem::File* FileSystem::createFile(const string& fullPath, ByteQueue& info) {
  Folder* parent;
  File* file = rootFolder.findFile(fullPath, &parent);
  if (!parent || file) // if parent folder was not found or the file exist
    return nullptr;
  pair<string, string> brokenPath = extractLast(fullPath, '/');
  file = &parent->files[brokenPath.second];
  file->deserialize(info);
  return file;
}

FileSystem::File* FileSystem::retrieveFile(const string& fullPath) {
  return rootFolder.findFile(fullPath);
}

FileSystem::File* FileSystem::updateFile(const string& fullPath, const string& newName) {
  if (!parseName(newName)) // if the new name is invalid
    return nullptr;
  Folder* parent;
  File* file = rootFolder.findFile(fullPath, &parent);
  if (!parent || !file) // if the parent folder or the file don't exist
    return nullptr;
  string newNameWithSlash = string("/") + newName;
  // if the new file already exist
  if (parent->files.find(newNameWithSlash) != parent->files.end())
    return nullptr;
  File* newFile = &parent->files[newNameWithSlash];
  *newFile = *file;
  pair<string, string> brokenPath = extractLast(fullPath, '/');
  parent->files.erase(brokenPath.second);
  return newFile;
}

bool FileSystem::deleteFile(const string& fullPath) {
  Folder* parent;
  File* file = rootFolder.findFile(fullPath, &parent);
  if (!parent || !file) // if the parent folder or the file don't exist
    return false;
  file->erase();
  pair<string, string> brokenPath = extractLast(fullPath, '/');
  parent->files.erase(brokenPath.second);
  return true;
}

uint32_t FileSystem::getTotalFolders() {
  return rootFolder.getTotalFolders();
}

uint32_t FileSystem::getTotalFiles() {
  return rootFolder.getTotalFiles();
}

uint64_t FileSystem::getTotalSize() {
  return rootFolder.getTotalSize();
}

ByteQueue FileSystem::readFile(FILE* fp) {
  fseek(fp, 0, SEEK_END);
  size_t size = ftell(fp);
  fseek(fp, 0, SEEK_SET);
  ByteQueue data(size);
  fread(data.ptr(), size, 1, fp);
  return data;
}
<|endoftext|>


<commit_before>#pragma once

namespace routing
{
namespace transit
{
double constexpr kTransitMaxSpeedKMpH = 400.0;
// @TODO(bykoianko, Zverik) Edge and gate weights should be always valid. This weights should come
// from transit graph json. But now it's not so. |kTransitAverageSpeedMPS| should be used now only for
// weight calculating at transit section generation stage and the constant should be removed later.
double constexpr kTransitAverageSpeedMPS = 11.0;
}  // namespace transit
}  // namespace routing
<commit_msg>Removing unused kTransitAverageSpeedMPS.<commit_after>#pragma once

namespace routing
{
namespace transit
{
double constexpr kTransitMaxSpeedKMpH = 400.0;
}  // namespace transit
}  // namespace routing
<|endoftext|>


<commit_before>#include "riptide_controllers/alignment_controller.h"

#undef debug
#undef report
#undef progress

int main(int argc, char **argv) {
  ros::init(argc, argv, "alignment_controller");
  AlignmentController ac;
  ros::spin();
}

void AlignmentController::UpdateError() {
  sample_duration = ros::Time::now() - sample_start;
  dt = sample_duration.toSec();

  d_y_error = (y_error - last_y_error) / dt;
  last_y_error = y_error;

  accel.data = y_pid.computeCommand(y_error, d_y_error, sample_duration);

  cmd_pub.publish(accel);
  sample_start = ros::Time::now();
}

AlignmentController::AlignmentController() {
    ros::NodeHandle ypid("sway_controller");
    object_sub = nh.subscribe<riptide_msgs::ObjectData>("task/gate/object_data", 1, &AlignmentController::ObjectCB, this);
    y_pid.init(ypid, false);

    cmd_pub = nh.advertise<std_msgs::Float32>("command/accel/linear/y", 1);
    sample_start = ros::Time::now();
}

// Subscribe to state/vision/gate
void AlignmentController::ObjectCB(const riptide_msgs::ObjectData::ConstPtr &msg) {
  // Y axis in robot frame maps to X axis of camera frame
  y_error = msg->rel_pos.x;
  ROS_INFO("%f", y_error);
  AlignmentController::UpdateError();
}
<commit_msg>Began adding depth command to alignment controller<commit_after>#include "riptide_controllers/alignment_controller.h"

#undef debug
#undef report
#undef progress

string[] tasks = {"gate", "pole"};
int tindex = 0;

int main(int argc, char **argv) {
  ros::init(argc, argv, "alignment_controller");
  AlignmentController ac;
  ros::spin();
}

void AlignmentController::UpdateError() {
  sample_duration = ros::Time::now() - sample_start;
  dt = sample_duration.toSec();

  // We are trying to align: -error = target
  x_error = -x_target;
  y_error = -y_target;

  d_x_error = (x_error - last_x_error) / dt;
  d_y_error = (y_error - last_y_error) / dt;

  last_x_error = x_error;
  last_y_error = y_error;

  accel_x.data = x_pid.computeCommand(x_error, d_x_error, sample_duration);
  accel_y.data = y_pid.computeCommand(y_error, d_y_error, sample_duration);
  depth.data = d_error + current_depth;

  // Use depth controller to set
  d_pub.publish(depth);
  x_pub.publish(accel_x);
  y_pub.publish(accel_y);
  sample_start = ros::Time::now();
}

AlignmentController::AlignmentController() {
    ros::NodeHandle xpid("surge_controller");
    ros::NodeHandle ypid("sway_controller");
    object_sub = nh.subscribe<riptide_msgs::ObjectData>("task/" + tasks[tindex] + "/object_data", 1, &AlignmentController::ObjectCB, this);
    depth_sub = nh.subscribe<riptide_msgs::Depth>("state/depth", 1, &AlignmentController::DepthCB, this);

    x_pid.init(xpid, false);
    y_pid.init(ypid, false);

    x_pub = nh.advertise<std_msgs::Float32>("command/accel/linear/x", 1);
    y_pub = nh.advertise<std_msgs::Float32>("command/accel/linear/y", 1);
    d_pub = nh.advertise<std_msgs::Float32>("command/depth", 1);

    sample_start = ros::Time::now();
}

// Subscribe to state/vision/<task>/object_data to get relative position of task.
// Task position is the setpoint
void AlignmentController::ObjectCB(const riptide_msgs::ObjectData::ConstPtr &msg) {
  x_target = msg->rel_pos.x;
  y_target = msg->rel_pos.y;
  d_error = -msg->rel_pos.z;

  ROS_INFO("%f", y_target);
  AlignmentController::UpdateError();
}

// Subscribe to state/depth to update the target depth passed along to the depth controller
void AlignmentController::DepthCB(const riptide_msgs::ObjectData::ConstPtr &msg) {

}
<|endoftext|>


<commit_before>#include "riptide_controllers/alignment_controller.h"

#undef debug
#undef report
#undef progress
#define MAX_TASK_ID 1

string[] tasks = {"gate", "pole"};
int current_task_id = 0;

int main(int argc, char **argv) {
  ros::init(argc, argv, "alignment_controller");
  AlignmentController ac;
  ros::spin();
}

// Function: UpdateError()
// Computes and publishes new commands based on incoming alignment data and
// target data. There is some clever stuff in here to deal with the two alignment
// planes we deal in.
void AlignmentController::UpdateError() {
  sample_duration = ros::Time::now() - sample_start;
  dt = sample_duration.toSec();

  error.y = (target.y - task.y);
  error_dot.y = (error.y - last_error.y) / dt;
  last_error.y = error.y;
  sway_cmd = y_pid.computeCommand(error.y, error_dot.y, sample_duration);

  // If we are aligning in the YZ plane (forward cam), then X acceleration is
  // dependent on bounding box width (approximation for distance from task), while
  // Z acceleration is determined by offset in the Z axis.
  // If we are aligning in the YX plane (downward cam), then Z acceleration is
  // dependent on boudning box width, while X acceleration is determined by offset
  // in the X axis.
  if (alignment_plane == AlignmentCommand.YZ) {
    error.z = (target.z - task.z);
    error.x = (target_bbox_width - task_bbox_width);
  } else if (alignment_plane == AlignmentCommand.YX) {
    error.z = (target_bbox_width - task_bbox_width);
    error.x = (target.x - task.x);
  }

  error_dot.x = (error.x - last_error.x) / dt;
  last_error.x = error.x;
  surge_cmd = x_pid.computeCommand(error.x, error_dot.x, sample_duration);

  error_dot.z = (error.z - last_error.z) / dt;
  last_error.z = error.z;
  heave_cmd = z_pid.computeCommand(error.z, error_dot.z, sample_duration);

  x_pub.publish(surge_cmd);
  y_pub.publish(sway_cmd);
  z_pub.publish(heave_cmd);

  sample_start = ros::Time::now();
}

// Constructor: AlignmentController()
AlignmentController::AlignmentController() {
    ros::NodeHandle surge("surge_controller");
    ros::NodeHandle sway("sway_controller");
    ros::NodeHandle heave("heave_controller");

    alignment_sub = nh.subscribe<riptide_msgs::TaskAlignment>("task/" + tasks[current_task_id] + "/alignment", 1, &AlignmentController::AlignmentCB, this);
    command_sub = nh.subscribe<riptide_msgs::AlignmentCommand>("command/alignment", 1, &AlignmentController::CommandCB, this);

    x_pid.init(surge, false);
    y_pid.init(sway, false);
    z_pid.init(heave, false);

    x_pub = nh.advertise<std_msgs::Float32>("command/accel/linear/x", 1);
    y_pub = nh.advertise<std_msgs::Float32>("command/accel/linear/y", 1);
    z_pub = nh.advertise<std_msgs::Float32>("command/accel/linear/z", 1);

    sample_start = ros::Time::now();
}

// Function: UpdateTaskID
// Parameters: id - ID of the new task to subscribe to
//
void AlignmentController::UpdateTaskID(int id) {
  // Validate id
  if (id >= 0 && id < MAX_TASK_ID) {
    alignment_sub.shutdown(); // Unsubscribe from old task topic
    alignment_sub = nh.subscribe<riptide_msgs::TaskAlignment>("task/" + tasks[current_task_id] + "/alignment", 1, &AlignmentController::AlignmentCB, this);
    current_task_id = id;
  }
}

// Function: AlignmentCB
// Parameters: TaskAlignment msg
// Subscribe to state/vision/<task>/object_data to get relative position of task.
void AlignmentController::AlignmentCB(const riptide_msgs::TaskAlignment::ConstPtr &msg) {
  task.x = msg.relative_pos.x;
  task.y = msg.relative_pos.y;
  task.z = msg.relative_pos.z;

  // Boudning box width is always captured by the Y coordinate of the bounding box vertices.
  // This is because we only care about the YZ (forward cam) and YX (downward cam)
  // planes
  task_bbox_width = abs(msg.bbox.top_left.y - msg.bbox.bottom_right.y);

  AlignmentController::UpdateError();
}

// Function: CommandCB
// Parameters: AlignmentCommand msg
// Subscribe to /command/alignment to get target alignment relative to task
void AlignmentController::CommandCB(const riptide_msgs::AlignmentCommand::ConstPtr &cmd) {
  alignment_plane = cmd.alignment_plane;

  target.x = cmd.target_pos.x;
  target.y = cmd.target_pos.y;
  target.z = cmd.target_pos.z;

  target_bbox_width = cmd.bbox_width;

  if (cmd.task_id != current_task_id) {
    AlignmentController::UpdateTaskID(cmd.task_id);
  }

  AlignmentController::UpdateError();
}
<commit_msg>Require target before aligning<commit_after>#include "riptide_controllers/alignment_controller.h"

#undef debug
#undef report
#undef progress
#define MAX_TASK_ID 1

string[] tasks = {"gate", "pole"};
int current_task_id = 0;

int main(int argc, char **argv) {
  ros::init(argc, argv, "alignment_controller");
  AlignmentController ac;
  ros::spin();
}

// Function: UpdateError()
// Computes and publishes new commands based on incoming alignment data and
// target data. There is some clever stuff in here to deal with the two alignment
// planes we deal in.
void AlignmentController::UpdateError() {
  sample_duration = ros::Time::now() - sample_start;
  dt = sample_duration.toSec();

  error.y = (target.y - task.y);
  error_dot.y = (error.y - last_error.y) / dt;
  last_error.y = error.y;
  sway_cmd = y_pid.computeCommand(error.y, error_dot.y, sample_duration);

  // If we are aligning in the YZ plane (forward cam), then X acceleration is
  // dependent on bounding box width (approximation for distance from task), while
  // Z acceleration is determined by offset in the Z axis.
  // If we are aligning in the YX plane (downward cam), then Z acceleration is
  // dependent on boudning box width, while X acceleration is determined by offset
  // in the X axis.
  if (alignment_plane == AlignmentCommand.YZ) {
    error.z = (target.z - task.z);
    error.x = (target_bbox_width - task_bbox_width);
  } else if (alignment_plane == AlignmentCommand.YX) {
    error.z = (target_bbox_width - task_bbox_width);
    error.x = (target.x - task.x);
  }

  error_dot.x = (error.x - last_error.x) / dt;
  last_error.x = error.x;
  surge_cmd = x_pid.computeCommand(error.x, error_dot.x, sample_duration);

  error_dot.z = (error.z - last_error.z) / dt;
  last_error.z = error.z;
  heave_cmd = z_pid.computeCommand(error.z, error_dot.z, sample_duration);

  x_pub.publish(surge_cmd);
  y_pub.publish(sway_cmd);
  z_pub.publish(heave_cmd);

  sample_start = ros::Time::now();
}

// Constructor: AlignmentController()
AlignmentController::AlignmentController() {
    ros::NodeHandle surge("surge_controller");
    ros::NodeHandle sway("sway_controller");
    ros::NodeHandle heave("heave_controller");

    alignment_sub = nh.subscribe<riptide_msgs::TaskAlignment>("task/" + tasks[current_task_id] + "/alignment", 1, &AlignmentController::AlignmentCB, this);
    command_sub = nh.subscribe<riptide_msgs::AlignmentCommand>("command/alignment", 1, &AlignmentController::CommandCB, this);

    x_pid.init(surge, false);
    y_pid.init(sway, false);
    z_pid.init(heave, false);

    x_pub = nh.advertise<std_msgs::Float32>("command/accel/linear/x", 1);
    y_pub = nh.advertise<std_msgs::Float32>("command/accel/linear/y", 1);
    z_pub = nh.advertise<std_msgs::Float32>("command/accel/linear/z", 1);

    sample_start = ros::Time::now();
}

// Function: UpdateTaskID
// Parameters: id - ID of the new task to subscribe to
//
void AlignmentController::UpdateTaskID(int id) {
  // Validate id
  if (id >= 0 && id < MAX_TASK_ID) {
    alignment_sub.shutdown(); // Unsubscribe from old task topic
    alignment_sub = nh.subscribe<riptide_msgs::TaskAlignment>("task/" + tasks[current_task_id] + "/alignment", 1, &AlignmentController::AlignmentCB, this);
    current_task_id = id;
  }
}

// Function: AlignmentCB
// Parameters: TaskAlignment msg
// Subscribe to state/vision/<task>/object_data to get relative position of task.
void AlignmentController::AlignmentCB(const riptide_msgs::TaskAlignment::ConstPtr &msg) {
  if (pid_initialized) {
    task.x = msg.relative_pos.x;
    task.y = msg.relative_pos.y;
    task.z = msg.relative_pos.z;

    // Boudning box width is always captured by the Y coordinate of the bounding box vertices.
    // This is because we only care about the YZ (forward cam) and YX (downward cam)
    // planes
    task_bbox_width = abs(msg.bbox.top_left.y - msg.bbox.bottom_right.y);

    AlignmentController::UpdateError();
  }
}

// Function: CommandCB
// Parameters: AlignmentCommand msg
// Subscribe to /command/alignment to get target alignment relative to task
void AlignmentController::CommandCB(const riptide_msgs::AlignmentCommand::ConstPtr &cmd) {
  alignment_plane = cmd.alignment_plane;

  target.x = cmd.target_pos.x;
  target.y = cmd.target_pos.y;
  target.z = cmd.target_pos.z;

  target_bbox_width = cmd.bbox_width;

  if (cmd.task_id != current_task_id) {
    AlignmentController::UpdateTaskID(cmd.task_id);
  }

  AlignmentController::UpdateError();

  if (!pid_initialized)
    pid_initialized = true;
}
<|endoftext|>