<commit_before>/*
 * COPYRIGHT:        See LICENSE in the top level directory
 * PROJECT:          HPCsim
 * FILE:             HPCsim/main.cpp
 * PURPOSE:          Main simulation file
 * PROGRAMMER:       Pierre Schweitzer (pierre@reactos.org)
 */

#include <iostream>
#include <unistd.h>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <getopt.h>
#include <fcntl.h>
#include <unistd.h>
#include <dlfcn.h>
#include <cassert>
#include <cstddef>

#include "TThreadsFactory.h"
#include "RngStream.h"
#include "simulation.h"

#define PATH_MAX 0x1000

#define DEFAULT_NAME {'H', 'P', 'C', 's', 'i', 'm', '.', 'o', 'u', 't', '\0'}

struct TSimulationAddresses
{
    TSimulationInit fSimulationInit;
    TRunInit fRunInit;
    TEventInit fEventInit;
    TEventRun fEventRun;
    TEventClear fEventClear;
    TRunClear fRunClear;
    TSimulationUnload fSimulationUnload;
};

#ifdef USE_PILOT_THREAD
struct TPilotJobContext
{
    unsigned long fEvents;
    void * fSimulationContext;
};
#endif

static pthread_mutex_t gPipeLock;
static int gPipe[2];
static TResult gNullResult;
static TSimulationAddresses gSimulation;

#define LoadAndSetSimulationFunction(name)                      \
    gSimulation.f##name = (T##name)dlsym(simulationLib, #name); \
    if (gSimulation.f##name == 0) {                             \
        std::cerr << "Failed loading " << #name << std::endl;   \
        goto end;                                               \
    }

/* Exported */
extern "C" double RandU01(void * context)
{
    RngStream * rand = reinterpret_cast<RngStream *>(context);

    return rand->RandU01();
}

/* Exported */
extern "C" void QueueResult(TResult * result, void * context)
{
    RngStream * rand = reinterpret_cast<RngStream *>(context);

    /* Set our ID first, and send to write thread */
    memcpy(result->fId, rand->GetDigest(), sizeof(TResult::fId));
    pthread_mutex_lock(&gPipeLock);
    write(gPipe[1], result, sizeof(TResult));
    pthread_mutex_unlock(&gPipeLock);
}

static void * SimulationLoop(void * Arg)
{
#ifdef USE_PILOT_THREAD
    TPilotJobContext * context = reinterpret_cast<TPilotJobContext *>(Arg);
    void * simulationContext = context->fSimulationContext;

    for (unsigned long event = 0; event < context->fEvents; ++event)
#else
    void * simulationContext = reinterpret_cast<void *>(Arg);
#endif
    {
        void * eventContext;
        RngStream rand;

        /* Init the event */
        if (gSimulation.fEventInit(simulationContext, &rand, &eventContext) < 0)
        {
#ifdef USE_PILOT_THREAD
            continue;
#else
            sem_post(TThreadsFactory::GetInstance()->GetInitLock());
            return 0;
#endif
        }

        /* Release init lock */
        sem_post(TThreadsFactory::GetInstance()->GetInitLock());

        /* Call the simulation */
        gSimulation.fEventRun(simulationContext, eventContext);

#ifdef USE_PILOT_THREAD
        sem_wait(TThreadsFactory::GetInstance()->GetInitLock());
#endif

        /* Notify end of event */
        gSimulation.fEventClear(simulationContext, eventContext);
    }

#ifdef USE_PILOT_THREAD
    sem_post(TThreadsFactory::GetInstance()->GetInitLock());
#endif

    return 0;
}

