<commit_before>// Copyright  (C)  2007  Ruben Smits <ruben dot smits at mech dot kuleuven dot be>

// Version: 1.0
// Author: Ruben Smits <ruben dot smits at mech dot kuleuven dot be>
// Maintainer: Ruben Smits <ruben dot smits at mech dot kuleuven dot be>
// URL: http://www.orocos.org/kdl

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

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

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

#ifndef KDL_TREE_HPP
#define KDL_TREE_HPP

#include "config.h"

#include "segment.hpp"
#include "chain.hpp"

#include <string>
#include <map>

#ifdef KDL_USE_NEW_TREE_INTERFACE
#include <boost/shared_ptr.hpp>
#endif //#ifdef KDL_USE_NEW_TREE_INTERFACE

namespace KDL
{
    class TreeElement;

#ifdef KDL_USE_NEW_TREE_INTERFACE
    //We use smart pointers for managing tree nodes for now becuase
    //c++11 and unique_ptr support is not ubiquitous
    typedef boost::shared_ptr<TreeElement> TreeElementPtr;
    typedef boost::shared_ptr<const TreeElement> TreeElementConstPtr;
    typedef std::map<std::string, TreeElementPtr> SegmentMap;
    typedef TreeElementPtr TreeElementType;

#define GetTreeElementChildren(tree_element) (tree_element)->children
#define GetTreeElementParent(tree_element) (tree_element)->parent
#define GetTreeElementQNr(tree_element) (tree_element)->q_nr
#define GetTreeElementSegment(tree_element) (tree_element)->segment

#else //#ifdef KDL_USE_NEW_TREE_INTERFACE
    //Forward declaration
    typedef std::map<std::string,TreeElement> SegmentMap;
    typedef TreeElement TreeElementType;

#define GetTreeElementChildren(tree_element) (tree_element).children
#define GetTreeElementParent(tree_element) (tree_element).parent
#define GetTreeElementQNr(tree_element) (tree_element).q_nr
#define GetTreeElementSegment(tree_element) (tree_element).segment

#endif //#ifdef KDL_USE_NEW_TREE_INTERFACE

    class TreeElement
    {
    public:
        TreeElement(const Segment& segment_in,const SegmentMap::const_iterator& parent_in,unsigned int q_nr_in):
            segment(segment_in),
            q_nr(q_nr_in),
            parent(parent_in)
        {}

        static TreeElementType Root(const std::string& root_name)
        {
#ifdef KDL_USE_NEW_TREE_INTERFACE
            return TreeElementType(new TreeElement(root_name));
#else //#define KDL_USE_NEW_TREE_INTERFACE
            return TreeElementType(root_name);
#endif
        }

        Segment segment;
        unsigned int q_nr;
        SegmentMap::const_iterator  parent;
        std::vector<SegmentMap::const_iterator > children;

    private:
        TreeElement(const std::string& name):segment(name), q_nr(0) {}
    };

    /**
     * \brief  This class encapsulates a tree
     * kinematic interconnection structure. It is build out of segments.
     *
     * @ingroup KinematicFamily
     */
    class Tree
    {
    private:
        SegmentMap segments;
        unsigned int nrOfJoints;
        unsigned int nrOfSegments;

        std::string root_name;

        bool addTreeRecursive(SegmentMap::const_iterator root, const std::string& hook_name);

    public:
        /**
         * The constructor of a tree, a new tree is always empty
         */
        explicit Tree(const std::string& root_name="root");
        Tree(const Tree& in);
        Tree& operator= (const Tree& arg);

        /**
         * Adds a new segment to the end of the segment with
         * hook_name as segment_name
         *
         * @param segment new segment to add
         * @param hook_name name of the segment to connect this
         * segment with.
         *
         * @return false if hook_name could not be found.
         */
         bool addSegment(const Segment& segment, const std::string& hook_name);

        /**
         * Adds a complete chain to the end of the segment with
         * hook_name as segment_name.
         *
         * @param hook_name name of the segment to connect the chain with.
         *
         * @return false if hook_name could not be found.
         */
        bool addChain(const Chain& chain, const std::string& hook_name);

        /**
         * Adds a complete tree to the end of the segment with
         * hookname as segment_name.
         *
         * @param tree Tree to add
         * @param hook_name name of the segment to connect the tree with
         *
         * @return false if hook_name could not be found
         */
        bool addTree(const Tree& tree, const std::string& hook_name);

        /**
         * Request the total number of joints in the tree.\n
         *  Important: It is not the same as the
         * total number of segments since a segment does not need to have
         * a joint.
         *
         * @return total nr of joints
         */
        unsigned int getNrOfJoints()const
        {
            return nrOfJoints;
        };

        /**
         * Request the total number of segments in the tree.
         * @return total number of segments
         */
        unsigned int getNrOfSegments()const {return nrOfSegments;};

        /**
         * Request the segment of the tree with name segment_name.
         *
         * @param segment_name the name of the requested segment
         *
         * @return constant iterator pointing to the requested segment
         */
        SegmentMap::const_iterator getSegment(const std::string& segment_name)const
        {
            return segments.find(segment_name);
        };
        /**
         * Request the root segment of the tree
         *
         * @return constant iterator pointing to the root segment
         */
        SegmentMap::const_iterator getRootSegment()const
        {
          return segments.find(root_name);
        };

        /**
         * Request the chain of the tree between chain_root and chain_tip.  The chain_root
         * and chain_tip can be in different branches of the tree, the chain_root can be
         * an ancestor of chain_tip, and chain_tip can be an ancestor of chain_root.
         *
         * @param chain_root the name of the root segment of the chain
         * @param chain_tip the name of the tip segment of the chain
         * @param chain the resulting chain
         *
         * @return success or failure
         */
      bool getChain(const std::string& chain_root, const std::string& chain_tip, Chain& chain)const;

        const SegmentMap& getSegments()const
        {
            return segments;
        }

        virtual ~Tree(){};

    };
}
#endif

<commit_msg>+ fix build failure of Robot module when using occ<commit_after>// Copyright  (C)  2007  Ruben Smits <ruben dot smits at mech dot kuleuven dot be>

// Version: 1.0
// Author: Ruben Smits <ruben dot smits at mech dot kuleuven dot be>
// Maintainer: Ruben Smits <ruben dot smits at mech dot kuleuven dot be>
// URL: http://www.orocos.org/kdl

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

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

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

#ifndef KDL_TREE_HPP
#define KDL_TREE_HPP

// This file comes along with oce but not with occ.
//#include "config.h"

#include "segment.hpp"
#include "chain.hpp"

#include <string>
#include <map>

#ifdef KDL_USE_NEW_TREE_INTERFACE
#include <boost/shared_ptr.hpp>
#endif //#ifdef KDL_USE_NEW_TREE_INTERFACE

namespace KDL
{
    class TreeElement;

#ifdef KDL_USE_NEW_TREE_INTERFACE
    //We use smart pointers for managing tree nodes for now becuase
    //c++11 and unique_ptr support is not ubiquitous
    typedef boost::shared_ptr<TreeElement> TreeElementPtr;
    typedef boost::shared_ptr<const TreeElement> TreeElementConstPtr;
    typedef std::map<std::string, TreeElementPtr> SegmentMap;
    typedef TreeElementPtr TreeElementType;

#define GetTreeElementChildren(tree_element) (tree_element)->children
#define GetTreeElementParent(tree_element) (tree_element)->parent
#define GetTreeElementQNr(tree_element) (tree_element)->q_nr
#define GetTreeElementSegment(tree_element) (tree_element)->segment

#else //#ifdef KDL_USE_NEW_TREE_INTERFACE
    //Forward declaration
    typedef std::map<std::string,TreeElement> SegmentMap;
    typedef TreeElement TreeElementType;

#define GetTreeElementChildren(tree_element) (tree_element).children
#define GetTreeElementParent(tree_element) (tree_element).parent
#define GetTreeElementQNr(tree_element) (tree_element).q_nr
#define GetTreeElementSegment(tree_element) (tree_element).segment

#endif //#ifdef KDL_USE_NEW_TREE_INTERFACE

    class TreeElement
    {
    public:
        TreeElement(const Segment& segment_in,const SegmentMap::const_iterator& parent_in,unsigned int q_nr_in):
            segment(segment_in),
            q_nr(q_nr_in),
            parent(parent_in)
        {}

        static TreeElementType Root(const std::string& root_name)
        {
#ifdef KDL_USE_NEW_TREE_INTERFACE
            return TreeElementType(new TreeElement(root_name));
#else //#define KDL_USE_NEW_TREE_INTERFACE
            return TreeElementType(root_name);
#endif
        }

        Segment segment;
        unsigned int q_nr;
        SegmentMap::const_iterator  parent;
        std::vector<SegmentMap::const_iterator > children;

    private:
        TreeElement(const std::string& name):segment(name), q_nr(0) {}
    };

    /**
     * \brief  This class encapsulates a tree
     * kinematic interconnection structure. It is build out of segments.
     *
     * @ingroup KinematicFamily
     */
    class Tree
    {
    private:
        SegmentMap segments;
        unsigned int nrOfJoints;
        unsigned int nrOfSegments;

        std::string root_name;

        bool addTreeRecursive(SegmentMap::const_iterator root, const std::string& hook_name);

    public:
        /**
         * The constructor of a tree, a new tree is always empty
         */
        explicit Tree(const std::string& root_name="root");
        Tree(const Tree& in);
        Tree& operator= (const Tree& arg);

        /**
         * Adds a new segment to the end of the segment with
         * hook_name as segment_name
         *
         * @param segment new segment to add
         * @param hook_name name of the segment to connect this
         * segment with.
         *
         * @return false if hook_name could not be found.
         */
         bool addSegment(const Segment& segment, const std::string& hook_name);

        /**
         * Adds a complete chain to the end of the segment with
         * hook_name as segment_name.
         *
         * @param hook_name name of the segment to connect the chain with.
         *
         * @return false if hook_name could not be found.
         */
        bool addChain(const Chain& chain, const std::string& hook_name);

        /**
         * Adds a complete tree to the end of the segment with
         * hookname as segment_name.
         *
         * @param tree Tree to add
         * @param hook_name name of the segment to connect the tree with
         *
         * @return false if hook_name could not be found
         */
        bool addTree(const Tree& tree, const std::string& hook_name);

        /**
         * Request the total number of joints in the tree.\n
         *  Important: It is not the same as the
         * total number of segments since a segment does not need to have
         * a joint.
         *
         * @return total nr of joints
         */
        unsigned int getNrOfJoints()const
        {
            return nrOfJoints;
        };

        /**
         * Request the total number of segments in the tree.
         * @return total number of segments
         */
        unsigned int getNrOfSegments()const {return nrOfSegments;};

        /**
         * Request the segment of the tree with name segment_name.
         *
         * @param segment_name the name of the requested segment
         *
         * @return constant iterator pointing to the requested segment
         */
        SegmentMap::const_iterator getSegment(const std::string& segment_name)const
        {
            return segments.find(segment_name);
        };
        /**
         * Request the root segment of the tree
         *
         * @return constant iterator pointing to the root segment
         */
        SegmentMap::const_iterator getRootSegment()const
        {
          return segments.find(root_name);
        };

