<commit_before>/*
   Copyright 2017 Thomas Krause <thomaskrause@posteo.de>

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

#include "simdindexjoin.h"

#include <annis/operators/operator.h>     // for Operator
#include <annis/util/comparefunctions.h>  // for checkAnnotationEqual
#include <algorithm>                      // for move
#include <future>                         // for future, async, launch, laun...
#include <list>                           // for list
#include "annis/iterators.h"              // for AnnoIt, Iterator
#include "annis/types.h"                  // for Match, Annotation, nodeid_t
#include "annis/util/threadpool.h"        // for ThreadPool

#include <Vc/Memory>

using namespace annis;

SIMDIndexJoin::SIMDIndexJoin(std::shared_ptr<Iterator> lhs, size_t lhsIdx,
                             std::shared_ptr<Operator> op,
                             const AnnoStorage<nodeid_t>& annos,
                             Annotation rhsAnnoToFind)
  : lhs(lhs), lhsIdx(lhsIdx), op(op), annos(annos), rhsAnnoToFind(rhsAnnoToFind)
{
}

bool SIMDIndexJoin::next(std::vector<Match> &tuple)
{
  tuple.clear();

  do
  {
    while(!matchBuffer.empty())
    {
      const MatchPair& m = matchBuffer.front();

      tuple.reserve(m.lhs.size()+1);
      tuple.insert(tuple.begin(), m.lhs.begin(), m.lhs.end());
      tuple.push_back({m.rhs, rhsAnnoToFind});

      matchBuffer.pop_front();
      return true;

    }
  } while (nextMatchBuffer());

  return false;
}

void SIMDIndexJoin::reset()
{
  if(lhs)
  {
    lhs->reset();
  }

  matchBuffer.clear();
}

bool SIMDIndexJoin::fillMatchBuffer()
{
  std::vector<Match> currentLHS;

  Vc::uint32_v valueTemplate(rhsAnnoToFind.val);

  while(matchBuffer.empty() && lhs->next(currentLHS))
  {
    std::unique_ptr<AnnoIt> reachableNodesIt = op->retrieveMatches(currentLHS[lhsIdx]);
    if(reachableNodesIt)
    {
      std::vector<nodeid_t> reachableNodes;

      Match n;
      while(reachableNodesIt->next(n))
      {
        reachableNodes.push_back(n.node);
      }

      Vc::Memory<Vc::uint32_v> vAnnoVals(reachableNodes.size());

      for(size_t i=0; i < vAnnoVals.entriesCount(); i++)
      {
        std::vector<Annotation> foundAnnos = annos.getAnnotations(n.node, rhsAnnoToFind.ns, rhsAnnoToFind.name);
        vAnnoVals[i] = foundAnnos.empty() ? 0 : foundAnnos[0].val;
      }

      for(size_t i=0; i < vAnnoVals.vectorsCount(); i++)
      {
        Vc::Mask<uint32_t> maskFoundAnnos = (vAnnoVals.vector(i) == valueTemplate);

        if(!maskFoundAnnos.isEmpty())
        {
          for(int i=maskFoundAnnos.firstOne(); i < maskFoundAnnos.size(); i++)
          {
            if(maskFoundAnnos[i])
            {
              matchBuffer.push_back({currentLHS, reachableNodes[i]});
            }
          }
        }
      }

/*
      for(Annotation currentRHSAnno : matchGeneratorFunc(reachableNode.node))
      {
        if((op->isReflexive() || currentLHS[lhsIdx].node != reachableNode.node
        || !checkAnnotationEqual(currentLHS[lhsIdx].anno, currentRHSAnno)))
        {
          matchBuffer.push_back({currentLHS, {reachableNode.node, currentRHSAnno}});
        }
      }
*/
    }
  }
}

bool SIMDIndexJoin::nextMatchBuffer()
{
  while(fillMatchBuffer())
  {
    // if there is a non empty result return true, otherwise try more entries of the task buffer
    if(!matchBuffer.empty())
    {
      return true;
    }
  }

  // return false if there is no more value to fetch from the task buffer.
  return false;
}

