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

// include ---------------------------------------------------------------

#ifndef _STDCTRL_HXX //autogen
#include <svtools/stdctrl.hxx>
#endif
#ifndef _COMBOBOX_HXX //autogen
#include <vcl/combobox.hxx>
#endif
#ifndef _EDIT_HXX //autogen
#include <vcl/edit.hxx>
#endif
#ifndef _LSTBOX_HXX //autogen
#include <vcl/lstbox.hxx>
#endif
#ifndef _BUTTON_HXX //autogen
#include <vcl/button.hxx>
#endif
#ifndef _GROUP_HXX //autogen
#include <vcl/group.hxx>
#endif
#ifndef _FIXED_HXX //autogen
#include <vcl/fixed.hxx>
#endif
#ifndef _DIALOG_HXX //autogen
#include <vcl/dialog.hxx>
#endif
#ifndef _SFX_CHILDWIN_HXX //autogen
#include <sfx2/childwin.hxx>
#endif
#ifndef _BASEDLGS_HXX
#include <sfx2/basedlgs.hxx>
#endif
#ifndef _SVARRAY_HXX //autogen
#include <svtools/svarray.hxx>
#endif
#define _SVSTDARR_STRINGSDTOR
#include <svtools/svstdarr.hxx>

#ifndef _SVEDIT_HXX //autogen
#include <svtools/svmedit.hxx>
#endif

#ifndef _SFX_SRCHDEFS_HXX_
#include <sfx2/srchdefs.hxx>
#endif

#ifndef INCLUDED_SVXDLLAPI_H
#include "svx/svxdllapi.h"
#endif

// forward ---------------------------------------------------------------

class SvxSearchItem;
class MoreButton;
class SfxStyleSheetBasePool;
class SvxJSearchOptionsPage;
class SvxSearchController;

struct SearchDlg_Impl;

#ifndef NO_SVX_SEARCH

// struct SearchAttrItem -------------------------------------------------

struct SearchAttrItem
{
    USHORT          nSlot;
    SfxPoolItem*    pItem;
};

// class SearchAttrItemList ----------------------------------------------

SV_DECL_VARARR_VISIBILITY(SrchAttrItemList, SearchAttrItem, 8, 8, SVX_DLLPUBLIC);

class SVX_DLLPUBLIC SearchAttrItemList : private SrchAttrItemList
{
public:
    SearchAttrItemList() {}
    SearchAttrItemList( const SearchAttrItemList& rList );
    ~SearchAttrItemList();

    void            Put( const SfxItemSet& rSet );
    SfxItemSet&     Get( SfxItemSet& rSet );
    void            Clear();
    USHORT          Count() const { return SrchAttrItemList::Count(); }
    SearchAttrItem& operator[](USHORT nPos) const
                        { return SrchAttrItemList::operator[]( nPos ); }
    SearchAttrItem& GetObject( USHORT nPos ) const
                        { return SrchAttrItemList::GetObject( nPos ); }

    // der Pointer auf das Item wird nicht kopiert!!! (also nicht l"oschen)
    void Insert( const SearchAttrItem& rItem )
        { SrchAttrItemList::Insert( rItem, SrchAttrItemList::Count() ); }
    // l"oscht die Pointer auf die Items
    void Remove( USHORT nPos, USHORT nLen = 1 );
};

#ifndef SV_NODIALOG

// class SvxSearchDialogWrapper ------------------------------------------

class SVX_DLLPUBLIC SvxSearchDialogWrapper : public SfxChildWindow
{
public:
    SvxSearchDialogWrapper( Window*pParent, USHORT nId,
                            SfxBindings* pBindings, SfxChildWinInfo* pInfo );

    SFX_DECL_CHILDWINDOW(SvxSearchDialogWrapper);
};

// class SvxSearchDialog -------------------------------------------------

/*
    {k:\svx\prototyp\dialog\srchdlg.hxx}

    [Beschreibung]
    In diesem Modeless-Dialog werden die Attribute einer Suche eingestellt
    und damit eine Suche gestartet. Es sind mehrere Sucharten
    ( Suchen, Alle suchen, Ersetzen, Alle ersetzen ) m"oglich.

    [Items]
    <SvxSearchItem><SID_ATTR_SEARCH>
*/

class SvxSearchDialog : public SfxModelessDialog
{
friend class SvxSearchController;
friend class SvxSearchDialogWrapper;
friend class SvxJSearchOptionsDialog;

public:
    SvxSearchDialog( Window* pParent, SfxBindings& rBind );
    SvxSearchDialog( Window* pParent, SfxChildWindow* pChildWin, SfxBindings& rBind );
    ~SvxSearchDialog();

    virtual BOOL    Close();

    // Window
    virtual void    Activate();

    void            GetSearchItems( SfxItemSet& rSet );
    void            GetReplaceItems( SfxItemSet& rSet );

    const SearchAttrItemList*   GetSearchItemList() const
                                    { return pSearchList; }
    const SearchAttrItemList*   GetReplaceItemList() const
                                    { return pReplaceList; }

    inline BOOL     HasSearchAttributes() const;
    inline BOOL     HasReplaceAttributes() const;

    PushButton&     GetReplaceBtn() { return aReplaceBtn; }

    INT32           GetTransliterationFlags() const;

private:
    FixedText       aSearchText;
    ComboBox        aSearchLB;
    ListBox         aSearchTmplLB;
    FixedInfo       aSearchAttrText;

    FixedText       aReplaceText;
    ComboBox        aReplaceLB;
    ListBox         aReplaceTmplLB;
    FixedInfo       aReplaceAttrText;

    PushButton      aSearchBtn;
    PushButton      aSearchAllBtn;
    FixedLine       aSearchCmdLine;
    PushButton      aReplaceBtn;
    PushButton      aReplaceAllBtn;

    FixedLine       aSearchComponentFL;
    PushButton      aSearchComponent1PB;
    PushButton      aSearchComponent2PB;

    CheckBox        aMatchCaseCB;
    CheckBox        aWordBtn;

    FixedLine       aButtonsFL;
    MoreButton*     pMoreBtn;
    HelpButton      aHelpBtn;
    CancelButton    aCloseBtn;

    FixedLine       aOptionsFL;
    CheckBox        aSelectionBtn;
    CheckBox        aBackwardsBtn;
    CheckBox        aRegExpBtn;
    CheckBox        aSimilarityBox;
    PushButton      aSimilarityBtn;
    CheckBox        aLayoutBtn;
    CheckBox        aJapMatchFullHalfWidthCB;
    CheckBox        aJapOptionsCB;
    PushButton      aJapOptionsBtn;

    PushButton      aAttributeBtn;
    PushButton      aFormatBtn;
    PushButton      aNoFormatBtn;

    FixedLine       aCalcFL;
    FixedText       aCalcSearchInFT;
    ListBox         aCalcSearchInLB;
    FixedText       aCalcSearchDirFT;
    RadioButton     aRowsBtn;
    RadioButton     aColumnsBtn;
    CheckBox        aAllSheetsCB;

    SfxBindings&    rBindings;
    BOOL            bWriter;
    BOOL            bSearch;
    BOOL            bFormat;
    USHORT          nOptions;
    FASTBOOL        bSet;
    FASTBOOL        bReadOnly;
    FASTBOOL        bConstruct;
    ULONG           nModifyFlag;
    String          aStylesStr;
    String          aLayoutStr;
    String          aCalcStr;

    SvStringsDtor   aSearchStrings;
    SvStringsDtor   aReplaceStrings;

    SearchDlg_Impl*         pImpl;
    SearchAttrItemList*     pSearchList;
    SearchAttrItemList*     pReplaceList;
    SvxSearchItem*          pSearchItem;

    SvxSearchController*    pSearchController;
    SvxSearchController*    pOptionsController;
    SvxSearchController*    pFamilyController;
    SvxSearchController*    pSearchSetController;
    SvxSearchController*    pReplaceSetController;

    mutable INT32           nTransliterationFlags;

#ifdef _SVX_SRCHDLG_CXX
    DECL_LINK( ModifyHdl_Impl, ComboBox* pEdit );
    DECL_LINK( FlagHdl_Impl, Control* pCtrl );
    DECL_LINK( CommandHdl_Impl, Button* pBtn );
    DECL_LINK( TemplateHdl_Impl, Button* );
    DECL_LINK( FocusHdl_Impl, Control* );
    DECL_LINK( LoseFocusHdl_Impl, Control* );
    DECL_LINK( FormatHdl_Impl, Button* );
    DECL_LINK( NoFormatHdl_Impl, Button* );
    DECL_LINK( AttributeHdl_Impl, Button* );
    DECL_LINK( TimeoutHdl_Impl, Timer* );

    void            Construct_Impl();
    void            InitControls_Impl();
    void            CalculateDelta_Impl();
    void            Init_Impl( int bHasItemSet );
    void            InitAttrList_Impl( const SfxItemSet* pSSet,
                                       const SfxItemSet* pRSet );
    void            Remember_Impl( const String &rStr,BOOL bSearch );
    void            PaintAttrText_Impl();
    String&         BuildAttrText_Impl( String& rStr, BOOL bSrchFlag ) const;

    void            TemplatesChanged_Impl( SfxStyleSheetBasePool& rPool );
    void            EnableControls_Impl( const USHORT nFlags );
    void            EnableControl_Impl( Control* pCtrl );
    void            SetItem_Impl( const SvxSearchItem* pItem );

    void            SetModifyFlag_Impl( const Control* pCtrl );
    void            SaveToModule_Impl();

    void            ApplyTransliterationFlags_Impl( INT32 nSettings );
#endif
};

inline BOOL SvxSearchDialog::HasSearchAttributes() const
{
    int bLen = aSearchAttrText.GetText().Len();
    return ( aSearchAttrText.IsEnabled() && bLen );
}

inline BOOL SvxSearchDialog::HasReplaceAttributes() const
{
    int bLen = aReplaceAttrText.GetText().Len();
    return ( aReplaceAttrText.IsEnabled() && bLen );
}

//////////////////////////////////////////////////////////////////////

/* //CHINA001
class SvxJSearchOptionsDialog : public SfxSingleTabDialog
{
    INT32                   nInitialTlFlags;
    SvxJSearchOptionsPage  *pPage;

    // disallow copy-constructor and assignment-operator for now
    SvxJSearchOptionsDialog( const SvxJSearchOptionsDialog & );
    SvxJSearchOptionsDialog & operator == ( const SvxJSearchOptionsDialog & );

public:
    SvxJSearchOptionsDialog( Window *pParent,
                            const SfxItemSet& rOptionsSet, USHORT nUniqueId,
                            INT32 nInitialFlags  );
    virtual ~SvxJSearchOptionsDialog();

    // Window
    virtual void    Activate();

    INT32           GetTransliterationFlags() const;
    void            SetTransliterationFlags( INT32 nSettings );
};
*/ //CHINA001

//////////////////////////////////////////////////////////////////////

#endif  // SV_NODIALOG
#endif  // NO_SVX_SEARCH

#endif

<commit_msg>INTEGRATION: CWS warnings01 (1.14.220); FILE MERGED 2006/04/07 17:58:52 sb 1.14.220.2: RESYNC: (1.14-1.15); FILE MERGED 2006/02/17 15:23:28 cl 1.14.220.1: warning free code changes<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: srchdlg.hxx,v $
 *
 *  $Revision: 1.16 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 14:42:19 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _SVX_SRCHDLG_HXX
#define _SVX_SRCHDLG_HXX

// include ---------------------------------------------------------------

#ifndef _STDCTRL_HXX //autogen
#include <svtools/stdctrl.hxx>
#endif
#ifndef _COMBOBOX_HXX //autogen
#include <vcl/combobox.hxx>
#endif
#ifndef _EDIT_HXX //autogen
#include <vcl/edit.hxx>
#endif
#ifndef _LSTBOX_HXX //autogen
#include <vcl/lstbox.hxx>
#endif
#ifndef _BUTTON_HXX //autogen
#include <vcl/button.hxx>
#endif
#ifndef _GROUP_HXX //autogen
#include <vcl/group.hxx>
#endif
#ifndef _FIXED_HXX //autogen
#include <vcl/fixed.hxx>
#endif
#ifndef _DIALOG_HXX //autogen
#include <vcl/dialog.hxx>
#endif
#ifndef _SFX_CHILDWIN_HXX //autogen
#include <sfx2/childwin.hxx>
#endif
#ifndef _BASEDLGS_HXX
#include <sfx2/basedlgs.hxx>
#endif
#ifndef _SVARRAY_HXX //autogen
#include <svtools/svarray.hxx>
#endif
#define _SVSTDARR_STRINGSDTOR
#include <svtools/svstdarr.hxx>