        /**
         * Request the chain of the tree between chain_root and chain_tip.  The chain_root
         * and chain_tip can be in different branches of the tree, the chain_root can be
         * an ancestor of chain_tip, and chain_tip can be an ancestor of chain_root.
         *
         * @param chain_root the name of the root segment of the chain
         * @param chain_tip the name of the tip segment of the chain
         * @param chain the resulting chain
         *
         * @return success or failure
         */
      bool getChain(const std::string& chain_root, const std::string& chain_tip, Chain& chain)const;

        const SegmentMap& getSegments()const
        {
            return segments;
        }

        virtual ~Tree(){};

    };
}
#endif

<|endoftext|>


<commit_before>//===--- Task.cpp - Task object and management ----------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Object management routines for asynchronous task objects.
//
//===----------------------------------------------------------------------===//

#include "swift/Runtime/Concurrency.h"
#include "swift/ABI/Task.h"
#include "swift/ABI/Metadata.h"
#include "swift/Runtime/HeapObject.h"
#include "TaskPrivate.h"

using namespace swift;

SWIFT_CC(swift)
static void destroySimpleTask(SWIFT_CONTEXT HeapObject *_obj) {
  auto obj = static_cast<AsyncTask*>(_obj);

  assert(!obj->isFuture());

  // The task execution itself should always hold a reference to it, so
  // if we get here, we know the task has finished running, which means
  // swift_task_complete should have been run, which will have torn down
  // the task-local allocator.  There's actually nothing else to clean up
  // here.

  free(obj);
}

/// Heap metadata for a simple asynchronous task that does not
/// include a future.
static FullMetadata<HeapMetadata> simpleTaskHeapMetadata = {
  {
    {
      &destroySimpleTask
    },
    {
      /*value witness table*/ nullptr
    }
  },
  {
    MetadataKind::SimpleTask
  }
};

/// The function that we put in the context of a simple task
/// (one with no future) to handle the final return.
SWIFT_CC(swift)
static void completeTask(AsyncTask *task, ExecutorRef executor,
                         AsyncContext *context) {
  // Tear down the task-local allocator immediately; there's no need
  // to wait for the object to be destroyed.
  _swift_task_alloc_destroy(task);

  // TODO: set something in the status?
  // TODO: notify the parent somehow?
  // TODO: remove this task from the child-task chain?
  // TODO: notify tasks waiting on the future?

  // Release the task, balancing the retain that a running task
  // has on itself.
  swift_release(task);
}

AsyncTaskAndContext
swift::swift_task_create(JobFlags flags, AsyncTask *parent,
                         const AsyncFunctionPointer<void()> *function) {
  return swift_task_create_f(flags, parent, function->Function.get(),
                             function->ExpectedContextSize);
}

AsyncTaskAndContext
swift::swift_task_create_f(JobFlags flags, AsyncTask *parent,
                           AsyncFunctionType<void()> *function,
                           size_t initialContextSize) {
  assert(!flags.task_isFuture() && "function doesn't support creating futures");
  assert((parent != nullptr) == flags.task_isChildTask());

  // Figure out the size of the header.
  size_t headerSize = sizeof(AsyncTask);
  if (parent) headerSize += sizeof(AsyncTask::ChildFragment);

  // Allocate the initial context together with the job.
  // This means that we never get rid of this allocation.
  size_t amountToAllocate = headerSize + initialContextSize;

  // TODO: if this is necessary we need to teach LLVM lowering to request async
  // context sizes that are mulitple of that maximum alignment.
  // For now disable this assert.
  // assert(amountToAllocate % MaximumAlignment == 0);

  void *allocation = malloc(amountToAllocate);

  AsyncContext *initialContext =
    reinterpret_cast<AsyncContext*>(
      reinterpret_cast<char*>(allocation) + headerSize);

  // Initialize the task so that resuming it will run the given
  // function on the initial context.
  AsyncTask *task =
    new(allocation) AsyncTask(&simpleTaskHeapMetadata, flags,
                              function, initialContext);

  // Initialize the child fragment if applicable.
  // TODO: propagate information from the parent?
  if (parent) {
    auto childFragment = task->childFragment();
    new (childFragment) AsyncTask::ChildFragment(parent);
  }

  // Configure the initial context.
  //
  // FIXME: if we store a null pointer here using the standard ABI for
  // signed null pointers, then we'll have to authenticate context pointers
  // as if they might be null, even though the only time they ever might
  // be is the final hop.  Store a signed null instead.
  initialContext->Parent = nullptr;
  initialContext->ResumeParent = &completeTask;
  initialContext->ResumeParentExecutor = ExecutorRef::noPreference();
  initialContext->Flags = AsyncContextKind::Ordinary;
  initialContext->Flags.setShouldNotDeallocateInCallee(true);

  // Initialize the task-local allocator.
  _swift_task_alloc_initialize(task);

  return {task, initialContext};
}

// TODO: Remove this hack.
void swift::swift_task_run(AsyncTask *taskToRun) {
  taskToRun->run(ExecutorRef::noPreference());
}
<commit_msg>Revert "Silence an assert"<commit_after>//===--- Task.cpp - Task object and management ----------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Object management routines for asynchronous task objects.
//
//===----------------------------------------------------------------------===//

#include "swift/Runtime/Concurrency.h"
#include "swift/ABI/Task.h"
#include "swift/ABI/Metadata.h"
#include "swift/Runtime/HeapObject.h"
#include "TaskPrivate.h"

using namespace swift;

SWIFT_CC(swift)
static void destroySimpleTask(SWIFT_CONTEXT HeapObject *_obj) {
  auto obj = static_cast<AsyncTask*>(_obj);

  assert(!obj->isFuture());

  // The task execution itself should always hold a reference to it, so
  // if we get here, we know the task has finished running, which means
  // swift_task_complete should have been run, which will have torn down
  // the task-local allocator.  There's actually nothing else to clean up
  // here.

  free(obj);
}

/// Heap metadata for a simple asynchronous task that does not
/// include a future.
static FullMetadata<HeapMetadata> simpleTaskHeapMetadata = {
  {
    {
      &destroySimpleTask
    },
    {
      /*value witness table*/ nullptr
    }
  },
  {
    MetadataKind::SimpleTask
  }
};

/// The function that we put in the context of a simple task
/// (one with no future) to handle the final return.
SWIFT_CC(swift)
static void completeTask(AsyncTask *task, ExecutorRef executor,
                         AsyncContext *context) {
  // Tear down the task-local allocator immediately; there's no need
  // to wait for the object to be destroyed.
  _swift_task_alloc_destroy(task);

  // TODO: set something in the status?
  // TODO: notify the parent somehow?
  // TODO: remove this task from the child-task chain?
  // TODO: notify tasks waiting on the future?

  // Release the task, balancing the retain that a running task
  // has on itself.
  swift_release(task);
}

AsyncTaskAndContext
swift::swift_task_create(JobFlags flags, AsyncTask *parent,
                         const AsyncFunctionPointer<void()> *function) {
  return swift_task_create_f(flags, parent, function->Function.get(),
                             function->ExpectedContextSize);
}

AsyncTaskAndContext
swift::swift_task_create_f(JobFlags flags, AsyncTask *parent,
                           AsyncFunctionType<void()> *function,
                           size_t initialContextSize) {
  assert(!flags.task_isFuture() && "function doesn't support creating futures");
  assert((parent != nullptr) == flags.task_isChildTask());

  // Figure out the size of the header.
  size_t headerSize = sizeof(AsyncTask);
  if (parent) headerSize += sizeof(AsyncTask::ChildFragment);

  // Allocate the initial context together with the job.
  // This means that we never get rid of this allocation.
  size_t amountToAllocate = headerSize + initialContextSize;

  assert(amountToAllocate % MaximumAlignment == 0);

  void *allocation = malloc(amountToAllocate);

  AsyncContext *initialContext =
    reinterpret_cast<AsyncContext*>(
      reinterpret_cast<char*>(allocation) + headerSize);

  // Initialize the task so that resuming it will run the given
  // function on the initial context.
  AsyncTask *task =
    new(allocation) AsyncTask(&simpleTaskHeapMetadata, flags,
                              function, initialContext);

  // Initialize the child fragment if applicable.
  // TODO: propagate information from the parent?
  if (parent) {
    auto childFragment = task->childFragment();
    new (childFragment) AsyncTask::ChildFragment(parent);
  }

  // Configure the initial context.
  //
  // FIXME: if we store a null pointer here using the standard ABI for
  // signed null pointers, then we'll have to authenticate context pointers
  // as if they might be null, even though the only time they ever might
  // be is the final hop.  Store a signed null instead.
  initialContext->Parent = nullptr;
  initialContext->ResumeParent = &completeTask;
  initialContext->ResumeParentExecutor = ExecutorRef::noPreference();
  initialContext->Flags = AsyncContextKind::Ordinary;
  initialContext->Flags.setShouldNotDeallocateInCallee(true);

  // Initialize the task-local allocator.
  _swift_task_alloc_initialize(task);

  return {task, initialContext};
}

// TODO: Remove this hack.
void swift::swift_task_run(AsyncTask *taskToRun) {
  taskToRun->run(ExecutorRef::noPreference());
}
<|endoftext|>


<commit_before>#include "gtest/gtest.h"

#include <iostream> // TODO: remove.
#include <sstream>

#include "Allocator.h"
#include "QueryParser.h"

namespace BitFunnel
{
    TEST(QueryParser, TODO)
    {
        Allocator allocator(512);
        std::stringstream s;

        s << "wat";
        QueryParser wat(s, allocator);

        auto watResult = wat.Parse();
        std::cout << watResult << std::endl;
    }
}
<commit_msg>WIP: output TermMatchNode.<commit_after>#include "gtest/gtest.h"

#include <iostream> // TODO: remove.
#include <sstream>

#include "Allocator.h"
#include "BitFunnel/TermMatchNode.h"
#include "QueryParser.h"
#include "TextObjectFormatter.h"

namespace BitFunnel
{
    void TodoFnName()
    {

    }

    TEST(QueryParser, TODO)
    {
        Allocator allocator(512);
        std::stringstream s;

        s << "wat";
        QueryParser wat(s, allocator);

        auto watResult = wat.Parse();
        ASSERT_NE(nullptr, watResult);

        std::stringstream output;
        TextObjectFormatter formatter(output);
        watResult->Format(formatter);

        std::cout << output.str() << std::endl;
    }
}
<|endoftext|>


<commit_before>
#include "AConfig.h"
#if(HAS_STD_PILOT)
#include "Device.h"
#include "Pin.h"
#include "Pilot.h"
#include "Timer.h"

Timer pilotTimer;
bool _headingHoldEnabled = false;
int  _headingHoldTarget = 0;
int hdg = 0;
int hdg_Error;
int raw_Left, raw_Right;
int left, right;  // motor outputs in microseconds, +/-500
int loop_Gain = 1;
int integral_Divisor = 100;
long hdg_Error_Integral = 0;
int tgt_Hdg = 0;
bool _depthHoldEnabled = false;
int _depthHoldTarget = 0;
int depth = 0;
int depth_Error = 0;
int raw_lift =0;
int lift = 0;
int target_depth;
int raw_yaw, yaw;

