<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: tabvwsh.hxx,v $
 * $Revision: 1.30 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef SC_TABVWSH_HXX
#define SC_TABVWSH_HXX

#include <sfx2/viewsh.hxx>
#include <sfx2/viewfac.hxx>
#include "scdllapi.h"
#include "dbfunc.hxx"           // -> tabview
#include "target.hxx"
#include "rangelst.hxx"         // ScRangeListRef
#include "shellids.hxx"

class FmFormShell;
class SbxObject;
class SdrOle2Obj;
class SfxBindings;
class SfxChildWindow;
class SfxModelessDialog;
class SvxBorderLine;
class SvxBoxObjectRef;
class SvxNumberInfoItem;
struct SfxChildWinInfo;

class ScArea;
class ScAuditingShell;
class ScDrawShell;
class ScDrawTextObjectBar;
class ScEditShell;
class ScInputHandler;
class ScPivotShell;
class ScDrawFormShell;
class ScCellShell;
class ScOleObjectShell;
class ScGraphicShell;
class ScMediaShell;
class ScChartShell;
class ScPageBreakShell;
class ScDPObject;
class ScNavigatorSettings;

struct ScHeaderFieldData;

namespace com { namespace sun { namespace star { namespace frame {
    class XDispatchProviderInterceptor;
} } } }

namespace svx {
    class ExtrusionBar;
    class FontworkBar;
}

enum ObjectSelectionType
{
    OST_NONE,
    OST_Cell,
    OST_Editing,
    OST_DrawText,
    OST_Drawing,
    OST_DrawForm,
    OST_Pivot,
    OST_Auditing,
    OST_OleObject,
    OST_Chart,
    OST_Graphic,
    OST_Media
};

//==================================================================

class SC_DLLPUBLIC ScTabViewShell: public SfxViewShell, public ScDBFunc
{
private:
    static USHORT           nInsertCtrlState;
    static USHORT           nInsCellsCtrlState;
    static USHORT           nInsObjCtrlState;

    ObjectSelectionType     eCurOST;
    USHORT                  nDrawSfxId;
    USHORT                  nCtrlSfxId;
    USHORT                  nFormSfxId;
    String                  sDrawCustom;                // current custom shape type
    ScDrawShell*            pDrawShell;
    ScDrawTextObjectBar*    pDrawTextShell;
    ScEditShell*            pEditShell;
    ScPivotShell*           pPivotShell;
    ScAuditingShell*        pAuditingShell;
    ScDrawFormShell*        pDrawFormShell;
    ScCellShell*            pCellShell;
    ScOleObjectShell*       pOleObjectShell;
    ScChartShell*           pChartShell;
    ScGraphicShell*         pGraphicShell;
    ScMediaShell*           pMediaShell;
    ScPageBreakShell*       pPageBreakShell;
    svx::ExtrusionBar*      pExtrusionBarShell;
    svx::FontworkBar*       pFontworkBarShell;

    FmFormShell*            pFormShell;

    ScInputHandler*         pInputHandler;              // fuer OLE-Eingabezeile

    SvxBorderLine*          pCurFrameLine;

    ::com::sun::star::uno::Reference<
        ::com::sun::star::frame::XDispatchProviderInterceptor >
                            xDisProvInterceptor;

    Point                   aWinPos;

    ScTabViewTarget         aTarget;
    ScArea*                 pPivotSource;
    ScDPObject*             pDialogDPObject;

    ScNavigatorSettings*    pNavSettings;

    // used in first Activate
    ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue > aPendingUserData;
    BOOL                    bFirstActivate;

    BOOL                    bActiveDrawSh;
    BOOL                    bActiveDrawTextSh;
    BOOL                    bActivePivotSh;
    BOOL                    bActiveAuditingSh;
    BOOL                    bActiveDrawFormSh;
    BOOL                    bActiveOleObjectSh;
    BOOL                    bActiveChartSh;
    BOOL                    bActiveGraphicSh;
    BOOL                    bActiveMediaSh;
    BOOL                    bActiveEditSh;

    BOOL                    bFormShellAtTop;            // does the FormShell need to be on top?

    BOOL                    bDontSwitch;                // EditShell nicht abschalten
    BOOL                    bInFormatDialog;            // fuer GetSelectionText
    BOOL                    bPrintSelected;             // for result of SvxPrtQryBox

    BOOL                    bReadOnly;                  // um Status-Aenderungen zu erkennen

    SbxObject*              pScSbxObject;

    BOOL                    bChartDlgIsEdit;            // Datenbereich aendern
    BOOL                    bChartAreaValid;            // wenn Chart aufgezogen wird
    String                  aEditChartName;
    ScRangeListRef          aChartSource;
    Rectangle               aChartPos;
    SCTAB                   nChartDestTab;
    USHORT                  nCurRefDlgId;

    SfxBroadcaster*         pAccessibilityBroadcaster;

    static const int        MASTERENUMCOMMANDS = 6;
    String                  aCurrShapeEnumCommand[ MASTERENUMCOMMANDS ];

private:
    SC_DLLPRIVATE void  Construct( BYTE nForceDesignMode = SC_FORCEMODE_NONE );

    SC_DLLPRIVATE void          SetMySubShell( SfxShell* pShell );
    SC_DLLPRIVATE SfxShell*     GetMySubShell() const;

    SC_DLLPRIVATE void          DoReadUserData( const String& rData );
    SC_DLLPRIVATE void          DoReadUserDataSequence( const ::com::sun::star::uno::Sequence<
                                     ::com::sun::star::beans::PropertyValue >& rSettings );

    SC_DLLPRIVATE DECL_LINK( SimpleRefClose, String* );
    SC_DLLPRIVATE DECL_LINK( SimpleRefDone, String* );
    SC_DLLPRIVATE DECL_LINK( SimpleRefAborted, String* );
    SC_DLLPRIVATE DECL_LINK( SimpleRefChange, String* );
    SC_DLLPRIVATE DECL_LINK( FormControlActivated, FmFormShell* );

protected:
    virtual void    Activate(BOOL bMDI);
    virtual void    Deactivate(BOOL bMDI);
    virtual USHORT  PrepareClose( BOOL bUI = TRUE, BOOL bForBrowsing = FALSE );

    virtual void    ShowCursor(FASTBOOL bOn);

    virtual void    Move();     // Benachrichtigung

    virtual void    AdjustPosSizePixel( const Point &rPos, const Size &rSize );     // alt

    virtual void    InnerResizePixel( const Point &rOfs, const Size &rSize );       // neu
    virtual void    OuterResizePixel( const Point &rOfs, const Size &rSize );
    virtual void    SetZoomFactor( const Fraction &rZoomX, const Fraction &rZoomY );

    virtual void    QueryObjAreaPixel( Rectangle& rRect ) const;

    virtual Size    GetOptimalSizePixel() const;

    virtual String  GetSelectionText( BOOL bWholeWord );
    virtual BOOL    HasSelection( BOOL bText ) const;
    virtual String  GetDescription() const;

    virtual void    WriteUserData(String &, BOOL bBrowse = FALSE);
    virtual void    ReadUserData(const String &, BOOL bBrowse = FALSE);
    virtual void    WriteUserDataSequence (::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue >&, sal_Bool bBrowse = sal_False );
    virtual void    ReadUserDataSequence (const ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue >&, sal_Bool bBrowse = sal_False );

    virtual void    UIDeactivated( SfxInPlaceClient* pClient );

    virtual FASTBOOL KeyInput( const KeyEvent &rKeyEvent );
    virtual SdrView* GetDrawView() const;

public:
                    TYPEINFO();

                    SFX_DECL_INTERFACE(SCID_TABVIEW_SHELL)
                    SFX_DECL_VIEWFACTORY(ScTabViewShell);

                    // -> Clone-Methode fuer Factory

                    ScTabViewShell( SfxViewFrame*           pViewFrame,
                                    const ScTabViewShell&   rWin );

                    // aus einer allgemeinen Shell konstruieren und
                    // soviel wie moeglich uebernehmen (SliderPos etc.):

                    ScTabViewShell( SfxViewFrame*           pViewFrame,
                                    SfxViewShell*           pOldSh );

    virtual         ~ScTabViewShell();

    Window*         GetDialogParent();

    void            ExecuteInputDirect();

    ScInputHandler* GetInputHandler() const;
    void            UpdateInputHandler( BOOL bForce = FALSE, BOOL bStopEditing = TRUE );
    BOOL            TabKeyInput(const KeyEvent& rKEvt);
    BOOL            SfxKeyInput(const KeyEvent& rKEvt);

    void            SetActive();

    SvxBorderLine*  GetDefaultFrameLine() const { return pCurFrameLine; }
    void            SetDefaultFrameLine(const SvxBorderLine* pLine );

    void            ExecuteShowNIY( SfxRequest& rReq );
    void            StateDisabled( SfxItemSet& rSet );

    void            Execute( SfxRequest& rReq );
    void            GetState( SfxItemSet& rSet );

    void            ExecuteTable( SfxRequest& rReq );
    void            GetStateTable( SfxItemSet& rSet );

    void            WindowChanged();
    void            ExecDraw(SfxRequest&);
    void            ExecDrawIns(SfxRequest& rReq);
    void            GetDrawState(SfxItemSet &rSet);
    void            GetDrawInsState(SfxItemSet &rSet);
    void            ExecGallery(SfxRequest& rReq);      // StarGallery
    void            GetGalleryState(SfxItemSet& rSet);

    void            ExecChildWin(SfxRequest& rReq);
    void            GetChildWinState( SfxItemSet& rSet );

    void            ExecImageMap( SfxRequest& rReq );
    void            GetImageMapState( SfxItemSet& rSet );

    void            ExecTbx( SfxRequest& rReq );
    void            GetTbxState( SfxItemSet& rSet );

    void            ExecuteSave( SfxRequest& rReq );
    void            GetSaveState( SfxItemSet& rSet );
    void            ExecSearch( SfxRequest& rReq );

    void            ExecuteUndo(SfxRequest& rReq);
    void            GetUndoState(SfxItemSet &rSet);

    void            ExecuteSbx( SfxRequest& rReq );
    void            GetSbxState( SfxItemSet& rSet );

    void            ExecuteObject(SfxRequest& rReq);
    void            GetObjectState(SfxItemSet &rSet);

    void            ExecDrawOpt(SfxRequest& rReq);
    void            GetDrawOptState(SfxItemSet &rSet);

    void            SetDrawShell( BOOL bActive );
    void            SetDrawTextShell( BOOL bActive );

    void            SetPivotShell( BOOL bActive );
    ScArea*         GetPivotSource(){return pPivotSource;}
    void            SetPivotSource(ScArea* pSrc){pPivotSource=pSrc;}
    void            SetDialogDPObject( const ScDPObject* pObj );
    const ScDPObject* GetDialogDPObject() const { return pDialogDPObject; }

    BOOL            GetDontSwitch(){return bDontSwitch;}
    void            SetDontSwitch(BOOL bFlag){bDontSwitch=bFlag;}

    void            SetAuditShell( BOOL bActive );
    void            SetDrawFormShell( BOOL bActive );
    void            SetEditShell(EditView* pView, BOOL bActive );
    void            SetOleObjectShell( BOOL bActive );
    void            SetChartShell( BOOL bActive );
    void            SetGraphicShell( BOOL bActive );
    void            SetMediaShell( BOOL bActive );

    void            SetDrawShellOrSub();
    void            SetCurSubShell( ObjectSelectionType eOST, BOOL bForce = FALSE );

    void            SetFormShellAtTop( BOOL bSet );

    ObjectSelectionType GetCurObjectSelectionType();

    virtual ErrCode DoVerb(long nVerb);

    void            StopEditShell();
    BOOL            IsDrawTextShell() const;
    BOOL            IsAuditShell() const;

    void            SetDrawTextUndo( SfxUndoManager* pUndoMgr );

    void            FillFieldData( ScHeaderFieldData& rData );

    void            ResetChartArea();
    void            SetChartArea( const ScRangeListRef& rSource, const Rectangle& rDest );
    BOOL            GetChartArea( ScRangeListRef& rSource, Rectangle& rDest, SCTAB& rTab ) const;

    BOOL            IsChartDlgEdit() const;
    void            SetChartDlgEdit(BOOL bFlag){bChartDlgIsEdit=bFlag;}

