<commit_before>#include <WinSock2.h>
#include <WS2tcpip.h>
#include <Windows.h>

#include "AimpHTTP.h"
#include "AIMPSoundcloud.h"
#include "AIMPString.h"
#include "Tools.h"
#include <process.h>
#include "SDK/apiFileManager.h"

bool AimpHTTP::m_initialized = false;
IAIMPServiceHTTPClient *AimpHTTP::m_httpClient = nullptr;
std::set<AimpHTTP::EventListener *> AimpHTTP::m_handlers;

AimpHTTP::EventListener::EventListener(CallbackFunc callback, bool isFile) : m_isFileStream(isFile), m_callback(callback) {
    AimpHTTP::m_handlers.insert(this);
}

AimpHTTP::EventListener::~EventListener() {
    AimpHTTP::m_handlers.erase(this);
}

void WINAPI AimpHTTP::EventListener::OnAccept(IAIMPString *ContentType, const INT64 ContentSize, BOOL *Allow) {
    ContentType->AddRef();
    ContentType->Release();
    *Allow = AimpHTTP::m_initialized && Plugin::instance()->core();
}

void WINAPI AimpHTTP::EventListener::OnAcceptHeaders(IAIMPString *Header, BOOL *Allow) {
    Header->AddRef();
    Header->Release();
    *Allow = AimpHTTP::m_initialized && Plugin::instance()->core();
}

void WINAPI AimpHTTP::EventListener::OnComplete(IAIMPErrorInfo *ErrorInfo, BOOL Canceled) {
    if (m_stream) {
        if (AimpHTTP::m_initialized && Plugin::instance()->core()) {
            if (m_isFileStream) {
                m_stream->Release();
                if (m_callback)
                    m_callback(nullptr, 0);
                return;
            }

            if (m_callback || m_imageContainer) {
                int s = (int)m_stream->GetSize();
                unsigned char *buf = new unsigned char[s + 1];
                buf[s] = 0;
                m_stream->Seek(0, AIMP_STREAM_SEEKMODE_FROM_BEGINNING);
                m_stream->Read(buf, s);

                if (m_callback) {
                    m_callback(buf, s);
                } else if (m_imageContainer) {
                    if (s <= m_maxSize) {
                        (*m_imageContainer)->SetDataSize(s);
                        memcpy((*m_imageContainer)->GetData(), buf, s);
                    } else {
                        (*m_imageContainer)->Release();
                        *m_imageContainer = nullptr;
                    }
                }
                delete[] buf;
            }
        }
        m_stream->Release();
    }
}

void WINAPI AimpHTTP::EventListener::OnProgress(const INT64 Downloaded, const INT64 Total) {

}

bool AimpHTTP::Get(const std::wstring &url, CallbackFunc callback, bool synchronous) {
    if (!AimpHTTP::m_initialized || !Plugin::instance()->core())
        return false;

    EventListener *listener = new EventListener(callback);
    Plugin::instance()->core()->CreateObject(IID_IAIMPMemoryStream, reinterpret_cast<void **>(&(listener->m_stream)));

    return SUCCEEDED(m_httpClient->Get(AIMPString(url), synchronous ? AIMP_SERVICE_HTTPCLIENT_FLAGS_WAITFOR : 0, listener->m_stream, listener, 0, reinterpret_cast<void **>(&(listener->m_taskId))));
}

bool AimpHTTP::Download(const std::wstring &url, const std::wstring &destination, CallbackFunc callback) {
    if (!AimpHTTP::m_initialized || !Plugin::instance()->core())
        return false;

    EventListener *listener = new EventListener(callback, true);
    IAIMPServiceFileStreaming *fileStreaming = nullptr;
    if (SUCCEEDED(Plugin::instance()->core()->QueryInterface(IID_IAIMPServiceFileStreaming, reinterpret_cast<void **>(&fileStreaming)))) {
        fileStreaming->CreateStreamForFile(AIMPString(destination), AIMP_SERVICE_FILESTREAMING_FLAG_CREATENEW, -1, -1, &(listener->m_stream));
        fileStreaming->Release();
    }

    return SUCCEEDED(m_httpClient->Get(AIMPString(url), 0, listener->m_stream, listener, 0, reinterpret_cast<void **>(&(listener->m_taskId))));
}

bool AimpHTTP::DownloadImage(const std::wstring &url, IAIMPImageContainer **Image, int maxSize) {
    if (!AimpHTTP::m_initialized || !Plugin::instance()->core())
        return false;

    EventListener *listener = new EventListener(nullptr);
    Plugin::instance()->core()->CreateObject(IID_IAIMPMemoryStream, reinterpret_cast<void **>(&(listener->m_stream)));

    if (SUCCEEDED(Plugin::instance()->core()->CreateObject(IID_IAIMPImageContainer, reinterpret_cast<void **>(Image)))) {
        listener->m_imageContainer = Image;
        listener->m_maxSize = maxSize;

        return SUCCEEDED(m_httpClient->Get(AIMPString(url), AIMP_SERVICE_HTTPCLIENT_FLAGS_WAITFOR, listener->m_stream, listener, 0, reinterpret_cast<void **>(&(listener->m_taskId))));
    }
    return false;
}

bool AimpHTTP::Post(const std::wstring &url, const std::string &body, CallbackFunc callback, bool synchronous) {
    if (!AimpHTTP::m_initialized || !Plugin::instance()->core())
        return false;

    IAIMPStream *postData = nullptr;
    if (SUCCEEDED(Plugin::instance()->core()->CreateObject(IID_IAIMPMemoryStream, reinterpret_cast<void **>(&postData)))) {
        postData->Write((unsigned char *)(body.data()), body.size(), nullptr);

        EventListener *listener = new EventListener(callback);
        Plugin::instance()->core()->CreateObject(IID_IAIMPMemoryStream, reinterpret_cast<void **>(&(listener->m_stream)));

        bool ok = SUCCEEDED(m_httpClient->Post(AIMPString(url), synchronous ? AIMP_SERVICE_HTTPCLIENT_FLAGS_WAITFOR : 0, listener->m_stream, postData, listener, 0, reinterpret_cast<void **>(&(listener->m_taskId))));
        postData->Release();
        return ok;
    }
    return false;
}

bool AimpHTTP::Init(IAIMPCore *Core) {
    m_initialized = SUCCEEDED(Core->QueryInterface(IID_IAIMPServiceHTTPClient, reinterpret_cast<void **>(&m_httpClient)));

    return m_initialized;
}

void AimpHTTP::Deinit() {
    m_initialized = false;

    std::unordered_set<uintptr_t *> ids;
    for (auto x : m_handlers) ids.insert(x->m_taskId);
    for (auto x : ids) m_httpClient->Cancel(x, AIMP_SERVICE_HTTPCLIENT_FLAGS_WAITFOR);

    if (m_httpClient) {
        m_httpClient->Release();
        m_httpClient = nullptr;
    }
}

bool AimpHTTP::Put(const std::wstring &url, CallbackFunc callback) {
    return RawRequest("PUT", url, callback);
}

bool AimpHTTP::Delete(const std::wstring &url, CallbackFunc callback) {
    return RawRequest("DELETE", url, callback);
}

void AimpHTTP::RawRequestThread(void *args) {
    ThreadParams *params = static_cast<ThreadParams *>(args);
    std::string request = params->request;
    std::string host = params->host;
    AimpHTTP::CallbackFunc callback = params->callback;
    delete params;

    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        DebugA("WSAStartup failed.\n");
        return;
    }

    struct addrinfo hints;
    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_socktype = SOCK_STREAM;

    struct addrinfo *targetAdressInfo = NULL;
    DWORD getAddrRes = getaddrinfo(host.c_str(), NULL, &hints, &targetAdressInfo);
    if (getAddrRes != 0 || targetAdressInfo == NULL) {
        DebugA("Could not resolve the Host Name\n");
        WSACleanup();
        return;
    }

    SOCKADDR_IN sockAddr;
    sockAddr.sin_addr = ((struct sockaddr_in *)targetAdressInfo->ai_addr)->sin_addr;
    sockAddr.sin_family = AF_INET;
    sockAddr.sin_port = htons(80);
    freeaddrinfo(targetAdressInfo);

    SOCKET webSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (webSocket == INVALID_SOCKET) {
        DebugA("Creation of the Socket Failed\n");
        WSACleanup();
        return;
    }

    if (connect(webSocket, (SOCKADDR *)&sockAddr, sizeof(sockAddr)) != 0) {
        DebugA("Could not connect\n");
        closesocket(webSocket);
        WSACleanup();
        return;
    }

    const char *httpRequest = request.c_str();
    int sentBytes = send(webSocket, httpRequest, strlen(httpRequest), 0);
    if (sentBytes < (int)request.size() || sentBytes == SOCKET_ERROR) {
        DebugA("Could not send the request to the Server");
        closesocket(webSocket);
        WSACleanup();
        return;
    }

    char buffer[10240];
    ZeroMemory(buffer, sizeof(buffer));
    int dataLen;
    if ((dataLen = recv(webSocket, buffer, sizeof(buffer), 0) > 0)) {
        if (char *body = strstr(buffer, "\r\n\r\n")) {
            body += 4;
            if (callback && m_initialized && Plugin::instance()->core())
                callback(reinterpret_cast<unsigned char *>(body), strlen(body));
        }
    }

    closesocket(webSocket);
    WSACleanup();
};

bool AimpHTTP::RawRequest(const std::string &method, const std::wstring &url, CallbackFunc callback) {
    // Not perfect but does its job

    std::string narrow_url = Tools::ToString(url);
    const char *urlc = narrow_url.c_str();
    if (urlc = strstr(urlc, "://")) {
        urlc += 3;
        if (const char *request = strstr(urlc, "/")) {
            ThreadParams *p = new ThreadParams();
            p->request += method + " ";
            p->request += request;
            p->host = std::string(urlc, request);
            p->request += " HTTP/1.1\r\nHost: " + p->host + "\r\nConnection: close\r\n\r\n";
            p->callback = callback;

            HANDLE hThread = (HANDLE)_beginthread(AimpHTTP::RawRequestThread, 0, p);
            return hThread != INVALID_HANDLE_VALUE;
        }
    }
    return false;
}
<commit_msg>fixed from PVS-Studio:<commit_after>#include <WinSock2.h>
#include <WS2tcpip.h>
#include <Windows.h>

#include "AimpHTTP.h"
#include "AIMPSoundcloud.h"
#include "AIMPString.h"
#include "Tools.h"
#include <process.h>
#include "SDK/apiFileManager.h"

bool AimpHTTP::m_initialized = false;
IAIMPServiceHTTPClient *AimpHTTP::m_httpClient = nullptr;
std::set<AimpHTTP::EventListener *> AimpHTTP::m_handlers;

AimpHTTP::EventListener::EventListener(CallbackFunc callback, bool isFile) : m_isFileStream(isFile), m_callback(callback) {
    AimpHTTP::m_handlers.insert(this);
}

AimpHTTP::EventListener::~EventListener() {
    AimpHTTP::m_handlers.erase(this);
}

void WINAPI AimpHTTP::EventListener::OnAccept(IAIMPString *ContentType, const INT64 ContentSize, BOOL *Allow) {
    ContentType->AddRef();
    ContentType->Release();
    *Allow = AimpHTTP::m_initialized && Plugin::instance()->core();
}

void WINAPI AimpHTTP::EventListener::OnAcceptHeaders(IAIMPString *Header, BOOL *Allow) {
    Header->AddRef();
    Header->Release();
    *Allow = AimpHTTP::m_initialized && Plugin::instance()->core();
}