#ifndef _SVEDIT_HXX //autogen
#include <svtools/svmedit.hxx>
#endif

#ifndef _SFX_SRCHDEFS_HXX_
#include <sfx2/srchdefs.hxx>
#endif

#ifndef INCLUDED_SVXDLLAPI_H
#include "svx/svxdllapi.h"
#endif

// forward ---------------------------------------------------------------

class SvxSearchItem;
class MoreButton;
class SfxStyleSheetBasePool;
class SvxJSearchOptionsPage;
class SvxSearchController;

struct SearchDlg_Impl;

#ifndef NO_SVX_SEARCH

// struct SearchAttrItem -------------------------------------------------

struct SearchAttrItem
{
    USHORT          nSlot;
    SfxPoolItem*    pItem;
};

// class SearchAttrItemList ----------------------------------------------

SV_DECL_VARARR_VISIBILITY(SrchAttrItemList, SearchAttrItem, 8, 8, SVX_DLLPUBLIC)

class SVX_DLLPUBLIC SearchAttrItemList : private SrchAttrItemList
{
public:
    SearchAttrItemList() {}
    SearchAttrItemList( const SearchAttrItemList& rList );
    ~SearchAttrItemList();

    void            Put( const SfxItemSet& rSet );
    SfxItemSet&     Get( SfxItemSet& rSet );
    void            Clear();
    USHORT          Count() const { return SrchAttrItemList::Count(); }
    SearchAttrItem& operator[](USHORT nPos) const
                        { return SrchAttrItemList::operator[]( nPos ); }
    SearchAttrItem& GetObject( USHORT nPos ) const
                        { return SrchAttrItemList::GetObject( nPos ); }

    // der Pointer auf das Item wird nicht kopiert!!! (also nicht l"oschen)
    void Insert( const SearchAttrItem& rItem )
        { SrchAttrItemList::Insert( rItem, SrchAttrItemList::Count() ); }
    // l"oscht die Pointer auf die Items
    void Remove( USHORT nPos, USHORT nLen = 1 );
};

#ifndef SV_NODIALOG

// class SvxSearchDialogWrapper ------------------------------------------

class SVX_DLLPUBLIC SvxSearchDialogWrapper : public SfxChildWindow
{
public:
    SvxSearchDialogWrapper( Window*pParent, USHORT nId,
                            SfxBindings* pBindings, SfxChildWinInfo* pInfo );

    SFX_DECL_CHILDWINDOW(SvxSearchDialogWrapper);
};

// class SvxSearchDialog -------------------------------------------------

/*
    {k:\svx\prototyp\dialog\srchdlg.hxx}

    [Beschreibung]
    In diesem Modeless-Dialog werden die Attribute einer Suche eingestellt
    und damit eine Suche gestartet. Es sind mehrere Sucharten
    ( Suchen, Alle suchen, Ersetzen, Alle ersetzen ) m"oglich.

    [Items]
    <SvxSearchItem><SID_ATTR_SEARCH>
*/

class SvxSearchDialog : public SfxModelessDialog
{
friend class SvxSearchController;
friend class SvxSearchDialogWrapper;
friend class SvxJSearchOptionsDialog;

public:
    SvxSearchDialog( Window* pParent, SfxBindings& rBind );
    SvxSearchDialog( Window* pParent, SfxChildWindow* pChildWin, SfxBindings& rBind );
    ~SvxSearchDialog();

    virtual BOOL    Close();

    // Window
    virtual void    Activate();

    void            GetSearchItems( SfxItemSet& rSet );
    void            GetReplaceItems( SfxItemSet& rSet );

    const SearchAttrItemList*   GetSearchItemList() const
                                    { return pSearchList; }
    const SearchAttrItemList*   GetReplaceItemList() const
                                    { return pReplaceList; }

    inline BOOL     HasSearchAttributes() const;
    inline BOOL     HasReplaceAttributes() const;

    PushButton&     GetReplaceBtn() { return aReplaceBtn; }

    INT32           GetTransliterationFlags() const;

private:
    FixedText       aSearchText;
    ComboBox        aSearchLB;
    ListBox         aSearchTmplLB;
    FixedInfo       aSearchAttrText;

    FixedText       aReplaceText;
    ComboBox        aReplaceLB;
    ListBox         aReplaceTmplLB;
    FixedInfo       aReplaceAttrText;

    PushButton      aSearchBtn;
    PushButton      aSearchAllBtn;
    FixedLine       aSearchCmdLine;
    PushButton      aReplaceBtn;
    PushButton      aReplaceAllBtn;

    FixedLine       aSearchComponentFL;
    PushButton      aSearchComponent1PB;
    PushButton      aSearchComponent2PB;

    CheckBox        aMatchCaseCB;
    CheckBox        aWordBtn;

    FixedLine       aButtonsFL;
    MoreButton*     pMoreBtn;
    HelpButton      aHelpBtn;
    CancelButton    aCloseBtn;

    FixedLine       aOptionsFL;
    CheckBox        aSelectionBtn;
    CheckBox        aBackwardsBtn;
    CheckBox        aRegExpBtn;
    CheckBox        aSimilarityBox;
    PushButton      aSimilarityBtn;
    CheckBox        aLayoutBtn;
    CheckBox        aJapMatchFullHalfWidthCB;
    CheckBox        aJapOptionsCB;
    PushButton      aJapOptionsBtn;

    PushButton      aAttributeBtn;
    PushButton      aFormatBtn;
    PushButton      aNoFormatBtn;

    FixedLine       aCalcFL;
    FixedText       aCalcSearchInFT;
    ListBox         aCalcSearchInLB;
    FixedText       aCalcSearchDirFT;
    RadioButton     aRowsBtn;
    RadioButton     aColumnsBtn;
    CheckBox        aAllSheetsCB;

    SfxBindings&    rBindings;
    BOOL            bWriter;
    BOOL            bSearch;
    BOOL            bFormat;
    USHORT          nOptions;
    FASTBOOL        bSet;
    FASTBOOL        bReadOnly;
    FASTBOOL        bConstruct;
    ULONG           nModifyFlag;
    String          aStylesStr;
    String          aLayoutStr;
    String          aCalcStr;

    SvStringsDtor   aSearchStrings;
    SvStringsDtor   aReplaceStrings;

    SearchDlg_Impl*         pImpl;
    SearchAttrItemList*     pSearchList;
    SearchAttrItemList*     pReplaceList;
    SvxSearchItem*          pSearchItem;

    SvxSearchController*    pSearchController;
    SvxSearchController*    pOptionsController;
    SvxSearchController*    pFamilyController;
    SvxSearchController*    pSearchSetController;
    SvxSearchController*    pReplaceSetController;

    mutable INT32           nTransliterationFlags;

#ifdef _SVX_SRCHDLG_CXX
    DECL_LINK( ModifyHdl_Impl, ComboBox* pEdit );
    DECL_LINK( FlagHdl_Impl, Control* pCtrl );
    DECL_LINK( CommandHdl_Impl, Button* pBtn );
    DECL_LINK( TemplateHdl_Impl, Button* );
    DECL_LINK( FocusHdl_Impl, Control* );
    DECL_LINK( LoseFocusHdl_Impl, Control* );
    DECL_LINK( FormatHdl_Impl, Button* );
    DECL_LINK( NoFormatHdl_Impl, Button* );
    DECL_LINK( AttributeHdl_Impl, Button* );
    DECL_LINK( TimeoutHdl_Impl, Timer* );

    void            Construct_Impl();
    void            InitControls_Impl();
    void            CalculateDelta_Impl();
    void            Init_Impl( int bHasItemSet );
    void            InitAttrList_Impl( const SfxItemSet* pSSet,
                                       const SfxItemSet* pRSet );
    void            Remember_Impl( const String &rStr,BOOL bSearch );
    void            PaintAttrText_Impl();
    String&         BuildAttrText_Impl( String& rStr, BOOL bSrchFlag ) const;

    void            TemplatesChanged_Impl( SfxStyleSheetBasePool& rPool );
    void            EnableControls_Impl( const USHORT nFlags );
    void            EnableControl_Impl( Control* pCtrl );
    void            SetItem_Impl( const SvxSearchItem* pItem );

    void            SetModifyFlag_Impl( const Control* pCtrl );
    void            SaveToModule_Impl();

    void            ApplyTransliterationFlags_Impl( INT32 nSettings );
#endif
};

inline BOOL SvxSearchDialog::HasSearchAttributes() const
{
    int bLen = aSearchAttrText.GetText().Len();
    return ( aSearchAttrText.IsEnabled() && bLen );
}

inline BOOL SvxSearchDialog::HasReplaceAttributes() const
{
    int bLen = aReplaceAttrText.GetText().Len();
    return ( aReplaceAttrText.IsEnabled() && bLen );
}

//////////////////////////////////////////////////////////////////////

/* //CHINA001
class SvxJSearchOptionsDialog : public SfxSingleTabDialog
{
    INT32                   nInitialTlFlags;
    SvxJSearchOptionsPage  *pPage;

    // disallow copy-constructor and assignment-operator for now
    SvxJSearchOptionsDialog( const SvxJSearchOptionsDialog & );
    SvxJSearchOptionsDialog & operator == ( const SvxJSearchOptionsDialog & );

public:
    SvxJSearchOptionsDialog( Window *pParent,
                            const SfxItemSet& rOptionsSet, USHORT nUniqueId,
                            INT32 nInitialFlags  );
    virtual ~SvxJSearchOptionsDialog();

    // Window
    virtual void    Activate();

    INT32           GetTransliterationFlags() const;
    void            SetTransliterationFlags( INT32 nSettings );
};
*/ //CHINA001

//////////////////////////////////////////////////////////////////////

#endif  // SV_NODIALOG
#endif  // NO_SVX_SEARCH

#endif

<|endoftext|>


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