void Pilot::device_setup(){
  pilotTimer.reset();
  Serial.println(F("log:pilot setup complete;"));
}

void Pilot::device_loop(Command command){
//intended to respond to fly by wire commands: MaintainHeading(); TurnTo(compassheading); DiveTo(depth);
    if( command.cmp("holdHeading_toggle")){
      if (_headingHoldEnabled) {
        _headingHoldEnabled = false;
        raw_Left = 0;
        raw_Right = 0;
        hdg_Error_Integral = 0;  // Reset error integrator
        tgt_Hdg = -500;  // -500 = system not in hdg hold

        int argsToSend[] = {1,00}; //include number of parms as last parm
        command.pushCommand("yaw",argsToSend);
        Serial.println(F("log:heading_hold_disabled;"));

      } else {
        _headingHoldEnabled = true;
        if(command.args[0]==0){
          _headingHoldTarget = navdata::HDGD;
        } else {
          _headingHoldTarget = command.args[1];
        }
        tgt_Hdg = _headingHoldTarget;
        Serial.print(F("log:heading_hold_enabled on="));
        Serial.print(tgt_Hdg);
        Serial.println(';');
      }
      Serial.print(F("targetHeading:"));
      if (_headingHoldEnabled) {
        Serial.print(tgt_Hdg);
      } else {
        Serial.print(DISAABLED);
      }
      Serial.println(';');
    }

    if( command.cmp("holdDepth_toggle")){
      if (_depthHoldEnabled) {
        _depthHoldEnabled = false;
        raw_lift = 0;
        target_depth = 0;

        int argsToSend[] = {1,0}; //include number of parms as last parm
        command.pushCommand("lift",argsToSend);
        Serial.println(F("log:depth_hold_disabled;"));

      } else {
        _depthHoldEnabled = true;
        if(command.args[0]==0){
          _depthHoldTarget = navdata::DEAP*100;  //casting to cm
        } else {
          _depthHoldTarget = command.args[1];
        }
        target_depth = _depthHoldTarget;
        Serial.print(F("log:depth_hold_enabled on="));
        Serial.print(target_depth);
        Serial.println(';');
      }
      Serial.print(F("targetDepth:"));
      if (_depthHoldEnabled) {
        Serial.print(target_depth);
      } else {
        Serial.pitnt(DISABLED);
      }
      Serial.println(';');
    }

    if (pilotTimer.elapsed (50)) {

      // Autopilot Test #3 6 Jan 2014
      // Hold vehicle at arbitrary heading
      // Integer math; proportional control plus basic integrator
      // No hysteresis around 180 degree error

      // Check whether hold mode is on

      if (_depthHoldEnabled)
      {
        depth = navdata::DEAP*100;
        depth_Error = target_depth-depth;  //positive error = positive lift = go deaper.

        raw_lift = depth_Error * loop_Gain;
        lift = constrain(raw_lift, -50, 50);

        Serial.println(F("log:dhold pushing command;"));
        Serial.print(F("dp_er:"));
        Serial.print(depth_Error);
        Serial.println(';');
        int argsToSend[] = {1,lift}; //include number of parms as last parm
        command.pushCommand("lift",argsToSend);

      }

      if (_headingHoldEnabled)
      {

        // Code for hold mode here
        hdg = navdata::HDGD;

        // Calculate heading error

        hdg_Error = hdg - tgt_Hdg;

        if (hdg_Error > 180)
        {
        hdg_Error = hdg_Error - 360;
        }

        if (hdg_Error < -179)
        {
        hdg_Error = hdg_Error + 360;
        }

        // Run error accumulator (integrator)
        hdg_Error_Integral = hdg_Error_Integral + hdg_Error;

        // Calculator motor outputs
        raw_yaw = -1 * hdg_Error * loop_Gain;

        // raw_Left = raw_Left - (hdg_Error_Integral / integral_Divisor);
        // raw_Right = raw_Right + (hdg_Error_Integral / integral_Divisor);

        // Constrain and output to motors

        yaw = constrain(raw_yaw, -50, 50);
        Serial.println(F("log:hold pushing command;"));
        Serial.print(F("p_er:"));
        Serial.print(hdg_Error);
        Serial.println(';');

        int argsToSend[] = {1,yaw}; //include number of parms as last parm
        command.pushCommand("yaw",argsToSend);
      }

    }
}
#endif

<commit_msg>Revert "Revert "Fix spelling in Arduino""<commit_after>
#include "AConfig.h"
#if(HAS_STD_PILOT)
#include "Device.h"
#include "Pin.h"
#include "Pilot.h"
#include "Timer.h"

Timer pilotTimer;
bool _headingHoldEnabled = false;
int  _headingHoldTarget = 0;
int hdg = 0;
int hdg_Error;
int raw_Left, raw_Right;
int left, right;  // motor outputs in microseconds, +/-500
int loop_Gain = 1;
int integral_Divisor = 100;
long hdg_Error_Integral = 0;
int tgt_Hdg = 0;
bool _depthHoldEnabled = false;
int _depthHoldTarget = 0;
int depth = 0;
int depth_Error = 0;
int raw_lift =0;
int lift = 0;
int target_depth;
int raw_yaw, yaw;

void Pilot::device_setup(){
  pilotTimer.reset();
  Serial.println(F("log:pilot setup complete;"));
}

void Pilot::device_loop(Command command){
//intended to respond to fly by wire commands: MaintainHeading(); TurnTo(compassheading); DiveTo(depth);
    if( command.cmp("holdHeading_toggle")){
      if (_headingHoldEnabled) {
        _headingHoldEnabled = false;
        raw_Left = 0;
        raw_Right = 0;
        hdg_Error_Integral = 0;  // Reset error integrator
        tgt_Hdg = -500;  // -500 = system not in hdg hold

        int argsToSend[] = {1,00}; //include number of parms as last parm
        command.pushCommand("yaw",argsToSend);
        Serial.println(F("log:heading_hold_disabled;"));

      } else {
        _headingHoldEnabled = true;
        if(command.args[0]==0){
          _headingHoldTarget = navdata::HDGD;
        } else {
          _headingHoldTarget = command.args[1];
        }
        tgt_Hdg = _headingHoldTarget;
        Serial.print(F("log:heading_hold_enabled on="));
        Serial.print(tgt_Hdg);
        Serial.println(';');
      }
      Serial.print(F("targetHeading:"));
      if (_headingHoldEnabled) {
        Serial.print(tgt_Hdg);
      } else {
        Serial.print(DISABLED);
      }
      Serial.println(';');
    }

    if( command.cmp("holdDepth_toggle")){
      if (_depthHoldEnabled) {
        _depthHoldEnabled = false;
        raw_lift = 0;
        target_depth = 0;

        int argsToSend[] = {1,0}; //include number of parms as last parm
        command.pushCommand("lift",argsToSend);
        Serial.println(F("log:depth_hold_disabled;"));

      } else {
        _depthHoldEnabled = true;
        if(command.args[0]==0){
          _depthHoldTarget = navdata::DEAP*100;  //casting to cm
        } else {
          _depthHoldTarget = command.args[1];
        }
        target_depth = _depthHoldTarget;
        Serial.print(F("log:depth_hold_enabled on="));
        Serial.print(target_depth);
        Serial.println(';');
      }
      Serial.print(F("targetDepth:"));
      if (_depthHoldEnabled) {
        Serial.print(target_depth);
      } else {
        Serial.pitnt(DISABLED);
      }
      Serial.println(';');
    }

    if (pilotTimer.elapsed (50)) {

      // Autopilot Test #3 6 Jan 2014
      // Hold vehicle at arbitrary heading
      // Integer math; proportional control plus basic integrator
      // No hysteresis around 180 degree error

      // Check whether hold mode is on

      if (_depthHoldEnabled)
      {
        depth = navdata::DEAP*100;
        depth_Error = target_depth-depth;  //positive error = positive lift = go deaper.

        raw_lift = depth_Error * loop_Gain;
        lift = constrain(raw_lift, -50, 50);

        Serial.println(F("log:dhold pushing command;"));
        Serial.print(F("dp_er:"));
        Serial.print(depth_Error);
        Serial.println(';');
        int argsToSend[] = {1,lift}; //include number of parms as last parm
        command.pushCommand("lift",argsToSend);

      }

      if (_headingHoldEnabled)
      {

        // Code for hold mode here
        hdg = navdata::HDGD;

        // Calculate heading error

        hdg_Error = hdg - tgt_Hdg;

        if (hdg_Error > 180)
        {
        hdg_Error = hdg_Error - 360;
        }

        if (hdg_Error < -179)
        {
        hdg_Error = hdg_Error + 360;
        }

        // Run error accumulator (integrator)
        hdg_Error_Integral = hdg_Error_Integral + hdg_Error;

        // Calculator motor outputs
        raw_yaw = -1 * hdg_Error * loop_Gain;

        // raw_Left = raw_Left - (hdg_Error_Integral / integral_Divisor);
        // raw_Right = raw_Right + (hdg_Error_Integral / integral_Divisor);

        // Constrain and output to motors

        yaw = constrain(raw_yaw, -50, 50);
        Serial.println(F("log:hold pushing command;"));
        Serial.print(F("p_er:"));
        Serial.print(hdg_Error);
        Serial.println(';');

        int argsToSend[] = {1,yaw}; //include number of parms as last parm
        command.pushCommand("yaw",argsToSend);
      }

    }
}
#endif

<|endoftext|>


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

#include "ofwindow.h"
#include <QMouseEvent>

const bool OFWindow::VERBOSE_CONSOLE = false;

OFWindow::OFWindow(QWindow *parent)
    : QWindow(parent),
      m_renderer(*this),
      m_alreadyExposed(false)
{
    // Surface type shall be OpenGL
    setSurfaceType(QWindow::OpenGLSurface);
}

OFWindow::~OFWindow()
{
    // Wait for the RenderThread to stop
    m_renderer.stop();
    m_renderer.wait();
}

void OFWindow::exposeEvent(QExposeEvent *)
{
    // The renderer shall not be started until the window is exposed for the first time
    if (!m_alreadyExposed) {
        m_renderer.start();
        m_alreadyExposed = true;
    }
    // else Do not attempt to start the renderer twice!
}

unsigned int OFWindow::mapQtButtonToOFButton(Qt::MouseButtons qButton)
{
    unsigned int button = 0;

    if (qButton == Qt::LeftButton) {
        button = 1;
    }
    else if (qButton == Qt::RightButton) {
        button = 3;
    }

    return button;
}

int OFWindow::mapQtKeyEventToOsgKey(QKeyEvent *event) {
    int key;

    // Convert uppercase to lowercase as necessary
    if (event->key() >= Qt::Key_A && event->key() <= Qt::Key_Z) {
        key = static_cast<int>(event->text().at(0).toLatin1());
    }
    else {
        key = event->key();
    }

    return key;
}

void OFWindow::mousePressEvent(QMouseEvent *event)
{
    unsigned int button = mapQtButtonToOFButton(event->button());

    if (m_alreadyExposed) {
        if (button != 0) {
            if (VERBOSE_CONSOLE) {
                if (event->button() == 1) {
                    qDebug() << "mouseDown left at (" << event->x() << ", " << event->y() << ")";
                }
                else if (event->button() == 3) {
                    qDebug() << "mouseDown right at (" << event->x() << ", " << event->y() << ")";
                }
            }

            if (m_renderer.winproxy() != 0x0) {
                m_renderer.winproxy()->buttonPress(event->x(), event->y(), button);
            }
        }
    }
}

