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

#include <string.h>
#include <stdexcept>

#include <realm/util/thread.hpp>

#if !defined _WIN32
#  include <unistd.h>
#endif

// "Process shared mutexes" are not officially supported on Android,
// but they appear to work anyway.
#if (defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED > 0) || REALM_ANDROID
#  define REALM_HAVE_PTHREAD_PROCESS_SHARED
#endif

// Unfortunately Older Ubuntu releases such as 10.04 reports support
// for robust mutexes by setting _POSIX_THREADS = 200809L and
// _POSIX_THREAD_PROCESS_SHARED = 200809L even though they do not
// provide pthread_mutex_consistent(). See also
// http://www.gnu.org/software/gnulib/manual/gnulib.html#pthread_005fmutex_005fconsistent.
// Support was added to glibc 2.12, so we disable for earlier versions
// of glibs
#ifdef REALM_HAVE_PTHREAD_PROCESS_SHARED
#  if !defined _WIN32 // 'robust' not supported by our windows pthreads port
#    if _POSIX_THREADS >= 200809L
#      ifdef __GNU_LIBRARY__
#        if __GLIBC__ >= 2  && __GLIBC_MINOR__ >= 12
#          define REALM_HAVE_ROBUST_PTHREAD_MUTEX
#        endif
#      else
#        define REALM_HAVE_ROBUST_PTHREAD_MUTEX
#      endif
#    endif
#  endif
#endif

using namespace realm;
using namespace realm::util;

namespace {

// Valgrind can show still-reachable leaks for pthread_create() on many systems (AIX, Debian, etc) because
// glibc declares a static memory pool for threads which are free'd by the OS on process termination. See
// http://www.network-theory.co.uk/docs/valgrind/valgrind_20.html under --run-libc-freeres=<yes|no>.
// This can give false positives because of missing suppression, etc (not real leaks!). It's also a problem
// on Windows, so we have written our own clean-up method for the Windows port.
#if defined _WIN32 && defined REALM_DEBUG
void free_threadpool();

class Initialization
{
public:
    ~Initialization()
    {
        free_threadpool();
    }
};

Initialization initialization;

void free_threadpool()
{
    pthread_cleanup();
}
#endif

} // anonymous namespace

void Thread::join()
{
    if (!m_joinable)
        throw std::runtime_error("Thread is not joinable");
    void** value_ptr = nullptr; // Ignore return value
    int r = pthread_join(m_id, value_ptr);
    if (REALM_UNLIKELY(r != 0))
        join_failed(r); // Throws
    m_joinable = false;
}

void Thread::set_name(const std::string& name)
{
#if defined _GNU_SOURCE && !REALM_ANDROID && !REALM_PLATFORM_APPLE
    const size_t max = 16;
    size_t n = name.size();
    if (n > max-1)
        n = max-1;
    char name_2[max];
    std::copy(name.data(), name.data()+n, name_2);
    name_2[n] = '\0';
    pthread_t id = pthread_self();
    int r = pthread_setname_np(id, name_2);
    if (REALM_UNLIKELY(r != 0))
        throw std::runtime_error("pthread_setname_np() failed.");
#elif REALM_PLATFORM_APPLE
    int r = pthread_setname_np(name.data());
    if (REALM_UNLIKELY(r != 0))
        throw std::runtime_error("pthread_setname_np() failed.");
#else
    static_cast<void>(name);
#endif
}

bool Thread::get_name(std::string& name)
{
#if (defined _GNU_SOURCE && !REALM_ANDROID) || REALM_PLATFORM_APPLE
    const size_t max = 64;
    char name_2[max];
    pthread_t id = pthread_self();
    int r = pthread_getname_np(id, name_2, max);
    if (REALM_UNLIKELY(r != 0))
        throw std::runtime_error("pthread_getname_np() failed.");
    name.assign(name_2, strlen(name_2)); // Throws
    return true;
#else
    static_cast<void>(name);
    return false;
#endif
}

REALM_NORETURN void Thread::create_failed(int)
{
    throw std::runtime_error("pthread_create() failed");
}

REALM_NORETURN void Thread::join_failed(int)
{
    // It is intentional that the argument is ignored here.
    throw std::runtime_error("pthread_join() failed.");
}

void Mutex::init_as_process_shared(bool robust_if_available)
{
#ifdef REALM_HAVE_PTHREAD_PROCESS_SHARED
    pthread_mutexattr_t attr;
    int r = pthread_mutexattr_init(&attr);
    if (REALM_UNLIKELY(r != 0))
        attr_init_failed(r);
    r = pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
    REALM_ASSERT(r == 0);
#  ifdef REALM_HAVE_ROBUST_PTHREAD_MUTEX
    if (robust_if_available) {
        r = pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST);
        REALM_ASSERT(r == 0);
    }
#  else // !REALM_HAVE_ROBUST_PTHREAD_MUTEX
    static_cast<void>(robust_if_available);
#  endif
    r = pthread_mutex_init(&m_impl, &attr);
    int r2 = pthread_mutexattr_destroy(&attr);
    REALM_ASSERT(r2 == 0);
    if (REALM_UNLIKELY(r != 0))
        init_failed(r);
#else // !REALM_HAVE_PTHREAD_PROCESS_SHARED
    static_cast<void>(robust_if_available);
    throw std::runtime_error("No support for process-shared mutexes");
#endif
}

REALM_NORETURN void Mutex::init_failed(int err)
{
    switch (err) {
        case ENOMEM:
            throw std::bad_alloc();
        default:
            throw std::runtime_error("pthread_mutex_init() failed");
    }
}

REALM_NORETURN void Mutex::attr_init_failed(int err)
{
    switch (err) {
        case ENOMEM:
            throw std::bad_alloc();
        default:
            throw std::runtime_error("pthread_mutexattr_init() failed");
    }
}

REALM_NORETURN void Mutex::destroy_failed(int err) noexcept
{
    if (err == EBUSY)
        REALM_TERMINATE("Destruction of mutex in use");
    REALM_TERMINATE("pthread_mutex_destroy() failed");
}

REALM_NORETURN void Mutex::lock_failed(int err) noexcept
{
    switch (err) {
        case EDEADLK:
            REALM_TERMINATE("pthread_mutex_lock() failed: Recursive locking of mutex (deadlock)");
        case EINVAL:
            REALM_TERMINATE("pthread_mutex_lock() failed: Invalid mutex object provided");
        case EAGAIN:
            REALM_TERMINATE("pthread_mutex_lock() failed: Maximum number of recursive locks exceeded");
        default:
            REALM_TERMINATE("pthread_mutex_lock() failed");
    }
}

bool RobustMutex::is_robust_on_this_platform() noexcept
{
#ifdef REALM_HAVE_ROBUST_PTHREAD_MUTEX
    return true;
#else
    return false;
#endif
}

bool RobustMutex::low_level_lock()
{
    int r = pthread_mutex_lock(&m_impl);
    if (REALM_LIKELY(r == 0))
        return true;
#ifdef REALM_HAVE_ROBUST_PTHREAD_MUTEX
    if (r == EOWNERDEAD)
        return false;
    if (r == ENOTRECOVERABLE)
        throw NotRecoverable();
#endif
    lock_failed(r);
}

bool RobustMutex::is_valid() noexcept
{
    // FIXME: This check tries to lock the mutex, and only unlocks it if the
    // return value is zero. If pthread_mutex_trylock() fails with EOWNERDEAD,
    // this leads to deadlock during the following propper attempt to lock. This
    // cannot be fixed by also unlocking on failure with EOWNERDEAD, because
    // that would mark the mutex as consistent again and prevent the expected
    // notification.
    int r = pthread_mutex_trylock(&m_impl);
    if (r == 0) {
        r = pthread_mutex_unlock(&m_impl);
        REALM_ASSERT(r == 0);
        return true;
    }
    return r != EINVAL;
}

void RobustMutex::mark_as_consistent() noexcept
{
#ifdef REALM_HAVE_ROBUST_PTHREAD_MUTEX
    int r = pthread_mutex_consistent(&m_impl);
    REALM_ASSERT(r == 0);
#endif
}

CondVar::CondVar(process_shared_tag)
{
#ifdef REALM_HAVE_PTHREAD_PROCESS_SHARED
    pthread_condattr_t attr;
    int r = pthread_condattr_init(&attr);
    if (REALM_UNLIKELY(r != 0))
        attr_init_failed(r);
    r = pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
    REALM_ASSERT(r == 0);
    r = pthread_cond_init(&m_impl, &attr);
    int r2 = pthread_condattr_destroy(&attr);
    REALM_ASSERT(r2 == 0);
    if (REALM_UNLIKELY(r != 0))
        init_failed(r);
#else // !REALM_HAVE_PTHREAD_PROCESS_SHARED
    throw std::runtime_error("No support for process-shared condition variables");
#endif
}

REALM_NORETURN void CondVar::init_failed(int err)
{
    switch (err) {
        case ENOMEM:
            throw std::bad_alloc();
        default:
            throw std::runtime_error("pthread_cond_init() failed");
    }
}

void CondVar::handle_wait_error(int err)
{
    switch (err) {
#ifdef REALM_HAVE_ROBUST_PTHREAD_MUTEX
        case ENOTRECOVERABLE:
            throw RobustMutex::NotRecoverable();
        case EOWNERDEAD:
            return;
#endif
        case EINVAL:
            REALM_TERMINATE("pthread_cond_wait()/pthread_cond_timedwait() failed: Invalid argument provided");
        case EPERM:
            REALM_TERMINATE("pthread_cond_wait()/pthread_cond_timedwait() failed:"
                            "Mutex not owned by calling thread");
        default:
            REALM_TERMINATE("pthread_cond_wait()/pthread_cond_timedwait() failed");
    }
}

REALM_NORETURN void CondVar::attr_init_failed(int err)
{
    switch (err) {
        case ENOMEM:
            throw std::bad_alloc();
        default:
            throw std::runtime_error("pthread_condattr_init() failed");
    }
}

REALM_NORETURN void CondVar::destroy_failed(int err) noexcept
{
    if (err == EBUSY)
        REALM_TERMINATE("Destruction of condition variable in use");
    REALM_TERMINATE("pthread_cond_destroy() failed");
}
<commit_msg>Eliminate any risk of buffer overrun in Thread::get_name()<commit_after>/*************************************************************************
 *
 * Copyright 2016 Realm Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 **************************************************************************/

#include <string.h>
#include <stdexcept>

#include <realm/util/thread.hpp>

#if !defined _WIN32
#  include <unistd.h>
#endif

// "Process shared mutexes" are not officially supported on Android,
// but they appear to work anyway.
#if (defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED > 0) || REALM_ANDROID
#  define REALM_HAVE_PTHREAD_PROCESS_SHARED
#endif

// Unfortunately Older Ubuntu releases such as 10.04 reports support
// for robust mutexes by setting _POSIX_THREADS = 200809L and
// _POSIX_THREAD_PROCESS_SHARED = 200809L even though they do not
// provide pthread_mutex_consistent(). See also
// http://www.gnu.org/software/gnulib/manual/gnulib.html#pthread_005fmutex_005fconsistent.
// Support was added to glibc 2.12, so we disable for earlier versions
// of glibs
#ifdef REALM_HAVE_PTHREAD_PROCESS_SHARED
#  if !defined _WIN32 // 'robust' not supported by our windows pthreads port
#    if _POSIX_THREADS >= 200809L
#      ifdef __GNU_LIBRARY__
#        if __GLIBC__ >= 2  && __GLIBC_MINOR__ >= 12
#          define REALM_HAVE_ROBUST_PTHREAD_MUTEX
#        endif
#      else
#        define REALM_HAVE_ROBUST_PTHREAD_MUTEX
#      endif
#    endif
#  endif
#endif