#include "tincan.h"
#include "tincan_exception.h"
namespace tincan
{
Tincan::Tincan() :
  exit_event_(false, false)
{}

Tincan::~Tincan()
{
}

void
Tincan::SetIpopControllerLink(
  shared_ptr<IpopControllerLink> ctrl_handle)
{
  ctrl_link_ = ctrl_handle;
}

void Tincan::CreateOverlay(
  const Json::Value & olay_desc)
{
  unique_ptr<OverlayDescriptor> ol_desc(new OverlayDescriptor);
  ol_desc->uid = olay_desc[TincanControl::OverlayId].asString();
  if(IsOverlayExisit(ol_desc->uid))
    throw TCEXCEPT("The specified overlay identifier already exisits");
  ol_desc->stun_addr = olay_desc["StunAddress"].asString();
  ol_desc->turn_addr = olay_desc["TurnAddress"].asString();
  ol_desc->turn_pass = olay_desc["TurnPass"].asString();
  ol_desc->turn_user = olay_desc["TurnUser"].asString();
  ol_desc->enable_ip_mapping = olay_desc["EnableIPMapping"].asBool();
  unique_ptr<Overlay> olay;
  if(olay_desc["Type"].asString() == "VNET")
  {
    olay = make_unique<VirtualNetwork>(move(ol_desc), ctrl_link_);
  }
  else if(olay_desc["Type"].asString() == "TUNNEL")
  {
    olay = make_unique<Tunnel>(move(ol_desc), ctrl_link_);
  }
  else
    throw TCEXCEPT("Invalid Overlay type specified");
  unique_ptr<TapDescriptor> tap_desc = make_unique<TapDescriptor>();
  tap_desc->name = olay_desc["TapName"].asString();
  tap_desc->ip4 = olay_desc["IP4"].asString();
  tap_desc->prefix4 = olay_desc["PrefixLen4"].asUInt();
  tap_desc->mtu4 = olay_desc[TincanControl::MTU4].asUInt();

  olay->Configure(move(tap_desc));
  olay->Start();
  lock_guard<mutex> lg(ovlays_mutex_);
  ovlays_.push_back(move(olay));

  return;
}

void
Tincan::CreateVlink(
  const Json::Value & link_desc,
  TincanControl & ctrl)
{
  unique_ptr<PeerDescriptor> peer_desc = make_unique<PeerDescriptor>();
  peer_desc->uid =
    link_desc[TincanControl::PeerInfo][TincanControl::UID].asString();
  peer_desc->vip4 =
    link_desc[TincanControl::PeerInfo][TincanControl::VIP4].asString();
  peer_desc->cas =
    link_desc[TincanControl::PeerInfo][TincanControl::CAS].asString();
  peer_desc->fingerprint =
    link_desc[TincanControl::PeerInfo][TincanControl::FPR].asString();
  peer_desc->mac_address =
    link_desc[TincanControl::PeerInfo][TincanControl::MAC].asString();
  string tap_name = link_desc[TincanControl::TapName].asString();
  unique_ptr<VlinkDescriptor> vl_desc = make_unique<VlinkDescriptor>();
  vl_desc->uid = link_desc[TincanControl::LinkId].asString();
  string olid = link_desc[TincanControl::OverlayId].asString();
  vl_desc->sec_enabled = link_desc[TincanControl::EncryptionEnabled].asBool();

  Overlay & ol = OverlayFromId(olid);
  shared_ptr<VirtualLink> vlink =
    ol.CreateVlink(move(vl_desc), move(peer_desc));
  if(vlink->Candidates().empty())
  {
    std::lock_guard<std::mutex> lg(inprogess_controls_mutex_);
    inprogess_controls_.push_back(
      make_pair(link_desc[TincanControl::LinkId].asString(), ctrl));
    vlink->SignalLocalCasReady.connect(this, &Tincan::OnLocalCasUpdated);
  }
  else
  {
    ctrl.SetResponse(vlink->Candidates(), true);
    ctrl_link_->Deliver(ctrl);
  }
}

void
Tincan::InjectFrame(
  const Json::Value & frame_desc)
{
  const string & olid = frame_desc[TincanControl::OverlayId].asString();
  Overlay & ol = OverlayFromId(olid);
  ol.InjectFame(frame_desc[TincanControl::Data].asString());
}

void
Tincan::QueryLinkCas(
  const Json::Value & link_desc,
  Json::Value & cas_info)
{
  const string olid = link_desc[TincanControl::OverlayId].asString();
  const string vlid = link_desc[TincanControl::LinkId].asString();
  Overlay & ol = OverlayFromId(olid);
  ol.QueryLinkCas(vlid, cas_info);
}

void
Tincan::QueryLinkStats(
  const Json::Value & overlay_ids,
  Json::Value & stat_info)
{
  for(uint32_t i = 0; i < overlay_ids["OverlayIds"].size(); i++)
  {
    vector<string>link_ids;
    string olid = overlay_ids["OverlayIds"][i].asString();
    stat_info[olid] = Json::Value(Json::objectValue);
    Overlay & ol = OverlayFromId(olid);
    ol.QueryLinkIds(link_ids);
    for(auto vlid : link_ids)
    {
      ol.QueryLinkInfo(vlid, stat_info[olid]);
    }
  }

}

void
Tincan::QueryOverlayInfo(
  const Json::Value & olay_desc,
  Json::Value & olay_info)
{
  Overlay & ol = OverlayFromId(olay_desc[TincanControl::OverlayId].asString());
  ol.QueryInfo(olay_info);
}

void
Tincan::RemoveOverlay(
  const Json::Value & olay_desc)
{
  const string olid = olay_desc[TincanControl::OverlayId].asString();
  if(olid.empty())
    throw TCEXCEPT("No overlay id specified");

  lock_guard<mutex> lg(ovlays_mutex_);
  for(auto ol = ovlays_.begin(); ol != ovlays_.end(); ol++)
  {
    if((*ol)->Descriptor().uid.compare(olid) == 0)
    {
      (*ol)->Shutdown();
      ovlays_.erase(ol);
    }
  }
  LOG(LS_WARNING) << "No such virtual network exists " << olid;
}

void
Tincan::RemoveVlink(
  const Json::Value & link_desc)
{
  const string olid = link_desc[TincanControl::OverlayId].asString();
  const string vlid = link_desc[TincanControl::LinkId].asString();
  if(olid.empty() || vlid.empty())
    throw TCEXCEPT("Required identifier not specified");

  lock_guard<mutex> lg(ovlays_mutex_);
  for(auto & ol : ovlays_)
  {
    if(ol->Descriptor().uid.compare(olid) == 0)
    {
      ol->RemoveLink(vlid);
    }
  }
}

void
Tincan::SendIcc(
  const Json::Value & icc_desc)
{
  const string olid = icc_desc[TincanControl::OverlayId].asString();
  Overlay & ol = OverlayFromId(olid);
  const string & link_id = icc_desc[TincanControl::LinkId].asString();
  const string & data = icc_desc[TincanControl::Data].asString();
  ol.SendIcc(link_id, data);
}

void
Tincan::SetIgnoredNetworkInterfaces(
  const Json::Value & ignore_list)
{
  int count = ignore_list[TincanControl::IgnoredNetInterfaces].size();
  Json::Value network_ignore_list =
    ignore_list[TincanControl::IgnoredNetInterfaces];
  vector<string> if_list(count);
  for(int i = 0; i < count; i++)
  {
    if_list[i] = network_ignore_list[i].asString();
  }

  Overlay & oly = OverlayFromId(ignore_list[TincanControl::OverlayId].asString());
  oly.IgnoredNetworkInterfaces(if_list);
}

void
Tincan::OnLocalCasUpdated(
  string link_id,
  string lcas)
{
  if(lcas.empty())
  {
    lcas = "No local candidates available on this vlink";
    LOG(LS_WARNING) << lcas;
  }
  bool to_deliver = false;
  unique_ptr<TincanControl> ctrl;
  {
    std::lock_guard<std::mutex> lg(inprogess_controls_mutex_);
    auto itr = inprogess_controls_.begin();
    for(; itr != inprogess_controls_.end(); itr++)
    {
      if(itr->first == link_id)
      {
        to_deliver = true;
        ctrl = make_unique<TincanControl>(move(itr->second));
        inprogess_controls_.erase(itr);
        break;
      }
    }
  }
  if(to_deliver)
  {
    ctrl->SetResponse(lcas, true);
    ctrl_link_->Deliver(move(ctrl));
  }
}

void Tincan::UpdateRouteTable(
  const Json::Value & rts_desc)
{
  string olid = rts_desc[TincanControl::OverlayId].asString();
  Overlay & ol = OverlayFromId(olid);
  ol.UpdateRouteTable(rts_desc["Table"]);
}

void
Tincan::Run()
{
  //TODO:Code cleanup
#if defined(_IPOP_WIN)
  self_ = this;
  SetConsoleCtrlHandler(ControlHandler, TRUE);
#endif // _IPOP_WIN

  //Start tincan control to get config from Controller
  unique_ptr<ControlDispatch> ctrl_dispatch(new ControlDispatch);
  ctrl_dispatch->SetDispatchToTincanInf(this);
  ctrl_listener_ = make_shared<ControlListener>(move(ctrl_dispatch));
  ctl_thread_.Start(ctrl_listener_.get());
  exit_event_.Wait(Event::kForever);
}

bool
Tincan::IsOverlayExisit(
  const string & oid)
{
  lock_guard<mutex> lg(ovlays_mutex_);
  for(auto const & vnet : ovlays_) {
    if(vnet->Descriptor().uid.compare(oid) == 0)
      return true;
  }
  return false;
}

Overlay &
Tincan::OverlayFromId(
  const string & oid)
{
  lock_guard<mutex> lg(ovlays_mutex_);
  for(auto const & vnet : ovlays_)
  {
    //list of vnets will be small enough where a linear search is satifactory
    if(vnet->Descriptor().uid.compare(oid) == 0)
      return *vnet.get();
  }
  string msg("No virtual network exists by this name: ");
  msg.append(oid);
  throw TCEXCEPT(msg.c_str());
}
//-----------------------------------------------------------------------------
void Tincan::OnStop() {
  Shutdown();
  exit_event_.Set();
}

void
Tincan::Shutdown()
{
  lock_guard<mutex> lg(ovlays_mutex_);
  ctl_thread_.Quit();
  for(auto const & vnet : ovlays_) {
    vnet->Shutdown();
  }
}

/*
FUNCTION:ControlHandler
PURPOSE: Handles keyboard signals
PARAMETERS: The signal code
RETURN VALUE: Success/Failure
++*/
#if defined(_IPOP_WIN)
BOOL __stdcall Tincan::ControlHandler(DWORD CtrlType) {
  switch(CtrlType) {
  case CTRL_BREAK_EVENT:  // use Ctrl+C or Ctrl+Break to send
  case CTRL_C_EVENT:      // termination signal
    cout << "Stopping tincan... " << std::endl;
    self_->OnStop();
    return(TRUE);
  }
  return(FALSE);
}
#endif // _IPOP_WIN
} // namespace tincan
<commit_msg>Verify ICC data is a string<commit_after>/*
* ipop-project
* Copyright 2016, University of Florida
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#include "tincan.h"
#include "tincan_exception.h"
namespace tincan
{
Tincan::Tincan() :
  exit_event_(false, false)
{}

Tincan::~Tincan()
{
}

void
Tincan::SetIpopControllerLink(
  shared_ptr<IpopControllerLink> ctrl_handle)
{
  ctrl_link_ = ctrl_handle;
}

void Tincan::CreateOverlay(
  const Json::Value & olay_desc)
{
  unique_ptr<OverlayDescriptor> ol_desc(new OverlayDescriptor);
  ol_desc->uid = olay_desc[TincanControl::OverlayId].asString();
  if(IsOverlayExisit(ol_desc->uid))
    throw TCEXCEPT("The specified overlay identifier already exisits");
  ol_desc->stun_addr = olay_desc["StunAddress"].asString();
  ol_desc->turn_addr = olay_desc["TurnAddress"].asString();
  ol_desc->turn_pass = olay_desc["TurnPass"].asString();
  ol_desc->turn_user = olay_desc["TurnUser"].asString();
  ol_desc->enable_ip_mapping = olay_desc["EnableIPMapping"].asBool();
  unique_ptr<Overlay> olay;
  if(olay_desc["Type"].asString() == "VNET")
  {
    olay = make_unique<VirtualNetwork>(move(ol_desc), ctrl_link_);
  }
  else if(olay_desc["Type"].asString() == "TUNNEL")
  {
    olay = make_unique<Tunnel>(move(ol_desc), ctrl_link_);
  }
  else
    throw TCEXCEPT("Invalid Overlay type specified");
  unique_ptr<TapDescriptor> tap_desc = make_unique<TapDescriptor>();
  tap_desc->name = olay_desc["TapName"].asString();
  tap_desc->ip4 = olay_desc["IP4"].asString();
  tap_desc->prefix4 = olay_desc["PrefixLen4"].asUInt();
  tap_desc->mtu4 = olay_desc[TincanControl::MTU4].asUInt();

  olay->Configure(move(tap_desc));
  olay->Start();
  lock_guard<mutex> lg(ovlays_mutex_);
  ovlays_.push_back(move(olay));

  return;
}

void
Tincan::CreateVlink(
  const Json::Value & link_desc,
  TincanControl & ctrl)
{
  unique_ptr<PeerDescriptor> peer_desc = make_unique<PeerDescriptor>();
  peer_desc->uid =
    link_desc[TincanControl::PeerInfo][TincanControl::UID].asString();
  peer_desc->vip4 =
    link_desc[TincanControl::PeerInfo][TincanControl::VIP4].asString();
  peer_desc->cas =
    link_desc[TincanControl::PeerInfo][TincanControl::CAS].asString();
  peer_desc->fingerprint =
    link_desc[TincanControl::PeerInfo][TincanControl::FPR].asString();
  peer_desc->mac_address =
    link_desc[TincanControl::PeerInfo][TincanControl::MAC].asString();
  string tap_name = link_desc[TincanControl::TapName].asString();
  unique_ptr<VlinkDescriptor> vl_desc = make_unique<VlinkDescriptor>();
  vl_desc->uid = link_desc[TincanControl::LinkId].asString();
  string olid = link_desc[TincanControl::OverlayId].asString();
  vl_desc->sec_enabled = link_desc[TincanControl::EncryptionEnabled].asBool();

  Overlay & ol = OverlayFromId(olid);
  shared_ptr<VirtualLink> vlink =
    ol.CreateVlink(move(vl_desc), move(peer_desc));
  if(vlink->Candidates().empty())
  {
    std::lock_guard<std::mutex> lg(inprogess_controls_mutex_);
    inprogess_controls_.push_back(
      make_pair(link_desc[TincanControl::LinkId].asString(), ctrl));
    vlink->SignalLocalCasReady.connect(this, &Tincan::OnLocalCasUpdated);
  }
  else
  {
    ctrl.SetResponse(vlink->Candidates(), true);
    ctrl_link_->Deliver(ctrl);
  }
}

void
Tincan::InjectFrame(
  const Json::Value & frame_desc)
{
  const string & olid = frame_desc[TincanControl::OverlayId].asString();
  Overlay & ol = OverlayFromId(olid);
  ol.InjectFame(frame_desc[TincanControl::Data].asString());
}

void
Tincan::QueryLinkCas(
  const Json::Value & link_desc,
  Json::Value & cas_info)
{
  const string olid = link_desc[TincanControl::OverlayId].asString();
  const string vlid = link_desc[TincanControl::LinkId].asString();
  Overlay & ol = OverlayFromId(olid);
  ol.QueryLinkCas(vlid, cas_info);
}

void
Tincan::QueryLinkStats(
  const Json::Value & overlay_ids,
  Json::Value & stat_info)
{
  for(uint32_t i = 0; i < overlay_ids["OverlayIds"].size(); i++)
  {
    vector<string>link_ids;
    string olid = overlay_ids["OverlayIds"][i].asString();
    stat_info[olid] = Json::Value(Json::objectValue);
    Overlay & ol = OverlayFromId(olid);
    ol.QueryLinkIds(link_ids);
    for(auto vlid : link_ids)
    {
      ol.QueryLinkInfo(vlid, stat_info[olid]);
    }
  }

}

void
Tincan::QueryOverlayInfo(
  const Json::Value & olay_desc,
  Json::Value & olay_info)
{
  Overlay & ol = OverlayFromId(olay_desc[TincanControl::OverlayId].asString());
  ol.QueryInfo(olay_info);
}

void
Tincan::RemoveOverlay(
  const Json::Value & olay_desc)
{
  const string olid = olay_desc[TincanControl::OverlayId].asString();
  if(olid.empty())
    throw TCEXCEPT("No overlay id specified");

  lock_guard<mutex> lg(ovlays_mutex_);
  for(auto ol = ovlays_.begin(); ol != ovlays_.end(); ol++)
  {
    if((*ol)->Descriptor().uid.compare(olid) == 0)
    {
      (*ol)->Shutdown();
      ovlays_.erase(ol);
    }
  }
  LOG(LS_WARNING) << "No such virtual network exists " << olid;
}

void
Tincan::RemoveVlink(
  const Json::Value & link_desc)
{
  const string olid = link_desc[TincanControl::OverlayId].asString();
  const string vlid = link_desc[TincanControl::LinkId].asString();
  if(olid.empty() || vlid.empty())
    throw TCEXCEPT("Required identifier not specified");

  lock_guard<mutex> lg(ovlays_mutex_);
  for(auto & ol : ovlays_)
  {
    if(ol->Descriptor().uid.compare(olid) == 0)
    {
      ol->RemoveLink(vlid);
    }
  }
}

void
Tincan::SendIcc(
  const Json::Value & icc_desc)
{
  const string olid = icc_desc[TincanControl::OverlayId].asString();
  const string & link_id = icc_desc[TincanControl::LinkId].asString();
  if(icc_desc[TincanControl::Data].isString())
  {
    const string & data = icc_desc[TincanControl::Data].asString();
    Overlay & ol = OverlayFromId(olid);
    ol.SendIcc(link_id, data);
  }
  else
    throw TCEXCEPT("Icc data is not represented as a string");
}

void
Tincan::SetIgnoredNetworkInterfaces(
  const Json::Value & ignore_list)
{
  int count = ignore_list[TincanControl::IgnoredNetInterfaces].size();
  Json::Value network_ignore_list =
    ignore_list[TincanControl::IgnoredNetInterfaces];
  vector<string> if_list(count);
  for(int i = 0; i < count; i++)
  {
    if_list[i] = network_ignore_list[i].asString();
  }

  Overlay & oly = OverlayFromId(ignore_list[TincanControl::OverlayId].asString());
  oly.IgnoredNetworkInterfaces(if_list);
}

void
Tincan::OnLocalCasUpdated(
  string link_id,
  string lcas)
{
  if(lcas.empty())
  {
    lcas = "No local candidates available on this vlink";
    LOG(LS_WARNING) << lcas;
  }
  bool to_deliver = false;
  unique_ptr<TincanControl> ctrl;
  {
    std::lock_guard<std::mutex> lg(inprogess_controls_mutex_);
    auto itr = inprogess_controls_.begin();
    for(; itr != inprogess_controls_.end(); itr++)
    {
      if(itr->first == link_id)
      {
        to_deliver = true;
        ctrl = make_unique<TincanControl>(move(itr->second));
        inprogess_controls_.erase(itr);
        break;
      }
    }
  }
  if(to_deliver)
  {
    ctrl->SetResponse(lcas, true);
    ctrl_link_->Deliver(move(ctrl));
  }
}

void Tincan::UpdateRouteTable(
  const Json::Value & rts_desc)
{
  string olid = rts_desc[TincanControl::OverlayId].asString();
  Overlay & ol = OverlayFromId(olid);
  ol.UpdateRouteTable(rts_desc["Table"]);
}

void
Tincan::Run()
{
  //TODO:Code cleanup
#if defined(_IPOP_WIN)
  self_ = this;
  SetConsoleCtrlHandler(ControlHandler, TRUE);
#endif // _IPOP_WIN

  //Start tincan control to get config from Controller
  unique_ptr<ControlDispatch> ctrl_dispatch(new ControlDispatch);
  ctrl_dispatch->SetDispatchToTincanInf(this);
  ctrl_listener_ = make_shared<ControlListener>(move(ctrl_dispatch));
  ctl_thread_.Start(ctrl_listener_.get());
  exit_event_.Wait(Event::kForever);
}

bool
Tincan::IsOverlayExisit(
  const string & oid)
{
  lock_guard<mutex> lg(ovlays_mutex_);
  for(auto const & vnet : ovlays_) {
    if(vnet->Descriptor().uid.compare(oid) == 0)
      return true;
  }
  return false;
}

Overlay &
Tincan::OverlayFromId(
  const string & oid)
{
  lock_guard<mutex> lg(ovlays_mutex_);
  for(auto const & vnet : ovlays_)
  {
    //list of vnets will be small enough where a linear search is satifactory
    if(vnet->Descriptor().uid.compare(oid) == 0)
      return *vnet.get();
  }
  string msg("No virtual network exists by this name: ");
  msg.append(oid);
  throw TCEXCEPT(msg.c_str());
}
//-----------------------------------------------------------------------------
void Tincan::OnStop() {
  Shutdown();
  exit_event_.Set();
}

void
Tincan::Shutdown()
{
  lock_guard<mutex> lg(ovlays_mutex_);
  ctl_thread_.Quit();
  for(auto const & vnet : ovlays_) {
    vnet->Shutdown();
  }
}

/*
FUNCTION:ControlHandler
PURPOSE: Handles keyboard signals
PARAMETERS: The signal code
RETURN VALUE: Success/Failure
++*/
#if defined(_IPOP_WIN)
BOOL __stdcall Tincan::ControlHandler(DWORD CtrlType) {
  switch(CtrlType) {
  case CTRL_BREAK_EVENT:  // use Ctrl+C or Ctrl+Break to send
  case CTRL_C_EVENT:      // termination signal
    cout << "Stopping tincan... " << std::endl;
    self_->OnStop();
    return(TRUE);
  }
  return(FALSE);
}
#endif // _IPOP_WIN
} // namespace tincan
<|endoftext|>


