<commit_before>#include "btree/backfill.hpp"

#include "errors.hpp"
#include <algorithm>
#include <vector>
#include <boost/make_shared.hpp>

#include "buffer_cache/buf_lock.hpp"
#include "buffer_cache/co_functions.hpp"
#include "buffer_cache/transactor.hpp"
#include "btree/btree_data_provider.hpp"
#include "btree/node.hpp"
#include "btree/internal_node.hpp"
#include "btree/leaf_node.hpp"
#include "btree/parallel_traversal.hpp"
#include "btree/slice.hpp"

// Backfilling

// We want a backfill operation to follow a few simple rules.
//
// 1. Get as far away from the root as possible.
//
// 2. Avoid using more than K + O(1) blocks, for some user-selected
// constant K.
//
// 3. Prefetch efficiently.
//
// This code hopefully will be nice to genericize; you could
// reimplement rget if you genericized this.

// The Lifecyle of a block_id_t
//
// Every time we deal with a block_id_t, it goes through these states...
//
// 1. Knowledge of the block_id_t.  This is where we know about the
// block_id_t, and haven't done anything about it yet.
//
// 2. Acquiring its subtree_recency value from the serializer.  The
// block_id_t is grouped with a bunch of others in an array, and we've
// sent a request to the serializer to respond with all these
// subtree_recency values (and the original array).
//
// 3. Acquired the subtree_recency value.  The block_id_t's
// subtree_recency is known, but we still have not attempted to
// acquire the block.  (If the recency is insufficiently recent, we
// stop here.)
//
// 4. Block acquisition pending.  We have sent a request to acquire
// the block.  It has not yet successfully completed.
//
// 5I. Block acquisition complete, it's an internal node, partly
// processed children.  We hold the lock on the block, and the
// children blocks are currently being processed and have not reached
// stage 4.
//
// 6I. Live children all reached stage 4.  We can now release ownership
// of the block.  We stop here.
//
// 5L. Block acquisition complete, it's a leaf node, we may have to
// handle large values.
//
// 6L. Large values all pending or better, so we can release ownership
// of the block.  We stop here.

struct backfill_traversal_helper_t : public btree_traversal_helper_t {

    // The deletes have to go first (since they get overridden by
    // newer sets)
    void preprocess_btree_superblock(boost::shared_ptr<transactor_t>& txor, const btree_superblock_t *superblock) {
        dump_keys_from_delete_queue(txor, superblock->delete_queue_block, since_when_, callback_);
    }

    void process_a_leaf(boost::shared_ptr<transactor_t>& txor, buf_t *leaf_node_buf) {
        const leaf_node_t *data = reinterpret_cast<const leaf_node_t *>(leaf_node_buf->get_data_read());

        // Remember, we only want to process recent keys.

        int npairs = data->npairs;

        for (int i = 0; i < npairs; ++i) {
            uint16_t offset = data->pair_offsets[i];
            repli_timestamp recency = leaf::get_timestamp_value(data, offset);
            const btree_leaf_pair *pair = leaf::get_pair(data, offset);

            if (recency.time >= since_when_.time) {
                const btree_value *value = pair->value();
                unique_ptr_t<value_data_provider_t> data_provider(value_data_provider_t::create(value, txor));
                backfill_atom_t atom;
                atom.key.assign(pair->key.size, pair->key.contents);
                atom.value = data_provider;
                atom.flags = value->mcflags();
                atom.exptime = value->exptime();
                atom.recency = recency;
                atom.cas_or_zero = value->has_cas() ? value->cas() : 0;
                callback_->on_keyvalue(atom);
            }
        }
    }

    void postprocess_internal_node(UNUSED buf_t *internal_node_buf) {
        // do nothing
    }
    void postprocess_btree_superblock(UNUSED buf_t *superblock_buf) {
        // do nothing
    }

    access_t transaction_mode() { return rwi_read; }
    access_t btree_superblock_mode() { return rwi_read; }
    access_t btree_node_mode() { return rwi_read; }

    struct annoying_t : public get_subtree_recencies_callback_t {
        interesting_children_callback_t *cb;
        boost::scoped_array<block_id_t> block_ids;
        int num_block_ids;
        boost::scoped_array<repli_timestamp> recencies;
        repli_timestamp since_when;

        void got_subtree_recencies() {
            boost::scoped_array<block_id_t> local_block_ids;
            local_block_ids.swap(block_ids);
            int j = 0;
            for (int i = 0; i < num_block_ids; ++i) {
                if (recencies[i].time >= since_when.time) {
                    local_block_ids[j] = local_block_ids[i];
                    ++j;
                }
            }
            int num_surviving_block_ids = j;

            delete this;
            coro_t::spawn(boost::bind(&interesting_children_callback_t::receive_interesting_children, cb, boost::ref(local_block_ids), num_surviving_block_ids));
        }
    };

    void filter_interesting_children(boost::shared_ptr<transactor_t>& txor, const block_id_t *block_ids, int num_block_ids, interesting_children_callback_t *cb) {
        annoying_t *fsm = new annoying_t;
        fsm->cb = cb;
        fsm->block_ids.reset(new block_id_t[num_block_ids]);
        std::copy(block_ids, block_ids + num_block_ids, fsm->block_ids.get());
        fsm->num_block_ids = num_block_ids;
        fsm->since_when = since_when_;
        fsm->recencies.reset(new repli_timestamp[num_block_ids]);

        txor->get()->get_subtree_recencies(fsm->block_ids.get(), num_block_ids, fsm->recencies.get(), fsm);
    }

    backfill_callback_t *callback_;
    repli_timestamp since_when_;

    backfill_traversal_helper_t(backfill_callback_t *callback, repli_timestamp since_when)
        : callback_(callback), since_when_(since_when) { }
};

void btree_backfill(btree_slice_t *slice, repli_timestamp since_when, backfill_callback_t *callback) {
    rassert(coro_t::self());

    backfill_traversal_helper_t helper(callback, since_when);

    btree_parallel_traversal(slice, repli_timestamp::invalid, &helper);

    callback->done();
}
<commit_msg>Removed a few header includes from backfill.cc.<commit_after>#include "btree/backfill.hpp"

#include <algorithm>

#include "errors.hpp"
#include "buffer_cache/co_functions.hpp"
#include "buffer_cache/transactor.hpp"
#include "btree/btree_data_provider.hpp"
#include "btree/node.hpp"
#include "btree/internal_node.hpp"
#include "btree/leaf_node.hpp"
#include "btree/parallel_traversal.hpp"

class btree_slice_t;

struct backfill_traversal_helper_t : public btree_traversal_helper_t {

    // The deletes have to go first (since they get overridden by
    // newer sets)
    void preprocess_btree_superblock(boost::shared_ptr<transactor_t>& txor, const btree_superblock_t *superblock) {
        dump_keys_from_delete_queue(txor, superblock->delete_queue_block, since_when_, callback_);
    }

    void process_a_leaf(boost::shared_ptr<transactor_t>& txor, buf_t *leaf_node_buf) {
        const leaf_node_t *data = reinterpret_cast<const leaf_node_t *>(leaf_node_buf->get_data_read());

        // Remember, we only want to process recent keys.

        int npairs = data->npairs;

        for (int i = 0; i < npairs; ++i) {
            uint16_t offset = data->pair_offsets[i];
            repli_timestamp recency = leaf::get_timestamp_value(data, offset);
            const btree_leaf_pair *pair = leaf::get_pair(data, offset);

            if (recency.time >= since_when_.time) {
                const btree_value *value = pair->value();
                unique_ptr_t<value_data_provider_t> data_provider(value_data_provider_t::create(value, txor));
                backfill_atom_t atom;
                atom.key.assign(pair->key.size, pair->key.contents);
                atom.value = data_provider;
                atom.flags = value->mcflags();
                atom.exptime = value->exptime();
                atom.recency = recency;
                atom.cas_or_zero = value->has_cas() ? value->cas() : 0;
                callback_->on_keyvalue(atom);
            }
        }
    }

    void postprocess_internal_node(UNUSED buf_t *internal_node_buf) {
        // do nothing
    }
    void postprocess_btree_superblock(UNUSED buf_t *superblock_buf) {
        // do nothing
    }

    access_t transaction_mode() { return rwi_read; }
    access_t btree_superblock_mode() { return rwi_read; }
    access_t btree_node_mode() { return rwi_read; }

    struct annoying_t : public get_subtree_recencies_callback_t {
        interesting_children_callback_t *cb;
        boost::scoped_array<block_id_t> block_ids;
        int num_block_ids;
        boost::scoped_array<repli_timestamp> recencies;
        repli_timestamp since_when;

        void got_subtree_recencies() {
            boost::scoped_array<block_id_t> local_block_ids;
            local_block_ids.swap(block_ids);
            int j = 0;
            for (int i = 0; i < num_block_ids; ++i) {
                if (recencies[i].time >= since_when.time) {
                    local_block_ids[j] = local_block_ids[i];
                    ++j;
                }
            }
            int num_surviving_block_ids = j;

            delete this;
            coro_t::spawn(boost::bind(&interesting_children_callback_t::receive_interesting_children, cb, boost::ref(local_block_ids), num_surviving_block_ids));
        }
    };

    void filter_interesting_children(boost::shared_ptr<transactor_t>& txor, const block_id_t *block_ids, int num_block_ids, interesting_children_callback_t *cb) {
        annoying_t *fsm = new annoying_t;
        fsm->cb = cb;
        fsm->block_ids.reset(new block_id_t[num_block_ids]);
        std::copy(block_ids, block_ids + num_block_ids, fsm->block_ids.get());
        fsm->num_block_ids = num_block_ids;
        fsm->since_when = since_when_;
        fsm->recencies.reset(new repli_timestamp[num_block_ids]);

        txor->get()->get_subtree_recencies(fsm->block_ids.get(), num_block_ids, fsm->recencies.get(), fsm);
    }

    backfill_callback_t *callback_;
    repli_timestamp since_when_;

    backfill_traversal_helper_t(backfill_callback_t *callback, repli_timestamp since_when)
        : callback_(callback), since_when_(since_when) { }
};

void btree_backfill(btree_slice_t *slice, repli_timestamp since_when, backfill_callback_t *callback) {
    rassert(coro_t::self());

    backfill_traversal_helper_t helper(callback, since_when);

    btree_parallel_traversal(slice, repli_timestamp::invalid, &helper);

    callback->done();
}
<|endoftext|>


<commit_before>/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Nathan Osman
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 **/

#include <QDir>
#include <QStack>

#include "bundle.h"
#include "bundle_p.h"
#include "bundleitem.h"

Bundle::Bundle(QObject *parent)
    : QObject(parent),
      d(new BundlePrivate)
{
}

Bundle::~Bundle()
{
    delete d;
}

int Bundle::count() const
{
    return d->items.count();
}

qint64 Bundle::totalSize() const
{
    return d->totalSize;
}

void Bundle::addFile(const QString &filename)
{
    QFileInfo info(filename);

    d->items.append(BundleItem(info));
    d->totalSize += info.size();
}

void Bundle::addDirectory(const QString &path)
{
    QDir root(path);
    QStack<QString> stack;

    // Push the root path on the stack and then go up one level so that
    // the relative filenames will include the name of the directory
    stack.push(root.absolutePath());
    root.cdUp();

    while(stack.count()) {
        QString tos = stack.pop();

        foreach(QFileInfo info, QDir(tos).entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)) {

            // Add the item to the bundle
            d->items.append(BundleItem(root, info));

            // If the item is a directory, add it to the stack
            // Otherwise, add its size to the total
            if(info.isDir()) {
                stack.push(info.absoluteFilePath());
            } else {
                d->totalSize += info.size();
            }
        }
    }
}
<commit_msg>Ensured that root directory was added to bundles.<commit_after>/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Nathan Osman
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 **/

#include <QDir>
#include <QStack>

#include "bundle.h"
#include "bundle_p.h"
#include "bundleitem.h"

Bundle::Bundle(QObject *parent)
    : QObject(parent),
      d(new BundlePrivate)
{
}

Bundle::~Bundle()
{
    delete d;
}

int Bundle::count() const
{
    return d->items.count();
}

qint64 Bundle::totalSize() const
{
    return d->totalSize;
}

void Bundle::addFile(const QString &filename)
{
    QFileInfo info(filename);

    d->items.append(BundleItem(info));
    d->totalSize += info.size();
}

void Bundle::addDirectory(const QString &path)
{
    QDir root(path);
    QStack<QString> stack;

    // Ensure that the root directory is created
    d->items.append(BundleItem(QFileInfo(root.absolutePath())));

    // Push the root path on the stack and then go up one level so that
    // the relative filenames will include the name of the directory
    stack.push(root.absolutePath());
    root.cdUp();

    while(stack.count()) {
        QString tos = stack.pop();

        foreach(QFileInfo info, QDir(tos).entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)) {

            // Add the item to the bundle
            d->items.append(BundleItem(root, info));

            // If the item is a directory, add it to the stack
            // Otherwise, add its size to the total
            if(info.isDir()) {
                stack.push(info.absoluteFilePath());
            } else {
                d->totalSize += info.size();
            }
        }
    }
}
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2001 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named LICENSE that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "KeyMap.h"
#include <ctype.h>