    void            SetEditChartName(const String& aStr){aEditChartName=aStr;}
    const String&   GetEditChartName() const;

    virtual void SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
                         const SfxHint& rHint, const TypeId& rHintType );

    ScNavigatorSettings*    GetNavigatorSettings();

    // Drucken:
    virtual SfxPrinter*     GetPrinter( BOOL bCreate = FALSE );
    virtual USHORT          SetPrinter( SfxPrinter* pNewPrinter,
                                          USHORT nDiffFlags = SFX_PRINTER_ALL, bool bIsApi=false );

    virtual PrintDialog*    CreatePrintDialog( Window* pParent );
    virtual SfxTabPage*     CreatePrintOptionsPage( Window *pParent, const SfxItemSet &rOptions );
    virtual void            PreparePrint( PrintDialog* pPrintDialog = NULL );
    virtual ErrCode         DoPrint( SfxPrinter *pPrinter,
                                         PrintDialog *pPrintDialog,
                                         BOOL bSilent, BOOL bIsAPI );
    virtual USHORT          Print( SfxProgress& rProgress, BOOL bIsAPI, PrintDialog* pPrintDialog = NULL );

    void            TestFunction( USHORT nPar );

    void            ConnectObject( SdrOle2Obj* pObj );
    BOOL            ActivateObject( SdrOle2Obj* pObj, long nVerb );

    void            DeactivateOle();

    static ScTabViewShell* GetActiveViewShell();
    SfxModelessDialog*  CreateRefDialog( SfxBindings* pB, SfxChildWindow* pCW,
                                        SfxChildWinInfo* pInfo,
                                        Window* pParent, USHORT nSlotId );

    void            UpdateOleZoom();
    inline SbxObject* GetScSbxObject() const
                    { return pScSbxObject; }
    inline void     SetScSbxObject( SbxObject* pOb )
                    { pScSbxObject = pOb; }

    FmFormShell*    GetFormShell() const    { return pFormShell; }

    void    InsertURL( const String& rName, const String& rURL, const String& rTarget,
                            USHORT nMode );
    void    InsertURLButton( const String& rName, const String& rURL, const String& rTarget,
                            const Point* pInsPos = NULL );
    void    InsertURLField( const String& rName, const String& rURL, const String& rTarget );

    BOOL    SelectObject( const String& rName );

    void    SetInFormatDialog(BOOL bFlag) {bInFormatDialog=bFlag;}
    BOOL    IsInFormatDialog() {return bInFormatDialog;}

    void    ForceMove()     { Move(); }

    void    MakeNumberInfoItem      ( ScDocument*            pDoc,
                                      ScViewData*            pViewData,
                                      SvxNumberInfoItem**    ppItem );

    void    UpdateNumberFormatter   ( ScDocument*               pDoc,
                                      const SvxNumberInfoItem&  rInfoItem );

    void    ExecuteCellFormatDlg    ( SfxRequest& rReq, USHORT nTabPage = 0xffff );

    BOOL    GetFunction( String& rFuncStr );

    void    StartSimpleRefDialog( const String& rTitle, const String& rInitVal,
                                    BOOL bCloseOnButtonUp, BOOL bSingleCell, BOOL bMultiSelection );
    void    StopSimpleRefDialog();

    void    SetCurRefDlgId( USHORT nNew );

    void    AddAccessibilityObject( SfxListener& rObject );
    void    RemoveAccessibilityObject( SfxListener& rObject );
    void    BroadcastAccessibility( const SfxHint &rHint );
    BOOL    HasAccessibilityObjects();

    using ScTabView::ShowCursor;
};

//==================================================================

#endif

<commit_msg>INTEGRATION: CWS xmlfilter06 (1.30.52); FILE MERGED 2008/07/11 14:21:01 tbe 1.30.52.1: #i91550# Reference input mode when entering a formula starting with + or -<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: tabvwsh.hxx,v $
 * $Revision: 1.31 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef SC_TABVWSH_HXX
#define SC_TABVWSH_HXX

#include <sfx2/viewsh.hxx>
#include <sfx2/viewfac.hxx>
#include "scdllapi.h"
#include "dbfunc.hxx"           // -> tabview
#include "target.hxx"
#include "rangelst.hxx"         // ScRangeListRef
#include "shellids.hxx"

class FmFormShell;
class SbxObject;
class SdrOle2Obj;
class SfxBindings;
class SfxChildWindow;
class SfxModelessDialog;
class SvxBorderLine;
class SvxBoxObjectRef;
class SvxNumberInfoItem;
struct SfxChildWinInfo;

class ScArea;
class ScAuditingShell;
class ScDrawShell;
class ScDrawTextObjectBar;
class ScEditShell;
class ScInputHandler;
class ScPivotShell;
class ScDrawFormShell;
class ScCellShell;
class ScOleObjectShell;
class ScGraphicShell;
class ScMediaShell;
class ScChartShell;
class ScPageBreakShell;
class ScDPObject;
class ScNavigatorSettings;

struct ScHeaderFieldData;

namespace com { namespace sun { namespace star { namespace frame {
    class XDispatchProviderInterceptor;
} } } }

namespace svx {
    class ExtrusionBar;
    class FontworkBar;
}

enum ObjectSelectionType
{
    OST_NONE,
    OST_Cell,
    OST_Editing,
    OST_DrawText,
    OST_Drawing,
    OST_DrawForm,
    OST_Pivot,
    OST_Auditing,
    OST_OleObject,
    OST_Chart,
    OST_Graphic,
    OST_Media
};

//==================================================================

class SC_DLLPUBLIC ScTabViewShell: public SfxViewShell, public ScDBFunc
{
private:
    static USHORT           nInsertCtrlState;
    static USHORT           nInsCellsCtrlState;
    static USHORT           nInsObjCtrlState;

    ObjectSelectionType     eCurOST;
    USHORT                  nDrawSfxId;
    USHORT                  nCtrlSfxId;
    USHORT                  nFormSfxId;
    String                  sDrawCustom;                // current custom shape type
    ScDrawShell*            pDrawShell;
    ScDrawTextObjectBar*    pDrawTextShell;
    ScEditShell*            pEditShell;
    ScPivotShell*           pPivotShell;
    ScAuditingShell*        pAuditingShell;
    ScDrawFormShell*        pDrawFormShell;
    ScCellShell*            pCellShell;
    ScOleObjectShell*       pOleObjectShell;
    ScChartShell*           pChartShell;
    ScGraphicShell*         pGraphicShell;
    ScMediaShell*           pMediaShell;
    ScPageBreakShell*       pPageBreakShell;
    svx::ExtrusionBar*      pExtrusionBarShell;
    svx::FontworkBar*       pFontworkBarShell;

    FmFormShell*            pFormShell;

    ScInputHandler*         pInputHandler;              // fuer OLE-Eingabezeile

    SvxBorderLine*          pCurFrameLine;

    ::com::sun::star::uno::Reference<
        ::com::sun::star::frame::XDispatchProviderInterceptor >
                            xDisProvInterceptor;

    Point                   aWinPos;

    ScTabViewTarget         aTarget;
    ScArea*                 pPivotSource;
    ScDPObject*             pDialogDPObject;

    ScNavigatorSettings*    pNavSettings;

    // used in first Activate
    ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue > aPendingUserData;
    BOOL                    bFirstActivate;

    BOOL                    bActiveDrawSh;
    BOOL                    bActiveDrawTextSh;
    BOOL                    bActivePivotSh;
    BOOL                    bActiveAuditingSh;
    BOOL                    bActiveDrawFormSh;
    BOOL                    bActiveOleObjectSh;
    BOOL                    bActiveChartSh;
    BOOL                    bActiveGraphicSh;
    BOOL                    bActiveMediaSh;
    BOOL                    bActiveEditSh;

    BOOL                    bFormShellAtTop;            // does the FormShell need to be on top?

    BOOL                    bDontSwitch;                // EditShell nicht abschalten
    BOOL                    bInFormatDialog;            // fuer GetSelectionText
    BOOL                    bPrintSelected;             // for result of SvxPrtQryBox

    BOOL                    bReadOnly;                  // um Status-Aenderungen zu erkennen

    SbxObject*              pScSbxObject;

    BOOL                    bChartDlgIsEdit;            // Datenbereich aendern
    BOOL                    bChartAreaValid;            // wenn Chart aufgezogen wird
    String                  aEditChartName;
    ScRangeListRef          aChartSource;
    Rectangle               aChartPos;
    SCTAB                   nChartDestTab;
    USHORT                  nCurRefDlgId;

    SfxBroadcaster*         pAccessibilityBroadcaster;

    static const int        MASTERENUMCOMMANDS = 6;
    String                  aCurrShapeEnumCommand[ MASTERENUMCOMMANDS ];

private:
    SC_DLLPRIVATE void  Construct( BYTE nForceDesignMode = SC_FORCEMODE_NONE );

    SC_DLLPRIVATE void          SetMySubShell( SfxShell* pShell );
    SC_DLLPRIVATE SfxShell*     GetMySubShell() const;

    SC_DLLPRIVATE void          DoReadUserData( const String& rData );
    SC_DLLPRIVATE void          DoReadUserDataSequence( const ::com::sun::star::uno::Sequence<
                                     ::com::sun::star::beans::PropertyValue >& rSettings );

    SC_DLLPRIVATE DECL_LINK( SimpleRefClose, String* );
    SC_DLLPRIVATE DECL_LINK( SimpleRefDone, String* );
    SC_DLLPRIVATE DECL_LINK( SimpleRefAborted, String* );
    SC_DLLPRIVATE DECL_LINK( SimpleRefChange, String* );
    SC_DLLPRIVATE DECL_LINK( FormControlActivated, FmFormShell* );

protected:
    virtual void    Activate(BOOL bMDI);
    virtual void    Deactivate(BOOL bMDI);
    virtual USHORT  PrepareClose( BOOL bUI = TRUE, BOOL bForBrowsing = FALSE );

    virtual void    ShowCursor(FASTBOOL bOn);

    virtual void    Move();     // Benachrichtigung

    virtual void    AdjustPosSizePixel( const Point &rPos, const Size &rSize );     // alt

    virtual void    InnerResizePixel( const Point &rOfs, const Size &rSize );       // neu
    virtual void    OuterResizePixel( const Point &rOfs, const Size &rSize );
    virtual void    SetZoomFactor( const Fraction &rZoomX, const Fraction &rZoomY );

    virtual void    QueryObjAreaPixel( Rectangle& rRect ) const;

    virtual Size    GetOptimalSizePixel() const;

    virtual String  GetSelectionText( BOOL bWholeWord );
    virtual BOOL    HasSelection( BOOL bText ) const;
    virtual String  GetDescription() const;

    virtual void    WriteUserData(String &, BOOL bBrowse = FALSE);
    virtual void    ReadUserData(const String &, BOOL bBrowse = FALSE);
    virtual void    WriteUserDataSequence (::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue >&, sal_Bool bBrowse = sal_False );
    virtual void    ReadUserDataSequence (const ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue >&, sal_Bool bBrowse = sal_False );

    virtual void    UIDeactivated( SfxInPlaceClient* pClient );

    virtual FASTBOOL KeyInput( const KeyEvent &rKeyEvent );
    virtual SdrView* GetDrawView() const;

public:
                    TYPEINFO();

                    SFX_DECL_INTERFACE(SCID_TABVIEW_SHELL)
                    SFX_DECL_VIEWFACTORY(ScTabViewShell);

                    // -> Clone-Methode fuer Factory

                    ScTabViewShell( SfxViewFrame*           pViewFrame,
                                    const ScTabViewShell&   rWin );

                    // aus einer allgemeinen Shell konstruieren und
                    // soviel wie moeglich uebernehmen (SliderPos etc.):

                    ScTabViewShell( SfxViewFrame*           pViewFrame,
                                    SfxViewShell*           pOldSh );

    virtual         ~ScTabViewShell();

    Window*         GetDialogParent();

    bool            IsRefInputMode() const;
    void            ExecuteInputDirect();

    ScInputHandler* GetInputHandler() const;
    void            UpdateInputHandler( BOOL bForce = FALSE, BOOL bStopEditing = TRUE );
    BOOL            TabKeyInput(const KeyEvent& rKEvt);
    BOOL            SfxKeyInput(const KeyEvent& rKEvt);

    void            SetActive();