void WINAPI AimpHTTP::EventListener::OnComplete(IAIMPErrorInfo *ErrorInfo, BOOL Canceled) {
    if (m_stream) {
        if (AimpHTTP::m_initialized && Plugin::instance()->core()) {
            if (m_isFileStream) {
                m_stream->Release();
                if (m_callback)
                    m_callback(nullptr, 0);
                return;
            }

            if (m_callback || m_imageContainer) {
                int s = (int)m_stream->GetSize();
                unsigned char *buf = new unsigned char[s + 1];
                buf[s] = 0;
                m_stream->Seek(0, AIMP_STREAM_SEEKMODE_FROM_BEGINNING);
                m_stream->Read(buf, s);

                if (m_callback) {
                    m_callback(buf, s);
                } else if (m_imageContainer) {
                    if (s <= m_maxSize) {
                        (*m_imageContainer)->SetDataSize(s);
                        memcpy((*m_imageContainer)->GetData(), buf, s);
                    } else {
                        (*m_imageContainer)->Release();
                        *m_imageContainer = nullptr;
                    }
                }
                delete[] buf;
            }
        }
        m_stream->Release();
    }
}

void WINAPI AimpHTTP::EventListener::OnProgress(const INT64 Downloaded, const INT64 Total) {

}

bool AimpHTTP::Get(const std::wstring &url, CallbackFunc callback, bool synchronous) {
    if (!AimpHTTP::m_initialized || !Plugin::instance()->core())
        return false;

    EventListener *listener = new EventListener(callback);
    Plugin::instance()->core()->CreateObject(IID_IAIMPMemoryStream, reinterpret_cast<void **>(&(listener->m_stream)));

    return SUCCEEDED(m_httpClient->Get(AIMPString(url), synchronous ? AIMP_SERVICE_HTTPCLIENT_FLAGS_WAITFOR : 0, listener->m_stream, listener, 0, reinterpret_cast<void **>(&(listener->m_taskId))));
}

bool AimpHTTP::Download(const std::wstring &url, const std::wstring &destination, CallbackFunc callback) {
    if (!AimpHTTP::m_initialized || !Plugin::instance()->core())
        return false;

    EventListener *listener = new EventListener(callback, true);
    IAIMPServiceFileStreaming *fileStreaming = nullptr;
    if (SUCCEEDED(Plugin::instance()->core()->QueryInterface(IID_IAIMPServiceFileStreaming, reinterpret_cast<void **>(&fileStreaming)))) {
        fileStreaming->CreateStreamForFile(AIMPString(destination), AIMP_SERVICE_FILESTREAMING_FLAG_CREATENEW, -1, -1, &(listener->m_stream));
        fileStreaming->Release();
    }

    return SUCCEEDED(m_httpClient->Get(AIMPString(url), 0, listener->m_stream, listener, 0, reinterpret_cast<void **>(&(listener->m_taskId))));
}

bool AimpHTTP::DownloadImage(const std::wstring &url, IAIMPImageContainer **Image, int maxSize) {
    if (!AimpHTTP::m_initialized || !Plugin::instance()->core())
        return false;

    EventListener *listener = new EventListener(nullptr);
    Plugin::instance()->core()->CreateObject(IID_IAIMPMemoryStream, reinterpret_cast<void **>(&(listener->m_stream)));

    if (SUCCEEDED(Plugin::instance()->core()->CreateObject(IID_IAIMPImageContainer, reinterpret_cast<void **>(Image)))) {
        listener->m_imageContainer = Image;
        listener->m_maxSize = maxSize;

        return SUCCEEDED(m_httpClient->Get(AIMPString(url), AIMP_SERVICE_HTTPCLIENT_FLAGS_WAITFOR, listener->m_stream, listener, 0, reinterpret_cast<void **>(&(listener->m_taskId))));
    }
    return false;
}

bool AimpHTTP::Post(const std::wstring &url, const std::string &body, CallbackFunc callback, bool synchronous) {
    if (!AimpHTTP::m_initialized || !Plugin::instance()->core())
        return false;

    IAIMPStream *postData = nullptr;
    if (SUCCEEDED(Plugin::instance()->core()->CreateObject(IID_IAIMPMemoryStream, reinterpret_cast<void **>(&postData)))) {
        postData->Write((unsigned char *)(body.data()), body.size(), nullptr);

        EventListener *listener = new EventListener(callback);
        Plugin::instance()->core()->CreateObject(IID_IAIMPMemoryStream, reinterpret_cast<void **>(&(listener->m_stream)));

        bool ok = SUCCEEDED(m_httpClient->Post(AIMPString(url), synchronous ? AIMP_SERVICE_HTTPCLIENT_FLAGS_WAITFOR : 0, listener->m_stream, postData, listener, 0, reinterpret_cast<void **>(&(listener->m_taskId))));
        postData->Release();
        return ok;
    }
    return false;
}

bool AimpHTTP::Init(IAIMPCore *Core) {
    m_initialized = SUCCEEDED(Core->QueryInterface(IID_IAIMPServiceHTTPClient, reinterpret_cast<void **>(&m_httpClient)));

    return m_initialized;
}

void AimpHTTP::Deinit() {
    m_initialized = false;

    std::unordered_set<uintptr_t *> ids;
    for (auto x : m_handlers) ids.insert(x->m_taskId);
    for (auto x : ids) m_httpClient->Cancel(x, AIMP_SERVICE_HTTPCLIENT_FLAGS_WAITFOR);

    if (m_httpClient) {
        m_httpClient->Release();
        m_httpClient = nullptr;
    }
}

bool AimpHTTP::Put(const std::wstring &url, CallbackFunc callback) {
    return RawRequest("PUT", url, callback);
}

bool AimpHTTP::Delete(const std::wstring &url, CallbackFunc callback) {
    return RawRequest("DELETE", url, callback);
}

void AimpHTTP::RawRequestThread(void *args) {
    ThreadParams *params = static_cast<ThreadParams *>(args);
    std::string request = params->request;
    std::string host = params->host;
    AimpHTTP::CallbackFunc callback = params->callback;
    delete params;

    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        DebugA("WSAStartup failed.\n");
        return;
    }

    struct addrinfo hints;
    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_socktype = SOCK_STREAM;

    struct addrinfo *targetAdressInfo = NULL;
    DWORD getAddrRes = getaddrinfo(host.c_str(), NULL, &hints, &targetAdressInfo);
    if (getAddrRes != 0 || targetAdressInfo == NULL) {
        DebugA("Could not resolve the Host Name\n");
        WSACleanup();
        return;
    }

    SOCKADDR_IN sockAddr;
    sockAddr.sin_addr = ((struct sockaddr_in *)targetAdressInfo->ai_addr)->sin_addr;
    sockAddr.sin_family = AF_INET;
    sockAddr.sin_port = htons(80);
    freeaddrinfo(targetAdressInfo);

    SOCKET webSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (webSocket == INVALID_SOCKET) {
        DebugA("Creation of the Socket Failed\n");
        WSACleanup();
        return;
    }

    if (connect(webSocket, (SOCKADDR *)&sockAddr, sizeof(sockAddr)) != 0) {
        DebugA("Could not connect\n");
        closesocket(webSocket);
        WSACleanup();
        return;
    }

    const char *httpRequest = request.c_str();
    int sentBytes = send(webSocket, httpRequest, strlen(httpRequest), 0);
    if (sentBytes < (int)request.size() || sentBytes == SOCKET_ERROR) {
        DebugA("Could not send the request to the Server");
        closesocket(webSocket);
        WSACleanup();
        return;
    }

    char buffer[10240];
    ZeroMemory(buffer, sizeof(buffer));
    int dataLen;
    if ((dataLen = recv(webSocket, buffer, sizeof(buffer), 0)) > 0) {
        if (char *body = strstr(buffer, "\r\n\r\n")) {
            body += 4;
            if (callback && m_initialized && Plugin::instance()->core())
                callback(reinterpret_cast<unsigned char *>(body), strlen(body));
        }
    }

    closesocket(webSocket);
    WSACleanup();
};

bool AimpHTTP::RawRequest(const std::string &method, const std::wstring &url, CallbackFunc callback) {
    // Not perfect but does its job

    std::string narrow_url = Tools::ToString(url);
    const char *urlc = narrow_url.c_str();
    if (urlc = strstr(urlc, "://")) {
        urlc += 3;
        if (const char *request = strstr(urlc, "/")) {
            ThreadParams *p = new ThreadParams();
            p->request += method + " ";
            p->request += request;
            p->host = std::string(urlc, request);
            p->request += " HTTP/1.1\r\nHost: " + p->host + "\r\nConnection: close\r\n\r\n";
            p->callback = callback;

            HANDLE hThread = (HANDLE)_beginthread(AimpHTTP::RawRequestThread, 0, p);
            return hThread != INVALID_HANDLE_VALUE;
        }
    }
    return false;
}
<|endoftext|>


