<commit_before>#include <libmemcached/memcached.h>

#include <string>

class Memcached
{
public:

  Memcached()
    :
      memc(),
      result()
  {
    memcached_create(&memc);
  }

  Memcached(memcached_st *clone)
    :
      memc(),
      result()
  {
    memcached_clone(&memc, clone);
  }

  ~Memcached()
  {
    memcached_free(&memc);
  }

  std::string fetch(std::string& key, size_t *key_length, size_t *value_length)
  {
    uint32_t flags;
    memcached_return rc;
    std::string ret_val;

    char *value= memcached_fetch(&memc, const_cast<char *>(key.c_str()), key_length,
                                 value_length, &flags, &rc);
    if (value)
    {
      ret_val.assign(value);
    }
    return ret_val;
  }

  std::string get(const std::string& key, size_t *value_length)
  {
    uint32_t flags;
    memcached_return rc;
    std::string ret_val;

    char *value= memcached_get(&memc, key.c_str(), key.length(),
                               value_length, &flags, &rc);
    if (value)
    {
      ret_val.assign(value);
    }
    return ret_val;
  }

  std::string get_by_key(const std::string& master_key,
                         const std::string& key,
                         size_t *value_length)
  {
    uint32_t flags;
    memcached_return rc;
    std::string ret_val;

    char *value= memcached_get_by_key(&memc, master_key.c_str(), master_key.length(),
                                      key.c_str(), key.length(),
                                      value_length, &flags, &rc);
    if (value)
    {
      ret_val.assign(value);
    }
    return ret_val;
  }