<commit_before>// tsStego.cpp
// Released under the MIT License
//
// A simple implementation of stegonography in C++
// Uses the LodePNG library version 20140801 by Lode Vandevenne

#include <fstream>
#include <sstream>
#include <iostream>
#include <exception>
#include "lodepng.h"

// Read the plain text file in
void read_text_file(const char* filename, std::vector<unsigned char>& plaintext)
{
	try
	{
		std::fstream text_file(filename);
		while (text_file.good())
			plaintext.push_back(text_file.get());
	}
	catch (...)
	{
		throw std::exception("Exception in read_text_file()");
		return;
	}
}

// Write the plain text file out
void write_text_file(const char* filename, std::vector<unsigned char>& plaintext)
{
	try
	{
		std::ofstream text_file(filename);
		// TODO: Debug the mystery trailing character on the output
		for (auto& c : plaintext)
			text_file.put(c);
	}
	catch (...)
	{
		throw std::exception("Exception in write_text_file()");
		return;
	}
}

// Read the PNG file and save the data into the data structure
// Color values in the vector are 4 bytes per pixel, ordered RGBARGBA...
// On an error, throws an exception
void read_png_from_file(const char* filename, std::vector<unsigned char>& image, unsigned int& width, unsigned int& height)
{
	unsigned int error = 0;
	try
	{
		unsigned int error = lodepng::decode(image, width, height, filename);
	}
	catch (...)
	{
		throw std::exception("Exception in lodepng::decode()");
		return;
	}

	if (error)
	{
		std::stringstream err_desc;
		err_desc << "Decoder error " << error << ": " << lodepng_error_text(error);
		std::string s = err_desc.str();
		throw std::exception(s.c_str());
	}
}

// Write the PNG file from the data structure
// Color values in the vector are 4 bytes per pixel, ordered RGBARGBA...
// On an error, throws an exception
void write_png_to_file(const char* filename, std::vector<unsigned char>& image, unsigned int width, unsigned int height)
{
	unsigned int error = 0;

	try
	{
		unsigned error = lodepng::encode(filename, image, width, height);
	}
	catch (...)
	{
		throw std::exception("Exception in lodepng::decode()");
		return;
	}

	if (error)
	{
		std::stringstream err_desc;
		err_desc << "Encoder error " << error << ": " << lodepng_error_text(error);
		std::string s = err_desc.str();
		throw std::exception(s.c_str());
	}
}

// Take the 8 bits per char and split them 3-2-3, putting 3 bits into the Red, 2 bits into the Green,
// 3 bits into the Blue, and nothing in Alpha
// The bits will be placed starting from the LSB of each byte so as to make the least impact to the
// image when viewed by a human
// We put fewer bits into the Green channel because human eyes are more sensitive to a yellowish-green
void merge_plaintext_into_img_data(std::vector<unsigned char>& plaintext, std::vector<unsigned char>& img_data)
{
	// Bounds check
	// Using 4 * the plaintext size because each element in img_data is a color channel of a pixel, of which
	// there are 4 channels per pixel, and we're going to overwrite certain bits across three of the channels
	if (img_data.size() < 4 * plaintext.size())
		throw std::exception("Exception in merge_plaintext_into_img_data: image is too small to fit all the text");

	// An iterator for moving through the image data
	auto img_ptr = img_data.begin();
	unsigned char tmp = 0;

	// Loop through all the characters
	for (auto& c : plaintext)
	{
		// First 3 MSBs from the char are put into the Red channels 3 LSBs
		tmp = c & 0xE0; // mask off just the 3 MSBs
		tmp = tmp >> 5; // shift those 3 bits to the right 5 to make them align with the 3 LSBs
		c = c & tmp; //
	}
}