    SvxBorderLine*  GetDefaultFrameLine() const { return pCurFrameLine; }
    void            SetDefaultFrameLine(const SvxBorderLine* pLine );

    void            ExecuteShowNIY( SfxRequest& rReq );
    void            StateDisabled( SfxItemSet& rSet );

    void            Execute( SfxRequest& rReq );
    void            GetState( SfxItemSet& rSet );

    void            ExecuteTable( SfxRequest& rReq );
    void            GetStateTable( SfxItemSet& rSet );

    void            WindowChanged();
    void            ExecDraw(SfxRequest&);
    void            ExecDrawIns(SfxRequest& rReq);
    void            GetDrawState(SfxItemSet &rSet);
    void            GetDrawInsState(SfxItemSet &rSet);
    void            ExecGallery(SfxRequest& rReq);      // StarGallery
    void            GetGalleryState(SfxItemSet& rSet);

    void            ExecChildWin(SfxRequest& rReq);
    void            GetChildWinState( SfxItemSet& rSet );

    void            ExecImageMap( SfxRequest& rReq );
    void            GetImageMapState( SfxItemSet& rSet );

    void            ExecTbx( SfxRequest& rReq );
    void            GetTbxState( SfxItemSet& rSet );

    void            ExecuteSave( SfxRequest& rReq );
    void            GetSaveState( SfxItemSet& rSet );
    void            ExecSearch( SfxRequest& rReq );

    void            ExecuteUndo(SfxRequest& rReq);
    void            GetUndoState(SfxItemSet &rSet);

    void            ExecuteSbx( SfxRequest& rReq );
    void            GetSbxState( SfxItemSet& rSet );

    void            ExecuteObject(SfxRequest& rReq);
    void            GetObjectState(SfxItemSet &rSet);

    void            ExecDrawOpt(SfxRequest& rReq);
    void            GetDrawOptState(SfxItemSet &rSet);

    void            SetDrawShell( BOOL bActive );
    void            SetDrawTextShell( BOOL bActive );

    void            SetPivotShell( BOOL bActive );
    ScArea*         GetPivotSource(){return pPivotSource;}
    void            SetPivotSource(ScArea* pSrc){pPivotSource=pSrc;}
    void            SetDialogDPObject( const ScDPObject* pObj );
    const ScDPObject* GetDialogDPObject() const { return pDialogDPObject; }

    BOOL            GetDontSwitch(){return bDontSwitch;}
    void            SetDontSwitch(BOOL bFlag){bDontSwitch=bFlag;}

    void            SetAuditShell( BOOL bActive );
    void            SetDrawFormShell( BOOL bActive );
    void            SetEditShell(EditView* pView, BOOL bActive );
    void            SetOleObjectShell( BOOL bActive );
    void            SetChartShell( BOOL bActive );
    void            SetGraphicShell( BOOL bActive );
    void            SetMediaShell( BOOL bActive );

    void            SetDrawShellOrSub();
    void            SetCurSubShell( ObjectSelectionType eOST, BOOL bForce = FALSE );

    void            SetFormShellAtTop( BOOL bSet );

    ObjectSelectionType GetCurObjectSelectionType();

    virtual ErrCode DoVerb(long nVerb);

    void            StopEditShell();
    BOOL            IsDrawTextShell() const;
    BOOL            IsAuditShell() const;

    void            SetDrawTextUndo( SfxUndoManager* pUndoMgr );

    void            FillFieldData( ScHeaderFieldData& rData );

    void            ResetChartArea();
    void            SetChartArea( const ScRangeListRef& rSource, const Rectangle& rDest );
    BOOL            GetChartArea( ScRangeListRef& rSource, Rectangle& rDest, SCTAB& rTab ) const;

    BOOL            IsChartDlgEdit() const;
    void            SetChartDlgEdit(BOOL bFlag){bChartDlgIsEdit=bFlag;}

    void            SetEditChartName(const String& aStr){aEditChartName=aStr;}
    const String&   GetEditChartName() const;

    virtual void SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
                         const SfxHint& rHint, const TypeId& rHintType );

    ScNavigatorSettings*    GetNavigatorSettings();

    // Drucken:
    virtual SfxPrinter*     GetPrinter( BOOL bCreate = FALSE );
    virtual USHORT          SetPrinter( SfxPrinter* pNewPrinter,
                                          USHORT nDiffFlags = SFX_PRINTER_ALL, bool bIsApi=false );

    virtual PrintDialog*    CreatePrintDialog( Window* pParent );
    virtual SfxTabPage*     CreatePrintOptionsPage( Window *pParent, const SfxItemSet &rOptions );
    virtual void            PreparePrint( PrintDialog* pPrintDialog = NULL );
    virtual ErrCode         DoPrint( SfxPrinter *pPrinter,
                                         PrintDialog *pPrintDialog,
                                         BOOL bSilent, BOOL bIsAPI );
    virtual USHORT          Print( SfxProgress& rProgress, BOOL bIsAPI, PrintDialog* pPrintDialog = NULL );

    void            TestFunction( USHORT nPar );

    void            ConnectObject( SdrOle2Obj* pObj );
    BOOL            ActivateObject( SdrOle2Obj* pObj, long nVerb );

    void            DeactivateOle();

    static ScTabViewShell* GetActiveViewShell();
    SfxModelessDialog*  CreateRefDialog( SfxBindings* pB, SfxChildWindow* pCW,
                                        SfxChildWinInfo* pInfo,
                                        Window* pParent, USHORT nSlotId );

    void            UpdateOleZoom();
    inline SbxObject* GetScSbxObject() const
                    { return pScSbxObject; }
    inline void     SetScSbxObject( SbxObject* pOb )
                    { pScSbxObject = pOb; }

    FmFormShell*    GetFormShell() const    { return pFormShell; }

    void    InsertURL( const String& rName, const String& rURL, const String& rTarget,
                            USHORT nMode );
    void    InsertURLButton( const String& rName, const String& rURL, const String& rTarget,
                            const Point* pInsPos = NULL );
    void    InsertURLField( const String& rName, const String& rURL, const String& rTarget );

    BOOL    SelectObject( const String& rName );

    void    SetInFormatDialog(BOOL bFlag) {bInFormatDialog=bFlag;}
    BOOL    IsInFormatDialog() {return bInFormatDialog;}

    void    ForceMove()     { Move(); }

    void    MakeNumberInfoItem      ( ScDocument*            pDoc,
                                      ScViewData*            pViewData,
                                      SvxNumberInfoItem**    ppItem );

    void    UpdateNumberFormatter   ( ScDocument*               pDoc,
                                      const SvxNumberInfoItem&  rInfoItem );

    void    ExecuteCellFormatDlg    ( SfxRequest& rReq, USHORT nTabPage = 0xffff );

    BOOL    GetFunction( String& rFuncStr );

    void    StartSimpleRefDialog( const String& rTitle, const String& rInitVal,
                                    BOOL bCloseOnButtonUp, BOOL bSingleCell, BOOL bMultiSelection );
    void    StopSimpleRefDialog();

    void    SetCurRefDlgId( USHORT nNew );

    void    AddAccessibilityObject( SfxListener& rObject );
    void    RemoveAccessibilityObject( SfxListener& rObject );
    void    BroadcastAccessibility( const SfxHint &rHint );
    BOOL    HasAccessibilityObjects();

    using ScTabView::ShowCursor;
};

//==================================================================

#endif

<|endoftext|>


<commit_before>// -*- mode: c++; c-basic-offset:4 -*-

// This file is part of libdap, A C++ implementation of the OPeNDAP Data
// Access Protocol.

// Copyright (c) 2005,2018 OPeNDAP, Inc.
// Author: James Gallagher <jgallagher@opendap.org>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.

#include <cppunit/TextTestRunner.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/extensions/HelperMacros.h>

#include <cstring>
#include <string>

#include <unistd.h>

#include "GNURegex.h"

#include "Array.h"
#include "Int16.h"
#include "Int64.h"
#include "Float32.h"
#include "Str.h"
#include "D4Enum.h"
#include "Structure.h"
#include "D4Dimensions.h"

#include "run_tests_cppunit.h"
#include "test_config.h"

using namespace CppUnit;
using namespace std;

namespace libdap {

class ArrayTest: public TestFixture {
private:
    Array *d_cardinal = nullptr;
    Array *d_string = nullptr;
    Array *d_structure = nullptr;
    Array *d_card_dap4 = nullptr;

    Int16 *d_int16 = nullptr;
    Str *d_str = nullptr;
    Structure *d_struct = nullptr;

    string svalues[4] = {"0 String", "1 String", "2 String", "3 String" };

public:
    ArrayTest() = default;

    ~ArrayTest() = default;

    void setUp()
    {
        d_int16 = new Int16("Int16");
        DBG(cerr << "d_int16: " << d_int16 << endl);
        d_cardinal = new Array("Array_of_Int16", d_int16);
        d_cardinal->append_dim(4, "dimension");
        dods_int16 buffer[4] = { 0, 1, 2, 3 };
        d_cardinal->val2buf(buffer);

        // Added to test if Arrays with DAP4 protos will have is_dap4() == true. jhrg 7/27/22
        Int64 i64("");
        d_card_dap4 = new Array("Array_of_Int64", &i64);
        d_card_dap4->append_dim(4, "dimension");
        dods_int64 buffer64[4] = { 0, 1, 2, 3 };
        d_card_dap4->val2buf(buffer64);

        d_str = new Str("Str");
        d_string = new Array("Array_of_String", d_str);
        d_string->append_dim(4, "dimension");
        string sbuffer[4] = { "0 String", "1 String", "2 String", "3 String" };
        d_string->val2buf(sbuffer);

        d_struct = new Structure("Structure");
        d_struct->add_var(d_int16);
        d_structure = new Array("Array_of_Strctures", d_struct);
        d_structure->append_dim(4, "dimension");
        ostringstream oss;
        for (int i = 0; i < 4; ++i) {
            oss.str("");
            oss << "field" << i;
            Int16 *n = new Int16(oss.str());
            DBG(cerr << "n " << i << ": " << n << endl);
            oss.str("");
            oss << "element" << i;
            Structure *s = new Structure(oss.str());
            s->add_var(n);
            d_structure->set_vec(i, s);
            delete n;
            n = 0;
            delete s;
            s = 0;
        }

        delete d_int16;
        d_int16 = 0;
        delete d_str;
        d_str = 0;
        delete d_struct;
        d_struct = 0;
    }

    void tearDown()
    {
        delete d_cardinal;
        delete d_string;
        delete d_structure;
    }

    bool re_match(Regex &r, const char *s)
    {
        int match_position = r.match(s, strlen(s));
        DBG(cerr << "match position: " << match_position
            << " string length: " << (int)strlen(s) << endl);
        return match_position == (int) strlen(s);
    }

    CPPUNIT_TEST_SUITE (ArrayTest);

    CPPUNIT_TEST (cons_test);
    CPPUNIT_TEST (test_is_dap4_1);
    CPPUNIT_TEST (test_is_dap4_2);
    CPPUNIT_TEST (test_is_dap4_3);
    CPPUNIT_TEST (test_is_dap4_4);
    CPPUNIT_TEST (assignment_test_1);
    CPPUNIT_TEST (assignment_test_2);
    CPPUNIT_TEST (assignment_test_3);
    CPPUNIT_TEST (prepend_dim_test);
    CPPUNIT_TEST (prepend_dim_2_test);
    CPPUNIT_TEST (clear_dims_test);
    CPPUNIT_TEST (error_handling_test);
    CPPUNIT_TEST (error_handling_2_test);
    CPPUNIT_TEST (duplicate_cardinal_test);
    CPPUNIT_TEST (duplicate_string_test);
    CPPUNIT_TEST (duplicate_structure_test);

    CPPUNIT_TEST_SUITE_END();

    void cons_test()
    {
        Array a1 = Array("a", "b", d_int16, true);
        CPPUNIT_ASSERT(a1.name() == "a");
    }

    void test_is_dap4_1() {
        DBG(d_card_dap4->dump(cerr));
        CPPUNIT_ASSERT_MESSAGE("This Array should register as DAP4", d_card_dap4->is_dap4());
    }

    void test_is_dap4_2() {
        DBG(d_cardinal->dump(cerr));
        CPPUNIT_ASSERT_MESSAGE("This Array should not register as DAP4", !d_cardinal->is_dap4());
    }