const BzfKeyEvent	BzfKeyMap::defaults1[] = {
				{ 0, BzfKeyEvent::LeftMouse, 0 },
				{ 0, BzfKeyEvent::MiddleMouse, 0 },
				{ 0, BzfKeyEvent::RightMouse, 0 },
				{ '1', 0, 0 },
				{ '2', 0, 0 },
				{ '3', 0, 0 },
				{ 'n', 0, 0 },
				{ 'm', 0, 0 },
				{ ',', 0, 0 },
				{ '\t', 0, 0 },
				{ 'b', 0, 0 },
				{ 's', 0, 0 },
				{ 'f', 0, 0 },
				{ '=', 0, 0 },
				{ '-', 0, 0 },
				{ 0, BzfKeyEvent::Pause, 0 },
				{ 0, BzfKeyEvent::F12, 0 },
				{ 0, BzfKeyEvent::PageUp, 0 },
				{ 0, BzfKeyEvent::PageDown, 0 }

			};
const BzfKeyEvent	BzfKeyMap::defaults2[] = {
				{ 0, 0, 0 },
				{ ' ', 0, 0 },
				{ 0, 0, 0 },
				{ 0, 0, 0 },
				{ 0, 0, 0 },
				{ 0, 0, 0 },
				{ 0, 0, 0 },
				{ 0, 0, 0 },
				{ 0, 0, 0 },
				{ 0, 0, 0 },
				{ 0, 0, 0 },
				{ 0, 0, 0 },
				{ 0, 0, 0 },
				{ '+', 0, 0 },
				{ '_', 0, 0 },
				{ 'p', 0, 0 },
				{ 0, 0, 0 },
				{ 0, 0, 0 },
				{ 0, 0, 0 }
			};
const char*		BzfKeyMap::keyName[] = {
				"fireKey",
				"dropFlagKey",
				"identifyKey",
				"shortRangeKey",
				"mediumRangeKey",
				"longRangeKey",
				"sendAllKey",
				"sendTeamKey",
				"sendNemesisKey",
				"jumpKey",
				"binocularsKey",
				"scoreKey",
				"flagHelpKey",
				"timeForwardKey",
				"timeBackwardKey",
				"pauseKey",
				"quitKey",
				"scrollBackwardKey",
				"scrollForwardKey",
			};

const char*		BzfKeyMap::eventNames[] = {
				"???",
				"Pause",
				"Home",
				"End",
				"Left Arrow",
				"Right Arrow",
				"Up Arrow",
				"Down Arrow",
				"Page Up",
				"Page Down",
				"Insert",
				"Delete",
				"F1",
				"F2",
				"F3",
				"F4",
				"F5",
				"F6",
				"F7",
				"F8",
				"F9",
				"F10",
				"F11",
				"F12",
				"Left Mouse",
				"Middle Mouse",
				"Right Mouse"
			};

BzfKeyMap::BzfKeyMap()
{
  resetAll();
}

BzfKeyMap::~BzfKeyMap()
{
  // do nothing
}

void			BzfKeyMap::resetAll()
{
  reset(FireShot);
  reset(DropFlag);
  reset(Identify);
  reset(ShortRange);
  reset(MediumRange);
  reset(LongRange);
  reset(SendAll);
  reset(SendTeam);
  reset(SendNemesis);
  reset(Jump);
  reset(Binoculars);
  reset(Score);
  reset(FlagHelp);
  reset(TimeForward);
  reset(TimeBackward);
  reset(Pause);
  reset(Quit);
  reset(ScrollBackward);
  reset(ScrollForward);
}

void			BzfKeyMap::reset(Key key)
{
  clear(key);
  set(key, defaults1[key]);
  set(key, defaults2[key]);
}

void			BzfKeyMap::clear(Key key)
{
  map1[key].ascii = 0;
  map1[key].button = 0;
  map1[key].shift = 0;
  map2[key].ascii = 0;
  map2[key].button = 0;
  map2[key].shift = 0;
}

void			BzfKeyMap::set(Key key, const BzfKeyEvent& event)
{
  if ((map1[key].ascii != 0 || map1[key].button != 0) &&
      (map2[key].ascii != 0 || map2[key].button != 0))
    clear(key);

  if (map1[key].ascii == 0 && map1[key].button == 0) {
    map1[key].ascii = toupper(event.ascii);
    map1[key].button = event.button;
  }
  else {
    map2[key].ascii = toupper(event.ascii);
    map2[key].button = event.button;
  }
}

void			BzfKeyMap::unset(Key key, const BzfKeyEvent& event)
{
  if (event.ascii == 0 && event.button == 0) return;
  if (map1[key].ascii == toupper(event.ascii) &&
      map1[key].button == event.button) {
    map1[key] = map2[key];
    map2[key].ascii = 0;
    map2[key].button = 0;
  }
  else if (map2[key].ascii == toupper(event.ascii) &&
	   map2[key].button == event.button) {
    map2[key].ascii = 0;
    map2[key].button = 0;
  }
}

const BzfKeyEvent&	BzfKeyMap::get(Key key) const
{
  return map1[key];
}

const BzfKeyEvent&	BzfKeyMap::getAlternate(Key key) const
{
  return map2[key];
}

BzfKeyMap::Key		BzfKeyMap::isMapped(char ascii) const
{
  BzfKeyEvent event;
  event.ascii = ascii;
  event.button = 0;
  event.shift = 0;
  return isMapped(event);
}

BzfKeyMap::Key		BzfKeyMap::isMapped(BzfKeyEvent::Button button) const
{
  BzfKeyEvent event;
  event.ascii = 0;
  event.button = button;
  event.shift = 0;
  return isMapped(event);
}

BzfKeyMap::Key		BzfKeyMap::isMapped(const BzfKeyEvent& event) const
{
  if (event.ascii == 0 && event.button == 0)
    return LastKey;

  for (int i = 0; i < LastKey; i++) {
    if (map1[i].ascii == toupper(event.ascii) &&
	map1[i].button == event.button)
      return (Key)i;
    if (map2[i].ascii == toupper(event.ascii) &&
	map2[i].button == event.button)
      return (Key)i;
  }
  return LastKey;
}

boolean			BzfKeyMap::isMappedTo(Key key,
				const BzfKeyEvent& event) const
{
  if (event.ascii == 0 && event.button == 0)
    return False;

  if (map1[key].ascii == toupper(event.ascii) &&
      map1[key].button == event.button)
    return True;
  if (map2[key].ascii == toupper(event.ascii) &&
      map2[key].button == event.button)
    return True;

  return False;
}

BzfString		BzfKeyMap::getKeyName(Key key)
{
  return BzfString(keyName[key]);
}

BzfKeyMap::Key		BzfKeyMap::lookupKeyName(const BzfString& name)
{
  for (int i = 0; i < (int)(sizeof(keyName) / sizeof(keyName[0])); i++)
    if (name == keyName[i])
      return (Key)i;
  return LastKey;
}

BzfString		BzfKeyMap::getKeyEventString(const BzfKeyEvent& event)
{
  if (event.ascii != 0) {
    if (event.ascii == '\b') return "Backspace";
    if (!isspace(event.ascii)) return BzfString(&event.ascii, 1);
    if (event.ascii == ' ') return "Space";
    if (event.ascii == '\t') return "Tab";
    if (event.ascii == '\r') return "Enter";
    return "???";
  }

  return eventNames[event.button];
}

boolean			BzfKeyMap::translateStringToEvent(
				const BzfString& value, BzfKeyEvent& event)
{
  event.shift = 0;

  // ignore bogus value
  if (value == "???") return False;

  // check for plain ascii (one character) values
  if (value.getLength() == 1) {
    char c = value[0];
    if (isalnum(c) || ispunct(c)) {
      event.ascii = c;
      event.button = 0;
      return True;
    }
    return False;
  }

  // check whitespace values
  if (value == "Space") {
    event.ascii = ' ';
    event.button = 0;
    return True;
  }
  if (value == "Tab") {
    event.ascii = '\t';
    event.button = 0;
    return True;
  }
  if (value == "Backspace") {
    event.ascii = '\b';
    event.button = 0;
    return True;
  }
  if (value == "Enter") {
    event.ascii = '\r';
    event.button = 0;
    return True;
  }

  // check non-ascii button strings
  for (int i = 0; i < (int)(sizeof(eventNames) / sizeof(eventNames[0])); i++)
    if (value == eventNames[i]) {
      event.ascii = 0;
      event.button = i;
      return True;
    }

  return False;
}
<commit_msg>enter = fire, L = lock<commit_after>/* bzflag
 * Copyright (c) 1993 - 2001 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named LICENSE that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "KeyMap.h"
#include <ctype.h>

const BzfKeyEvent	BzfKeyMap::defaults1[] = {
				{ 0, BzfKeyEvent::LeftMouse, 0 },
				{ 0, BzfKeyEvent::MiddleMouse, 0 },
				{ 0, BzfKeyEvent::RightMouse, 0 },
				{ '1', 0, 0 },
				{ '2', 0, 0 },
				{ '3', 0, 0 },
				{ 'n', 0, 0 },
				{ 'm', 0, 0 },
				{ ',', 0, 0 },
				{ '\t', 0, 0 },
				{ 'b', 0, 0 },
				{ 's', 0, 0 },
				{ 'f', 0, 0 },
				{ '=', 0, 0 },
				{ '-', 0, 0 },
				{ 0, BzfKeyEvent::Pause, 0 },
				{ 0, BzfKeyEvent::F12, 0 },
				{ 0, BzfKeyEvent::PageUp, 0 },
				{ 0, BzfKeyEvent::PageDown, 0 }

			};
const BzfKeyEvent	BzfKeyMap::defaults2[] = {
				{ '\r', 0, 0 },
				{ ' ', 0, 0 },
				{ 'l', 0, 0 },
				{ 0, 0, 0 },
				{ 0, 0, 0 },
				{ 0, 0, 0 },
				{ 0, 0, 0 },
				{ 0, 0, 0 },
				{ 0, 0, 0 },
				{ 0, 0, 0 },
				{ 0, 0, 0 },
				{ 0, 0, 0 },
				{ 0, 0, 0 },
				{ '+', 0, 0 },
				{ '_', 0, 0 },
				{ 'p', 0, 0 },
				{ 0, 0, 0 },
				{ 0, 0, 0 },
				{ 0, 0, 0 }
			};
const char*		BzfKeyMap::keyName[] = {
				"fireKey",
				"dropFlagKey",
				"identifyKey",
				"shortRangeKey",
				"mediumRangeKey",
				"longRangeKey",
				"sendAllKey",
				"sendTeamKey",
				"sendNemesisKey",
				"jumpKey",
				"binocularsKey",
				"scoreKey",
				"flagHelpKey",
				"timeForwardKey",
				"timeBackwardKey",
				"pauseKey",
				"quitKey",
				"scrollBackwardKey",
				"scrollForwardKey",
			};

const char*		BzfKeyMap::eventNames[] = {
				"???",
				"Pause",
				"Home",
				"End",
				"Left Arrow",
				"Right Arrow",
				"Up Arrow",
				"Down Arrow",
				"Page Up",
				"Page Down",
				"Insert",
				"Delete",
				"F1",
				"F2",
				"F3",
				"F4",
				"F5",
				"F6",
				"F7",
				"F8",
				"F9",
				"F10",
				"F11",
				"F12",
				"Left Mouse",
				"Middle Mouse",
				"Right Mouse"
			};

BzfKeyMap::BzfKeyMap()
{
  resetAll();
}

BzfKeyMap::~BzfKeyMap()
{
  // do nothing
}

void			BzfKeyMap::resetAll()
{
  reset(FireShot);
  reset(DropFlag);
  reset(Identify);
  reset(ShortRange);
  reset(MediumRange);
  reset(LongRange);
  reset(SendAll);
  reset(SendTeam);
  reset(SendNemesis);
  reset(Jump);
  reset(Binoculars);
  reset(Score);
  reset(FlagHelp);
  reset(TimeForward);
  reset(TimeBackward);
  reset(Pause);
  reset(Quit);
  reset(ScrollBackward);
  reset(ScrollForward);
}

void			BzfKeyMap::reset(Key key)
{
  clear(key);
  set(key, defaults1[key]);
  set(key, defaults2[key]);
}

void			BzfKeyMap::clear(Key key)
{
  map1[key].ascii = 0;
  map1[key].button = 0;
  map1[key].shift = 0;
  map2[key].ascii = 0;
  map2[key].button = 0;
  map2[key].shift = 0;
}

void			BzfKeyMap::set(Key key, const BzfKeyEvent& event)
{
  if ((map1[key].ascii != 0 || map1[key].button != 0) &&
      (map2[key].ascii != 0 || map2[key].button != 0))
    clear(key);

  if (map1[key].ascii == 0 && map1[key].button == 0) {
    map1[key].ascii = toupper(event.ascii);
    map1[key].button = event.button;
  }
  else {
    map2[key].ascii = toupper(event.ascii);
    map2[key].button = event.button;
  }
}

void			BzfKeyMap::unset(Key key, const BzfKeyEvent& event)
{
  if (event.ascii == 0 && event.button == 0) return;
  if (map1[key].ascii == toupper(event.ascii) &&
      map1[key].button == event.button) {
    map1[key] = map2[key];
    map2[key].ascii = 0;
    map2[key].button = 0;
  }
  else if (map2[key].ascii == toupper(event.ascii) &&
	   map2[key].button == event.button) {
    map2[key].ascii = 0;
    map2[key].button = 0;
  }
}

const BzfKeyEvent&	BzfKeyMap::get(Key key) const
{
  return map1[key];
}

const BzfKeyEvent&	BzfKeyMap::getAlternate(Key key) const
{
  return map2[key];
}

BzfKeyMap::Key		BzfKeyMap::isMapped(char ascii) const
{
  BzfKeyEvent event;
  event.ascii = ascii;
  event.button = 0;
  event.shift = 0;
  return isMapped(event);
}

BzfKeyMap::Key		BzfKeyMap::isMapped(BzfKeyEvent::Button button) const
{
  BzfKeyEvent event;
  event.ascii = 0;
  event.button = button;
  event.shift = 0;
  return isMapped(event);
}

BzfKeyMap::Key		BzfKeyMap::isMapped(const BzfKeyEvent& event) const
{
  if (event.ascii == 0 && event.button == 0)
    return LastKey;

  for (int i = 0; i < LastKey; i++) {
    if (map1[i].ascii == toupper(event.ascii) &&
	map1[i].button == event.button)
      return (Key)i;
    if (map2[i].ascii == toupper(event.ascii) &&
	map2[i].button == event.button)
      return (Key)i;
  }
  return LastKey;
}

boolean			BzfKeyMap::isMappedTo(Key key,
				const BzfKeyEvent& event) const
{
  if (event.ascii == 0 && event.button == 0)
    return False;

  if (map1[key].ascii == toupper(event.ascii) &&
      map1[key].button == event.button)
    return True;
  if (map2[key].ascii == toupper(event.ascii) &&
      map2[key].button == event.button)
    return True;

  return False;
}

BzfString		BzfKeyMap::getKeyName(Key key)
{
  return BzfString(keyName[key]);
}

BzfKeyMap::Key		BzfKeyMap::lookupKeyName(const BzfString& name)
{
  for (int i = 0; i < (int)(sizeof(keyName) / sizeof(keyName[0])); i++)
    if (name == keyName[i])
      return (Key)i;
  return LastKey;
}

BzfString		BzfKeyMap::getKeyEventString(const BzfKeyEvent& event)
{
  if (event.ascii != 0) {
    if (event.ascii == '\b') return "Backspace";
    if (!isspace(event.ascii)) return BzfString(&event.ascii, 1);
    if (event.ascii == ' ') return "Space";
    if (event.ascii == '\t') return "Tab";
    if (event.ascii == '\r') return "Enter";
    return "???";
  }

  return eventNames[event.button];
}

boolean			BzfKeyMap::translateStringToEvent(
				const BzfString& value, BzfKeyEvent& event)
{
  event.shift = 0;

  // ignore bogus value
  if (value == "???") return False;

  // check for plain ascii (one character) values
  if (value.getLength() == 1) {
    char c = value[0];
    if (isalnum(c) || ispunct(c)) {
      event.ascii = c;
      event.button = 0;
      return True;
    }
    return False;
  }

  // check whitespace values
  if (value == "Space") {
    event.ascii = ' ';
    event.button = 0;
    return True;
  }
  if (value == "Tab") {
    event.ascii = '\t';
    event.button = 0;
    return True;
  }
  if (value == "Backspace") {
    event.ascii = '\b';
    event.button = 0;
    return True;
  }
  if (value == "Enter") {
    event.ascii = '\r';
    event.button = 0;
    return True;
  }

  // check non-ascii button strings
  for (int i = 0; i < (int)(sizeof(eventNames) / sizeof(eventNames[0])); i++)
    if (value == eventNames[i]) {
      event.ascii = 0;
      event.button = i;
      return True;
    }

  return False;
}
<|endoftext|>


<commit_before>#ifndef CAN_EMULATOR

#include "usbutil.h"
#include "canread.h"
#include "serialutil.h"
#include "signals.h"
#include "log.h"
#include "cJSON.h"
#include "listener.h"
#include <stdint.h>

extern SerialDevice SERIAL_DEVICE;
extern UsbDevice USB_DEVICE;
extern Listener listener;

/* Forward declarations */

