<commit_before>/*******************************************************************************
Copyright (c) 2014, Jan Koester jan.koester@gmx.net
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the <organization> nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/

#include <fcntl.h>
#include <cstdlib>
#include <config.h>
#include <errno.h>
#include <signal.h>
#include "os/os.h"

#define READEVENT 0
#define SENDEVENT 1

//#define DEBUG_MUTEX

#include "../event.h"

libhttppp::Event::Event(ServerSocket *serversocket) {
    _ServerSocket=serversocket;
    _ServerSocket->setnonblocking();
    _ServerSocket->listenSocket();
    _EventEndloop =true;
    _Cpool= new ConnectionPool(_ServerSocket);
    _Events = new struct kevent[(_ServerSocket->getMaxconnections())];
    _Mutex = new Mutex;
    _firstConnectionContext=NULL;
    _lastConnectionContext=NULL;
}

libhttppp::Event::~Event() {
#ifdef DEBUG_MUTEX
   _httpexception.Note("~Event","Lock MainMutex");
#endif
  _Mutex->lock();
  delete   _Cpool;
  delete[] _Events;
  delete   _firstConnectionContext;
  delete   _Mutex;
  _lastConnectionContext=NULL;
}

libhttppp::Event* _EventIns=NULL;

void libhttppp::Event::CtrlHandler(int signum) {
    _EventIns->_EventEndloop=false;
}

void libhttppp::Event::runEventloop() {
    int srvssocket=_ServerSocket->getSocket();
    int maxconnets=_ServerSocket->getMaxconnections();
    int nev = 0;
    _setEvent = (struct kevent){0};
    _Kq = kqueue();
    EV_SET(&_setEvent, srvssocket, EVFILT_READ, EV_ADD, 0, 0, NULL);
    if (kevent(_Kq, &_setEvent, 1, NULL, 0, NULL) == -1)
      _httpexception.Critical("runeventloop","can't create kqueue!");
    signal(SIGPIPE, SIG_IGN);

    while(_EventEndloop) {
	nev = kevent(_Kq, NULL, 0, _Events,maxconnets, NULL);
        if(nev<0){
            if(errno== EINTR){
                continue;
            }else{
                 _httpexception.Critical("epoll wait failure");
                 throw _httpexception;
            }

        }
        for(int i=0; i<nev; i++) {
            ConnectionContext *curct=NULL;
            if(_Events[i].ident == srvssocket) {
              try {
              /*will create warning debug mode that normally because the check already connection
               * with this socket if getconnection throw they will be create a new one
               */
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Lock MainMutex");
#endif
                _Mutex->lock();
                curct=addConnectionContext();
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Unlock MainMutex");
#endif
                _Mutex->unlock();
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Lock ConnectionMutex");
#endif
                curct->_Mutex->lock();
                ClientSocket *clientsocket=curct->_CurConnection->getClientSocket();
                int fd=_ServerSocket->acceptEvent(clientsocket);
                clientsocket->setnonblocking();
                if(fd>0) {
                  _setEvent.udata = (void*) curct;
                  EV_SET(&_setEvent, fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
                  if (kevent(_Kq, &_setEvent, 1, NULL, 0, NULL) == -1){
                    _httpexception.Error("runeventloop","can't accep't in  kqueue!");
                  }else{
                    ConnectEvent(curct->_CurConnection);
                  }
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Unlock ConnectionMutex");
#endif
                  curct->_Mutex->unlock();
                } else {
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Unlock ConnectionMutex");
#endif
                   curct->_Mutex->unlock();
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Lock MainMutex");
#endif
                  _Mutex->lock();
                  delConnectionContext(curct->_CurConnection);
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Unlock MainMutex");
#endif
                  _Mutex->unlock();
                }

              } catch(HTTPException &e) {
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Lock MainMutex");
#endif
                _Mutex->lock();
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Unlock ConnectionMutex");
#endif
                curct->_Mutex->unlock();
                delConnectionContext(curct->_CurConnection);
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Unlock MainMutex");
#endif
                _Mutex->unlock();
                if(e.isCritical())
                  throw e;
              }
            } else {
                curct=(ConnectionContext*)_Events[i].udata;
                if(_Events[i].filter == EVFILT_READ) {
		    Thread curthread;
		    curthread.Create(ReadEvent,curct);
                    curthread.Detach();
                }else{
                    CloseEvent(curct);
                }
            }
        }
        _EventIns=this;
        signal(SIGINT, CtrlHandler);
    }
}

libhttppp::Event::ConnectionContext::ConnectionContext(){
  _CurConnection=NULL;
  _CurCPool=NULL;
  _CurEvent=NULL;
  _Mutex=new Mutex;
  _nextConnectionContext=NULL;
}

libhttppp::Event::ConnectionContext::~ConnectionContext(){
  delete _Mutex;
  delete _nextConnectionContext;
}

libhttppp::Event::ConnectionContext * libhttppp::Event::ConnectionContext::nextConnectionContext(){
  return _nextConnectionContext;
}

libhttppp::Event::ConnectionContext * libhttppp::Event::addConnectionContext(){
  if(!_firstConnectionContext){
    _firstConnectionContext=new ConnectionContext();
#ifdef DEBUG_MUTEX
    _httpexception.Note("addConnection","Lock ConnectionMutex");
#endif
    _firstConnectionContext->_Mutex->lock();
    _lastConnectionContext=_firstConnectionContext;
#ifdef DEBUG_MUTEX
    _httpexception.Note("addConnection","Unlock ConnectionMutex");
#endif
    _firstConnectionContext->_Mutex->unlock();
  }else{
#ifdef DEBUG_MUTEX
    _httpexception.Note("addConnection","Lock ConnectionMutex");
#endif
    ConnectionContext *prevcon=_lastConnectionContext;
    prevcon->_Mutex->lock();
    _lastConnectionContext->_nextConnectionContext=new ConnectionContext();
    _lastConnectionContext=_lastConnectionContext->_nextConnectionContext;
#ifdef DEBUG_MUTEX
    _httpexception.Note("addConnection","Unlock ConnectionMutex");
#endif
    prevcon->_Mutex->unlock();
  }
  _lastConnectionContext->_CurConnection=_Cpool->addConnection();
  _lastConnectionContext->_CurCPool=_Cpool;
  _lastConnectionContext->_CurEvent=this;

  return _lastConnectionContext;
}

libhttppp::Event::ConnectionContext * libhttppp::Event::delConnectionContext(libhttppp::Connection* delcon){
  ConnectionContext *prevcontext=NULL;
#ifdef DEBUG_MUTEX
  _httpexception.Note("delConnection","Lock MainMutex");
#endif
  _Mutex->lock();
  for(ConnectionContext *curcontext=_firstConnectionContext; curcontext;
      curcontext=curcontext->nextConnectionContext()){
    if(curcontext->_CurConnection==delcon){
#ifdef DEBUG_MUTEX
      _httpexception.Note("delConnection","Lock ConnectionMutex");
#endif
      curcontext->_Mutex->lock();
      _Cpool->delConnection(delcon);
      if(prevcontext){
#ifdef DEBUG_MUTEX
        _httpexception.Note("delConnection","Lock prevConnectionMutex");
#endif
        prevcontext->_Mutex->lock();
        prevcontext->_nextConnectionContext=curcontext->_nextConnectionContext;
        if(_lastConnectionContext==curcontext){
          _lastConnectionContext=prevcontext;
        }
#ifdef DEBUG_MUTEX
        _httpexception.Note("delConnection","unlock prevConnectionMutex");
#endif
        prevcontext->_Mutex->unlock();
      }else{
#ifdef DEBUG_MUTEX
        _httpexception.Note("delConnection","lock firstConnectionMutex");
#endif
        _firstConnectionContext->_Mutex->lock();
#ifdef DEBUG_MUTEX
        _httpexception.Note("delConnection","lock lastConnectionMutex");
#endif
        _lastConnectionContext->_Mutex->lock();
        _firstConnectionContext=curcontext->_nextConnectionContext;
        if(_lastConnectionContext->_CurConnection==delcon)
          _lastConnectionContext=_firstConnectionContext;
        if(_firstConnectionContext){
#ifdef DEBUG_MUTEX
        _httpexception.Note("delConnection","unlock firstConnectionMutex");
#endif
        _firstConnectionContext->_Mutex->unlock();
        }
        if(_lastConnectionContext){
#ifdef DEBUG_MUTEX
     _httpexception.Note("delConnection","unlock lastConnectionMutex");
#endif
        _lastConnectionContext->_Mutex->unlock();
        }
      }
      curcontext->_nextConnectionContext=NULL;
      delete curcontext;
      break;
    }
    prevcontext=curcontext;
  }
#ifdef DEBUG_MUTEX
  _httpexception.Note("delConnection","unlock MainMutex");
#endif
  _Mutex->unlock();
  if(prevcontext && prevcontext->_nextConnectionContext){
    return prevcontext->_nextConnectionContext;
  }else{
    ConnectionContext *fcontext=_firstConnectionContext;
    return fcontext;
  }
}

