<commit_before>/*************************************************************************
 *
 *  $RCSfile: AccessibleDrawDocumentView.hxx,v $
 *
 *  $Revision: 1.1 $
 *
 *  last change: $Author: af $ $Date: 2002-04-18 17:51:21 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SD_ACCESSIBILITY_ACCESSIBLE_DRAW_DOCUMENT_VIEW_HXX
#define _SD_ACCESSIBILITY_ACCESSIBLE_DRAW_DOCUMENT_VIEW_HXX

#ifndef _SD_ACCESSIBILITY_ACCESSIBLE_DOCUMENT_VIEW_BASE_HXX
#include "AccessibleDocumentViewBase.hxx"
#endif

namespace accessibility {

/** @descr
        This class implements the UAA for views of Draw and Impress
        documents.
*/
class AccessibleDrawDocumentView
    :   public AccessibleDocumentViewBase
{
public:
    //=====  internal  ========================================================
    AccessibleDrawDocumentView (SdWindow* pSdWindow,
        SdViewShell* pViewShell,
        const ::com::sun::star::uno::Reference<
        ::com::sun::star::frame::XController>& rxController,
        const ::com::sun::star::uno::Reference<
        ::drafts::com::sun::star::accessibility::XAccessible>& rxParent);

    virtual ~AccessibleDrawDocumentView (void);

    void Init (void);

    //=====  IAccessibleViewForwarderListener  ================================
    virtual void ViewForwarderChanged (ChangeType aChangeType,
        const IAccessibleViewForwarder* pViewForwarder);

    //=====  XAccessibleContext  ==============================================

    virtual sal_Int32 SAL_CALL
        getAccessibleChildCount (void)
        throw (::com::sun::star::uno::RuntimeException);

    virtual ::com::sun::star::uno::Reference< ::drafts::com::sun::star::accessibility::XAccessible> SAL_CALL
        getAccessibleChild (long nIndex)
        throw (::com::sun::star::uno::RuntimeException);

    //=====  XServiceInfo  ====================================================

    /** Returns an identifier for the implementation of this object.
    */
    virtual ::rtl::OUString SAL_CALL
        getImplementationName (void)
        throw (::com::sun::star::uno::RuntimeException);

    //=====  lang::XEventListener  ============================================

    virtual void SAL_CALL
        disposing (const ::com::sun::star::lang::EventObject& rEventObject)
        throw (::com::sun::star::uno::RuntimeException);

    //=====  XFrameActionListener  ============================================

    virtual void SAL_CALL
        frameAction (const ::com::sun::star::frame::FrameActionEvent& rEventObject)
        throw (::com::sun::star::uno::RuntimeException);

    //=====  XPropertyChangeListener  =========================================

    virtual void SAL_CALL
        propertyChange (const ::com::sun::star::beans::PropertyChangeEvent& rEventObject)
        throw (::com::sun::star::uno::RuntimeException);

protected:
    // The visible children of the document view.
    ChildrenManager* mpChildrenManager;

    /// Model of the document.
    com::sun::star::uno::Reference < ::drafts::com::sun::star::accessibility::XAccessible>
        mxPageShape;

    /** Update the draw page shape.  If a draw page shape does not yet exist
        it is created.
    */
    AccessiblePageShape* UpdateDrawPageShape (void);

    /// Set this object's name if is different to the current name.
    virtual ::rtl::OUString
        CreateAccessibleName ()
        throw (::com::sun::star::uno::RuntimeException);

    /// Set this object's description if is different to the current description.
    virtual ::rtl::OUString
        CreateAccessibleDescription ()
        throw (::com::sun::star::uno::RuntimeException);
};

} // end of namespace accessibility

#endif
<commit_msg>#95585# Enhanced the documentation a little.<commit_after>/*************************************************************************
 *
 *  $RCSfile: AccessibleDrawDocumentView.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: af $ $Date: 2002-04-22 08:32:27 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SD_ACCESSIBILITY_ACCESSIBLE_DRAW_DOCUMENT_VIEW_HXX
#define _SD_ACCESSIBILITY_ACCESSIBLE_DRAW_DOCUMENT_VIEW_HXX

#ifndef _SD_ACCESSIBILITY_ACCESSIBLE_DOCUMENT_VIEW_BASE_HXX
#include "AccessibleDocumentViewBase.hxx"
#endif

namespace accessibility {

/** This class makes draw documents in the general view modes
    accessible.  It passes all shapes on the current draw page to a
    children manager and additionally creates a new shape that
    represents the actual draw page.

    Please see the documentation of the base class for further
    explanations of the individual methods.
*/
class AccessibleDrawDocumentView
    : public AccessibleDocumentViewBase
{
public:
    //=====  internal  ========================================================

    AccessibleDrawDocumentView (SdWindow* pSdWindow,
        SdViewShell* pViewShell,
        const ::com::sun::star::uno::Reference<
        ::com::sun::star::frame::XController>& rxController,
        const ::com::sun::star::uno::Reference<
        ::drafts::com::sun::star::accessibility::XAccessible>& rxParent);

    virtual ~AccessibleDrawDocumentView (void);

    /** Complete the initialization begun in the constructor.
    */
    virtual void Init (void);

    //=====  IAccessibleViewForwarderListener  ================================

    virtual void ViewForwarderChanged (ChangeType aChangeType,
        const IAccessibleViewForwarder* pViewForwarder);

    //=====  XAccessibleContext  ==============================================

    virtual sal_Int32 SAL_CALL
        getAccessibleChildCount (void)
        throw (::com::sun::star::uno::RuntimeException);

    virtual ::com::sun::star::uno::Reference< ::drafts::com::sun::star::accessibility::XAccessible> SAL_CALL
        getAccessibleChild (long nIndex)
        throw (::com::sun::star::uno::RuntimeException);

    //=====  XServiceInfo  ====================================================

    /** Returns an identifier for the implementation of this object.
    */
    virtual ::rtl::OUString SAL_CALL
        getImplementationName (void)
        throw (::com::sun::star::uno::RuntimeException);

    //=====  lang::XEventListener  ============================================

    virtual void SAL_CALL
        disposing (const ::com::sun::star::lang::EventObject& rEventObject)
        throw (::com::sun::star::uno::RuntimeException);

    //=====  XFrameActionListener  ============================================

    virtual void SAL_CALL
        frameAction (const ::com::sun::star::frame::FrameActionEvent& rEventObject)
        throw (::com::sun::star::uno::RuntimeException);

    //=====  XPropertyChangeListener  =========================================

    virtual void SAL_CALL
        propertyChange (const ::com::sun::star::beans::PropertyChangeEvent& rEventObject)
        throw (::com::sun::star::uno::RuntimeException);

protected:
    /** This object manages the shapes of the represented draw page.  It is
        responsible to determine the visible shapes and create on demand the
        accessible objects representing them.
    */
    ChildrenManager* mpChildrenManager;

    /** Create a shape the represents the page as seen on the screen.
    */
    AccessiblePageShape* CreateDrawPageShape (void);

    /// Create an accessible name that contains the current view mode.
    virtual ::rtl::OUString
        CreateAccessibleName ()
        throw (::com::sun::star::uno::RuntimeException);

    /// Create an accessible description that contains the current
    /// view mode.
    virtual ::rtl::OUString
        CreateAccessibleDescription ()
        throw (::com::sun::star::uno::RuntimeException);
};

} // end of namespace accessibility

#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: TaskPaneShellManager.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: kz $ $Date: 2006-12-12 18:42:43 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sd.hxx"

#include "TaskPaneShellManager.hxx"

#include "ViewShellManager.hxx"
#include <osl/diagnose.h>
#include <vcl/window.hxx>

#include <algorithm>

namespace sd { namespace toolpanel {

TaskPaneShellManager::TaskPaneShellManager (
    ViewShellManager& rViewShellManager,
    const ViewShell& rViewShell)
    : mrViewShellManager(rViewShellManager),
      mrViewShell(rViewShell),
      maSubShells()
{
}

TaskPaneShellManager::~TaskPaneShellManager (void)
{
    while ( ! maSubShells.empty())
        RemoveSubShell(maSubShells.begin()->second.mpShell);
}

SfxShell* TaskPaneShellManager::CreateShell( ShellId nId, ::Window* , FrameView* )
{
    SubShells::const_iterator iShell (maSubShells.find(nId));
    if (iShell != maSubShells.end())
        return iShell->second.mpShell;
    else
        return NULL;
}

void TaskPaneShellManager::ReleaseShell (SfxShell* )
{
    // Nothing to do.
}

void TaskPaneShellManager::AddSubShell (
    ShellId nId,
    SfxShell* pShell,
    ::Window* pWindow)
{
    if (pShell != NULL)
    {
        maSubShells[nId] = ShellDescriptor(pShell,pWindow);
        if (pWindow != NULL)
        {
            pWindow->AddEventListener(LINK(this,TaskPaneShellManager,WindowCallback));
            if (pWindow->IsReallyVisible())
                mrViewShellManager.ActivateSubShell(mrViewShell, nId);
        }
        else
            mrViewShellManager.ActivateSubShell(mrViewShell, nId);
    }
}

void TaskPaneShellManager::RemoveSubShell (const SfxShell* pShell)
{
    if (pShell != NULL)
    {
        SubShells::iterator iShell;
        for (iShell=maSubShells.begin(); iShell!=maSubShells.end(); ++iShell)
            if (iShell->second.mpShell == pShell)
            {
                if (iShell->second.mpWindow != NULL)
                    iShell->second.mpWindow->RemoveEventListener(
                        LINK(this,TaskPaneShellManager,WindowCallback));
                mrViewShellManager.DeactivateSubShell(mrViewShell,iShell->first);
                maSubShells.erase(iShell);
                break;
            }
    }
}

void TaskPaneShellManager::MoveToTop (SfxShell* pShell)
{
    SubShells::const_iterator iShell;
    for (iShell=maSubShells.begin(); iShell!=maSubShells.end(); ++iShell)
        if (iShell->second.mpShell == pShell)
        {
            ViewShellManager::UpdateLock aLocker (mrViewShellManager);
            mrViewShellManager.MoveSubShellToTop(mrViewShell,iShell->first);
            mrViewShellManager.MoveToTop(mrViewShell);
            break;
        }
}

IMPL_LINK(TaskPaneShellManager, WindowCallback, VclWindowEvent*, pEvent)
{
    if (pEvent != NULL)
    {
        SubShells::const_iterator iShell;
        ::Window* pWindow = pEvent->GetWindow();
        for (iShell=maSubShells.begin(); iShell!=maSubShells.end(); ++iShell)
            if (iShell->second.mpWindow == pWindow)
                break;
        if (iShell != maSubShells.end())
            switch (pEvent->GetId())
            {
                case VCLEVENT_WINDOW_SHOW:
                    mrViewShellManager.ActivateSubShell(mrViewShell,iShell->first);
                    break;

                case VCLEVENT_WINDOW_HIDE:
                    // Do not activate the sub shell.  This leads to
                    // problems with shapes currently being in text edit
                    // mode: Deactivating the shell leads to leaving the
                    // text editing mode.
                    // mrViewShellManager.DeactivateSubShell(mrViewShell,iShell->first);
                    break;
            }
    }

    return 0;
}

} } // end of namespace ::sd::toolpanel
<commit_msg>INTEGRATION: CWS presenterview (1.9.54); FILE MERGED 2007/07/10 15:03:01 af 1.9.54.1: #i18486# Converted several members of ViewShellBase to shared_ptrs.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: TaskPaneShellManager.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: kz $ $Date: 2008-04-03 14:47:04 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sd.hxx"

#include "TaskPaneShellManager.hxx"

#include "ViewShellManager.hxx"
#include <osl/diagnose.h>
#include <vcl/window.hxx>

#include <algorithm>