SIMDIndexJoin::~SIMDIndexJoin()
{
}
<commit_msg>Adapt reflexifity rule for SIMDIndexJoin<commit_after>/*
   Copyright 2017 Thomas Krause <thomaskrause@posteo.de>

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

#include "simdindexjoin.h"

#include <annis/operators/operator.h>     // for Operator
#include <annis/util/comparefunctions.h>  // for checkAnnotationEqual
#include <algorithm>                      // for move
#include <future>                         // for future, async, launch, laun...
#include <list>                           // for list
#include "annis/iterators.h"              // for AnnoIt, Iterator
#include "annis/types.h"                  // for Match, Annotation, nodeid_t
#include "annis/util/threadpool.h"        // for ThreadPool

#include <Vc/Memory>

using namespace annis;

SIMDIndexJoin::SIMDIndexJoin(std::shared_ptr<Iterator> lhs, size_t lhsIdx,
                             std::shared_ptr<Operator> op,
                             const AnnoStorage<nodeid_t>& annos,
                             Annotation rhsAnnoToFind)
  : lhs(lhs), lhsIdx(lhsIdx), op(op), annos(annos), rhsAnnoToFind(rhsAnnoToFind)
{
}

bool SIMDIndexJoin::next(std::vector<Match> &tuple)
{
  tuple.clear();

  do
  {
    while(!matchBuffer.empty())
    {
      const MatchPair& m = matchBuffer.front();

      tuple.reserve(m.lhs.size()+1);
      tuple.insert(tuple.begin(), m.lhs.begin(), m.lhs.end());
      tuple.push_back({m.rhs, rhsAnnoToFind});

      matchBuffer.pop_front();
      return true;

    }
  } while (nextMatchBuffer());

  return false;
}

void SIMDIndexJoin::reset()
{
  if(lhs)
  {
    lhs->reset();
  }

  matchBuffer.clear();
}

bool SIMDIndexJoin::fillMatchBuffer()
{
  std::vector<Match> currentLHS;

  Vc::uint32_v valueTemplate(rhsAnnoToFind.val);

  while(matchBuffer.empty() && lhs->next(currentLHS))
  {
    std::unique_ptr<AnnoIt> reachableNodesIt = op->retrieveMatches(currentLHS[lhsIdx]);
    if(reachableNodesIt)
    {
      std::vector<nodeid_t> reachableNodes;

      Match n;
      while(reachableNodesIt->next(n))
      {
        reachableNodes.push_back(n.node);
      }

      Vc::Memory<Vc::uint32_v> vAnnoVals(reachableNodes.size());

      for(size_t i=0; i < vAnnoVals.entriesCount(); i++)
      {
        std::vector<Annotation> foundAnnos = annos.getAnnotations(n.node, rhsAnnoToFind.ns, rhsAnnoToFind.name);
        vAnnoVals[i] = foundAnnos.empty() ? 0 : foundAnnos[0].val;
      }

      for(size_t i=0; i < vAnnoVals.vectorsCount(); i++)
      {
        Vc::Mask<uint32_t> maskFoundAnnos = (vAnnoVals.vector(i) == valueTemplate);

        if(!maskFoundAnnos.isEmpty())
        {
          for(int i=maskFoundAnnos.firstOne(); i < maskFoundAnnos.size(); i++)
          {
            if(maskFoundAnnos[i])
            {
              if((op->isReflexive() || currentLHS[lhsIdx].node != reachableNodes[i]))
              {
                matchBuffer.push_back({currentLHS, reachableNodes[i]});
              }
            }
          }
        }
      }
    }
  }
}

bool SIMDIndexJoin::nextMatchBuffer()
{
  while(fillMatchBuffer())
  {
    // if there is a non empty result return true, otherwise try more entries of the task buffer
    if(!matchBuffer.empty())
    {
      return true;
    }
  }

  // return false if there is no more value to fetch from the task buffer.
  return false;
}

SIMDIndexJoin::~SIMDIndexJoin()
{
}
<|endoftext|>


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

#ifndef SC_DPSAVE_HXX
#define SC_DPSAVE_HXX

#ifndef _STRING_HXX //autogen
#include <tools/string.hxx>
#endif

#ifndef _LIST_HXX //autogen wg. List
#include <tools/list.hxx>
#endif

#ifndef _COM_SUN_STAR_SHEET_XDIMENSIONSSUPPLIER_HPP_
#include <com/sun/star/sheet/XDimensionsSupplier.hpp>
#endif

#ifndef INCLUDED_SCDLLAPI_H
#include "scdllapi.h"
#endif

namespace com { namespace sun { namespace star { namespace sheet {
    struct DataPilotFieldReference;
    struct DataPilotFieldSortInfo;
    struct DataPilotFieldAutoShowInfo;
    struct DataPilotFieldLayoutInfo;
} } } }

class SvStream;
class ScDPDimensionSaveData;

// --------------------------------------------------------------------
//
//  classes to save Data Pilot settings
//

class ScDPSaveMember
{
private:
    String      aName;
    USHORT      nVisibleMode;
    USHORT      nShowDetailsMode;

public:
                            ScDPSaveMember(const String& rName);
                            ScDPSaveMember(const ScDPSaveMember& r);
                            ScDPSaveMember(SvStream& rStream);
                            ~ScDPSaveMember();

    BOOL                    operator== ( const ScDPSaveMember& r ) const;

    const String&           GetName() const { return aName; }
    BOOL                    HasIsVisible() const;
    void                    SetIsVisible(BOOL bSet);
    BOOL                    GetIsVisible() const { return BOOL(nVisibleMode); }
    BOOL                    HasShowDetails() const;
    void                    SetShowDetails(BOOL bSet);
    BOOL                    GetShowDetails() const { return BOOL(nShowDetailsMode); }

    void                    SetName( const String& rNew );  // used if the source member was renamed (groups)

    void                    WriteToSource( const com::sun::star::uno::Reference<
                                            com::sun::star::uno::XInterface>& xMember );

    void                    Store( SvStream& rStream ) const;
};

class ScDPSaveDimension
{
private:
    String      aName;
    String*     pLayoutName;        // alternative name for layout, not used (yet)
    String*     pSelectedPage;
    BOOL        bIsDataLayout;
    BOOL        bDupFlag;
    USHORT      nOrientation;
    USHORT      nFunction;          // enum GeneralFunction, for data dimensions
    long        nUsedHierarchy;
    USHORT      nShowEmptyMode;     //! at level
    BOOL        bSubTotalDefault;   //! at level
    long        nSubTotalCount;
    USHORT*     pSubTotalFuncs;     // enum GeneralFunction
    ::com::sun::star::sheet::DataPilotFieldReference* pReferenceValue;
    ::com::sun::star::sheet::DataPilotFieldSortInfo*  pSortInfo;            // (level)
    ::com::sun::star::sheet::DataPilotFieldAutoShowInfo* pAutoShowInfo;     // (level)
    ::com::sun::star::sheet::DataPilotFieldLayoutInfo* pLayoutInfo;         // (level)
    List        aMemberList;

public:
                            ScDPSaveDimension(const String& rName, BOOL bDataLayout);
                            ScDPSaveDimension(const ScDPSaveDimension& r);
                            ScDPSaveDimension(SvStream& rStream);
                            ~ScDPSaveDimension();

    BOOL                    operator== ( const ScDPSaveDimension& r ) const;

    const List&             GetMembers() const { return aMemberList; }
    void                    AddMember(ScDPSaveMember* pMember) { aMemberList.Insert(pMember, LIST_APPEND); };

    void                    SetDupFlag(BOOL bSet)   { bDupFlag = bSet; }
    BOOL                    GetDupFlag() const      { return bDupFlag; }

    const String&           GetName() const         { return aName; }
    BOOL                    IsDataLayout() const    { return bIsDataLayout; }

    void                    SetName( const String& rNew );  // used if the source dim was renamed (groups)

    void                    SetOrientation(USHORT nNew);
    void                    SetSubTotals(BOOL bSet);        // to be removed!
    void                    SetSubTotals(long nCount, const USHORT* pFuncs);
    long                    GetSubTotalsCount() const { return nSubTotalCount; }
    USHORT                  GetSubTotalFunc(long nIndex) const { return pSubTotalFuncs[nIndex]; }
    void                    SetShowEmpty(BOOL bSet);
    BOOL                    GetShowEmpty() const { return BOOL(nShowEmptyMode); }
    void                    SetFunction(USHORT nNew);       // enum GeneralFunction
    USHORT                  GetFunction() const { return nFunction; }
    void                    SetUsedHierarchy(long nNew);
    long                    GetUsedHierarchy() const { return nUsedHierarchy; }
    void                    SetLayoutName(const String* pName);
    const String&           GetLayoutName() const;
    BOOL                    HasLayoutName() const;
    void                    ResetLayoutName();

    const ::com::sun::star::sheet::DataPilotFieldReference* GetReferenceValue() const   { return pReferenceValue; }
    void                    SetReferenceValue(const ::com::sun::star::sheet::DataPilotFieldReference* pNew);

    const ::com::sun::star::sheet::DataPilotFieldSortInfo* GetSortInfo() const          { return pSortInfo; }
    void                    SetSortInfo(const ::com::sun::star::sheet::DataPilotFieldSortInfo* pNew);
    const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo* GetAutoShowInfo() const  { return pAutoShowInfo; }
    void                    SetAutoShowInfo(const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo* pNew);
    const ::com::sun::star::sheet::DataPilotFieldLayoutInfo* GetLayoutInfo() const      { return pLayoutInfo; }
    void                    SetLayoutInfo(const ::com::sun::star::sheet::DataPilotFieldLayoutInfo* pNew);

    void                    SetCurrentPage( const String* pPage );      // NULL = no selection (all)
    BOOL                    HasCurrentPage() const;
    const String&           GetCurrentPage() const;

    USHORT                  GetOrientation() const  { return nOrientation; }

    ScDPSaveMember*         GetExistingMemberByName(const String& rName);
    ScDPSaveMember*         GetMemberByName(const String& rName);

    void                    WriteToSource( const com::sun::star::uno::Reference<
                                            com::sun::star::uno::XInterface>& xDim );

    void                    Store( SvStream& rStream ) const;
};

class ScDPSaveData
{
private:
    List        aDimList;
    ScDPDimensionSaveData* pDimensionData;      // settings that create new dimensions
    USHORT      nColumnGrandMode;
    USHORT      nRowGrandMode;
    USHORT      nIgnoreEmptyMode;
    USHORT      nRepeatEmptyMode;
    BOOL        bFilterButton;      // not passed to DataPilotSource
    BOOL        bDrillDown;         // not passed to DataPilotSource

public:
                            ScDPSaveData();
                            ScDPSaveData(const ScDPSaveData& r);
                            ~ScDPSaveData();

    ScDPSaveData&           operator= ( const ScDPSaveData& r );

    BOOL                    operator== ( const ScDPSaveData& r ) const;

    const List&             GetDimensions() const { return aDimList; }
    void                    AddDimension(ScDPSaveDimension* pDim) { aDimList.Insert(pDim, LIST_APPEND); }

    ScDPSaveDimension*      GetDimensionByName(const String& rName);
    ScDPSaveDimension*      GetDataLayoutDimension();

    ScDPSaveDimension*      DuplicateDimension(const String& rName);
    ScDPSaveDimension&      DuplicateDimension(const ScDPSaveDimension& rDim);

    SC_DLLPUBLIC ScDPSaveDimension*     GetExistingDimensionByName(const String& rName);
    ScDPSaveDimension*      GetNewDimensionByName(const String& rName);

    void                    RemoveDimensionByName(const String& rName);

    ScDPSaveDimension*      GetInnermostDimension(USHORT nOrientation);
    long                    GetDataDimensionCount() const;

    void                    SetPosition( ScDPSaveDimension* pDim, long nNew );
    void                    SetColumnGrand( BOOL bSet );
    BOOL                    GetColumnGrand() const { return BOOL(nColumnGrandMode); }
    void                    SetRowGrand( BOOL bSet );
    BOOL                    GetRowGrand() const { return BOOL(nRowGrandMode); }
    void                    SetIgnoreEmptyRows( BOOL bSet );
    BOOL                    GetIgnoreEmptyRows() const { return BOOL(nIgnoreEmptyMode); }
    void                    SetRepeatIfEmpty( BOOL bSet );
    BOOL                    GetRepeatIfEmpty() const { return BOOL(nRepeatEmptyMode); }

    void                    SetFilterButton( BOOL bSet );
    BOOL                    GetFilterButton() const { return bFilterButton; }
    void                    SetDrillDown( BOOL bSet );
    BOOL                    GetDrillDown() const { return bDrillDown; }

    void                    WriteToSource( const com::sun::star::uno::Reference<
                                            com::sun::star::sheet::XDimensionsSupplier>& xSource );

    void                    Store( SvStream& rStream ) const;
    void                    Load( SvStream& rStream );

    BOOL                    IsEmpty() const;

    const ScDPDimensionSaveData* GetExistingDimensionData() const   { return pDimensionData; }
    ScDPDimensionSaveData*  GetDimensionData();     // create if not there
    void                    SetDimensionData( const ScDPDimensionSaveData* pNew );      // copied
};

#endif

<commit_msg>INTEGRATION: CWS ooo19126 (1.7.346); FILE MERGED 2005/09/05 15:00:43 rt 1.7.346.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: dpsave.hxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 17:35:34 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef SC_DPSAVE_HXX
#define SC_DPSAVE_HXX

#ifndef _STRING_HXX //autogen
#include <tools/string.hxx>
#endif

#ifndef _LIST_HXX //autogen wg. List
#include <tools/list.hxx>
#endif

#ifndef _COM_SUN_STAR_SHEET_XDIMENSIONSSUPPLIER_HPP_
#include <com/sun/star/sheet/XDimensionsSupplier.hpp>
#endif

#ifndef INCLUDED_SCDLLAPI_H
#include "scdllapi.h"
#endif

namespace com { namespace sun { namespace star { namespace sheet {
    struct DataPilotFieldReference;
    struct DataPilotFieldSortInfo;
    struct DataPilotFieldAutoShowInfo;
    struct DataPilotFieldLayoutInfo;
} } } }

class SvStream;
class ScDPDimensionSaveData;

// --------------------------------------------------------------------
//
//  classes to save Data Pilot settings
//

class ScDPSaveMember
{
private:
    String      aName;
    USHORT      nVisibleMode;
    USHORT      nShowDetailsMode;

public:
                            ScDPSaveMember(const String& rName);
                            ScDPSaveMember(const ScDPSaveMember& r);
                            ScDPSaveMember(SvStream& rStream);
                            ~ScDPSaveMember();

    BOOL                    operator== ( const ScDPSaveMember& r ) const;

    const String&           GetName() const { return aName; }
    BOOL                    HasIsVisible() const;
    void                    SetIsVisible(BOOL bSet);
    BOOL                    GetIsVisible() const { return BOOL(nVisibleMode); }
    BOOL                    HasShowDetails() const;
    void                    SetShowDetails(BOOL bSet);
    BOOL                    GetShowDetails() const { return BOOL(nShowDetailsMode); }

    void                    SetName( const String& rNew );  // used if the source member was renamed (groups)

    void                    WriteToSource( const com::sun::star::uno::Reference<
                                            com::sun::star::uno::XInterface>& xMember );

    void                    Store( SvStream& rStream ) const;
};

class ScDPSaveDimension
{
private:
    String      aName;
    String*     pLayoutName;        // alternative name for layout, not used (yet)
    String*     pSelectedPage;
    BOOL        bIsDataLayout;
    BOOL        bDupFlag;
    USHORT      nOrientation;
    USHORT      nFunction;          // enum GeneralFunction, for data dimensions
    long        nUsedHierarchy;
    USHORT      nShowEmptyMode;     //! at level
    BOOL        bSubTotalDefault;   //! at level
    long        nSubTotalCount;
    USHORT*     pSubTotalFuncs;     // enum GeneralFunction
    ::com::sun::star::sheet::DataPilotFieldReference* pReferenceValue;
    ::com::sun::star::sheet::DataPilotFieldSortInfo*  pSortInfo;            // (level)
    ::com::sun::star::sheet::DataPilotFieldAutoShowInfo* pAutoShowInfo;     // (level)
    ::com::sun::star::sheet::DataPilotFieldLayoutInfo* pLayoutInfo;         // (level)
    List        aMemberList;

public:
                            ScDPSaveDimension(const String& rName, BOOL bDataLayout);
                            ScDPSaveDimension(const ScDPSaveDimension& r);
                            ScDPSaveDimension(SvStream& rStream);
                            ~ScDPSaveDimension();

    BOOL                    operator== ( const ScDPSaveDimension& r ) const;

    const List&             GetMembers() const { return aMemberList; }
    void                    AddMember(ScDPSaveMember* pMember) { aMemberList.Insert(pMember, LIST_APPEND); };

    void                    SetDupFlag(BOOL bSet)   { bDupFlag = bSet; }
    BOOL                    GetDupFlag() const      { return bDupFlag; }

    const String&           GetName() const         { return aName; }
    BOOL                    IsDataLayout() const    { return bIsDataLayout; }

    void                    SetName( const String& rNew );  // used if the source dim was renamed (groups)

    void                    SetOrientation(USHORT nNew);
    void                    SetSubTotals(BOOL bSet);        // to be removed!
    void                    SetSubTotals(long nCount, const USHORT* pFuncs);
    long                    GetSubTotalsCount() const { return nSubTotalCount; }
    USHORT                  GetSubTotalFunc(long nIndex) const { return pSubTotalFuncs[nIndex]; }
    void                    SetShowEmpty(BOOL bSet);
    BOOL                    GetShowEmpty() const { return BOOL(nShowEmptyMode); }
    void                    SetFunction(USHORT nNew);       // enum GeneralFunction
    USHORT                  GetFunction() const { return nFunction; }
    void                    SetUsedHierarchy(long nNew);
    long                    GetUsedHierarchy() const { return nUsedHierarchy; }
    void                    SetLayoutName(const String* pName);
    const String&           GetLayoutName() const;
    BOOL                    HasLayoutName() const;
    void                    ResetLayoutName();

    const ::com::sun::star::sheet::DataPilotFieldReference* GetReferenceValue() const   { return pReferenceValue; }
    void                    SetReferenceValue(const ::com::sun::star::sheet::DataPilotFieldReference* pNew);

    const ::com::sun::star::sheet::DataPilotFieldSortInfo* GetSortInfo() const          { return pSortInfo; }
    void                    SetSortInfo(const ::com::sun::star::sheet::DataPilotFieldSortInfo* pNew);
    const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo* GetAutoShowInfo() const  { return pAutoShowInfo; }
    void                    SetAutoShowInfo(const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo* pNew);
    const ::com::sun::star::sheet::DataPilotFieldLayoutInfo* GetLayoutInfo() const      { return pLayoutInfo; }
    void                    SetLayoutInfo(const ::com::sun::star::sheet::DataPilotFieldLayoutInfo* pNew);

    void                    SetCurrentPage( const String* pPage );      // NULL = no selection (all)
    BOOL                    HasCurrentPage() const;
    const String&           GetCurrentPage() const;

    USHORT                  GetOrientation() const  { return nOrientation; }

    ScDPSaveMember*         GetExistingMemberByName(const String& rName);
    ScDPSaveMember*         GetMemberByName(const String& rName);

    void                    WriteToSource( const com::sun::star::uno::Reference<
                                            com::sun::star::uno::XInterface>& xDim );

    void                    Store( SvStream& rStream ) const;
};

class ScDPSaveData
{
private:
    List        aDimList;
    ScDPDimensionSaveData* pDimensionData;      // settings that create new dimensions
    USHORT      nColumnGrandMode;
    USHORT      nRowGrandMode;
    USHORT      nIgnoreEmptyMode;
    USHORT      nRepeatEmptyMode;
    BOOL        bFilterButton;      // not passed to DataPilotSource
    BOOL        bDrillDown;         // not passed to DataPilotSource

public:
                            ScDPSaveData();
                            ScDPSaveData(const ScDPSaveData& r);
                            ~ScDPSaveData();

    ScDPSaveData&           operator= ( const ScDPSaveData& r );

    BOOL                    operator== ( const ScDPSaveData& r ) const;

    const List&             GetDimensions() const { return aDimList; }
    void                    AddDimension(ScDPSaveDimension* pDim) { aDimList.Insert(pDim, LIST_APPEND); }

    ScDPSaveDimension*      GetDimensionByName(const String& rName);
    ScDPSaveDimension*      GetDataLayoutDimension();

    ScDPSaveDimension*      DuplicateDimension(const String& rName);
    ScDPSaveDimension&      DuplicateDimension(const ScDPSaveDimension& rDim);

    SC_DLLPUBLIC ScDPSaveDimension*     GetExistingDimensionByName(const String& rName);
    ScDPSaveDimension*      GetNewDimensionByName(const String& rName);

    void                    RemoveDimensionByName(const String& rName);

    ScDPSaveDimension*      GetInnermostDimension(USHORT nOrientation);
    long                    GetDataDimensionCount() const;

    void                    SetPosition( ScDPSaveDimension* pDim, long nNew );
    void                    SetColumnGrand( BOOL bSet );
    BOOL                    GetColumnGrand() const { return BOOL(nColumnGrandMode); }
    void                    SetRowGrand( BOOL bSet );
    BOOL                    GetRowGrand() const { return BOOL(nRowGrandMode); }
    void                    SetIgnoreEmptyRows( BOOL bSet );
    BOOL                    GetIgnoreEmptyRows() const { return BOOL(nIgnoreEmptyMode); }
    void                    SetRepeatIfEmpty( BOOL bSet );
    BOOL                    GetRepeatIfEmpty() const { return BOOL(nRepeatEmptyMode); }

    void                    SetFilterButton( BOOL bSet );
    BOOL                    GetFilterButton() const { return bFilterButton; }
    void                    SetDrillDown( BOOL bSet );
    BOOL                    GetDrillDown() const { return bDrillDown; }

    void                    WriteToSource( const com::sun::star::uno::Reference<
                                            com::sun::star::sheet::XDimensionsSupplier>& xSource );

    void                    Store( SvStream& rStream ) const;
    void                    Load( SvStream& rStream );

    BOOL                    IsEmpty() const;

    const ScDPDimensionSaveData* GetExistingDimensionData() const   { return pDimensionData; }
    ScDPDimensionSaveData*  GetDimensionData();     // create if not there
    void                    SetDimensionData( const ScDPDimensionSaveData* pNew );      // copied
};

#endif

<|endoftext|>


<commit_before>#pragma once

#include "Tag.hpp"
#include "../Expression.hpp"
#include "../Exception.hpp"

namespace liquidpp
{

struct UnevaluatedTag : public Tag {
   UnevaluatedTag() = default;

   UnevaluatedTag(string_view data)
   {
      data.remove_prefix(data[2] == '-' ? 3 : 2);
      if (data.size() < 3)
         throw Exception("Tag is too short!", data);
      data.remove_suffix(data[data.size() - 3] == '-' ? 3 : 2);

      auto tokens = Expression::splitTokens(data);
      if (tokens.empty())
         throw Exception("Tag definition without tag name!", data);
      name = tokens[0];
      if (tokens.size() > 1)
      {
         const char* start = &tokens[1].front();
         const char* end = &*tokens.back().end();
         size_t len = end - start;
         value = string_view{start, len};
      }
      else
         value = data.substr(data.size()-1, 0);
   }

   void render(Context& context, std::string& out) const override final {
   }
};

};
<commit_msg>Don't dereference result of string_view::end()<commit_after>#pragma once

#include "Tag.hpp"
#include "../Expression.hpp"
#include "../Exception.hpp"

namespace liquidpp
{

struct UnevaluatedTag : public Tag {
   UnevaluatedTag() = default;

   UnevaluatedTag(string_view data)
   {
      data.remove_prefix(data[2] == '-' ? 3 : 2);
      if (data.size() < 3)
         throw Exception("Tag is too short!", data);
      data.remove_suffix(data[data.size() - 3] == '-' ? 3 : 2);

      auto tokens = Expression::splitTokens(data);
      if (tokens.empty())
         throw Exception("Tag definition without tag name!", data);
      name = tokens[0];
      if (tokens.size() > 1)
      {
         const char* start = tokens[1].data();
         const char* end = tokens.back().data() + tokens.back().size();
         size_t len = end - start;
         value = string_view{start, len};
      }
      else
         value = data.substr(data.size()-1, 0);
   }

   void render(Context& context, std::string& out) const override final {
   }
};

};
<|endoftext|>


<commit_before>#include <signal.h>
#include <functional>
#include <sstream>
#include <unordered_map>
#include "jsoncpp/json.h"
#include "Util/util.h"
#include "Util/logger.h"
#include "Util/onceToken.h"
#include "Util/NoticeCenter.h"
#include "Util/SqlPool.h"
#include "Common/config.h"
#include "Common/MediaSource.h"
#include "Http/HttpRequester.h"
#include "Http/HttpSession.h"
#include "Network/TcpServer.h"
#include "Player/PlayerProxy.h"

using namespace Json;
using namespace toolkit;
using namespace mediakit;

typedef map<string,variant,StrCaseCompare> ApiArgsType;

#define API_ARGS HttpSession::KeyValue &headerIn, \
                 HttpSession::KeyValue &headerOut, \
                 ApiArgsType &allArgs, \
                 Json::Value &val

#define API_REGIST(field, name, ...) \
    s_map_api.emplace("/index/"#field"/"#name,[](API_ARGS,const HttpSession::HttpResponseInvoker &invoker){ \
         static auto lam = [&](API_ARGS) __VA_ARGS__ ;  \
         lam(headerIn, headerOut, allArgs, val); \
         invoker("200 OK", headerOut, val.toStyledString()); \
     });

#define API_REGIST_INVOKER(field, name, ...) \
    s_map_api.emplace("/index/"#field"/"#name,[](API_ARGS,const HttpSession::HttpResponseInvoker &invoker) __VA_ARGS__);

//异步http api lambad定义
typedef std::function<void(API_ARGS,const HttpSession::HttpResponseInvoker &invoker)> AsyncHttpApi;
//api列表
static map<string, AsyncHttpApi> s_map_api;

namespace API {
typedef enum {
    SqlFailed = -200,
    AuthFailed = -100,
    OtherFailed = -1,
    Success = 0
} ApiErr;

#define API_FIELD "api."
const char kApiDebug[] = API_FIELD"apiDebug";
static onceToken token([]() {
    mINI::Instance()[kApiDebug] = "1";
});
}//namespace API

class ApiRetException: public std::runtime_error {
public:
    ApiRetException(const char *str = "success" ,int code = API::Success):runtime_error(str){
        _code = code;
    }
    ~ApiRetException() = default;
    int code(){ return _code; }
private:
    int _code;
};

class AuthException : public ApiRetException {
public:
    AuthException(const char *str):ApiRetException(str,API::AuthFailed){}
    ~AuthException() = default;
};

//获取HTTP请求中url参数、content参数
static ApiArgsType getAllArgs(const Parser &parser) {
    ApiArgsType allArgs;
    if(parser["Content-Type"].find("application/x-www-form-urlencoded") == 0){
        auto contentArgs = parser.parseArgs(parser.Content());
        for (auto &pr : contentArgs) {
            allArgs[pr.first] = HttpSession::urlDecode(pr.second);
        }
    }else if(parser["Content-Type"].find("application/json") == 0){
        try {
            stringstream ss(parser.Content());
            Value jsonArgs;
            ss >> jsonArgs;
            auto keys = jsonArgs.getMemberNames();
            for (auto key = keys.begin(); key != keys.end(); ++key){
                allArgs[*key] = jsonArgs[*key].asString();
            }
        }catch (std::exception &ex){
            WarnL << ex.what();
        }
    }else if(!parser["Content-Type"].empty()){
        WarnL << "invalid Content-Type:" << parser["Content-Type"];
    }

    auto &urlArgs = parser.getUrlArgs();
    for (auto &pr : urlArgs) {
        allArgs[pr.first] = HttpSession::urlDecode(pr.second);
    }
    return std::move(allArgs);
}

static inline void addHttpListener(){
    GET_CONFIG_AND_REGISTER(bool, api_debug, API::kApiDebug);
    //注册监听kBroadcastHttpRequest事件
    NoticeCenter::Instance().addListener(nullptr, Broadcast::kBroadcastHttpRequest, [](BroadcastHttpRequestArgs) {
        auto it = s_map_api.find(parser.Url());
        if (it == s_map_api.end()) {
            consumed = false;
            return;
        }
        //该api已被消费
        consumed = true;
        AsyncHttpApi api = it->second;
        //异步执行该api，防止阻塞NoticeCenter
        EventPollerPool::Instance().getExecutor()->async([api, parser, invoker]() {
            //执行API
            Json::Value val;
            val["code"] = API::Success;
            HttpSession::KeyValue &headerIn = parser.getValues();
            HttpSession::KeyValue headerOut;
            auto allArgs = getAllArgs(parser);
            headerOut["Content-Type"] = "application/json; charset=utf-8";
            if(api_debug){
                auto newInvoker = [invoker,parser,allArgs](const string &codeOut,
                                                           const HttpSession::KeyValue &headerOut,
                                                           const string &contentOut){
                    stringstream ss;
                    for(auto &pr : allArgs ){
                        ss << pr.first << " : " << (string)pr.second << "\r\n";
                    }

                    DebugL << "\r\n# request:\r\n" << parser.Method() << " " << parser.FullUrl() << "\r\n"
                           << "# content:\r\n" << parser.Content() << "\r\n"
                           << "# args:\r\n" << ss.str()
                           << "# response:\r\n"
                           << contentOut << "\r\n";

                    invoker(codeOut,headerOut,contentOut);
                };
                ((HttpSession::HttpResponseInvoker &)invoker) = newInvoker;
            }

            try {
                api(headerIn, headerOut, allArgs, val, invoker);
            } catch(AuthException &ex){
                val["code"] = API::AuthFailed;
                val["msg"] = ex.what();
                invoker("200 OK", headerOut, val.toStyledString());
            } catch(ApiRetException &ex){
                val["code"] = ex.code();
                val["msg"] = ex.what();
                invoker("200 OK", headerOut, val.toStyledString());
            } catch(SqlException &ex){
                val["code"] = API::SqlFailed;
                val["msg"] = StrPrinter << "操作数据库失败:" << ex.what() << ":" << ex.getSql();
                WarnL << ex.what() << ":" << ex.getSql();
                invoker("200 OK", headerOut, val.toStyledString());
            } catch (std::exception &ex) {
                val["code"] = API::OtherFailed;
                val["msg"] = ex.what();
                invoker("200 OK", headerOut, val.toStyledString());
            }
        });
    });
}

//安装api接口
void installWebApi() {
    addHttpListener();

    /**
     * 获取线程负载
     */
    API_REGIST_INVOKER(api, getThreadsLoad, {
        EventPollerPool::Instance().getExecutorDelay([invoker, headerOut](const vector<int> &vecDelay) {
            Value val;
            auto vec = EventPollerPool::Instance().getExecutorLoad();
            int i = 0;
            for (auto load : vec) {
                Value obj(objectValue);
                obj["load"] = load;
                obj["delay"] = vecDelay[i++];
                val["data"].append(obj);
            }
            invoker("200 OK", headerOut, val.toStyledString());
        });
    });

    /**
     * 获取服务器配置
     */
    API_REGIST(api, getServerConfig, {
        Value obj;
        for (auto &pr : mINI::Instance()) {
            obj[pr.first] = (string &) pr.second;
        }
        val["data"].append(obj);
    });

    /**
     * 设置服务器配置
     */
    API_REGIST(api, setServerConfig, {
        auto &ini = mINI::Instance();
        int changed = 0;
        for (auto &pr : allArgs) {
            if (ini.find(pr.first) == ini.end()) {
                //没有这个key
                continue;
            }
            if (ini[pr.first] == pr.second) {
                continue;
            }
            ini[pr.first] = pr.second;
            //替换成功
            ++changed;
        }
        if (changed > 0) {
            NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastReloadConfig);
            ini.dumpFile();
        }
        val["changed"] = changed;
    });

    /**
     * 获取服务器api列表
     */
    API_REGIST(api,getApiList,{
        for(auto &pr : s_map_api){
            val["data"].append(pr.first);
        }
    });

    /**
     * 重启服务器
     */
    API_REGIST(api,restartServer,{
        EventPollerPool::Instance().getPoller()->doDelayTask(1000,[](){
            //尝试正常退出
            ::kill(getpid(), SIGINT);

            //3秒后强制退出
            EventPollerPool::Instance().getPoller()->doDelayTask(3000,[](){
                exit(0);
                return 0;
            });

            return 0;
        });
        val["msg"] = "服务器将在一秒后自动重启";
    });

    API_REGIST(api,getMediaList,{
        //获取所有MediaSource列表
        val["code"] = 0;
        val["msg"] = "success";
        MediaSource::for_each_media([&](const string &schema,
                                        const string &vhost,
                                        const string &app,
                                        const string &stream,
                                        const MediaSource::Ptr &media){
            if(!allArgs["schema"].empty() && allArgs["schema"] != schema){
                return;
            }
            if(!allArgs["vhost"].empty() && allArgs["vhost"] != vhost){
                return;
            }
            if(!allArgs["app"].empty() && allArgs["app"] != app){
                return;
            }
            Value item;
            item["schema"] = schema;
            item["vhost"] = vhost;
            item["app"] = app;
            item["stream"] = stream;
            val["data"].append(item);
        });
    });

    API_REGIST(api,kick_pusher,{
        //踢掉推流器
        auto src = MediaSource::find(allArgs["schema"],
                                     allArgs["vhost"],
                                     allArgs["app"],
                                     allArgs["stream"]);
        if(src){
            bool flag = src->close();
            val["code"] = flag ? 0 : -1;
            val["msg"] = flag ? "success" : "kick failed";
        }else{
            val["code"] = -2;
            val["msg"] = "can not find the pusher";
        }
    });

    API_REGIST(api,kick_session,{
        //踢掉tcp会话
        auto id = allArgs["id"];
        if(id.empty()){
            val["code"] = -1;
            val["msg"] = "illegal parameter:id";
            return;
        }
        auto session = SessionMap::Instance().get(id);
        if(!session){
            val["code"] = -2;
            val["msg"] = "can not find the target";
            return;
        }
        session->safeShutdown();
        val["code"] = 0;
        val["msg"] = "success";
    });

    static unordered_map<uint64_t ,PlayerProxy::Ptr> s_proxyMap;
    static recursive_mutex s_proxyMapMtx;
    API_REGIST(api,addStreamProxy,{
        //添加拉流代理
        PlayerProxy::Ptr player(new PlayerProxy(
                allArgs["vhost"],
                allArgs["app"],
                allArgs["stream"],
                allArgs["enable_hls"],
                allArgs["enable_mp4"]
        ));
        //指定RTP over TCP(播放rtsp时有效)
        (*player)[kRtpType] = allArgs["rtp_type"].as<int>();
        //开始播放，如果播放失败或者播放中止，将会自动重试若干次，重试次数在配置文件中配置，默认一直重试
        player->play(allArgs["url"]);

        val["data"]["id"] = player.get();
        lock_guard<recursive_mutex> lck(s_proxyMapMtx);
        s_proxyMap[(uint64_t)player.get()] = player;
    });

    API_REGIST(api,delStreamProxy,{
        lock_guard<recursive_mutex> lck(s_proxyMapMtx);
        val["data"]["flag"] = s_proxyMap.erase(allArgs["id"].as<uint64_t>()) == 1;
    });

    ////////////以下是注册的Hook API////////////
    API_REGIST(hook,on_publish,{
        //开始推流事件
        val["code"] = 0;
        val["msg"] = "success";
    });

    API_REGIST(hook,on_play,{
        //开始播放事件
        val["code"] = 0;
        val["msg"] = "success";
    });

    API_REGIST(hook,on_flow_report,{
        //流量统计hook api
        val["code"] = 0;
        val["msg"] = "success";
    });

    API_REGIST(hook,on_rtsp_realm,{
        //rtsp是否需要鉴权
        val["code"] = 0;
        val["realm"] = "zlmediakit_reaml";
    });

    API_REGIST(hook,on_rtsp_auth,{
        //rtsp鉴权密码，密码等于用户名
        //rtsp可以有双重鉴权！后面还会触发on_play事件
        val["code"] = 0;
        val["encrypted"] = false;
        val["passwd"] = allArgs["user_name"];
    });

    API_REGIST(hook,on_stream_changed,{
        //媒体注册或反注册事件
        val["code"] = 0;
        val["msg"] = "success";
    });

    API_REGIST(hook,on_stream_not_found,{
        //媒体未找到事件
        val["code"] = 0;
        val["msg"] = "success";
    });

    API_REGIST(hook,on_record_mp4,{
        //录制mp4分片完毕事件
        val["code"] = 0;
        val["msg"] = "success";
    });

}<commit_msg>修复variant无法转换成json的bug<commit_after>#include <signal.h>
#include <functional>
#include <sstream>
#include <unordered_map>
#include "jsoncpp/json.h"
#include "Util/util.h"
#include "Util/logger.h"
#include "Util/onceToken.h"
#include "Util/NoticeCenter.h"
#include "Util/SqlPool.h"
#include "Common/config.h"
#include "Common/MediaSource.h"
#include "Http/HttpRequester.h"
#include "Http/HttpSession.h"
#include "Network/TcpServer.h"
#include "Player/PlayerProxy.h"