  bool mget(char **keys, size_t *key_length,
            unsigned int number_of_keys)
  {

    memcached_return rc= memcached_mget(&memc, keys, key_length, number_of_keys);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool set(const std::string& key, const std::string& value)
  {
    memcached_return rc= memcached_set(&memc,
                                       key.c_str(), key.length(),
                                       value.c_str(), value.length(),
                                       time_t(0), uint32_t(0));
    return (rc == MEMCACHED_SUCCESS);
  }

  bool set_by_key(const std::string& master_key,
                  const std::string& key,
                  const std::string& value)
  {
    memcached_return rc= memcached_set_by_key(&memc, master_key.c_str(),
                                              master_key.length(),
                                              key.c_str(), key.length(),
                                              value.c_str(), value.length(),
                                              time_t(0),
                                              uint32_t(0));
    return (rc == MEMCACHED_SUCCESS);
  }

  bool increment(const std::string& key, unsigned int offset, uint64_t *value)
  {
    memcached_return rc= memcached_increment(&memc, key.c_str(), key.length(),
                                             offset, value);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool decrement(const std::string& key, unsigned int offset, uint64_t *value)
  {
    memcached_return rc= memcached_decrement(&memc, key.c_str(),
                                             key.length(),
                                             offset, value);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool add(const std::string& key, const std::string& value, size_t value_length)
  {
    memcached_return rc= memcached_add(&memc, key.c_str(), key.length(),
                                       value.c_str(), value_length, 0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool add_by_key(const std::string& master_key, const std::string& key,
                  const std::string& value, size_t value_length)
  {
    memcached_return rc= memcached_add_by_key(&memc,
                                              master_key.c_str(),
                                              master_key.length(),
                                              key.c_str(),
                                              key.length(),
                                              value.c_str(),
                                              value_length,
                                              0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool replace(const std::string& key, const std::string& value,
               size_t value_length)
  {
    memcached_return rc= memcached_replace(&memc, key.c_str(), key.length(),
                                           value.c_str(), value_length,
                                           0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool replace_by_key(const std::string& master_key, const std::string& key,
                      const std::string& value, size_t value_length)
  {
    memcached_return rc= memcached_replace_by_key(&memc,
                                                  master_key.c_str(),
                                                  master_key.length(),
                                                  key.c_str(),
                                                  key.length(),
                                                  value.c_str(),
                                                  value_length,
                                                  0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool prepend(const std::string& key, const std::string& value,
               size_t value_length)
  {
    memcached_return rc= memcached_prepend(&memc, key.c_str(), key.length(),
                                           value.c_str(), value_length, 0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool prepend_by_key(const std::string& master_key, const std::string& key,
                      const std::string& value, size_t value_length)
  {
    memcached_return rc= memcached_prepend_by_key(&memc,
                                                  master_key.c_str(),
                                                  master_key.length(),
                                                  key.c_str(),
                                                  key.length(),
                                                  value.c_str(),
                                                  value_length,
                                                  0,
                                                  0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool append(const std::string& key, const std::string& value,
              size_t value_length)
  {
    memcached_return rc= memcached_append(&memc,
                                          key.c_str(),
                                          key.length(),
                                          value.c_str(),
                                          value_length, 0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool append_by_key(const std::string& master_key, const std::string& key,
                     const std::string& value, size_t value_length)
  {
    memcached_return rc= memcached_append_by_key(&memc,
                                                 master_key.c_str(),
                                                 master_key.length(),
                                                 key.c_str(),
                                                 key.length(),
                                                 value.c_str(),
                                                 value_length, 0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool cas(const std::string& key, const std::string& value,
           size_t value_length, uint64_t cas_arg)
  {
    memcached_return rc= memcached_cas(&memc, key.c_str(), key.length(),
                                       value.c_str(), value_length, 0, 0, cas_arg);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool cas_by_key(const std::string& master_key, const std::string& key,
                  const std::string& value, size_t value_length,
                  uint64_t cas_arg)
  {
    memcached_return rc= memcached_cas_by_key(&memc,
                                              master_key.c_str(),
                                              master_key.length(),
                                              key.c_str(),
                                              key.length(),
                                              value.c_str(),
                                              value_length,
                                              0, 0, cas_arg);
    return (rc == MEMCACHED_SUCCESS);
  }

  // using 'remove' vs. 'delete' since 'delete' is a keyword
  bool remove(const std::string& key)
  {
    memcached_return rc= memcached_delete(&memc, key.c_str(), key.length(), 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool delete_by_key(const std::string& master_key,
                     const std::string& key)
  {
    memcached_return rc= memcached_delete_by_key(&memc,
                                                 master_key.c_str(),
                                                 master_key.length(),
                                                 key.c_str(),
                                                 key.length(),
                                                 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  const std::string lib_version() const
  {
    const char *ver= memcached_lib_version();
    const std::string version(ver);
    return version;
  }

private:
  memcached_st memc;
  memcached_result_st result;
};
<commit_msg>Cleaning up formatting in the C++ interface.<commit_after>#include <libmemcached/memcached.h>

#include <string>

class Memcached
{
public:

  Memcached()
    :
      memc(),
      result()
  {
    memcached_create(&memc);
  }

  Memcached(memcached_st *clone)
    :
      memc(),
      result()
  {
    memcached_clone(&memc, clone);
  }

  ~Memcached()
  {
    memcached_free(&memc);
  }

  std::string fetch(std::string &key, size_t *key_length, size_t *value_length)
  {
    uint32_t flags;
    memcached_return rc;
    std::string ret_val;

    char *value= memcached_fetch(&memc, const_cast<char *>(key.c_str()), key_length,
                                 value_length, &flags, &rc);
    if (value)
    {
      ret_val.assign(value);
    }
    return ret_val;
  }

  std::string get(const std::string &key, size_t *value_length)
  {
    uint32_t flags;
    memcached_return rc;
    std::string ret_val;

    char *value= memcached_get(&memc, key.c_str(), key.length(),
                               value_length, &flags, &rc);
    if (value)
    {
      ret_val.assign(value);
    }
    return ret_val;
  }

  std::string get_by_key(const std::string &master_key,
                         const std::string &key,
                         size_t *value_length)
  {
    uint32_t flags;
    memcached_return rc;
    std::string ret_val;

    char *value= memcached_get_by_key(&memc, master_key.c_str(), master_key.length(),
                                      key.c_str(), key.length(),
                                      value_length, &flags, &rc);
    if (value)
    {
      ret_val.assign(value);
    }
    return ret_val;
  }

  bool mget(char **keys, size_t *key_length,
            unsigned int number_of_keys)
  {

    memcached_return rc= memcached_mget(&memc, keys, key_length, number_of_keys);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool set(const std::string &key, const std::string &value)
  {
    memcached_return rc= memcached_set(&memc,
                                       key.c_str(), key.length(),
                                       value.c_str(), value.length(),
                                       time_t(0), uint32_t(0));
    return (rc == MEMCACHED_SUCCESS);
  }

  bool set_by_key(const std::string &master_key,
                  const std::string &key,
                  const std::string &value)
  {
    memcached_return rc= memcached_set_by_key(&memc, master_key.c_str(),
                                              master_key.length(),
                                              key.c_str(), key.length(),
                                              value.c_str(), value.length(),
                                              time_t(0),
                                              uint32_t(0));
    return (rc == MEMCACHED_SUCCESS);
  }

  bool increment(const std::string &key, unsigned int offset, uint64_t *value)
  {
    memcached_return rc= memcached_increment(&memc, key.c_str(), key.length(),
                                             offset, value);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool decrement(const std::string &key, unsigned int offset, uint64_t *value)
  {
    memcached_return rc= memcached_decrement(&memc, key.c_str(),
                                             key.length(),
                                             offset, value);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool add(const std::string &key, const std::string &value)
  {
    memcached_return rc= memcached_add(&memc, key.c_str(), key.length(),
                                       value.c_str(), value.length(), 0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool add_by_key(const std::string &master_key,
                  const std::string &key,
                  const std::string &value)
  {
    memcached_return rc= memcached_add_by_key(&memc,
                                              master_key.c_str(),
                                              master_key.length(),
                                              key.c_str(),
                                              key.length(),
                                              value.c_str(),
                                              value.length(),
                                              0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool replace(const std::string &key, const std::string &value)
  {
    memcached_return rc= memcached_replace(&memc, key.c_str(), key.length(),
                                           value.c_str(), value.length(),
                                           0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool replace_by_key(const std::string &master_key,
                      const std::string &key,
                      const std::string &value)
  {
    memcached_return rc= memcached_replace_by_key(&memc,
                                                  master_key.c_str(),
                                                  master_key.length(),
                                                  key.c_str(),
                                                  key.length(),
                                                  value.c_str(),
                                                  value.length(),
                                                  0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool prepend(const std::string &key, const std::string &value)
  {
    memcached_return rc= memcached_prepend(&memc, key.c_str(), key.length(),
                                           value.c_str(), value.length(), 0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool prepend_by_key(const std::string &master_key,
                      const std::string &key,
                      const std::string &value)
  {
    memcached_return rc= memcached_prepend_by_key(&memc,
                                                  master_key.c_str(),
                                                  master_key.length(),
                                                  key.c_str(),
                                                  key.length(),
                                                  value.c_str(),
                                                  value.length(),
                                                  0,
                                                  0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool append(const std::string &key, const std::string &value)
  {
    memcached_return rc= memcached_append(&memc,
                                          key.c_str(),
                                          key.length(),
                                          value.c_str(),
                                          value.length(),
                                          0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool append_by_key(const std::string &master_key,
                     const std::string &key,
                     const std::string &value)
  {
    memcached_return rc= memcached_append_by_key(&memc,
                                                 master_key.c_str(),
                                                 master_key.length(),
                                                 key.c_str(),
                                                 key.length(),
                                                 value.c_str(),
                                                 value.length(),
                                                 0, 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool cas(const std::string &key,
           const std::string &value,
           uint64_t cas_arg)
  {
    memcached_return rc= memcached_cas(&memc, key.c_str(), key.length(),
                                       value.c_str(), value.length(),
                                       0, 0, cas_arg);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool cas_by_key(const std::string &master_key,
                  const std::string &key,
                  const std::string &value,
                  uint64_t cas_arg)
  {
    memcached_return rc= memcached_cas_by_key(&memc,
                                              master_key.c_str(),
                                              master_key.length(),
                                              key.c_str(),
                                              key.length(),
                                              value.c_str(),
                                              value.length(),
                                              0, 0, cas_arg);
    return (rc == MEMCACHED_SUCCESS);
  }

  // using 'remove' vs. 'delete' since 'delete' is a keyword
  bool remove(const std::string &key)
  {
    memcached_return rc= memcached_delete(&memc, key.c_str(), key.length(), 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  bool delete_by_key(const std::string &master_key,
                     const std::string &key)
  {
    memcached_return rc= memcached_delete_by_key(&memc,
                                                 master_key.c_str(),
                                                 master_key.length(),
                                                 key.c_str(),
                                                 key.length(),
                                                 0);
    return (rc == MEMCACHED_SUCCESS);
  }

  const std::string lib_version() const
  {
    const char *ver= memcached_lib_version();
    const std::string version(ver);
    return version;
  }

private:
  memcached_st memc;
  memcached_result_st result;
};
<|endoftext|>


<commit_before>#ifndef LIBTEN_SCHEDULER_HH
#define LIBTEN_SCHEDULER_HH

#include <condition_variable>
#include "ten/descriptors.hh"
#include "ten/llqueue.hh"
#include "task_impl.hh"
#include "alarm.hh"
#include "io.hh"

namespace ten {

// TODO: api to register at-proc-exit cleanup functions
// this can be used to free io, or other per-proc
// resources like dns resolving threads, etc.

class scheduler {
    typedef ten::alarm_clock<ptr<task::pimpl>, proc_clock_t> alarm_clock;
    friend class proc;
    friend struct io;
    friend void this_task::sleep_until(const proc_time_t& sleep_time);
    friend class deadline;
    friend struct deadline_pimpl;
private:
    ptr<task::pimpl> ctask;
    context ctx;
    std::deque<ptr<task::pimpl>> runqueue;
    optional<io> _io;
    std::deque<std::shared_ptr<task::pimpl>> alltasks;
    //! other threads use this to add tasks to runqueue
    llqueue<ptr<task::pimpl>> dirtyq;

    //! tasks in this proc
    std::atomic<uint64_t> taskcount;
    //! current time cached in a few places through the event loop
    proc_time_t now;
    //! tasks with pending timeouts
    alarm_clock alarms;

    //! lock to protect condition
    std::mutex _mutex;
    //! cond used to wake up when runqueue is empty and no epoll
    std::condition_variable _cv;

    //! true when canceled
    std::atomic<bool> canceled;
    bool _shutdown_sequence_initiated = false;
private:
    void check_canceled();
    void check_dirty_queue();
    void check_timeout_tasks();
public:
    scheduler();
    ~scheduler();

    //! cancel all tasks in this scheduler
    void shutdown();
    io &get_io();

    //! call schedule in a loop while taskcount > 0
    void loop();
    //! run one iteration of the scheduler
    void schedule();

    const proc_time_t & update_cached_time() {
        now = proc_clock_t::now();
        return now;
    }

    const proc_time_t &cached_time() const {
        return now;
    }

    void attach_task(std::shared_ptr<task::pimpl> t);
    void remove_task(ptr<task::pimpl> t);

    void dump_tasks(std::ostream &out) const {
        for (auto &t : alltasks) {
            out << t << "\n";
        }
    }

    void wakeup();
    void wait(std::unique_lock <std::mutex> &lock, optional<proc_time_t> when);

    bool cancel_task_by_id(uint64_t id);

    ptr<task::pimpl> current_task() const {
        return ctask;
    }

    void cancel() {
        canceled = true;
        wakeup();
    }

    context &sched_context() { return ctx; }

private:
    friend class task;
    friend void this_task::yield();
    void ready(ptr<task::pimpl> t, bool front=false);
    void ready_for_io(ptr<task::pimpl> t);
    void unsafe_ready(ptr<task::pimpl> t);
};

} // ten

#endif

<commit_msg>fix taskdump<commit_after>#ifndef LIBTEN_SCHEDULER_HH
#define LIBTEN_SCHEDULER_HH

#include <condition_variable>
#include "ten/descriptors.hh"
#include "ten/llqueue.hh"
#include "task_impl.hh"
#include "alarm.hh"
#include "io.hh"

namespace ten {

// TODO: api to register at-proc-exit cleanup functions
// this can be used to free io, or other per-proc
// resources like dns resolving threads, etc.

class scheduler {
    typedef ten::alarm_clock<ptr<task::pimpl>, proc_clock_t> alarm_clock;
    friend class proc;
    friend struct io;
    friend void this_task::sleep_until(const proc_time_t& sleep_time);
    friend class deadline;
    friend struct deadline_pimpl;
private:
    ptr<task::pimpl> ctask;
    context ctx;
    std::deque<ptr<task::pimpl>> runqueue;
    optional<io> _io;
    std::deque<std::shared_ptr<task::pimpl>> alltasks;
    //! other threads use this to add tasks to runqueue
    llqueue<ptr<task::pimpl>> dirtyq;

    //! tasks in this proc
    std::atomic<uint64_t> taskcount;
    //! current time cached in a few places through the event loop
    proc_time_t now;
    //! tasks with pending timeouts
    alarm_clock alarms;

    //! lock to protect condition
    std::mutex _mutex;
    //! cond used to wake up when runqueue is empty and no epoll
    std::condition_variable _cv;

    //! true when canceled
    std::atomic<bool> canceled;
    bool _shutdown_sequence_initiated = false;
private:
    void check_canceled();
    void check_dirty_queue();
    void check_timeout_tasks();
public:
    scheduler();
    ~scheduler();

    //! cancel all tasks in this scheduler
    void shutdown();
    io &get_io();

    //! call schedule in a loop while taskcount > 0
    void loop();
    //! run one iteration of the scheduler
    void schedule();

    const proc_time_t & update_cached_time() {
        now = proc_clock_t::now();
        return now;
    }

    const proc_time_t &cached_time() const {
        return now;
    }

    void attach_task(std::shared_ptr<task::pimpl> t);
    void remove_task(ptr<task::pimpl> t);

    void dump_tasks(std::ostream &out) const {
        for (auto &t : alltasks) {
            out << ptr<task::pimpl>{t.get()} << "\n";
        }
    }

    void wakeup();
    void wait(std::unique_lock <std::mutex> &lock, optional<proc_time_t> when);

    bool cancel_task_by_id(uint64_t id);

    ptr<task::pimpl> current_task() const {
        return ctask;
    }

    void cancel() {
        canceled = true;
        wakeup();
    }

    context &sched_context() { return ctx; }

private:
    friend class task;
    friend void this_task::yield();
    void ready(ptr<task::pimpl> t, bool front=false);
    void ready_for_io(ptr<task::pimpl> t);
    void unsafe_ready(ptr<task::pimpl> t);
};

} // ten

#endif

<|endoftext|>


<commit_before>#include "mainwindow.h"
#include <QApplication>
#include <QTranslator>
#include <QLibraryInfo>

int main (int argc, char *argv[]){

     QApplication app(argc, argv);
     //Qt translations
     QTranslator qtTranslator;
     qtTranslator.load("qt_" + QLocale::system().name(),
       QLibraryInfo::location(QLibraryInfo::TranslationsPath));
     app.installTranslator(&qtTranslator);

     NobleNote window;
     window.show();
     return app.exec();
}
<commit_msg>test push<commit_after>#include "mainwindow.h"
#include <QApplication>
#include <QTranslator>
#include <QLibraryInfo>

int main (int argc, char *argv[]){

     QApplication app(argc, argv);
     //Qt translations
     QTranslator qtTranslator;
     qtTranslator.load("qt_" + QLocale::system().name(),
       QLibraryInfo::location(QLibraryInfo::TranslationsPath));
     app.installTranslator(&qtTranslator);

     NobleNote window;
     window.show();
     return app.exec();
}
<|endoftext|>


<commit_before>/*  -*-c++-*-
 *  Copyright (C) 2008 Cedric Pinson <cedric.pinson@plopbyte.net>
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * 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
 * OpenSceneGraph Public License for more details.
*/

#include <iostream>
#include <osg/Geometry>
#include <osg/Shape>
#include <osg/ShapeDrawable>
#include <osgViewer/Viewer>
#include <osgGA/TrackballManipulator>
#include <osg/MatrixTransform>

#include <osgAnimation/BasicAnimationManager>
#include <osgAnimation/Channel>
#include <osgAnimation/UpdateMatrixTransform>
#include <osgAnimation/StackedTranslateElement>

using namespace osgAnimation;

osg::ref_ptr<osg::Geode> createAxis()
{
    osg::ref_ptr<osg::Geode> geode (new osg::Geode());
    osg::ref_ptr<osg::Geometry> geometry (new osg::Geometry());

    osg::ref_ptr<osg::Vec3Array> vertices (new osg::Vec3Array());
    vertices->push_back (osg::Vec3 ( 0.0, 0.0, 0.0));
    vertices->push_back (osg::Vec3 ( 10.0, 0.0, 0.0));
    vertices->push_back (osg::Vec3 ( 0.0, 0.0, 0.0));
    vertices->push_back (osg::Vec3 ( 0.0, 10.0, 0.0));
    vertices->push_back (osg::Vec3 ( 0.0, 0.0, 0.0));
    vertices->push_back (osg::Vec3 ( 0.0, 0.0, 10.0));
    geometry->setVertexArray (vertices.get());

    osg::ref_ptr<osg::Vec4Array> colors (new osg::Vec4Array());
    colors->push_back (osg::Vec4 (1.0f, 0.0f, 0.0f, 1.0f));
    colors->push_back (osg::Vec4 (1.0f, 0.0f, 0.0f, 1.0f));
    colors->push_back (osg::Vec4 (0.0f, 1.0f, 0.0f, 1.0f));
    colors->push_back (osg::Vec4 (0.0f, 1.0f, 0.0f, 1.0f));
    colors->push_back (osg::Vec4 (0.0f, 0.0f, 1.0f, 1.0f));
    colors->push_back (osg::Vec4 (0.0f, 0.0f, 1.0f, 1.0f));
    geometry->setColorArray (colors.get());

    geometry->setColorBinding (osg::Geometry::BIND_PER_VERTEX);
    geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,6));

    geode->addDrawable( geometry.get() );
    geode->getOrCreateStateSet()->setMode(GL_LIGHTING, false);
    return geode;
}

int main (int argc, char* argv[])
{
    osg::ArgumentParser arguments(&argc, argv);
    osgViewer::Viewer viewer(arguments);

    viewer.setCameraManipulator(new osgGA::TrackballManipulator());

    osg::Group* root = new osg::Group;

    osg::ref_ptr<osg::Geode> axe = createAxis();
    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
    geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.0f,0.0f,0.0f),0.5)));

    osg::ref_ptr<osg::MatrixTransform> trans = new osg::MatrixTransform();
    trans->setName("AnimatedNode");
    trans->setDataVariance(osg::Object::DYNAMIC);
    osgAnimation::UpdateMatrixTransform* updatecb = new osgAnimation::UpdateMatrixTransform("AnimatedCallback");
    updatecb->getStackedTransforms().push_back(new osgAnimation::StackedTranslateElement("position"));
    trans->setUpdateCallback(updatecb);
    trans->setMatrix(osg::Matrix::identity());
    trans->addChild (geode.get());

    root->addChild (axe.get());
    root->addChild (trans.get());

    // Define a scheduler for our animations
    osg::Group* grp = new osg::Group;
    osgAnimation::BasicAnimationManager* mng = new osgAnimation::BasicAnimationManager();
    grp->setUpdateCallback(mng);

    grp->addChild(root);

    // And we finaly define our channel
    osgAnimation::Vec3LinearChannel* channelAnimation1 = new osgAnimation::Vec3LinearChannel;
    channelAnimation1->setTargetName("AnimatedCallback");
    channelAnimation1->setName("position");
    channelAnimation1->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::Vec3Keyframe(0, osg::Vec3(0,0,0)));
    channelAnimation1->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::Vec3Keyframe(2, osg::Vec3(1,1,0)));
    osgAnimation::Animation* anim1 = new osgAnimation::Animation;
    anim1->addChannel(channelAnimation1);
    anim1->setPlayMode(osgAnimation::Animation::PPONG);

    osgAnimation::Vec3LinearChannel* channelAnimation2 = new osgAnimation::Vec3LinearChannel;
    channelAnimation2->setTargetName("AnimatedCallback");
    channelAnimation2->setName("euler");
    channelAnimation2->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::Vec3Keyframe(0, osg::Vec3(0,0,0)));
    channelAnimation2->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::Vec3Keyframe(1.5, osg::Vec3(2*osg::PI,0,0)));
    osgAnimation::Animation* anim2 = new osgAnimation::Animation;
    anim2->addChannel(channelAnimation2);
    anim2->setPlayMode(osgAnimation::Animation::LOOP);

    // We register all animation inside the scheduler
    mng->registerAnimation(anim1);
    mng->registerAnimation(anim2);

    mng->playAnimation(anim1);
    mng->playAnimation(anim2);

    viewer.setSceneData( grp );
    return viewer.run();
}
<commit_msg>From Jan Klimke, "I did recently some work understanding the osgAnimation classes. Here the osganimationsolid example seems not to be very helpful at the moment. There are basically no comments in it and additionally there is a second animation defined which was simply not working (wrong channel type for angle animation). I added some comments and fixed the example to contain 2 working animations by now. I think this could help others who are trying to understand the osgAnimation plugin.<commit_after>/*  -*-c++-*-
 *  Copyright (C) 2008 Cedric Pinson <cedric.pinson@plopbyte.net>
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * 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
 * OpenSceneGraph Public License for more details.
*/

#include <iostream>
#include <osg/Geometry>
#include <osg/Shape>
#include <osg/ShapeDrawable>
#include <osgViewer/Viewer>
#include <osgGA/TrackballManipulator>
#include <osg/MatrixTransform>

#include <osgAnimation/BasicAnimationManager>
#include <osgAnimation/Channel>
#include <osgAnimation/UpdateMatrixTransform>
#include <osgAnimation/StackedTranslateElement>
#include <osgAnimation/StackedRotateAxisElement>

using namespace osgAnimation;

osg::ref_ptr<osg::Geode> createAxis()
{
    osg::ref_ptr<osg::Geode> geode (new osg::Geode());
    osg::ref_ptr<osg::Geometry> geometry (new osg::Geometry());

    osg::ref_ptr<osg::Vec3Array> vertices (new osg::Vec3Array());
    vertices->push_back (osg::Vec3 ( 0.0, 0.0, 0.0));
    vertices->push_back (osg::Vec3 ( 10.0, 0.0, 0.0));
    vertices->push_back (osg::Vec3 ( 0.0, 0.0, 0.0));
    vertices->push_back (osg::Vec3 ( 0.0, 10.0, 0.0));
    vertices->push_back (osg::Vec3 ( 0.0, 0.0, 0.0));
    vertices->push_back (osg::Vec3 ( 0.0, 0.0, 10.0));
    geometry->setVertexArray (vertices.get());

    osg::ref_ptr<osg::Vec4Array> colors (new osg::Vec4Array());
    colors->push_back (osg::Vec4 (1.0f, 0.0f, 0.0f, 1.0f));
    colors->push_back (osg::Vec4 (1.0f, 0.0f, 0.0f, 1.0f));
    colors->push_back (osg::Vec4 (0.0f, 1.0f, 0.0f, 1.0f));
    colors->push_back (osg::Vec4 (0.0f, 1.0f, 0.0f, 1.0f));
    colors->push_back (osg::Vec4 (0.0f, 0.0f, 1.0f, 1.0f));
    colors->push_back (osg::Vec4 (0.0f, 0.0f, 1.0f, 1.0f));
    geometry->setColorArray (colors.get());

    geometry->setColorBinding (osg::Geometry::BIND_PER_VERTEX);
    geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,6));

    geode->addDrawable( geometry.get() );
    geode->getOrCreateStateSet()->setMode(GL_LIGHTING, false);
    return geode;
}

int main (int argc, char* argv[])
{
    osg::ArgumentParser arguments(&argc, argv);
    osgViewer::Viewer viewer(arguments);

    viewer.setCameraManipulator(new osgGA::TrackballManipulator());

    osg::Group* root = new osg::Group;

    osg::ref_ptr<osg::Geode> axe = createAxis();
    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
    geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.0f,0.0f,0.0f),0.5)));

    //Tranformation to be manipulated by the animation
    osg::ref_ptr<osg::MatrixTransform> trans = new osg::MatrixTransform();
    trans->setName("AnimatedNode");
    //Dynamic object, has to be updated during update traversal
    trans->setDataVariance(osg::Object::DYNAMIC);
    //Animation callback for Matrix transforms, name is targetName for Channels
    osgAnimation::UpdateMatrixTransform* updatecb = new osgAnimation::UpdateMatrixTransform("AnimatedCallback");
    //add manipulator Stack, names must match with channel names
    //elements are applied in LIFO order
    //The first element modifies the position component of the matrix
    //The second element modifies the rotation around x-axis
    updatecb->getStackedTransforms().push_back(new osgAnimation::StackedTranslateElement("position"));
    updatecb->getStackedTransforms().push_back(new osgAnimation::StackedRotateAxisElement("euler",osg::Vec3(1,0,0),0));
    //connect the UpdateMatrixTransform callback to the MatrixTRanform
    trans->setUpdateCallback(updatecb);
    //initialize MatrixTranform
    trans->setMatrix(osg::Matrix::identity());
    //append geometry node
    trans->addChild (geode.get());

    root->addChild (axe.get());
    root->addChild (trans.get());

    // Define a scheduler for our animations
    osg::Group* grp = new osg::Group;
    //add the animation manager to the scene graph to get it called during update traversals
    osgAnimation::BasicAnimationManager* mng = new osgAnimation::BasicAnimationManager();
    grp->setUpdateCallback(mng);
    //add the rest of the scene to the grp node
    grp->addChild(root);

    // And we finaly define our channel for linear Vector interpolation
    osgAnimation::Vec3LinearChannel* channelAnimation1 = new osgAnimation::Vec3LinearChannel;
    //name of the AnimationUpdateCallback
    channelAnimation1->setTargetName("AnimatedCallback");
    //name of the StackedElementTransform for position modification
    channelAnimation1->setName("position");
    //Create keyframes for (in this case linear) interpolation of a osg::Vec3
    channelAnimation1->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::Vec3Keyframe(0, osg::Vec3(0,0,0)));
    channelAnimation1->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::Vec3Keyframe(2, osg::Vec3(1,1,0)));
    osgAnimation::Animation* anim1 = new osgAnimation::Animation;
    anim1->addChannel(channelAnimation1);
    anim1->setPlayMode(osgAnimation::Animation::PPONG);

    //define the channel for interpolation of a float angle value
    osgAnimation::FloatLinearChannel* channelAnimation2 = new osgAnimation::FloatLinearChannel;
    //name of the AnimationUpdateCallback
    channelAnimation2->setTargetName("AnimatedCallback");
    //name of the StackedElementTransform for position modification
    channelAnimation2->setName("euler");
    //Create keyframes for (in this case linear) interpolation of a osg::Vec3
    channelAnimation2->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::FloatKeyframe(0, 0));
    channelAnimation2->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::FloatKeyframe(1.5, 2*osg::PI));
    osgAnimation::Animation* anim2 = new osgAnimation::Animation;
    anim2->addChannel(channelAnimation2);
    anim2->setPlayMode(osgAnimation::Animation::LOOP);

    // We register all animation inside the scheduler
    mng->registerAnimation(anim1);
    mng->registerAnimation(anim2);

    //start the animation
    mng->playAnimation(anim1);
    mng->playAnimation(anim2);

    //set the grp-Group with the scene and the AnimationManager as viewer's scene data
    viewer.setSceneData( grp );
    return viewer.run();
}
<|endoftext|>


<commit_before>#include <fstream>

#include <boost/filesystem.hpp>

#include <util/helpers.hpp>
#include <imageprocessing/ConnectedComponent.h>
#include <sopnet/exceptions.h>
#include <sopnet/segments/EndSegment.h>
#include <sopnet/segments/ContinuationSegment.h>
#include <sopnet/segments/BranchSegment.h>
#include "GeometryFeatureExtractor.h"

logger::LogChannel geometryfeatureextractorlog("geometryfeatureextractorlog", "[GeometryFeatureExtractor] ");

util::ProgramOption optionDisableSliceDistanceFeature(
		util::_module           = "sopnet.features",
		util::_long_name        = "disableSliceDistanceFeature",
		util::_description_text = "Disable the use of slice distance features.");

GeometryFeatureExtractor::GeometryFeatureExtractor() :
	_features(new Features()),
	_overlap(false, false),
	_alignedOverlap(false, true),
	_noSliceDistance(optionDisableSliceDistanceFeature) {

	registerInput(_segments, "segments");
	registerOutput(_features, "features");
}

void
GeometryFeatureExtractor::updateOutputs() {

	LOG_DEBUG(geometryfeatureextractorlog) << "extracting features" << std::endl;

	_features->clear();

	if (_noSliceDistance)
		_features->resize(_segments->size(), 11);
	else
		_features->resize(_segments->size(), 15);

	// features for end segments
	_features->addName("e size");

	// features for continuation and branch
	_features->addName("c&b center distance");
	_features->addName("c&b set difference");
	_features->addName("c&b set difference ratio");
	_features->addName("c&b aligned set difference");
	_features->addName("c&b aligned set difference ratio");
	_features->addName("c&b size");
	_features->addName("c&b overlap");
	_features->addName("c&b overlap ratio");
	_features->addName("c&b aligned overlap");
	_features->addName("c&b aligned overlap ratio");

	if (!_noSliceDistance) {

		_features->addName("c&b average slice distance");
		_features->addName("c&b max slice distance");
		_features->addName("c&b aligned average slice distance");
		_features->addName("c&b aligned max slice distance");
	}

	foreach (boost::shared_ptr<EndSegment> segment, _segments->getEnds())
		getFeatures(*segment);

	foreach (boost::shared_ptr<ContinuationSegment> segment, _segments->getContinuations())
		getFeatures(*segment);

	foreach (boost::shared_ptr<BranchSegment> segment, _segments->getBranches())
		getFeatures(*segment);

	LOG_ALL(geometryfeatureextractorlog) << "found features: " << *_features << std::endl;

	LOG_DEBUG(geometryfeatureextractorlog) << "done" << std::endl;

	// free memory
	_distance.clearCache();
}

template <typename SegmentType>
void
GeometryFeatureExtractor::getFeatures(const SegmentType& segment) {

	computeFeatures(segment, _features->get(segment.getId()));
}

void
GeometryFeatureExtractor::computeFeatures(const EndSegment& end, std::vector<double>& features) {

	features[0] = end.getSlice()->getComponent()->getSize();
	features[1] = Features::NoFeatureValue;
	features[2] = Features::NoFeatureValue;
	features[3] = Features::NoFeatureValue;
	features[4] = Features::NoFeatureValue;
	features[5] = Features::NoFeatureValue;
	features[6] = Features::NoFeatureValue;
	features[7] = Features::NoFeatureValue;
	features[8] = Features::NoFeatureValue;
	features[9] = Features::NoFeatureValue;
	features[10] = Features::NoFeatureValue;

	if (!_noSliceDistance) {

		features[11] = Features::NoFeatureValue;
		features[12] = Features::NoFeatureValue;
		features[13] = Features::NoFeatureValue;
		features[14] = Features::NoFeatureValue;
	}
}

void
GeometryFeatureExtractor::computeFeatures(const ContinuationSegment& continuation, std::vector<double>& features) {

	const util::point<double>& sourceCenter = continuation.getSourceSlice()->getComponent()->getCenter();
	const util::point<double>& targetCenter = continuation.getTargetSlice()->getComponent()->getCenter();

	unsigned int sourceSize = continuation.getSourceSlice()->getComponent()->getSize();
	unsigned int targetSize = continuation.getTargetSlice()->getComponent()->getSize();

	util::point<double> difference = sourceCenter - targetCenter;

	double distance = difference.x*difference.x + difference.y*difference.y;

	double overlap = _overlap(*continuation.getSourceSlice(), *continuation.getTargetSlice());

	double overlapRatio = overlap/(sourceSize + targetSize - overlap);

	double alignedOverlap = _alignedOverlap(*continuation.getSourceSlice(), *continuation.getTargetSlice());

	double alignedOverlapRatio = alignedOverlap/(sourceSize + targetSize - overlap);

	double setDifference = (sourceSize - overlap) + (targetSize - overlap);

	double setDifferenceRatio = setDifference/(sourceSize + targetSize);

	double alignedSetDifference = (sourceSize - alignedOverlap) + (targetSize - alignedOverlap);

	double alignedSetDifferenceRatio = alignedSetDifference/(sourceSize + targetSize);

	features[0] = Features::NoFeatureValue;
	features[1] = distance;
	features[2] = setDifference;
	features[3] = setDifferenceRatio;
	features[4] = alignedSetDifference;
	features[5] = alignedSetDifferenceRatio;
	features[6] =
			(continuation.getSourceSlice()->getComponent()->getSize() +
			 continuation.getTargetSlice()->getComponent()->getSize())*0.5;
	features[7] = overlap;
	features[8] = overlapRatio;
	features[0] = alignedOverlap;
	features[10] = alignedOverlapRatio;

	if (!_noSliceDistance) {

		double averageSliceDistance, maxSliceDistance;

		_distance(*continuation.getSourceSlice(), *continuation.getTargetSlice(), true, false, averageSliceDistance, maxSliceDistance);

		double alignedAverageSliceDistance, alignedMaxSliceDistance;

		_distance(*continuation.getSourceSlice(), *continuation.getTargetSlice(), true, true, alignedAverageSliceDistance, alignedMaxSliceDistance);

		features[11] = averageSliceDistance;
		features[12] = maxSliceDistance;
		features[13] = alignedAverageSliceDistance;
		features[14] = alignedMaxSliceDistance;
	}
}

void
GeometryFeatureExtractor::computeFeatures(const BranchSegment& branch, std::vector<double>& features) {

	const util::point<double>& sourceCenter  = branch.getSourceSlice()->getComponent()->getCenter();
	const util::point<double>& targetCenter1 = branch.getTargetSlice1()->getComponent()->getCenter();
	const util::point<double>& targetCenter2 = branch.getTargetSlice2()->getComponent()->getCenter();

	unsigned int sourceSize  = branch.getSourceSlice()->getComponent()->getSize();
	unsigned int targetSize1 = branch.getTargetSlice1()->getComponent()->getSize();
	unsigned int targetSize2 = branch.getTargetSlice2()->getComponent()->getSize();
	unsigned int targetSize  = targetSize1 + targetSize2;

	util::point<double> difference = sourceCenter - (targetCenter1*targetSize1 + targetCenter2*targetSize2)/((double)(targetSize));

	double distance = difference.x*difference.x + difference.y*difference.y;

	double overlap = _overlap(*branch.getTargetSlice1(), *branch.getTargetSlice2(), *branch.getSourceSlice());

	double overlapRatio = overlap/(sourceSize + targetSize - overlap);

	double alignedOverlap = _alignedOverlap(*branch.getTargetSlice1(), *branch.getTargetSlice2(), *branch.getSourceSlice());

	double alignedOverlapRatio = alignedOverlap/(sourceSize + targetSize - alignedOverlap);

	double setDifference = (sourceSize - overlap) + (targetSize - overlap);

	double setDifferenceRatio = setDifference/(sourceSize + targetSize);

	double alignedSetDifference = (sourceSize - alignedOverlap) + (targetSize - alignedOverlap);

	double alignedSetDifferenceRatio = alignedSetDifference/(sourceSize + targetSize);

	features[0] = Features::NoFeatureValue;
	features[1] = distance;
	features[2] = setDifference;
	features[3] = setDifferenceRatio;
	features[4] = alignedSetDifference;
	features[5] = alignedSetDifferenceRatio;
	features[6] =
			(branch.getSourceSlice()->getComponent()->getSize() +
			 branch.getTargetSlice1()->getComponent()->getSize() +
			 branch.getTargetSlice2()->getComponent()->getSize())/3.0;
	features[7] = overlap;
	features[8] = overlapRatio;
	features[9] = alignedOverlap;
	features[10] = alignedOverlapRatio;

	if (!_noSliceDistance) {

		double averageSliceDistance, maxSliceDistance;

		_distance(*branch.getTargetSlice1(), *branch.getTargetSlice2(), *branch.getSourceSlice(), true, false, averageSliceDistance, maxSliceDistance);

		double alignedAverageSliceDistance, alignedMaxSliceDistance;

		_distance(*branch.getTargetSlice1(), *branch.getTargetSlice2(), *branch.getSourceSlice(), true, true, alignedAverageSliceDistance, alignedMaxSliceDistance);

		features[11] = averageSliceDistance;
		features[12] = maxSliceDistance;
		features[13] = alignedAverageSliceDistance;
		features[14] = alignedMaxSliceDistance;
	}
}
<commit_msg>Fixed e-size bug: the aligned overlap feature for continuations was written to the end segment size field instead of its own field<commit_after>#include <fstream>

#include <boost/filesystem.hpp>

#include <util/helpers.hpp>
#include <imageprocessing/ConnectedComponent.h>
#include <sopnet/exceptions.h>
#include <sopnet/segments/EndSegment.h>
#include <sopnet/segments/ContinuationSegment.h>
#include <sopnet/segments/BranchSegment.h>
#include "GeometryFeatureExtractor.h"

logger::LogChannel geometryfeatureextractorlog("geometryfeatureextractorlog", "[GeometryFeatureExtractor] ");

util::ProgramOption optionDisableSliceDistanceFeature(
		util::_module           = "sopnet.features",
		util::_long_name        = "disableSliceDistanceFeature",
		util::_description_text = "Disable the use of slice distance features.");

GeometryFeatureExtractor::GeometryFeatureExtractor() :
	_features(new Features()),
	_overlap(false, false),
	_alignedOverlap(false, true),
	_noSliceDistance(optionDisableSliceDistanceFeature) {

	registerInput(_segments, "segments");
	registerOutput(_features, "features");
}

void
GeometryFeatureExtractor::updateOutputs() {

	LOG_DEBUG(geometryfeatureextractorlog) << "extracting features" << std::endl;

	_features->clear();

	if (_noSliceDistance)
		_features->resize(_segments->size(), 11);
	else
		_features->resize(_segments->size(), 15);

	// features for end segments
	_features->addName("e size");

	// features for continuation and branch
	_features->addName("c&b center distance");
	_features->addName("c&b set difference");
	_features->addName("c&b set difference ratio");
	_features->addName("c&b aligned set difference");
	_features->addName("c&b aligned set difference ratio");
	_features->addName("c&b size");
	_features->addName("c&b overlap");
	_features->addName("c&b overlap ratio");
	_features->addName("c&b aligned overlap");
	_features->addName("c&b aligned overlap ratio");

	if (!_noSliceDistance) {

		_features->addName("c&b average slice distance");
		_features->addName("c&b max slice distance");
		_features->addName("c&b aligned average slice distance");
		_features->addName("c&b aligned max slice distance");
	}

	foreach (boost::shared_ptr<EndSegment> segment, _segments->getEnds())
		getFeatures(*segment);

	foreach (boost::shared_ptr<ContinuationSegment> segment, _segments->getContinuations())
		getFeatures(*segment);

	foreach (boost::shared_ptr<BranchSegment> segment, _segments->getBranches())
		getFeatures(*segment);

	LOG_ALL(geometryfeatureextractorlog) << "found features: " << *_features << std::endl;

	LOG_DEBUG(geometryfeatureextractorlog) << "done" << std::endl;

	// free memory
	_distance.clearCache();
}

template <typename SegmentType>
void
GeometryFeatureExtractor::getFeatures(const SegmentType& segment) {

	computeFeatures(segment, _features->get(segment.getId()));
}

void
GeometryFeatureExtractor::computeFeatures(const EndSegment& end, std::vector<double>& features) {

	features[0] = end.getSlice()->getComponent()->getSize();
	features[1] = Features::NoFeatureValue;
	features[2] = Features::NoFeatureValue;
	features[3] = Features::NoFeatureValue;
	features[4] = Features::NoFeatureValue;
	features[5] = Features::NoFeatureValue;
	features[6] = Features::NoFeatureValue;
	features[7] = Features::NoFeatureValue;
	features[8] = Features::NoFeatureValue;
	features[9] = Features::NoFeatureValue;
	features[10] = Features::NoFeatureValue;

	if (!_noSliceDistance) {

		features[11] = Features::NoFeatureValue;
		features[12] = Features::NoFeatureValue;
		features[13] = Features::NoFeatureValue;
		features[14] = Features::NoFeatureValue;
	}
}

void
GeometryFeatureExtractor::computeFeatures(const ContinuationSegment& continuation, std::vector<double>& features) {

	const util::point<double>& sourceCenter = continuation.getSourceSlice()->getComponent()->getCenter();
	const util::point<double>& targetCenter = continuation.getTargetSlice()->getComponent()->getCenter();

	unsigned int sourceSize = continuation.getSourceSlice()->getComponent()->getSize();
	unsigned int targetSize = continuation.getTargetSlice()->getComponent()->getSize();

	util::point<double> difference = sourceCenter - targetCenter;

	double distance = difference.x*difference.x + difference.y*difference.y;

	double overlap = _overlap(*continuation.getSourceSlice(), *continuation.getTargetSlice());

	double overlapRatio = overlap/(sourceSize + targetSize - overlap);

	double alignedOverlap = _alignedOverlap(*continuation.getSourceSlice(), *continuation.getTargetSlice());

	double alignedOverlapRatio = alignedOverlap/(sourceSize + targetSize - overlap);

	double setDifference = (sourceSize - overlap) + (targetSize - overlap);

	double setDifferenceRatio = setDifference/(sourceSize + targetSize);

	double alignedSetDifference = (sourceSize - alignedOverlap) + (targetSize - alignedOverlap);

	double alignedSetDifferenceRatio = alignedSetDifference/(sourceSize + targetSize);

	features[0] = Features::NoFeatureValue;
	features[1] = distance;
	features[2] = setDifference;
	features[3] = setDifferenceRatio;
	features[4] = alignedSetDifference;
	features[5] = alignedSetDifferenceRatio;
	features[6] =
			(continuation.getSourceSlice()->getComponent()->getSize() +
			 continuation.getTargetSlice()->getComponent()->getSize())*0.5;
	features[7] = overlap;
	features[8] = overlapRatio;
	features[9] = alignedOverlap;
	features[10] = alignedOverlapRatio;

	if (!_noSliceDistance) {

		double averageSliceDistance, maxSliceDistance;

		_distance(*continuation.getSourceSlice(), *continuation.getTargetSlice(), true, false, averageSliceDistance, maxSliceDistance);

		double alignedAverageSliceDistance, alignedMaxSliceDistance;

		_distance(*continuation.getSourceSlice(), *continuation.getTargetSlice(), true, true, alignedAverageSliceDistance, alignedMaxSliceDistance);

		features[11] = averageSliceDistance;
		features[12] = maxSliceDistance;
		features[13] = alignedAverageSliceDistance;
		features[14] = alignedMaxSliceDistance;
	}
}

void
GeometryFeatureExtractor::computeFeatures(const BranchSegment& branch, std::vector<double>& features) {

	const util::point<double>& sourceCenter  = branch.getSourceSlice()->getComponent()->getCenter();
	const util::point<double>& targetCenter1 = branch.getTargetSlice1()->getComponent()->getCenter();
	const util::point<double>& targetCenter2 = branch.getTargetSlice2()->getComponent()->getCenter();

	unsigned int sourceSize  = branch.getSourceSlice()->getComponent()->getSize();
	unsigned int targetSize1 = branch.getTargetSlice1()->getComponent()->getSize();
	unsigned int targetSize2 = branch.getTargetSlice2()->getComponent()->getSize();
	unsigned int targetSize  = targetSize1 + targetSize2;

	util::point<double> difference = sourceCenter - (targetCenter1*targetSize1 + targetCenter2*targetSize2)/((double)(targetSize));

	double distance = difference.x*difference.x + difference.y*difference.y;

	double overlap = _overlap(*branch.getTargetSlice1(), *branch.getTargetSlice2(), *branch.getSourceSlice());

	double overlapRatio = overlap/(sourceSize + targetSize - overlap);

	double alignedOverlap = _alignedOverlap(*branch.getTargetSlice1(), *branch.getTargetSlice2(), *branch.getSourceSlice());

	double alignedOverlapRatio = alignedOverlap/(sourceSize + targetSize - alignedOverlap);

	double setDifference = (sourceSize - overlap) + (targetSize - overlap);

	double setDifferenceRatio = setDifference/(sourceSize + targetSize);

	double alignedSetDifference = (sourceSize - alignedOverlap) + (targetSize - alignedOverlap);

	double alignedSetDifferenceRatio = alignedSetDifference/(sourceSize + targetSize);

	features[0] = Features::NoFeatureValue;
	features[1] = distance;
	features[2] = setDifference;
	features[3] = setDifferenceRatio;
	features[4] = alignedSetDifference;
	features[5] = alignedSetDifferenceRatio;
	features[6] =
			(branch.getSourceSlice()->getComponent()->getSize() +
			 branch.getTargetSlice1()->getComponent()->getSize() +
			 branch.getTargetSlice2()->getComponent()->getSize())/3.0;
	features[7] = overlap;
	features[8] = overlapRatio;
	features[9] = alignedOverlap;
	features[10] = alignedOverlapRatio;

	if (!_noSliceDistance) {

		double averageSliceDistance, maxSliceDistance;

		_distance(*branch.getTargetSlice1(), *branch.getTargetSlice2(), *branch.getSourceSlice(), true, false, averageSliceDistance, maxSliceDistance);

		double alignedAverageSliceDistance, alignedMaxSliceDistance;

		_distance(*branch.getTargetSlice1(), *branch.getTargetSlice2(), *branch.getSourceSlice(), true, true, alignedAverageSliceDistance, alignedMaxSliceDistance);

		features[11] = averageSliceDistance;
		features[12] = maxSliceDistance;
		features[13] = alignedAverageSliceDistance;
		features[14] = alignedMaxSliceDistance;
	}
}
<|endoftext|>


<commit_before>#include <iostream>
#include <utility>
#include <string>
#include <experimental/filesystem>
#include <fstream>
#include <string>

#include "fec_file_parser.h"
#include "running_median_by_date_calculator.h"
#include "running_median_by_zip_calculator.h"

using std::cout;
using std::endl;
using std::tuple;
using std::string;
using std::fstream;
using std::ios;
using std::experimental::filesystem::path;
namespace fs = std::experimental::filesystem;
using ResultsRow = RunningMedianByDateCalculator::ResultsRow;

class FecFileProcessor {
public:
    FecFileProcessor( fstream& itcontStream, fstream& medianvalsByZipStream, fstream& medianvalsByDateStream) :
        parser_(&itcontStream)
      , medianvalsByZipStream_(medianvalsByZipStream)
      , medianvalsByDateStream_(medianvalsByDateStream)

    {

    }
    ~FecFileProcessor() = default;

    void run() {
        ///TODO rewrite this function using std::async or boost::asio

        FecFileRecordsBlock recordsBlock;
        while (!parser_.isEof()) {
            recordsBlock = parser_.getNextRecordsBlock();
            for (auto&& record : recordsBlock) {
                if (!record.ZIP_CODE.empty()) {
                    calcByZip_.put (record.CMTE_ID, record.ZIP_CODE, record.TRANSACTION_AMT);
                    medianvalsByZipStream_ << record.CMTE_ID
                                    << "|" << record.ZIP_CODE
                                    << "|" << calcByZip_.getMedian(record.CMTE_ID, record.ZIP_CODE)
                                    << "|" << calcByZip_.getTotalNumber(record.CMTE_ID, record.ZIP_CODE)
                                    << "|" << calcByZip_.getTotalAmount(record.CMTE_ID, record.ZIP_CODE)
                                    << "\n";
                }
                calcByDate_.put(record.CMTE_ID, record.TRANSACTION_DT, record.TRANSACTION_AMT);

            }
            medianvalsByZipStream_.flush();
        }
        calcByDate_.prepareResults();
        auto&& resultsByDateTable = calcByDate_.getResults();
        for (auto&& row : resultsByDateTable) {
            string recipient;
            recipient = row->key.substr(0, row->key.length() - 8);
            Date date;
            date.YEAR  = std::stoul( row->key.substr(row->key.length() - 8, row->key.length() - 4) );
            date.MONTH = std::stoul( row->key.substr(row->key.length() - 4, row->key.length() - 2) );
            date.DAY   = std::stoul( row->key.substr(row->key.length() - 2) );
            medianvalsByDateStream_ << recipient
                            << "|" << date.MONTH << date.DAY << date.YEAR
                            << "|" << row->medianAmount
                            << "|" << row->totalNumber
                            << "|" << row->totalAmount
                            << "\n";
        }
        medianvalsByDateStream_.flush();

    }

private:
    fstream& medianvalsByZipStream_;
    fstream& medianvalsByDateStream_;
    FecFileParser parser_;
    RunningMedianByDateCalculator calcByDate_;
    RunningMedianByZipCalculator  calcByZip_;
};

void
printUsage(const char* progName) {
    cout << "Usage:\n"
         << progName << " path_to_itcont.txt path_to_medianvals_by_zip.txt path_to_medianvals_by_date.txt" << endl;
}

int
main (int argc, char *argv[]) {

	if (argc != 4 ) {
		printUsage(argv[0]);
		return -1;
	}

    path itcontPath(argv[1]);
    fstream itcontStream(itcontPath);
    if (!itcontStream.is_open()) {
        std::cout << "failed to open " << itcontPath << '\n';
        return 1;
    }

    path medianvalsByZipPath(argv[2]);

    fstream medianvalsByZipStream(medianvalsByZipPath, ios::trunc | ios::out);
    if (!medianvalsByZipStream.is_open()) {
        std::cout << "failed to open " << medianvalsByZipPath << '\n';
        return 1;
    }

    path medianvalsByDatePath(argv[3]);
    fstream medianvalsByDateStream(medianvalsByDatePath, ios::trunc | ios::out);
    if (!medianvalsByDateStream.is_open()) {
        std::cout << "failed to open " << medianvalsByDatePath << '\n';
        return 1;
    }

    FecFileProcessor fecFileProcessor{itcontStream, medianvalsByZipStream, medianvalsByDateStream};
    fecFileProcessor.run();

}
<commit_msg>Fixed error with output date for medianvals_by_date.txt.<commit_after>#include <iostream>
#include <utility>
#include <string>
#include <experimental/filesystem>
#include <fstream>
#include <string>
#include <iomanip>

#include "fec_file_parser.h"
#include "running_median_by_date_calculator.h"
#include "running_median_by_zip_calculator.h"

using std::cout;
using std::endl;
using std::tuple;
using std::string;
using std::fstream;
using std::ios;
using std::setfill;
using std::setw;
using std::experimental::filesystem::path;
namespace fs = std::experimental::filesystem;
using ResultsRow = RunningMedianByDateCalculator::ResultsRow;

class FecFileProcessor {
public:
    FecFileProcessor( fstream& itcontStream, fstream& medianvalsByZipStream, fstream& medianvalsByDateStream) :
        parser_(&itcontStream)
      , medianvalsByZipStream_(medianvalsByZipStream)
      , medianvalsByDateStream_(medianvalsByDateStream)

    {

    }
    ~FecFileProcessor() = default;

    void run() {
        ///TODO rewrite this function using std::async or boost::asio

        FecFileRecordsBlock recordsBlock;
        while (!parser_.isEof()) {
            recordsBlock = parser_.getNextRecordsBlock();
            for (auto&& record : recordsBlock) {
                if (!record.ZIP_CODE.empty()) {
                    calcByZip_.put (record.CMTE_ID, record.ZIP_CODE, record.TRANSACTION_AMT);
                    medianvalsByZipStream_ << record.CMTE_ID
                                    << "|" << record.ZIP_CODE
                                    << "|" << calcByZip_.getMedian(record.CMTE_ID, record.ZIP_CODE)
                                    << "|" << calcByZip_.getTotalNumber(record.CMTE_ID, record.ZIP_CODE)
                                    << "|" << calcByZip_.getTotalAmount(record.CMTE_ID, record.ZIP_CODE)
                                    << "\n";
                }
                calcByDate_.put(record.CMTE_ID, record.TRANSACTION_DT, record.TRANSACTION_AMT);

            }
            medianvalsByZipStream_.flush();
        }
        calcByDate_.prepareResults();
        auto&& resultsByDateTable = calcByDate_.getResults();
        for (auto&& row : resultsByDateTable) {
            string recipient;
            recipient = row->key.substr(0, row->key.length() - 8);
            string dataStr = row->key.substr(row->key.length() - 8);;
            Date date;
            date.YEAR  = std::stoul( dataStr.substr(0, 4) );
            date.MONTH = std::stoul( dataStr.substr(4, 2) );
            date.DAY   = std::stoul( dataStr.substr(6, 2) );
            medianvalsByDateStream_ << recipient
                            << "|" << setfill('0')<< setw(2) << date.MONTH << setfill('0')<< setw(2) << date.DAY << date.YEAR
                            << "|" << row->medianAmount
                            << "|" << row->totalNumber
                            << "|" << row->totalAmount
                            << "\n";
        }
        medianvalsByDateStream_.flush();
    }

private:
    fstream& medianvalsByZipStream_;
    fstream& medianvalsByDateStream_;
    FecFileParser parser_;
    RunningMedianByDateCalculator calcByDate_;
    RunningMedianByZipCalculator  calcByZip_;
};

void
printUsage(const char* progName) {
    cout << "Usage:\n"
         << progName << " path_to_itcont.txt path_to_medianvals_by_zip.txt path_to_medianvals_by_date.txt" << endl;
}

int
main (int argc, char *argv[]) {

	if (argc != 4 ) {
		printUsage(argv[0]);
		return -1;
	}

    path itcontPath(argv[1]);
    fstream itcontStream(itcontPath);
    if (!itcontStream.is_open()) {
        std::cout << "failed to open " << itcontPath << '\n';
        return 1;
    }

    path medianvalsByZipPath(argv[2]);

    fstream medianvalsByZipStream(medianvalsByZipPath, ios::trunc | ios::out);
    if (!medianvalsByZipStream.is_open()) {
        std::cout << "failed to open " << medianvalsByZipPath << '\n';
        return 1;
    }

    path medianvalsByDatePath(argv[3]);
    fstream medianvalsByDateStream(medianvalsByDatePath, ios::trunc | ios::out);
    if (!medianvalsByDateStream.is_open()) {
        std::cout << "failed to open " << medianvalsByDatePath << '\n';
        return 1;
    }

    FecFileProcessor fecFileProcessor{itcontStream, medianvalsByZipStream, medianvalsByDateStream};
    fecFileProcessor.run();

}
<|endoftext|>


<commit_before>#include "selectors.hh"

#include "string.hh"

#include <algorithm>

namespace Kakoune
{

namespace
{

bool is_eol(char c)
{
    return c == '\n';
}

bool is_blank(char c)
{
    return c == ' ' or c == '\t';
}

template<bool punctuation_is_word = false>
bool is_word(char c);

template<>
bool is_word<false>(char c)
{
    if (c >= '0' and c <= '9')
        return true;
    if (c >= 'a' and c <= 'z')
        return true;
    if (c >= 'A' and c <= 'Z')
        return true;
    if (c == '_')
        return true;
    return false;
}

template<>
bool is_word<true>(char c)
{
    return !is_blank(c) and !is_eol(c);
}

static bool is_punctuation(char c)
{
    return not (is_word(c) or is_blank(c) or is_eol(c));
}

enum class CharCategories
{
    Blank,
    EndOfLine,
    Word,
    Punctuation,
};

template<bool punctuation_is_word = false>
CharCategories categorize(char c)
{
    if (is_word(c))
        return CharCategories::Word;
    if (is_eol(c))
        return CharCategories::EndOfLine;
    if (is_blank(c))
        return CharCategories::Blank;
    return punctuation_is_word ? CharCategories::Word
                               : CharCategories::Punctuation;
}

template<typename T>
bool skip_while(BufferIterator& it, T condition)
{
    while (not it.is_end() and condition(*it))
        ++it;
    return not it.is_end() and condition(*it);
}

template<typename T>
bool skip_while_reverse(BufferIterator& it, T condition)
{
    while (not it.is_begin() and condition(*it))
        --it;
    return not it.is_end() and condition(*it);
}

}

typedef boost::regex_iterator<BufferIterator> RegexIterator;

template<bool punctuation_is_word>
SelectionAndCaptures select_to_next_word(const Selection& selection)
{
    BufferIterator begin = selection.last();
    if (categorize<punctuation_is_word>(*begin) !=
        categorize<punctuation_is_word>(*(begin+1)))
        ++begin;

    skip_while(begin, is_eol);
    BufferIterator end = begin+1;

    if (not punctuation_is_word and is_punctuation(*begin))
        skip_while(end, is_punctuation);
    else if (is_word<punctuation_is_word>(*begin))
        skip_while(end, is_word<punctuation_is_word>);

    bool with_end = skip_while(end, is_blank);

    return Selection(begin, with_end ? end : end-1);
}
template SelectionAndCaptures select_to_next_word<false>(const Selection&);
template SelectionAndCaptures select_to_next_word<true>(const Selection&);

template<bool punctuation_is_word>
SelectionAndCaptures select_to_next_word_end(const Selection& selection)
{
    BufferIterator begin = selection.last();
    if (categorize<punctuation_is_word>(*begin) !=
        categorize<punctuation_is_word>(*(begin+1)))
        ++begin;

    skip_while(begin, is_eol);
    BufferIterator end = begin;
    skip_while(end, is_blank);

    bool with_end = false;
    if (not punctuation_is_word and is_punctuation(*end))
        with_end = skip_while(end, is_punctuation);
    else if (is_word<punctuation_is_word>(*end))
        with_end = skip_while(end, is_word<punctuation_is_word>);

    return Selection(begin, with_end ? end : end-1);
}
template SelectionAndCaptures select_to_next_word_end<false>(const Selection&);
template SelectionAndCaptures select_to_next_word_end<true>(const Selection&);

template<bool punctuation_is_word>
SelectionAndCaptures select_to_previous_word(const Selection& selection)
{
    BufferIterator begin = selection.last();

    if (categorize<punctuation_is_word>(*begin) !=
        categorize<punctuation_is_word>(*(begin-1)))
        --begin;

    skip_while_reverse(begin, is_eol);
    BufferIterator end = begin;
    skip_while_reverse(end, is_blank);

    bool with_end = false;
    if (not punctuation_is_word and is_punctuation(*end))
        with_end = skip_while_reverse(end, is_punctuation);
    else if (is_word<punctuation_is_word>(*end))
        with_end = skip_while_reverse(end, is_word<punctuation_is_word>);

    return Selection(begin, with_end ? end : end+1);
}
template SelectionAndCaptures select_to_previous_word<false>(const Selection&);
template SelectionAndCaptures select_to_previous_word<true>(const Selection&);

SelectionAndCaptures select_line(const Selection& selection)
{
    BufferIterator first = selection.last();
    if (*first == '\n' and not (first + 1).is_end())
        ++first;

    while (not first.is_begin() and *(first - 1) != '\n')
        --first;

    BufferIterator last = first;
    while (not (last + 1).is_end() and *last != '\n')
        ++last;
    return Selection(first, last);
}

SelectionAndCaptures select_matching(const Selection& selection)
{
    std::vector<char> matching_pairs = { '(', ')', '{', '}', '[', ']', '<', '>' };
    BufferIterator it = selection.last();
    std::vector<char>::iterator match = matching_pairs.end();
    while (not is_eol(*it))
    {
        match = std::find(matching_pairs.begin(), matching_pairs.end(), *it);
        if (match != matching_pairs.end())
            break;
        ++it;
    }
    if (match == matching_pairs.end())
        return selection;

    BufferIterator begin = it;

    if (((match - matching_pairs.begin()) % 2) == 0)
    {
        int level = 0;
        const char opening = *match;
        const char closing = *(match+1);
        while (not it.is_end())
        {
            if (*it == opening)
                ++level;
            else if (*it == closing and --level == 0)
                return Selection(begin, it);

            ++it;
        }
    }
    else
    {
        int level = 0;
        const char opening = *(match-1);
        const char closing = *match;
        while (not it.is_begin())
        {
            if (*it == closing)
                ++level;
            else if (*it == opening and --level == 0)
                return Selection(begin, it);
            --it;
        }
    }
    return selection;
}

SelectionAndCaptures select_surrounding(const Selection& selection,
                             const std::pair<char, char>& matching,
                             bool inside)
{
    int level = 0;
    BufferIterator first = selection.last();
    while (not first.is_begin())
    {
        if (first != selection.last() and *first == matching.second)
            ++level;
        else if (*first == matching.first)
        {
            if (level == 0)
                break;
            else
                --level;
        }
        --first;
    }
    if (level != 0 or *first != matching.first)
        return selection;

    level = 0;
    BufferIterator last = first + 1;
    while (not last.is_end())
    {
        if (*last == matching.first)
            ++level;
        else if (*last == matching.second)
        {
            if (level == 0)
                break;
            else
                --level;
        }
        ++last;
    }
    if (level != 0 or *last != matching.second)
        return selection;

    if (inside)
    {
        ++first;
        if (first != last)
            --last;
    }
    return Selection(first, last);
}

SelectionAndCaptures select_to(const Selection& selection,
                               char c, int count, bool inclusive)
{
    BufferIterator begin = selection.last();
    BufferIterator end = begin;
    do
    {
        ++end;
        skip_while(end, [c](char cur) { return not is_eol(cur) and cur != c; });
        if (end.is_end() or is_eol(*end))
            return selection;
    }
    while (--count > 0);

    return Selection(begin, inclusive ? end : end-1);
}

SelectionAndCaptures select_to_reverse(const Selection& selection,
                                       char c, int count, bool inclusive)
{
    BufferIterator begin = selection.last();
    BufferIterator end = begin;
    do
    {
        --end;
        skip_while_reverse(end, [c](char cur) { return not is_eol(cur) and cur != c; });
        if (end.is_begin() or is_eol(*end))
            return selection;
    }
    while (--count > 0);

    return Selection(begin, inclusive ? end : end+1);
}

SelectionAndCaptures select_to_eol(const Selection& selection)
{
    BufferIterator begin = selection.last();
    BufferIterator end = begin + 1;
    skip_while(end, [](char cur) { return not is_eol(cur); });
    return Selection(begin, end-1);
}

SelectionAndCaptures select_to_eol_reverse(const Selection& selection)
{
    BufferIterator begin = selection.last();
    BufferIterator end = begin - 1;
    skip_while_reverse(end, [](char cur) { return not is_eol(cur); });
    return Selection(begin, end.is_begin() ? end : end+1);
}

template<bool punctuation_is_word>
SelectionAndCaptures select_whole_word(const Selection& selection, bool inner)
{
    BufferIterator first = selection.last();
    BufferIterator last = first;
    if (is_word(*first))
    {
        if (not skip_while_reverse(first, is_word<punctuation_is_word>))
            ++first;
        skip_while(last, is_word<punctuation_is_word>);
        if (not inner)
            skip_while(last, is_blank);
    }
    else if (not inner)
    {
        if (not skip_while_reverse(first, is_blank))
            ++first;
        skip_while(last, is_blank);
        if (not is_word<punctuation_is_word>(*last))
            return selection;
        skip_while(last, is_word<punctuation_is_word>);
    }
    --last;
    return Selection(first, last);
}
template SelectionAndCaptures select_whole_word<false>(const Selection&, bool);
template SelectionAndCaptures select_whole_word<true>(const Selection&, bool);

SelectionAndCaptures select_whole_lines(const Selection& selection)
{
     BufferIterator first = selection.first();
     BufferIterator last =  selection.last();
     BufferIterator& to_line_start = first <= last ? first : last;
     BufferIterator& to_line_end = first <= last ? last : first;

     --to_line_start;
     skip_while_reverse(to_line_start, [](char cur) { return not is_eol(cur); });
     ++to_line_start;

     skip_while(to_line_end, [](char cur) { return not is_eol(cur); });

     return Selection(first, last);
}

SelectionAndCaptures select_whole_buffer(const Selection& selection)
{
    const Buffer& buffer = selection.first().buffer();
    return Selection(buffer.begin(), buffer.end()-1);
}

SelectionAndCaptures select_next_match(const Selection& selection,
                                       const String& regex)
{
    try
    {
        BufferIterator begin = selection.last();
        BufferIterator end = begin;
        CaptureList captures;

        Regex ex(regex.begin(), regex.end());
        boost::match_results<BufferIterator> matches;

        if (boost::regex_search(begin+1, begin.buffer().end(),
                                matches, ex))
        {
            begin = matches[0].first;
            end   = matches[0].second;
            for (auto& match : matches)
                captures.push_back(String(match.first, match.second));
        }
        else if (boost::regex_search(begin.buffer().begin(), begin+1,
                                     matches, ex))
        {
            begin = matches[0].first;
            end   = matches[0].second;
            for (auto& match : matches)
                captures.push_back(String(match.first, match.second));
        }
        else
            throw runtime_error("'" + regex + "': no matches found");

        if (begin == end)
            ++end;

        return SelectionAndCaptures(begin, end - 1, std::move(captures));
    }
    catch (boost::regex_error& err)
    {
        throw runtime_error(String("regex error: ") + err.what());
    }
}

SelectionAndCapturesList select_all_matches(const Selection& selection,
                                            const String& regex)
{
    try
    {
        Regex ex(regex.begin(), regex.end());
        RegexIterator re_it(selection.begin(), selection.end(), ex);
        RegexIterator re_end;

        SelectionAndCapturesList result;
        for (; re_it != re_end; ++re_it)
        {
            BufferIterator begin = (*re_it)[0].first;
            BufferIterator end   = (*re_it)[0].second;

            CaptureList captures;
            for (auto& match : *re_it)
                captures.push_back(String(match.first, match.second));

            result.push_back(SelectionAndCaptures(begin,
                                                  begin == end ? end : end-1,
                                                  std::move(captures)));
        }
        return result;
    }
    catch (boost::regex_error& err)
    {
        throw runtime_error(String("regex error: ") + err.what());
    }
}

SelectionAndCapturesList split_selection(const Selection& selection,
                                         const String& separator_regex)
{
    try
    {
        Regex ex(separator_regex.begin(), separator_regex.end());
        RegexIterator re_it(selection.begin(), selection.end(), ex,
                            boost::regex_constants::match_nosubs);
        RegexIterator re_end;

        SelectionAndCapturesList result;
        BufferIterator begin = selection.begin();
        for (; re_it != re_end; ++re_it)
        {
            BufferIterator end = (*re_it)[0].first;

            result.push_back(Selection(begin, (begin == end) ? end : end-1));
            begin = (*re_it)[0].second;
        }
        result.push_back(Selection(begin, selection.last()));
        return result;
    }
    catch (boost::regex_error& err)
    {
        throw runtime_error(String("regex error: ") + err.what());
    }
}

}
<commit_msg>select_all_matches: reject match that start at the end of originating selection<commit_after>#include "selectors.hh"

#include "string.hh"

#include <algorithm>

namespace Kakoune
{

namespace
{

bool is_eol(char c)
{
    return c == '\n';
}

bool is_blank(char c)
{
    return c == ' ' or c == '\t';
}

template<bool punctuation_is_word = false>
bool is_word(char c);

template<>
bool is_word<false>(char c)
{
    if (c >= '0' and c <= '9')
        return true;
    if (c >= 'a' and c <= 'z')
        return true;
    if (c >= 'A' and c <= 'Z')
        return true;
    if (c == '_')
        return true;
    return false;
}

template<>
bool is_word<true>(char c)
{
    return !is_blank(c) and !is_eol(c);
}

static bool is_punctuation(char c)
{
    return not (is_word(c) or is_blank(c) or is_eol(c));
}

enum class CharCategories
{
    Blank,
    EndOfLine,
    Word,
    Punctuation,
};

template<bool punctuation_is_word = false>
CharCategories categorize(char c)
{
    if (is_word(c))
        return CharCategories::Word;
    if (is_eol(c))
        return CharCategories::EndOfLine;
    if (is_blank(c))
        return CharCategories::Blank;
    return punctuation_is_word ? CharCategories::Word
                               : CharCategories::Punctuation;
}

template<typename T>
bool skip_while(BufferIterator& it, T condition)
{
    while (not it.is_end() and condition(*it))
        ++it;
    return not it.is_end() and condition(*it);
}

template<typename T>
bool skip_while_reverse(BufferIterator& it, T condition)
{
    while (not it.is_begin() and condition(*it))
        --it;
    return not it.is_end() and condition(*it);
}

}

typedef boost::regex_iterator<BufferIterator> RegexIterator;

template<bool punctuation_is_word>
SelectionAndCaptures select_to_next_word(const Selection& selection)
{
    BufferIterator begin = selection.last();
    if (categorize<punctuation_is_word>(*begin) !=
        categorize<punctuation_is_word>(*(begin+1)))
        ++begin;

    skip_while(begin, is_eol);
    BufferIterator end = begin+1;

    if (not punctuation_is_word and is_punctuation(*begin))
        skip_while(end, is_punctuation);
    else if (is_word<punctuation_is_word>(*begin))
        skip_while(end, is_word<punctuation_is_word>);

    bool with_end = skip_while(end, is_blank);

    return Selection(begin, with_end ? end : end-1);
}
template SelectionAndCaptures select_to_next_word<false>(const Selection&);
template SelectionAndCaptures select_to_next_word<true>(const Selection&);

template<bool punctuation_is_word>
SelectionAndCaptures select_to_next_word_end(const Selection& selection)
{
    BufferIterator begin = selection.last();
    if (categorize<punctuation_is_word>(*begin) !=
        categorize<punctuation_is_word>(*(begin+1)))
        ++begin;

    skip_while(begin, is_eol);
    BufferIterator end = begin;
    skip_while(end, is_blank);

    bool with_end = false;
    if (not punctuation_is_word and is_punctuation(*end))
        with_end = skip_while(end, is_punctuation);
    else if (is_word<punctuation_is_word>(*end))
        with_end = skip_while(end, is_word<punctuation_is_word>);

    return Selection(begin, with_end ? end : end-1);
}
template SelectionAndCaptures select_to_next_word_end<false>(const Selection&);
template SelectionAndCaptures select_to_next_word_end<true>(const Selection&);

template<bool punctuation_is_word>
SelectionAndCaptures select_to_previous_word(const Selection& selection)
{
    BufferIterator begin = selection.last();

    if (categorize<punctuation_is_word>(*begin) !=
        categorize<punctuation_is_word>(*(begin-1)))
        --begin;

    skip_while_reverse(begin, is_eol);
    BufferIterator end = begin;
    skip_while_reverse(end, is_blank);

    bool with_end = false;
    if (not punctuation_is_word and is_punctuation(*end))
        with_end = skip_while_reverse(end, is_punctuation);
    else if (is_word<punctuation_is_word>(*end))
        with_end = skip_while_reverse(end, is_word<punctuation_is_word>);

    return Selection(begin, with_end ? end : end+1);
}
template SelectionAndCaptures select_to_previous_word<false>(const Selection&);
template SelectionAndCaptures select_to_previous_word<true>(const Selection&);

SelectionAndCaptures select_line(const Selection& selection)
{
    BufferIterator first = selection.last();
    if (*first == '\n' and not (first + 1).is_end())
        ++first;

    while (not first.is_begin() and *(first - 1) != '\n')
        --first;

    BufferIterator last = first;
    while (not (last + 1).is_end() and *last != '\n')
        ++last;
    return Selection(first, last);
}

SelectionAndCaptures select_matching(const Selection& selection)
{
    std::vector<char> matching_pairs = { '(', ')', '{', '}', '[', ']', '<', '>' };
    BufferIterator it = selection.last();
    std::vector<char>::iterator match = matching_pairs.end();
    while (not is_eol(*it))
    {
        match = std::find(matching_pairs.begin(), matching_pairs.end(), *it);
        if (match != matching_pairs.end())
            break;
        ++it;
    }
    if (match == matching_pairs.end())
        return selection;

    BufferIterator begin = it;

    if (((match - matching_pairs.begin()) % 2) == 0)
    {
        int level = 0;
        const char opening = *match;
        const char closing = *(match+1);
        while (not it.is_end())
        {
            if (*it == opening)
                ++level;
            else if (*it == closing and --level == 0)
                return Selection(begin, it);

            ++it;
        }
    }
    else
    {
        int level = 0;
        const char opening = *(match-1);
        const char closing = *match;
        while (not it.is_begin())
        {
            if (*it == closing)
                ++level;
            else if (*it == opening and --level == 0)
                return Selection(begin, it);
            --it;
        }
    }
    return selection;
}

SelectionAndCaptures select_surrounding(const Selection& selection,
                             const std::pair<char, char>& matching,
                             bool inside)
{
    int level = 0;
    BufferIterator first = selection.last();
    while (not first.is_begin())
    {
        if (first != selection.last() and *first == matching.second)
            ++level;
        else if (*first == matching.first)
        {
            if (level == 0)
                break;
            else
                --level;
        }
        --first;
    }
    if (level != 0 or *first != matching.first)
        return selection;

    level = 0;
    BufferIterator last = first + 1;
    while (not last.is_end())
    {
        if (*last == matching.first)
            ++level;
        else if (*last == matching.second)
        {
            if (level == 0)
                break;
            else
                --level;
        }
        ++last;
    }
    if (level != 0 or *last != matching.second)
        return selection;

    if (inside)
    {
        ++first;
        if (first != last)
            --last;
    }
    return Selection(first, last);
}

SelectionAndCaptures select_to(const Selection& selection,
                               char c, int count, bool inclusive)
{
    BufferIterator begin = selection.last();
    BufferIterator end = begin;
    do
    {
        ++end;
        skip_while(end, [c](char cur) { return not is_eol(cur) and cur != c; });
        if (end.is_end() or is_eol(*end))
            return selection;
    }
    while (--count > 0);

    return Selection(begin, inclusive ? end : end-1);
}

SelectionAndCaptures select_to_reverse(const Selection& selection,
                                       char c, int count, bool inclusive)
{
    BufferIterator begin = selection.last();
    BufferIterator end = begin;
    do
    {
        --end;
        skip_while_reverse(end, [c](char cur) { return not is_eol(cur) and cur != c; });
        if (end.is_begin() or is_eol(*end))
            return selection;
    }
    while (--count > 0);

    return Selection(begin, inclusive ? end : end+1);
}

SelectionAndCaptures select_to_eol(const Selection& selection)
{
    BufferIterator begin = selection.last();
    BufferIterator end = begin + 1;
    skip_while(end, [](char cur) { return not is_eol(cur); });
    return Selection(begin, end-1);
}

SelectionAndCaptures select_to_eol_reverse(const Selection& selection)
{
    BufferIterator begin = selection.last();
    BufferIterator end = begin - 1;
    skip_while_reverse(end, [](char cur) { return not is_eol(cur); });
    return Selection(begin, end.is_begin() ? end : end+1);
}

template<bool punctuation_is_word>
SelectionAndCaptures select_whole_word(const Selection& selection, bool inner)
{
    BufferIterator first = selection.last();
    BufferIterator last = first;
    if (is_word(*first))
    {
        if (not skip_while_reverse(first, is_word<punctuation_is_word>))
            ++first;
        skip_while(last, is_word<punctuation_is_word>);
        if (not inner)
            skip_while(last, is_blank);
    }
    else if (not inner)
    {
        if (not skip_while_reverse(first, is_blank))
            ++first;
        skip_while(last, is_blank);
        if (not is_word<punctuation_is_word>(*last))
            return selection;
        skip_while(last, is_word<punctuation_is_word>);
    }
    --last;
    return Selection(first, last);
}
template SelectionAndCaptures select_whole_word<false>(const Selection&, bool);
template SelectionAndCaptures select_whole_word<true>(const Selection&, bool);

SelectionAndCaptures select_whole_lines(const Selection& selection)
{
     BufferIterator first = selection.first();
     BufferIterator last =  selection.last();
     BufferIterator& to_line_start = first <= last ? first : last;
     BufferIterator& to_line_end = first <= last ? last : first;

     --to_line_start;
     skip_while_reverse(to_line_start, [](char cur) { return not is_eol(cur); });
     ++to_line_start;

     skip_while(to_line_end, [](char cur) { return not is_eol(cur); });

     return Selection(first, last);
}

SelectionAndCaptures select_whole_buffer(const Selection& selection)
{
    const Buffer& buffer = selection.first().buffer();
    return Selection(buffer.begin(), buffer.end()-1);
}

SelectionAndCaptures select_next_match(const Selection& selection,
                                       const String& regex)
{
    try
    {
        BufferIterator begin = selection.last();
        BufferIterator end = begin;
        CaptureList captures;

        Regex ex(regex.begin(), regex.end());
        boost::match_results<BufferIterator> matches;

        if (boost::regex_search(begin+1, begin.buffer().end(),
                                matches, ex))
        {
            begin = matches[0].first;
            end   = matches[0].second;
            for (auto& match : matches)
                captures.push_back(String(match.first, match.second));
        }
        else if (boost::regex_search(begin.buffer().begin(), begin+1,
                                     matches, ex))
        {
            begin = matches[0].first;
            end   = matches[0].second;
            for (auto& match : matches)
                captures.push_back(String(match.first, match.second));
        }
        else
            throw runtime_error("'" + regex + "': no matches found");

        if (begin == end)
            ++end;

        return SelectionAndCaptures(begin, end - 1, std::move(captures));
    }
    catch (boost::regex_error& err)
    {
        throw runtime_error(String("regex error: ") + err.what());
    }
}

SelectionAndCapturesList select_all_matches(const Selection& selection,
                                            const String& regex)
{
    try
    {
        Regex ex(regex.begin(), regex.end());
        RegexIterator re_it(selection.begin(), selection.end(), ex);
        RegexIterator re_end;

        SelectionAndCapturesList result;
        for (; re_it != re_end; ++re_it)
        {
            BufferIterator begin = (*re_it)[0].first;
            BufferIterator end   = (*re_it)[0].second;

            if (begin == selection.end())
                continue;

            CaptureList captures;
            for (auto& match : *re_it)
                captures.push_back(String(match.first, match.second));

            result.push_back(SelectionAndCaptures(begin,
                                                  begin == end ? end : end-1,
                                                  std::move(captures)));
        }
        return result;
    }
    catch (boost::regex_error& err)
    {
        throw runtime_error(String("regex error: ") + err.what());
    }
}

SelectionAndCapturesList split_selection(const Selection& selection,
                                         const String& separator_regex)
{
    try
    {
        Regex ex(separator_regex.begin(), separator_regex.end());
        RegexIterator re_it(selection.begin(), selection.end(), ex,
                            boost::regex_constants::match_nosubs);
        RegexIterator re_end;

        SelectionAndCapturesList result;
        BufferIterator begin = selection.begin();
        for (; re_it != re_end; ++re_it)
        {
            BufferIterator end = (*re_it)[0].first;

            result.push_back(Selection(begin, (begin == end) ? end : end-1));
            begin = (*re_it)[0].second;
        }
        result.push_back(Selection(begin, selection.last()));
        return result;
    }
    catch (boost::regex_error& err)
    {
        throw runtime_error(String("regex error: ") + err.what());
    }
}

}
<|endoftext|>