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

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

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

#include "xmlfilterdialogstrings.hrc"
#include "xmlfiltertabpagebasic.hxx"
#include "xmlfiltertabpagebasic.hrc"
#include "xmlfiltersettingsdialog.hxx"
#include "xmlfilterhelpids.hrc"

using namespace rtl;

XMLFilterTabPageBasic::XMLFilterTabPageBasic( Window* pParent, ResMgr& rResMgr ) :
    TabPage( pParent, ResId( RID_XML_FILTER_TABPAGE_BASIC, &rResMgr ) ),
    maFTFilterName( this, ResId( FT_XML_FILTER_NAME ) ),
    maEDFilterName( this, ResId( ED_XML_FILTER_NAME ) ),
    maFTApplication( this, ResId( FT_XML_APPLICATION ) ),
    maCBApplication( this, ResId( CB_XML_APPLICATION ) ),
    maFTInterfaceName( this, ResId( FT_XML_INTERFACE_NAME ) ),
    maEDInterfaceName( this, ResId( ED_XML_INTERFACE_NAME ) ),
    maFTExtension( this, ResId( FT_XML_EXTENSION ) ),
    maEDExtension( this, ResId( ED_XML_EXTENSION ) ),
    maFTDescription( this, ResId( FT_XML_DESCRIPTION ) ),
    maEDDescription( this, ResId( ED_XML_DESCRIPTION ) )
{
    maCBApplication.SetHelpId( HID_XML_FILTER_APPLICATION );
    maEDDescription.SetHelpId( HID_XML_FILTER_DESCRIPTION );

    FreeResource();

    std::vector< application_info_impl* >& rInfos = getApplicationInfos();
    std::vector< application_info_impl* >::iterator aIter( rInfos.begin() );
    while( aIter != rInfos.end() )
    {
        XubString aEntry( (*aIter++)->maDocumentUIName );
        maCBApplication.InsertEntry( aEntry );
    }
}

XMLFilterTabPageBasic::~XMLFilterTabPageBasic()
{
}

static OUString checkExtensions( const String& rExtensions )
{
    const sal_Unicode* pSource = rExtensions.GetBuffer();
    sal_Int32 nCount = rExtensions.Len();

    String aRet;
    while( nCount-- )
    {
        switch(*pSource)
        {
        case sal_Unicode(','):
            aRet += sal_Unicode(';');
            break;
        case sal_Unicode('.'):
        case sal_Unicode('*'):
            break;
        default:
            aRet += *pSource;
        }

        pSource++;
    }

    return aRet;
}

bool XMLFilterTabPageBasic::FillInfo( filter_info_impl* pInfo )
{
    if( pInfo )
    {
        if( maEDFilterName.GetText().Len() )
            pInfo->maFilterName = maEDFilterName.GetText();

        if( maCBApplication.GetText().Len() )
            pInfo->maDocumentService = maCBApplication.GetText();

        if( maEDInterfaceName.GetText().Len() )
            pInfo->maInterfaceName = maEDInterfaceName.GetText();

        if( maEDExtension.GetText().Len() )
            pInfo->maExtension = checkExtensions( maEDExtension.GetText() );

        pInfo->maComment = string_encode( maEDDescription.GetText() );

        if( pInfo->maDocumentService.getLength() )
        {
            std::vector< application_info_impl* >& rInfos = getApplicationInfos();
            std::vector< application_info_impl* >::iterator aIter( rInfos.begin() );
            while( aIter != rInfos.end() )
            {
                if( pInfo->maDocumentService == (*aIter)->maDocumentUIName )
                {
                    pInfo->maDocumentService = (*aIter)->maDocumentService;
                    pInfo->maExportService = (*aIter)->maXMLExporter;
                    pInfo->maImportService = (*aIter)->maXMLImporter;
                    break;
                }
                aIter++;
            }
        }
    }

    return true;
}

void XMLFilterTabPageBasic::SetInfo(const filter_info_impl* pInfo)
{
    if( pInfo )
    {
        maEDFilterName.SetText( string_decode(pInfo->maFilterName) );
        /*
        if( pInfo->maDocumentService.getLength() )
            maCBApplication.SetText( getApplicationUIName( pInfo->maDocumentService ) );
        */
        if( pInfo->maExportService.getLength() )
            maCBApplication.SetText( getApplicationUIName( pInfo->maImportService ) );
        else
            maCBApplication.SetText( getApplicationUIName( pInfo->maExportService ) );
        maEDInterfaceName.SetText( string_decode(pInfo->maInterfaceName) );
        maEDExtension.SetText( pInfo->maExtension );
        maEDDescription.SetText( string_decode( pInfo->maComment ) );
    }
}
<commit_msg>INTEGRATION: CWS residcleanup (1.5.100); FILE MERGED 2007/02/28 21:10:09 pl 1.5.100.1: #i74635# no more ResMgr fallback<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: xmlfiltertabpagebasic.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2007-04-26 08:13:12 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

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

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

#include "xmlfilterdialogstrings.hrc"
#include "xmlfiltertabpagebasic.hxx"
#include "xmlfiltertabpagebasic.hrc"
#include "xmlfiltersettingsdialog.hxx"
#include "xmlfilterhelpids.hrc"

using namespace rtl;

XMLFilterTabPageBasic::XMLFilterTabPageBasic( Window* pParent, ResMgr& rResMgr ) :
    TabPage( pParent, ResId( RID_XML_FILTER_TABPAGE_BASIC, rResMgr ) ),
    maFTFilterName( this, ResId( FT_XML_FILTER_NAME, rResMgr ) ),
    maEDFilterName( this, ResId( ED_XML_FILTER_NAME, rResMgr ) ),
    maFTApplication( this, ResId( FT_XML_APPLICATION, rResMgr ) ),
    maCBApplication( this, ResId( CB_XML_APPLICATION, rResMgr ) ),
    maFTInterfaceName( this, ResId( FT_XML_INTERFACE_NAME, rResMgr ) ),
    maEDInterfaceName( this, ResId( ED_XML_INTERFACE_NAME, rResMgr ) ),
    maFTExtension( this, ResId( FT_XML_EXTENSION, rResMgr ) ),
    maEDExtension( this, ResId( ED_XML_EXTENSION, rResMgr ) ),
    maFTDescription( this, ResId( FT_XML_DESCRIPTION, rResMgr ) ),
    maEDDescription( this, ResId( ED_XML_DESCRIPTION, rResMgr ) )
{
    maCBApplication.SetHelpId( HID_XML_FILTER_APPLICATION );
    maEDDescription.SetHelpId( HID_XML_FILTER_DESCRIPTION );

    FreeResource();

    std::vector< application_info_impl* >& rInfos = getApplicationInfos();
    std::vector< application_info_impl* >::iterator aIter( rInfos.begin() );
    while( aIter != rInfos.end() )
    {
        XubString aEntry( (*aIter++)->maDocumentUIName );
        maCBApplication.InsertEntry( aEntry );
    }
}

XMLFilterTabPageBasic::~XMLFilterTabPageBasic()
{
}

static OUString checkExtensions( const String& rExtensions )
{
    const sal_Unicode* pSource = rExtensions.GetBuffer();
    sal_Int32 nCount = rExtensions.Len();

    String aRet;
    while( nCount-- )
    {
        switch(*pSource)
        {
        case sal_Unicode(','):
            aRet += sal_Unicode(';');
            break;
        case sal_Unicode('.'):
        case sal_Unicode('*'):
            break;
        default:
            aRet += *pSource;
        }

        pSource++;
    }

    return aRet;
}

bool XMLFilterTabPageBasic::FillInfo( filter_info_impl* pInfo )
{
    if( pInfo )
    {
        if( maEDFilterName.GetText().Len() )
            pInfo->maFilterName = maEDFilterName.GetText();

        if( maCBApplication.GetText().Len() )
            pInfo->maDocumentService = maCBApplication.GetText();

        if( maEDInterfaceName.GetText().Len() )
            pInfo->maInterfaceName = maEDInterfaceName.GetText();

        if( maEDExtension.GetText().Len() )
            pInfo->maExtension = checkExtensions( maEDExtension.GetText() );

        pInfo->maComment = string_encode( maEDDescription.GetText() );

        if( pInfo->maDocumentService.getLength() )
        {
            std::vector< application_info_impl* >& rInfos = getApplicationInfos();
            std::vector< application_info_impl* >::iterator aIter( rInfos.begin() );
            while( aIter != rInfos.end() )
            {
                if( pInfo->maDocumentService == (*aIter)->maDocumentUIName )
                {
                    pInfo->maDocumentService = (*aIter)->maDocumentService;
                    pInfo->maExportService = (*aIter)->maXMLExporter;
                    pInfo->maImportService = (*aIter)->maXMLImporter;
                    break;
                }
                aIter++;
            }
        }
    }

    return true;
}

void XMLFilterTabPageBasic::SetInfo(const filter_info_impl* pInfo)
{
    if( pInfo )
    {
        maEDFilterName.SetText( string_decode(pInfo->maFilterName) );
        /*
        if( pInfo->maDocumentService.getLength() )
            maCBApplication.SetText( getApplicationUIName( pInfo->maDocumentService ) );
        */
        if( pInfo->maExportService.getLength() )
            maCBApplication.SetText( getApplicationUIName( pInfo->maImportService ) );
        else
            maCBApplication.SetText( getApplicationUIName( pInfo->maExportService ) );
        maEDInterfaceName.SetText( string_decode(pInfo->maInterfaceName) );
        maEDExtension.SetText( pInfo->maExtension );
        maEDDescription.SetText( string_decode( pInfo->maComment ) );
    }
}
<|endoftext|>


<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 RC 1        *
*                (c) 2006-2011 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* 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.          *
*******************************************************************************
*                              SOFA :: Framework                              *
*                                                                             *
* Authors: The SOFA Team (see Authors.txt)                                    *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/

// Author: Pierre-Jean Bensoussan, Digital Trainers (2008)

#include <sofa/core/behavior/BaseController.h>

#include <sofa/core/objectmodel/Event.h>
#include <sofa/core/objectmodel/JoystickEvent.h>
#include <sofa/core/objectmodel/KeypressedEvent.h>
#include <sofa/core/objectmodel/KeyreleasedEvent.h>
#include <sofa/core/objectmodel/MouseEvent.h>
#include <sofa/core/objectmodel/HapticDeviceEvent.h>

#include <iostream>

namespace sofa
{

namespace core
{

namespace behavior
{

BaseController::BaseController()
    : handleEventTriggersUpdate( initData(&handleEventTriggersUpdate, "handleEventTriggersUpdate", "Event handling frequency controls the controller update frequency" ) )
{

}

void BaseController::handleEvent(core::objectmodel::Event *event)
{
    if (dynamic_cast<sofa::simulation::AnimateBeginEvent *>(event))
    {
        onBeginAnimationStep();
    }
    else if (dynamic_cast<sofa::simulation::AnimateEndEvent *>(event))
    {
        onEndAnimationStep();
    }
    else if (dynamic_cast<sofa::core::objectmodel::KeypressedEvent *>(event))
    {
        sofa::core::objectmodel::KeypressedEvent *kpev = dynamic_cast<sofa::core::objectmodel::KeypressedEvent *>(event);
        onKeyPressedEvent(kpev);
    }
    else if (dynamic_cast<sofa::core::objectmodel::KeyreleasedEvent *>(event))
    {
        sofa::core::objectmodel::KeyreleasedEvent *krev = dynamic_cast<sofa::core::objectmodel::KeyreleasedEvent *>(event);
        onKeyReleasedEvent(krev);
    }
    else if (dynamic_cast<sofa::core::objectmodel::MouseEvent *>(event))
    {
        sofa::core::objectmodel::MouseEvent *mev = dynamic_cast<sofa::core::objectmodel::MouseEvent *>(event);
        onMouseEvent(mev);
    }
    else if (dynamic_cast<sofa::core::objectmodel::JoystickEvent *>(event))
    {
        sofa::core::objectmodel::JoystickEvent *jev = dynamic_cast<sofa::core::objectmodel::JoystickEvent *>(event);
        onJoystickEvent(jev);
    }
    else if (dynamic_cast<sofa::core::objectmodel::HapticDeviceEvent *>(event))
    {
        sofa::core::objectmodel::HapticDeviceEvent *oev = dynamic_cast<sofa::core::objectmodel::HapticDeviceEvent *>(event);
        onHapticDeviceEvent(oev);
    }
}

}

}

}

}