<commit_before>/*
    Copyright (C) 2001 by W.C.A. Wijngaards

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

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

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"
#include "genmaze.h"

csGenMaze::csGenMaze(int w, int h)
{
  width = w;
  height = h;
  maze = new csGenMazeNode [width*height];
  straightness = 0.5;
  cyclicalness = 0.1;
  InitMaze();
}

csGenMaze::~csGenMaze()
{
  delete[] maze;
}

void csGenMaze::InitMaze()
{
  for(int y=0; y<height; y++)
    for(int x=0; x<height; x++)
    {
      GetNode(x,y).visited = false;
      for(int i=0; i<4; i++)
        GetNode(x,y).opening[i] = false;
    }
}

void csGenMaze::MakeAccess(int x, int y)
{
  if(x==0) GetNode(x,y).opening[3] = true;
  if(y==0) GetNode(x,y).opening[0] = true;
  if(x==width-1) GetNode(x,y).opening[1] = true;
  if(y==height-1) GetNode(x,y).opening[2] = true;
}

void csGenMaze::GenerateMaze(int x, int y)
{
  srand(time(0));
  int direction = int(float(rand()+1)/RAND_MAX*4.0);
  VisitNode(x, y, direction);
}

void csGenMaze::VisitNode(int x, int y, int direction)
{
  /// generate an order in which to test the neighbours.
  int order[4];
  GenOrder(order, direction);
  GetNode(x,y).visited = true;
  /// take each direction and go there...
  for(int i=0; i<4; i++)
  {
    int nx, ny;
    GetNeighbor(order[i], x, y, nx, ny);
    /// don't go outside the map
    if( nx < 0 || nx >=width || ny < 0 || ny >=height )
      continue;
    /// been there?
    if(GetNode(nx,ny).visited)
    {
      // avoid the cycle?
      if( (1.0+rand())/RAND_MAX > cyclicalness )
        continue;
    }
    /// make opening
    MakeOpening(x, y, nx, ny);
    /// visit that neightbor
    if(GetNode(nx, ny).visited) continue;
    VisitNode(nx, ny, order[i]);
  }
}

void csGenMaze::GenOrder(int order[4], int direction)
{
  CS_ASSERT( direction >= 0 && direction < 4);
  bool done[4];
  int i;
  for(int i=0; i<4; i++) done[i] = false;
  i=0;
  if( float(rand()+1)/RAND_MAX < straightness)
  {
    i=1;
    order[0] = direction;
    done[direction] = true;
  }
  for(;i<4; i++)
  {
    /// skip from 0 ... 4-i-1
    int skip = int(float(rand()+1)/RAND_MAX*(4-i));
    CS_ASSERT( skip >= 0 && skip <= 4-i-1 );
    /// find it
    int numskipped = 0;
    int found = 0;
    for(int k=0; k<4; k++)
    {
      if(!done[k])
      {
        numskipped++;
        if(numskipped == skip+1){ found = k; break; }
      }
    }
    /// store it;
    order[i] = found;
    done[found] = true;
  }

  CS_ASSERT(done[0] && done[1] && done[2] && done[3]);
}

void csGenMaze::GetNeighbor(int dir, int x, int y, int& nx, int& ny)
{
  nx = x; ny = y;
  switch(dir) {
    case 0: ny--; break;
    case 1: nx++; break;
    case 2: ny++; break;
    case 3: nx--; break;
  }
}

void csGenMaze::MakeOpening(int x1, int y1, int x2, int y2)
{
  if(x1==x2-1)
  {
    GetNode(x1,y1).opening[1] = true;
    GetNode(x2,y2).opening[3] = true;
    return;
  }
  if(x1==x2+1)
  {
    GetNode(x1,y1).opening[3] = true;
    GetNode(x2,y2).opening[1] = true;
    return;
  }
  if(y1==y2-1)
  {
    GetNode(x1,y1).opening[2] = true;
    GetNode(x2,y2).opening[0] = true;
    return;
  }
  if(y1==y2+1)
  {
    GetNode(x1,y1).opening[0] = true;
    GetNode(x2,y2).opening[2] = true;
    return;
  }
}

bool csGenMaze::Opening(int x1, int y1, int x2, int y2)
{
  if(x1==x2-1)
  {
    CS_ASSERT( GetNode(x1,y1).opening[1] == GetNode(x2,y2).opening[3]);
    return GetNode(x1,y1).opening[1];
  }
  if(x1==x2+1)
  {
    CS_ASSERT( GetNode(x1,y1).opening[3] == GetNode(x2,y2).opening[1]);
    return GetNode(x1,y1).opening[3];
  }
  if(y1==y2-1)
  {
    CS_ASSERT( GetNode(x1,y1).opening[2] == GetNode(x2,y2).opening[0]);
    return GetNode(x1,y1).opening[2];
  }
  if(y1==y2+1)
  {
    CS_ASSERT( GetNode(x1,y1).opening[0] == GetNode(x2,y2).opening[2]);
    return GetNode(x1,y1).opening[0];
  }
  /// unreachable
  CS_ASSERT(false);
  return false;
}
<commit_msg>More robust.<commit_after>/*
    Copyright (C) 2001 by W.C.A. Wijngaards

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

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

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"
#include "genmaze.h"

csGenMaze::csGenMaze(int w, int h)
{
  width = w;
  height = h;
  maze = new csGenMazeNode [width*height];
  straightness = 0.5;
  cyclicalness = 0.1;
  InitMaze();
}

csGenMaze::~csGenMaze()
{
  delete[] maze;
}

void csGenMaze::InitMaze()
{
  for(int y=0; y<height; y++)
    for(int x=0; x<height; x++)
    {
      GetNode(x,y).visited = false;
      for(int i=0; i<4; i++)
        GetNode(x,y).opening[i] = false;
    }
}

void csGenMaze::MakeAccess(int x, int y)
{
  if(x==0) GetNode(x,y).opening[3] = true;
  if(y==0) GetNode(x,y).opening[0] = true;
  if(x==width-1) GetNode(x,y).opening[1] = true;
  if(y==height-1) GetNode(x,y).opening[2] = true;
}

void csGenMaze::GenerateMaze(int x, int y)
{
  srand(time(0));
  int direction = int(float(rand()+1)/RAND_MAX*4.0);
  VisitNode(x, y, direction);
}

void csGenMaze::VisitNode(int x, int y, int direction)
{
  /// generate an order in which to test the neighbours.
  int order[4];
  GenOrder(order, direction);
  GetNode(x,y).visited = true;
  /// take each direction and go there...
  for(int i=0; i<4; i++)
  {
    int nx, ny;
    GetNeighbor(order[i], x, y, nx, ny);
    /// don't go outside the map
    if( nx < 0 || nx >=width || ny < 0 || ny >=height )
      continue;
    /// been there?
    if(GetNode(nx,ny).visited)
    {
      // avoid the cycle?
      if( (1.0+rand())/RAND_MAX > cyclicalness )
        continue;
    }
    /// make opening
    MakeOpening(x, y, nx, ny);
    /// visit that neightbor
    if(GetNode(nx, ny).visited) continue;
    VisitNode(nx, ny, order[i]);
  }
}

void csGenMaze::GenOrder(int order[4], int direction)
{
  CS_ASSERT( direction >= 0 && direction < 4);
  bool done[4];
  int i;
  for(int i=0; i<4; i++) done[i] = false;
  i=0;
  if( float(rand()+1)/RAND_MAX < straightness)
  {
    i=1;
    order[0] = direction;
    done[direction] = true;
  }
  for(;i<4; i++)
  {
    /// skip from 0 ... 4-i-1
    int skip = int(float(4-i)*float(rand()+1)/RAND_MAX);
    if(skip > 4-i-1) skip = 4-i-1;
    CS_ASSERT( skip >= 0 && skip <= 4-i-1 );
    /// find it
    int numskipped = 0;
    int found = 0;
    for(int k=0; k<4; k++)
    {
      if(!done[k])
      {
        numskipped++;
        if(numskipped == skip+1){ found = k; break; }
      }
    }
    /// store it;
    order[i] = found;
    done[found] = true;
  }

  CS_ASSERT(done[0] && done[1] && done[2] && done[3]);
}

void csGenMaze::GetNeighbor(int dir, int x, int y, int& nx, int& ny)
{
  nx = x; ny = y;
  switch(dir) {
    case 0: ny--; break;
    case 1: nx++; break;
    case 2: ny++; break;
    case 3: nx--; break;
  }
}

void csGenMaze::MakeOpening(int x1, int y1, int x2, int y2)
{
  if(x1==x2-1)
  {
    GetNode(x1,y1).opening[1] = true;
    GetNode(x2,y2).opening[3] = true;
    return;
  }
  if(x1==x2+1)
  {
    GetNode(x1,y1).opening[3] = true;
    GetNode(x2,y2).opening[1] = true;
    return;
  }
  if(y1==y2-1)
  {
    GetNode(x1,y1).opening[2] = true;
    GetNode(x2,y2).opening[0] = true;
    return;
  }
  if(y1==y2+1)
  {
    GetNode(x1,y1).opening[0] = true;
    GetNode(x2,y2).opening[2] = true;
    return;
  }
}

bool csGenMaze::Opening(int x1, int y1, int x2, int y2)
{
  if(x1==x2-1)
  {
    CS_ASSERT( GetNode(x1,y1).opening[1] == GetNode(x2,y2).opening[3]);
    return GetNode(x1,y1).opening[1];
  }
  if(x1==x2+1)
  {
    CS_ASSERT( GetNode(x1,y1).opening[3] == GetNode(x2,y2).opening[1]);
    return GetNode(x1,y1).opening[3];
  }
  if(y1==y2-1)
  {
    CS_ASSERT( GetNode(x1,y1).opening[2] == GetNode(x2,y2).opening[0]);
    return GetNode(x1,y1).opening[2];
  }
  if(y1==y2+1)
  {
    CS_ASSERT( GetNode(x1,y1).opening[0] == GetNode(x2,y2).opening[2]);
    return GetNode(x1,y1).opening[0];
  }
  /// unreachable
  CS_ASSERT(false);
  return false;
}
<|endoftext|>


<commit_before>void Rec(TString file="/Users/jklay/Projects/LHC/alice/work/beamtest07/Period_LHC07a_EMCAL.Run_000000518.Host_001.Seq_10.root")
{
  // Reconstruction of RAW data from the input file raw.root
  // Boris Polichtchouk, 31 Aug 2007

  AliCDBManager::Instance()->SetDefaultStorage("local://$ALICE_ROOT");
  AliCDBManager::Instance()->SetSpecificStorage("EMCAL/Calib/Data","local://");

  //AliLog::SetGlobalDebugLevel(2);

  AliReconstruction rec ;
  rec.SetOption("EMCAL","OldRCUFormat");
  rec.SetRunTracking("") ;
  rec.SetRunVertexFinder(kFALSE) ;
  rec.SetRunLocalReconstruction("EMCAL") ;
  rec.SetFillESD("EMCAL") ;

  rec.SetInput(file.Data());  // read RAW data

  rec.SetEventRange(0,10);
  rec.SetNumberOfEventsPerFile(-1);

  rec.Run();

}
<commit_msg>Modified to be used in trunk (Cynthia H.)<commit_after>void Rec(TString file="/scratch/alicehp2/commun/testbeam07/LHC07a_EMCAL/000000190/raw/07000000190001.10.root")
{

  // Modified for aliroot v4-13
  // Cynthia Hadjidakis, 30 May 2008
  // Reconstruction of RAW data from the input file raw.root
  // Boris Polichtchouk, 31 Aug 2007

  AliCDBManager::Instance()->SetDefaultStorage("local://$ALICE_ROOT");
  AliCDBManager::Instance()->SetSpecificStorage("EMCAL/Calib/Data","local://$ALICE_ROOT/EMCAL/beamtest07/");

  //AliLog::SetGlobalDebugLevel(2);
  AliMagFMaps* field = new AliMagFMaps("Maps","Maps", 2, 1., 10., 1);
  AliTracker::SetFieldMap(field,kFALSE);

  AliReconstruction rec ;
  rec.SetOption("EMCAL","OldRCUFormat");
  rec.SetRunQA(kFALSE);       // bug with QA
  rec.SetRunTracking("") ;
  rec.SetRunVertexFinder(kFALSE) ;
  rec.SetRunLocalReconstruction("EMCAL") ;
  rec.SetFillESD("EMCAL") ;

  rec.SetInput(file.Data());  // read RAW data

  rec.SetEventRange(0,-1);
  rec.SetNumberOfEventsPerFile(-1);
  rec.Run();

  delete rec;
  gObjectTable->Print();

}

<|endoftext|>


<commit_before>#include "Sound.h"
#include <alure/alure.h>
#include <map>
#include "ResourceManager.h"
#include <assert.h>
#include "Engine/Logging.h"

namespace Sound
{

const int CHUNK_LENGTH = 16386;

typedef std::map<std::string, ALuint> BufferMap;
BufferMap sounds;

int soundSourceCount;
ALuint* soundSources;
ALuint musicSource;
ALuint musicBufs[2];
alureStream* currentMusicStream = NULL;
std::string currentMusicName = "";
int soundSourceIndex = 0;

void DieUnpleasantly()
{
	StopMusic();
	alureShutdownDevice();
}

ALubyte* GetSoundData(const std::string& path, size_t& length)
{
	SDL_RWops* rwops = ResourceManager::OpenFile(path + ".aiff");
	if (!rwops)
		rwops = ResourceManager::OpenFile(path + ".ogg");
	if (!rwops)
	{
		length = 0;
		return NULL;
	}
	return (ALubyte*)ResourceManager::ReadFull(&length, rwops, 1);
}

static ALuint GetSound(const std::string& name)
{
	BufferMap::iterator iter = sounds.find(name);
	if (iter != sounds.end())
		return iter->second;
	size_t length;
	ALubyte* data = GetSoundData("Sounds/" + name, length);
	ALuint buf = alureCreateBufferFromMemory(data, length);
	free(data);
	sounds.insert(std::make_pair(name, buf));
	return buf;
}

void Init(int frequency, int resolution, int sources)
{
	(void)resolution;
	--sources; // one spare source for music
	ALCint attribs[] = {
		ALC_FREQUENCY, frequency,
		ALC_MONO_SOURCES, sources,
		ALC_STEREO_SOURCES, 1,
		0
	};
	alureInitDevice(NULL, attribs);
	soundSources = new ALuint[sources];
	alGenSources(sources, soundSources);
	alGenSources(1, &musicSource);
	//alGenBuffers(2, musicBufs);
	soundSourceCount = sources;
	atexit(DieUnpleasantly);
}

static ALuint GetFreeSource()
{
	int idx = soundSourceIndex++;
	soundSourceIndex = soundSourceIndex % soundSourceCount;
	return soundSources[idx];
}

void Preload(const std::string& name)
{
	GetSound(name);
}

void PlaySound(const std::string& name, float gain)
{
	ALuint buf    = GetSound(name);
	ALuint source = GetFreeSource();
	alSourcei(source, AL_BUFFER, buf);
	alSourcePlay(source);
}

static void MusicEndCallback(void* ud, ALuint source)
{
	alureDestroyStream(currentMusicStream, 2, musicBufs);
	currentMusicStream = NULL;
	currentMusicName = "";
	free(ud);
}

void PlayMusic(const std::string& name)
{
	if (currentMusicStream)
		alureStopSource(musicSource, AL_TRUE);
	size_t length;
	ALubyte* data = GetSoundData("Music/" + name, length);
	currentMusicName = name;
	currentMusicStream = alureCreateStreamFromStaticMemory(data, length, CHUNK_LENGTH, 2, musicBufs);
	alurePlaySourceStream(musicSource, currentMusicStream, 2, 1, MusicEndCallback, data);
	LOG("Sound", LOG_MESSAGE, "Music: %s", name.c_str());
	if (!data)
		LOG("Sound", LOG_WARNING, "failed to find music");
}

void StopMusic()
{
	if (!currentMusicStream)
		return;
	alureStopSource(musicSource, AL_TRUE);
}

std::string MusicName()
{
	return "";
}

float MusicVolume()
{
	return 1.0f;
}

void SetMusicVolume(float mvol)
{
}

float SoundVolume()
{
	return 1.0f;
}

void SetSoundVolume(float mvol)
{
}

}
<commit_msg>Made sound playing honour the volume parameter.<commit_after>#include "Sound.h"
#include <alure/alure.h>
#include <map>
#include "ResourceManager.h"
#include <assert.h>
#include "Engine/Logging.h"

namespace Sound
{

const int CHUNK_LENGTH = 16386;

typedef std::map<std::string, ALuint> BufferMap;
BufferMap sounds;

int soundSourceCount;
ALuint* soundSources;
ALuint musicSource;
ALuint musicBufs[2];
alureStream* currentMusicStream = NULL;
std::string currentMusicName = "";
int soundSourceIndex = 0;

void DieUnpleasantly()
{
	StopMusic();
	alureShutdownDevice();
}

ALubyte* GetSoundData(const std::string& path, size_t& length)
{
	SDL_RWops* rwops = ResourceManager::OpenFile(path + ".aiff");
	if (!rwops)
		rwops = ResourceManager::OpenFile(path + ".ogg");
	if (!rwops)
	{
		length = 0;
		return NULL;
	}
	return (ALubyte*)ResourceManager::ReadFull(&length, rwops, 1);
}

static ALuint GetSound(const std::string& name)
{
	BufferMap::iterator iter = sounds.find(name);
	if (iter != sounds.end())
		return iter->second;
	size_t length;
	ALubyte* data = GetSoundData("Sounds/" + name, length);
	ALuint buf = alureCreateBufferFromMemory(data, length);
	free(data);
	sounds.insert(std::make_pair(name, buf));
	return buf;
}

void Init(int frequency, int resolution, int sources)
{
	(void)resolution;
	--sources; // one spare source for music
	ALCint attribs[] = {
		ALC_FREQUENCY, frequency,
		ALC_MONO_SOURCES, sources,
		ALC_STEREO_SOURCES, 1,
		0
	};
	alureInitDevice(NULL, attribs);
	soundSources = new ALuint[sources];
	alGenSources(sources, soundSources);
	alGenSources(1, &musicSource);
	//alGenBuffers(2, musicBufs);
	soundSourceCount = sources;
	atexit(DieUnpleasantly);
}

static ALuint GetFreeSource()
{
	int idx = soundSourceIndex++;
	soundSourceIndex = soundSourceIndex % soundSourceCount;
	return soundSources[idx];
}

void Preload(const std::string& name)
{
	GetSound(name);
}

void PlaySound(const std::string& name, float gain)
{
	ALuint buf    = GetSound(name);
	ALuint source = GetFreeSource();
	alSourcei(source, AL_BUFFER, buf);
	alSourcef(source, AL_GAIN, gain);
	alSourcePlay(source);
}

static void MusicEndCallback(void* ud, ALuint source)
{
	alureDestroyStream(currentMusicStream, 2, musicBufs);
	currentMusicStream = NULL;
	currentMusicName = "";
	free(ud);
}

void PlayMusic(const std::string& name)
{
	if (currentMusicStream)
		alureStopSource(musicSource, AL_TRUE);
	size_t length;
	ALubyte* data = GetSoundData("Music/" + name, length);
	currentMusicName = name;
	currentMusicStream = alureCreateStreamFromStaticMemory(data, length, CHUNK_LENGTH, 2, musicBufs);
	alurePlaySourceStream(musicSource, currentMusicStream, 2, 1, MusicEndCallback, data);
	LOG("Sound", LOG_MESSAGE, "Music: %s", name.c_str());
	if (!data)
		LOG("Sound", LOG_WARNING, "failed to find music");
}

void StopMusic()
{
	if (!currentMusicStream)
		return;
	alureStopSource(musicSource, AL_TRUE);
}

std::string MusicName()
{
	return "";
}

float MusicVolume()
{
	return 1.0f;
}

void SetMusicVolume(float mvol)
{
}

float SoundVolume()
{
	return 1.0f;
}

void SetSoundVolume(float mvol)
{
}

}
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2007 Artem Pavlenko
 *
 * This library 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.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
// $Id$

#include "kismet_datasource.hpp"
#include "kismet_featureset.hpp"

// network
#include  <netdb.h>
#include  <arpa/inet.h>
#include  <netinet/in.h>
#include  <sys/socket.h>
#include  <sys/types.h>
#include  <sys/stat.h>
#include  <fcntl.h>
#include  <unistd.h>

// mapnik
#include <mapnik/ptree_helpers.hpp>

// boost
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/tokenizer.hpp>
#include <boost/bind.hpp>

#define MAX_TCP_BUFFER 4096 // maximum accepted TCP data block size

// If you change this also change the according sscanf line!
#define MAX_KISMET_LINE 1024 // maximum length of a kismet command (assumed)

using boost::lexical_cast;
using boost::bad_lexical_cast;

using mapnik::datasource;
using mapnik::parameters;

DATASOURCE_PLUGIN(kismet_datasource)

using mapnik::Envelope;
using mapnik::coord2d;
using mapnik::query;
using mapnik::featureset_ptr;
using mapnik::layer_descriptor;
using mapnik::attribute_descriptor;
using mapnik::datasource_exception;

using namespace std;

boost::mutex knd_list_mutex;
std::list<kismet_network_data> knd_list;
const unsigned int queue_size = 20;

kismet_datasource::kismet_datasource(parameters const& params)
   : datasource(params),
     extent_(),
     extent_initialized_(false),
     type_(datasource::Vector),
     desc_(*params.get<std::string>("type"),
     *params.get<std::string>("encoding","utf-8"))
{
    //cout << "kismet_datasource::kismet_datasource()" << endl;

    boost::optional<std::string> host = params.get<std::string>("host");
    if (!host) throw datasource_exception("missing <host> paramater");

    boost::optional<std::string> port = params.get<std::string>("port");
    if (!port) throw datasource_exception("missing <port> paramater");

    unsigned int portnr = atoi ((*port).c_str () );
    kismet_thread.reset (new boost::thread (boost::bind (&kismet_datasource::run, this, *host, portnr)));

    boost::optional<std::string> ext  = params_.get<std::string>("extent");
    if (ext)
    {
        boost::char_separator<char> sep(",");
        boost::tokenizer<boost::char_separator<char> > tok(*ext,sep);
        unsigned i = 0;
        bool success = false;
        double d[4];
        for (boost::tokenizer<boost::char_separator<char> >::iterator beg=tok.begin();
             beg!=tok.end();++beg)
        {
           try
           {
               d[i] = boost::lexical_cast<double>(*beg);
           }
           catch (boost::bad_lexical_cast & ex)
           {
              std::clog << ex.what() << "\n";
              break;
           }
           if (i==3)
           {
              success = true;
              break;
           }
           ++i;
        }
        if (success)
        {
           extent_.init(d[0],d[1],d[2],d[3]);
           extent_initialized_ = true;
        }
    }
}

kismet_datasource::~kismet_datasource()
{
}

std::string const kismet_datasource::name_="kismet";

std::string kismet_datasource::name()
{
   return name_;
}

int kismet_datasource::type() const
{
   return type_;
}

Envelope<double> kismet_datasource::envelope() const
{
   //cout << "kismet_datasource::envelope()" << endl;
   return extent_;
}

layer_descriptor kismet_datasource::get_descriptor() const
{
   return desc_;
}

featureset_ptr kismet_datasource::features(query const& q) const
{
    //cout << "kismet_datasource::features()" << endl;

    // TODO: use Envelope to filter bbox before adding to featureset_ptr
    //mapnik::Envelope<double> const& e = q.get_bbox();

    boost::mutex::scoped_lock lock(knd_list_mutex);
    return featureset_ptr (new kismet_featureset(knd_list, desc_.get_encoding()));

    // TODO: if illegal:
    // return featureset_ptr();
}

featureset_ptr kismet_datasource::features_at_point(coord2d const& pt) const
{
    //cout << "kismet_datasource::features_at_point()" << endl;

#if 0
   if (dataset_ && layer_)
   {
        OGRPoint point;
        point.setX (pt.x);
        point.setY (pt.y);

        layer_->SetSpatialFilter (&point);

        return featureset_ptr(new ogr_featureset(*dataset_, *layer_, desc_.get_encoding()));
   }
#endif

   return featureset_ptr();
}

void kismet_datasource::run (const std::string &ip_host, const unsigned int port)
{
  //cout << "+run" << endl;

  int                 sockfd, n;
  struct sockaddr_in  sock_addr;
  struct in_addr      inadr;
  struct hostent      *host;
  char                buffer[MAX_TCP_BUFFER]; // TCP data send from kismet_server
  string command;

  if (inet_aton(ip_host.c_str (), &inadr))
  {
    host = gethostbyaddr((char *) &inadr, sizeof(inadr), AF_INET);
  }
  else
  {
    host = gethostbyname(ip_host.c_str ());
  }

  if (host == NULL)
  {
    herror ("plugins/input/kismet: Error while searching host");
    return;
  }

  sock_addr.sin_family = AF_INET;
  sock_addr.sin_port   = htons(port);
  memcpy(&sock_addr.sin_addr, host->h_addr_list[0],
         sizeof(sock_addr.sin_addr));

  if ( (sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
  {
    cerr << "plugins/input/kismet: Error while creating socket" << endl;
    return;
  }

  if (connect(sockfd, (struct sockaddr *) &sock_addr, sizeof(sock_addr)))
  {
    cerr << "plugins/input/kismet: Error while connecting" << endl;
    return;
  }

  command = "!1 ENABLE NETWORK ssid,bssid,wep,bestlat,bestlon\n";

  if (write(sockfd, command.c_str (), command.length ()) != (signed) command.length ())
  {
    cerr << "plugins/input/kismet: Error sending command to " << ip_host << endl;
    close(sockfd);
    return;
  }

  char ssid[MAX_KISMET_LINE] = {};
  char bssid[MAX_KISMET_LINE] = {};
  double bestlat = 0;
  double bestlon = 0;
  int crypt = crypt_none;

  // BUG: if kismet_server is active sending after mapnik was killed and then restarted the
  // assert is called. Needs to be analyzed!
  while ( (n = read(sockfd, buffer, sizeof(buffer))) > 0)
  {
    assert (n < MAX_TCP_BUFFER);

    buffer[n] = '\0';
    string bufferObj (buffer); // TCP data send from kismet_server as STL string

    //cout << "BufferObj: " << endl << bufferObj << "[END]" << endl;

    string::size_type found = 0;
    string::size_type search_start = 0;
    string kismet_line; // contains a line from kismet_server
    do
    {
      found = bufferObj.find ('\n', search_start);
      if (found != string::npos)
      {
        kismet_line.assign (bufferObj, search_start, found - search_start);

        //cout << "Line: " << kismet_line << "[ENDL]" << endl;

        int param_number = 5; // the number of parameters to parse

        // Attention: string length specified to the constant!
        if (sscanf (kismet_line.c_str (), "*NETWORK: \001%1024[^\001]\001 %1024s %d %lf %lf", ssid, bssid, &crypt, &bestlat, &bestlon) == param_number)
        {
          //printf ("ssid=%s, bssid=%s, crypt=%d, bestlat=%f, bestlon=%f\n", ssid, bssid, crypt, bestlat, bestlon);

          kismet_network_data knd (ssid, bssid, bestlat, bestlon, crypt);

          boost::mutex::scoped_lock lock(knd_list_mutex);

          // the queue only grows to a max size
          if (knd_list.size () >= queue_size)
          {
            knd_list.pop_front ();
          }

          knd_list.push_back (knd);
        }
        else
        {
          // do nothing if not matched!
        }

        search_start = found + 1;
      }
    }
    while (found != string::npos);
  }

  if (n < 0)
  {
    cerr << "plugins/input/kismet: Error while reading from socket" << endl;
  }

  close(sockfd);

  //cout << "-run" << endl;
}
<commit_msg>add missing include<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2007 Artem Pavlenko
 *
 * This library 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.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
// $Id$

#include "kismet_datasource.hpp"
#include "kismet_featureset.hpp"

// network
#include  <netdb.h>
#include  <arpa/inet.h>
#include  <netinet/in.h>
#include  <sys/socket.h>
#include  <sys/types.h>
#include  <sys/stat.h>
#include  <fcntl.h>
#include  <unistd.h>
#include  <stdio.h>

// mapnik
#include <mapnik/ptree_helpers.hpp>

// boost
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/tokenizer.hpp>
#include <boost/bind.hpp>

#define MAX_TCP_BUFFER 4096 // maximum accepted TCP data block size

// If you change this also change the according sscanf line!
#define MAX_KISMET_LINE 1024 // maximum length of a kismet command (assumed)

using boost::lexical_cast;
using boost::bad_lexical_cast;

using mapnik::datasource;
using mapnik::parameters;

DATASOURCE_PLUGIN(kismet_datasource)

using mapnik::Envelope;
using mapnik::coord2d;
using mapnik::query;
using mapnik::featureset_ptr;
using mapnik::layer_descriptor;
using mapnik::attribute_descriptor;
using mapnik::datasource_exception;

using namespace std;

boost::mutex knd_list_mutex;
std::list<kismet_network_data> knd_list;
const unsigned int queue_size = 20;

kismet_datasource::kismet_datasource(parameters const& params)
   : datasource(params),
     extent_(),
     extent_initialized_(false),
     type_(datasource::Vector),
     desc_(*params.get<std::string>("type"),
     *params.get<std::string>("encoding","utf-8"))
{
    //cout << "kismet_datasource::kismet_datasource()" << endl;

    boost::optional<std::string> host = params.get<std::string>("host");
    if (!host) throw datasource_exception("missing <host> paramater");

    boost::optional<std::string> port = params.get<std::string>("port");
    if (!port) throw datasource_exception("missing <port> paramater");

    unsigned int portnr = atoi ((*port).c_str () );
    kismet_thread.reset (new boost::thread (boost::bind (&kismet_datasource::run, this, *host, portnr)));

    boost::optional<std::string> ext  = params_.get<std::string>("extent");
    if (ext)
    {
        boost::char_separator<char> sep(",");
        boost::tokenizer<boost::char_separator<char> > tok(*ext,sep);
        unsigned i = 0;
        bool success = false;
        double d[4];
        for (boost::tokenizer<boost::char_separator<char> >::iterator beg=tok.begin();
             beg!=tok.end();++beg)
        {
           try
           {
               d[i] = boost::lexical_cast<double>(*beg);
           }
           catch (boost::bad_lexical_cast & ex)
           {
              std::clog << ex.what() << "\n";
              break;
           }
           if (i==3)
           {
              success = true;
              break;
           }
           ++i;
        }
        if (success)
        {
           extent_.init(d[0],d[1],d[2],d[3]);
           extent_initialized_ = true;
        }
    }
}

kismet_datasource::~kismet_datasource()
{
}

std::string const kismet_datasource::name_="kismet";

std::string kismet_datasource::name()
{
   return name_;
}

int kismet_datasource::type() const
{
   return type_;
}

Envelope<double> kismet_datasource::envelope() const
{
   //cout << "kismet_datasource::envelope()" << endl;
   return extent_;
}

layer_descriptor kismet_datasource::get_descriptor() const
{
   return desc_;
}

featureset_ptr kismet_datasource::features(query const& q) const
{
    //cout << "kismet_datasource::features()" << endl;

    // TODO: use Envelope to filter bbox before adding to featureset_ptr
    //mapnik::Envelope<double> const& e = q.get_bbox();

    boost::mutex::scoped_lock lock(knd_list_mutex);
    return featureset_ptr (new kismet_featureset(knd_list, desc_.get_encoding()));

    // TODO: if illegal:
    // return featureset_ptr();
}

featureset_ptr kismet_datasource::features_at_point(coord2d const& pt) const
{
    //cout << "kismet_datasource::features_at_point()" << endl;

#if 0
   if (dataset_ && layer_)
   {
        OGRPoint point;
        point.setX (pt.x);
        point.setY (pt.y);

        layer_->SetSpatialFilter (&point);

        return featureset_ptr(new ogr_featureset(*dataset_, *layer_, desc_.get_encoding()));
   }
#endif

   return featureset_ptr();
}

void kismet_datasource::run (const std::string &ip_host, const unsigned int port)
{
  //cout << "+run" << endl;

  int                 sockfd, n;
  struct sockaddr_in  sock_addr;
  struct in_addr      inadr;
  struct hostent      *host;
  char                buffer[MAX_TCP_BUFFER]; // TCP data send from kismet_server
  string command;

  if (inet_aton(ip_host.c_str (), &inadr))
  {
    host = gethostbyaddr((char *) &inadr, sizeof(inadr), AF_INET);
  }
  else
  {
    host = gethostbyname(ip_host.c_str ());
  }

  if (host == NULL)
  {
    herror ("plugins/input/kismet: Error while searching host");
    return;
  }

  sock_addr.sin_family = AF_INET;
  sock_addr.sin_port   = htons(port);
  memcpy(&sock_addr.sin_addr, host->h_addr_list[0],
         sizeof(sock_addr.sin_addr));

  if ( (sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
  {
    cerr << "plugins/input/kismet: Error while creating socket" << endl;
    return;
  }

  if (connect(sockfd, (struct sockaddr *) &sock_addr, sizeof(sock_addr)))
  {
    cerr << "plugins/input/kismet: Error while connecting" << endl;
    return;
  }

  command = "!1 ENABLE NETWORK ssid,bssid,wep,bestlat,bestlon\n";

  if (write(sockfd, command.c_str (), command.length ()) != (signed) command.length ())
  {
    cerr << "plugins/input/kismet: Error sending command to " << ip_host << endl;
    close(sockfd);
    return;
  }

  char ssid[MAX_KISMET_LINE] = {};
  char bssid[MAX_KISMET_LINE] = {};
  double bestlat = 0;
  double bestlon = 0;
  int crypt = crypt_none;

  // BUG: if kismet_server is active sending after mapnik was killed and then restarted the
  // assert is called. Needs to be analyzed!
  while ( (n = read(sockfd, buffer, sizeof(buffer))) > 0)
  {
    assert (n < MAX_TCP_BUFFER);

    buffer[n] = '\0';
    string bufferObj (buffer); // TCP data send from kismet_server as STL string

    //cout << "BufferObj: " << endl << bufferObj << "[END]" << endl;

    string::size_type found = 0;
    string::size_type search_start = 0;
    string kismet_line; // contains a line from kismet_server
    do
    {
      found = bufferObj.find ('\n', search_start);
      if (found != string::npos)
      {
        kismet_line.assign (bufferObj, search_start, found - search_start);

        //cout << "Line: " << kismet_line << "[ENDL]" << endl;

        int param_number = 5; // the number of parameters to parse

        // Attention: string length specified to the constant!
        if (sscanf (kismet_line.c_str (), "*NETWORK: \001%1024[^\001]\001 %1024s %d %lf %lf", ssid, bssid, &crypt, &bestlat, &bestlon) == param_number)
        {
          //printf ("ssid=%s, bssid=%s, crypt=%d, bestlat=%f, bestlon=%f\n", ssid, bssid, crypt, bestlat, bestlon);

          kismet_network_data knd (ssid, bssid, bestlat, bestlon, crypt);

          boost::mutex::scoped_lock lock(knd_list_mutex);

          // the queue only grows to a max size
          if (knd_list.size () >= queue_size)
          {
            knd_list.pop_front ();
          }

          knd_list.push_back (knd);
        }
        else
        {
          // do nothing if not matched!
        }

        search_start = found + 1;
      }
    }
    while (found != string::npos);
  }

  if (n < 0)
  {
    cerr << "plugins/input/kismet: Error while reading from socket" << endl;
  }

  close(sockfd);

  //cout << "-run" << endl;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form under the terms of the GNU
 *    General Public License as published by the Free Software
 *    Foundation; either version 2 of the License, or (at your option)
 *    any later version.
 *
 *    This program 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 General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

# include  "config.h"
# include  "compiler.h"
# include  "netlist.h"
# include  "ivl_assert.h"

/*
 * NOTE: The name_ is perm-allocated by the caller.
 */