/*Workers*/
void *libhttppp::Event::ReadEvent(void *curcon){
  ConnectionContext *ccon=(ConnectionContext*)curcon;
  Event *eventins=ccon->_CurEvent;
#ifdef DEBUG_MUTEX
  ccon->_httpexception.Note("ReadEvent","lock ConnectionMutex");
#endif
  ccon->_Mutex->lock();
  Connection *con=(Connection*)ccon->_CurConnection;
  try {
    char buf[BLOCKSIZE];
    int rcvsize=0;
    do{
      rcvsize=eventins->_ServerSocket->recvData(con->getClientSocket(),buf,BLOCKSIZE);
      if(rcvsize>0)
        con->addRecvQueue(buf,rcvsize);
    }while(rcvsize>0);
    eventins->RequestEvent(con);
#ifdef DEBUG_MUTEX
  ccon->_httpexception.Note("ReadEvent","unlock ConnectionMutex");
#endif
    ccon->_Mutex->unlock();
    WriteEvent(ccon);
  } catch(HTTPException &e) {
#ifdef DEBUG_MUTEX
      ccon->_httpexception.Note("ReadEvent","unlock ConnectionMutex");
#endif
      ccon->_Mutex->unlock();
       if(e.isCritical()) {
         throw e;
       }
       if(e.isError()){
          con->cleanRecvData();
          CloseEvent(ccon);
       }
  }
  return NULL;
}

void *libhttppp::Event::WriteEvent(void* curcon){
  ConnectionContext *ccon=(ConnectionContext*)curcon;
  Event *eventins=ccon->_CurEvent;
#ifdef DEBUG_MUTEX
  ccon->_httpexception.Note("WriteEvent","lock ConnectionMutex");
#endif
  ccon->_Mutex->lock();
  Connection *con=(Connection*)ccon->_CurConnection;
  try {
    ssize_t sended=0;
    while(con->getSendData()){
      sended=eventins->_ServerSocket->sendData(con->getClientSocket(),
                                    (void*)con->getSendData()->getData(),
                                    con->getSendData()->getDataSize());
      if(sended>0)
        con->resizeSendQueue(sended);
    }
    eventins->ResponseEvent(con);
  } catch(HTTPException &e) {
    CloseEvent(ccon);
  }
#ifdef DEBUG_MUTEX
  ccon->_httpexception.Note("WriteEvent","unlock ConnectionMutex");
#endif
  ccon->_Mutex->unlock();
  return NULL;
}

void *libhttppp::Event::CloseEvent(void *curcon){
  ConnectionContext *ccon=(ConnectionContext*)curcon;
  Event *eventins=ccon->_CurEvent;
#ifdef DEBUG_MUTEX
  ccon->_httpexception.Note("CloseEvent","ConnectionMutex");
#endif
  ccon->_Mutex->lock();
  Connection *con=(Connection*)ccon->_CurConnection;
  eventins->DisconnectEvent(con);
#ifdef DEBUG_MUTEX
  ccon->_httpexception.Note("CloseEvent","unlock ConnectionMutex");
#endif
  ccon->_Mutex->unlock();
  try {
    EV_SET(&eventins->_setEvent,con->getClientSocket()->getSocket(), EVFILT_READ, EV_DELETE, 0, 0, NULL);
    if (kevent(eventins->_Kq,&eventins->_setEvent, 1, NULL, 0, NULL) == -1)
      eventins->_httpexception.Error("Connection can't delete from kqueue");
    eventins->delConnectionContext(con);
    curcon=NULL;
    eventins->_httpexception.Note("Connection shutdown!");
  } catch(HTTPException &e) {
    eventins->_httpexception.Note("Can't do Connection shutdown!");
  }
  return NULL;
}

/*Event Handlers*/
void libhttppp::Event::RequestEvent(libhttppp::Connection *curcon) {
    return;
}

void libhttppp::Event::ResponseEvent(libhttppp::Connection *curcon) {
    return;
}

void libhttppp::Event::ConnectEvent(libhttppp::Connection *curcon) {
    return;
}

void libhttppp::Event::DisconnectEvent(libhttppp::Connection *curcon) {
    return;
}
<commit_msg>working on kqueue<commit_after>/*******************************************************************************
Copyright (c) 2014, Jan Koester jan.koester@gmx.net
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the <organization> nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/

#include <fcntl.h>
#include <cstdlib>
#include <config.h>
#include <errno.h>
#include <signal.h>
#include "os/os.h"

#define READEVENT 0
#define SENDEVENT 1

//#define DEBUG_MUTEX

#include "../event.h"

libhttppp::Event::Event(ServerSocket *serversocket) {
    _ServerSocket=serversocket;
    _ServerSocket->setnonblocking();
    _ServerSocket->listenSocket();
    _EventEndloop =true;
    _Cpool= new ConnectionPool(_ServerSocket);
    _Events = new struct kevent[(_ServerSocket->getMaxconnections())];
    _Mutex = new Mutex;
    _firstConnectionContext=NULL;
    _lastConnectionContext=NULL;
}

libhttppp::Event::~Event() {
#ifdef DEBUG_MUTEX
   _httpexception.Note("~Event","Lock MainMutex");
#endif
  _Mutex->lock();
  delete   _Cpool;
  delete[] _Events;
  delete   _firstConnectionContext;
  delete   _Mutex;
  _lastConnectionContext=NULL;
}

libhttppp::Event* _EventIns=NULL;

void libhttppp::Event::CtrlHandler(int signum) {
    _EventIns->_EventEndloop=false;
}

void libhttppp::Event::runEventloop() {
    int srvssocket=_ServerSocket->getSocket();
    int maxconnets=_ServerSocket->getMaxconnections();
    int nev = 0;
    _setEvent = (struct kevent){0};
    _Kq = kqueue();
    EV_SET(&_setEvent, srvssocket, EVFILT_READ, EV_ADD, 0, 0, NULL);
    if (kevent(_Kq, &_setEvent, 1, NULL, 0, NULL) == -1)
      _httpexception.Critical("runeventloop","can't create kqueue!");
    signal(SIGPIPE, SIG_IGN);

    while(_EventEndloop) {
	nev = kevent(_Kq, NULL, 0, _Events,maxconnets, NULL);
        if(nev<0){
            if(errno== EINTR){
                continue;
            }else{
                 _httpexception.Critical("epoll wait failure");
                 throw _httpexception;
            }

        }
        for(int i=0; i<nev; i++) {
            ConnectionContext *curct=NULL;
            if(_Events[i].ident == srvssocket) {
              try {
              /*will create warning debug mode that normally because the check already connection
               * with this socket if getconnection throw they will be create a new one
               */
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Lock MainMutex");
#endif
                _Mutex->lock();
                curct=addConnectionContext();
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Unlock MainMutex");
#endif
                _Mutex->unlock();
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Lock ConnectionMutex");
#endif
                curct->_Mutex->lock();
                ClientSocket *clientsocket=curct->_CurConnection->getClientSocket();
                int fd=_ServerSocket->acceptEvent(clientsocket);
                clientsocket->setnonblocking();
                if(fd>0) {
                  EV_SET(&_setEvent, fd, EVFILT_READ, EV_ADD, 0, 0, (void*) curct);
                  if (kevent(_Kq, &_setEvent, 1, NULL, 0, NULL) == -1){
                    _httpexception.Error("runeventloop","can't accep't in  kqueue!");
                  }else{
                    ConnectEvent(curct->_CurConnection);
                  }
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Unlock ConnectionMutex");
#endif
                  curct->_Mutex->unlock();
                } else {
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Unlock ConnectionMutex");
#endif
                   curct->_Mutex->unlock();
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Lock MainMutex");
#endif
                  _Mutex->lock();
                  delConnectionContext(curct->_CurConnection);
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Unlock MainMutex");
#endif
                  _Mutex->unlock();
                }

              } catch(HTTPException &e) {
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Lock MainMutex");
#endif
                _Mutex->lock();
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Unlock ConnectionMutex");
#endif
                curct->_Mutex->unlock();
                delConnectionContext(curct->_CurConnection);
#ifdef DEBUG_MUTEX
                _httpexception.Note("runeventloop","Unlock MainMutex");
#endif
                _Mutex->unlock();
                if(e.isCritical())
                  throw e;
              }
            } else {
                curct=(ConnectionContext*)_Events[i].udata;
                if(_Events[i].filter == EVFILT_READ) {
		    Thread curthread;
		    curthread.Create(ReadEvent,curct);
                    curthread.Detach();
                }else{
                    CloseEvent(curct);
                }
            }
        }
        _EventIns=this;
        signal(SIGINT, CtrlHandler);
    }
}