<commit_msg>FIX: } mismatch<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 RC 1        *
*                (c) 2006-2011 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* 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.          *
*******************************************************************************
*                              SOFA :: Framework                              *
*                                                                             *
* Authors: The SOFA Team (see Authors.txt)                                    *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/

// Author: Pierre-Jean Bensoussan, Digital Trainers (2008)

#include <sofa/core/behavior/BaseController.h>

#include <sofa/core/objectmodel/Event.h>
#include <sofa/core/objectmodel/JoystickEvent.h>
#include <sofa/core/objectmodel/KeypressedEvent.h>
#include <sofa/core/objectmodel/KeyreleasedEvent.h>
#include <sofa/core/objectmodel/MouseEvent.h>
#include <sofa/core/objectmodel/HapticDeviceEvent.h>

#include <iostream>

namespace sofa
{

namespace core
{

namespace behavior
{

BaseController::BaseController()
    : handleEventTriggersUpdate( initData(&handleEventTriggersUpdate, "handleEventTriggersUpdate", "Event handling frequency controls the controller update frequency" ) )
{

}

void BaseController::handleEvent(core::objectmodel::Event *event)
{
    if (dynamic_cast<sofa::simulation::AnimateBeginEvent *>(event))
    {
        onBeginAnimationStep();
    }
    else if (dynamic_cast<sofa::simulation::AnimateEndEvent *>(event))
    {
        onEndAnimationStep();
    }
    else if (dynamic_cast<sofa::core::objectmodel::KeypressedEvent *>(event))
    {
        sofa::core::objectmodel::KeypressedEvent *kpev = dynamic_cast<sofa::core::objectmodel::KeypressedEvent *>(event);
        onKeyPressedEvent(kpev);
    }
    else if (dynamic_cast<sofa::core::objectmodel::KeyreleasedEvent *>(event))
    {
        sofa::core::objectmodel::KeyreleasedEvent *krev = dynamic_cast<sofa::core::objectmodel::KeyreleasedEvent *>(event);
        onKeyReleasedEvent(krev);
    }
    else if (dynamic_cast<sofa::core::objectmodel::MouseEvent *>(event))
    {
        sofa::core::objectmodel::MouseEvent *mev = dynamic_cast<sofa::core::objectmodel::MouseEvent *>(event);
        onMouseEvent(mev);
    }
    else if (dynamic_cast<sofa::core::objectmodel::JoystickEvent *>(event))
    {
        sofa::core::objectmodel::JoystickEvent *jev = dynamic_cast<sofa::core::objectmodel::JoystickEvent *>(event);
        onJoystickEvent(jev);
    }
    else if (dynamic_cast<sofa::core::objectmodel::HapticDeviceEvent *>(event))
    {
        sofa::core::objectmodel::HapticDeviceEvent *oev = dynamic_cast<sofa::core::objectmodel::HapticDeviceEvent *>(event);
        onHapticDeviceEvent(oev);
    }
}

} //behavior

} //core

} //sofa

<|endoftext|>


<commit_before>/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.

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 "post_latgen_faster_mapped.h"

using namespace kaldi;
typedef kaldi::int32 int32;
using fst::SymbolTable;
using fst::Fst;
using fst::StdArc;

Decoder::Decoder(std::string trans_model_in_filename,
                 std::string word_syms_filename,
                 std::string fst_in_filename,
                 std::string logprior_in_filename,
                 kaldi::BaseFloat acoustic_scale) {
  const char *usage =
      "Generate lattices using neural net model.\n"
      "Usage: post-latgen-faster-mapped [options] <trans-model> "
      "<fst-in|fsts-rspecifier> <logprior> <posts-rspecifier>"
      " <lattice-wspecifier> [ <words-wspecifier> [<alignments-wspecifier>] "
      "]\n";
  ParseOptions po(usage);
  allow_partial = false;
  this->acoustic_scale = acoustic_scale;
  LatticeFasterDecoderConfig config;

  config.Register(&po);
  int32 beam = 11;
  po.Register("beam", &beam, "Beam size");
  po.Register("acoustic-scale",
              &acoustic_scale,
              "Scaling factor for acoustic likelihoods");
  po.Register("word-symbol-table",
              &word_syms_filename,
              "Symbol table for words [for debug output]");
  po.Register("allow-partial",
              &allow_partial,
              "If true, produce output even if end state was not reached.");

  // int argc = 2;
  // char *argv[] = {"post-latgen-faster-mapped", "--beam=11"};
  // po.Read(argc, argv);

  std::ifstream is_logprior(logprior_in_filename);
  logprior.Read(is_logprior, false);

  {
    bool binary;
    Input ki(trans_model_in_filename, &binary);
    this->trans_model.Read(ki.Stream(), binary);
  }

  this->determinize = config.determinize_lattice;

  this->word_syms = NULL;
  if (word_syms_filename != "") {
    if (!(word_syms = fst::SymbolTable::ReadText(word_syms_filename))) {
      KALDI_ERR << "Could not read symbol table from file "
                << word_syms_filename;
    }
  }

  // Input FST is just one FST, not a table of FSTs.
  this->decode_fst = fst::ReadFstKaldiGeneric(fst_in_filename);

  this->decoder = new LatticeFasterDecoder(*decode_fst, config);

  std::string lattice_wspecifier =
      "ark:|gzip -c > mapped_decoder_data/lat.JOB.gz";
  if (!(determinize ? compact_lattice_writer.Open(lattice_wspecifier)
                    : lattice_writer.Open(lattice_wspecifier)))
    KALDI_ERR << "Could not open table for writing lattices: ";
  // << lattice_wspecifier;

  words_writer = new Int32VectorWriter("");
  alignment_writer = new Int32VectorWriter("");
}

Decoder::~Decoder() {
  if (!this->word_syms) delete this->word_syms;
  delete this->decode_fst;
  delete this->decoder;
  delete words_writer;
  delete alignment_writer;
}

std::string Decoder::decode(std::string key,
                            kaldi::Matrix<kaldi::BaseFloat> &loglikes) {
  std::string decoding_result;
  if (loglikes.NumRows() == 0) {
    KALDI_WARN << "Zero-length utterance: " << key;
    // num_fail++;
  }
  KALDI_ASSERT(loglikes.NumCols() == logprior.Dim());

  loglikes.ApplyLog();
  loglikes.AddVecToRows(-1.0, logprior);

  DecodableMatrixScaledMapped matrix_decodable(
      trans_model, loglikes, acoustic_scale);
  double like;

  if (DecodeUtteranceLatticeFaster(*decoder,
                                   matrix_decodable,
                                   trans_model,
                                   word_syms,
                                   key,
                                   acoustic_scale,
                                   determinize,
                                   allow_partial,
                                   alignment_writer,
                                   words_writer,
                                   &compact_lattice_writer,
                                   &lattice_writer,
                                   &like)) {
    // tot_like += like;
    // frame_count += loglikes.NumRows();
    // num_success++;
    decoding_result = "succeed!";
  } else {  // else num_fail++;
    decoding_result = "fail!";
  }
  return decoding_result;
}

std::vector<std::string> Decoder::decode(std::string posterior_rspecifier) {
  std::vector<std::string> ret;

  try {
    double tot_like = 0.0;
    kaldi::int64 frame_count = 0;
    // int num_success = 0, num_fail = 0;

    KALDI_ASSERT(ClassifyRspecifier(fst_in_filename, NULL, NULL) ==
                 kNoRspecifier);
    SequentialBaseFloatMatrixReader posterior_reader("ark:" +
                                                     posterior_rspecifier);

    Timer timer;
    timer.Reset();

    {
      for (; !posterior_reader.Done(); posterior_reader.Next()) {
        std::string utt = posterior_reader.Key();
        Matrix<BaseFloat> &loglikes(posterior_reader.Value());
        KALDI_LOG << utt << " " << loglikes.NumRows() << " x "
                  << loglikes.NumCols();
        ret.push_back(decode(utt, loglikes));
      }
    }

    double elapsed = timer.Elapsed();
    return ret;
  } catch (const std::exception &e) {
    std::cerr << e.what();
    // ret.push_back("error");
    return ret;
  }
}
<commit_msg>Add missing defined decoding function<commit_after>/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.

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 "post_latgen_faster_mapped.h"

using namespace kaldi;
typedef kaldi::int32 int32;
using fst::SymbolTable;
using fst::Fst;
using fst::StdArc;

Decoder::Decoder(std::string trans_model_in_filename,
                 std::string word_syms_filename,
                 std::string fst_in_filename,
                 std::string logprior_in_filename,
                 kaldi::BaseFloat acoustic_scale) {
  const char *usage =
      "Generate lattices using neural net model.\n"
      "Usage: post-latgen-faster-mapped [options] <trans-model> "
      "<fst-in|fsts-rspecifier> <logprior> <posts-rspecifier>"
      " <lattice-wspecifier> [ <words-wspecifier> [<alignments-wspecifier>] "
      "]\n";
  ParseOptions po(usage);
  allow_partial = false;
  this->acoustic_scale = acoustic_scale;
  LatticeFasterDecoderConfig config;

  config.Register(&po);
  int32 beam = 11;
  po.Register("beam", &beam, "Beam size");
  po.Register("acoustic-scale",
              &acoustic_scale,
              "Scaling factor for acoustic likelihoods");
  po.Register("word-symbol-table",
              &word_syms_filename,
              "Symbol table for words [for debug output]");
  po.Register("allow-partial",
              &allow_partial,
              "If true, produce output even if end state was not reached.");

  // int argc = 2;
  // char *argv[] = {"post-latgen-faster-mapped", "--beam=11"};
  // po.Read(argc, argv);

  std::ifstream is_logprior(logprior_in_filename);
  logprior.Read(is_logprior, false);

  {
    bool binary;
    Input ki(trans_model_in_filename, &binary);
    this->trans_model.Read(ki.Stream(), binary);
  }

  this->determinize = config.determinize_lattice;

  this->word_syms = NULL;
  if (word_syms_filename != "") {
    if (!(word_syms = fst::SymbolTable::ReadText(word_syms_filename))) {
      KALDI_ERR << "Could not read symbol table from file "
                << word_syms_filename;
    }
  }

  // Input FST is just one FST, not a table of FSTs.
  this->decode_fst = fst::ReadFstKaldiGeneric(fst_in_filename);

  this->decoder = new LatticeFasterDecoder(*decode_fst, config);

  std::string lattice_wspecifier =
      "ark:|gzip -c > mapped_decoder_data/lat.JOB.gz";
  if (!(determinize ? compact_lattice_writer.Open(lattice_wspecifier)
                    : lattice_writer.Open(lattice_wspecifier)))
    KALDI_ERR << "Could not open table for writing lattices: ";
  // << lattice_wspecifier;

  words_writer = new Int32VectorWriter("");
  alignment_writer = new Int32VectorWriter("");
}

Decoder::~Decoder() {
  if (!this->word_syms) delete this->word_syms;
  delete this->decode_fst;
  delete this->decoder;
  delete words_writer;
  delete alignment_writer;
}

std::vector<std::string> Decoder::decode(std::string posterior_rspecifier) {
  std::vector<std::string> ret;

  try {
    double tot_like = 0.0;
    kaldi::int64 frame_count = 0;
    // int num_success = 0, num_fail = 0;

    KALDI_ASSERT(ClassifyRspecifier(fst_in_filename, NULL, NULL) ==
                 kNoRspecifier);
    SequentialBaseFloatMatrixReader posterior_reader("ark:" +
                                                     posterior_rspecifier);

    Timer timer;
    timer.Reset();

    {
      for (; !posterior_reader.Done(); posterior_reader.Next()) {
        std::string utt = posterior_reader.Key();
        Matrix<BaseFloat> &loglikes(posterior_reader.Value());
        KALDI_LOG << utt << " " << loglikes.NumRows() << " x "
                  << loglikes.NumCols();
        ret.push_back(decode(utt, loglikes));
      }
    }

    double elapsed = timer.Elapsed();
    return ret;
  } catch (const std::exception &e) {
    std::cerr << e.what();
    // ret.push_back("error");
    return ret;
  }
}