using namespace realm;
using namespace realm::util;

namespace {

// Valgrind can show still-reachable leaks for pthread_create() on many systems (AIX, Debian, etc) because
// glibc declares a static memory pool for threads which are free'd by the OS on process termination. See
// http://www.network-theory.co.uk/docs/valgrind/valgrind_20.html under --run-libc-freeres=<yes|no>.
// This can give false positives because of missing suppression, etc (not real leaks!). It's also a problem
// on Windows, so we have written our own clean-up method for the Windows port.
#if defined _WIN32 && defined REALM_DEBUG
void free_threadpool();

class Initialization
{
public:
    ~Initialization()
    {
        free_threadpool();
    }
};

Initialization initialization;

void free_threadpool()
{
    pthread_cleanup();
}
#endif

} // anonymous namespace

void Thread::join()
{
    if (!m_joinable)
        throw std::runtime_error("Thread is not joinable");
    void** value_ptr = nullptr; // Ignore return value
    int r = pthread_join(m_id, value_ptr);
    if (REALM_UNLIKELY(r != 0))
        join_failed(r); // Throws
    m_joinable = false;
}

void Thread::set_name(const std::string& name)
{
#if defined _GNU_SOURCE && !REALM_ANDROID && !REALM_PLATFORM_APPLE
    const size_t max = 16;
    size_t n = name.size();
    if (n > max-1)
        n = max-1;
    char name_2[max];
    std::copy(name.data(), name.data()+n, name_2);
    name_2[n] = '\0';
    pthread_t id = pthread_self();
    int r = pthread_setname_np(id, name_2);
    if (REALM_UNLIKELY(r != 0))
        throw std::runtime_error("pthread_setname_np() failed.");
#elif REALM_PLATFORM_APPLE
    int r = pthread_setname_np(name.data());
    if (REALM_UNLIKELY(r != 0))
        throw std::runtime_error("pthread_setname_np() failed.");
#else
    static_cast<void>(name);
#endif
}

bool Thread::get_name(std::string& name)
{
#if (defined _GNU_SOURCE && !REALM_ANDROID) || REALM_PLATFORM_APPLE
    const size_t max = 64;
    char name_2[max];
    pthread_t id = pthread_self();
    int r = pthread_getname_np(id, name_2, max);
    if (REALM_UNLIKELY(r != 0))
        throw std::runtime_error("pthread_getname_np() failed.");
    name_2[max-1] = '\0'; // Eliminate any risk of buffer overrun in strlen().
    name.assign(name_2, strlen(name_2)); // Throws
    return true;
#else
    static_cast<void>(name);
    return false;
#endif
}

REALM_NORETURN void Thread::create_failed(int)
{
    throw std::runtime_error("pthread_create() failed");
}

REALM_NORETURN void Thread::join_failed(int)
{
    // It is intentional that the argument is ignored here.
    throw std::runtime_error("pthread_join() failed.");
}

void Mutex::init_as_process_shared(bool robust_if_available)
{
#ifdef REALM_HAVE_PTHREAD_PROCESS_SHARED
    pthread_mutexattr_t attr;
    int r = pthread_mutexattr_init(&attr);
    if (REALM_UNLIKELY(r != 0))
        attr_init_failed(r);
    r = pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
    REALM_ASSERT(r == 0);
#  ifdef REALM_HAVE_ROBUST_PTHREAD_MUTEX
    if (robust_if_available) {
        r = pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST);
        REALM_ASSERT(r == 0);
    }
#  else // !REALM_HAVE_ROBUST_PTHREAD_MUTEX
    static_cast<void>(robust_if_available);
#  endif
    r = pthread_mutex_init(&m_impl, &attr);
    int r2 = pthread_mutexattr_destroy(&attr);
    REALM_ASSERT(r2 == 0);
    if (REALM_UNLIKELY(r != 0))
        init_failed(r);
#else // !REALM_HAVE_PTHREAD_PROCESS_SHARED
    static_cast<void>(robust_if_available);
    throw std::runtime_error("No support for process-shared mutexes");
#endif
}

REALM_NORETURN void Mutex::init_failed(int err)
{
    switch (err) {
        case ENOMEM:
            throw std::bad_alloc();
        default:
            throw std::runtime_error("pthread_mutex_init() failed");
    }
}

REALM_NORETURN void Mutex::attr_init_failed(int err)
{
    switch (err) {
        case ENOMEM:
            throw std::bad_alloc();
        default:
            throw std::runtime_error("pthread_mutexattr_init() failed");
    }
}

REALM_NORETURN void Mutex::destroy_failed(int err) noexcept
{
    if (err == EBUSY)
        REALM_TERMINATE("Destruction of mutex in use");
    REALM_TERMINATE("pthread_mutex_destroy() failed");
}

REALM_NORETURN void Mutex::lock_failed(int err) noexcept
{
    switch (err) {
        case EDEADLK:
            REALM_TERMINATE("pthread_mutex_lock() failed: Recursive locking of mutex (deadlock)");
        case EINVAL:
            REALM_TERMINATE("pthread_mutex_lock() failed: Invalid mutex object provided");
        case EAGAIN:
            REALM_TERMINATE("pthread_mutex_lock() failed: Maximum number of recursive locks exceeded");
        default:
            REALM_TERMINATE("pthread_mutex_lock() failed");
    }
}

bool RobustMutex::is_robust_on_this_platform() noexcept
{
#ifdef REALM_HAVE_ROBUST_PTHREAD_MUTEX
    return true;
#else
    return false;
#endif
}

bool RobustMutex::low_level_lock()
{
    int r = pthread_mutex_lock(&m_impl);
    if (REALM_LIKELY(r == 0))
        return true;
#ifdef REALM_HAVE_ROBUST_PTHREAD_MUTEX
    if (r == EOWNERDEAD)
        return false;
    if (r == ENOTRECOVERABLE)
        throw NotRecoverable();
#endif
    lock_failed(r);
}

bool RobustMutex::is_valid() noexcept
{
    // FIXME: This check tries to lock the mutex, and only unlocks it if the
    // return value is zero. If pthread_mutex_trylock() fails with EOWNERDEAD,
    // this leads to deadlock during the following propper attempt to lock. This
    // cannot be fixed by also unlocking on failure with EOWNERDEAD, because
    // that would mark the mutex as consistent again and prevent the expected
    // notification.
    int r = pthread_mutex_trylock(&m_impl);
    if (r == 0) {
        r = pthread_mutex_unlock(&m_impl);
        REALM_ASSERT(r == 0);
        return true;
    }
    return r != EINVAL;
}

void RobustMutex::mark_as_consistent() noexcept
{
#ifdef REALM_HAVE_ROBUST_PTHREAD_MUTEX
    int r = pthread_mutex_consistent(&m_impl);
    REALM_ASSERT(r == 0);
#endif
}

CondVar::CondVar(process_shared_tag)
{
#ifdef REALM_HAVE_PTHREAD_PROCESS_SHARED
    pthread_condattr_t attr;
    int r = pthread_condattr_init(&attr);
    if (REALM_UNLIKELY(r != 0))
        attr_init_failed(r);
    r = pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
    REALM_ASSERT(r == 0);
    r = pthread_cond_init(&m_impl, &attr);
    int r2 = pthread_condattr_destroy(&attr);
    REALM_ASSERT(r2 == 0);
    if (REALM_UNLIKELY(r != 0))
        init_failed(r);
#else // !REALM_HAVE_PTHREAD_PROCESS_SHARED
    throw std::runtime_error("No support for process-shared condition variables");
#endif
}

REALM_NORETURN void CondVar::init_failed(int err)
{
    switch (err) {
        case ENOMEM:
            throw std::bad_alloc();
        default:
            throw std::runtime_error("pthread_cond_init() failed");
    }
}

void CondVar::handle_wait_error(int err)
{
    switch (err) {
#ifdef REALM_HAVE_ROBUST_PTHREAD_MUTEX
        case ENOTRECOVERABLE:
            throw RobustMutex::NotRecoverable();
        case EOWNERDEAD:
            return;
#endif
        case EINVAL:
            REALM_TERMINATE("pthread_cond_wait()/pthread_cond_timedwait() failed: Invalid argument provided");
        case EPERM:
            REALM_TERMINATE("pthread_cond_wait()/pthread_cond_timedwait() failed:"
                            "Mutex not owned by calling thread");
        default:
            REALM_TERMINATE("pthread_cond_wait()/pthread_cond_timedwait() failed");
    }
}

REALM_NORETURN void CondVar::attr_init_failed(int err)
{
    switch (err) {
        case ENOMEM:
            throw std::bad_alloc();
        default:
            throw std::runtime_error("pthread_condattr_init() failed");
    }
}

REALM_NORETURN void CondVar::destroy_failed(int err) noexcept
{
    if (err == EBUSY)
        REALM_TERMINATE("Destruction of condition variable in use");
    REALM_TERMINATE("pthread_cond_destroy() failed");
}
<|endoftext|>


<commit_before>#include "drivers/ublox_neo7.hpp"

#include <cstdlib>
#include <cstring>

#include "chprintf.h"
#include "unit_config.hpp"

const char NMEA_LF = '\n';
const char *NMEA_DELIMS = ",\0";

struct GPGLLMessage {
  float lon;
  char lonDir;
  float lat;
  char latDir;
  float utc;
  char valid;
};

void UBloxNEO7::init() {
  // TODO(yoos): Turn off default (1Hz?!) sentences and poll at 10Hz.
  //chprintf((BaseSequentialStream*)sd, "$PUBX,40,GLL,0,0,0,0,0,0*5C\r\n");
  chprintf((BaseSequentialStream*)sd, "$PUBX,40,GGA,0,0,0,0,0,0*5A\r\n");
  chprintf((BaseSequentialStream*)sd, "$PUBX,40,GSA,0,0,0,0,0,0*4E\r\n");
  chprintf((BaseSequentialStream*)sd, "$PUBX,40,RMC,0,0,0,0,0,0*47\r\n");
  chprintf((BaseSequentialStream*)sd, "$PUBX,40,GSV,0,0,0,0,0,0*59\r\n");
  chprintf((BaseSequentialStream*)sd, "$PUBX,40,VTG,0,0,0,0,0,0*5E\r\n");
}

GPSReading UBloxNEO7::readGPS() {
  // Read all available bytes until the newline character. NMEA dictates that
  // messages should end with a CRLF, but we'll only look for the LF.
  std::size_t len = readUntil(NMEA_LF);

  //static int loop = 0;
  //if (loop % 100 == 0) {
  //  chprintf((BaseSequentialStream*)sd, "$PUBX,00*33\r\n");
  //}
  //loop = (loop+1) % 100;

  // Check if a full line is ready to be processed
  if(len > 0) {
    char *start = reinterpret_cast<char *>(rxbuf.data());
    //chprintf((BaseSequentialStream*)&SD4, "%s", rxbuf.data());

    // Skip over the leading "$"
    start += 1;

    char *token = std::strtok(start, NMEA_DELIMS);

    // Only care about GPGLL messages
    if(std::strcmp("GPGLL", token) == 0) {
      GPGLLMessage message;
      int position = 0;

      while((token = std::strtok(nullptr, NMEA_DELIMS)) != nullptr) {
        switch(position++) {
          case 0:
            message.lat = atof(token);
            break;
          case 1:
            message.latDir = token[0];
            break;
          case 2:
            message.lon = atof(token);
            break;
          case 3:
            message.lonDir = token[0];
            break;
          case 4:
            message.utc = atof(token);
            break;
          case 5:
            message.valid = token[0];
            break;
        };
      }

      return GPSReading {
        // Make sure we got all parts of the message. If fields are omitted in
        // the message then `strtok` will skip over repeated delimiters and the
        // above loop will complete before all delimiters were found.
        .valid = message.valid && position == 7,
        .lat = dmd2float(message.lat, message.latDir),
        .lon = dmd2float(message.lon, message.lonDir),
        .utc = message.utc
      };
    }
  } else {
    // TODO: Return previous message with old timestamp.
      return GPSReading {
        .valid = false,
        .lat = 0.0,
        .lon = 0.0,
        .utc = 0.0
      };
  }
}