libhttppp::Event::ConnectionContext::ConnectionContext(){
  _CurConnection=NULL;
  _CurCPool=NULL;
  _CurEvent=NULL;
  _Mutex=new Mutex;
  _nextConnectionContext=NULL;
}

libhttppp::Event::ConnectionContext::~ConnectionContext(){
  delete _Mutex;
  delete _nextConnectionContext;
}

libhttppp::Event::ConnectionContext * libhttppp::Event::ConnectionContext::nextConnectionContext(){
  return _nextConnectionContext;
}

libhttppp::Event::ConnectionContext * libhttppp::Event::addConnectionContext(){
  if(!_firstConnectionContext){
    _firstConnectionContext=new ConnectionContext();
#ifdef DEBUG_MUTEX
    _httpexception.Note("addConnection","Lock ConnectionMutex");
#endif
    _firstConnectionContext->_Mutex->lock();
    _lastConnectionContext=_firstConnectionContext;
#ifdef DEBUG_MUTEX
    _httpexception.Note("addConnection","Unlock ConnectionMutex");
#endif
    _firstConnectionContext->_Mutex->unlock();
  }else{
#ifdef DEBUG_MUTEX
    _httpexception.Note("addConnection","Lock ConnectionMutex");
#endif
    ConnectionContext *prevcon=_lastConnectionContext;
    prevcon->_Mutex->lock();
    _lastConnectionContext->_nextConnectionContext=new ConnectionContext();
    _lastConnectionContext=_lastConnectionContext->_nextConnectionContext;
#ifdef DEBUG_MUTEX
    _httpexception.Note("addConnection","Unlock ConnectionMutex");
#endif
    prevcon->_Mutex->unlock();
  }
  _lastConnectionContext->_CurConnection=_Cpool->addConnection();
  _lastConnectionContext->_CurCPool=_Cpool;
  _lastConnectionContext->_CurEvent=this;

  return _lastConnectionContext;
}

libhttppp::Event::ConnectionContext * libhttppp::Event::delConnectionContext(libhttppp::Connection* delcon){
  ConnectionContext *prevcontext=NULL;
#ifdef DEBUG_MUTEX
  _httpexception.Note("delConnection","Lock MainMutex");
#endif
  _Mutex->lock();
  for(ConnectionContext *curcontext=_firstConnectionContext; curcontext;
      curcontext=curcontext->nextConnectionContext()){
    if(curcontext->_CurConnection==delcon){
#ifdef DEBUG_MUTEX
      _httpexception.Note("delConnection","Lock ConnectionMutex");
#endif
      curcontext->_Mutex->lock();
      _Cpool->delConnection(delcon);
      if(prevcontext){
#ifdef DEBUG_MUTEX
        _httpexception.Note("delConnection","Lock prevConnectionMutex");
#endif
        prevcontext->_Mutex->lock();
        prevcontext->_nextConnectionContext=curcontext->_nextConnectionContext;
        if(_lastConnectionContext==curcontext){
          _lastConnectionContext=prevcontext;
        }
#ifdef DEBUG_MUTEX
        _httpexception.Note("delConnection","unlock prevConnectionMutex");
#endif
        prevcontext->_Mutex->unlock();
      }else{
#ifdef DEBUG_MUTEX
        _httpexception.Note("delConnection","lock firstConnectionMutex");
#endif
        _firstConnectionContext->_Mutex->lock();
#ifdef DEBUG_MUTEX
        _httpexception.Note("delConnection","lock lastConnectionMutex");
#endif
        _lastConnectionContext->_Mutex->lock();
        _firstConnectionContext=curcontext->_nextConnectionContext;
        if(_lastConnectionContext->_CurConnection==delcon)
          _lastConnectionContext=_firstConnectionContext;
        if(_firstConnectionContext){
#ifdef DEBUG_MUTEX
        _httpexception.Note("delConnection","unlock firstConnectionMutex");
#endif
        _firstConnectionContext->_Mutex->unlock();
        }
        if(_lastConnectionContext){
#ifdef DEBUG_MUTEX
     _httpexception.Note("delConnection","unlock lastConnectionMutex");
#endif
        _lastConnectionContext->_Mutex->unlock();
        }
      }
      curcontext->_nextConnectionContext=NULL;
      delete curcontext;
      break;
    }
    prevcontext=curcontext;
  }
#ifdef DEBUG_MUTEX
  _httpexception.Note("delConnection","unlock MainMutex");
#endif
  _Mutex->unlock();
  if(prevcontext && prevcontext->_nextConnectionContext){
    return prevcontext->_nextConnectionContext;
  }else{
    ConnectionContext *fcontext=_firstConnectionContext;
    return fcontext;
  }
}

/*Workers*/
void *libhttppp::Event::ReadEvent(void *curcon){
  ConnectionContext *ccon=(ConnectionContext*)curcon;
  Event *eventins=ccon->_CurEvent;
#ifdef DEBUG_MUTEX
  ccon->_httpexception.Note("ReadEvent","lock ConnectionMutex");
#endif
  ccon->_Mutex->lock();
  Connection *con=(Connection*)ccon->_CurConnection;
  try {
    char buf[BLOCKSIZE];
    int rcvsize=0;
    do{
      rcvsize=eventins->_ServerSocket->recvData(con->getClientSocket(),buf,BLOCKSIZE);
      if(rcvsize>0)
        con->addRecvQueue(buf,rcvsize);
    }while(rcvsize>0);
    eventins->RequestEvent(con);
#ifdef DEBUG_MUTEX
  ccon->_httpexception.Note("ReadEvent","unlock ConnectionMutex");
#endif
    ccon->_Mutex->unlock();
    WriteEvent(ccon);
  } catch(HTTPException &e) {
#ifdef DEBUG_MUTEX
      ccon->_httpexception.Note("ReadEvent","unlock ConnectionMutex");
#endif
      ccon->_Mutex->unlock();
       if(e.isCritical()) {
         throw e;
       }
       if(e.isError()){
          con->cleanRecvData();
          CloseEvent(ccon);
       }
  }
  return NULL;
}

