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

#ifndef _XMLOFF_XMLIMP_HXX
#include "xmlimp.hxx"
#endif
#ifndef _XMLOFF_XMLUCONV_HXX
#include "xmluconv.hxx"
#endif

#ifndef _COM_SUN_STAR_IO_XOUTPUTSTREAM_HPP_
#include <com/sun/star/io/XOutputStream.hpp>
#endif

#ifndef _XMLOFF_XMLBASE64IMPORTCONTEXT_HXX
#include "XMLBase64ImportContext.hxx"
#endif

using namespace ::rtl;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::xml::sax;
using namespace ::com::sun::star::io;

//-----------------------------------------------------------------------------

TYPEINIT1( XMLBase64ImportContext, SvXMLImportContext );

XMLBase64ImportContext::XMLBase64ImportContext(
        SvXMLImport& rImport, USHORT nPrfx, const OUString& rLName,
        const Reference< XAttributeList >& xAttrList,
        const Reference< XOutputStream >& rOut ) :
    SvXMLImportContext( rImport, nPrfx, rLName ),
    xOut( rOut )
{
}

XMLBase64ImportContext::~XMLBase64ImportContext()
{
}

void XMLBase64ImportContext::EndElement()
{
    xOut->closeOutput();
}

void XMLBase64ImportContext::Characters( const ::rtl::OUString& rChars )
{
    OUString sTrimmedChars( rChars. trim() );
    if( sTrimmedChars.getLength() )
    {
        OUString sChars;
        if( sBase64CharsLeft )
        {
            sChars = sBase64CharsLeft;
            sChars += sTrimmedChars;
            sBase64CharsLeft = OUString();
        }
        else
        {
            sChars = sTrimmedChars;
        }
        Sequence< sal_Int8 > aBuffer( (sChars.getLength() / 4) * 3 );
        sal_Int32 nCharsDecoded =
            GetImport().GetMM100UnitConverter().
                decodeBase64SomeChars( aBuffer, sChars );
        xOut->writeBytes( aBuffer );
        if( nCharsDecoded != sChars.getLength() )
            sBase64CharsLeft = sChars.copy( nCharsDecoded );
    }
}

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

#ifndef _XMLOFF_XMLIMP_HXX
#include "xmlimp.hxx"
#endif
#ifndef _XMLOFF_XMLUCONV_HXX
#include "xmluconv.hxx"
#endif

#ifndef _COM_SUN_STAR_IO_XOUTPUTSTREAM_HPP_
#include <com/sun/star/io/XOutputStream.hpp>
#endif

#ifndef _XMLOFF_XMLBASE64IMPORTCONTEXT_HXX
#include "XMLBase64ImportContext.hxx"
#endif

using namespace ::rtl;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::xml::sax;
using namespace ::com::sun::star::io;

//-----------------------------------------------------------------------------

TYPEINIT1( XMLBase64ImportContext, SvXMLImportContext );

XMLBase64ImportContext::XMLBase64ImportContext(
        SvXMLImport& rImport, USHORT nPrfx, const OUString& rLName,
        const Reference< XAttributeList >& xAttrList,
        const Reference< XOutputStream >& rOut ) :
    SvXMLImportContext( rImport, nPrfx, rLName ),
    xOut( rOut )
{
}

XMLBase64ImportContext::~XMLBase64ImportContext()
{
}

void XMLBase64ImportContext::EndElement()
{
    xOut->closeOutput();
}

void XMLBase64ImportContext::Characters( const ::rtl::OUString& rChars )
{
    OUString sTrimmedChars( rChars. trim() );
    if( sTrimmedChars.getLength() )
    {
        OUString sChars;
        if( sBase64CharsLeft )
        {
            sChars = sBase64CharsLeft;
            sChars += sTrimmedChars;
            sBase64CharsLeft = OUString();
        }
        else
        {
            sChars = sTrimmedChars;
        }
        Sequence< sal_Int8 > aBuffer( (sChars.getLength() / 4) * 3 );
        sal_Int32 nCharsDecoded =
            GetImport().GetMM100UnitConverter().
                decodeBase64SomeChars( aBuffer, sChars );
        xOut->writeBytes( aBuffer );
        if( nCharsDecoded != sChars.getLength() )
            sBase64CharsLeft = sChars.copy( nCharsDecoded );
    }
}

<|endoftext|>


<commit_before>#include <bts/blockchain/account_operations.hpp>
#include <bts/blockchain/chain_interface.hpp>
#include <bts/blockchain/exceptions.hpp>
#include <bts/blockchain/transaction_evaluation_state.hpp>
#include <fc/time.hpp>

namespace bts { namespace blockchain {

   bool register_account_operation::is_delegate()const
   {
       return delegate_pay_rate <= 100;
   }

   void register_account_operation::evaluate( transaction_evaluation_state& eval_state )
   { try {
      if( !eval_state._current_state->is_valid_account_name( this->name ) )
         FC_CAPTURE_AND_THROW( invalid_account_name, (name) );

      oaccount_record current_account = eval_state._current_state->get_account_record( this->name );
      if( current_account.valid() )
          FC_CAPTURE_AND_THROW( account_already_registered, (name) );

      current_account = eval_state._current_state->get_account_record( this->owner_key );
      if( current_account.valid() )
          FC_CAPTURE_AND_THROW( account_key_in_use, (this->owner_key)(current_account) );

      current_account = eval_state._current_state->get_account_record( this->active_key );
      if( current_account.valid() )
          FC_CAPTURE_AND_THROW( account_key_in_use, (this->active_key)(current_account) );

      if( eval_state._current_state->get_parent_account_name( this->name ).valid() )
      {
          if( !eval_state.any_parent_has_signed( this->name ) )
              FC_CAPTURE_AND_THROW( missing_parent_account_signature, (*this) );
      }

      const time_point_sec now = eval_state._current_state->now();

      account_record new_record;
      new_record.id                = eval_state._current_state->new_account_id();
      new_record.name              = this->name;
      new_record.public_data       = this->public_data;
      new_record.owner_key         = this->owner_key;
      new_record.set_active_key( now, this->active_key );
      new_record.registration_date = now;
      new_record.last_update       = now;
      new_record.meta_data         = this->meta_data;

      if( this->is_delegate() )
      {
          new_record.delegate_info = delegate_stats();
          new_record.delegate_info->pay_rate = this->delegate_pay_rate;
          new_record.delegate_info->signing_key = this->active_key;

          const asset reg_fee( eval_state._current_state->get_delegate_registration_fee( this->delegate_pay_rate ), 0 );
          eval_state.required_fees += reg_fee;
      }

      eval_state._current_state->store_account_record( new_record );
   } FC_CAPTURE_AND_RETHROW( (*this) ) }

   bool update_account_operation::is_delegate()const
   {
       return delegate_pay_rate <= 100;
   }

   void update_account_operation::evaluate( transaction_evaluation_state& eval_state )
   { try {
      oaccount_record current_record = eval_state._current_state->get_account_record( this->account_id );
      if( !current_record.valid() )
          FC_CAPTURE_AND_THROW( unknown_account_id, (account_id) );

      if( current_record->is_retracted() )
          FC_CAPTURE_AND_THROW( account_retracted, (current_record) );

      // If updating active key
      if( this->active_key.valid() && *this->active_key != current_record->active_key() )
      {
          const oaccount_record account_with_same_key = eval_state._current_state->get_account_record( *this->active_key );
          if( account_with_same_key.valid() )
              FC_CAPTURE_AND_THROW( account_key_in_use, (*this->active_key)(account_with_same_key) );

          if( !eval_state.check_signature( current_record->owner_key ) && !eval_state.any_parent_has_signed( current_record->name ) )
              FC_CAPTURE_AND_THROW( missing_signature, (*this) );

          current_record->set_active_key( eval_state._current_state->now(), *this->active_key );
      }
      else
      {
          if( !eval_state.account_or_any_parent_has_signed( *current_record ) )
              FC_CAPTURE_AND_THROW( missing_signature, (*this) );
      }

      if( this->public_data.valid() )
          current_record->public_data = *this->public_data;

      // Delegates accounts cannot revert to a normal account
      if( current_record->is_delegate() )
          FC_ASSERT( this->is_delegate() );

      if( this->is_delegate() )
      {
          if( current_record->is_delegate() )
          {
              // Delegates cannot increase their pay rate
              FC_ASSERT( this->delegate_pay_rate <= current_record->delegate_info->pay_rate );
              current_record->delegate_info->pay_rate = this->delegate_pay_rate;
          }
          else
          {
              current_record->delegate_info = delegate_stats();
              current_record->delegate_info->pay_rate = this->delegate_pay_rate;
              current_record->delegate_info->signing_key = current_record->active_key();
              const asset reg_fee( eval_state._current_state->get_delegate_registration_fee( this->delegate_pay_rate ), 0 );
              eval_state.required_fees += reg_fee;
          }
      }

      current_record->last_update = eval_state._current_state->now();

      eval_state._current_state->store_account_record( *current_record );
   } FC_CAPTURE_AND_RETHROW( (*this) ) }

   void withdraw_pay_operation::evaluate( transaction_evaluation_state& eval_state )
   { try {
      if( this->amount <= 0 )
          FC_CAPTURE_AND_THROW( negative_withdraw, (amount) );

      const account_id_type account_id = abs( this->account_id );
      oaccount_record account = eval_state._current_state->get_account_record( account_id );
      if( !account.valid() )
          FC_CAPTURE_AND_THROW( unknown_account_id, (account_id) );

      if( !account->is_delegate() )
          FC_CAPTURE_AND_THROW( not_a_delegate, (account) );

      if( account->delegate_info->pay_balance < this->amount )
         FC_CAPTURE_AND_THROW( insufficient_funds, (account)(amount) );

      if( !eval_state.account_or_any_parent_has_signed( *account ) )
          FC_CAPTURE_AND_THROW( missing_signature, (*this) );

      account->delegate_info->pay_balance -= this->amount;
      eval_state.net_delegate_votes[ account_id ].votes_for -= this->amount;
      eval_state.add_balance( asset( this->amount, 0 ) );

      eval_state._current_state->store_account_record( *account );
   } FC_CAPTURE_AND_RETHROW( (*this) ) }

   void link_account_operation::evaluate( transaction_evaluation_state& eval_state )
   { try {
      FC_ASSERT( !"Link account operation is not enabled yet!" );

      auto source_account_rec = eval_state._current_state->get_account_record( source_account );
      if( !source_account_rec.valid() )
          FC_CAPTURE_AND_THROW( unknown_account_id, (*this) );

      if( source_account_rec->is_retracted() )
          FC_CAPTURE_AND_THROW( account_retracted, (*this) );

      auto destination_account_rec = eval_state._current_state->get_account_record( destination_account );
      if( !destination_account_rec.valid() )
          FC_CAPTURE_AND_THROW( unknown_account_id, (*this) );

      if( destination_account_rec->is_retracted() )
          FC_CAPTURE_AND_THROW( account_retracted, (*this) );

      if( !eval_state.account_or_any_parent_has_signed( *source_account_rec ) )
          FC_CAPTURE_AND_THROW( missing_signature, (*this) );

      // STORE LINK...
   } FC_CAPTURE_AND_RETHROW( (*this) ) }

#ifndef WIN32
#warning [SOFTFORK] Disable this operation until the next BTS hardfork, then remove
#endif
   void update_block_signing_key::evaluate( transaction_evaluation_state& eval_state )
   { try {
      oaccount_record account_rec = eval_state._current_state->get_account_record( this->account_id );
      if( !account_rec.valid() )
          FC_CAPTURE_AND_THROW( unknown_account_id, (account_id) );

      if( account_rec->is_retracted() )
          FC_CAPTURE_AND_THROW( account_retracted, (*account_rec) );

      if( !account_rec->is_delegate() )
          FC_CAPTURE_AND_THROW( not_a_delegate, (*account_rec) );

      if( !eval_state.account_or_any_parent_has_signed( *account_rec ) )
          FC_CAPTURE_AND_THROW( missing_signature, (*this) );

      account_rec->delegate_info->signing_key = this->block_signing_key;
      account_rec->delegate_info->num_signing_key_changes++;
      account_rec->delegate_info->last_signing_key_change_block_num = eval_state._current_state->get_head_block_num();
      account_rec->delegate_info->next_secret_hash = optional<secret_hash_type>();
      account_rec->last_update = eval_state._current_state->now();

      eval_state._current_state->store_account_record( *account_rec );
   } FC_CAPTURE_AND_RETHROW( (*this) ) }

} } // bts::blockchain
<commit_msg>Do not allow multiple delegates to have the same block signing key; issue #873<commit_after>#include <bts/blockchain/account_operations.hpp>
#include <bts/blockchain/chain_interface.hpp>
#include <bts/blockchain/exceptions.hpp>
#include <bts/blockchain/transaction_evaluation_state.hpp>
#include <fc/time.hpp>