void OFWindow::mouseReleaseEvent(QMouseEvent *event)
{
    unsigned int button = mapQtButtonToOFButton(event->button());

    if (m_alreadyExposed) {
        if (button != 0) {
            if (VERBOSE_CONSOLE) {
                if (event->button() == 1) {
                    qDebug() << "mouseUp left at (" << event->x() << ", " << event->y() << ")";
                }
                else if (event->button() == 3) {
                    qDebug() << "mouseUp right at (" << event->x() << ", " << event->y() << ")";
                }
            }

            if (m_renderer.winproxy() != 0x0) {
                m_renderer.winproxy()->buttonRelease(event->x(), event->y(), button);
            }
        }
    }
}

void OFWindow::mouseMoveEvent(QMouseEvent *event)
{
    if (m_alreadyExposed) {
        if (VERBOSE_CONSOLE) {
            qDebug() << "mouseMoved to (" << event->x() << ", " << event->y() << ")";
        }
        if (m_renderer.winproxy() != 0x0) {
            m_renderer.winproxy()->mouseMotion(event->x(), event->y());
        }
    }
}

void OFWindow::keyPressEvent(QKeyEvent *event)
{
    int key;

    if (m_alreadyExposed) {
        if (VERBOSE_CONSOLE) {
            qDebug() << "keyPressed " << event->key() << " (" << (char)event->key() << ")";
        }
        if (m_renderer.winproxy() != 0x0) {
            key = mapQtKeyEventToOsgKey(event);
            m_renderer.winproxy()->keyPress(key);
        }
    }
}

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

#include "ofwindow.h"
#include <QMouseEvent>

const bool OFWindow::VERBOSE_CONSOLE = false;

OFWindow::OFWindow(QWindow *parent)
    : QWindow(parent),
      m_renderer(*this),
      m_alreadyExposed(false)
{
    // Surface type shall be OpenGL
    setSurfaceType(QWindow::OpenGLSurface);
}

OFWindow::~OFWindow()
{
    // Wait for the RenderThread to stop
    m_renderer.stop();
    m_renderer.wait();
}

void OFWindow::exposeEvent(QExposeEvent *)
{
    // The renderer shall not be started until the window is exposed for the first time
    if (!m_alreadyExposed) {
        m_renderer.start();
        m_alreadyExposed = true;
    }
    // else Do not attempt to start the renderer twice!
}

unsigned int OFWindow::mapQtButtonToOFButton(Qt::MouseButtons qButton)
{
    unsigned int button = 0;

    if (qButton == Qt::LeftButton) {
        button = 1;
    }
    else if (qButton == Qt::RightButton) {
        button = 3;
    }

    return button;
}

int OFWindow::mapQtKeyEventToOsgKey(QKeyEvent *event) {
    int key;

    // Convert uppercase to lowercase as necessary
    if (event->key() >= Qt::Key_A && event->key() <= Qt::Key_Z) {
        key = static_cast<int>(event->text().at(0).toLatin1());
    }
    else {
        key = event->key();
    }

    return key;
}

void OFWindow::mousePressEvent(QMouseEvent *event)
{
    unsigned int button = mapQtButtonToOFButton(event->button());

    if (m_renderer.winproxy()->isAnimating()) {
        if (button != 0) {
            if (VERBOSE_CONSOLE) {
                if (event->button() == 1) {
                    qDebug() << "mouseDown left at (" << event->x() << ", " << event->y() << ")";
                }
                else if (event->button() == 3) {
                    qDebug() << "mouseDown right at (" << event->x() << ", " << event->y() << ")";
                }
            }

            if (m_renderer.winproxy() != 0x0) {
                m_renderer.winproxy()->buttonPress(event->x(), event->y(), button);
            }
        }
    }
}

void OFWindow::mouseReleaseEvent(QMouseEvent *event)
{
    unsigned int button = mapQtButtonToOFButton(event->button());

    if (m_renderer.winproxy()->isAnimating()) {
        if (button != 0) {
            if (VERBOSE_CONSOLE) {
                if (event->button() == 1) {
                    qDebug() << "mouseUp left at (" << event->x() << ", " << event->y() << ")";
                }
                else if (event->button() == 3) {
                    qDebug() << "mouseUp right at (" << event->x() << ", " << event->y() << ")";
                }
            }

            if (m_renderer.winproxy() != 0x0) {
                m_renderer.winproxy()->buttonRelease(event->x(), event->y(), button);
            }
        }
    }
}

void OFWindow::mouseMoveEvent(QMouseEvent *event)
{
    if (m_renderer.winproxy()->isAnimating()) {
        if (VERBOSE_CONSOLE) {
            qDebug() << "mouseMoved to (" << event->x() << ", " << event->y() << ")";
        }
        if (m_renderer.winproxy() != 0x0) {
            m_renderer.winproxy()->mouseMotion(event->x(), event->y());
        }
    }
}

void OFWindow::keyPressEvent(QKeyEvent *event)
{
    int key;

    if (m_renderer.winproxy()->isAnimating()) {
        if (VERBOSE_CONSOLE) {
            qDebug() << "keyPressed " << event->key() << " (" << (char)event->key() << ")";
        }
        if (m_renderer.winproxy() != 0x0) {
            key = mapQtKeyEventToOsgKey(event);
            m_renderer.winproxy()->keyPress(key);
        }
    }
}

void OFWindow::resizeEvent(QResizeEvent *event) {
    if (m_renderer.winproxy() != 0x0) {
        if (m_renderer.winproxy()->isAnimating()) {
            m_renderer.winproxy()->resizeWindow(0, 0, event->size().width(), event->size().height());
        }
    }
    QWindow::resizeEvent(event);
}
<|endoftext|>


<commit_before># pragma once
# include <Siv3D.hpp>
# include "AscIMessgeButton.hpp"

namespace asc
{
	using namespace s3d;

	using TextureAssetName = String;
	using FontAssetName = String;

	class DefaultButton : public IMessageButton
	{
	public:

		void init() override {}

		void update() override {}

		void onClick() override {}

		void draw() const override {}

	};

	class MessageManager
	{
	private:

		std::unique_ptr<IMessageButton> m_button;

		bool m_isAutomatic;

		Stopwatch m_stopwatch;

		uint32 m_charCount;

		String m_text;

		String m_name;

		KeyCombination m_submit;

		KeyCombination m_skip;

		int32 m_speed;

		int32 m_time;

		TextureAssetName m_texture;

		FontAssetName m_textFont;

		FontAssetName m_nameFont;

		Color m_color;

		Rect m_region;

		Point m_textPosition;

		Point m_namePosition;

		std::function<void()> m_onCountChar;

	public:

		MessageManager(std::function<void()> onCountChar) :
			m_button(std::make_unique<DefaultButton>()),
			m_charCount(0U),
			m_speed(100),
			m_time(100),
			m_onCountChar(onCountChar)
		{
			m_stopwatch.start();
			m_stopwatch.pause();
		}

		void setName(const String& name)
		{
			m_name = name;
		}

		void setText(const String& text)
		{
			m_text = text;
		}

		void setKey(const KeyCombination& submit, const KeyCombination& skip)
		{
			m_submit = submit;
			m_skip = skip;
		}

		void setSpeed(int32 speed)
		{
			m_speed = speed;
		}

		void setTime(int32 time)
		{
			m_time = time;
		}

		void setTexture(const TextureAssetName& texture, const Rect& region)
		{
			m_texture = texture;
			m_region = region;
		}

		void setFont(const FontAssetName& text, const FontAssetName& name)
		{
			m_textFont = text;
			m_nameFont = name;
		}

		void setColor(const Color& color)
		{
			m_color = color;
		}

		void setPosition(const Point& text, const Point& name)
		{
			m_textPosition = text;
			m_namePosition = name;
		}

		void setButton(std::unique_ptr<IMessageButton> button)
		{
			m_button.swap(button);
		}

		void start(bool isAutomatic = false)
		{
			m_stopwatch.restart();
			m_charCount = 0U;
			m_isAutomatic = isAutomatic;
		}

		void update()
		{
			if(m_stopwatch.isPaused())
				return;

			const auto typingTime = static_cast<int32>(m_text.length) * m_speed;

			if (m_stopwatch.ms() >= typingTime)
			{
				if (m_stopwatch.ms() >= typingTime + m_time && (m_submit.clicked || m_skip.pressed || m_isAutomatic))
				{
					m_stopwatch.pause();
				}
			}
			else if(m_submit.clicked || m_skip.pressed)
			{
				m_stopwatch.set(static_cast<Milliseconds>(m_text.length * m_speed));
			}

			const auto charCount = Min<uint32>(m_stopwatch.ms() / m_speed, m_text.length);

			if (charCount > m_charCount)
			{
				m_charCount = charCount;

				if (m_text[charCount - 1] != L' ')
				{
					m_onCountChar();
				}
			}
		}

		void clear()
		{
			m_name.clear();
			m_text.clear();
			m_stopwatch.pause();
		}

		bool isUpdating() const
		{
			return !m_stopwatch.isPaused();
		}

		void draw() const
		{
			m_region(TextureAsset(m_texture)).draw();

			FontAsset(m_nameFont).draw(m_name, m_namePosition, m_color);
			FontAsset(m_textFont).draw(m_text.substr(0U, m_charCount), m_textPosition, m_color);
		}

	};
}
<commit_msg>MessageManager::isUpdating show by active instead of pause.<commit_after># pragma once
# include <Siv3D.hpp>
# include "AscIMessgeButton.hpp"

namespace asc
{
	using namespace s3d;

	using TextureAssetName = String;
	using FontAssetName = String;

	class DefaultButton : public IMessageButton
	{
	public:

		void init() override {}

		void update() override {}

		void onClick() override {}

		void draw() const override {}

	};

	class MessageManager
	{
	private:

		std::unique_ptr<IMessageButton> m_button;

		bool m_isAutomatic;

		Stopwatch m_stopwatch;

		uint32 m_charCount;

		String m_text;

		String m_name;

		KeyCombination m_submit;

		KeyCombination m_skip;

		int32 m_speed;

		int32 m_time;

		TextureAssetName m_texture;

		FontAssetName m_textFont;

		FontAssetName m_nameFont;

		Color m_color;

		Rect m_region;

		Point m_textPosition;

		Point m_namePosition;

		std::function<void()> m_onCountChar;

	public:

		MessageManager(std::function<void()> onCountChar) :
			m_button(std::make_unique<DefaultButton>()),
			m_charCount(0U),
			m_speed(100),
			m_time(100),
			m_onCountChar(onCountChar) {}

		void setName(const String& name)
		{
			m_name = name;
		}

		void setText(const String& text)
		{
			m_text = text;
		}

		void setKey(const KeyCombination& submit, const KeyCombination& skip)
		{
			m_submit = submit;
			m_skip = skip;
		}

		void setSpeed(int32 speed)
		{
			m_speed = speed;
		}

		void setTime(int32 time)
		{
			m_time = time;
		}

