<commit_before>/*
**  Copyright (C) 2012 Aldebaran Robotics
**  See COPYING for the license
*/

// Disable "'this': used in base member initializer list"
#ifdef _MSC_VER
# pragma warning( push )
# pragma warning(disable: 4355)
#endif

#include <iostream>
#include <vector>
#include <map>
#include <set>

#include <qitype/genericobject.hpp>
#include <qimessaging/transportserver.hpp>
#include <qimessaging/transportsocket.hpp>
#include <qimessaging/servicedirectory.hpp>
#include <qimessaging/session.hpp>
#include <qimessaging/serviceinfo.hpp>
#include <qitype/objecttypebuilder.hpp>
#include "transportserver_p.hpp"
#include "serverresult.hpp"
#include "session_p.hpp"
#include <qi/os.hpp>
#include <qi/log.hpp>
#include <qimessaging/url.hpp>
#include "servicedirectory_p.hpp"
#include "server.hpp"

qiLogCategory("qimessaging.servicedirectory");

namespace qi
{
  ServiceDirectoryPrivate::ServiceDirectoryPrivate()
    : _sdbo(boost::shared_ptr<ServiceDirectoryBoundObject>(new ServiceDirectoryBoundObject))
  {
    _server.addObject(1, _sdbo);
  }

  ServiceDirectoryPrivate::~ServiceDirectoryPrivate()
  {
  }

  qi::ObjectPtr createSDP(ServiceDirectoryBoundObject* self) {
    static qi::ObjectTypeBuilder<ServiceDirectoryBoundObject>* ob = 0;
    if (!ob)
    {
      ob = new qi::ObjectTypeBuilder<ServiceDirectoryBoundObject>();
      ob->advertiseMethod("service", &ServiceDirectoryBoundObject::service);
      ob->advertiseMethod("services", &ServiceDirectoryBoundObject::services);
      ob->advertiseMethod("registerService", &ServiceDirectoryBoundObject::registerService);
      ob->advertiseMethod("unregisterService", &ServiceDirectoryBoundObject::unregisterService);
      ob->advertiseMethod("serviceReady", &ServiceDirectoryBoundObject::serviceReady);
      ob->advertiseEvent("serviceAdded", &ServiceDirectoryBoundObject::serviceAdded);
      ob->advertiseEvent("serviceRemoved", &ServiceDirectoryBoundObject::serviceRemoved);
    }
    return ob->object(self);
  }

  ServiceDirectoryBoundObject::ServiceDirectoryBoundObject()
    : ServiceBoundObject(1, Message::GenericObject_Main, createSDP(this), qi::MetaCallType_Direct)
    , servicesCount(0)
  {
  }

  ServiceDirectoryBoundObject::~ServiceDirectoryBoundObject()
  {
  }

  void ServiceDirectoryBoundObject::onSocketDisconnected(TransportSocketPtr socket, int error)
  {
    boost::recursive_mutex::scoped_lock lock(mutex);
    // if services were connected behind the socket
    std::map<TransportSocketPtr, std::vector<unsigned int> >::iterator it;
    it = socketToIdx.find(socket);
    if (it == socketToIdx.end()) {
      ServiceBoundObject::onSocketDisconnected(socket, error);
      return;
    }
    // Copy the vector, iterators will be invalidated.
    std::vector<unsigned int> ids = it->second;
    // Always start at the beginning since we erase elements on unregisterService
    // and mess up the iterator
    for (std::vector<unsigned int>::iterator it2 = ids.begin();
         it2 != ids.end();
         ++it2)
    {
      qiLogInfo() << "Service #" << *it2 << " disconnected";
      try {
        unregisterService(*it2);
      } catch (std::runtime_error &) {
        qiLogWarning() << "Cannot unregister service #" << *it2;
      }
    }
    socketToIdx.erase(it);
    ServiceBoundObject::onSocketDisconnected(socket, error);
  }

  std::vector<ServiceInfo> ServiceDirectoryBoundObject::services()
  {
    boost::recursive_mutex::scoped_lock lock(mutex);
    std::vector<ServiceInfo> result;
    std::map<unsigned int, ServiceInfo>::const_iterator it;

    for (it = connectedServices.begin(); it != connectedServices.end(); ++it)
      result.push_back(it->second);

    return result;
  }

  ServiceInfo ServiceDirectoryBoundObject::service(const std::string &name)
  {
    boost::recursive_mutex::scoped_lock lock(mutex);
    std::map<unsigned int, ServiceInfo>::const_iterator servicesIt;
    std::map<std::string, unsigned int>::const_iterator it;

    it = nameToIdx.find(name);
    if (it == nameToIdx.end()) {
      std::stringstream ss;
      ss << "Cannot find service '" << name << "' in index";
      throw std::runtime_error(ss.str());
    }

    unsigned int idx = it->second;

    servicesIt = connectedServices.find(idx);
    if (servicesIt == connectedServices.end()) {
      std::stringstream ss;
      ss << "Cannot find ServiceInfo for service '" << name << "'";
      throw std::runtime_error(ss.str());
    }
    return servicesIt->second;
  }

  unsigned int ServiceDirectoryBoundObject::registerService(const ServiceInfo &svcinfo)
  {
    boost::recursive_mutex::scoped_lock lock(mutex);
    std::map<std::string, unsigned int>::iterator it;
    it = nameToIdx.find(svcinfo.name());
    if (it != nameToIdx.end())
    {
      std::stringstream ss;
      ss << "Service \"" <<
        svcinfo.name() <<
        "\" (#" << it->second << ") is already registered. " <<
        "Rejecting conflicting registration attempt.";
      qiLogWarning()  << ss.str();
      throw std::runtime_error(ss.str());
    }

    unsigned int idx = ++servicesCount;
    nameToIdx[svcinfo.name()] = idx;
    // Do not add serviceDirectory on the map (socket() == null)
    if (idx != qi::Message::Service_ServiceDirectory)
    {
      socketToIdx[currentSocket()].push_back(idx);
    }
    pendingServices[idx] = svcinfo;
    pendingServices[idx].setServiceId(idx);

    std::stringstream ss;
    ss << "Registered Service \"" << svcinfo.name() << "\" (#" << idx << ")";
    if (! svcinfo.name().empty() && svcinfo.name()[0] == '_') {
      // Hide services whose name starts with an underscore
      qiLogDebug() << ss.str();
    }
    else
    {
      qiLogInfo() << ss.str();
    }

    qi::UrlVector::const_iterator jt;
    for (jt = svcinfo.endpoints().begin(); jt != svcinfo.endpoints().end(); ++jt)
    {
      qiLogDebug() << "Service \"" << svcinfo.name() << "\" is now on " << jt->str();
    }

    return idx;
  }

  void ServiceDirectoryBoundObject::unregisterService(const unsigned int &idx)
  {
    boost::recursive_mutex::scoped_lock lock(mutex);
    // search the id before accessing it
    // otherwise operator[] create a empty entry
    std::map<unsigned int, ServiceInfo>::iterator it2;
    it2 = connectedServices.find(idx);
    if (it2 == connectedServices.end())
    {
      std::stringstream ss;
      ss << "Unregister Service: Can't find service #" << idx;
      qiLogError() << ss.str();
      throw std::runtime_error(ss.str());
    }

    std::map<std::string, unsigned int>::iterator it;
    it = nameToIdx.find(connectedServices[idx].name());
    if (it == nameToIdx.end())
    {
      std::stringstream ss;
      ss << "Unregister Service: Mapping error, service #" << idx << " not in nameToIdx";
      qiLogError() << ss.str();
      throw std::runtime_error(ss.str());
    }
    std::string serviceName = it2->second.name();

    std::stringstream ss;
    ss << "Unregistered Service  \""
          << serviceName
          << "\" (#" << idx << ")";

    if (! serviceName.empty() && serviceName[0] == '_') {
      // Hide services whose name starts with underscore
      qiLogDebug() << ss.str();
    }
    else
    {
      qiLogInfo() << ss.str();
    }

    nameToIdx.erase(it);
    connectedServices.erase(it2);

    // Find and remove serviceId into socketToIdx map
    {
      std::map<TransportSocketPtr , std::vector<unsigned int> >::iterator it;
      for (it = socketToIdx.begin(); it != socketToIdx.end(); ++it) {
        std::vector<unsigned int>::iterator jt;
        for (jt = it->second.begin(); jt != it->second.end(); ++jt) {
          if (*jt == idx) {
            it->second.erase(jt);
            //socketToIdx is erased by onSocketDisconnected
            break;
          }
        }
      }
    }
    serviceRemoved(idx, serviceName);
  }

  void ServiceDirectoryBoundObject::serviceReady(const unsigned int &idx)
  {
    boost::recursive_mutex::scoped_lock lock(mutex);
    // search the id before accessing it
    // otherwise operator[] create a empty entry
    std::map<unsigned int, ServiceInfo>::iterator itService;
    itService = pendingServices.find(idx);
    if (itService == pendingServices.end())
    {
      std::stringstream ss;
      ss << "Can't find pending service #" << idx;
      qiLogError() << ss.str();
      throw std::runtime_error(ss.str());
    }

    std::string serviceName = itService->second.name();
    connectedServices[idx] = itService->second;
    pendingServices.erase(itService);

    serviceAdded(idx, serviceName);
  }

  ServiceDirectory::ServiceDirectory()
    : _p(new ServiceDirectoryPrivate())
  {
  }

  ServiceDirectory::~ServiceDirectory()
  {
    close();
    delete _p;
  }

  qi::Future<void> ServiceDirectory::listen(const qi::Url &address)
  {
    qiLogInfo() << "ServiceDirectory listener created on " << address.str();
    qi::Future<void> f = _p->_server.listen(address);

    ServiceDirectoryBoundObject *sdbo = static_cast<ServiceDirectoryBoundObject*>(_p->_sdbo.get());

    ServiceInfo si;
    si.setName("ServiceDirectory");
    si.setServiceId(1);
    si.setMachineId(qi::os::getMachineId());
    si.setEndpoints(_p->_server.endpoints());
    unsigned int regid = sdbo->registerService(si);
    sdbo->serviceReady(1);
    //serviceDirectory must have id '1'
    assert(regid == 1);
    return f;
  }

  bool ServiceDirectory::setIdentity(const std::string& key,
                                     const std::string& crt)
  {
    return _p->_server.setIdentity(key, crt);
  }

  qi::UrlVector ServiceDirectory::endpoints() const {
    return _p->_server.endpoints();
  }

  void ServiceDirectory::close() {
    qiLogInfo() << "Closing ServiceDirectory";
    _p->_server.close();
  }

} // !qi

#ifdef _MSC_VER
# pragma warning( pop )
#endif
<commit_msg>servicedirectory: unregisterService: handle pendingService<commit_after>/*
**  Copyright (C) 2012 Aldebaran Robotics
**  See COPYING for the license
*/

// Disable "'this': used in base member initializer list"
#ifdef _MSC_VER
# pragma warning( push )
# pragma warning(disable: 4355)
#endif

#include <iostream>
#include <vector>
#include <map>
#include <set>

#include <qitype/genericobject.hpp>
#include <qimessaging/transportserver.hpp>
#include <qimessaging/transportsocket.hpp>
#include <qimessaging/servicedirectory.hpp>
#include <qimessaging/session.hpp>
#include <qimessaging/serviceinfo.hpp>
#include <qitype/objecttypebuilder.hpp>
#include "transportserver_p.hpp"
#include "serverresult.hpp"
#include "session_p.hpp"
#include <qi/os.hpp>
#include <qi/log.hpp>
#include <qimessaging/url.hpp>
#include "servicedirectory_p.hpp"
#include "server.hpp"

qiLogCategory("qimessaging.servicedirectory");

namespace qi
{
  ServiceDirectoryPrivate::ServiceDirectoryPrivate()
    : _sdbo(boost::shared_ptr<ServiceDirectoryBoundObject>(new ServiceDirectoryBoundObject))
  {
    _server.addObject(1, _sdbo);
  }

  ServiceDirectoryPrivate::~ServiceDirectoryPrivate()
  {
  }