    void test_is_dap4_3() {
        // An array Enum is always DAP4, even when the underlying type of the enum is not
        D4Enum enum16("", dods_int16_c);
        unique_ptr<Array> enum_array_dap4(new Array("Array_of_Enum", &enum16));
        enum_array_dap4->append_dim(4, "dimension");
        dods_int16 buffer16[4] = { 0, 1, 2, 3 };
        enum_array_dap4->val2buf(buffer16);

        DBG(enum_array_dap4->dump(cerr));
        CPPUNIT_ASSERT_MESSAGE("This Array should register as DAP4", enum_array_dap4->is_dap4());
    }

    void test_is_dap4_4() {
        D4Enum enum64("", dods_int64_c);
        unique_ptr<Array> enum_array_dap4(new Array("Array_of_Enum", &enum64));
        enum_array_dap4->append_dim(4, "dimension");
        dods_int64 buffer64[4] = { 0, 1, 2, 3 };
        enum_array_dap4->val2buf(buffer64);

        DBG(enum_array_dap4->dump(cerr));
        CPPUNIT_ASSERT_MESSAGE("This Array should register as DAP4", enum_array_dap4->is_dap4());
    }

    void assignment_test_1()
    {
        // Are fields from the object copied by the assignment
        Array a1 = Array("a", d_int16);
        a1.append_dim(17, "bob");
        CPPUNIT_ASSERT(a1.dimension_size(a1.dim_begin()) == 17);
        a1 = *d_cardinal;
        CPPUNIT_ASSERT(a1.dimension_size(a1.dim_begin()) == 4);
    }

    void assignment_test_2()
    {
        // Self-assignment; are objects changed by the assignment?
        Array a1 = Array("a", d_int16);
        Array *before = &a1;
        a1 = a1;
        Array *after = &a1;
        CPPUNIT_ASSERT_MESSAGE("The pointers should be the same", before == after);
    }

    // This tests that the assignment operator defined in Array correctly copies
    // information held in a parent class (Vector). jhrg 2/9/22
    void assignment_test_3()
    {
        // Array copies the proto pointer and manages the storage
#if 0
        unique_ptr<Float32> f32(new Float32("float_proto"));
        Array a1 = Array("a", f32.get());
#endif
        auto f32_ptr = new Float32("float_proto");
        Array a1 = Array("a", f32_ptr);
	delete f32_ptr;

        CPPUNIT_ASSERT_MESSAGE("The type of a1.var() should be dods_float32", a1.var()->type() == dods_float32_c);
        a1 = *d_cardinal;
        CPPUNIT_ASSERT_MESSAGE("The type of a1.var() should now be dods_int16_c", a1.var()->type() == dods_int16_c);
    }

    void prepend_dim_test()
    {
        Array a1 = Array("a", d_int16);
        Array::Dim_iter i = a1.dim_begin();
        CPPUNIT_ASSERT(a1.dimension_size(i) == 0);
        a1.prepend_dim(2, "dim_a");
        i = a1.dim_begin();
        CPPUNIT_ASSERT(a1.dimension_size(i) == 2);
        a1.prepend_dim(3, "dim_b");
    }

    void prepend_dim_2_test()
    {
        Array a1 = Array("a", d_int16);
        string expected_name[2] = {"dim_b", "myDim"};
        int j = 0;
        D4Dimensions *dims = new D4Dimensions();
        D4Dimension *d = new D4Dimension("dim_b", 2, dims);
        a1.prepend_dim(2, "dim_a");
        a1.prepend_dim(d);
        a1.rename_dim("dim_a", "myDim");
        for (Array::Dim_iter i = a1.dim_begin(); i != a1.dim_end(); i++, j++) {
            CPPUNIT_ASSERT(a1.dimension_name(i) == expected_name[j]);
        }
        delete dims;
        delete d;
    }

    void clear_dims_test()
    {
        Array a1 = Array("a", d_int16);
        a1.prepend_dim(2, "dim_a");
        a1.prepend_dim(3, "dim_b");
        a1.clear_all_dims();
        Array::Dim_iter i = a1.dim_begin();
        CPPUNIT_ASSERT(a1.dimension_size(i) == 0);
    }

    void error_handling_test()
    {
        Array a1 = Array("a", d_int16);
        Array::Dim_iter i = a1.dim_begin();
        string msg;
        CPPUNIT_ASSERT_THROW(a1.dimension_name(i), InternalErr);
        CPPUNIT_ASSERT(!a1.check_semantics(msg));
    }

    void error_handling_2_test()
    {
        Array a1 = Array("a", d_int16);
        a1.append_dim(2, "dim_a");
        Array::Dim_iter i = a1.dim_begin();
        CPPUNIT_ASSERT(a1.dimension_size(i) == 2);
        CPPUNIT_ASSERT_THROW(a1.add_constraint(i, 2, 1, 1), Error);
        CPPUNIT_ASSERT_THROW(a1.add_constraint(i, 0, 1, 2), Error);
        CPPUNIT_ASSERT_THROW(a1.add_constraint(i, 0, 3, 1), Error);
    }

    void duplicate_structure_test()
    {
        Array::Dim_iter i = d_structure->dim_begin();
        CPPUNIT_ASSERT(d_structure->dimension_size(i) == 4);
#ifdef DODS_DEBUG
        for (int i = 0; i < 4; ++i) {
            Structure *s = dynamic_cast<Structure*>(d_structure->var(i));
            DBG(cerr << "s: " << s << endl);
            if (s)
            s->print_decl(cerr);
        }
#endif

        Array *a = new Array(*d_structure);
        // a = *d_structure; I test operator= in duplicate_cardinal_test().
        i = a->dim_begin();
        CPPUNIT_ASSERT(a->dimension_size(i) == 4);
        for (int i = 0; i < 4; ++i) {
            // The point of this test is to ensure that the const ctor
            // performs a deep copy; first test to make sure the pointers
            // to BaseType instnaces are different in the two objects.
            Structure *src = dynamic_cast<Structure*>(d_structure->var(i));
            Structure *dest = dynamic_cast<Structure*>(a->var(i));
            CPPUNIT_ASSERT(src != dest);

            // However, for the deep copy to be correct, the two arrays must
            // have equivalent elements. We know there's only one field...
            CPPUNIT_ASSERT(src->type() == dods_structure_c && dest->type() == dods_structure_c);
            Constructor::Vars_iter s = src->var_begin();
            Constructor::Vars_iter d = dest->var_begin();
            CPPUNIT_ASSERT((*s)->type() == dods_int16_c && (*d)->type() == dods_int16_c);
            CPPUNIT_ASSERT((*s)->name() == (*d)->name());
        }
        delete a;
        a = 0;
    }

    void duplicate_string_test()
    {
        Array::Dim_iter i = d_string->dim_begin();
        CPPUNIT_ASSERT(d_string->dimension_size(i) == 4);
        string *s = new string[4];
        d_string->buf2val((void**) &s);
        for (int i = 0; i < 4; ++i) {
            CPPUNIT_ASSERT(s[i] == svalues[i]);
            DBG(cerr << "s[" << i << "]: " << s[i] << endl);
        }

        Array a = *d_string;
        i = a.dim_begin();
        CPPUNIT_ASSERT(a.dimension_size(i) == 4);

        string *s2 = new string[4];
        d_string->buf2val((void**) &s2);
        for (int i = 0; i < 4; ++i) {
            CPPUNIT_ASSERT(s2[i] == svalues[i]);
            DBG(cerr << "s2[" << i << "]: " << s2[i] << endl);
        }

        delete[] s;
        s = 0;
        delete[] s2;
        s2 = 0;
    }

    void duplicate_cardinal_test()
    {
        Array::Dim_iter i = d_cardinal->dim_begin();
        CPPUNIT_ASSERT(d_cardinal->dimension_size(i) == 4);
        dods_int16 *b = new dods_int16[4];
        d_cardinal->buf2val((void**) &b);
        for (int i = 0; i < 4; ++i) {
            CPPUNIT_ASSERT(b[i] == i);
            DBG(cerr << "b[" << i << "]: " << b[i] << endl);
        }
        delete[] b;
        b = 0;

        Array a = *d_cardinal;
        i = a.dim_begin();
        CPPUNIT_ASSERT(a.dimension_size(i) == 4);

        dods_int16 *b2 = new dods_int16[4];
        d_cardinal->buf2val((void**) &b2);
        for (int i = 0; i < 4; ++i) {
            CPPUNIT_ASSERT(b2[i] == i);
            DBG(cerr << "b2[" << i << "]: " << b2[i] << endl);
        }
        delete[] b2;
        b2 = 0;
    }

};

CPPUNIT_TEST_SUITE_REGISTRATION (ArrayTest);

} // namespace libdap

int main(int argc, char *argv[])
{
    return run_tests<libdap::ArrayTest>(argc, argv) ? 0: 1;
}
<commit_msg>HYRAX-863, trim the original ArrayTest code a bit<commit_after>// -*- mode: c++; c-basic-offset:4 -*-

// This file is part of libdap, A C++ implementation of the OPeNDAP Data
// Access Protocol.

// Copyright (c) 2005,2018 OPeNDAP, Inc.
// Author: James Gallagher <jgallagher@opendap.org>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.

#include <cppunit/TextTestRunner.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/extensions/HelperMacros.h>

#include <cstring>
#include <string>

#include <unistd.h>

#include "GNURegex.h"

#include "Array.h"
#include "Byte.h"
#include "Int16.h"
#include "Float32.h"
#include "Int64.h"
#include "D4Enum.h"
#include "D4Dimensions.h"

#include "run_tests_cppunit.h"
#include "test_config.h"

using namespace CppUnit;
using namespace std;

namespace libdap {

class ArrayTest: public TestFixture {
private:
    Array *d_cardinal = nullptr;
    Array *d_card_dap4 = nullptr;

    Array *d_cardinal_byte = nullptr;
    Array *d_card_dap4_byte = nullptr;

    Int16 *d_int16 = nullptr;
    Byte *d_uint8 = nullptr;

public:
    ArrayTest() = default;

    ~ArrayTest() = default;

    void setUp()
    {
        d_int16 = new Int16("Int16");
        DBG(cerr << "d_int16: " << d_int16 << endl);
        d_cardinal = new Array("Array_of_Int16", d_int16);
        d_cardinal->append_dim(4, "dimension");
        dods_int16 buffer[4] = { 0, 1, 2, 3 };
        d_cardinal->val2buf(buffer);

        // Added to test if Arrays with DAP4 protos will have is_dap4() == true. jhrg 7/27/22
        Int64 i64("");
        d_card_dap4 = new Array("Array_of_Int64", &i64);
        d_card_dap4->append_dim(4, "dimension");
        dods_int64 buffer64[4] = { 0, 1, 2, 3 };
        d_card_dap4->val2buf(buffer64);

        delete d_int16;
        d_int16 = 0;
    }

    void tearDown()
    {
        delete d_cardinal;
        delete d_card_dap4;
    }

    CPPUNIT_TEST_SUITE (ArrayTest);

    CPPUNIT_TEST (cons_test);
#if 0
    CPPUNIT_TEST (test_is_dap4_1);
    CPPUNIT_TEST (test_is_dap4_2);
    CPPUNIT_TEST (test_is_dap4_3);
    CPPUNIT_TEST (test_is_dap4_4);
    CPPUNIT_TEST (assignment_test_1);
    CPPUNIT_TEST (assignment_test_2);
    CPPUNIT_TEST (assignment_test_3);
    CPPUNIT_TEST (prepend_dim_test);
    CPPUNIT_TEST (prepend_dim_2_test);
    CPPUNIT_TEST (clear_dims_test);
    CPPUNIT_TEST (error_handling_test);
    CPPUNIT_TEST (error_handling_2_test);
    CPPUNIT_TEST (duplicate_cardinal_test);
#endif

    CPPUNIT_TEST_SUITE_END();

    void cons_test()
    {
        Array a1 = Array("a", "b", d_int16, true);
        CPPUNIT_ASSERT(a1.name() == "a");
    }

    void test_is_dap4_1() {
        DBG(d_card_dap4->dump(cerr));
        CPPUNIT_ASSERT_MESSAGE("This Array should register as DAP4", d_card_dap4->is_dap4());
    }

    void test_is_dap4_2() {
        DBG(d_cardinal->dump(cerr));
        CPPUNIT_ASSERT_MESSAGE("This Array should not register as DAP4", !d_cardinal->is_dap4());
    }