bool UBloxNEO7::healthy() {
  return true;
}
<commit_msg>Fix bad if statement organization in GPS driver.<commit_after>#include "drivers/ublox_neo7.hpp"

#include <cstdlib>
#include <cstring>

#include "chprintf.h"
#include "unit_config.hpp"

const char NMEA_LF = '\n';
const char *NMEA_DELIMS = ",\0";

struct GPGLLMessage {
  float lon;
  char lonDir;
  float lat;
  char latDir;
  float utc;
  char valid;
};

void UBloxNEO7::init() {
}

GPSReading UBloxNEO7::readGPS() {
  // Read all available bytes until the newline character. NMEA dictates that
  // messages should end with a CRLF, but we'll only look for the LF.
  std::size_t len = readUntil(NMEA_LF);

  //static int loop = 0;
  //if (loop % 100 == 0) {
  //  chprintf((BaseSequentialStream*)sd, "$PUBX,00*33\r\n");
  //}
  //loop = (loop+1) % 100;

  // Check if a full line is ready to be processed
  if(len > 0) {
    char *start = reinterpret_cast<char *>(rxbuf.data());
    //chprintf((BaseSequentialStream*)&SD4, "%s", rxbuf.data());

    // Skip over the leading "$"
    start += 1;

    char *token = std::strtok(start, NMEA_DELIMS);

    // Only care about GPGLL messages
    if(std::strcmp("GPGLL", token) == 0) {
      GPGLLMessage message;
      int position = 0;

      while((token = std::strtok(nullptr, NMEA_DELIMS)) != nullptr) {
        switch(position++) {
          case 0:
            message.lat = atof(token);
            break;
          case 1:
            message.latDir = token[0];
            break;
          case 2:
            message.lon = atof(token);
            break;
          case 3:
            message.lonDir = token[0];
            break;
          case 4:
            message.utc = atof(token);
            break;
          case 5:
            message.valid = token[0];
            break;
        };
      }

      return GPSReading {
        // Make sure we got all parts of the message. If fields are omitted in
        // the message then `strtok` will skip over repeated delimiters and the
        // above loop will complete before all delimiters were found.
        .valid = message.valid && position == 7,
        .lat = dmd2float(message.lat, message.latDir),
        .lon = dmd2float(message.lon, message.lonDir),
        .utc = message.utc
      };
    }
  }

  // TODO: Return previous message with old timestamp.
  return GPSReading {
    .valid = false,
      .lat = 10000.0,
      .lon = 10000.0,
      .utc = 0.0
  };
}

bool UBloxNEO7::healthy() {
  return true;
}
<|endoftext|>


<commit_before>/*
 * $Id$
 *
 * Copyright(C) 1998-2004 Satoshi Nakamura
 * All rights reserved.
 *
 */

#include <qmapplication.h>
#include <qmfilenames.h>
#include <qmmacro.h>

#include <qsconv.h>
#include <qsosutil.h>
#include <qsstl.h>

#include <algorithm>

#include "filter.h"

using namespace qm;
using namespace qs;

/****************************************************************************
 *
 * FilterManager
 *
 */

qm::FilterManager::FilterManager()
{
	SYSTEMTIME st;
	::GetSystemTime(&st);
	::SystemTimeToFileTime(&st, &ft_);

	load();
}

qm::FilterManager::~FilterManager()
{
	clear();
}

const FilterManager::FilterList& qm::FilterManager::getFilters()
{
//	load();
	return listFilter_;
}

bool qm::FilterManager::load()
{
	wstring_ptr wstrPath(Application::getApplication().getProfilePath(FileNames::FILTERS_XML));

	W2T(wstrPath.get(), ptszPath);
	AutoHandle hFile(::CreateFile(ptszPath, GENERIC_READ, 0, 0,
		OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0));
	if (hFile.get()) {
		FILETIME ft;
		::GetFileTime(hFile.get(), 0, 0, &ft);
		hFile.close();

		if (::CompareFileTime(&ft, &ft_) != 0) {
			clear();

			XMLReader reader;
			FilterContentHandler handler(&listFilter_);
			reader.setContentHandler(&handler);
			if (!reader.parse(wstrPath.get()))
				return false;

			ft_ = ft;
		}
	}
	else {
		clear();

		SYSTEMTIME st;
		::GetSystemTime(&st);
		::SystemTimeToFileTime(&st, &ft_);
	}

	return true;
}

void qm::FilterManager::clear()
{
	std::for_each(listFilter_.begin(), listFilter_.end(), deleter<Filter>());
	listFilter_.clear();
}

/****************************************************************************
 *
 * Filter
 *
 */

qm::Filter::Filter(const WCHAR* pwszName,
				   std::auto_ptr<Macro> pMacro) :
	pMacro_(pMacro)
{
	wstrName_ = allocWString(pwszName);
}

qm::Filter::Filter(const Filter& filter)
{
	wstrName_ = allocWString(filter.wstrName_.get());

	wstring_ptr wstrMacro(filter.pMacro_->getString());
	MacroParser parser(MacroParser::TYPE_FILTER);
	pMacro_ = parser.parse(wstrMacro.get());
	assert(pMacro_.get());
}

qm::Filter::~Filter()
{
}

const WCHAR* qm::Filter::getName() const
{
	return wstrName_.get();
}

const Macro* qm::Filter::getMacro() const
{
	return pMacro_.get();
}

bool qm::Filter::match(MacroContext* pContext) const
{
	assert(pContext);

	MacroValuePtr pValue(pMacro_->value(pContext));
	return pValue.get() && pValue->boolean();
}

/****************************************************************************
 *
 * FilterContentHandler
 *
 */

qm::FilterContentHandler::FilterContentHandler(FilterList* pListFilter) :
	pListFilter_(pListFilter),
	state_(STATE_ROOT)
{
}

qm::FilterContentHandler::~FilterContentHandler()
{
}

bool qm::FilterContentHandler::startElement(const WCHAR* pwszNamespaceURI,
											const WCHAR* pwszLocalName,
											const WCHAR* pwszQName,
											const Attributes& attributes)
{
	if (wcscmp(pwszLocalName, L"filters") == 0) {
		if (state_ != STATE_ROOT)
			return false;
		if (attributes.getLength() != 0)
			return false;
		state_ = STATE_FILTERS;
	}
	else if (wcscmp(pwszLocalName, L"filter") == 0) {
		if (state_ != STATE_FILTERS)
			return false;

		const WCHAR* pwszName = 0;
		for (int n = 0; n < attributes.getLength(); ++n) {
			const WCHAR* pwszAttrName = attributes.getLocalName(n);
			if (wcscmp(pwszAttrName, L"name") == 0)
				pwszName = attributes.getValue(n);
			else
				return false;
		}
		if (!pwszName)
			return false;

		assert(!wstrName_.get());
		wstrName_ = allocWString(pwszName);

		state_ = STATE_FILTER;
	}
	else {
		return false;
	}

	return true;
}

bool qm::FilterContentHandler::endElement(const WCHAR* pwszNamespaceURI,
										  const WCHAR* pwszLocalName,
										  const WCHAR* pwszQName)
{
	if (wcscmp(pwszLocalName, L"filters") == 0) {
		assert(state_ == STATE_FILTERS);
		state_ = STATE_ROOT;
	}
	else if (wcscmp(pwszLocalName, L"filter") == 0) {
		assert(state_ == STATE_FILTER);

		const WCHAR* pwszMacro = buffer_.getCharArray();
		MacroParser parser(MacroParser::TYPE_FILTER);
		std::auto_ptr<Macro> pMacro(parser.parse(pwszMacro));
		if (!pMacro.get())
			return false;
		std::auto_ptr<Filter> pFilter(new Filter(wstrName_.get(), pMacro));
		pListFilter_->push_back(pFilter.get());
		pFilter.release();

		wstrName_.reset(0);
		buffer_.remove();

		state_ = STATE_FILTERS;
	}
	else {
		return false;
	}

	return true;
}

bool qm::FilterContentHandler::characters(const WCHAR* pwsz,
										  size_t nStart,
										  size_t nLength)
{
	if (state_ == STATE_FILTER) {
		buffer_.append(pwsz + nStart, nLength);
	}
	else {
		const WCHAR* p = pwsz + nStart;
		for (size_t n = 0; n < nLength; ++n, ++p) {
			if (*p != L' ' && *p != L'\t' && *p != '\n')
				return false;
		}
	}

	return true;
}
<commit_msg>Reload filter.xml if needed.<commit_after>/*
 * $Id$
 *
 * Copyright(C) 1998-2004 Satoshi Nakamura
 * All rights reserved.
 *
 */

#include <qmapplication.h>
#include <qmfilenames.h>
#include <qmmacro.h>

#include <qsconv.h>
#include <qsosutil.h>
#include <qsstl.h>

#include <algorithm>

#include "filter.h"

using namespace qm;
using namespace qs;

/****************************************************************************
 *
 * FilterManager
 *
 */

qm::FilterManager::FilterManager()
{
	SYSTEMTIME st;
	::GetSystemTime(&st);
	::SystemTimeToFileTime(&st, &ft_);
}

qm::FilterManager::~FilterManager()
{
	clear();
}

const FilterManager::FilterList& qm::FilterManager::getFilters()
{
	load();
	return listFilter_;
}

bool qm::FilterManager::load()
{
	wstring_ptr wstrPath(Application::getApplication().getProfilePath(FileNames::FILTERS_XML));

	W2T(wstrPath.get(), ptszPath);
	AutoHandle hFile(::CreateFile(ptszPath, GENERIC_READ, 0, 0,
		OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0));
	if (hFile.get()) {
		FILETIME ft;
		::GetFileTime(hFile.get(), 0, 0, &ft);
		hFile.close();

		if (::CompareFileTime(&ft, &ft_) != 0) {
			clear();

			XMLReader reader;
			FilterContentHandler handler(&listFilter_);
			reader.setContentHandler(&handler);
			if (!reader.parse(wstrPath.get()))
				return false;

			ft_ = ft;
		}
	}
	else {
		clear();

		SYSTEMTIME st;
		::GetSystemTime(&st);
		::SystemTimeToFileTime(&st, &ft_);
	}

	return true;
}

void qm::FilterManager::clear()
{
	std::for_each(listFilter_.begin(), listFilter_.end(), deleter<Filter>());
	listFilter_.clear();
}

/****************************************************************************
 *
 * Filter
 *
 */

qm::Filter::Filter(const WCHAR* pwszName,
				   std::auto_ptr<Macro> pMacro) :
	pMacro_(pMacro)
{
	wstrName_ = allocWString(pwszName);
}