// TODO:
//		- Load the PNG file into the image data structure [ DONE ]
//		- Load the plain text file [ DONE ]
//		- Save the image data structure as a new PNG file [ DONE ]
//		- Save the plain text as a new text file [ DONE ]
//		- Handle command line input
//		- Encipher the plain text
//		- Merge the cipher text into the image data structure
//		- Load the enciphered PNG file into the enciphered image data structure
//		- Extract the cipher text from the enciphered image data structure
//		- Decipher to plain text
int main(int argc, char** argv)
{
	// Testing the read file function
	std::vector<unsigned char>plain_text;
	read_text_file("example.txt", plain_text);

	plain_text[3] = 'F';
	write_text_file("output.txt", plain_text);

	// Just testing the LodePNG library for now...input, modification, and output
	std::vector<unsigned char> img_data;
	unsigned int h, w;

	read_png_from_file("planet.png", img_data, w, h);

	unsigned int index = 0;

	for (auto& color_val : img_data)
	{
		if (index % 4 == 2)
		{
			if (color_val >= 255)
				color_val = 0;
		}

		index++;
	}

	write_png_to_file("output.png", img_data, w, h);

	return 0;
}<commit_msg>Bug fix for trailing character 0x255 Fixed the logic bug where the character was saved even if the text file reached EOF (resulting in an extraneous 0x255 in the vector of chars).<commit_after>// tsStego.cpp
// Released under the MIT License
//
// A simple implementation of stegonography in C++
// Uses the LodePNG library version 20140801 by Lode Vandevenne

#include <fstream>
#include <sstream>
#include <iostream>
#include <exception>
#include "lodepng.h"

// Read the plain text file in
void read_text_file(const char* filename, std::vector<unsigned char>& plaintext)
{
	try
	{
		std::fstream text_file(filename);
		while (text_file.good())
		{
			unsigned char c = text_file.get();
			if (text_file.good())
				plaintext.push_back(c);
		}
	}
	catch (...)
	{
		throw std::exception("Exception in read_text_file()");
		return;
	}
}

// Write the plain text file out
void write_text_file(const char* filename, std::vector<unsigned char>& plaintext)
{
	try
	{
		std::ofstream text_file(filename);
		for (auto& c : plaintext)
			text_file.put(c);
	}
	catch (...)
	{
		throw std::exception("Exception in write_text_file()");
		return;
	}
}

// Read the PNG file and save the data into the data structure
// Color values in the vector are 4 bytes per pixel, ordered RGBARGBA...
// On an error, throws an exception
void read_png_from_file(const char* filename, std::vector<unsigned char>& image, unsigned int& width, unsigned int& height)
{
	unsigned int error = 0;
	try
	{
		unsigned int error = lodepng::decode(image, width, height, filename);
	}
	catch (...)
	{
		throw std::exception("Exception in lodepng::decode()");
		return;
	}

	if (error)
	{
		std::stringstream err_desc;
		err_desc << "Decoder error " << error << ": " << lodepng_error_text(error);
		std::string s = err_desc.str();
		throw std::exception(s.c_str());
	}
}

// Write the PNG file from the data structure
// Color values in the vector are 4 bytes per pixel, ordered RGBARGBA...
// On an error, throws an exception
void write_png_to_file(const char* filename, std::vector<unsigned char>& image, unsigned int width, unsigned int height)
{
	unsigned int error = 0;

	try
	{
		unsigned error = lodepng::encode(filename, image, width, height);
	}
	catch (...)
	{
		throw std::exception("Exception in lodepng::decode()");
		return;
	}

	if (error)
	{
		std::stringstream err_desc;
		err_desc << "Encoder error " << error << ": " << lodepng_error_text(error);
		std::string s = err_desc.str();
		throw std::exception(s.c_str());
	}
}

// Take the 8 bits per char and split them 3-2-3, putting 3 bits into the Red, 2 bits into the Green,
// 3 bits into the Blue, and nothing in Alpha
// The bits will be placed starting from the LSB of each byte so as to make the least impact to the
// image when viewed by a human
// We put fewer bits into the Green channel because human eyes are more sensitive to a yellowish-green
void merge_plaintext_into_img_data(std::vector<unsigned char>& plaintext, std::vector<unsigned char>& img_data)
{
	// Bounds check
	// Using 4 * the plaintext size because each element in img_data is a color channel of a pixel, of which
	// there are 4 channels per pixel, and we're going to overwrite certain bits across three of the channels
	if (img_data.size() < 4 * plaintext.size())
		throw std::exception("Exception in merge_plaintext_into_img_data: image is too small to fit all the text");

	// An iterator for moving through the image data
	auto img_ptr = img_data.begin();
	unsigned char tmp = 0;

	// Loop through all the characters
	for (auto& c : plaintext)
	{
		// First 3 MSBs from the char are put into the Red channels 3 LSBs
		tmp = c & 0xE0; // mask off just the 3 MSBs
		tmp = tmp >> 5; // shift those 3 bits to the right 5 to make them align with the 3 LSBs
		c = ( c & 0x1F) | (tmp & 0x7); // merge the 5 bits from the original with the 3 shifted MSBs of the text

		c++; // Next character
		img_ptr++; // Next color channel (Blue)

		// Next 3 bits from the char are put into the Blue channels 3 LSBs
		tmp = c & 0x1C; // mask off just the 3 bits in the middle of the byte
		tmp = tmp >> 2; // shift those 3 bits to the right 2 to make them align with the 3 LSBs
		c = (c & 0x1F) | (tmp & 0x7); // merge the 5 bits from the original with the 3 shifted MSBs of the text

		c++; // Next character
		img_ptr++; // Next color channel (Green)

		// Next 2 bits from the char are put into the Green channels 2 LSBs
		tmp = c & 0x3; // mask off just the 2 LSBs
		c = (c & 0x1F) | (tmp & 0x7); // merge the 5 bits from the original with the 3 shifted MSBs of the text

		img_ptr++; // Next color channel (Alpha)
		img_ptr++; // Next color channel (Red of the next pixel)
	}
}

// TODO:
//		- Load the PNG file into the image data structure [ DONE ]
//		- Load the plain text file [ DONE ]
//		- Save the image data structure as a new PNG file [ DONE ]
//		- Save the plain text as a new text file [ DONE ]
//		- Handle command line input
//		- Encipher the plain text
//		- Merge the cipher text into the image data structure
//		- Load the enciphered PNG file into the enciphered image data structure
//		- Extract the cipher text from the enciphered image data structure
//		- Decipher to plain text
int main(int argc, char** argv)
{
	// Testing the read file function
	std::vector<unsigned char>plain_text;
	read_text_file("example.txt", plain_text);

	plain_text[3] = 'F';
	write_text_file("output.txt", plain_text);

	// Just testing the LodePNG library for now...input, modification, and output
	std::vector<unsigned char> img_data;
	unsigned int h, w;

	read_png_from_file("planet.png", img_data, w, h);

	unsigned int index = 0;

	for (auto& color_val : img_data)
	{
		if (index % 4 == 2)
		{
			if (color_val >= 255)
				color_val = 0;
		}

		index++;
	}

	write_png_to_file("output.png", img_data, w, h);

	return 0;
}<|endoftext|>


<commit_before>//===- PDBSymbolExe.cpp - ---------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include <utility>

#include "llvm/DebugInfo/PDB/PDBSymbol.h"
#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"

#if defined(_WIN32)
#include <windows.h>
#endif

using namespace llvm;

namespace {
std::string GuidToString(PDB_UniqueId *Id) {
#if defined(_WIN32)
  GUID *Guid = reinterpret_cast<GUID *>(Id);
  OLECHAR GuidBuf[40];
  int Result = StringFromGUID2(*Guid, GuidBuf, 39);
  const char *InputBytes = reinterpret_cast<const char *>(GuidBuf);
  std::string ResultString;
  convertUTF16ToUTF8String(ArrayRef<char>(InputBytes, Result * 2),
                           ResultString);
  return ResultString;
#else
  return std::string();
#endif
}
}

PDBSymbolExe::PDBSymbolExe(std::unique_ptr<IPDBRawSymbol> Symbol)
    : PDBSymbol(std::move(Symbol)) {}

void PDBSymbolExe::dump(llvm::raw_ostream &OS) const {
}
<commit_msg>Removed unused function mistakenly left in, triggering -Werror.<commit_after>//===- PDBSymbolExe.cpp - ---------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include <utility>

#include "llvm/DebugInfo/PDB/PDBSymbol.h"
#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

PDBSymbolExe::PDBSymbolExe(std::unique_ptr<IPDBRawSymbol> Symbol)
    : PDBSymbol(std::move(Symbol)) {}

void PDBSymbolExe::dump(llvm::raw_ostream &OS) const {
}
<|endoftext|>


<commit_before>#include <iostream>

#include "State.h"
#include "utils.h"
#include "constants.h"

#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>

typedef boost::numeric::ublas::matrix<double> matrixD;
using namespace std;

int main(int argc, char** argv) {
  cout << endl << "test_state: Hello World!" << endl;

  // load some data
  matrixD data;
  string filename = "SynData2.csv";
  // string filename = "analyze_2d/ring_data.csv";
  LoadData(filename, data);
  cout << "data is: " << data << endl;
  int num_rows = data.size1();
  int num_cols = data.size2();

  // create the objects to test
  vector<int> global_row_indices = create_sequence(data.size1());
  vector<int> global_column_indices = create_sequence(data.size2());
  vector<string> global_col_types;
  vector<int> global_col_multinomial_counts;
  for(int i=0; i<global_column_indices.size(); i++) {
    global_col_types.push_back(CONTINUOUS_DATATYPE);
    global_col_multinomial_counts.push_back(0);
  }
  State s = State(data, global_col_types, global_col_multinomial_counts, global_row_indices, global_column_indices, 11);

  cout << "start X_D" << endl << s.get_X_D() << endl;
  int num_views = s.get_num_views();
  cout << "s.num_views: " << num_views << endl;
  for(int view_idx=0; view_idx<num_views; view_idx++) {
    View &v = s.get_view(view_idx);
    cout << "view idx " << view_idx << ": ";
    v.print();
  }

  for(int i=0;i<200;i++) {
    cout << "transition #: " << i << endl;
    s.transition(data);
    cout << "s.num_views: " << s.get_num_views();
    cout << "; s.column_crp_score: " << s.get_column_crp_score();
    cout << "; s.data_score: " << s.get_data_score();
    cout << "; s.score: " << s.get_marginal_logp();
    cout << endl;
  }

  num_views = s.get_num_views();
  for(int view_idx=0; view_idx<num_views; view_idx++) {
    View &v = s.get_view(view_idx);
    cout << "view_idx " << view_idx << ": " << endl;
    v.print();
  }

  cout << "FINAL STATE" << endl;
  cout << s << endl;

  cout << "end X_D" << endl << s.get_X_D() << endl;
  cout << endl << "test_state: Goodbye World!" << endl;
}
<commit_msg>change printout<commit_after>#include <iostream>

#include "State.h"
#include "utils.h"
#include "constants.h"

#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>

typedef boost::numeric::ublas::matrix<double> matrixD;
using namespace std;

int main(int argc, char** argv) {
  cout << endl << "test_state: Hello World!" << endl;

  // load some data
  matrixD data;
  string filename = "SynData2.csv";
  // string filename = "analyze_2d/ring_data.csv";
  LoadData(filename, data);
  cout << "data is: " << data << endl;
  int num_rows = data.size1();
  int num_cols = data.size2();

  // create the objects to test
  vector<int> global_row_indices = create_sequence(data.size1());
  vector<int> global_column_indices = create_sequence(data.size2());
  vector<string> global_col_types;
  vector<int> global_col_multinomial_counts;
  for(int i=0; i<global_column_indices.size(); i++) {
    global_col_types.push_back(CONTINUOUS_DATATYPE);
    global_col_multinomial_counts.push_back(0);
  }
  State s = State(data, global_col_types, global_col_multinomial_counts, global_row_indices, global_column_indices, 11);

  cout << "start X_D" << endl << s.get_X_D() << endl;
  int num_views = s.get_num_views();
  cout << "s.num_views: " << num_views << endl;
  for(int view_idx=0; view_idx<num_views; view_idx++) {
    View &v = s.get_view(view_idx);
    cout << "view idx " << view_idx << ": ";
    v.print();
  }

  for(int i=0;i<200;i++) {
    cout << "transition #: " << i << endl;
    s.transition(data);
    cout << "s.num_views: " << s.get_num_views() << endl;
    for(int j=0;j<s.get_num_views(); j++) {
      cout << "view " << j << " row_paritition_model_counts: " << s.get_row_partition_model_counts_i(j) << endl;
    }
    cout << "s.column_crp_score: " << s.get_column_crp_score();
    cout << "; s.data_score: " << s.get_data_score();
    cout << "; s.score: " << s.get_marginal_logp();
    cout << endl;
  }

  num_views = s.get_num_views();
  for(int view_idx=0; view_idx<num_views; view_idx++) {
    View &v = s.get_view(view_idx);
    cout << "view_idx " << view_idx << ": " << endl;
    v.print();
  }

  cout << "FINAL STATE" << endl;
  cout << s << endl;

  cout << "end X_D" << endl << s.get_X_D() << endl;
  cout << endl << "test_state: Goodbye World!" << endl;
}
<|endoftext|>