void *libhttppp::Event::WriteEvent(void* curcon){
  ConnectionContext *ccon=(ConnectionContext*)curcon;
  Event *eventins=ccon->_CurEvent;
#ifdef DEBUG_MUTEX
  ccon->_httpexception.Note("WriteEvent","lock ConnectionMutex");
#endif
  ccon->_Mutex->lock();
  Connection *con=(Connection*)ccon->_CurConnection;
  try {
    ssize_t sended=0;
    while(con->getSendData()){
      sended=eventins->_ServerSocket->sendData(con->getClientSocket(),
                                    (void*)con->getSendData()->getData(),
                                    con->getSendData()->getDataSize());
      if(sended>0)
        con->resizeSendQueue(sended);
    }
    eventins->ResponseEvent(con);
  } catch(HTTPException &e) {
    CloseEvent(ccon);
  }
#ifdef DEBUG_MUTEX
  ccon->_httpexception.Note("WriteEvent","unlock ConnectionMutex");
#endif
  ccon->_Mutex->unlock();
  return NULL;
}

void *libhttppp::Event::CloseEvent(void *curcon){
  ConnectionContext *ccon=(ConnectionContext*)curcon;
  Event *eventins=ccon->_CurEvent;
#ifdef DEBUG_MUTEX
  ccon->_httpexception.Note("CloseEvent","ConnectionMutex");
#endif
  ccon->_Mutex->lock();
  Connection *con=(Connection*)ccon->_CurConnection;
  eventins->DisconnectEvent(con);
#ifdef DEBUG_MUTEX
  ccon->_httpexception.Note("CloseEvent","unlock ConnectionMutex");
#endif
  ccon->_Mutex->unlock();
  try {
    EV_SET(&eventins->_setEvent,con->getClientSocket()->getSocket(), EVFILT_READ, EV_DELETE, 0, 0, NULL);
    if (kevent(eventins->_Kq,&eventins->_setEvent, 1, NULL, 0, NULL) == -1)
      eventins->_httpexception.Error("Connection can't delete from kqueue");
    eventins->delConnectionContext(con);
    curcon=NULL;
    eventins->_httpexception.Note("Connection shutdown!");
  } catch(HTTPException &e) {
    eventins->_httpexception.Note("Can't do Connection shutdown!");
  }
  return NULL;
}

/*Event Handlers*/
void libhttppp::Event::RequestEvent(libhttppp::Connection *curcon) {
    return;
}

void libhttppp::Event::ResponseEvent(libhttppp::Connection *curcon) {
    return;
}

void libhttppp::Event::ConnectEvent(libhttppp::Connection *curcon) {
    return;
}

void libhttppp::Event::DisconnectEvent(libhttppp::Connection *curcon) {
    return;
}
<|endoftext|>


<commit_before>//// License: Apache 2.0. See LICENSE file in root directory.
//// Copyright(c) 2020 Intel Corporation. All Rights Reserved.

#include "l500-options.h"
#include "l500-private.h"
#include "l500-depth.h"

const std::string MIN_CONTROLS_FW_VERSION("1.3.9.0");

namespace librealsense
{
    using namespace ivcam2;

    float l500_hw_options::query() const
    {
        return query(int(_resolution->query()));
    }

    void l500_hw_options::set(float value)
    {
        _hw_monitor->send(command{ AMCSET, _type, (int)value });
    }

    option_range l500_hw_options::get_range() const
    {
        return _range;
    }

    l500_hw_options::l500_hw_options(hw_monitor* hw_monitor, l500_control type, option* resolution)
        :_hw_monitor(hw_monitor),
        _type(type),
        _resolution(resolution)
    {
        auto min = _hw_monitor->send(command{ AMCGET, _type, get_min });
        auto max = _hw_monitor->send(command{ AMCGET, _type, get_max });
        auto step = _hw_monitor->send(command{ AMCGET, _type, get_step });

        auto def = query(int(_resolution->query()));

        if (min.size() < sizeof(int32_t) || max.size() < sizeof(int32_t) || step.size() < sizeof(int32_t))
        {
            std::stringstream s;
            s << "Size of data returned is not valid min size = " << min.size() << ", max size = " << max.size() << ", step size = " << step.size();
            throw std::runtime_error(s.str());
        }

        auto max_value = float(*(reinterpret_cast<int32_t*>(max.data())));
        auto min_value = float(*(reinterpret_cast<int32_t*>(min.data())));

        if (type == noise_filtering)
        {
            // Hack until addressed in firmware
            min_value = std::min(max_value, std::max(min_value, 2.f));
        }

        _range = option_range{ min_value,
            max_value,
            float(*(reinterpret_cast<int32_t*>(step.data()))),
            def };
    }

    void l500_hw_options::enable_recording(std::function<void(const option&)> recording_action)
    {}

    float l500_hw_options::query(int mode) const
    {
        auto res = _hw_monitor->send(command{ AMCGET, _type, get_current, mode });

        if (res.size() < sizeof(int32_t))
        {
            std::stringstream s;
            s << "Size of data returned is not valid min size = " << res.size();
            throw std::runtime_error(s.str());
        }

        auto val = *(reinterpret_cast<int32_t*>((void*)res.data()));
        return float(val);
    }