NetEvent::NetEvent(perm_string n)
: name_(n)
{
      scope_ = 0;
      snext_ = 0;
      probes_ = 0;
      trig_ = 0;
      waitref_ = 0;
      exprref_ = 0;
      wlist_ = 0;
}

NetEvent::~NetEvent()
{
      assert(waitref_ == 0);
      if (scope_) scope_->rem_event(this);
      while (probes_) {
	    NetEvProbe*tmp = probes_->enext_;
	    delete probes_;
	    probes_ = tmp;
      }
	/* name_ is lex_strings. */
}

perm_string NetEvent::name() const
{
      return name_;
}

NetScope* NetEvent::scope()
{
      assert(scope_);
      return scope_;
}

const NetScope* NetEvent::scope() const
{
      assert(scope_);
      return scope_;
}

unsigned NetEvent::nprobe() const
{
      unsigned cnt = 0;
      NetEvProbe*cur = probes_;
      while (cur) {
	    cnt += 1;
	    cur = cur->enext_;
      }

      return cnt;
}

NetEvProbe* NetEvent::probe(unsigned idx)
{
      NetEvProbe*cur = probes_;
      while (cur && idx) {
	    cur = cur->enext_;
	    idx -= 1;
      }
      return cur;
}

const NetEvProbe* NetEvent::probe(unsigned idx) const
{
      NetEvProbe*cur = probes_;
      while (cur && idx) {
	    cur = cur->enext_;
	    idx -= 1;
      }
      return cur;
}