  qi::ObjectPtr createSDP(ServiceDirectoryBoundObject* self) {
    static qi::ObjectTypeBuilder<ServiceDirectoryBoundObject>* ob = 0;
    if (!ob)
    {
      ob = new qi::ObjectTypeBuilder<ServiceDirectoryBoundObject>();
      ob->advertiseMethod("service", &ServiceDirectoryBoundObject::service);
      ob->advertiseMethod("services", &ServiceDirectoryBoundObject::services);
      ob->advertiseMethod("registerService", &ServiceDirectoryBoundObject::registerService);
      ob->advertiseMethod("unregisterService", &ServiceDirectoryBoundObject::unregisterService);
      ob->advertiseMethod("serviceReady", &ServiceDirectoryBoundObject::serviceReady);
      ob->advertiseEvent("serviceAdded", &ServiceDirectoryBoundObject::serviceAdded);
      ob->advertiseEvent("serviceRemoved", &ServiceDirectoryBoundObject::serviceRemoved);
    }
    return ob->object(self);
  }

  ServiceDirectoryBoundObject::ServiceDirectoryBoundObject()
    : ServiceBoundObject(1, Message::GenericObject_Main, createSDP(this), qi::MetaCallType_Direct)
    , servicesCount(0)
  {
  }

  ServiceDirectoryBoundObject::~ServiceDirectoryBoundObject()
  {
  }

  void ServiceDirectoryBoundObject::onSocketDisconnected(TransportSocketPtr socket, int error)
  {
    boost::recursive_mutex::scoped_lock lock(mutex);
    // if services were connected behind the socket
    std::map<TransportSocketPtr, std::vector<unsigned int> >::iterator it;
    it = socketToIdx.find(socket);
    if (it == socketToIdx.end()) {
      ServiceBoundObject::onSocketDisconnected(socket, error);
      return;
    }
    // Copy the vector, iterators will be invalidated.
    std::vector<unsigned int> ids = it->second;
    // Always start at the beginning since we erase elements on unregisterService
    // and mess up the iterator
    for (std::vector<unsigned int>::iterator it2 = ids.begin();
         it2 != ids.end();
         ++it2)
    {
      qiLogInfo() << "Service #" << *it2 << " disconnected";
      try {
        unregisterService(*it2);
      } catch (std::runtime_error &) {
        qiLogWarning() << "Cannot unregister service #" << *it2;
      }
    }
    socketToIdx.erase(it);
    ServiceBoundObject::onSocketDisconnected(socket, error);
  }

  std::vector<ServiceInfo> ServiceDirectoryBoundObject::services()
  {
    boost::recursive_mutex::scoped_lock lock(mutex);
    std::vector<ServiceInfo> result;
    std::map<unsigned int, ServiceInfo>::const_iterator it;

    for (it = connectedServices.begin(); it != connectedServices.end(); ++it)
      result.push_back(it->second);

    return result;
  }

  ServiceInfo ServiceDirectoryBoundObject::service(const std::string &name)
  {
    boost::recursive_mutex::scoped_lock lock(mutex);
    std::map<unsigned int, ServiceInfo>::const_iterator servicesIt;
    std::map<std::string, unsigned int>::const_iterator it;

    it = nameToIdx.find(name);
    if (it == nameToIdx.end()) {
      std::stringstream ss;
      ss << "Cannot find service '" << name << "' in index";
      throw std::runtime_error(ss.str());
    }

    unsigned int idx = it->second;

    servicesIt = connectedServices.find(idx);
    if (servicesIt == connectedServices.end()) {
      std::stringstream ss;
      ss << "Cannot find ServiceInfo for service '" << name << "'";
      throw std::runtime_error(ss.str());
    }
    return servicesIt->second;
  }

  unsigned int ServiceDirectoryBoundObject::registerService(const ServiceInfo &svcinfo)
  {
    boost::recursive_mutex::scoped_lock lock(mutex);
    std::map<std::string, unsigned int>::iterator it;
    it = nameToIdx.find(svcinfo.name());
    if (it != nameToIdx.end())
    {
      std::stringstream ss;
      ss << "Service \"" <<
        svcinfo.name() <<
        "\" (#" << it->second << ") is already registered. " <<
        "Rejecting conflicting registration attempt.";
      qiLogWarning()  << ss.str();
      throw std::runtime_error(ss.str());
    }

    unsigned int idx = ++servicesCount;
    nameToIdx[svcinfo.name()] = idx;
    // Do not add serviceDirectory on the map (socket() == null)
    if (idx != qi::Message::Service_ServiceDirectory)
    {
      socketToIdx[currentSocket()].push_back(idx);
    }
    pendingServices[idx] = svcinfo;
    pendingServices[idx].setServiceId(idx);

    std::stringstream ss;
    ss << "Registered Service \"" << svcinfo.name() << "\" (#" << idx << ")";
    if (! svcinfo.name().empty() && svcinfo.name()[0] == '_') {
      // Hide services whose name starts with an underscore
      qiLogDebug() << ss.str();
    }
    else
    {
      qiLogInfo() << ss.str();
    }

    qi::UrlVector::const_iterator jt;
    for (jt = svcinfo.endpoints().begin(); jt != svcinfo.endpoints().end(); ++jt)
    {
      qiLogDebug() << "Service \"" << svcinfo.name() << "\" is now on " << jt->str();
    }

    return idx;
  }

  void ServiceDirectoryBoundObject::unregisterService(const unsigned int &idx)
  {
    boost::recursive_mutex::scoped_lock lock(mutex);
    bool pending = false;
    // search the id before accessing it
    // otherwise operator[] create a empty entry
    std::map<unsigned int, ServiceInfo>::iterator it2;
    it2 = connectedServices.find(idx);
    if (it2 == connectedServices.end()) {
      qiLogVerbose() << "Unregister Service: service #" << idx << " not found in the"
                     << " connected list. Looking in the pending list.";
      it2 = pendingServices.find(idx);
      pending = true;
      if (it2 == pendingServices.end())
      {
        std::stringstream ss;
        ss << "Unregister Service: Can't find service #" << idx;
        qiLogError() << ss.str();
        throw std::runtime_error(ss.str());
      }
    }

    std::string serviceName = it2->second.name();

    std::map<std::string, unsigned int>::iterator it;
    it = nameToIdx.find(serviceName);
    if (it == nameToIdx.end())
    {
      std::stringstream ss;
      ss << "Unregister Service: Mapping error, service #" << idx << " (" << serviceName << ") not in nameToIdx";
      qiLogError() << ss.str();
      throw std::runtime_error(ss.str());
    }

    std::stringstream ss;
    ss << "Unregistered Service  \""
          << serviceName
          << "\" (#" << idx << ")";

    if (! serviceName.empty() && serviceName[0] == '_') {
      // Hide services whose name starts with underscore
      qiLogDebug() << ss.str();
    }
    else
    {
      qiLogInfo() << ss.str();
    }

    nameToIdx.erase(it);
    if (pending)
      pendingServices.erase(it2);
    else
      connectedServices.erase(it2);

    // Find and remove serviceId into socketToIdx map
    {
      std::map<TransportSocketPtr , std::vector<unsigned int> >::iterator it;
      for (it = socketToIdx.begin(); it != socketToIdx.end(); ++it) {
        std::vector<unsigned int>::iterator jt;
        for (jt = it->second.begin(); jt != it->second.end(); ++jt) {
          if (*jt == idx) {
            it->second.erase(jt);
            //socketToIdx is erased by onSocketDisconnected
            break;
          }
        }
      }
    }
    serviceRemoved(idx, serviceName);
  }

  void ServiceDirectoryBoundObject::serviceReady(const unsigned int &idx)
  {
    boost::recursive_mutex::scoped_lock lock(mutex);
    // search the id before accessing it
    // otherwise operator[] create a empty entry
    std::map<unsigned int, ServiceInfo>::iterator itService;
    itService = pendingServices.find(idx);
    if (itService == pendingServices.end())
    {
      std::stringstream ss;
      ss << "Can't find pending service #" << idx;
      qiLogError() << ss.str();
      throw std::runtime_error(ss.str());
    }

    std::string serviceName = itService->second.name();
    connectedServices[idx] = itService->second;
    pendingServices.erase(itService);

    serviceAdded(idx, serviceName);
  }

  ServiceDirectory::ServiceDirectory()
    : _p(new ServiceDirectoryPrivate())
  {
  }

  ServiceDirectory::~ServiceDirectory()
  {
    close();
    delete _p;
  }

  qi::Future<void> ServiceDirectory::listen(const qi::Url &address)
  {
    qiLogInfo() << "ServiceDirectory listener created on " << address.str();
    qi::Future<void> f = _p->_server.listen(address);

    ServiceDirectoryBoundObject *sdbo = static_cast<ServiceDirectoryBoundObject*>(_p->_sdbo.get());

    ServiceInfo si;
    si.setName("ServiceDirectory");
    si.setServiceId(1);
    si.setMachineId(qi::os::getMachineId());
    si.setEndpoints(_p->_server.endpoints());
    unsigned int regid = sdbo->registerService(si);
    sdbo->serviceReady(1);
    //serviceDirectory must have id '1'
    assert(regid == 1);
    return f;
  }

  bool ServiceDirectory::setIdentity(const std::string& key,
                                     const std::string& crt)
  {
    return _p->_server.setIdentity(key, crt);
  }

  qi::UrlVector ServiceDirectory::endpoints() const {
    return _p->_server.endpoints();
  }

  void ServiceDirectory::close() {
    qiLogInfo() << "Closing ServiceDirectory";
    _p->_server.close();
  }

} // !qi

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


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <iostream>

#include "ast/DebugVisitor.hpp"
#include "ast/SourceFile.hpp"

#include "VisitorUtils.hpp"
#include "Variable.hpp"

using namespace eddic;

ast::DebugVisitor::DebugVisitor() : level(0) {}

std::string ast::DebugVisitor::indent() const {
    std::string acc = "";
    for(int i = 0; i < level; ++i){
        acc += "\t";
    }
    return acc;
}

std::string toStringType(ast::Type type){
    if(auto* ptr = boost::get<ast::SimpleType>(&type)){
        return ptr->type;
    } else if(auto* ptr = boost::get<ast::ArrayType>(&type)){
        return ptr->type + "[]";
    }

    assert(false);
}

void ast::DebugVisitor::operator()(ast::SourceFile& program) const {
    std::cout << indent() << "SourceFile" << std::endl;

    ++level;

    visit_each(*this, program.Content->blocks);
}

void ast::DebugVisitor::operator()(ast::Import& import) const {
    std::cout << indent() << "include \"" << import.file << "\"" << std::endl;
}

void ast::DebugVisitor::operator()(ast::StandardImport& import) const {
    std::cout << indent() << "include <" << import.header << ">" << std::endl;
}

template<typename Visitor, typename Container>
void print_each_sub(Visitor& visitor, Container& container){
    visitor.level++;
    visit_each(visitor, container);
    visitor.level--;
}

template<typename Visitor, typename Container>
void print_sub(Visitor& visitor, Container& container){
    visitor.level++;
    visit(visitor, container);
    visitor.level--;
}

void ast::DebugVisitor::operator()(ast::FunctionDeclaration& declaration) const {
    std::cout << indent() << "Function " << declaration.Content->functionName << std::endl;
    print_each_sub(*this, declaration.Content->instructions);
}

void ast::DebugVisitor::operator()(ast::Struct& struct_) const {
    std::cout << indent() << "Structure declaration: " << struct_.Content->name << std::endl;
    level++;
    visit_each_non_variant(*this, struct_.Content->members);
    level--;
}

void ast::DebugVisitor::operator()(ast::MemberDeclaration& declaration) const {
    std::cout << indent() << declaration.Content->type  << " " << declaration.Content->name << std::endl;
}

void ast::DebugVisitor::operator()(ast::GlobalVariableDeclaration&) const {
    std::cout << indent() << "Global Variable" << std::endl;
}

void ast::DebugVisitor::operator()(ast::GlobalArrayDeclaration&) const {
    std::cout << indent() << "Global Array" << std::endl;
}

void ast::DebugVisitor::operator()(ast::For& for_) const {
    std::cout << indent() << "For" << std::endl;
    print_each_sub(*this, for_.Content->instructions);
}

void ast::DebugVisitor::operator()(ast::Foreach& for_) const {
    std::cout << indent() << "Foreach" << std::endl;
    print_each_sub(*this, for_.Content->instructions);
}