std::string Decoder::decode(
    std::string key,
    const std::vector<std::vector<kaldi::BaseFloat>> &log_probs) {
  size_t num_frames = log_probs.size();
  size_t dim_label = log_probs[0].size();

  kaldi::Matrix<kaldi::BaseFloat> loglikes(
      num_frames, dim_label, kaldi::kSetZero, kaldi::kStrideEqualNumCols);
  for (size_t i = 0; i < num_frames; ++i) {
    memcpy(loglikes.Data() + i * dim_label,
           log_probs[i].data(),
           sizeof(kaldi::BaseFloat) * dim_label);
  }

  return decode(key, loglikes);
}

std::string Decoder::decode(std::string key,
                            kaldi::Matrix<kaldi::BaseFloat> &loglikes) {
  std::string decoding_result;
  if (loglikes.NumRows() == 0) {
    KALDI_WARN << "Zero-length utterance: " << key;
    // num_fail++;
  }
  KALDI_ASSERT(loglikes.NumCols() == logprior.Dim());

  loglikes.ApplyLog();
  loglikes.AddVecToRows(-1.0, logprior);

  DecodableMatrixScaledMapped matrix_decodable(
      trans_model, loglikes, acoustic_scale);
  double like;

  if (DecodeUtteranceLatticeFaster(*decoder,
                                   matrix_decodable,
                                   trans_model,
                                   word_syms,
                                   key,
                                   acoustic_scale,
                                   determinize,
                                   allow_partial,
                                   alignment_writer,
                                   words_writer,
                                   &compact_lattice_writer,
                                   &lattice_writer,
                                   &like)) {
    // tot_like += like;
    // frame_count += loglikes.NumRows();
    // num_success++;
    decoding_result = "succeed!";
  } else {  // else num_fail++;
    decoding_result = "fail!";
  }
  return decoding_result;
}
<|endoftext|>


<commit_before>#pragma once

#include <map>
#include <vector>

#include <utki/Unique.hpp>

#include "../exception.hpp"
#include "Widget.hpp"

namespace morda{

/**
 * @brief Container widget.
 * A widget which can contain children widgets.
 * From GUI script it can be instantiated as 'Container' and can  have child widgets specified. For example:
 * @code
 * Container{
 *     Text{
 *         text{"Hello world!"}
 *     }
 *     Text{
 *         text{"Hi!"}
 *     }
 * }
 * @endcode
 */
class Container : virtual public Widget{

public:
	typedef std::vector<std::shared_ptr<Widget>> list;
	typedef std::vector<std::shared_ptr<const Widget>> const_list;
private:
	static_assert(sizeof(list) == sizeof(const_list), "sizeof(list) differs from sizeof(const_list)");
	static_assert(sizeof(list::value_type) == sizeof(const_list::value_type), "sizeof(list::value_type) differs from sizeof(const_list::value_type)");

	// NOTE: according to C++11 standard it is undefined behaviour to read the inactive union member,
	//       but we rely on compiler implementing it the right way.
	union children_union{
		list variable;
		const_list constant; // this member never becomes active one, but we will read it when we need constant list of children

		children_union() :
				variable() // this sets the 'variable' member of the union as an active one
		{}
		~children_union(){}
	} children_v;

	//Map which maps pointer ID to a pair holding reference to capturing widget and number of mouse capture clicks
	std::map<unsigned, std::pair<std::weak_ptr<Widget>, unsigned>> mouseCaptureMap;

protected:
	//flag indicating that modifications to children list are blocked
	bool isBlocked = false;

	class BlockedFlagGuard{
		bool& blocked;
	public:
		BlockedFlagGuard(bool& blocked) :
				blocked(blocked)
		{
			this->blocked = true;
		}

		~BlockedFlagGuard()noexcept{
			this->blocked = false;
		}
	};

protected:
	/**
	 * @brief Create layout parameters object specific for this container.
	 * Other widgets which subclass Container and need additional parameters for laying out children widgets should extend the Widget::LayoutParams class
	 * and override this method to construct the correct LayoutParams instance.
	 * @param chain - STOB chain describing layout parameters.
	 * @return A new instance of layout parameters object.
	 */
	virtual std::unique_ptr<LayoutParams> createLayoutParams(const stob::Node* chain = nullptr)const{
		return utki::makeUnique<Widget::LayoutParams>(chain);
	}

	/**
	 * @brief Calculate basic dimensions of widget.
	 * Calculates basic dimensions of given widget if it would be placed to
	 * this container with given layout parameters, basically this is just
	 * resolving of 'min', 'max' and 'fill' special values of dimensions.
	 * @param w - widget to calculate dimensions for.
	 * @param lp - layout parameters of the widget.
	 * @return Dimensions of widget.
	 */
	Vec2r dimForWidget(const Widget& w, const LayoutParams& lp)const;

protected:

	/**
	 * @brief Get layout parameters of child widget.
	 * Same as getLayoutParams() but also tries to cast the LayoutParams object to specified class.
	 * @param w - widget to get layout parameters for.
	 * @return Layout parameters of given child widget.
	 */
	template <class T> const T& getLayoutParamsAs(const Widget& w)const{
		auto p = dynamic_cast<const T*>(&this->getLayoutParams(w));
		if(!p){
			w.layoutParams.reset();
			p = dynamic_cast<const T*>(&this->getLayoutParams(w));
		}

		ASSERT(p)
		return *p;
	}

public:
	class LayoutExc : public Exc{
	public:
		LayoutExc(const std::string& message) : Exc(message){}
	};

	/**
	 * @brief Get layout parameters of child widget.
	 * @param w - widget to get layout parameters for.
	 * @return Layout parameters of given child widget.
	 */
	LayoutParams& getLayoutParams(Widget& w);

	/**
	 * @brief Get layout parameters of child widget.
	 * @param w - widget to get layout parameters for.
	 * @return Layout parameters of given child widget.
	 */
	const LayoutParams& getLayoutParams(const Widget& w)const;

	using Widget::getLayoutParams;
protected:
	void renderChild(const Matr4r& matrix, const Widget& c)const;
public:
	/**
	 * @brief Constructor.
	 * @param chain - STOB chain describing the widget. Can be nullptr in which case empty container widget is created.
	 */
	Container(const stob::Node* chain = nullptr);

	/**
	 * @brief Render to screen.
	 * This is an override of Widget::render(). It just renders all container widgets.
	 * Normally, users do not need to call this method, it will be called by framework when needed.
	 */
	void render(const morda::Matr4r& matrix)const override;

	/**
	 * @brief Handle mouse button event.
	 * Override of Widget::onMouseButton() method. It passes the event to the container's child widgets in reverse order.
	 * Normally, users do not need to call this method, it will be called by framework when needed.
	 */
	bool onMouseButton(bool isDown, const morda::Vec2r& pos, MouseButton_e button, unsigned pointerID) override;

	/**
	 * @brief Handle mouse move event.
	 * Override of Widget::onMouseMove() method. It passes the event to the container's child widgets in reverse order.
	 * Normally, users do not need to call this method, it will be called by framework when needed.
	 */
	bool onMouseMove(const morda::Vec2r& pos, unsigned pointerID) override;

	/**
	 * @brief Handle hover changed event.
	 * Normally, users do not need to call this method, it will be called by framework when needed.
	 */
	void onHoverChanged(unsigned pointerID)override;

	/**
	 * @brief Layout child widgets.
	 * This implementation of layout method checks if any of child widgets needs re-layout and if so it calls layout method on them.
	 */
	void layOut()override;

	/**
	 * @brief Change Z order of a child widget.
	 * This function invalidates iterators which were obtained before calling to it.
	 * @param child - child widget to change Z order of.
	 * @param before - iterator into the children list before which to insert the child.
	 * @return new child iterator.
	 */
	list::const_iterator change_child_z_position(list::const_iterator child, list::const_iterator before);

	/**
	 * @brief Insert a widget to the container.
	 * This function invalidates iterators which were obtained before calling to it.
	 * @param w - widget to insert.
	 * @param before - iterator within this container before which the widget will be inserted.
	 * @return iterator pointing to the newly inserted widget.
	 */
	list::const_iterator insert(std::shared_ptr<Widget> w, list::const_iterator before);

	/**
	 * @brief Insert a widget to the end of children list of the container.
	 * This function invalidates iterators which were obtained before calling to it.
	 * @param w - widget to insert.
	 * @return iterator pointing to the newly inserted widget.
	 */
	list::const_iterator push_back(std::shared_ptr<Widget> w){
		//TODO: rewrite using push_back()?
		return this->insert(std::move(w), this->children().end());
	}

	// TODO: rename to 'inflate_and_push_back'?
	/**
	 * @brief Add child widgets inflating them from GUI description.
	 * This function invalidates iterators which were obtained before calling to it.
	 * @param chain - STOB chain describing child widgets to add.
	 */
	void add(const stob::Node& chain);

	//TODO: depreacted, remove.
	/**
	 * @brief Remove child widget.
	 * @param iter - iterator of the widget to remove.
	 * @return Removed widget.
	 * @throw morda::Exc if iterator does not point to child widget of this container.
	 */
	std::shared_ptr<Widget> remove(list::const_iterator iter);

	//TODO: depreacted, remove.
	/**
	 * @brief Remove child widget.
	 * @param w - child widget to remove.
	 * @return Removed widget.
	 * @throw morda::Exc if given widget is not a child widget of this container.
	 */
	std::shared_ptr<Widget> remove(Widget& w);

	/**
	 * @brief Remove child from container.
	 * This function invalidates iterators which were obtained before calling to it.
	 * @param child - iterator of the child to remove.
	 * @return iterator pointing to the next child after removed one.
	 */
	list::const_iterator erase(list::const_iterator child);

	/**
	 * @brief Remove all child widgets.
	 * This function invalidates iterators which were obtained before calling to it.
	 */
	void clear();

	/**
	 * @brief Try get widget by id.
	 * It searches through the whole widget sub-hierarchy, not just direct children of this container.
	 * @param id - id of the child widget to look for.
	 * @return pointer to widget with given id if found.
	 * @return nullptr if there is no widget with given id found.
	 */
	std::shared_ptr<Widget> try_get_widget(const std::string& id)noexcept override;

	/**
	 * @brief Get list of child widgets.
	 * @return List of child widgets.
	 */
	const list& children()noexcept{
		return this->children_v.variable;
	}

	/**
	 * @brief Get constant list of child widgets.
	 * @return Constant list of child widgets.
	 */
	const const_list& children()const noexcept{
		// TRACE(<< "sizeof(list::value_type) = " << sizeof(list::value_type) << std::endl)
		// TRACE(<< "sizeof(const_list::value_type) = " << sizeof(const_list::value_type) << std::endl)
		return this->children_v.constant;
	}

	/**
	 * @brief Find widget in the list of container's children.
	 * @param w - child widget to find.
	 * @return iterator for child widget.
	 * @return end iterator if given widget was not found from the list of container's children.
	 */
	list::const_iterator find(const Widget* w);

	/**
	 * @brief Find widget in the list of container's children.
	 * @param w - child widget to find.
	 * @return iterator for child widget.
	 * @return end iterator if given widget was not found from the list of container's children.
	 */
	const_list::const_iterator find(const Widget* w)const;