		void setTexture(const TextureAssetName& texture, const Rect& region)
		{
			m_texture = texture;
			m_region = region;
		}

		void setFont(const FontAssetName& text, const FontAssetName& name)
		{
			m_textFont = text;
			m_nameFont = name;
		}

		void setColor(const Color& color)
		{
			m_color = color;
		}

		void setPosition(const Point& text, const Point& name)
		{
			m_textPosition = text;
			m_namePosition = name;
		}

		void setButton(std::unique_ptr<IMessageButton> button)
		{
			m_button.swap(button);
		}

		void start(bool isAutomatic = false)
		{
			m_stopwatch.start();
			m_charCount = 0U;
			m_isAutomatic = isAutomatic;
		}

		void update()
		{
			if(!isUpdating())
				return;

			const auto typingTime = static_cast<int32>(m_text.length) * m_speed;

			if (m_stopwatch.ms() >= typingTime)
			{
				if (m_stopwatch.ms() >= typingTime + m_time && (m_submit.clicked || m_skip.pressed || m_isAutomatic))
				{
					m_stopwatch.reset();
				}
			}
			else if(m_submit.clicked || m_skip.pressed)
			{
				m_stopwatch.set(static_cast<Milliseconds>(m_text.length * m_speed));
			}

			const auto charCount = Min<uint32>(m_stopwatch.ms() / m_speed, m_text.length);

			if (charCount > m_charCount)
			{
				m_charCount = charCount;

				if (m_text[charCount - 1] != L' ')
				{
					m_onCountChar();
				}
			}
		}

		void clear()
		{
			m_name.clear();
			m_text.clear();
			m_stopwatch.pause();
		}

		bool isUpdating() const
		{
			return m_stopwatch.isActive();
		}

		void draw() const
		{
			m_region(TextureAsset(m_texture)).draw();

			FontAsset(m_nameFont).draw(m_name, m_namePosition, m_color);
			FontAsset(m_textFont).draw(m_text.substr(0U, m_charCount), m_textPosition, m_color);
		}

	};
}
<|endoftext|>


<commit_before># pragma once
# include <Siv3D.hpp>

namespace asc
{
	using namespace s3d;

	class MessageManager
	{
	private:

		bool m_isAutomatic;

		Stopwatch m_stopwatch;

		String m_name;

		String m_text;

		uint32 m_charCount;

		std::function<void()> m_onCountChar;

	public:

		MessageManager() = default;

		MessageManager(std::function<void()> onCountChar) :
			m_charCount(0U),
			m_onCountChar(onCountChar)
		{
			m_stopwatch.start();
			m_stopwatch.pause();
		}

		virtual ~MessageManager() = default;

		void start(bool isAutomatic = false)
		{
			m_stopwatch.restart();
			m_charCount = 0U;
			m_isAutomatic = isAutomatic;
		}

		void update()
		{
			// ToDo Configurable
			const int32 m_textSpeed = 100;
			const int32 m_textWait = 100;

			if(m_stopwatch.isPaused())
				return;

			const auto typingTime = static_cast<int32>(m_text.length) * m_textSpeed;

			if (m_stopwatch.ms() >= typingTime)
			{
				if (m_stopwatch.ms() >= typingTime + m_textWait && (Input::KeyEnter.clicked || Input::KeyQ.pressed || m_isAutomatic))
				{
					m_stopwatch.pause();
				}
			}
			else if(Input::KeyEnter.clicked || Input::KeyQ.pressed)
			{
				m_stopwatch.set(static_cast<Milliseconds>(m_text.length * m_textSpeed));
			}

			const auto charCount = Min<uint32>(m_stopwatch.ms() / m_textSpeed, m_text.length);

			if (charCount > m_charCount)
			{
				m_charCount = charCount;

				if (m_text[charCount - 1] != L' ')
				{
					m_onCountChar();
				}
			}
		}

		void setName(const String& name)
		{
			m_name = name;
		}

		void setText(const String& text)
		{
			m_text = text;
		}

		void clear()
		{
			m_name.clear();
			m_text.clear();
			m_stopwatch.pause();
		}

		void draw() const
		{
			// ToDo Configurable
			const Rect m_messageBox(6, 440, 1268, 285);
			const Point m_namePosition(40, 525);
			const Point m_textPosition(60, 575);
			const String m_messageBoxTexture = L"test_message_box";
			const String m_nameFont = L"test_name";
			const String m_textFont = L"test_text";
			const Color m_messageColor = Palette::Black;

			m_messageBox(TextureAsset(m_messageBoxTexture)).draw();

			FontAsset(m_nameFont).draw(m_name, m_namePosition, m_messageColor);
			FontAsset(m_textFont).draw(m_text.substr(0U, m_charCount), m_textPosition, m_messageColor);
		}

		bool isUpdating() const
		{
			return !m_stopwatch.isPaused();
		}

	};
}
<commit_msg>Delete Default Constructor.<commit_after># pragma once
# include <Siv3D.hpp>

namespace asc
{
	using namespace s3d;

	class MessageManager
	{
	private:

		bool m_isAutomatic;

		Stopwatch m_stopwatch;

		String m_name;

		String m_text;

		uint32 m_charCount;

		std::function<void()> m_onCountChar;

	public:

		MessageManager(std::function<void()> onCountChar) :
			m_charCount(0U),
			m_onCountChar(onCountChar)
		{
			m_stopwatch.start();
			m_stopwatch.pause();
		}

		virtual ~MessageManager() = default;

		void start(bool isAutomatic = false)
		{
			m_stopwatch.restart();
			m_charCount = 0U;
			m_isAutomatic = isAutomatic;
		}

		void update()
		{
			// ToDo Configurable
			const int32 m_textSpeed = 100;
			const int32 m_textWait = 100;

			if(m_stopwatch.isPaused())
				return;

			const auto typingTime = static_cast<int32>(m_text.length) * m_textSpeed;

			if (m_stopwatch.ms() >= typingTime)
			{
				if (m_stopwatch.ms() >= typingTime + m_textWait && (Input::KeyEnter.clicked || Input::KeyQ.pressed || m_isAutomatic))
				{
					m_stopwatch.pause();
				}
			}
			else if(Input::KeyEnter.clicked || Input::KeyQ.pressed)
			{
				m_stopwatch.set(static_cast<Milliseconds>(m_text.length * m_textSpeed));
			}

			const auto charCount = Min<uint32>(m_stopwatch.ms() / m_textSpeed, m_text.length);

			if (charCount > m_charCount)
			{
				m_charCount = charCount;

				if (m_text[charCount - 1] != L' ')
				{
					m_onCountChar();
				}
			}
		}

		void setName(const String& name)
		{
			m_name = name;
		}

		void setText(const String& text)
		{
			m_text = text;
		}

		void clear()
		{
			m_name.clear();
			m_text.clear();
			m_stopwatch.pause();
		}

		void draw() const
		{
			// ToDo Configurable
			const Rect m_messageBox(6, 440, 1268, 285);
			const Point m_namePosition(40, 525);
			const Point m_textPosition(60, 575);
			const String m_messageBoxTexture = L"test_message_box";
			const String m_nameFont = L"test_name";
			const String m_textFont = L"test_text";
			const Color m_messageColor = Palette::Black;

			m_messageBox(TextureAsset(m_messageBoxTexture)).draw();

			FontAsset(m_nameFont).draw(m_name, m_namePosition, m_messageColor);
			FontAsset(m_textFont).draw(m_text.substr(0U, m_charCount), m_textPosition, m_messageColor);
		}

		bool isUpdating() const
		{
			return !m_stopwatch.isPaused();
		}

	};
}
<|endoftext|>


<commit_before>/** \brief Implementation of the MarcRecord class.
 *  \author Oliver Obenland (oliver.obenland@uni-tuebingen.de)
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2016 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "MarcRecord.h"
#include "MarcTag.h"
#include "util.h"

const size_t MarcRecord::FIELD_NOT_FOUND;

MarcRecord &MarcRecord::operator=(const MarcRecord &rhs) {
    if (likely(&rhs != this)) {
        leader_ = rhs.leader_;
        raw_data_ = rhs.raw_data_;
        directory_entries_ = rhs.directory_entries_;
    }
    return *this;
}

std::string MarcRecord::getFieldData(const size_t index) const {
    if (index == MarcRecord::FIELD_NOT_FOUND or directory_entries_.cbegin() + index >= directory_entries_.cend())
        return "";
    const DirectoryEntry &entry(directory_entries_[index]);
    return std::string(raw_data_, entry.getFieldOffset(), entry.getFieldLength() - 1);
}

Subfields MarcRecord::getSubfields(const size_t index) const {
    if (index == MarcRecord::FIELD_NOT_FOUND or directory_entries_.cbegin() + index >= directory_entries_.cend())
        return Subfields();
    return Subfields(getFieldData(index));
}

void MarcRecord::deleteSubfield(const size_t field_index, const char subfield_code) {
    Subfields subfields(getSubfields(field_index));
    subfields.erase(subfield_code);
    updateField(field_index, subfields.toString());
}

MarcTag MarcRecord::getTag(const size_t index) const {
    if (directory_entries_.cbegin() + index >= directory_entries_.cend())
        return "";
    return directory_entries_[index].getTag();
}

size_t MarcRecord::getFieldIndex(const MarcTag &field_tag) const {
    for (size_t i(0); i < getNumberOfFields(); ++i) {
        if (directory_entries_[i].getTag() == field_tag)
            return i;
    }
    return MarcRecord::FIELD_NOT_FOUND;
}

size_t MarcRecord::getFieldIndices(const MarcTag &field_tag, std::vector <size_t> *const field_indices) const {
    field_indices->clear();

    size_t field_index(getFieldIndex(field_tag));
    while (static_cast<size_t>(field_index) < directory_entries_.size() and
           directory_entries_[field_index].getTag() == field_tag) {
        field_indices->emplace_back(field_index);
        ++field_index;
    }

    return field_indices->size();
}

void MarcRecord::updateField(const size_t field_index, const std::string &new_field_value) {
    DirectoryEntry &entry(directory_entries_[field_index]);
    size_t offset = raw_data_.size();
    size_t length = new_field_value.length() + 1 /* For new field separator. */;

    entry.setFieldLength(length);
    entry.setFieldOffset(offset);
    raw_data_ += new_field_value + '\x1E';
}

bool MarcRecord::insertSubfield(const MarcTag &new_field_tag, const char subfield_code,
                                const std::string &new_subfield_value, const char indicator1, const char indicator2) {
    return insertField(new_field_tag, std::string(1, indicator1) + std::string(1, indicator2) + "\x1F"
                                      + std::string(1, subfield_code) + new_subfield_value);
}

size_t MarcRecord::insertField(const MarcTag &new_field_tag, const std::string &new_field_value) {

    // Find the insertion location:
    auto insertion_location(directory_entries_.begin());
    while (insertion_location != directory_entries_.end() and new_field_tag >= insertion_location->getTag())
        ++insertion_location;

    const size_t offset(raw_data_.size());
    const size_t length(new_field_value.length() + 1) /* For new field separator. */;
    const auto inserted_location(directory_entries_.emplace(insertion_location, new_field_tag, length, offset));
    raw_data_ += new_field_value + '\x1E';

    const size_t index(std::distance(directory_entries_.begin(), inserted_location));
    return index;
}