namespace sd { namespace toolpanel {

TaskPaneShellManager::TaskPaneShellManager (
    const ::boost::shared_ptr<ViewShellManager>& rpViewShellManager,
    const ViewShell& rViewShell)
    : mpViewShellManager(rpViewShellManager),
      mrViewShell(rViewShell),
      maSubShells()
{
}

TaskPaneShellManager::~TaskPaneShellManager (void)
{
    while ( ! maSubShells.empty())
        RemoveSubShell(maSubShells.begin()->second.mpShell);
}

SfxShell* TaskPaneShellManager::CreateShell( ShellId nId, ::Window* , FrameView* )
{
    SubShells::const_iterator iShell (maSubShells.find(nId));
    if (iShell != maSubShells.end())
        return iShell->second.mpShell;
    else
        return NULL;
}

void TaskPaneShellManager::ReleaseShell (SfxShell* )
{
    // Nothing to do.
}

void TaskPaneShellManager::AddSubShell (
    ShellId nId,
    SfxShell* pShell,
    ::Window* pWindow)
{
    if (pShell != NULL)
    {
        maSubShells[nId] = ShellDescriptor(pShell,pWindow);
        if (pWindow != NULL)
        {
            pWindow->AddEventListener(LINK(this,TaskPaneShellManager,WindowCallback));
            if (pWindow->IsReallyVisible())
                mpViewShellManager->ActivateSubShell(mrViewShell, nId);
        }
        else
            mpViewShellManager->ActivateSubShell(mrViewShell, nId);
    }
}

void TaskPaneShellManager::RemoveSubShell (const SfxShell* pShell)
{
    if (pShell != NULL)
    {
        SubShells::iterator iShell;
        for (iShell=maSubShells.begin(); iShell!=maSubShells.end(); ++iShell)
            if (iShell->second.mpShell == pShell)
            {
                if (iShell->second.mpWindow != NULL)
                    iShell->second.mpWindow->RemoveEventListener(
                        LINK(this,TaskPaneShellManager,WindowCallback));
                mpViewShellManager->DeactivateSubShell(mrViewShell,iShell->first);
                maSubShells.erase(iShell);
                break;
            }
    }
}

void TaskPaneShellManager::MoveToTop (SfxShell* pShell)
{
    SubShells::const_iterator iShell;
    for (iShell=maSubShells.begin(); iShell!=maSubShells.end(); ++iShell)
        if (iShell->second.mpShell == pShell)
        {
            ViewShellManager::UpdateLock aLocker (mpViewShellManager);
            mpViewShellManager->MoveSubShellToTop(mrViewShell,iShell->first);
            mpViewShellManager->MoveToTop(mrViewShell);
            break;
        }
}

IMPL_LINK(TaskPaneShellManager, WindowCallback, VclWindowEvent*, pEvent)
{
    if (pEvent != NULL)
    {
        SubShells::const_iterator iShell;
        ::Window* pWindow = pEvent->GetWindow();
        for (iShell=maSubShells.begin(); iShell!=maSubShells.end(); ++iShell)
            if (iShell->second.mpWindow == pWindow)
                break;
        if (iShell != maSubShells.end())
            switch (pEvent->GetId())
            {
                case VCLEVENT_WINDOW_SHOW:
                    mpViewShellManager->ActivateSubShell(mrViewShell,iShell->first);
                    break;

                case VCLEVENT_WINDOW_HIDE:
                    // Do not activate the sub shell.  This leads to
                    // problems with shapes currently being in text edit
                    // mode: Deactivating the shell leads to leaving the
                    // text editing mode.
                    // mpViewShellManager->DeactivateSubShell(mrViewShell,iShell->first);
                    break;
            }
    }

    return 0;
}

} } // end of namespace ::sd::toolpanel
<|endoftext|>


<commit_before>/*
 *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "sdk/android/native_api/stacktrace/stacktrace.h"

#include <dlfcn.h>
#include <errno.h>
#include <linux/futex.h>
#include <sys/ptrace.h>
#include <sys/ucontext.h>
#include <syscall.h>
#include <ucontext.h>
#include <unistd.h>
#include <unwind.h>
#include <atomic>

// ptrace.h is polluting the namespace. Clean up to avoid conflicts with rtc.
#if defined(DS)
#undef DS
#endif

#include "absl/base/attributes.h"
#include "rtc_base/critical_section.h"
#include "rtc_base/logging.h"
#include "rtc_base/strings/string_builder.h"

namespace webrtc {

namespace {

// Maximum stack trace depth we allow before aborting.
constexpr size_t kMaxStackSize = 100;
// Signal that will be used to interrupt threads. SIGURG ("Urgent condition on
// socket") is chosen because Android does not set up a specific handler for
// this signal.
constexpr int kSignal = SIGURG;

// Note: This class is only meant for use within this file, and for the
// simplified use case of a single Wait() and a single Signal(), followed by
// discarding the object (never reused).
// This is a replacement of rtc::Event that is async-safe and doesn't use
// pthread api. This is necessary since signal handlers cannot allocate memory
// or use pthread api. This class is ported from Chromium.
class AsyncSafeWaitableEvent {
 public:
  AsyncSafeWaitableEvent() {
    std::atomic_store_explicit(&futex_, 0, std::memory_order_release);
  }

  ~AsyncSafeWaitableEvent() {}

  // Returns false in the event of an error and errno is set to indicate the
  // cause of the error.
  bool Wait() {
    // futex() can wake up spuriously if this memory address was previously used
    // for a pthread mutex. So, also check the condition.
    while (true) {
      int res = syscall(SYS_futex, &futex_, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0,
                        nullptr, nullptr, 0);
      if (std::atomic_load_explicit(&futex_, std::memory_order_acquire) != 0)
        return true;
      if (res != 0)
        return false;
    }
  }

  void Signal() {
    std::atomic_store_explicit(&futex_, 1, std::memory_order_release);
    syscall(SYS_futex, &futex_, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1, nullptr,
            nullptr, 0);
  }

 private:
  std::atomic<int> futex_;
};

// Struct to store the arguments to the signal handler.
struct SignalHandlerOutputState {
  // This event is signalled when signal handler is done executing.
  AsyncSafeWaitableEvent signal_handler_finish_event;
  // Running counter of array index below.
  size_t stack_size_counter = 0;
  // Array storing the stack trace.
  uintptr_t addresses[kMaxStackSize];
};

// Global lock to ensure only one thread gets interrupted at a time.
ABSL_CONST_INIT rtc::GlobalLock g_signal_handler_lock;
// Argument passed to the ThreadSignalHandler() from the sampling thread to the
// sampled (stopped) thread. This value is set just before sending signal to the
// thread and reset when handler is done.
SignalHandlerOutputState* volatile g_signal_handler_output_state;

// This function is called iteratively for each stack trace element and stores
// the element in the array from |unwind_output_state|.
_Unwind_Reason_Code UnwindBacktrace(struct _Unwind_Context* unwind_context,
                                    void* unwind_output_state) {
  SignalHandlerOutputState* const output_state =
      static_cast<SignalHandlerOutputState*>(unwind_output_state);

  // Avoid overflowing the stack trace array.
  if (output_state->stack_size_counter >= kMaxStackSize)
    return _URC_END_OF_STACK;

  // Store the instruction pointer in the array. Subtract 2 since we want to get
  // the call instruction pointer, not the return address which is the
  // instruction after.
  output_state->addresses[output_state->stack_size_counter] =
      _Unwind_GetIP(unwind_context) - 2;
  ++output_state->stack_size_counter;

  return _URC_NO_REASON;
}

// This signal handler is exectued on the interrupted thread.
void SignalHandler(int signum, siginfo_t* info, void* ptr) {
  _Unwind_Backtrace(&UnwindBacktrace, g_signal_handler_output_state);
  g_signal_handler_output_state->signal_handler_finish_event.Signal();
}

// Temporarily change the signal handler to a function that records a raw stack
// trace and interrupt the given tid. This function will block until the output
// thread stack trace has been stored in |params|. The return value is an error
// string on failure and null on success.
const char* CaptureRawStacktrace(int pid,
                                 int tid,
                                 SignalHandlerOutputState* params) {
  // This function is under a global lock since we are changing the signal
  // handler and using global state for the output. The lock is to ensure only
  // one thread at a time gets captured. The lock also means we need to be very
  // careful with what statements we put in this function, and we should even
  // avoid logging here.
  struct sigaction act;
  struct sigaction old_act;
  memset(&act, 0, sizeof(act));
  act.sa_sigaction = &SignalHandler;
  act.sa_flags = SA_RESTART | SA_SIGINFO;
  sigemptyset(&act.sa_mask);

  rtc::GlobalLockScope ls(&g_signal_handler_lock);
  g_signal_handler_output_state = params;

  if (sigaction(kSignal, &act, &old_act) != 0)
    return "Failed to change signal action";

  // Interrupt the thread which will execute SignalHandler() on the given
  // thread.
  if (tgkill(pid, tid, kSignal) != 0)
    return "Failed to interrupt thread";

  // Wait until the thread is done recording its stack trace.
  if (!params->signal_handler_finish_event.Wait())
    return "Failed to wait for thread to finish stack trace";

  // Restore previous signal handler.
  sigaction(kSignal, &old_act, /* old_act= */ nullptr);

  return nullptr;
}

// Translate addresses into symbolic information using dladdr().
std::vector<StackTraceElement> FormatStackTrace(
    const SignalHandlerOutputState& params) {
  std::vector<StackTraceElement> stack_trace;
  for (size_t i = 0; i < params.stack_size_counter; ++i) {
    const uintptr_t address = params.addresses[i];

    Dl_info dl_info = {};
    if (!dladdr(reinterpret_cast<void*>(address), &dl_info)) {
      RTC_LOG(LS_WARNING)
          << "Could not translate address to symbolic information for address "
          << address << " at stack depth " << i;
      continue;
    }

    StackTraceElement stack_trace_element;
    stack_trace_element.shared_object_path = dl_info.dli_fname;
    stack_trace_element.relative_address = static_cast<uint32_t>(
        address - reinterpret_cast<uintptr_t>(dl_info.dli_fbase));
    stack_trace_element.symbol_name = dl_info.dli_sname;

    stack_trace.push_back(stack_trace_element);
  }

  return stack_trace;
}

}  // namespace

std::vector<StackTraceElement> GetStackTrace(int tid) {
  // Only a thread itself can unwind its stack, so we will interrupt the given
  // tid with a custom signal handler in order to unwind its stack. The stack
  // will be recorded to |params| through the use of the global pointer
  // |g_signal_handler_param|.
  SignalHandlerOutputState params;

  const char* error_string = CaptureRawStacktrace(getpid(), tid, &params);
  if (error_string != nullptr) {
    RTC_LOG(LS_ERROR) << error_string << ". tid: " << tid
                      << ". errno: " << errno;
    return {};
  }
  if (params.stack_size_counter >= kMaxStackSize) {
    RTC_LOG(LS_WARNING) << "Stack trace for thread " << tid << " was truncated";
  }
  return FormatStackTrace(params);
}

std::vector<StackTraceElement> GetStackTrace() {
  SignalHandlerOutputState params;
  _Unwind_Backtrace(&UnwindBacktrace, &params);
  if (params.stack_size_counter >= kMaxStackSize) {
    RTC_LOG(LS_WARNING) << "Stack trace was truncated";
  }
  return FormatStackTrace(params);
}