void receiveCan(CanBus*);

void initializeAllCan();
bool receiveWriteRequest(uint8_t*);

void setup() {
    initializeLogging();
    initializeSerial(&SERIAL_DEVICE);
    initializeUsb(&USB_DEVICE);
    initializeAllCan();
}

void loop() {
    for(int i = 0; i < getCanBusCount(); i++) {
        receiveCan(&getCanBuses()[i]);
    }
    processListenerQueues(&listener);
    readFromHost(&USB_DEVICE, &receiveWriteRequest);
    readFromSerial(&SERIAL_DEVICE, &receiveWriteRequest);
    for(int i = 0; i < getCanBusCount(); i++) {
        processCanWriteQueue(&getCanBuses()[i]);
    }
}

void initializeAllCan() {
    for(int i = 0; i < getCanBusCount(); i++) {
        initializeCan(&(getCanBuses()[i]));
    }
}

bool receiveWriteRequest(uint8_t* message) {
    cJSON *root = cJSON_Parse((char*)message);
    if(root != NULL) {
        cJSON* nameObject = cJSON_GetObjectItem(root, "name");
        if(nameObject == NULL) {
            debug("Write request is malformed, missing name: %s\r\n", message);
            return true;
        }
        char* name = nameObject->valuestring;
        cJSON* value = cJSON_GetObjectItem(root, "value");
        CanSignal* signal = lookupSignal(name, getSignals(),
                getSignalCount(), true);
        CanCommand* command = lookupCommand(name, getCommands(),
                getCommandCount());
        if(signal != NULL) {
            sendCanSignal(signal, value, getSignals(), getSignalCount());
        } else if(command != NULL) {
            command->handler(name, value, getSignals(), getSignalCount());
        } else {
            debug("Writing not allowed for signal with name %s\r\n", name);
        }
        cJSON_Delete(root);
        return true;
    }
    return false;
}

/*
 * Check to see if a packet has been received. If so, read the packet and print
 * the packet payload to the serial monitor.
 */
void receiveCan(CanBus* bus) {
    // TODO what happens if we process until the queue is empty?
    if(QUEUE_LENGTH(CanMessage, &bus->receiveQueue) > 0) {
        CanMessage message = QUEUE_POP(CanMessage, &bus->receiveQueue);
        decodeCanMessage(message.id, message.data);
    }
}

void reset() {
    initializeAllCan();
}

#endif // CAN_EMULATOR
<commit_msg>Remove extra whitespace.<commit_after>#ifndef CAN_EMULATOR

#include "usbutil.h"
#include "canread.h"
#include "serialutil.h"
#include "signals.h"
#include "log.h"
#include "cJSON.h"
#include "listener.h"
#include <stdint.h>

extern SerialDevice SERIAL_DEVICE;
extern UsbDevice USB_DEVICE;
extern Listener listener;

/* Forward declarations */

void receiveCan(CanBus*);
void initializeAllCan();
bool receiveWriteRequest(uint8_t*);

void setup() {
    initializeLogging();
    initializeSerial(&SERIAL_DEVICE);
    initializeUsb(&USB_DEVICE);
    initializeAllCan();
}

void loop() {
    for(int i = 0; i < getCanBusCount(); i++) {
        receiveCan(&getCanBuses()[i]);
    }
    processListenerQueues(&listener);
    readFromHost(&USB_DEVICE, &receiveWriteRequest);
    readFromSerial(&SERIAL_DEVICE, &receiveWriteRequest);
    for(int i = 0; i < getCanBusCount(); i++) {
        processCanWriteQueue(&getCanBuses()[i]);
    }
}

void initializeAllCan() {
    for(int i = 0; i < getCanBusCount(); i++) {
        initializeCan(&(getCanBuses()[i]));
    }
}

bool receiveWriteRequest(uint8_t* message) {
    cJSON *root = cJSON_Parse((char*)message);
    if(root != NULL) {
        cJSON* nameObject = cJSON_GetObjectItem(root, "name");
        if(nameObject == NULL) {
            debug("Write request is malformed, missing name: %s\r\n", message);
            return true;
        }
        char* name = nameObject->valuestring;
        cJSON* value = cJSON_GetObjectItem(root, "value");
        CanSignal* signal = lookupSignal(name, getSignals(),
                getSignalCount(), true);
        CanCommand* command = lookupCommand(name, getCommands(),
                getCommandCount());
        if(signal != NULL) {
            sendCanSignal(signal, value, getSignals(), getSignalCount());
        } else if(command != NULL) {
            command->handler(name, value, getSignals(), getSignalCount());
        } else {
            debug("Writing not allowed for signal with name %s\r\n", name);
        }
        cJSON_Delete(root);
        return true;
    }
    return false;
}

/*
 * Check to see if a packet has been received. If so, read the packet and print
 * the packet payload to the serial monitor.
 */
void receiveCan(CanBus* bus) {
    // TODO what happens if we process until the queue is empty?
    if(QUEUE_LENGTH(CanMessage, &bus->receiveQueue) > 0) {
        CanMessage message = QUEUE_POP(CanMessage, &bus->receiveQueue);
        decodeCanMessage(message.id, message.data);
    }
}

void reset() {
    initializeAllCan();
}

#endif // CAN_EMULATOR
<|endoftext|>


<commit_before>#include <Arduino.h>
#include "chibi_monitor.h"

namespace Chibi {

	StateMachine<Monitor>::stateFunction_t Monitor::m_commands[16] = {
	    0,                            // 0
	    &Monitor::stateAddressInput,  // 1
	    &Monitor::stateDataInput,     // 2
	    0,                            // 3
	    &Monitor::stateRun,           // 4
	    &Monitor::stateStep,          // 5
	    0,                            // 6
	    0,                            // 7
	    &Monitor::stateLoad,          // 8
	    &Monitor::stateSave,          // 9
	    &Monitor::stateSerialTrace,   // a
	    &Monitor::stateSerialDump,    // b
	    &Monitor::stateSoftReset,     // c
	    &Monitor::stateHardReset,     // d
	    0,                            // e
	    0};                           // f

	Monitor::Monitor()
	    : StateMachine(this), m_cursorBlink(false), m_keyPressed(0xff), m_currentAddr(0x10) {
	}

	void Monitor::init(IO* io, Core* core) {
		m_core = core;
		m_io = io;
		m_cursorPos = 0;
		m_cursorTime = TimeOutms(250);

		io->setKeyReceiver(this);
		stateGoto(&Monitor::stateCommand);
	}

	void Monitor::update() {
		stateUpdate();
	}

	void Monitor::onKey(uint8_t scancode, uint8_t value, bool pressed) {
		if (pressed) {
			m_keyPressed = value;
		}
	}

	uint8_t Monitor::getKey() {
		uint8_t key = m_keyPressed;
		m_keyPressed = 0xff;
		return key;
	}

	void Monitor::updateCursor() {
		if (m_cursorPos != -1) {
			m_io->setDP(m_cursorPos & 3, m_cursorBlink);
			if (m_cursorTime.hasTimedOut()) {
				m_cursorTime.reset();
				m_cursorBlink = !m_cursorBlink;
			}
		} else {
			m_io->setDP(0, false);
		}
	}

	void Monitor::handleCommonKeys(uint8_t key) {
		if (key == KEY_CMD) {
			stateGoto(&Monitor::stateCommand);
		}
		if (key == KEY_UP) {
			m_currentAddr++;
		}
		if (key == KEY_DOWN) {
			m_currentAddr--;
		}
	}

	void Monitor::stateCommand(Phase_t p) {
		uint8_t& command = m_stateValue;
		if (p == Enter) {
			m_io->clearDisplay();
			m_io->displayDigit(3, 0xc);
			m_cursorPos = 0;
			command = 0;
		}
		if (p == Update) {
			m_io->displayDigit(0, command);
			updateCursor();

			uint8_t key = getKey();
			if (key != 0xff) {
				if (key < 0x10) {
					m_io->displayDigit(0, key);
					command = key;
				}
				if (key == KEY_ENTER) {
					if (m_commands[command]) {
						stateGoto(m_commands[command]);
					}
				}
			}
		}
		if (p == Leave) {
		}
	}

	static uint8_t byteInputHelper(uint8_t pos, uint8_t value, uint8_t inp) {
		if (pos == 0) {
			value &= 0xf0;
			value |= inp;
		} else {
			value &= 0x0f;
			value |= (inp << 4);
		}
		return value;
	}

	void Monitor::stateAddressInput(Phase_t p) {
		if (p == Enter) {
			m_io->clearDisplay();
			m_io->displayDigit(3, 0xa);
			m_cursorPos = 1;
		}
		if (p == Update) {
			m_io->displayByte(0, m_currentAddr);
			updateCursor();

			uint8_t key = getKey();
			if (key != 0xff) {
				if (key < 0x10) {
					m_currentAddr = byteInputHelper(m_cursorPos, m_currentAddr, key);
					m_cursorPos = (m_cursorPos - 1) & 1;
				}
				handleCommonKeys(key);
				if (key == KEY_ENTER) {
					stateGoto(&Monitor::stateCommand);
				}
			}
		}
		if (p == Leave) {
		}
	}