namespace bts { namespace blockchain {

   bool register_account_operation::is_delegate()const
   {
       return delegate_pay_rate <= 100;
   }

   void register_account_operation::evaluate( transaction_evaluation_state& eval_state )
   { try {
      if( !eval_state._current_state->is_valid_account_name( this->name ) )
         FC_CAPTURE_AND_THROW( invalid_account_name, (name) );

      oaccount_record current_account = eval_state._current_state->get_account_record( this->name );
      if( current_account.valid() )
          FC_CAPTURE_AND_THROW( account_already_registered, (name) );

      current_account = eval_state._current_state->get_account_record( this->owner_key );
      if( current_account.valid() )
          FC_CAPTURE_AND_THROW( account_key_in_use, (this->owner_key)(current_account) );

      current_account = eval_state._current_state->get_account_record( this->active_key );
      if( current_account.valid() )
          FC_CAPTURE_AND_THROW( account_key_in_use, (this->active_key)(current_account) );

      if( eval_state._current_state->get_parent_account_name( this->name ).valid() )
      {
          if( !eval_state.any_parent_has_signed( this->name ) )
              FC_CAPTURE_AND_THROW( missing_parent_account_signature, (*this) );
      }

      const time_point_sec now = eval_state._current_state->now();

      account_record new_record;
      new_record.id                = eval_state._current_state->new_account_id();
      new_record.name              = this->name;
      new_record.public_data       = this->public_data;
      new_record.owner_key         = this->owner_key;
      new_record.set_active_key( now, this->active_key );
      new_record.registration_date = now;
      new_record.last_update       = now;
      new_record.meta_data         = this->meta_data;

      if( this->is_delegate() )
      {
          new_record.delegate_info = delegate_stats();
          new_record.delegate_info->pay_rate = this->delegate_pay_rate;
          new_record.delegate_info->signing_key = this->active_key;

          const asset reg_fee( eval_state._current_state->get_delegate_registration_fee( this->delegate_pay_rate ), 0 );
          eval_state.required_fees += reg_fee;
      }

      eval_state._current_state->store_account_record( new_record );
   } FC_CAPTURE_AND_RETHROW( (*this) ) }

   bool update_account_operation::is_delegate()const
   {
       return delegate_pay_rate <= 100;
   }

   void update_account_operation::evaluate( transaction_evaluation_state& eval_state )
   { try {
      oaccount_record current_record = eval_state._current_state->get_account_record( this->account_id );
      if( !current_record.valid() )
          FC_CAPTURE_AND_THROW( unknown_account_id, (account_id) );

      if( current_record->is_retracted() )
          FC_CAPTURE_AND_THROW( account_retracted, (current_record) );

      // If updating active key
      if( this->active_key.valid() && *this->active_key != current_record->active_key() )
      {
          const oaccount_record account_with_same_key = eval_state._current_state->get_account_record( *this->active_key );
          if( account_with_same_key.valid() )
              FC_CAPTURE_AND_THROW( account_key_in_use, (*this->active_key)(account_with_same_key) );

          if( !eval_state.check_signature( current_record->owner_key ) && !eval_state.any_parent_has_signed( current_record->name ) )
              FC_CAPTURE_AND_THROW( missing_signature, (*this) );

          current_record->set_active_key( eval_state._current_state->now(), *this->active_key );
      }
      else
      {
          if( !eval_state.account_or_any_parent_has_signed( *current_record ) )
              FC_CAPTURE_AND_THROW( missing_signature, (*this) );
      }

      if( this->public_data.valid() )
          current_record->public_data = *this->public_data;

      // Delegates accounts cannot revert to a normal account
      if( current_record->is_delegate() )
          FC_ASSERT( this->is_delegate() );

      if( this->is_delegate() )
      {
          if( current_record->is_delegate() )
          {
              // Delegates cannot increase their pay rate
              FC_ASSERT( this->delegate_pay_rate <= current_record->delegate_info->pay_rate );
              current_record->delegate_info->pay_rate = this->delegate_pay_rate;
          }
          else
          {
              current_record->delegate_info = delegate_stats();
              current_record->delegate_info->pay_rate = this->delegate_pay_rate;
              current_record->delegate_info->signing_key = current_record->active_key();
              const asset reg_fee( eval_state._current_state->get_delegate_registration_fee( this->delegate_pay_rate ), 0 );
              eval_state.required_fees += reg_fee;
          }
      }

      current_record->last_update = eval_state._current_state->now();

      eval_state._current_state->store_account_record( *current_record );
   } FC_CAPTURE_AND_RETHROW( (*this) ) }

   void withdraw_pay_operation::evaluate( transaction_evaluation_state& eval_state )
   { try {
      if( this->amount <= 0 )
          FC_CAPTURE_AND_THROW( negative_withdraw, (amount) );

      const account_id_type account_id = abs( this->account_id );
      oaccount_record account = eval_state._current_state->get_account_record( account_id );
      if( !account.valid() )
          FC_CAPTURE_AND_THROW( unknown_account_id, (account_id) );

      if( !account->is_delegate() )
          FC_CAPTURE_AND_THROW( not_a_delegate, (account) );

      if( account->delegate_info->pay_balance < this->amount )
         FC_CAPTURE_AND_THROW( insufficient_funds, (account)(amount) );

      if( !eval_state.account_or_any_parent_has_signed( *account ) )
          FC_CAPTURE_AND_THROW( missing_signature, (*this) );

      account->delegate_info->pay_balance -= this->amount;
      eval_state.net_delegate_votes[ account_id ].votes_for -= this->amount;
      eval_state.add_balance( asset( this->amount, 0 ) );

      eval_state._current_state->store_account_record( *account );
   } FC_CAPTURE_AND_RETHROW( (*this) ) }

   void link_account_operation::evaluate( transaction_evaluation_state& eval_state )
   { try {
      FC_ASSERT( !"Link account operation is not enabled yet!" );

      auto source_account_rec = eval_state._current_state->get_account_record( source_account );
      if( !source_account_rec.valid() )
          FC_CAPTURE_AND_THROW( unknown_account_id, (*this) );

      if( source_account_rec->is_retracted() )
          FC_CAPTURE_AND_THROW( account_retracted, (*this) );

      auto destination_account_rec = eval_state._current_state->get_account_record( destination_account );
      if( !destination_account_rec.valid() )
          FC_CAPTURE_AND_THROW( unknown_account_id, (*this) );

      if( destination_account_rec->is_retracted() )
          FC_CAPTURE_AND_THROW( account_retracted, (*this) );

      if( !eval_state.account_or_any_parent_has_signed( *source_account_rec ) )
          FC_CAPTURE_AND_THROW( missing_signature, (*this) );

      // STORE LINK...
   } FC_CAPTURE_AND_RETHROW( (*this) ) }

#ifndef WIN32
#warning [SOFTFORK] Disable this operation until the next BTS hardfork, then remove
#endif
   void update_block_signing_key::evaluate( transaction_evaluation_state& eval_state )
   { try {
      oaccount_record account_rec = eval_state._current_state->get_account_record( this->account_id );
      if( !account_rec.valid() )
          FC_CAPTURE_AND_THROW( unknown_account_id, (account_id) );

      if( account_rec->is_retracted() )
          FC_CAPTURE_AND_THROW( account_retracted, (*account_rec) );

      if( !account_rec->is_delegate() )
          FC_CAPTURE_AND_THROW( not_a_delegate, (*account_rec) );

      oaccount_record existing_record = eval_state._current_state->get_account_record( this->block_signing_key );
      if( existing_record.valid() )
          FC_CAPTURE_AND_THROW( account_key_in_use, (*existing_record) );

      if( !eval_state.account_or_any_parent_has_signed( *account_rec ) )
          FC_CAPTURE_AND_THROW( missing_signature, (*this) );

      account_rec->delegate_info->signing_key = this->block_signing_key;
      account_rec->delegate_info->num_signing_key_changes++;
      account_rec->delegate_info->last_signing_key_change_block_num = eval_state._current_state->get_head_block_num();
      account_rec->delegate_info->next_secret_hash = optional<secret_hash_type>();
      account_rec->last_update = eval_state._current_state->now();

      eval_state._current_state->store_account_record( *account_rec );
   } FC_CAPTURE_AND_RETHROW( (*this) ) }

} } // bts::blockchain
<|endoftext|>


<commit_before>/* FasTC
 * Copyright (c) 2014 University of North Carolina at Chapel Hill.
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for educational, research, and non-profit purposes, without
 * fee, and without a written agreement is hereby granted, provided that the
 * above copyright notice, this paragraph, and the following four paragraphs
 * appear in all copies.
 *
 * Permission to incorporate this software into commercial products may be
 * obtained by contacting the authors or the Office of Technology Development
 * at the University of North Carolina at Chapel Hill <otd@unc.edu>.
 *
 * This software program and documentation are copyrighted by the University of
 * North Carolina at Chapel Hill. The software program and documentation are
 * supplied "as is," without any accompanying services from the University of
 * North Carolina at Chapel Hill or the authors. The University of North
 * Carolina at Chapel Hill and the authors do not warrant that the operation of
 * the program will be uninterrupted or error-free. The end-user understands
 * that the program was developed for research purposes and is advised not to
 * rely exclusively on the program for any reason.
 *
 * IN NO EVENT SHALL THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE
 * AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,
 * OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF
 * THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF NORTH CAROLINA
 * AT CHAPEL HILL OR THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *
 * THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS SPECIFICALLY
 * DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND ANY
 * STATUTORY WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE PROVIDED HEREUNDER IS ON
 * AN "AS IS" BASIS, AND THE UNIVERSITY  OF NORTH CAROLINA AT CHAPEL HILL AND
 * THE AUTHORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
 * ENHANCEMENTS, OR MODIFICATIONS.
 *
 * Please send all BUG REPORTS to <pavel@cs.unc.edu>.
 *
 * The authors may be contacted via:
 *
 * Pavel Krajcevski
 * Dept of Computer Science
 * 201 S Columbia St
 * Frederick P. Brooks, Jr. Computer Science Bldg
 * Chapel Hill, NC 27599-3175
 * USA
 *
 * <http://gamma.cs.unc.edu/FasTC/>
 */

#include "ImageLoaderKTX.h"

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <iostream>

#include "TexCompTypes.h"
#include "ScopedAllocator.h"

#include "GLDefines.h"
#include "Image.h"
#include "CompressedImage.h"

class ByteReader {
 private:
  const uint8 *m_Data;
  uint32 m_BytesLeft;
 public:
  ByteReader(const uint8 *data, uint32 bytesExpected)
    : m_Data(data), m_BytesLeft(bytesExpected)
  { }

  bool Advance(uint32 nBytes) {
    if(nBytes > m_BytesLeft) {
      assert(!"Cannot read any more, unexpected bytes!");
      return false;
    }

    m_Data += nBytes;
    m_BytesLeft -= nBytes;
    return true;
  }

  operator const uint8 *() {
    return m_Data;
  }