std::string StackTraceToString(
    const std::vector<StackTraceElement>& stack_trace) {
  rtc::StringBuilder string_builder;

  for (size_t i = 0; i < stack_trace.size(); ++i) {
    const StackTraceElement& stack_trace_element = stack_trace[i];
    string_builder.AppendFormat(
        "#%02zu pc %08x %s", i,
        static_cast<uint32_t>(stack_trace_element.relative_address),
        stack_trace_element.shared_object_path);
    // The symbol name is only available for unstripped .so files.
    if (stack_trace_element.symbol_name != nullptr)
      string_builder.AppendFormat(" %s", stack_trace_element.symbol_name);

    string_builder.AppendFormat("\n");
  }

  return string_builder.Release();
}

}  // namespace webrtc
<commit_msg>Add null checks in stacktrace.cc<commit_after>/*
 *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "sdk/android/native_api/stacktrace/stacktrace.h"

#include <dlfcn.h>
#include <errno.h>
#include <linux/futex.h>
#include <sys/ptrace.h>
#include <sys/ucontext.h>
#include <syscall.h>
#include <ucontext.h>
#include <unistd.h>
#include <unwind.h>
#include <atomic>

// ptrace.h is polluting the namespace. Clean up to avoid conflicts with rtc.
#if defined(DS)
#undef DS
#endif

#include "absl/base/attributes.h"
#include "rtc_base/critical_section.h"
#include "rtc_base/logging.h"
#include "rtc_base/strings/string_builder.h"

namespace webrtc {

namespace {

// Maximum stack trace depth we allow before aborting.
constexpr size_t kMaxStackSize = 100;
// Signal that will be used to interrupt threads. SIGURG ("Urgent condition on
// socket") is chosen because Android does not set up a specific handler for
// this signal.
constexpr int kSignal = SIGURG;

// Note: This class is only meant for use within this file, and for the
// simplified use case of a single Wait() and a single Signal(), followed by
// discarding the object (never reused).
// This is a replacement of rtc::Event that is async-safe and doesn't use
// pthread api. This is necessary since signal handlers cannot allocate memory
// or use pthread api. This class is ported from Chromium.
class AsyncSafeWaitableEvent {
 public:
  AsyncSafeWaitableEvent() {
    std::atomic_store_explicit(&futex_, 0, std::memory_order_release);
  }

  ~AsyncSafeWaitableEvent() {}

  // Returns false in the event of an error and errno is set to indicate the
  // cause of the error.
  bool Wait() {
    // futex() can wake up spuriously if this memory address was previously used
    // for a pthread mutex. So, also check the condition.
    while (true) {
      int res = syscall(SYS_futex, &futex_, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0,
                        nullptr, nullptr, 0);
      if (std::atomic_load_explicit(&futex_, std::memory_order_acquire) != 0)
        return true;
      if (res != 0)
        return false;
    }
  }

  void Signal() {
    std::atomic_store_explicit(&futex_, 1, std::memory_order_release);
    syscall(SYS_futex, &futex_, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1, nullptr,
            nullptr, 0);
  }

 private:
  std::atomic<int> futex_;
};

// Struct to store the arguments to the signal handler.
struct SignalHandlerOutputState {
  // This event is signalled when signal handler is done executing.
  AsyncSafeWaitableEvent signal_handler_finish_event;
  // Running counter of array index below.
  size_t stack_size_counter = 0;
  // Array storing the stack trace.
  uintptr_t addresses[kMaxStackSize];
};

// Global lock to ensure only one thread gets interrupted at a time.
ABSL_CONST_INIT rtc::GlobalLock g_signal_handler_lock;
// Argument passed to the ThreadSignalHandler() from the sampling thread to the
// sampled (stopped) thread. This value is set just before sending signal to the
// thread and reset when handler is done.
SignalHandlerOutputState* volatile g_signal_handler_output_state;

// This function is called iteratively for each stack trace element and stores
// the element in the array from |unwind_output_state|.
_Unwind_Reason_Code UnwindBacktrace(struct _Unwind_Context* unwind_context,
                                    void* unwind_output_state) {
  SignalHandlerOutputState* const output_state =
      static_cast<SignalHandlerOutputState*>(unwind_output_state);

  // Abort if output state is corrupt.
  if (output_state == nullptr)
    return _URC_END_OF_STACK;

  // Avoid overflowing the stack trace array.
  if (output_state->stack_size_counter >= kMaxStackSize)
    return _URC_END_OF_STACK;

  // Store the instruction pointer in the array. Subtract 2 since we want to get
  // the call instruction pointer, not the return address which is the
  // instruction after.
  output_state->addresses[output_state->stack_size_counter] =
      _Unwind_GetIP(unwind_context) - 2;
  ++output_state->stack_size_counter;

  return _URC_NO_REASON;
}

// This signal handler is exectued on the interrupted thread.
void SignalHandler(int signum, siginfo_t* info, void* ptr) {
  // This should have been set by the thread requesting the stack trace.
  SignalHandlerOutputState* signal_handler_output_state =
      g_signal_handler_output_state;
  if (signal_handler_output_state != nullptr) {
    _Unwind_Backtrace(&UnwindBacktrace, signal_handler_output_state);
    signal_handler_output_state->signal_handler_finish_event.Signal();
  }
}

// Temporarily change the signal handler to a function that records a raw stack
// trace and interrupt the given tid. This function will block until the output
// thread stack trace has been stored in |params|. The return value is an error
// string on failure and null on success.
const char* CaptureRawStacktrace(int pid,
                                 int tid,
                                 SignalHandlerOutputState* params) {
  // This function is under a global lock since we are changing the signal
  // handler and using global state for the output. The lock is to ensure only
  // one thread at a time gets captured. The lock also means we need to be very
  // careful with what statements we put in this function, and we should even
  // avoid logging here.
  struct sigaction act;
  struct sigaction old_act;
  memset(&act, 0, sizeof(act));
  act.sa_sigaction = &SignalHandler;
  act.sa_flags = SA_RESTART | SA_SIGINFO;
  sigemptyset(&act.sa_mask);

  rtc::GlobalLockScope ls(&g_signal_handler_lock);
  g_signal_handler_output_state = params;

  if (sigaction(kSignal, &act, &old_act) != 0)
    return "Failed to change signal action";

  // Interrupt the thread which will execute SignalHandler() on the given
  // thread.
  if (tgkill(pid, tid, kSignal) != 0)
    return "Failed to interrupt thread";

  // Wait until the thread is done recording its stack trace.
  if (!params->signal_handler_finish_event.Wait())
    return "Failed to wait for thread to finish stack trace";

  // Restore previous signal handler.
  sigaction(kSignal, &old_act, /* old_act= */ nullptr);

  return nullptr;
}

// Translate addresses into symbolic information using dladdr().
std::vector<StackTraceElement> FormatStackTrace(
    const SignalHandlerOutputState& params) {
  std::vector<StackTraceElement> stack_trace;
  for (size_t i = 0; i < params.stack_size_counter; ++i) {
    const uintptr_t address = params.addresses[i];

    Dl_info dl_info = {};
    if (!dladdr(reinterpret_cast<void*>(address), &dl_info)) {
      RTC_LOG(LS_WARNING)
          << "Could not translate address to symbolic information for address "
          << address << " at stack depth " << i;
      continue;
    }

    StackTraceElement stack_trace_element;
    stack_trace_element.shared_object_path = dl_info.dli_fname;
    stack_trace_element.relative_address = static_cast<uint32_t>(
        address - reinterpret_cast<uintptr_t>(dl_info.dli_fbase));
    stack_trace_element.symbol_name = dl_info.dli_sname;

    stack_trace.push_back(stack_trace_element);
  }

  return stack_trace;
}

}  // namespace

std::vector<StackTraceElement> GetStackTrace(int tid) {
  // Only a thread itself can unwind its stack, so we will interrupt the given
  // tid with a custom signal handler in order to unwind its stack. The stack
  // will be recorded to |params| through the use of the global pointer
  // |g_signal_handler_param|.
  SignalHandlerOutputState params;

  const char* error_string = CaptureRawStacktrace(getpid(), tid, &params);
  if (error_string != nullptr) {
    RTC_LOG(LS_ERROR) << error_string << ". tid: " << tid
                      << ". errno: " << errno;
    return {};
  }
  if (params.stack_size_counter >= kMaxStackSize) {
    RTC_LOG(LS_WARNING) << "Stack trace for thread " << tid << " was truncated";
  }
  return FormatStackTrace(params);
}

std::vector<StackTraceElement> GetStackTrace() {
  SignalHandlerOutputState params;
  _Unwind_Backtrace(&UnwindBacktrace, &params);
  if (params.stack_size_counter >= kMaxStackSize) {
    RTC_LOG(LS_WARNING) << "Stack trace was truncated";
  }
  return FormatStackTrace(params);
}

std::string StackTraceToString(
    const std::vector<StackTraceElement>& stack_trace) {
  rtc::StringBuilder string_builder;

  for (size_t i = 0; i < stack_trace.size(); ++i) {
    const StackTraceElement& stack_trace_element = stack_trace[i];
    string_builder.AppendFormat(
        "#%02zu pc %08x %s", i,
        static_cast<uint32_t>(stack_trace_element.relative_address),
        stack_trace_element.shared_object_path);
    // The symbol name is only available for unstripped .so files.
    if (stack_trace_element.symbol_name != nullptr)
      string_builder.AppendFormat(" %s", stack_trace_element.symbol_name);

    string_builder.AppendFormat("\n");
  }

  return string_builder.Release();
}

}  // namespace webrtc
<|endoftext|>


<commit_before>#pragma once

#include <hop_bits/optimisationAlgorithm.hpp>

namespace hop {
  class CovarianceMatrixAdaptationEvolutionStrategy : public OptimisationAlgorithm {
    public:
      //TODO: which input parameters should be added to the constructor?
      explicit CovarianceMatrixAdaptationEvolutionStrategy(const std::shared_ptr<OptimisationProblem> optimisationProblem);

      CovarianceMatrixAdaptationEvolutionStrategy(const CovarianceMatrixAdaptationEvolutionStrategy&) = delete;
      CovarianceMatrixAdaptationEvolutionStrategy& operator=(const CovarianceMatrixAdaptationEvolutionStrategy&) = delete;

      std::string to_string() const override;

    protected:
      void optimiseImplementation() override;
      //input parameters
      int numberOfDimensions_; //N
      arma::Col<double> objectiveValues_; //xmean
	  double sigma_;
      double stopValue_; //stopfitness

      //selection parameters
      int lambda_;
	  double mu_;
      arma::Col<double> weights_;
      double mueff_;

      //adaptation parameters
	  double cc_;
	  double cs_;
	  double c1_;
	  double cmu_;
	  double damps_;

      //dynamic parameters and constants
	  arma::Col<double> pc_;
	  arma::Col<double> ps_;
	  arma::Mat<double> B_;
      arma::Mat<double> D_;
	  arma::Mat<double> C_;
	  arma::Mat<double> invsqrtC_;
	  double eigeneval_;
	  double chiN_;

      //function to use
      double frosenbrock(arma::Col<double> x);
  };
}
<commit_msg>devel: Simple style changes<commit_after>#pragma once

#include <hop_bits/optimisationAlgorithm.hpp>

namespace hop {
  class CovarianceMatrixAdaptationEvolutionStrategy : public OptimisationAlgorithm {
    public:
      //TODO: which input parameters should be added to the constructor?
      explicit CovarianceMatrixAdaptationEvolutionStrategy(
      	const std::shared_ptr<OptimisationProblem> optimisationProblem);

      CovarianceMatrixAdaptationEvolutionStrategy(const CovarianceMatrixAdaptationEvolutionStrategy&) = delete;
      CovarianceMatrixAdaptationEvolutionStrategy& operator=(const CovarianceMatrixAdaptationEvolutionStrategy&) = delete;

      std::string to_string() const override;

    protected:
      void optimiseImplementation() override;
      // input parameters
      // N
      unsigned int numberOfDimensions_;
      // xmean
      arma::Col<double> objectiveValues_;
      double sigma_;
      // stopfitness
      double stopValue_;

      // selection parameters
      int lambda_;
      double mu_;
      arma::Col<double> weights_;
      double mueff_;

      // adaptation parameters
      double cc_;
      double cs_;
      double c1_;
      double cmu_;
      double damps_;