using namespace Json;
using namespace toolkit;
using namespace mediakit;

typedef map<string,variant,StrCaseCompare> ApiArgsType;

#define API_ARGS HttpSession::KeyValue &headerIn, \
                 HttpSession::KeyValue &headerOut, \
                 ApiArgsType &allArgs, \
                 Json::Value &val

#define API_REGIST(field, name, ...) \
    s_map_api.emplace("/index/"#field"/"#name,[](API_ARGS,const HttpSession::HttpResponseInvoker &invoker){ \
         static auto lam = [&](API_ARGS) __VA_ARGS__ ;  \
         lam(headerIn, headerOut, allArgs, val); \
         invoker("200 OK", headerOut, val.toStyledString()); \
     });

#define API_REGIST_INVOKER(field, name, ...) \
    s_map_api.emplace("/index/"#field"/"#name,[](API_ARGS,const HttpSession::HttpResponseInvoker &invoker) __VA_ARGS__);

//异步http api lambad定义
typedef std::function<void(API_ARGS,const HttpSession::HttpResponseInvoker &invoker)> AsyncHttpApi;
//api列表
static map<string, AsyncHttpApi> s_map_api;

namespace API {
typedef enum {
    SqlFailed = -200,
    AuthFailed = -100,
    OtherFailed = -1,
    Success = 0
} ApiErr;

#define API_FIELD "api."
const char kApiDebug[] = API_FIELD"apiDebug";
static onceToken token([]() {
    mINI::Instance()[kApiDebug] = "1";
});
}//namespace API

class ApiRetException: public std::runtime_error {
public:
    ApiRetException(const char *str = "success" ,int code = API::Success):runtime_error(str){
        _code = code;
    }
    ~ApiRetException() = default;
    int code(){ return _code; }
private:
    int _code;
};

class AuthException : public ApiRetException {
public:
    AuthException(const char *str):ApiRetException(str,API::AuthFailed){}
    ~AuthException() = default;
};

//获取HTTP请求中url参数、content参数
static ApiArgsType getAllArgs(const Parser &parser) {
    ApiArgsType allArgs;
    if(parser["Content-Type"].find("application/x-www-form-urlencoded") == 0){
        auto contentArgs = parser.parseArgs(parser.Content());
        for (auto &pr : contentArgs) {
            allArgs[pr.first] = HttpSession::urlDecode(pr.second);
        }
    }else if(parser["Content-Type"].find("application/json") == 0){
        try {
            stringstream ss(parser.Content());
            Value jsonArgs;
            ss >> jsonArgs;
            auto keys = jsonArgs.getMemberNames();
            for (auto key = keys.begin(); key != keys.end(); ++key){
                allArgs[*key] = jsonArgs[*key].asString();
            }
        }catch (std::exception &ex){
            WarnL << ex.what();
        }
    }else if(!parser["Content-Type"].empty()){
        WarnL << "invalid Content-Type:" << parser["Content-Type"];
    }

    auto &urlArgs = parser.getUrlArgs();
    for (auto &pr : urlArgs) {
        allArgs[pr.first] = HttpSession::urlDecode(pr.second);
    }
    return std::move(allArgs);
}

static inline void addHttpListener(){
    GET_CONFIG_AND_REGISTER(bool, api_debug, API::kApiDebug);
    //注册监听kBroadcastHttpRequest事件
    NoticeCenter::Instance().addListener(nullptr, Broadcast::kBroadcastHttpRequest, [](BroadcastHttpRequestArgs) {
        auto it = s_map_api.find(parser.Url());
        if (it == s_map_api.end()) {
            consumed = false;
            return;
        }
        //该api已被消费
        consumed = true;
        AsyncHttpApi api = it->second;
        //异步执行该api，防止阻塞NoticeCenter
        EventPollerPool::Instance().getExecutor()->async([api, parser, invoker]() {
            //执行API
            Json::Value val;
            val["code"] = API::Success;
            HttpSession::KeyValue &headerIn = parser.getValues();
            HttpSession::KeyValue headerOut;
            auto allArgs = getAllArgs(parser);
            headerOut["Content-Type"] = "application/json; charset=utf-8";
            if(api_debug){
                auto newInvoker = [invoker,parser,allArgs](const string &codeOut,
                                                           const HttpSession::KeyValue &headerOut,
                                                           const string &contentOut){
                    stringstream ss;
                    for(auto &pr : allArgs ){
                        ss << pr.first << " : " << pr.second << "\r\n";
                    }

                    DebugL << "\r\n# request:\r\n" << parser.Method() << " " << parser.FullUrl() << "\r\n"
                           << "# content:\r\n" << parser.Content() << "\r\n"
                           << "# args:\r\n" << ss.str()
                           << "# response:\r\n"
                           << contentOut << "\r\n";

                    invoker(codeOut,headerOut,contentOut);
                };
                ((HttpSession::HttpResponseInvoker &)invoker) = newInvoker;
            }

            try {
                api(headerIn, headerOut, allArgs, val, invoker);
            } catch(AuthException &ex){
                val["code"] = API::AuthFailed;
                val["msg"] = ex.what();
                invoker("200 OK", headerOut, val.toStyledString());
            } catch(ApiRetException &ex){
                val["code"] = ex.code();
                val["msg"] = ex.what();
                invoker("200 OK", headerOut, val.toStyledString());
            } catch(SqlException &ex){
                val["code"] = API::SqlFailed;
                val["msg"] = StrPrinter << "操作数据库失败:" << ex.what() << ":" << ex.getSql();
                WarnL << ex.what() << ":" << ex.getSql();
                invoker("200 OK", headerOut, val.toStyledString());
            } catch (std::exception &ex) {
                val["code"] = API::OtherFailed;
                val["msg"] = ex.what();
                invoker("200 OK", headerOut, val.toStyledString());
            }
        });
    });
}

//安装api接口
void installWebApi() {
    addHttpListener();

    /**
     * 获取线程负载
     */
    API_REGIST_INVOKER(api, getThreadsLoad, {
        EventPollerPool::Instance().getExecutorDelay([invoker, headerOut](const vector<int> &vecDelay) {
            Value val;
            auto vec = EventPollerPool::Instance().getExecutorLoad();
            int i = 0;
            for (auto load : vec) {
                Value obj(objectValue);
                obj["load"] = load;
                obj["delay"] = vecDelay[i++];
                val["data"].append(obj);
            }
            invoker("200 OK", headerOut, val.toStyledString());
        });
    });

    /**
     * 获取服务器配置
     */
    API_REGIST(api, getServerConfig, {
        Value obj;
        for (auto &pr : mINI::Instance()) {
            obj[pr.first] = (string &) pr.second;
        }
        val["data"].append(obj);
    });

    /**
     * 设置服务器配置
     */
    API_REGIST(api, setServerConfig, {
        auto &ini = mINI::Instance();
        int changed = 0;
        for (auto &pr : allArgs) {
            if (ini.find(pr.first) == ini.end()) {
                //没有这个key
                continue;
            }
            if (ini[pr.first] == pr.second) {
                continue;
            }
            ini[pr.first] = pr.second;
            //替换成功
            ++changed;
        }
        if (changed > 0) {
            NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastReloadConfig);
            ini.dumpFile();
        }
        val["changed"] = changed;
    });

    /**
     * 获取服务器api列表
     */
    API_REGIST(api,getApiList,{
        for(auto &pr : s_map_api){
            val["data"].append(pr.first);
        }
    });

    /**
     * 重启服务器
     */
    API_REGIST(api,restartServer,{
        EventPollerPool::Instance().getPoller()->doDelayTask(1000,[](){
            //尝试正常退出
            ::kill(getpid(), SIGINT);

            //3秒后强制退出
            EventPollerPool::Instance().getPoller()->doDelayTask(3000,[](){
                exit(0);
                return 0;
            });

            return 0;
        });
        val["msg"] = "服务器将在一秒后自动重启";
    });

    API_REGIST(api,getMediaList,{
        //获取所有MediaSource列表
        val["code"] = 0;
        val["msg"] = "success";
        MediaSource::for_each_media([&](const string &schema,
                                        const string &vhost,
                                        const string &app,
                                        const string &stream,
                                        const MediaSource::Ptr &media){
            if(!allArgs["schema"].empty() && allArgs["schema"] != schema){
                return;
            }
            if(!allArgs["vhost"].empty() && allArgs["vhost"] != vhost){
                return;
            }
            if(!allArgs["app"].empty() && allArgs["app"] != app){
                return;
            }
            Value item;
            item["schema"] = schema;
            item["vhost"] = vhost;
            item["app"] = app;
            item["stream"] = stream;
            val["data"].append(item);
        });
    });

    API_REGIST(api,kick_pusher,{
        //踢掉推流器
        auto src = MediaSource::find(allArgs["schema"],
                                     allArgs["vhost"],
                                     allArgs["app"],
                                     allArgs["stream"]);
        if(src){
            bool flag = src->close();
            val["code"] = flag ? 0 : -1;
            val["msg"] = flag ? "success" : "kick failed";
        }else{
            val["code"] = -2;
            val["msg"] = "can not find the pusher";
        }
    });

    API_REGIST(api,kick_session,{
        //踢掉tcp会话
        auto id = allArgs["id"];
        if(id.empty()){
            val["code"] = -1;
            val["msg"] = "illegal parameter:id";
            return;
        }
        auto session = SessionMap::Instance().get(id);
        if(!session){
            val["code"] = -2;
            val["msg"] = "can not find the target";
            return;
        }
        session->safeShutdown();
        val["code"] = 0;
        val["msg"] = "success";
    });

    static unordered_map<uint64_t ,PlayerProxy::Ptr> s_proxyMap;
    static recursive_mutex s_proxyMapMtx;
    API_REGIST(api,addStreamProxy,{
        //添加拉流代理
        PlayerProxy::Ptr player(new PlayerProxy(
                allArgs["vhost"],
                allArgs["app"],
                allArgs["stream"],
                allArgs["enable_hls"],
                allArgs["enable_mp4"]
        ));
        //指定RTP over TCP(播放rtsp时有效)
        (*player)[kRtpType] = allArgs["rtp_type"].as<int>();
        //开始播放，如果播放失败或者播放中止，将会自动重试若干次，重试次数在配置文件中配置，默认一直重试
        player->play(allArgs["url"]);

        val["data"]["id"] = player.get();
        lock_guard<recursive_mutex> lck(s_proxyMapMtx);
        s_proxyMap[(uint64_t)player.get()] = player;
    });

    API_REGIST(api,delStreamProxy,{
        lock_guard<recursive_mutex> lck(s_proxyMapMtx);
        val["data"]["flag"] = s_proxyMap.erase(allArgs["id"].as<uint64_t>()) == 1;
    });

    ////////////以下是注册的Hook API////////////
    API_REGIST(hook,on_publish,{
        //开始推流事件
        val["code"] = 0;
        val["msg"] = "success";
    });

    API_REGIST(hook,on_play,{
        //开始播放事件
        val["code"] = 0;
        val["msg"] = "success";
    });

    API_REGIST(hook,on_flow_report,{
        //流量统计hook api
        val["code"] = 0;
        val["msg"] = "success";
    });

    API_REGIST(hook,on_rtsp_realm,{
        //rtsp是否需要鉴权
        val["code"] = 0;
        val["realm"] = "zlmediakit_reaml";
    });

    API_REGIST(hook,on_rtsp_auth,{
        //rtsp鉴权密码，密码等于用户名
        //rtsp可以有双重鉴权！后面还会触发on_play事件
        val["code"] = 0;
        val["encrypted"] = false;
        val["passwd"] = allArgs["user_name"].data();
    });

    API_REGIST(hook,on_stream_changed,{
        //媒体注册或反注册事件
        val["code"] = 0;
        val["msg"] = "success";
    });

    API_REGIST(hook,on_stream_not_found,{
        //媒体未找到事件
        val["code"] = 0;
        val["msg"] = "success";
    });

    API_REGIST(hook,on_record_mp4,{
        //录制mp4分片完毕事件
        val["code"] = 0;
        val["msg"] = "success";
    });

}<|endoftext|>