qm::Filter::Filter(const Filter& filter)
{
	wstrName_ = allocWString(filter.wstrName_.get());

	wstring_ptr wstrMacro(filter.pMacro_->getString());
	MacroParser parser(MacroParser::TYPE_FILTER);
	pMacro_ = parser.parse(wstrMacro.get());
	assert(pMacro_.get());
}

qm::Filter::~Filter()
{
}

const WCHAR* qm::Filter::getName() const
{
	return wstrName_.get();
}

const Macro* qm::Filter::getMacro() const
{
	return pMacro_.get();
}

bool qm::Filter::match(MacroContext* pContext) const
{
	assert(pContext);

	MacroValuePtr pValue(pMacro_->value(pContext));
	return pValue.get() && pValue->boolean();
}

/****************************************************************************
 *
 * FilterContentHandler
 *
 */

qm::FilterContentHandler::FilterContentHandler(FilterList* pListFilter) :
	pListFilter_(pListFilter),
	state_(STATE_ROOT)
{
}

qm::FilterContentHandler::~FilterContentHandler()
{
}

bool qm::FilterContentHandler::startElement(const WCHAR* pwszNamespaceURI,
											const WCHAR* pwszLocalName,
											const WCHAR* pwszQName,
											const Attributes& attributes)
{
	if (wcscmp(pwszLocalName, L"filters") == 0) {
		if (state_ != STATE_ROOT)
			return false;
		if (attributes.getLength() != 0)
			return false;
		state_ = STATE_FILTERS;
	}
	else if (wcscmp(pwszLocalName, L"filter") == 0) {
		if (state_ != STATE_FILTERS)
			return false;

		const WCHAR* pwszName = 0;
		for (int n = 0; n < attributes.getLength(); ++n) {
			const WCHAR* pwszAttrName = attributes.getLocalName(n);
			if (wcscmp(pwszAttrName, L"name") == 0)
				pwszName = attributes.getValue(n);
			else
				return false;
		}
		if (!pwszName)
			return false;

		assert(!wstrName_.get());
		wstrName_ = allocWString(pwszName);

		state_ = STATE_FILTER;
	}
	else {
		return false;
	}

	return true;
}

bool qm::FilterContentHandler::endElement(const WCHAR* pwszNamespaceURI,
										  const WCHAR* pwszLocalName,
										  const WCHAR* pwszQName)
{
	if (wcscmp(pwszLocalName, L"filters") == 0) {
		assert(state_ == STATE_FILTERS);
		state_ = STATE_ROOT;
	}
	else if (wcscmp(pwszLocalName, L"filter") == 0) {
		assert(state_ == STATE_FILTER);

		const WCHAR* pwszMacro = buffer_.getCharArray();
		MacroParser parser(MacroParser::TYPE_FILTER);
		std::auto_ptr<Macro> pMacro(parser.parse(pwszMacro));
		if (!pMacro.get())
			return false;
		std::auto_ptr<Filter> pFilter(new Filter(wstrName_.get(), pMacro));
		pListFilter_->push_back(pFilter.get());
		pFilter.release();

		wstrName_.reset(0);
		buffer_.remove();

		state_ = STATE_FILTERS;
	}
	else {
		return false;
	}

	return true;
}

bool qm::FilterContentHandler::characters(const WCHAR* pwsz,
										  size_t nStart,
										  size_t nLength)
{
	if (state_ == STATE_FILTER) {
		buffer_.append(pwsz + nStart, nLength);
	}
	else {
		const WCHAR* p = pwsz + nStart;
		for (size_t n = 0; n < nLength; ++n, ++p) {
			if (*p != L' ' && *p != L'\t' && *p != '\n')
				return false;
		}
	}

	return true;
}
<|endoftext|>


<commit_before>/*
    This file is part of Kontact.
    Copyright (c) 2003 Kontact Developer

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

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include <qwidget.h>

#include <kaction.h>
#include <kapplication.h>
#include <kdebug.h>
#include <kgenericfactory.h>
#include <kiconloader.h>
#include <kparts/componentfactory.h>
#include <kstandarddirs.h>
#include <dcopclient.h>
#include <ktempfile.h>

#include <kabc/addressee.h>

#include <libkcal/vcaldrag.h>
#include <libkcal/icaldrag.h>
#include <libkcal/calendarlocal.h>

#include <libkdepim/kvcarddrag.h>

#include <kmail/kmail_part.h>
#include <kmail/kmkernel.h>

#include "core.h"
#include "summarywidget.h"

#include "kmail_plugin.h"

using namespace KCal;

typedef KGenericFactory<KMailPlugin, Kontact::Core> KMailPluginFactory;
K_EXPORT_COMPONENT_FACTORY( libkontact_kmailplugin,
                            KMailPluginFactory( "kontact_kmailplugin" ) )

KMailPlugin::KMailPlugin(Kontact::Core *core, const char *, const QStringList& )
  : Kontact::Plugin( core, core, "kmail" ),
    mStub( 0 )
{
  setInstance( KMailPluginFactory::instance() );

  insertNewAction( new KAction( i18n( "New Message..." ), "mail_new",
                   0, this, SLOT( slotNewMail() ), actionCollection(),
                   "new_mail" ) );

  mUniqueAppWatcher = new Kontact::UniqueAppWatcher(
      new Kontact::UniqueAppHandlerFactory<KMailUniqueAppHandler>(), this );
}

bool KMailPlugin::canDecodeDrag( QMimeSource *qms )
{
  return ( ICalDrag::canDecode( qms ) ||
           VCalDrag::canDecode( qms ) ||
           KVCardDrag::canDecode( qms ) );
}

void KMailPlugin::processDropEvent( QDropEvent * de )
{
  kdDebug() << k_funcinfo << endl;
  CalendarLocal cal;
  KABC::Addressee::List list;

  if ( VCalDrag::decode( de, &cal ) || ICalDrag::decode( de, &cal ) ) {
    KTempFile tmp( locateLocal( "tmp", "incidences-" ), ".ics" );
    cal.save( tmp.name() );
    openComposer( QString::null, KURL::fromPathOrURL( tmp.name() ) );
  }
  else if ( KVCardDrag::decode( de, list ) ) {
    KABC::Addressee::List::Iterator it;
    QStringList to;
    for ( it = list.begin(); it != list.end(); ++it ) {
      to += ( *it ).fullEmail();
    }
    openComposer( to.join(", ") );
  }

}

void KMailPlugin::openComposer( const QString& to, const KURL& attach )
{
  (void) part(); // ensure part is loaded
  Q_ASSERT( mStub );
  if ( mStub ) {
    if ( attach.isValid() )
      mStub->openComposer( "", "", "", "", "", false, KURL(), attach );
    else
      mStub->openComposer( to, "", "", "", "", false, KURL() );
  }
}

void KMailPlugin::slotNewMail()
{
  openComposer( QString::null );
}

void KMailPlugin::raise()
{
  core()->selectPlugin( this );
}

KMailPlugin::~KMailPlugin()
{
}

bool KMailPlugin::createDCOPInterface( const QString& serviceType )
{
  if ( serviceType == "DCOP/ResourceBackend/IMAP" ) {
    if ( part() )
      return true;
  }

  return false;
}

QString KMailPlugin::tipFile() const
{
  QString file = ::locate("data", "kmail/tips");
  return file;
}

KPIM::Part* KMailPlugin::createPart()
{
  KPIM::Part *part = loadPart();
  if ( !part ) return 0;

  connect( part, SIGNAL( raise() ), SLOT( raise() ) );

  mStub = new KMailIface_stub( dcopClient(), "kmail", "KMailIface" );

  return part;
}

QStringList KMailPlugin::invisibleToolbarActions() const
{
  return QStringList( "new_message" );
}

bool KMailPlugin::isRunningStandalone()
{
  return mUniqueAppWatcher->isRunningStandalone();
}

Kontact::Summary *KMailPlugin::createSummaryWidget( QWidget *parent )
{
  return new SummaryWidget( this, parent );
}

////

#include "../../../kmail/kmail_options.h"
void KMailUniqueAppHandler::loadCommandLineOptions()
{
    KCmdLineArgs::addCmdLineOptions( kmail_options );
}

int KMailUniqueAppHandler::newInstance()
{
    // Ensure part is loaded
    (void)plugin()->part();
    DCOPRef kmail( "kmail", "KMailIface" );
    DCOPReply reply = kmail.call( "handleCommandLine", false );
    if ( reply.isValid() ) {
        bool handled = reply;
        //kdDebug(5602) << k_funcinfo << "handled=" << handled << endl;
        if ( !handled ) // no args -> simply bring kmail plugin to front
            return Kontact::UniqueAppHandler::newInstance();
    }
    return 0;
}

bool KMailPlugin::queryClose() const {
  KMailIface_stub stub( kapp->dcopClient(), "kmail", "KMailIface" );
  bool canClose=stub.canQueryClose();
  return canClose;
}

#include "kmail_plugin.moc"
<commit_msg>Forward port "New Message" fix from the branch.<commit_after>/*
    This file is part of Kontact.
    Copyright (c) 2003 Kontact Developer

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

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include <qwidget.h>

#include <kaction.h>
#include <kapplication.h>
#include <kdebug.h>
#include <kgenericfactory.h>
#include <kiconloader.h>
#include <kparts/componentfactory.h>
#include <kstandarddirs.h>
#include <dcopclient.h>
#include <ktempfile.h>

#include <kabc/addressee.h>

#include <libkcal/vcaldrag.h>
#include <libkcal/icaldrag.h>
#include <libkcal/calendarlocal.h>

#include <libkdepim/kvcarddrag.h>

#include <kmail/kmail_part.h>
#include <kmail/kmkernel.h>

#include "core.h"
#include "summarywidget.h"

#include "kmail_plugin.h"

using namespace KCal;

typedef KGenericFactory<KMailPlugin, Kontact::Core> KMailPluginFactory;
K_EXPORT_COMPONENT_FACTORY( libkontact_kmailplugin,
                            KMailPluginFactory( "kontact_kmailplugin" ) )

KMailPlugin::KMailPlugin(Kontact::Core *core, const char *, const QStringList& )
  : Kontact::Plugin( core, core, "kmail" ),
    mStub( 0 )
{
  setInstance( KMailPluginFactory::instance() );

  insertNewAction( new KAction( i18n( "New Message..." ), "mail_new",
                   0, this, SLOT( slotNewMail() ), actionCollection(),
                   "new_mail" ) );

  mUniqueAppWatcher = new Kontact::UniqueAppWatcher(
      new Kontact::UniqueAppHandlerFactory<KMailUniqueAppHandler>(), this );
}

bool KMailPlugin::canDecodeDrag( QMimeSource *qms )
{
  return ( ICalDrag::canDecode( qms ) ||
           VCalDrag::canDecode( qms ) ||
           KVCardDrag::canDecode( qms ) );
}

void KMailPlugin::processDropEvent( QDropEvent * de )
{
  kdDebug() << k_funcinfo << endl;
  CalendarLocal cal;
  KABC::Addressee::List list;

  if ( VCalDrag::decode( de, &cal ) || ICalDrag::decode( de, &cal ) ) {
    KTempFile tmp( locateLocal( "tmp", "incidences-" ), ".ics" );
    cal.save( tmp.name() );
    openComposer( QString::null, KURL::fromPathOrURL( tmp.name() ) );
  }
  else if ( KVCardDrag::decode( de, list ) ) {
    KABC::Addressee::List::Iterator it;
    QStringList to;
    for ( it = list.begin(); it != list.end(); ++it ) {
      to += ( *it ).fullEmail();
    }
    openComposer( to.join(", ") );
  }

}

void KMailPlugin::openComposer( const QString& to, const KURL& attach )
{
  (void) part(); // ensure part is loaded
  Q_ASSERT( mStub );
  if ( mStub ) {
    if ( attach.isValid() )
      mStub->openComposer( "", "", "", "", "", false, KURL(), attach );
    else
      mStub->newMessage();
  }
}

void KMailPlugin::slotNewMail()
{
  openComposer( KURL() );
}

void KMailPlugin::raise()
{
  core()->selectPlugin( this );
}

KMailPlugin::~KMailPlugin()
{
}

bool KMailPlugin::createDCOPInterface( const QString& serviceType )
{
  if ( serviceType == "DCOP/ResourceBackend/IMAP" ) {
    if ( part() )
      return true;
  }

  return false;
}

QString KMailPlugin::tipFile() const
{
  QString file = ::locate("data", "kmail/tips");
  return file;
}

KPIM::Part* KMailPlugin::createPart()
{
  KPIM::Part *part = loadPart();
  if ( !part ) return 0;

  connect( part, SIGNAL( raise() ), SLOT( raise() ) );

  mStub = new KMailIface_stub( dcopClient(), "kmail", "KMailIface" );

  return part;
}

QStringList KMailPlugin::invisibleToolbarActions() const
{
  return QStringList( "new_message" );
}

bool KMailPlugin::isRunningStandalone()
{
  return mUniqueAppWatcher->isRunningStandalone();
}

Kontact::Summary *KMailPlugin::createSummaryWidget( QWidget *parent )
{
  return new SummaryWidget( this, parent );
}

////

#include "../../../kmail/kmail_options.h"
void KMailUniqueAppHandler::loadCommandLineOptions()
{
    KCmdLineArgs::addCmdLineOptions( kmail_options );
}

int KMailUniqueAppHandler::newInstance()
{
    // Ensure part is loaded
    (void)plugin()->part();
    DCOPRef kmail( "kmail", "KMailIface" );
    DCOPReply reply = kmail.call( "handleCommandLine", false );
    if ( reply.isValid() ) {
        bool handled = reply;
        //kdDebug(5602) << k_funcinfo << "handled=" << handled << endl;
        if ( !handled ) // no args -> simply bring kmail plugin to front
            return Kontact::UniqueAppHandler::newInstance();
    }
    return 0;
}

bool KMailPlugin::queryClose() const {
  KMailIface_stub stub( kapp->dcopClient(), "kmail", "KMailIface" );
  bool canClose=stub.canQueryClose();
  return canClose;
}

#include "kmail_plugin.moc"
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of The Qt Company Ltd nor the names of its
**     contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/

/*
    treeitem.cpp

    A container for items of data supplied by the simple tree model.
*/