  const uint8 *GetData() const { return m_Data; }
  uint32 GetBytesLeft() const { return m_BytesLeft; }
};

class IntLoader {
 public:
  virtual uint32 ReadInt(const uint8 *data) const = 0;
  bool LoadInt(ByteReader &data, uint32 &result) const {
    result = ReadInt(data);
    data.Advance(4);
    return true;
  }
  virtual ~IntLoader() { }
};

class BigEndianIntLoader : public IntLoader {
 public:
  BigEndianIntLoader() { }
  virtual uint32 ReadInt(const uint8 *data) const {
    uint32 ret = 0;
    ret |= data[0];
    for(uint32 i = 1; i < 4; i++) {
      ret <<= 8;
      ret |= data[i];
    }
    return ret;
  }
};
static const BigEndianIntLoader gBEldr;

class LittleEndianIntLoader : public IntLoader {
 public:
  LittleEndianIntLoader() { }
  virtual uint32 ReadInt(const uint8 *data) const {
    uint32 ret = 0;
    ret |= data[3];
    for(int32 i = 3; i >= 0; i--) {
      ret <<= 8;
      ret |= data[i];
    }
    return ret;
  }
};
static const LittleEndianIntLoader gLEldr;

ImageLoaderKTX::ImageLoaderKTX(const uint8 *rawData, const int32 rawDataSz)
  : ImageLoader(rawData, rawDataSz), m_Processor(NULL)
{ }

ImageLoaderKTX::~ImageLoaderKTX() { }

FasTC::Image<> *ImageLoaderKTX::LoadImage() {

  // Get rid of the pixel data if it exists...
  if(m_PixelData) {
    delete m_PixelData;
    m_PixelData = NULL;
  }

  if(!ReadData()) {
    return NULL;
  }

  if(!m_bIsCompressed) {
    uint32 *pixels = reinterpret_cast<uint32 *>(m_PixelData);
    return new FasTC::Image<>(m_Width, m_Height, pixels);
  }

  return new CompressedImage(m_Width, m_Height, m_Format, m_PixelData);
}

bool ImageLoaderKTX::ReadData() {

  // Default is uncompressed
  m_bIsCompressed = false;

  ByteReader rdr (m_RawData, m_NumRawDataBytes);

  // First, check to make sure that the identifier is present...
  static const uint8 kKTXID[12] = {
    0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A
  };

  if(memcmp(rdr.GetData(), kKTXID, 12) == 0) {
    rdr.Advance(12);
  } else {
    return false;
  }

  const IntLoader *ldr = NULL;
  if(rdr.GetData()[0] == 0x04) {
    ldr = &gBEldr;
  } else {
    ldr = &gLEldr;
  }
  rdr.Advance(4);

  #define LOAD(x) uint32 x; do { if(!ldr->LoadInt(rdr, x)) { return false; } } while(0)
  LOAD(glType);
  LOAD(glTypeSize);
  LOAD(glFormat);
  LOAD(glInternalFormat);
  LOAD(glBaseInternalFormat);
  LOAD(pixelWidth);
  LOAD(pixelHeight);
  LOAD(pixelDepth);
  LOAD(numberOfArrayElements);
  LOAD(numberOfFaces);
  LOAD(numberOfMipmapLevels);
  LOAD(bytesOfKeyValueData);

  // Do we need to read the data?
  if(m_Processor) {
    const uint8 *imgData = rdr.GetData() + bytesOfKeyValueData;
    while(rdr.GetData() < imgData) {
      LOAD(keyAndValueByteSize);
      FasTC::ScopedAllocator<uint8> keyValueData =
        FasTC::ScopedAllocator<uint8>::Create(keyAndValueByteSize);
      if(!keyValueData) {
        fprintf(stderr, "KTX loader - out of memory.\n");
        return false;
      }

      // Read the bytes...
      memcpy(keyValueData, rdr.GetData(), keyAndValueByteSize);
      const char *key = reinterpret_cast<const char *>((const uint8 *)keyValueData);
      const char *value = key;
      while(value != '\0') {
        value++;
      }
      value++; // consume the null byte

      m_Processor(key, value);
      rdr.Advance((keyAndValueByteSize + 3) & ~0x3);
    }
  } else {
    rdr.Advance(bytesOfKeyValueData);
  }

  // The following code only supports a limited subset of
  // image types, the full spec (if we choose to support it)
  // is here:
  // http://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec

  // Read image data...
  if(numberOfMipmapLevels != 1) {
    fprintf(stderr, "KTX loader - unsupported mipmap levels: %d\n", numberOfMipmapLevels);
    return false;
  }

  LOAD(imageSize);

  if(numberOfArrayElements > 1) {
    fprintf(stderr,
            "KTX loader - unsupported number of array elements: %d\n",
            numberOfArrayElements);
    return false;
  }

  if(numberOfFaces != 1) {
    fprintf(stderr,
            "KTX loader - unsupported number of faces: %d\n"
            "This likely means that we are trying to load a cube map.\n",
            numberOfFaces);
    return false;
  }

  if(pixelDepth != 0) {
    fprintf(stderr, "KTX loader - 3D textures not supported\n");
    return false;
  }

  if(pixelHeight == 0) {
    fprintf(stderr, "KTX loader - 1D textures not supported\n");
    return false;
  }

  if(pixelWidth == 0) {
    fprintf(stderr, "KTX loader - nonzero pixel width??\n");
    return false;
  }

  m_Width = pixelWidth;
  m_Height = pixelHeight;

  if(glType == 0 && glFormat == 0) {
    switch(glInternalFormat) {
      case GL_COMPRESSED_RGBA_BPTC_UNORM:
        m_Format = FasTC::eCompressionFormat_BPTC;
        break;
      default:
        fprintf(stderr, "KTX loader - texture format (0x%x) unsupported!\n", glInternalFormat);
        return false;
    }

    uint32 dataSize = CompressedImage::GetCompressedSize(pixelWidth * pixelHeight * 4, m_Format);
    m_PixelData = new uint8[dataSize];
    memcpy(m_PixelData, rdr.GetData(), dataSize);
    rdr.Advance(dataSize);

    m_bIsCompressed = true;
  } else {

    if(glType != GL_BYTE) {
      fprintf(stderr, "KTX loader - unsupported OpenGL type: 0x%x\n", glType);
      return false;
    }

    if(glInternalFormat != GL_RGBA8) {
      fprintf(stderr, "KTX loader - unsupported internal format: 0x%x\n", glFormat);
      return false;
    }

    // We should have RGBA8 data here so we can simply load it
    // as we normally would.
    uint32 pixelDataSz = m_Width * m_Height * 4;
    m_PixelData = new uint8[pixelDataSz];
    memcpy(m_PixelData, rdr.GetData(), pixelDataSz);
    rdr.Advance(pixelDataSz);
  }
  return rdr.GetBytesLeft() == 0;
}

<commit_msg>Add ASTC values to KTX loader<commit_after>/* FasTC
 * Copyright (c) 2014 University of North Carolina at Chapel Hill.
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for educational, research, and non-profit purposes, without
 * fee, and without a written agreement is hereby granted, provided that the
 * above copyright notice, this paragraph, and the following four paragraphs
 * appear in all copies.
 *
 * Permission to incorporate this software into commercial products may be
 * obtained by contacting the authors or the Office of Technology Development
 * at the University of North Carolina at Chapel Hill <otd@unc.edu>.
 *
 * This software program and documentation are copyrighted by the University of
 * North Carolina at Chapel Hill. The software program and documentation are
 * supplied "as is," without any accompanying services from the University of
 * North Carolina at Chapel Hill or the authors. The University of North
 * Carolina at Chapel Hill and the authors do not warrant that the operation of
 * the program will be uninterrupted or error-free. The end-user understands
 * that the program was developed for research purposes and is advised not to
 * rely exclusively on the program for any reason.
 *
 * IN NO EVENT SHALL THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE
 * AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,
 * OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF
 * THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF NORTH CAROLINA
 * AT CHAPEL HILL OR THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *
 * THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS SPECIFICALLY
 * DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND ANY
 * STATUTORY WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE PROVIDED HEREUNDER IS ON
 * AN "AS IS" BASIS, AND THE UNIVERSITY  OF NORTH CAROLINA AT CHAPEL HILL AND
 * THE AUTHORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
 * ENHANCEMENTS, OR MODIFICATIONS.
 *
 * Please send all BUG REPORTS to <pavel@cs.unc.edu>.
 *
 * The authors may be contacted via:
 *
 * Pavel Krajcevski
 * Dept of Computer Science
 * 201 S Columbia St
 * Frederick P. Brooks, Jr. Computer Science Bldg
 * Chapel Hill, NC 27599-3175
 * USA
 *
 * <http://gamma.cs.unc.edu/FasTC/>
 */

#include "ImageLoaderKTX.h"

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <iostream>

#include "TexCompTypes.h"
#include "ScopedAllocator.h"

#include "GLDefines.h"
#include "Image.h"
#include "CompressedImage.h"

class ByteReader {
 private:
  const uint8 *m_Data;
  uint32 m_BytesLeft;
 public:
  ByteReader(const uint8 *data, uint32 bytesExpected)
    : m_Data(data), m_BytesLeft(bytesExpected)
  { }

  bool Advance(uint32 nBytes) {
    if(nBytes > m_BytesLeft) {
      assert(!"Cannot read any more, unexpected bytes!");
      return false;
    }

    m_Data += nBytes;
    m_BytesLeft -= nBytes;
    return true;
  }

  operator const uint8 *() {
    return m_Data;
  }

  const uint8 *GetData() const { return m_Data; }
  uint32 GetBytesLeft() const { return m_BytesLeft; }
};

class IntLoader {
 public:
  virtual uint32 ReadInt(const uint8 *data) const = 0;
  bool LoadInt(ByteReader &data, uint32 &result) const {
    result = ReadInt(data);
    data.Advance(4);
    return true;
  }
  virtual ~IntLoader() { }
};

class BigEndianIntLoader : public IntLoader {
 public:
  BigEndianIntLoader() { }
  virtual uint32 ReadInt(const uint8 *data) const {
    uint32 ret = 0;
    ret |= data[0];
    for(uint32 i = 1; i < 4; i++) {
      ret <<= 8;
      ret |= data[i];
    }
    return ret;
  }
};
static const BigEndianIntLoader gBEldr;

class LittleEndianIntLoader : public IntLoader {
 public:
  LittleEndianIntLoader() { }
  virtual uint32 ReadInt(const uint8 *data) const {
    uint32 ret = 0;
    ret |= data[3];
    for(int32 i = 3; i >= 0; i--) {
      ret <<= 8;
      ret |= data[i];
    }
    return ret;
  }
};
static const LittleEndianIntLoader gLEldr;

ImageLoaderKTX::ImageLoaderKTX(const uint8 *rawData, const int32 rawDataSz)
  : ImageLoader(rawData, rawDataSz), m_Processor(NULL)
{ }

ImageLoaderKTX::~ImageLoaderKTX() { }

FasTC::Image<> *ImageLoaderKTX::LoadImage() {

  // Get rid of the pixel data if it exists...
  if(m_PixelData) {
    delete m_PixelData;
    m_PixelData = NULL;
  }

  if(!ReadData()) {
    return NULL;
  }

  if(!m_bIsCompressed) {
    uint32 *pixels = reinterpret_cast<uint32 *>(m_PixelData);
    return new FasTC::Image<>(m_Width, m_Height, pixels);
  }

  return new CompressedImage(m_Width, m_Height, m_Format, m_PixelData);
}