<commit_before>#include <getopt.h>
#include <string>
#include <iostream>
#include "gfakluge.hpp"

using namespace std;
using namespace gfak;

void spec_help(char** argv){
    cout << "gfa_spec_convert: convert GFA 0.1 <-> 1.0 <-> 2.0, walks <-> paths, etc." << endl
        << "Usage: " << argv[0] << " [OPTIONS] <GFA_FILE> > gfa_out.gfa" << endl
        << "Options: " << endl
        << "  -w / --walks   Output paths as walks, but maintain version (NOT SPEC COMPLIANT)." << endl
        << "  -p / --paths   Output walks as paths, but maintain version." << endl
        << "  -s / --spec [0.1, 1.0, 2.0]   Convert the input GFA file to specification [0.1, 1.0, or 2.0]." << endl
        << "                                NB: not all GFA specs are backward/forward compatible, so a subset of the GFA may be used." << endl
        << "  -b / --block-order   Output GFA in block order [HSLP / HSLW | HSEFGUO]."
        << endl;
}

int main(int argc, char** argv){
    string gfa_file = "";
    bool block_order = false;
    double spec_version = 0.1;
    bool use_paths = true;

    if (argc < 2){
        spec_help(argv);
        exit(0);
    }

    int c;
    optind = 1;
    while (true){
        static struct option long_options[] =
        {
            {"help", no_argument, 0, 'h'},
            {"block-order", no_argument, 0, 'b'},
            {"gfa-file", required_argument, 0, 'i'},
            {"paths", no_argument, 0, 'p'},
            {"walks", no_argument, 0, 'w'},
            {"spec", required_argument, 0, 's'},
            {0,0,0,0}
        };

        int option_index = 0;
        c = getopt_long(argc, argv, "hbpws:", long_options, &option_index);
        if (c == -1){
            break;
        }

        switch (c){
            case 'i':
                gfa_file = optarg;
                break;

            case '?':
            case 'h':
                spec_help(argv);
                exit(0);

            case 'b':
                block_order = true;
                break;
            case 's':
                spec_version = stod(optarg);
                break;
            case 'w':
                use_paths = false;
                break;
            case 'p':
                use_paths = true;
                break;

            default:
                abort();
        }
    }
    gfa_file = argv[optind];

    GFAKluge gg;
    gg.parse_gfa_file(gfa_file);

    if (use_paths){
        gg.set_version(1.0);
    }
    else{
        gg.set_version(0.1);
        gg.set_walks(true);
    }

    if (spec_version == 0.1){
        gg.set_version(0.1);
    }
    else if (spec_version == 1.0){
        gg.set_version(1.0);
    }
    else if (spec_version == 2.0){
        gg.set_version(2.0);
    }
    else if (spec_version != 0.0){
        cerr << "Invalid specification number: " << spec_version << endl
        << "Please provide one of [0.1, 1.0, 2.0]." << endl;
        exit(22);
    }

    if (block_order){
        cout << gg.block_order_string();
    }
    else{
        cout << gg.to_string();
    }

	return 0;
}
<commit_msg>Fix spec_convert help<commit_after>#include <getopt.h>
#include <string>
#include <iostream>
#include "gfakluge.hpp"