#include "treeitem.h"

#include <QStringList>
#include <QMessageBox>

#include <assert.h>

using namespace tln::docutils;

//! [0]

const QString TreeItem::default_header_attribute_name_string = "Attribute name";
const QString TreeItem::default_header_attribute_value_string = "Attribue value";
const QString TreeItem::default_header_element_name_string = "Element/node name";
const QString TreeItem::default_header_element_value_string = "Element value";
const QString TreeItem::default_element_name_string = "Sample_element";
const QString TreeItem::default_element_value_string = "Sample_value";
const QString TreeItem::attribute_element_name_string = "*attribute*";
const QString TreeItem::attribute_element_value_string = "*attribute*";

const QString TreeItem::forbidden_tag_name_characters = R"(^:\-\+\.\,!@#$%&*;~`"'<\^\(\)\\/\|\?\[\]\{\} )";

TreeItem::TreeItem(const QVector<QVariant> &data, TreeItem *parent, QObject *qparent, TreeItemType type)
	: QObject(qparent)
	, itemType(type)
	, tag_name_validator(QRegularExpression("[^0-9" + forbidden_tag_name_characters + "][" + forbidden_tag_name_characters + "]*"))
{
	parentItem = parent;
    itemData = data;

	bool data_empty = true;
	for (int i = 0; i < data.size(); ++i)
	{
		if (!data.at(i).toString().isEmpty())
			data_empty = false;
	}
	if(data_empty)
		populateColumnsWithDefaultValues();

	return;
}
//! [0]

//! [1]
TreeItem::~TreeItem()
{
    qDeleteAll(childItems);
	qDeleteAll(attributeItems);
}
//! [1]

//! [2]
TreeItem *TreeItem::child(int number)
{
	if (number >= attributeCount())
		return childItems.value(number - attributeCount());
	else
		return attributeItems.value(number);
}

TreeItem * TreeItem::element(const int number)
{
	if (number < 0 || number >= childItems.size())
		return nullptr;

	return childItems.value(number);
}

TreeItem * TreeItem::attribute(const int number)
{
	if (number < 0 || number > attributeItems.size())
		return nullptr;
	return attributeItems.value(number);
}
//! [2]

//! [3]
int TreeItem::childCount() const
{
    return childItems.count();
}
//! [3]

//! [4]
int TreeItem::childNumber() const
{
    if (parentItem)
        return parentItem->childItems.indexOf(const_cast<TreeItem*>(this));

    return 0;
}
//! [4]

//! [5]
int TreeItem::columnCount() const
{
    return itemData.count();
}
int TreeItem::attributeCount() const
{
	return attributeItems.count();
}
//! [5]

//! [6]
QVariant TreeItem::data(int column) const
{
    return itemData.value(column);
}
//! [6]

//! [7]
bool TreeItem::insertChildren(int position, int count, int columns)
{
    if (position < 0 || position > (childItems.size() + attributeItems.size()) || count <= 0 || itemType == TreeItemType::ATTRIBUTE)
        return false;

	if (childItems.size() == 0 && itemType != TreeItemType::HEADER)
	{
		this->setData(elementValueColumn, QVariant(""));
		this->itemType = TreeItemType::NODE;
	}

    for (int row = 0; row < count; ++row) {
        QVector<QVariant> data(columns);
        TreeItem *item = new TreeItem(data, this, this);
        childItems.insert(position, item);
    }

    return true;
}
//! [7]

bool TreeItem::insertAttributes(int position, int count, int columns)
{
	if (position < 0 || position > attributeItems.size() || count <= 0 || itemType == TreeItemType::ATTRIBUTE)
		return false;

	for (int row = 0; row < count; ++row)
	{
		QVector<QVariant> data(columns);

		TreeItem *item = nullptr;
		//if (attributeItems.size() != 0)
		//{
			item = new TreeItem(data, this, this, TreeItemType::ATTRIBUTE);
		//}
		//else
		//{
			//item = new TreeItem(data, nullptr, this, TreeItemType::ATTRIBUTE);
			//this->setData(attributeNameColumn, item->data(attributeNameColumn));
			//this->setData(attributeValueColumn, item->data(attributeValueColumn));
		//}
		attributeItems.insert(position, item);
	}

	return true;
}

//! [8]
bool TreeItem::insertColumns(int position, int columns)
{
    if (position < 0 || position > itemData.size())
        return false;

    for (int column = 0; column < columns; ++column)
        itemData.insert(position, QVariant());

    foreach (TreeItem *child, childItems)
        child->insertColumns(position, columns);

    return true;
}
//! [8]

//! [9]
TreeItem *TreeItem::parent()
{
    return parentItem;
}
//! [9]

//! [10]
bool TreeItem::removeChildren(int position, int count)
{
    if (position < 0 || position + count > childItems.size())
        return false;

    for (int row = 0; row < count; ++row)
        delete childItems.takeAt(position);

	// if all the children have been removed, the node becomes an element:
	if (this->childCount() == 0)
	{
		assert(this->type() == TreeItemType::NODE || this->type() == TreeItemType::HEADER);
		if (this->type() != TreeItemType::HEADER)
			this->itemType = TreeItemType::ELEMENT;
	}

    return true;
}
//! [10]

bool TreeItem::removeColumns(int position, int columns)
{
    if (position < 0 || position + columns > itemData.size())
        return false;

    for (int column = 0; column < columns; ++column)
        itemData.remove(position);

    foreach (TreeItem *child, childItems)
        child->removeColumns(position, columns);

    return true;
}

//! [11]
bool TreeItem::setData(int column, const QVariant &value)
{
    if (column < 0 || column >= itemData.size())
        return false;

	if (childCount() == 0 || column != 1)
	{
		if (column == 0)
		{
			int pos = 0;
			QValidator::State state = tag_name_validator.validate(value.toString(), pos);
			if (state == QValidator::Acceptable || this->type() == TreeItemType::ATTRIBUTE || this->type() == TreeItemType::HEADER)
				itemData[column] = value;
			else
			{
				QMessageBox::information(nullptr, "XKMLGen", tr("Incorrect tag name."));
				return false;
			}
		}
		else
		{
			itemData[column] = value;
		}
	}
	// it means that the element is a node and someone tries to edit its value column:
	else
	{
		emit changeOfNodeValueAttempted(itemData[0]);
		return false;
	}

	return true;
}
void TreeItem::populateColumnsWithDefaultValues()
{
	switch (type())
	{
	case TreeItemType::ELEMENT:
		this->setData(elementNameColumn, default_element_name_string);
		this->setData(elementValueColumn, default_element_value_string);
		break;
	case TreeItemType::ATTRIBUTE:
		this->setData(elementNameColumn, attribute_element_name_string);
		this->setData(elementValueColumn, attribute_element_value_string);
		break;
	case TreeItemType::NODE:
		this->setData(elementNameColumn, default_element_name_string);
		break;
	case TreeItemType::HEADER:
		this->setData(elementNameColumn, default_header_element_name_string);
		this->setData(elementValueColumn, default_header_element_value_string);
		this->setData(attributeNameColumn, default_header_element_name_string);
		this->setData(attributeValueColumn, default_header_attribute_value_string);
		break;
	}

	return;
}
//! [11]
<commit_msg>removeChildren() fixed to account for attributes.<commit_after>/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of The Qt Company Ltd nor the names of its
**     contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/

/*
    treeitem.cpp

    A container for items of data supplied by the simple tree model.
*/

#include "treeitem.h"

#include <QStringList>
#include <QMessageBox>

#include <assert.h>

using namespace tln::docutils;

//! [0]

const QString TreeItem::default_header_attribute_name_string = "Attribute name";
const QString TreeItem::default_header_attribute_value_string = "Attribue value";
const QString TreeItem::default_header_element_name_string = "Element/node name";
const QString TreeItem::default_header_element_value_string = "Element value";
const QString TreeItem::default_element_name_string = "Sample_element";
const QString TreeItem::default_element_value_string = "Sample_value";
const QString TreeItem::attribute_element_name_string = "*attribute*";
const QString TreeItem::attribute_element_value_string = "*attribute*";

const QString TreeItem::forbidden_tag_name_characters = R"(^:\-\+\.\,!@#$%&*;~`"'<\^\(\)\\/\|\?\[\]\{\} )";

TreeItem::TreeItem(const QVector<QVariant> &data, TreeItem *parent, QObject *qparent, TreeItemType type)
	: QObject(qparent)
	, itemType(type)
	, tag_name_validator(QRegularExpression("[^0-9" + forbidden_tag_name_characters + "][" + forbidden_tag_name_characters + "]*"))
{
	parentItem = parent;
    itemData = data;

	bool data_empty = true;
	for (int i = 0; i < data.size(); ++i)
	{
		if (!data.at(i).toString().isEmpty())
			data_empty = false;
	}
	if(data_empty)
		populateColumnsWithDefaultValues();

	return;
}
//! [0]