bool ImageLoaderKTX::ReadData() {

  // Default is uncompressed
  m_bIsCompressed = false;

  ByteReader rdr (m_RawData, m_NumRawDataBytes);

  // First, check to make sure that the identifier is present...
  static const uint8 kKTXID[12] = {
    0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A
  };

  if(memcmp(rdr.GetData(), kKTXID, 12) == 0) {
    rdr.Advance(12);
  } else {
    return false;
  }

  const IntLoader *ldr = NULL;
  if(rdr.GetData()[0] == 0x04) {
    ldr = &gBEldr;
  } else {
    ldr = &gLEldr;
  }
  rdr.Advance(4);

  #define LOAD(x) uint32 x; do { if(!ldr->LoadInt(rdr, x)) { return false; } } while(0)
  LOAD(glType);
  LOAD(glTypeSize);
  LOAD(glFormat);
  LOAD(glInternalFormat);
  LOAD(glBaseInternalFormat);
  LOAD(pixelWidth);
  LOAD(pixelHeight);
  LOAD(pixelDepth);
  LOAD(numberOfArrayElements);
  LOAD(numberOfFaces);
  LOAD(numberOfMipmapLevels);
  LOAD(bytesOfKeyValueData);

  // Do we need to read the data?
  if(m_Processor) {
    const uint8 *imgData = rdr.GetData() + bytesOfKeyValueData;
    while(rdr.GetData() < imgData) {
      LOAD(keyAndValueByteSize);
      FasTC::ScopedAllocator<uint8> keyValueData =
        FasTC::ScopedAllocator<uint8>::Create(keyAndValueByteSize);
      if(!keyValueData) {
        fprintf(stderr, "KTX loader - out of memory.\n");
        return false;
      }

      // Read the bytes...
      memcpy(keyValueData, rdr.GetData(), keyAndValueByteSize);
      const char *key = reinterpret_cast<const char *>((const uint8 *)keyValueData);
      const char *value = key;
      while(value != '\0') {
        value++;
      }
      value++; // consume the null byte

      m_Processor(key, value);
      rdr.Advance((keyAndValueByteSize + 3) & ~0x3);
    }
  } else {
    rdr.Advance(bytesOfKeyValueData);
  }

  // The following code only supports a limited subset of
  // image types, the full spec (if we choose to support it)
  // is here:
  // http://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec

  // Read image data...
  if(numberOfMipmapLevels != 1) {
    fprintf(stderr, "KTX loader - unsupported mipmap levels: %d\n", numberOfMipmapLevels);
    return false;
  }

  LOAD(imageSize);

  if(numberOfArrayElements > 1) {
    fprintf(stderr,
            "KTX loader - unsupported number of array elements: %d\n",
            numberOfArrayElements);
    return false;
  }

  if(numberOfFaces != 1) {
    fprintf(stderr,
            "KTX loader - unsupported number of faces: %d\n"
            "This likely means that we are trying to load a cube map.\n",
            numberOfFaces);
    return false;
  }

  if(pixelDepth != 0) {
    fprintf(stderr, "KTX loader - 3D textures not supported\n");
    return false;
  }

  if(pixelHeight == 0) {
    fprintf(stderr, "KTX loader - 1D textures not supported\n");
    return false;
  }

  if(pixelWidth == 0) {
    fprintf(stderr, "KTX loader - nonzero pixel width??\n");
    return false;
  }

  m_Width = pixelWidth;
  m_Height = pixelHeight;

  if(glType == 0 && glFormat == 0) {
    switch(glInternalFormat) {
      case GL_COMPRESSED_RGBA_BPTC_UNORM:
        m_Format = FasTC::eCompressionFormat_BPTC;
        break;

      case COMPRESSED_RGBA_ASTC_4x4_KHR:
        m_Format = FasTC::eCompressionFormat_ASTC4x4;
        break;

      case COMPRESSED_RGBA_ASTC_5x4_KHR:
        m_Format = FasTC::eCompressionFormat_ASTC5x4;
        break;

      case COMPRESSED_RGBA_ASTC_5x5_KHR:
        m_Format = FasTC::eCompressionFormat_ASTC5x5;
        break;

      case COMPRESSED_RGBA_ASTC_6x5_KHR:
        m_Format = FasTC::eCompressionFormat_ASTC6x5;
        break;

      case COMPRESSED_RGBA_ASTC_6x6_KHR:
        m_Format = FasTC::eCompressionFormat_ASTC6x6;
        break;

      case COMPRESSED_RGBA_ASTC_8x5_KHR:
        m_Format = FasTC::eCompressionFormat_ASTC8x5;
        break;

      case COMPRESSED_RGBA_ASTC_8x6_KHR:
        m_Format = FasTC::eCompressionFormat_ASTC8x6;
        break;

      case COMPRESSED_RGBA_ASTC_8x8_KHR:
        m_Format = FasTC::eCompressionFormat_ASTC8x8;
        break;

      case COMPRESSED_RGBA_ASTC_10x5_KHR:
        m_Format = FasTC::eCompressionFormat_ASTC10x5;
        break;

      case COMPRESSED_RGBA_ASTC_10x6_KHR:
        m_Format = FasTC::eCompressionFormat_ASTC10x6;
        break;

      case COMPRESSED_RGBA_ASTC_10x8_KHR:
        m_Format = FasTC::eCompressionFormat_ASTC10x8;
        break;

      case COMPRESSED_RGBA_ASTC_10x10_KHR:
        m_Format = FasTC::eCompressionFormat_ASTC10x10;
        break;

      case COMPRESSED_RGBA_ASTC_12x10_KHR:
        m_Format = FasTC::eCompressionFormat_ASTC12x10;
        break;

      case COMPRESSED_RGBA_ASTC_12x12_KHR:
        m_Format = FasTC::eCompressionFormat_ASTC12x12;
        break;

      default:
        fprintf(stderr, "KTX loader - texture format (0x%x) unsupported!\n", glInternalFormat);
        return false;
    }

    uint32 dataSize = CompressedImage::GetCompressedSize(pixelWidth * pixelHeight * 4, m_Format);
    m_PixelData = new uint8[dataSize];
    memcpy(m_PixelData, rdr.GetData(), dataSize);
    rdr.Advance(dataSize);

    m_bIsCompressed = true;
  } else {

    if(glType != GL_BYTE) {
      fprintf(stderr, "KTX loader - unsupported OpenGL type: 0x%x\n", glType);
      return false;
    }

    if(glInternalFormat != GL_RGBA8) {
      fprintf(stderr, "KTX loader - unsupported internal format: 0x%x\n", glFormat);
      return false;
    }

    // We should have RGBA8 data here so we can simply load it
    // as we normally would.
    uint32 pixelDataSz = m_Width * m_Height * 4;
    m_PixelData = new uint8[pixelDataSz];
    memcpy(m_PixelData, rdr.GetData(), pixelDataSz);
    rdr.Advance(pixelDataSz);
  }
  return rdr.GetBytesLeft() == 0;
}

<|endoftext|>


<commit_before>#include "src/subcarrier.h"

#ifdef HAVE_LIQUID

#include <cmath>
#include <complex>
#include <cstdio>
#include <deque>
#include <iostream>
#include <tuple>

#ifdef HAVE_SNDFILE
#include <sndfile.h>
#endif

#include "src/common.h"
#include "src/liquid_wrappers.h"

namespace redsea {

namespace {

const float kCarrierFrequency_Hz  = 57000.0f;
const float kBitsPerSecond        = 1187.5f;
const int   kInputBufferSize      = 4096;
const int   kSamplesPerSymbol     = 3;
const float kAGCBandwidth_Hz      = 500.0f;
const float kAGCInitialGain       = 0.0077f;
const float kLowpassCutoff_Hz     = 2400.0f;
const float kSymsyncBandwidth_Hz  = 2400.0f;
const int   kSymsyncDelay         = 2;
const float kSymsyncBeta          = 0.8f;
const float kPLLBandwidth_Hz      = 0.3f;
const float kPLLMultiplier        = 9.0f;

float hertz2step(float Hz) {
  return Hz * 2.0f * M_PI / kTargetSampleRate_Hz;
}

#ifdef DEBUG
float step2hertz(float step) {
  return step * kTargetSampleRate_Hz / (2.0f * M_PI);
}
#endif

}  // namespace

bool MPXReader::eof() const {
  return is_eof_;
}

StdinReader::StdinReader(const Options& options) :
    samplerate_(options.samplerate),
    buffer_(new (std::nothrow) int16_t[kInputBufferSize]),
    feed_thru_(options.feed_thru) {
  is_eof_ = false;
}

StdinReader::~StdinReader() {
  delete[] buffer_;
}

std::vector<float> StdinReader::ReadBlock() {
  int num_read = fread(buffer_, sizeof(buffer_[0]), kInputBufferSize,
      stdin);

  if (feed_thru_)
    fwrite(buffer_, sizeof(buffer_[0]), num_read, stdout);

  if (num_read < kInputBufferSize)
    is_eof_ = true;

  std::vector<float> result(num_read);
  for (int i = 0; i < num_read; i++)
    result[i] = buffer_[i];

  return result;
}

float StdinReader::samplerate() const {
  return samplerate_;
}

#ifdef HAVE_SNDFILE
SndfileReader::SndfileReader(const Options& options) :
    info_({0, 0, 0, 0, 0, 0}),
    file_(sf_open(options.sndfilename.c_str(), SFM_READ, &info_)),
    buffer_(new (std::nothrow) float[info_.channels * kInputBufferSize]) {
  is_eof_ = false;
}

SndfileReader::~SndfileReader() {
  sf_close(file_);
  delete[] buffer_;
}

std::vector<float> SndfileReader::ReadBlock() {
  sf_count_t num_read = sf_readf_float(file_, buffer_, kInputBufferSize);
  if (num_read != kInputBufferSize)
    is_eof_ = true;

  // TODO(windytan): downmix channels
  std::vector<float> result(buffer_, buffer_ + num_read);
  return result;
}

float SndfileReader::samplerate() const {
  return info_.samplerate;
}
#endif

BiphaseDecoder::BiphaseDecoder() : prev_psk_symbol_(0.0f),
  clock_history_(48), clock_(0), clock_polarity_(0) {
}

BiphaseDecoder::~BiphaseDecoder() {
}

// Return {is_clock, symbol}
//   is_clock: true if symbol valid
//   symbol:   binary symbol in constellation {-1,0} => 0, {1,0} => 1
std::pair<bool, std::complex<float>> BiphaseDecoder::push(
    std::complex<float> psk_symbol) {

  std::complex<float> biphase = (psk_symbol - prev_psk_symbol_) * 0.5f;
  bool is_clock = (clock_ % 2 == clock_polarity_);

  clock_history_[clock_] = std::fabs(biphase.real());

  // Periodically evaluate validity of the chosen biphase clock polarity
  if (++clock_ == clock_history_.size()) {
    float a = 0;
    float b = 0;

    for (size_t i = 0; i < clock_history_.size(); i++) {
      if (i % 2 == 0)
        a += clock_history_[i];
      else
        b += clock_history_[i];
      clock_history_[i] = 0.f;
    }

    if      (a > b) clock_polarity_ = 0;
    else if (b > a) clock_polarity_ = 1;

    clock_ = 0;
  }

  prev_psk_symbol_ = psk_symbol;

  return {is_clock, biphase};
}

DeltaDecoder::DeltaDecoder() : prev_(0) {
}

DeltaDecoder::~DeltaDecoder() {
}

unsigned DeltaDecoder::Decode(unsigned d) {
  unsigned bit = (d != prev_);
  prev_ = d;
  return bit;
}

Subcarrier::Subcarrier(const Options& options) : numsamples_(0),
    resample_ratio_(kTargetSampleRate_Hz / options.samplerate),
    bit_buffer_(),
    fir_lpf_(256, kLowpassCutoff_Hz / kTargetSampleRate_Hz),
    agc_(kAGCBandwidth_Hz / kTargetSampleRate_Hz, kAGCInitialGain),
    nco_approx_(hertz2step(kCarrierFrequency_Hz)),
    nco_exact_(hertz2step(kCarrierFrequency_Hz)),
    symsync_(LIQUID_FIRFILT_RRC, kSamplesPerSymbol, kSymsyncDelay,
             kSymsyncBeta, 32),
    modem_(LIQUID_MODEM_PSK2),
    resampler_(resample_ratio_, 13),
    is_eof_(false), delta_decoder_() {
  symsync_.set_bandwidth(kSymsyncBandwidth_Hz / kTargetSampleRate_Hz);
  symsync_.set_output_rate(1);
  nco_exact_.set_pll_bandwidth(kPLLBandwidth_Hz / kTargetSampleRate_Hz);

#ifdef HAVE_SNDFILE
  if (options.input_type == INPUT_MPX_SNDFILE)
    mpx_ = new SndfileReader(options);
  else
#endif
    mpx_ = new StdinReader(options);

  resample_ratio_ = kTargetSampleRate_Hz / mpx_->samplerate();
  resampler_.set_rate(resample_ratio_);
}

Subcarrier::~Subcarrier() {
}

/** MPX to bits
 */
void Subcarrier::DemodulateMoreBits() {
  // Read from MPX source
  std::vector<float> inbuffer = mpx_->ReadBlock();
  is_eof_ = mpx_->eof();

  // Resample if needed
  int num_samples = 0;

  std::vector<std::complex<float>> complex_samples(
      resample_ratio_ <= 1.0f ? inbuffer.size() :
                                inbuffer.size() * resample_ratio_);

  if (resample_ratio_ == 1.0f) {
    for (size_t i = 0; i < inbuffer.size(); i++)
      complex_samples[i] = inbuffer[i];
    num_samples = inbuffer.size();
  } else {
    int i_resampled = 0;
    for (size_t i = 0; i < inbuffer.size(); i++) {
      std::complex<float> buf[4];
      int num_resampled = resampler_.execute(inbuffer[i], buf);

      for (int j = 0; j < num_resampled; j++) {
        complex_samples[i_resampled] = buf[j];
        i_resampled++;
      }
    }
    num_samples = i_resampled;
  }

  const int decimate_ratio = kTargetSampleRate_Hz / kBitsPerSecond / 2 /
                             kSamplesPerSymbol;

  for (int i = 0; i < num_samples; i++) {
    std::complex<float> sample = complex_samples[i];

    // Mix RDS to baseband for filtering purposes
    std::complex<float> sample_baseband = nco_approx_.MixDown(sample);

    fir_lpf_.push(sample_baseband);

    if (numsamples_ % decimate_ratio == 0) {
      std::complex<float> sample_lopass = agc_.execute(fir_lpf_.execute());

      // PLL-controlled 57 kHz mixdown - aliasing is intentional so we don't
      // have to mix it back up first
      sample_lopass = nco_exact_.MixDown(sample_lopass);

      std::vector<std::complex<float>> symbols =
        symsync_.execute(sample_lopass);

      for (std::complex<float> symbol : symbols) {
#ifdef DEBUG
        printf("sy:%f,%f,%f\n",
            numsamples_ / kTargetSampleRate_Hz,
            symbol.real(),
            symbol.imag());
#endif

        // Modem here is only used to track PLL phase error
        modem_.Demodulate(symbol);
        nco_exact_.StepPLL(modem_.phase_error() * kPLLMultiplier);

        bool is_clock;
        std::complex<float> biphase;
        std::tie(is_clock, biphase) = biphase_decoder_.push(symbol);

        // One biphase symbol received for every 2 PSK symbols
        if (is_clock) {
          bit_buffer_.push_back(delta_decoder_.Decode(
                biphase.real() >= 0));
#ifdef DEBUG
          printf("bi:%f,%f,%f\n",
              numsamples_ / kTargetSampleRate_Hz,
              biphase.real(),
              biphase.imag());
#endif
        }
      }
#ifdef DEBUG
      printf("f:%f,%f,%f,%f,%f,%f,%f\n",
          numsamples_ / kTargetSampleRate_Hz,
          static_cast<float>(sample),
          step2hertz(nco_exact_.frequency()),
          modem_.phase_error(),
          agc_.gain(),
          sample_lopass.real(),
          sample_lopass.imag());
#endif
    }

    nco_exact_.Step();
    nco_approx_.Step();

    numsamples_++;
  }
}

int Subcarrier::NextBit() {
  while (bit_buffer_.size() < 1 && !eof())
    DemodulateMoreBits();

  int bit = 0;

  if (bit_buffer_.size() > 0) {
    bit = bit_buffer_.front();
    bit_buffer_.pop_front();
  }

  return bit;
}

bool Subcarrier::eof() const {
  return is_eof_;
}

#ifdef DEBUG
float Subcarrier::t() const {
  return numsamples_ / kTargetSampleRate_Hz;
}
#endif

}  // namespace redsea