unsigned NetEvent::ntrig() const
{
      unsigned cnt = 0;
      NetEvTrig*cur = trig_;
      while (cur) {
	    cnt += 1;
	    cur = cur->enext_;
      }

      return cnt;
}

unsigned NetEvent::nwait() const
{
      return waitref_;
}

unsigned NetEvent::nexpr() const
{
      return exprref_;
}

/*
 * A "similar" event is one that has an identical non-nil set of
 * probes.
 */
void NetEvent::find_similar_event(list<NetEvent*>&event_list)
{
      if (probes_ == 0)
	    return;

      set<NetEvent*> candidate_events;

	/* First, get a list of all the NetEvProbes that are connected
	   to my first probe. Then use that to create a set of
	   candidate events. These candidate events are a superset of
	   the similar events, so I will be culling this list later. */
      list<NetEvProbe*>first_probes;
      probes_->find_similar_probes(first_probes);

      for (list<NetEvProbe*>::iterator idx = first_probes.begin()
		 ; idx != first_probes.end() ; ++ idx ) {

	    candidate_events.insert( (*idx)->event() );
      }

      if (candidate_events.empty())
	    return;

	/* Now scan the remaining probes, in each case checking that
	   the probe event is a candidate event. After each iteration,
	   events that don't have a similar probe will be removed from
	   the candidate_events set. If the candidate_events set
	   becomes empty, then give up. */
      unsigned probe_count = 1;
      for (NetEvProbe*cur = probes_->enext_ ; cur;  cur = cur->enext_) {
	    list<NetEvProbe*>similar_probes;
	    cur->find_similar_probes(similar_probes);

	    set<NetEvent*> candidate_tmp;
	    for (list<NetEvProbe*>::iterator idx = similar_probes.begin()
		       ; idx != similar_probes.end() ; ++ idx ) {

		  NetEvent*tmp = (*idx)->event();
		  if (candidate_events.find(tmp) != candidate_events.end())
			candidate_tmp .insert(tmp);
	    }

	      // None of the candidate events match this probe? Give up!
	    if (candidate_tmp.empty())
		  return;

	    candidate_events = candidate_tmp;
	    probe_count += 1;
      }

        /* Scan the surviving candidate events. We know that they all
	   have probes that match the current event's probes. Check
	   for remaining compatibility details and save the survivors
	   in the event_list that the caller passed. */
      for (set<NetEvent*>::iterator idx = candidate_events.begin()
		 ; idx != candidate_events.end() ; ++ idx ) {

	    NetEvent*tmp = *idx;

	      // This shouldn't be possible?
	    if (tmp == this)
		  continue;

              /* For automatic tasks, the VVP runtime holds state for events
                 in the automatically allocated context. This means we can't
                 merge similar events in different automatic tasks. */
            if (scope()->is_auto() && (tmp->scope() != scope()))
                  continue;

	    unsigned tcnt = 0;
	    for (NetEvProbe*cur = tmp->probes_ ; cur ; cur = cur->enext_)
		  tcnt += 1;

	    if (tcnt == probe_count)
		  event_list .push_back(tmp);
      }

}