//! [1]
TreeItem::~TreeItem()
{
    qDeleteAll(childItems);
	qDeleteAll(attributeItems);
}
//! [1]

//! [2]
TreeItem *TreeItem::child(int number)
{
	if (number >= attributeCount())
		return childItems.value(number - attributeCount());
	else
		return attributeItems.value(number);
}

TreeItem * TreeItem::element(const int number)
{
	if (number < 0 || number >= childItems.size())
		return nullptr;

	return childItems.value(number);
}

TreeItem * TreeItem::attribute(const int number)
{
	if (number < 0 || number > attributeItems.size())
		return nullptr;
	return attributeItems.value(number);
}
//! [2]

//! [3]
int TreeItem::childCount() const
{
    return childItems.count();
}
//! [3]

//! [4]
int TreeItem::childNumber() const
{
    if (parentItem)
        return parentItem->childItems.indexOf(const_cast<TreeItem*>(this));

    return 0;
}
//! [4]

//! [5]
int TreeItem::columnCount() const
{
    return itemData.count();
}
int TreeItem::attributeCount() const
{
	return attributeItems.count();
}
//! [5]

//! [6]
QVariant TreeItem::data(int column) const
{
    return itemData.value(column);
}
//! [6]

//! [7]
bool TreeItem::insertChildren(int position, int count, int columns)
{
    if (position < 0 || position > (childItems.size() + attributeItems.size()) || count <= 0 || itemType == TreeItemType::ATTRIBUTE)
        return false;

	if (childItems.size() == 0 && itemType != TreeItemType::HEADER)
	{
		this->setData(elementValueColumn, QVariant(""));
		this->itemType = TreeItemType::NODE;
	}

    for (int row = 0; row < count; ++row) {
        QVector<QVariant> data(columns);
        TreeItem *item = new TreeItem(data, this, this);
        childItems.insert(position, item);
    }

    return true;
}
//! [7]

bool TreeItem::insertAttributes(int position, int count, int columns)
{
	if (position < 0 || position > attributeItems.size() || count <= 0 || itemType == TreeItemType::ATTRIBUTE)
		return false;

	for (int row = 0; row < count; ++row)
	{
		QVector<QVariant> data(columns);

		TreeItem *item = nullptr;
		//if (attributeItems.size() != 0)
		//{
			item = new TreeItem(data, this, this, TreeItemType::ATTRIBUTE);
		//}
		//else
		//{
			//item = new TreeItem(data, nullptr, this, TreeItemType::ATTRIBUTE);
			//this->setData(attributeNameColumn, item->data(attributeNameColumn));
			//this->setData(attributeValueColumn, item->data(attributeValueColumn));
		//}
		attributeItems.insert(position, item);
	}

	return true;
}

//! [8]
bool TreeItem::insertColumns(int position, int columns)
{
    if (position < 0 || position > itemData.size())
        return false;

    for (int column = 0; column < columns; ++column)
        itemData.insert(position, QVariant());

    foreach (TreeItem *child, childItems)
        child->insertColumns(position, columns);

    return true;
}
//! [8]

//! [9]
TreeItem *TreeItem::parent()
{
    return parentItem;
}
//! [9]

//! [10]
bool TreeItem::removeChildren(int position, int count)
{
    if (position < 0 || position + count > (childItems.size() + attributeItems.size()))
        return false;

	for (int row = 0; row < count; ++row)
	{
		if (position >= this->attributeCount())
			delete childItems.takeAt(position - this->attributeCount());
		else
			delete attributeItems.takeAt(position);
	}

	// if all the children have been removed, the node becomes an element:
	if (this->childCount() == 0)
	{
		assert(this->type() == TreeItemType::NODE || this->type() == TreeItemType::HEADER);
		if (this->type() != TreeItemType::HEADER)
			this->itemType = TreeItemType::ELEMENT;
	}

    return true;
}
//! [10]

bool TreeItem::removeColumns(int position, int columns)
{
    if (position < 0 || position + columns > itemData.size())
        return false;

    for (int column = 0; column < columns; ++column)
        itemData.remove(position);

    foreach (TreeItem *child, childItems)
        child->removeColumns(position, columns);

    return true;
}

//! [11]
bool TreeItem::setData(int column, const QVariant &value)
{
    if (column < 0 || column >= itemData.size())
        return false;

	if (childCount() == 0 || column != 1)
	{
		if (column == 0)
		{
			int pos = 0;
			QValidator::State state = tag_name_validator.validate(value.toString(), pos);
			if (state == QValidator::Acceptable || this->type() == TreeItemType::ATTRIBUTE || this->type() == TreeItemType::HEADER)
				itemData[column] = value;
			else
			{
				QMessageBox::information(nullptr, "XKMLGen", tr("Incorrect tag name."));
				return false;
			}
		}
		else
		{
			itemData[column] = value;
		}
	}
	// it means that the element is a node and someone tries to edit its value column:
	else
	{
		emit changeOfNodeValueAttempted(itemData[0]);
		return false;
	}

	return true;
}
void TreeItem::populateColumnsWithDefaultValues()
{
	switch (type())
	{
	case TreeItemType::ELEMENT:
		this->setData(elementNameColumn, default_element_name_string);
		this->setData(elementValueColumn, default_element_value_string);
		break;
	case TreeItemType::ATTRIBUTE:
		this->setData(elementNameColumn, attribute_element_name_string);
		this->setData(elementValueColumn, attribute_element_value_string);
		break;
	case TreeItemType::NODE:
		this->setData(elementNameColumn, default_element_name_string);
		break;
	case TreeItemType::HEADER:
		this->setData(elementNameColumn, default_header_element_name_string);
		this->setData(elementValueColumn, default_header_element_value_string);
		this->setData(attributeNameColumn, default_header_element_name_string);
		this->setData(attributeValueColumn, default_header_attribute_value_string);
		break;
	}

	return;
}
//! [11]
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: scdetect.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 22:49:39 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *
 ************************************************************************/

#ifndef _SC_TYPEDETECT_HXX
#define _SC_TYPEDETECT_HXX

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

#ifndef _COM_SUN_STAR_DOCUMENT_XEXTENDEDFILTERDETECTION_HPP_
#include <com/sun/star/document/XExtendedFilterDetection.hpp>
#endif

#ifndef _COM_SUN_STAR_UNO_EXCEPTION_HPP_
#include <com/sun/star/uno/Exception.hpp>
#endif

#ifndef _COM_SUN_STAR_UNO_REFERENCE_H_
#include <com/sun/star/uno/Reference.h>
#endif

#ifndef _CPPUHELPER_IMPLBASE2_HXX_
#include <cppuhelper/implbase2.hxx>
#endif

#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#include <cppuhelper/factory.hxx>
#include <tools/link.hxx>
#include <tools/string.hxx>

class SfxObjectFactory;
class SfxFilterMatcher;
class LoadEnvironment_Impl;
class SfxMedium;

namespace com
{
    namespace sun
    {
        namespace star
        {
            namespace uno
            {
                class Any;
            }
            namespace lang
            {
                class XMultiServiceFactory;
            }
            namespace frame
            {
                class XFrame;
            }
            namespace beans
            {
                struct PropertyValue;
            }
        }
    }
}

#include <sfx2/sfxuno.hxx>

#define REFERENCE ::com::sun::star::uno::Reference
#define SEQUENCE ::com::sun::star::uno::Sequence
#define RUNTIME_EXCEPTION ::com::sun::star::uno::RuntimeException

class ScFilterDetect : public ::cppu::WeakImplHelper2< ::com::sun::star::document::XExtendedFilterDetection, ::com::sun::star::lang::XServiceInfo >
{
public:
                            ScFilterDetect( const REFERENCE < ::com::sun::star::lang::XMultiServiceFactory >& xFactory );
    virtual                 ~ScFilterDetect();

    SFX_DECL_XSERVICEINFO

    //----------------------------------------------------------------------------------
    // XExtendedFilterDetect
    //----------------------------------------------------------------------------------
    virtual ::rtl::OUString SAL_CALL detect( SEQUENCE< ::com::sun::star::beans::PropertyValue >& lDescriptor ) throw( RUNTIME_EXCEPTION );
};

#endif
<commit_msg>INTEGRATION: CWS changefileheader (1.3.700); FILE MERGED 2008/04/01 15:31:16 thb 1.3.700.3: #i85898# Stripping all external header guards 2008/04/01 12:36:57 thb 1.3.700.2: #i85898# Stripping all external header guards 2008/03/31 17:19:35 rt 1.3.700.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: scdetect.hxx,v $
 * $Revision: 1.4 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _SC_TYPEDETECT_HXX
#define _SC_TYPEDETECT_HXX

#include <rtl/ustring.hxx>
#include <tools/debug.hxx>
#include <com/sun/star/document/XExtendedFilterDetection.hpp>
#include <com/sun/star/uno/Exception.hpp>
#include <com/sun/star/uno/Reference.h>
#include <cppuhelper/implbase2.hxx>

#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#include <cppuhelper/factory.hxx>
#include <tools/link.hxx>
#include <tools/string.hxx>

class SfxObjectFactory;
class SfxFilterMatcher;
class LoadEnvironment_Impl;
class SfxMedium;

namespace com
{
    namespace sun
    {
        namespace star
        {
            namespace uno
            {
                class Any;
            }
            namespace lang
            {
                class XMultiServiceFactory;
            }
            namespace frame
            {
                class XFrame;
            }
            namespace beans
            {
                struct PropertyValue;
            }
        }
    }
}

#include <sfx2/sfxuno.hxx>

#define REFERENCE ::com::sun::star::uno::Reference
#define SEQUENCE ::com::sun::star::uno::Sequence
#define RUNTIME_EXCEPTION ::com::sun::star::uno::RuntimeException

class ScFilterDetect : public ::cppu::WeakImplHelper2< ::com::sun::star::document::XExtendedFilterDetection, ::com::sun::star::lang::XServiceInfo >
{
public:
                            ScFilterDetect( const REFERENCE < ::com::sun::star::lang::XMultiServiceFactory >& xFactory );
    virtual                 ~ScFilterDetect();

    SFX_DECL_XSERVICEINFO

    //----------------------------------------------------------------------------------
    // XExtendedFilterDetect
    //----------------------------------------------------------------------------------
    virtual ::rtl::OUString SAL_CALL detect( SEQUENCE< ::com::sun::star::beans::PropertyValue >& lDescriptor ) throw( RUNTIME_EXCEPTION );
};

#endif
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "timermanager.h"

namespace dukat
{
    Timer* TimerManager::create_timer(float interval, std::function<void(void)> callback, bool recurring)
    {
        auto timer = std::make_unique<Timer>(interval, callback, recurring);
        auto res = timer.get();
        timers.push_back(std::move(timer));
        return res;
    }

    void TimerManager::cancel_timer(Timer* timer)
    {
        auto it = std::find_if(timers.begin(), timers.end(), [timer](const std::unique_ptr<Timer>& ptr) {
            return ptr.get() == timer;
        });
        if (it != timers.end())
        {
            timers.erase(it);
        }
    }

    void TimerManager::update(float delta)
    {
        for (auto it = timers.begin(); it != timers.end(); )
        {
            (*it)->remaining -= delta;
            // check if timer has expired
            if ((*it)->remaining <= 0.0f)
            {
                if ((*it)->callback)
                {
                    (*it)->callback();
                }

                if ((*it)->recurring)
                {
                    (*it)->remaining = (*it)->interval;
                }
                else
                {
                    timers.erase(it);
                    continue;
                }
            }

            ++it;
        }
    }
}<commit_msg>Fixed deletion of expired timers<commit_after>#include "stdafx.h"
#include "timermanager.h"