void MarcRecord::deleteField(const size_t field_index) {
    directory_entries_.erase(directory_entries_.begin() + field_index);
}

void MarcRecord::deleteFields(const std::vector <std::pair<size_t, size_t>> &blocks) {
    std::vector <DirectoryEntry> new_entries;
    new_entries.reserve(directory_entries_.size());

    size_t copy_start(0);
    for (const std::pair <size_t, size_t> block : blocks) {
        new_entries.insert(new_entries.end(), directory_entries_.begin() + copy_start,
                           directory_entries_.begin() + block.first);
        copy_start = block.second;
    }
    new_entries.insert(new_entries.end(), directory_entries_.begin() + copy_start, directory_entries_.end());
    new_entries.swap(directory_entries_);
}

std::string MarcRecord::extractFirstSubfield(const MarcTag &tag, const char subfield_code) const {
    const size_t index(getFieldIndex(tag));
    if (index == FIELD_NOT_FOUND)
        return "";
    return getSubfields(tag).getFirstSubfieldValue(subfield_code);
}

std::string MarcRecord::extractFirstSubfield(const size_t field_index, const char subfield_code) const {
    const Subfields subfields(getFieldData(field_index));
    return subfields.getFirstSubfieldValue(subfield_code);
}

size_t MarcRecord::extractAllSubfields(const std::string &tags, std::vector <std::string> *const values,
                                       const std::string &ignore_subfield_codes) const
{
    values->clear();

    std::vector <std::string> individual_tags;
    StringUtil::Split(tags, ':', &individual_tags);
    for (const auto &tag : individual_tags) {
        size_t field_index(getFieldIndex(tag));
        while (static_cast<size_t>(field_index) < directory_entries_.size() and
               directory_entries_[field_index].getTag() == tag) {
            const Subfields subfields(getSubfields(field_index));
            for (const auto &subfield : subfields) {
                if (ignore_subfield_codes.find(subfield.code_) == std::string::npos)
                    values->emplace_back(subfield.value_);
            }
            ++field_index;
        }
    }
    return values->size();
}

size_t MarcRecord::extractSubfield(const MarcTag &tag, const char subfield_code,
                                   std::vector <std::string> *const values) const
{
    values->clear();

    size_t field_index(getFieldIndex(tag));
    while (static_cast<size_t>(field_index) < directory_entries_.size() and
           tag == directory_entries_[field_index].getTag()) {
        const Subfields subfields(getSubfields(field_index));
        const auto begin_end(subfields.getIterators(subfield_code));
        for (auto subfield_code_and_value(begin_end.first);
             subfield_code_and_value != begin_end.second; ++subfield_code_and_value)
            values->emplace_back(subfield_code_and_value->value_);
        ++field_index;
    }
    return values->size();
}

size_t MarcRecord::extractSubfields(const MarcTag &tag, const std::string &subfield_codes,
                                    std::vector <std::string> *const values) const
{
    values->clear();

    size_t field_index(getFieldIndex(tag));
    while (static_cast<size_t>(field_index) < directory_entries_.size() and
           tag == directory_entries_[field_index].getTag()) {
        const Subfields subfields(getSubfields(field_index));
        for (const auto &subfield : subfields) {
            if (subfield_codes.find(subfield.code_) != std::string::npos)
                values->emplace_back(subfield.value_);
        }
        ++field_index;
    }

    return values->size();
}

size_t MarcRecord::findAllLocalDataBlocks(std::vector <std::pair<size_t, size_t>> *const local_block_boundaries) const {
    local_block_boundaries->clear();

    size_t local_block_start(getFieldIndex("LOK"));
    if (local_block_start == FIELD_NOT_FOUND)
        return 0;

    size_t local_block_end(local_block_start + 1);
    while (local_block_end < directory_entries_.size()) {
        if (StringUtil::StartsWith(getFieldData(local_block_end), "  ""\x1F""0000")) {
            local_block_boundaries->emplace_back(std::make_pair(local_block_start, local_block_end));
            local_block_start = local_block_end;
        }
        ++local_block_end;
    }
    local_block_boundaries->emplace_back(std::make_pair(local_block_start, local_block_end));

    return local_block_boundaries->size();
}

static inline bool IndicatorsMatch(const std::string &indicator_pattern, const std::string &indicators) {
    if (indicator_pattern[0] != '?' and indicator_pattern[0] != indicators[0])
        return false;
    if (indicator_pattern[1] != '?' and indicator_pattern[1] != indicators[1])
        return false;
    return true;
}

size_t MarcRecord::findFieldsInLocalBlock(const MarcTag &field_tag, const std::string &indicators,
                                          const std::pair <size_t, size_t> &block_start_and_end,
                                          std::vector <size_t> *const field_indices) const
{
    field_indices->clear();
    if (unlikely(indicators.length() != 2))
        Error("in MarcRecord::FindFieldInLocalBlock: indicators must be precisely 2 characters long!");

    const std::string FIELD_PREFIX("  ""\x1F""0" + field_tag.to_string());
    for (size_t index(block_start_and_end.first); index < block_start_and_end.second; ++index) {
        const std::string &current_field(getFieldData(index));
        if (StringUtil::StartsWith(current_field, FIELD_PREFIX)
            and IndicatorsMatch(indicators, current_field.substr(7, 2)))
            field_indices->emplace_back(index);
    }
    return field_indices->size();
}

void MarcRecord::filterTags(const std::unordered_set <MarcTag> &drop_tags) {
    std::vector <std::pair<size_t, size_t>> deleted_blocks;
    for (auto entry = directory_entries_.begin(); entry < directory_entries_.end(); ++entry) {
        const auto tag_iter = drop_tags.find(entry->getTag());
        if (tag_iter == drop_tags.cend())
            continue;
        const size_t block_start = std::distance(directory_entries_.begin(), entry);
        for (/* empty */; entry < directory_entries_.end() and entry->getTag() == *tag_iter; ++entry);
        const size_t block_end = std::distance(directory_entries_.begin(), entry);

        deleted_blocks.emplace_back(block_start, block_end);
    }
    deleteFields(deleted_blocks);
}

std::string MarcRecord::getLanguage(const std::string &default_language_code) const {
    const std::string &language(extractFirstSubfield("041", 'a'));
    if (likely(not language.empty()))
        return language;
    return default_language_code;
}

std::string MarcRecord::getLanguageCode() const {
    const size_t _008_index(getFieldIndex("008"));
    if (_008_index == FIELD_NOT_FOUND)
        return "";
    // Language codes start at offset 35 and have a length of 3.
    const auto entry = directory_entries_[_008_index];
    if (entry.getFieldLength() < 38)
        return "";

    return std::string(raw_data_, entry.getFieldOffset() + 35, 3);
}

bool MarcRecord::isElectronicResource() const {
    if (std::toupper(leader_[6]) == 'M')
        return true;

    if (leader_.isMonograph()) {
        std::vector<size_t> _007_field_indices;
        getFieldIndices("007", &_007_field_indices);
        for (auto _007_field_index : _007_field_indices) {
            const std::string _007_field_contents(getFieldData(_007_field_index));
            if (not _007_field_contents.empty() and std::toupper(_007_field_contents[0]) == 'C')
                return true;
        }
    }

    return false;
}

void MarcRecord::combine(const MarcRecord &record) {
    const size_t offset(raw_data_.size());
    raw_data_ += record.raw_data_;

    // Ignore first field. We only need one 001-field.
    directory_entries_.reserve(record.directory_entries_.size() - 1);
    for (auto iter(record.directory_entries_.begin() + 1); iter < record.directory_entries_.end(); ++iter) {
        directory_entries_.emplace_back(*iter);
        directory_entries_.back().setFieldOffset(iter->getFieldOffset() + offset);
    }
}

bool MarcRecord::ProcessRecords(MarcReader * const marc_reader, RecordFunc process_record,
                                MarcWriter * const marc_writer, std::string * const err_msg)
{
    err_msg->clear();

    while (MarcRecord record = marc_reader->read()) {
        if (not (*process_record)(&record, marc_writer, err_msg))
            return false;
        err_msg->clear();
    }

    return err_msg->empty();
}
<commit_msg>Clean-up of legacy and plainly weird code.<commit_after>/** \brief Implementation of the MarcRecord class.
 *  \author Oliver Obenland (oliver.obenland@uni-tuebingen.de)
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2016 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "MarcRecord.h"
#include "MarcTag.h"
#include "util.h"

const size_t MarcRecord::FIELD_NOT_FOUND;

MarcRecord &MarcRecord::operator=(const MarcRecord &rhs) {
    if (likely(&rhs != this)) {
        leader_ = rhs.leader_;
        raw_data_ = rhs.raw_data_;
        directory_entries_ = rhs.directory_entries_;
    }
    return *this;
}

std::string MarcRecord::getFieldData(const size_t index) const {
    if (index == MarcRecord::FIELD_NOT_FOUND or directory_entries_.cbegin() + index >= directory_entries_.cend())
        return "";
    const DirectoryEntry &entry(directory_entries_[index]);
    return std::string(raw_data_, entry.getFieldOffset(), entry.getFieldLength() - 1);
}

Subfields MarcRecord::getSubfields(const size_t index) const {
    if (index == MarcRecord::FIELD_NOT_FOUND or directory_entries_.cbegin() + index >= directory_entries_.cend())
        return Subfields();
    return Subfields(getFieldData(index));
}

void MarcRecord::deleteSubfield(const size_t field_index, const char subfield_code) {
    Subfields subfields(getSubfields(field_index));
    subfields.erase(subfield_code);
    updateField(field_index, subfields.toString());
}

MarcTag MarcRecord::getTag(const size_t index) const {
    if (directory_entries_.cbegin() + index >= directory_entries_.cend())
        return "";
    return directory_entries_[index].getTag();
}

size_t MarcRecord::getFieldIndex(const MarcTag &field_tag) const {
    for (size_t i(0); i < getNumberOfFields(); ++i) {
        if (directory_entries_[i].getTag() == field_tag)
            return i;
    }
    return MarcRecord::FIELD_NOT_FOUND;
}

size_t MarcRecord::getFieldIndices(const MarcTag &field_tag, std::vector <size_t> *const field_indices) const {
    field_indices->clear();

    size_t field_index(getFieldIndex(field_tag));
    while (field_index < directory_entries_.size() and directory_entries_[field_index].getTag() == field_tag) {
        field_indices->emplace_back(field_index);
        ++field_index;
    }

    return field_indices->size();
}

void MarcRecord::updateField(const size_t field_index, const std::string &new_field_value) {
    DirectoryEntry &entry(directory_entries_[field_index]);
    size_t offset = raw_data_.size();
    size_t length = new_field_value.length() + 1 /* For new field separator. */;

    entry.setFieldLength(length);
    entry.setFieldOffset(offset);
    raw_data_ += new_field_value + '\x1E';
}

bool MarcRecord::insertSubfield(const MarcTag &new_field_tag, const char subfield_code,
                                const std::string &new_subfield_value, const char indicator1, const char indicator2) {
    return insertField(new_field_tag, std::string(1, indicator1) + std::string(1, indicator2) + "\x1F"
                                      + std::string(1, subfield_code) + new_subfield_value);
}