    l500_options::l500_options(std::shared_ptr<context> ctx, const platform::backend_device_group & group) :
        device(ctx, group),
        l500_device(ctx, group)
    {
        auto& raw_depth_sensor = get_raw_depth_sensor();
        auto& depth_sensor = get_depth_sensor();

        if (_fw_version < firmware_version(MIN_CONTROLS_FW_VERSION))
        {
            depth_sensor.register_option
            (RS2_OPTION_VISUAL_PRESET, std::make_shared<uvc_xu_option<int >>(raw_depth_sensor, ivcam2::depth_xu, ivcam2::L500_AMBIENT,
                "Change the depth ambient light to ambient: 1 for no ambient and 2 for low ambient",
                std::map<float, std::string>{ { float(RS2_AMBIENT_LIGHT_NO_AMBIENT), "No Ambient"},
                { float(RS2_AMBIENT_LIGHT_LOW_AMBIENT), "Low Ambient" }}));
        }
        else
        {
            // On USB2 we have only QVGA sensor mode
            bool usb3mode = (_usb_mode >= platform::usb3_type || _usb_mode == platform::usb_undefined);

            auto default_sensor_mode = static_cast<float>(usb3mode ? RS2_SENSOR_MODE_VGA : RS2_SENSOR_MODE_QVGA);

            auto resolution_option = std::make_shared<float_option_with_description<rs2_sensor_mode>>(option_range{ RS2_SENSOR_MODE_VGA,RS2_SENSOR_MODE_COUNT - 1,1, default_sensor_mode }, "Notify the sensor about the intended streaming mode. Required for preset ");

            depth_sensor.register_option(RS2_OPTION_SENSOR_MODE, resolution_option);

            _hw_options[RS2_OPTION_POST_PROCESSING_SHARPENING] = register_option<l500_hw_options, hw_monitor*, l500_control, option*>(RS2_OPTION_POST_PROCESSING_SHARPENING, _hw_monitor.get(), post_processing_sharpness, resolution_option.get());
            _hw_options[RS2_OPTION_PRE_PROCESSING_SHARPENING] = register_option<l500_hw_options, hw_monitor*, l500_control, option*>(RS2_OPTION_PRE_PROCESSING_SHARPENING, _hw_monitor.get(), pre_processing_sharpness, resolution_option.get());
            _hw_options[RS2_OPTION_NOISE_FILTERING] = register_option<l500_hw_options, hw_monitor*, l500_control, option*>(RS2_OPTION_NOISE_FILTERING, _hw_monitor.get(), noise_filtering, resolution_option.get());
            _hw_options[RS2_OPTION_AVALANCHE_PHOTO_DIODE] = register_option<l500_hw_options, hw_monitor*, l500_control, option*>(RS2_OPTION_AVALANCHE_PHOTO_DIODE, _hw_monitor.get(), apd, resolution_option.get());
            _hw_options[RS2_OPTION_CONFIDENCE_THRESHOLD] = register_option<l500_hw_options, hw_monitor*, l500_control, option*>(RS2_OPTION_CONFIDENCE_THRESHOLD, _hw_monitor.get(), confidence, resolution_option.get());
            _hw_options[RS2_OPTION_LASER_POWER] = register_option<l500_hw_options, hw_monitor*, l500_control, option*>(RS2_OPTION_LASER_POWER, _hw_monitor.get(), laser_gain, resolution_option.get());
            _hw_options[RS2_OPTION_MIN_DISTANCE] = register_option<l500_hw_options, hw_monitor*, l500_control, option*>(RS2_OPTION_MIN_DISTANCE, _hw_monitor.get(), min_distance, resolution_option.get());
            _hw_options[RS2_OPTION_INVALIDATION_BYPASS] = register_option<l500_hw_options, hw_monitor*, l500_control, option*>(RS2_OPTION_INVALIDATION_BYPASS, _hw_monitor.get(), invalidation_bypass, resolution_option.get());

            _ambient_light = register_option<uvc_xu_option<int>, uvc_sensor&, platform::extension_unit, uint8_t, std::string, const std::map<float, std::string>& >
                (RS2_OPTION_AMBIENT_LIGHT, raw_depth_sensor, ivcam2::depth_xu, ivcam2::L500_AMBIENT,
                    "Change the depth ambient light to ambient: 1 for no ambient and 2 for low ambient",
                    std::map<float, std::string>{ { RS2_AMBIENT_LIGHT_NO_AMBIENT, "No Ambient"},
                    { RS2_AMBIENT_LIGHT_LOW_AMBIENT, "Low Ambient" }});

            _preset = register_option <float_option_with_description<rs2_l500_visual_preset>, option_range>
                (RS2_OPTION_VISUAL_PRESET, option_range{ RS2_L500_VISUAL_PRESET_CUSTOM , RS2_L500_VISUAL_PRESET_SHORT_RANGE, 1, RS2_L500_VISUAL_PRESET_DEFAULT },
                    "Preset to calibrate the camera to environment ambient, no ambient or low ambient. 1 is no ambient and 2 is low ambient");

            _advanced_options = get_advanced_controls();
        }
    }

    std::vector<rs2_option> l500_options::get_advanced_controls()
    {
        std::vector<rs2_option> res;

        res.push_back(RS2_OPTION_AMBIENT_LIGHT);
        for (auto&& o : _hw_options)
            res.push_back(o.first);

        return res;
    }

    void l500_options::on_set_option(rs2_option opt, float value)
    {
        if (opt == RS2_OPTION_VISUAL_PRESET)
        {
            change_preset(static_cast<rs2_l500_visual_preset>(int(value)));
        }
        else
        {
            auto advanced_controls = get_advanced_controls();
            if (std::find(advanced_controls.begin(), advanced_controls.end(), opt) != advanced_controls.end())
                move_to_custom ();
            else
                throw  wrong_api_call_sequence_exception(to_string() << "on_set_option support advanced controls only "<< opt<<" injected");
        }
    }

    void l500_options::change_preset(rs2_l500_visual_preset preset)
    {
        if ((preset != RS2_L500_VISUAL_PRESET_CUSTOM) &&
            (preset != RS2_L500_VISUAL_PRESET_DEFAULT))
            reset_hw_controls();

        switch (preset)
        {
        case RS2_L500_VISUAL_PRESET_NO_AMBIENT:
            _ambient_light->set_with_no_signal(RS2_AMBIENT_LIGHT_NO_AMBIENT);
            break;
        case RS2_L500_VISUAL_PRESET_LOW_AMBIENT:
            _ambient_light->set_with_no_signal(RS2_AMBIENT_LIGHT_LOW_AMBIENT);
            set_max_laser();
            break;
        case RS2_L500_VISUAL_PRESET_MAX_RANGE:
            _ambient_light->set_with_no_signal(RS2_AMBIENT_LIGHT_NO_AMBIENT);
            set_max_laser();
            break;
        case RS2_L500_VISUAL_PRESET_SHORT_RANGE:
            _ambient_light->set_with_no_signal(RS2_AMBIENT_LIGHT_LOW_AMBIENT);
            break;
        case RS2_L500_VISUAL_PRESET_CUSTOM:
            move_to_custom();
            break;
        case RS2_L500_VISUAL_PRESET_DEFAULT:
            LOG_ERROR("L515 Visual Preset option cannot be changed to Default");
            throw  invalid_value_exception(to_string() << "The Default preset signifies that the controls have not been changed \n"
                                                           "since initialization, the API does not support changing back to this state.\n"
                                                           "Please choose one of the other presets");
            break;
        default: break;
        };
    }

    void l500_options::move_to_custom ()
    {
        for (auto& o : _hw_options)
        {
            auto  val = o.second->query();
            o.second->set_with_no_signal(val);
        }
        _preset->set_with_no_signal(RS2_L500_VISUAL_PRESET_CUSTOM);
    }

    void l500_options::reset_hw_controls()
    {
        for (auto& o : _hw_options)
            o.second->set_with_no_signal(-1);
    }

    void l500_options::set_max_laser()
    {
        auto range = _hw_options[RS2_OPTION_LASER_POWER]->get_range();
        _hw_options[RS2_OPTION_LASER_POWER]->set_with_no_signal(range.max);
    }
}
<commit_msg>remove SW limitation of noise filter range<commit_after>//// License: Apache 2.0. See LICENSE file in root directory.
//// Copyright(c) 2020 Intel Corporation. All Rights Reserved.

#include "l500-options.h"
#include "l500-private.h"
#include "l500-depth.h"

const std::string MIN_CONTROLS_FW_VERSION("1.3.9.0");

namespace librealsense
{
    using namespace ivcam2;

    float l500_hw_options::query() const
    {
        return query(int(_resolution->query()));
    }

    void l500_hw_options::set(float value)
    {
        _hw_monitor->send(command{ AMCSET, _type, (int)value });
    }

    option_range l500_hw_options::get_range() const
    {
        return _range;
    }

    l500_hw_options::l500_hw_options(hw_monitor* hw_monitor, l500_control type, option* resolution)
        :_hw_monitor(hw_monitor),
        _type(type),
        _resolution(resolution)
    {
        auto min = _hw_monitor->send(command{ AMCGET, _type, get_min });
        auto max = _hw_monitor->send(command{ AMCGET, _type, get_max });
        auto step = _hw_monitor->send(command{ AMCGET, _type, get_step });

        auto def = query(int(_resolution->query()));

        if (min.size() < sizeof(int32_t) || max.size() < sizeof(int32_t) || step.size() < sizeof(int32_t))
        {
            std::stringstream s;
            s << "Size of data returned is not valid min size = " << min.size() << ", max size = " << max.size() << ", step size = " << step.size();
            throw std::runtime_error(s.str());
        }

        auto max_value = float(*(reinterpret_cast<int32_t*>(max.data())));
        auto min_value = float(*(reinterpret_cast<int32_t*>(min.data())));

        _range = option_range{ min_value,
            max_value,
            float(*(reinterpret_cast<int32_t*>(step.data()))),
            def };
    }

    void l500_hw_options::enable_recording(std::function<void(const option&)> recording_action)
    {}

    float l500_hw_options::query(int mode) const
    {
        auto res = _hw_monitor->send(command{ AMCGET, _type, get_current, mode });

        if (res.size() < sizeof(int32_t))
        {
            std::stringstream s;
            s << "Size of data returned is not valid min size = " << res.size();
            throw std::runtime_error(s.str());
        }

        auto val = *(reinterpret_cast<int32_t*>((void*)res.data()));
        return float(val);
    }