using namespace std;
using namespace gfak;

void spec_help(char** argv){
    cout << "gfa_spec_convert: convert GFA 0.1 <-> 1.0 <-> 2.0, walks <-> paths, etc." << endl
        << "Usage: " << argv[0] << " [OPTIONS] <GFA_FILE> > gfa_out.gfa" << endl
        << "Options: " << endl
        << "  -w / --walks   Output paths as walks, but maintain version (NOT SPEC COMPLIANT)." << endl
        << "  -p / --paths   Output walks as paths, but maintain version." << endl
        << "  -s / --spec [0.1, 1.0, 2.0]   Convert the input GFA file to specification [0.1, 1.0, or 2.0]." << endl
        << "                                NB: not all GFA specs are backward/forward compatible, so a subset of the GFA may be used." << endl
        << "  -b / --block-order   Output GFA in block order [HSLP / HSLW | HSEFGUO]."
        << endl;
}

int main(int argc, char** argv){
    string gfa_file = "";
    bool block_order = false;
    double spec_version = 0.1;
    bool use_paths = true;

    if (argc < 2){
        spec_help(argv);
        exit(0);
    }

    int c;
    optind = 1;
    while (true){
        static struct option long_options[] =
        {
            {"help", no_argument, 0, 'h'},
            {"block-order", no_argument, 0, 'b'},
            {"gfa-file", required_argument, 0, 'i'},
            {"paths", no_argument, 0, 'p'},
            {"walks", no_argument, 0, 'w'},
            {"spec", required_argument, 0, 's'},
            {0,0,0,0}
        };

        int option_index = 0;
        c = getopt_long(argc, argv, "hbpws:", long_options, &option_index);
        if (c == -1){
            break;
        }

        switch (c){
            case 'i':
                gfa_file = optarg;
                break;

            case '?':
            case 'h':
                spec_help(argv);
                exit(0);

            case 'b':
                block_order = true;
                break;
            case 's':
                spec_version = stod(optarg);
                break;
            case 'w':
                use_paths = false;
                break;
            case 'p':
                use_paths = true;
                break;

            default:
                abort();
        }
    }
    gfa_file = argv[optind];

    GFAKluge gg;
    gg.parse_gfa_file(gfa_file);

    gg.set_walks(!use_paths);

    if (spec_version == 0.1){
        gg.set_version(0.1);
    }
    else if (spec_version == 1.0){
        gg.set_version(1.0);
    }
    else if (spec_version == 2.0){
        gg.set_version(2.0);
    }
    else if (spec_version != 0.0){
        cerr << "Invalid specification number: " << spec_version << endl
        << "Please provide one of [0.1, 1.0, 2.0]." << endl;
        exit(22);
    }

    if (block_order){
        cout << gg.block_order_string();
    }
    else{
        cout << gg.to_string();
    }

	return 0;
}
<|endoftext|>


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