    void test_is_dap4_3() {
        // An array Enum is always DAP4, even when the underlying type of the enum is not
        D4Enum enum16("", dods_int16_c);
        unique_ptr<Array> enum_array_dap4(new Array("Array_of_Enum", &enum16));
        enum_array_dap4->append_dim(4, "dimension");
        dods_int16 buffer16[4] = { 0, 1, 2, 3 };
        enum_array_dap4->val2buf(buffer16);

        DBG(enum_array_dap4->dump(cerr));
        CPPUNIT_ASSERT_MESSAGE("This Array should register as DAP4", enum_array_dap4->is_dap4());
    }

    void test_is_dap4_4() {
        D4Enum enum64("", dods_int64_c);
        unique_ptr<Array> enum_array_dap4(new Array("Array_of_Enum", &enum64));
        enum_array_dap4->append_dim(4, "dimension");
        dods_int64 buffer64[4] = { 0, 1, 2, 3 };
        enum_array_dap4->val2buf(buffer64);

        DBG(enum_array_dap4->dump(cerr));
        CPPUNIT_ASSERT_MESSAGE("This Array should register as DAP4", enum_array_dap4->is_dap4());
    }

    void assignment_test_1()
    {
        // Are fields from the object copied by the assignment
        Array a1 = Array("a", d_int16);
        a1.append_dim(17, "bob");
        CPPUNIT_ASSERT(a1.dimension_size(a1.dim_begin()) == 17);
        a1 = *d_cardinal;
        CPPUNIT_ASSERT(a1.dimension_size(a1.dim_begin()) == 4);
    }

    void assignment_test_2()
    {
        // Self-assignment; are objects changed by the assignment?
        Array a1 = Array("a", d_int16);
        Array *before = &a1;
        a1 = a1;
        Array *after = &a1;
        CPPUNIT_ASSERT_MESSAGE("The pointers should be the same", before == after);
    }

    // This tests that the assignment operator defined in Array correctly copies
    // information held in a parent class (Vector). jhrg 2/9/22
    void assignment_test_3()
    {
        // Array copies the proto pointer and manages the storage
#if 0
        unique_ptr<Float32> f32(new Float32("float_proto"));
        Array a1 = Array("a", f32.get());
#endif
        auto f32_ptr = new Float32("float_proto");
        Array a1 = Array("a", f32_ptr);
	delete f32_ptr;

        CPPUNIT_ASSERT_MESSAGE("The type of a1.var() should be dods_float32", a1.var()->type() == dods_float32_c);
        a1 = *d_cardinal;
        CPPUNIT_ASSERT_MESSAGE("The type of a1.var() should now be dods_int16_c", a1.var()->type() == dods_int16_c);
    }

    void prepend_dim_test()
    {
        Array a1 = Array("a", d_int16);
        Array::Dim_iter i = a1.dim_begin();
        CPPUNIT_ASSERT(a1.dimension_size(i) == 0);
        a1.prepend_dim(2, "dim_a");
        i = a1.dim_begin();
        CPPUNIT_ASSERT(a1.dimension_size(i) == 2);
        a1.prepend_dim(3, "dim_b");
    }

    void prepend_dim_2_test()
    {
        Array a1 = Array("a", d_int16);
        string expected_name[2] = {"dim_b", "myDim"};
        int j = 0;
        D4Dimensions *dims = new D4Dimensions();
        D4Dimension *d = new D4Dimension("dim_b", 2, dims);
        a1.prepend_dim(2, "dim_a");
        a1.prepend_dim(d);
        a1.rename_dim("dim_a", "myDim");
        for (Array::Dim_iter i = a1.dim_begin(); i != a1.dim_end(); i++, j++) {
            CPPUNIT_ASSERT(a1.dimension_name(i) == expected_name[j]);
        }
        delete dims;
        delete d;
    }

    void clear_dims_test()
    {
        Array a1 = Array("a", d_int16);
        a1.prepend_dim(2, "dim_a");
        a1.prepend_dim(3, "dim_b");
        a1.clear_all_dims();
        Array::Dim_iter i = a1.dim_begin();
        CPPUNIT_ASSERT(a1.dimension_size(i) == 0);
    }

    void error_handling_test()
    {
        Array a1 = Array("a", d_int16);
        Array::Dim_iter i = a1.dim_begin();
        string msg;
        CPPUNIT_ASSERT_THROW(a1.dimension_name(i), InternalErr);
        CPPUNIT_ASSERT(!a1.check_semantics(msg));
    }

    void error_handling_2_test()
    {
        Array a1 = Array("a", d_int16);
        a1.append_dim(2, "dim_a");
        Array::Dim_iter i = a1.dim_begin();
        CPPUNIT_ASSERT(a1.dimension_size(i) == 2);
        CPPUNIT_ASSERT_THROW(a1.add_constraint(i, 2, 1, 1), Error);
        CPPUNIT_ASSERT_THROW(a1.add_constraint(i, 0, 1, 2), Error);
        CPPUNIT_ASSERT_THROW(a1.add_constraint(i, 0, 3, 1), Error);
    }

    void duplicate_cardinal_test()
    {
        Array::Dim_iter i = d_cardinal->dim_begin();
        CPPUNIT_ASSERT(d_cardinal->dimension_size(i) == 4);
        dods_int16 *b = new dods_int16[4];
        d_cardinal->buf2val((void**) &b);
        for (int i = 0; i < 4; ++i) {
            CPPUNIT_ASSERT(b[i] == i);
            DBG(cerr << "b[" << i << "]: " << b[i] << endl);
        }
        delete[] b;
        b = 0;

        Array a = *d_cardinal;
        i = a.dim_begin();
        CPPUNIT_ASSERT(a.dimension_size(i) == 4);

        dods_int16 *b2 = new dods_int16[4];
        d_cardinal->buf2val((void**) &b2);
        for (int i = 0; i < 4; ++i) {
            CPPUNIT_ASSERT(b2[i] == i);
            DBG(cerr << "b2[" << i << "]: " << b2[i] << endl);
        }
        delete[] b2;
        b2 = 0;
    }

};

CPPUNIT_TEST_SUITE_REGISTRATION (ArrayTest);

} // namespace libdap

int main(int argc, char *argv[])
{
    return run_tests<libdap::ArrayTest>(argc, argv) ? 0: 1;
}
<|endoftext|>


<commit_before>#include "IRremote.h"

#ifdef SENDING_SUPPORTED
//+=============================================================================
void IRsend::sendRaw(const unsigned int buf[], unsigned int len, unsigned int hz) {
    // Set IR carrier frequency
    enableIROut(hz);

    for (unsigned int i = 0; i < len; i++) {
        if (i & 1) {
            space(buf[i]);
        } else {
            mark(buf[i]);
        }
    }

    space(0);  // Always end with the LED off
}

void IRsend::sendRaw_P(const unsigned int buf[], unsigned int len, unsigned int hz) {
#if !defined(__AVR__)
    sendRaw(buf,len,hz); // Let the function work for non AVR platforms
#else
    // Set IR carrier frequency
    enableIROut(hz);

    for (unsigned int i = 0; i < len; i++) {
        uint16_t duration = pgm_read_word_near(buf + sizeof(uint16_t) * i);
        if (i & 1) {
            space(duration);
        } else {
            mark(duration);
        }
    }
    space(0);  // Always end with the LED off
#endif

}

#ifdef USE_SOFT_CARRIER
void inline IRsend::sleepMicros(unsigned long us) {
#ifdef USE_SPIN_WAIT
    sleepUntilMicros(micros() + us);
#else
    if (us > 0U) { // Is this necessary? (Official docu https://www.arduino.cc/en/Reference/DelayMicroseconds does not tell.)
        delayMicroseconds((unsigned int) us);
    }
#endif
}

void inline IRsend::sleepUntilMicros(unsigned long targetTime) {
#ifdef USE_SPIN_WAIT
    while (micros() < targetTime)
    ;
#else
    unsigned long now = micros();
    if (now < targetTime) {
        sleepMicros(targetTime - now);
    }
#endif
}
#endif // USE_SOFT_CARRIER

//+=============================================================================
// Sends an IR mark for the specified number of microseconds.
// The mark output is modulated at the PWM frequency.
//

void IRsend::mark(unsigned int time) {
#ifdef USE_SOFT_CARRIER
    unsigned long start = micros();
    unsigned long stop = start + time;
    if (stop + periodTime < start) {
        // Counter wrap-around, happens very seldomly, but CAN happen.
        // Just give up instead of possibly damaging the hardware.
        return;
    }
    unsigned long nextPeriodEnding = start;
    unsigned long now = micros();
    while (now < stop) {
        SENDPIN_ON(sendPin);
        sleepMicros (periodOnTime);
        SENDPIN_OFF(sendPin);
        nextPeriodEnding += periodTime;
        sleepUntilMicros(nextPeriodEnding);
        now = micros();
    }
#elif defined(USE_NO_CARRIER)
    digitalWrite(sendPin, LOW); // Set output to active low.
#else
    TIMER_ENABLE_PWM; // Enable pin 3 PWM output
#endif
    if (time > 0) {
        custom_delay_usec(time);
    }
}

//+=============================================================================
// Leave pin off for time (given in microseconds)
// Sends an IR space for the specified number of microseconds.
// A space is no output, so the PWM output is disabled.
//
void IRsend::space(unsigned int time) {
#if defined(USE_NO_CARRIER)
    digitalWrite(sendPin, HIGH); // Set output to inactive high.
#else
    TIMER_DISABLE_PWM; // Disable pin 3 PWM output
#endif
    if (time > 0) {
        IRsend::custom_delay_usec(time);
    }
}

#ifdef USE_DEFAULT_ENABLE_IR_OUT
//+=============================================================================
// Enables IR output.  The khz value controls the modulation frequency in kilohertz.
// The IR output will be on pin 3 (OC2B).
// This routine is designed for 36-40KHz; if you use it for other values, it's up to you
// to make sure it gives reasonable results.  (Watch out for overflow / underflow / rounding.)
// TIMER2 is used in phase-correct PWM mode, with OCR2A controlling the frequency and OCR2B
// controlling the duty cycle.
// There is no prescaling, so the output frequency is 16MHz / (2 * OCR2A)
// To turn the output on and off, we leave the PWM running, but connect and disconnect the output pin.
// A few hours staring at the ATmega documentation and this will all make sense.
// See my Secrets of Arduino PWM at http://arcfn.com/2009/07/secrets-of-arduino-pwm.html for details.
//
void IRsend::enableIROut(int khz) {
#ifdef USE_SOFT_CARRIER
    periodTime = (1000U + khz / 2) / khz; // = 1000/khz + 1/2 = round(1000.0/khz)
    periodOnTime = periodTime * DUTY_CYCLE / 100U - PULSE_CORRECTION;
#endif

#if defined(USE_NO_CARRIER)
    pinMode(sendPin, OUTPUT);
    digitalWrite(sendPin, HIGH); // Set output to inactive high.
#else
    // Disable the Timer2 Interrupt (which is used for receiving IR)
    TIMER_DISABLE_INTR; //Timer2 Overflow Interrupt

    pinMode(sendPin, OUTPUT);

    SENDPIN_OFF(sendPin); // When not sending, we want it low

    timerConfigkHz(khz);
#endif
}
#endif

//+=============================================================================
// Custom delay function that circumvents Arduino's delayMicroseconds limit

void IRsend::custom_delay_usec(unsigned long uSecs) {
    if (uSecs > 4) {
        unsigned long start = micros();
        unsigned long endMicros = start + uSecs - 4;
        if (endMicros < start) { // Check if overflow
            while (micros() > start) {
            } // wait until overflow
        }
        while (micros() < endMicros) {
        } // normal wait
    }
    //else {
    //  __asm__("nop\n\t"); // must have or compiler optimizes out
    //}
}

#endif // SENDING_SUPPORTED
<commit_msg>fixed send issue<commit_after>#include "IRremote.h"

#ifdef SENDING_SUPPORTED
//+=============================================================================
void IRsend::sendRaw(const unsigned int buf[], unsigned int len, unsigned int hz) {
    // Set IR carrier frequency
    enableIROut(hz);

    for (unsigned int i = 0; i < len; i++) {
        if (i & 1) {
            space(buf[i]);
        } else {
            mark(buf[i]);
        }
    }

    space(0);  // Always end with the LED off
}