	void Monitor::stateDataInput(Phase_t p) {
		if (p == Enter) {
			m_io->clearDisplay();
			m_cursorPos = 1;
		}
		if (p == Update) {
			m_io->displayByte(1, m_currentAddr);
			m_io->displayByte(0, m_core->peek(m_currentAddr));
			updateCursor();

			uint8_t key = getKey();
			if (key != 0xff) {
				if (key < 0x10) {
					uint8_t data = m_core->peek(m_currentAddr);
					data = byteInputHelper(m_cursorPos, data, key);
					m_core->poke(m_currentAddr, data);
					m_cursorPos = (m_cursorPos - 1) & 1;
				}
				handleCommonKeys(key);
				if (key == KEY_ENTER) {
					m_currentAddr++;
				}
			}
		}
		if (p == Leave) {
		}
	}

	void Monitor::stateSoftReset(Phase_t p) {
		if (p == Enter) {
			m_io->clearDisplay();
			m_io->displayByte(0, 0xcc);
		}
		if (p == Update) {
			uint8_t key = getKey();
			if (key == KEY_ENTER) {
				stateGoto(&Monitor::stateCommand);
				m_core->reset(false);
			}
			if (key == KEY_CMD) {
				stateGoto(&Monitor::stateCommand);
			}
		}
		if (p == Leave) {
		}
	}

	void Monitor::stateHardReset(Phase_t p) {
		if (p == Enter) {
			m_io->clearDisplay();
			m_io->displayByte(0, 0xcc);
		}
		if (p == Update) {
			uint8_t key = getKey();
			if (key == KEY_ENTER) {
				stateGoto(&Monitor::stateCommand);
				m_core->reset(true);
			}
			if (key == KEY_CMD) {
				stateGoto(&Monitor::stateCommand);
			}
		}
		if (p == Leave) {
		}
	}

	void Monitor::stateRun(Phase_t p) {
		if (p == Enter) {
		}
		if (p == Update) {
			stateGoto(&Monitor::stateCommand);
		}
		if (p == Leave) {
		}
	}

	void Monitor::stateStep(Phase_t p) {
		if (p == Enter) {
			m_io->clearDisplay();
		}
		if (p == Update) {
			m_io->displayByte(1, m_core->peek(Core::ADDR_PC));
			m_io->displayByte(0, m_core->peek(Core::ADDR_A));
			m_io->setDP(0, m_core->peek(Core::ADDR_FLAGS) != 0);

			uint8_t key = getKey();
			if (key == KEY_ENTER) {
				m_core->exec();
			}
			if (key == KEY_CMD) {
				stateGoto(&Monitor::stateCommand);
			}
		}
		if (p == Leave) {
		}
	}

	void Monitor::stateSave(Phase_t p) {
		if (p == Enter) {
		}
		if (p == Update) {
			stateGoto(&Monitor::stateCommand);
		}
		if (p == Leave) {
		}
	}

	void Monitor::stateLoad(Phase_t p) {
		if (p == Enter) {
		}
		if (p == Update) {
			stateGoto(&Monitor::stateCommand);
		}
		if (p == Leave) {
		}
	}

	void Monitor::stateSerialTrace(Phase_t p) {
		if (p == Enter) {
		}
		if (p == Update) {
			stateGoto(&Monitor::stateCommand);
		}
		if (p == Leave) {
		}
	}

	void printHex(uint8_t val) {
		Serial.print(val >> 4, HEX);
		Serial.print(val & 0xf, HEX);
	}

	void Monitor::stateSerialDump(Phase_t p) {
		uint8_t& addr = m_stateValue;
		if (p == Enter) {
			m_io->clearDisplay();
			addr = 0;
		}
		if (p == Update) {
			m_io->displayByte(0, addr);
			if ((addr & 0x0f) == 0) {
				Serial.println("");
				printHex(addr);
				Serial.print(": ");
			}

			printHex(m_core->peek(addr));
			Serial.print(' ');

			if (addr == 0xff) {
				Serial.println("");
				stateGoto(&Monitor::stateCommand);
			} else {
				addr++;
			}
		}
		if (p == Leave) {
		}
	}
}
<commit_msg>added initial save and load impl<commit_after>#include <Arduino.h>
#include <EEPROM.h>
#include "chibi_monitor.h"

namespace Chibi {

	StateMachine<Monitor>::stateFunction_t Monitor::m_commands[16] = {
	    0,                            // 0
	    &Monitor::stateAddressInput,  // 1
	    &Monitor::stateDataInput,     // 2
	    0,                            // 3
	    &Monitor::stateRun,           // 4
	    &Monitor::stateStep,          // 5
	    0,                            // 6
	    0,                            // 7
	    &Monitor::stateLoad,          // 8
	    &Monitor::stateSave,          // 9
	    &Monitor::stateSerialTrace,   // a
	    &Monitor::stateSerialDump,    // b
	    &Monitor::stateSoftReset,     // c
	    &Monitor::stateHardReset,     // d
	    0,                            // e
	    0};                           // f

	Monitor::Monitor()
	    : StateMachine(this), m_cursorBlink(false), m_keyPressed(0xff), m_currentAddr(0x10) {
	}

	void Monitor::init(IO* io, Core* core) {
		m_core = core;
		m_io = io;
		m_cursorPos = 0;
		m_cursorTime = TimeOutms(250);

		io->setKeyReceiver(this);
		stateGoto(&Monitor::stateCommand);
	}

	void Monitor::update() {
		stateUpdate();
	}

	void Monitor::onKey(uint8_t scancode, uint8_t value, bool pressed) {
		if (pressed) {
			m_keyPressed = value;
		}
	}

	uint8_t Monitor::getKey() {
		uint8_t key = m_keyPressed;
		m_keyPressed = 0xff;
		return key;
	}

	void Monitor::updateCursor() {
		if (m_cursorPos != -1) {
			m_io->setDP(m_cursorPos & 3, m_cursorBlink);
			if (m_cursorTime.hasTimedOut()) {
				m_cursorTime.reset();
				m_cursorBlink = !m_cursorBlink;
			}
		} else {
			m_io->setDP(0, false);
		}
	}

	void Monitor::handleCommonKeys(uint8_t key) {
		if (key == KEY_CMD) {
			stateGoto(&Monitor::stateCommand);
		}
		if (key == KEY_UP) {
			m_currentAddr++;
		}
		if (key == KEY_DOWN) {
			m_currentAddr--;
		}
	}

	void Monitor::stateCommand(Phase_t p) {
		uint8_t& command = m_stateValue;
		if (p == Enter) {
			m_io->clearDisplay();
			m_io->displayDigit(3, 0xc);
			m_cursorPos = 0;
			command = 0;
		}
		if (p == Update) {
			m_io->displayDigit(0, command);
			updateCursor();

			uint8_t key = getKey();
			if (key != 0xff) {
				if (key < 0x10) {
					m_io->displayDigit(0, key);
					command = key;
				}
				if (key == KEY_ENTER) {
					if (m_commands[command]) {
						stateGoto(m_commands[command]);
					}
				}
			}
		}
		if (p == Leave) {
		}
	}

	static uint8_t byteInputHelper(uint8_t pos, uint8_t value, uint8_t inp) {
		if (pos == 0) {
			value &= 0xf0;
			value |= inp;
		} else {
			value &= 0x0f;
			value |= (inp << 4);
		}
		return value;
	}

	void Monitor::stateAddressInput(Phase_t p) {
		if (p == Enter) {
			m_io->clearDisplay();
			m_io->displayDigit(3, 0xa);
			m_cursorPos = 1;
		}
		if (p == Update) {
			m_io->displayByte(0, m_currentAddr);
			updateCursor();

			uint8_t key = getKey();
			if (key != 0xff) {
				if (key < 0x10) {
					m_currentAddr = byteInputHelper(m_cursorPos, m_currentAddr, key);
					m_cursorPos = (m_cursorPos - 1) & 1;
				}
				handleCommonKeys(key);
				if (key == KEY_ENTER) {
					stateGoto(&Monitor::stateCommand);
				}
			}
		}
		if (p == Leave) {
		}
	}

	void Monitor::stateDataInput(Phase_t p) {
		if (p == Enter) {
			m_io->clearDisplay();
			m_cursorPos = 1;
		}
		if (p == Update) {
			m_io->displayByte(1, m_currentAddr);
			m_io->displayByte(0, m_core->peek(m_currentAddr));
			updateCursor();

			uint8_t key = getKey();
			if (key != 0xff) {
				if (key < 0x10) {
					uint8_t data = m_core->peek(m_currentAddr);
					data = byteInputHelper(m_cursorPos, data, key);
					m_core->poke(m_currentAddr, data);
					m_cursorPos = (m_cursorPos - 1) & 1;
				}
				handleCommonKeys(key);
				if (key == KEY_ENTER) {
					m_currentAddr++;
				}
			}
		}
		if (p == Leave) {
		}
	}

	void Monitor::stateSoftReset(Phase_t p) {
		if (p == Enter) {
			m_io->clearDisplay();
			m_io->displayByte(0, 0xcc);
		}
		if (p == Update) {
			uint8_t key = getKey();
			if (key == KEY_ENTER) {
				stateGoto(&Monitor::stateCommand);
				m_core->reset(false);
			}
			if (key == KEY_CMD) {
				stateGoto(&Monitor::stateCommand);
			}
		}
		if (p == Leave) {
		}
	}

	void Monitor::stateHardReset(Phase_t p) {
		if (p == Enter) {
			m_io->clearDisplay();
			m_io->displayByte(0, 0xcc);
		}
		if (p == Update) {
			uint8_t key = getKey();
			if (key == KEY_ENTER) {
				stateGoto(&Monitor::stateCommand);
				m_core->reset(true);
			}
			if (key == KEY_CMD) {
				stateGoto(&Monitor::stateCommand);
			}
		}
		if (p == Leave) {
		}
	}

	void Monitor::stateRun(Phase_t p) {
		if (p == Enter) {
		}
		if (p == Update) {
			stateGoto(&Monitor::stateCommand);
		}
		if (p == Leave) {
		}
	}

	void Monitor::stateStep(Phase_t p) {
		if (p == Enter) {
			m_io->clearDisplay();
		}
		if (p == Update) {
			m_io->displayByte(1, m_core->peek(Core::ADDR_PC));
			m_io->displayByte(0, m_core->peek(Core::ADDR_A));
			m_io->setDP(0, m_core->peek(Core::ADDR_FLAGS) != 0);

			uint8_t key = getKey();
			if (key == KEY_ENTER) {
				m_core->exec();
			}
			if (key == KEY_CMD) {
				stateGoto(&Monitor::stateCommand);
			}
		}
		if (p == Leave) {
		}
	}

	void Monitor::stateSave(Phase_t p) {
		uint8_t& addr = m_stateValue;
		if (p == Enter) {
			m_io->clearDisplay();
			addr = 0;
		}
		if (p == Update) {
			m_io->displayByte(0, addr);
			EEPROM.write(addr, m_core->peek(addr));

			if (addr == 0xff) {
				stateGoto(&Monitor::stateCommand);
			} else {
				addr++;
			}
		}
	}

	void Monitor::stateLoad(Phase_t p) {
		uint8_t& addr = m_stateValue;
		if (p == Enter) {
			m_io->clearDisplay();
			addr = 0;
		}
		if (p == Update) {
			m_io->displayByte(0, addr);
			m_core->poke(addr, EEPROM.read(addr));

			if (addr == 0xff) {
				stateGoto(&Monitor::stateCommand);
			} else {
				addr++;
			}
			delay(2);
		}
	}

	void Monitor::stateSerialTrace(Phase_t p) {
		if (p == Enter) {
		}
		if (p == Update) {
			stateGoto(&Monitor::stateCommand);
		}
		if (p == Leave) {
		}
	}

	void printHex(uint8_t val) {
		Serial.print(val >> 4, HEX);
		Serial.print(val & 0xf, HEX);
	}