void NetEvent::replace_event(NetEvent*that)
{
      while (wlist_) {
	    wlist_->obj->replace_event(this, that);
      }
}

NexusSet* NetEvent::nex_async_()
{
	/* If there are behavioral trigger statements attached to me,
	   then this is not an asynchronous event. */
      if (trig_ != 0)
	    return 0;

      NexusSet*tmp = new NexusSet;
      for (NetEvProbe*cur = probes_ ;  cur != 0 ;  cur = cur->enext_) {
	    if (cur->edge() != NetEvProbe::ANYEDGE) {
		  delete tmp;
		  return 0;
	    }

	    for (unsigned idx = 0 ;  idx < cur->pin_count() ;  idx += 1) {
		  Nexus*nex = cur->pin(idx).nexus();
		  tmp->add(nex, 0, nex->vector_width());
	    }
      }

      return tmp;
}

NetEvTrig::NetEvTrig(NetEvent*ev)
: event_(ev)
{
      enext_ = event_->trig_;
      event_->trig_ = this;
}

NetEvTrig::~NetEvTrig()
{
      if (event_->trig_ == this) {
	    event_->trig_ = enext_;

      } else {
	    NetEvTrig*cur = event_->trig_;
	    while (cur->enext_ != this) {
		  assert(cur->enext_);
		  cur = cur->enext_;
	    }

	    cur->enext_ = this->enext_;
      }
}

const NetEvent* NetEvTrig::event() const
{
      return event_;
}

NetEvProbe::NetEvProbe(NetScope*s, perm_string n, NetEvent*tgt,
		       edge_t t, unsigned p)
: NetNode(s, n, p), event_(tgt), edge_(t)
{
      for (unsigned idx = 0 ;  idx < p ;  idx += 1) {
	    pin(idx).set_dir(Link::INPUT);
      }

      enext_ = event_->probes_;
      event_->probes_ = this;
}

NetEvProbe::~NetEvProbe()
{
      if (event_->probes_ == this) {
	    event_->probes_ = enext_;

      } else {
	    NetEvProbe*cur = event_->probes_;
	    while (cur->enext_ != this) {
		  assert(cur->enext_);
		  cur = cur->enext_;
	    }

	    cur->enext_ = this->enext_;
      }
}

NetEvProbe::edge_t NetEvProbe::edge() const
{
      return edge_;
}

NetEvent* NetEvProbe::event()
{
      return event_;
}

const NetEvent* NetEvProbe::event() const
{
      return event_;
}

/*
 * A similar NetEvProbe is one that is connected to all the same nexa
 * that this probe is connected to, and also is the same edge
 * type. Don't count myself as a similar probe.
 */
void NetEvProbe::find_similar_probes(list<NetEvProbe*>&plist)
{
      Nexus*nex = pin(0).nexus();

      for (Link*lcur = nex->first_nlink(); lcur; lcur = lcur->next_nlink()) {
	    NetPins*obj = lcur->get_obj();
	      // Skip NexusSet objects
	    if (obj == 0)
		  continue;

	    if (obj->pin_count() != pin_count())
		  continue;

	    NetEvProbe*tmp = dynamic_cast<NetEvProbe*>(obj);
	    if (tmp == 0)
		  continue;

	    if (tmp == this)
		  continue;

	    if (edge() != tmp->edge())
		  continue;

	    bool ok_flag = true;
	    for (unsigned idx = 1 ;  ok_flag && idx < pin_count() ;  idx += 1)
		  if (! pin(idx).is_linked(tmp->pin(idx)))
			ok_flag = false;

	    if (ok_flag == true)
		  plist .push_back(tmp);
      }
}

NetEvWait::NetEvWait(NetProc*pr)
: statement_(pr)
{
}

NetEvWait::~NetEvWait()
{
      if (! events_.empty()) {
	    for (unsigned idx = 0 ;  idx < events_.size() ;  idx += 1) {
		  NetEvent*tgt = events_[idx];
		  tgt->waitref_ -= 1;

		  struct NetEvent::wcell_*tmp = tgt->wlist_;
		  if (tmp->obj == this) {
			tgt->wlist_ = tmp->next;
			delete tmp;
		  } else {
			assert(tmp->next);
			while (tmp->next->obj != this) {
			      tmp = tmp->next;
			      assert(tmp->next);
			}
			tmp->next = tmp->next->next;
			delete tmp;
		  }
	    }
	    events_.clear();
      }
      delete statement_;
}

void NetEvWait::add_event(NetEvent*tgt)
{
	/* A wait fork is an empty event. */
      if (! tgt) {
	    assert(events_.empty());
	    events_.push_back(0);
	    return;
      }

      events_.push_back(tgt);

	// Remember to tell the NetEvent that there is someone
	// pointing to it.
      tgt->waitref_ += 1;

      struct NetEvent::wcell_*tmp = new NetEvent::wcell_;
      tmp->obj = this;
      tmp->next = tgt->wlist_;
      tgt->wlist_ = tmp;
}

void NetEvWait::replace_event(NetEvent*src, NetEvent*repl)
{
      unsigned idx;
      for (idx = 0 ;  idx < events_.size() ;  idx += 1) {
	    if (events_[idx] == src)
		  break;
      }

      assert(idx < events_.size());

	// First, remove me from the list held by the src NetEvent.
      assert(src->waitref_ > 0);
      src->waitref_ -= 1;
      struct NetEvent::wcell_*tmp = src->wlist_;
      if (tmp->obj == this) {
	    src->wlist_ = tmp->next;
	    delete tmp;
      } else {
	    assert(tmp->next);
	    while (tmp->next->obj != this) {
		  tmp = tmp->next;
		  assert(tmp->next);
	    }
	    tmp->next = tmp->next->next;
	    delete tmp;
      }

	// Replace the src pointer with the repl pointer.
      events_[idx] = repl;

	// Remember to tell the replacement NetEvent that there is
	// someone pointing to it.
      repl->waitref_ += 1;

      tmp = new NetEvent::wcell_;
      tmp->obj = this;
      tmp->next = repl->wlist_;
      repl->wlist_ = tmp;

}

NetProc* NetEvWait::statement()
{
      return statement_;
}
<commit_msg>Fix cleanup of NetEvWait class.<commit_after>/*
 * Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form under the terms of the GNU
 *    General Public License as published by the Free Software
 *    Foundation; either version 2 of the License, or (at your option)
 *    any later version.
 *
 *    This program 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 General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

# include  "config.h"
# include  "compiler.h"
# include  "netlist.h"
# include  "ivl_assert.h"

/*
 * NOTE: The name_ is perm-allocated by the caller.
 */
NetEvent::NetEvent(perm_string n)
: name_(n)
{
      scope_ = 0;
      snext_ = 0;
      probes_ = 0;
      trig_ = 0;
      waitref_ = 0;
      exprref_ = 0;
      wlist_ = 0;
}

NetEvent::~NetEvent()
{
      assert(waitref_ == 0);
      if (scope_) scope_->rem_event(this);
      while (probes_) {
	    NetEvProbe*tmp = probes_->enext_;
	    delete probes_;
	    probes_ = tmp;
      }
	/* name_ is lex_strings. */
}

perm_string NetEvent::name() const
{
      return name_;
}

NetScope* NetEvent::scope()
{
      assert(scope_);
      return scope_;
}

const NetScope* NetEvent::scope() const
{
      assert(scope_);
      return scope_;
}

unsigned NetEvent::nprobe() const
{
      unsigned cnt = 0;
      NetEvProbe*cur = probes_;
      while (cur) {
	    cnt += 1;
	    cur = cur->enext_;
      }

      return cnt;
}

NetEvProbe* NetEvent::probe(unsigned idx)
{
      NetEvProbe*cur = probes_;
      while (cur && idx) {
	    cur = cur->enext_;
	    idx -= 1;
      }
      return cur;
}

const NetEvProbe* NetEvent::probe(unsigned idx) const
{
      NetEvProbe*cur = probes_;
      while (cur && idx) {
	    cur = cur->enext_;
	    idx -= 1;
      }
      return cur;
}

unsigned NetEvent::ntrig() const
{
      unsigned cnt = 0;
      NetEvTrig*cur = trig_;
      while (cur) {
	    cnt += 1;
	    cur = cur->enext_;
      }

      return cnt;
}

unsigned NetEvent::nwait() const
{
      return waitref_;
}

unsigned NetEvent::nexpr() const
{
      return exprref_;
}

/*
 * A "similar" event is one that has an identical non-nil set of
 * probes.
 */