void IRsend::sendRaw_P(const unsigned int buf[], unsigned int len, unsigned int hz) {
#if !defined(__AVR__)
    sendRaw(buf,len,hz); // Let the function work for non AVR platforms
#else
    // Set IR carrier frequency
    enableIROut(hz);

    for (unsigned int i = 0; i < len; i++) {
        uint16_t duration = pgm_read_word_near(buf + sizeof(uint16_t) * i);
        if (i & 1) {
            space(duration);
        } else {
            mark(duration);
        }
    }
    space(0);  // Always end with the LED off
#endif

}

#ifdef USE_SOFT_CARRIER
void inline IRsend::sleepMicros(unsigned long us) {
#ifdef USE_SPIN_WAIT
    sleepUntilMicros(micros() + us);
#else
    if (us > 0U) { // Is this necessary? (Official docu https://www.arduino.cc/en/Reference/DelayMicroseconds does not tell.)
        delayMicroseconds((unsigned int) us);
    }
#endif
}

void inline IRsend::sleepUntilMicros(unsigned long targetTime) {
#ifdef USE_SPIN_WAIT
    while (micros() < targetTime)
    ;
#else
    unsigned long now = micros();
    if (now < targetTime) {
        sleepMicros(targetTime - now);
    }
#endif
}
#endif // USE_SOFT_CARRIER

//+=============================================================================
// Sends an IR mark for the specified number of microseconds.
// The mark output is modulated at the PWM frequency.
//

void IRsend::mark(unsigned int time) {
#ifdef USE_SOFT_CARRIER
    unsigned long start = micros();
    unsigned long stop = start + time;
    if (stop + periodTime < start) {
        // Counter wrap-around, happens very seldomly, but CAN happen.
        // Just give up instead of possibly damaging the hardware.
        return;
    }
    unsigned long nextPeriodEnding = start;
    unsigned long now = micros();
    while (now < stop) {
        SENDPIN_ON(sendPin);
        sleepMicros (periodOnTime);
        SENDPIN_OFF(sendPin);
        nextPeriodEnding += periodTime;
        sleepUntilMicros(nextPeriodEnding);
        now = micros();
    }
#elif defined(USE_NO_CARRIER)
    digitalWrite(sendPin, LOW); // Set output to active low.
#else
    TIMER_ENABLE_PWM; // Enable pin 3 PWM output
#endif
    // ! This is a bug, no need to delay here
    // if (time > 0) {
    //     custom_delay_usec(time);
    // }
}

//+=============================================================================
// Leave pin off for time (given in microseconds)
// Sends an IR space for the specified number of microseconds.
// A space is no output, so the PWM output is disabled.
//
void IRsend::space(unsigned int time) {
#if defined(USE_NO_CARRIER)
    digitalWrite(sendPin, HIGH); // Set output to inactive high.
#else
    TIMER_DISABLE_PWM; // Disable pin 3 PWM output
#endif
    if (time > 0) {
        IRsend::custom_delay_usec(time);
    }
}

#ifdef USE_DEFAULT_ENABLE_IR_OUT
//+=============================================================================
// Enables IR output.  The khz value controls the modulation frequency in kilohertz.
// The IR output will be on pin 3 (OC2B).
// This routine is designed for 36-40KHz; if you use it for other values, it's up to you
// to make sure it gives reasonable results.  (Watch out for overflow / underflow / rounding.)
// TIMER2 is used in phase-correct PWM mode, with OCR2A controlling the frequency and OCR2B
// controlling the duty cycle.
// There is no prescaling, so the output frequency is 16MHz / (2 * OCR2A)
// To turn the output on and off, we leave the PWM running, but connect and disconnect the output pin.
// A few hours staring at the ATmega documentation and this will all make sense.
// See my Secrets of Arduino PWM at http://arcfn.com/2009/07/secrets-of-arduino-pwm.html for details.
//
void IRsend::enableIROut(int khz) {
#ifdef USE_SOFT_CARRIER
    periodTime = (1000U + khz / 2) / khz; // = 1000/khz + 1/2 = round(1000.0/khz)
    periodOnTime = periodTime * DUTY_CYCLE / 100U - PULSE_CORRECTION;
#endif

#if defined(USE_NO_CARRIER)
    pinMode(sendPin, OUTPUT);
    digitalWrite(sendPin, HIGH); // Set output to inactive high.
#else
    // Disable the Timer2 Interrupt (which is used for receiving IR)
    TIMER_DISABLE_INTR; //Timer2 Overflow Interrupt

    pinMode(sendPin, OUTPUT);

    SENDPIN_OFF(sendPin); // When not sending, we want it low

    timerConfigkHz(khz);
#endif
}
#endif

//+=============================================================================
// Custom delay function that circumvents Arduino's delayMicroseconds limit

void IRsend::custom_delay_usec(unsigned long uSecs) {
    if (uSecs > 4) {
        unsigned long start = micros();
        unsigned long endMicros = start + uSecs - 4;
        if (endMicros < start) { // Check if overflow
            while (micros() > start) {
            } // wait until overflow
        }
        while (micros() < endMicros) {
        } // normal wait
    }
    //else {
    //  __asm__("nop\n\t"); // must have or compiler optimizes out
    //}
}

#endif // SENDING_SUPPORTED
<|endoftext|>


<commit_before>/* Copyright 2012-present Facebook, Inc.
 * Licensed under the Apache License, Version 2.0 */

#include "watchman.h"
#include <system_error>
#ifndef _WIN32
#include <dirent.h>
#endif
#ifdef __APPLE__
# include <sys/utsname.h>
# include <sys/attr.h>
# include <sys/vnode.h>
#endif
#include "FileDescriptor.h"

using watchman::FileDescriptor;
using watchman::OpenFileHandleOptions;

#ifdef HAVE_GETATTRLISTBULK
typedef struct {
  uint32_t len;
  attribute_set_t returned;
  uint32_t err;

  /* The attribute data length will not be greater than NAME_MAX + 1
   * characters, which is NAME_MAX * 3 + 1 bytes (as one UTF-8-encoded
   * character may take up to three bytes
   */
  attrreference_t name; // ATTR_CMN_NAME
  dev_t dev;            // ATTR_CMN_DEVID
  fsobj_type_t objtype; // ATTR_CMN_OBJTYPE
  struct timespec mtime; // ATTR_CMN_MODTIME
  struct timespec ctime; // ATTR_CMN_CHGTIME
  struct timespec atime; // ATTR_CMN_ACCTIME
  uid_t uid; // ATTR_CMN_OWNERID
  gid_t gid; // ATTR_CMN_GRPID
  uint32_t mode; // ATTR_CMN_ACCESSMASK, Only the permission bits of st_mode
                 // are valid; other bits should be ignored,
                 // e.g., by masking with ~S_IFMT.
  uint64_t ino;  // ATTR_CMN_FILEID
  uint32_t link; // ATTR_FILE_LINKCOUNT or ATTR_DIR_LINKCOUNT
  off_t file_size; // ATTR_FILE_TOTALSIZE

} __attribute__((packed)) bulk_attr_item;
#endif

#ifndef _WIN32
class DirHandle : public watchman_dir_handle {
#ifdef HAVE_GETATTRLISTBULK
  FileDescriptor fd_;
  struct attrlist attrlist_;
  int retcount_{0};
  char buf_[64 * (sizeof(bulk_attr_item) + NAME_MAX * 3 + 1)];
  char *cursor_{nullptr};
#endif
  DIR *d_{nullptr};
  struct watchman_dir_ent ent_;

 public:
  explicit DirHandle(const char* path, bool strict);
  ~DirHandle() override;
  const watchman_dir_ent* readDir() override;
  int getFd() const override;
};
#else
static const char *w_basename(const char *path) {
  const char *last = path + strlen(path) - 1;
  while (last >= path) {
    if (*last == '/' || *last == '\\') {
      return last + 1;
    }
    --last;
  }
  return NULL;
}
#endif

#ifndef _WIN32
/* Opens a directory making sure it's not a symlink */
static DIR *opendir_nofollow(const char *path)
{
  auto fd = openFileHandle(path, OpenFileHandleOptions::strictOpenDir());
# if !defined(HAVE_FDOPENDIR) || defined(__APPLE__)
  /* fdopendir doesn't work on earlier versions OS X, and we don't
   * use this function since 10.10, as we prefer to use getattrlistbulk
   * in that case */
  return opendir(path);
# else
  // errno should be set appropriately if this is not a directory
  auto d = fdopendir(fd.fd());
  if (d) {
    fd.release();
  }
  return d;
# endif
}
#endif

#ifdef HAVE_GETATTRLISTBULK
// I've seen bulkstat report incorrect sizes on kernel version 14.5.0.
// (That's OSX 10.10.5).
// Let's avoid it for major kernel versions < 15.
// Using statics here to avoid querying the uname on every opendir.
// There is opportunity for a data race the first time through, but the
// worst case side effect is wasted compute early on.
static bool use_bulkstat_by_default(void) {
  static bool probed = false;
  static bool safe = false;

  if (!probed) {
    struct utsname name;
    if (uname(&name) == 0) {
      int maj = 0, min = 0, patch = 0;
      sscanf(name.release, "%d.%d.%d", &maj, &min, &patch);
      if (maj >= 15) {
        safe = true;
      }
    }
    probed = true;
  }

  return safe;
}
#endif

#ifndef _WIN32
std::unique_ptr<watchman_dir_handle> w_dir_open(const char* path, bool strict) {
  return watchman::make_unique<DirHandle>(path, strict);
}

DirHandle::DirHandle(const char* path, bool strict) {
#ifdef HAVE_GETATTRLISTBULK
  if (cfg_get_bool("_use_bulkstat", use_bulkstat_by_default())) {
    auto opts = strict ? OpenFileHandleOptions::strictOpenDir()
                       : OpenFileHandleOptions::openDir();

    fd_ = openFileHandle(path, opts);

    auto info = fd_.getInfo();

    if (!info.isDir()) {
      throw std::system_error(ENOTDIR, std::generic_category(), path);
    }

    attrlist_ = attrlist();
    attrlist_.bitmapcount = ATTR_BIT_MAP_COUNT;
    attrlist_.commonattr = ATTR_CMN_RETURNED_ATTRS |
      ATTR_CMN_ERROR |
      ATTR_CMN_NAME |
      ATTR_CMN_DEVID |
      ATTR_CMN_OBJTYPE |
      ATTR_CMN_MODTIME |
      ATTR_CMN_CHGTIME |
      ATTR_CMN_ACCTIME |
      ATTR_CMN_OWNERID |
      ATTR_CMN_GRPID |
      ATTR_CMN_ACCESSMASK |
      ATTR_CMN_FILEID;
    attrlist_.dirattr = ATTR_DIR_LINKCOUNT;
    attrlist_.fileattr = ATTR_FILE_TOTALSIZE | ATTR_FILE_LINKCOUNT;
    return;
  }
#endif
  d_ = strict ? opendir_nofollow(path) : opendir(path);

  if (!d_) {
    throw std::system_error(
        errno,
        std::generic_category(),
        std::string(strict ? "opendir_nofollow: " : "opendir: ") + path);
  }
}