#endif  // HAVE_LIQUID
<commit_msg>exit on eof<commit_after>#include "src/subcarrier.h"

#ifdef HAVE_LIQUID

#include <cmath>
#include <complex>
#include <cstdio>
#include <deque>
#include <iostream>
#include <tuple>

#ifdef HAVE_SNDFILE
#include <sndfile.h>
#endif

#include "src/common.h"
#include "src/liquid_wrappers.h"

namespace redsea {

namespace {

const float kCarrierFrequency_Hz  = 57000.0f;
const float kBitsPerSecond        = 1187.5f;
const int   kInputBufferSize      = 4096;
const int   kSamplesPerSymbol     = 3;
const float kAGCBandwidth_Hz      = 500.0f;
const float kAGCInitialGain       = 0.0077f;
const float kLowpassCutoff_Hz     = 2400.0f;
const float kSymsyncBandwidth_Hz  = 2400.0f;
const int   kSymsyncDelay         = 2;
const float kSymsyncBeta          = 0.8f;
const float kPLLBandwidth_Hz      = 0.3f;
const float kPLLMultiplier        = 9.0f;

float hertz2step(float Hz) {
  return Hz * 2.0f * M_PI / kTargetSampleRate_Hz;
}

#ifdef DEBUG
float step2hertz(float step) {
  return step * kTargetSampleRate_Hz / (2.0f * M_PI);
}
#endif

}  // namespace

bool MPXReader::eof() const {
  return is_eof_;
}

StdinReader::StdinReader(const Options& options) :
    samplerate_(options.samplerate),
    buffer_(new (std::nothrow) int16_t[kInputBufferSize]),
    feed_thru_(options.feed_thru) {
  is_eof_ = false;
}

StdinReader::~StdinReader() {
  delete[] buffer_;
}

std::vector<float> StdinReader::ReadBlock() {
  int num_read = fread(buffer_, sizeof(buffer_[0]), kInputBufferSize,
      stdin);

  if (feed_thru_)
    fwrite(buffer_, sizeof(buffer_[0]), num_read, stdout);

  if (num_read < kInputBufferSize)
    is_eof_ = true;

  std::vector<float> result(num_read);
  for (int i = 0; i < num_read; i++)
    result[i] = buffer_[i];

  return result;
}

float StdinReader::samplerate() const {
  return samplerate_;
}

#ifdef HAVE_SNDFILE
SndfileReader::SndfileReader(const Options& options) :
    info_({0, 0, 0, 0, 0, 0}),
    file_(sf_open(options.sndfilename.c_str(), SFM_READ, &info_)),
    buffer_(new (std::nothrow) float[info_.channels * kInputBufferSize]) {
  is_eof_ = false;
  if (info_.frames == 0) {
    std::cerr << "Couldn't open " << options.sndfilename << std::endl;
    is_eof_ = true;
  }
}

SndfileReader::~SndfileReader() {
  sf_close(file_);
  delete[] buffer_;
}

std::vector<float> SndfileReader::ReadBlock() {
  sf_count_t num_read = sf_readf_float(file_, buffer_, kInputBufferSize);
  if (num_read != kInputBufferSize)
    is_eof_ = true;

  // TODO(windytan): downmix channels
  std::vector<float> result(buffer_, buffer_ + num_read);
  return result;
}

float SndfileReader::samplerate() const {
  return info_.samplerate;
}
#endif

BiphaseDecoder::BiphaseDecoder() : prev_psk_symbol_(0.0f),
  clock_history_(48), clock_(0), clock_polarity_(0) {
}

BiphaseDecoder::~BiphaseDecoder() {
}

// Return {is_clock, symbol}
//   is_clock: true if symbol valid
//   symbol:   binary symbol in constellation {-1,0} => 0, {1,0} => 1
std::pair<bool, std::complex<float>> BiphaseDecoder::push(
    std::complex<float> psk_symbol) {

  std::complex<float> biphase = (psk_symbol - prev_psk_symbol_) * 0.5f;
  bool is_clock = (clock_ % 2 == clock_polarity_);

  clock_history_[clock_] = std::fabs(biphase.real());

  // Periodically evaluate validity of the chosen biphase clock polarity
  if (++clock_ == clock_history_.size()) {
    float a = 0;
    float b = 0;

    for (size_t i = 0; i < clock_history_.size(); i++) {
      if (i % 2 == 0)
        a += clock_history_[i];
      else
        b += clock_history_[i];
      clock_history_[i] = 0.f;
    }

    if      (a > b) clock_polarity_ = 0;
    else if (b > a) clock_polarity_ = 1;

    clock_ = 0;
  }

  prev_psk_symbol_ = psk_symbol;

  return {is_clock, biphase};
}

DeltaDecoder::DeltaDecoder() : prev_(0) {
}

DeltaDecoder::~DeltaDecoder() {
}

unsigned DeltaDecoder::Decode(unsigned d) {
  unsigned bit = (d != prev_);
  prev_ = d;
  return bit;
}

Subcarrier::Subcarrier(const Options& options) : numsamples_(0),
    resample_ratio_(kTargetSampleRate_Hz / options.samplerate),
    bit_buffer_(),
    fir_lpf_(256, kLowpassCutoff_Hz / kTargetSampleRate_Hz),
    agc_(kAGCBandwidth_Hz / kTargetSampleRate_Hz, kAGCInitialGain),
    nco_approx_(hertz2step(kCarrierFrequency_Hz)),
    nco_exact_(hertz2step(kCarrierFrequency_Hz)),
    symsync_(LIQUID_FIRFILT_RRC, kSamplesPerSymbol, kSymsyncDelay,
             kSymsyncBeta, 32),
    modem_(LIQUID_MODEM_PSK2),
    resampler_(resample_ratio_, 13),
    is_eof_(false), delta_decoder_() {
  symsync_.set_bandwidth(kSymsyncBandwidth_Hz / kTargetSampleRate_Hz);
  symsync_.set_output_rate(1);
  nco_exact_.set_pll_bandwidth(kPLLBandwidth_Hz / kTargetSampleRate_Hz);

#ifdef HAVE_SNDFILE
  if (options.input_type == INPUT_MPX_SNDFILE)
    mpx_ = new SndfileReader(options);
  else
#endif
    mpx_ = new StdinReader(options);

  resample_ratio_ = kTargetSampleRate_Hz / mpx_->samplerate();
  resampler_.set_rate(resample_ratio_);
}

Subcarrier::~Subcarrier() {
}

/** MPX to bits
 */
void Subcarrier::DemodulateMoreBits() {
  // Read from MPX source
  is_eof_ = mpx_->eof();
  if (is_eof_)
    return;

  std::vector<float> inbuffer = mpx_->ReadBlock();

  // Resample if needed
  int num_samples = 0;

  std::vector<std::complex<float>> complex_samples(
      resample_ratio_ <= 1.0f ? inbuffer.size() :
                                inbuffer.size() * resample_ratio_);

  if (resample_ratio_ == 1.0f) {
    for (size_t i = 0; i < inbuffer.size(); i++)
      complex_samples[i] = inbuffer[i];
    num_samples = inbuffer.size();
  } else {
    int i_resampled = 0;
    for (size_t i = 0; i < inbuffer.size(); i++) {
      std::complex<float> buf[4];
      int num_resampled = resampler_.execute(inbuffer[i], buf);

      for (int j = 0; j < num_resampled; j++) {
        complex_samples[i_resampled] = buf[j];
        i_resampled++;
      }
    }
    num_samples = i_resampled;
  }

  const int decimate_ratio = kTargetSampleRate_Hz / kBitsPerSecond / 2 /
                             kSamplesPerSymbol;

  for (int i = 0; i < num_samples; i++) {
    std::complex<float> sample = complex_samples[i];

    // Mix RDS to baseband for filtering purposes
    std::complex<float> sample_baseband = nco_approx_.MixDown(sample);

    fir_lpf_.push(sample_baseband);

    if (numsamples_ % decimate_ratio == 0) {
      std::complex<float> sample_lopass = agc_.execute(fir_lpf_.execute());

      // PLL-controlled 57 kHz mixdown - aliasing is intentional so we don't
      // have to mix it back up first
      sample_lopass = nco_exact_.MixDown(sample_lopass);

      std::vector<std::complex<float>> symbols =
        symsync_.execute(sample_lopass);

      for (std::complex<float> symbol : symbols) {
#ifdef DEBUG
        printf("sy:%f,%f,%f\n",
            numsamples_ / kTargetSampleRate_Hz,
            symbol.real(),
            symbol.imag());
#endif

        // Modem here is only used to track PLL phase error
        modem_.Demodulate(symbol);
        nco_exact_.StepPLL(modem_.phase_error() * kPLLMultiplier);

        bool is_clock;
        std::complex<float> biphase;
        std::tie(is_clock, biphase) = biphase_decoder_.push(symbol);

        // One biphase symbol received for every 2 PSK symbols
        if (is_clock) {
          bit_buffer_.push_back(delta_decoder_.Decode(
                biphase.real() >= 0));
#ifdef DEBUG
          printf("bi:%f,%f,%f\n",
              numsamples_ / kTargetSampleRate_Hz,
              biphase.real(),
              biphase.imag());
#endif
        }
      }
#ifdef DEBUG
      printf("f:%f,%f,%f,%f,%f,%f,%f\n",
          numsamples_ / kTargetSampleRate_Hz,
          static_cast<float>(sample),
          step2hertz(nco_exact_.frequency()),
          modem_.phase_error(),
          agc_.gain(),
          sample_lopass.real(),
          sample_lopass.imag());
#endif
    }

    nco_exact_.Step();
    nco_approx_.Step();

    numsamples_++;
  }
}

int Subcarrier::NextBit() {
  while (bit_buffer_.size() < 1 && !eof())
    DemodulateMoreBits();

  int bit = 0;

  if (bit_buffer_.size() > 0) {
    bit = bit_buffer_.front();
    bit_buffer_.pop_front();
  }

  return bit;
}

bool Subcarrier::eof() const {
  return is_eof_;
}

#ifdef DEBUG
float Subcarrier::t() const {
  return numsamples_ / kTargetSampleRate_Hz;
}
#endif

}  // namespace redsea