      // dynamic parameters and constants
      arma::Col<double> pc_;
      arma::Col<double> ps_;
      arma::Mat<double> B_;
      arma::Mat<double> D_;
      arma::Mat<double> C_;
      arma::Mat<double> invsqrtC_;
      double eigeneval_;
      double chiN_;

      //function to use
      double frosenbrock(arma::Col<double> x);
  };
}
<|endoftext|>


<commit_before>//
//  Tape.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 29/08/2016.
//  Copyright © 2016 Thomas Harte. All rights reserved.
//

#include "Tape.hpp"

#include <deque>

using namespace StaticAnalyser::Acorn;

/*!
	A partly-abstract base class to help in the authorship of tape format parsers;
	provides hooks for a
*/
template <typename WaveType, typename SymbolType> class TapeParser {
	public:
		TapeParser(const std::shared_ptr<Storage::Tape::Tape> &tape) : _tape(tape) {}

		std::unique_ptr<SymbolType> get_next_symbol()
		{
			while(!_tape->is_at_end())
			{
				std::unique_ptr<SymbolType> symbol = dequeue_next_symbol(_wave_queue);
				if(symbol) return symbol;

				while(!_tape->is_at_end())
				{
					Storage::Tape::Tape::Pulse next_pulse = _tape->get_next_pulse();
					std::unique_ptr<WaveType> next_wave = get_wave_type_for_pulse(next_pulse);
					if(next_wave)
					{
						_wave_queue.push_back(*next_wave);
						break;
					}
				}
			}

			return nullptr;
		}

		void reset_error_flag()		{	_error_flag = false;		}
		bool get_error_flag()		{	return _error_flag;			}
		bool is_at_end()			{	return _tape->is_at_end();	}

	protected:
		bool _error_flag;

	private:
		virtual std::unique_ptr<WaveType> get_wave_type_for_pulse(Storage::Tape::Tape::Pulse) = 0;
		virtual std::unique_ptr<SymbolType> dequeue_next_symbol(std::deque<WaveType> _wave_queue) = 0;
		std::deque<WaveType> _wave_queue;
		std::shared_ptr<Storage::Tape::Tape> _tape;
};

enum class WaveType {
	Short, Long, Unrecognised
};

enum class SymbolType {
	One, Zero
};

class Acorn1200BaudTapeParser: public TapeParser<WaveType, SymbolType> {
	public:
		Acorn1200BaudTapeParser(const std::shared_ptr<Storage::Tape::Tape> &tape) : TapeParser(tape) {}

		int get_next_bit()
		{
			std::unique_ptr<SymbolType> symbol = get_next_symbol();
			return (symbol && *symbol == SymbolType::One) ? 1 : 0;
		}

		int get_next_byte()
		{
			int value = 0;
			int c = 8;
			if(get_next_bit())
			{
				_error_flag = true;
				return -1;
			}
			while(c--)
			{
				value = (value >> 1) | (get_next_bit() << 7);
			}
			if(!get_next_bit())
			{
				_error_flag = true;
				return -1;
			}
			add_to_crc((uint8_t)value);
			return value;
		}

		int get_next_short()
		{
			int result = get_next_byte();
			result |= get_next_byte() << 8;
			return result;
		}

		int get_next_word()
		{
			int result = get_next_short();
			result |= get_next_short() << 8;
			return result;
		}

		void reset_crc()	{	_crc = 0;		}
		uint16_t get_crc()	{	return _crc;	}

	private:
		std::unique_ptr<WaveType> get_wave_type_for_pulse(Storage::Tape::Tape::Pulse pulse)
		{
			WaveType wave_type = WaveType::Unrecognised;
			switch(pulse.type)
			{
				default: break;
				case Storage::Tape::Tape::Pulse::High:
				case Storage::Tape::Tape::Pulse::Low:
					float pulse_length = pulse.length.get_float();
					if(pulse_length >= 0.35 / 2400.0 && pulse_length < 0.7 / 2400.0) wave_type = WaveType::Short;
					if(pulse_length >= 0.35 / 1200.0 && pulse_length < 0.7 / 1200.0) wave_type = WaveType::Long;
				break;
			}

			return std::unique_ptr<WaveType>(new WaveType(wave_type));
		}

		std::unique_ptr<SymbolType> dequeue_next_symbol(std::deque<WaveType> _wave_queue)
		{
			while(_wave_queue.size() && _wave_queue.front() == WaveType::Unrecognised)
			{
				_wave_queue.pop_front();
			}

			if(_wave_queue.size() >= 2 && _wave_queue[0] == WaveType::Long && _wave_queue[1] == WaveType::Long)
			{
				_wave_queue.erase(_wave_queue.begin(), _wave_queue.begin()+2);
				return std::unique_ptr<SymbolType>(new SymbolType(SymbolType::Zero));
			}

			if(	_wave_queue.size() >= 4 &&
				_wave_queue[0] == WaveType::Short &&
				_wave_queue[1] == WaveType::Short &&
				_wave_queue[2] == WaveType::Short &&
				_wave_queue[3] == WaveType::Short)
			{
				_wave_queue.erase(_wave_queue.begin(), _wave_queue.begin()+4);
				return std::unique_ptr<SymbolType>(new SymbolType(SymbolType::One));
			}

			return nullptr;
		}

		void add_to_crc(uint8_t value)
		{
			_crc ^= (uint16_t)value << 8;
			for(int c = 0; c < 8; c++)
			{
				uint16_t exclusive_or = (_crc&0x8000) ? 0x1021 : 0x0000;
				_crc = (uint16_t)(_crc << 1) ^ exclusive_or;
			}
		}

		uint16_t _crc;
};

static std::unique_ptr<File::Chunk> GetNextChunk(Acorn1200BaudTapeParser &parser)
{
	std::unique_ptr<File::Chunk> new_chunk(new File::Chunk);
	int shift_register = 0;

// TODO: move this into the parser
#define shift()	shift_register = (shift_register >> 1) |  (parser.get_next_bit() << 9)

	// find next area of high tone
	while(!parser.is_at_end() && (shift_register != 0x3ff))
	{
		shift();
	}

	// find next 0x2a (swallowing stop bit)
	while(!parser.is_at_end() && (shift_register != 0x254))
	{
		shift();
	}

#undef shift

	parser.reset_crc();
	parser.reset_error_flag();

	// read out name
	char name[10];
	int name_ptr = 0;
	while(!parser.is_at_end() && name_ptr < 10)
	{
		name[name_ptr] = (char)parser.get_next_byte();
		if(!name[name_ptr]) break;
		name_ptr++;
	}
	new_chunk->name = name;

	// addresses
	new_chunk->load_address = (uint32_t)parser.get_next_word();
	new_chunk->execution_address = (uint32_t)parser.get_next_word();
	new_chunk->block_number = (uint16_t)parser.get_next_short();
	new_chunk->block_length = (uint16_t)parser.get_next_short();
	new_chunk->block_flag = (uint8_t)parser.get_next_byte();
	new_chunk->next_address = (uint32_t)parser.get_next_word();

	uint16_t calculated_header_crc = parser.get_crc();
	uint16_t stored_header_crc = (uint16_t)parser.get_next_short();
	stored_header_crc = (uint16_t)((stored_header_crc >> 8) | (stored_header_crc << 8));
	new_chunk->header_crc_matched = stored_header_crc == calculated_header_crc;

	parser.reset_crc();
	new_chunk->data.reserve(new_chunk->block_length);
	for(int c = 0; c < new_chunk->block_length; c++)
	{
		new_chunk->data.push_back((uint8_t)parser.get_next_byte());
	}

	if(new_chunk->block_length && !new_chunk->block_flag&0x40)
	{
		uint16_t calculated_data_crc = parser.get_crc();
		uint16_t stored_data_crc = (uint16_t)parser.get_next_short();
		stored_data_crc = (uint16_t)((stored_data_crc >> 8) | (stored_data_crc << 8));
		new_chunk->data_crc_matched = stored_data_crc == calculated_data_crc;
	}
	else
	{
		new_chunk->data_crc_matched = true;
	}

	return parser.get_error_flag() ? nullptr : std::move(new_chunk);
}

std::unique_ptr<File> GetNextFile(std::deque<File::Chunk> &chunks)
{
	// find next chunk with a block number of 0
	while(chunks.size() && chunks.front().block_number)
	{
		chunks.pop_front();
	}

	if(!chunks.size()) return nullptr;

	// accumulate chunks for as long as block number is sequential and the end-of-file bit isn't set
	std::unique_ptr<File> file(new File);

	uint16_t block_number = chunks.front().block_number;
	file->chunks.push_back(chunks.front());
	chunks.pop_front();

	while(chunks.size())
	{
		if(chunks.front().block_number != block_number + 1) return nullptr;

		bool was_last = chunks.front().block_flag & 0x80;
		file->chunks.push_back(chunks.front());
		chunks.pop_front();
		block_number++;

		if(was_last) break;
	}

	// accumulate total data, copy flags appropriately
	file->name = file->chunks.front().name;
	file->load_address = file->chunks.front().load_address;
	file->execution_address = file->chunks.front().execution_address;
	file->is_protected = !!(file->chunks.back().block_flag & 0x01);	// I think the last flags are the ones that count; TODO: check.

	// copy all data into a single big block
	for(File::Chunk chunk : file->chunks)
	{
		file->data.insert(file->data.end(), chunk.data.begin(), chunk.data.end());
	}

	return file;
}

std::list<File> StaticAnalyser::Acorn::GetFiles(const std::shared_ptr<Storage::Tape::Tape> &tape)
{
	Acorn1200BaudTapeParser parser(tape);

	// populate chunk list
	std::deque<File::Chunk> chunk_list;
	while(!parser.is_at_end())
	{
		std::unique_ptr<File::Chunk> chunk = GetNextChunk(parser);
		if(chunk)
		{
			chunk_list.push_back(*chunk);
		}
	}

	// decompose into file list
	std::list<File> file_list;

	while(chunk_list.size())
	{
		std::unique_ptr<File> next_file = GetNextFile(chunk_list);
		if(next_file)
		{
			file_list.push_back(*next_file);
		}
	}

	return file_list;
}
<commit_msg>Fixed accidental implicit assumption that Acorn files will be at least two blocks.<commit_after>//
//  Tape.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 29/08/2016.
//  Copyright © 2016 Thomas Harte. All rights reserved.
//

#include "Tape.hpp"

#include <deque>

using namespace StaticAnalyser::Acorn;

/*!
	A partly-abstract base class to help in the authorship of tape format parsers;
	provides hooks for a
*/
template <typename WaveType, typename SymbolType> class TapeParser {
	public:
		TapeParser(const std::shared_ptr<Storage::Tape::Tape> &tape) : _tape(tape) {}

		std::unique_ptr<SymbolType> get_next_symbol()
		{
			while(!_tape->is_at_end())
			{
				std::unique_ptr<SymbolType> symbol = dequeue_next_symbol(_wave_queue);
				if(symbol) return symbol;

				while(!_tape->is_at_end())
				{
					Storage::Tape::Tape::Pulse next_pulse = _tape->get_next_pulse();
					std::unique_ptr<WaveType> next_wave = get_wave_type_for_pulse(next_pulse);
					if(next_wave)
					{
						_wave_queue.push_back(*next_wave);
						break;
					}
				}
			}

			return nullptr;
		}

		void reset_error_flag()		{	_error_flag = false;		}
		bool get_error_flag()		{	return _error_flag;			}
		bool is_at_end()			{	return _tape->is_at_end();	}

	protected:
		bool _error_flag;

	private:
		virtual std::unique_ptr<WaveType> get_wave_type_for_pulse(Storage::Tape::Tape::Pulse) = 0;
		virtual std::unique_ptr<SymbolType> dequeue_next_symbol(std::deque<WaveType> &_wave_queue) = 0;
		std::deque<WaveType> _wave_queue;
		std::shared_ptr<Storage::Tape::Tape> _tape;
};