namespace dukat
{
    Timer* TimerManager::create_timer(float interval, std::function<void(void)> callback, bool recurring)
    {
        auto timer = std::make_unique<Timer>(interval, callback, recurring);
        auto res = timer.get();
        timers.push_back(std::move(timer));
        return res;
    }

    void TimerManager::cancel_timer(Timer* timer)
    {
        auto it = std::find_if(timers.begin(), timers.end(), [timer](const std::unique_ptr<Timer>& ptr) {
            return ptr.get() == timer;
        });
        if (it != timers.end())
        {
            timers.erase(it);
        }
    }

    void TimerManager::update(float delta)
    {
        for (auto it = timers.begin(); it != timers.end(); )
        {
            (*it)->remaining -= delta;
            // check if timer has expired
            if ((*it)->remaining <= 0.0f)
            {
                if ((*it)->callback)
                {
                    (*it)->callback();
                }

                if ((*it)->recurring)
                {
                    (*it)->remaining = (*it)->interval;
                }
                else
                {
                    it = timers.erase(it);
                    continue;
                }
            }

            ++it;
        }
    }
}<|endoftext|>


<commit_before>#pragma once
/*
**  Copyright (C) 2013 Aldebaran Robotics
**  See COPYING for the license
*/

#ifndef _QITYPE_DETAIL_PROPERTY_HXX_
#define _QITYPE_DETAIL_PROPERTY_HXX_

#include <boost/thread/locks.hpp>
#include <qi/property.hpp>
#include <qi/future.hpp>
#include <qi/property.hpp>
#include <ka/errorhandling.hpp>

namespace qi
{
  inline FutureSync<void> GenericProperty::set(const AnyValue& v)
  {
    auto conv = v.convert(_type);
    if (!conv->type())
      throw std::runtime_error(std::string("Failed converting ") + v.type()->infoString() + " to " + _type->infoString());

    const auto convOwnedRef = conv.ownsReference();
    return Property<AnyValue>::set(AnyValue(conv.release(), false, convOwnedRef));
  }

  template<typename T>
  SignalingProperty<T>::SignalingProperty(SignalBase::OnSubscribers onsubscribe)
    : SignalF<void(const T&)>(std::move(onsubscribe))
  {
  }

  template<typename T>
  SignalingProperty<T>::SignalingProperty(ExecutionContext* execContext,
                                          SignalBase::OnSubscribers onsubscribe)
    : SignalF<void(const T&)>(execContext, std::move(onsubscribe))
  {
  }

  template <typename T>
  PropertyImpl<T>::PropertyImpl(ExecutionContext* execContext,
                                Getter getter,
                                Setter setter,
                                SignalBase::OnSubscribers onsubscribe)
    : SignalingProperty<T>(execContext, std::move(onsubscribe))
    , _getter(std::move(getter))
    , _setter(std::move(setter))
  {
  }

  template <typename T>
  PropertyImpl<T>::PropertyImpl(Getter getter, Setter setter, SignalBase::OnSubscribers onsubscribe)
    : SignalingProperty<T>(std::move(onsubscribe))
    , _getter(std::move(getter))
    , _setter(std::move(setter))
  {
  }

  template <typename T>
  PropertyImpl<T>::PropertyImpl(AutoAnyReference defaultValue,
                                Getter getter,
                                Setter setter,
                                SignalBase::OnSubscribers onsubscribe)
    : SignalingProperty<T>(std::move(onsubscribe))
    , _getter(std::move(getter))
    , _setter(std::move(setter))
    , _value(defaultValue.to<T>())
  {
  }

  template <typename T>
  PropertyImpl<T>::PropertyImpl(AutoAnyReference defaultValue,
                                ExecutionContext* execContext,
                                Getter getter,
                                Setter setter,
                                SignalBase::OnSubscribers onsubscribe)
    : SignalingProperty<T>(execContext, std::move(onsubscribe))
    , _getter(std::move(getter))
    , _setter(std::move(setter))
    , _value(defaultValue.to<T>())
  {
  }

  template<typename T>
  T PropertyImpl<T>::getImpl() const
  {
    if (_getter)
      return _getter(boost::ref(_value));
    else
      return _value;
  }
  template<typename T>
  void PropertyImpl<T>::setImpl(const T& v)
  {
    qiLogDebug("qitype.property") << "set " << this << " " << (!!_setter);
    if (_setter)
    {
      const bool ok = _setter(boost::ref(_value), v);
      if (ok)
        (*this)(_value);
    }
    else
    {
      _value = v;
      (*this)(_value);
    }
  }

  template<typename T>
  ReadOnlyProperty<T>::ReadOnlyProperty(SignalingProperty<T>& s)
    : _source{ s }
    , _subscription{ s.connect(track([=](const T& val){ (*this)(val); }, this)) }
  {
  }

  template<typename T>
  ReadOnlyProperty<T>::~ReadOnlyProperty()
  {
    ka::invoke_catch(qi::exceptionLogError("qi.type.readonlyproperty",
                                           "Error while destroying a read only property"),
                     [&] {
                       Trackable<ReadOnlyProperty>::destroy();
                       _source.disconnectAsync(_subscription);
                     });
  }

  template<typename T>
  FutureSync<T> ReadOnlyProperty<T>::get() const
  {
    return _source.get();
  }

  template<typename T>
  FutureSync<AnyValue> ReadOnlyProperty<T>::value() const
  {
    return _source.get().async().then(FutureCallbackType_Sync, [](const T& v) {
      return AnyValue::from(v);
    });
  }

  template<typename T>
  FutureSync<void> ReadOnlyProperty<T>::setValue(AutoAnyReference)
  {
    return makeFutureError<void>("Property is read-only, it cannot be set from this interface.");
  }

  template<typename T>
  FutureSync<T> UnsafeProperty<T>::get() const
  {
    return FutureSync<T>(this->getImpl());
  }

  template<typename T>
  FutureSync<void> UnsafeProperty<T>::set(const T& v)
  {
    this->setImpl(v);
    return FutureSync<void>(0);
  }

  template<typename T>
  FutureSync<AnyValue> UnsafeProperty<T>::value() const
  {
    return FutureSync<AnyValue>(AnyValue::from(this->getImpl()));
  }

  template<typename T>
  FutureSync<void> UnsafeProperty<T>::setValue(AutoAnyReference value)
  {
    this->setImpl(value.to<T>());
    return FutureSync<void>(0);
  }

  template<typename T>
  Property<T>::~Property()
  {
    _tracked.destroy();
    joinStrand();
    SignalBase::clearExecutionContext();
  }

  template<typename T>
  FutureSync<T> Property<T>::get() const
  {
    return strand().async(track([this]{ return this->getImpl(); }, &_tracked));
  }

  template<typename T>
  FutureSync<void> Property<T>::set(const T& v)
  {
    return strand().async(track([this, v]{ this->setImpl(v); }, &_tracked));
  }

  template<typename T>
  FutureSync<AnyValue> Property<T>::value() const
  {
    return strand().async(track([this]{ return AnyValue::from(this->getImpl()); }, &_tracked));
  }

  template<typename T>
  FutureSync<void> Property<T>::setValue(AutoAnyReference value)
  {
    const auto v = value.to<T>();
    return strand().async(track([this, v]{ this->setImpl(v); }, &_tracked));
  }

  template<typename T>
  Strand& Property<T>::strand() const
  {
    struct Src : boost::static_visitor<Strand&>, ka::src_t {};
    return boost::apply_visitor(Src{}, _strand);
  }

  template<typename T>
  void Property<T>::joinStrand() QI_NOEXCEPT(true)
  {
    struct JoinStrand : boost::static_visitor<void>
    {
      void operator()(Strand*) const
      {
        // Do nothing, we do not own the strand, we have no right to join it.
      }

      void operator()(Strand& strand) const
      {
        strand.join();
      }
    };
    boost::apply_visitor(JoinStrand{}, _strand);
  }
}

#endif  // _QITYPE_DETAIL_PROPERTY_HXX_
<commit_msg>build: Fixes build error with android_arm-linux64 toolchain.<commit_after>#pragma once
/*
**  Copyright (C) 2013 Aldebaran Robotics
**  See COPYING for the license
*/

#ifndef _QITYPE_DETAIL_PROPERTY_HXX_
#define _QITYPE_DETAIL_PROPERTY_HXX_

#include <boost/thread/locks.hpp>
#include <qi/property.hpp>
#include <qi/future.hpp>
#include <qi/property.hpp>
#include <ka/errorhandling.hpp>

namespace qi
{
  inline FutureSync<void> GenericProperty::set(const AnyValue& v)
  {
    auto conv = v.convert(_type);
    if (!conv->type())
      throw std::runtime_error(std::string("Failed converting ") + v.type()->infoString() + " to " + _type->infoString());

    const auto convOwnedRef = conv.ownsReference();
    return Property<AnyValue>::set(AnyValue(conv.release(), false, convOwnedRef));
  }

  template<typename T>
  SignalingProperty<T>::SignalingProperty(SignalBase::OnSubscribers onsubscribe)
    : SignalF<void(const T&)>(std::move(onsubscribe))
  {
  }

  template<typename T>
  SignalingProperty<T>::SignalingProperty(ExecutionContext* execContext,
                                          SignalBase::OnSubscribers onsubscribe)
    : SignalF<void(const T&)>(execContext, std::move(onsubscribe))
  {
  }

  template <typename T>
  PropertyImpl<T>::PropertyImpl(ExecutionContext* execContext,
                                Getter getter,
                                Setter setter,
                                SignalBase::OnSubscribers onsubscribe)
    : SignalingProperty<T>(execContext, std::move(onsubscribe))
    , _getter(std::move(getter))
    , _setter(std::move(setter))
  {
  }

  template <typename T>
  PropertyImpl<T>::PropertyImpl(Getter getter, Setter setter, SignalBase::OnSubscribers onsubscribe)
    : SignalingProperty<T>(std::move(onsubscribe))
    , _getter(std::move(getter))
    , _setter(std::move(setter))
  {
  }

  template <typename T>
  PropertyImpl<T>::PropertyImpl(AutoAnyReference defaultValue,
                                Getter getter,
                                Setter setter,
                                SignalBase::OnSubscribers onsubscribe)
    : SignalingProperty<T>(std::move(onsubscribe))
    , _getter(std::move(getter))
    , _setter(std::move(setter))
    , _value(defaultValue.to<T>())
  {
  }

  template <typename T>
  PropertyImpl<T>::PropertyImpl(AutoAnyReference defaultValue,
                                ExecutionContext* execContext,
                                Getter getter,
                                Setter setter,
                                SignalBase::OnSubscribers onsubscribe)
    : SignalingProperty<T>(execContext, std::move(onsubscribe))
    , _getter(std::move(getter))
    , _setter(std::move(setter))
    , _value(defaultValue.to<T>())
  {
  }

  template<typename T>
  T PropertyImpl<T>::getImpl() const
  {
    if (_getter)
      return _getter(boost::ref(_value));
    else
      return _value;
  }
  template<typename T>
  void PropertyImpl<T>::setImpl(const T& v)
  {
    qiLogDebug("qitype.property") << "set " << this << " " << (!!_setter);
    if (_setter)
    {
      const bool ok = _setter(boost::ref(_value), v);
      if (ok)
        (*this)(_value);
    }
    else
    {
      _value = v;
      (*this)(_value);
    }
  }