	/**
	 * @brief Recursively find all children of given type.
	 * @return list of children found.
	 */
	template <class T> std::vector<std::shared_ptr<T>> get_all_widgets(){
		std::vector<std::shared_ptr<T>> ret;

		if(auto t = std::dynamic_pointer_cast<T>(this->sharedFromThis(this))){
			ret.emplace_back(t);
		}

		for(auto& child : this->children()){
			if(auto c = std::dynamic_pointer_cast<Container>(child)){
				auto res = c->get_all_widgets<T>();
				ret.insert(
						ret.end(),
						std::make_move_iterator(res.begin()),
						std::make_move_iterator(res.end())
					);
			}else if(auto c = std::dynamic_pointer_cast<T>(child)){
				ret.emplace_back(std::move(c));
			}
		}
		return ret;
	}

	/**
	 * @brief Called when children list changes.
	 * This implementation requests re-layout.
     */
	virtual void onChildrenListChanged(){
		this->setRelayoutNeeded();
	}
};

template <class T> T* Widget::findAncestor(const char* name){
	if(!this->parent()){
		return nullptr;
	}

	auto p = dynamic_cast<T*>(this->parent());

	if(p){
		if(!name || p->id == name){
			return p;
		}
	}

	return this->parent()->findAncestor<T>();
}

}
<commit_msg>comment improvement<commit_after>#pragma once

#include <map>
#include <vector>

#include <utki/Unique.hpp>

#include "../exception.hpp"
#include "Widget.hpp"

namespace morda{

/**
 * @brief Container widget.
 * A widget which can contain children widgets.
 * From GUI script it can be instantiated as 'Container' and can  have child widgets specified. For example:
 * @code
 * Container{
 *     Text{
 *         text{"Hello world!"}
 *     }
 *     Text{
 *         text{"Hi!"}
 *     }
 * }
 * @endcode
 */
class Container : virtual public Widget{

public:
	typedef std::vector<std::shared_ptr<Widget>> list;
	typedef std::vector<std::shared_ptr<const Widget>> const_list;
private:
	static_assert(sizeof(list) == sizeof(const_list), "sizeof(list) differs from sizeof(const_list)");
	static_assert(sizeof(list::value_type) == sizeof(const_list::value_type), "sizeof(list::value_type) differs from sizeof(const_list::value_type)");

	// NOTE: according to C++11 standard it is undefined behaviour to read the inactive union member,
	//       but we rely on compiler implementing it the right way.
	union children_union{
		list variable;
		const_list constant; // this member never becomes active one, but we will read it when we need constant list of children

		children_union() :
				variable() // this sets the 'variable' member of the union as an active one
		{}
		~children_union(){}
	} children_v;

	//Map which maps pointer ID to a pair holding reference to capturing widget and number of mouse capture clicks
	std::map<unsigned, std::pair<std::weak_ptr<Widget>, unsigned>> mouseCaptureMap;

protected:
	//flag indicating that modifications to children list are blocked
	bool isBlocked = false;

	class BlockedFlagGuard{
		bool& blocked;
	public:
		BlockedFlagGuard(bool& blocked) :
				blocked(blocked)
		{
			this->blocked = true;
		}

		~BlockedFlagGuard()noexcept{
			this->blocked = false;
		}
	};

protected:
	/**
	 * @brief Create layout parameters object specific for this container.
	 * Other widgets which subclass Container and need additional parameters for laying out children widgets should extend the Widget::LayoutParams class
	 * and override this method to construct the correct LayoutParams instance.
	 * @param chain - STOB chain describing layout parameters.
	 * @return A new instance of layout parameters object.
	 */
	virtual std::unique_ptr<LayoutParams> createLayoutParams(const stob::Node* chain = nullptr)const{
		return utki::makeUnique<Widget::LayoutParams>(chain);
	}

	/**
	 * @brief Calculate basic dimensions of widget.
	 * Calculates basic dimensions of given widget if it would be placed to
	 * this container with given layout parameters, basically this is just
	 * resolving of 'min', 'max' and 'fill' special values of dimensions.
	 * @param w - widget to calculate dimensions for.
	 * @param lp - layout parameters of the widget.
	 * @return Dimensions of widget.
	 */
	Vec2r dimForWidget(const Widget& w, const LayoutParams& lp)const;

protected:

	/**
	 * @brief Get layout parameters of child widget.
	 * Same as getLayoutParams() but also tries to cast the LayoutParams object to specified class.
	 * @param w - widget to get layout parameters for.
	 * @return Layout parameters of given child widget.
	 */
	template <class T> const T& getLayoutParamsAs(const Widget& w)const{
		auto p = dynamic_cast<const T*>(&this->getLayoutParams(w));
		if(!p){
			w.layoutParams.reset();
			p = dynamic_cast<const T*>(&this->getLayoutParams(w));
		}

		ASSERT(p)
		return *p;
	}

public:
	class LayoutExc : public Exc{
	public:
		LayoutExc(const std::string& message) : Exc(message){}
	};

	/**
	 * @brief Get layout parameters of child widget.
	 * @param w - widget to get layout parameters for.
	 * @return Layout parameters of given child widget.
	 */
	LayoutParams& getLayoutParams(Widget& w);

	/**
	 * @brief Get layout parameters of child widget.
	 * @param w - widget to get layout parameters for.
	 * @return Layout parameters of given child widget.
	 */
	const LayoutParams& getLayoutParams(const Widget& w)const;

	using Widget::getLayoutParams;
protected:
	void renderChild(const Matr4r& matrix, const Widget& c)const;
public:
	/**
	 * @brief Constructor.
	 * @param chain - STOB chain describing the widget. Can be nullptr in which case empty container widget is created.
	 */
	Container(const stob::Node* chain = nullptr);

	/**
	 * @brief Render to screen.
	 * This is an override of Widget::render(). It just renders all container widgets.
	 * Normally, users do not need to call this method, it will be called by framework when needed.
	 */
	void render(const morda::Matr4r& matrix)const override;

	/**
	 * @brief Handle mouse button event.
	 * Override of Widget::onMouseButton() method. It passes the event to the container's child widgets in reverse order.
	 * Normally, users do not need to call this method, it will be called by framework when needed.
	 */
	bool onMouseButton(bool isDown, const morda::Vec2r& pos, MouseButton_e button, unsigned pointerID) override;

	/**
	 * @brief Handle mouse move event.
	 * Override of Widget::onMouseMove() method. It passes the event to the container's child widgets in reverse order.
	 * Normally, users do not need to call this method, it will be called by framework when needed.
	 */
	bool onMouseMove(const morda::Vec2r& pos, unsigned pointerID) override;

	/**
	 * @brief Handle hover changed event.
	 * Normally, users do not need to call this method, it will be called by framework when needed.
	 */
	void onHoverChanged(unsigned pointerID)override;

	/**
	 * @brief Layout child widgets.
	 * This implementation of layout method checks if any of child widgets needs re-layout and if so it calls layout method on them.
	 */
	void layOut()override;

	/**
	 * @brief Change Z order of a child widget.
	 * This function invalidates iterators which were obtained before calling to it.
	 * @param child - child widget to change Z order of.
	 * @param before - iterator into the children list before which to insert the child.
	 * @return new child iterator.
	 */
	list::const_iterator change_child_z_position(list::const_iterator child, list::const_iterator before);

	/**
	 * @brief Insert a widget to the container.
	 * This function invalidates iterators which were obtained before calling to it.
	 * @param w - widget to insert.
	 * @param before - iterator within this container before which the widget will be inserted.
	 * @return iterator pointing to the newly inserted widget.
	 */
	list::const_iterator insert(std::shared_ptr<Widget> w, list::const_iterator before);

	/**
	 * @brief Insert a widget to the end of children list of the container.
	 * This function invalidates iterators which were obtained before calling to it.
	 * @param w - widget to insert.
	 * @return iterator pointing to the newly inserted widget.
	 */
	list::const_iterator push_back(std::shared_ptr<Widget> w){
		//TODO: rewrite using push_back()?
		return this->insert(std::move(w), this->children().end());
	}

	// TODO: rename to 'inflate_and_push_back'?
	/**
	 * @brief Add child widgets inflating them from GUI description.
	 * This function invalidates iterators which were obtained before calling to it.
	 * @param chain - STOB chain describing child widgets to add.
	 */
	void add(const stob::Node& chain);

	//TODO: depreacted, remove.
	/**
	 * @brief Remove child widget.
	 * @param iter - iterator of the widget to remove.
	 * @return Removed widget.
	 * @throw morda::Exc if iterator does not point to child widget of this container.
	 */
	std::shared_ptr<Widget> remove(list::const_iterator iter);

	//TODO: depreacted, remove.
	/**
	 * @brief Remove child widget.
	 * @param w - child widget to remove.
	 * @return Removed widget.
	 * @throw morda::Exc if given widget is not a child widget of this container.
	 */
	std::shared_ptr<Widget> remove(Widget& w);

	/**
	 * @brief Remove child from container.
	 * This function invalidates iterators which were obtained before calling to it.
	 * @param child - iterator of the child to remove.
	 * @return iterator pointing to the next child after removed one.
	 */
	list::const_iterator erase(list::const_iterator child);

	/**
	 * @brief Remove all child widgets.
	 * This function invalidates iterators which were obtained before calling to it.
	 */
	void clear();

	/**
	 * @brief Try get widget by id.
	 * It searches through the whole widget sub-hierarchy, not just direct children of this container.
	 * @param id - id of the child widget to look for.
	 * @return pointer to widget with given id if found.
	 * @return nullptr if there is no widget with given id found.
	 */
	std::shared_ptr<Widget> try_get_widget(const std::string& id)noexcept override;

	/**
	 * @brief Get list of child widgets.
	 * @return List of child widgets.
	 */
	const list& children()noexcept{
		return this->children_v.variable;
	}

	/**
	 * @brief Get constant list of child widgets.
	 * @return Constant list of child widgets.
	 */
	const const_list& children()const noexcept{
		// TRACE(<< "sizeof(list::value_type) = " << sizeof(list::value_type) << std::endl)
		// TRACE(<< "sizeof(const_list::value_type) = " << sizeof(const_list::value_type) << std::endl)
		return this->children_v.constant;
	}

	/**
	 * @brief Find widget in the list of container's children.
	 * @param w - child widget to find.
	 * @return iterator for child widget.
	 * @return end iterator if given widget was not found from the list of container's children.
	 */
	list::const_iterator find(const Widget* w);

	/**
	 * @brief Find widget in the list of container's children.
	 * @param w - child widget to find.
	 * @return iterator for child widget.
	 * @return end iterator if given widget was not found from the list of container's children.
	 */
	const_list::const_iterator find(const Widget* w)const;

	/**
	 * @brief Recursively find all widgets of given type.
	 * @return list of widgets found.
	 */
	template <class T> std::vector<std::shared_ptr<T>> get_all_widgets(){
		std::vector<std::shared_ptr<T>> ret;

		if(auto t = std::dynamic_pointer_cast<T>(this->sharedFromThis(this))){
			ret.emplace_back(t);
		}

		for(auto& child : this->children()){
			if(auto c = std::dynamic_pointer_cast<Container>(child)){
				auto res = c->get_all_widgets<T>();
				ret.insert(
						ret.end(),
						std::make_move_iterator(res.begin()),
						std::make_move_iterator(res.end())
					);
			}else if(auto c = std::dynamic_pointer_cast<T>(child)){
				ret.emplace_back(std::move(c));
			}
		}
		return ret;
	}

	/**
	 * @brief Called when children list changes.
	 * This implementation requests re-layout.
     */
	virtual void onChildrenListChanged(){
		this->setRelayoutNeeded();
	}
};

template <class T> T* Widget::findAncestor(const char* name){
	if(!this->parent()){
		return nullptr;
	}

	auto p = dynamic_cast<T*>(this->parent());

	if(p){
		if(!name || p->id == name){
			return p;
		}
	}

	return this->parent()->findAncestor<T>();
}

}
<|endoftext|>


<commit_before>/*
 * FogLAMP category management
 *
 * Copyright (c) 2018 Dianomic Systems
 *
 * Released under the Apache 2.0 Licence
 *
 * Author: Mark Riddoch
 */