#include "ReferenceVariant.hh"
#include <QHash>

namespace clockwork {
/**
 * @see graphics/Mesh.hh.
 */
class Mesh;
/**
 *
 */
class Renderer {
public:
	/**
	 * An enumeration of available line-drawing algorithms.
	 */
	enum class LineDrawingAlgorithm {
		Bresenham,
		XiaolinWu
	};
	/**
	 * An enumeration of available primitives.
	 */
	enum class Primitive {
		Point,
		Line,
		LineStrip,
		LineLoop,
		Triangle,
		TriangleStrip,
		TriangleFan
	};
	/**
	 * An enumeration of available rendering algorithms.
	 */
	enum class RenderingAlgorithm {
		Point,
		Wireframe,
		Random,
		Depth,
		Normals,
		Texture,
		Constant,
		Phong,
		Cel,
		Bump,
		Deferred
	};
	/**
	 * Checks whether T is a valid Uniform value type.
	 */
	template<class T>
	struct UniformValidator :
	std::integral_constant<bool, true> {};
	/**
	 *
	 */
	using Uniform = ReferenceVariant<UniformValidator>;
	/**
	 * Checks whether T is a valid Varying value type.
	 */
	template<class T>
	struct VaryingValidator :
	std::integral_constant<bool, true> {};
	/**
	 *
	 */
	using Varying = ReferenceVariant<VaryingValidator>;
	/**
	 *
	 */
	struct PipelineContext {
		/**
		 * The primitive mode.
		 */
		Primitive primitiveMode;
		/**
		 * The set of uniform variables.
		 */
		QHash<QString, Uniform> uniform;
		/**
		 * The set of varying variables.
		 */
		QHash<QString, Varying> varying;
	};
	/**
	 * Renders the specified mesh in the given state.
	 * @param context the rendering pipeline context.
	 * @param mesh the polygon mesh to render.
	 */
	static void draw(PipelineContext& context, const Mesh& mesh);
};
} // namespace clockwork

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

#include "ReferenceVariant.hh"
#include "Point.hh"
#include "Point3.hh"
#include "Point4.hh"
#include "Vector3.hh"
#include "Vector4.hh"
#include "Matrix4.hh"
#include "ColorARGB.hh"
#include <QHash>

namespace clockwork {
/**
 * @see graphics/Mesh.hh.
 */
class Mesh;
/**
 *
 */
class Renderer {
public:
	/**
	 * An enumeration of available line-drawing algorithms.
	 */
	enum class LineDrawingAlgorithm {
		Bresenham,
		XiaolinWu
	};
	/**
	 * An enumeration of available primitives.
	 */
	enum class Primitive {
		Point,
		Line,
		LineStrip,
		LineLoop,
		Triangle,
		TriangleStrip,
		TriangleFan
	};
	/**
	 * An enumeration of available rendering algorithms.
	 */
	enum class RenderingAlgorithm {
		Point,
		Wireframe,
		Random,
		Depth,
		Normals,
		Texture,
		Constant,
		Phong,
		Cel,
		Bump,
		Deferred
	};
	/**
	 * Checks whether T is a valid Uniform value type.
	 */
	template<class T>
	struct UniformValidator :
	std::integral_constant<bool, true> {};
	/**
	 *
	 */
	using Uniform = ReferenceVariant<UniformValidator>;
	/**
	 * Checks whether T is a valid Varying value type. Varying attributes are
	 * restricted to arithmetic types, as well as Point, Point3, Point4,
	 * Vector3, Vector4, Matrix4 or ColorARGB.
	 */
	template<class T>
	struct VaryingValidator :
	std::integral_constant<bool,
		std::is_arithmetic<T>::value ||
		std::is_base_of<Point, T>::value ||
		std::is_base_of<Point3, T>::value ||
		std::is_base_of<Point4, T>::value ||
		std::is_base_of<Vector3, T>::value ||
		std::is_base_of<math::Vector4i, T>::value ||
		std::is_base_of<math::Vector4u, T>::value ||
		std::is_base_of<math::Vector4f, T>::value ||
		std::is_base_of<math::Vector4d, T>::value ||
		std::is_base_of<Matrix4, T>::value ||
		std::is_base_of<ColorARGB, T>::value> {};
	/**
	 *
	 */
	using Varying = ReferenceVariant<VaryingValidator>;
	/**
	 *
	 */
	struct PipelineContext {
		/**
		 * The primitive mode.
		 */
		Primitive primitiveMode;
		/**
		 * The set of uniform variables.
		 */
		QHash<QString, Uniform> uniform;
		/**
		 * The set of varying variables.
		 */
		QHash<QString, Varying> varying;
	};
	/**
	 * Renders the specified mesh in the given state.
	 * @param context the rendering pipeline context.
	 * @param mesh the polygon mesh to render.
	 */
	static void draw(PipelineContext& context, const Mesh& mesh);
};
} // namespace clockwork

#endif // CLOCKWORK_RENDERER_HH
<|endoftext|>


<commit_before>#include "haxor/hc/node/all.hh"
#include "haxor/hc/compiler.hh"
#include "haxor/hc/pseudo.hh"
#include "haxor/common/hdr.hh"
#include "haxor/common/opcode.hh"
#include <sstream>
#include <vector>
#include <algorithm>
#include <fstream>
#include <stdexcept>

namespace haxor {
  compiler::compiler() : lexer(*this), parser(lexer, *this) {
  }