void ast::DebugVisitor::operator()(ast::ForeachIn& for_) const {
    std::cout << indent() << "Foreach in " << std::endl;
    print_each_sub(*this, for_.Content->instructions);
}

void ast::DebugVisitor::operator()(ast::While& while_) const {
    std::cout << indent() << "While" << std::endl;
    std::cout << indent() << "Condition:" << std::endl;
    print_sub(*this, while_.Content->condition);
    print_each_sub(*this, while_.Content->instructions);
}

void ast::DebugVisitor::operator()(ast::DoWhile& while_) const {
    std::cout << indent() << "Do while" << std::endl;
    std::cout << indent() << "Condition:" << std::endl;
    print_sub(*this, while_.Content->condition);
    std::cout << indent() << "Body:" << std::endl;
    print_each_sub(*this, while_.Content->instructions);
}

void ast::DebugVisitor::operator()(ast::Swap&) const {
    std::cout << indent() << "Swap" << std::endl;
}

void ast::DebugVisitor::operator()(ast::If& if_) const {
    std::cout << indent() << "If" << std::endl;
    std::cout << indent() << "Condition:" << std::endl;
    print_sub(*this, if_.Content->condition);
    std::cout << indent() << "Body:" << std::endl;
    print_each_sub(*this, if_.Content->instructions);
}

void ast::DebugVisitor::operator()(ast::FunctionCall& call) const {
    std::cout << indent() << "FunctionCall " << call.Content->functionName << std::endl;
    print_each_sub(*this, call.Content->values);
}

void ast::DebugVisitor::operator()(ast::BuiltinOperator& builtin) const {
    std::cout << indent() << "Builtin Operator " << (int) builtin.Content->type << std::endl;
    print_each_sub(*this, builtin.Content->values);
}

void ast::DebugVisitor::operator()(ast::VariableDeclaration& declaration) const {
    std::cout << indent() << "Variable declaration [" << declaration.Content->variableName << "]" << std::endl;

    if(declaration.Content->value){
        print_sub(*this, *declaration.Content->value);
    }
}

void ast::DebugVisitor::operator()(ast::ArrayDeclaration&) const {
    std::cout << indent() << "Array declaration" << std::endl;
}

void ast::DebugVisitor::operator()(ast::SuffixOperation& op) const {
    std::cout << indent() << op.Content->variableName << "(suffix)" << (int)op.Content->op << std::endl;
}

void ast::DebugVisitor::operator()(ast::PrefixOperation& op) const {
    std::cout << indent() << (int)op.Content->op << "(prefix)" << op.Content->variableName << std::endl;
}

void ast::DebugVisitor::operator()(ast::Assignment& assign) const {
    std::cout << indent() << "Assignment [operator = " << static_cast<int>(assign.Content->op) << " ] ";
    visit(*this, assign.Content->left_value);

    print_sub(*this, assign.Content->value);
}

void ast::DebugVisitor::operator()(ast::Return& return_) const {
    std::cout << indent() << "Function return" << std::endl;
    print_sub(*this, return_.Content->value);
}

void ast::DebugVisitor::operator()(ast::Litteral& litteral) const {
    std::cout << indent() << "Litteral [" << litteral.value << "]" << std::endl;
}

void ast::DebugVisitor::operator()(ast::Integer& integer) const {
    std::cout << indent() << "Integer [" << integer.value << "]" << std::endl;
}

void ast::DebugVisitor::operator()(ast::IntegerSuffix& integer) const {
    std::cout << indent() << "Float (suffix) [" << integer.value << "f]" << std::endl;
}

void ast::DebugVisitor::operator()(ast::Float& float_) const {
    std::cout << indent() << "Float [" << float_.value << "]" << std::endl;
}

void ast::DebugVisitor::operator()(ast::True&) const {
    std::cout << indent() << "true" << std::endl;
}

void ast::DebugVisitor::operator()(ast::Null&) const {
    std::cout << indent() << "null" << std::endl;
}

void ast::DebugVisitor::operator()(ast::False&) const {
    std::cout << indent() << "false" << std::endl;
}

void ast::DebugVisitor::operator()(ast::VariableValue& value) const {
    std::cout << indent() << "Variable " << value.Content->var->name();

    for(auto& member : value.Content->memberNames){
        std::cout << "." << member;
    }

    std::cout << std::endl;
}

void ast::DebugVisitor::operator()(ast::DereferenceValue& value) const {
    std::cout << indent() << "Dereference Variable Value" << std::endl;;

    print_sub(*this, value.Content->ref);
}

void ast::DebugVisitor::operator()(ast::ArrayValue&) const {
    std::cout << indent() << "Array value" << std::endl;
}

void ast::DebugVisitor::operator()(ast::Expression& value) const {
    std::cout << indent() << "Expression [" << value.Content->operations.size() << "]" << std::endl;
    ++level;
    visit(*this, value.Content->first);
    for(auto& operation : value.Content->operations){
        std::cout << indent() << (int) operation.get<0>() << std::endl;
        visit(*this, operation.get<1>());
    }
    --level;
}

void ast::DebugVisitor::operator()(ast::Minus& value) const {
    std::cout << indent() << "Unary +" << std::endl;
    print_sub(*this, value.Content->value);
}

void ast::DebugVisitor::operator()(ast::Plus& value) const {
    std::cout << indent() << "Unary -" << std::endl;
    print_sub(*this, value.Content->value);
}

void ast::DebugVisitor::operator()(ast::Cast& cast) const {
    std::cout << indent() << "Cast " << std::endl;
    std::cout << indent() << "\tType: " << toStringType(cast.Content->type) << std::endl;
    print_sub(*this, cast.Content->value);
}
<commit_msg>Improve the printing<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <iostream>

#include "ast/DebugVisitor.hpp"
#include "ast/SourceFile.hpp"

#include "VisitorUtils.hpp"
#include "Variable.hpp"

using namespace eddic;

ast::DebugVisitor::DebugVisitor() : level(0) {}

std::string ast::DebugVisitor::indent() const {
    std::string acc = "";
    for(int i = 0; i < level; ++i){
        acc += "\t";
    }
    return acc;
}

std::string toStringType(ast::Type type){
    if(auto* ptr = boost::get<ast::SimpleType>(&type)){
        return ptr->type;
    } else if(auto* ptr = boost::get<ast::ArrayType>(&type)){
        return ptr->type + "[]";
    }

    assert(false);
}

void ast::DebugVisitor::operator()(ast::SourceFile& program) const {
    std::cout << indent() << "SourceFile" << std::endl;

    ++level;

    visit_each(*this, program.Content->blocks);
}

void ast::DebugVisitor::operator()(ast::Import& import) const {
    std::cout << indent() << "include \"" << import.file << "\"" << std::endl;
}

void ast::DebugVisitor::operator()(ast::StandardImport& import) const {
    std::cout << indent() << "include <" << import.header << ">" << std::endl;
}

template<typename Visitor, typename Container>
void print_each_sub(Visitor& visitor, Container& container){
    visitor.level++;
    visit_each(visitor, container);
    visitor.level--;
}

template<typename Visitor, typename Container>
void print_sub(Visitor& visitor, Container& container){
    visitor.level++;
    visit(visitor, container);
    visitor.level--;
}

void ast::DebugVisitor::operator()(ast::FunctionDeclaration& declaration) const {
    std::cout << indent() << "Function " << declaration.Content->functionName << std::endl;
    print_each_sub(*this, declaration.Content->instructions);
}

void ast::DebugVisitor::operator()(ast::Struct& struct_) const {
    std::cout << indent() << "Structure declaration: " << struct_.Content->name << std::endl;
    level++;
    visit_each_non_variant(*this, struct_.Content->members);
    level--;
}

void ast::DebugVisitor::operator()(ast::MemberDeclaration& declaration) const {
    std::cout << indent() << declaration.Content->type  << " " << declaration.Content->name << std::endl;
}

void ast::DebugVisitor::operator()(ast::GlobalVariableDeclaration&) const {
    std::cout << indent() << "Global Variable" << std::endl;
}

void ast::DebugVisitor::operator()(ast::GlobalArrayDeclaration&) const {
    std::cout << indent() << "Global Array" << std::endl;
}

void ast::DebugVisitor::operator()(ast::For& for_) const {
    std::cout << indent() << "For" << std::endl;
    print_each_sub(*this, for_.Content->instructions);
}

void ast::DebugVisitor::operator()(ast::Foreach& for_) const {
    std::cout << indent() << "Foreach" << std::endl;
    print_each_sub(*this, for_.Content->instructions);
}

void ast::DebugVisitor::operator()(ast::ForeachIn& for_) const {
    std::cout << indent() << "Foreach in " << std::endl;
    print_each_sub(*this, for_.Content->instructions);
}

void ast::DebugVisitor::operator()(ast::While& while_) const {
    std::cout << indent() << "While" << std::endl;
    std::cout << indent() << "Condition:" << std::endl;
    print_sub(*this, while_.Content->condition);
    print_each_sub(*this, while_.Content->instructions);
}

void ast::DebugVisitor::operator()(ast::DoWhile& while_) const {
    std::cout << indent() << "Do while" << std::endl;
    std::cout << indent() << "Condition:" << std::endl;
    print_sub(*this, while_.Content->condition);
    std::cout << indent() << "Body:" << std::endl;
    print_each_sub(*this, while_.Content->instructions);
}

void ast::DebugVisitor::operator()(ast::Swap&) const {
    std::cout << indent() << "Swap" << std::endl;
}

void ast::DebugVisitor::operator()(ast::If& if_) const {
    std::cout << indent() << "If" << std::endl;
    std::cout << indent() << "Condition:" << std::endl;
    print_sub(*this, if_.Content->condition);
    std::cout << indent() << "Body:" << std::endl;
    print_each_sub(*this, if_.Content->instructions);
}

void ast::DebugVisitor::operator()(ast::FunctionCall& call) const {
    std::cout << indent() << "FunctionCall " << call.Content->functionName << std::endl;
    print_each_sub(*this, call.Content->values);
}

void ast::DebugVisitor::operator()(ast::BuiltinOperator& builtin) const {
    std::cout << indent() << "Builtin Operator " << (int) builtin.Content->type << std::endl;
    print_each_sub(*this, builtin.Content->values);
}

void ast::DebugVisitor::operator()(ast::VariableDeclaration& declaration) const {
    std::cout << indent() << "Variable declaration [" << declaration.Content->variableName << "]" << std::endl;

    if(declaration.Content->value){
        print_sub(*this, *declaration.Content->value);
    }
}

void ast::DebugVisitor::operator()(ast::ArrayDeclaration&) const {
    std::cout << indent() << "Array declaration" << std::endl;
}

void ast::DebugVisitor::operator()(ast::SuffixOperation& op) const {
    std::cout << indent() << op.Content->variableName << "(suffix)" << (int)op.Content->op << std::endl;
}

void ast::DebugVisitor::operator()(ast::PrefixOperation& op) const {
    std::cout << indent() << (int)op.Content->op << "(prefix)" << op.Content->variableName << std::endl;
}

void ast::DebugVisitor::operator()(ast::Assignment& assign) const {
    std::cout << indent() << "Assignment [operator = " << static_cast<int>(assign.Content->op) << " ] " << std::endl;

    std::cout << indent() << "Left Value:" << std::endl;
    print_sub(*this, assign.Content->left_value);

    std::cout << indent() << "Right Value:" << std::endl;
    print_sub(*this, assign.Content->value);
}

void ast::DebugVisitor::operator()(ast::Return& return_) const {
    std::cout << indent() << "Function return" << std::endl;
    print_sub(*this, return_.Content->value);
}

void ast::DebugVisitor::operator()(ast::Litteral& litteral) const {
    std::cout << indent() << "Litteral [" << litteral.value << "]" << std::endl;
}

void ast::DebugVisitor::operator()(ast::Integer& integer) const {
    std::cout << indent() << "Integer [" << integer.value << "]" << std::endl;
}

void ast::DebugVisitor::operator()(ast::IntegerSuffix& integer) const {
    std::cout << indent() << "Float (suffix) [" << integer.value << "f]" << std::endl;
}

void ast::DebugVisitor::operator()(ast::Float& float_) const {
    std::cout << indent() << "Float [" << float_.value << "]" << std::endl;
}

void ast::DebugVisitor::operator()(ast::True&) const {
    std::cout << indent() << "true" << std::endl;
}