size_t MarcRecord::insertField(const MarcTag &new_field_tag, const std::string &new_field_value) {

    // Find the insertion location:
    auto insertion_location(directory_entries_.begin());
    while (insertion_location != directory_entries_.end() and new_field_tag >= insertion_location->getTag())
        ++insertion_location;

    const size_t offset(raw_data_.size());
    const size_t length(new_field_value.length() + 1) /* For new field separator. */;
    const auto inserted_location(directory_entries_.emplace(insertion_location, new_field_tag, length, offset));
    raw_data_ += new_field_value + '\x1E';

    const size_t index(std::distance(directory_entries_.begin(), inserted_location));
    return index;
}

void MarcRecord::deleteField(const size_t field_index) {
    directory_entries_.erase(directory_entries_.begin() + field_index);
}

void MarcRecord::deleteFields(const std::vector <std::pair<size_t, size_t>> &blocks) {
    std::vector <DirectoryEntry> new_entries;
    new_entries.reserve(directory_entries_.size());

    size_t copy_start(0);
    for (const std::pair <size_t, size_t> block : blocks) {
        new_entries.insert(new_entries.end(), directory_entries_.begin() + copy_start,
                           directory_entries_.begin() + block.first);
        copy_start = block.second;
    }
    new_entries.insert(new_entries.end(), directory_entries_.begin() + copy_start, directory_entries_.end());
    new_entries.swap(directory_entries_);
}

std::string MarcRecord::extractFirstSubfield(const MarcTag &tag, const char subfield_code) const {
    const size_t index(getFieldIndex(tag));
    if (index == FIELD_NOT_FOUND)
        return "";
    return getSubfields(index).getFirstSubfieldValue(subfield_code);
}

std::string MarcRecord::extractFirstSubfield(const size_t field_index, const char subfield_code) const {
    const Subfields subfields(getSubfields(field_index));
    return subfields.getFirstSubfieldValue(subfield_code);
}

size_t MarcRecord::extractAllSubfields(const std::string &tags, std::vector <std::string> *const values,
                                       const std::string &ignore_subfield_codes) const
{
    values->clear();

    std::vector <std::string> individual_tags;
    StringUtil::Split(tags, ':', &individual_tags);
    for (const auto &tag : individual_tags) {
        size_t field_index(getFieldIndex(tag));
        while (field_index < directory_entries_.size() and directory_entries_[field_index].getTag() == tag) {
            const Subfields subfields(getSubfields(field_index));
            for (const auto &subfield : subfields) {
                if (ignore_subfield_codes.find(subfield.code_) == std::string::npos)
                    values->emplace_back(subfield.value_);
            }
            ++field_index;
        }
    }
    return values->size();
}

size_t MarcRecord::extractSubfield(const MarcTag &tag, const char subfield_code,
                                   std::vector <std::string> *const values) const
{
    values->clear();

    size_t field_index(getFieldIndex(tag));
    while (field_index < directory_entries_.size() and tag == directory_entries_[field_index].getTag()) {
        const Subfields subfields(getSubfields(field_index));
        const auto begin_end(subfields.getIterators(subfield_code));
        for (auto subfield_code_and_value(begin_end.first);
             subfield_code_and_value != begin_end.second; ++subfield_code_and_value)
            values->emplace_back(subfield_code_and_value->value_);
        ++field_index;
    }
    return values->size();
}

size_t MarcRecord::extractSubfields(const MarcTag &tag, const std::string &subfield_codes,
                                    std::vector <std::string> *const values) const
{
    values->clear();

    size_t field_index(getFieldIndex(tag));
    while (field_index < directory_entries_.size() and tag == directory_entries_[field_index].getTag()) {
        const Subfields subfields(getSubfields(field_index));
        for (const auto &subfield : subfields) {
            if (subfield_codes.find(subfield.code_) != std::string::npos)
                values->emplace_back(subfield.value_);
        }
        ++field_index;
    }

    return values->size();
}

size_t MarcRecord::findAllLocalDataBlocks(std::vector <std::pair<size_t, size_t>> *const local_block_boundaries) const {
    local_block_boundaries->clear();

    size_t local_block_start(getFieldIndex("LOK"));
    if (local_block_start == FIELD_NOT_FOUND)
        return 0;

    size_t local_block_end(local_block_start + 1);
    while (local_block_end < directory_entries_.size()) {
        if (StringUtil::StartsWith(getFieldData(local_block_end), "  ""\x1F""0000")) {
            local_block_boundaries->emplace_back(std::make_pair(local_block_start, local_block_end));
            local_block_start = local_block_end;
        }
        ++local_block_end;
    }
    local_block_boundaries->emplace_back(std::make_pair(local_block_start, local_block_end));

    return local_block_boundaries->size();
}

static inline bool IndicatorsMatch(const std::string &indicator_pattern, const std::string &indicators) {
    if (indicator_pattern[0] != '?' and indicator_pattern[0] != indicators[0])
        return false;
    if (indicator_pattern[1] != '?' and indicator_pattern[1] != indicators[1])
        return false;
    return true;
}

size_t MarcRecord::findFieldsInLocalBlock(const MarcTag &field_tag, const std::string &indicators,
                                          const std::pair <size_t, size_t> &block_start_and_end,
                                          std::vector <size_t> *const field_indices) const
{
    field_indices->clear();
    if (unlikely(indicators.length() != 2))
        Error("in MarcRecord::FindFieldInLocalBlock: indicators must be precisely 2 characters long!");

    const std::string FIELD_PREFIX("  ""\x1F""0" + field_tag.to_string());
    for (size_t index(block_start_and_end.first); index < block_start_and_end.second; ++index) {
        const std::string &current_field(getFieldData(index));
        if (StringUtil::StartsWith(current_field, FIELD_PREFIX)
            and IndicatorsMatch(indicators, current_field.substr(7, 2)))
            field_indices->emplace_back(index);
    }
    return field_indices->size();
}

void MarcRecord::filterTags(const std::unordered_set <MarcTag> &drop_tags) {
    std::vector <std::pair<size_t, size_t>> deleted_blocks;
    for (auto entry = directory_entries_.begin(); entry < directory_entries_.end(); ++entry) {
        const auto tag_iter = drop_tags.find(entry->getTag());
        if (tag_iter == drop_tags.cend())
            continue;
        const size_t block_start = std::distance(directory_entries_.begin(), entry);
        for (/* empty */; entry < directory_entries_.end() and entry->getTag() == *tag_iter; ++entry);
        const size_t block_end = std::distance(directory_entries_.begin(), entry);

        deleted_blocks.emplace_back(block_start, block_end);
    }
    deleteFields(deleted_blocks);
}

std::string MarcRecord::getLanguage(const std::string &default_language_code) const {
    const std::string &language(extractFirstSubfield("041", 'a'));
    if (likely(not language.empty()))
        return language;
    return default_language_code;
}

std::string MarcRecord::getLanguageCode() const {
    const size_t _008_index(getFieldIndex("008"));
    if (_008_index == FIELD_NOT_FOUND)
        return "";
    // Language codes start at offset 35 and have a length of 3.
    const auto entry = directory_entries_[_008_index];
    if (entry.getFieldLength() < 38)
        return "";

    return std::string(raw_data_, entry.getFieldOffset() + 35, 3);
}

bool MarcRecord::isElectronicResource() const {
    if (std::toupper(leader_[6]) == 'M')
        return true;

    if (leader_.isMonograph()) {
        std::vector<size_t> _007_field_indices;
        getFieldIndices("007", &_007_field_indices);
        for (auto _007_field_index : _007_field_indices) {
            const std::string _007_field_contents(getFieldData(_007_field_index));
            if (not _007_field_contents.empty() and std::toupper(_007_field_contents[0]) == 'C')
                return true;
        }
    }

    return false;
}

void MarcRecord::combine(const MarcRecord &record) {
    const size_t offset(raw_data_.size());
    raw_data_ += record.raw_data_;

    // Ignore first field. We only need one 001-field.
    directory_entries_.reserve(record.directory_entries_.size() - 1);
    for (auto iter(record.directory_entries_.begin() + 1); iter < record.directory_entries_.end(); ++iter) {
        directory_entries_.emplace_back(*iter);
        directory_entries_.back().setFieldOffset(iter->getFieldOffset() + offset);
    }
}

bool MarcRecord::ProcessRecords(MarcReader * const marc_reader, RecordFunc process_record,
                                MarcWriter * const marc_writer, std::string * const err_msg)
{
    err_msg->clear();

    while (MarcRecord record = marc_reader->read()) {
        if (not (*process_record)(&record, marc_writer, err_msg))
            return false;
        err_msg->clear();
    }

    return err_msg->empty();
}
<|endoftext|>