	void Monitor::stateSerialDump(Phase_t p) {
		uint8_t& addr = m_stateValue;
		if (p == Enter) {
			m_io->clearDisplay();
			addr = 0;
		}
		if (p == Update) {
			m_io->displayByte(0, addr);
			if ((addr & 0x0f) == 0) {
				Serial.println("");
				printHex(addr);
				Serial.print(": ");
			}

			printHex(m_core->peek(addr));
			Serial.print(' ');

			if (addr == 0xff) {
				Serial.println("");
				stateGoto(&Monitor::stateCommand);
			} else {
				addr++;
			}
		}
		if (p == Leave) {
		}
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2012-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "clientversion.h"

#include "tinyformat.h"

#include <string>

/**
 * Name of client reported in the 'version' message. Report the same name
 * for both bitcoind and bitcoin-core, to make it harder for attackers to
 * target servers or GUI users specifically.
 */
const std::string CLIENT_NAME("Satoshi");

/**
 * Client version number
 */
#define CLIENT_VERSION_SUFFIX ""

/**
 * The following part of the code determines the CLIENT_BUILD variable.
 * Several mechanisms are used for this:
 * * first, if HAVE_BUILD_INFO is defined, include build.h, a file that is
 *   generated by the build environment, possibly containing the output
 *   of git-describe in a macro called BUILD_DESC
 * * secondly, if this is an exported version of the code, GIT_ARCHIVE will
 *   be defined (automatically using the export-subst git attribute), and
 *   GIT_COMMIT will contain the commit id.
 * * then, three options exist for determining CLIENT_BUILD:
 *   * if BUILD_DESC is defined, use that literally (output of git-describe)
 *   * if not, but GIT_COMMIT is defined, use v[maj].[min].[rev].[build]-g[commit]
 *   * otherwise, use v[maj].[min].[rev].[build]-unk
 * finally CLIENT_VERSION_SUFFIX is added
 */

//! First, include build.h if requested
#ifdef HAVE_BUILD_INFO
#include "build.h"
#endif

//! git will put "#define GIT_ARCHIVE 1" on the next line inside archives. $Format:%n#define GIT_ARCHIVE 1$
#ifdef GIT_ARCHIVE
#define GIT_COMMIT_ID "$Format:%h$"
#define GIT_COMMIT_DATE "$Format:%cD$"
#endif

#define BUILD_DESC_WITH_SUFFIX(maj, min, rev, build, suffix) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-" DO_STRINGIZE(suffix)

#define BUILD_DESC_FROM_COMMIT(maj, min, rev, build, commit) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-g" commit

#define BUILD_DESC_FROM_UNKNOWN(maj, min, rev, build) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-unk"

#ifndef BUILD_DESC
#ifdef BUILD_SUFFIX
#define BUILD_DESC BUILD_DESC_WITH_SUFFIX(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD, BUILD_SUFFIX)
#elif defined(GIT_COMMIT_ID)
#define BUILD_DESC BUILD_DESC_FROM_COMMIT(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD, GIT_COMMIT_ID)
#else
#define BUILD_DESC BUILD_DESC_FROM_UNKNOWN(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD)
#endif
#endif

const std::string CLIENT_BUILD(BUILD_DESC CLIENT_VERSION_SUFFIX);

static std::string FormatVersion(int nVersion)
{
    if (nVersion % 100 == 0)
        return strprintf("%d.%d.%d", nVersion / 1000000, (nVersion / 10000) % 100, (nVersion / 100) % 100);
    else
        return strprintf("%d.%d.%d.%d", nVersion / 1000000, (nVersion / 10000) % 100, (nVersion / 100) % 100, nVersion % 100);
}

std::string FormatFullVersion()
{
    return CLIENT_BUILD;
}

/**
 * Format the subversion field according to BIP 14 spec (https://github.com/bitcoin/bips/blob/master/bip-0014.mediawiki)
 */
std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector<std::string>& comments, const bool fBaseNameOnly)
{
    std::ostringstream ss;
    ss << "/";
    ss << name << ":" << FormatVersion(nClientVersion);
    if (!comments.empty())
    {
        std::vector<std::string>::const_iterator it(comments.begin());
        ss << "(" << *it;
        for(++it; it != comments.end(); ++it)
            ss << "; " << *it;
        ss << ")";
    }
    ss << "/";
    if (!fBaseNameOnly)
        ss << "UASF-Segwit:0.3(BIP148)/";
    return ss.str();
}
<commit_msg>add knots-esque ua comment (#35)<commit_after>// Copyright (c) 2012-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "clientversion.h"

#include "tinyformat.h"
#include "util.h"
#include "validation.h"

#include <string>

/**
 * Name of client reported in the 'version' message. Report the same name
 * for both bitcoind and bitcoin-core, to make it harder for attackers to
 * target servers or GUI users specifically.
 */
const std::string CLIENT_NAME("Satoshi");

/**
 * Client version number
 */
#define CLIENT_VERSION_SUFFIX ""

/**
 * The following part of the code determines the CLIENT_BUILD variable.
 * Several mechanisms are used for this:
 * * first, if HAVE_BUILD_INFO is defined, include build.h, a file that is
 *   generated by the build environment, possibly containing the output
 *   of git-describe in a macro called BUILD_DESC
 * * secondly, if this is an exported version of the code, GIT_ARCHIVE will
 *   be defined (automatically using the export-subst git attribute), and
 *   GIT_COMMIT will contain the commit id.
 * * then, three options exist for determining CLIENT_BUILD:
 *   * if BUILD_DESC is defined, use that literally (output of git-describe)
 *   * if not, but GIT_COMMIT is defined, use v[maj].[min].[rev].[build]-g[commit]
 *   * otherwise, use v[maj].[min].[rev].[build]-unk
 * finally CLIENT_VERSION_SUFFIX is added
 */

//! First, include build.h if requested
#ifdef HAVE_BUILD_INFO
#include "build.h"
#endif

//! git will put "#define GIT_ARCHIVE 1" on the next line inside archives. $Format:%n#define GIT_ARCHIVE 1$
#ifdef GIT_ARCHIVE
#define GIT_COMMIT_ID "$Format:%h$"
#define GIT_COMMIT_DATE "$Format:%cD$"
#endif

#define BUILD_DESC_WITH_SUFFIX(maj, min, rev, build, suffix) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-" DO_STRINGIZE(suffix)

#define BUILD_DESC_FROM_COMMIT(maj, min, rev, build, commit) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-g" commit

#define BUILD_DESC_FROM_UNKNOWN(maj, min, rev, build) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-unk"

#ifndef BUILD_DESC
#ifdef BUILD_SUFFIX
#define BUILD_DESC BUILD_DESC_WITH_SUFFIX(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD, BUILD_SUFFIX)
#elif defined(GIT_COMMIT_ID)
#define BUILD_DESC BUILD_DESC_FROM_COMMIT(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD, GIT_COMMIT_ID)
#else
#define BUILD_DESC BUILD_DESC_FROM_UNKNOWN(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD)
#endif
#endif

const std::string CLIENT_BUILD(BUILD_DESC CLIENT_VERSION_SUFFIX);

static std::string FormatVersion(int nVersion)
{
    if (nVersion % 100 == 0)
        return strprintf("%d.%d.%d", nVersion / 1000000, (nVersion / 10000) % 100, (nVersion / 100) % 100);
    else
        return strprintf("%d.%d.%d.%d", nVersion / 1000000, (nVersion / 10000) % 100, (nVersion / 100) % 100, nVersion % 100);
}

std::string FormatFullVersion()
{
    return CLIENT_BUILD;
}

/**
 * Format the subversion field according to BIP 14 spec (https://github.com/bitcoin/bips/blob/master/bip-0014.mediawiki)
 */
std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector<std::string>& comments, const bool fBaseNameOnly)
{
    std::ostringstream ss;
    ss << "/";
    ss << name << ":" << FormatVersion(nClientVersion);
    if (!comments.empty())
    {
        std::vector<std::string>::const_iterator it(comments.begin());
        ss << "(" << *it;
        for(++it; it != comments.end(); ++it)
            ss << "; " << *it;
        ss << ")";
    }
    ss << "/";
    if (!fBaseNameOnly) {
        if (GetBoolArg("-bip148", DEFAULT_BIP148))
            ss << "UASF-Segwit:0.3(BIP148)/";
        else
            ss << "UASF-Segwit:0.3(!BIP148)/";
    }
    return ss.str();
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "gtk3cairotextrender.hxx"

GtkCairoTextRender::GtkCairoTextRender(GtkSalGraphics& rParent)
    : mrParent(rParent)
{
}

GlyphCache& GtkCairoTextRender::getPlatformGlyphCache()
{
    return mrParent.getPlatformGlyphCache();
}

cairo_t* GtkCairoTextRender::getCairoContext()
{
    return mrParent.getCairoContext();
}

void GtkCairoTextRender::getSurfaceOffset(double& nDX, double& nDY)
{
    nDX = 0;
    nDY = 0;
}

void GtkCairoTextRender::clipRegion(cairo_t* cr)
{
    mrParent.clipRegion(cr);
}

void GtkCairoTextRender::drawSurface(cairo_t* /*cr*/)
{
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>vcl: [loplugin:staticcall]<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "gtk3cairotextrender.hxx"

GtkCairoTextRender::GtkCairoTextRender(GtkSalGraphics& rParent)
    : mrParent(rParent)
{
}

GlyphCache& GtkCairoTextRender::getPlatformGlyphCache()
{
    return SvpSalGraphics::getPlatformGlyphCache();
}

cairo_t* GtkCairoTextRender::getCairoContext()
{
    return mrParent.getCairoContext();
}

void GtkCairoTextRender::getSurfaceOffset(double& nDX, double& nDY)
{
    nDX = 0;
    nDY = 0;
}

void GtkCairoTextRender::clipRegion(cairo_t* cr)
{
    mrParent.clipRegion(cr);
}

void GtkCairoTextRender::drawSurface(cairo_t* /*cr*/)
{
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/vespalib/testkit/testapp.h>
#include <vespa/log/log.h>

LOG_SETUP("new_test");

void cmp(const void *a, const void *b) {
    EXPECT_EQUAL(a, b);
}
void cmp(const void *base, size_t offset, const void *p) {
    cmp((static_cast<const char *>(base) + offset), p);
}

TEST("verify new with normal alignment") {
    struct S {
        int a;
        long b;
        int c;
    };
    static_assert(sizeof(S) == 24, "sizeof(S) == 16");
    auto s = std::make_unique<S>();
    cmp(s.get(), &s->a);
    cmp(s.get(), 8, &s->b);
    cmp(s.get(), 16, &s->c);
    LOG(info, "&s=%p &s.b=%p &s.c=%p", s.get(), &s->b, &s->c);
}

TEST("verify new with alignment = 16") {
    struct S {
        int a;
        alignas(16) long b;
        int c;
    };
    static_assert(sizeof(S) == 32, "sizeof(S) == 32");
    auto s = std::make_unique<S>();
    cmp(s.get(), &s->a);
    cmp(s.get(), 16, &s->b);
    cmp(s.get(), 24, &s->c);
    LOG(info, "&s=%p &s.b=%p &s.c=%p", s.get(), &s->b, &s->c);
}

TEST("verify new with alignment = 32") {
    struct S {
        int a;
        alignas(32) long b;
        int c;
    };
    static_assert(sizeof(S) == 64, "sizeof(S) == 64");
    auto s = std::make_unique<S>();
    cmp(s.get(), &s->a);
    cmp(s.get(), 32, &s->b);
    cmp(s.get(), 40, &s->c);
    LOG(info, "&s=%p &s.b=%p &s.c=%p", s.get(), &s->b, &s->c);
}

TEST("verify new with alignment = 64") {
    struct S {
        int a;
        alignas(64) long b;
        int c;
    };
    static_assert(sizeof(S) == 128, "sizeof(S) == 128");
    auto s = std::make_unique<S>();
    cmp(s.get(), &s->a);
    cmp(s.get(), 64, &s->b);
    cmp(s.get(), 72, &s->c);
    LOG(info, "&s=%p &s.b=%p &s.c=%p", s.get(), &s->b, &s->c);
}

TEST("verify new with alignment = 64 with single element") {
    struct S {
        alignas(64) long a;
    };
    static_assert(sizeof(S) == 64, "sizeof(S) == 64");
    auto s = std::make_unique<S>();
    cmp(s.get(), &s->a);
    LOG(info, "&s=%p", s.get());
}

TEST("verify new with alignment = 64 with single element") {
    struct alignas(64) S {
        long a;
    };
    static_assert(sizeof(S) == 64, "sizeof(S) == 64");
    auto s = std::make_unique<S>();
    cmp(s.get(), &s->a);
    LOG(info, "&s=%p", s.get());
}

TEST_MAIN() { TEST_RUN_ALL(); }
<commit_msg>Add test of alignment.<commit_after>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/vespalib/testkit/testapp.h>
#include <vespa/log/log.h>

LOG_SETUP("new_test");

void cmp(const void *a, const void *b) {
    EXPECT_EQUAL(a, b);
}
void cmp(const void *base, size_t offset, const void *p) {
    cmp((static_cast<const char *>(base) + offset), p);
}

template <typename S>
void veryfy_aligned(const S * p) {
    EXPECT_TRUE((uintptr_t(p) % alignof(S)) == 0);
}

TEST("verify new with normal alignment") {
    struct S {
        int a;
        long b;
        int c;
    };
    static_assert(sizeof(S) == 24);
    static_assert(alignof(S) == 8);
    auto s = std::make_unique<S>();
    veryfy_aligned(s.get());
    cmp(s.get(), &s->a);
    cmp(s.get(), 8, &s->b);
    cmp(s.get(), 16, &s->c);
    LOG(info, "&s=%p &s.b=%p &s.c=%p", s.get(), &s->b, &s->c);
}

TEST("verify new with alignment = 16") {
    struct S {
        int a;
        alignas(16) long b;
        int c;
    };
    static_assert(sizeof(S) == 32);
    static_assert(alignof(S) == 16);
    auto s = std::make_unique<S>();
    veryfy_aligned(s.get());
    cmp(s.get(), &s->a);
    cmp(s.get(), 16, &s->b);
    cmp(s.get(), 24, &s->c);
    LOG(info, "&s=%p &s.b=%p &s.c=%p", s.get(), &s->b, &s->c);
}

TEST("verify new with alignment = 32") {
    struct S {
        int a;
        alignas(32) long b;
        int c;
    };
    static_assert(sizeof(S) == 64);
    static_assert(alignof(S) == 32);
    auto s = std::make_unique<S>();
    veryfy_aligned(s.get());
    cmp(s.get(), &s->a);
    cmp(s.get(), 32, &s->b);
    cmp(s.get(), 40, &s->c);
    LOG(info, "&s=%p &s.b=%p &s.c=%p", s.get(), &s->b, &s->c);
}

TEST("verify new with alignment = 64") {
    struct S {
        int a;
        alignas(64) long b;
        int c;
    };
    static_assert(sizeof(S) == 128);
    static_assert(alignof(S) == 64);
    auto s = std::make_unique<S>();
    veryfy_aligned(s.get());
    cmp(s.get(), &s->a);
    cmp(s.get(), 64, &s->b);
    cmp(s.get(), 72, &s->c);
    LOG(info, "&s=%p &s.b=%p &s.c=%p", s.get(), &s->b, &s->c);
}

TEST("verify new with alignment = 64 with single element") {
    struct S {
        alignas(64) long a;
    };
    static_assert(sizeof(S) == 64);
    static_assert(alignof(S) == 64);
    auto s = std::make_unique<S>();
    veryfy_aligned(s.get());
    cmp(s.get(), &s->a);
    LOG(info, "&s=%p", s.get());
}

TEST("verify new with alignment = 64 with single element") {
    struct alignas(64) S {
        long a;
    };
    static_assert(sizeof(S) == 64);
    static_assert(alignof(S) == 64);
    auto s = std::make_unique<S>();
    veryfy_aligned(s.get());
    cmp(s.get(), &s->a);
    LOG(info, "&s=%p", s.get());
}

TEST_MAIN() { TEST_RUN_ALL(); }
<|endoftext|>


<commit_before>#include "vortex_controller/controller_ros.h"

#include "vortex/eigen_helper.h"
#include <tf/transform_datatypes.h>
#include <eigen_conversions/eigen_msg.h>

#include "std_msgs/String.h"

#include <math.h>
#include <map>
#include <string>
#include <vector>

Controller::Controller(ros::NodeHandle nh) : nh(nh)
{
  command_sub = nh.subscribe("propulsion_command", 10, &Controller::commandCallback, this);
  state_sub   = nh.subscribe("state_estimate", 10, &Controller::stateCallback, this);
  wrench_pub  = nh.advertise<geometry_msgs::Wrench>("rov_forces", 10);
  mode_pub    = nh.advertise<std_msgs::String>("controller/mode", 10);

  control_mode = ControlModes::OPEN_LOOP;

  if (!nh.getParam("/controller/frequency", frequency))
  {
    ROS_WARN("Failed to read parameter controller frequency, defaulting to 10 Hz.");
    frequency = 10;
  }

  state = new State();
  initSetpoints();
  initPositionHoldController();

  // Set up a dynamic reconfigure server
  dynamic_reconfigure::Server<vortex_controller::VortexControllerConfig>::CallbackType cb;
  cb = boost::bind(&Controller::configCallback, this, _1, _2);
  dr_srv.setCallback(cb);

  ROS_INFO("Node initialized.");
}

void Controller::commandCallback(const vortex_msgs::PropulsionCommand& msg)
{
  if (!healthyMessage(msg))
  {
    ROS_WARN("Propulsion command message out of range, ignoring...");
    return;
  }

  ControlMode new_control_mode;
  {
    int i;
    for (i = 0; i < msg.control_mode.size(); ++i)
      if (msg.control_mode[i])
        break;
    new_control_mode = static_cast<ControlMode>(i);
  }

  if (new_control_mode != control_mode)
  {
    control_mode = new_control_mode;

    Eigen::Vector3d    position;
    Eigen::Quaterniond orientation;
    Eigen::Vector6d    velocity;

    // Reset setpoints to be equal to state
    state->get(&position, &orientation, &velocity);
    setpoints->set(position, orientation);

    ROS_INFO_STREAM("Changing mode to " << controlModeString(control_mode) << ".");
  }
  publishControlMode();

  double time = msg.header.stamp.toSec();
  Eigen::Vector6d command;
  for (int i = 0; i < 6; ++i)
    command(i) = msg.motion[i];
  setpoints->update(time, command);
}

void Controller::stateCallback(const nav_msgs::Odometry &msg)
{
  Eigen::Vector3d    position;
  Eigen::Quaterniond orientation;
  Eigen::Vector6d    velocity;

  tf::pointMsgToEigen(msg.pose.pose.position, position);
  tf::quaternionMsgToEigen(msg.pose.pose.orientation, orientation);
  tf::twistMsgToEigen(msg.twist.twist, velocity);

  const double MAX_QUAT_NORM_DEVIATION = 0.1;
  bool orientation_invalid = (abs(orientation.norm() - 1) > MAX_QUAT_NORM_DEVIATION);
  if (isFucked(position) || isFucked(velocity) || orientation_invalid)
  {
    ROS_WARN("Requested state not valid, ignoring...");
    return;
  }

  state->set(position, orientation, velocity);
}

void Controller::configCallback(const vortex_controller::VortexControllerConfig &config, uint32_t level)
{
  ROS_INFO_STREAM("Setting gains [a=" << config.a << ", b=" << config.b << ", c=" << config.c << "].");
  position_hold_controller->setGains(config.a, config.b, config.c);
}

void Controller::spin()
{
  Eigen::Vector6d    tau_command          = Eigen::VectorXd::Zero(6);
  Eigen::Vector6d    tau_openloop         = Eigen::VectorXd::Zero(6);
  Eigen::Vector6d    tau_feedback         = Eigen::VectorXd::Zero(6);

  Eigen::Vector3d    position_state       = Eigen::Vector3d::Zero();
  Eigen::Quaterniond orientation_state    = Eigen::Quaterniond::Identity();
  Eigen::Vector6d    velocity_state       = Eigen::VectorXd::Zero(6);

  Eigen::Vector3d    position_setpoint    = Eigen::Vector3d::Zero();
  Eigen::Quaterniond orientation_setpoint = Eigen::Quaterniond::Identity();

  ros::Rate rate(frequency);
  while (ros::ok())
  {
    // TODO(mortenfyhn): check value of bool return from getters
    state->get(&position_state, &orientation_state, &velocity_state);
    setpoints->get(&position_setpoint, &orientation_setpoint);

    switch (control_mode)
    {
      case ControlModes::OPEN_LOOP:
      {
        setpoints->get(&tau_command);
        break;
      }

      case ControlModes::ATTITUDE_HOLD:
      {
        // Linear motion in open loop
        setpoints->get(tau_openloop);
        tau_openloop.tail(3) = Eigen::Vector3d::Zero();

        // Orientation in closed loop
        position_state.setZero();
        position_setpoint.setZero();
        tau_feedback = position_hold_controller->compute(
          position_state, orientation_state, velocity_state, position_setpoint, orientation_setpoint);

        // sum the two
        tau_command = tau_openloop + tau_feedback;
        break;
      }

      case ControlModes::SIXDOF:
      {
        tau_command = position_hold_controller->compute(position_state,
                                                        orientation_state,
                                                        velocity_state,
                                                        position_setpoint,
                                                        orientation_setpoint);
        break;
      }

      case ControlModes::RPY_DEPTH:
      {
        // TODO(mortenfyhn): make this similar to depth hold
        tau_command(0) = tau_openloop(0);
        tau_command(1) = tau_openloop(1);
        tau_command(2) = tau_feedback(2);
        tau_command(3) = tau_feedback(3);
        tau_command(4) = tau_feedback(4);
        tau_command(5) = tau_feedback(5);
        break;
      }

      case ControlModes::DEPTH_HOLD:
      {
        setpoints->get(&tau_openloop);

        bool depth_change_commanded = abs(tau_openloop(2)) > FORCE_DEADZONE_LIMIT;
        if (depth_change_commanded)
        {
          tau_command = tau_openloop;
        }
        else
        {
          position_setpoint(0) = position_state(0);
          position_setpoint(1) = position_state(1);
          orientation_setpoint = orientation_state;
          tau_feedback = position_hold_controller->compute(position_state,
                                                         orientation_state,
                                                         velocity_state,
                                                         position_setpoint,
                                                         orientation_setpoint);
          tau_command = tau_feedback + tau_openloop;
        }
        break;
      }

      default:
      {
        ROS_ERROR("Default control mode reached.");
        break;
      }
    }

    geometry_msgs::Wrench msg;
    tf::wrenchEigenToMsg(tau_command, msg);
    wrench_pub.publish(msg);

    ros::spinOnce();
    rate.sleep();
  }
}

void Controller::initSetpoints()
{
  std::vector<double> v;

  if (!nh.getParam("/propulsion/command/wrench/max", v))
    ROS_FATAL("Failed to read parameter max wrench command.");
  Eigen::Vector6d wrench_command_max = Eigen::Vector6d::Map(v.data(), v.size());

  if (!nh.getParam("/propulsion/command/wrench/scaling", v))
    ROS_FATAL("Failed to read parameter scaling wrench command.");
  Eigen::Vector6d wrench_command_scaling = Eigen::Vector6d::Map(v.data(), v.size());

  if (!nh.getParam("/propulsion/command/pose/rate", v))
    ROS_FATAL("Failed to read parameter pose command rate.");
  Eigen::Vector6d pose_command_rate = Eigen::Vector6d::Map(v.data(), v.size());

  setpoints = new Setpoints(wrench_command_scaling,
                            wrench_command_max,
                            pose_command_rate);
}

void Controller::initPositionHoldController()
{
  // Read controller gains from parameter server
  std::map<std::string, double> gains;
  if (!nh.getParam("/controller/gains", gains))
    ROS_FATAL("Failed to read parameter controller gains.");

  // Read center of gravity and buoyancy vectors
  std::vector<double> r_G_vec, r_B_vec;
  if (!nh.getParam("/physical/center_of_mass", r_G_vec))
    ROS_FATAL("Failed to read robot center of mass parameter.");
  if (!nh.getParam("/physical/center_of_buoyancy", r_B_vec))
    ROS_FATAL("Failed to read robot center of buoyancy parameter.");
  Eigen::Vector3d r_G(r_G_vec.data());
  Eigen::Vector3d r_B(r_B_vec.data());

  // Read and calculate ROV weight and buoyancy
  double mass, displacement, acceleration_of_gravity, density_of_water;
  if (!nh.getParam("/physical/mass_kg", mass))
    ROS_FATAL("Failed to read parameter mass.");
  if (!nh.getParam("/physical/displacement_m3", displacement))
    ROS_FATAL("Failed to read parameter displacement.");
  if (!nh.getParam("/gravity/acceleration", acceleration_of_gravity))
    ROS_FATAL("Failed to read parameter acceleration of gravity");
  if (!nh.getParam("/water/density", density_of_water))
    ROS_FATAL("Failed to read parameter density of water");
  double W = mass * acceleration_of_gravity;
  double B = density_of_water * displacement * acceleration_of_gravity;

  position_hold_controller = new QuaternionPdController(gains["a"],
                                                        gains["b"],
                                                        gains["c"],
                                                        W, B, r_G, r_B);
}

bool Controller::healthyMessage(const vortex_msgs::PropulsionCommand& msg)
{
  // Check that motion commands are in range
  for (int i = 0; i < msg.motion.size(); ++i)
  {
    if (msg.motion[i] > 1 || msg.motion[i] < -1)
    {
      ROS_WARN("Motion command out of range.");
      return false;
    }
  }

  // Check that exactly one control mode is requested
  int num_requested_modes = 0;
  for (int i = 0; i < msg.control_mode.size(); ++i)
    if (msg.control_mode[i])
      num_requested_modes++;

  if (num_requested_modes != 1)
  {
    ROS_WARN_STREAM("Invalid control mode. Attempt to set "
                    << num_requested_modes << " control modes at once.");
    return false;
  }

  return true;
}

void Controller::publishControlMode()
{
  std::string s = controlModeString(control_mode);
  std_msgs::String msg;
  msg.data = s;
  mode_pub.publish(msg);
}
<commit_msg>Fix pass reference error<commit_after>#include "vortex_controller/controller_ros.h"

#include "vortex/eigen_helper.h"
#include <tf/transform_datatypes.h>
#include <eigen_conversions/eigen_msg.h>

#include "std_msgs/String.h"

#include <math.h>
#include <map>
#include <string>
#include <vector>

Controller::Controller(ros::NodeHandle nh) : nh(nh)
{
  command_sub = nh.subscribe("propulsion_command", 10, &Controller::commandCallback, this);
  state_sub   = nh.subscribe("state_estimate", 10, &Controller::stateCallback, this);
  wrench_pub  = nh.advertise<geometry_msgs::Wrench>("rov_forces", 10);
  mode_pub    = nh.advertise<std_msgs::String>("controller/mode", 10);

  control_mode = ControlModes::OPEN_LOOP;

  if (!nh.getParam("/controller/frequency", frequency))
  {
    ROS_WARN("Failed to read parameter controller frequency, defaulting to 10 Hz.");
    frequency = 10;
  }

  state = new State();
  initSetpoints();
  initPositionHoldController();

  // Set up a dynamic reconfigure server
  dynamic_reconfigure::Server<vortex_controller::VortexControllerConfig>::CallbackType cb;
  cb = boost::bind(&Controller::configCallback, this, _1, _2);
  dr_srv.setCallback(cb);

  ROS_INFO("Node initialized.");
}

void Controller::commandCallback(const vortex_msgs::PropulsionCommand& msg)
{
  if (!healthyMessage(msg))
  {
    ROS_WARN("Propulsion command message out of range, ignoring...");
    return;
  }

  ControlMode new_control_mode;
  {
    int i;
    for (i = 0; i < msg.control_mode.size(); ++i)
      if (msg.control_mode[i])
        break;
    new_control_mode = static_cast<ControlMode>(i);
  }

  if (new_control_mode != control_mode)
  {
    control_mode = new_control_mode;

    Eigen::Vector3d    position;
    Eigen::Quaterniond orientation;
    Eigen::Vector6d    velocity;

    // Reset setpoints to be equal to state
    state->get(&position, &orientation, &velocity);
    setpoints->set(position, orientation);

    ROS_INFO_STREAM("Changing mode to " << controlModeString(control_mode) << ".");
  }
  publishControlMode();

  double time = msg.header.stamp.toSec();
  Eigen::Vector6d command;
  for (int i = 0; i < 6; ++i)
    command(i) = msg.motion[i];
  setpoints->update(time, command);
}

void Controller::stateCallback(const nav_msgs::Odometry &msg)
{
  Eigen::Vector3d    position;
  Eigen::Quaterniond orientation;
  Eigen::Vector6d    velocity;

  tf::pointMsgToEigen(msg.pose.pose.position, position);
  tf::quaternionMsgToEigen(msg.pose.pose.orientation, orientation);
  tf::twistMsgToEigen(msg.twist.twist, velocity);

  const double MAX_QUAT_NORM_DEVIATION = 0.1;
  bool orientation_invalid = (abs(orientation.norm() - 1) > MAX_QUAT_NORM_DEVIATION);
  if (isFucked(position) || isFucked(velocity) || orientation_invalid)
  {
    ROS_WARN("Requested state not valid, ignoring...");
    return;
  }

  state->set(position, orientation, velocity);
}

void Controller::configCallback(const vortex_controller::VortexControllerConfig &config, uint32_t level)
{
  ROS_INFO_STREAM("Setting gains [a=" << config.a << ", b=" << config.b << ", c=" << config.c << "].");
  position_hold_controller->setGains(config.a, config.b, config.c);
}

void Controller::spin()
{
  Eigen::Vector6d    tau_command          = Eigen::VectorXd::Zero(6);
  Eigen::Vector6d    tau_openloop         = Eigen::VectorXd::Zero(6);
  Eigen::Vector6d    tau_feedback         = Eigen::VectorXd::Zero(6);

  Eigen::Vector3d    position_state       = Eigen::Vector3d::Zero();
  Eigen::Quaterniond orientation_state    = Eigen::Quaterniond::Identity();
  Eigen::Vector6d    velocity_state       = Eigen::VectorXd::Zero(6);

  Eigen::Vector3d    position_setpoint    = Eigen::Vector3d::Zero();
  Eigen::Quaterniond orientation_setpoint = Eigen::Quaterniond::Identity();

  ros::Rate rate(frequency);
  while (ros::ok())
  {
    // TODO(mortenfyhn): check value of bool return from getters
    state->get(&position_state, &orientation_state, &velocity_state);
    setpoints->get(&position_setpoint, &orientation_setpoint);

    switch (control_mode)
    {
      case ControlModes::OPEN_LOOP:
      {
        setpoints->get(&tau_command);
        break;
      }

      case ControlModes::ATTITUDE_HOLD:
      {
        // Linear motion in open loop
        setpoints->get(&tau_openloop);
        tau_openloop.tail(3) = Eigen::Vector3d::Zero();

        // Orientation in closed loop
        position_state.setZero();
        position_setpoint.setZero();
        tau_feedback = position_hold_controller->compute(
          position_state, orientation_state, velocity_state, position_setpoint, orientation_setpoint);

        // sum the two
        tau_command = tau_openloop + tau_feedback;
        break;
      }

      case ControlModes::SIXDOF:
      {
        tau_command = position_hold_controller->compute(position_state,
                                                        orientation_state,
                                                        velocity_state,
                                                        position_setpoint,
                                                        orientation_setpoint);
        break;
      }

      case ControlModes::RPY_DEPTH:
      {
        // TODO(mortenfyhn): make this similar to depth hold
        tau_command(0) = tau_openloop(0);
        tau_command(1) = tau_openloop(1);
        tau_command(2) = tau_feedback(2);
        tau_command(3) = tau_feedback(3);
        tau_command(4) = tau_feedback(4);
        tau_command(5) = tau_feedback(5);
        break;
      }

      case ControlModes::DEPTH_HOLD:
      {
        setpoints->get(&tau_openloop);

        bool depth_change_commanded = abs(tau_openloop(2)) > FORCE_DEADZONE_LIMIT;
        if (depth_change_commanded)
        {
          tau_command = tau_openloop;
        }
        else
        {
          position_setpoint(0) = position_state(0);
          position_setpoint(1) = position_state(1);
          orientation_setpoint = orientation_state;
          tau_feedback = position_hold_controller->compute(position_state,
                                                         orientation_state,
                                                         velocity_state,
                                                         position_setpoint,
                                                         orientation_setpoint);
          tau_command = tau_feedback + tau_openloop;
        }
        break;
      }

      default:
      {
        ROS_ERROR("Default control mode reached.");
        break;
      }
    }

    geometry_msgs::Wrench msg;
    tf::wrenchEigenToMsg(tau_command, msg);
    wrench_pub.publish(msg);

    ros::spinOnce();
    rate.sleep();
  }
}

void Controller::initSetpoints()
{
  std::vector<double> v;

  if (!nh.getParam("/propulsion/command/wrench/max", v))
    ROS_FATAL("Failed to read parameter max wrench command.");
  Eigen::Vector6d wrench_command_max = Eigen::Vector6d::Map(v.data(), v.size());

  if (!nh.getParam("/propulsion/command/wrench/scaling", v))
    ROS_FATAL("Failed to read parameter scaling wrench command.");
  Eigen::Vector6d wrench_command_scaling = Eigen::Vector6d::Map(v.data(), v.size());

  if (!nh.getParam("/propulsion/command/pose/rate", v))
    ROS_FATAL("Failed to read parameter pose command rate.");
  Eigen::Vector6d pose_command_rate = Eigen::Vector6d::Map(v.data(), v.size());

  setpoints = new Setpoints(wrench_command_scaling,
                            wrench_command_max,
                            pose_command_rate);
}

void Controller::initPositionHoldController()
{
  // Read controller gains from parameter server
  std::map<std::string, double> gains;
  if (!nh.getParam("/controller/gains", gains))
    ROS_FATAL("Failed to read parameter controller gains.");

  // Read center of gravity and buoyancy vectors
  std::vector<double> r_G_vec, r_B_vec;
  if (!nh.getParam("/physical/center_of_mass", r_G_vec))
    ROS_FATAL("Failed to read robot center of mass parameter.");
  if (!nh.getParam("/physical/center_of_buoyancy", r_B_vec))
    ROS_FATAL("Failed to read robot center of buoyancy parameter.");
  Eigen::Vector3d r_G(r_G_vec.data());
  Eigen::Vector3d r_B(r_B_vec.data());

  // Read and calculate ROV weight and buoyancy
  double mass, displacement, acceleration_of_gravity, density_of_water;
  if (!nh.getParam("/physical/mass_kg", mass))
    ROS_FATAL("Failed to read parameter mass.");
  if (!nh.getParam("/physical/displacement_m3", displacement))
    ROS_FATAL("Failed to read parameter displacement.");
  if (!nh.getParam("/gravity/acceleration", acceleration_of_gravity))
    ROS_FATAL("Failed to read parameter acceleration of gravity");
  if (!nh.getParam("/water/density", density_of_water))
    ROS_FATAL("Failed to read parameter density of water");
  double W = mass * acceleration_of_gravity;
  double B = density_of_water * displacement * acceleration_of_gravity;

  position_hold_controller = new QuaternionPdController(gains["a"],
                                                        gains["b"],
                                                        gains["c"],
                                                        W, B, r_G, r_B);
}

bool Controller::healthyMessage(const vortex_msgs::PropulsionCommand& msg)
{
  // Check that motion commands are in range
  for (int i = 0; i < msg.motion.size(); ++i)
  {
    if (msg.motion[i] > 1 || msg.motion[i] < -1)
    {
      ROS_WARN("Motion command out of range.");
      return false;
    }
  }

  // Check that exactly one control mode is requested
  int num_requested_modes = 0;
  for (int i = 0; i < msg.control_mode.size(); ++i)
    if (msg.control_mode[i])
      num_requested_modes++;

  if (num_requested_modes != 1)
  {
    ROS_WARN_STREAM("Invalid control mode. Attempt to set "
                    << num_requested_modes << " control modes at once.");
    return false;
  }

  return true;
}

void Controller::publishControlMode()
{
  std::string s = controlModeString(control_mode);
  std_msgs::String msg;
  msg.data = s;
  mode_pub.publish(msg);
}
<|endoftext|>


<commit_before>/********************************************************************* *\
 * INTEL CORPORATION PROPRIETARY INFORMATION
 * This software is supplied under the terms of a license agreement or
 * nondisclosure agreement with Intel Corporation and may not be copied
 * or disclosed except in accordance with the terms of that agreement.
 * Copyright (C) 2014 Intel Corporation. All Rights Reserved.
 ********************************************************************* */

#include "trianglemesh.h"
#include "../common/model.h"
// embree stuff
#include "embree2/rtcore.h"
#include "embree2/rtcore_scene.h"
#include "embree2/rtcore_geometry.h"
#include "../include/ospray/ospray.h"
// ispc side
#include "trianglemesh_ispc.h"

#define RTC_INVALID_ID RTC_INVALID_GEOMETRY_ID

namespace ospray {
  using std::cout;
  using std::endl;

  TriangleMesh::TriangleMesh()
    : eMesh(RTC_INVALID_ID)
  {
    //    cout << "creating new ispc-side trianglemesh!" << endl;
    this->ispcEquivalent = ispc::TriangleMesh_create(this);
  }

  void TriangleMesh::finalize(Model *model)
  {
    static int numPrints = 0;
    numPrints++;
    if (logLevel > 2)
      if (numPrints == 5)
        cout << "(all future printouts for triangle mesh creation will be emitted)" << endl;

    if (logLevel > 2)
      if (numPrints < 5)
        std::cout << "ospray: finalizing triangle mesh ..." << std::endl;
    Assert((eMesh == RTC_INVALID_ID) && "triangle mesh already built!?");

    Assert(model && "invalid model pointer");

    RTCScene embreeSceneHandle = model->embreeSceneHandle;

    vertexData = getParamData("vertex",getParamData("position"));
    normalData = getParamData("vertex.normal",getParamData("normal"));
    colorData  = getParamData("vertex.color",getParamData("color"));
    texcoordData = getParamData("vertex.texcoord",getParamData("texcoord"));
    indexData  = getParamData("index",getParamData("triangle"));
    prim_materialIDData = getParamData("prim.materialID");
    materialListData = getParamData("materialList");
    geom_materialID = getParam1i("geom.materialID",-1);

    Assert2(vertexData != NULL,
            "triangle mesh geometry does not have either 'position'"
            " or 'vertex' array");
    Assert2(indexData != NULL,
            "triangle mesh geometry does not have either 'index'"
            " or 'triangle' array");

    // PING;
    // PRINT(indexData);
    // PRINT(normalData);
    // PRINT(colorData);
    // PRINT(texcoordData);
    // PRINT(prim_materialIDData);
    // PRINT(materialListData);
    // PRINT(indexData->data);
    // PRINT(vertexData->data);

    this->index = (vec3i*)indexData->data;
    this->vertex = (vec3fa*)vertexData->data;
    this->normal = normalData ? (vec3fa*)normalData->data : NULL;
    this->color  = colorData ? (vec4f*)colorData->data : NULL;
    this->texcoord = texcoordData ? (vec2f*)texcoordData->data : NULL;
    this->prim_materialID  = prim_materialIDData ? (uint32*)prim_materialIDData->data : NULL;
    this->materialList  = materialListData ? (ospray::Material**)materialListData->data : NULL;

    if (materialList) {
      const int num_materials = materialListData->numItems;
      ispcMaterialPtrs = new void*[num_materials];
      for (int i = 0; i < num_materials; i++) {
        this->ispcMaterialPtrs[i] = this->materialList[i]->getIE();
      }
    } else {
      this->ispcMaterialPtrs = NULL;
    }

    size_t numTris  = -1;
    size_t numVerts = -1;
    switch (indexData->type) {
    case OSP_int32:  numTris = indexData->size() / 3; break;
    case OSP_uint32: numTris = indexData->size() / 3; break;
    case OSP_vec3i:  numTris = indexData->size(); break;
    case OSP_vec3ui: numTris = indexData->size(); break;
    default:
      throw std::runtime_error("unsupported trianglemesh.index data type");
    }
    switch (vertexData->type) {
    case OSP_float:   numVerts = vertexData->size() / 4; break;
    case OSP_vec3fa:  numVerts = vertexData->size(); break;
    default:
      throw std::runtime_error("unsupported trianglemesh.vertex data type");
    }

    eMesh = rtcNewTriangleMesh(embreeSceneHandle,RTC_GEOMETRY_STATIC,
                               numTris,numVerts);
    rtcSetBuffer(embreeSceneHandle,eMesh,RTC_VERTEX_BUFFER,
                 (void*)this->vertex,0,
                 ospray::sizeOf(vertexData->type));
    rtcSetBuffer(embreeSceneHandle,eMesh,RTC_INDEX_BUFFER,
                 (void*)this->index,0,
                 ospray::sizeOf(indexData->type));

    box3f bounds = embree::empty;

    for (int i=0;i<vertexData->size();i++)
      bounds.extend(vertex[i]);

    if (logLevel > 2)
      if (numPrints < 5) {
        cout << "  created triangle mesh (" << numTris << " tris "
             << ", " << numVerts << " vertices)" << endl;
        cout << "  mesh bounds " << bounds << endl;
      }
    rtcEnable(model->embreeSceneHandle,eMesh);

    ispc::TriangleMesh_set(getIE(),model->getIE(),eMesh,
                           numTris,
                           (ispc::vec3i*)index,
                           (ispc::vec3fa*)vertex,
                           (ispc::vec3fa*)normal,
                           (ispc::vec4f*)color,
                           (ispc::vec2f*)texcoord,
                           geom_materialID,
                           ispcMaterialPtrs,
                           (uint32*)prim_materialID);
  }

  //! helper fct that creates a tessllated unit arrow
  /*! this function creates a tessllated 'unit' arrow, where 'unit'
    means itreaches from Z=-1 to Z=+1. With of arrow head and
    arrow body are given as parameters, as it the number of
    segments for tessellating. The total number of triangles from
    this arrow is 'numSegments*5'. */
  ospray::TriangleMesh *makeArrow(int numSegments,
                                  float headWidth,
                                  float bodyWidth,
                                  float headLength)
  {
    std::vector<vec3fa> vtx;
    std::vector<vec3i>  idx;

    // tail ring
    int tailCenter = vtx.size();
    vtx.push_back(vec3fa(0,0,-1.f));
    int tailRingStart = vtx.size();
    for (int i=0;i<numSegments;i++) {
      const float u = cosf(i*(2.f*M_PI/numSegments));
      const float v = sinf(i*(2.f*M_PI/numSegments));
      vtx.push_back(vec3fa(u*bodyWidth,v*bodyWidth,-1.f));
      idx.push_back(vec3i(tailCenter,
                          tailRingStart+i,
                          tailRingStart+((i+1)%numSegments)));
    }
#if 1
    // body
    int bodyRingStart = vtx.size();
    for (int i=0;i<numSegments;i++) {
      const float u = cosf(i*(2.f*M_PI/numSegments));
      const float v = sinf(i*(2.f*M_PI/numSegments));
      vtx.push_back(vec3fa(u*bodyWidth,v*bodyWidth,+1.f-headLength));
      int a = tailRingStart+i;
      int b = bodyRingStart+i;
      int c = tailRingStart+(i+1)%numSegments;
      int d = bodyRingStart+(i+1)%numSegments;
      idx.push_back(vec3i(a,b,c));
      idx.push_back(vec3i(b,c,d));
    }

    // tip
    int tipTop = vtx.size();
    vtx.push_back(vec3fa(0,0,+1.f));
    int tipMid = vtx.size();
    vtx.push_back(vec3fa(0,0,+1.f-headLength));
    int tipRingStart = vtx.size();
    for (int i=0;i<numSegments;i++) {
      const float u = cosf(i*(2.f*M_PI/numSegments));
      const float v = sinf(i*(2.f*M_PI/numSegments));
      vtx.push_back(vec3fa(u*headWidth,v*headWidth,+1.f-headLength));
      int a = tipRingStart+i;
      int b = tipRingStart+(i+1)%numSegments;
      idx.push_back(vec3i(a,b,tipTop));
      idx.push_back(vec3i(a,b,tipMid));
    }
#endif

    ospray::TriangleMesh *mesh = new TriangleMesh;
    mesh->findParam("index",1)->set(new Data(idx.size(),OSP_vec3i,&idx[0],0));
    mesh->findParam("vertex",1)->set(new Data(vtx.size(),OSP_vec3fa,&vtx[0],0));
    // mesh->commit();
    return mesh;
  }
}
<commit_msg>pushing version to help debugging<commit_after>/********************************************************************* *\
 * INTEL CORPORATION PROPRIETARY INFORMATION
 * This software is supplied under the terms of a license agreement or
 * nondisclosure agreement with Intel Corporation and may not be copied
 * or disclosed except in accordance with the terms of that agreement.
 * Copyright (C) 2014 Intel Corporation. All Rights Reserved.
 ********************************************************************* */

#include "trianglemesh.h"
#include "../common/model.h"
// embree stuff
#include "embree2/rtcore.h"
#include "embree2/rtcore_scene.h"
#include "embree2/rtcore_geometry.h"
#include "../include/ospray/ospray.h"
// ispc side
#include "trianglemesh_ispc.h"

#define RTC_INVALID_ID RTC_INVALID_GEOMETRY_ID

namespace ospray {
  using std::cout;
  using std::endl;

  TriangleMesh::TriangleMesh()
    : eMesh(RTC_INVALID_ID)
  {
    //    cout << "creating new ispc-side trianglemesh!" << endl;
    this->ispcEquivalent = ispc::TriangleMesh_create(this);
  }

  void TriangleMesh::finalize(Model *model)
  {
    static int numPrints = 0;
    numPrints++;
    if (logLevel > 2)
      if (numPrints == 5)
        cout << "(all future printouts for triangle mesh creation will be emitted)" << endl;

    if (logLevel > 2)
      if (numPrints < 5)
        std::cout << "ospray: finalizing triangle mesh ..." << std::endl;
    Assert((eMesh == RTC_INVALID_ID) && "triangle mesh already built!?");

    Assert(model && "invalid model pointer");

    RTCScene embreeSceneHandle = model->embreeSceneHandle;

    vertexData = getParamData("vertex",getParamData("position"));
    normalData = getParamData("vertex.normal",getParamData("normal"));
    colorData  = getParamData("vertex.color",getParamData("color"));
    texcoordData = getParamData("vertex.texcoord",getParamData("texcoord"));
    indexData  = getParamData("index",getParamData("triangle"));
    prim_materialIDData = getParamData("prim.materialID");
    materialListData = getParamData("materialList");
    geom_materialID = getParam1i("geom.materialID",-1);

    Assert2(vertexData != NULL,
            "triangle mesh geometry does not have either 'position'"
            " or 'vertex' array");
    Assert2(indexData != NULL,
            "triangle mesh geometry does not have either 'index'"
            " or 'triangle' array");

    // PING;
    // PRINT(indexData);
    // PRINT(normalData);
    // PRINT(colorData);
    // PRINT(texcoordData);
    // PRINT(prim_materialIDData);
    // PRINT(materialListData);
    // PRINT(indexData->data);
    // PRINT(vertexData->data);

    this->index = (vec3i*)indexData->data;
    this->vertex = (vec3fa*)vertexData->data;
    this->normal = normalData ? (vec3fa*)normalData->data : NULL;
    this->color  = colorData ? (vec4f*)colorData->data : NULL;
    this->texcoord = texcoordData ? (vec2f*)texcoordData->data : NULL;
    this->prim_materialID  = prim_materialIDData ? (uint32*)prim_materialIDData->data : NULL;
    this->materialList  = materialListData ? (ospray::Material**)materialListData->data : NULL;

    if (materialList) {
      const int num_materials = materialListData->numItems;
      ispcMaterialPtrs = new void*[num_materials];
      for (int i = 0; i < num_materials; i++) {
        this->ispcMaterialPtrs[i] = this->materialList[i]->getIE();
      }
    } else {
      this->ispcMaterialPtrs = NULL;
    }

    size_t numTris  = -1;
    size_t numVerts = -1;
    switch (indexData->type) {
    case OSP_int32:  numTris = indexData->size() / 3; break;
    case OSP_uint32: numTris = indexData->size() / 3; break;
    case OSP_vec3i:  numTris = indexData->size(); break;
    case OSP_vec3ui: numTris = indexData->size(); break;
    default:
      throw std::runtime_error("unsupported trianglemesh.index data type");
    }
    switch (vertexData->type) {
    case OSP_float:   numVerts = vertexData->size() / 4; break;
    case OSP_vec3fa:  numVerts = vertexData->size(); break;
    default:
      throw std::runtime_error("unsupported trianglemesh.vertex data type");
    }

    eMesh = rtcNewTriangleMesh(embreeSceneHandle,RTC_GEOMETRY_STATIC,
                               numTris,numVerts);
    rtcSetBuffer(embreeSceneHandle,eMesh,RTC_VERTEX_BUFFER,
                 (void*)this->vertex,0,
                 ospray::sizeOf(vertexData->type));
    rtcSetBuffer(embreeSceneHandle,eMesh,RTC_INDEX_BUFFER,
                 (void*)this->index,0,
                 ospray::sizeOf(indexData->type));

    box3f bounds = embree::empty;

    for (int i=0;i<vertexData->size();i++)
      bounds.extend(vertex[i]);

    if (logLevel > 2)
      if (numPrints < 5) {
        cout << "  created triangle mesh (" << numTris << " tris "
             << ", " << numVerts << " vertices)" << endl;
        cout << "  mesh bounds " << bounds << endl;
      }
    // rtcEnable(model->embreeSceneHandle,eMesh);

    ispc::TriangleMesh_set(getIE(),model->getIE(),eMesh,
                           numTris,
                           (ispc::vec3i*)index,
                           (ispc::vec3fa*)vertex,
                           (ispc::vec3fa*)normal,
                           (ispc::vec4f*)color,
                           (ispc::vec2f*)texcoord,
                           geom_materialID,
                           ispcMaterialPtrs,
                           (uint32*)prim_materialID);
  }

  //! helper fct that creates a tessllated unit arrow
  /*! this function creates a tessllated 'unit' arrow, where 'unit'
    means itreaches from Z=-1 to Z=+1. With of arrow head and
    arrow body are given as parameters, as it the number of
    segments for tessellating. The total number of triangles from
    this arrow is 'numSegments*5'. */
  ospray::TriangleMesh *makeArrow(int numSegments,
                                  float headWidth,
                                  float bodyWidth,
                                  float headLength)
  {
    std::vector<vec3fa> vtx;
    std::vector<vec3i>  idx;

    // tail ring
    int tailCenter = vtx.size();
    vtx.push_back(vec3fa(0,0,-1.f));
    int tailRingStart = vtx.size();
    for (int i=0;i<numSegments;i++) {
      const float u = cosf(i*(2.f*M_PI/numSegments));
      const float v = sinf(i*(2.f*M_PI/numSegments));
      vtx.push_back(vec3fa(u*bodyWidth,v*bodyWidth,-1.f));
      idx.push_back(vec3i(tailCenter,
                          tailRingStart+i,
                          tailRingStart+((i+1)%numSegments)));
    }
#if 1
    // body
    int bodyRingStart = vtx.size();
    for (int i=0;i<numSegments;i++) {
      const float u = cosf(i*(2.f*M_PI/numSegments));
      const float v = sinf(i*(2.f*M_PI/numSegments));
      vtx.push_back(vec3fa(u*bodyWidth,v*bodyWidth,+1.f-headLength));
      int a = tailRingStart+i;
      int b = bodyRingStart+i;
      int c = tailRingStart+(i+1)%numSegments;
      int d = bodyRingStart+(i+1)%numSegments;
      idx.push_back(vec3i(a,b,c));
      idx.push_back(vec3i(b,c,d));
    }

    // tip
    int tipTop = vtx.size();
    vtx.push_back(vec3fa(0,0,+1.f));
    int tipMid = vtx.size();
    vtx.push_back(vec3fa(0,0,+1.f-headLength));
    int tipRingStart = vtx.size();
    for (int i=0;i<numSegments;i++) {
      const float u = cosf(i*(2.f*M_PI/numSegments));
      const float v = sinf(i*(2.f*M_PI/numSegments));
      vtx.push_back(vec3fa(u*headWidth,v*headWidth,+1.f-headLength));
      int a = tipRingStart+i;
      int b = tipRingStart+(i+1)%numSegments;
      idx.push_back(vec3i(a,b,tipTop));
      idx.push_back(vec3i(a,b,tipMid));
    }
#endif

    ospray::TriangleMesh *mesh = new TriangleMesh;
    mesh->findParam("index",1)->set(new Data(idx.size(),OSP_vec3i,&idx[0],0));
    mesh->findParam("vertex",1)->set(new Data(vtx.size(),OSP_vec3fa,&vtx[0],0));
    // mesh->commit();
    return mesh;
  }
}
<|endoftext|>