void ast::DebugVisitor::operator()(ast::Null&) const {
    std::cout << indent() << "null" << std::endl;
}

void ast::DebugVisitor::operator()(ast::False&) const {
    std::cout << indent() << "false" << std::endl;
}

void ast::DebugVisitor::operator()(ast::VariableValue& value) const {
    std::cout << indent() << "Variable " << value.Content->var->name();

    for(auto& member : value.Content->memberNames){
        std::cout << "." << member;
    }

    std::cout << std::endl;
}

void ast::DebugVisitor::operator()(ast::DereferenceValue& value) const {
    std::cout << indent() << "Dereference Variable Value" << std::endl;;

    std::cout << indent() << "Left Value:" << std::endl;
    print_sub(*this, value.Content->ref);
}

void ast::DebugVisitor::operator()(ast::ArrayValue&) const {
    std::cout << indent() << "Array value" << std::endl;
}

void ast::DebugVisitor::operator()(ast::Expression& value) const {
    std::cout << indent() << "Expression [" << value.Content->operations.size() << "]" << std::endl;
    ++level;
    visit(*this, value.Content->first);
    for(auto& operation : value.Content->operations){
        std::cout << indent() << (int) operation.get<0>() << std::endl;
        visit(*this, operation.get<1>());
    }
    --level;
}

void ast::DebugVisitor::operator()(ast::Minus& value) const {
    std::cout << indent() << "Unary +" << std::endl;
    print_sub(*this, value.Content->value);
}

void ast::DebugVisitor::operator()(ast::Plus& value) const {
    std::cout << indent() << "Unary -" << std::endl;
    print_sub(*this, value.Content->value);
}

void ast::DebugVisitor::operator()(ast::Cast& cast) const {
    std::cout << indent() << "Cast " << std::endl;
    std::cout << indent() << "\tType: " << toStringType(cast.Content->type) << std::endl;
    print_sub(*this, cast.Content->value);
}
<|endoftext|>


<commit_before>/***********************************************************************
 cpoolw.cpp - Windows threads version of ConnectionPool example.  Shows
 	how to create and use a concrete ConnectionPool derivative.

 Copyright (c) 2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"

#include <mysql++.h>

#include <iostream>

using namespace std;

// Define a concrete ConnectionPool derivative.  Takes connection
// parameters as inputs to its ctor, which it uses to create the
// connections we're called upon to make.  Note that we also declare
// a global pointer to an object of this type, which we create soon
// after startup; this should be a common usage pattern, as what use
// are multiple pools?
class SimpleConnectionPool : public mysqlpp::ConnectionPool
{
public:
	// The object's only constructor
	SimpleConnectionPool(const char* db, const char* server,
			const char* user, const char* password) :
	db_(db ? db : ""),
	server_(server ? server : ""),
	user_(user ? user : ""),
	password_(password ? password : "")
	{
	}

	// The destructor.  We _must_ call ConnectionPool::clear() here,
	// because our superclass can't do it for us.
	~SimpleConnectionPool()
	{
		clear();
	}

protected:
	// Superclass overrides
	mysqlpp::Connection* create()
	{
		// Create connection using the parameters we were passed upon
		// creation.  This could be something much more complex, but for
		// the purposes of the example, this suffices.
		cout << "Creating new pooled connection..." << endl;
		return new mysqlpp::Connection(
				db_.empty() ? 0 : db_.c_str(),
				server_.empty() ? 0 : server_.c_str(),
				user_.empty() ? 0 : user_.c_str(),
				password_.empty() ? "" : password_.c_str());
	}

	void destroy(mysqlpp::Connection* cp)
	{
		// Our superclass can't know how we created the Connection, so
		// it delegates destruction to us, to be safe.
		cout << "Destroying pooled connection..." << endl;
		delete cp;
	}

	unsigned int max_idle_time()
	{
		// Set our idle time at an example-friendly 3 seconds.  A real
		// pool would return some fraction of the server's connection
		// idle timeout instead.
		return 3;
	}

private:
	// Our connection parameters
	std::string db_, server_, user_, password_;
}
*poolptr = 0;

int
main(int argc, char *argv[])
{
	// Get database access parameters from command line
    const char* db = 0, *server = 0, *user = 0, *pass = "";
	if (!parse_command_line(argc, argv, &db, &server, &user, &pass)) {
		return 1;
	}

	// Create the pool and grab a connection.  We do it mainly to test
	// that the parameters are good before we start doing real work.
	// Note that unlike cpoolp, we don't bother to check that MySQL++
	// and the underlying C API library are thread-aware.  It's not
	// optional for Windows.
	poolptr = new SimpleConnectionPool(db, server, user, pass);
	try {
		mysqlpp::Connection* cp = poolptr->grab();
		poolptr->release(cp);
	}
	catch (mysqlpp::Exception& e) {
		cerr << "Failed to set up initial pooled connection: " <<
				e.what() << endl;
		return 1;
	}

	// Setup complete.  Now let's spin some threads...
	cout << "Pool created and working correctly.  Now to do some "
			"real work..." << endl;

	// Shut it all down...
	delete poolptr;

	return 0;
}
<commit_msg>Recent cpoolp changes to Windows' cpoolw.<commit_after>/***********************************************************************
 cpoolw.cpp - Windows threads version of ConnectionPool example.  Shows
 	how to create and use a concrete ConnectionPool derivative.

 Copyright (c) 2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"

#include <mysql++.h>

#include <iostream>

using namespace std;

// Define a concrete ConnectionPool derivative.  Takes connection
// parameters as inputs to its ctor, which it uses to create the
// connections we're called upon to make.  Note that we also declare
// a global pointer to an object of this type, which we create soon
// after startup; this should be a common usage pattern, as what use
// are multiple pools?
class SimpleConnectionPool : public mysqlpp::ConnectionPool
{
public:
	// The object's only constructor
	SimpleConnectionPool(const char* db, const char* server,
			const char* user, const char* password) :
	db_(db ? db : ""),
	server_(server ? server : ""),
	user_(user ? user : ""),
	password_(password ? password : "")
	{
	}

	// The destructor.  We _must_ call ConnectionPool::clear() here,
	// because our superclass can't do it for us.
	~SimpleConnectionPool()
	{
		clear();
	}

protected:
	// Superclass overrides
	mysqlpp::Connection* create()
	{
		// Create connection using the parameters we were passed upon
		// creation.  This could be something much more complex, but for
		// the purposes of the example, this suffices.
		cout << endl << "Creating new pooled connection!" << endl;
		return new mysqlpp::Connection(
				db_.empty() ? 0 : db_.c_str(),
				server_.empty() ? 0 : server_.c_str(),
				user_.empty() ? 0 : user_.c_str(),
				password_.empty() ? "" : password_.c_str());
	}

	void destroy(mysqlpp::Connection* cp)
	{
		// Our superclass can't know how we created the Connection, so
		// it delegates destruction to us, to be safe.
		cout << endl << "Destroying pooled connection!" << endl;
		delete cp;
	}

	unsigned int max_idle_time()
	{
		// Set our idle time at an example-friendly 3 seconds.  A real
		// pool would return some fraction of the server's connection
		// idle timeout instead.
		return 3;
	}

private:
	// Our connection parameters
	std::string db_, server_, user_, password_;
}
*poolptr = 0;

static DWORD WINAPI
worker_thread(LPVOID running_flag)
{
	// Pull data from the sample table a bunch of times, releasing the
	// connection we use each time.
	for (int i = 0; i < 6; ++i) {
		// Go get a free connection from the pool, or create a new one
		// if there are no free conns yet.
		mysqlpp::Connection* cp = poolptr->grab();
		if (!cp) {
			cerr << "Failed to get a connection from the pool!" << endl;
			break;
		}

		// Pull a copy of the sample stock table and print a dot for
		// each row in the result set.
		mysqlpp::Query query(cp->query("select * from stock"));
		mysqlpp::StoreQueryResult res = query.store();
		for (int j = 0; j < res.num_rows(); ++j) {
			cout.put('.');
		}

		// Immediately release the connection once we're done using it.
		// If we don't, the pool can't detect idle connections reliably.
		poolptr->release(cp);

		// Delay 1-4 seconds before doing it again.  Because this can
		// delay longer than the idle timeout, we'll occasionally force
		// the creation of a new connection on the next loop.
		Sleep(1000 * (rand() % 4 + 1));
	}

	// Tell main() that this thread is no longer running
	*reinterpret_cast<bool*>(running_flag) = false;

	return 0;
}
int
main(int argc, char *argv[])
{
	// Get database access parameters from command line
    const char* db = 0, *server = 0, *user = 0, *pass = "";
	if (!parse_command_line(argc, argv, &db, &server, &user, &pass)) {
		return 1;
	}

	// Create the pool and grab a connection.  We do it mainly to test
	// that the parameters are good before we start doing real work.
	// Note that unlike cpoolp, we don't bother to check that MySQL++
	// and the underlying C API library are thread-aware.  It's not
	// optional for Windows.
	poolptr = new SimpleConnectionPool(db, server, user, pass);
	try {
		mysqlpp::Connection* cp = poolptr->grab();
		poolptr->release(cp);
	}
	catch (mysqlpp::Exception& e) {
		cerr << "Failed to set up initial pooled connection: " <<
				e.what() << endl;
		return 1;
	}

	// Setup complete.  Now let's spin some threads...
	cout << "Pool created and working correctly.  Now to do some "
			"real work..." << endl;
	srand(time(0));
	bool running[] = {
			true, true, true, true, true, true, true,
			true, true, true, true, true, true, true };
	const int num_threads = sizeof(running) / sizeof(running[0]);
	int i;
	for (i = 0; i < num_threads; ++i) {
		if (CreateThread(0, 0, worker_thread, running + i, 0, 0) == 0) {
			cerr << "Failed to create thread " << i <<
					": error code " << GetLastError() << endl;
			return 1;
		}
	}

	// Test the 'running' flags every second until we find that they're
	// all turned off, indicating that all threads are stopped.
	cout << endl << "Waiting for threads to complete..." << endl;
	do {
		Sleep(1000);
		i = 0;
		while (i < num_threads && !running[i]) ++i;
	}
	while (i < num_threads);
	cout << endl << "All threads stopped!" << endl;
	// Shut it all down...
	delete poolptr;

	return 0;
}
<|endoftext|>


<commit_before>// Copyright 2014 Intel Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ozone/platform/ozone_platform_wayland.h"

#include "base/at_exit.h"
#include "base/bind.h"
#include "ozone/platform/ozone_gpu_platform_support_host.h"
#include "ozone/platform/ozone_wayland_window.h"
#include "ozone/platform/window_manager_wayland.h"
#include "ozone/wayland/display.h"
#include "ozone/wayland/ozone_wayland_screen.h"
#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
#include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
#include "ui/events/ozone/layout/xkb/xkb_evdev_codes.h"
#include "ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.h"
#include "ui/ozone/common/native_display_delegate_ozone.h"
#include "ui/ozone/common/stub_overlay_manager.h"
#include "ui/ozone/public/system_input_injector.h"
#include "ui/platform_window/platform_window_delegate.h"

namespace ui {

namespace {

// OzonePlatform for Wayland
//
// This platform is Linux with the Wayland display server.
class OzonePlatformWayland : public OzonePlatform {
 public:
  OzonePlatformWayland() {
    base::AtExitManager::RegisterTask(
        base::Bind(&base::DeletePointer<OzonePlatformWayland>, this));
  }

  ~OzonePlatformWayland() override {
  }

  // OzonePlatform:
  ui::SurfaceFactoryOzone* GetSurfaceFactoryOzone() override {
    return wayland_display_.get();
  }

  CursorFactoryOzone* GetCursorFactoryOzone() override {
    return cursor_factory_ozone_.get();
  }

  ui::OverlayManagerOzone* GetOverlayManager() override {
    return overlay_manager_.get();
  }

  InputController* GetInputController() override {
    return NULL;
  }

  scoped_ptr<SystemInputInjector> CreateSystemInputInjector() override {
    return scoped_ptr<SystemInputInjector>();
  }

  GpuPlatformSupportHost* GetGpuPlatformSupportHost() override {
    return gpu_platform_host_.get();
  }

  GpuPlatformSupport* GetGpuPlatformSupport() override {
    return wayland_display_.get();
  }

  scoped_ptr<PlatformWindow> CreatePlatformWindow(
      PlatformWindowDelegate* delegate,
      const gfx::Rect& bounds) override {
    return scoped_ptr<PlatformWindow>(
        new OzoneWaylandWindow(delegate,
                               gpu_platform_host_.get(),
                               window_manager_.get(),
                               bounds));
  }

  scoped_ptr<DesktopPlatformScreen> CreatePlatformScreen(
      DesktopPlatformScreenDelegate* delegate) {
    return scoped_ptr<DesktopPlatformScreen>(
         new ozonewayland::OzoneWaylandScreen(delegate,
                                              window_manager_.get()));
  }

  scoped_ptr<NativeDisplayDelegate> CreateNativeDisplayDelegate() override {
    return nullptr;
  }

  void InitializeUI() override {
    // For tests.
    if (wayland_display_.get())
      return;

    gpu_platform_host_.reset(new ui::OzoneGpuPlatformSupportHost());
    // Needed as Browser creates accelerated widgets through SFO.
    wayland_display_.reset(new ozonewayland::WaylandDisplay());
    cursor_factory_ozone_.reset(new ui::BitmapCursorFactoryOzone());
    overlay_manager_.reset(new StubOverlayManager());
    KeyboardLayoutEngineManager::SetKeyboardLayoutEngine(make_scoped_ptr(
        new XkbKeyboardLayoutEngine(xkb_evdev_code_converter_)));
    window_manager_.reset(
        new ui::WindowManagerWayland(gpu_platform_host_.get()));
  }

  void InitializeGPU() override {
    if (!wayland_display_)
      wayland_display_.reset(new ozonewayland::WaylandDisplay());

    if (!wayland_display_->InitializeHardware())
      LOG(FATAL) << "failed to initialize display hardware";
  }

 private:
  scoped_ptr<ui::BitmapCursorFactoryOzone> cursor_factory_ozone_;
  scoped_ptr<ozonewayland::WaylandDisplay> wayland_display_;
  scoped_ptr<StubOverlayManager> overlay_manager_;
  scoped_ptr<ui::WindowManagerWayland> window_manager_;
  XkbEvdevCodes xkb_evdev_code_converter_;
  scoped_ptr<ui::OzoneGpuPlatformSupportHost> gpu_platform_host_;
  DISALLOW_COPY_AND_ASSIGN(OzonePlatformWayland);
};

}  // namespace

OzonePlatform* CreateOzonePlatformWayland() { return new OzonePlatformWayland; }

scoped_ptr<DesktopPlatformScreen> CreatePlatformScreen(
    DesktopPlatformScreenDelegate* delegate) {
  OzonePlatformWayland* platform =
      static_cast<OzonePlatformWayland*>(ui::OzonePlatform::GetInstance());
  return platform->CreatePlatformScreen(delegate);
}

}  // namespace ui
<commit_msg>Gardening: Adapt to https://codereview.chromium.org/1248713002<commit_after>// Copyright 2014 Intel Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ozone/platform/ozone_platform_wayland.h"

#include "base/at_exit.h"
#include "base/bind.h"
#include "ozone/platform/ozone_gpu_platform_support_host.h"
#include "ozone/platform/ozone_wayland_window.h"
#include "ozone/platform/window_manager_wayland.h"
#include "ozone/wayland/display.h"
#include "ozone/wayland/ozone_wayland_screen.h"
#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
#include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
#include "ui/events/ozone/layout/xkb/xkb_evdev_codes.h"
#include "ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.h"
#include "ui/ozone/common/native_display_delegate_ozone.h"
#include "ui/ozone/common/stub_overlay_manager.h"
#include "ui/ozone/public/system_input_injector.h"
#include "ui/platform_window/platform_window_delegate.h"

namespace ui {

namespace {

// OzonePlatform for Wayland
//
// This platform is Linux with the Wayland display server.
class OzonePlatformWayland : public OzonePlatform {
 public:
  OzonePlatformWayland() {
    base::AtExitManager::RegisterTask(
        base::Bind(&base::DeletePointer<OzonePlatformWayland>, this));
  }

  ~OzonePlatformWayland() override {
  }

  // OzonePlatform:
  ui::SurfaceFactoryOzone* GetSurfaceFactoryOzone() override {
    return wayland_display_.get();
  }

  CursorFactoryOzone* GetCursorFactoryOzone() override {
    return cursor_factory_ozone_.get();
  }

  ui::OverlayManagerOzone* GetOverlayManager() override {
    return overlay_manager_.get();
  }

  InputController* GetInputController() override {
    return NULL;
  }

  scoped_ptr<SystemInputInjector> CreateSystemInputInjector() override {
    return scoped_ptr<SystemInputInjector>();
  }

  GpuPlatformSupportHost* GetGpuPlatformSupportHost() override {
    return gpu_platform_host_.get();
  }

  GpuPlatformSupport* GetGpuPlatformSupport() override {
    return wayland_display_.get();
  }

  scoped_ptr<PlatformWindow> CreatePlatformWindow(
      PlatformWindowDelegate* delegate,
      const gfx::Rect& bounds) override {
    return scoped_ptr<PlatformWindow>(
        new OzoneWaylandWindow(delegate,
                               gpu_platform_host_.get(),
                               window_manager_.get(),
                               bounds));
  }

  scoped_ptr<DesktopPlatformScreen> CreatePlatformScreen(
      DesktopPlatformScreenDelegate* delegate) {
    return scoped_ptr<DesktopPlatformScreen>(
         new ozonewayland::OzoneWaylandScreen(delegate,
                                              window_manager_.get()));
  }

  scoped_ptr<NativeDisplayDelegate> CreateNativeDisplayDelegate() override {
    return nullptr;
  }

  base::ScopedFD OpenClientNativePixmapDevice() const override {
    return base::ScopedFD();
  }

  void InitializeUI() override {
    // For tests.
    if (wayland_display_.get())
      return;

    gpu_platform_host_.reset(new ui::OzoneGpuPlatformSupportHost());
    // Needed as Browser creates accelerated widgets through SFO.
    wayland_display_.reset(new ozonewayland::WaylandDisplay());
    cursor_factory_ozone_.reset(new ui::BitmapCursorFactoryOzone());
    overlay_manager_.reset(new StubOverlayManager());
    KeyboardLayoutEngineManager::SetKeyboardLayoutEngine(make_scoped_ptr(
        new XkbKeyboardLayoutEngine(xkb_evdev_code_converter_)));
    window_manager_.reset(
        new ui::WindowManagerWayland(gpu_platform_host_.get()));
  }

  void InitializeGPU() override {
    if (!wayland_display_)
      wayland_display_.reset(new ozonewayland::WaylandDisplay());

    if (!wayland_display_->InitializeHardware())
      LOG(FATAL) << "failed to initialize display hardware";
  }

 private:
  scoped_ptr<ui::BitmapCursorFactoryOzone> cursor_factory_ozone_;
  scoped_ptr<ozonewayland::WaylandDisplay> wayland_display_;
  scoped_ptr<StubOverlayManager> overlay_manager_;
  scoped_ptr<ui::WindowManagerWayland> window_manager_;
  XkbEvdevCodes xkb_evdev_code_converter_;
  scoped_ptr<ui::OzoneGpuPlatformSupportHost> gpu_platform_host_;
  DISALLOW_COPY_AND_ASSIGN(OzonePlatformWayland);
};

}  // namespace

OzonePlatform* CreateOzonePlatformWayland() { return new OzonePlatformWayland; }

scoped_ptr<DesktopPlatformScreen> CreatePlatformScreen(
    DesktopPlatformScreenDelegate* delegate) {
  OzonePlatformWayland* platform =
      static_cast<OzonePlatformWayland*>(ui::OzonePlatform::GetInstance());
  return platform->CreatePlatformScreen(delegate);
}

}  // namespace ui
<|endoftext|>


<commit_before>// ------------------------------------------------------------------------
// Pion is a development platform for building Reactors that process Events
// ------------------------------------------------------------------------
// Copyright (C) 2007-2008 Atomic Labs, Inc.  (http://www.atomiclabs.com)
//
// Pion is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// Pion is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for
// more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Pion.  If not, see <http://www.gnu.org/licenses/>.
//

#include "QueryService.hpp"
#include <boost/bind.hpp>
#include <pion/net/HTTPResponseWriter.hpp>
#include <pion/net/PionUser.hpp>
#include "PlatformConfig.hpp"

using namespace pion;
using namespace pion::net;

namespace pion {		// begin namespace pion
namespace plugins {		// begin namespace plugins

// QueryService member functions

/// handles requests for QueryService
void QueryService::operator()(HTTPRequestPtr& request, TCPConnectionPtr& tcp_conn)
{
	// split out the path branches from the HTTP request
	PathBranches branches;
	splitPathBranches(branches, request->getResource());

	std::string xml;

/*
	for (int i = 0; i < branches.size() ; i++ )
		xml += branches[i] + "::";

	xml += "\r\n";
*/
	if (branches.empty()) {
		xml += "No branch (/reactors) defined";
	} else if (branches.front() == "reactors") {
		xml += getConfig().getReactionEngine().query(
			branches.at(1),
			branches,
			request->getQueryParams());
	} else {
		xml += "Only /reactors supported";
	}

	// prepare the writer object for XML output
	HTTPResponseWriterPtr writer(HTTPResponseWriter::create(tcp_conn, *request,
															boost::bind(&TCPConnection::finish, tcp_conn)));
	writer->getResponse().setContentType(HTTPTypes::CONTENT_TYPE_XML);

	// send the response
	writer->write(xml);
	writer->send();
}

}	// end namespace plugins
}	// end namespace pion