const watchman_dir_ent* DirHandle::readDir() {
#ifdef HAVE_GETATTRLISTBULK
  if (fd_) {
    bulk_attr_item *item;

    if (!cursor_) {
      // Read the next batch of results
      int retcount;

      errno = 0;
      retcount = getattrlistbulk(
          fd_.fd(), &attrlist_, buf_, sizeof(buf_), FSOPT_PACK_INVAL_ATTRS);
      if (retcount == -1) {
        throw std::system_error(
            errno, std::generic_category(), "getattrlistbulk");
      }
      if (retcount == 0) {
        // End of the stream
        return nullptr;
      }

      retcount_ = retcount;
      cursor_ = buf_;
    }

    // Decode the next item
    item = (bulk_attr_item*)cursor_;
    cursor_ += item->len;
    if (--retcount_ == 0) {
      cursor_ = nullptr;
    }

    ent_.d_name = ((char*)&item->name) + item->name.attr_dataoffset;
    if (item->err) {
      w_log(
          W_LOG_ERR,
          "item error %s: %d %s\n",
          ent_.d_name,
          item->err,
          strerror(item->err));
      // We got the name, so we can return something useful
      ent_.has_stat = false;
      return &ent_;
    }

    ent_.stat = watchman::FileInformation();

    ent_.stat.dev = item->dev;
    memcpy(&ent_.stat.mtime, &item->mtime, sizeof(item->mtime));
    memcpy(&ent_.stat.ctime, &item->ctime, sizeof(item->ctime));
    memcpy(&ent_.stat.atime, &item->atime, sizeof(item->atime));
    ent_.stat.uid = item->uid;
    ent_.stat.gid = item->gid;
    ent_.stat.mode = item->mode & ~S_IFMT;
    ent_.stat.ino = item->ino;

    switch (item->objtype) {
      case VREG:
        ent_.stat.mode |= S_IFREG;
        ent_.stat.size = item->file_size;
        ent_.stat.nlink = item->link;
        break;
      case VDIR:
        ent_.stat.mode |= S_IFDIR;
        ent_.stat.nlink = item->link;
        break;
      case VLNK:
        ent_.stat.mode |= S_IFLNK;
        ent_.stat.size = item->file_size;
        break;
      case VBLK:
        ent_.stat.mode |= S_IFBLK;
        break;
      case VCHR:
        ent_.stat.mode |= S_IFCHR;
        break;
      case VFIFO:
        ent_.stat.mode |= S_IFIFO;
        break;
      case VSOCK:
        ent_.stat.mode |= S_IFSOCK;
        break;
    }
    ent_.has_stat = true;
    return &ent_;
  }
#endif

  if (!d_) {
    return nullptr;
  }
  errno = 0;
  auto dent = readdir(d_);
  if (!dent) {
    if (errno) {
      throw std::system_error(errno, std::generic_category(), "readdir");
    }
    return nullptr;
  }

  ent_.d_name = dent->d_name;
  ent_.has_stat = false;
  return &ent_;
}

DirHandle::~DirHandle() {
  if (d_) {
    closedir(d_);
  }
}

int DirHandle::getFd() const {
#ifdef HAVE_GETATTRLISTBULK
  if (cfg_get_bool("_use_bulkstat", use_bulkstat_by_default())) {
    return fd_.fd();
  }
#endif
  return dirfd(d_);
}
#endif

/* vim:ts=2:sw=2:et:
 */
<commit_msg>improve error handling in getattrlistbulk()<commit_after>/* Copyright 2012-present Facebook, Inc.
 * Licensed under the Apache License, Version 2.0 */

#include "watchman.h"
#include <system_error>
#ifndef _WIN32
#include <dirent.h>
#endif
#ifdef __APPLE__
# include <sys/utsname.h>
# include <sys/attr.h>
# include <sys/vnode.h>
#endif
#include "FileDescriptor.h"

using namespace watchman;
using watchman::FileDescriptor;
using watchman::OpenFileHandleOptions;

#ifdef HAVE_GETATTRLISTBULK
// The ordering of these fields is defined by the ordering of the
// corresponding ATTR_XXX flags that are listed after each item.
// Those flags appear in a specific order in the getattrlist()
// man page.  We use FSOPT_PACK_INVAL_ATTRS to ensure that the
// kernel won't omit a field that it didn't return to us.
typedef struct {
  uint32_t len;
  attribute_set_t returned; // ATTR_CMN_RETURNED_ATTRS
  uint32_t err; // ATTR_CMN_ERROR

  /* The attribute data length will not be greater than NAME_MAX + 1
   * characters, which is NAME_MAX * 3 + 1 bytes (as one UTF-8-encoded
   * character may take up to three bytes
   */
  attrreference_t name; // ATTR_CMN_NAME
  dev_t dev;            // ATTR_CMN_DEVID
  fsobj_type_t objtype; // ATTR_CMN_OBJTYPE
  struct timespec mtime; // ATTR_CMN_MODTIME
  struct timespec ctime; // ATTR_CMN_CHGTIME
  struct timespec atime; // ATTR_CMN_ACCTIME
  uid_t uid; // ATTR_CMN_OWNERID
  gid_t gid; // ATTR_CMN_GRPID
  uint32_t mode; // ATTR_CMN_ACCESSMASK, Only the permission bits of st_mode
                 // are valid; other bits should be ignored,
                 // e.g., by masking with ~S_IFMT.
  uint64_t ino;  // ATTR_CMN_FILEID
  uint32_t link; // ATTR_FILE_LINKCOUNT or ATTR_DIR_LINKCOUNT
  off_t file_size; // ATTR_FILE_TOTALSIZE

} __attribute__((packed)) bulk_attr_item;
#endif

#ifndef _WIN32
class DirHandle : public watchman_dir_handle {
#ifdef HAVE_GETATTRLISTBULK
  FileDescriptor fd_;
  struct attrlist attrlist_;
  int retcount_{0};
  char buf_[64 * (sizeof(bulk_attr_item) + NAME_MAX * 3 + 1)];
  char *cursor_{nullptr};
#endif
  DIR *d_{nullptr};
  struct watchman_dir_ent ent_;

 public:
  explicit DirHandle(const char* path, bool strict);
  ~DirHandle() override;
  const watchman_dir_ent* readDir() override;
  int getFd() const override;
};
#else
static const char *w_basename(const char *path) {
  const char *last = path + strlen(path) - 1;
  while (last >= path) {
    if (*last == '/' || *last == '\\') {
      return last + 1;
    }
    --last;
  }
  return NULL;
}
#endif

#ifndef _WIN32
/* Opens a directory making sure it's not a symlink */
static DIR *opendir_nofollow(const char *path)
{
  auto fd = openFileHandle(path, OpenFileHandleOptions::strictOpenDir());
# if !defined(HAVE_FDOPENDIR) || defined(__APPLE__)
  /* fdopendir doesn't work on earlier versions OS X, and we don't
   * use this function since 10.10, as we prefer to use getattrlistbulk
   * in that case */
  return opendir(path);
# else
  // errno should be set appropriately if this is not a directory
  auto d = fdopendir(fd.fd());
  if (d) {
    fd.release();
  }
  return d;
# endif
}
#endif

#ifdef HAVE_GETATTRLISTBULK
// I've seen bulkstat report incorrect sizes on kernel version 14.5.0.
// (That's OSX 10.10.5).
// Let's avoid it for major kernel versions < 15.
// Using statics here to avoid querying the uname on every opendir.
// There is opportunity for a data race the first time through, but the
// worst case side effect is wasted compute early on.
static bool use_bulkstat_by_default(void) {
  static bool probed = false;
  static bool safe = false;

  if (!probed) {
    struct utsname name;
    if (uname(&name) == 0) {
      int maj = 0, min = 0, patch = 0;
      sscanf(name.release, "%d.%d.%d", &maj, &min, &patch);
      if (maj >= 15) {
        safe = true;
      }
    }
    probed = true;
  }

  return safe;
}
#endif

#ifndef _WIN32
std::unique_ptr<watchman_dir_handle> w_dir_open(const char* path, bool strict) {
  return watchman::make_unique<DirHandle>(path, strict);
}

DirHandle::DirHandle(const char* path, bool strict) {
#ifdef HAVE_GETATTRLISTBULK
  if (cfg_get_bool("_use_bulkstat", use_bulkstat_by_default())) {
    auto opts = strict ? OpenFileHandleOptions::strictOpenDir()
                       : OpenFileHandleOptions::openDir();

    fd_ = openFileHandle(path, opts);

    auto info = fd_.getInfo();

    if (!info.isDir()) {
      throw std::system_error(ENOTDIR, std::generic_category(), path);
    }

    attrlist_ = attrlist();
    attrlist_.bitmapcount = ATTR_BIT_MAP_COUNT;
    // These field flags are listed here in the same order that they
    // are listed in the getattrlist() manpage, which is also the
    // same order that they will be emitted into the buffer, which
    // is thus the order that they must appear in bulk_attr_item.
    attrlist_.commonattr = ATTR_CMN_RETURNED_ATTRS |
      ATTR_CMN_ERROR |
      ATTR_CMN_NAME |
      ATTR_CMN_DEVID |
      ATTR_CMN_OBJTYPE |
      ATTR_CMN_MODTIME |
      ATTR_CMN_CHGTIME |
      ATTR_CMN_ACCTIME |
      ATTR_CMN_OWNERID |
      ATTR_CMN_GRPID |
      ATTR_CMN_ACCESSMASK |
      ATTR_CMN_FILEID;
    attrlist_.dirattr = ATTR_DIR_LINKCOUNT;
    attrlist_.fileattr = ATTR_FILE_TOTALSIZE | ATTR_FILE_LINKCOUNT;
    return;
  }
#endif
  d_ = strict ? opendir_nofollow(path) : opendir(path);

  if (!d_) {
    throw std::system_error(
        errno,
        std::generic_category(),
        std::string(strict ? "opendir_nofollow: " : "opendir: ") + path);
  }
}

const watchman_dir_ent* DirHandle::readDir() {
#ifdef HAVE_GETATTRLISTBULK
  if (fd_) {
    bulk_attr_item *item;

    if (!cursor_) {
      // Read the next batch of results
      int retcount;

      errno = 0;
      retcount = getattrlistbulk(
          fd_.fd(),
          &attrlist_,
          buf_,
          sizeof(buf_),
          // FSOPT_PACK_INVAL_ATTRS informs the kernel that we want to
          // include attrs in our buffer even if it doesn't return them
          // to us; we want this because we took pains to craft our
          // bulk_attr_item struct to avoid pointer math.
          FSOPT_PACK_INVAL_ATTRS);
      if (retcount == -1) {
        throw std::system_error(
            errno, std::generic_category(), "getattrlistbulk");
      }
      if (retcount == 0) {
        // End of the stream
        return nullptr;
      }

      retcount_ = retcount;
      cursor_ = buf_;
    }

    // Decode the next item
    item = (bulk_attr_item*)cursor_;
    cursor_ += item->len;
    if (--retcount_ == 0) {
      cursor_ = nullptr;
    }

    w_string_piece name{};

    if (item->returned.commonattr & ATTR_CMN_NAME) {
      ent_.d_name = ((char*)&item->name) + item->name.attr_dataoffset;
      name = w_string_piece(ent_.d_name);
    }

    if (item->returned.commonattr & ATTR_CMN_ERROR) {
      log(ERR,
          "getattrlistbulk: error while reading dir: entry ",
          name,
          strerror(item->err));

      // No name means we've got nothing useful to go on
      if (name.empty()) {
        throw std::system_error(
            item->err, std::generic_category(), "getattrlistbulk");
      }

      // Getting the name means that we can at least enumerate the dir
      // contents.
      ent_.has_stat = false;
      return &ent_;
    }

    if (name.empty()) {
      throw std::system_error(
          EIO,
          std::generic_category(),
          "getattrlistbulk didn't return a name for a directory entry!?");
    }

    if (item->returned.commonattr != (attrlist_.commonattr & ~ATTR_CMN_ERROR)) {
      log(ERR,
          "getattrlistbulk didn't return all useful stat data! returned=",
          item->returned.commonattr);
      // We can still yield the name, so we don't need to throw an exception
      // in this case.
      ent_.has_stat = false;
      return &ent_;
    }

    ent_.stat = watchman::FileInformation();

    ent_.stat.dev = item->dev;
    memcpy(&ent_.stat.mtime, &item->mtime, sizeof(item->mtime));
    memcpy(&ent_.stat.ctime, &item->ctime, sizeof(item->ctime));
    memcpy(&ent_.stat.atime, &item->atime, sizeof(item->atime));
    ent_.stat.uid = item->uid;
    ent_.stat.gid = item->gid;
    ent_.stat.mode = item->mode & ~S_IFMT;
    ent_.stat.ino = item->ino;

    switch (item->objtype) {
      case VREG:
        ent_.stat.mode |= S_IFREG;
        ent_.stat.size = item->file_size;
        ent_.stat.nlink = item->link;
        break;
      case VDIR:
        ent_.stat.mode |= S_IFDIR;
        ent_.stat.nlink = item->link;
        break;
      case VLNK:
        ent_.stat.mode |= S_IFLNK;
        ent_.stat.size = item->file_size;
        break;
      case VBLK:
        ent_.stat.mode |= S_IFBLK;
        break;
      case VCHR:
        ent_.stat.mode |= S_IFCHR;
        break;
      case VFIFO:
        ent_.stat.mode |= S_IFIFO;
        break;
      case VSOCK:
        ent_.stat.mode |= S_IFSOCK;
        break;
    }
    ent_.has_stat = true;
    return &ent_;
  }
#endif

  if (!d_) {
    return nullptr;
  }
  errno = 0;
  auto dent = readdir(d_);
  if (!dent) {
    if (errno) {
      throw std::system_error(errno, std::generic_category(), "readdir");
    }
    return nullptr;
  }

  ent_.d_name = dent->d_name;
  ent_.has_stat = false;
  return &ent_;
}