#include <config_category.h>
#include <string>
#include <rapidjson/document.h>
#include <sstream>
#include <iostream>
#include <time.h>
#include <stdlib.h>

using namespace std;
using namespace rapidjson;

/**
 * Construct a ConfigCategories object from a JSON document returned from
 * the FogLAMP configuratrion service.
 */
ConfigCategories::ConfigCategories(const std::string& json)
{
	Document doc;
	doc.Parse(json.c_str());
	if (doc.HasParseError())
	{
		throw new exception();
	}
	if (doc.HasMember("categories"))
	{
		const Value& categories = doc["categories"];
		if (categories.IsArray())
		{
			// Process every rows and create the result set
			for (auto& cat : categories.GetArray())
			{
				if (!cat.IsObject())
				{
					throw new exception();
				}
				ConfigCategoryDescription *value = new ConfigCategoryDescription(cat["key"].GetString(),
							cat["description"].GetString());
				m_categories.push_back(value);
			}
		}
		else
		{
			throw new exception();
		}
	}
}

/**
 * ConfigCategories destructor
 */
ConfigCategories::~ConfigCategories()
{
	for (auto it = m_categories.cbegin(); it != m_categories.cend(); it++)
	{
		delete *it;
	}
}

/**
 * Configuration Category constructor
 *
 * @param name	The name of the configuration category
 * @param json	JSON content of the configuration category
 */
ConfigCategory::ConfigCategory(const string& name, const string& json) : m_name(name)
{
	Document doc;
	doc.Parse(json.c_str());
	if (doc.HasParseError())
	{
		throw new exception();
	}
	for (Value::ConstMemberIterator itr = doc.MemberBegin(); itr != doc.MemberEnd(); ++itr)
	{
		m_items.push_back(new CategoryItem(itr->name.GetString(), itr->value));
	}
}

/**
 * Configuration category destructor
 */
ConfigCategory::~ConfigCategory()
{
	for (auto it = m_items.cbegin(); it != m_items.cend(); it++)
	{
		delete *it;
	}
}

/**
 * Check for the existance of an item within the configuration category
 *
 * @param name	Item name to check within the category
 */
bool ConfigCategory::itemExists(const string& name) const
{
	for (int i = 0; i < m_items.size(); i++)
	{
		if (name.compare(m_items[i]->m_name) == 0)
		{
			return true;
		}
	}
	return false;
}

/**
 * Return the value of the configuration category item
 *
 * @param name	The name of the configuration item to return
 * @return string	The configuration item name
 * @throws exception if the item does not exist in the category
 */
string ConfigCategory::getValue(const string& name) const
{
	for (int i = 0; i < m_items.size(); i++)
	{
		if (name.compare(m_items[i]->m_name) == 0)
		{
			return m_items[i]->m_value;
		}
	}
	throw new exception;
}

/**
 * Return the type of the configuration category item
 *
 * @param name	The name of the configuration item to return
 * @return string	The configuration item name
 * @throws exception if the item does not exist in the category
 */
string ConfigCategory::getType(const string& name) const
{
	for (int i = 0; i < m_items.size(); i++)
	{
		if (name.compare(m_items[i]->m_name) == 0)
		{
			return m_items[i]->m_type;
		}
	}
	throw new exception;
}

/**
 * Return the description of the configuration category item
 *
 * @param name	The name of the configuration item to return
 * @return string	The configuration item name
 * @throws exception if the item does not exist in the category
 */
string ConfigCategory::getDescription(const string& name) const
{
	for (int i = 0; i < m_items.size(); i++)
	{
		if (name.compare(m_items[i]->m_name) == 0)
		{
			return m_items[i]->m_description;
		}
	}
	throw new exception;
}

/**
 * Return the default value of the configuration category item
 *
 * @param name	The name of the configuration item to return
 * @return string	The configuration item name
 * @throws exception if the item does not exist in the category
 */
string ConfigCategory::getDefault(const string& name) const
{
	for (int i = 0; i < m_items.size(); i++)
	{
		if (name.compare(m_items[i]->m_name) == 0)
		{
			return m_items[i]->m_default;
		}
	}
	throw new exception;
}

/**
 * Set the description for the configuration category
 *
 * @param description	The configuration category description
 */
void ConfigCategory::setDescription(const string& description)
{
	m_description = description;
}

string ConfigCategory::toJSON() const
{
ostringstream convert;

	convert << "{ \"key\" : \"" << m_name << "\", ";
	convert << "\"description\" : \"" << m_description << "\", ";
	for (auto it = m_items.cbegin(); it != m_items.cend(); it++)
	{
		convert << (*it)->toJSON();
		if (it + 1 != m_items.cend() )
		{
			convert << ", ";
		}
	}
	convert << "}";
	return convert.str();
}

/**
 * Constructor for a configuration item
 */
ConfigCategory::CategoryItem::CategoryItem(const string& name, const Value& item)
{
	m_name = name;
	if (! item.IsObject())
	{
		throw new exception();
	}
	if (item.HasMember("type"))
		m_type = item["type"].GetString();
	else
		m_type = "";
	if (item.HasMember("description"))
		m_description = item["description"].GetString();
	else
		m_description = "";
	if (item.HasMember("value"))
		m_value = item["value"].GetString();
	else
		m_value = "";
	if (item.HasMember("default"))
		m_default = item["default"].GetString();
	else
		m_default = "";
}

/**
 * Create a JSON representation of the configuration item
 */
string ConfigCategory::CategoryItem::toJSON() const
{
ostringstream convert;

	convert << "\"" << m_name << "\" : { ";
	convert << "\"description\" : \"" << m_description << "\", ";
	convert << "\"type\" : \"" << m_type << "\", ";
	convert << "\"value\" : \"" << m_value << "\", ";
	convert << "\"default\" : \"" << m_default << "\" }";
	return convert.str();
}
<commit_msg>FOGL_1330: fix JSON config creation<commit_after>/*
 * FogLAMP category management
 *
 * Copyright (c) 2018 Dianomic Systems
 *
 * Released under the Apache 2.0 Licence
 *
 * Author: Mark Riddoch
 */
#include <config_category.h>
#include <string>
#include <rapidjson/document.h>
#include <sstream>
#include <iostream>
#include <time.h>
#include <stdlib.h>

using namespace std;
using namespace rapidjson;

/**
 * Construct a ConfigCategories object from a JSON document returned from
 * the FogLAMP configuratrion service.
 */
ConfigCategories::ConfigCategories(const std::string& json)
{
	Document doc;
	doc.Parse(json.c_str());
	if (doc.HasParseError())
	{
		throw new exception();
	}
	if (doc.HasMember("categories"))
	{
		const Value& categories = doc["categories"];
		if (categories.IsArray())
		{
			// Process every rows and create the result set
			for (auto& cat : categories.GetArray())
			{
				if (!cat.IsObject())
				{
					throw new exception();
				}
				ConfigCategoryDescription *value = new ConfigCategoryDescription(cat["key"].GetString(),
							cat["description"].GetString());
				m_categories.push_back(value);
			}
		}
		else
		{
			throw new exception();
		}
	}
}

/**
 * ConfigCategories destructor
 */
ConfigCategories::~ConfigCategories()
{
	for (auto it = m_categories.cbegin(); it != m_categories.cend(); it++)
	{
		delete *it;
	}
}

/**
 * Configuration Category constructor
 *
 * @param name	The name of the configuration category
 * @param json	JSON content of the configuration category
 */
ConfigCategory::ConfigCategory(const string& name, const string& json) : m_name(name)
{
	Document doc;
	doc.Parse(json.c_str());
	if (doc.HasParseError())
	{
		throw new exception();
	}
	for (Value::ConstMemberIterator itr = doc.MemberBegin(); itr != doc.MemberEnd(); ++itr)
	{
		m_items.push_back(new CategoryItem(itr->name.GetString(), itr->value));
	}
}

/**
 * Configuration category destructor
 */
ConfigCategory::~ConfigCategory()
{
	for (auto it = m_items.cbegin(); it != m_items.cend(); it++)
	{
		delete *it;
	}
}

/**
 * Check for the existance of an item within the configuration category
 *
 * @param name	Item name to check within the category
 */
bool ConfigCategory::itemExists(const string& name) const
{
	for (int i = 0; i < m_items.size(); i++)
	{
		if (name.compare(m_items[i]->m_name) == 0)
		{
			return true;
		}
	}
	return false;
}

/**
 * Return the value of the configuration category item
 *
 * @param name	The name of the configuration item to return
 * @return string	The configuration item name
 * @throws exception if the item does not exist in the category
 */
string ConfigCategory::getValue(const string& name) const
{
	for (int i = 0; i < m_items.size(); i++)
	{
		if (name.compare(m_items[i]->m_name) == 0)
		{
			return m_items[i]->m_value;
		}
	}
	throw new exception;
}

/**
 * Return the type of the configuration category item
 *
 * @param name	The name of the configuration item to return
 * @return string	The configuration item name
 * @throws exception if the item does not exist in the category
 */
string ConfigCategory::getType(const string& name) const
{
	for (int i = 0; i < m_items.size(); i++)
	{
		if (name.compare(m_items[i]->m_name) == 0)
		{
			return m_items[i]->m_type;
		}
	}
	throw new exception;
}

/**
 * Return the description of the configuration category item
 *
 * @param name	The name of the configuration item to return
 * @return string	The configuration item name
 * @throws exception if the item does not exist in the category
 */
string ConfigCategory::getDescription(const string& name) const
{
	for (int i = 0; i < m_items.size(); i++)
	{
		if (name.compare(m_items[i]->m_name) == 0)
		{
			return m_items[i]->m_description;
		}
	}
	throw new exception;
}

/**
 * Return the default value of the configuration category item
 *
 * @param name	The name of the configuration item to return
 * @return string	The configuration item name
 * @throws exception if the item does not exist in the category
 */
string ConfigCategory::getDefault(const string& name) const
{
	for (int i = 0; i < m_items.size(); i++)
	{
		if (name.compare(m_items[i]->m_name) == 0)
		{
			return m_items[i]->m_default;
		}
	}
	throw new exception;
}

/**
 * Set the description for the configuration category
 *
 * @param description	The configuration category description
 */
void ConfigCategory::setDescription(const string& description)
{
	m_description = description;
}

string ConfigCategory::toJSON() const
{
ostringstream convert;

	convert << "{ \"key\" : \"" << m_name << "\", ";
	convert << "\"description\" : \"" << m_description << "\", \"value\" : {";
	for (auto it = m_items.cbegin(); it != m_items.cend(); it++)
	{
		convert << (*it)->toJSON();
		if (it + 1 != m_items.cend() )
		{
			convert << ", ";
		}
	}
	convert << "} }";
	return convert.str();
}

/**
 * Constructor for a configuration item
 */
ConfigCategory::CategoryItem::CategoryItem(const string& name, const Value& item)
{
	m_name = name;
	if (! item.IsObject())
	{
		throw new exception();
	}
	if (item.HasMember("type"))
		m_type = item["type"].GetString();
	else
		m_type = "";
	if (item.HasMember("description"))
		m_description = item["description"].GetString();
	else
		m_description = "";
	if (item.HasMember("value"))
		m_value = item["value"].GetString();
	else
		m_value = "";
	if (item.HasMember("default"))
		m_default = item["default"].GetString();
	else
		m_default = "";
}

/**
 * Create a JSON representation of the configuration item
 */
string ConfigCategory::CategoryItem::toJSON() const
{
ostringstream convert;

	convert << "\"" << m_name << "\" : { ";
	convert << "\"description\" : \"" << m_description << "\", ";
	convert << "\"type\" : \"" << m_type << "\", ";
	convert << "\"value\" : \"" << m_value << "\", ";
	convert << "\"default\" : \"" << m_default << "\" }";
	return convert.str();
}
<|endoftext|>


<commit_before>/**
*  Copyright (C) 2015 3D Repo Ltd
*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU Affero General Public License as
*  published by the Free Software Foundation, either version 3 of the
*  License, or (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Affero General Public License for more details.
*
*  You should have received a copy of the GNU Affero General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/**
* Abstract optimizer class
*/