/// creates new QueryService objects
extern "C" PION_SERVICE_API pion::server::PlatformService *pion_create_QueryService(void)
{
	return new pion::plugins::QueryService();
}

/// destroys QueryService objects
extern "C" PION_SERVICE_API void pion_destroy_QueryService(pion::plugins::QueryService *service_ptr)
{
	delete service_ptr;
}
<commit_msg>QueryService -- WIP<commit_after>// ------------------------------------------------------------------------
// Pion is a development platform for building Reactors that process Events
// ------------------------------------------------------------------------
// Copyright (C) 2007-2008 Atomic Labs, Inc.  (http://www.atomiclabs.com)
//
// Pion is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// Pion is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for
// more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Pion.  If not, see <http://www.gnu.org/licenses/>.
//

#include "QueryService.hpp"
#include <boost/bind.hpp>
#include <pion/net/HTTPResponseWriter.hpp>
#include <pion/net/PionUser.hpp>
#include "PlatformConfig.hpp"

using namespace pion;
using namespace pion::net;

namespace pion {		// begin namespace pion
namespace plugins {		// begin namespace plugins

// QueryService member functions

/// handles requests for QueryService
void QueryService::operator()(HTTPRequestPtr& request, TCPConnectionPtr& tcp_conn)
{
	// split out the path branches from the HTTP request
	PathBranches branches;
	splitPathBranches(branches, request->getResource());

	std::string xml;

/*
	for (int i = 0; i < branches.size() ; i++ )
		xml += branches[i] + "::";

	xml += "\r\n";
*/
	if (branches.empty()) {
		xml += "No branch (/reactors) defined";
	} else if (branches.front() == "reactors") {
		xml = getConfig().getReactionEngine().query(
			branches.at(1),
			branches,
			request->getQueryParams());
	} else {
		xml += "Only /reactors supported";
	}

	// Set Content-type to "text/plain" (plain ascii text)
	HTTPResponseWriterPtr writer(HTTPResponseWriter::create(tcp_conn, *request,
															boost::bind(&TCPConnection::finish, tcp_conn)));
	writer->getResponse().setContentType(HTTPTypes::CONTENT_TYPE_TEXT);

	writer->write(xml.c_str());

	// send the writer
	writer->send();
}

}	// end namespace plugins
}	// end namespace pion

/// creates new QueryService objects
extern "C" PION_SERVICE_API pion::server::PlatformService *pion_create_QueryService(void)
{
	return new pion::plugins::QueryService();
}

/// destroys QueryService objects
extern "C" PION_SERVICE_API void pion_destroy_QueryService(pion::plugins::QueryService *service_ptr)
{
	delete service_ptr;
}
<|endoftext|>