<commit_before>/**
 * @file cpp_rpc_example.cpp
 * @author Mislav Novakovic <mislav.novakovic@sartura.hr>
 * @author Michal Vasko <mvasko@cesnet.cz>
 * @brief Example usage of rpc(), rpc_tree(), rpc_subscribe_tree(),
 * rpc_send() and others related to the Remote procedure call (RPC)
 * mechanism
 *
 * @copyright
 * Copyright 2016 - 2019 Deutsche Telekom AG.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <unistd.h>
#include <iostream>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>

#include <libyang/Tree_Data.hpp>

#include "Session.hpp"

#define MAX_LEN 100

using namespace std;

void
print_value(sysrepo::S_Val value)
{
    cout << value->xpath();
    cout << " ";
    switch (value->type()) {
    case SR_CONTAINER_T:
    case SR_CONTAINER_PRESENCE_T:
        cout << "(container)" << endl;
        break;
    case SR_LIST_T:
        cout << "(list instance)" << endl;
        break;
    case SR_STRING_T:
        cout << "= " << value->data()->get_string() << endl;;
        break;
    case SR_BOOL_T:
    if (value->data()->get_bool())
            cout << "= true" << endl;
    else
            cout << "= false" << endl;
        break;
    case SR_ENUM_T:
        cout << "= " << value->data()->get_enum() << endl;;
        break;
    case SR_UINT8_T:
        cout << "= " << unsigned(value->data()->get_uint8()) << endl;
        break;
    case SR_UINT16_T:
        cout << "= " << unsigned(value->data()->get_uint16()) << endl;
        break;
    case SR_UINT32_T:
        cout << "= " << unsigned(value->data()->get_uint32()) << endl;
        break;
    case SR_UINT64_T:
        cout << "= " << unsigned(value->data()->get_uint64()) << endl;
        break;
    case SR_INT8_T:
        cout << "= " << value->data()->get_int8() << endl;
        break;
    case SR_INT16_T:
        cout << "= " << value->data()->get_int16() << endl;
        break;
    case SR_INT32_T:
        cout << "= " << value->data()->get_int32() << endl;
        break;
    case SR_INT64_T:
        cout << "= " << value->data()->get_int64() << endl;
        break;
     case SR_IDENTITYREF_T:
        cout << "= " << value->data()->get_identityref() << endl;
        break;
    case SR_BITS_T:
        cout << "= " << value->data()->get_bits() << endl;
        break;
    case SR_BINARY_T:
        cout << "= " << value->data()->get_binary() << endl;
        break;
    default:
        cout << "(unprintable)" << endl;
    }
    return;
}

int
main(int argc, char **argv)
{
    const char *module_name = "test-examples";
    try {

        printf("Application will make an rpc call in %s\n", module_name);
        /* connect to sysrepo */
        auto conn = std::make_shared<sysrepo::Connection>();

        /* start session */
        auto sess = std::make_shared<sysrepo::Session>(conn);

        /* subscribe for changes in running config */
        auto subscribe = std::make_shared<sysrepo::Subscribe>(sess);
        auto cbVals = [](sysrepo::S_Session session, const char* op_path, const sysrepo::S_Vals input, sr_event_t event, uint32_t request_id, sysrepo::S_Vals_Holder output) {
            cout << "\n ========== RPC CALLED ==========\n" << endl;

            auto out_vals = output->allocate(3);

            for(size_t n = 0; n < input->val_cnt(); ++n)
                print_value(input->val(n));

            out_vals->val(0)->set("/test-examples:activate-software-image/status",
                    "The image acmefw-2.3 is being installed.",
                    SR_STRING_T);
            out_vals->val(1)->set("/test-examples:activate-software-image/version",
                    "2.3",
                    SR_STRING_T);
            out_vals->val(2)->set("/test-examples:activate-software-image/location",
                    "/root/",
                    SR_STRING_T);

            return SR_ERR_OK;
        };

        auto cbTree = [] (sysrepo::S_Session session, const char *op_path, const libyang::S_Data_Node input, sr_event_t event,
                uint32_t request_id, libyang::S_Data_Node output) {
            cout << "\n ========== RPC TREE CALLED ==========\n" << endl;
            cout << input->print_mem(LYD_XML, LYP_FORMAT);

            libyang::S_Context ctx = session->get_context();

            output->new_path(ctx, "status", "The image acmefw-2.3 is being installed.", LYD_ANYDATA_CONSTSTRING, LYD_PATH_OPT_OUTPUT);
            output->new_path(ctx, "version", "2.3", LYD_ANYDATA_CONSTSTRING, LYD_PATH_OPT_OUTPUT);
            output->new_path(ctx, "location", "/root/", LYD_ANYDATA_CONSTSTRING, LYD_PATH_OPT_OUTPUT);

            return SR_ERR_OK;
        };

        cout << "\n ========== SUBSCRIBE TO RPC CALL ==========\n" << endl;

        subscribe->rpc_subscribe("/test-examples:activate-software-image", cbVals);

        auto in_vals = std::make_shared<sysrepo::Vals>(2);

        in_vals->val(0)->set("/test-examples:activate-software-image/image-name",
                           "acmefw-2.3",
               SR_STRING_T);
        in_vals->val(1)->set("/test-examples:activate-software-image/location",
                           "/root/",
                           SR_STRING_T);

        cout << "\n ========== START RPC CALL ==========\n" << endl;
        auto out_vals = sess->rpc_send("/test-examples:activate-software-image", in_vals);

        cout << "\n ========== PRINT RETURN VALUE ==========\n" << endl;
        for(size_t n=0; n < out_vals->val_cnt(); ++n)
            print_value(out_vals->val(n));

        cout << "\n ========== SUBSCRIBE TO RPC TREE CALL ==========\n" << endl;
        subscribe->rpc_subscribe_tree("/test-examples:activate-software-image", cbTree, 0, SR_SUBSCR_CTX_REUSE);

        libyang::S_Context ctx = conn->get_context();
        libyang::S_Module mod = ctx->get_module(module_name);
        auto in_trees = std::make_shared<libyang::Data_Node>(ctx, "/test-examples:activate-software-image", nullptr, LYD_ANYDATA_CONSTSTRING, 0);
        std::make_shared<libyang::Data_Node>(libyang::Data_Node(in_trees, mod, "image-name", "acmefw-2.3"));
        std::make_shared<libyang::Data_Node>(libyang::Data_Node(in_trees, mod, "location", "/root/"));

        cout << "\n ========== START RPC TREE CALL ==========\n" << endl;
        auto out_trees = sess->rpc_send(in_trees);

        cout << "\n ========== PRINT RETURN VALUE ==========\n" << endl;
        cout << out_trees->print_mem(LYD_XML, LYP_FORMAT);

        cout << "\n ========== END PROGRAM ==========\n" << endl;
    } catch( const std::exception& e ) {
        cout << e.what() << endl;
        return -1;
    }
    return 0;
}
<commit_msg>bindings BUGFIX do not subscribe to an RPC twice with same priority<commit_after>/**
 * @file cpp_rpc_example.cpp
 * @author Mislav Novakovic <mislav.novakovic@sartura.hr>
 * @author Michal Vasko <mvasko@cesnet.cz>
 * @brief Example usage of rpc(), rpc_tree(), rpc_subscribe_tree(),
 * rpc_send() and others related to the Remote procedure call (RPC)
 * mechanism
 *
 * @copyright
 * Copyright 2016 - 2019 Deutsche Telekom AG.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <unistd.h>
#include <iostream>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>

#include <libyang/Tree_Data.hpp>

#include "Session.hpp"

#define MAX_LEN 100

using namespace std;

void
print_value(sysrepo::S_Val value)
{
    cout << value->xpath();
    cout << " ";
    switch (value->type()) {
    case SR_CONTAINER_T:
    case SR_CONTAINER_PRESENCE_T:
        cout << "(container)" << endl;
        break;
    case SR_LIST_T:
        cout << "(list instance)" << endl;
        break;
    case SR_STRING_T:
        cout << "= " << value->data()->get_string() << endl;;
        break;
    case SR_BOOL_T:
    if (value->data()->get_bool())
            cout << "= true" << endl;
    else
            cout << "= false" << endl;
        break;
    case SR_ENUM_T:
        cout << "= " << value->data()->get_enum() << endl;;
        break;
    case SR_UINT8_T:
        cout << "= " << unsigned(value->data()->get_uint8()) << endl;
        break;
    case SR_UINT16_T:
        cout << "= " << unsigned(value->data()->get_uint16()) << endl;
        break;
    case SR_UINT32_T:
        cout << "= " << unsigned(value->data()->get_uint32()) << endl;
        break;
    case SR_UINT64_T:
        cout << "= " << unsigned(value->data()->get_uint64()) << endl;
        break;
    case SR_INT8_T:
        cout << "= " << value->data()->get_int8() << endl;
        break;
    case SR_INT16_T:
        cout << "= " << value->data()->get_int16() << endl;
        break;
    case SR_INT32_T:
        cout << "= " << value->data()->get_int32() << endl;
        break;
    case SR_INT64_T:
        cout << "= " << value->data()->get_int64() << endl;
        break;
     case SR_IDENTITYREF_T:
        cout << "= " << value->data()->get_identityref() << endl;
        break;
    case SR_BITS_T:
        cout << "= " << value->data()->get_bits() << endl;
        break;
    case SR_BINARY_T:
        cout << "= " << value->data()->get_binary() << endl;
        break;
    default:
        cout << "(unprintable)" << endl;
    }
    return;
}

int
main(int argc, char **argv)
{
    const char *module_name = "test-examples";
    try {

        printf("Application will make an rpc call in %s\n", module_name);
        /* connect to sysrepo */
        auto conn = std::make_shared<sysrepo::Connection>();

        /* start session */
        auto sess = std::make_shared<sysrepo::Session>(conn);

        /* subscribe for changes in running config */
        auto subscribe = std::make_shared<sysrepo::Subscribe>(sess);
        auto cbVals = [](sysrepo::S_Session session, const char* op_path, const sysrepo::S_Vals input, sr_event_t event, uint32_t request_id, sysrepo::S_Vals_Holder output) {
            cout << "\n ========== RPC CALLED ==========\n" << endl;

            auto out_vals = output->allocate(3);

            for(size_t n = 0; n < input->val_cnt(); ++n)
                print_value(input->val(n));

            out_vals->val(0)->set("/test-examples:activate-software-image/status",
                    "The image acmefw-2.3 is being installed.",
                    SR_STRING_T);
            out_vals->val(1)->set("/test-examples:activate-software-image/version",
                    "2.3",
                    SR_STRING_T);
            out_vals->val(2)->set("/test-examples:activate-software-image/location",
                    "/root/",
                    SR_STRING_T);

            return SR_ERR_OK;
        };

        auto cbTree = [] (sysrepo::S_Session session, const char *op_path, const libyang::S_Data_Node input, sr_event_t event,
                uint32_t request_id, libyang::S_Data_Node output) {
            cout << "\n ========== RPC TREE CALLED ==========\n" << endl;
            cout << input->print_mem(LYD_XML, LYP_FORMAT);

            libyang::S_Context ctx = session->get_context();

            output->new_path(ctx, "status", "The image acmefw-2.3 is being installed.", LYD_ANYDATA_CONSTSTRING, LYD_PATH_OPT_OUTPUT);
            output->new_path(ctx, "version", "2.3", LYD_ANYDATA_CONSTSTRING, LYD_PATH_OPT_OUTPUT);
            output->new_path(ctx, "location", "/root/", LYD_ANYDATA_CONSTSTRING, LYD_PATH_OPT_OUTPUT);

            return SR_ERR_OK;
        };

        cout << "\n ========== SUBSCRIBE TO RPC CALL ==========\n" << endl;

        subscribe->rpc_subscribe("/test-examples:activate-software-image", cbVals, 1);

        auto in_vals = std::make_shared<sysrepo::Vals>(2);

        in_vals->val(0)->set("/test-examples:activate-software-image/image-name",
                           "acmefw-2.3",
               SR_STRING_T);
        in_vals->val(1)->set("/test-examples:activate-software-image/location",
                           "/root/",
                           SR_STRING_T);

        cout << "\n ========== START RPC CALL ==========\n" << endl;
        auto out_vals = sess->rpc_send("/test-examples:activate-software-image", in_vals);

        cout << "\n ========== PRINT RETURN VALUE ==========\n" << endl;
        for(size_t n=0; n < out_vals->val_cnt(); ++n)
            print_value(out_vals->val(n));

        cout << "\n ========== SUBSCRIBE TO RPC TREE CALL ==========\n" << endl;
        subscribe->rpc_subscribe_tree("/test-examples:activate-software-image", cbTree, 0, SR_SUBSCR_CTX_REUSE);

        libyang::S_Context ctx = conn->get_context();
        libyang::S_Module mod = ctx->get_module(module_name);
        auto in_trees = std::make_shared<libyang::Data_Node>(ctx, "/test-examples:activate-software-image", nullptr, LYD_ANYDATA_CONSTSTRING, 0);
        std::make_shared<libyang::Data_Node>(libyang::Data_Node(in_trees, mod, "image-name", "acmefw-2.3"));
        std::make_shared<libyang::Data_Node>(libyang::Data_Node(in_trees, mod, "location", "/root/"));

        cout << "\n ========== START RPC TREE CALL ==========\n" << endl;
        auto out_trees = sess->rpc_send(in_trees);

        cout << "\n ========== PRINT RETURN VALUE ==========\n" << endl;
        cout << out_trees->print_mem(LYD_XML, LYP_FORMAT);

        cout << "\n ========== END PROGRAM ==========\n" << endl;
    } catch( const std::exception& e ) {
        cout << e.what() << endl;
        return -1;
    }
    return 0;
}
<|endoftext|>