#endif  // HAVE_LIQUID
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: XMLAutoTextEventImport.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 11:02:16 $
 *
 *  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_xmloff.hxx"

#ifndef _XMLOFF_XMLAUTOTEXTEVENTIMPORT_HXX
#include "XMLAutoTextEventImport.hxx"
#endif

#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
#include <com/sun/star/uno/Reference.hxx>
#endif

#ifndef _COM_SUN_STAR_XML_SAX_XATTRIBUTELIST_HPP_
#include <com/sun/star/xml/sax/XAttributeList.hpp>
#endif

#ifndef _COM_SUN_STAR_DOCUMENT_XEVENTSSUPPLIER_HPP_
#include <com/sun/star/document/XEventsSupplier.hpp>
#endif

#ifndef _COM_SUN_STAR_UNO_XINTERFACE_HPP_
#include <com/sun/star/uno/XInterface.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif

#ifndef _XMLOFF_XMLAUTOTEXTCONTAINEREVENTIMPORT_HXX
#include "XMLAutoTextContainerEventImport.hxx"
#endif

#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif

#ifndef _XMLOFF_XMLTOKEN_HXX
#include "xmltoken.hxx"
#endif

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

using namespace ::com::sun::star;

using ::rtl::OUString;
using ::com::sun::star::uno::Any;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;
using ::com::sun::star::uno::Type;
using ::com::sun::star::uno::XInterface;
using ::com::sun::star::uno::RuntimeException;
using ::com::sun::star::uno::Exception;
using ::com::sun::star::xml::sax::XAttributeList;
using ::com::sun::star::document::XEventsSupplier;
using ::com::sun::star::container::XNameReplace;
using ::com::sun::star::lang::XMultiServiceFactory;
using ::xmloff::token::IsXMLToken;
using ::xmloff::token::XML_AUTO_TEXT_EVENTS;

const sal_Char sAPI_AutoText[] = "com.sun.star.text.AutoTextContainer";

// #110680#
XMLAutoTextEventImport::XMLAutoTextEventImport(
    const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory) throw()
:   SvXMLImport(xServiceFactory)
{
}

XMLAutoTextEventImport::~XMLAutoTextEventImport() throw()
{
}

void XMLAutoTextEventImport::initialize(
    const Sequence<Any> & rArguments )
        throw(Exception, RuntimeException)
{
    // The events may come as either an XNameReplace or XEventsSupplier.

    const sal_Int32 nLength = rArguments.getLength();
    for( sal_Int32 i = 0; i < nLength; i++ )
    {
        const Type& rType = rArguments[i].getValueType();
        if ( rType == ::getCppuType( (Reference<XEventsSupplier>*)NULL ) )
        {
            Reference<XEventsSupplier> xSupplier;
            rArguments[i] >>= xSupplier;
            DBG_ASSERT(xSupplier.is(), "need XEventsSupplier or XNameReplace");

            xEvents = xSupplier->getEvents();
        }
        else if (rType == ::getCppuType( (Reference<XNameReplace>*)NULL ) )
        {
            rArguments[i] >>= xEvents;
            DBG_ASSERT(xEvents.is(), "need XEventsSupplier or XNameReplace");
        }
    }

    // call parent
    SvXMLImport::initialize(rArguments);
}

SvXMLImportContext* XMLAutoTextEventImport::CreateContext(
    sal_uInt16 nPrefix,
    const OUString& rLocalName,
    const Reference<XAttributeList > & xAttrList )
{
    if ( xEvents.is() && (XML_NAMESPACE_OOO == nPrefix) &&
         IsXMLToken( rLocalName, XML_AUTO_TEXT_EVENTS) )
    {
        return new XMLAutoTextContainerEventImport(
            *this, nPrefix, rLocalName, xEvents);
    }
    else
    {
        return SvXMLImport::CreateContext(nPrefix, rLocalName, xAttrList);
    }
}

Sequence< OUString > SAL_CALL
    XMLAutoTextEventImport_getSupportedServiceNames()
        throw()
{
    Sequence< OUString > aSeq( 1 );
    aSeq[0] = XMLAutoTextEventImport_getImplementationName();
    return aSeq;
}

OUString SAL_CALL XMLAutoTextEventImport_getImplementationName() throw()
{
    return OUString( RTL_CONSTASCII_USTRINGPARAM(
        "com.sun.star.comp.Writer.XMLOasisAutotextEventsImporter" ) );
}

Reference< XInterface > SAL_CALL XMLAutoTextEventImport_createInstance(
        const Reference< XMultiServiceFactory > & rSMgr)
    throw( Exception )
{
    // #110680#
    // return (cppu::OWeakObject*)new XMLAutoTextEventImport;
    return (cppu::OWeakObject*)new XMLAutoTextEventImport(rSMgr);
}

<commit_msg>INTEGRATION: CWS vgbugs07 (1.9.124); FILE MERGED 2007/06/04 13:23:35 vg 1.9.124.1: #i76605# Remove -I .../inc/module hack introduced by hedaburemove01<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: XMLAutoTextEventImport.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: hr $ $Date: 2007-06-27 15:51:43 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

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

#ifndef _XMLOFF_XMLAUTOTEXTEVENTIMPORT_HXX
#include "XMLAutoTextEventImport.hxx"
#endif

#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
#include <com/sun/star/uno/Reference.hxx>
#endif

#ifndef _COM_SUN_STAR_XML_SAX_XATTRIBUTELIST_HPP_
#include <com/sun/star/xml/sax/XAttributeList.hpp>
#endif

#ifndef _COM_SUN_STAR_DOCUMENT_XEVENTSSUPPLIER_HPP_
#include <com/sun/star/document/XEventsSupplier.hpp>
#endif

#ifndef _COM_SUN_STAR_UNO_XINTERFACE_HPP_
#include <com/sun/star/uno/XInterface.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif

#ifndef _XMLOFF_XMLAUTOTEXTCONTAINEREVENTIMPORT_HXX
#include "XMLAutoTextContainerEventImport.hxx"
#endif

#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif

#ifndef _XMLOFF_XMLTOKEN_HXX
#include <xmloff/xmltoken.hxx>
#endif

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

using namespace ::com::sun::star;

using ::rtl::OUString;
using ::com::sun::star::uno::Any;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;
using ::com::sun::star::uno::Type;
using ::com::sun::star::uno::XInterface;
using ::com::sun::star::uno::RuntimeException;
using ::com::sun::star::uno::Exception;
using ::com::sun::star::xml::sax::XAttributeList;
using ::com::sun::star::document::XEventsSupplier;
using ::com::sun::star::container::XNameReplace;
using ::com::sun::star::lang::XMultiServiceFactory;
using ::xmloff::token::IsXMLToken;
using ::xmloff::token::XML_AUTO_TEXT_EVENTS;

const sal_Char sAPI_AutoText[] = "com.sun.star.text.AutoTextContainer";

// #110680#
XMLAutoTextEventImport::XMLAutoTextEventImport(
    const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory) throw()
:   SvXMLImport(xServiceFactory)
{
}

XMLAutoTextEventImport::~XMLAutoTextEventImport() throw()
{
}

void XMLAutoTextEventImport::initialize(
    const Sequence<Any> & rArguments )
        throw(Exception, RuntimeException)
{
    // The events may come as either an XNameReplace or XEventsSupplier.

    const sal_Int32 nLength = rArguments.getLength();
    for( sal_Int32 i = 0; i < nLength; i++ )
    {
        const Type& rType = rArguments[i].getValueType();
        if ( rType == ::getCppuType( (Reference<XEventsSupplier>*)NULL ) )
        {
            Reference<XEventsSupplier> xSupplier;
            rArguments[i] >>= xSupplier;
            DBG_ASSERT(xSupplier.is(), "need XEventsSupplier or XNameReplace");

            xEvents = xSupplier->getEvents();
        }
        else if (rType == ::getCppuType( (Reference<XNameReplace>*)NULL ) )
        {
            rArguments[i] >>= xEvents;
            DBG_ASSERT(xEvents.is(), "need XEventsSupplier or XNameReplace");
        }
    }

    // call parent
    SvXMLImport::initialize(rArguments);
}

SvXMLImportContext* XMLAutoTextEventImport::CreateContext(
    sal_uInt16 nPrefix,
    const OUString& rLocalName,
    const Reference<XAttributeList > & xAttrList )
{
    if ( xEvents.is() && (XML_NAMESPACE_OOO == nPrefix) &&
         IsXMLToken( rLocalName, XML_AUTO_TEXT_EVENTS) )
    {
        return new XMLAutoTextContainerEventImport(
            *this, nPrefix, rLocalName, xEvents);
    }
    else
    {
        return SvXMLImport::CreateContext(nPrefix, rLocalName, xAttrList);
    }
}

Sequence< OUString > SAL_CALL
    XMLAutoTextEventImport_getSupportedServiceNames()
        throw()
{
    Sequence< OUString > aSeq( 1 );
    aSeq[0] = XMLAutoTextEventImport_getImplementationName();
    return aSeq;
}