enum class WaveType {
	Short, Long, Unrecognised
};

enum class SymbolType {
	One, Zero
};

class Acorn1200BaudTapeParser: public TapeParser<WaveType, SymbolType> {
	public:
		Acorn1200BaudTapeParser(const std::shared_ptr<Storage::Tape::Tape> &tape) : TapeParser(tape) {}

		int get_next_bit()
		{
			std::unique_ptr<SymbolType> symbol = get_next_symbol();
			return (symbol && *symbol == SymbolType::One) ? 1 : 0;
		}

		int get_next_byte()
		{
			int value = 0;
			int c = 8;
			if(get_next_bit())
			{
				_error_flag = true;
				return -1;
			}
			while(c--)
			{
				value = (value >> 1) | (get_next_bit() << 7);
			}
			if(!get_next_bit())
			{
				_error_flag = true;
				return -1;
			}
			add_to_crc((uint8_t)value);
			return value;
		}

		int get_next_short()
		{
			int result = get_next_byte();
			result |= get_next_byte() << 8;
			return result;
		}

		int get_next_word()
		{
			int result = get_next_short();
			result |= get_next_short() << 8;
			return result;
		}

		void reset_crc()	{	_crc = 0;		}
		uint16_t get_crc()	{	return _crc;	}

	private:
		std::unique_ptr<WaveType> get_wave_type_for_pulse(Storage::Tape::Tape::Pulse pulse)
		{
			WaveType wave_type = WaveType::Unrecognised;
			switch(pulse.type)
			{
				default: break;
				case Storage::Tape::Tape::Pulse::High:
				case Storage::Tape::Tape::Pulse::Low:
					float pulse_length = pulse.length.get_float();
					if(pulse_length >= 0.35 / 2400.0 && pulse_length < 0.7 / 2400.0) wave_type = WaveType::Short;
					if(pulse_length >= 0.35 / 1200.0 && pulse_length < 0.7 / 1200.0) wave_type = WaveType::Long;
				break;
			}

			return std::unique_ptr<WaveType>(new WaveType(wave_type));
		}

		std::unique_ptr<SymbolType> dequeue_next_symbol(std::deque<WaveType> &_wave_queue)
		{
			while(_wave_queue.size() && _wave_queue.front() == WaveType::Unrecognised)
			{
				_wave_queue.pop_front();
			}

			if(_wave_queue.size() >= 2 && _wave_queue[0] == WaveType::Long && _wave_queue[1] == WaveType::Long)
			{
				_wave_queue.erase(_wave_queue.begin(), _wave_queue.begin()+2);
				return std::unique_ptr<SymbolType>(new SymbolType(SymbolType::Zero));
			}

			if(	_wave_queue.size() >= 4 &&
				_wave_queue[0] == WaveType::Short &&
				_wave_queue[1] == WaveType::Short &&
				_wave_queue[2] == WaveType::Short &&
				_wave_queue[3] == WaveType::Short)
			{
				_wave_queue.erase(_wave_queue.begin(), _wave_queue.begin()+4);
				return std::unique_ptr<SymbolType>(new SymbolType(SymbolType::One));
			}

			return nullptr;
		}

		void add_to_crc(uint8_t value)
		{
			_crc ^= (uint16_t)value << 8;
			for(int c = 0; c < 8; c++)
			{
				uint16_t exclusive_or = (_crc&0x8000) ? 0x1021 : 0x0000;
				_crc = (uint16_t)(_crc << 1) ^ exclusive_or;
			}
		}

		uint16_t _crc;
};

static std::unique_ptr<File::Chunk> GetNextChunk(Acorn1200BaudTapeParser &parser)
{
	std::unique_ptr<File::Chunk> new_chunk(new File::Chunk);
	int shift_register = 0;

// TODO: move this into the parser
#define shift()	shift_register = (shift_register >> 1) |  (parser.get_next_bit() << 9)

	// find next area of high tone
	while(!parser.is_at_end() && (shift_register != 0x3ff))
	{
		shift();
	}

	// find next 0x2a (swallowing stop bit)
	while(!parser.is_at_end() && (shift_register != 0x254))
	{
		shift();
	}

#undef shift

	parser.reset_crc();
	parser.reset_error_flag();

	// read out name
	char name[10];
	int name_ptr = 0;
	while(!parser.is_at_end() && name_ptr < 10)
	{
		name[name_ptr] = (char)parser.get_next_byte();
		if(!name[name_ptr]) break;
		name_ptr++;
	}
	new_chunk->name = name;

	// addresses
	new_chunk->load_address = (uint32_t)parser.get_next_word();
	new_chunk->execution_address = (uint32_t)parser.get_next_word();
	new_chunk->block_number = (uint16_t)parser.get_next_short();
	new_chunk->block_length = (uint16_t)parser.get_next_short();
	new_chunk->block_flag = (uint8_t)parser.get_next_byte();
	new_chunk->next_address = (uint32_t)parser.get_next_word();

	uint16_t calculated_header_crc = parser.get_crc();
	uint16_t stored_header_crc = (uint16_t)parser.get_next_short();
	stored_header_crc = (uint16_t)((stored_header_crc >> 8) | (stored_header_crc << 8));
	new_chunk->header_crc_matched = stored_header_crc == calculated_header_crc;

	parser.reset_crc();
	new_chunk->data.reserve(new_chunk->block_length);
	for(int c = 0; c < new_chunk->block_length; c++)
	{
		new_chunk->data.push_back((uint8_t)parser.get_next_byte());
	}

	if(new_chunk->block_length && !new_chunk->block_flag&0x40)
	{
		uint16_t calculated_data_crc = parser.get_crc();
		uint16_t stored_data_crc = (uint16_t)parser.get_next_short();
		stored_data_crc = (uint16_t)((stored_data_crc >> 8) | (stored_data_crc << 8));
		new_chunk->data_crc_matched = stored_data_crc == calculated_data_crc;
	}
	else
	{
		new_chunk->data_crc_matched = true;
	}

	return parser.get_error_flag() ? nullptr : std::move(new_chunk);
}

std::unique_ptr<File> GetNextFile(std::deque<File::Chunk> &chunks)
{
	// find next chunk with a block number of 0
	while(chunks.size() && chunks.front().block_number)
	{
		chunks.pop_front();
	}

	if(!chunks.size()) return nullptr;

	// accumulate chunks for as long as block number is sequential and the end-of-file bit isn't set
	std::unique_ptr<File> file(new File);

	uint16_t block_number = 0;

	while(chunks.size())
	{
		if(chunks.front().block_number != block_number) return nullptr;

		bool was_last = chunks.front().block_flag & 0x80;
		file->chunks.push_back(chunks.front());
		chunks.pop_front();
		block_number++;

		if(was_last) break;
	}

	// accumulate total data, copy flags appropriately
	file->name = file->chunks.front().name;
	file->load_address = file->chunks.front().load_address;
	file->execution_address = file->chunks.front().execution_address;
	file->is_protected = !!(file->chunks.back().block_flag & 0x01);	// I think the last flags are the ones that count; TODO: check.

	// copy all data into a single big block
	for(File::Chunk chunk : file->chunks)
	{
		file->data.insert(file->data.end(), chunk.data.begin(), chunk.data.end());
	}

	return file;
}

std::list<File> StaticAnalyser::Acorn::GetFiles(const std::shared_ptr<Storage::Tape::Tape> &tape)
{
	Acorn1200BaudTapeParser parser(tape);

	// populate chunk list
	std::deque<File::Chunk> chunk_list;
	while(!parser.is_at_end())
	{
		std::unique_ptr<File::Chunk> chunk = GetNextChunk(parser);
		if(chunk)
		{
			chunk_list.push_back(*chunk);
		}
	}

	// decompose into file list
	std::list<File> file_list;

	while(chunk_list.size())
	{
		std::unique_ptr<File> next_file = GetNextFile(chunk_list);
		if(next_file)
		{
			file_list.push_back(*next_file);
		}
	}

	return file_list;
}
<|endoftext|>


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

#include <string.h>

#include <grpc/support/log.h>

#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h"
#include "src/core/ext/filters/client_channel/resolver_registry.h"
#include "src/core/lib/iomgr/combiner.h"
#include "test/core/util/test_config.h"

static grpc_combiner* g_combiner;

static void test_succeeds(grpc_core::ResolverFactory* factory,
                          const char* string) {
  gpr_log(GPR_DEBUG, "test: '%s' should be valid for '%s'", string,
          factory->scheme());
  grpc_core::ExecCtx exec_ctx;
  grpc_uri* uri = grpc_uri_parse(string, 0);
  GPR_ASSERT(uri);
  grpc_core::ResolverArgs args;
  args.uri = uri;
  args.combiner = g_combiner;
  grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
      factory->CreateResolver(args);
  GPR_ASSERT(resolver != nullptr);
  grpc_uri_destroy(uri);
}

static void test_fails(grpc_core::ResolverFactory* factory,
                       const char* string) {
  gpr_log(GPR_DEBUG, "test: '%s' should be invalid for '%s'", string,
          factory->scheme());
  grpc_core::ExecCtx exec_ctx;
  grpc_uri* uri = grpc_uri_parse(string, 0);
  GPR_ASSERT(uri);
  grpc_core::ResolverArgs args;
  args.uri = uri;
  args.combiner = g_combiner;
  grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
      factory->CreateResolver(args);
  GPR_ASSERT(resolver == nullptr);
  grpc_uri_destroy(uri);
}