    l500_options::l500_options(std::shared_ptr<context> ctx, const platform::backend_device_group & group) :
        device(ctx, group),
        l500_device(ctx, group)
    {
        auto& raw_depth_sensor = get_raw_depth_sensor();
        auto& depth_sensor = get_depth_sensor();

        if (_fw_version < firmware_version(MIN_CONTROLS_FW_VERSION))
        {
            depth_sensor.register_option
            (RS2_OPTION_VISUAL_PRESET, std::make_shared<uvc_xu_option<int >>(raw_depth_sensor, ivcam2::depth_xu, ivcam2::L500_AMBIENT,
                "Change the depth ambient light to ambient: 1 for no ambient and 2 for low ambient",
                std::map<float, std::string>{ { float(RS2_AMBIENT_LIGHT_NO_AMBIENT), "No Ambient"},
                { float(RS2_AMBIENT_LIGHT_LOW_AMBIENT), "Low Ambient" }}));
        }
        else
        {
            // On USB2 we have only QVGA sensor mode
            bool usb3mode = (_usb_mode >= platform::usb3_type || _usb_mode == platform::usb_undefined);

            auto default_sensor_mode = static_cast<float>(usb3mode ? RS2_SENSOR_MODE_VGA : RS2_SENSOR_MODE_QVGA);

            auto resolution_option = std::make_shared<float_option_with_description<rs2_sensor_mode>>(option_range{ RS2_SENSOR_MODE_VGA,RS2_SENSOR_MODE_COUNT - 1,1, default_sensor_mode }, "Notify the sensor about the intended streaming mode. Required for preset ");

            depth_sensor.register_option(RS2_OPTION_SENSOR_MODE, resolution_option);

            _hw_options[RS2_OPTION_POST_PROCESSING_SHARPENING] = register_option<l500_hw_options, hw_monitor*, l500_control, option*>(RS2_OPTION_POST_PROCESSING_SHARPENING, _hw_monitor.get(), post_processing_sharpness, resolution_option.get());
            _hw_options[RS2_OPTION_PRE_PROCESSING_SHARPENING] = register_option<l500_hw_options, hw_monitor*, l500_control, option*>(RS2_OPTION_PRE_PROCESSING_SHARPENING, _hw_monitor.get(), pre_processing_sharpness, resolution_option.get());
            _hw_options[RS2_OPTION_NOISE_FILTERING] = register_option<l500_hw_options, hw_monitor*, l500_control, option*>(RS2_OPTION_NOISE_FILTERING, _hw_monitor.get(), noise_filtering, resolution_option.get());
            _hw_options[RS2_OPTION_AVALANCHE_PHOTO_DIODE] = register_option<l500_hw_options, hw_monitor*, l500_control, option*>(RS2_OPTION_AVALANCHE_PHOTO_DIODE, _hw_monitor.get(), apd, resolution_option.get());
            _hw_options[RS2_OPTION_CONFIDENCE_THRESHOLD] = register_option<l500_hw_options, hw_monitor*, l500_control, option*>(RS2_OPTION_CONFIDENCE_THRESHOLD, _hw_monitor.get(), confidence, resolution_option.get());
            _hw_options[RS2_OPTION_LASER_POWER] = register_option<l500_hw_options, hw_monitor*, l500_control, option*>(RS2_OPTION_LASER_POWER, _hw_monitor.get(), laser_gain, resolution_option.get());
            _hw_options[RS2_OPTION_MIN_DISTANCE] = register_option<l500_hw_options, hw_monitor*, l500_control, option*>(RS2_OPTION_MIN_DISTANCE, _hw_monitor.get(), min_distance, resolution_option.get());
            _hw_options[RS2_OPTION_INVALIDATION_BYPASS] = register_option<l500_hw_options, hw_monitor*, l500_control, option*>(RS2_OPTION_INVALIDATION_BYPASS, _hw_monitor.get(), invalidation_bypass, resolution_option.get());

            _ambient_light = register_option<uvc_xu_option<int>, uvc_sensor&, platform::extension_unit, uint8_t, std::string, const std::map<float, std::string>& >
                (RS2_OPTION_AMBIENT_LIGHT, raw_depth_sensor, ivcam2::depth_xu, ivcam2::L500_AMBIENT,
                    "Change the depth ambient light to ambient: 1 for no ambient and 2 for low ambient",
                    std::map<float, std::string>{ { RS2_AMBIENT_LIGHT_NO_AMBIENT, "No Ambient"},
                    { RS2_AMBIENT_LIGHT_LOW_AMBIENT, "Low Ambient" }});

            _preset = register_option <float_option_with_description<rs2_l500_visual_preset>, option_range>
                (RS2_OPTION_VISUAL_PRESET, option_range{ RS2_L500_VISUAL_PRESET_CUSTOM , RS2_L500_VISUAL_PRESET_SHORT_RANGE, 1, RS2_L500_VISUAL_PRESET_DEFAULT },
                    "Preset to calibrate the camera to environment ambient, no ambient or low ambient. 1 is no ambient and 2 is low ambient");

            _advanced_options = get_advanced_controls();
        }
    }

    std::vector<rs2_option> l500_options::get_advanced_controls()
    {
        std::vector<rs2_option> res;

        res.push_back(RS2_OPTION_AMBIENT_LIGHT);
        for (auto&& o : _hw_options)
            res.push_back(o.first);

        return res;
    }

    void l500_options::on_set_option(rs2_option opt, float value)
    {
        if (opt == RS2_OPTION_VISUAL_PRESET)
        {
            change_preset(static_cast<rs2_l500_visual_preset>(int(value)));
        }
        else
        {
            auto advanced_controls = get_advanced_controls();
            if (std::find(advanced_controls.begin(), advanced_controls.end(), opt) != advanced_controls.end())
                move_to_custom ();
            else
                throw  wrong_api_call_sequence_exception(to_string() << "on_set_option support advanced controls only "<< opt<<" injected");
        }
    }

    void l500_options::change_preset(rs2_l500_visual_preset preset)
    {
        if ((preset != RS2_L500_VISUAL_PRESET_CUSTOM) &&
            (preset != RS2_L500_VISUAL_PRESET_DEFAULT))
            reset_hw_controls();

        switch (preset)
        {
        case RS2_L500_VISUAL_PRESET_NO_AMBIENT:
            _ambient_light->set_with_no_signal(RS2_AMBIENT_LIGHT_NO_AMBIENT);
            break;
        case RS2_L500_VISUAL_PRESET_LOW_AMBIENT:
            _ambient_light->set_with_no_signal(RS2_AMBIENT_LIGHT_LOW_AMBIENT);
            set_max_laser();
            break;
        case RS2_L500_VISUAL_PRESET_MAX_RANGE:
            _ambient_light->set_with_no_signal(RS2_AMBIENT_LIGHT_NO_AMBIENT);
            set_max_laser();
            break;
        case RS2_L500_VISUAL_PRESET_SHORT_RANGE:
            _ambient_light->set_with_no_signal(RS2_AMBIENT_LIGHT_LOW_AMBIENT);
            break;
        case RS2_L500_VISUAL_PRESET_CUSTOM:
            move_to_custom();
            break;
        case RS2_L500_VISUAL_PRESET_DEFAULT:
            LOG_ERROR("L515 Visual Preset option cannot be changed to Default");
            throw  invalid_value_exception(to_string() << "The Default preset signifies that the controls have not been changed \n"
                                                           "since initialization, the API does not support changing back to this state.\n"
                                                           "Please choose one of the other presets");
            break;
        default: break;
        };
    }

    void l500_options::move_to_custom ()
    {
        for (auto& o : _hw_options)
        {
            auto  val = o.second->query();
            o.second->set_with_no_signal(val);
        }
        _preset->set_with_no_signal(RS2_L500_VISUAL_PRESET_CUSTOM);
    }