#include "repo_optimizer_ifc.h"
#include "../../core/model/bson/repo_bson_factory.h"
#include "../../core/model/bson/repo_node_transformation.h"
#include <algorithm>

using namespace repo::manipulator::modeloptimizer;
const static std::string IFC_MAPPED_ITEM = "IFCMAPPEDITEM";
const static std::string IFC_RELVOID_ELE = "$RELVOIDSELEMENT";
const static std::string IFC_RELVOID_ELE2 = "IFCRELVOIDSELEMENT";
const static std::string IFC_RELAGGREGATES = "$RELAGGREGATES";
const static std::string IFC_TYPE_SPACE = "IFCSPACE";

auto defaultG = repo::core::model::RepoScene::GraphType::DEFAULT;

IFCOptimzer::IFCOptimzer()
{
}

IFCOptimzer::~IFCOptimzer()
{
}

bool IFCOptimzer::apply(repo::core::model::RepoScene *scene)
{
	bool success = false;
	std::unordered_map<std::string, std::vector<repo::core::model::RepoNode*>> transByName;
	//sort transformations by name

	auto tranNodes = scene->getAllTransformations(defaultG);
	for (auto &trans : tranNodes)
	{
		auto name = trans->getName();
		std::transform(name.begin(), name.end(), name.begin(), ::toupper);
		if (transByName.find(name) == transByName.end())
		{
			transByName[name] = std::vector<repo::core::model::RepoNode*>();
		}

		transByName[name].push_back(trans);
	}

	std::vector<std::string> transToRemove = { IFC_MAPPED_ITEM, IFC_RELVOID_ELE, IFC_RELVOID_ELE2, IFC_RELAGGREGATES };
	success = removeTransformationsWithNames(scene, transByName, transToRemove);
	//TODO: group
	success &= sanitiseTransformationNames(scene);

	return success;
}

bool IFCOptimzer::removeTransformationsWithNames(
	repo::core::model::RepoScene *scene,
	const std::unordered_map<std::string, std::vector<repo::core::model::RepoNode*>>  &transByName,
	const std::vector<std::string> &names)
{
	bool success = true;
	for (const auto name : names)
	{
		auto it = transByName.find(name);
		if (it != transByName.end())
		{
			repoTrace << "Removing " << name << "s...";
			for (auto &node : it->second)
			{
				auto transNode = dynamic_cast<repo::core::model::TransformationNode *>(node);
				auto transSharedID = transNode->getSharedID();
				auto parents = transNode->getParentIDs();

				auto children = scene->getChildrenAsNodes(defaultG, transNode->getSharedID());
				auto trans = transNode->getTransMatrix(false);

				//Remove self from child
				for (auto &child : children)
				{
					if (child)
					{
						if (!transNode->isIdentity())
						{
							auto newChild = child->cloneAndApplyTransformation(trans);
							child->swap(newChild);
						}

						scene->abandonChild(defaultG, transSharedID, child, false, true);
					}
					else
					{
						repoError << "Child with nullpointer found";
						success = false;
					}
				}

				//Remove self from parent and  patch children to parents
				for (const auto &parent : parents)
				{
					auto parentNode = scene->getNodeBySharedID(defaultG, parent);

					if (parentNode)
					{
						//remove linkage to parent
						scene->abandonChild(defaultG, parent, transNode, true, false);
						for (auto &child : children)
						{
							scene->addInheritance(defaultG, parentNode, child);
						}
					}
					else
					{
						repoError << "Failed to find parent with id " << parent;
						success = false;
					}
				}

				scene->removeNode(defaultG, transSharedID);
			}
		}
	}
	return success;
}