<commit_before>#include <cmath>
#include <iostream>
#include <utils/tiny_tools.h>

using namespace std;

int main()
{
  cout << "Testing some of the tiny tools..." << endl;

  for (int j = 0; j <= 10; j++) {
    double x1 = sqrt((double) (1<<j));
    double x2 = twotothejhalf(j);
    cout << "* 2^{" << j << "/2}= " << x2 << ", error: " << fabs(x2-x1) << endl;
  }

  cout << endl
       << "- checking positive dyadic modulo routine:" << endl;

  const int expo = 3;
  for (int j = -10; j <= 10; j++) {
    cout << j << " modulo 2^" << expo << "="
	 << dyadic_modulo(j,expo)
	 << endl;
  }

#if 1

    cout << "improving the log2 Function" << endl;

    unsigned int v;  // 32-bit value to find the log2 of
    const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000}; //, 0xFFFFFFFF00000000};
    const unsigned int S[] = {1, 2, 4, 8, 16}; //, 32};
    int i;

#if 1
    // first check what the new method does
    for (i = 4; i >= 0; i--)
    {
        cout << "b[" << i <<"] = " << b[i] << endl;
    }

    for (unsigned int num = 1; num < -1; ++num)
    {
        v = num;
        register unsigned int r = 0; // result of log2(v) will go here
        for (i = 4; i >= 0; i--) // unroll for speed...
        {
          if (v & b[i])
          {
            v >>= S[i];
            r |= S[i];
          }
        }
        assert (r == log2(num));
        //assert (r == floor(log2((double)num))); // classical log2 for double
        //cout << "num = " << num << "; r = " << r << "; v = " << v << "; log2(num) = " << log2(num) << "; floor(log2(num)) = " << floor(log2(num)) << endl;
    }

    //for (unsigned int num = 1; num < -1; ++num)
    for (int num = 1; num > 0; ++num)
    {
        v = num;
        register unsigned int r = 0; // result of log2(v) will go here
        for (i = 4; i >= 0; i--) // unroll for speed...
        {
          if (v & b[i])
          {
            v >>= S[i];
            r |= S[i];
          }
        }
        assert (r == log2((unsigned int)num));
        //assert (r == floor(log2((double)num))); // classical log2 for double
        //cout << "num = " << num << "; r = " << r << "; v = " << v << "; log2(num) = " << log2(num) << "; floor(log2(num)) = " << floor(log2(num)) << endl;
    }
    cout << "sizeof(int) = " << sizeof(int) << endl;
    cout << "sizeof(unsigned int) = " << sizeof(unsigned int) << endl;
    cout << "done" << endl;
    abort();
#endif

    cout << "Compare speed of floor(log2(double)) and log2(int)" << endl;
    int repetitions(1); // about 6 minutes per repetition
    clock_t tstart, tend;
    double time1(0), time2(0);
    //
    cout << "performing first speed test" << endl;
    tstart = clock();
    for (unsigned int rep = 0; rep < repetitions; ++rep)
    {
        for (unsigned int num = 1; num< -1; ++num)
        {
            v = num;
            register unsigned int r = 0; // result of log2(v) will go here
            for (i = 4; i >= 0; i--) // unroll for speed...
            {
                if (v & b[i])
                {
                    v >>= S[i];
                    r |= S[i];
                }
            }
            //v = log2(num);
            //cout << "num = " << num << "; r = " << r << "; v = " << v << "; log2(num) = " << log2(num) << "; floor(log2(num)) = " << floor(log2(num)) << endl;
        }
    }
    tend = clock();
    time1 = (double)(tend-tstart)/CLOCKS_PER_SEC;
    //
    cout << "performing second speed test" << endl;
    tstart = clock();
    for (unsigned int rep = 0; rep < repetitions; ++rep)
    {
        for (unsigned int num = 1; num< -1; ++num)
        {
            //v = floor(log2(num));
            v = log2(num);
        }
    }
    tend = clock();
    time2 = (double)(tend-tstart)/CLOCKS_PER_SEC;
    cout << "Repetitions = " << repetitions << endl
            << "test1 " << time1 << "sec; test2 " << time2 << "sec" << endl;
#endif
    return 0;
}
<commit_msg>prior version of test_tools did not include a necessary library in order to compile<commit_after>#include <cstdlib>
#include <cmath>
#include <iostream>
#include <utils/tiny_tools.h>

using namespace std;

int main()
{
  cout << "Testing some of the tiny tools..." << endl;

  for (int j = 0; j <= 10; j++) {
    double x1 = sqrt((double) (1<<j));
    double x2 = twotothejhalf(j);
    cout << "* 2^{" << j << "/2}= " << x2 << ", error: " << fabs(x2-x1) << endl;
  }

  cout << endl
       << "- checking positive dyadic modulo routine:" << endl;

  const int expo = 3;
  for (int j = -10; j <= 10; j++) {
    cout << j << " modulo 2^" << expo << "="
	 << dyadic_modulo(j,expo)
	 << endl;
  }

#if 1

    cout << "improving the log2 Function" << endl;

    unsigned int v;  // 32-bit value to find the log2 of
    const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000}; //, 0xFFFFFFFF00000000};
    const unsigned int S[] = {1, 2, 4, 8, 16}; //, 32};
    int i;

#if 1
    // first check what the new method does
    for (i = 4; i >= 0; i--)
    {
        cout << "b[" << i <<"] = " << b[i] << endl;
    }

    for (unsigned int num = 1; num < -1; ++num)
    {
        v = num;
        register unsigned int r = 0; // result of log2(v) will go here
        for (i = 4; i >= 0; i--) // unroll for speed...
        {
          if (v & b[i])
          {
            v >>= S[i];
            r |= S[i];
          }
        }
        assert (r == log2(num));
        //assert (r == floor(log2((double)num))); // classical log2 for double
        //cout << "num = " << num << "; r = " << r << "; v = " << v << "; log2(num) = " << log2(num) << "; floor(log2(num)) = " << floor(log2(num)) << endl;
    }

    //for (unsigned int num = 1; num < -1; ++num)
    for (int num = 1; num > 0; ++num)
    {
        v = num;
        register unsigned int r = 0; // result of log2(v) will go here
        for (i = 4; i >= 0; i--) // unroll for speed...
        {
          if (v & b[i])
          {
            v >>= S[i];
            r |= S[i];
          }
        }
        assert (r == log2((unsigned int)num));
        //assert (r == floor(log2((double)num))); // classical log2 for double
        //cout << "num = " << num << "; r = " << r << "; v = " << v << "; log2(num) = " << log2(num) << "; floor(log2(num)) = " << floor(log2(num)) << endl;
    }
    cout << "sizeof(int) = " << sizeof(int) << endl;
    cout << "sizeof(unsigned int) = " << sizeof(unsigned int) << endl;
    cout << "done" << endl;
    abort();
#endif

    cout << "Compare speed of floor(log2(double)) and log2(int)" << endl;
    int repetitions(1); // about 6 minutes per repetition
    clock_t tstart, tend;
    double time1(0), time2(0);
    //
    cout << "performing first speed test" << endl;
    tstart = clock();
    for (unsigned int rep = 0; rep < repetitions; ++rep)
    {
        for (unsigned int num = 1; num< -1; ++num)
        {
            v = num;
            register unsigned int r = 0; // result of log2(v) will go here
            for (i = 4; i >= 0; i--) // unroll for speed...
            {
                if (v & b[i])
                {
                    v >>= S[i];
                    r |= S[i];
                }
            }
            //v = log2(num);
            //cout << "num = " << num << "; r = " << r << "; v = " << v << "; log2(num) = " << log2(num) << "; floor(log2(num)) = " << floor(log2(num)) << endl;
        }
    }
    tend = clock();
    time1 = (double)(tend-tstart)/CLOCKS_PER_SEC;
    //
    cout << "performing second speed test" << endl;
    tstart = clock();
    for (unsigned int rep = 0; rep < repetitions; ++rep)
    {
        for (unsigned int num = 1; num< -1; ++num)
        {
            //v = floor(log2(num));
            v = log2(num);
        }
    }
    tend = clock();
    time2 = (double)(tend-tstart)/CLOCKS_PER_SEC;
    cout << "Repetitions = " << repetitions << endl
            << "test1 " << time1 << "sec; test2 " << time2 << "sec" << endl;
#endif
    return 0;
}
<|endoftext|>


<commit_before>//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#include "RuntimeDebugPch.h"

namespace Js
{
    DebugContext::DebugContext(Js::ScriptContext * scriptContext) :
        scriptContext(scriptContext),
        hostDebugContext(nullptr),
        diagProbesContainer(nullptr),
        debuggerMode(DebuggerMode::NotDebugging)
    {
        Assert(scriptContext != nullptr);
    }

    DebugContext::~DebugContext()
    {
        Assert(this->scriptContext == nullptr);
        Assert(this->hostDebugContext == nullptr);
        Assert(this->diagProbesContainer == nullptr);
    }

    void DebugContext::Initialize()
    {
        Assert(this->diagProbesContainer == nullptr);
        this->diagProbesContainer = HeapNew(ProbeContainer);
        this->diagProbesContainer->Initialize(this->scriptContext);
    }

    void DebugContext::Close()
    {
        Assert(this->scriptContext != nullptr);
        this->scriptContext = nullptr;

        if (this->diagProbesContainer != nullptr)
        {
            this->diagProbesContainer->Close();
            HeapDelete(this->diagProbesContainer);
            this->diagProbesContainer = nullptr;
        }

        if (this->hostDebugContext != nullptr)
        {
            this->hostDebugContext->Delete();
            this->hostDebugContext = nullptr;
        }
    }

    void DebugContext::SetHostDebugContext(HostDebugContext * hostDebugContext)
    {
        Assert(this->hostDebugContext == nullptr);
        Assert(hostDebugContext != nullptr);

        this->hostDebugContext = hostDebugContext;
    }

    bool DebugContext::CanRegisterFunction() const
    {
        if (this->hostDebugContext == nullptr || this->scriptContext == nullptr || this->scriptContext->IsClosed() || this->IsDebugContextInNonDebugMode())
        {
            return false;
        }
        return true;
    }

    void DebugContext::RegisterFunction(Js::ParseableFunctionInfo * func, LPCWSTR title)
    {
        if (!this->CanRegisterFunction())
        {
            return;
        }

        this->RegisterFunction(func, func->GetHostSourceContext(), title);
    }

    void DebugContext::RegisterFunction(Js::ParseableFunctionInfo * func, DWORD_PTR dwDebugSourceContext, LPCWSTR title)
    {
        if (!this->CanRegisterFunction())
        {
            return;
        }

        FunctionBody * functionBody = nullptr;
        if (func->IsDeferredParseFunction())
        {
            HRESULT hr = S_OK;
            Assert(!this->scriptContext->GetThreadContext()->IsScriptActive());

            BEGIN_JS_RUNTIME_CALL_EX_AND_TRANSLATE_EXCEPTION_AND_ERROROBJECT_TO_HRESULT_NESTED(this->scriptContext, false)
            {
                functionBody = func->Parse();
            }
            END_JS_RUNTIME_CALL_AND_TRANSLATE_EXCEPTION_AND_ERROROBJECT_TO_HRESULT(hr);

            if (FAILED(hr))
            {
                return;
            }
        }
        else
        {
            functionBody = func->GetFunctionBody();
        }
        this->RegisterFunction(functionBody, dwDebugSourceContext, title);
    }

    void DebugContext::RegisterFunction(Js::FunctionBody * functionBody, DWORD_PTR dwDebugSourceContext, LPCWSTR title)
    {
        if (!this->CanRegisterFunction())
        {
            return;
        }

        this->hostDebugContext->DbgRegisterFunction(this->scriptContext, functionBody, dwDebugSourceContext, title);
    }