<commit_before>#include "gtest/gtest.h"
#include "gtest/gtest-spi.h"
#include <string>
#include <exception>
#include <thread>

#include "config.h"
#include "cmysql_database.h"
#include "cmysql_databasepool.h"
#include "database.h"

TEST( TestMySQL_Database, TestConstructor )
{
	const ::configFile::Database	&dbb = Core::Config::getInstance("test.ini").database();
	std::string host = dbb.host();
	std::string _database = dbb.database();
	std::string user = dbb.user();
	std::string pass = dbb.password();

	EXPECT_NO_FATAL_FAILURE( Core::CMySQL_Database database(host.c_str(), _database.c_str(), user.c_str(), pass.c_str()));
}

TEST( TestMySQL_Database, TestQExecuteFails )
{
	Core::CMySQL_Database database;
	EXPECT_ANY_THROW(database.Connect("azertyu", "dhfui34hf4", "dfj3gqf27", "Rahf7823"));
        EXPECT_ANY_THROW(database.QExecute("DROP TABLE IF EXISTS test_table;"));
        EXPECT_ANY_THROW(database.QExecute("CREATE TABLE test_table(id INT);"));
        EXPECT_ANY_THROW(database.QExecute("DROP TABLE test_table;") );
        EXPECT_THROW(database.QExecute("use table test_table;"), std::exception);
}

TEST( TestMySQL_Database, TestQExecute )
{
        const ::configFile::Database    &dbb = Core::Config::getInstance("test.ini").database();
        std::string host = dbb.host();
        std::string _database = dbb.database();
        std::string user = dbb.user();
        std::string pass = dbb.password();

	Core::CMySQL_Database database(host.c_str(), _database.c_str(), user.c_str(), pass.c_str());
	EXPECT_NO_FATAL_FAILURE( database.QExecute("DROP TABLE IF EXISTS test_table;"));
	EXPECT_NO_FATAL_FAILURE(database.QExecute("CREATE TABLE test_table(id INT);"));
	EXPECT_NO_FATAL_FAILURE(database.QExecute("DROP TABLE test_table;") );
	EXPECT_THROW(database.QExecute("use table test_table;"), std::exception);
}

TEST(TestMySQL_Database, TestQStore)
{
        const ::configFile::Database    &dbb = Core::Config::getInstance("test.ini").database();
        std::string host = dbb.host();
        std::string _database = dbb.database();
        std::string user = dbb.user();
        std::string pass = dbb.password();

	Core::CMySQL_Database	database(host.c_str(), _database.c_str(), user.c_str(), pass.c_str());
	database.QExecute("DROP TABLE IF EXISTS test_table;");
	database.QExecute("CREATE TABLE test_table(id INT, value INT, str VARCHAR(64), fl FLOAT, data BLOB);");
	database.QExecute("insert into test_table(id, value, str, fl, data) values(0, 12, 'plop', 3.14, '\x08\x12\x24');");
	database.QExecute("insert into test_table(id, value, str, fl, data) values(1, NULL, 'null values', NULL, NULL);");
        database.QExecute("DELETE FROM accounts WHERE username='test';");
        database.QExecute("INSERT INTO accounts (username, password, access) VALUES ('test', 'cc03e747a6afbbcbf8be7668acfebee5', 1);");
	std::unique_ptr<Core::IResult>	res;
	EXPECT_NO_FATAL_FAILURE(res = std::move(database.QStore("select * from test_table;")));
	uint32_t	id;
	EXPECT_EQ(res->getInt("id", id), true);
	EXPECT_EQ(id, 0);
	std::string	str;
	EXPECT_EQ(res->getString("str", str), true);
	EXPECT_EQ(str, "plop");
	float dec;
	EXPECT_EQ(res->getFloat("fl", dec), true);
	EXPECT_FLOAT_EQ(dec, 3.14);
	res->useRow(1);
	EXPECT_EQ(res->getInt("value", id), false);
	EXPECT_EQ(id, 0);
}

TEST(TestMySQL_Database, TestError)
{
        const ::configFile::Database    &dbb = Core::Config::getInstance("test.ini").database();
        std::string host = dbb.host();
        std::string _database = dbb.database();
        std::string user = dbb.user();
        std::string pass = dbb.password();

	Core::CMySQL_Database	database(host, _database, user, pass);
}

TEST(TestMySQL_Database, TestMultipleResults)
{
	const ::configFile::Database    &dbb = Core::Config::getInstance("test.ini").database();
	std::string host = dbb.host();
	std::string _database = dbb.database();
	std::string user = dbb.user();
	std::string pass = dbb.password();

	Core::CMySQL_Database	database(host.c_str(), _database.c_str(), user.c_str(), pass.c_str());
	database.QExecute("DROP TABLE IF EXISTS test_table;");
	database.QExecute("CREATE TABLE test_table(id INT, value INT, str VARCHAR(64), data BLOB);");
	database.QExecute("insert into test_table(id, value, str, data) values(0, 12, 'plop', '\x08\x12\x24');");
	database.QExecute("insert into test_table(id, value, str, data) values(1, NULL, 'null values', NULL);");
	std::unique_ptr<Core::IResult>	res, res2;
	EXPECT_NO_FATAL_FAILURE(res = std::move(database.QStore("select * from test_table;")));
	EXPECT_NO_FATAL_FAILURE(res2 = std::move(database.QStore("select * from test_table;")));
}

TEST(TestMySQL_Database, TestThreaded)
{
	const ::configFile::Database    &dbb = Core::Config::getInstance("test.ini").database();
	std::string host = dbb.host();
	std::string _database = dbb.database();
	std::string user = dbb.user();
	std::string pass = dbb.password();

	Core::CMySQL_Database	database(host.c_str(), _database.c_str(), user.c_str(), pass.c_str());
	database.QExecute("DROP TABLE IF EXISTS test_table;");
	database.QExecute("CREATE TABLE test_table(id INT, value INT, str VARCHAR(64), data BLOB);");
	database.QExecute("insert into test_table(id, value, str, data) values(0, 12, 'plop', '\x08\x12\x24');");
	database.QExecute("insert into test_table(id, value, str, data) values(1, NULL, 'null values', NULL);");

	std::thread first([&database] () {
			std::unique_ptr<Core::IResult> res;
			for (int i = 0; i < 20; ++i)
				EXPECT_NO_FATAL_FAILURE(res = std::move(database.QStore("select * from test_table;")));
			});
	std::thread second([&database] () {
			std::unique_ptr<Core::IResult> res;
			for (int i = 0; i < 20; ++i)
				EXPECT_NO_FATAL_FAILURE(res = std::move(database.QStore("select * from test_table;")));
			});
	first.join();
	second.join();
}

TEST(TestMySQL_Database, TestIRowAndIterator)
{
	const ::configFile::Database    &dbb = Core::Config::getInstance("test.ini").database();
	std::string host = dbb.host();
	std::string _database = dbb.database();
	std::string user = dbb.user();
	std::string pass = dbb.password();

	Core::CMySQL_Database	database(host, _database, user, pass);
	database.QExecute("DROP TABLE IF EXISTS test_table;");
	database.QExecute("CREATE TABLE test_table(id INT, value INT, str VARCHAR(64), data BLOB);");
	database.QExecute("insert into test_table(id, value, str, data) values(0, 12, 'plop', '\x08\x12\x24');");
	database.QExecute("insert into test_table(id, value, str, data) values(1, NULL, NULL, NULL);");

	std::unique_ptr<Core::IResult> res = database.QStore("select * from test_table;");
	EXPECT_NO_FATAL_FAILURE([&res] () {
			std::string a;
			for (auto &it : *res) {
				std::string tmp;
				uint32_t t;
				it->getInt("id", t);
				a += std::to_string(t);
				if (it->getString("str", tmp))
					a += tmp;
			}
			EXPECT_EQ(a, "0plop1");
		}());
}

TEST(TestMySQL_DatabasePool, TestGetInstance) {
	struct Filename {
		constexpr static const char *str() { return "test.ini"; }
	};
	EXPECT_NO_FATAL_FAILURE(Core::IDatabasePool &pool = Core::databasePoolFilename<Filename>::getInstance());
	EXPECT_NO_FATAL_FAILURE([] () {
			Core::IDatabasePool &pool = Core::databasePoolFilename<Filename>::getInstance();
			EXPECT_NO_FATAL_FAILURE(Core::IDatabase &database = pool.getDatabase());
		});

	EXPECT_NO_FATAL_FAILURE([] () {
			Core::IDatabasePool &pool = Core::databasePoolFilename<Filename>::getInstance();
			Core::IDatabase &database = pool.getDatabase();
			database.QExecute("DROP TABLE IF EXISTS test_table;");
			database.QExecute("CREATE TABLE test_table(id INT, value INT, str VARCHAR(64), data BLOB);");
			database.QExecute("insert into test_table(id, value, str, data) values(0, 12, 'plop', '\x08\x12\x24');");
			database.QExecute("insert into test_table(id, value, str, data) values(1, NULL, NULL, NULL);");
			auto res = database.QStore("select * from test_table;");
			std::string s;
			res->getString("str", s);
			EXPECT_EQ(s, "plop");
		}());
}
<commit_msg>Added tests<commit_after>#include "gtest/gtest.h"
#include "gtest/gtest-spi.h"
#include <string>
#include <exception>
#include <thread>

#include "config.h"
#include "cmysql_database.h"
#include "cmysql_databasepool.h"
#include "database.h"

TEST( TestMySQL_Database, TestConstructor )
{
	const ::configFile::Database	&dbb = Core::Config::getInstance("test.ini").database();
	std::string host = dbb.host();
	std::string _database = dbb.database();
	std::string user = dbb.user();
	std::string pass = dbb.password();

	EXPECT_NO_FATAL_FAILURE( Core::CMySQL_Database database(host.c_str(), _database.c_str(), user.c_str(), pass.c_str()));
}

TEST( TestMySQL_Database, TestQExecuteFails )
{
	Core::CMySQL_Database database;
	EXPECT_ANY_THROW(database.Connect("azertyu", "dhfui34hf4", "dfj3gqf27", "Rahf7823"));
        EXPECT_ANY_THROW(database.QExecute("DROP TABLE IF EXISTS test_table;"));
        EXPECT_ANY_THROW(database.QExecute("CREATE TABLE test_table(id INT);"));
        EXPECT_ANY_THROW(database.QExecute("DROP TABLE test_table;") );
        EXPECT_THROW(database.QExecute("use table test_table;"), std::exception);
}

TEST( TestMySQL_Database, TestQExecute )
{
        const ::configFile::Database    &dbb = Core::Config::getInstance("test.ini").database();
        std::string host = dbb.host();
        std::string _database = dbb.database();
        std::string user = dbb.user();
        std::string pass = dbb.password();

	Core::CMySQL_Database database(host.c_str(), _database.c_str(), user.c_str(), pass.c_str());
	EXPECT_NO_FATAL_FAILURE( database.QExecute("DROP TABLE IF EXISTS test_table;"));
	EXPECT_NO_FATAL_FAILURE(database.QExecute("CREATE TABLE test_table(id INT);"));
	EXPECT_NO_FATAL_FAILURE(database.QExecute("DROP TABLE test_table;") );
	EXPECT_THROW(database.QExecute("use table test_table;"), std::exception);
}

TEST(TestMySQL_Database, TestQStore)
{
        const ::configFile::Database    &dbb = Core::Config::getInstance("test.ini").database();
        std::string host = dbb.host();
        std::string _database = dbb.database();
        std::string user = dbb.user();
        std::string pass = dbb.password();

	Core::CMySQL_Database	database(host.c_str(), _database.c_str(), user.c_str(), pass.c_str());
	database.QExecute("DROP TABLE IF EXISTS test_table;");
	database.QExecute("CREATE TABLE test_table(id INT, value INT, str VARCHAR(64), fl FLOAT, data BLOB);");
	database.QExecute("insert into test_table(id, value, str, fl, data) values(0, 12, 'plop', 3.14, '\x08\x12\x24');");
	database.QExecute("insert into test_table(id, value, str, fl, data) values(1, NULL, 'null values', NULL, NULL);");
        database.QExecute("DELETE FROM accounts WHERE username='test';");
        database.QExecute("INSERT INTO accounts (username, password, access) VALUES ('test', 'cc03e747a6afbbcbf8be7668acfebee5', 1);");
	std::unique_ptr<Core::IResult>	res;
	EXPECT_NO_FATAL_FAILURE(res = std::move(database.QStore("select * from test_table;")));
	uint32_t	id;
	EXPECT_EQ(res->getInt("id", id), true);
	EXPECT_EQ(id, 0);
	std::string	str;
	EXPECT_EQ(res->getString("str", str), true);
	EXPECT_EQ(str, "plop");
	float dec;
	EXPECT_EQ(res->getFloat("fl", dec), true);
	EXPECT_FLOAT_EQ(dec, 3.14);
	res->useRow(1);
	EXPECT_EQ(res->getInt("value", id), false);
	EXPECT_EQ(id, 0);
}