static void * WriteResults(void * Arg)
{
    TResult result;
    char * outputFile = reinterpret_cast<char *>(Arg);
    int outFD;

    /* Open the output file */
    outFD = open(outputFile, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    assert(outFD != -1);

    /* Read the incoming event */
    while (read(gPipe[0], &result, sizeof(TResult)) > 0)
    {
        /* End signal => stop dealing with data */
        if (memcmp(&result, &gNullResult, sizeof(TResult)) == 0)
            break;

        /* Write the event to the output file - only write what's needed */
        write(outFD, &result, offsetof(TResult, fResult) + result.fResultLength);
    }

    close(outFD);

    return 0;
}

static void PrintUsage(char * name)
{
    std::cerr << "Usage: " << name << " --simulation|-s name.so [--threads|-t X --first|-f X --events|-e X --output|-o name]" << std::endl;
    std::cerr << "\t- Simulation: path of the shared library containing the simulation" << std::endl;
    std::cerr << "\t- Threads: amount of threads to use for computing (min 1). Beware an extra thread will be used for results writing" << std::endl;
    std::cerr << "\t- First: start the event loop at this event" << std::endl;
    std::cerr << "\t- Events: number of events to compute" << std::endl;
    std::cerr << "\t- Output: name of the output file to write" << std::endl;
}

int main(int argc, char * argv[])
{
    int option;
    unsigned int nThreads = 1;
    unsigned long nEvents = 100;
    unsigned long firstEvent = 0;
    char outputFile[PATH_MAX] = DEFAULT_NAME;
    char simulationFile[PATH_MAX] = "";
    pthread_t writingThread;
    void * ret;
    void * simulationLib;
    void * simulationContext;
#ifdef USE_PILOT_THREAD
    unsigned long eventsPerThread = 0;
    unsigned long padding = 0;
    TPilotJobContext * contexts = 0;
    TPilotJobContext * context = 0;
#endif

    /* Parse arguments */
    while (true)
    {
        static struct option long_options[] =
        {
            {"threads", required_argument, 0, 't'},
            {"events", required_argument, 0, 'e'},
            {"output", required_argument, 0, 'o'},
            {"first", required_argument, 0, 'f'},
            {"simulation", required_argument, 0, 's'},
            {0, 0, 0, 0}
        };

        int option_index = 0;
        option = getopt_long(argc, argv, "e:t:o:f:s:", long_options, &option_index);
        if (option == -1)
            break;

        switch (option)
        {
            static bool written = false;

            case 't':
                nThreads = strtoul(optarg, 0, 10);
                break;

            case 'e':
                nEvents = strtoul(optarg, 0, 10);
                break;

            case 'o':
                strncpy(outputFile, optarg, PATH_MAX - 1);
                outputFile[PATH_MAX - 1] = '\0';
                break;

            case 'f':
                firstEvent = strtoul(optarg, 0, 10);
                break;

            case 's':
                strncpy(simulationFile, optarg, PATH_MAX - 1);
                simulationFile[PATH_MAX - 1] = '\0';
                break;

            case '?':
                if (!written)
                {
                    PrintUsage(argv[0]);
                    written = true;
                }
                break;
        }
    }

    if (simulationFile[0] == '\0')
    {
        PrintUsage(argv[0]);
        return 0;
    }

    /* Open the simulation worker */
    simulationLib = dlopen(simulationFile, RTLD_NOW | RTLD_LOCAL);
    if (simulationLib == 0)
    {
        std::cerr << "Failed loading " << simulationFile << std::endl;
        return 0;
    }

    /* Load its functions */
    LoadAndSetSimulationFunction(SimulationInit);
    LoadAndSetSimulationFunction(RunInit);
    LoadAndSetSimulationFunction(EventInit);
    LoadAndSetSimulationFunction(EventRun);
    LoadAndSetSimulationFunction(EventClear);
    LoadAndSetSimulationFunction(RunClear);
    LoadAndSetSimulationFunction(SimulationUnload);

    /* Init the simulation */
    if (gSimulation.fSimulationInit(nThreads, nEvents, firstEvent, &simulationContext) < 0)
    {
        std::cerr << "Failed initializing library" << std::endl;
        goto end;
    }

    /* Advance in the generator */
    for (unsigned long i = 0; i < firstEvent; ++i)
    {
        RngStream rand;
    }

    /* Initialize our pipe lock */
    pthread_mutex_init(&gPipeLock, 0);
    /* Start our threads factory */
    TThreadsFactory::GetInstance()->SetMaxThreads(nThreads);
    /* Init our null event */
    memset(&gNullResult, 0, sizeof(TResult));

    /* Open the communication pipe */
    if (pipe(gPipe) == -1)
    {
        std::cerr << "Failed creating pipes" << std::endl;
        goto end2;
    }

    /* Start our background writing thread */
    if (pthread_create(&writingThread, 0, WriteResults, outputFile) != 0)
    {
        std::cerr << "Failed creating writing thread" << std::endl;
        goto end3;
    }

    /* Initialize the run */
    if (gSimulation.fRunInit(simulationContext) < 0)
    {
        std::cerr << "Failed initializing run" << std::endl;
        goto end4;
    }

#ifndef USE_PILOT_THREAD
    /* Hot loop, the simulation happens here */
    for (unsigned long event = 0; event < nEvents; ++event)
    {
        TThreadsFactory::GetInstance()->CreateThread(SimulationLoop, simulationContext);
    }
#else
    /* Alloc once, use multipe times - reduce overhead */
    contexts = new TPilotJobContext[nThreads];

    /* Compute number of events required per thread */
    eventsPerThread = nEvents / nThreads;
    /* Compute number of threads where we have to +1 number of events to get exact amount */
    padding = nEvents % nThreads;
    /* Start at first event */
    context = contexts;

    for (unsigned long thread = 0; thread < nThreads; ++thread)
    {
        context->fSimulationContext = simulationContext;
        context->fEvents = eventsPerThread + ((thread < padding) ? 1 : 0);
        TThreadsFactory::GetInstance()->CreateThread(simulationContext, context);

        ++context;
    }
#endif

    /* Wait for all the propagations to finish */
    TThreadsFactory::GetInstance()->WaitForAllThreads();

#ifdef USE_PILOT_THREAD
    delete contexts;
#endif

    /* Signal end of run */
    gSimulation.fRunClear(simulationContext);

end4:
    /* Send the end signal to writer */
    write(gPipe[1], &gNullResult, sizeof(TResult));

    /* Wait for the end of the writer */
    pthread_join(writingThread, &ret);

end3:
    close(gPipe[0]);
    close(gPipe[1]);
end2:
    pthread_mutex_destroy(&gPipeLock);
    gSimulation.fSimulationUnload(simulationContext);
end:
    dlclose(simulationLib);
    return 0;
}
<commit_msg>Fix mismatching delete operatorr<commit_after>/*
 * COPYRIGHT:        See LICENSE in the top level directory
 * PROJECT:          HPCsim
 * FILE:             HPCsim/main.cpp
 * PURPOSE:          Main simulation file
 * PROGRAMMER:       Pierre Schweitzer (pierre@reactos.org)
 */

#include <iostream>
#include <unistd.h>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <getopt.h>
#include <fcntl.h>
#include <unistd.h>
#include <dlfcn.h>
#include <cassert>
#include <cstddef>

#include "TThreadsFactory.h"
#include "RngStream.h"
#include "simulation.h"

#define PATH_MAX 0x1000

#define DEFAULT_NAME {'H', 'P', 'C', 's', 'i', 'm', '.', 'o', 'u', 't', '\0'}

struct TSimulationAddresses
{
    TSimulationInit fSimulationInit;
    TRunInit fRunInit;
    TEventInit fEventInit;
    TEventRun fEventRun;
    TEventClear fEventClear;
    TRunClear fRunClear;
    TSimulationUnload fSimulationUnload;
};

#ifdef USE_PILOT_THREAD
struct TPilotJobContext
{
    unsigned long fEvents;
    void * fSimulationContext;
};
#endif

static pthread_mutex_t gPipeLock;
static int gPipe[2];
static TResult gNullResult;
static TSimulationAddresses gSimulation;

#define LoadAndSetSimulationFunction(name)                      \
    gSimulation.f##name = (T##name)dlsym(simulationLib, #name); \
    if (gSimulation.f##name == 0) {                             \
        std::cerr << "Failed loading " << #name << std::endl;   \
        goto end;                                               \
    }

/* Exported */
extern "C" double RandU01(void * context)
{
    RngStream * rand = reinterpret_cast<RngStream *>(context);

    return rand->RandU01();
}

/* Exported */
extern "C" void QueueResult(TResult * result, void * context)
{
    RngStream * rand = reinterpret_cast<RngStream *>(context);

    /* Set our ID first, and send to write thread */
    memcpy(result->fId, rand->GetDigest(), sizeof(TResult::fId));
    pthread_mutex_lock(&gPipeLock);
    write(gPipe[1], result, sizeof(TResult));
    pthread_mutex_unlock(&gPipeLock);
}

static void * SimulationLoop(void * Arg)
{
#ifdef USE_PILOT_THREAD
    TPilotJobContext * context = reinterpret_cast<TPilotJobContext *>(Arg);
    void * simulationContext = context->fSimulationContext;

    for (unsigned long event = 0; event < context->fEvents; ++event)
#else
    void * simulationContext = reinterpret_cast<void *>(Arg);
#endif
    {
        void * eventContext;
        RngStream rand;

        /* Init the event */
        if (gSimulation.fEventInit(simulationContext, &rand, &eventContext) < 0)
        {
#ifdef USE_PILOT_THREAD
            continue;
#else
            sem_post(TThreadsFactory::GetInstance()->GetInitLock());
            return 0;
#endif
        }

        /* Release init lock */
        sem_post(TThreadsFactory::GetInstance()->GetInitLock());

        /* Call the simulation */
        gSimulation.fEventRun(simulationContext, eventContext);

#ifdef USE_PILOT_THREAD
        sem_wait(TThreadsFactory::GetInstance()->GetInitLock());
#endif

        /* Notify end of event */
        gSimulation.fEventClear(simulationContext, eventContext);
    }

#ifdef USE_PILOT_THREAD
    sem_post(TThreadsFactory::GetInstance()->GetInitLock());
#endif

    return 0;
}

static void * WriteResults(void * Arg)
{
    TResult result;
    char * outputFile = reinterpret_cast<char *>(Arg);
    int outFD;

    /* Open the output file */
    outFD = open(outputFile, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    assert(outFD != -1);

    /* Read the incoming event */
    while (read(gPipe[0], &result, sizeof(TResult)) > 0)
    {
        /* End signal => stop dealing with data */
        if (memcmp(&result, &gNullResult, sizeof(TResult)) == 0)
            break;

        /* Write the event to the output file - only write what's needed */
        write(outFD, &result, offsetof(TResult, fResult) + result.fResultLength);
    }

    close(outFD);

    return 0;
}

static void PrintUsage(char * name)
{
    std::cerr << "Usage: " << name << " --simulation|-s name.so [--threads|-t X --first|-f X --events|-e X --output|-o name]" << std::endl;
    std::cerr << "\t- Simulation: path of the shared library containing the simulation" << std::endl;
    std::cerr << "\t- Threads: amount of threads to use for computing (min 1). Beware an extra thread will be used for results writing" << std::endl;
    std::cerr << "\t- First: start the event loop at this event" << std::endl;
    std::cerr << "\t- Events: number of events to compute" << std::endl;
    std::cerr << "\t- Output: name of the output file to write" << std::endl;
}

int main(int argc, char * argv[])
{
    int option;
    unsigned int nThreads = 1;
    unsigned long nEvents = 100;
    unsigned long firstEvent = 0;
    char outputFile[PATH_MAX] = DEFAULT_NAME;
    char simulationFile[PATH_MAX] = "";
    pthread_t writingThread;
    void * ret;
    void * simulationLib;
    void * simulationContext;
#ifdef USE_PILOT_THREAD
    unsigned long eventsPerThread = 0;
    unsigned long padding = 0;
    TPilotJobContext * contexts = 0;
    TPilotJobContext * context = 0;
#endif

    /* Parse arguments */
    while (true)
    {
        static struct option long_options[] =
        {
            {"threads", required_argument, 0, 't'},
            {"events", required_argument, 0, 'e'},
            {"output", required_argument, 0, 'o'},
            {"first", required_argument, 0, 'f'},
            {"simulation", required_argument, 0, 's'},
            {0, 0, 0, 0}
        };

        int option_index = 0;
        option = getopt_long(argc, argv, "e:t:o:f:s:", long_options, &option_index);
        if (option == -1)
            break;

        switch (option)
        {
            static bool written = false;

            case 't':
                nThreads = strtoul(optarg, 0, 10);
                break;

            case 'e':
                nEvents = strtoul(optarg, 0, 10);
                break;

            case 'o':
                strncpy(outputFile, optarg, PATH_MAX - 1);
                outputFile[PATH_MAX - 1] = '\0';
                break;

            case 'f':
                firstEvent = strtoul(optarg, 0, 10);
                break;

            case 's':
                strncpy(simulationFile, optarg, PATH_MAX - 1);
                simulationFile[PATH_MAX - 1] = '\0';
                break;

            case '?':
                if (!written)
                {
                    PrintUsage(argv[0]);
                    written = true;
                }
                break;
        }
    }

    if (simulationFile[0] == '\0')
    {
        PrintUsage(argv[0]);
        return 0;
    }

    /* Open the simulation worker */
    simulationLib = dlopen(simulationFile, RTLD_NOW | RTLD_LOCAL);
    if (simulationLib == 0)
    {
        std::cerr << "Failed loading " << simulationFile << std::endl;
        return 0;
    }

    /* Load its functions */
    LoadAndSetSimulationFunction(SimulationInit);
    LoadAndSetSimulationFunction(RunInit);
    LoadAndSetSimulationFunction(EventInit);
    LoadAndSetSimulationFunction(EventRun);
    LoadAndSetSimulationFunction(EventClear);
    LoadAndSetSimulationFunction(RunClear);
    LoadAndSetSimulationFunction(SimulationUnload);

    /* Init the simulation */
    if (gSimulation.fSimulationInit(nThreads, nEvents, firstEvent, &simulationContext) < 0)
    {
        std::cerr << "Failed initializing library" << std::endl;
        goto end;
    }

    /* Advance in the generator */
    for (unsigned long i = 0; i < firstEvent; ++i)
    {
        RngStream rand;
    }

    /* Initialize our pipe lock */
    pthread_mutex_init(&gPipeLock, 0);
    /* Start our threads factory */
    TThreadsFactory::GetInstance()->SetMaxThreads(nThreads);
    /* Init our null event */
    memset(&gNullResult, 0, sizeof(TResult));

    /* Open the communication pipe */
    if (pipe(gPipe) == -1)
    {
        std::cerr << "Failed creating pipes" << std::endl;
        goto end2;
    }

    /* Start our background writing thread */
    if (pthread_create(&writingThread, 0, WriteResults, outputFile) != 0)
    {
        std::cerr << "Failed creating writing thread" << std::endl;
        goto end3;
    }

    /* Initialize the run */
    if (gSimulation.fRunInit(simulationContext) < 0)
    {
        std::cerr << "Failed initializing run" << std::endl;
        goto end4;
    }

#ifndef USE_PILOT_THREAD
    /* Hot loop, the simulation happens here */
    for (unsigned long event = 0; event < nEvents; ++event)
    {
        TThreadsFactory::GetInstance()->CreateThread(SimulationLoop, simulationContext);
    }
#else
    /* Alloc once, use multipe times - reduce overhead */
    contexts = new TPilotJobContext[nThreads];

    /* Compute number of events required per thread */
    eventsPerThread = nEvents / nThreads;
    /* Compute number of threads where we have to +1 number of events to get exact amount */
    padding = nEvents % nThreads;
    /* Start at first event */
    context = contexts;

    for (unsigned long thread = 0; thread < nThreads; ++thread)
    {
        context->fSimulationContext = simulationContext;
        context->fEvents = eventsPerThread + ((thread < padding) ? 1 : 0);
        TThreadsFactory::GetInstance()->CreateThread(simulationContext, context);

        ++context;
    }
#endif

    /* Wait for all the propagations to finish */
    TThreadsFactory::GetInstance()->WaitForAllThreads();

#ifdef USE_PILOT_THREAD
    delete[] contexts;
#endif

    /* Signal end of run */
    gSimulation.fRunClear(simulationContext);

end4:
    /* Send the end signal to writer */
    write(gPipe[1], &gNullResult, sizeof(TResult));

    /* Wait for the end of the writer */
    pthread_join(writingThread, &ret);

end3:
    close(gPipe[0]);
    close(gPipe[1]);
end2:
    pthread_mutex_destroy(&gPipeLock);
    gSimulation.fSimulationUnload(simulationContext);
end:
    dlclose(simulationLib);
    return 0;
}
<|endoftext|>


<commit_before>

// $Id: parallel_ghost_sync.C 2501 2007-11-20 02:33:29Z benkirk $

// The libMesh Finite Element Library.
// Copyright (C) 2002-2007  Benjamin S. Kirk, John W. Peterson

// 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ Includes -----------------------------------
#include <limits>
#include <utility>

// Local Includes -----------------------------------
#include "elem.h"
#include "location_maps.h"
#include "mesh_base.h"
#include "node.h"
#include "parallel.h"

//--------------------------------------------------------------------------

template <typename T>
void LocationMap<T>::init(MeshBase& mesh)
{
  // This function must be run on all processors at once
  // for non-serial meshes
  if (!mesh.is_serial())
    parallel_only();

  START_LOG("init()", "LocationMap");

  // Clear the old map
  _map.clear();

  // Cache a bounding box
  _lower_bound.clear();
  _lower_bound.resize(3, std::numeric_limits<Real>::max());
  _upper_bound.clear();
  _upper_bound.resize(3, -std::numeric_limits<Real>::max());

  MeshBase::node_iterator       it  = mesh.nodes_begin();
  const MeshBase::node_iterator end = mesh.nodes_end();

  for (; it != end; ++it)
    {
      Node* node = *it;

      // Expand the bounding box if necessary
      _lower_bound[0] = std::min(_lower_bound[0],
                                 (*node)(0));
      _lower_bound[1] = std::min(_lower_bound[1],
                                 (*node)(1));
      _lower_bound[2] = std::min(_lower_bound[2],
                                 (*node)(2));
      _upper_bound[0] = std::max(_upper_bound[0],
                                 (*node)(0));
      _upper_bound[1] = std::max(_upper_bound[1],
                                 (*node)(1));
      _upper_bound[2] = std::max(_upper_bound[2],
                                 (*node)(2));
    }

  // On a parallel mesh we might not yet have a full bounding box
  if (!mesh.is_serial())
    {
      Parallel::min(_lower_bound);
      Parallel::max(_upper_bound);
    }

  this->fill(mesh);

  STOP_LOG("init()", "LocationMap");
}

template <typename T>
void LocationMap<T>::insert(T &t)
{
  this->_map.insert(std::make_pair(this->key(this->point_of(t)), &t));
}

template <>
Point LocationMap<Node>::point_of(const Node& node) const
{
  return node;
}

template <>
Point LocationMap<Elem>::point_of(const Elem& elem) const
{
  return elem.centroid();
}

template <typename T>
T* LocationMap<T>::find(const Point& p,
                     const Real tol)
{
  // Look for the key in the multimap
  std::pair<typename map_type::iterator,
            typename map_type::iterator>
    pos = _map.equal_range(this->key(p));

  while (pos.first != pos.second)
    if (p.absolute_fuzzy_equals
         (this->point_of(*(pos.first->second)), tol))
      return pos.first->second;
    else
      ++pos.first;

  return NULL;
}

template <typename T>
unsigned int LocationMap<T>::key(const Point& p)
{
  Real xscaled = (p(0) - _lower_bound[0])/
                 (_upper_bound[0] - _lower_bound[0]),
       yscaled = (p(1) - _lower_bound[1])/
                 (_upper_bound[1] - _lower_bound[1]),
       zscaled = (p(2) - _lower_bound[2])/
                 (_upper_bound[2] - _lower_bound[2]);

  // 10 bits per coordinate, to work with 32+ bit machines
  unsigned chunkmax = 1024;
  Real chunkfloat = 1024.0;

  unsigned int n0 = static_cast<unsigned int> (chunkfloat * xscaled),
               n1 = static_cast<unsigned int> (chunkfloat * yscaled),
               n2 = static_cast<unsigned int> (chunkfloat * zscaled);

  return chunkmax*chunkmax*n0 + chunkmax*n1 + n2;
}

template <>
void LocationMap<Node>::fill(MeshBase& mesh)
{
  // Populate the nodes map
  MeshBase::node_iterator  it = mesh.nodes_begin(),
                          end = mesh.nodes_end();
  for (; it != end; ++it)
    this->insert(**it);
}

template <>
void LocationMap<Elem>::fill(MeshBase& mesh)
{
  // Populate the elem map
  MeshBase::element_iterator       it  = mesh.active_elements_begin(),
                                   end = mesh.active_elements_end();
  for (; it != end; ++it)
    this->insert(**it);
}

template class LocationMap<Elem>;
template class LocationMap<Node>;
<commit_msg>Don't miss any points because of epsilon differences in location<commit_after>

// $Id: parallel_ghost_sync.C 2501 2007-11-20 02:33:29Z benkirk $

// The libMesh Finite Element Library.
// Copyright (C) 2002-2007  Benjamin S. Kirk, John W. Peterson

// 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ Includes -----------------------------------
#include <limits>
#include <utility>

// Local Includes -----------------------------------
#include "elem.h"
#include "location_maps.h"
#include "mesh_base.h"
#include "node.h"
#include "parallel.h"

//--------------------------------------------------------------------------

template <typename T>
void LocationMap<T>::init(MeshBase& mesh)
{
  // This function must be run on all processors at once
  // for non-serial meshes
  if (!mesh.is_serial())
    parallel_only();

  START_LOG("init()", "LocationMap");

  // Clear the old map
  _map.clear();

  // Cache a bounding box
  _lower_bound.clear();
  _lower_bound.resize(3, std::numeric_limits<Real>::max());
  _upper_bound.clear();
  _upper_bound.resize(3, -std::numeric_limits<Real>::max());

  MeshBase::node_iterator       it  = mesh.nodes_begin();
  const MeshBase::node_iterator end = mesh.nodes_end();

  for (; it != end; ++it)
    {
      Node* node = *it;

      // Expand the bounding box if necessary
      _lower_bound[0] = std::min(_lower_bound[0],
                                 (*node)(0));
      _lower_bound[1] = std::min(_lower_bound[1],
                                 (*node)(1));
      _lower_bound[2] = std::min(_lower_bound[2],
                                 (*node)(2));
      _upper_bound[0] = std::max(_upper_bound[0],
                                 (*node)(0));
      _upper_bound[1] = std::max(_upper_bound[1],
                                 (*node)(1));
      _upper_bound[2] = std::max(_upper_bound[2],
                                 (*node)(2));
    }

  // On a parallel mesh we might not yet have a full bounding box
  if (!mesh.is_serial())
    {
      Parallel::min(_lower_bound);
      Parallel::max(_upper_bound);
    }

  this->fill(mesh);

  STOP_LOG("init()", "LocationMap");
}

template <typename T>
void LocationMap<T>::insert(T &t)
{
  this->_map.insert(std::make_pair(this->key(this->point_of(t)), &t));
}

template <>
Point LocationMap<Node>::point_of(const Node& node) const
{
  return node;
}

template <>
Point LocationMap<Elem>::point_of(const Elem& elem) const
{
  return elem.centroid();
}

template <typename T>
T* LocationMap<T>::find(const Point& p,
                     const Real tol)
{
  // Look for a likely key in the multimap
  unsigned int pointkey = this->key(p);

  // Look for the exact key first
  std::pair<typename map_type::iterator,
            typename map_type::iterator>
    pos = _map.equal_range(pointkey);

  while (pos.first != pos.second)
    if (p.absolute_fuzzy_equals
         (this->point_of(*(pos.first->second)), tol))
      return pos.first->second;
    else
      ++pos.first;

  // Look for neighboring bins' keys next
  const unsigned int chunkmax = 1024;
  for (int xoffset = -1; xoffset != 2; ++xoffset)
    {
      for (int yoffset = -1; yoffset != 2; ++yoffset)
        {
          for (int zoffset = -1; zoffset != 2; ++zoffset)
            {
              std::pair<typename map_type::iterator,
                        typename map_type::iterator>
                pos = _map.equal_range(pointkey +
				       xoffset*chunkmax*chunkmax +
				       yoffset*chunkmax +
				       zoffset);
              while (pos.first != pos.second)
                if (p.absolute_fuzzy_equals
                     (this->point_of(*(pos.first->second)), tol))
                  return pos.first->second;
                else
                  ++pos.first;
            }
        }
    }

  return NULL;
}

template <typename T>
unsigned int LocationMap<T>::key(const Point& p)
{
  Real xscaled = (p(0) - _lower_bound[0])/
                 (_upper_bound[0] - _lower_bound[0]),
       yscaled = (p(1) - _lower_bound[1])/
                 (_upper_bound[1] - _lower_bound[1]),
       zscaled = (p(2) - _lower_bound[2])/
                 (_upper_bound[2] - _lower_bound[2]);

  // 10 bits per coordinate, to work with 32+ bit machines
  const unsigned int chunkmax = 1024;
  const Real chunkfloat = 1024.0;

  unsigned int n0 = static_cast<unsigned int> (chunkfloat * xscaled),
               n1 = static_cast<unsigned int> (chunkfloat * yscaled),
               n2 = static_cast<unsigned int> (chunkfloat * zscaled);

  return chunkmax*chunkmax*n0 + chunkmax*n1 + n2;
}

template <>
void LocationMap<Node>::fill(MeshBase& mesh)
{
  // Populate the nodes map
  MeshBase::node_iterator  it = mesh.nodes_begin(),
                          end = mesh.nodes_end();
  for (; it != end; ++it)
    this->insert(**it);
}

template <>
void LocationMap<Elem>::fill(MeshBase& mesh)
{
  // Populate the elem map
  MeshBase::element_iterator       it  = mesh.active_elements_begin(),
                                   end = mesh.active_elements_end();
  for (; it != end; ++it)
    this->insert(**it);
}

template class LocationMap<Elem>;
template class LocationMap<Node>;
<|endoftext|>


<commit_before>#include <File.h>
#include <ObjectList.h>
#include <String.h>
#include <cstdlib>
#include <stdio.h>
#include <cctype>
#include "Json.h"

JsonValue::JsonValue()
{

}

template<class T>
T*
ParseNew(JsonParser* parser)
{
	T* t = new T();
	t->Parse(parser);
	return t;
}

void
JsonValue::Serialize(BString* str)
{

}

void
JsonValue::Parse(JsonParser* parser)
{

}

void
JsonString::Serialize(BString* str)
{
	*str << "\"";
	*str << *this;
	*str << "\"";
}

JsonPair::JsonPair(JsonString* n, JsonValue* v)
	:
	fName(n),
	fValue(v)
{
}

JsonObject::JsonObject()
	:
	fPairList(new BObjectList<JsonPair>())
{

}

void
JsonObject::AddPair(JsonString* str, JsonValue* val)
{
	fPairList->AddItem(new JsonPair(str, val));
}

JsonValue*
JsonObject::Get(BString key)
{
	for(int i = 0; i < fPairList->CountItems(); i++) {
		JsonPair* pair = fPairList->ItemAt(i);
		if(*pair->fName == key)
			return pair->fValue;
	}
	return NULL;
}

void
JsonObject::Serialize(BString* str)
{
	*str << "{";
	for (int i = 0; i < fPairList->CountItems(); i++) {
		JsonPair* pair = fPairList->ItemAt(i);
		pair->fName->Serialize(str);
		*str << ": ";
		pair->fValue->Serialize(str);
		if(i < fPairList->CountItems()-1) {
			*str << ", ";
		}
	}
	*str << "}";
}

void
JsonNumber::Serialize(BString* str)
{
	*str << fDouble;
}

void
JsonArray::Serialize(BString* str)
{
	*str << "[";
	for (int i = 0; i < CountItems(); i++) {
		JsonValue* val = ItemAt(i);
		val->Serialize(str);
		if(i < CountItems()-1) {
			*str << ", ";
		}
	}
	*str << "]";
}

void
JsonBool::Serialize(BString* str)
{
	*str << fVal ? "true" : "false";
}

void
JsonNull::Serialize(BString* str)
{
	*str << "null";
}

void
JsonParser::TakeUntil(char end)
{
	while(Peek() != end)
		TakeOne();
}

JsonParser::JsonParser(BString string)
{
	fPointer = 0;
	fString = string;

	TakeWhitespace();
	char firstChar = Peek();

	JsonValue* thing;
	switch(firstChar) {
		case '{':
			thing = ParseNew<JsonObject>(this);
			break;
		case '[':
			thing = ParseNew<JsonArray>(this);
			break;
	}
	fValue = thing;
}

void
JsonNumber::Parse(JsonParser* parser) {
	BString numberPart;
	parser->TakeWhitespace();
	if(parser->Peek() == '-') {
		numberPart << '-';
		parser->TakeOne();
	}
	while(isdigit(parser->Peek()))
		numberPart << parser->TakeOne();
	if(parser->Peek() == '.') {
		numberPart << '.';
		parser->TakeOne();
	}
	while(isdigit(parser->Peek()))
		numberPart << parser->TakeOne();
	if(parser->Peek() == 'e') {
		numberPart << 'e';
		parser->TakeOne();
	}
	while(isdigit(parser->Peek()))
		numberPart << parser->TakeOne();
	double i = strtod(numberPart.String(), NULL);
	fDouble = i;
}

double
JsonNumber::Value() {
	return fDouble;
}

void
JsonParser::TakeWhitespace() {
	while(Peek() != NULL && isspace(Peek()))
		TakeOne();
}

char
JsonParser::Peek() {
	if(fPointer > fString.Length())
		return NULL;
	return fString[fPointer];
}

char
JsonParser::TakeOne() {
	if(fPointer > fString.Length())
		return NULL;
	return fString[fPointer++];
}

enum States {
	StringTakeChar,
	StringTakeSpecial
};

void
JsonString::Parse(JsonParser* parser)
{
	if(parser->Peek() == '"')
		parser->TakeOne();
	States state = StringTakeChar;

	char chr;
	while(chr = parser->TakeOne()) {
		switch (state) {
			case StringTakeChar:
				switch (chr) {
					case '\\':
						state = StringTakeSpecial;
						break;
					case '"':
						return;
						break;
					default:
						*this << chr;
						break;
				}
				break;
			case StringTakeSpecial:
				switch(chr) {
					case 'b':
						*this << '\b';
						break;
					case 'f':
						*this << '\f';
						break;
					case 'n':
						*this << '\n';
						break;
					case 'r':
						*this << '\r';
						break;
					case 't':
						*this << '\t';
						break;
					case 'u':
						parser->TakeOne();
						parser->TakeOne();
						parser->TakeOne();
						parser->TakeOne();
						break;
					default:
						*this << chr;
				}
				break;
		}
	}
}

JsonValue*
JsonParser::TakeValue()
{
	TakeWhitespace();
	switch(Peek()) {
		case '"':
			return ParseNew<JsonString>(this);
			break;
		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
		case '-':
			return ParseNew<JsonNumber>(this);
			break;
		case '[':
			return ParseNew<JsonArray>(this);
			break;
		case '{':
			return ParseNew<JsonObject>(this);
			break;
		case 't':
			TakeOne();
			TakeOne();
			TakeOne();
			TakeOne();
			return new JsonBool(true);
			break;
		case 'f':
			TakeOne();
			TakeOne();
			TakeOne();
			TakeOne();
			TakeOne();
			return new JsonBool(false);
			break;
		case 'n':
			TakeOne();
			TakeOne();
			TakeOne();
			TakeOne();
			return new JsonNull();
			break;
	}
}

void
JsonObject::Parse(JsonParser* parser)
{
	parser->TakeUntil('{');
	parser->TakeOne();
	char chr;
	JsonString* name;
	while (chr = parser->Peek()) {
		if (chr == '}') {
			parser->TakeOne();
			return;
		}
		parser->TakeWhitespace();
		name = ParseNew<JsonString>(parser);
		parser->TakeUntil(':');
		parser->TakeOne();
		AddPair(name, parser->TakeValue());
		parser->TakeWhitespace();
		if(parser->Peek() == ',')
			parser->TakeOne();
		parser->TakeWhitespace();
	}
}

void
JsonArray::Parse(JsonParser* parser)
{
	char chr;
	parser->TakeOne();

	while(chr = parser->Peek()) {
		if(chr == ']') {
			parser->TakeOne();
			return;
		}
		parser->TakeWhitespace();
		AddItem(parser->TakeValue());
		parser->TakeWhitespace();
		if(parser->Peek() == ',')
			parser->TakeOne();
	}
}

JsonValue*
JsonParser::Value()
{
	return fValue;
}
<commit_msg>JSON: Fix string parser<commit_after>#include <File.h>
#include <ObjectList.h>
#include <String.h>
#include <cstdlib>
#include <stdio.h>
#include <cctype>
#include "Json.h"

JsonValue::JsonValue()
{

}

template<class T>
T*
ParseNew(JsonParser* parser)
{
	T* t = new T();
	t->Parse(parser);
	return t;
}

void
JsonValue::Serialize(BString* str)
{

}

void
JsonValue::Parse(JsonParser* parser)
{

}

void
JsonString::Serialize(BString* str)
{
	*str << "\"";
	*str << *this;
	*str << "\"";
}

JsonPair::JsonPair(JsonString* n, JsonValue* v)
	:
	fName(n),
	fValue(v)
{
}

JsonObject::JsonObject()
	:
	fPairList(new BObjectList<JsonPair>())
{

}

void
JsonObject::AddPair(JsonString* str, JsonValue* val)
{
	fPairList->AddItem(new JsonPair(str, val));
}

JsonValue*
JsonObject::Get(BString key)
{
	for(int i = 0; i < fPairList->CountItems(); i++) {
		JsonPair* pair = fPairList->ItemAt(i);
		if(*pair->fName == key)
			return pair->fValue;
	}
	return NULL;
}

void
JsonObject::Serialize(BString* str)
{
	*str << "{";
	for (int i = 0; i < fPairList->CountItems(); i++) {
		JsonPair* pair = fPairList->ItemAt(i);
		pair->fName->Serialize(str);
		*str << ": ";
		pair->fValue->Serialize(str);
		if(i < fPairList->CountItems()-1) {
			*str << ", ";
		}
	}
	*str << "}";
}

void
JsonNumber::Serialize(BString* str)
{
	*str << fDouble;
}

void
JsonArray::Serialize(BString* str)
{
	*str << "[";
	for (int i = 0; i < CountItems(); i++) {
		JsonValue* val = ItemAt(i);
		val->Serialize(str);
		if(i < CountItems()-1) {
			*str << ", ";
		}
	}
	*str << "]";
}

void
JsonBool::Serialize(BString* str)
{
	*str << fVal ? "true" : "false";
}

void
JsonNull::Serialize(BString* str)
{
	*str << "null";
}

void
JsonParser::TakeUntil(char end)
{
	while(Peek() != end)
		TakeOne();
}

JsonParser::JsonParser(BString string)
{
	fPointer = 0;
	fString = string;

	TakeWhitespace();
	char firstChar = Peek();

	JsonValue* thing;
	switch(firstChar) {
		case '{':
			thing = ParseNew<JsonObject>(this);
			break;
		case '[':
			thing = ParseNew<JsonArray>(this);
			break;
	}
	fValue = thing;
}

void
JsonNumber::Parse(JsonParser* parser) {
	BString numberPart;
	parser->TakeWhitespace();
	if(parser->Peek() == '-') {
		numberPart << '-';
		parser->TakeOne();
	}
	while(isdigit(parser->Peek()))
		numberPart << parser->TakeOne();
	if(parser->Peek() == '.') {
		numberPart << '.';
		parser->TakeOne();
	}
	while(isdigit(parser->Peek()))
		numberPart << parser->TakeOne();
	if(parser->Peek() == 'e') {
		numberPart << 'e';
		parser->TakeOne();
	}
	while(isdigit(parser->Peek()))
		numberPart << parser->TakeOne();
	double i = strtod(numberPart.String(), NULL);
	fDouble = i;
}

double
JsonNumber::Value() {
	return fDouble;
}

void
JsonParser::TakeWhitespace() {
	while(Peek() != NULL && isspace(Peek()))
		TakeOne();
}

char
JsonParser::Peek() {
	if(fPointer > fString.Length())
		return NULL;
	return fString[fPointer];
}

char
JsonParser::TakeOne() {
	if(fPointer > fString.Length())
		return NULL;
	return fString[fPointer++];
}

enum States {
	StringTakeChar,
	StringTakeSpecial
};

void
JsonString::Parse(JsonParser* parser)
{
	if(parser->Peek() == '"')
		parser->TakeOne();
	States state = StringTakeChar;

	char chr;
	while(chr = parser->TakeOne()) {
		switch (state) {
			case StringTakeChar:
				switch (chr) {
					case '\\':
						state = StringTakeSpecial;
						break;
					case '"':
						return;
						break;
					default:
						*this << chr;
						break;
				}
				break;
			case StringTakeSpecial:
				switch(chr) {
					case 'b':
						*this << '\b';
						break;
					case 'f':
						*this << '\f';
						break;
					case 'n':
						*this << '\n';
						break;
					case 'r':
						*this << '\r';
						break;
					case 't':
						*this << '\t';
						break;
					case 'u':
						parser->TakeOne();
						parser->TakeOne();
						parser->TakeOne();
						parser->TakeOne();
						break;
					default:
						*this << chr;
				}
				state = StringTakeChar;
				break;
		}
	}
}

JsonValue*
JsonParser::TakeValue()
{
	TakeWhitespace();
	switch(Peek()) {
		case '"':
			return ParseNew<JsonString>(this);
			break;
		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
		case '-':
			return ParseNew<JsonNumber>(this);
			break;
		case '[':
			return ParseNew<JsonArray>(this);
			break;
		case '{':
			return ParseNew<JsonObject>(this);
			break;
		case 't':
			TakeOne();
			TakeOne();
			TakeOne();
			TakeOne();
			return new JsonBool(true);
			break;
		case 'f':
			TakeOne();
			TakeOne();
			TakeOne();
			TakeOne();
			TakeOne();
			return new JsonBool(false);
			break;
		case 'n':
			TakeOne();
			TakeOne();
			TakeOne();
			TakeOne();
			return new JsonNull();
			break;
	}
}

void
JsonObject::Parse(JsonParser* parser)
{
	parser->TakeUntil('{');
	parser->TakeOne();
	char chr;
	JsonString* name;
	while (chr = parser->Peek()) {
		if (chr == '}') {
			parser->TakeOne();
			return;
		}
		parser->TakeWhitespace();
		name = ParseNew<JsonString>(parser);
		parser->TakeUntil(':');
		parser->TakeOne();
		AddPair(name, parser->TakeValue());
		parser->TakeWhitespace();
		if(parser->Peek() == ',')
			parser->TakeOne();
		parser->TakeWhitespace();
	}
}

void
JsonArray::Parse(JsonParser* parser)
{
	char chr;
	parser->TakeOne();

	while(chr = parser->Peek()) {
		if(chr == ']') {
			parser->TakeOne();
			return;
		}
		parser->TakeWhitespace();
		AddItem(parser->TakeValue());
		parser->TakeWhitespace();
		if(parser->Peek() == ',')
			parser->TakeOne();
	}
}

JsonValue*
JsonParser::Value()
{
	return fValue;
}
<|endoftext|>


<commit_before>//
//  Created by Derek van Vliet on 2015-03-16.
//  Copyright (c) 2015 Get Set Games Inc. All rights reserved.
//

#include "BlueprintSoundPrivatePCH.h"

#if PLATFORM_IOS
#include <AVFoundation/AVAudioSession.h>
#elif PLATFORM_ANDROID

#endif

void UBlueprintSoundFunctions::SetSoundClassVolume(USoundClass* SoundClass, float Volume)
{
	if (SoundClass)
	{
		SoundClass->Properties.Volume = Volume;
	}
}

float UBlueprintSoundFunctions::GetSoundClassVolume(USoundClass* SoundClass)
{
	if (SoundClass)
	{
		return SoundClass->Properties.Volume;
	}

	return 0.0f;
}

void UBlueprintSoundFunctions::SetSoundClassPitch(USoundClass* SoundClass, float Pitch)
{
	if (SoundClass)
	{
		SoundClass->Properties.Pitch = Pitch;
	}
}

float UBlueprintSoundFunctions::GetSoundClassPitch(USoundClass* SoundClass)
{
	if (SoundClass)
	{
		return SoundClass->Properties.Pitch;
	}

	return 0.0f;
}

bool UBlueprintSoundFunctions::IsExternalBackgroundSoundActive()
{
#if PLATFORM_IOS
	return [[AVAudioSession sharedInstance] isOtherAudioPlaying];
#elif PLATFORM_ANDROID

#endif

	return false;
}<commit_msg>added support for checking if external audio is playing on android<commit_after>//
//  Created by Derek van Vliet on 2015-03-16.
//  Copyright (c) 2015 Get Set Games Inc. All rights reserved.
//

#include "BlueprintSoundPrivatePCH.h"

#if PLATFORM_IOS
#include <AVFoundation/AVAudioSession.h>
#elif PLATFORM_ANDROID

#endif

void UBlueprintSoundFunctions::SetSoundClassVolume(USoundClass* SoundClass, float Volume)
{
	if (SoundClass)
	{
		SoundClass->Properties.Volume = Volume;
	}
}

float UBlueprintSoundFunctions::GetSoundClassVolume(USoundClass* SoundClass)
{
	if (SoundClass)
	{
		return SoundClass->Properties.Volume;
	}

	return 0.0f;
}

void UBlueprintSoundFunctions::SetSoundClassPitch(USoundClass* SoundClass, float Pitch)
{
	if (SoundClass)
	{
		SoundClass->Properties.Pitch = Pitch;
	}
}

float UBlueprintSoundFunctions::GetSoundClassPitch(USoundClass* SoundClass)
{
	if (SoundClass)
	{
		return SoundClass->Properties.Pitch;
	}

	return 0.0f;
}

bool UBlueprintSoundFunctions::IsExternalBackgroundSoundActive()
{
#if PLATFORM_IOS
	return [[AVAudioSession sharedInstance] isOtherAudioPlaying];
#elif PLATFORM_ANDROID
	extern bool AndroidThunkCpp_IsMusicActive();
	return AndroidThunkCpp_IsMusicActive();
#endif

	return false;
}<|endoftext|>


<commit_before>#include "linedetector.h"
#include <pcl_ros/point_cloud.h>
#include <igvc/CVUtils.hpp>

cv_bridge::CvImagePtr cv_ptr;
typedef pcl::PointCloud<pcl::PointXYZ> PCLCloud;

void LineDetector::info_img_callback(const sensor_msgs::ImageConstPtr& msg, const sensor_msgs::CameraInfoConstPtr& cam_info) {
    cam.fromCameraInfo(cam_info);
    img_callback(msg);
}

void LineDetector::img_callback(const sensor_msgs::ImageConstPtr& msg) {
    cv_ptr = cv_bridge::toCvCopy(msg, "");
    src_img = cv_ptr->image;

    cv::resize(src_img, src_img, cv::Size(524, 524), 0, 0, CV_INTER_AREA);
    fin_img = cv::Mat::zeros(src_img.size(), src_img.type());

    cv::GaussianBlur(src_img, working, cv::Size(0,0), 2.0);

    cv::Canny(working, working, 45, 135, 3);

    std::vector<cv::Vec4i> lines;
    cv::HoughLinesP(working, lines, 1.0, CV_PI/180, 80, 35, 15);
    for (size_t i = 0; i < lines.size(); ++i) {
        line(fin_img, cv::Point(lines[i][0], lines[i][1]), cv::Point(lines[i][2], lines[i][3]), cv::Scalar(255, 255, 255), 3, 8);
    }

    if (hasInfo) {
        cloud = toPointCloud(tf_listener, MatToContours(fin_img), cam, topic);
    } else {
        cloud = toPointCloud(tf_listener, MatToContours(fin_img), fin_img.size().height, fin_img.size().width, topic);
    }
    _line_cloud.publish(cloud);

    cv_ptr->image = fin_img;
    _filt_img.publish(cv_ptr->toImageMsg());
}

LineDetector::LineDetector(ros::NodeHandle &handle, const std::string& topic)
      : _it(handle)
      , topic(topic)
      , tf_listener(handle)
{
     if (!hasInfo) {
        _src_img = _it.subscribe(topic + "/image_raw", 1, &LineDetector::img_callback, this);
     } else {
        _src_img_info = _it.subscribeCamera(topic + "/image_raw", 1, &LineDetector::info_img_callback, this);
     }
    _filt_img = _it.advertise(topic + "/filt_img", 1);
    _line_cloud = handle.advertise<PCLCloud>(topic + "/line_cloud", 100);
}

<commit_msg>Added grayscale to line detector, needed<commit_after>#include "linedetector.h"
#include <pcl_ros/point_cloud.h>
#include <igvc/CVUtils.hpp>

cv_bridge::CvImagePtr cv_ptr;
typedef pcl::PointCloud<pcl::PointXYZ> PCLCloud;

void LineDetector::info_img_callback(const sensor_msgs::ImageConstPtr& msg, const sensor_msgs::CameraInfoConstPtr& cam_info) {
    cam.fromCameraInfo(cam_info);
    img_callback(msg);
}

void LineDetector::img_callback(const sensor_msgs::ImageConstPtr& msg) {
    cv_ptr = cv_bridge::toCvCopy(msg, "");
    src_img = cv_ptr->image;

    cv::cvtColor(src_img, src_img, CV_BGR2GRAY);

    cv::resize(src_img, src_img, cv::Size(524, 524), 0, 0, CV_INTER_AREA);
    fin_img = cv::Mat::zeros(src_img.size(), src_img.type());

    cv::GaussianBlur(src_img, working, cv::Size(0,0), 2.0);

    cv::Canny(working, working, 45, 135, 3);

    std::vector<cv::Vec4i> lines;
    cv::HoughLinesP(working, lines, 1.0, CV_PI/180, 80, 35, 15);
    for (size_t i = 0; i < lines.size(); ++i) {
        line(fin_img, cv::Point(lines[i][0], lines[i][1]), cv::Point(lines[i][2], lines[i][3]), cv::Scalar(255, 255, 255), 3, 8);
    }

    if (hasInfo) {
        cloud = toPointCloud(tf_listener, MatToContours(fin_img), cam, topic);
    } else {
        cloud = toPointCloud(tf_listener, MatToContours(fin_img), fin_img.size().height, fin_img.size().width, topic);
    }
    _line_cloud.publish(cloud);

    cv::cvtColor(fin_img, fin_img, CV_GRAY2BGR);

    cv_ptr->image = fin_img;
    _filt_img.publish(cv_ptr->toImageMsg());
}

LineDetector::LineDetector(ros::NodeHandle &handle, const std::string& topic)
      : _it(handle)
      , topic(topic)
      , tf_listener(handle)
{
     if (!hasInfo) {
        _src_img = _it.subscribe(topic + "/image_raw", 1, &LineDetector::img_callback, this);
     } else {
        _src_img_info = _it.subscribeCamera(topic + "/image_raw", 1, &LineDetector::info_img_callback, this);
     }
    _filt_img = _it.advertise(topic + "/filt_img", 1);
    _line_cloud = handle.advertise<PCLCloud>(topic + "/line_cloud", 100);
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 New Designs Unlimited, LLC
 * Opensource Automated License Plate Recognition [http://www.openalpr.com]
 *
 * This file is part of OpenAlpr.
 *
 * OpenAlpr is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License
 * version 3 as published by the Free Software Foundation
 *
 * 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "videobuffer.h"

void imageCollectionThread(void* arg);
void getALPRImages(cv::VideoCapture cap, VideoDispatcher* dispatcher);

VideoBuffer::VideoBuffer()
{
  dispatcher = NULL;

}

VideoBuffer::~VideoBuffer()
{
  if (dispatcher != NULL)
  {
    dispatcher->active = false;
  }
}

VideoDispatcher* VideoBuffer::createDispatcher(std::string mjpeg_url, int fps)
{
  return new VideoDispatcher(mjpeg_url, fps);
}

void VideoBuffer::connect(std::string mjpeg_url, int fps)
{

    if (hasEnding(mjpeg_url, ".mjpg") == false)
    {
      // The filename doesn't end with ".mjpg" so the downstream processing may not treat it as such
      // OpenCV doesn't have a way to force the rendering, other than via URL path.  So, let's add it to the URL

      std::size_t found = mjpeg_url.find("?");
      if (found!=std::string::npos)
      {
	// URL already contains a "?"
	mjpeg_url = mjpeg_url + "&openalprfiletype=file.mjpg";
      }
      else
      {
	// URL does not contain a "?"
	mjpeg_url = mjpeg_url + "?openalprfiletype=file.mjpg";
      }

    }

    dispatcher = createDispatcher(mjpeg_url, fps);

    tthread::thread* t = new tthread::thread(imageCollectionThread, (void*) dispatcher);

}

int VideoBuffer::getLatestFrame(cv::Mat* frame, std::vector<cv::Rect>& regionsOfInterest)
{
  if (dispatcher == NULL)
    return -1;

  return dispatcher->getLatestFrame(frame, regionsOfInterest);
}

void VideoBuffer::disconnect()
{
  if (dispatcher != NULL)
  {
    dispatcher->active = false;
  }

  dispatcher = NULL;
}

void imageCollectionThread(void* arg)
{

  VideoDispatcher* dispatcher = (VideoDispatcher*) arg;

  while (dispatcher->active)
  {
    try
    {
      cv::VideoCapture cap=cv::VideoCapture();
	  std::cout << "Connecting..." << std::endl;
	  cap.open(dispatcher->mjpeg_url);

      if (cap.isOpened())
      {
		  std::cout << "Connected" << std::endl;
		  getALPRImages(cap, dispatcher);
      }
      else
      {
	std::stringstream ss;
	ss << "Stream " << dispatcher->mjpeg_url << " failed to open.";
	dispatcher->log_error(ss.str());
      }

    }
    catch (const std::runtime_error& error)
    {
      // Error occured while trying to gather image.  Retry, don't exit.
      std::stringstream ss;
      ss << "VideoBuffer exception: " << error.what();
      dispatcher->log_error( ss.str() );
    }
    catch (cv::Exception e)
    {
      // OpenCV Exception occured while trying to gather image.  Retry, don't exit.
      std::stringstream ss;
      ss << "VideoBuffer OpenCV exception: " << e.what();
      dispatcher->log_error( ss.str() );
    }

    // Delay 1 second
    sleep_ms(1000);

  }

}

// Continuously grabs images from the video capture.  If there is an error,
// it returns so that the video capture can be recreated.
void getALPRImages(cv::VideoCapture cap, VideoDispatcher* dispatcher)
{
  cv::Mat frame;

  while (dispatcher->active)
  {
    while (dispatcher->active)
    {

      bool hasImage = false;
      try
      {
	hasImage = cap.read(frame);
	// Double check the image to make sure it's valid.
	if (!frame.data || frame.empty())
	{
	  std::stringstream ss;
	  ss << "Stream " << dispatcher->mjpeg_url << " received invalid frame";
	  dispatcher->log_error(ss.str());
	  return;
	}

	dispatcher->mMutex.lock();
	dispatcher->setLatestFrame(&frame);
	dispatcher->mMutex.unlock();
	  }
      catch (const std::runtime_error& error)
      {
	// Error occured while trying to gather image.  Retry, don't exit.
	std::stringstream ss;
	ss << "Exception happened " <<  error.what();
	dispatcher->log_error(ss.str());
	dispatcher->mMutex.unlock();
	return;
      }

      dispatcher->mMutex.unlock();

      if (hasImage == false)
	break;

      // Delay 15ms
      sleep_ms(15);
    }

    // Delay 100ms
    sleep_ms(100);
  }
}<commit_msg>Revert "Only lock  when needed."<commit_after>/*
 * Copyright (c) 2014 New Designs Unlimited, LLC
 * Opensource Automated License Plate Recognition [http://www.openalpr.com]
 *
 * This file is part of OpenAlpr.
 *
 * OpenAlpr is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License
 * version 3 as published by the Free Software Foundation
 *
 * 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "videobuffer.h"

void imageCollectionThread(void* arg);
void getALPRImages(cv::VideoCapture cap, VideoDispatcher* dispatcher);

VideoBuffer::VideoBuffer()
{
  dispatcher = NULL;

}

VideoBuffer::~VideoBuffer()
{
  if (dispatcher != NULL)
  {
    dispatcher->active = false;
  }
}

VideoDispatcher* VideoBuffer::createDispatcher(std::string mjpeg_url, int fps)
{
  return new VideoDispatcher(mjpeg_url, fps);
}

void VideoBuffer::connect(std::string mjpeg_url, int fps)
{

    if (hasEnding(mjpeg_url, ".mjpg") == false)
    {
      // The filename doesn't end with ".mjpg" so the downstream processing may not treat it as such
      // OpenCV doesn't have a way to force the rendering, other than via URL path.  So, let's add it to the URL

      std::size_t found = mjpeg_url.find("?");
      if (found!=std::string::npos)
      {
	// URL already contains a "?"
	mjpeg_url = mjpeg_url + "&openalprfiletype=file.mjpg";
      }
      else
      {
	// URL does not contain a "?"
	mjpeg_url = mjpeg_url + "?openalprfiletype=file.mjpg";
      }

    }

    dispatcher = createDispatcher(mjpeg_url, fps);

    tthread::thread* t = new tthread::thread(imageCollectionThread, (void*) dispatcher);

}

int VideoBuffer::getLatestFrame(cv::Mat* frame, std::vector<cv::Rect>& regionsOfInterest)
{
  if (dispatcher == NULL)
    return -1;

  return dispatcher->getLatestFrame(frame, regionsOfInterest);
}

void VideoBuffer::disconnect()
{
  if (dispatcher != NULL)
  {
    dispatcher->active = false;
  }

  dispatcher = NULL;
}

void imageCollectionThread(void* arg)
{

  VideoDispatcher* dispatcher = (VideoDispatcher*) arg;

  while (dispatcher->active)
  {
    try
    {
      cv::VideoCapture cap=cv::VideoCapture();
	  std::cout << "Connecting..." << std::endl;
	  cap.open(dispatcher->mjpeg_url);

      if (cap.isOpened())
      {
		  std::cout << "Connected" << std::endl;
		  getALPRImages(cap, dispatcher);
      }
      else
      {
	std::stringstream ss;
	ss << "Stream " << dispatcher->mjpeg_url << " failed to open.";
	dispatcher->log_error(ss.str());
      }

    }
    catch (const std::runtime_error& error)
    {
      // Error occured while trying to gather image.  Retry, don't exit.
      std::stringstream ss;
      ss << "VideoBuffer exception: " << error.what();
      dispatcher->log_error( ss.str() );
    }
    catch (cv::Exception e)
    {
      // OpenCV Exception occured while trying to gather image.  Retry, don't exit.
      std::stringstream ss;
      ss << "VideoBuffer OpenCV exception: " << e.what();
      dispatcher->log_error( ss.str() );
    }

    // Delay 1 second
    sleep_ms(1000);

  }

}

// Continuously grabs images from the video capture.  If there is an error,
// it returns so that the video capture can be recreated.
void getALPRImages(cv::VideoCapture cap, VideoDispatcher* dispatcher)
{
  cv::Mat frame;

  while (dispatcher->active)
  {
    while (dispatcher->active)
    {

      dispatcher->mMutex.lock();
      bool hasImage = false;
      try
      {
	hasImage = cap.read(frame);
	// Double check the image to make sure it's valid.
	if (!frame.data || frame.empty())
	{
	  dispatcher->mMutex.unlock();
	  std::stringstream ss;
	  ss << "Stream " << dispatcher->mjpeg_url << " received invalid frame";
	  dispatcher->log_error(ss.str());
	  return;
	}

	dispatcher->setLatestFrame(&frame);
      }
      catch (const std::runtime_error& error)
      {
	// Error occured while trying to gather image.  Retry, don't exit.
	std::stringstream ss;
	ss << "Exception happened " <<  error.what();
	dispatcher->log_error(ss.str());
	dispatcher->mMutex.unlock();
	return;
      }

      dispatcher->mMutex.unlock();

      if (hasImage == false)
	break;

      // Delay 15ms
      sleep_ms(15);
    }

    // Delay 100ms
    sleep_ms(100);
  }
}<|endoftext|>


<commit_before>/*****************************************************************************
 * standardpanel.cpp : The "standard" playlist panel : just a treeview
 ****************************************************************************
 * Copyright (C) 2000-2009 VideoLAN
 * $Id$
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
 *          JB Kempf <jb@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it 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.
 *****************************************************************************/

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include "dialogs_provider.hpp"

#include "components/playlist/playlist_model.hpp"
#include "components/playlist/standardpanel.hpp"
#include "components/playlist/icon_view.hpp"
#include "util/customwidgets.hpp"

#include <vlc_intf_strings.h>

#include <QPushButton>
#include <QHeaderView>
#include <QKeyEvent>
#include <QModelIndexList>
#include <QLabel>
#include <QMenu>
#include <QSignalMapper>
#include <QWheelEvent>
#include <QToolButton>
#include <QFontMetrics>

#include <assert.h>

#include "sorting.h"

StandardPLPanel::StandardPLPanel( PlaylistWidget *_parent,
                                  intf_thread_t *_p_intf,
                                  playlist_t *p_playlist,
                                  playlist_item_t *p_root ):
                                  QWidget( _parent ), p_intf( _p_intf )
{
    layout = new QGridLayout( this );
    layout->setSpacing( 0 ); layout->setMargin( 0 );
    setMinimumWidth( 300 );

    model = new PLModel( p_playlist, p_intf, p_root, this );
    CONNECT( model, currentChanged( const QModelIndex& ),
             this, handleExpansion( const QModelIndex& ) );

    iconView = NULL;
    treeView = NULL;

    currentRootId = -1;

    /* Title label */
    /*title = new QLabel;
    QFont titleFont;
    titleFont.setPointSize( titleFont.pointSize() + 6 );
    titleFont.setFamily( "Verdana" );
    title->setFont( titleFont );
    layout->addWidget( title, 0, 0 );*/

    locationBar = new LocationBar( model );
    layout->addWidget( locationBar, 0, 0 );

    /* A Spacer and the search possibilities */
    layout->setColumnStretch( 1, 10 );

    SearchLineEdit *search = new SearchLineEdit( this );
    search->setMaximumWidth( 300 );
    layout->addWidget( search, 0, 4 );
    CONNECT( search, textChanged( const QString& ),
             this, search( const QString& ) );
    layout->setColumnStretch( 4, 2 );

    /* Add item to the playlist button */
    addButton = new QPushButton;
    addButton->setIcon( QIcon( ":/buttons/playlist/playlist_add" ) );
    addButton->setMaximumWidth( 30 );
    BUTTONACT( addButton, popupAdd() );
    layout->addWidget( addButton, 0, 3 );

    QPushButton *viewButton = new QPushButton( this );
    viewButton->setIcon( QIcon( ":/buttons/playlist/playlist_add" ) );
    layout->addWidget( viewButton, 0, 2 );
    BUTTONACT( viewButton, toggleView() );

    /* Saved Settings */
    getSettings()->beginGroup("Playlist");

    int i_viewMode = getSettings()->value( "view-mode", TREE_VIEW ).toInt();
    if( i_viewMode == ICON_VIEW )
    {
        createIconView();
        currentView = iconView;
    }
    else
    {
        createTreeView();
        currentView = treeView;
    }

    getSettings()->endGroup();

    last_activated_id = -1;
    CONNECT( THEMIM, inputChanged( input_thread_t * ),
             this, handleInputChange( input_thread_t * ) );
}

StandardPLPanel::~StandardPLPanel()
{
    getSettings()->beginGroup("Playlist");
    if( treeView )
        getSettings()->setValue( "headerStateV2", treeView->header()->saveState() );
    getSettings()->setValue( "view-mode", ( currentView == iconView ) ? ICON_VIEW : TREE_VIEW );
    getSettings()->endGroup();
}

/* Unused anymore, but might be useful, like in right-click menu */
void StandardPLPanel::gotoPlayingItem()
{
    currentView->scrollTo( model->currentIndex() );
}

void StandardPLPanel::handleExpansion( const QModelIndex& index )
{
    assert( currentView );
    currentView->scrollTo( index );
}

/* PopupAdd Menu for the Add Menu */
void StandardPLPanel::popupAdd()
{
    QMenu popup;
    if( currentRootId == THEPL->p_local_category->i_id ||
        currentRootId == THEPL->p_local_onelevel->i_id )
    {
        popup.addAction( qtr(I_PL_ADDF), THEDP, SLOT( simplePLAppendDialog()) );
        popup.addAction( qtr(I_PL_ADDDIR), THEDP, SLOT( PLAppendDir()) );
        popup.addAction( qtr(I_OP_ADVOP), THEDP, SLOT( PLAppendDialog()) );
    }
    else if( ( THEPL->p_ml_category &&
                currentRootId == THEPL->p_ml_category->i_id ) ||
             ( THEPL->p_ml_onelevel &&
                currentRootId == THEPL->p_ml_onelevel->i_id ) )
    {
        popup.addAction( qtr(I_PL_ADDF), THEDP, SLOT( simpleMLAppendDialog()) );
        popup.addAction( qtr(I_PL_ADDDIR), THEDP, SLOT( MLAppendDir() ) );
        popup.addAction( qtr(I_OP_ADVOP), THEDP, SLOT( MLAppendDialog() ) );
    }

    popup.exec( QCursor::pos() - addButton->mapFromGlobal( QCursor::pos() )
                        + QPoint( 0, addButton->height() ) );
}

void StandardPLPanel::popupPlView( const QPoint &point )
{
    QModelIndex index = currentView->indexAt( point );
    QPoint globalPoint = currentView->viewport()->mapToGlobal( point );
    QItemSelectionModel *selection = currentView->selectionModel();
    QModelIndexList list = selection->selectedIndexes();
    model->popup( index, globalPoint, list );
}

void StandardPLPanel::popupSelectColumn( QPoint pos )
{
    QMenu menu;
    assert( treeView );

    /* We do not offer the option to hide index 0 column, or
    * QTreeView will behave weird */
    int i, j;
    for( i = 1 << 1, j = 1; i < COLUMN_END; i <<= 1, j++ )
    {
        QAction* option = menu.addAction(
            qfu( psz_column_title( i ) ) );
        option->setCheckable( true );
        option->setChecked( !treeView->isColumnHidden( j ) );
        selectColumnsSigMapper->setMapping( option, j );
        CONNECT( option, triggered(), selectColumnsSigMapper, map() );
    }
    menu.exec( QCursor::pos() );
}

void StandardPLPanel::toggleColumnShown( int i )
{
    treeView->setColumnHidden( i, !treeView->isColumnHidden( i ) );
}

/* Search in the playlist */
void StandardPLPanel::search( const QString& searchText )
{
    model->search( searchText );
}

/* Set the root of the new Playlist */
/* This activated by the selector selection */
void StandardPLPanel::setRoot( playlist_item_t *p_item )
{
    QPL_LOCK;
    assert( p_item );

    playlist_item_t *p_pref_item = playlist_GetPreferredNode( THEPL, p_item );
    if( p_pref_item ) p_item = p_pref_item;

    /* needed for popupAdd() */
    currentRootId = p_item->i_id;

    /* cosmetics, ..still need playlist locking.. */
    /*char *psz_title = input_item_GetName( p_item->p_input );
    title->setText( qfu(psz_title) );
    free( psz_title );*/

    QPL_UNLOCK;

    /* do THE job */
    model->rebuild( p_item );

    locationBar->setIndex( QModelIndex() );

    /* enable/disable adding */
    if( p_item == THEPL->p_local_category ||
        p_item == THEPL->p_local_onelevel )
    {
        addButton->setEnabled( true );
        addButton->setToolTip( qtr(I_PL_ADDPL) );
    }
    else if( ( THEPL->p_ml_category && p_item == THEPL->p_ml_category) ||
              ( THEPL->p_ml_onelevel && p_item == THEPL->p_ml_onelevel ) )
    {
        addButton->setEnabled( true );
        addButton->setToolTip( qtr(I_PL_ADDML) );
    }
    else
        addButton->setEnabled( false );
}

void StandardPLPanel::removeItem( int i_id )
{
    model->removeItem( i_id );
}

/* Delete and Suppr key remove the selection
   FilterKey function and code function */
void StandardPLPanel::keyPressEvent( QKeyEvent *e )
{
    switch( e->key() )
    {
    case Qt::Key_Back:
    case Qt::Key_Delete:
        deleteSelection();
        break;
    }
}

void StandardPLPanel::deleteSelection()
{
    QItemSelectionModel *selection = currentView->selectionModel();
    QModelIndexList list = selection->selectedIndexes();
    model->doDelete( list );
}

void StandardPLPanel::createIconView()
{
    iconView = new PlIconView( model, this );
    iconView->setContextMenuPolicy( Qt::CustomContextMenu );
    CONNECT( iconView, customContextMenuRequested( const QPoint & ),
             this, popupPlView( const QPoint & ) );
    CONNECT( iconView, activated( const QModelIndex & ),
             this, activate( const QModelIndex & ) );
    CONNECT( locationBar, invoked( const QModelIndex & ),
             iconView, setRootIndex( const QModelIndex & ) );

    layout->addWidget( iconView, 1, 0, 1, -1 );
}

void StandardPLPanel::createTreeView()
{
    /* Create and configure the QTreeView */
    treeView = new QTreeView;

    treeView->setIconSize( QSize( 20, 20 ) );
    treeView->setAlternatingRowColors( true );
    treeView->setAnimated( true );
    treeView->setUniformRowHeights( true );
    treeView->setSortingEnabled( true );
    treeView->header()->setSortIndicator( -1 , Qt::AscendingOrder );
    treeView->header()->setSortIndicatorShown( true );
    treeView->header()->setClickable( true );
    treeView->header()->setContextMenuPolicy( Qt::CustomContextMenu );

    treeView->setSelectionBehavior( QAbstractItemView::SelectRows );
    treeView->setSelectionMode( QAbstractItemView::ExtendedSelection );
    treeView->setDragEnabled( true );
    treeView->setAcceptDrops( true );
    treeView->setDropIndicatorShown( true );
    treeView->setContextMenuPolicy( Qt::CustomContextMenu );

    /* setModel after setSortingEnabled(true), or the model will sort immediately! */
    treeView->setModel( model );

    if( getSettings()->contains( "headerStateV2" ) )
    {
        treeView->header()->restoreState(
                getSettings()->value( "headerStateV2" ).toByteArray() );
    }
    else
    {
        for( int m = 1, c = 0; m != COLUMN_END; m <<= 1, c++ )
        {
            treeView->setColumnHidden( c, !( m & COLUMN_DEFAULT ) );
            if( m == COLUMN_TITLE ) treeView->header()->resizeSection( c, 200 );
            else if( m == COLUMN_DURATION ) treeView->header()->resizeSection( c, 80 );
        }
    }

    /* Connections for the TreeView */
    CONNECT( treeView, activated( const QModelIndex& ),
             this, activate( const QModelIndex& ) );
    CONNECT( treeView->header(), customContextMenuRequested( const QPoint & ),
             this, popupSelectColumn( QPoint ) );
    CONNECT( treeView, customContextMenuRequested( const QPoint & ),
             this, popupPlView( const QPoint & ) );

    /* SignalMapper for columns */
    selectColumnsSigMapper = new QSignalMapper( this );
    CONNECT( selectColumnsSigMapper, mapped( int ),
             this, toggleColumnShown( int ) );

    /* Finish the layout */
    layout->addWidget( treeView, 1, 0, 1, -1 );
}

void StandardPLPanel::toggleView()
{
    if( treeView && treeView->isVisible() )
    {
        if( iconView == NULL )
            createIconView();

        locationBar->setIndex( iconView->rootIndex() );
        treeView->hide();
        iconView->show();
        currentView = iconView;
    }
    else
    {
        if( treeView == NULL )
            createTreeView();

        locationBar->setIndex( treeView->rootIndex() );
        iconView->hide();
        treeView->show();
        currentView = treeView;
    }
}

void StandardPLPanel::wheelEvent( QWheelEvent *e )
{
    // Accept this event in order to prevent unwanted volume up/down changes
    e->accept();
}

void StandardPLPanel::activate( const QModelIndex &index )
{
    last_activated_id = model->itemId( index );
    if( model->hasChildren( index ) )
    {
        if( currentView == iconView ) {
            iconView->setRootIndex( index );
            //title->setText( index.data().toString() );
            locationBar->setIndex( index );
        }
    }
    else
    {
        model->activateItem( index );
    }
}

void StandardPLPanel::handleInputChange( input_thread_t *p_input_thread )
{
    if( currentView != iconView ) return;

    input_item_t *p_input_item = input_GetItem( p_input_thread );
    if( !p_input_item ) return;

    playlist_Lock( THEPL );

    playlist_item_t *p_item = playlist_ItemGetByInput( THEPL, p_input_item );

    if( p_item  && p_item->p_parent &&
        p_item->p_parent->i_id == last_activated_id )
    {
        QModelIndex index = model->index( p_item->p_parent->i_id, 0 );
        iconView->setRootIndex( index );
        //title->setText( index.data().toString() );
        locationBar->setIndex( index );
        last_activated_id = p_item->i_id;
    }

    playlist_Unlock( THEPL );
}

LocationBar::LocationBar( PLModel *m )
{
  model = m;
  mapper = new QSignalMapper;
  CONNECT( mapper, mapped( int ), this, invoke( int ) );
}

void LocationBar::setIndex( const QModelIndex &index )
{
  clear();
  QAction *prev = NULL;
  QModelIndex i = index;
  QFont font;
  QFontMetrics metrics( font );
  while( true )
  {
      QToolButton *btn = new QToolButton;
      PLItem *item = model->getItem( i );
      QString text = qfu(input_item_GetTitleFbName( item->inputItem() ));
      text = QString("/ ") + metrics.elidedText( text, Qt::ElideRight, 150 );
      btn->setText( text );
      btn->setToolButtonStyle( Qt::ToolButtonTextBesideIcon );
      prev = insertWidget( prev, btn );

      mapper->setMapping( btn, item->id() );
      CONNECT( btn, clicked( ), mapper, map( ) );

      if( i.isValid() ) i = i.parent();
      else break;
  }
}

void LocationBar::invoke( int i_id )
{
  QModelIndex index = model->index( i_id, 0 );
  emit invoked ( index );
}
<commit_msg>fix memleak<commit_after>/*****************************************************************************
 * standardpanel.cpp : The "standard" playlist panel : just a treeview
 ****************************************************************************
 * Copyright (C) 2000-2009 VideoLAN
 * $Id$
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
 *          JB Kempf <jb@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it 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.
 *****************************************************************************/

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include "dialogs_provider.hpp"

#include "components/playlist/playlist_model.hpp"
#include "components/playlist/standardpanel.hpp"
#include "components/playlist/icon_view.hpp"
#include "util/customwidgets.hpp"

#include <vlc_intf_strings.h>

#include <QPushButton>
#include <QHeaderView>
#include <QKeyEvent>
#include <QModelIndexList>
#include <QLabel>
#include <QMenu>
#include <QSignalMapper>
#include <QWheelEvent>
#include <QToolButton>
#include <QFontMetrics>

#include <assert.h>

#include "sorting.h"

StandardPLPanel::StandardPLPanel( PlaylistWidget *_parent,
                                  intf_thread_t *_p_intf,
                                  playlist_t *p_playlist,
                                  playlist_item_t *p_root ):
                                  QWidget( _parent ), p_intf( _p_intf )
{
    layout = new QGridLayout( this );
    layout->setSpacing( 0 ); layout->setMargin( 0 );
    setMinimumWidth( 300 );

    model = new PLModel( p_playlist, p_intf, p_root, this );
    CONNECT( model, currentChanged( const QModelIndex& ),
             this, handleExpansion( const QModelIndex& ) );

    iconView = NULL;
    treeView = NULL;

    currentRootId = -1;

    /* Title label */
    /*title = new QLabel;
    QFont titleFont;
    titleFont.setPointSize( titleFont.pointSize() + 6 );
    titleFont.setFamily( "Verdana" );
    title->setFont( titleFont );
    layout->addWidget( title, 0, 0 );*/

    locationBar = new LocationBar( model );
    layout->addWidget( locationBar, 0, 0 );

    /* A Spacer and the search possibilities */
    layout->setColumnStretch( 1, 10 );

    SearchLineEdit *search = new SearchLineEdit( this );
    search->setMaximumWidth( 300 );
    layout->addWidget( search, 0, 4 );
    CONNECT( search, textChanged( const QString& ),
             this, search( const QString& ) );
    layout->setColumnStretch( 4, 2 );

    /* Add item to the playlist button */
    addButton = new QPushButton;
    addButton->setIcon( QIcon( ":/buttons/playlist/playlist_add" ) );
    addButton->setMaximumWidth( 30 );
    BUTTONACT( addButton, popupAdd() );
    layout->addWidget( addButton, 0, 3 );

    QPushButton *viewButton = new QPushButton( this );
    viewButton->setIcon( QIcon( ":/buttons/playlist/playlist_add" ) );
    layout->addWidget( viewButton, 0, 2 );
    BUTTONACT( viewButton, toggleView() );

    /* Saved Settings */
    getSettings()->beginGroup("Playlist");

    int i_viewMode = getSettings()->value( "view-mode", TREE_VIEW ).toInt();
    if( i_viewMode == ICON_VIEW )
    {
        createIconView();
        currentView = iconView;
    }
    else
    {
        createTreeView();
        currentView = treeView;
    }

    getSettings()->endGroup();

    last_activated_id = -1;
    CONNECT( THEMIM, inputChanged( input_thread_t * ),
             this, handleInputChange( input_thread_t * ) );
}

StandardPLPanel::~StandardPLPanel()
{
    getSettings()->beginGroup("Playlist");
    if( treeView )
        getSettings()->setValue( "headerStateV2", treeView->header()->saveState() );
    getSettings()->setValue( "view-mode", ( currentView == iconView ) ? ICON_VIEW : TREE_VIEW );
    getSettings()->endGroup();
}

/* Unused anymore, but might be useful, like in right-click menu */
void StandardPLPanel::gotoPlayingItem()
{
    currentView->scrollTo( model->currentIndex() );
}

void StandardPLPanel::handleExpansion( const QModelIndex& index )
{
    assert( currentView );
    currentView->scrollTo( index );
}

/* PopupAdd Menu for the Add Menu */
void StandardPLPanel::popupAdd()
{
    QMenu popup;
    if( currentRootId == THEPL->p_local_category->i_id ||
        currentRootId == THEPL->p_local_onelevel->i_id )
    {
        popup.addAction( qtr(I_PL_ADDF), THEDP, SLOT( simplePLAppendDialog()) );
        popup.addAction( qtr(I_PL_ADDDIR), THEDP, SLOT( PLAppendDir()) );
        popup.addAction( qtr(I_OP_ADVOP), THEDP, SLOT( PLAppendDialog()) );
    }
    else if( ( THEPL->p_ml_category &&
                currentRootId == THEPL->p_ml_category->i_id ) ||
             ( THEPL->p_ml_onelevel &&
                currentRootId == THEPL->p_ml_onelevel->i_id ) )
    {
        popup.addAction( qtr(I_PL_ADDF), THEDP, SLOT( simpleMLAppendDialog()) );
        popup.addAction( qtr(I_PL_ADDDIR), THEDP, SLOT( MLAppendDir() ) );
        popup.addAction( qtr(I_OP_ADVOP), THEDP, SLOT( MLAppendDialog() ) );
    }

    popup.exec( QCursor::pos() - addButton->mapFromGlobal( QCursor::pos() )
                        + QPoint( 0, addButton->height() ) );
}

void StandardPLPanel::popupPlView( const QPoint &point )
{
    QModelIndex index = currentView->indexAt( point );
    QPoint globalPoint = currentView->viewport()->mapToGlobal( point );
    QItemSelectionModel *selection = currentView->selectionModel();
    QModelIndexList list = selection->selectedIndexes();
    model->popup( index, globalPoint, list );
}

void StandardPLPanel::popupSelectColumn( QPoint pos )
{
    QMenu menu;
    assert( treeView );

    /* We do not offer the option to hide index 0 column, or
    * QTreeView will behave weird */
    int i, j;
    for( i = 1 << 1, j = 1; i < COLUMN_END; i <<= 1, j++ )
    {
        QAction* option = menu.addAction(
            qfu( psz_column_title( i ) ) );
        option->setCheckable( true );
        option->setChecked( !treeView->isColumnHidden( j ) );
        selectColumnsSigMapper->setMapping( option, j );
        CONNECT( option, triggered(), selectColumnsSigMapper, map() );
    }
    menu.exec( QCursor::pos() );
}

void StandardPLPanel::toggleColumnShown( int i )
{
    treeView->setColumnHidden( i, !treeView->isColumnHidden( i ) );
}

/* Search in the playlist */
void StandardPLPanel::search( const QString& searchText )
{
    model->search( searchText );
}

/* Set the root of the new Playlist */
/* This activated by the selector selection */
void StandardPLPanel::setRoot( playlist_item_t *p_item )
{
    QPL_LOCK;
    assert( p_item );

    playlist_item_t *p_pref_item = playlist_GetPreferredNode( THEPL, p_item );
    if( p_pref_item ) p_item = p_pref_item;

    /* needed for popupAdd() */
    currentRootId = p_item->i_id;

    /* cosmetics, ..still need playlist locking.. */
    /*char *psz_title = input_item_GetName( p_item->p_input );
    title->setText( qfu(psz_title) );
    free( psz_title );*/

    QPL_UNLOCK;

    /* do THE job */
    model->rebuild( p_item );

    locationBar->setIndex( QModelIndex() );

    /* enable/disable adding */
    if( p_item == THEPL->p_local_category ||
        p_item == THEPL->p_local_onelevel )
    {
        addButton->setEnabled( true );
        addButton->setToolTip( qtr(I_PL_ADDPL) );
    }
    else if( ( THEPL->p_ml_category && p_item == THEPL->p_ml_category) ||
              ( THEPL->p_ml_onelevel && p_item == THEPL->p_ml_onelevel ) )
    {
        addButton->setEnabled( true );
        addButton->setToolTip( qtr(I_PL_ADDML) );
    }
    else
        addButton->setEnabled( false );
}

void StandardPLPanel::removeItem( int i_id )
{
    model->removeItem( i_id );
}

/* Delete and Suppr key remove the selection
   FilterKey function and code function */
void StandardPLPanel::keyPressEvent( QKeyEvent *e )
{
    switch( e->key() )
    {
    case Qt::Key_Back:
    case Qt::Key_Delete:
        deleteSelection();
        break;
    }
}

void StandardPLPanel::deleteSelection()
{
    QItemSelectionModel *selection = currentView->selectionModel();
    QModelIndexList list = selection->selectedIndexes();
    model->doDelete( list );
}

void StandardPLPanel::createIconView()
{
    iconView = new PlIconView( model, this );
    iconView->setContextMenuPolicy( Qt::CustomContextMenu );
    CONNECT( iconView, customContextMenuRequested( const QPoint & ),
             this, popupPlView( const QPoint & ) );
    CONNECT( iconView, activated( const QModelIndex & ),
             this, activate( const QModelIndex & ) );
    CONNECT( locationBar, invoked( const QModelIndex & ),
             iconView, setRootIndex( const QModelIndex & ) );

    layout->addWidget( iconView, 1, 0, 1, -1 );
}

void StandardPLPanel::createTreeView()
{
    /* Create and configure the QTreeView */
    treeView = new QTreeView;

    treeView->setIconSize( QSize( 20, 20 ) );
    treeView->setAlternatingRowColors( true );
    treeView->setAnimated( true );
    treeView->setUniformRowHeights( true );
    treeView->setSortingEnabled( true );
    treeView->header()->setSortIndicator( -1 , Qt::AscendingOrder );
    treeView->header()->setSortIndicatorShown( true );
    treeView->header()->setClickable( true );
    treeView->header()->setContextMenuPolicy( Qt::CustomContextMenu );

    treeView->setSelectionBehavior( QAbstractItemView::SelectRows );
    treeView->setSelectionMode( QAbstractItemView::ExtendedSelection );
    treeView->setDragEnabled( true );
    treeView->setAcceptDrops( true );
    treeView->setDropIndicatorShown( true );
    treeView->setContextMenuPolicy( Qt::CustomContextMenu );

    /* setModel after setSortingEnabled(true), or the model will sort immediately! */
    treeView->setModel( model );

    if( getSettings()->contains( "headerStateV2" ) )
    {
        treeView->header()->restoreState(
                getSettings()->value( "headerStateV2" ).toByteArray() );
    }
    else
    {
        for( int m = 1, c = 0; m != COLUMN_END; m <<= 1, c++ )
        {
            treeView->setColumnHidden( c, !( m & COLUMN_DEFAULT ) );
            if( m == COLUMN_TITLE ) treeView->header()->resizeSection( c, 200 );
            else if( m == COLUMN_DURATION ) treeView->header()->resizeSection( c, 80 );
        }
    }

    /* Connections for the TreeView */
    CONNECT( treeView, activated( const QModelIndex& ),
             this, activate( const QModelIndex& ) );
    CONNECT( treeView->header(), customContextMenuRequested( const QPoint & ),
             this, popupSelectColumn( QPoint ) );
    CONNECT( treeView, customContextMenuRequested( const QPoint & ),
             this, popupPlView( const QPoint & ) );

    /* SignalMapper for columns */
    selectColumnsSigMapper = new QSignalMapper( this );
    CONNECT( selectColumnsSigMapper, mapped( int ),
             this, toggleColumnShown( int ) );

    /* Finish the layout */
    layout->addWidget( treeView, 1, 0, 1, -1 );
}

void StandardPLPanel::toggleView()
{
    if( treeView && treeView->isVisible() )
    {
        if( iconView == NULL )
            createIconView();

        locationBar->setIndex( iconView->rootIndex() );
        treeView->hide();
        iconView->show();
        currentView = iconView;
    }
    else
    {
        if( treeView == NULL )
            createTreeView();

        locationBar->setIndex( treeView->rootIndex() );
        iconView->hide();
        treeView->show();
        currentView = treeView;
    }
}

void StandardPLPanel::wheelEvent( QWheelEvent *e )
{
    // Accept this event in order to prevent unwanted volume up/down changes
    e->accept();
}

void StandardPLPanel::activate( const QModelIndex &index )
{
    last_activated_id = model->itemId( index );
    if( model->hasChildren( index ) )
    {
        if( currentView == iconView ) {
            iconView->setRootIndex( index );
            //title->setText( index.data().toString() );
            locationBar->setIndex( index );
        }
    }
    else
    {
        model->activateItem( index );
    }
}

void StandardPLPanel::handleInputChange( input_thread_t *p_input_thread )
{
    if( currentView != iconView ) return;

    input_item_t *p_input_item = input_GetItem( p_input_thread );
    if( !p_input_item ) return;

    playlist_Lock( THEPL );

    playlist_item_t *p_item = playlist_ItemGetByInput( THEPL, p_input_item );

    if( p_item  && p_item->p_parent &&
        p_item->p_parent->i_id == last_activated_id )
    {
        QModelIndex index = model->index( p_item->p_parent->i_id, 0 );
        iconView->setRootIndex( index );
        //title->setText( index.data().toString() );
        locationBar->setIndex( index );
        last_activated_id = p_item->i_id;
    }

    playlist_Unlock( THEPL );
}

LocationBar::LocationBar( PLModel *m )
{
  model = m;
  mapper = new QSignalMapper;
  CONNECT( mapper, mapped( int ), this, invoke( int ) );
}

void LocationBar::setIndex( const QModelIndex &index )
{
  clear();
  QAction *prev = NULL;
  QModelIndex i = index;
  QFont font;
  QFontMetrics metrics( font );
  while( true )
  {
      QToolButton *btn = new QToolButton;
      PLItem *item = model->getItem( i );
      char *fb_name = input_item_GetTitleFbName( item->inputItem() );
      QString text = qfu(fb_name);
      free(fb_name);
      text = QString("/ ") + metrics.elidedText( text, Qt::ElideRight, 150 );
      btn->setText( text );
      btn->setToolButtonStyle( Qt::ToolButtonTextBesideIcon );
      prev = insertWidget( prev, btn );

      mapper->setMapping( btn, item->id() );
      CONNECT( btn, clicked( ), mapper, map( ) );

      if( i.isValid() ) i = i.parent();
      else break;
  }
}

void LocationBar::invoke( int i_id )
{
  QModelIndex index = model->index( i_id, 0 );
  emit invoked ( index );
}
<|endoftext|>


<commit_before>#include "testutil.h"

#include <fstream>
#include <sstream>

#include <gtest/gtest.h>

#include "../../cvmfs/manifest.h"

#ifdef __APPLE__
  #include <sys/sysctl.h>
#endif

void SkipWhitespace(std::istringstream &iss) {
  while (iss.good()) {
    const char next = iss.peek();
    if (next != ' ' && next != '\t') {
      break;
    }
    iss.get();
  }
}

pid_t GetParentPid(const pid_t pid) {
  pid_t parent_pid = 0;

#ifdef __APPLE__
  int mib[4];
  size_t len;
  struct kinfo_proc kp;

  len = 4;
  sysctlnametomib("kern.proc.pid", mib, &len);

  mib[3] = pid;
  len = sizeof(kp);
  if (sysctl(mib, 4, &kp, &len, NULL, 0) == 0) {
    parent_pid = kp.kp_eproc.e_ppid;
  }
#else
  static const std::string ppid_label = "PPid:";

  std::stringstream proc_status_path;
  proc_status_path << "/proc/" << pid << "/status";

  std::ifstream proc_status(proc_status_path.str().c_str());

  std::string line;
  while (std::getline(proc_status, line)) {
    if (line.compare(0, ppid_label.size(), ppid_label) == 0) {
      const std::string s_ppid = line.substr(ppid_label.size());
      std::istringstream iss_ppid(s_ppid);
      SkipWhitespace(iss_ppid);
      int i_ppid = 0; iss_ppid >> i_ppid;
      if (i_ppid > 0) {
        parent_pid = static_cast<pid_t>(i_ppid);
      }
      break;
    }
  }
#endif

  return parent_pid;
}

namespace catalog {

DirectoryEntry DirectoryEntryTestFactory::RegularFile() {
  DirectoryEntry dirent;
  dirent.mode_ = 33188;
  return dirent;
}

DirectoryEntry DirectoryEntryTestFactory::Directory() {
  DirectoryEntry dirent;
  dirent.mode_ = 16893;
  return dirent;
}

DirectoryEntry DirectoryEntryTestFactory::Symlink() {
  DirectoryEntry dirent;
  dirent.mode_ = 41471;
  return dirent;
}

DirectoryEntry DirectoryEntryTestFactory::ChunkedFile() {
  DirectoryEntry dirent;
  dirent.mode_ = 33188;
  dirent.is_chunked_file_ = true;
  return dirent;
}

} /* namespace catalog */

//
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//

MockCatalog::AvailableCatalogs MockCatalog::available_catalogs;
unsigned int                   MockCatalog::instances = 0;

const std::string MockCatalog::rhs       = "f9d87ae2cc46be52b324335ff05fae4c1a7c4dd4";
const shash::Any  MockCatalog::root_hash = shash::Any(shash::kSha1,
                                                      shash::HexPtr(MockCatalog::rhs),
                                                      'C');

void MockCatalog::Reset() {
  MockCatalog::instances = 0;
  MockCatalog::UnregisterCatalogs();
}

void MockCatalog::RegisterCatalog(MockCatalog *catalog) {
  ASSERT_EQ (MockCatalog::available_catalogs.end(),
             MockCatalog::available_catalogs.find(catalog->hash()));
  MockCatalog::available_catalogs[catalog->hash()] = catalog;
}

void MockCatalog::UnregisterCatalogs() {
  MockCatalog::AvailableCatalogs::const_iterator i, iend;
  for (i    = MockCatalog::available_catalogs.begin(),
       iend = MockCatalog::available_catalogs.end();
       i != iend; ++i)
  {
    delete i->second;
  }
  MockCatalog::available_catalogs.clear();
}

MockCatalog* MockCatalog::GetCatalog(const shash::Any &catalog_hash) {
  AvailableCatalogs::const_iterator clg_itr =
    MockCatalog::available_catalogs.find(catalog_hash);
  return (MockCatalog::available_catalogs.end() != clg_itr)
    ? clg_itr->second
    : NULL;
}

MockCatalog* MockCatalog::AttachFreely(const std::string  &root_path,
                                       const std::string  &file,
                                       const shash::Any   &catalog_hash,
                                             MockCatalog  *parent) {
  const MockCatalog *catalog = MockCatalog::GetCatalog(catalog_hash);
  if (catalog == NULL) {
    return NULL;
  } else {
    MockCatalog *new_catalog = catalog->Clone();
    new_catalog->set_parent(parent);
    return new_catalog;
  }
}

void MockCatalog::RegisterChild(MockCatalog *child) {
  NestedCatalog nested;
  nested.path  = PathString(child->root_path());
  nested.hash  = child->hash();
  nested.child = child;
  nested.size  = child->catalog_size();
  children_.push_back(nested);
}

void MockCatalog::AddFile(const shash::Any   &content_hash,
                          const size_t        file_size) {
  MockCatalog::File f;
  f.hash = content_hash;
  f.size = file_size;
  files_.push_back(f);
}

UniquePtr<history::History>* MockObjectFetcher::s_history;
std::set<shash::Any>* MockObjectFetcher::deleted_catalogs = NULL;

void MockCatalog::AddChunk(const shash::Any  &chunk_content_hash,
                           const size_t       chunk_size) {
  MockCatalog::Chunk c;
  c.hash = chunk_content_hash;
  c.size = chunk_size;
  chunks_.push_back(c);
}

const MockCatalog::HashVector& MockCatalog::GetReferencedObjects() const {
  if (referenced_objects_.empty()) {
    referenced_objects_.reserve(   children_.size()
                                 + files_.size()
                                 + chunks_.size());

          NestedCatalogList::const_iterator i    = children_.begin();
    const NestedCatalogList::const_iterator iend = children_.end();
    for (; i != iend; ++i) {
      referenced_objects_.push_back(i->hash);
    }

          FileList::const_iterator j    = files_.begin();
    const FileList::const_iterator jend = files_.end();
    for (; j != jend; ++j) {
      referenced_objects_.push_back(j->hash);
    }

          ChunkList::const_iterator k    = chunks_.begin();
    const ChunkList::const_iterator kend = chunks_.end();
    for (; k != kend; ++k) {
      referenced_objects_.push_back(k->hash);
    }
  }

  return referenced_objects_;
}

manifest::Manifest* MockObjectFetcher::FetchManifest() {
  return new manifest::Manifest(MockCatalog::root_hash, 0, "");
}
<commit_msg>TEST: simplify MockCatalog::GetReferencedObjects<commit_after>#include "testutil.h"

#include <fstream>
#include <sstream>
#include <algorithm>

#include <gtest/gtest.h>

#include "../../cvmfs/manifest.h"

#ifdef __APPLE__
  #include <sys/sysctl.h>
#endif

void SkipWhitespace(std::istringstream &iss) {
  while (iss.good()) {
    const char next = iss.peek();
    if (next != ' ' && next != '\t') {
      break;
    }
    iss.get();
  }
}

pid_t GetParentPid(const pid_t pid) {
  pid_t parent_pid = 0;

#ifdef __APPLE__
  int mib[4];
  size_t len;
  struct kinfo_proc kp;

  len = 4;
  sysctlnametomib("kern.proc.pid", mib, &len);

  mib[3] = pid;
  len = sizeof(kp);
  if (sysctl(mib, 4, &kp, &len, NULL, 0) == 0) {
    parent_pid = kp.kp_eproc.e_ppid;
  }
#else
  static const std::string ppid_label = "PPid:";

  std::stringstream proc_status_path;
  proc_status_path << "/proc/" << pid << "/status";

  std::ifstream proc_status(proc_status_path.str().c_str());

  std::string line;
  while (std::getline(proc_status, line)) {
    if (line.compare(0, ppid_label.size(), ppid_label) == 0) {
      const std::string s_ppid = line.substr(ppid_label.size());
      std::istringstream iss_ppid(s_ppid);
      SkipWhitespace(iss_ppid);
      int i_ppid = 0; iss_ppid >> i_ppid;
      if (i_ppid > 0) {
        parent_pid = static_cast<pid_t>(i_ppid);
      }
      break;
    }
  }
#endif

  return parent_pid;
}

namespace catalog {

DirectoryEntry DirectoryEntryTestFactory::RegularFile() {
  DirectoryEntry dirent;
  dirent.mode_ = 33188;
  return dirent;
}

DirectoryEntry DirectoryEntryTestFactory::Directory() {
  DirectoryEntry dirent;
  dirent.mode_ = 16893;
  return dirent;
}

DirectoryEntry DirectoryEntryTestFactory::Symlink() {
  DirectoryEntry dirent;
  dirent.mode_ = 41471;
  return dirent;
}

DirectoryEntry DirectoryEntryTestFactory::ChunkedFile() {
  DirectoryEntry dirent;
  dirent.mode_ = 33188;
  dirent.is_chunked_file_ = true;
  return dirent;
}

} /* namespace catalog */

//
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//

MockCatalog::AvailableCatalogs MockCatalog::available_catalogs;
unsigned int                   MockCatalog::instances = 0;

const std::string MockCatalog::rhs       = "f9d87ae2cc46be52b324335ff05fae4c1a7c4dd4";
const shash::Any  MockCatalog::root_hash = shash::Any(shash::kSha1,
                                                      shash::HexPtr(MockCatalog::rhs),
                                                      'C');

void MockCatalog::Reset() {
  MockCatalog::instances = 0;
  MockCatalog::UnregisterCatalogs();
}

void MockCatalog::RegisterCatalog(MockCatalog *catalog) {
  ASSERT_EQ (MockCatalog::available_catalogs.end(),
             MockCatalog::available_catalogs.find(catalog->hash()));
  MockCatalog::available_catalogs[catalog->hash()] = catalog;
}

void MockCatalog::UnregisterCatalogs() {
  MockCatalog::AvailableCatalogs::const_iterator i, iend;
  for (i    = MockCatalog::available_catalogs.begin(),
       iend = MockCatalog::available_catalogs.end();
       i != iend; ++i)
  {
    delete i->second;
  }
  MockCatalog::available_catalogs.clear();
}

MockCatalog* MockCatalog::GetCatalog(const shash::Any &catalog_hash) {
  AvailableCatalogs::const_iterator clg_itr =
    MockCatalog::available_catalogs.find(catalog_hash);
  return (MockCatalog::available_catalogs.end() != clg_itr)
    ? clg_itr->second
    : NULL;
}

MockCatalog* MockCatalog::AttachFreely(const std::string  &root_path,
                                       const std::string  &file,
                                       const shash::Any   &catalog_hash,
                                             MockCatalog  *parent) {
  const MockCatalog *catalog = MockCatalog::GetCatalog(catalog_hash);
  if (catalog == NULL) {
    return NULL;
  } else {
    MockCatalog *new_catalog = catalog->Clone();
    new_catalog->set_parent(parent);
    return new_catalog;
  }
}

void MockCatalog::RegisterChild(MockCatalog *child) {
  NestedCatalog nested;
  nested.path  = PathString(child->root_path());
  nested.hash  = child->hash();
  nested.child = child;
  nested.size  = child->catalog_size();
  children_.push_back(nested);
}

void MockCatalog::AddFile(const shash::Any   &content_hash,
                          const size_t        file_size) {
  MockCatalog::File f;
  f.hash = content_hash;
  f.size = file_size;
  files_.push_back(f);
}

UniquePtr<history::History>* MockObjectFetcher::s_history;
std::set<shash::Any>* MockObjectFetcher::deleted_catalogs = NULL;

void MockCatalog::AddChunk(const shash::Any  &chunk_content_hash,
                           const size_t       chunk_size) {
  MockCatalog::Chunk c;
  c.hash = chunk_content_hash;
  c.size = chunk_size;
  chunks_.push_back(c);
}

template <class T>
struct HashExtractor {
  const shash::Any& operator() (const T &object) const {
    return object.hash;
  }
};

const MockCatalog::HashVector& MockCatalog::GetReferencedObjects() const {
  if (referenced_objects_.empty()) {
    const size_t num_objs = children_.size() + files_.size() + chunks_.size();
    referenced_objects_.resize(num_objs);
    HashVector::iterator i = referenced_objects_.begin();

    i = std::transform(children_.begin(), children_.end(),
                       i, HashExtractor<NestedCatalog>());
    i = std::transform(files_.begin(), files_.end(),
                       i, HashExtractor<File>());
    i = std::transform(chunks_.begin(), chunks_.end(),
                       i, HashExtractor<Chunk>());
  }

  return referenced_objects_;
}

manifest::Manifest* MockObjectFetcher::FetchManifest() {
  return new manifest::Manifest(MockCatalog::root_hash, 0, "");
}
<|endoftext|>