void NetEvent::find_similar_event(list<NetEvent*>&event_list)
{
      if (probes_ == 0)
	    return;

      set<NetEvent*> candidate_events;

	/* First, get a list of all the NetEvProbes that are connected
	   to my first probe. Then use that to create a set of
	   candidate events. These candidate events are a superset of
	   the similar events, so I will be culling this list later. */
      list<NetEvProbe*>first_probes;
      probes_->find_similar_probes(first_probes);

      for (list<NetEvProbe*>::iterator idx = first_probes.begin()
		 ; idx != first_probes.end() ; ++ idx ) {

	    candidate_events.insert( (*idx)->event() );
      }

      if (candidate_events.empty())
	    return;

	/* Now scan the remaining probes, in each case checking that
	   the probe event is a candidate event. After each iteration,
	   events that don't have a similar probe will be removed from
	   the candidate_events set. If the candidate_events set
	   becomes empty, then give up. */
      unsigned probe_count = 1;
      for (NetEvProbe*cur = probes_->enext_ ; cur;  cur = cur->enext_) {
	    list<NetEvProbe*>similar_probes;
	    cur->find_similar_probes(similar_probes);

	    set<NetEvent*> candidate_tmp;
	    for (list<NetEvProbe*>::iterator idx = similar_probes.begin()
		       ; idx != similar_probes.end() ; ++ idx ) {

		  NetEvent*tmp = (*idx)->event();
		  if (candidate_events.find(tmp) != candidate_events.end())
			candidate_tmp .insert(tmp);
	    }

	      // None of the candidate events match this probe? Give up!
	    if (candidate_tmp.empty())
		  return;

	    candidate_events = candidate_tmp;
	    probe_count += 1;
      }

        /* Scan the surviving candidate events. We know that they all
	   have probes that match the current event's probes. Check
	   for remaining compatibility details and save the survivors
	   in the event_list that the caller passed. */
      for (set<NetEvent*>::iterator idx = candidate_events.begin()
		 ; idx != candidate_events.end() ; ++ idx ) {

	    NetEvent*tmp = *idx;

	      // This shouldn't be possible?
	    if (tmp == this)
		  continue;

              /* For automatic tasks, the VVP runtime holds state for events
                 in the automatically allocated context. This means we can't
                 merge similar events in different automatic tasks. */
            if (scope()->is_auto() && (tmp->scope() != scope()))
                  continue;

	    unsigned tcnt = 0;
	    for (NetEvProbe*cur = tmp->probes_ ; cur ; cur = cur->enext_)
		  tcnt += 1;

	    if (tcnt == probe_count)
		  event_list .push_back(tmp);
      }

}

void NetEvent::replace_event(NetEvent*that)
{
      while (wlist_) {
	    wlist_->obj->replace_event(this, that);
      }
}

NexusSet* NetEvent::nex_async_()
{
	/* If there are behavioral trigger statements attached to me,
	   then this is not an asynchronous event. */
      if (trig_ != 0)
	    return 0;

      NexusSet*tmp = new NexusSet;
      for (NetEvProbe*cur = probes_ ;  cur != 0 ;  cur = cur->enext_) {
	    if (cur->edge() != NetEvProbe::ANYEDGE) {
		  delete tmp;
		  return 0;
	    }

	    for (unsigned idx = 0 ;  idx < cur->pin_count() ;  idx += 1) {
		  Nexus*nex = cur->pin(idx).nexus();
		  tmp->add(nex, 0, nex->vector_width());
	    }
      }

      return tmp;
}

NetEvTrig::NetEvTrig(NetEvent*ev)
: event_(ev)
{
      enext_ = event_->trig_;
      event_->trig_ = this;
}

NetEvTrig::~NetEvTrig()
{
      if (event_->trig_ == this) {
	    event_->trig_ = enext_;

      } else {
	    NetEvTrig*cur = event_->trig_;
	    while (cur->enext_ != this) {
		  assert(cur->enext_);
		  cur = cur->enext_;
	    }

	    cur->enext_ = this->enext_;
      }
}

const NetEvent* NetEvTrig::event() const
{
      return event_;
}

NetEvProbe::NetEvProbe(NetScope*s, perm_string n, NetEvent*tgt,
		       edge_t t, unsigned p)
: NetNode(s, n, p), event_(tgt), edge_(t)
{
      for (unsigned idx = 0 ;  idx < p ;  idx += 1) {
	    pin(idx).set_dir(Link::INPUT);
      }

      enext_ = event_->probes_;
      event_->probes_ = this;
}

NetEvProbe::~NetEvProbe()
{
      if (event_->probes_ == this) {
	    event_->probes_ = enext_;

      } else {
	    NetEvProbe*cur = event_->probes_;
	    while (cur->enext_ != this) {
		  assert(cur->enext_);
		  cur = cur->enext_;
	    }

	    cur->enext_ = this->enext_;
      }
}

NetEvProbe::edge_t NetEvProbe::edge() const
{
      return edge_;
}

NetEvent* NetEvProbe::event()
{
      return event_;
}

const NetEvent* NetEvProbe::event() const
{
      return event_;
}

/*
 * A similar NetEvProbe is one that is connected to all the same nexa
 * that this probe is connected to, and also is the same edge
 * type. Don't count myself as a similar probe.
 */
void NetEvProbe::find_similar_probes(list<NetEvProbe*>&plist)
{
      Nexus*nex = pin(0).nexus();

      for (Link*lcur = nex->first_nlink(); lcur; lcur = lcur->next_nlink()) {
	    NetPins*obj = lcur->get_obj();
	      // Skip NexusSet objects
	    if (obj == 0)
		  continue;

	    if (obj->pin_count() != pin_count())
		  continue;

	    NetEvProbe*tmp = dynamic_cast<NetEvProbe*>(obj);
	    if (tmp == 0)
		  continue;

	    if (tmp == this)
		  continue;

	    if (edge() != tmp->edge())
		  continue;

	    bool ok_flag = true;
	    for (unsigned idx = 1 ;  ok_flag && idx < pin_count() ;  idx += 1)
		  if (! pin(idx).is_linked(tmp->pin(idx)))
			ok_flag = false;

	    if (ok_flag == true)
		  plist .push_back(tmp);
      }
}

NetEvWait::NetEvWait(NetProc*pr)
: statement_(pr)
{
}

NetEvWait::~NetEvWait()
{
      if (! events_.empty()) {
	    for (unsigned idx = 0 ;  idx < events_.size() ;  idx += 1) {
		  NetEvent*tgt = events_[idx];
		  tgt->waitref_ -= 1;

		  struct NetEvent::wcell_*tmp = tgt->wlist_;
		  if (tmp->obj == this) {
			tgt->wlist_ = tmp->next;
			delete tmp;
		  } else {
			assert(tmp->next);
			while (tmp->next->obj != this) {
			      tmp = tmp->next;
			      assert(tmp->next);
			}
			tmp->next = tmp->next->next;
			delete tmp;
		  }
		  delete tgt;
	    }
	    events_.clear();
      }
      delete statement_;
}

void NetEvWait::add_event(NetEvent*tgt)
{
	/* A wait fork is an empty event. */
      if (! tgt) {
	    assert(events_.empty());
	    events_.push_back(0);
	    return;
      }

      events_.push_back(tgt);

	// Remember to tell the NetEvent that there is someone
	// pointing to it.
      tgt->waitref_ += 1;

      struct NetEvent::wcell_*tmp = new NetEvent::wcell_;
      tmp->obj = this;
      tmp->next = tgt->wlist_;
      tgt->wlist_ = tmp;
}

void NetEvWait::replace_event(NetEvent*src, NetEvent*repl)
{
      unsigned idx;
      for (idx = 0 ;  idx < events_.size() ;  idx += 1) {
	    if (events_[idx] == src)
		  break;
      }

      assert(idx < events_.size());

	// First, remove me from the list held by the src NetEvent.
      assert(src->waitref_ > 0);
      src->waitref_ -= 1;
      struct NetEvent::wcell_*tmp = src->wlist_;
      if (tmp->obj == this) {
	    src->wlist_ = tmp->next;
	    delete tmp;
      } else {
	    assert(tmp->next);
	    while (tmp->next->obj != this) {
		  tmp = tmp->next;
		  assert(tmp->next);
	    }
	    tmp->next = tmp->next->next;
	    delete tmp;
      }

	// Replace the src pointer with the repl pointer.
      events_[idx] = repl;

	// Remember to tell the replacement NetEvent that there is
	// someone pointing to it.
      repl->waitref_ += 1;

      tmp = new NetEvent::wcell_;
      tmp->obj = this;
      tmp->next = repl->wlist_;
      repl->wlist_ = tmp;

}

NetProc* NetEvWait::statement()
{
      return statement_;
}
<|endoftext|>


<commit_before>// FacilityModel.cpp
// Implements the FacilityModel class

#include "FacilityModel.h"

#include "Timer.h"
#include "BookKeeper.h"
#include "QueryEngine.h"
#include "InstModel.h"

#include <stdlib.h>
#include <sstream>
#include "Logger.h"
#include <limits>