int main(int argc, char** argv) {
  grpc_test_init(argc, argv);
  grpc_init();

  g_combiner = grpc_combiner_create();

  grpc_core::ResolverFactory* dns =
      grpc_core::ResolverRegistry::LookupResolverFactory("dns");

  test_succeeds(dns, "dns:10.2.1.1");
  test_succeeds(dns, "dns:10.2.1.1:1234");
  test_succeeds(dns, "ipv4:www.google.com");
  if (grpc_resolve_address == grpc_resolve_address_ares) {
    test_succeeds(dns, "ipv4://8.8.8.8/8.8.8.8:8888");
  } else {
    test_fails(dns, "ipv4://8.8.8.8/8.8.8.8:8888");
  }

  {
    grpc_core::ExecCtx exec_ctx;
    GRPC_COMBINER_UNREF(g_combiner, "test");
  }
  grpc_shutdown();

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

#include <string.h>

#include <grpc/support/log.h>

#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h"
#include "src/core/ext/filters/client_channel/resolver_registry.h"
#include "src/core/lib/iomgr/combiner.h"
#include "test/core/util/test_config.h"

static grpc_combiner* g_combiner;

static void test_succeeds(grpc_core::ResolverFactory* factory,
                          const char* string) {
  gpr_log(GPR_DEBUG, "test: '%s' should be valid for '%s'", string,
          factory->scheme());
  grpc_core::ExecCtx exec_ctx;
  grpc_uri* uri = grpc_uri_parse(string, 0);
  GPR_ASSERT(uri);
  grpc_core::ResolverArgs args;
  args.uri = uri;
  args.combiner = g_combiner;
  grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
      factory->CreateResolver(args);
  GPR_ASSERT(resolver != nullptr);
  grpc_uri_destroy(uri);
}

static void test_fails(grpc_core::ResolverFactory* factory,
                       const char* string) {
  gpr_log(GPR_DEBUG, "test: '%s' should be invalid for '%s'", string,
          factory->scheme());
  grpc_core::ExecCtx exec_ctx;
  grpc_uri* uri = grpc_uri_parse(string, 0);
  GPR_ASSERT(uri);
  grpc_core::ResolverArgs args;
  args.uri = uri;
  args.combiner = g_combiner;
  grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
      factory->CreateResolver(args);
  GPR_ASSERT(resolver == nullptr);
  grpc_uri_destroy(uri);
}

int main(int argc, char** argv) {
  grpc_test_init(argc, argv);
  grpc_init();

  g_combiner = grpc_combiner_create();

  grpc_core::ResolverFactory* dns =
      grpc_core::ResolverRegistry::LookupResolverFactory("dns");

  test_succeeds(dns, "dns:10.2.1.1");
  test_succeeds(dns, "dns:10.2.1.1:1234");
  test_succeeds(dns, "dns:www.google.com");
  test_succeeds(dns, "dns:///www.google.com");
  if (grpc_resolve_address == grpc_resolve_address_ares) {
    test_succeeds(dns, "dns://8.8.8.8/8.8.8.8:8888");
  } else {
    test_fails(dns, "dns://8.8.8.8/8.8.8.8:8888");
  }

  {
    grpc_core::ExecCtx exec_ctx;
    GRPC_COMBINER_UNREF(g_combiner, "test");
  }
  grpc_shutdown();

  return 0;
}
<|endoftext|>


<commit_before>#ifndef RENDERING_SYSTEM_HPP
#define RENDERING_SYSTEM_HPP
#include "LotsOfLines/IRenderer.hpp"
#include "LotsOfLines/DataModel.hpp"
#include "LotsOfLines/IVertexBufferObject.hpp"
#include "LotsOfLines/VisualizationOptions.hpp"
#include <vector>

namespace LotsOfLines
{
	class IVisualizationMethod;

	enum E_VISUALIZATION_TYPE
	{
		EVT_PARALLEL_COORDINATES,
		EVT_COLLOCATED_PAIRED_COORDINATES,
		EVT_RADIAL_PAIRED_COORDINATES,
		EVT_SHIFTED_PAIRED_COORDINATES,
		EVT_COUNT
	};

	typedef std::vector<std::shared_ptr<IVisualizationMethod> > VisualizationMethodList;

	///@brief The RenderingSystem manages different drivers to render with and handles all visualization rendering.
	class RenderingSystem
	{
	public:

		RenderingSystem(IRenderer* driver);

		///@brief Initialize the rendering system and its driver.
		bool init();

		///@return Pointer to the driver implementation.
		IRenderer* getDriver() const;

	private:

		IRenderer* m_driver;

	public:

		///@brief Registers a visualization method and makes it available to use.
		void registerVisualizationMethod(E_VISUALIZATION_TYPE type, std::shared_ptr<IVisualizationMethod> visMethod);

		///@brief Get the list of currently registered visualization methods.
		void getVisualizationMethods(VisualizationMethodList& visualizationMethodsOut);

		///@brief Set current visualization type and regenerate vertex buffers.
		void setVisualizationType(E_VISUALIZATION_TYPE type);

		///@brief Regenerate the visualization after options or datasets have changed.
		void redraw();

		///@return Shared pointer to the current visualization method.
		std::shared_ptr<IVisualizationMethod> getCurrentVisualizationMethod();

		///@brief Set the data set that will be drawn by the rendering system.
		void setDataSet(std::shared_ptr<DataSet> dataSet);

		///@return Current visualization options in use.
		VisualizationOptions& getVisualizationOptions();

		///@brief Set the color to use when rendering a data class.
		void setDataClassColor(unsigned int classIdx, float r, float g, float b);
		///@return 3-element float array with data class color.
		const float* getDataClassColor(unsigned int classIdx) const;
		///@return The full array of data class colors
		const float** getDataClassColors() const;
		///@return The total number of data class colors that have been configured.
		unsigned int getDataClassColorCount() const;

	private:

		float m_dataClassColors[10][3] =
		{
			{ 1.0f, 0.0f, 0.0f },
			{ 0.0f, 1.0f, 0.0f },
			{ 0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f }
		};

		E_VISUALIZATION_TYPE m_currentVisualizationType = EVT_COUNT;

		std::map<E_VISUALIZATION_TYPE, std::shared_ptr<IVisualizationMethod> > m_visualizationMethods;

		std::shared_ptr<DataSet> m_dataSet = nullptr;

		VisualizationOptions m_options;

		///@brief Generate a VBO from a data set.
		std::shared_ptr<IVertexBufferObject> generateFromDataSet(std::shared_ptr<DataSet> dataSet, E_VISUALIZATION_TYPE type, std::vector<Vertex>& verticesOut);

	public:

		///@brief Call when a mouse press event occurs on the window
		void onMousePress(int x, int y);
		///@brief Call when a mouse press event occurs on the window
		void onRightClick(int x, int y);
		///@brief Call when a mouse move event occurs on the window
		void onMouseMove(int x, int y);
		///@brief Call when a mouse release event occurs on the window
		void onMouseRelease(int x, int y);
		///@brief Call when a mouse scroll wheel event occurs.
		///@param delta The amount of degrees the mouse wheel was moved.
		void onMouseScroll(int delta);

	private:

		bool m_mousePressed = false;
		int m_startMouseX = 0, m_startMouseY = 0;

		float m_camX = 0.0f, m_camY = 0.0f;
		float m_zoomX = 1.0f, m_zoomY = 1.0f;
		float m_camStartX = 0.0f, m_camStartY = 0.0f;

		unsigned int m_windowWidth;
		unsigned int m_windowHeight;

		glm::mat4x4 m_modelViewProjection;

		///@brief Expands a selection from a vertex to the entire line.
		void expandSelectionToLine(Vertex* vertices, unsigned int vertexCount, Vertex* selected);

	public:

		///@brief Call when the window is resized.
		void onResize(unsigned int width, unsigned int height);

		///@brief Scales the view to the current visualization automatically.
		void autoViewTransform(E_VISUALIZATION_TYPE type);

		void setViewTransform(float camX, float camY, float zoomX, float zoomY);

		void draw(float r = 0.2f, float g = 0.2f, float b = 0.2f);

		void drawVBO(std::shared_ptr<IVertexBufferObject> vbo);

		///@brief Set the line that's selected.
		void setSelectedLine(unsigned int lineIndex);

		///@brief Gets index of the closest line to the
		unsigned int getClosestLine(float x, float y);

	private:

		bool m_autoViewTransformFlag = false;

		std::shared_ptr<IVertexBufferObject> m_vbo;
		std::vector<Vertex> m_vertices;
	};
}

#endif<commit_msg>Changed default class colors.<commit_after>#ifndef RENDERING_SYSTEM_HPP
#define RENDERING_SYSTEM_HPP
#include "LotsOfLines/IRenderer.hpp"
#include "LotsOfLines/DataModel.hpp"
#include "LotsOfLines/IVertexBufferObject.hpp"
#include "LotsOfLines/VisualizationOptions.hpp"
#include <vector>

namespace LotsOfLines
{
	class IVisualizationMethod;

	enum E_VISUALIZATION_TYPE
	{
		EVT_PARALLEL_COORDINATES,
		EVT_COLLOCATED_PAIRED_COORDINATES,
		EVT_RADIAL_PAIRED_COORDINATES,
		EVT_SHIFTED_PAIRED_COORDINATES,
		EVT_COUNT
	};

	typedef std::vector<std::shared_ptr<IVisualizationMethod> > VisualizationMethodList;

	///@brief The RenderingSystem manages different drivers to render with and handles all visualization rendering.
	class RenderingSystem
	{
	public:

		RenderingSystem(IRenderer* driver);

		///@brief Initialize the rendering system and its driver.
		bool init();

		///@return Pointer to the driver implementation.
		IRenderer* getDriver() const;

	private:

		IRenderer* m_driver;

	public:

		///@brief Registers a visualization method and makes it available to use.
		void registerVisualizationMethod(E_VISUALIZATION_TYPE type, std::shared_ptr<IVisualizationMethod> visMethod);

		///@brief Get the list of currently registered visualization methods.
		void getVisualizationMethods(VisualizationMethodList& visualizationMethodsOut);

		///@brief Set current visualization type and regenerate vertex buffers.
		void setVisualizationType(E_VISUALIZATION_TYPE type);

		///@brief Regenerate the visualization after options or datasets have changed.
		void redraw();

		///@return Shared pointer to the current visualization method.
		std::shared_ptr<IVisualizationMethod> getCurrentVisualizationMethod();

		///@brief Set the data set that will be drawn by the rendering system.
		void setDataSet(std::shared_ptr<DataSet> dataSet);

		///@return Current visualization options in use.
		VisualizationOptions& getVisualizationOptions();

		///@brief Set the color to use when rendering a data class.
		void setDataClassColor(unsigned int classIdx, float r, float g, float b);
		///@return 3-element float array with data class color.
		const float* getDataClassColor(unsigned int classIdx) const;
		///@return The full array of data class colors
		const float** getDataClassColors() const;
		///@return The total number of data class colors that have been configured.
		unsigned int getDataClassColorCount() const;

	private:

		//rgb(191,48,48)
		//rgb(217,116,0)
		//rgb(255,217,64)
		//rgb(51,48,13)
		//rgb(45,128,32)
		//rgb(0,255,0)
		//rgb(182,242,230)
		//rgb(0,111,166)
		//rgb(61,85,242)
		//rgb(191,96,159)
		float m_dataClassColors[10][3] =
		{
			{ 0.74902f, 0.188235f, 0.188235f },
			{ 0.239216f, 0.333333f, 0.94902f },
			{ 0.176471f, 0.501961f, 0.12549f },
			{ 0.0f, 1.0f, 0.0f },
			{ 1.0f, 0.85098f, 0.25098f },
			{ 0.713725f, 0.94902f, 0.901961f },
			{ 0.0f, 0.435294f, 0.65098f },
			{ 0.74902f, 0.376471f, 0.623529f },
			{ 0.2f, 0.188235f, 0.0509804f },
			{ 0.85098f, 0.454902f, 0.0f }
		};

		E_VISUALIZATION_TYPE m_currentVisualizationType = EVT_COUNT;

		std::map<E_VISUALIZATION_TYPE, std::shared_ptr<IVisualizationMethod> > m_visualizationMethods;

		std::shared_ptr<DataSet> m_dataSet = nullptr;

		VisualizationOptions m_options;

		///@brief Generate a VBO from a data set.
		std::shared_ptr<IVertexBufferObject> generateFromDataSet(std::shared_ptr<DataSet> dataSet, E_VISUALIZATION_TYPE type, std::vector<Vertex>& verticesOut);

	public:

		///@brief Call when a mouse press event occurs on the window
		void onMousePress(int x, int y);
		///@brief Call when a mouse press event occurs on the window
		void onRightClick(int x, int y);
		///@brief Call when a mouse move event occurs on the window
		void onMouseMove(int x, int y);
		///@brief Call when a mouse release event occurs on the window
		void onMouseRelease(int x, int y);
		///@brief Call when a mouse scroll wheel event occurs.
		///@param delta The amount of degrees the mouse wheel was moved.
		void onMouseScroll(int delta);

	private:

		bool m_mousePressed = false;
		int m_startMouseX = 0, m_startMouseY = 0;

		float m_camX = 0.0f, m_camY = 0.0f;
		float m_zoomX = 1.0f, m_zoomY = 1.0f;
		float m_camStartX = 0.0f, m_camStartY = 0.0f;

		unsigned int m_windowWidth;
		unsigned int m_windowHeight;

		glm::mat4x4 m_modelViewProjection;

		///@brief Expands a selection from a vertex to the entire line.
		void expandSelectionToLine(Vertex* vertices, unsigned int vertexCount, Vertex* selected);

	public:

		///@brief Call when the window is resized.
		void onResize(unsigned int width, unsigned int height);

		///@brief Scales the view to the current visualization automatically.
		void autoViewTransform(E_VISUALIZATION_TYPE type);

		void setViewTransform(float camX, float camY, float zoomX, float zoomY);

		void draw(float r = 0.2f, float g = 0.2f, float b = 0.2f);

		void drawVBO(std::shared_ptr<IVertexBufferObject> vbo);

		///@brief Set the line that's selected.
		void setSelectedLine(unsigned int lineIndex);

		///@brief Gets index of the closest line to the
		unsigned int getClosestLine(float x, float y);

	private:

		bool m_autoViewTransformFlag = false;

		std::shared_ptr<IVertexBufferObject> m_vbo;
		std::vector<Vertex> m_vertices;
	};
}

#endif<|endoftext|>


<commit_before>// $Id$
// vim:tabstop=2

/***********************************************************************
Moses - factored phrase-based language decoder
Copyright (C) 2006 University of Edinburgh

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 Street, Fifth Floor, Boston, MA  02110-1301  USA
***********************************************************************/

#include "util/check.hh"
#include <algorithm>
#include <sstream>
#include <string>
#include "memory.h"
#include "FactorCollection.h"
#include "Phrase.h"
#include "StaticData.h"  // GetMaxNumFactors

#include "util/string_piece.hh"
#include "util/tokenize_piece.hh"

using namespace std;

namespace Moses
{

Phrase::Phrase() {}

Phrase::Phrase(size_t reserveSize)
{
  m_words.reserve(reserveSize);
}

Phrase::Phrase(const vector< const Word* > &mergeWords)
{
  m_words.reserve(mergeWords.size());
  for (size_t currPos = 0 ; currPos < mergeWords.size() ; currPos++) {
    AddWord(*mergeWords[currPos]);
  }
}

Phrase::~Phrase()
{
}

void Phrase::MergeFactors(const Phrase &copy)
{
  CHECK(GetSize() == copy.GetSize());
  size_t size = GetSize();
  const size_t maxNumFactors = MAX_NUM_FACTORS;
  for (size_t currPos = 0 ; currPos < size ; currPos++) {
    for (unsigned int currFactor = 0 ; currFactor < maxNumFactors ; currFactor++) {
      FactorType factorType = static_cast<FactorType>(currFactor);
      const Factor *factor = copy.GetFactor(currPos, factorType);
      if (factor != NULL)
        SetFactor(currPos, factorType, factor);
    }
  }
}

void Phrase::MergeFactors(const Phrase &copy, FactorType factorType)
{
  CHECK(GetSize() == copy.GetSize());
  for (size_t currPos = 0 ; currPos < GetSize() ; currPos++)
    SetFactor(currPos, factorType, copy.GetFactor(currPos, factorType));
}

void Phrase::MergeFactors(const Phrase &copy, const std::vector<FactorType>& factorVec)
{
  CHECK(GetSize() == copy.GetSize());
  for (size_t currPos = 0 ; currPos < GetSize() ; currPos++)
    for (std::vector<FactorType>::const_iterator i = factorVec.begin();
         i != factorVec.end(); ++i) {
      SetFactor(currPos, *i, copy.GetFactor(currPos, *i));
    }
}

Phrase Phrase::GetSubString(const WordsRange &wordsRange) const
{
  Phrase retPhrase(wordsRange.GetNumWordsCovered());

  for (size_t currPos = wordsRange.GetStartPos() ; currPos <= wordsRange.GetEndPos() ; currPos++) {
    Word &word = retPhrase.AddWord();
    word = GetWord(currPos);
  }

  return retPhrase;
}

Phrase Phrase::GetSubString(const WordsRange &wordsRange, FactorType factorType) const
{
	Phrase retPhrase(wordsRange.GetNumWordsCovered());

	for (size_t currPos = wordsRange.GetStartPos() ; currPos <= wordsRange.GetEndPos() ; currPos++)
	{
		const Factor* f = GetFactor(currPos, factorType);
		Word &word = retPhrase.AddWord();
		word.SetFactor(factorType, f);
	}

	return retPhrase;
}

std::string Phrase::GetStringRep(const vector<FactorType> factorsToPrint) const
{
  stringstream strme;
  for (size_t pos = 0 ; pos < GetSize() ; pos++) {
    strme << GetWord(pos).GetString(factorsToPrint, (pos != GetSize()-1));
  }

  return strme.str();
}

Word &Phrase::AddWord()
{
  m_words.push_back(Word());
  return m_words.back();
}

void Phrase::Append(const Phrase &endPhrase)
{

  for (size_t i = 0; i < endPhrase.GetSize(); i++) {
    AddWord(endPhrase.GetWord(i));
  }
}

void Phrase::PrependWord(const Word &newWord)
{
  AddWord();

  // shift
  for (size_t pos = GetSize() - 1; pos >= 1; --pos) {
    const Word &word = m_words[pos - 1];
    m_words[pos] = word;
  }

  m_words[0] = newWord;
}

void Phrase::CreateFromString(const std::vector<FactorType> &factorOrder, const StringPiece &phraseString, const StringPiece &factorDelimiter)
{
  FactorCollection &factorCollection = FactorCollection::Instance();

  for (util::TokenIter<util::AnyCharacter, true> word_it(phraseString, util::AnyCharacter(" \t")); word_it; ++word_it) {
    Word &word = AddWord();
    size_t index = 0;
    for (util::TokenIter<util::MultiCharacter, false> factor_it(*word_it, util::MultiCharacter(factorDelimiter));
        factor_it && (index < factorOrder.size());
        ++factor_it, ++index) {
      word[factorOrder[index]] = factorCollection.AddFactor(*factor_it);
    }
    if (index != factorOrder.size()) {
      TRACE_ERR( "[ERROR] Malformed input: '" << *word_it << "'" <<  std::endl
                 << "In '" << phraseString << "'" << endl
                 << "  Expected input to have words composed of " << factorOrder.size() << " factor(s) (form FAC1|FAC2|...)" << std::endl
                 << "  but instead received input with " << index << " factor(s).\n");
      abort();
    }
  }
}

void Phrase::CreateFromStringNewFormat(FactorDirection direction
                                       , const std::vector<FactorType> &factorOrder
                                       , const StringPiece &phraseString
                                       , const std::string & /*factorDelimiter */
                                       , Word &lhs)
{
  // parse
  vector<StringPiece> annotatedWordVector;
  for (util::TokenIter<util::AnyCharacter, true> it(phraseString, "\t "); it; ++it) {
    annotatedWordVector.push_back(*it);
  }
  // KOMMA|none ART|Def.Z NN|Neut.NotGen.Sg VVFIN|none
  //		to
  // "KOMMA|none" "ART|Def.Z" "NN|Neut.NotGen.Sg" "VVFIN|none"

  m_words.reserve(annotatedWordVector.size()-1);

  for (size_t phrasePos = 0 ; phrasePos < annotatedWordVector.size() -  1 ; phrasePos++) {
    StringPiece &annotatedWord = annotatedWordVector[phrasePos];
    bool isNonTerminal;
    if (annotatedWord.size() >= 2 && *annotatedWord.data() == '[' && annotatedWord.data()[annotatedWord.size() - 1] == ']') {
      // non-term
      isNonTerminal = true;

      size_t nextPos = annotatedWord.find('[', 1);
      CHECK(nextPos != string::npos);

      if (direction == Input)
        annotatedWord = annotatedWord.substr(1, nextPos - 2);
      else
        annotatedWord = annotatedWord.substr(nextPos + 1, annotatedWord.size() - nextPos - 2);
    } else {
      isNonTerminal = false;
    }

    Word &word = AddWord();
    word.CreateFromString(direction, factorOrder, annotatedWord, isNonTerminal);

  }

  // lhs
  const StringPiece &annotatedWord = annotatedWordVector.back();
  CHECK(annotatedWord.size() >= 2 && *annotatedWord.data() == '[' && annotatedWord.data()[annotatedWord.size() - 1] == ']');

  lhs.CreateFromString(direction, factorOrder, annotatedWord.substr(1, annotatedWord.size() - 2), true);
  assert(lhs.IsNonTerminal());
}

int Phrase::Compare(const Phrase &other) const
{
#ifdef min
#undef min
#endif
  size_t thisSize			= GetSize()
                        ,compareSize	= other.GetSize();
  if (thisSize != compareSize) {
    return (thisSize < compareSize) ? -1 : 1;
  }

  for (size_t pos = 0 ; pos < thisSize ; pos++) {
    const Word &thisWord	= GetWord(pos)
                            ,&otherWord	= other.GetWord(pos);
    int ret = Word::Compare(thisWord, otherWord);

    if (ret != 0)
      return ret;
  }

  return 0;
}

bool Phrase::Contains(const vector< vector<string> > &subPhraseVector
                      , const vector<FactorType> &inputFactor) const
{
  const size_t subSize = subPhraseVector.size()
                         ,thisSize= GetSize();
  if (subSize > thisSize)
    return false;

  // try to match word-for-word
  for (size_t currStartPos = 0 ; currStartPos < (thisSize - subSize + 1) ; currStartPos++) {
    bool match = true;

    for (size_t currFactorIndex = 0 ; currFactorIndex < inputFactor.size() ; currFactorIndex++) {
      FactorType factorType = inputFactor[currFactorIndex];
      for (size_t currSubPos = 0 ; currSubPos < subSize ; currSubPos++) {
        size_t currThisPos = currSubPos + currStartPos;
        const string &subStr	= subPhraseVector[currSubPos][currFactorIndex]
                                ,&thisStr	= GetFactor(currThisPos, factorType)->GetString();
        if (subStr != thisStr) {
          match = false;
          break;
        }
      }
      if (!match)
        break;
    }

    if (match)
      return true;
  }
  return false;
}

bool Phrase::IsCompatible(const Phrase &inputPhrase) const
{
  if (inputPhrase.GetSize() != GetSize()) {
    return false;
  }

  const size_t size = GetSize();

  const size_t maxNumFactors = MAX_NUM_FACTORS;
  for (size_t currPos = 0 ; currPos < size ; currPos++) {
    for (unsigned int currFactor = 0 ; currFactor < maxNumFactors ; currFactor++) {
      FactorType factorType = static_cast<FactorType>(currFactor);
      const Factor *thisFactor 		= GetFactor(currPos, factorType)
                                    ,*inputFactor	= inputPhrase.GetFactor(currPos, factorType);
      if (thisFactor != NULL && inputFactor != NULL && thisFactor != inputFactor)
        return false;
    }
  }
  return true;

}

bool Phrase::IsCompatible(const Phrase &inputPhrase, FactorType factorType) const
{
  if (inputPhrase.GetSize() != GetSize())	{
    return false;
  }
  for (size_t currPos = 0 ; currPos < GetSize() ; currPos++) {
    if (GetFactor(currPos, factorType) != inputPhrase.GetFactor(currPos, factorType))
      return false;
  }
  return true;
}

bool Phrase::IsCompatible(const Phrase &inputPhrase, const std::vector<FactorType>& factorVec) const
{
  if (inputPhrase.GetSize() != GetSize())	{
    return false;
  }
  for (size_t currPos = 0 ; currPos < GetSize() ; currPos++) {
    for (std::vector<FactorType>::const_iterator i = factorVec.begin();
         i != factorVec.end(); ++i) {
      if (GetFactor(currPos, *i) != inputPhrase.GetFactor(currPos, *i))
        return false;
    }
  }
  return true;
}

size_t Phrase::GetNumTerminals() const
{
  size_t ret = 0;

  for (size_t pos = 0; pos < GetSize(); ++pos) {
    if (!GetWord(pos).IsNonTerminal())
      ret++;
  }
  return ret;
}

void Phrase::InitializeMemPool()
{
}

void Phrase::FinalizeMemPool()
{
}

TO_STRING_BODY(Phrase);

// friend
ostream& operator<<(ostream& out, const Phrase& phrase)
{
//	out << "(size " << phrase.GetSize() << ") ";
  for (size_t pos = 0 ; pos < phrase.GetSize() ; pos++) {
    const Word &word = phrase.GetWord(pos);
    out << word;
  }
  return out;
}

}

<commit_msg>Error messages<commit_after>// $Id$
// vim:tabstop=2

/***********************************************************************
Moses - factored phrase-based language decoder
Copyright (C) 2006 University of Edinburgh

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 Street, Fifth Floor, Boston, MA  02110-1301  USA
***********************************************************************/

#include "util/check.hh"
#include <algorithm>
#include <sstream>
#include <string>
#include "memory.h"
#include "FactorCollection.h"
#include "Phrase.h"
#include "StaticData.h"  // GetMaxNumFactors

#include "util/exception.hh"
#include "util/string_piece.hh"
#include "util/tokenize_piece.hh"

using namespace std;

namespace Moses
{

Phrase::Phrase() {}

Phrase::Phrase(size_t reserveSize)
{
  m_words.reserve(reserveSize);
}

Phrase::Phrase(const vector< const Word* > &mergeWords)
{
  m_words.reserve(mergeWords.size());
  for (size_t currPos = 0 ; currPos < mergeWords.size() ; currPos++) {
    AddWord(*mergeWords[currPos]);
  }
}

Phrase::~Phrase()
{
}

void Phrase::MergeFactors(const Phrase &copy)
{
  CHECK(GetSize() == copy.GetSize());
  size_t size = GetSize();
  const size_t maxNumFactors = MAX_NUM_FACTORS;
  for (size_t currPos = 0 ; currPos < size ; currPos++) {
    for (unsigned int currFactor = 0 ; currFactor < maxNumFactors ; currFactor++) {
      FactorType factorType = static_cast<FactorType>(currFactor);
      const Factor *factor = copy.GetFactor(currPos, factorType);
      if (factor != NULL)
        SetFactor(currPos, factorType, factor);
    }
  }
}

void Phrase::MergeFactors(const Phrase &copy, FactorType factorType)
{
  CHECK(GetSize() == copy.GetSize());
  for (size_t currPos = 0 ; currPos < GetSize() ; currPos++)
    SetFactor(currPos, factorType, copy.GetFactor(currPos, factorType));
}

void Phrase::MergeFactors(const Phrase &copy, const std::vector<FactorType>& factorVec)
{
  CHECK(GetSize() == copy.GetSize());
  for (size_t currPos = 0 ; currPos < GetSize() ; currPos++)
    for (std::vector<FactorType>::const_iterator i = factorVec.begin();
         i != factorVec.end(); ++i) {
      SetFactor(currPos, *i, copy.GetFactor(currPos, *i));
    }
}

Phrase Phrase::GetSubString(const WordsRange &wordsRange) const
{
  Phrase retPhrase(wordsRange.GetNumWordsCovered());

  for (size_t currPos = wordsRange.GetStartPos() ; currPos <= wordsRange.GetEndPos() ; currPos++) {
    Word &word = retPhrase.AddWord();
    word = GetWord(currPos);
  }

  return retPhrase;
}

Phrase Phrase::GetSubString(const WordsRange &wordsRange, FactorType factorType) const
{
	Phrase retPhrase(wordsRange.GetNumWordsCovered());

	for (size_t currPos = wordsRange.GetStartPos() ; currPos <= wordsRange.GetEndPos() ; currPos++)
	{
		const Factor* f = GetFactor(currPos, factorType);
		Word &word = retPhrase.AddWord();
		word.SetFactor(factorType, f);
	}

	return retPhrase;
}

std::string Phrase::GetStringRep(const vector<FactorType> factorsToPrint) const
{
  stringstream strme;
  for (size_t pos = 0 ; pos < GetSize() ; pos++) {
    strme << GetWord(pos).GetString(factorsToPrint, (pos != GetSize()-1));
  }

  return strme.str();
}

Word &Phrase::AddWord()
{
  m_words.push_back(Word());
  return m_words.back();
}

void Phrase::Append(const Phrase &endPhrase)
{

  for (size_t i = 0; i < endPhrase.GetSize(); i++) {
    AddWord(endPhrase.GetWord(i));
  }
}

void Phrase::PrependWord(const Word &newWord)
{
  AddWord();

  // shift
  for (size_t pos = GetSize() - 1; pos >= 1; --pos) {
    const Word &word = m_words[pos - 1];
    m_words[pos] = word;
  }

  m_words[0] = newWord;
}

void Phrase::CreateFromString(const std::vector<FactorType> &factorOrder, const StringPiece &phraseString, const StringPiece &factorDelimiter)
{
  FactorCollection &factorCollection = FactorCollection::Instance();

  for (util::TokenIter<util::AnyCharacter, true> word_it(phraseString, util::AnyCharacter(" \t")); word_it; ++word_it) {
    Word &word = AddWord();
    size_t index = 0;
    for (util::TokenIter<util::MultiCharacter, false> factor_it(*word_it, util::MultiCharacter(factorDelimiter));
        factor_it && (index < factorOrder.size());
        ++factor_it, ++index) {
      word[factorOrder[index]] = factorCollection.AddFactor(*factor_it);
    }
    if (index != factorOrder.size()) {
      TRACE_ERR( "[ERROR] Malformed input: '" << *word_it << "'" <<  std::endl
                 << "In '" << phraseString << "'" << endl
                 << "  Expected input to have words composed of " << factorOrder.size() << " factor(s) (form FAC1|FAC2|...)" << std::endl
                 << "  but instead received input with " << index << " factor(s).\n");
      abort();
    }
  }
}

class NonTerminalParseException : public util::Exception {};

void Phrase::CreateFromStringNewFormat(FactorDirection direction
                                       , const std::vector<FactorType> &factorOrder
                                       , const StringPiece &phraseString
                                       , const std::string & /*factorDelimiter */
                                       , Word &lhs)
{
  // parse
  vector<StringPiece> annotatedWordVector;
  for (util::TokenIter<util::AnyCharacter, true> it(phraseString, "\t "); it; ++it) {
    annotatedWordVector.push_back(*it);
  }
  // KOMMA|none ART|Def.Z NN|Neut.NotGen.Sg VVFIN|none
  //		to
  // "KOMMA|none" "ART|Def.Z" "NN|Neut.NotGen.Sg" "VVFIN|none"

  m_words.reserve(annotatedWordVector.size()-1);

  for (size_t phrasePos = 0 ; phrasePos < annotatedWordVector.size() -  1 ; phrasePos++) {
    StringPiece &annotatedWord = annotatedWordVector[phrasePos];
    bool isNonTerminal;
    if (annotatedWord.size() >= 2 && *annotatedWord.data() == '[' && annotatedWord.data()[annotatedWord.size() - 1] == ']') {
      // non-term
      isNonTerminal = true;

      size_t nextPos = annotatedWord.find('[', 1);
      UTIL_THROW_IF(nextPos == string::npos, NonTerminalParseException, "The string " << annotatedWord << " was parsed as a non-terminal but does not take the form [source][target].");
      CHECK(nextPos != string::npos);

      if (direction == Input)
        annotatedWord = annotatedWord.substr(1, nextPos - 2);
      else
        annotatedWord = annotatedWord.substr(nextPos + 1, annotatedWord.size() - nextPos - 2);
    } else {
      isNonTerminal = false;
    }

    Word &word = AddWord();
    word.CreateFromString(direction, factorOrder, annotatedWord, isNonTerminal);

  }

  // lhs
  const StringPiece &annotatedWord = annotatedWordVector.back();
  UTIL_THROW_IF(annotatedWord.size() < 2 || *annotatedWord.data() != '[' || annotatedWord.data()[annotatedWord.size() - 1] != ']', NonTerminalParseException, "The last entry should be a single non-terminal but was given as " << annotatedWord);
  lhs.CreateFromString(direction, factorOrder, annotatedWord.substr(1, annotatedWord.size() - 2), true);
  assert(lhs.IsNonTerminal());
}

int Phrase::Compare(const Phrase &other) const
{
#ifdef min
#undef min
#endif
  size_t thisSize			= GetSize()
                        ,compareSize	= other.GetSize();
  if (thisSize != compareSize) {
    return (thisSize < compareSize) ? -1 : 1;
  }

  for (size_t pos = 0 ; pos < thisSize ; pos++) {
    const Word &thisWord	= GetWord(pos)
                            ,&otherWord	= other.GetWord(pos);
    int ret = Word::Compare(thisWord, otherWord);

    if (ret != 0)
      return ret;
  }

  return 0;
}

bool Phrase::Contains(const vector< vector<string> > &subPhraseVector
                      , const vector<FactorType> &inputFactor) const
{
  const size_t subSize = subPhraseVector.size()
                         ,thisSize= GetSize();
  if (subSize > thisSize)
    return false;

  // try to match word-for-word
  for (size_t currStartPos = 0 ; currStartPos < (thisSize - subSize + 1) ; currStartPos++) {
    bool match = true;

    for (size_t currFactorIndex = 0 ; currFactorIndex < inputFactor.size() ; currFactorIndex++) {
      FactorType factorType = inputFactor[currFactorIndex];
      for (size_t currSubPos = 0 ; currSubPos < subSize ; currSubPos++) {
        size_t currThisPos = currSubPos + currStartPos;
        const string &subStr	= subPhraseVector[currSubPos][currFactorIndex]
                                ,&thisStr	= GetFactor(currThisPos, factorType)->GetString();
        if (subStr != thisStr) {
          match = false;
          break;
        }
      }
      if (!match)
        break;
    }

    if (match)
      return true;
  }
  return false;
}

bool Phrase::IsCompatible(const Phrase &inputPhrase) const
{
  if (inputPhrase.GetSize() != GetSize()) {
    return false;
  }

  const size_t size = GetSize();

  const size_t maxNumFactors = MAX_NUM_FACTORS;
  for (size_t currPos = 0 ; currPos < size ; currPos++) {
    for (unsigned int currFactor = 0 ; currFactor < maxNumFactors ; currFactor++) {
      FactorType factorType = static_cast<FactorType>(currFactor);
      const Factor *thisFactor 		= GetFactor(currPos, factorType)
                                    ,*inputFactor	= inputPhrase.GetFactor(currPos, factorType);
      if (thisFactor != NULL && inputFactor != NULL && thisFactor != inputFactor)
        return false;
    }
  }
  return true;

}

bool Phrase::IsCompatible(const Phrase &inputPhrase, FactorType factorType) const
{
  if (inputPhrase.GetSize() != GetSize())	{
    return false;
  }
  for (size_t currPos = 0 ; currPos < GetSize() ; currPos++) {
    if (GetFactor(currPos, factorType) != inputPhrase.GetFactor(currPos, factorType))
      return false;
  }
  return true;
}

bool Phrase::IsCompatible(const Phrase &inputPhrase, const std::vector<FactorType>& factorVec) const
{
  if (inputPhrase.GetSize() != GetSize())	{
    return false;
  }
  for (size_t currPos = 0 ; currPos < GetSize() ; currPos++) {
    for (std::vector<FactorType>::const_iterator i = factorVec.begin();
         i != factorVec.end(); ++i) {
      if (GetFactor(currPos, *i) != inputPhrase.GetFactor(currPos, *i))
        return false;
    }
  }
  return true;
}

size_t Phrase::GetNumTerminals() const
{
  size_t ret = 0;

  for (size_t pos = 0; pos < GetSize(); ++pos) {
    if (!GetWord(pos).IsNonTerminal())
      ret++;
  }
  return ret;
}

void Phrase::InitializeMemPool()
{
}

void Phrase::FinalizeMemPool()
{
}

TO_STRING_BODY(Phrase);

// friend
ostream& operator<<(ostream& out, const Phrase& phrase)
{
//	out << "(size " << phrase.GetSize() << ") ";
  for (size_t pos = 0 ; pos < phrase.GetSize() ; pos++) {
    const Word &word = phrase.GetWord(pos);
    out << word;
  }
  return out;
}

}

<|endoftext|>