    void l500_options::reset_hw_controls()
    {
        for (auto& o : _hw_options)
            o.second->set_with_no_signal(-1);
    }

    void l500_options::set_max_laser()
    {
        auto range = _hw_options[RS2_OPTION_LASER_POWER]->get_range();
        _hw_options[RS2_OPTION_LASER_POWER]->set_with_no_signal(range.max);
    }
}
<|endoftext|>


<commit_before>#ifndef STRING_UTILS_HPP_INCLUDED
#define STRING_UTILS_HPP_INCLUDED

/**
 @file string_utils.hpp
 @author François Becker

MIT License

Copyright (c) 2017 François Becker

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

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

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

#include <string>
#include <vector>
#include <sstream>

namespace fbu
{
    namespace string
    {
        //==============================================================================
        inline void find_and_replace(std::string& source, std::string const& find, std::string const& replace)
        {
            for(std::string::size_type i = 0; (i = source.find(find, i)) != std::string::npos;)
            {
                source.replace(i, find.length(), replace);
                i += replace.length();
            }
        }

        //==============================================================================
        inline std::vector<std::string> string_split(std::string pString, const char* pDelimiter)
        {
            std::vector<std::string> strings;

            std::string::size_type pos = 0;
            std::string::size_type prev = 0;
            while ((pos = pString.find(pDelimiter, prev)) != std::string::npos)
            {
                strings.push_back(pString.substr(prev, pos - prev));
                prev = pos + 1;
            }

            // To get the last substring (or only, if delimiter is not found)
            strings.push_back(pString.substr(prev));

            return strings;
        }

        //==============================================================================
        template<typename T>
        const std::string convert_to_string(const T &v)
        {
            std::ostringstream ss;
            ss << v;
            return ss.str();
        };

        //==============================================================================
        inline bool hasEnding(const std::string& fullString, const std::string& ending)
        {
            return (fullString.length() >= ending.length())
            && (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending));
        }

        //==============================================================================
        inline std::string removeEnding(const std::string& pString, const std::string& pEnding)
        {
            size_t lFound = pString.rfind(pEnding);
            if (lFound != std::string::npos)
            {
                std::string lCopy(pString);
                return lCopy.erase(lFound);
            }
            return pString;
        }

#if FBU_UNIT_TESTS
        // TODO: move this to a unit test file
        static struct c_ut
        {
            c_ut()
            {
                assert(removeEnding("aaaaa.bbb", ".bbb") == "aaaaa");
                assert(removeEnding("aaaaa.bbb", ".ccc") == "aaaaa.bbb");
            }
        } ut;
#endif
    }
}

#endif
<commit_msg>string_utils.hpp: added fbu::string::string_split()<commit_after>#ifndef STRING_UTILS_HPP_INCLUDED
#define STRING_UTILS_HPP_INCLUDED

/**
 @file string_utils.hpp
 @author François Becker

MIT License

Copyright (c) 2017 François Becker

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

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

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

#include <string>
#include <vector>
#include <sstream>

namespace fbu
{
    namespace string
    {
        //==============================================================================
        inline void find_and_replace(std::string& source, std::string const& find, std::string const& replace)
        {
            for(std::string::size_type i = 0; (i = source.find(find, i)) != std::string::npos;)
            {
                source.replace(i, find.length(), replace);
                i += replace.length();
            }
        }

        inline std::vector<std::string> string_split(const std::string& pString, char pSplitChar)
        {
            std::istringstream split(pString);
            std::vector<std::string> tokens;
            for (std::string each; std::getline(split, each, pSplitChar); tokens.push_back(each));

            return tokens;
        }

        //==============================================================================
        inline std::vector<std::string> string_split(std::string pString, const char* pDelimiter)
        {
            std::vector<std::string> strings;

            std::string::size_type pos = 0;
            std::string::size_type prev = 0;
            while ((pos = pString.find(pDelimiter, prev)) != std::string::npos)
            {
                strings.push_back(pString.substr(prev, pos - prev));
                prev = pos + 1;
            }

            // To get the last substring (or only, if delimiter is not found)
            strings.push_back(pString.substr(prev));

            return strings;
        }

        //==============================================================================
        template<typename T>
        const std::string convert_to_string(const T &v)
        {
            std::ostringstream ss;
            ss << v;
            return ss.str();
        };

        //==============================================================================
        inline bool hasEnding(const std::string& fullString, const std::string& ending)
        {
            return (fullString.length() >= ending.length())
            && (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending));
        }

        //==============================================================================
        inline std::string removeEnding(const std::string& pString, const std::string& pEnding)
        {
            size_t lFound = pString.rfind(pEnding);
            if (lFound != std::string::npos)
            {
                std::string lCopy(pString);
                return lCopy.erase(lFound);
            }
            return pString;
        }

#if FBU_UNIT_TESTS
        // TODO: move this to a unit test file
        static struct c_ut
        {
            c_ut()
            {
                assert(removeEnding("aaaaa.bbb", ".bbb") == "aaaaa");
                assert(removeEnding("aaaaa.bbb", ".ccc") == "aaaaa.bbb");
            }
        } ut;
#endif
    }
}

#endif
<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_DEBUG_HPP_INCLUDED
#define TORRENT_DEBUG_HPP_INCLUDED

#ifdef TORRENT_DEBUG

#include <string>
#include "libtorrent/config.hpp"

#if TORRENT_USE_IOSTREAM
#include <fstream>
#include <iostream>
#endif

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/lexical_cast.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/convenience.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

namespace libtorrent
{
	// DEBUG API

	namespace fs = boost::filesystem;

	struct logger
	{
		logger(fs::path const& logpath, fs::path const& filename, int instance, bool append = true)
		{
#if TORRENT_USE_IOSTREAM

#ifndef BOOST_NO_EXCEPTIONS
			try
			{
#endif
				fs::path dir(fs::complete(logpath / ("libtorrent_logs" + boost::lexical_cast<std::string>(instance))));
				if (!fs::exists(dir)) fs::create_directories(dir);
				m_file.open((dir / filename).string().c_str(), std::ios_base::out | (append ? std::ios_base::app : std::ios_base::out));
				*this << "\n\n\n*** starting log ***\n";
#ifndef BOOST_NO_EXCEPTIONS
			}
			catch (std::exception& e)
			{
				std::cerr << "failed to create log '" << filename.string() << "': " << e.what() << std::endl;
			}
#endif
#endif
		}

		template <class T>
		logger& operator<<(T const& v)
		{
#if TORRENT_USE_IOSTREAM
			m_file << v;
			m_file.flush();
#endif
			return *this;
		}

#if TORRENT_USE_IOSTREAM
		std::ofstream m_file;
#endif
	};

}
#endif // TORRENT_DEBUG

#endif // TORRENT_DEBUG_HPP_INCLUDED

<commit_msg>fix release logging build<commit_after>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_DEBUG_HPP_INCLUDED
#define TORRENT_DEBUG_HPP_INCLUDED

#include <string>
#include "libtorrent/config.hpp"

#if TORRENT_USE_IOSTREAM
#include <fstream>
#include <iostream>
#endif

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/lexical_cast.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/convenience.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

namespace libtorrent
{
	// DEBUG API

	namespace fs = boost::filesystem;

	struct logger
	{
		logger(fs::path const& logpath, fs::path const& filename, int instance, bool append = true)
		{
#if TORRENT_USE_IOSTREAM

#ifndef BOOST_NO_EXCEPTIONS
			try
			{
#endif
				fs::path dir(fs::complete(logpath / ("libtorrent_logs" + boost::lexical_cast<std::string>(instance))));
				if (!fs::exists(dir)) fs::create_directories(dir);
				m_file.open((dir / filename).string().c_str(), std::ios_base::out | (append ? std::ios_base::app : std::ios_base::out));
				*this << "\n\n\n*** starting log ***\n";
#ifndef BOOST_NO_EXCEPTIONS
			}
			catch (std::exception& e)
			{
				std::cerr << "failed to create log '" << filename.string() << "': " << e.what() << std::endl;
			}
#endif
#endif
		}

		template <class T>
		logger& operator<<(T const& v)
		{
#if TORRENT_USE_IOSTREAM
			m_file << v;
			m_file.flush();
#endif
			return *this;
		}

#if TORRENT_USE_IOSTREAM
		std::ofstream m_file;
#endif
	};

}

#endif // TORRENT_DEBUG_HPP_INCLUDED

<|endoftext|>


<commit_before>//=============================================================================================================
/**
* @file     test_fiff_cov.cpp
* @author   Lorenz Esch <lorenz.esch@tu-ilmenau.de>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     April, 2017
*
* @section  LICENSE
*
* Copyright (C) 2017, Lorenz Esch and Matti Hamalainen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
*       following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
*       the following disclaimer in the documentation and/or other materials provided with the distribution.
*     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
*       to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* @brief    Test for I/O of a FiffCov
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include <fiff/fiff_cov.h>

#include <iostream>
#include <utils/ioutils.h>

//*************************************************************************************************************
//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QtTest>

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace FIFFLIB;
using namespace UTILSLIB;

//=============================================================================================================
/**
* DECLARE CLASS TestFiffCov
*
* @brief The TestFiffCov class provides covariance reading verification tests
*
*/
class TestFiffCov: public QObject
{
    Q_OBJECT

public:
    TestFiffCov();

private slots:
    void initTestCase();
    void compareData();
    void compareKind();
    void compareDiag();
    void compareDim();
    void compareNfree();
    void cleanupTestCase();

private:
    double epsilon;