bool IFCOptimzer::sanitiseTransformationNames(
	repo::core::model::RepoScene *scene)
{
	auto transformations = scene->getAllTransformations(defaultG);
	for (auto &trans : transformations)
	{
		//format of names: IFCTYPE_NAME_GUID
		auto name = trans->getName();
		auto posFirstUnderScore = name.find_first_of('_');
		auto posGuid = name.size() - 22;

		auto ifcType = name.substr(0, posFirstUnderScore);
		auto realName = name.substr(posFirstUnderScore + 1, posGuid - (posFirstUnderScore + 2));
		auto guid = name.substr(posGuid);

		auto ifcTypeUpper = ifcType;

		std::transform(ifcTypeUpper.begin(), ifcTypeUpper.end(), ifcTypeUpper.begin(), ::toupper);

		if (ifcTypeUpper == IFC_TYPE_SPACE)
		{
			realName += " " + IFC_TYPE_SPACE_LABEL;
		}

		auto newTrans = trans->cloneAndChangeName(realName, false);
		scene->modifyNode(defaultG, trans, &newTrans, true);

		repo::core::model::RepoBSON newMeta = BSON("IFC Type" << ifcType << "IFC GUID" << guid);

		//Check for metadata
		auto metas = scene->getChildrenNodesFiltered(defaultG, trans->getSharedID(), repo::core::model::NodeType::METADATA);
		if (metas.size())
		{
			//Metadata exists, append to them
			for (auto &meta : metas)
			{
				auto metaNode = dynamic_cast<repo::core::model::MetadataNode*>(meta);
				repo::core::model::RepoNode updatedMeta = metaNode->cloneAndAddMetadata(newMeta);
				scene->modifyNode(defaultG, meta, &updatedMeta, false);
			}
		}
		else
		{
			//no metadata, create one
			auto metaNode = new repo::core::model::MetadataNode(
				repo::core::model::RepoBSONFactory::makeMetaDataNode(newMeta, "", realName, { trans->getSharedID() }));
			std::vector<repo::core::model::RepoNode*> metaVec = { metaNode };
			scene->addNodes(metaVec);
		}
	}

	return true;
}<commit_msg>#131 rename meta data just like the transformation<commit_after>/**
*  Copyright (C) 2015 3D Repo Ltd
*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU Affero General Public License as
*  published by the Free Software Foundation, either version 3 of the
*  License, or (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Affero General Public License for more details.
*
*  You should have received a copy of the GNU Affero General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/**
* Abstract optimizer class
*/

#include "repo_optimizer_ifc.h"
#include "../../core/model/bson/repo_bson_factory.h"
#include "../../core/model/bson/repo_node_transformation.h"
#include <algorithm>

using namespace repo::manipulator::modeloptimizer;
const static std::string IFC_MAPPED_ITEM = "IFCMAPPEDITEM";
const static std::string IFC_RELVOID_ELE = "$RELVOIDSELEMENT";
const static std::string IFC_RELVOID_ELE2 = "IFCRELVOIDSELEMENT";
const static std::string IFC_RELAGGREGATES = "$RELAGGREGATES";
const static std::string IFC_TYPE_SPACE = "IFCSPACE";

auto defaultG = repo::core::model::RepoScene::GraphType::DEFAULT;

IFCOptimzer::IFCOptimzer()
{
}

IFCOptimzer::~IFCOptimzer()
{
}

bool IFCOptimzer::apply(repo::core::model::RepoScene *scene)
{
	bool success = false;
	std::unordered_map<std::string, std::vector<repo::core::model::RepoNode*>> transByName;
	//sort transformations by name

	auto tranNodes = scene->getAllTransformations(defaultG);
	for (auto &trans : tranNodes)
	{
		auto name = trans->getName();
		std::transform(name.begin(), name.end(), name.begin(), ::toupper);
		if (transByName.find(name) == transByName.end())
		{
			transByName[name] = std::vector<repo::core::model::RepoNode*>();
		}

		transByName[name].push_back(trans);
	}

	std::vector<std::string> transToRemove = { IFC_MAPPED_ITEM, IFC_RELVOID_ELE, IFC_RELVOID_ELE2, IFC_RELAGGREGATES };
	success = removeTransformationsWithNames(scene, transByName, transToRemove);
	//TODO: group
	success &= sanitiseTransformationNames(scene);

	return success;
}

bool IFCOptimzer::removeTransformationsWithNames(
	repo::core::model::RepoScene *scene,
	const std::unordered_map<std::string, std::vector<repo::core::model::RepoNode*>>  &transByName,
	const std::vector<std::string> &names)
{
	bool success = true;
	for (const auto name : names)
	{
		auto it = transByName.find(name);
		if (it != transByName.end())
		{
			repoTrace << "Removing " << name << "s...";
			for (auto &node : it->second)
			{
				auto transNode = dynamic_cast<repo::core::model::TransformationNode *>(node);
				auto transSharedID = transNode->getSharedID();
				auto parents = transNode->getParentIDs();

				auto children = scene->getChildrenAsNodes(defaultG, transNode->getSharedID());
				auto trans = transNode->getTransMatrix(false);

				//Remove self from child
				for (auto &child : children)
				{
					if (child)
					{
						if (!transNode->isIdentity())
						{
							auto newChild = child->cloneAndApplyTransformation(trans);
							child->swap(newChild);
						}

						scene->abandonChild(defaultG, transSharedID, child, false, true);
					}
					else
					{
						repoError << "Child with nullpointer found";
						success = false;
					}
				}

				//Remove self from parent and  patch children to parents
				for (const auto &parent : parents)
				{
					auto parentNode = scene->getNodeBySharedID(defaultG, parent);

					if (parentNode)
					{
						//remove linkage to parent
						scene->abandonChild(defaultG, parent, transNode, true, false);
						for (auto &child : children)
						{
							scene->addInheritance(defaultG, parentNode, child);
						}
					}
					else
					{
						repoError << "Failed to find parent with id " << parent;
						success = false;
					}
				}

				scene->removeNode(defaultG, transSharedID);
			}
		}
	}
	return success;
}

bool IFCOptimzer::sanitiseTransformationNames(
	repo::core::model::RepoScene *scene)
{
	auto transformations = scene->getAllTransformations(defaultG);
	for (auto &trans : transformations)
	{
		//format of names: IFCTYPE_NAME_GUID
		auto name = trans->getName();
		auto posFirstUnderScore = name.find_first_of('_');
		auto posGuid = name.size() - 22;

		auto ifcType = name.substr(0, posFirstUnderScore);
		auto realName = name.substr(posFirstUnderScore + 1, posGuid - (posFirstUnderScore + 2));
		auto guid = name.substr(posGuid);

		auto ifcTypeUpper = ifcType;

		std::transform(ifcTypeUpper.begin(), ifcTypeUpper.end(), ifcTypeUpper.begin(), ::toupper);

		if (ifcTypeUpper == IFC_TYPE_SPACE)
		{
			realName += " " + IFC_TYPE_SPACE_LABEL;
		}

		auto newTrans = trans->cloneAndChangeName(realName, false);
		scene->modifyNode(defaultG, trans, &newTrans, true);

		repo::core::model::RepoBSON newMeta = BSON("IFC Type" << ifcType << "IFC GUID" << guid);

		//Check for metadata
		auto metas = scene->getChildrenNodesFiltered(defaultG, trans->getSharedID(), repo::core::model::NodeType::METADATA);
		if (metas.size())
		{
			//Metadata exists, append to them
			for (auto &meta : metas)
			{
				auto metaNode = dynamic_cast<repo::core::model::MetadataNode*>(meta);
				repo::core::model::RepoNode updatedMeta = metaNode->cloneAndAddMetadata(newMeta);
				updatedMeta = metaNode->cloneAndChangeName(realName, false);
				scene->modifyNode(defaultG, meta, &updatedMeta, false);
			}
		}
		else
		{
			//no metadata, create one
			auto metaNode = new repo::core::model::MetadataNode(
				repo::core::model::RepoBSONFactory::makeMetaDataNode(newMeta, "", realName, { trans->getSharedID() }));
			std::vector<repo::core::model::RepoNode*> metaVec = { metaNode };
			scene->addNodes(metaVec);
		}
	}

	return true;
}<|endoftext|>


<commit_before>/**
 * \file    test-library.cpp
 * \brief   test code of C++ language for unit test framework
 * \author  Yunhui Fu (yhfudev@gmail.com)
 * \version 1.0
 * \date    2017-12-06
 * \copyright MIT License
 */
#include <stdio.h>
#include <string.h>
#include <unistd.h> // sleep
#include <stdlib.h>
#include <math.h>

#include <iostream>

/*#define CIUT_ENABLED 1 /**< user defined, a global macro defined to 1 to active the unit test code */

#if defined(CIUT_ENABLED) && (CIUT_ENABLED == 1)
#include <ciut.h>
#include <ciut-sio.h>

#define NUM_ARRAY(a) (sizeof(a)/sizeof((a)[0]))

TEST_CASE( .name="timeval", .description="Test the time functions." ) {

    SECTION("test timeval sub") {
        static struct timeval sub_data[] = {
            {0,   0}, {0,   0}, {0, 0},
            {0, 500}, {0, 500}, {0, 0},
            {1, 500}, {0, 500}, {1, 0},
        };
        size_t i;
        for (i = 0; i < NUM_ARRAY(sub_data); i += 3) {
            struct timeval ret;
            timeval_sub (&(sub_data[i + 0]), &(sub_data[i + 1]), &ret);
            CIUT_LOG("%" PRIuSZ ") %ld.%06ld - %ld.%06ld = ? %ld.%06ld", i / 3, sub_data[i + 0].tv_sec, sub_data[i + 0].tv_usec, sub_data[i + 1].tv_sec, sub_data[i + 1].tv_usec, sub_data[i + 2].tv_sec, sub_data[i + 2].tv_usec);
            REQUIRE((sub_data[i + 2].tv_sec == ret.tv_sec) && (sub_data[i + 2].tv_usec == ret.tv_usec));
        }
    }
}

#define msleep(microseconds) usleep((microseconds) * 1000);

TEST_CASE( .name="msleep", .description="Test measure time.", .skip=0 ) {
    SECTION("test measure time") {
        size_t sleeptime = 1000;
        size_t ret_millisecond = 0;
        TMC_BEGIN();
        msleep(sleeptime);
        TMC_END(ret_millisecond);
        CIUT_LOG ("sleep milli seconds=%" PRIuSZ, ret_millisecond);
        REQUIRE (abs((int)ret_millisecond - (int)sleeptime) <= sleeptime/5);
    }
}

MYLOG_GLOBAL_INIT;

TEST_CASE( .name="log-MLT", .description="Test log.", .skip=0 ) {
    SECTION("test log") {
        MYLOG_INIT_2STDERR();
        MLT("the network port=%d", 1);
    }
}

static int
cb_cuit_check_output_sio (FILE * outf, void * user_arg)
{
    char * msg = (char *)user_arg;
    assert (NULL != msg);
    fprintf(outf, "%s", msg);
    return 0;
}

TEST_CASE( .name="ciutsio", .description="Test ciut sio." ) {
    SECTION("test cuit_check_output") {
#define CSTR_TEST1 ""
        REQUIRE(0 == cuit_check_output(cb_cuit_check_output_sio, (void *)CSTR_TEST1, CSTR_TEST1));
#undef CSTR_TEST1
#define CSTR_TEST1 "this is my test string 1123243."
        REQUIRE(0 == cuit_check_output(cb_cuit_check_output_sio, (void *)CSTR_TEST1, CSTR_TEST1));
#undef CSTR_TEST1
    }
}

#ifndef _WIN32
// test uclog.h
TEST_CASE( .name="log-writer", .description="Test log writer." ) {

    SECTION("test log writer") {
        REQUIRE(0 == writer(NULL, NULL, 0));
        REQUIRE(0 == writer(NULL, "", 0));
        REQUIRE(0 == writer(NULL, "abc", 0));
        REQUIRE(3 == writer(NULL, "abc", 3));
        REQUIRE(0 == noop1(NULL, NULL, 0));
        REQUIRE(0 == noop3(NULL, NULL, 0));
        REQUIRE(0 == noop4(NULL));
    }

    SECTION("test C++ log buffer") {
        std::clog.rdbuf(new Syslog::sbuf("foo", LOG_LOCAL0));
        std::clog << Syslog::Notice << "myprog-E-net-0003 test log message" << std::endl;
        std::clog << "myprog-E-net-0003 the default is debug level" << std::endl;
    }

    // example1: to syslog
    SECTION("test C log syslog") {
        setlogmask (LOG_UPTO (LOG_NOTICE));
        openlog ("myapp", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
        MYLOG_INIT_2SYSLOG(); // OR: fsyslog(&stderr); MYLOG_INIT_2STDERR();
        MLT("the network port=%d", 1);
        MLF("myapp-F-net-3013 network failed!");
        closelog ();
    }
    SECTION("test C log stderr") {
        MYLOG_INIT_2STDERR();
        MLT("the network port=%d", 1);
    }

}

#endif

#endif /* CIUT_ENABLED */

<commit_msg>remove test time<commit_after>/**
 * \file    test-library.cpp
 * \brief   test code of C++ language for unit test framework
 * \author  Yunhui Fu (yhfudev@gmail.com)
 * \version 1.0
 * \date    2017-12-06
 * \copyright MIT License
 */
#include <stdio.h>
#include <string.h>
#include <unistd.h> // sleep
#include <stdlib.h>
#include <math.h>

#include <iostream>

/*#define CIUT_ENABLED 1 /**< user defined, a global macro defined to 1 to active the unit test code */

#if defined(CIUT_ENABLED) && (CIUT_ENABLED == 1)
#include <ciut.h>
#include <ciut-sio.h>

#define NUM_ARRAY(a) (sizeof(a)/sizeof((a)[0]))

TEST_CASE( .name="timeval", .description="Test the time functions." ) {

    SECTION("test timeval sub") {
        static struct timeval sub_data[] = {
            {0,   0}, {0,   0}, {0, 0},
            {0, 500}, {0, 500}, {0, 0},
            {1, 500}, {0, 500}, {1, 0},
        };
        size_t i;
        for (i = 0; i < NUM_ARRAY(sub_data); i += 3) {
            struct timeval ret;
            timeval_sub (&(sub_data[i + 0]), &(sub_data[i + 1]), &ret);
            CIUT_LOG("%" PRIuSZ ") %ld.%06ld - %ld.%06ld = ? %ld.%06ld", i / 3, sub_data[i + 0].tv_sec, sub_data[i + 0].tv_usec, sub_data[i + 1].tv_sec, sub_data[i + 1].tv_usec, sub_data[i + 2].tv_sec, sub_data[i + 2].tv_usec);
            REQUIRE((sub_data[i + 2].tv_sec == ret.tv_sec) && (sub_data[i + 2].tv_usec == ret.tv_usec));
        }
    }
}

#define msleep(microseconds) usleep((microseconds) * 1000);

#if 0
TEST_CASE( .name="msleep", .description="Test measure time.", .skip=1 ) {
    SECTION("test measure time") {
        size_t sleeptime = 1000;
        size_t ret_millisecond = 0;
        TMC_BEGIN();
        msleep(sleeptime);
        TMC_END(ret_millisecond);
        CIUT_LOG ("sleep milli seconds=%" PRIuSZ, ret_millisecond);
        REQUIRE (abs((int)ret_millisecond - (int)sleeptime) <= sleeptime/10);
    }
}
#endif

MYLOG_GLOBAL_INIT;

TEST_CASE( .name="log-MLT", .description="Test log.", .skip=0 ) {
    SECTION("test log") {
        MYLOG_INIT_2STDERR();
        MLT("the network port=%d", 1);
    }
}

static int
cb_cuit_check_output_sio (FILE * outf, void * user_arg)
{
    char * msg = (char *)user_arg;
    assert (NULL != msg);
    fprintf(outf, "%s", msg);
    return 0;
}

TEST_CASE( .name="ciutsio", .description="Test ciut sio." ) {
    SECTION("test cuit_check_output") {
#define CSTR_TEST1 ""
        REQUIRE(0 == cuit_check_output(cb_cuit_check_output_sio, (void *)CSTR_TEST1, CSTR_TEST1));
#undef CSTR_TEST1
#define CSTR_TEST1 "this is my test string 1123243."
        REQUIRE(0 == cuit_check_output(cb_cuit_check_output_sio, (void *)CSTR_TEST1, CSTR_TEST1));
#undef CSTR_TEST1
    }
}

#ifndef _WIN32
// test uclog.h
TEST_CASE( .name="log-writer", .description="Test log writer." ) {

    SECTION("test log writer") {
        REQUIRE(0 == writer(NULL, NULL, 0));
        REQUIRE(0 == writer(NULL, "", 0));
        REQUIRE(0 == writer(NULL, "abc", 0));
        REQUIRE(3 == writer(NULL, "abc", 3));
        REQUIRE(0 == noop1(NULL, NULL, 0));
        REQUIRE(0 == noop3(NULL, NULL, 0));
        REQUIRE(0 == noop4(NULL));
    }

    SECTION("test C++ log buffer") {
        std::clog.rdbuf(new Syslog::sbuf("foo", LOG_LOCAL0));
        std::clog << Syslog::Notice << "myprog-E-net-0003 test log message" << std::endl;
        std::clog << "myprog-E-net-0003 the default is debug level" << std::endl;
    }

    // example1: to syslog
    SECTION("test C log syslog") {
        setlogmask (LOG_UPTO (LOG_NOTICE));
        openlog ("myapp", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
        MYLOG_INIT_2SYSLOG(); // OR: fsyslog(&stderr); MYLOG_INIT_2STDERR();
        MLT("the network port=%d", 1);
        MLF("myapp-F-net-3013 network failed!");
        closelog ();
    }
    SECTION("test C log stderr") {
        MYLOG_INIT_2STDERR();
        MLT("the network port=%d", 1);
    }

}

#endif

#endif /* CIUT_ENABLED */

<|endoftext|>


<commit_before>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2020  The Symbiflow Authors
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#include <algorithm>
#include "clocks.h"
#include "kernel/log.h"
#include "kernel/register.h"
#include "kernel/rtlil.h"
#include "propagation.h"

USING_YOSYS_NAMESPACE

PRIVATE_NAMESPACE_BEGIN

struct ReadSdcCmd : public Frontend {
    ReadSdcCmd() : Frontend("sdc", "Read SDC file") {}

    void help() override {
	//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
	log("\n");
	log("    read_sdc <filename>\n");
	log("\n");
	log("Read SDC file.\n");
	log("\n");
    }

    void execute(std::istream*& f, std::string filename,
                 std::vector<std::string> args, RTLIL::Design*) override {
	if (args.size() < 2) {
	    log_cmd_error("Missing script file.\n");
	}
	size_t argidx = 1;
	extra_args(f, filename, args, argidx);
	std::string content{std::istreambuf_iterator<char>(*f),
	                    std::istreambuf_iterator<char>()};
	log("%s\n", content.c_str());
	Tcl_Interp* interp = yosys_get_tcl_interp();
	if (Tcl_EvalFile(interp, args[argidx].c_str()) != TCL_OK) {
	    log_cmd_error("TCL interpreter returned an error: %s\n",
	                  Tcl_GetStringResult(interp));
	}
    }
};

struct CreateClockCmd : public Pass {
    CreateClockCmd(Clocks& clocks)
        : Pass("create_clock", "Create clock object"), clocks_(clocks) {}

    void help() override {
	log("\n");
	log("    create_clock [ -name clock_name ] -period period_value "
	    "[-waveform <edge_list>] <target>\n");
	log("Define a clock.\n");
	log("If name is not specified then the name of the first target is "
	    "selected as the clock's name.\n");
	log("Period is expressed in nanoseconds.\n");
	log("The waveform option specifies the duty cycle (the rising a "
	    "falling edges) of the clock.\n");
	log("It is specified as a list of two elements/time values: the first "
	    "rising edge and the next falling edge.\n");
	log("\n");
    }

    void execute(std::vector<std::string> args,
                 RTLIL::Design* design) override {
	size_t argidx;
	std::string name;
	float rising_edge(0);
	float falling_edge(0);
	float period(0);
	if (args.size() < 4) {
	    log_cmd_error("Incorrect number of arguments\n");
	}
	for (argidx = 1; argidx < args.size(); argidx++) {
	    std::string arg = args[argidx];
	    if (arg == "-name" && argidx + 1 < args.size()) {
		name = args[++argidx];
		continue;
	    }
	    if (arg == "-period" && argidx + 1 < args.size()) {
		period = std::stof(args[++argidx]);
		continue;
	    }
	    if (arg == "-waveform" && argidx + 1 < args.size()) {
		std::string edges(args[++argidx]);
		std::copy_if(edges.begin(), edges.end(), edges.begin(),
		             [](char c) { return c != '{' or c != '}'; });
		std::stringstream ss(edges);
		ss >> rising_edge >> falling_edge;
		continue;
	    }
	    break;
	}
	if (period <= 0) {
	    log_cmd_error("Incorrect period value\n");
	}
	// Add "w:" prefix to selection arguments to enforce wire object
	// selection
	AddWirePrefix(args, argidx);
	extra_args(args, argidx, design);
	// If clock name is not specified then take the name of the first target
	std::vector<RTLIL::Wire*> selected_wires;
	for (auto module : design->modules()) {
	    if (!design->selected(module)) {
		continue;
	    }
	    for (auto wire : module->wires()) {
		if (design->selected(module, wire)) {
		    log("Selected wire %s\n", wire->name.c_str());
		    selected_wires.push_back(wire);
		}
	    }
	}
	if (selected_wires.size() == 0) {
	    log_cmd_error("Target selection is empty\n");
	}
	if (name.empty()) {
	    name = selected_wires.at(0)->name.str();
	}
	clocks_.AddClockWires(name, selected_wires, period, rising_edge,
	                      falling_edge);
	log("Created clock %s with period %f, waveform %f,%f\n", name.c_str(),
	    period, rising_edge, falling_edge);
    }

    void AddWirePrefix(std::vector<std::string>& args, size_t argidx) {
	auto selection_begin = args.begin() + argidx;
	std::transform(selection_begin, args.end(), selection_begin,
	               [](std::string& w) { return "w:" + w; });
    }

    Clocks& clocks_;
};

struct GetClocksCmd : public Pass {
    GetClocksCmd(Clocks& clocks)
        : Pass("get_clocks", "Create clock object"), clocks_(clocks) {}

    void help() override {
	log("\n");
	log("    get_clocks\n");
	log("\n");
	log("Returns all clocks in the design.\n");
	log("\n");
    }

    void execute(__attribute__((unused)) std::vector<std::string> args,
                 __attribute__((unused)) RTLIL::Design* design) override {
	std::vector<std::string> clock_names(clocks_.GetClockNames());
	if (clock_names.size() == 0) {
	    log_warning("No clocks found in design\n");
	}
	Tcl_Interp* interp = yosys_get_tcl_interp();
	Tcl_Obj* tcl_list = Tcl_NewListObj(0, NULL);
	for (auto name : clock_names) {
	    Tcl_Obj* name_obj = Tcl_NewStringObj(name.c_str(), name.size());
	    Tcl_ListObjAppendElement(interp, tcl_list, name_obj);
	}
	Tcl_SetObjResult(interp, tcl_list);
    }

    Clocks& clocks_;
};

struct PropagateClocksCmd : public Pass {
    PropagateClocksCmd(Clocks& clocks)
        : Pass("propagate_clocks", "Propagate clock information"),
          clocks_(clocks) {}

    void help() override {
	log("\n");
	log("    propagate_clocks\n");
	log("\n");
	log("Propagate clock information throughout the design.\n");
	log("\n");
    }

    void execute(__attribute__((unused)) std::vector<std::string> args,
                 RTLIL::Design* design) override {
	if (!design->top_module()) {
	    log_cmd_error("No top module selected\n");
	}

	std::array<std::unique_ptr<Propagation>, 3> passes{
	    std::unique_ptr<NaturalPropagation>(
	        new NaturalPropagation(design, this)),
	    std::unique_ptr<BufferPropagation>(new BufferPropagation(design, this)),
	    std::unique_ptr<ClockDividerPropagation>(new ClockDividerPropagation(design, this))};

	for (auto& pass : passes) {
	    pass->Run(clocks_);
	}
    }

    Clocks& clocks_;
};

class SdcPlugin {
   public:
    SdcPlugin()
        : create_clock_cmd_(clocks_),
          get_clocks_cmd_(clocks_),
          propagate_clocks_cmd_(clocks_) {
	log("Loaded SDC plugin\n");
    }

    ReadSdcCmd read_sdc_cmd_;
    CreateClockCmd create_clock_cmd_;
    GetClocksCmd get_clocks_cmd_;
    PropagateClocksCmd propagate_clocks_cmd_;

   private:
    Clocks clocks_;
} SdcPlugin;

PRIVATE_NAMESPACE_END
<commit_msg>SDC: Inform about SDC being read<commit_after>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2020  The Symbiflow Authors
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#include <algorithm>
#include "clocks.h"
#include "kernel/log.h"
#include "kernel/register.h"
#include "kernel/rtlil.h"
#include "propagation.h"

USING_YOSYS_NAMESPACE

PRIVATE_NAMESPACE_BEGIN

struct ReadSdcCmd : public Frontend {
    ReadSdcCmd() : Frontend("sdc", "Read SDC file") {}

    void help() override {
	//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
	log("\n");
	log("    read_sdc <filename>\n");
	log("\n");
	log("Read SDC file.\n");
	log("\n");
    }

    void execute(std::istream*& f, std::string filename,
                 std::vector<std::string> args, RTLIL::Design*) override {
	if (args.size() < 2) {
	    log_cmd_error("Missing script file.\n");
	}
	log("\nReading clock constraints file(SDC)\n\n");
	size_t argidx = 1;
	extra_args(f, filename, args, argidx);
	std::string content{std::istreambuf_iterator<char>(*f),
	                    std::istreambuf_iterator<char>()};
	log("%s\n", content.c_str());
	Tcl_Interp* interp = yosys_get_tcl_interp();
	if (Tcl_EvalFile(interp, args[argidx].c_str()) != TCL_OK) {
	    log_cmd_error("TCL interpreter returned an error: %s\n",
	                  Tcl_GetStringResult(interp));
	}
    }
};

struct CreateClockCmd : public Pass {
    CreateClockCmd(Clocks& clocks)
        : Pass("create_clock", "Create clock object"), clocks_(clocks) {}

    void help() override {
	log("\n");
	log("    create_clock [ -name clock_name ] -period period_value "
	    "[-waveform <edge_list>] <target>\n");
	log("Define a clock.\n");
	log("If name is not specified then the name of the first target is "
	    "selected as the clock's name.\n");
	log("Period is expressed in nanoseconds.\n");
	log("The waveform option specifies the duty cycle (the rising a "
	    "falling edges) of the clock.\n");
	log("It is specified as a list of two elements/time values: the first "
	    "rising edge and the next falling edge.\n");
	log("\n");
    }

    void execute(std::vector<std::string> args,
                 RTLIL::Design* design) override {
	size_t argidx;
	std::string name;
	float rising_edge(0);
	float falling_edge(0);
	float period(0);
	if (args.size() < 4) {
	    log_cmd_error("Incorrect number of arguments\n");
	}
	for (argidx = 1; argidx < args.size(); argidx++) {
	    std::string arg = args[argidx];
	    if (arg == "-name" && argidx + 1 < args.size()) {
		name = args[++argidx];
		continue;
	    }
	    if (arg == "-period" && argidx + 1 < args.size()) {
		period = std::stof(args[++argidx]);
		continue;
	    }
	    if (arg == "-waveform" && argidx + 1 < args.size()) {
		std::string edges(args[++argidx]);
		std::copy_if(edges.begin(), edges.end(), edges.begin(),
		             [](char c) { return c != '{' or c != '}'; });
		std::stringstream ss(edges);
		ss >> rising_edge >> falling_edge;
		continue;
	    }
	    break;
	}
	if (period <= 0) {
	    log_cmd_error("Incorrect period value\n");
	}
	// Add "w:" prefix to selection arguments to enforce wire object
	// selection
	AddWirePrefix(args, argidx);
	extra_args(args, argidx, design);
	// If clock name is not specified then take the name of the first target
	std::vector<RTLIL::Wire*> selected_wires;
	for (auto module : design->modules()) {
	    if (!design->selected(module)) {
		continue;
	    }
	    for (auto wire : module->wires()) {
		if (design->selected(module, wire)) {
#ifdef SDC_DEBUG
		    log("Selected wire %s\n", RTLIL::unescape_id(wire->name).c_str());
#endif
		    selected_wires.push_back(wire);
		}
	    }
	}
	if (selected_wires.size() == 0) {
	    log_cmd_error("Target selection is empty\n");
	}
	if (name.empty()) {
	    name = RTLIL::unescape_id(selected_wires.at(0)->name);
	}
	clocks_.AddClockWires(name, selected_wires, period, rising_edge,
	                      falling_edge);
	log("Created clock %s with period %f, waveform {%f %f}\n", name.c_str(),
	    period, rising_edge, falling_edge);
    }

    void AddWirePrefix(std::vector<std::string>& args, size_t argidx) {
	auto selection_begin = args.begin() + argidx;
	std::transform(selection_begin, args.end(), selection_begin,
	               [](std::string& w) { return "w:" + w; });
    }

    Clocks& clocks_;
};

struct GetClocksCmd : public Pass {
    GetClocksCmd(Clocks& clocks)
        : Pass("get_clocks", "Create clock object"), clocks_(clocks) {}

    void help() override {
	log("\n");
	log("    get_clocks\n");
	log("\n");
	log("Returns all clocks in the design.\n");
	log("\n");
    }

    void execute(__attribute__((unused)) std::vector<std::string> args,
                 __attribute__((unused)) RTLIL::Design* design) override {
	std::vector<std::string> clock_names(clocks_.GetClockNames());
	if (clock_names.size() == 0) {
	    log_warning("No clocks found in design\n");
	}
	Tcl_Interp* interp = yosys_get_tcl_interp();
	Tcl_Obj* tcl_list = Tcl_NewListObj(0, NULL);
	for (auto name : clock_names) {
	    Tcl_Obj* name_obj = Tcl_NewStringObj(name.c_str(), name.size());
	    Tcl_ListObjAppendElement(interp, tcl_list, name_obj);
	}
	Tcl_SetObjResult(interp, tcl_list);
    }

    Clocks& clocks_;
};

struct PropagateClocksCmd : public Pass {
    PropagateClocksCmd(Clocks& clocks)
        : Pass("propagate_clocks", "Propagate clock information"),
          clocks_(clocks) {}

    void help() override {
	log("\n");
	log("    propagate_clocks\n");
	log("\n");
	log("Propagate clock information throughout the design.\n");
	log("\n");
    }

    void execute(__attribute__((unused)) std::vector<std::string> args,
                 RTLIL::Design* design) override {
	if (!design->top_module()) {
	    log_cmd_error("No top module selected\n");
	}

	std::array<std::unique_ptr<Propagation>, 3> passes{
	    std::unique_ptr<NaturalPropagation>(
	        new NaturalPropagation(design, this)),
	    std::unique_ptr<BufferPropagation>(new BufferPropagation(design, this)),
	    std::unique_ptr<ClockDividerPropagation>(new ClockDividerPropagation(design, this))};

	for (auto& pass : passes) {
	    pass->Run(clocks_);
	}
    }

    Clocks& clocks_;
};

class SdcPlugin {
   public:
    SdcPlugin()
        : create_clock_cmd_(clocks_),
          get_clocks_cmd_(clocks_),
          propagate_clocks_cmd_(clocks_) {
	log("Loaded SDC plugin\n");
    }

    ReadSdcCmd read_sdc_cmd_;
    CreateClockCmd create_clock_cmd_;
    GetClocksCmd get_clocks_cmd_;
    PropagateClocksCmd propagate_clocks_cmd_;

   private:
    Clocks clocks_;
} SdcPlugin;

PRIVATE_NAMESPACE_END
<|endoftext|>