DirHandle::~DirHandle() {
  if (d_) {
    closedir(d_);
  }
}

int DirHandle::getFd() const {
#ifdef HAVE_GETATTRLISTBULK
  if (cfg_get_bool("_use_bulkstat", use_bulkstat_by_default())) {
    return fd_.fd();
  }
#endif
  return dirfd(d_);
}
#endif

/* vim:ts=2:sw=2:et:
 */
<|endoftext|>


<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2019 ScyllaDB Ltd.
 */

#pragma once

#include <seastar/core/future.hh>

#if __cplusplus > 201703L
#include <version>
#endif

#if !defined(__cpp_lib_coroutine) && !defined(SEASTAR_COROUTINES_TS)
#error Coroutines support disabled.
#endif

#include <seastar/core/std-coroutine.hh>

#ifdef SEASTAR_COROUTINES_TS
#define SEASTAR_INTERNAL_COROUTINE_NAMESPACE std::experimental
#else
#define SEASTAR_INTERNAL_COROUTINE_NAMESPACE std
#endif

namespace SEASTAR_INTERNAL_COROUTINE_NAMESPACE {

template<typename... T, typename... Args>
class coroutine_traits<seastar::future<T...>, Args...> {
public:
    class promise_type final : public seastar::task {
        seastar::promise<T...> _promise;
    public:
        promise_type() = default;
        promise_type(promise_type&&) = delete;
        promise_type(const promise_type&) = delete;

        template<typename... U>
        void return_value(U&&... value) {
            _promise.set_value(std::forward<U>(value)...);
        }
        void unhandled_exception() noexcept {
            _promise.set_exception(std::current_exception());
        }

        seastar::future<T...> get_return_object() noexcept {
            return _promise.get_future();
        }

        suspend_never initial_suspend() noexcept { return { }; }
        suspend_never final_suspend() noexcept { return { }; }

        virtual void run_and_dispose() noexcept override {
            auto handle = SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<promise_type>::from_promise(*this);
            handle.resume();
        }
    };
};

template<typename... Args>
class coroutine_traits<seastar::future<>, Args...> {
public:
   class promise_type final : public seastar::task {
        seastar::promise<> _promise;
    public:
        promise_type() = default;
        promise_type(promise_type&&) = delete;
        promise_type(const promise_type&) = delete;

        void return_void() noexcept {
            _promise.set_value();
        }
        void unhandled_exception() noexcept {
            _promise.set_exception(std::current_exception());
        }

        seastar::future<> get_return_object() noexcept {
            return _promise.get_future();
        }

        suspend_never initial_suspend() noexcept { return { }; }
        suspend_never final_suspend() noexcept { return { }; }

        virtual void run_and_dispose() noexcept override {
            auto handle = SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<promise_type>::from_promise(*this);
            handle.resume();
        }
    };
};

}

namespace seastar {

namespace internal {

template<typename... T>
struct awaiter {
    seastar::future<T...> _future;
public:
    explicit awaiter(seastar::future<T...>&& f) noexcept : _future(std::move(f)) { }

    awaiter(const awaiter&) = delete;
    awaiter(awaiter&&) = delete;

    bool await_ready() const noexcept {
        return _future.available();
    }

    template<typename U>
    void await_suspend(SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<U> hndl) noexcept {
        _future.set_coroutine(hndl.promise());
    }

    std::tuple<T...> await_resume() { return _future.get(); }
};

template<typename T>
struct awaiter<T> {
    seastar::future<T> _future;
public:
    explicit awaiter(seastar::future<T>&& f) noexcept : _future(std::move(f)) { }

    awaiter(const awaiter&) = delete;
    awaiter(awaiter&&) = delete;

    bool await_ready() const noexcept {
        return _future.available();
    }

    template<typename U>
    void await_suspend(SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<U> hndl) noexcept {
        _future.set_coroutine(hndl.promise());
    }

    T await_resume() { return _future.get0(); }
};

template<>
struct awaiter<> {
    seastar::future<> _future;
public:
    explicit awaiter(seastar::future<>&& f) noexcept : _future(std::move(f)) { }

    awaiter(const awaiter&) = delete;
    awaiter(awaiter&&) = delete;

    bool await_ready() const noexcept {
        return _future.available();
    }

    template<typename U>
    void await_suspend(SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<U> hndl) noexcept {
        _future.set_coroutine(hndl.promise());
    }

    void await_resume() { _future.get(); }
};

}

template<typename... T>
auto operator co_await(future<T...> f) noexcept {
    return internal::awaiter<T...>(std::move(f));
}

}
<commit_msg>coroutines: reduce template bloat<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2019 ScyllaDB Ltd.
 */

#pragma once

#include <seastar/core/future.hh>

#if __cplusplus > 201703L
#include <version>
#endif

#if !defined(__cpp_lib_coroutine) && !defined(SEASTAR_COROUTINES_TS)
#error Coroutines support disabled.
#endif

#include <seastar/core/std-coroutine.hh>

#ifdef SEASTAR_COROUTINES_TS
#define SEASTAR_INTERNAL_COROUTINE_NAMESPACE std::experimental
#else
#define SEASTAR_INTERNAL_COROUTINE_NAMESPACE std
#endif

namespace seastar {

namespace internal {

template <typename... T>
class coroutine_traits_base {
public:
    class promise_type final : public seastar::task {
        seastar::promise<T...> _promise;
    public:
        promise_type() = default;
        promise_type(promise_type&&) = delete;
        promise_type(const promise_type&) = delete;

        template<typename... U>
        void return_value(U&&... value) {
            _promise.set_value(std::forward<U>(value)...);
        }
        void unhandled_exception() noexcept {
            _promise.set_exception(std::current_exception());
        }

        seastar::future<T...> get_return_object() noexcept {
            return _promise.get_future();
        }

        SEASTAR_INTERNAL_COROUTINE_NAMESPACE::suspend_never initial_suspend() noexcept { return { }; }
        SEASTAR_INTERNAL_COROUTINE_NAMESPACE::suspend_never final_suspend() noexcept { return { }; }

        virtual void run_and_dispose() noexcept override {
            auto handle = SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<promise_type>::from_promise(*this);
            handle.resume();
        }
    };
};

template <>
class coroutine_traits_base<> {
public:
   class promise_type final : public seastar::task {
        seastar::promise<> _promise;
    public:
        promise_type() = default;
        promise_type(promise_type&&) = delete;
        promise_type(const promise_type&) = delete;

        void return_void() noexcept {
            _promise.set_value();
        }
        void unhandled_exception() noexcept {
            _promise.set_exception(std::current_exception());
        }

        seastar::future<> get_return_object() noexcept {
            return _promise.get_future();
        }

        SEASTAR_INTERNAL_COROUTINE_NAMESPACE::suspend_never initial_suspend() noexcept { return { }; }
        SEASTAR_INTERNAL_COROUTINE_NAMESPACE::suspend_never final_suspend() noexcept { return { }; }

        virtual void run_and_dispose() noexcept override {
            auto handle = SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<promise_type>::from_promise(*this);
            handle.resume();
        }
    };
};

template<typename... T>
struct awaiter {
    seastar::future<T...> _future;
public:
    explicit awaiter(seastar::future<T...>&& f) noexcept : _future(std::move(f)) { }

    awaiter(const awaiter&) = delete;
    awaiter(awaiter&&) = delete;

    bool await_ready() const noexcept {
        return _future.available();
    }

    template<typename U>
    void await_suspend(SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<U> hndl) noexcept {
        _future.set_coroutine(hndl.promise());
    }

    std::tuple<T...> await_resume() { return _future.get(); }
};

template<typename T>
struct awaiter<T> {
    seastar::future<T> _future;
public:
    explicit awaiter(seastar::future<T>&& f) noexcept : _future(std::move(f)) { }

    awaiter(const awaiter&) = delete;
    awaiter(awaiter&&) = delete;

    bool await_ready() const noexcept {
        return _future.available();
    }

    template<typename U>
    void await_suspend(SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<U> hndl) noexcept {
        _future.set_coroutine(hndl.promise());
    }

    T await_resume() { return _future.get0(); }
};

template<>
struct awaiter<> {
    seastar::future<> _future;
public:
    explicit awaiter(seastar::future<>&& f) noexcept : _future(std::move(f)) { }

    awaiter(const awaiter&) = delete;
    awaiter(awaiter&&) = delete;

    bool await_ready() const noexcept {
        return _future.available();
    }

    template<typename U>
    void await_suspend(SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<U> hndl) noexcept {
        _future.set_coroutine(hndl.promise());
    }

    void await_resume() { _future.get(); }
};

} // seastar::internal

template<typename... T>
auto operator co_await(future<T...> f) noexcept {
    return internal::awaiter<T...>(std::move(f));
}

} // seastar

namespace SEASTAR_INTERNAL_COROUTINE_NAMESPACE {

template<typename... T, typename... Args>
class coroutine_traits<seastar::future<T...>, Args...> : public seastar::internal::coroutine_traits_base<T...> {
};

} // SEASTAR_INTERNAL_COROUTINE_NAMESPACE

<|endoftext|>


<commit_before>#pragma once

#include <regex>
#include <string>

namespace valijson {
namespace internal {
namespace uri {

/**
  * @brief  Placeholder function to check whether a URI is absolute
  *
  * This function just checks for '://'
  */
inline bool isUriAbsolute(const std::string &documentUri)
{
    static const char * placeholderMarker = "://";

    return documentUri.find(placeholderMarker) != std::string::npos;
}

/**
 * @brief  Placeholder function to check whether a URI is a URN
 *
 * This function validates that the URI matches the RFC 8141
 */
inline bool isUrn(const std::string &documentUri) {
  static const std::regex pattern(
      "^((urn)|(URN)):[a-zA-Z0-9]+[-]{0,1}[a-zA-Z0-9]+(:[-a-zA-Z0-9\\\\._~%!"
      "$&'()\\/*+,;=]+)+(\\?[-a-zA-Z0-9\\\\._~%!$&'()\\/"
      "*+,;:=]+){0,1}(#[-a-zA-Z0-9\\\\._~%!$&'()\\/*+,;:=]+){0,1}$");

  return std::regex_match(documentUri, pattern);
}

/**
 * Placeholder function to resolve a relative URI within a given scope
 */
inline std::string resolveRelativeUri(
        const std::string &resolutionScope,
        const std::string &relativeUri)
{
    return resolutionScope + relativeUri;
}

} // namespace uri
} // namespace internal
} // namespace valijson
<commit_msg>Update urn regex to match widely accepted expression<commit_after>#pragma once

#include <regex>
#include <string>

namespace valijson {
namespace internal {
namespace uri {

/**
  * @brief  Placeholder function to check whether a URI is absolute
  *
  * This function just checks for '://'
  */
inline bool isUriAbsolute(const std::string &documentUri)
{
    static const char * placeholderMarker = "://";

    return documentUri.find(placeholderMarker) != std::string::npos;
}

/**
 * @brief  Placeholder function to check whether a URI is a URN
 *
 * This function validates that the URI matches the RFC 8141
 */
inline bool isUrn(const std::string &documentUri) {
  static const std::regex pattern(
      "^(?i:urn:(?!urn:)([a-z0-9][a-z0-9-]{1,31}):((?:[-a-z0-9()+,.:=@;$_!*'&~\\/]|%[0-9a-f]{2})+)(?:\\?\\+(.*?))?(?:\\?=(.*?))?(?:#(.*?))?)$");

  return std::regex_match(documentUri, pattern);
}

/**
 * Placeholder function to resolve a relative URI within a given scope
 */
inline std::string resolveRelativeUri(
        const std::string &resolutionScope,
        const std::string &relativeUri)
{
    return resolutionScope + relativeUri;
}

} // namespace uri
} // namespace internal
} // namespace valijson
<|endoftext|>