    FiffCov covLoaded;
    FiffCov covResult;
};

//*************************************************************************************************************

TestFiffCov::TestFiffCov()
: epsilon(0.000001)
{
}

//*************************************************************************************************************

void TestFiffCov::initTestCase()
{
    qDebug() << "Epsilon" << epsilon;

    //Read the results produced with MNE-CPP
    QFile t_fileIn(QDir::currentPath()+"/mne-cpp-test-data/MEG/sample/sample_audvis-cov.fif");
    covLoaded = FiffCov(t_fileIn);

    //Read the result data produced with mne_matlab
    MatrixXd data;
    IOUtils::read_eigen_matrix(data, QDir::currentPath()+"/mne-cpp-test-data/Result/ref_data_sample_audvis-cov.dat");
    covResult.data = data;

    covResult.kind = 1;
    covResult.diag = 0;
    covResult.dim = 366;
    covResult.nfree = 15972;

}

//*************************************************************************************************************

void TestFiffCov::compareData()
{
    //Make the values a little bit bigger
    MatrixXd data_diff = covResult.data*1000000 - covLoaded.data*1000000;

//    qDebug()<<"abs(covResult.data.sum()) "<<covResult.data.normalized().sum();
//    qDebug()<<"abs(covLoaded.data.sum()) "<<covLoaded.data.normalized().sum();
//    qDebug()<<"abs(data_diff.sum()) "<<abs(data_diff.sum());
//    qDebug()<<"epsilon "<<epsilon;

    QVERIFY( std::abs(data_diff.sum()) < epsilon );
}

//*************************************************************************************************************

void TestFiffCov::compareKind()
{
    QVERIFY( covResult.kind == covLoaded.kind );
}

//*************************************************************************************************************

void TestFiffCov::compareDiag()
{
    QVERIFY( covResult.diag == covLoaded.diag );
}

//*************************************************************************************************************

void TestFiffCov::compareDim()
{
    QVERIFY( covResult.dim == covLoaded.dim );
}

//*************************************************************************************************************

void TestFiffCov::compareNfree()
{
    QVERIFY( covResult.nfree == covLoaded.nfree );
}

//*************************************************************************************************************

void TestFiffCov::cleanupTestCase()
{
}

//*************************************************************************************************************
//=============================================================================================================
// MAIN
//=============================================================================================================

QTEST_APPLESS_MAIN(TestFiffCov)
#include "test_fiff_cov.moc"
<commit_msg>Changed file paths in test_fiff_cov.cpp to applicationDirPath<commit_after>//=============================================================================================================
/**
* @file     test_fiff_cov.cpp
* @author   Lorenz Esch <lorenz.esch@tu-ilmenau.de>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     April, 2017
*
* @section  LICENSE
*
* Copyright (C) 2017, Lorenz Esch and Matti Hamalainen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
*       following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
*       the following disclaimer in the documentation and/or other materials provided with the distribution.
*     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
*       to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* @brief    Test for I/O of a FiffCov
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include <fiff/fiff_cov.h>

#include <iostream>
#include <utils/ioutils.h>

//*************************************************************************************************************
//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QtTest>

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace FIFFLIB;
using namespace UTILSLIB;

//=============================================================================================================
/**
* DECLARE CLASS TestFiffCov
*
* @brief The TestFiffCov class provides covariance reading verification tests
*
*/
class TestFiffCov: public QObject
{
    Q_OBJECT

public:
    TestFiffCov();

private slots:
    void initTestCase();
    void compareData();
    void compareKind();
    void compareDiag();
    void compareDim();
    void compareNfree();
    void cleanupTestCase();

private:
    double epsilon;

    FiffCov covLoaded;
    FiffCov covResult;
};

//*************************************************************************************************************

TestFiffCov::TestFiffCov()
: epsilon(0.000001)
{
}

//*************************************************************************************************************

void TestFiffCov::initTestCase()
{
    qDebug() << "Epsilon" << epsilon;

    //Read the results produced with MNE-CPP
    QFile t_fileIn(QCoreApplication::applicationDirPath()+"/MNE-sample-data/MEG/sample/sample_audvis-cov.fif");
    covLoaded = FiffCov(t_fileIn);

    //Read the result data produced with mne_matlab
    MatrixXd data;
    IOUtils::read_eigen_matrix(data, QCoreApplication::applicationDirPath()+"/mne-cpp-test-data/Result/ref_data_sample_audvis-cov.dat");
    covResult.data = data;

    covResult.kind = 1;
    covResult.diag = 0;
    covResult.dim = 366;
    covResult.nfree = 15972;

}

//*************************************************************************************************************

void TestFiffCov::compareData()
{
    //Make the values a little bit bigger
    MatrixXd data_diff = covResult.data*1000000 - covLoaded.data*1000000;

//    qDebug()<<"abs(covResult.data.sum()) "<<covResult.data.normalized().sum();
//    qDebug()<<"abs(covLoaded.data.sum()) "<<covLoaded.data.normalized().sum();
//    qDebug()<<"abs(data_diff.sum()) "<<abs(data_diff.sum());
//    qDebug()<<"epsilon "<<epsilon;

    QVERIFY( std::abs(data_diff.sum()) < epsilon );
}

//*************************************************************************************************************

void TestFiffCov::compareKind()
{
    QVERIFY( covResult.kind == covLoaded.kind );
}

//*************************************************************************************************************

void TestFiffCov::compareDiag()
{
    QVERIFY( covResult.diag == covLoaded.diag );
}

//*************************************************************************************************************

void TestFiffCov::compareDim()
{
    QVERIFY( covResult.dim == covLoaded.dim );
}

//*************************************************************************************************************

void TestFiffCov::compareNfree()
{
    QVERIFY( covResult.nfree == covLoaded.nfree );
}

//*************************************************************************************************************

void TestFiffCov::cleanupTestCase()
{
}

//*************************************************************************************************************
//=============================================================================================================
// MAIN
//=============================================================================================================

QTEST_APPLESS_MAIN(TestFiffCov)
#include "test_fiff_cov.moc"
<|endoftext|>