OUString SAL_CALL XMLAutoTextEventImport_getImplementationName() throw()
{
    return OUString( RTL_CONSTASCII_USTRINGPARAM(
        "com.sun.star.comp.Writer.XMLOasisAutotextEventsImporter" ) );
}

Reference< XInterface > SAL_CALL XMLAutoTextEventImport_createInstance(
        const Reference< XMultiServiceFactory > & rSMgr)
    throw( Exception )
{
    // #110680#
    // return (cppu::OWeakObject*)new XMLAutoTextEventImport;
    return (cppu::OWeakObject*)new XMLAutoTextEventImport(rSMgr);
}

<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkNetCDFCAMReader.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkNetCDFCAMReader.h"

#include "vtkCellArray.h"
#include "vtkDoubleArray.h"
#include "vtkFieldData.h"
#include "vtkFloatArray.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkSmartPointer.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkUnstructuredGrid.h"

#include <map>
#include <vtk_netcdfcpp.h>

vtkStandardNewMacro(vtkNetCDFCAMReader);

//============================================================================
#define CALL_NETCDF(call) \
{ \
  int errorcode = call; \
  if (errorcode != NC_NOERR) \
  { \
    vtkErrorMacro(<< "netCDF Error: " << nc_strerror(errorcode)); \
    return 0; \
  } \
}

//----------------------------------------------------------------------------
vtkNetCDFCAMReader::vtkNetCDFCAMReader()
{
  this->FileName = NULL;
  this->ConnectivityFileName = NULL;
  this->PointsFile = NULL;
  this->ConnectivityFile = NULL;
  this->SetNumberOfInputPorts(0);
  this->SetNumberOfOutputPorts(1);
}

//----------------------------------------------------------------------------
vtkNetCDFCAMReader::~vtkNetCDFCAMReader()
{
  this->SetFileName(NULL);
  this->SetConnectivityFileName(NULL);
  if(this->PointsFile)
    {
    delete this->PointsFile;
    this->PointsFile = NULL;
    }
  if(this->ConnectivityFile)
    {
    delete this->ConnectivityFile;
    this->ConnectivityFile = NULL;
    }
}

//----------------------------------------------------------------------------
int vtkNetCDFCAMReader::CanReadFile(const char* fileName)
{
  NcFile file(fileName, NcFile::ReadOnly);
  return file.is_valid();
}

//----------------------------------------------------------------------------
void vtkNetCDFCAMReader::SetFileName(const char* fileName)
{
  vtkDebugMacro(<<" setting FileName to " << (fileName?fileName:"(null)") );
  if ( this->FileName == NULL && fileName == NULL)
    {
    return;
    }
  if ( this->FileName && fileName && (!strcmp(this->FileName,fileName)))
    {
    return;
    }
  if(this->PointsFile)
    {
    delete this->PointsFile;
    this->PointsFile = NULL;
    }
  if (this->FileName)
    {
    delete [] this->FileName;
    }
  if (fileName)
    {
    size_t n = strlen(fileName) + 1;
    char *cp1 =  new char[n];
    const char *cp2 = (fileName);
    this->FileName = cp1;
    do
      {
      *cp1++ = *cp2++;
      }
    while ( --n );
    }
   else
    {
    this->FileName = NULL;
    }
  this->Modified();
}

//----------------------------------------------------------------------------
void vtkNetCDFCAMReader::SetConnectivityFileName(const char* fileName)
{
  vtkDebugMacro(<<" setting ConnectivityFileName to "
                << (fileName?fileName:"(null)") );
  if ( this->ConnectivityFileName == NULL && fileName == NULL)
    {
    return;
    }
  if ( this->ConnectivityFileName && fileName &&
       (!strcmp(this->ConnectivityFileName,fileName)))
    {
    return;
    }
  if(this->ConnectivityFile)
    {
    delete this->ConnectivityFile;
    this->ConnectivityFile = NULL;
    }
  if (this->ConnectivityFileName)
    {
    delete [] this->ConnectivityFileName;
    }
  if (fileName)
    {
    size_t n = strlen(fileName) + 1;
    char *cp1 =  new char[n];
    const char *cp2 = (fileName);
    this->ConnectivityFileName = cp1;
    do
      {
      *cp1++ = *cp2++;
      }
    while ( --n );
    }
   else
    {
    this->ConnectivityFileName = NULL;
    }
  this->Modified();
}

//----------------------------------------------------------------------------
int vtkNetCDFCAMReader::RequestUpdateExtent(
  vtkInformation *,
  vtkInformationVector **,
  vtkInformationVector *outputVector)
{
  if(this->FileName == NULL || this->ConnectivityFileName == NULL)
    {
    vtkWarningMacro("Missing a file name.");
    return 0;
    }
  vtkInformation *outInfo = outputVector->GetInformationObject(0);

  int piece =
    outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER());
  int numPieces =
    outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES());

  // make sure piece is valid
  if (piece < 0 || piece >= numPieces)
    {
    return 1;
    }

  return 1;
}

//----------------------------------------------------------------------------
int vtkNetCDFCAMReader::RequestData(
  vtkInformation *,
  vtkInformationVector **,
  vtkInformationVector *outputVector)
{
  if(this->FileName == NULL || this->ConnectivityFileName == NULL)
    {
    vtkWarningMacro("Missing a file name.");
    return 0;
    }

  vtkInformation *outInfo = outputVector->GetInformationObject(0);
  vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast(
    outInfo->Get(vtkDataObject::DATA_OBJECT()));

  // All of the data in the first piece.
  if (outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) > 0)
    {
    return 1;
    }

  vtkDebugMacro(<<"Reading NetCDF CAM file.");

  if(this->PointsFile == NULL)
    {
    this->PointsFile = new NcFile(this->FileName, NcFile::ReadOnly);
    if(this->PointsFile->is_valid() == 0)
      {
      vtkErrorMacro(<< "Can't read file " << this->FileName);
      delete this->PointsFile;
      this->PointsFile = NULL;
      return 0;
      }
    }
  if(this->ConnectivityFile == NULL)
    {
    this->ConnectivityFile = new NcFile(this->ConnectivityFileName,
                                        NcFile::ReadOnly);
    if(this->ConnectivityFile->is_valid() == 0)
      {
      vtkErrorMacro(<< "Can't read file " << this->ConnectivityFileName);
      delete this->ConnectivityFile;
      this->ConnectivityFile = NULL;
      return 0;
      }
    }

  // read in the points first
  NcToken dimensionToken = "ncol";
  NcDim* dimension = this->PointsFile->get_dim(dimensionToken);
  NcToken lonToken = "lon";
  NcVar* lon = this->PointsFile->get_var(lonToken);
  NcToken latToken = "lat";
  NcVar* lat = this->PointsFile->get_var(latToken);
  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
  long numPoints = dimension->size();
  if(lat == NULL || lon == NULL)
    {
    vtkErrorMacro("Cannot find coordinates.");
    return 0;
    }
  if(lat->type() == ncDouble)
    {
    points->SetDataTypeToDouble();
    points->SetNumberOfPoints(numPoints);
    std::vector<double> array(numPoints*2);
    lon->get(&array[0], numPoints);
    lat->get(&array[numPoints], numPoints);
    for(long i=0;i<numPoints;i++)
      {
      points->SetPoint(i, array[i], array[i+numPoints], 0.);
      }
    }
  else
    {
    points->SetDataTypeToFloat();
    points->SetNumberOfPoints(numPoints);
    std::vector<float> array(numPoints*2);
    lon->get(&array[0], numPoints);
    lat->get(&array[numPoints], numPoints);
    for(long i=0;i<numPoints;i++)
      {
      points->SetPoint(i, array[i], array[i+numPoints], 0.);
      }
    }
  output->SetPoints(points);

  // read in any point data with dimensions (time, lev, ncol)
//   for(int i=0;i<this->PointsFile->num_vars();i++)
//     {
//     NcVar* variable = this->PointsFile->get_var(i);
//     NcToken variableName = variable->name();
//     if(variable->num_dims() != 3)
//       { // not a field variable
//       continue;
//       }
//     vtkDataArray* dataArray = NULL;
//     if(variable->type() == ncDouble)
//       {
//       vtkDoubleArray* doubleArray = vtkDoubleArray::New();
//       doubleArray->SetNumberOfTuples(numPoints);
//       variable->get(doubleArray->GetPointer(0), 0, 0, numPoints);
//       dataArray = doubleArray;
//       }
//     else
//       {
//       vtkFloatArray* floatArray = vtkFloatArray::New();
//       floatArray->SetNumberOfTuples(numPoints);
//       variable->get(floatArray->GetPointer(0), 0, 0, numPoints);
//       dataArray = floatArray;
//       }
//     dataArray->SetName(variableName);
//     output->GetPointData()->AddArray(dataArray);
//     dataArray->Delete();
//     }

  // now read in the cell connectivity.  note that this is a periodic
  // domain and only the points on the left boundary are included in
  // the points file.  if a cell uses a point that is on the left
  // boundary and it should be on the right boundary we will have
  // to create that point.  that's what boundaryPoints is used for.
  std::map<vtkIdType, vtkIdType> boundaryPoints;
  dimension = this->ConnectivityFile->get_dim("ncenters");
  if(dimension == NULL)
    {  //supposed to be ncells but in example dataset it is ncenters
    this->ConnectivityFile->get_dim("ncenters");
    }
  NcVar* connectivity = this->ConnectivityFile->get_var("element_corners");
  long numCells = dimension->size();
  output->Allocate(numCells);
  if(connectivity == NULL)
    {
    vtkErrorMacro("Cannot find cell connectivity.");
    return 0;
    }
  std::vector<int> cellConnectivity(4*numCells);
  connectivity->get(&(cellConnectivity[0]), 4, numCells);
  double bounds[6];
  output->GetBounds(bounds);
  double leftSide = bounds[0] + .25*(bounds[1]-bounds[0]);
  double rightSide = bounds[0] + .75*(bounds[1]-bounds[0]);
  for(long i=0;i<numCells;i++)
    {
    vtkIdType pointIds[4];
    bool nearRightBoundary = false;
    bool nearLeftBoundary = false;
    double point[3];
    for(int j=0;j<4;j++)
      {
      pointIds[j] = cellConnectivity[i+j*numCells]-1;
      output->GetPoint(pointIds[j], point);
      if(point[0] > rightSide)
        {
        nearRightBoundary = true;
        }
      else if(point[0] < leftSide)
        {
        nearLeftBoundary = true;
        }
      }
    if(nearLeftBoundary == true && nearRightBoundary == true)
      {
      for(int j=0;j<4;j++)
        {
        output->GetPoint(pointIds[j], point);
        if(point[0] < leftSide)
          {
          std::map<vtkIdType, vtkIdType>::iterator otherPoint =
            boundaryPoints.find(pointIds[j]);
          if(otherPoint != boundaryPoints.end())
            { // already made point on the right boundary
            pointIds[j] = otherPoint->second;
            }
          else
            { // need to make point on the right boundary
            vtkIdType newId =
              points->InsertNextPoint(point[0]+360., point[1], point[2]);
            boundaryPoints[pointIds[j]] = newId;
            output->GetPointData()->CopyData(output->GetPointData(),
                                             pointIds[j], newId);
            pointIds[j] = newId;
            }
          }
        }
      }
    output->InsertNextCell(VTK_QUAD, 4, pointIds);
    }

  vtkDebugMacro(<<"Read " <<output->GetNumberOfPoints() <<" points,"
                <<output->GetNumberOfCells() <<" cells.\n");

  return 1;
}

//----------------------------------------------------------------------------
int vtkNetCDFCAMReader::FillOutputPortInformation(int,
                                                  vtkInformation* info)
{
  info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkUnstructuredGrid");
  return 1;
}

//----------------------------------------------------------------------------
void vtkNetCDFCAMReader::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
}
<commit_msg>Reader now working with reading point data at first level.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkNetCDFCAMReader.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkNetCDFCAMReader.h"