using namespace std;

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FacilityModel::FacilityModel() :
  fac_lifetime_(numeric_limits<int>::max()),
  decommission_date_(numeric_limits<int>::max()) {
  setModelType("Facility");
  in_commods_ = std::vector<std::string>();
  out_commods_ = std::vector<std::string>();
};

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FacilityModel::~FacilityModel() {};

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FacilityModel::initCoreMembers(QueryEngine* qe) {
  Model::initCoreMembers(qe);

  // get lifetime
  try {
    setFacLifetime(atoi(qe->getElementContent("lifetime").c_str()));
  }
  catch (CycNullQueryException e) {
    setFacLifetime(TI->simDur());
  }

  // get the incommodities
  std::string commod;
  try {
    int numInCommod = qe->nElementsMatchingQuery("incommodity");
    for (int i=0;i<numInCommod;i++){
      commod = qe->getElementContent("incommodity",i);
      in_commods_.push_back(commod);
      LOG(LEV_DEBUG2, "none!") << "Facility " << ID() << " has just added incommodity" << commod;
    }
  }
  catch (CycNullQueryException e) {
  }

  // get the outcommodities
  try {
    int numOutCommod = qe->nElementsMatchingQuery("outcommodity");
    for (int i=0;i<numOutCommod;i++){
      commod = qe->getElementContent("outcommodity",i);
      out_commods_.push_back(commod);
      LOG(LEV_DEBUG2, "none!") << "Facility " << ID() << " has just added outcommodity" << commod;
    }
  }
  catch (CycNullQueryException e) {
  }
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Prototype* FacilityModel::clone() {
  FacilityModel* clone = dynamic_cast<FacilityModel*>(Model::constructModel(modelImpl()));
  clone->cloneCoreMembersFrom(this);
  clone->cloneModuleMembersFrom(this);
  clone->setBuildDate(TI->time());
  CLOG(LEV_DEBUG3) << clone->modelImpl() << " cloned: " << clone->str();
  CLOG(LEV_DEBUG3) << "               From: " << this->str();
  return clone;
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FacilityModel::cloneCoreMembersFrom(FacilityModel* source) {
  setName(source->name());
  setModelImpl(source->modelImpl());
  setModelType(source->modelType());
  setFacLifetime(source->facLifetime());
  in_commods_ = source->inputCommodities();
  out_commods_ = source->outputCommodities();
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FacilityModel::cloneModuleMembersFrom(FacilityModel* source) {}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
std::string FacilityModel::str() {
  stringstream ss("");
  ss << Model::str() << " with: "
     << " lifetime: " << facLifetime()
     << " build date: " << build_date_
     << " decommission date: " << decommission_date_;
  return ss.str();
};

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
InstModel* FacilityModel::facInst() {
  return dynamic_cast<InstModel*>( parent() );
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FacilityModel::handleTick(int time){
  // facilities should override this method, unless they're very naiive.
  // generally, a facility's handleTick() behavior should be to
  // offer an amount of its output material equal to its capacity
  // and to request an amount of raw material also equal to its capacity.
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FacilityModel::handleTock(int time){
  // facilities should override this method, unless they're very naiive.
  // generally, a faility's handleTock() behavior should be to
  // process any orders passed down from the market,
  // send the appropriate materials,
  // receive any materials the market has found a source for,
  // and record all material transfers.
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FacilityModel::handleDailyTasks(int time, int day){
  // facilities who have more intricate details should utilize this function
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FacilityModel::decommission() {
  if (!checkDecommissionCondition())
    throw CycOverrideException("Cannot decommission " + name());

  CLOG(LEV_INFO3) << name() << " is being decommissioned";
  deleteModel(this);
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FacilityModel::checkDecommissionCondition() {
  return true;
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
std::vector<std::string> FacilityModel::inputCommodities() {
  return in_commods_;
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
std::vector<std::string> FacilityModel::outputCommodities() {
  return out_commods_;
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FacilityModel::lifetimeReached() {
  return (TI->time() >= decommission_date_);
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FacilityModel::setBuildDate(int current_time) {
  build_date_ = current_time;
  setDecommissionDate(build_date_ + fac_lifetime_ - 1); // -1 because you want the decommission to occur on the previous time's tock
  CLOG(LEV_DEBUG3) << name() << " has set its time-related members: ";
  CLOG(LEV_DEBUG3) << " * lifetime: " << fac_lifetime_;
  CLOG(LEV_DEBUG3) << " * build date: " << build_date_;
  CLOG(LEV_DEBUG3) << " * decommisison date: " << decommission_date_;
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FacilityModel::setDecommissionDate(int time) {
  double current_time = TI->time();
  double final_time = TI->finalTime();
  if (time + current_time < final_time)
    {
      decommission_date_ = time;
    }
  else
    {
      decommission_date_ = final_time;
    }
}
<commit_msg>fixed an issue where the decommission date was not being set correctly<commit_after>// FacilityModel.cpp
// Implements the FacilityModel class

#include "FacilityModel.h"

#include "Timer.h"
#include "BookKeeper.h"
#include "QueryEngine.h"
#include "InstModel.h"

#include <stdlib.h>
#include <sstream>
#include "Logger.h"
#include <limits>

using namespace std;

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FacilityModel::FacilityModel() :
  fac_lifetime_(numeric_limits<int>::max()),
  decommission_date_(numeric_limits<int>::max()) {
  setModelType("Facility");
  in_commods_ = std::vector<std::string>();
  out_commods_ = std::vector<std::string>();
};

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FacilityModel::~FacilityModel() {};

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FacilityModel::initCoreMembers(QueryEngine* qe) {
  Model::initCoreMembers(qe);

  // get lifetime
  try {
    setFacLifetime(atoi(qe->getElementContent("lifetime").c_str()));
  }
  catch (CycNullQueryException e) {
    setFacLifetime(TI->simDur());
  }

  // get the incommodities
  std::string commod;
  try {
    int numInCommod = qe->nElementsMatchingQuery("incommodity");
    for (int i=0;i<numInCommod;i++){
      commod = qe->getElementContent("incommodity",i);
      in_commods_.push_back(commod);
      LOG(LEV_DEBUG2, "none!") << "Facility " << ID() << " has just added incommodity" << commod;
    }
  }
  catch (CycNullQueryException e) {
  }

  // get the outcommodities
  try {
    int numOutCommod = qe->nElementsMatchingQuery("outcommodity");
    for (int i=0;i<numOutCommod;i++){
      commod = qe->getElementContent("outcommodity",i);
      out_commods_.push_back(commod);
      LOG(LEV_DEBUG2, "none!") << "Facility " << ID() << " has just added outcommodity" << commod;
    }
  }
  catch (CycNullQueryException e) {
  }
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Prototype* FacilityModel::clone() {
  FacilityModel* clone = dynamic_cast<FacilityModel*>(Model::constructModel(modelImpl()));
  clone->cloneCoreMembersFrom(this);
  clone->cloneModuleMembersFrom(this);
  clone->setBuildDate(TI->time());
  CLOG(LEV_DEBUG3) << clone->modelImpl() << " cloned: " << clone->str();
  CLOG(LEV_DEBUG3) << "               From: " << this->str();
  return clone;
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FacilityModel::cloneCoreMembersFrom(FacilityModel* source) {
  setName(source->name());
  setModelImpl(source->modelImpl());
  setModelType(source->modelType());
  setFacLifetime(source->facLifetime());
  in_commods_ = source->inputCommodities();
  out_commods_ = source->outputCommodities();
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FacilityModel::cloneModuleMembersFrom(FacilityModel* source) {}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
std::string FacilityModel::str() {
  stringstream ss("");
  ss << Model::str() << " with: "
     << " lifetime: " << facLifetime()
     << " build date: " << build_date_
     << " decommission date: " << decommission_date_;
  return ss.str();
};

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
InstModel* FacilityModel::facInst() {
  return dynamic_cast<InstModel*>( parent() );
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FacilityModel::handleTick(int time){
  // facilities should override this method, unless they're very naiive.
  // generally, a facility's handleTick() behavior should be to
  // offer an amount of its output material equal to its capacity
  // and to request an amount of raw material also equal to its capacity.
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FacilityModel::handleTock(int time){
  // facilities should override this method, unless they're very naiive.
  // generally, a faility's handleTock() behavior should be to
  // process any orders passed down from the market,
  // send the appropriate materials,
  // receive any materials the market has found a source for,
  // and record all material transfers.
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FacilityModel::handleDailyTasks(int time, int day){
  // facilities who have more intricate details should utilize this function
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FacilityModel::decommission() {
  if (!checkDecommissionCondition())
    throw CycOverrideException("Cannot decommission " + name());

  CLOG(LEV_INFO3) << name() << " is being decommissioned";
  deleteModel(this);
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FacilityModel::checkDecommissionCondition() {
  return true;
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
std::vector<std::string> FacilityModel::inputCommodities() {
  return in_commods_;
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
std::vector<std::string> FacilityModel::outputCommodities() {
  return out_commods_;
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FacilityModel::lifetimeReached() {
  return (TI->time() >= decommission_date_);
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FacilityModel::setBuildDate(int current_time) {
  build_date_ = current_time;
  setDecommissionDate(build_date_ + fac_lifetime_ - 1); // -1 because you want the decommission to occur on the previous time's tock
  CLOG(LEV_DEBUG3) << name() << " has set its time-related members: ";
  CLOG(LEV_DEBUG3) << " * lifetime: " << fac_lifetime_;
  CLOG(LEV_DEBUG3) << " * build date: " << build_date_;
  CLOG(LEV_DEBUG3) << " * decommisison date: " << decommission_date_;
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FacilityModel::setDecommissionDate(int time) {
  double final_time = TI->finalTime();
  if (time < final_time)
    {
      decommission_date_ = time;
    }
  else
    {
      decommission_date_ = final_time;
    }
  CLOG(LEV_DEBUG3) << name() << " is setting its decommission date: ";
  CLOG(LEV_DEBUG3) << " * Set Time: " << time;
  CLOG(LEV_DEBUG3) << " * Final Time: " << final_time;
  CLOG(LEV_DEBUG3) << " * decommisison date: " << decommission_date_;
}
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_SPACES_CONTINUOUSLAGRANGE_HH
#define DUNE_GDT_SPACES_CONTINUOUSLAGRANGE_HH

#include <memory>

#include <dune/stuff/grid/layers.hh>
#include <dune/stuff/grid/provider/interface.hh>

#include "interface.hh"
#include "continuouslagrange/fem.hh"
#include "continuouslagrange/pdelab.hh"

namespace Dune {
namespace GDT {
namespace Spaces {

template <class GridType, Stuff::Grid::ChooseLayer layer_type, ChooseSpaceBackend backend_type, int polOrder,
          class RangeFieldType, int dimRange, int dimRangeCols = 1>
class ContinuousLagrangeProvider
{
  static const Stuff::Grid::ChoosePartView part_view_type = ChooseGridPartView<backend_type>::type;

public:
  typedef typename Stuff::Grid::Layer<GridType, layer_type, part_view_type>::Type GridLayerType;

private:
  template <class G, int p, class R, int r, int rC, GDT::ChooseSpaceBackend b>
  struct SpaceChooser
  {
    static_assert(AlwaysFalse<G>::value, "No space available for this backend!");
  };

  template <class G, int p, class R, int r, int rC>
  struct SpaceChooser<G, p, R, r, rC, GDT::ChooseSpaceBackend::fem>
  {
    typedef GDT::Spaces::ContinuousLagrange::FemBased<GridLayerType, p, R, r> Type;
  };

  template <class G, int p, class R, int r, int rC>
  struct SpaceChooser<G, p, R, r, rC, GDT::ChooseSpaceBackend::pdelab>
  {
    typedef GDT::Spaces::ContinuousLagrange::PdelabBased<GridLayerType, p, R, r> Type;
  };

  typedef Stuff::Grid::ConstProviderInterface<GridType> GridProviderType;
#if HAVE_DUNE_GRID_MULTISCALE
  typedef grid::Multiscale::ProviderInterface<GridType> MsGridProviderType;
#endif

public:
  typedef typename SpaceChooser<GridType, polOrder, RangeFieldType, dimRange, dimRangeCols, backend_type>::Type Type;

  static Type create(const std::shared_ptr<const GridLayerType> grid_layer)
  {
    return Type(grid_layer);
  }

  static Type create(const GridProviderType& grid_provider, const int level = 0)
  {
    return Type(grid_provider.template layer<layer_type, part_view_type>(level));
  }

#if HAVE_DUNE_GRID_MULTISCALE
  static Type create(const MsGridProviderType& grid_provider, const int level_or_subdomain = 0)
  {
    return Type(grid_provider.template layer<layer_type, part_view_type>(level_or_subdomain));
  }
#endif // HAVE_DUNE_GRID_MULTISCALE
}; // class ContinuousLagrangeProvider

} // namespace Spaces
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_SPACES_CONTINUOUSLAGRANGE_HH
<commit_msg>[spaces] ContinuousLagrangeProvider::create returns pointers<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_SPACES_CONTINUOUSLAGRANGE_HH
#define DUNE_GDT_SPACES_CONTINUOUSLAGRANGE_HH

#include <memory>

#include <dune/stuff/grid/layers.hh>
#include <dune/stuff/grid/provider/interface.hh>

#include "interface.hh"
#include "continuouslagrange/fem.hh"
#include "continuouslagrange/pdelab.hh"

namespace Dune {
namespace GDT {
namespace Spaces {

template <class GridType, Stuff::Grid::ChooseLayer layer_type, ChooseSpaceBackend backend_type, int polOrder,
          class RangeFieldType, int dimRange, int dimRangeCols = 1>
class ContinuousLagrangeProvider
{
  static const Stuff::Grid::ChoosePartView part_view_type = ChooseGridPartView<backend_type>::type;

public:
  typedef typename Stuff::Grid::Layer<GridType, layer_type, part_view_type>::Type GridLayerType;

private:
  template <class G, int p, class R, int r, int rC, GDT::ChooseSpaceBackend b>
  struct SpaceChooser
  {
    static_assert(AlwaysFalse<G>::value, "No space available for this backend!");
  };

  template <class G, int p, class R, int r, int rC>
  struct SpaceChooser<G, p, R, r, rC, GDT::ChooseSpaceBackend::fem>
  {
    typedef GDT::Spaces::ContinuousLagrange::FemBased<GridLayerType, p, R, r> Type;
  };

  template <class G, int p, class R, int r, int rC>
  struct SpaceChooser<G, p, R, r, rC, GDT::ChooseSpaceBackend::pdelab>
  {
    typedef GDT::Spaces::ContinuousLagrange::PdelabBased<GridLayerType, p, R, r> Type;
  };

  typedef Stuff::Grid::ConstProviderInterface<GridType> GridProviderType;
#if HAVE_DUNE_GRID_MULTISCALE
  typedef grid::Multiscale::ProviderInterface<GridType> MsGridProviderType;
#endif

public:
  typedef typename SpaceChooser<GridType, polOrder, RangeFieldType, dimRange, dimRangeCols, backend_type>::Type Type;

  static Type* create(const std::shared_ptr<const GridLayerType> grid_layer)
  {
    return new Type(grid_layer);
  }

  static Type* create(const GridProviderType& grid_provider, const int level = 0)
  {
    return new Type(grid_provider.template layer<layer_type, part_view_type>(level));
  }

#if HAVE_DUNE_GRID_MULTISCALE
  static Type create(const MsGridProviderType& grid_provider, const int level_or_subdomain = 0)
  {
    return Type(grid_provider.template layer<layer_type, part_view_type>(level_or_subdomain));
  }
#endif // HAVE_DUNE_GRID_MULTISCALE
}; // class ContinuousLagrangeProvider

} // namespace Spaces
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_SPACES_CONTINUOUSLAGRANGE_HH
<|endoftext|>