    // Sets the specified mode for the debugger.  The mode is used to inform
    // the runtime of whether or not functions should be JITed or interpreted
    // when they are defer parsed.
    // Note: Transitions back to NotDebugging are not allowed.  Once the debugger
    // is in SourceRundown or Debugging mode, it can only transition between those
    // two modes.
    void DebugContext::SetDebuggerMode(DebuggerMode mode)
    {
        if (this->debuggerMode == mode)
        {
            // Already in this mode so return.
            return;
        }

        if (mode == DebuggerMode::NotDebugging)
        {
            AssertMsg(false, "Transitioning to non-debug mode is not allowed.");
            return;
        }

        this->debuggerMode = mode;
    }

    HRESULT DebugContext::RundownSourcesAndReparse(bool shouldPerformSourceRundown, bool shouldReparseFunctions)
    {
        OUTPUT_TRACE(Js::DebuggerPhase, _u("DebugContext::RundownSourcesAndReparse scriptContext 0x%p, shouldPerformSourceRundown %d, shouldReparseFunctions %d\n"),
            this->scriptContext, shouldPerformSourceRundown, shouldReparseFunctions);

        Js::TempArenaAllocatorObject *tempAllocator = nullptr;
        JsUtil::List<Js::FunctionInfo *, Recycler>* pFunctionsToRegister = nullptr;
        JsUtil::List<Js::Utf8SourceInfo *, Recycler, false, Js::CopyRemovePolicy, RecyclerPointerComparer>* utf8SourceInfoList = nullptr;

        HRESULT hr = S_OK;
        ThreadContext* threadContext = this->scriptContext->GetThreadContext();

        BEGIN_TRANSLATE_OOM_TO_HRESULT_NESTED
        tempAllocator = threadContext->GetTemporaryAllocator(_u("debuggerAlloc"));

        utf8SourceInfoList = JsUtil::List<Js::Utf8SourceInfo *, Recycler, false, Js::CopyRemovePolicy, RecyclerPointerComparer>::New(this->scriptContext->GetRecycler());

        this->MapUTF8SourceInfoUntil([&](Js::Utf8SourceInfo * sourceInfo) -> bool
        {
            WalkAndAddUtf8SourceInfo(sourceInfo, utf8SourceInfoList);
            return false;
        });
        END_TRANSLATE_OOM_TO_HRESULT(hr);

        DEBUGGER_ATTACHDETACH_FATAL_ERROR_IF_FAILED(hr);

        // Cache ScriptContext as multiple calls below can go out of engine and ScriptContext can be closed which will delete DebugContext
        Js::ScriptContext* cachedScriptContext = this->scriptContext;

        utf8SourceInfoList->MapUntil([&](int index, Js::Utf8SourceInfo * sourceInfo) -> bool
        {
            if (cachedScriptContext->IsClosed())
            {
                // ScriptContext could be closed in previous iteration
                hr = E_FAIL;
                return true;
            }

            OUTPUT_TRACE(Js::DebuggerPhase, _u("DebugContext::RundownSourcesAndReparse scriptContext 0x%p, sourceInfo 0x%p, HasDebugDocument %d\n"),
                this->scriptContext, sourceInfo, sourceInfo->HasDebugDocument());

            if (sourceInfo->GetIsLibraryCode())
            {
                // Not putting the internal library code to the debug mode, but need to reinitialize execution mode limits of each
                // function body upon debugger detach, even for library code at the moment.
                if (shouldReparseFunctions)
                {
                    sourceInfo->MapFunction([](Js::FunctionBody *const pFuncBody)
                    {
                        if (pFuncBody->IsFunctionParsed())
                        {
                            pFuncBody->ReinitializeExecutionModeAndLimits();
                        }
                    });
                }
                return false;
            }

            Assert(sourceInfo->GetSrcInfo() && sourceInfo->GetSrcInfo()->sourceContextInfo);

#if DBG
            if (shouldPerformSourceRundown)
            {
                // We shouldn't have a debug document if we're running source rundown for the first time.
                Assert(!sourceInfo->HasDebugDocument());
            }
#endif // DBG

            DWORD_PTR dwDebugHostSourceContext = Js::Constants::NoHostSourceContext;

            if (shouldPerformSourceRundown && this->hostDebugContext != nullptr)
            {
                dwDebugHostSourceContext = this->hostDebugContext->GetHostSourceContext(sourceInfo);
            }

            pFunctionsToRegister = sourceInfo->GetTopLevelFunctionInfoList();

            if (pFunctionsToRegister == nullptr || pFunctionsToRegister->Count() == 0)
            {
                // This could happen if there are no functions to re-compile.
                return false;
            }

            if (this->hostDebugContext != nullptr && sourceInfo->GetSourceContextInfo())
            {
                // This call goes out of engine
                this->hostDebugContext->SetThreadDescription(sourceInfo->GetSourceContextInfo()->url); // the HRESULT is omitted.
            }

            bool fHasDoneSourceRundown = false;
            for (int i = 0; i < pFunctionsToRegister->Count(); i++)
            {
                if (cachedScriptContext->IsClosed())
                {
                    // ScriptContext could be closed in previous iteration
                    hr = E_FAIL;
                    return true;
                }

                Js::FunctionInfo *functionInfo = pFunctionsToRegister->Item(i);
                if (functionInfo == nullptr)
                {
                    continue;
                }

                if (shouldReparseFunctions)
                {
                    BEGIN_JS_RUNTIME_CALL_EX_AND_TRANSLATE_EXCEPTION_AND_ERROROBJECT_TO_HRESULT_NESTED(cachedScriptContext, false)
                    {
                        functionInfo->GetParseableFunctionInfo()->Parse();
                        // This is the first call to the function, ensure dynamic profile info
#if ENABLE_PROFILE_INFO
                        functionInfo->GetFunctionBody()->EnsureDynamicProfileInfo();
#endif
                    }
                    END_JS_RUNTIME_CALL_AND_TRANSLATE_EXCEPTION_AND_ERROROBJECT_TO_HRESULT(hr);

                    // Debugger attach/detach failure is catastrophic, take down the process
                    DEBUGGER_ATTACHDETACH_FATAL_ERROR_IF_FAILED(hr);
                }

                // Parsing the function may change its FunctionProxy.
                Js::ParseableFunctionInfo *parseableFunctionInfo = functionInfo->GetParseableFunctionInfo();

                if (!fHasDoneSourceRundown && shouldPerformSourceRundown && !cachedScriptContext->IsClosed())
                {
                    BEGIN_TRANSLATE_OOM_TO_HRESULT_NESTED
                    {
                        this->RegisterFunction(parseableFunctionInfo, dwDebugHostSourceContext, parseableFunctionInfo->GetSourceName());
                    }
                    END_TRANSLATE_OOM_TO_HRESULT(hr);

                    DEBUGGER_ATTACHDETACH_FATAL_ERROR_IF_FAILED(hr);

                    fHasDoneSourceRundown = true;
                }
            }

            if (shouldReparseFunctions)
            {
                sourceInfo->MapFunction([](Js::FunctionBody *const pFuncBody)
                {
                    if (pFuncBody->IsFunctionParsed())
                    {
                        pFuncBody->ReinitializeExecutionModeAndLimits();
                    }
                });
            }

            return false;
        });

        if (!cachedScriptContext->IsClosed())
        {
            if (shouldPerformSourceRundown && cachedScriptContext->HaveCalleeSources() && this->hostDebugContext != nullptr)
            {
                cachedScriptContext->MapCalleeSources([=](Js::Utf8SourceInfo* calleeSourceInfo)
                {
                    if (!cachedScriptContext->IsClosed())
                    {
                        // This call goes out of engine
                        this->hostDebugContext->ReParentToCaller(calleeSourceInfo);
                    }
                });
            }
        }
        else
        {
            hr = E_FAIL;
        }

        threadContext->ReleaseTemporaryAllocator(tempAllocator);

        return hr;
    }

    // Create an ordered flat list of sources to reparse. Caller of a source should be added to the list before we add the source itself.
    void DebugContext::WalkAndAddUtf8SourceInfo(Js::Utf8SourceInfo* sourceInfo, JsUtil::List<Js::Utf8SourceInfo *, Recycler, false, Js::CopyRemovePolicy, RecyclerPointerComparer> *utf8SourceInfoList)
    {
        Js::Utf8SourceInfo* callerUtf8SourceInfo = sourceInfo->GetCallerUtf8SourceInfo();
        if (callerUtf8SourceInfo)
        {
            Js::ScriptContext* callerScriptContext = callerUtf8SourceInfo->GetScriptContext();
            OUTPUT_TRACE(Js::DebuggerPhase, _u("DebugContext::WalkAndAddUtf8SourceInfo scriptContext 0x%p, sourceInfo 0x%p, callerUtf8SourceInfo 0x%p, sourceInfo scriptContext 0x%p, callerUtf8SourceInfo scriptContext 0x%p\n"),
                this->scriptContext, sourceInfo, callerUtf8SourceInfo, sourceInfo->GetScriptContext(), callerScriptContext);

            if (sourceInfo->GetScriptContext() == callerScriptContext)
            {
                WalkAndAddUtf8SourceInfo(callerUtf8SourceInfo, utf8SourceInfoList);
            }
            else if (callerScriptContext->IsScriptContextInNonDebugMode())
            {
                // The caller scriptContext is not in run down/debug mode so let's save the relationship so that we can re-parent callees afterwards.
                callerScriptContext->AddCalleeSourceInfoToList(sourceInfo);
            }
        }
        if (!utf8SourceInfoList->Contains(sourceInfo))
        {
            OUTPUT_TRACE(Js::DebuggerPhase, _u("DebugContext::WalkAndAddUtf8SourceInfo Adding to utf8SourceInfoList scriptContext 0x%p, sourceInfo 0x%p, sourceInfo scriptContext 0x%p\n"),
                this->scriptContext, sourceInfo, sourceInfo->GetScriptContext());
#if DBG
            bool found = false;
            this->MapUTF8SourceInfoUntil([&](Js::Utf8SourceInfo * sourceInfoTemp) -> bool
            {
                if (sourceInfoTemp == sourceInfo)
                {
                    found = true;
                }
                return found;
            });
            AssertMsg(found, "Parented eval feature have extra source");
#endif
            utf8SourceInfoList->Add(sourceInfo);
        }
    }

    template<class TMapFunction>
    void DebugContext::MapUTF8SourceInfoUntil(TMapFunction map)
    {
        this->scriptContext->MapScript([=](Js::Utf8SourceInfo* sourceInfo) -> bool {
            return map(sourceInfo);
        });
    }
}
<commit_msg>return hr so caller can failfast<commit_after>//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#include "RuntimeDebugPch.h"

namespace Js
{
    DebugContext::DebugContext(Js::ScriptContext * scriptContext) :
        scriptContext(scriptContext),
        hostDebugContext(nullptr),
        diagProbesContainer(nullptr),
        debuggerMode(DebuggerMode::NotDebugging)
    {
        Assert(scriptContext != nullptr);
    }

    DebugContext::~DebugContext()
    {
        Assert(this->scriptContext == nullptr);
        Assert(this->hostDebugContext == nullptr);
        Assert(this->diagProbesContainer == nullptr);
    }

    void DebugContext::Initialize()
    {
        Assert(this->diagProbesContainer == nullptr);
        this->diagProbesContainer = HeapNew(ProbeContainer);
        this->diagProbesContainer->Initialize(this->scriptContext);
    }

    void DebugContext::Close()
    {
        Assert(this->scriptContext != nullptr);
        this->scriptContext = nullptr;

        if (this->diagProbesContainer != nullptr)
        {
            this->diagProbesContainer->Close();
            HeapDelete(this->diagProbesContainer);
            this->diagProbesContainer = nullptr;
        }

        if (this->hostDebugContext != nullptr)
        {
            this->hostDebugContext->Delete();
            this->hostDebugContext = nullptr;
        }
    }

    void DebugContext::SetHostDebugContext(HostDebugContext * hostDebugContext)
    {
        Assert(this->hostDebugContext == nullptr);
        Assert(hostDebugContext != nullptr);

        this->hostDebugContext = hostDebugContext;
    }

    bool DebugContext::CanRegisterFunction() const
    {
        if (this->hostDebugContext == nullptr || this->scriptContext == nullptr || this->scriptContext->IsClosed() || this->IsDebugContextInNonDebugMode())
        {
            return false;
        }
        return true;
    }