#include "vtkCellArray.h"
#include "vtkDoubleArray.h"
#include "vtkFieldData.h"
#include "vtkFloatArray.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkSmartPointer.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkUnstructuredGrid.h"

#include <map>
#include <vtk_netcdfcpp.h>

vtkStandardNewMacro(vtkNetCDFCAMReader);

//============================================================================
#define CALL_NETCDF(call) \
{ \
  int errorcode = call; \
  if (errorcode != NC_NOERR) \
  { \
    vtkErrorMacro(<< "netCDF Error: " << nc_strerror(errorcode)); \
    return 0; \
  } \
}

//----------------------------------------------------------------------------
vtkNetCDFCAMReader::vtkNetCDFCAMReader()
{
  this->FileName = NULL;
  this->ConnectivityFileName = NULL;
  this->PointsFile = NULL;
  this->ConnectivityFile = NULL;
  this->SetNumberOfInputPorts(0);
  this->SetNumberOfOutputPorts(1);
}

//----------------------------------------------------------------------------
vtkNetCDFCAMReader::~vtkNetCDFCAMReader()
{
  this->SetFileName(NULL);
  this->SetConnectivityFileName(NULL);
  if(this->PointsFile)
    {
    delete this->PointsFile;
    this->PointsFile = NULL;
    }
  if(this->ConnectivityFile)
    {
    delete this->ConnectivityFile;
    this->ConnectivityFile = NULL;
    }
}

//----------------------------------------------------------------------------
int vtkNetCDFCAMReader::CanReadFile(const char* fileName)
{
  NcFile file(fileName, NcFile::ReadOnly);
  return file.is_valid();
}

//----------------------------------------------------------------------------
void vtkNetCDFCAMReader::SetFileName(const char* fileName)
{
  vtkDebugMacro(<<" setting FileName to " << (fileName?fileName:"(null)") );
  if ( this->FileName == NULL && fileName == NULL)
    {
    return;
    }
  if ( this->FileName && fileName && (!strcmp(this->FileName,fileName)))
    {
    return;
    }
  if(this->PointsFile)
    {
    delete this->PointsFile;
    this->PointsFile = NULL;
    }
  if (this->FileName)
    {
    delete [] this->FileName;
    }
  if (fileName)
    {
    size_t n = strlen(fileName) + 1;
    char *cp1 =  new char[n];
    const char *cp2 = (fileName);
    this->FileName = cp1;
    do
      {
      *cp1++ = *cp2++;
      }
    while ( --n );
    }
   else
    {
    this->FileName = NULL;
    }
  this->Modified();
}

//----------------------------------------------------------------------------
void vtkNetCDFCAMReader::SetConnectivityFileName(const char* fileName)
{
  vtkDebugMacro(<<" setting ConnectivityFileName to "
                << (fileName?fileName:"(null)") );
  if ( this->ConnectivityFileName == NULL && fileName == NULL)
    {
    return;
    }
  if ( this->ConnectivityFileName && fileName &&
       (!strcmp(this->ConnectivityFileName,fileName)))
    {
    return;
    }
  if(this->ConnectivityFile)
    {
    delete this->ConnectivityFile;
    this->ConnectivityFile = NULL;
    }
  if (this->ConnectivityFileName)
    {
    delete [] this->ConnectivityFileName;
    }
  if (fileName)
    {
    size_t n = strlen(fileName) + 1;
    char *cp1 =  new char[n];
    const char *cp2 = (fileName);
    this->ConnectivityFileName = cp1;
    do
      {
      *cp1++ = *cp2++;
      }
    while ( --n );
    }
   else
    {
    this->ConnectivityFileName = NULL;
    }
  this->Modified();
}

//----------------------------------------------------------------------------
int vtkNetCDFCAMReader::RequestUpdateExtent(
  vtkInformation *,
  vtkInformationVector **,
  vtkInformationVector *outputVector)
{
  if(this->FileName == NULL || this->ConnectivityFileName == NULL)
    {
    vtkWarningMacro("Missing a file name.");
    return 0;
    }
  vtkInformation *outInfo = outputVector->GetInformationObject(0);

  int piece =
    outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER());
  int numPieces =
    outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES());

  // make sure piece is valid
  if (piece < 0 || piece >= numPieces)
    {
    return 1;
    }

  return 1;
}

//----------------------------------------------------------------------------
int vtkNetCDFCAMReader::RequestData(
  vtkInformation *,
  vtkInformationVector **,
  vtkInformationVector *outputVector)
{
  if(this->FileName == NULL || this->ConnectivityFileName == NULL)
    {
    vtkWarningMacro("Missing a file name.");
    return 0;
    }

  vtkInformation *outInfo = outputVector->GetInformationObject(0);
  vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast(
    outInfo->Get(vtkDataObject::DATA_OBJECT()));

  // All of the data in the first piece.
  if (outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) > 0)
    {
    return 1;
    }

  vtkDebugMacro(<<"Reading NetCDF CAM file.");

  if(this->PointsFile == NULL)
    {
    this->PointsFile = new NcFile(this->FileName, NcFile::ReadOnly);
    if(this->PointsFile->is_valid() == 0)
      {
      vtkErrorMacro(<< "Can't read file " << this->FileName);
      delete this->PointsFile;
      this->PointsFile = NULL;
      return 0;
      }
    }
  if(this->ConnectivityFile == NULL)
    {
    this->ConnectivityFile = new NcFile(this->ConnectivityFileName,
                                        NcFile::ReadOnly);
    if(this->ConnectivityFile->is_valid() == 0)
      {
      vtkErrorMacro(<< "Can't read file " << this->ConnectivityFileName);
      delete this->ConnectivityFile;
      this->ConnectivityFile = NULL;
      return 0;
      }
    }

  // read in the points first
  NcDim* dimension = this->PointsFile->get_dim("ncol");
  NcVar* lon = this->PointsFile->get_var("lon");
  NcVar* lat = this->PointsFile->get_var("lat");
  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
  long numPoints = dimension->size();
  if(lat == NULL || lon == NULL)
    {
    vtkErrorMacro("Cannot find coordinates.");
    return 0;
    }
  if(lat->type() == ncDouble)
    {
    points->SetDataTypeToDouble();
    points->SetNumberOfPoints(numPoints);
    std::vector<double> array(numPoints*2);
    if(!lon->get(&array[0], numPoints))
      {
      return 0;
      }
    if(!lat->get(&array[numPoints], numPoints))
      {
      return 0;
      }
    for(long i=0;i<numPoints;i++)
      {
      points->SetPoint(i, array[i], array[i+numPoints], 0.);
      }
    }
  else
    {
    points->SetDataTypeToFloat();
    points->SetNumberOfPoints(numPoints);
    std::vector<float> array(numPoints*2);
    if(!lon->get(&array[0], numPoints))
      {
      return 0;
      }
    if(!lat->get(&array[numPoints], numPoints))
      {
      return 0;
      }
    for(long i=0;i<numPoints;i++)
      {
      points->SetPoint(i, array[i], array[i+numPoints], 0.);
      }
    for(long i=0;i<numPoints;i++)
      {
      points->SetPoint(i, array[i], array[i+numPoints], 0.);
      }
    }
  output->SetPoints(points);

  // read in any point data with dimensions (time, lev, ncol)
  NcDim* levelsDimension = this->PointsFile->get_dim("lev");
  long numLevels = levelsDimension->size();
  for(int i=0;i<this->PointsFile->num_vars();i++)
    {
    NcVar* variable = this->PointsFile->get_var(i);
    if(variable->num_dims() != 3 || variable->get_dim(0)->size() != 1 ||
       variable->get_dim(1)->size() != numLevels ||
       variable->get_dim(2)->size() != numPoints)
      { // not a field variable
      continue;
      }
    NcToken variableName = variable->name();
    // if we have a different level, that should be set here
    long level = 0;
    variable->set_cur(0, level, 0);
    vtkDataArray* dataArray = NULL;
    if(variable->type() == ncDouble)
      {
      vtkDoubleArray* doubleArray = vtkDoubleArray::New();
      doubleArray->SetNumberOfTuples(numPoints);
      if(!variable->get(doubleArray->GetPointer(0),
                        1, 1, numPoints))
        {
        return 0;
        }
      dataArray = doubleArray;
      }
    else
      {
      vtkFloatArray* floatArray = vtkFloatArray::New();
      floatArray->SetNumberOfTuples(numPoints);
      if(!variable->get(floatArray->GetPointer(0),
                        1, 1, numPoints))
        {
        return 0;
        }
      dataArray = floatArray;
      }
    dataArray->SetName(variableName);
    output->GetPointData()->AddArray(dataArray);
    dataArray->Delete();
    }

  // now read in the cell connectivity.  note that this is a periodic
  // domain and only the points on the left boundary are included in
  // the points file.  if a cell uses a point that is on the left
  // boundary and it should be on the right boundary we will have
  // to create that point.  that's what boundaryPoints is used for.
  std::map<vtkIdType, vtkIdType> boundaryPoints;
  dimension = this->ConnectivityFile->get_dim("ncenters");
  if(dimension == NULL)
    {  //supposed to be ncells but in example dataset it is ncenters
    this->ConnectivityFile->get_dim("ncenters");
    }
  NcVar* connectivity = this->ConnectivityFile->get_var("element_corners");
  long numCells = dimension->size();
  output->Allocate(numCells);
  if(connectivity == NULL)
    {
    vtkErrorMacro("Cannot find cell connectivity.");
    return 0;
    }
  std::vector<int> cellConnectivity(4*numCells);
  connectivity->get(&(cellConnectivity[0]), 4, numCells);
  double bounds[6];
  output->GetBounds(bounds);
  double leftSide = bounds[0] + .25*(bounds[1]-bounds[0]);
  double rightSide = bounds[0] + .75*(bounds[1]-bounds[0]);
  for(long i=0;i<numCells;i++)
    {
    vtkIdType pointIds[4];
    bool nearRightBoundary = false;
    bool nearLeftBoundary = false;
    double point[3];
    for(int j=0;j<4;j++)
      {
      pointIds[j] = cellConnectivity[i+j*numCells]-1;
      output->GetPoint(pointIds[j], point);
      if(point[0] > rightSide)
        {
        nearRightBoundary = true;
        }
      else if(point[0] < leftSide)
        {
        nearLeftBoundary = true;
        }
      }
    if(nearLeftBoundary == true && nearRightBoundary == true)
      {
      for(int j=0;j<4;j++)
        {
        output->GetPoint(pointIds[j], point);
        if(point[0] < leftSide)
          {
          std::map<vtkIdType, vtkIdType>::iterator otherPoint =
            boundaryPoints.find(pointIds[j]);
          if(otherPoint != boundaryPoints.end())
            { // already made point on the right boundary
            pointIds[j] = otherPoint->second;
            }
          else
            { // need to make point on the right boundary
            pointIds[j] = boundaryPoints[pointIds[j]] =
              points->InsertNextPoint(point[0]+360., point[1], point[2]);
            }
          }
        }
      }
    output->InsertNextCell(VTK_QUAD, 4, pointIds);
    }

  output->GetPointData()->CopyAllOn();
  output->GetPointData()->CopyAllocate(output->GetPointData(),
                                       output->GetNumberOfPoints());
  vtkPointData* pointData = output->GetPointData();
  for(std::map<vtkIdType, vtkIdType>::const_iterator it=
        boundaryPoints.begin();it!=boundaryPoints.end();it++)
    {
    pointData->CopyData(pointData, it->first, it->second);
    }

  vtkDebugMacro(<<"Read " <<output->GetNumberOfPoints() <<" points,"
                <<output->GetNumberOfCells() <<" cells.\n");

  return 1;
}

//----------------------------------------------------------------------------
int vtkNetCDFCAMReader::FillOutputPortInformation(int,
                                                  vtkInformation* info)
{
  info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkUnstructuredGrid");
  return 1;
}

//----------------------------------------------------------------------------
void vtkNetCDFCAMReader::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
}
<|endoftext|>