TEST(TestMySQL_Database, TestError)
{
        const ::configFile::Database    &dbb = Core::Config::getInstance("test.ini").database();
        std::string host = dbb.host();
        std::string _database = dbb.database();
        std::string user = dbb.user();
        std::string pass = dbb.password();

	Core::CMySQL_Database	database(host, _database, user, pass);
}

TEST(TestMySQL_Database, TestMultipleResults)
{
	const ::configFile::Database    &dbb = Core::Config::getInstance("test.ini").database();
	std::string host = dbb.host();
	std::string _database = dbb.database();
	std::string user = dbb.user();
	std::string pass = dbb.password();

	Core::CMySQL_Database	database(host.c_str(), _database.c_str(), user.c_str(), pass.c_str());
	database.QExecute("DROP TABLE IF EXISTS test_table;");
	database.QExecute("CREATE TABLE test_table(id INT, value INT, str VARCHAR(64), data BLOB);");
	database.QExecute("insert into test_table(id, value, str, data) values(0, 12, 'plop', '\x08\x12\x24');");
	database.QExecute("insert into test_table(id, value, str, data) values(1, NULL, 'null values', NULL);");
	std::unique_ptr<Core::IResult>	res, res2;
	EXPECT_NO_FATAL_FAILURE(res = std::move(database.QStore("select * from test_table;")));
	EXPECT_NO_FATAL_FAILURE(res2 = std::move(database.QStore("select * from test_table;")));
}

TEST(TestMySQL_Database, TestThreaded)
{
	const ::configFile::Database    &dbb = Core::Config::getInstance("test.ini").database();
	std::string host = dbb.host();
	std::string _database = dbb.database();
	std::string user = dbb.user();
	std::string pass = dbb.password();

	Core::CMySQL_Database	database(host.c_str(), _database.c_str(), user.c_str(), pass.c_str());
	database.QExecute("DROP TABLE IF EXISTS test_table;");
	database.QExecute("CREATE TABLE test_table(id INT, value INT, str VARCHAR(64), data BLOB);");
	database.QExecute("insert into test_table(id, value, str, data) values(0, 12, 'plop', '\x08\x12\x24');");
	database.QExecute("insert into test_table(id, value, str, data) values(1, NULL, 'null values', NULL);");

	std::thread first([&database] () {
			std::unique_ptr<Core::IResult> res;
			for (int i = 0; i < 20; ++i)
				EXPECT_NO_FATAL_FAILURE(res = std::move(database.QStore("select * from test_table;")));
			});
	std::thread second([&database] () {
			std::unique_ptr<Core::IResult> res;
			for (int i = 0; i < 20; ++i)
				EXPECT_NO_FATAL_FAILURE(res = std::move(database.QStore("select * from test_table;")));
			});
	first.join();
	second.join();
}

TEST(TestMySQL_Database, TestIRowAndIterator)
{
	const ::configFile::Database    &dbb = Core::Config::getInstance("test.ini").database();
	std::string host = dbb.host();
	std::string _database = dbb.database();
	std::string user = dbb.user();
	std::string pass = dbb.password();

	Core::CMySQL_Database	database(host, _database, user, pass);
	database.QExecute("DROP TABLE IF EXISTS test_table;");
	database.QExecute("CREATE TABLE test_table(id INT, value INT, str VARCHAR(64), data BLOB);");
	database.QExecute("insert into test_table(id, value, str, data) values(0, 12, 'plop', '\x08\x12\x24');");
	database.QExecute("insert into test_table(id, value, str, data) values(1, NULL, NULL, NULL);");

	std::unique_ptr<Core::IResult> res = database.QStore("select * from test_table;");
	EXPECT_NO_FATAL_FAILURE([&res] () {
			std::string a;
			for (auto &it : *res) {
				std::string tmp;
				uint32_t t;
				it->getInt("id", t);
				a += std::to_string(t);
				if (it->getString("str", tmp))
					a += tmp;
			}
			EXPECT_EQ(a, "0plop1");
		}());
}

TEST(TestMySQL_DatabasePool, TestGetInstance) {
	struct Filename {
		constexpr static const char *str() { return "test.ini"; }
	};
	EXPECT_NO_FATAL_FAILURE(Core::IDatabasePool &pool = Core::databasePoolFilename<Filename>::getInstance());
	EXPECT_NO_FATAL_FAILURE([] () {
			Core::IDatabasePool &pool = Core::databasePoolFilename<Filename>::getInstance();
			EXPECT_NO_FATAL_FAILURE(Core::IDatabase &database = pool.getDatabase());
		});

	EXPECT_NO_FATAL_FAILURE([] () {
			Core::IDatabasePool &pool = Core::databasePoolFilename<Filename>::getInstance();
			Core::IDatabase &database = pool.getDatabase();
			database.QExecute("DROP TABLE IF EXISTS test_table;");
			database.QExecute("CREATE TABLE test_table(id INT, value INT, str VARCHAR(64), data BLOB);");
			database.QExecute("insert into test_table(id, value, str, data) values(0, 12, 'plop', '\x08\x12\x24');");
			database.QExecute("insert into test_table(id, value, str, data) values(1, NULL, NULL, NULL);");
			auto res = database.QStore("select * from test_table;");
			std::string s;
			res->getString("str", s);
			EXPECT_EQ(s, "plop");
		}());
}

TEST(TestMySQL_Database, TestSQLEscape) {
	struct Filename {
		constexpr static const char *str() { return "test.ini"; }
	};
	auto &pool = Core::databasePoolFilename<Filename>::getInstance();
	EXPECT_EQ(Core::MySQL_Database::escapeDataNoConnection("test"), "test");
	EXPECT_EQ(Core::MySQL_Database::escapeDataNoConnection("1test1"), "1test1");
	EXPECT_EQ(Core::MySQL_Database::escapeDataNoConnection("\\test1"), "\\\\test1");
	EXPECT_EQ(Core::MySQL_Database::escapeDataNoConnection("'test1"), "\\'test1");
	EXPECT_EQ(Core::MySQL_Database::escapeDataNoConnection("\"test1"), "\\\"test1");
	EXPECT_EQ(Core::MySQL_Database::escapeDataNoConnection("\%test1"), "\\\%test1");
	EXPECT_EQ(pool.escapeData("test"), "test");
	EXPECT_EQ(pool.escapeData("1test1"), "1test1");
	EXPECT_EQ(pool.escapeData("\\test1"), "\\\\test1");
	EXPECT_EQ(pool.escapeData("'test1"), "\\'test1");
	EXPECT_EQ(pool.escapeData("\"test1"), "\\\"test1");
	EXPECT_EQ(pool.escapeData("\%test1"), "\\\%test1");
}
<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2013-2015 Tino Bog
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

// --- Internal Includes ---
#include "../inc/autoargs.hpp"

using namespace autoargs;

int main( int argc,
          char **argv )
{
  StringArg first { "first", "The first name", "John" };
  StringArg last { "last", "The last name", "Doe" };
  SizeArg age { "age", "The (true?) age", 33 };
  DoubleArg height { "height", "How tall?", 1.92 };
  BoolArg like { "like", "You like not-jokes?", true };

  ArgumentParser::parseCommandLine( argc, argv );

  std::cout << "Hello World!" << std::endl;
  std::cout << "My name is " << *first << " " << last.value( ) << "." << std::endl;
  std::cout << "I am " << age << " years old." << std::endl;
  std::cout << "I am " << height << " m tall." << std::endl;
  std::cout << "I like telenovelas." << ( like ? "" : "..not!" ) << std::endl;
}
<commit_msg>Fixing broken include<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2013-2015 Tino Bog
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

// --- Internal Includes ---
#include "autoargs.hpp"

using namespace autoargs;

int main( int argc,
          char **argv )
{
  StringArg first { "first", "The first name", "John" };
  StringArg last { "last", "The last name", "Doe" };
  SizeArg age { "age", "The (true?) age", 33 };
  DoubleArg height { "height", "How tall?", 1.92 };
  BoolArg like { "like", "You like not-jokes?", true };

  ArgumentParser::parseCommandLine( argc, argv );

  std::cout << "Hello World!" << std::endl;
  std::cout << "My name is " << *first << " " << last.value( ) << "." << std::endl;
  std::cout << "I am " << age << " years old." << std::endl;
  std::cout << "I am " << height << " m tall." << std::endl;
  std::cout << "I like telenovelas." << ( like ? "" : "..not!" ) << std::endl;
}
<|endoftext|>


<commit_before>#include "QCodeHighlighter.h"

#include "xo/system/assert.h"
#include "xo/filesystem/path.h"
#include "xo/numerical/math.h"
#include "xo/string/string_tools.h"
#include "xo/utility/hash.h"
#include "xo/container/flat_map.h"
#include <string>

QCodeHighlighter::QCodeHighlighter( QObject* parent, Language l ) : QSyntaxHighlighter( parent )
{
	setLanguage( l );
}

QCodeHighlighter::QCodeHighlighter( QTextDocument* parent, Language l ) : QSyntaxHighlighter( parent )
{
	setLanguage( l );
}

void QCodeHighlighter::highlightBlock( const QString &text )
{
	for ( auto& r : rules )
		applyRule( text, r );

	// apply multi-line comments
	if ( !commentStartRegex.pattern().isEmpty() )
	{
		int commentStart = 0, searchIndex = 0;
		bool isComment = previousBlockState() == 1;

		while ( searchIndex >= 0 )
		{
			if ( isComment )
			{
				auto matchEnd = match( commentEndRegex, text, searchIndex );
				if ( !matchEnd.hasMatch() )
				{
					// multiline comment goes beyond this line
					setFormat( commentStart, text.length() - commentStart, commentFormat );
					break;
				}
				else
				{
					// multiline comment ends here
					setFormat( commentStart, matchEnd.capturedEnd() - commentStart, commentFormat );
					searchIndex = matchEnd.capturedEnd();
					isComment = false;
				}
			}
			if ( !isComment )
			{
				auto matchStart = match( commentStartRegex, text, searchIndex );
				if ( matchStart.hasMatch() )
				{
					// multiline comment starts here
					commentStart = matchStart.capturedStart();
					searchIndex = matchStart.capturedEnd();
					isComment = true;
				}
				else break; // no more comments in this line
			}
		}
		setCurrentBlockState( isComment ? 1 : 0 );
	}
}

bool QCodeHighlighter::isBetweenQuotes( const QString & text, int index )
{
	int quotes_before = 0;
	for ( int i = 0; i < index; ++i )
		quotes_before += int( text[ i ] == '\"' );
	return xo::is_odd( quotes_before );
}

QRegularExpressionMatch QCodeHighlighter::match( const QRegularExpression & regex, const QString & text, int index )
{
	auto m = regex.match( text, index );
	while ( m.hasMatch() && isBetweenQuotes( text, m.capturedStart() ) )
		m = regex.match( text, m.capturedEnd() );
	return m;
}

void QCodeHighlighter::applyRule( const QString& text, const HighlightRule& r )
{
	for ( auto m = match( r.regExp, text, 0 ); m.hasMatch(); m = match( r.regExp, text, m.capturedEnd() ) )
		setFormat( m.capturedStart(), m.capturedLength(), r.format );
}