  void compiler::verify_code() {
    for (auto *item : *ast) {
      if (item->is_a(node::type::instr)) {
        auto *instr = dynamic_cast<node::instr*>(item);

        auto it = instr_list.find(instr->get_name());

        if (it != instr_list.end()) {
          if (instr->get_args()->size() != it->second.args.size()) {
            throw std::runtime_error("Invalid number of arguments.");
          }

          for (size_t i = 0; i < it->second.args.size(); i++) {
            if (it->second.args[i] == 'r') {
              if (!instr->get_args()->at(i)->is_a(node::type::reg)) {
                throw std::runtime_error("Invalid argument, expected register.");
              }
            } else if (it->second.args[i] == 'i') {
              if (!instr->get_args()->at(i)->is_a(node::type::num) && !instr->get_args()->at(i)->is_a(node::type::label)) {
                throw std::runtime_error("Invalid argument, expected number or label.");
              }
            }
          }
        } else {
          std::string error_msg = "Unknown instruction '" + instr->get_name() + "'";
          if (instr->has_location()) {
            error_msg += ", at location " + format_location(instr->get_location());
          }
          throw hc_syntax_error(error_msg); // set correct exception type
        }
      }
    }
  }

  void compiler::unwind_pseudo() {
    pseudo pseudo;
    pseudo.process(ast);
    delete ast;
    ast = pseudo.get_ast();
  }

  void compiler::mark_sections() {
    std::string current_section = ".text";
    for (auto *item : *ast) {
      if (item->get_type() == node::type::section) {
        current_section = dynamic_cast<node::section*>(item)->get_name();
      }
      item->set_section(current_section);
    }
  }

  void compiler::order_sections() {
    std::vector<std::string> sections = { ".text", ".data" };
    for (auto *item : *ast) {
      if (item->get_section() == ".bss") {
        continue;
      }

      if (std::find(sections.begin(), sections.end(), item->get_section()) == sections.end()) {
        sections.push_back(item->get_section());
      }
    }
    sections.push_back(".bss"); // bss must be always last one

    auto *sorted = new std::vector<node::base*>();
    for (auto section : sections) {
      std::copy_if(
        ast->begin(), ast->end(), std::back_inserter(*sorted),
        [section](node::base *n) {
          return n->get_section() == section;
        }
      );
    }
    delete ast;
    ast = sorted;
  }

  void compiler::calc_addresses() {
    int64_t current_address = ivt_size;

    for (auto *item : *ast) {
      item->set_addr(current_address);
      current_address += item->get_size();
    }
  }

  void compiler::collect_labels() {
    labels.clear();
    for (auto *item : *ast) {
      if (item->is_a(node::type::label)) {
        auto *label = dynamic_cast<node::label*>(item);
        labels.insert(std::make_pair(label->get_name(), label->get_addr()));
      }
    }
  }

  int64_t compiler::calc_bss_size() {
    int64_t bss_size = 0;
    for (auto *item : *ast) {
      if (item->get_section() == ".bss") {
        bss_size += item->get_size();
      }
    }

    return bss_size;
  }

  hdr_t compiler::build_hdr() {
    hdr_t hdr;
    hdr.magic = magic;
    hdr.version = version;

    if (labels.find("main") == labels.end()) {
      throw hc_missing_entry_point();
    }

    hdr.entry_point = labels.at("main");
    hdr.stack_size = 4096 * sizeof(word_t); // @TODO add option to customize
    hdr.bss_size = calc_bss_size();

    return hdr;
  }

  std::string& compiler::get_filename() {
    return filename;
  }

  void compiler::compile(const std::string &filename) {
    this->filename = filename;

    std::ifstream source;
    source.open(filename);

    if (source.fail()) {
      throw std::runtime_error("Cannot open source file: " + filename + ".");
    }

    lexer.set_stream(source);

    parser.parse();

    verify_code();
    unwind_pseudo();
    mark_sections();
    order_sections();
    calc_addresses();
    collect_labels();

    auto hdr = build_hdr();

    // compile
    std::fstream haxe;
    haxe.open(filename + ".e", std::ios::binary | std::fstream::out);
    haxe.write(reinterpret_cast<char*>(&hdr), sizeof(hdr));

    for (auto item : *ast) {
      if (item->get_section() == ".bss") {
        continue;
      }

      if (item->is_a(node::type::instr)) {
        node::instr *instr = dynamic_cast<node::instr*>(item);
        opcode_t opcode;
        opcode.cmd = instr_list.at(instr->get_name()).cmd;

        int reg_no = 1;
        for (auto arg : *instr->get_args()) {
          if (arg->is_a(node::type::reg)) {
            auto reg = resolve_reg(dynamic_cast<node::reg*>(arg)->get_name());

            opcode.set_reg(reg_no, reg);
            reg_no ++;
          } else if (arg->is_a(node::type::num)) {
            opcode.imm = dynamic_cast<node::num*>(arg)->get_value();
          } else if (arg->get_type() == node::type::label) {
            word_t imm = labels.at(dynamic_cast<node::label*>(arg)->get_name());

             if (instr_list.at(instr->get_name()).rel) {
               imm -= (item->get_addr() + sizeof(word_t));
             }

             if (instr_list.at(instr->get_name()).x8) {
               imm /= sizeof(word_t);
             }

             opcode.imm = imm;
           } else {
             std::cout << "fail" << std::endl;
           }
         }

         auto value = encode_opcode(opcode);
         haxe.write(reinterpret_cast<char*>(&value), sizeof(value));
      } else if (item->is_a(node::type::num)) {
        word_t value = dynamic_cast<node::num*>(item)->get_value();
        haxe.write(reinterpret_cast<char*>(&value), item->get_size());
      }
    }
  }

  uint8_t compiler::resolve_reg(const std::string &name) {
    auto item = reg_aliases.find(name);

    if (item != reg_aliases.end()) {
      return item->second;
    } else {
      return std::stoi(name.substr(1, std::string::npos));
    }

    // @TODO validation
  }

  void compiler::set_ast(std::vector<node::base*> *ast) {
    this->ast = ast;
  }

  std::string compiler::format_location(const class location &location) {
    std::stringstream ss;
    ss << location;
    return ss.str();
  }
}
<commit_msg>use const to make this code block more readable<commit_after>#include "haxor/hc/node/all.hh"
#include "haxor/hc/compiler.hh"
#include "haxor/hc/pseudo.hh"
#include "haxor/common/hdr.hh"
#include "haxor/common/opcode.hh"
#include <sstream>
#include <vector>
#include <algorithm>
#include <fstream>
#include <stdexcept>

namespace haxor {
  compiler::compiler() : lexer(*this), parser(lexer, *this) {
  }

  void compiler::verify_code() {
    for (auto *item : *ast) {
      if (item->is_a(node::type::instr)) {
        auto *instr = dynamic_cast<node::instr*>(item);

        auto it = instr_list.find(instr->get_name());

        if (it != instr_list.end()) {
          auto const &instr_def = it->second;

          if (instr->get_args()->size() != instr_def.args.size()) {
            throw std::runtime_error("Invalid number of arguments.");
          }

          for (size_t i = 0; i < instr_def.args.size(); i++) {
            if (instr_def.args[i] == 'r') {
              if (!instr->get_args()->at(i)->is_a(node::type::reg)) {
                throw std::runtime_error("Invalid argument, expected register.");
              }
            } else if (instr_def.args[i] == 'i') {
              if (!instr->get_args()->at(i)->is_a(node::type::num) && !instr->get_args()->at(i)->is_a(node::type::label)) {
                throw std::runtime_error("Invalid argument, expected number or label.");
              }
            }
          }
        } else {
          std::string error_msg = "Unknown instruction '" + instr->get_name() + "'";
          if (instr->has_location()) {
            error_msg += ", at location " + format_location(instr->get_location());
          }
          throw hc_syntax_error(error_msg); // set correct exception type
        }
      }
    }
  }

  void compiler::unwind_pseudo() {
    pseudo pseudo;
    pseudo.process(ast);
    delete ast;
    ast = pseudo.get_ast();
  }

  void compiler::mark_sections() {
    std::string current_section = ".text";
    for (auto *item : *ast) {
      if (item->get_type() == node::type::section) {
        current_section = dynamic_cast<node::section*>(item)->get_name();
      }
      item->set_section(current_section);
    }
  }

  void compiler::order_sections() {
    std::vector<std::string> sections = { ".text", ".data" };
    for (auto *item : *ast) {
      if (item->get_section() == ".bss") {
        continue;
      }

      if (std::find(sections.begin(), sections.end(), item->get_section()) == sections.end()) {
        sections.push_back(item->get_section());
      }
    }
    sections.push_back(".bss"); // bss must be always last one

    auto *sorted = new std::vector<node::base*>();
    for (auto section : sections) {
      std::copy_if(
        ast->begin(), ast->end(), std::back_inserter(*sorted),
        [section](node::base *n) {
          return n->get_section() == section;
        }
      );
    }
    delete ast;
    ast = sorted;
  }

  void compiler::calc_addresses() {
    int64_t current_address = ivt_size;

    for (auto *item : *ast) {
      item->set_addr(current_address);
      current_address += item->get_size();
    }
  }

  void compiler::collect_labels() {
    labels.clear();
    for (auto *item : *ast) {
      if (item->is_a(node::type::label)) {
        auto *label = dynamic_cast<node::label*>(item);
        labels.insert(std::make_pair(label->get_name(), label->get_addr()));
      }
    }
  }

  int64_t compiler::calc_bss_size() {
    int64_t bss_size = 0;
    for (auto *item : *ast) {
      if (item->get_section() == ".bss") {
        bss_size += item->get_size();
      }
    }

    return bss_size;
  }

  hdr_t compiler::build_hdr() {
    hdr_t hdr;
    hdr.magic = magic;
    hdr.version = version;

    if (labels.find("main") == labels.end()) {
      throw hc_missing_entry_point();
    }

    hdr.entry_point = labels.at("main");
    hdr.stack_size = 4096 * sizeof(word_t); // @TODO add option to customize
    hdr.bss_size = calc_bss_size();

    return hdr;
  }

  std::string& compiler::get_filename() {
    return filename;
  }