  template<typename T>
  ReadOnlyProperty<T>::ReadOnlyProperty(SignalingProperty<T>& s)
    : _source{ s }
    , _subscription{ s.connect(track([=](const T& val){ (*this)(val); }, this)) }
  {
  }

  template<typename T>
  ReadOnlyProperty<T>::~ReadOnlyProperty()
  {
    ka::invoke_catch(qi::exceptionLogError("qi.type.readonlyproperty",
                                           "Error while destroying a read only property"),
                     [&] {
                       this->destroy();
                       _source.disconnectAsync(_subscription);
                     });
  }

  template<typename T>
  FutureSync<T> ReadOnlyProperty<T>::get() const
  {
    return _source.get();
  }

  template<typename T>
  FutureSync<AnyValue> ReadOnlyProperty<T>::value() const
  {
    return _source.get().async().then(FutureCallbackType_Sync, [](const T& v) {
      return AnyValue::from(v);
    });
  }

  template<typename T>
  FutureSync<void> ReadOnlyProperty<T>::setValue(AutoAnyReference)
  {
    return makeFutureError<void>("Property is read-only, it cannot be set from this interface.");
  }

  template<typename T>
  FutureSync<T> UnsafeProperty<T>::get() const
  {
    return FutureSync<T>(this->getImpl());
  }

  template<typename T>
  FutureSync<void> UnsafeProperty<T>::set(const T& v)
  {
    this->setImpl(v);
    return FutureSync<void>(0);
  }

  template<typename T>
  FutureSync<AnyValue> UnsafeProperty<T>::value() const
  {
    return FutureSync<AnyValue>(AnyValue::from(this->getImpl()));
  }

  template<typename T>
  FutureSync<void> UnsafeProperty<T>::setValue(AutoAnyReference value)
  {
    this->setImpl(value.to<T>());
    return FutureSync<void>(0);
  }

  template<typename T>
  Property<T>::~Property()
  {
    _tracked.destroy();
    joinStrand();
    SignalBase::clearExecutionContext();
  }

  template<typename T>
  FutureSync<T> Property<T>::get() const
  {
    return strand().async(track([this]{ return this->getImpl(); }, &_tracked));
  }

  template<typename T>
  FutureSync<void> Property<T>::set(const T& v)
  {
    return strand().async(track([this, v]{ this->setImpl(v); }, &_tracked));
  }

  template<typename T>
  FutureSync<AnyValue> Property<T>::value() const
  {
    return strand().async(track([this]{ return AnyValue::from(this->getImpl()); }, &_tracked));
  }

  template<typename T>
  FutureSync<void> Property<T>::setValue(AutoAnyReference value)
  {
    const auto v = value.to<T>();
    return strand().async(track([this, v]{ this->setImpl(v); }, &_tracked));
  }

  template<typename T>
  Strand& Property<T>::strand() const
  {
    struct Src : boost::static_visitor<Strand&>, ka::src_t {};
    return boost::apply_visitor(Src{}, _strand);
  }

  template<typename T>
  void Property<T>::joinStrand() QI_NOEXCEPT(true)
  {
    struct JoinStrand : boost::static_visitor<void>
    {
      void operator()(Strand*) const
      {
        // Do nothing, we do not own the strand, we have no right to join it.
      }

      void operator()(Strand& strand) const
      {
        strand.join();
      }
    };
    boost::apply_visitor(JoinStrand{}, _strand);
  }
}

#endif  // _QITYPE_DETAIL_PROPERTY_HXX_
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2012, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id$
 */

#ifndef PCL_FEATURES_IMPL_SHOT_LRF_OMP_H_
#define PCL_FEATURES_IMPL_SHOT_LRF_OMP_H_

#include <utility>
#include <pcl/features/shot_lrf_omp.h>
#include <pcl/features/shot_lrf.h>

template<typename PointInT, typename PointOutT>
void
pcl::SHOTLocalReferenceFrameEstimationOMP<PointInT, PointOutT>::computeFeature (PointCloudOut &output)
{
  if (threads_ < 0)
    threads_ = 1;

  //check whether used with search radius or search k-neighbors
  if (this->getKSearch () != 0)
  {
    PCL_ERROR(
        "[pcl::%s::computeFeature] Error! Search method set to k-neighborhood. Call setKSearch(0) and setRadiusSearch( radius ) to use this class.\n",
        getClassName().c_str ());
    return;
  }
  tree_->setSortedResults (true);

#pragma omp parallel for num_threads(threads_)
  for (size_t i = 0; i < indices_->size (); ++i)
  {
    // point result
    Eigen::Matrix3f rf;
    PointOutT& output_rf = output[i];

    //output_rf.confidence = getLocalRF ((*indices_)[i], rf);
    //if (output_rf.confidence == std::numeric_limits<float>::max ())

    std::vector<int> n_indices;
    std::vector<float> n_sqr_distances;
    searchForNeighbors ((*indices_)[i], search_parameter_, n_indices, n_sqr_distances);
    if (getLocalRF ((*indices_)[i], rf) == std::numeric_limits<float>::max ())
    {
      output.is_dense = false;
    }

    output_rf.x_axis.getNormalVector3fMap () = rf.row (0);
    output_rf.y_axis.getNormalVector3fMap () = rf.row (1);
    output_rf.z_axis.getNormalVector3fMap () = rf.row (2);
  }

}

template<typename PointInT, typename PointOutT>
void
pcl::SHOTLocalReferenceFrameEstimationOMP<PointInT, PointOutT>::computeFeatureEigen (pcl::PointCloud<Eigen::MatrixXf> &output)
{
  if (threads_ < 0)
     threads_ = 1;

  //check whether used with search radius or search k-neighbors
  if (this->getKSearch () != 0)
  {
    PCL_ERROR(
        "[pcl::%s::computeFeatureEigen] Error! Search method set to k-neighborhood. Call setKSearch(0) and setRadiusSearch( radius ) to use this class.\n",
        getClassName().c_str ());
    return;
  }
  tree_->setSortedResults (true);

  // Set up the output channels
  output.channels["shot_lrf"].name = "shot_lrf";
  output.channels["shot_lrf"].offset = 0;
  output.channels["shot_lrf"].size = 4;
  output.channels["shot_lrf"].count = 9;
  output.channels["shot_lrf"].datatype = sensor_msgs::PointField::FLOAT32;

  //output.points.resize (indices_->size (), 10);
  output.points.resize (indices_->size (), 9);

#pragma omp parallel for num_threads(threads_)
  for (size_t i = 0; i < indices_->size (); ++i)
  {
    // point result
    Eigen::Matrix3f rf;

    //output.points (i, 9) = getLocalRF ((*indices_)[i], rf);
    //if (output.points (i, 9) == std::numeric_limits<float>::max ())
    if (getLocalRF ((*indices_)[i], rf) == std::numeric_limits<float>::max ())
    {
      output.is_dense = false;
    }

    output.points.block<1, 3> (i, 0) = rf.row (0);
    output.points.block<1, 3> (i, 3) = rf.row (1);
    output.points.block<1, 3> (i, 6) = rf.row (2);
  }

}

#define PCL_INSTANTIATE_SHOTLocalReferenceFrameEstimationOMP(T,OutT) template class PCL_EXPORTS pcl::SHOTLocalReferenceFrameEstimationOMP<T,OutT>;

#endif    // PCL_FEATURES_IMPL_SHOT_LRF_H_
<commit_msg>Fixes compilation problem on Windows due to size_t variable in omp loop.<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2012, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id$
 */

#ifndef PCL_FEATURES_IMPL_SHOT_LRF_OMP_H_
#define PCL_FEATURES_IMPL_SHOT_LRF_OMP_H_

#include <utility>
#include <pcl/features/shot_lrf_omp.h>
#include <pcl/features/shot_lrf.h>

template<typename PointInT, typename PointOutT>
void
pcl::SHOTLocalReferenceFrameEstimationOMP<PointInT, PointOutT>::computeFeature (PointCloudOut &output)
{
  if (threads_ < 0)
    threads_ = 1;

  //check whether used with search radius or search k-neighbors
  if (this->getKSearch () != 0)
  {
    PCL_ERROR(
        "[pcl::%s::computeFeature] Error! Search method set to k-neighborhood. Call setKSearch(0) and setRadiusSearch( radius ) to use this class.\n",
        getClassName().c_str ());
    return;
  }
  tree_->setSortedResults (true);

  int data_size = static_cast<int> (indices_->size ());
#pragma omp parallel for num_threads(threads_)
  for (int i = 0; i < data_size; ++i)
  {
    // point result
    Eigen::Matrix3f rf;
    PointOutT& output_rf = output[i];

    //output_rf.confidence = getLocalRF ((*indices_)[i], rf);
    //if (output_rf.confidence == std::numeric_limits<float>::max ())

    std::vector<int> n_indices;
    std::vector<float> n_sqr_distances;
    searchForNeighbors ((*indices_)[i], search_parameter_, n_indices, n_sqr_distances);
    if (getLocalRF ((*indices_)[i], rf) == std::numeric_limits<float>::max ())
    {
      output.is_dense = false;
    }

    output_rf.x_axis.getNormalVector3fMap () = rf.row (0);
    output_rf.y_axis.getNormalVector3fMap () = rf.row (1);
    output_rf.z_axis.getNormalVector3fMap () = rf.row (2);
  }

}

template<typename PointInT, typename PointOutT>
void
pcl::SHOTLocalReferenceFrameEstimationOMP<PointInT, PointOutT>::computeFeatureEigen (pcl::PointCloud<Eigen::MatrixXf> &output)
{
  if (threads_ < 0)
     threads_ = 1;

  //check whether used with search radius or search k-neighbors
  if (this->getKSearch () != 0)
  {
    PCL_ERROR(
        "[pcl::%s::computeFeatureEigen] Error! Search method set to k-neighborhood. Call setKSearch(0) and setRadiusSearch( radius ) to use this class.\n",
        getClassName().c_str ());
    return;
  }
  tree_->setSortedResults (true);

  int data_size = static_cast<int> (indices_->size ());

  // Set up the output channels
  output.channels["shot_lrf"].name = "shot_lrf";
  output.channels["shot_lrf"].offset = 0;
  output.channels["shot_lrf"].size = 4;
  output.channels["shot_lrf"].count = 9;
  output.channels["shot_lrf"].datatype = sensor_msgs::PointField::FLOAT32;

  //output.points.resize (indices_->size (), 10);
  output.points.resize (data_size, 9);

#pragma omp parallel for num_threads(threads_)
  for (int i = 0; i < data_size; ++i)
  {
    // point result
    Eigen::Matrix3f rf;

    //output.points (i, 9) = getLocalRF ((*indices_)[i], rf);
    //if (output.points (i, 9) == std::numeric_limits<float>::max ())
    if (getLocalRF ((*indices_)[i], rf) == std::numeric_limits<float>::max ())
    {
      output.is_dense = false;
    }

    output.points.block<1, 3> (i, 0) = rf.row (0);
    output.points.block<1, 3> (i, 3) = rf.row (1);
    output.points.block<1, 3> (i, 6) = rf.row (2);
  }

}

#define PCL_INSTANTIATE_SHOTLocalReferenceFrameEstimationOMP(T,OutT) template class PCL_EXPORTS pcl::SHOTLocalReferenceFrameEstimationOMP<T,OutT>;

#endif    // PCL_FEATURES_IMPL_SHOT_LRF_H_
<|endoftext|>