    void DebugContext::RegisterFunction(Js::ParseableFunctionInfo * func, LPCWSTR title)
    {
        if (!this->CanRegisterFunction())
        {
            return;
        }

        this->RegisterFunction(func, func->GetHostSourceContext(), title);
    }

    void DebugContext::RegisterFunction(Js::ParseableFunctionInfo * func, DWORD_PTR dwDebugSourceContext, LPCWSTR title)
    {
        if (!this->CanRegisterFunction())
        {
            return;
        }

        FunctionBody * functionBody = nullptr;
        if (func->IsDeferredParseFunction())
        {
            HRESULT hr = S_OK;
            Assert(!this->scriptContext->GetThreadContext()->IsScriptActive());

            BEGIN_JS_RUNTIME_CALL_EX_AND_TRANSLATE_EXCEPTION_AND_ERROROBJECT_TO_HRESULT_NESTED(this->scriptContext, false)
            {
                functionBody = func->Parse();
            }
            END_JS_RUNTIME_CALL_AND_TRANSLATE_EXCEPTION_AND_ERROROBJECT_TO_HRESULT(hr);

            if (FAILED(hr))
            {
                return;
            }
        }
        else
        {
            functionBody = func->GetFunctionBody();
        }
        this->RegisterFunction(functionBody, dwDebugSourceContext, title);
    }

    void DebugContext::RegisterFunction(Js::FunctionBody * functionBody, DWORD_PTR dwDebugSourceContext, LPCWSTR title)
    {
        if (!this->CanRegisterFunction())
        {
            return;
        }

        this->hostDebugContext->DbgRegisterFunction(this->scriptContext, functionBody, dwDebugSourceContext, title);
    }

    // Sets the specified mode for the debugger.  The mode is used to inform
    // the runtime of whether or not functions should be JITed or interpreted
    // when they are defer parsed.
    // Note: Transitions back to NotDebugging are not allowed.  Once the debugger
    // is in SourceRundown or Debugging mode, it can only transition between those
    // two modes.
    void DebugContext::SetDebuggerMode(DebuggerMode mode)
    {
        if (this->debuggerMode == mode)
        {
            // Already in this mode so return.
            return;
        }

        if (mode == DebuggerMode::NotDebugging)
        {
            AssertMsg(false, "Transitioning to non-debug mode is not allowed.");
            return;
        }

        this->debuggerMode = mode;
    }

    HRESULT DebugContext::RundownSourcesAndReparse(bool shouldPerformSourceRundown, bool shouldReparseFunctions)
    {
        OUTPUT_TRACE(Js::DebuggerPhase, _u("DebugContext::RundownSourcesAndReparse scriptContext 0x%p, shouldPerformSourceRundown %d, shouldReparseFunctions %d\n"),
            this->scriptContext, shouldPerformSourceRundown, shouldReparseFunctions);

        Js::TempArenaAllocatorObject *tempAllocator = nullptr;
        JsUtil::List<Js::FunctionInfo *, Recycler>* pFunctionsToRegister = nullptr;
        JsUtil::List<Js::Utf8SourceInfo *, Recycler, false, Js::CopyRemovePolicy, RecyclerPointerComparer>* utf8SourceInfoList = nullptr;

        HRESULT hr = S_OK;
        ThreadContext* threadContext = this->scriptContext->GetThreadContext();

        BEGIN_TRANSLATE_OOM_TO_HRESULT_NESTED
        tempAllocator = threadContext->GetTemporaryAllocator(_u("debuggerAlloc"));

        utf8SourceInfoList = JsUtil::List<Js::Utf8SourceInfo *, Recycler, false, Js::CopyRemovePolicy, RecyclerPointerComparer>::New(this->scriptContext->GetRecycler());

        this->MapUTF8SourceInfoUntil([&](Js::Utf8SourceInfo * sourceInfo) -> bool
        {
            WalkAndAddUtf8SourceInfo(sourceInfo, utf8SourceInfoList);
            return false;
        });
        END_TRANSLATE_OOM_TO_HRESULT(hr);

        if (FAILED(hr))
        {
            Assert(hr == E_OUTOFMEMORY);
            return hr;
        }

        // Cache ScriptContext as multiple calls below can go out of engine and ScriptContext can be closed which will delete DebugContext
        Js::ScriptContext* cachedScriptContext = this->scriptContext;

        utf8SourceInfoList->MapUntil([&](int index, Js::Utf8SourceInfo * sourceInfo) -> bool
        {
            if (cachedScriptContext->IsClosed())
            {
                // ScriptContext could be closed in previous iteration
                hr = E_FAIL;
                return true;
            }

            OUTPUT_TRACE(Js::DebuggerPhase, _u("DebugContext::RundownSourcesAndReparse scriptContext 0x%p, sourceInfo 0x%p, HasDebugDocument %d\n"),
                this->scriptContext, sourceInfo, sourceInfo->HasDebugDocument());

            if (sourceInfo->GetIsLibraryCode())
            {
                // Not putting the internal library code to the debug mode, but need to reinitialize execution mode limits of each
                // function body upon debugger detach, even for library code at the moment.
                if (shouldReparseFunctions)
                {
                    sourceInfo->MapFunction([](Js::FunctionBody *const pFuncBody)
                    {
                        if (pFuncBody->IsFunctionParsed())
                        {
                            pFuncBody->ReinitializeExecutionModeAndLimits();
                        }
                    });
                }
                return false;
            }

            Assert(sourceInfo->GetSrcInfo() && sourceInfo->GetSrcInfo()->sourceContextInfo);

#if DBG
            if (shouldPerformSourceRundown)
            {
                // We shouldn't have a debug document if we're running source rundown for the first time.
                Assert(!sourceInfo->HasDebugDocument());
            }
#endif // DBG

            DWORD_PTR dwDebugHostSourceContext = Js::Constants::NoHostSourceContext;

            if (shouldPerformSourceRundown && this->hostDebugContext != nullptr)
            {
                dwDebugHostSourceContext = this->hostDebugContext->GetHostSourceContext(sourceInfo);
            }

            pFunctionsToRegister = sourceInfo->GetTopLevelFunctionInfoList();

            if (pFunctionsToRegister == nullptr || pFunctionsToRegister->Count() == 0)
            {
                // This could happen if there are no functions to re-compile.
                return false;
            }

            if (this->hostDebugContext != nullptr && sourceInfo->GetSourceContextInfo())
            {
                // This call goes out of engine
                this->hostDebugContext->SetThreadDescription(sourceInfo->GetSourceContextInfo()->url); // the HRESULT is omitted.
            }

            bool fHasDoneSourceRundown = false;
            for (int i = 0; i < pFunctionsToRegister->Count(); i++)
            {
                if (cachedScriptContext->IsClosed())
                {
                    // ScriptContext could be closed in previous iteration
                    hr = E_FAIL;
                    return true;
                }

                Js::FunctionInfo *functionInfo = pFunctionsToRegister->Item(i);
                if (functionInfo == nullptr)
                {
                    continue;
                }

                if (shouldReparseFunctions)
                {
                    BEGIN_JS_RUNTIME_CALL_EX_AND_TRANSLATE_EXCEPTION_AND_ERROROBJECT_TO_HRESULT_NESTED(cachedScriptContext, false)
                    {
                        functionInfo->GetParseableFunctionInfo()->Parse();
                        // This is the first call to the function, ensure dynamic profile info
#if ENABLE_PROFILE_INFO
                        functionInfo->GetFunctionBody()->EnsureDynamicProfileInfo();
#endif
                    }
                    END_JS_RUNTIME_CALL_AND_TRANSLATE_EXCEPTION_AND_ERROROBJECT_TO_HRESULT(hr);

                    // Debugger attach/detach failure is catastrophic, take down the process
                    DEBUGGER_ATTACHDETACH_FATAL_ERROR_IF_FAILED(hr);
                }

                // Parsing the function may change its FunctionProxy.
                Js::ParseableFunctionInfo *parseableFunctionInfo = functionInfo->GetParseableFunctionInfo();

                if (!fHasDoneSourceRundown && shouldPerformSourceRundown && !cachedScriptContext->IsClosed())
                {
                    BEGIN_TRANSLATE_OOM_TO_HRESULT_NESTED
                    {
                        this->RegisterFunction(parseableFunctionInfo, dwDebugHostSourceContext, parseableFunctionInfo->GetSourceName());
                    }
                    END_TRANSLATE_OOM_TO_HRESULT(hr);

                    DEBUGGER_ATTACHDETACH_FATAL_ERROR_IF_FAILED(hr);

                    fHasDoneSourceRundown = true;
                }
            }

            if (shouldReparseFunctions)
            {
                sourceInfo->MapFunction([](Js::FunctionBody *const pFuncBody)
                {
                    if (pFuncBody->IsFunctionParsed())
                    {
                        pFuncBody->ReinitializeExecutionModeAndLimits();
                    }
                });
            }

            return false;
        });

        if (!cachedScriptContext->IsClosed())
        {
            if (shouldPerformSourceRundown && cachedScriptContext->HaveCalleeSources() && this->hostDebugContext != nullptr)
            {
                cachedScriptContext->MapCalleeSources([=](Js::Utf8SourceInfo* calleeSourceInfo)
                {
                    if (!cachedScriptContext->IsClosed())
                    {
                        // This call goes out of engine
                        this->hostDebugContext->ReParentToCaller(calleeSourceInfo);
                    }
                });
            }
        }
        else
        {
            hr = E_FAIL;
        }

        threadContext->ReleaseTemporaryAllocator(tempAllocator);

        return hr;
    }

    // Create an ordered flat list of sources to reparse. Caller of a source should be added to the list before we add the source itself.
    void DebugContext::WalkAndAddUtf8SourceInfo(Js::Utf8SourceInfo* sourceInfo, JsUtil::List<Js::Utf8SourceInfo *, Recycler, false, Js::CopyRemovePolicy, RecyclerPointerComparer> *utf8SourceInfoList)
    {
        Js::Utf8SourceInfo* callerUtf8SourceInfo = sourceInfo->GetCallerUtf8SourceInfo();
        if (callerUtf8SourceInfo)
        {
            Js::ScriptContext* callerScriptContext = callerUtf8SourceInfo->GetScriptContext();
            OUTPUT_TRACE(Js::DebuggerPhase, _u("DebugContext::WalkAndAddUtf8SourceInfo scriptContext 0x%p, sourceInfo 0x%p, callerUtf8SourceInfo 0x%p, sourceInfo scriptContext 0x%p, callerUtf8SourceInfo scriptContext 0x%p\n"),
                this->scriptContext, sourceInfo, callerUtf8SourceInfo, sourceInfo->GetScriptContext(), callerScriptContext);

            if (sourceInfo->GetScriptContext() == callerScriptContext)
            {
                WalkAndAddUtf8SourceInfo(callerUtf8SourceInfo, utf8SourceInfoList);
            }
            else if (callerScriptContext->IsScriptContextInNonDebugMode())
            {
                // The caller scriptContext is not in run down/debug mode so let's save the relationship so that we can re-parent callees afterwards.
                callerScriptContext->AddCalleeSourceInfoToList(sourceInfo);
            }
        }
        if (!utf8SourceInfoList->Contains(sourceInfo))
        {
            OUTPUT_TRACE(Js::DebuggerPhase, _u("DebugContext::WalkAndAddUtf8SourceInfo Adding to utf8SourceInfoList scriptContext 0x%p, sourceInfo 0x%p, sourceInfo scriptContext 0x%p\n"),
                this->scriptContext, sourceInfo, sourceInfo->GetScriptContext());
#if DBG
            bool found = false;
            this->MapUTF8SourceInfoUntil([&](Js::Utf8SourceInfo * sourceInfoTemp) -> bool
            {
                if (sourceInfoTemp == sourceInfo)
                {
                    found = true;
                }
                return found;
            });
            AssertMsg(found, "Parented eval feature have extra source");
#endif
            utf8SourceInfoList->Add(sourceInfo);
        }
    }

    template<class TMapFunction>
    void DebugContext::MapUTF8SourceInfoUntil(TMapFunction map)
    {
        this->scriptContext->MapScript([=](Js::Utf8SourceInfo* sourceInfo) -> bool {
            return map(sourceInfo);
        });
    }
}
<|endoftext|>