  void compiler::compile(const std::string &filename) {
    this->filename = filename;

    std::ifstream source;
    source.open(filename);

    if (source.fail()) {
      throw std::runtime_error("Cannot open source file: " + filename + ".");
    }

    lexer.set_stream(source);

    parser.parse();

    verify_code();
    unwind_pseudo();
    mark_sections();
    order_sections();
    calc_addresses();
    collect_labels();

    auto hdr = build_hdr();

    // compile
    std::fstream haxe;
    haxe.open(filename + ".e", std::ios::binary | std::fstream::out);
    haxe.write(reinterpret_cast<char*>(&hdr), sizeof(hdr));

    for (auto item : *ast) {
      if (item->get_section() == ".bss") {
        continue;
      }

      if (item->is_a(node::type::instr)) {
        node::instr *instr = dynamic_cast<node::instr*>(item);
        opcode_t opcode;
        opcode.cmd = instr_list.at(instr->get_name()).cmd;

        int reg_no = 1;
        for (auto arg : *instr->get_args()) {
          if (arg->is_a(node::type::reg)) {
            auto reg = resolve_reg(dynamic_cast<node::reg*>(arg)->get_name());

            opcode.set_reg(reg_no, reg);
            reg_no ++;
          } else if (arg->is_a(node::type::num)) {
            opcode.imm = dynamic_cast<node::num*>(arg)->get_value();
          } else if (arg->get_type() == node::type::label) {
            word_t imm = labels.at(dynamic_cast<node::label*>(arg)->get_name());

             if (instr_list.at(instr->get_name()).rel) {
               imm -= (item->get_addr() + sizeof(word_t));
             }

             if (instr_list.at(instr->get_name()).x8) {
               imm /= sizeof(word_t);
             }

             opcode.imm = imm;
           } else {
             std::cout << "fail" << std::endl;
           }
         }

         auto value = encode_opcode(opcode);
         haxe.write(reinterpret_cast<char*>(&value), sizeof(value));
      } else if (item->is_a(node::type::num)) {
        word_t value = dynamic_cast<node::num*>(item)->get_value();
        haxe.write(reinterpret_cast<char*>(&value), item->get_size());
      }
    }
  }

  uint8_t compiler::resolve_reg(const std::string &name) {
    auto item = reg_aliases.find(name);

    if (item != reg_aliases.end()) {
      return item->second;
    } else {
      return std::stoi(name.substr(1, std::string::npos));
    }

    // @TODO validation
  }

  void compiler::set_ast(std::vector<node::base*> *ast) {
    this->ast = ast;
  }

  std::string compiler::format_location(const class location &location) {
    std::stringstream ss;
    ss << location;
    return ss.str();
  }
}
<|endoftext|>


<commit_before>#include "GridCell.h"

GridCell::GridCell():
    m_status(false),
    m_property(NULL),
    m_elementGridImg(NULL)
{
    m_property = new GridElementProperty();
}

GridCell::~GridCell()
{
    if (m_property != NULL) {
        delete m_property;
    }
//    CC_SAFE_RELEASE_NULL(m_property);
}

GridCell* GridCell::createWithFrameName(const char *pszFileName)
{
    GridCell *cell = new GridCell();
    if (cell && cell->initWith(pszFileName))
    {
        cell->autorelease();

        return cell;
    }
    CC_SAFE_DELETE(cell);
    return NULL;
}

bool GridCell::initWith(const char *pszFileName)
{
    bool tRet=false;

    do {
        CC_BREAK_IF(!pszFileName);
        m_elementGridImg=CCSprite::createWithSpriteFrameName(pszFileName);
        CC_BREAK_IF(!m_elementGridImg);
        addChild(m_elementGridImg);

        tRet=true;
    } while (0);

    return tRet;
}

void GridCell::setCellProperty(GridElementProperty *pElement)
{
    m_property->mID=pElement->mID;
    m_property->mIndex.rIndex=pElement->mIndex.rIndex;
    m_property->mIndex.vIndex=pElement->mIndex.vIndex;
    m_property->mType=pElement->mType;
    do {
//        CC_BREAK_IF(!pElement);
//        m_property=pElement;
//        m_property->retain();
    } while (0);

    constructMonsterCellEX();
}

void GridCell::constructMonsterCellEX()
{
    do{
        CC_BREAK_IF(!m_property);
        CC_BREAK_IF(!m_property->mType==kElementType_Monster);

        CCString *attachValue=CCString::createWithFormat("%d",(int)m_property->mMonsterProperty.mDamage);
        CCLabelTTF *tAttackValueTTF = CCLabelTTF::create(attachValue->getCString(),"Marker Felt",14);
        CC_BREAK_IF(!tAttackValueTTF);
        tAttackValueTTF->setAnchorPoint(ccp(0.5,0.5));
        tAttackValueTTF->setContentSize(CCSizeMake(20, 15));
        tAttackValueTTF->setColor(ccc3(0,255,0));
        tAttackValueTTF->setPosition(ccp(m_elementGridImg->getPosition().x+m_elementGridImg->getContentSize().width,m_elementGridImg->getPosition().y+m_elementGridImg->getContentSize().height-tAttackValueTTF->getContentSize().height));
        this->addChild(tAttackValueTTF);

        CCString *defenceValue=CCString::createWithFormat("%d",(int)m_property->mMonsterProperty.mDamage);
        CCLabelTTF *tDefenceValueTTF = CCLabelTTF::create(defenceValue->getCString(),"Marker Felt",14);
        CC_BREAK_IF(!tDefenceValueTTF);
        tDefenceValueTTF->setAnchorPoint(ccp(0.5,0.5));
        tDefenceValueTTF->setContentSize(CCSizeMake(20, 15));
        tDefenceValueTTF->setColor(ccc3(0,255,0));
        tDefenceValueTTF->setPosition(ccp(m_elementGridImg->getPosition().x+m_elementGridImg->getContentSize().width,m_elementGridImg->getPosition().y+m_elementGridImg->getContentSize().height-2*tAttackValueTTF->getContentSize().height));
        this->addChild(tDefenceValueTTF);

        CCString *lifeValue=CCString::createWithFormat("%d",(int)m_property->mMonsterProperty.mDamage);
        CCLabelTTF *tLifeValueTTF = CCLabelTTF::create(lifeValue->getCString(),"Marker Felt",14);
        CC_BREAK_IF(!tLifeValueTTF);
        tLifeValueTTF->setAnchorPoint(ccp(0.5,0.5));
        tLifeValueTTF->setContentSize(CCSizeMake(20, 15));
        tLifeValueTTF->setColor(ccc3(255,0,0));
        tLifeValueTTF->setPosition(ccp(m_elementGridImg->getPosition().x+m_elementGridImg->getContentSize().width,m_elementGridImg->getPosition().y+m_elementGridImg->getContentSize().height-3*tAttackValueTTF->getContentSize().height));
        this->addChild(tLifeValueTTF);
    }while(0);
}

<commit_msg>添加cell set方法property的一些值<commit_after>#include "GridCell.h"

GridCell::GridCell():
    m_status(false),
    m_property(NULL),
    m_elementGridImg(NULL)
{
    m_property = new GridElementProperty();
}

GridCell::~GridCell()
{
    if (m_property != NULL) {
        delete m_property;
    }
//    CC_SAFE_RELEASE_NULL(m_property);
}

GridCell* GridCell::createWithFrameName(const char *pszFileName)
{
    GridCell *cell = new GridCell();
    if (cell && cell->initWith(pszFileName))
    {
        cell->autorelease();

        return cell;
    }
    CC_SAFE_DELETE(cell);
    return NULL;
}

bool GridCell::initWith(const char *pszFileName)
{
    bool tRet=false;

    do {
        CC_BREAK_IF(!pszFileName);
        m_elementGridImg=CCSprite::createWithSpriteFrameName(pszFileName);
        CC_BREAK_IF(!m_elementGridImg);
        addChild(m_elementGridImg);

        tRet=true;
    } while (0);

    return tRet;
}

void GridCell::setCellProperty(GridElementProperty *pElement)
{
    m_property->mID=pElement->mID;
    m_property->mIndex.rIndex=pElement->mIndex.rIndex;
    m_property->mIndex.vIndex=pElement->mIndex.vIndex;
    m_property->mType=pElement->mType;

    m_property->mMonsterProperty.mType = pElement->mMonsterProperty.mType;
    m_property->mMonsterProperty.mSkillType = pElement->mMonsterProperty.mSkillType;
    m_property->mMonsterProperty.mID = pElement->mMonsterProperty.mID;
    m_property->mMonsterProperty.mName = pElement->mMonsterProperty.mName;
    m_property->mMonsterProperty.mDescription = pElement->mMonsterProperty.mDescription;
    m_property->mMonsterProperty.mDefence = pElement->mMonsterProperty.mDefence;
    m_property->mMonsterProperty.mLife = pElement->mMonsterProperty.mLife;
    m_property->mMonsterProperty.mMaxLife = pElement->mMonsterProperty.mMaxLife;
    m_property->mMonsterProperty.mDamage = pElement->mMonsterProperty.mDamage;

    m_property->setStatus(pElement->getStatus());
    do {

    } while (0);

    constructMonsterCellEX();
}

void GridCell::constructMonsterCellEX()
{
    do{
        CC_BREAK_IF(!m_property);
        CC_BREAK_IF(!m_property->mType==kElementType_Monster);

        CCString *attachValue=CCString::createWithFormat("%d",(int)m_property->mMonsterProperty.mDamage);
        CCLabelTTF *tAttackValueTTF = CCLabelTTF::create(attachValue->getCString(),"Marker Felt",14);
        CC_BREAK_IF(!tAttackValueTTF);
        tAttackValueTTF->setAnchorPoint(ccp(0.5,0.5));
        tAttackValueTTF->setContentSize(CCSizeMake(20, 15));
        tAttackValueTTF->setColor(ccc3(0,255,0));
        tAttackValueTTF->setPosition(ccp(m_elementGridImg->getPosition().x+m_elementGridImg->getContentSize().width,m_elementGridImg->getPosition().y+m_elementGridImg->getContentSize().height-tAttackValueTTF->getContentSize().height));
        this->addChild(tAttackValueTTF);

        CCString *defenceValue=CCString::createWithFormat("%d",(int)m_property->mMonsterProperty.mDamage);
        CCLabelTTF *tDefenceValueTTF = CCLabelTTF::create(defenceValue->getCString(),"Marker Felt",14);
        CC_BREAK_IF(!tDefenceValueTTF);
        tDefenceValueTTF->setAnchorPoint(ccp(0.5,0.5));
        tDefenceValueTTF->setContentSize(CCSizeMake(20, 15));
        tDefenceValueTTF->setColor(ccc3(0,255,0));
        tDefenceValueTTF->setPosition(ccp(m_elementGridImg->getPosition().x+m_elementGridImg->getContentSize().width,m_elementGridImg->getPosition().y+m_elementGridImg->getContentSize().height-2*tAttackValueTTF->getContentSize().height));
        this->addChild(tDefenceValueTTF);

        CCString *lifeValue=CCString::createWithFormat("%d",(int)m_property->mMonsterProperty.mDamage);
        CCLabelTTF *tLifeValueTTF = CCLabelTTF::create(lifeValue->getCString(),"Marker Felt",14);
        CC_BREAK_IF(!tLifeValueTTF);
        tLifeValueTTF->setAnchorPoint(ccp(0.5,0.5));
        tLifeValueTTF->setContentSize(CCSizeMake(20, 15));
        tLifeValueTTF->setColor(ccc3(255,0,0));
        tLifeValueTTF->setPosition(ccp(m_elementGridImg->getPosition().x+m_elementGridImg->getContentSize().width,m_elementGridImg->getPosition().y+m_elementGridImg->getContentSize().height-3*tAttackValueTTF->getContentSize().height));
        this->addChild(tLifeValueTTF);
    }while(0);
}

<|endoftext|>