void QCodeHighlighter::setRegexes()
{
	rules.clear();
	commentStartRegex.setPattern( "" );
	commentEndRegex.setPattern( "" );

	switch ( language )
	{
	case Language::xml:
		rules.emplace_back( "<[\\s]*[/]?[\\s]*([^\\n]\\w*)(?=[\\s/>])", elementFormat );
		rules.emplace_back( "\\w+(?=\\=)", attributeFormat );
		rules.emplace_back( "\"[^\\n\"]+\"(?=[\\s/>])", valueFormat );
		rules.emplace_back( "/.^/", specialFormat );
		rules.emplace_back( "(<\\?|/>|>|<|</|\\?>", operatorFormat );
		rules.emplace_back( "\\b([-+]?[\\.\\d]+)", numberFormat );
		commentStartRegex.setPattern( "<!--" );
		commentEndRegex.setPattern( "-->" );
		break;

	case Language::zml:
		rules.emplace_back( "\\w+\\s*\\=?\\s*[\\{\\[]", elementFormat );
		rules.emplace_back( "\\w+\\s*(\\=)", attributeFormat ); // key = value
		rules.emplace_back( "\\w+(:\\s+)", attributeFormat ); // key: value
		rules.emplace_back( "\"[^\\n\"]*\"", valueFormat );
		rules.emplace_back( "<<\\s.*\\s>>", specialFormat );
		rules.emplace_back( "([\\{\\}\\[\\]\\=]|:\\s)", operatorFormat );
		rules.emplace_back( "\\b([-+]?[\\.\\d]+)", numberFormat );
		rules.emplace_back( "\\@\\w+", macroFormat );
		rules.emplace_back( "\\$\\w+", macroFormat );
		rules.emplace_back( "#[^\\n]*", commentFormat ); // #
		commentStartRegex.setPattern( "#{3,}" );
		commentEndRegex.setPattern( "#{3,}" );
		increaseIndentRegex.setPattern( "[\\{\\[]" );
		decreaseIndentRegex.setPattern( "[\\}\\]]" );
		break;

	case Language::lua:
		rules.emplace_back( "\\b(and|break|do|else|elseif|end|false|for|function|goto|if|in|local|nil|not|or|repeat|return|then|true|until|while)\\b", elementFormat );
		rules.emplace_back( "\"[^\\n\"]*\"", valueFormat );
		rules.emplace_back( "\\b([-+]?[\\.\\d]+)", numberFormat );
		rules.emplace_back( "[\\+\\-\\*\\/\\%\\\\#\\&\\~\\|\\<\\>\\(\\)\\{\\}\\[\\]\\=\\;\\:\\,\\.]", operatorFormat );
		rules.emplace_back( "--[^\\n]*", commentFormat );
		commentStartRegex.setPattern( "--\\[\\[" );
		commentEndRegex.setPattern( "\\]\\]" );
		increaseIndentRegex.setPattern( "^\\s*(do|if|elseif|else|function|repeat)\\b" );
		decreaseIndentRegex.setPattern( "^\\s*(end|until|else|elseif)\\b" );
	default:
		break;
	}
}

void QCodeHighlighter::setFormats()
{
	operatorFormat.setForeground( Qt::darkGray );
	elementFormat.setForeground( Qt::darkBlue );
	elementFormat.setFontWeight( QFont::Bold );
	attributeFormat.setForeground( Qt::darkBlue );
	//attributeFormat.setFontItalic( true );
	//attributeFormat.setFontWeight( QFont::Bold );
	valueFormat.setForeground( Qt::darkRed );
	commentFormat.setForeground( Qt::gray );
	commentFormat.setFontItalic( true );
	numberFormat.setForeground( Qt::darkCyan );
	macroFormat.setForeground( Qt::darkMagenta );
	//macroFormat.setFontItalic( true );
	specialFormat.setForeground( Qt::darkMagenta );
	specialFormat.setFontItalic( true );
	//specialFormat.setFontWeight( QFont::Bold );
}

void QCodeHighlighter::setLanguage( Language l )
{
	language = l;
	setFormats();
	setRegexes();
}

xo::flat_map< std::string, QCodeHighlighter::Language > g_languages{
	{ "scone", QCodeHighlighter::Language::zml },
	{ "xml", QCodeHighlighter::Language::xml },
	{ "osim", QCodeHighlighter::Language::xml },
	{ "lua", QCodeHighlighter::Language::lua },
	{ "zml", QCodeHighlighter::Language::zml },
	{ "hfd", QCodeHighlighter::Language::zml }
};

QCodeHighlighter::Language QCodeHighlighter::detectLanguage( const QString& filename )
{
	auto ext = xo::to_lower( xo::path( filename.toStdString() ).extension_no_dot().str() );
	if ( auto l = g_languages.find( ext ); l != g_languages.end() )
		return l->second;
	else return Language::unknown;
}

void QCodeHighlighter::registerLanguage( const QString& ext, Language lang )
{
	g_languages[ xo::to_lower( ext.toStdString() ) ] = lang;
}
<commit_msg>F*: fixed Lua automatic indentation when using 'for' or 'while'<commit_after>#include "QCodeHighlighter.h"

#include "xo/system/assert.h"
#include "xo/filesystem/path.h"
#include "xo/numerical/math.h"
#include "xo/string/string_tools.h"
#include "xo/utility/hash.h"
#include "xo/container/flat_map.h"
#include <string>

QCodeHighlighter::QCodeHighlighter( QObject* parent, Language l ) : QSyntaxHighlighter( parent )
{
	setLanguage( l );
}

QCodeHighlighter::QCodeHighlighter( QTextDocument* parent, Language l ) : QSyntaxHighlighter( parent )
{
	setLanguage( l );
}

void QCodeHighlighter::highlightBlock( const QString &text )
{
	for ( auto& r : rules )
		applyRule( text, r );

	// apply multi-line comments
	if ( !commentStartRegex.pattern().isEmpty() )
	{
		int commentStart = 0, searchIndex = 0;
		bool isComment = previousBlockState() == 1;

		while ( searchIndex >= 0 )
		{
			if ( isComment )
			{
				auto matchEnd = match( commentEndRegex, text, searchIndex );
				if ( !matchEnd.hasMatch() )
				{
					// multiline comment goes beyond this line
					setFormat( commentStart, text.length() - commentStart, commentFormat );
					break;
				}
				else
				{
					// multiline comment ends here
					setFormat( commentStart, matchEnd.capturedEnd() - commentStart, commentFormat );
					searchIndex = matchEnd.capturedEnd();
					isComment = false;
				}
			}
			if ( !isComment )
			{
				auto matchStart = match( commentStartRegex, text, searchIndex );
				if ( matchStart.hasMatch() )
				{
					// multiline comment starts here
					commentStart = matchStart.capturedStart();
					searchIndex = matchStart.capturedEnd();
					isComment = true;
				}
				else break; // no more comments in this line
			}
		}
		setCurrentBlockState( isComment ? 1 : 0 );
	}
}

bool QCodeHighlighter::isBetweenQuotes( const QString & text, int index )
{
	int quotes_before = 0;
	for ( int i = 0; i < index; ++i )
		quotes_before += int( text[ i ] == '\"' );
	return xo::is_odd( quotes_before );
}

QRegularExpressionMatch QCodeHighlighter::match( const QRegularExpression & regex, const QString & text, int index )
{
	auto m = regex.match( text, index );
	while ( m.hasMatch() && isBetweenQuotes( text, m.capturedStart() ) )
		m = regex.match( text, m.capturedEnd() );
	return m;
}

void QCodeHighlighter::applyRule( const QString& text, const HighlightRule& r )
{
	for ( auto m = match( r.regExp, text, 0 ); m.hasMatch(); m = match( r.regExp, text, m.capturedEnd() ) )
		setFormat( m.capturedStart(), m.capturedLength(), r.format );
}

void QCodeHighlighter::setRegexes()
{
	rules.clear();
	commentStartRegex.setPattern( "" );
	commentEndRegex.setPattern( "" );

	switch ( language )
	{
	case Language::xml:
		rules.emplace_back( "<[\\s]*[/]?[\\s]*([^\\n]\\w*)(?=[\\s/>])", elementFormat );
		rules.emplace_back( "\\w+(?=\\=)", attributeFormat );
		rules.emplace_back( "\"[^\\n\"]+\"(?=[\\s/>])", valueFormat );
		rules.emplace_back( "/.^/", specialFormat );
		rules.emplace_back( "(<\\?|/>|>|<|</|\\?>", operatorFormat );
		rules.emplace_back( "\\b([-+]?[\\.\\d]+)", numberFormat );
		commentStartRegex.setPattern( "<!--" );
		commentEndRegex.setPattern( "-->" );
		break;

	case Language::zml:
		rules.emplace_back( "\\w+\\s*\\=?\\s*[\\{\\[]", elementFormat );
		rules.emplace_back( "\\w+\\s*(\\=)", attributeFormat ); // key = value
		rules.emplace_back( "\\w+(:\\s+)", attributeFormat ); // key: value
		rules.emplace_back( "\"[^\\n\"]*\"", valueFormat );
		rules.emplace_back( "<<\\s.*\\s>>", specialFormat );
		rules.emplace_back( "([\\{\\}\\[\\]\\=]|:\\s)", operatorFormat );
		rules.emplace_back( "\\b([-+]?[\\.\\d]+)", numberFormat );
		rules.emplace_back( "\\@\\w+", macroFormat );
		rules.emplace_back( "\\$\\w+", macroFormat );
		rules.emplace_back( "#[^\\n]*", commentFormat ); // #
		commentStartRegex.setPattern( "#{3,}" );
		commentEndRegex.setPattern( "#{3,}" );
		increaseIndentRegex.setPattern( "[\\{\\[]" );
		decreaseIndentRegex.setPattern( "[\\}\\]]" );
		break;

	case Language::lua:
		rules.emplace_back( "\\b(and|break|do|else|elseif|end|false|for|function|goto|if|in|local|nil|not|or|repeat|return|then|true|until|while)\\b", elementFormat );
		rules.emplace_back( "\"[^\\n\"]*\"", valueFormat );
		rules.emplace_back( "\\b([-+]?[\\.\\d]+)", numberFormat );
		rules.emplace_back( "[\\+\\-\\*\\/\\%\\\\#\\&\\~\\|\\<\\>\\(\\)\\{\\}\\[\\]\\=\\;\\:\\,\\.]", operatorFormat );
		rules.emplace_back( "--[^\\n]*", commentFormat );
		commentStartRegex.setPattern( "--\\[\\[" );
		commentEndRegex.setPattern( "\\]\\]" );
		increaseIndentRegex.setPattern( "^\\s*(for|while|repeat|if|elseif|else|function)\\b" );
		decreaseIndentRegex.setPattern( "^\\s*(end|until|else|elseif)\\b" );
	default:
		break;
	}
}

void QCodeHighlighter::setFormats()
{
	operatorFormat.setForeground( Qt::darkGray );
	elementFormat.setForeground( Qt::darkBlue );
	elementFormat.setFontWeight( QFont::Bold );
	attributeFormat.setForeground( Qt::darkBlue );
	//attributeFormat.setFontItalic( true );
	//attributeFormat.setFontWeight( QFont::Bold );
	valueFormat.setForeground( Qt::darkRed );
	commentFormat.setForeground( Qt::gray );
	commentFormat.setFontItalic( true );
	numberFormat.setForeground( Qt::darkCyan );
	macroFormat.setForeground( Qt::darkMagenta );
	//macroFormat.setFontItalic( true );
	specialFormat.setForeground( Qt::darkMagenta );
	specialFormat.setFontItalic( true );
	//specialFormat.setFontWeight( QFont::Bold );
}

void QCodeHighlighter::setLanguage( Language l )
{
	language = l;
	setFormats();
	setRegexes();
}

xo::flat_map< std::string, QCodeHighlighter::Language > g_languages{
	{ "scone", QCodeHighlighter::Language::zml },
	{ "xml", QCodeHighlighter::Language::xml },
	{ "osim", QCodeHighlighter::Language::xml },
	{ "lua", QCodeHighlighter::Language::lua },
	{ "zml", QCodeHighlighter::Language::zml },
	{ "hfd", QCodeHighlighter::Language::zml }
};

QCodeHighlighter::Language QCodeHighlighter::detectLanguage( const QString& filename )
{
	auto ext = xo::to_lower( xo::path( filename.toStdString() ).extension_no_dot().str() );
	if ( auto l = g_languages.find( ext ); l != g_languages.end() )
		return l->second;
	else return Language::unknown;
}

void QCodeHighlighter::registerLanguage( const QString& ext, Language lang )
{
	g_languages[ xo::to_lower( ext.toStdString() ) ] = lang;
}
<|endoftext|>