<commit_before>#include <bts/blockchain/balance_operations.hpp>
#include <bts/blockchain/chain_interface.hpp>
#include <bts/blockchain/exceptions.hpp>

namespace bts { namespace blockchain {

   balance_id_type  deposit_operation::balance_id()const
   {
      return condition.get_address();
   }

   deposit_operation::deposit_operation( const address& owner,
                                         const asset& amnt,
                                         slate_id_type slate_id )
   {
      FC_ASSERT( amnt.amount > 0 );
      amount = amnt.amount;
      condition = withdraw_condition( withdraw_with_signature( owner ),
                                      amnt.asset_id, slate_id );
   }

   void define_delegate_slate_operation::evaluate( transaction_evaluation_state& eval_state )
   { try {
      auto slate_id = this->slate.id();

      if( this->slate.supported_delegates.size() > BTS_BLOCKCHAIN_MAX_SLATE_SIZE )
         FC_CAPTURE_AND_THROW( too_may_delegates_in_slate, (slate.supported_delegates.size()) );

      auto current_slate = eval_state._current_state->get_delegate_slate( slate_id );
      if( NOT current_slate )
      {
         for( auto delegate_id : this->slate.supported_delegates )
         {
            eval_state.verify_delegate_id( abs(delegate_id) );
         }
         eval_state._current_state->store_delegate_slate( slate_id, slate );
      }
   } FC_CAPTURE_AND_RETHROW( (eval_state) ) }

   /**
    *  TODO: Document Rules for Deposits
    *
    */
   void deposit_operation::evaluate( transaction_evaluation_state& eval_state )
   { try {
       if( this->amount <= 0 )
          FC_CAPTURE_AND_THROW( negative_deposit, (amount) );

       auto deposit_balance_id = this->balance_id();

       auto cur_record = eval_state._current_state->get_balance_record( deposit_balance_id );
       if( !cur_record )
       {
          cur_record = balance_record( this->condition );
       }
       cur_record->last_update   = eval_state._current_state->now();
       cur_record->balance       += this->amount;

       eval_state.sub_balance( deposit_balance_id, asset(this->amount, cur_record->condition.asset_id) );

       if( cur_record->condition.asset_id == 0 && cur_record->condition.delegate_slate_id )
          eval_state.adjust_vote( cur_record->condition.delegate_slate_id, this->amount );

       eval_state._current_state->store_balance_record( *cur_record );
   } FC_CAPTURE_AND_RETHROW( (*this) ) }

   /**
    *  TODO: Document rules for Withdraws
    */
   void withdraw_operation::evaluate( transaction_evaluation_state& eval_state )
   { try {
       if( this->amount <= 0 )
          FC_CAPTURE_AND_THROW( negative_deposit, (amount) );

      obalance_record current_balance_record = eval_state._current_state->get_balance_record( this->balance_id );

      if( !current_balance_record )
         FC_CAPTURE_AND_THROW( unknown_balance_record, (balance_id) );

      if( this->amount > current_balance_record->balance )
         FC_CAPTURE_AND_THROW( insufficient_funds,
                               (current_balance_record)
                               (amount)
                               (current_balance_record->balance - amount) );

      switch( (withdraw_condition_types)current_balance_record->condition.type )
      {
         case withdraw_signature_type:
         {
            auto owner = current_balance_record->condition.as<withdraw_with_signature>().owner;
            if( claim_input_data.size() )
            {
               auto pts_sig = fc::raw::unpack<withdraw_with_pts>( claim_input_data );
               fc::sha256::encoder enc;
               fc::raw::pack( enc, eval_state._current_state->get_property( chain_property_enum::chain_id ).as<fc::ripemd160>() );
               fc::raw::pack( enc, pts_sig.new_key );
               auto digest = enc.result();
               fc::ecc::public_key test_key( pts_sig.pts_signature, digest );
               if( address(test_key) == owner ||
                   address(pts_address(test_key,false,56) ) == owner ||
                   address(pts_address(test_key,true,56) ) == owner ||
                   address(pts_address(test_key,false,0) ) == owner ||
                   address(pts_address(test_key,true,0) ) == owner )
               {
                  if( !eval_state.check_signature( pts_sig.new_key) )
                     FC_CAPTURE_AND_THROW( missing_signature, (pts_sig) );
                  break;
               }
               else
               {
                  FC_CAPTURE_AND_THROW( missing_signature, (owner)(pts_sig) );
               }
            }
            else
            {
               if( !eval_state.check_signature( owner ) )
                  FC_CAPTURE_AND_THROW( missing_signature, (owner) );
            }
            break;
         }

         case withdraw_multi_sig_type:
         {
            auto multi_sig = current_balance_record->condition.as<withdraw_with_multi_sig>();
            uint32_t valid_signatures = 0;
            for( auto sig : multi_sig.owners )
               valid_signatures += eval_state.check_signature( sig );
            if( valid_signatures < multi_sig.required )
               FC_CAPTURE_AND_THROW( missing_signature, (valid_signatures)(multi_sig) );
            break;
         }

         case withdraw_password_type:
         {
            auto password_condition = current_balance_record->condition.as<withdraw_with_password>();
            try {
               if( password_condition.timeout < eval_state._current_state->now() )
               {
                  if( !eval_state.check_signature( password_condition.payor ) )
                     FC_CAPTURE_AND_THROW( missing_signature, (password_condition.payor) );
               }
               else
               {
                  if( !eval_state.check_signature( password_condition.payee ) )
                     FC_CAPTURE_AND_THROW( missing_signature, (password_condition.payee) );
                  if( claim_input_data.size() < sizeof( fc::ripemd160 ) )
                     FC_CAPTURE_AND_THROW( invalid_claim_password, (claim_input_data) );

                  auto input_password_hash = fc::ripemd160::hash( claim_input_data.data(),
                                                                  claim_input_data.size() );

                  if( password_condition.password_hash != input_password_hash )
                     FC_CAPTURE_AND_THROW( invalid_claim_password, (input_password_hash) );
               }
            } FC_CAPTURE_AND_RETHROW( (password_condition ) )
            break;
         }

         case withdraw_option_type:
         {
            auto option = current_balance_record->condition.as<withdraw_option>();
            try {
               if( eval_state._current_state->now() > option.date )
               {
                  if( !eval_state.check_signature( option.optionor ) )
                     FC_CAPTURE_AND_THROW( missing_signature, (option.optionor) );
               }
               else // the option hasn't expired
               {
                  if( !eval_state.check_signature( option.optionee ) )
                     FC_CAPTURE_AND_THROW( missing_signature, (option.optionee) );

                  auto pay_amount = asset( this->amount, current_balance_record->condition.asset_id ) * option.strike_price;
                  eval_state.add_required_deposit( option.optionee, pay_amount );
               }
            } FC_CAPTURE_AND_RETHROW( (option) )
            break;
         }

        case withdraw_domain_offer_type:
        {
            auto offer = current_balance_record->condition.as<withdraw_domain_offer>();
            try {
                // TODO check date
                // If it's yours it's free
                if( eval_state.check_signature( offer.owner ) )
                {
                    FC_ASSERT(!"unimplemented withdraw_domain_offer_type for cancels");
                    //TODO remove offer from state
                }
                else  // otherwise there has to be a domain transfer to the previous owner
                {
                    for (auto op : eval_state.trx.operations)
                    {
                        if (op.type == operation_type_enum::domain_transfer_operation)
                        {
                            auto transfer = op.as<domain_transfer_operation>();
                            FC_ASSERT( transfer.domain_name == offer.domain_name, "transferring wrong domain name" );
                            FC_ASSERT( transfer.owner == offer.owner_address, "transferring to wrong owner" );
                        }
                    }
                }
            } FC_CAPTURE_AND_RETHROW( (offer) )
        }

         case withdraw_null_type:
            FC_CAPTURE_AND_THROW( invalid_withdraw_condition, (current_balance_record->condition) );
            break;
      //   default:
      }
      // update delegate vote on withdrawn account..

      current_balance_record->balance -= this->amount;
      current_balance_record->last_update = eval_state._current_state->now();
      eval_state.add_balance( asset(this->amount, current_balance_record->condition.asset_id) );

      if( current_balance_record->condition.asset_id == 0 && current_balance_record->condition.delegate_slate_id )
         eval_state.adjust_vote( current_balance_record->condition.delegate_slate_id, -this->amount );

      eval_state._current_state->store_balance_record( *current_balance_record );
   } FC_CAPTURE_AND_RETHROW( (*this) ) }

} } // bts::blockchain
<commit_msg>fix build<commit_after>#include <bts/blockchain/balance_operations.hpp>
#include <bts/blockchain/dns_operations.hpp>
#include <bts/blockchain/chain_interface.hpp>
#include <bts/blockchain/exceptions.hpp>

namespace bts { namespace blockchain {

   balance_id_type  deposit_operation::balance_id()const
   {
      return condition.get_address();
   }

   deposit_operation::deposit_operation( const address& owner,
                                         const asset& amnt,
                                         slate_id_type slate_id )
   {
      FC_ASSERT( amnt.amount > 0 );
      amount = amnt.amount;
      condition = withdraw_condition( withdraw_with_signature( owner ),
                                      amnt.asset_id, slate_id );
   }

   void define_delegate_slate_operation::evaluate( transaction_evaluation_state& eval_state )
   { try {
      auto slate_id = this->slate.id();

      if( this->slate.supported_delegates.size() > BTS_BLOCKCHAIN_MAX_SLATE_SIZE )
         FC_CAPTURE_AND_THROW( too_may_delegates_in_slate, (slate.supported_delegates.size()) );

      auto current_slate = eval_state._current_state->get_delegate_slate( slate_id );
      if( NOT current_slate )
      {
         for( auto delegate_id : this->slate.supported_delegates )
         {
            eval_state.verify_delegate_id( abs(delegate_id) );
         }
         eval_state._current_state->store_delegate_slate( slate_id, slate );
      }
   } FC_CAPTURE_AND_RETHROW( (eval_state) ) }

   /**
    *  TODO: Document Rules for Deposits
    *
    */
   void deposit_operation::evaluate( transaction_evaluation_state& eval_state )
   { try {
       if( this->amount <= 0 )
          FC_CAPTURE_AND_THROW( negative_deposit, (amount) );

       auto deposit_balance_id = this->balance_id();

       auto cur_record = eval_state._current_state->get_balance_record( deposit_balance_id );
       if( !cur_record )
       {
          cur_record = balance_record( this->condition );
       }
       cur_record->last_update   = eval_state._current_state->now();
       cur_record->balance       += this->amount;

       eval_state.sub_balance( deposit_balance_id, asset(this->amount, cur_record->condition.asset_id) );

       if( cur_record->condition.asset_id == 0 && cur_record->condition.delegate_slate_id )
          eval_state.adjust_vote( cur_record->condition.delegate_slate_id, this->amount );

       eval_state._current_state->store_balance_record( *cur_record );
   } FC_CAPTURE_AND_RETHROW( (*this) ) }

   /**
    *  TODO: Document rules for Withdraws
    */
   void withdraw_operation::evaluate( transaction_evaluation_state& eval_state )
   { try {
       if( this->amount <= 0 )
          FC_CAPTURE_AND_THROW( negative_deposit, (amount) );

      obalance_record current_balance_record = eval_state._current_state->get_balance_record( this->balance_id );

      if( !current_balance_record )
         FC_CAPTURE_AND_THROW( unknown_balance_record, (balance_id) );

      if( this->amount > current_balance_record->balance )
         FC_CAPTURE_AND_THROW( insufficient_funds,
                               (current_balance_record)
                               (amount)
                               (current_balance_record->balance - amount) );

      switch( (withdraw_condition_types)current_balance_record->condition.type )
      {
         case withdraw_signature_type:
         {
            auto owner = current_balance_record->condition.as<withdraw_with_signature>().owner;
            if( claim_input_data.size() )
            {
               auto pts_sig = fc::raw::unpack<withdraw_with_pts>( claim_input_data );
               fc::sha256::encoder enc;
               fc::raw::pack( enc, eval_state._current_state->get_property( chain_property_enum::chain_id ).as<fc::ripemd160>() );
               fc::raw::pack( enc, pts_sig.new_key );
               auto digest = enc.result();
               fc::ecc::public_key test_key( pts_sig.pts_signature, digest );
               if( address(test_key) == owner ||
                   address(pts_address(test_key,false,56) ) == owner ||
                   address(pts_address(test_key,true,56) ) == owner ||
                   address(pts_address(test_key,false,0) ) == owner ||
                   address(pts_address(test_key,true,0) ) == owner )
               {
                  if( !eval_state.check_signature( pts_sig.new_key) )
                     FC_CAPTURE_AND_THROW( missing_signature, (pts_sig) );
                  break;
               }
               else
               {
                  FC_CAPTURE_AND_THROW( missing_signature, (owner)(pts_sig) );
               }
            }
            else
            {
               if( !eval_state.check_signature( owner ) )
                  FC_CAPTURE_AND_THROW( missing_signature, (owner) );
            }
            break;
         }

         case withdraw_multi_sig_type:
         {
            auto multi_sig = current_balance_record->condition.as<withdraw_with_multi_sig>();
            uint32_t valid_signatures = 0;
            for( auto sig : multi_sig.owners )
               valid_signatures += eval_state.check_signature( sig );
            if( valid_signatures < multi_sig.required )
               FC_CAPTURE_AND_THROW( missing_signature, (valid_signatures)(multi_sig) );
            break;
         }

         case withdraw_password_type:
         {
            auto password_condition = current_balance_record->condition.as<withdraw_with_password>();
            try {
               if( password_condition.timeout < eval_state._current_state->now() )
               {
                  if( !eval_state.check_signature( password_condition.payor ) )
                     FC_CAPTURE_AND_THROW( missing_signature, (password_condition.payor) );
               }
               else
               {
                  if( !eval_state.check_signature( password_condition.payee ) )
                     FC_CAPTURE_AND_THROW( missing_signature, (password_condition.payee) );
                  if( claim_input_data.size() < sizeof( fc::ripemd160 ) )
                     FC_CAPTURE_AND_THROW( invalid_claim_password, (claim_input_data) );

                  auto input_password_hash = fc::ripemd160::hash( claim_input_data.data(),
                                                                  claim_input_data.size() );

                  if( password_condition.password_hash != input_password_hash )
                     FC_CAPTURE_AND_THROW( invalid_claim_password, (input_password_hash) );
               }
            } FC_CAPTURE_AND_RETHROW( (password_condition ) )
            break;
         }

         case withdraw_option_type:
         {
            auto option = current_balance_record->condition.as<withdraw_option>();
            try {
               if( eval_state._current_state->now() > option.date )
               {
                  if( !eval_state.check_signature( option.optionor ) )
                     FC_CAPTURE_AND_THROW( missing_signature, (option.optionor) );
               }
               else // the option hasn't expired
               {
                  if( !eval_state.check_signature( option.optionee ) )
                     FC_CAPTURE_AND_THROW( missing_signature, (option.optionee) );

                  auto pay_amount = asset( this->amount, current_balance_record->condition.asset_id ) * option.strike_price;
                  eval_state.add_required_deposit( option.optionee, pay_amount );
               }
            } FC_CAPTURE_AND_RETHROW( (option) )
            break;
         }

        case withdraw_domain_offer_type:
        {
            auto offer = current_balance_record->condition.as<withdraw_domain_offer>();
            try {
                // TODO check date
                // If it's yours it's free
                if( eval_state.check_signature( offer.owner ) )
                {
                    FC_ASSERT(!"unimplemented withdraw_domain_offer_type for cancels");
                    //TODO remove offer from state
                }
                else  // otherwise there has to be a domain transfer to the previous owner
                {
                    for (auto op : eval_state.trx.operations)
                    {
                        if (op.type == operation_type_enum::domain_transfer_op_type)
                        {
                            auto transfer = op.as<domain_transfer_operation>();
                            FC_ASSERT( transfer.domain_name == offer.domain_name, "transferring wrong domain name" );
                            FC_ASSERT( transfer.owner == offer.owner, "transferring to wrong owner" );
                        }
                    }
                }
            } FC_CAPTURE_AND_RETHROW( (offer) )
        }

         case withdraw_null_type:
            FC_CAPTURE_AND_THROW( invalid_withdraw_condition, (current_balance_record->condition) );
            break;
      //   default:
      }
      // update delegate vote on withdrawn account..

      current_balance_record->balance -= this->amount;
      current_balance_record->last_update = eval_state._current_state->now();
      eval_state.add_balance( asset(this->amount, current_balance_record->condition.asset_id) );

      if( current_balance_record->condition.asset_id == 0 && current_balance_record->condition.delegate_slate_id )
         eval_state.adjust_vote( current_balance_record->condition.delegate_slate_id, -this->amount );

      eval_state._current_state->store_balance_record( *current_balance_record );
   } FC_CAPTURE_AND_RETHROW( (*this) ) }

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


<commit_before>#include "cinder/app/AppBasic.h"
#include "cinder/audio/Output.h"
#include "cinder/audio/Callback.h"
#include "cinder/CinderMath.h"

using namespace ci;
using namespace ci::app;

class AudioGenerativeApp : public AppBasic {
 public:
	void setup();
	void mouseMove( MouseEvent event );
	void sineWave( uint64_t inSampleOffset, uint32_t ioSampleCount, audio::Buffer32f *ioBuffer );
	void draw();

	float mFreqTarget;
	float mPhase;
	float mPhaseAdjust;
	float mMaxFreq;
};

void AudioGenerativeApp::setup()
{
	mMaxFreq = 2000.0f;
	mFreqTarget = 0.0f;
	mPhase = 0.0f;
	mPhaseAdjust = 0.0f;

	audio::Output::play( audio::createCallback( this, &AudioGenerativeApp::sineWave ) );
}

void AudioGenerativeApp::mouseMove( MouseEvent event )
{
	int height = getWindowHeight();
	//gFreqTarget = ( height - event.getY() ) / (float)height * gMaxFreq/ 44100.0f;
	mFreqTarget = math<float>::clamp( ( height - event.getY() ) / (float)height * mMaxFreq, 0.0, mMaxFreq );
}

void AudioGenerativeApp::sineWave( uint64_t inSampleOffset, uint32_t ioSampleCount, audio::Buffer32f *ioBuffer ) {
	mPhaseAdjust = mPhaseAdjust * 0.95f + ( mFreqTarget / 44100.0f ) * 0.05f;
	for( int  i = 0; i < ioSampleCount; i++ ) {
		mPhase += mPhaseAdjust;
		float r = mPhase - math<float>::floor( mPhase );
		float val = math<float>::sin( r * 2.0f * M_PI );

		ioBuffer->mData[i*ioBuffer->mNumberChannels] = val;
		ioBuffer->mData[i*ioBuffer->mNumberChannels + 1] = val;
	}
}

void AudioGenerativeApp::draw()
{
	gl::clear( Color( 0.1f, 0.1f, 0.1f ) );

	// draw a representation of the sine wave
	const float audioToVisualScale = 10.0f;
	const float waveHeight = 200.0f;
	gl::color( Color( 1.0f, 0.5f, 0.25f ) );
	glBegin( GL_LINE_STRIP );
	for( float x = -getWindowWidth() / 2; x < getWindowWidth() / 2; x += 0.5f ) {
		gl::vertex( getWindowCenter() + Vec2f( x, waveHeight * sin( x * mPhaseAdjust * audioToVisualScale ) ) );
	}
	glEnd();
}

CINDER_APP_BASIC( AudioGenerativeApp, RendererGl )
<commit_msg>adding alltom`s bug fix to prevent floating point errors in audioGenerative sample<commit_after>#include "cinder/app/AppBasic.h"
#include "cinder/audio/Output.h"
#include "cinder/audio/Callback.h"
#include "cinder/CinderMath.h"

using namespace ci;
using namespace ci::app;

class AudioGenerativeApp : public AppBasic {
 public:
	void setup();
	void mouseMove( MouseEvent event );
	void sineWave( uint64_t inSampleOffset, uint32_t ioSampleCount, audio::Buffer32f *ioBuffer );
	void draw();

	float mFreqTarget;
	float mPhase;
	float mPhaseAdjust;
	float mMaxFreq;
};

void AudioGenerativeApp::setup()
{
	mMaxFreq = 2000.0f;
	mFreqTarget = 0.0f;
	mPhase = 0.0f;
	mPhaseAdjust = 0.0f;

	audio::Output::play( audio::createCallback( this, &AudioGenerativeApp::sineWave ) );
}

void AudioGenerativeApp::mouseMove( MouseEvent event )
{
	int height = getWindowHeight();
	//gFreqTarget = ( height - event.getY() ) / (float)height * gMaxFreq/ 44100.0f;
	mFreqTarget = math<float>::clamp( ( height - event.getY() ) / (float)height * mMaxFreq, 0.0, mMaxFreq );
}

void AudioGenerativeApp::sineWave( uint64_t inSampleOffset, uint32_t ioSampleCount, audio::Buffer32f *ioBuffer ) {
	mPhaseAdjust = mPhaseAdjust * 0.95f + ( mFreqTarget / 44100.0f ) * 0.05f;
	for( int  i = 0; i < ioSampleCount; i++ ) {
		mPhase += mPhaseAdjust;
		mPhase = mPhase - math<float>::floor( mPhase );
		float val = math<float>::sin( mPhase * 2.0f * M_PI );

		ioBuffer->mData[i*ioBuffer->mNumberChannels] = val;
		ioBuffer->mData[i*ioBuffer->mNumberChannels + 1] = val;
	}
}

void AudioGenerativeApp::draw()
{
	gl::clear( Color( 0.1f, 0.1f, 0.1f ) );

	// draw a representation of the sine wave
	const float audioToVisualScale = 10.0f;
	const float waveHeight = 200.0f;
	gl::color( Color( 1.0f, 0.5f, 0.25f ) );
	glBegin( GL_LINE_STRIP );
	for( float x = -getWindowWidth() / 2; x < getWindowWidth() / 2; x += 0.5f ) {
		gl::vertex( getWindowCenter() + Vec2f( x, waveHeight * sin( x * mPhaseAdjust * audioToVisualScale ) ) );
	}
	glEnd();
}

CINDER_APP_BASIC( AudioGenerativeApp, RendererGl )
<|endoftext|>


<commit_before>#include "GSMLOC.h"

bool GSMLOC::atGSMLocationAndTime(unsigned char type, unsigned char cid) {
  const __FlashStringHelper *command = F("AT+CIPGSMLOC=%d,%d\r");
  const __FlashStringHelper *response = F("+CIPGSMLOC: ");
	char buffer[18]; // "AT+CIPGSMLOC=X,X\r"
  struct LocationTime locationTime;

	sprintf_P(buffer, (const char *)command, type, cid);

	dte->clearReceivedBuffer();
  if(!dte->ATCommand(buffer)) return false;
  if(!dte->ATResponseContain(response, 3000)) return false;
  char *pointer = strstr_P(dte->getResponse(), (const char *)response) + strlen_P((const char *)response);
  char *str = strtok(pointer, ",");
  for (size_t i = 0; i < 5 && str != NULL; i++) {
    if(i == 0) locationTime.locationCode = str[0] - '0';
    if(type == 1 && i < 3) {
      if(i == 1) strcpy(locationTime.longitude, str);
      if(i == 2) strcpy(locationTime.latitude, str);
    }
    if(type == 2 || (type == 1 && i == 3)) {
      if(i == 1 || i == 3) strcpy(locationTime.date, str);
      if(i == 2 || i == 4) strcpy(locationTime.time, str);
    }
    str = strtok(NULL, ",");
  }
	if(!dte->ATResponseOk()) return false;
  this->locationTime = locationTime;
	return true;
}

/* GSMLOC Class */
GSMLOC::GSMLOC(DTE &dte, IP &ip)
{
	this->dte = &dte;
  this->ip = &ip;
  locationTime = (struct LocationTime) { 0, "", "", "", "" };
}

struct LocationTime GSMLOC::getLocationTime(unsigned char cid) {
  if (strlen(locationTime.longitude) > 0) return locationTime;
  if (ip->getConnectionStatus(cid).status == 1) {
    if(!atGSMLocationAndTime(1, cid)) return (struct LocationTime) { 0, "", "", "", "" };
    if(locationTime.locationCode == 603) {
      if(!atGSMLocationAndTime(1, cid)) return (struct LocationTime) { 0, "", "", "", "" };
    }
  }
  return locationTime;
}
<commit_msg>Wait longer for AT+CIPGSMLOC response<commit_after>#include "GSMLOC.h"

bool GSMLOC::atGSMLocationAndTime(unsigned char type, unsigned char cid) {
  const __FlashStringHelper *command = F("AT+CIPGSMLOC=%d,%d\r");
  const __FlashStringHelper *response = F("+CIPGSMLOC: ");
	char buffer[18]; // "AT+CIPGSMLOC=X,X\r"
  struct LocationTime locationTime;

	sprintf_P(buffer, (const char *)command, type, cid);

	dte->clearReceivedBuffer();
  if(!dte->ATCommand(buffer)) return false;
  if(!dte->ATResponseContain(response, 10000)) return false;
  char *pointer = strstr_P(dte->getResponse(), (const char *)response) + strlen_P((const char *)response);
  char *str = strtok(pointer, ",");
  for (size_t i = 0; i < 5 && str != NULL; i++) {
    if(i == 0) locationTime.locationCode = str[0] - '0';
    if(type == 1 && i < 3) {
      if(i == 1) strcpy(locationTime.longitude, str);
      if(i == 2) strcpy(locationTime.latitude, str);
    }
    if(type == 2 || (type == 1 && i == 3)) {
      if(i == 1 || i == 3) strcpy(locationTime.date, str);
      if(i == 2 || i == 4) strcpy(locationTime.time, str);
    }
    str = strtok(NULL, ",");
  }
	if(!dte->ATResponseOk()) return false;
  this->locationTime = locationTime;
	return true;
}

/* GSMLOC Class */
GSMLOC::GSMLOC(DTE &dte, IP &ip)
{
	this->dte = &dte;
  this->ip = &ip;
  locationTime = (struct LocationTime) { 0, "", "", "", "" };
}

struct LocationTime GSMLOC::getLocationTime(unsigned char cid) {
  if (strlen(locationTime.longitude) > 0) return locationTime;
  if (ip->getConnectionStatus(cid).status == 1) {
    if(!atGSMLocationAndTime(1, cid)) return (struct LocationTime) { 0, "", "", "", "" };
    if(locationTime.locationCode == 603) {
      if(!atGSMLocationAndTime(1, cid)) return (struct LocationTime) { 0, "", "", "", "" };
    }
  }
  return locationTime;
}
<|endoftext|>


<commit_before>/**
 * @file mexopencv.hpp
 * @brief Global constant definitions
 * @author Kota Yamaguchi
 * @date 2012
 *
 * The header file for a MATLAB MEX-function that uses OpenCV library.
 * The file includes definition of MxArray class that converts between mxArray
 * and a couple of std:: and cv:: data types including cv::Mat.
 */
#ifndef __MEXOPENCV_HPP__
#define __MEXOPENCV_HPP__

#include "MxArray.hpp"

/**************************************************************\
*                       Global constants                       *
\**************************************************************/

/// Border type map for option processing
const ConstMap<std::string,int> BorderType = ConstMap<std::string,int>
    ("Constant",    cv::BORDER_CONSTANT)    // iiiiii|abcdefgh|iiiiiii for some i
    ("Replicate",   cv::BORDER_REPLICATE)   // aaaaaa|abcdefgh|hhhhhhh
    ("Reflect",     cv::BORDER_REFLECT)     // fedcba|abcdefgh|hgfedcb
    ("Wrap",        cv::BORDER_WRAP)        // cdefgh|abcdefgh|abcdefg
    ("Reflect101",  cv::BORDER_REFLECT_101) // gfedcb|abcdefgh|gfedcba
    ("Transparent", cv::BORDER_TRANSPARENT) // uvwxyz|absdefgh|ijklmno
    ("Default",     cv::BORDER_DEFAULT)     // same as "Reflect101"
    ("Isolated",    cv::BORDER_ISOLATED);   // do not look outside of ROI

/// Interpolation type map for option processing
const ConstMap<std::string,int> InterType = ConstMap<std::string,int>
    ("Nearest",  cv::INTER_NEAREST)  // nearest neighbor interpolation
    ("Linear",   cv::INTER_LINEAR)   // bilinear interpolation
    ("Cubic",    cv::INTER_CUBIC)    // bicubic interpolation
    ("Area",     cv::INTER_AREA)     // area-based (or super) interpolation
    ("Lanczos4", cv::INTER_LANCZOS4) // Lanczos interpolation over 8x8 neighborhood
    ("Max",      cv::INTER_MAX);
    //("WarpInverseMap", cv::WARP_INVERSE_MAP);

/// Thresholding type map for option processing
const ConstMap<std::string,int> ThreshType = ConstMap<std::string,int>
    ("Binary",    cv::THRESH_BINARY)
    ("BinaryInv", cv::THRESH_BINARY_INV)
    ("Trunc",     cv::THRESH_TRUNC)
    ("ToZero",    cv::THRESH_TOZERO)
    ("ToZeroInv", cv::THRESH_TOZERO_INV)
    ("Mask",      cv::THRESH_MASK);
    //("Otsu",    cv::THRESH_OTSU);

/// Distance types for Distance Transform and M-estimators
const ConstMap<std::string,int> DistType = ConstMap<std::string,int>
    ("User",   cv::DIST_USER)
    ("L1",     cv::DIST_L1)
    ("L2",     cv::DIST_L2)
    ("C",      cv::DIST_C)
    ("L12",    cv::DIST_L12)
    ("Fair",   cv::DIST_FAIR)
    ("Welsch", cv::DIST_WELSCH)
    ("Huber",  cv::DIST_HUBER);

/// Line type for drawing
const ConstMap<std::string,int> LineType = ConstMap<std::string,int>
    ("4",  cv::LINE_4)
    ("8",  cv::LINE_8)
    ("AA", cv::LINE_AA);

/// Thickness type for drawing
const ConstMap<std::string,int> ThicknessType = ConstMap<std::string,int>
    ("Filled", cv::FILLED);

/// Font faces for drawing
const ConstMap<std::string,int> FontFace = ConstMap<std::string,int>
    ("HersheySimplex",       cv::FONT_HERSHEY_SIMPLEX)
    ("HersheyPlain",         cv::FONT_HERSHEY_PLAIN)
    ("HersheyDuplex",        cv::FONT_HERSHEY_DUPLEX)
    ("HersheyComplex",       cv::FONT_HERSHEY_COMPLEX)
    ("HersheyTriplex",       cv::FONT_HERSHEY_TRIPLEX)
    ("HersheyComplexSmall",  cv::FONT_HERSHEY_COMPLEX_SMALL)
    ("HersheyScriptSimplex", cv::FONT_HERSHEY_SCRIPT_SIMPLEX)
    ("HersheyScriptComplex", cv::FONT_HERSHEY_SCRIPT_COMPLEX);

/// Font styles for drawing
const ConstMap<std::string,int> FontStyle = ConstMap<std::string,int>
    ("Regular", 0)
    ("Italic",  cv::FONT_ITALIC);

/// Norm type map for option processing
const ConstMap<std::string,int> NormType = ConstMap<std::string,int>
    ("Inf",      cv::NORM_INF)
    ("L1",       cv::NORM_L1)
    ("L2",       cv::NORM_L2)
    ("L2Sqr",    cv::NORM_L2SQR)
    ("Hamming",  cv::NORM_HAMMING)
    ("Hamming2", cv::NORM_HAMMING2);

/**************************************************************\
*                       Helper Functions                       *
\**************************************************************/

/// Alias for input/ouput arguments number check
inline void nargchk(bool cond)
{
    if (!cond) {
        mexErrMsgIdAndTxt("mexopencv:error", "Wrong number of arguments");
    }
}

/**************************************************************\
*           Conversion Functions: MxArray to vector            *
\**************************************************************/

/** Convert an MxArray to std::vector<cv::Point_<T>>
 *
 * @param arr MxArray object. In one of the following forms:
 * - a cell-array of 2D points (2-element vectors) of length \c N,
 *   e.g: <tt>{[x,y], [x,y], ...}</tt>
 * - a numeric matrix of size \c Nx2, \c Nx1x2, or \c 1xNx2 in the form:
 *   <tt>[x,y; x,y; ...]</tt> or <tt>cat(3, [x,y], [x,y], ...)</tt>
 * @return vector of 2D points of size \c N
 *
 * Example:
 * @code
 * MxArray cellArray(prhs[0]);
 * vector<Point2d> vp = MxArrayToVectorPoint<double>(cellArray);
 * @endcode
 */
template <typename T>
std::vector<cv::Point_<T> > MxArrayToVectorPoint(const MxArray& arr)
{
    std::vector<cv::Point_<T> > vp;
    if (arr.isNumeric()) {
        if (arr.numel() == 2)
            vp.push_back(arr.toPoint_<T>());
        else
            arr.toMat(cv::DataType<T>::depth).reshape(2, 0).copyTo(vp);
    }
    else if (arr.isCell()) {
        /*
        std::vector<MxArray> va(arr.toVector<MxArray>());
        vp.reserve(va.size());
        for (std::vector<MxArray>::const_iterator it = va.begin(); it != va.end(); ++it)
            vp.push_back(it->toPoint_<T>());
        */
        vp = arr.toVector(
            std::const_mem_fun_ref_t<cv::Point_<T>, MxArray>(
                &MxArray::toPoint_<T>));
    }
    else
        mexErrMsgIdAndTxt("mexopencv:error",
            "Unable to convert MxArray to std::vector<cv::Point_<T>>");
    return vp;
}

/** Convert an MxArray to std::vector<cv::Point3_<T>>
 *
 * @param arr MxArray object. In one of the following forms:
 * - a cell-array of 3D points (3-element vectors) of length \c N,
 *   e.g: <tt>{[x,y,z], [x,y,z], ...}</tt>
 * - a numeric matrix of size \c Nx3, \c Nx1x3, or \c 1xNx3 in the form:
 *   <tt>[x,y,z; x,y,z; ...]</tt> or <tt>cat(3, [x,y,z], [x,y,z], ...)</tt>
 * @return vector of 3D points of size \c N
 *
 * Example:
 * @code
 * MxArray cellArray(prhs[0]);
 * vector<Point3f> vp = MxArrayToVectorPoint3<float>(cellArray);
 * @endcode
 */
template <typename T>
std::vector<cv::Point3_<T> > MxArrayToVectorPoint3(const MxArray& arr)
{
    std::vector<cv::Point3_<T> > vp;
    if (arr.isNumeric()) {
        if (arr.numel() == 3)
            vp.push_back(arr.toPoint3_<T>());
        else
            arr.toMat(cv::DataType<T>::depth).reshape(3, 0).copyTo(vp);
    }
    else if (arr.isCell()) {
        /*
        std::vector<MxArray> va(arr.toVector<MxArray>());
        vp.reserve(va.size());
        for (std::vector<MxArray>::const_iterator it = va.begin(); it != va.end(); ++it)
            vp.push_back(it->toPoint3_<T>());
        */
        vp = arr.toVector(
            std::const_mem_fun_ref_t<cv::Point3_<T>, MxArray>(
                &MxArray::toPoint3_<T>));
    }
    else
        mexErrMsgIdAndTxt("mexopencv:error",
            "Unable to convert MxArray to std::vector<cv::Point3_<T>>");
    return vp;
}

/**************************************************************\
*      Conversion Functions: MxArray to vector of vectors      *
\**************************************************************/

/** Convert an MxArray to std::vector<std::vector<cv::Point_<T>>>
 *
 * @param arr MxArray object. In one of the following forms:
 * - a cell-array of cell-arrays of 2D points (2-element vectors),
 *   e.g: <tt>{{[x,y], [x,y], ..}, {[x,y], [x,y], ..}, ...}</tt>
 * - a cell-array of numeric matrices of size \c Mx2, \c Mx1x2, or \c 1xMx2,
 *   e.g: <tt>{[x,y; x,y; ...], [x,y; x,y; ...], ...}</tt> or
 *   <tt>{cat(3, [x,y], [x,y], ...), cat(3, [x,y], [x,y], ...), ...}</tt>
 * @return vector of vectors of 2D points
 *
 * Example:
 * @code
 * MxArray cellArray(prhs[0]);
 * vector<vector<Point2d>> vvp = MxArrayToVectorVectorPoint<double>(cellArray);
 * @endcode
 */
template <typename T>
std::vector<std::vector<cv::Point_<T> > > MxArrayToVectorVectorPoint(const MxArray& arr)
{
    std::vector<MxArray> vva(arr.toVector<MxArray>());
    std::vector<std::vector<cv::Point_<T> > > vvp;
    vvp.reserve(vva.size());
    for (std::vector<MxArray>::const_iterator it = vva.begin(); it != vva.end(); ++it) {
        /*
        std::vector<MxArray> va(it->toVector<MxArray());
        std::vector<cv::Point_<T> > vp;
        for (std::vector<MxArray>::const_iterator jt = va.begin(); jt != va.end(); ++jt) {
            vp.push_back(jt->toPoint_<T>());
        }
        vvp.push_back(vp);
        */
        vvp.push_back(MxArrayToVectorPoint<T>(*it));
    }
    return vvp;
}

/** Convert an MxArray to std::vector<std::vector<cv::Point3_<T>>>
 *
 * @param arr MxArray object. In one of the following forms:
 * - a cell-array of cell-arrays of 3D points (3-element vectors),
 *   e.g: <tt>{{[x,y,z], [x,y,z], ..}, {[x,y,z], [x,y,z], ..}, ...}</tt>
 * - a cell-array of numeric matrices of size \c Mx3, \c Mx1x3, or \c 1xMx3,
 *   e.g: <tt>{[x,y,z; x,y,z; ...], [x,y,z; x,y,z; ...], ...}</tt> or
 *   <tt>{cat(3, [x,y,z], [x,y,z], ...), cat(3, [x,y,z], [x,y,z], ...), ...}</tt>
 * @return vector of vectors of 3D points
 *
 * Example:
 * @code
 * MxArray cellArray(prhs[0]);
 * vector<vector<Point3d>> vvp = MxArrayToVectorVectorPoint3<double>(cellArray);
 * @endcode
 */
template <typename T>
std::vector<std::vector<cv::Point3_<T> > > MxArrayToVectorVectorPoint3(const MxArray& arr)
{
    std::vector<MxArray> vva(arr.toVector<MxArray>());
    std::vector<std::vector<cv::Point3_<T> > > vvp;
    vvp.reserve(vva.size());
    for (std::vector<MxArray>::const_iterator it = vva.begin(); it != vva.end(); ++it) {
        /*
        std::vector<MxArray> va(it->toVector<MxArray());
        std::vector<cv::Point3_<T> > vp;
        for (std::vector<MxArray>::const_iterator jt = va.begin(); jt != va.end(); ++jt) {
            vp.push_back(jt->toPoint3_<T>());
        }
        vvp.push_back(vp);
        */
        vvp.push_back(MxArrayToVectorPoint3<T>(*it));
    }
    return vvp;
}

#endif
<commit_msg>add similar conversion function for vector<Rect_<T>><commit_after>/**
 * @file mexopencv.hpp
 * @brief Global constant definitions
 * @author Kota Yamaguchi
 * @date 2012
 *
 * The header file for a MATLAB MEX-function that uses OpenCV library.
 * The file includes definition of MxArray class that converts between mxArray
 * and a couple of std:: and cv:: data types including cv::Mat.
 */
#ifndef __MEXOPENCV_HPP__
#define __MEXOPENCV_HPP__

#include "MxArray.hpp"

/**************************************************************\
*                       Global constants                       *
\**************************************************************/

/// Border type map for option processing
const ConstMap<std::string,int> BorderType = ConstMap<std::string,int>
    ("Constant",    cv::BORDER_CONSTANT)    // iiiiii|abcdefgh|iiiiiii for some i
    ("Replicate",   cv::BORDER_REPLICATE)   // aaaaaa|abcdefgh|hhhhhhh
    ("Reflect",     cv::BORDER_REFLECT)     // fedcba|abcdefgh|hgfedcb
    ("Wrap",        cv::BORDER_WRAP)        // cdefgh|abcdefgh|abcdefg
    ("Reflect101",  cv::BORDER_REFLECT_101) // gfedcb|abcdefgh|gfedcba
    ("Transparent", cv::BORDER_TRANSPARENT) // uvwxyz|absdefgh|ijklmno
    ("Default",     cv::BORDER_DEFAULT)     // same as "Reflect101"
    ("Isolated",    cv::BORDER_ISOLATED);   // do not look outside of ROI

/// Interpolation type map for option processing
const ConstMap<std::string,int> InterType = ConstMap<std::string,int>
    ("Nearest",  cv::INTER_NEAREST)  // nearest neighbor interpolation
    ("Linear",   cv::INTER_LINEAR)   // bilinear interpolation
    ("Cubic",    cv::INTER_CUBIC)    // bicubic interpolation
    ("Area",     cv::INTER_AREA)     // area-based (or super) interpolation
    ("Lanczos4", cv::INTER_LANCZOS4) // Lanczos interpolation over 8x8 neighborhood
    ("Max",      cv::INTER_MAX);
    //("WarpInverseMap", cv::WARP_INVERSE_MAP);

/// Thresholding type map for option processing
const ConstMap<std::string,int> ThreshType = ConstMap<std::string,int>
    ("Binary",    cv::THRESH_BINARY)
    ("BinaryInv", cv::THRESH_BINARY_INV)
    ("Trunc",     cv::THRESH_TRUNC)
    ("ToZero",    cv::THRESH_TOZERO)
    ("ToZeroInv", cv::THRESH_TOZERO_INV)
    ("Mask",      cv::THRESH_MASK);
    //("Otsu",    cv::THRESH_OTSU);

/// Distance types for Distance Transform and M-estimators
const ConstMap<std::string,int> DistType = ConstMap<std::string,int>
    ("User",   cv::DIST_USER)
    ("L1",     cv::DIST_L1)
    ("L2",     cv::DIST_L2)
    ("C",      cv::DIST_C)
    ("L12",    cv::DIST_L12)
    ("Fair",   cv::DIST_FAIR)
    ("Welsch", cv::DIST_WELSCH)
    ("Huber",  cv::DIST_HUBER);

/// Line type for drawing
const ConstMap<std::string,int> LineType = ConstMap<std::string,int>
    ("4",  cv::LINE_4)
    ("8",  cv::LINE_8)
    ("AA", cv::LINE_AA);

/// Thickness type for drawing
const ConstMap<std::string,int> ThicknessType = ConstMap<std::string,int>
    ("Filled", cv::FILLED);

/// Font faces for drawing
const ConstMap<std::string,int> FontFace = ConstMap<std::string,int>
    ("HersheySimplex",       cv::FONT_HERSHEY_SIMPLEX)
    ("HersheyPlain",         cv::FONT_HERSHEY_PLAIN)
    ("HersheyDuplex",        cv::FONT_HERSHEY_DUPLEX)
    ("HersheyComplex",       cv::FONT_HERSHEY_COMPLEX)
    ("HersheyTriplex",       cv::FONT_HERSHEY_TRIPLEX)
    ("HersheyComplexSmall",  cv::FONT_HERSHEY_COMPLEX_SMALL)
    ("HersheyScriptSimplex", cv::FONT_HERSHEY_SCRIPT_SIMPLEX)
    ("HersheyScriptComplex", cv::FONT_HERSHEY_SCRIPT_COMPLEX);

/// Font styles for drawing
const ConstMap<std::string,int> FontStyle = ConstMap<std::string,int>
    ("Regular", 0)
    ("Italic",  cv::FONT_ITALIC);

/// Norm type map for option processing
const ConstMap<std::string,int> NormType = ConstMap<std::string,int>
    ("Inf",      cv::NORM_INF)
    ("L1",       cv::NORM_L1)
    ("L2",       cv::NORM_L2)
    ("L2Sqr",    cv::NORM_L2SQR)
    ("Hamming",  cv::NORM_HAMMING)
    ("Hamming2", cv::NORM_HAMMING2);

/**************************************************************\
*                       Helper Functions                       *
\**************************************************************/

/// Alias for input/ouput arguments number check
inline void nargchk(bool cond)
{
    if (!cond) {
        mexErrMsgIdAndTxt("mexopencv:error", "Wrong number of arguments");
    }
}

/**************************************************************\
*           Conversion Functions: MxArray to vector            *
\**************************************************************/

/** Convert an MxArray to std::vector<cv::Point_<T>>
 *
 * @param arr MxArray object. In one of the following forms:
 * - a cell-array of 2D points (2-element vectors) of length \c N,
 *   e.g: <tt>{[x,y], [x,y], ...}</tt>
 * - a numeric matrix of size \c Nx2, \c Nx1x2, or \c 1xNx2 in the form:
 *   <tt>[x,y; x,y; ...]</tt> or <tt>cat(3, [x,y], [x,y], ...)</tt>
 * @return vector of 2D points of size \c N
 *
 * Example:
 * @code
 * MxArray cellArray(prhs[0]);
 * vector<Point2d> vp = MxArrayToVectorPoint<double>(cellArray);
 * @endcode
 */
template <typename T>
std::vector<cv::Point_<T> > MxArrayToVectorPoint(const MxArray& arr)
{
    std::vector<cv::Point_<T> > vp;
    if (arr.isNumeric()) {
        if (arr.numel() == 2)
            vp.push_back(arr.toPoint_<T>());
        else
            arr.toMat(cv::DataType<T>::depth).reshape(2, 0).copyTo(vp);
    }
    else if (arr.isCell()) {
        /*
        std::vector<MxArray> va(arr.toVector<MxArray>());
        vp.reserve(va.size());
        for (std::vector<MxArray>::const_iterator it = va.begin(); it != va.end(); ++it)
            vp.push_back(it->toPoint_<T>());
        */
        vp = arr.toVector(
            std::const_mem_fun_ref_t<cv::Point_<T>, MxArray>(
                &MxArray::toPoint_<T>));
    }
    else
        mexErrMsgIdAndTxt("mexopencv:error",
            "Unable to convert MxArray to std::vector<cv::Point_<T>>");
    return vp;
}

/** Convert an MxArray to std::vector<cv::Point3_<T>>
 *
 * @param arr MxArray object. In one of the following forms:
 * - a cell-array of 3D points (3-element vectors) of length \c N,
 *   e.g: <tt>{[x,y,z], [x,y,z], ...}</tt>
 * - a numeric matrix of size \c Nx3, \c Nx1x3, or \c 1xNx3 in the form:
 *   <tt>[x,y,z; x,y,z; ...]</tt> or <tt>cat(3, [x,y,z], [x,y,z], ...)</tt>
 * @return vector of 3D points of size \c N
 *
 * Example:
 * @code
 * MxArray cellArray(prhs[0]);
 * vector<Point3f> vp = MxArrayToVectorPoint3<float>(cellArray);
 * @endcode
 */
template <typename T>
std::vector<cv::Point3_<T> > MxArrayToVectorPoint3(const MxArray& arr)
{
    std::vector<cv::Point3_<T> > vp;
    if (arr.isNumeric()) {
        if (arr.numel() == 3)
            vp.push_back(arr.toPoint3_<T>());
        else
            arr.toMat(cv::DataType<T>::depth).reshape(3, 0).copyTo(vp);
    }
    else if (arr.isCell()) {
        /*
        std::vector<MxArray> va(arr.toVector<MxArray>());
        vp.reserve(va.size());
        for (std::vector<MxArray>::const_iterator it = va.begin(); it != va.end(); ++it)
            vp.push_back(it->toPoint3_<T>());
        */
        vp = arr.toVector(
            std::const_mem_fun_ref_t<cv::Point3_<T>, MxArray>(
                &MxArray::toPoint3_<T>));
    }
    else
        mexErrMsgIdAndTxt("mexopencv:error",
            "Unable to convert MxArray to std::vector<cv::Point3_<T>>");
    return vp;
}

/** Convert an MxArray to std::vector<cv::Rect_<T>>
 *
 * @param arr MxArray object. In one of the following forms:
 * - a cell-array of rectangles (4-element vectors) of length \c N,
 *   e.g: <tt>{[x,y,w,h], [x,y,w,h], ...}</tt>
 * - a numeric matrix of size \c Nx4, \c Nx1x4, or \c 1xNx4 in the form:
 *   <tt>[x,y,w,h; x,y,w,h; ...]</tt> or
 *   <tt>cat(3, [x,y,w,h], [x,y,w,h], ...)</tt>
 * @return vector of rectangles of size \c N
 *
 * Example:
 * @code
 * MxArray cellArray(prhs[0]);
 * vector<Rect2f> vr = MxArrayToVectorRect<float>(cellArray);
 * @endcode
 */
template <typename T>
std::vector<cv::Rect_<T> > MxArrayToVectorRect(const MxArray& arr)
{
    std::vector<cv::Rect_<T> > vr;
    if (arr.isNumeric()) {
        if (arr.numel() == 4)
            vr.push_back(arr.toRect_<T>());
        else
            arr.toMat(cv::DataType<T>::depth).reshape(4, 0).copyTo(vr);
    }
    else if (arr.isCell()) {
        /*
        std::vector<MxArray> va(arr.toVector<MxArray>());
        vr.reserve(va.size());
        for (std::vector<MxArray>::const_iterator it = va.begin(); it != va.end(); ++it)
            vr.push_back(it->toRect_<T>());
        */
        vr = arr.toVector(
            std::const_mem_fun_ref_t<cv::Rect_<T>, MxArray>(
                &MxArray::toRect_<T>));
    }
    else
        mexErrMsgIdAndTxt("mexopencv:error",
            "Unable to convert MxArray to std::vector<cv::Rect_<T>>");
    return vr;
}

/**************************************************************\
*      Conversion Functions: MxArray to vector of vectors      *
\**************************************************************/

/** Convert an MxArray to std::vector<std::vector<cv::Point_<T>>>
 *
 * @param arr MxArray object. In one of the following forms:
 * - a cell-array of cell-arrays of 2D points (2-element vectors),
 *   e.g: <tt>{{[x,y], [x,y], ..}, {[x,y], [x,y], ..}, ...}</tt>
 * - a cell-array of numeric matrices of size \c Mx2, \c Mx1x2, or \c 1xMx2,
 *   e.g: <tt>{[x,y; x,y; ...], [x,y; x,y; ...], ...}</tt> or
 *   <tt>{cat(3, [x,y], [x,y], ...), cat(3, [x,y], [x,y], ...), ...}</tt>
 * @return vector of vectors of 2D points
 *
 * Example:
 * @code
 * MxArray cellArray(prhs[0]);
 * vector<vector<Point2d>> vvp = MxArrayToVectorVectorPoint<double>(cellArray);
 * @endcode
 */
template <typename T>
std::vector<std::vector<cv::Point_<T> > > MxArrayToVectorVectorPoint(const MxArray& arr)
{
    std::vector<MxArray> vva(arr.toVector<MxArray>());
    std::vector<std::vector<cv::Point_<T> > > vvp;
    vvp.reserve(vva.size());
    for (std::vector<MxArray>::const_iterator it = vva.begin(); it != vva.end(); ++it) {
        /*
        std::vector<MxArray> va(it->toVector<MxArray());
        std::vector<cv::Point_<T> > vp;
        for (std::vector<MxArray>::const_iterator jt = va.begin(); jt != va.end(); ++jt) {
            vp.push_back(jt->toPoint_<T>());
        }
        vvp.push_back(vp);
        */
        vvp.push_back(MxArrayToVectorPoint<T>(*it));
    }
    return vvp;
}

/** Convert an MxArray to std::vector<std::vector<cv::Point3_<T>>>
 *
 * @param arr MxArray object. In one of the following forms:
 * - a cell-array of cell-arrays of 3D points (3-element vectors),
 *   e.g: <tt>{{[x,y,z], [x,y,z], ..}, {[x,y,z], [x,y,z], ..}, ...}</tt>
 * - a cell-array of numeric matrices of size \c Mx3, \c Mx1x3, or \c 1xMx3,
 *   e.g: <tt>{[x,y,z; x,y,z; ...], [x,y,z; x,y,z; ...], ...}</tt> or
 *   <tt>{cat(3, [x,y,z], [x,y,z], ...), cat(3, [x,y,z], [x,y,z], ...), ...}</tt>
 * @return vector of vectors of 3D points
 *
 * Example:
 * @code
 * MxArray cellArray(prhs[0]);
 * vector<vector<Point3d>> vvp = MxArrayToVectorVectorPoint3<double>(cellArray);
 * @endcode
 */
template <typename T>
std::vector<std::vector<cv::Point3_<T> > > MxArrayToVectorVectorPoint3(const MxArray& arr)
{
    std::vector<MxArray> vva(arr.toVector<MxArray>());
    std::vector<std::vector<cv::Point3_<T> > > vvp;
    vvp.reserve(vva.size());
    for (std::vector<MxArray>::const_iterator it = vva.begin(); it != vva.end(); ++it) {
        /*
        std::vector<MxArray> va(it->toVector<MxArray());
        std::vector<cv::Point3_<T> > vp;
        for (std::vector<MxArray>::const_iterator jt = va.begin(); jt != va.end(); ++jt) {
            vp.push_back(jt->toPoint3_<T>());
        }
        vvp.push_back(vp);
        */
        vvp.push_back(MxArrayToVectorPoint3<T>(*it));
    }
    return vvp;
}

#endif
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
#include <cstring>
#include <wait.h>
#include <vector>
#include <fcntl.h>
#include <cstdlib>
#include <errno.h>
#include <sys/stat.h>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string.hpp>

using namespace std;
using namespace boost;

void execfunction(char **argv, string command)
{
	int pid = fork();
	if(-1 == pid)
	{
		perror("There was an error with fork(). ");
	}
	else if(pid == 0)
	{
		if(-1 == execvp(command.c_str(), argv))
		{
			perror("There was an error with execvp() ");
			exit(1);
		}
		_exit(0);
	}
	else
	{
		int status;
		wait(&status);
		if(-1 == status)
		{
			perror("There was an error with wait(). ");
		}
	}
}

int main()
{
	int savestdout;
	if(-1 == (savestdout = dup(1)))
	{
		perror("There was an error with dup(). ");
	}
	if(-1 == close(1))
	{
		perror("There was an error with close(). ");
	}
	vector<string> branches;
	//call execvp to run git branch
	string file_name = "tempfile";
	int write_to;
	char **argv = new char*[3];
	argv[0] = const_cast<char*>("git");
	argv[1] = const_cast<char*>("branch");
	argv[2] = 0;
	if(-1 == (write_to = open(file_name.c_str() , O_CREAT | O_WRONLY | O_APPEND | O_TRUNC, S_IRUSR | S_IWUSR)))
	{
		perror("There was an error with open(). ");
		exit(1);
	}
	execfunction(argv, "git");
	delete []argv;
	if(-1 == close(write_to))
	{
		perror("There was an error with close(). ");
	}
	if(-1 == dup2(savestdout, 1))
	{
		perror("There was an error with dup2(). ");
	}
	int read_from;
	if(-1 == (read_from = open(file_name.c_str(), O_RDONLY)))
	{
		perror("There was an error with open(). ");
	}
	int size;
	char c[BUFSIZ];
	if(-1 == (size = read(read_from, &c, BUFSIZ)))
	{
		perror("There was an error with read(). ");
	}
	while(size > 0)
	{
		branches.push_back(string(c));
		if(-1 == (size = read(read_from, &c, BUFSIZ)))
		{
			perror("There was an error with read(). ");
		}
	}
	if(-1 == close(read_from))
	{
		perror("There was an error with close(). ");
	}
	//take all branch names and put into vector
	//for each branch name, call execvp git checkout branchname
	for(unsigned int i = 0; i < branches.size(); ++i)
	{
		branches.at(i) = (branches.at(i)).substr(2, (branches.at(i)).size()-3);
		cout << branches.at(i) << endl;
	}
	argv = new char*[3];
	argv[0] = const_cast<char*>("rm");
	argv[1] = const_cast<char*>(file_name.c_str());
	argv[2] = 0;
	execfunction(argv, "rm");
	delete []argv;
	//then open/create a file called branchname for whatever branch we are on
	if(-1 == (savestdout = dup(1)))
	{
		perror("There was an error with dup(). ");
	}
	if(-1 == close(1))
	{
		perror("There was an error with close(). ");
	}
	for(unsigned int i = 0; i < branches.size(); ++i)
	{
		argv = new char*[4];
		argv[0] = const_cast<char*>("git");
		argv[1] = const_cast<char*>("checkout");
		argv[2] = const_cast<char*>((branches.at(i)).c_str());
		argv[3] = 0;
		execfunction(argv, "git");
		delete []argv;
		string name = branches.at(i);
		name += "Branch";
		if(-1 == (write_to = open(name.c_str() , O_CREAT | O_WRONLY | O_APPEND | O_TRUNC, S_IRUSR | S_IWUSR)))
		{
			perror("There was an error with open(). ");
			exit(1);
		}
		argv = new char*[3];
		argv[0] = const_cast<char*>("git");
		argv[1] = const_cast<char*>("log");
		argv[2] = 0;
		execfunction(argv, "git");
		delete []argv;
		if(-1 == close(write_to))
		{
			perror("There was an error with close(). ");
		}
	}
	if(-1 == dup2(savestdout, 1))
	{
		perror("There was an error with dup2(). ");
	}
	argv = new char*[4];
	argv[0] = const_cast<char*>("git");
	argv[1] = const_cast<char*>("checkout");
	argv[2] = const_cast<char*>("master");
	argv[3] = 0;
	execfunction(argv, "git");
	delete []argv;
	//then call execvp git log to have all the output go to file
	//close file
	return 0;
}
<commit_msg>fixed checkout bug<commit_after>#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
#include <cstring>
#include <wait.h>
#include <vector>
#include <fcntl.h>
#include <cstdlib>
#include <errno.h>
#include <sys/stat.h>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string.hpp>

using namespace std;
using namespace boost;

void execfunction(char **argv, string command)
{
	int pid = fork();
	if(-1 == pid)
	{
		perror("There was an error with fork(). ");
	}
	else if(pid == 0)
	{
		if(-1 == execvp(command.c_str(), argv))
		{
			perror("There was an error with execvp() ");
			exit(1);
		}
		_exit(0);
	}
	else
	{
		int status;
		wait(&status);
		if(-1 == status)
		{
			perror("There was an error with wait(). ");
		}
	}
}

int main()
{
	int savestdout;
	if(-1 == (savestdout = dup(1)))
	{
		perror("There was an error with dup(). ");
	}
	if(-1 == close(1))
	{
		perror("There was an error with close(). ");
	}
	vector<string> branches;
	//call execvp to run git branch
	string file_name = "tempfile";
	int write_to;
	char **argv = new char*[3];
	argv[0] = const_cast<char*>("git");
	argv[1] = const_cast<char*>("branch");
	argv[2] = 0;
	if(-1 == (write_to = open(file_name.c_str() , O_CREAT | O_WRONLY | O_APPEND | O_TRUNC, S_IRUSR | S_IWUSR)))
	{
		perror("There was an error with open(). ");
		exit(1);
	}
	execfunction(argv, "git");
	delete []argv;
	if(-1 == close(write_to))
	{
		perror("There was an error with close(). ");
	}
	if(-1 == dup2(savestdout, 1))
	{
		perror("There was an error with dup2(). ");
	}
	int read_from;
	if(-1 == (read_from = open(file_name.c_str(), O_RDONLY)))
	{
		perror("There was an error with open(). ");
	}
	int size;
	char c[BUFSIZ];
	if(-1 == (size = read(read_from, &c, BUFSIZ)))
	{
		perror("There was an error with read(). ");
	}
	while(size > 0)
	{
		branches.push_back(string(c));
		if(-1 == (size = read(read_from, &c, BUFSIZ)))
		{
			perror("There was an error with read(). ");
		}
	}
	if(-1 == close(read_from))
	{
		perror("There was an error with close(). ");
	}
	//take all branch names and put into vector
	//for each branch name, call execvp git checkout branchname
	string currBranch;
	for(unsigned int i = 0; i < branches.size(); ++i)
	{
		if((branches.at(i)).at(0) == '*')
		{
			currBranch = (branches.at(i)).substr(2, (branches.at(i)).size()-3);
		}
		branches.at(i) = (branches.at(i)).substr(2, (branches.at(i)).size()-3);
		cout << branches.at(i) << endl;
	}
	argv = new char*[3];
	argv[0] = const_cast<char*>("rm");
	argv[1] = const_cast<char*>(file_name.c_str());
	argv[2] = 0;
	execfunction(argv, "rm");
	delete []argv;
	//then open/create a file called branchname for whatever branch we are on
	if(-1 == (savestdout = dup(1)))
	{
		perror("There was an error with dup(). ");
	}
	if(-1 == close(1))
	{
		perror("There was an error with close(). ");
	}
	int changed = 0;
	for(unsigned int i = 0; i < branches.size(); ++i)
	{
		if(currBranch != branches.at(i))
		{
			argv = new char*[4];
			argv[0] = const_cast<char*>("git");
			argv[1] = const_cast<char*>("checkout");
			argv[2] = const_cast<char*>((branches.at(i)).c_str());
			argv[3] = 0;
			execfunction(argv, "git");
			delete []argv;
			changed++;
		}
		string name = branches.at(i);
		name += "Branch";
		if(-1 == (write_to = open(name.c_str() , O_CREAT | O_WRONLY | O_APPEND | O_TRUNC, S_IRUSR | S_IWUSR)))
		{
			perror("There was an error with open(). ");
			exit(1);
		}
		argv = new char*[3];
		argv[0] = const_cast<char*>("git");
		argv[1] = const_cast<char*>("log");
		argv[2] = 0;
		execfunction(argv, "git");
		delete []argv;
		if(-1 == close(write_to))
		{
			perror("There was an error with close(). ");
		}
	}
	if(-1 == dup2(savestdout, 1))
	{
		perror("There was an error with dup2(). ");
	}
	if(changed > 0)
	{
		argv = new char*[4];
		argv[0] = const_cast<char*>("git");
		argv[1] = const_cast<char*>("checkout");
		argv[2] = const_cast<char*>(currBranch.c_str());
		argv[3] = 0;
		execfunction(argv, "git");
		delete []argv;
	}
	//then call execvp git log to have all the output go to file
	//close file
	return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
#include <cstring>
#include <wait.h>
#include <vector>
#include <fcntl.h>
#include <cstdlib>
#include <errno.h>
#include <sys/stat.h>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string.hpp>

using namespace std;
using namespace boost;
void execfunction(char **argv, string command)
{
	int pid = fork();
	if(-1 == pid)
	{
		perror("There was an error with fork(). ");
	}
	else if(pid == 0)
	{
		if(-1 == execvp(command.c_str(), argv))
		{
			perror("There was an error with execvp() ");
			exit(1);
		}
		_exit(0);
	}
	else
	{
		int status;
		wait(&status);
		if(-1 == status)
		{
			perror("There was an error with wait(). ");
		}
	}
}

int main()
{
	int savestdout;
	if(-1 == (savestdout = dup(1)))
	{
		perror("There was an error with dup(). ");
	}
	if(-1 == close(1))
	{
		perror("There was an error with close(). ");
	}
	vector<string> branches;
	//call execvp to run git branch
	string file_name = "tempfile";
	int write_to;
	char **argv = new char*[3];
	argv[0] = const_cast<char*>("git");
	argv[1] = const_cast<char*>("branch");
	argv[2] = 0;
	if(-1 == (write_to = open(file_name.c_str() , O_CREAT | O_WRONLY | O_APPEND | O_TRUNC, S_IRUSR | S_IWUSR)))
	{
		perror("There was an error with open(). ");
		exit(1);
	}
	execfunction(argv, "git");
	delete []argv;
	if(-1 == close(write_to))
	{
		perror("There was an error with close(). ");
	}
	if(-1 == dup2(savestdout, 1))
	{
		perror("There was an error with dup2(). ");
	}
	int read_from;
	if(-1 == (read_from = open(file_name.c_str(), O_RDONLY)))
	{
		perror("There was an error with open(). ");
	}
	int size;
	char c[BUFSIZ];
	if(-1 == (size = read(read_from, &c, BUFSIZ)))
	{
		perror("There was an error with read(). ");
	}
	while(size > 0)
	{
		branches.push_back(string(c));
		if(-1 == (size = read(read_from, &c, BUFSIZ)))
		{
			perror("There was an error with read(). ");
		}
	}
	if(-1 == close(read_from))
	{
		perror("There was an error with close(). ");
	}
	//take all branch names and put into vector
	//for each branch name, call execvp git checkout branchname
	for(unsigned int i = 0; i < branches.size(); ++i)
	{
		cout << branches.at(i);
		if(i < branches.size()-1)
		{
			cout << endl;
		}
	}
	argv = new char*[3];
	argv[0] = const_cast<char*>("rm");
	argv[1] = const_cast<char*>(file_name.c_str());
	argv[2] = 0;
	execfunction(argv, "rm");
	delete []argv;
	//then open/create a file called branchname for whatever branch we are on
	//then call execvp git log to have all the output go to file
	//close file
	//reopen stdout
	return 0;
}
<commit_msg>cleaned up branch names to use for later<commit_after>#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
#include <cstring>
#include <wait.h>
#include <vector>
#include <fcntl.h>
#include <cstdlib>
#include <errno.h>
#include <sys/stat.h>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string.hpp>

using namespace std;
using namespace boost;

void execfunction(char **argv, string command)
{
	int pid = fork();
	if(-1 == pid)
	{
		perror("There was an error with fork(). ");
	}
	else if(pid == 0)
	{
		if(-1 == execvp(command.c_str(), argv))
		{
			perror("There was an error with execvp() ");
			exit(1);
		}
		_exit(0);
	}
	else
	{
		int status;
		wait(&status);
		if(-1 == status)
		{
			perror("There was an error with wait(). ");
		}
	}
}

int main()
{
	int savestdout;
	if(-1 == (savestdout = dup(1)))
	{
		perror("There was an error with dup(). ");
	}
	if(-1 == close(1))
	{
		perror("There was an error with close(). ");
	}
	vector<string> branches;
	//call execvp to run git branch
	string file_name = "tempfile";
	int write_to;
	char **argv = new char*[3];
	argv[0] = const_cast<char*>("git");
	argv[1] = const_cast<char*>("branch");
	argv[2] = 0;
	if(-1 == (write_to = open(file_name.c_str() , O_CREAT | O_WRONLY | O_APPEND | O_TRUNC, S_IRUSR | S_IWUSR)))
	{
		perror("There was an error with open(). ");
		exit(1);
	}
	execfunction(argv, "git");
	delete []argv;
	if(-1 == close(write_to))
	{
		perror("There was an error with close(). ");
	}
	if(-1 == dup2(savestdout, 1))
	{
		perror("There was an error with dup2(). ");
	}
	int read_from;
	if(-1 == (read_from = open(file_name.c_str(), O_RDONLY)))
	{
		perror("There was an error with open(). ");
	}
	int size;
	char c[BUFSIZ];
	if(-1 == (size = read(read_from, &c, BUFSIZ)))
	{
		perror("There was an error with read(). ");
	}
	while(size > 0)
	{
		branches.push_back(string(c));
		if(-1 == (size = read(read_from, &c, BUFSIZ)))
		{
			perror("There was an error with read(). ");
		}
	}
	if(-1 == close(read_from))
	{
		perror("There was an error with close(). ");
	}
	//take all branch names and put into vector
	//for each branch name, call execvp git checkout branchname
	for(unsigned int i = 0; i < branches.size(); ++i)
	{
		branches.at(i) = (branches.at(i)).substr(2, (branches.at(i)).size()-3);
		cout << branches.at(i) << endl;
	}
	argv = new char*[3];
	argv[0] = const_cast<char*>("rm");
	argv[1] = const_cast<char*>(file_name.c_str());
	argv[2] = 0;
	execfunction(argv, "rm");
	delete []argv;
	//then open/create a file called branchname for whatever branch we are on
	for(unsigned int i = 0; i < branches.size(); ++i)
	{
	}
	//then call execvp git log to have all the output go to file
	//close file
	//reopen stdout
	return 0;
}
<|endoftext|>


<commit_before>/******************************************************************************\
* File:          shell.cpp
* Purpose:       Implementation of class wxExSTCShell
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
*
* Copyright (c) 1998-2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <numeric>
#include <functional>
#include <wx/config.h>
#include <wx/tokenzr.h>
#include <wx/extension/shell.h>
#include <wx/extension/defs.h> // for ID_SHELL_COMMAND

#if wxUSE_GUI

BEGIN_EVENT_TABLE(wxExSTCShell, wxExSTC)
  EVT_KEY_DOWN(wxExSTCShell::OnKey)
  EVT_MENU(wxID_PASTE, wxExSTCShell::OnCommand)
END_EVENT_TABLE()

wxExSTCShell::wxExSTCShell(
  wxWindow* parent,
  const wxString& prompt,
  const wxString& command_end,
  bool echo,
  int commands_save_in_config,
  long menu_flags,
  wxWindowID id,
  const wxPoint& pos,
  const wxSize& size,
  long style)
  : wxExSTC(
      parent,
      wxEmptyString,
      0,
      menu_flags,
      id,
      pos,
      size,
      style)
  , m_Command(wxEmptyString)
  , m_CommandEnd((command_end == wxEmptyString ? GetEOL(): command_end))
  , m_CommandStartPosition(0)
  , m_Echo(echo)
  // take a char that is not likely to appear inside commands
  , m_CommandsInConfigDelimiter(wxUniChar(0x03))
  , m_CommandsSaveInConfig(commands_save_in_config)
  , m_Prompt(prompt)
{
  // Override defaults from config.
  SetEdgeMode(wxSTC_EDGE_NONE);
  ResetMargins(false); // do not reset divider margin

  // Start with a prompt.
  Prompt();

  if (m_CommandsSaveInConfig > 0)
  {
    // Get all previous commands.
    wxStringTokenizer tkz(wxConfigBase::Get()->Read("Shell"),
      m_CommandsInConfigDelimiter);

    while (tkz.HasMoreTokens())
    {
      const wxString val = tkz.GetNextToken();
      m_Commands.push_front(val);
    }
  }

  // Take care that m_CommandsIterator is valid.
  m_CommandsIterator = m_Commands.end();
}

wxExSTCShell::~wxExSTCShell()
{
  if (m_CommandsSaveInConfig > 0)
  {
    wxString values;
    int items = 0;

    for (
      auto it = m_Commands.rbegin();
      it != m_Commands.rend() && items < m_CommandsSaveInConfig;
      it++)
    {
      values += *it + m_CommandsInConfigDelimiter;
      items++;
    }

    wxConfigBase::Get()->Write("Shell", values);
  }
}

const wxString wxExSTCShell::GetHistory() const
{
  return accumulate(m_Commands.begin(), m_Commands.end(), wxString());
}

void wxExSTCShell::KeepCommand()
{
  m_Commands.remove(m_Command);
  m_Commands.push_back(m_Command);
}

void wxExSTCShell::OnCommand(wxCommandEvent& command)
{
  switch (command.GetId())
  {
    case wxID_PASTE:
      // Take care that we cannot paste somewhere inside.
      if (GetCurrentPos() < m_CommandStartPosition)
      {
        DocumentEnd();
      }

      Paste();
      break;

    default:
      wxFAIL;
      break;
  }
}

void wxExSTCShell::OnKey(wxKeyEvent& event)
{
  const auto key = event.GetKeyCode();

  // Enter key pressed, we might have entered a command.
  if (key == WXK_RETURN)
  {
    // First get the command.
    SetTargetStart(GetTextLength());
    SetTargetEnd(0);
    SetSearchFlags(wxSTC_FIND_REGEXP);

    if (SearchInTarget("^" + m_Prompt + ".*") != -1)
    {
      m_Command = GetText().substr(
        GetTargetStart() + m_Prompt.length(),
        GetTextLength() - 1);
      m_Command.Trim();
    }

    if (m_Command.empty())
    {
      Prompt();
    }
    else if (
      m_CommandEnd == GetEOL() ||
      m_Command.EndsWith(m_CommandEnd))
    {
      // We have a command.
      EmptyUndoBuffer();

      // History command.
      if (m_Command == wxString("history") +
         (m_CommandEnd == GetEOL() ? wxString(wxEmptyString): m_CommandEnd))
      {
        KeepCommand();
        ShowHistory();
        Prompt();
      }
      // !.. command, get it from history.
      else if (m_Command.StartsWith("!"))
      {
        if (SetCommandFromHistory(m_Command.substr(1)))
        {
          AppendText(GetEOL() + m_Command);

          // We don't keep the command, so commands are not rearranged and
          // repeatingly calling !5 always gives the same command, just as bash does.

          wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, ID_SHELL_COMMAND);
          event.SetString(m_Command);
          wxPostEvent(GetParent(), event);
        }
        else
        {
          Prompt(GetEOL() + m_Command + ": " + _("event not found"));
        }
      }
      // Other command, send to parent.
      else
      {
        KeepCommand();
        wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, ID_SHELL_COMMAND);
        event.SetString(m_Command);
        wxPostEvent(GetParent(), event);
      }

      m_Command.clear();
    }
    else
    {
      if (m_Echo) event.Skip();
    }

    m_CommandsIterator = m_Commands.end();
  }
  // Up or down key pressed, and at the end of document.
  else if ((key == WXK_UP || key == WXK_DOWN) &&
            GetCurrentPos() == GetTextLength())
  {
    ShowCommand(key);
  }
  // Home key pressed.
  else if (key == WXK_HOME)
  {
    Home();

    const wxString line = GetLine(GetCurrentLine());

    if (line.StartsWith(m_Prompt))
    {
      GotoPos(GetCurrentPos() + m_Prompt.length());
    }
  }
  // Ctrl-Q pressed, used to stop processing.
  else if (event.GetModifiers() == wxMOD_CONTROL && key == 'Q')
  {
    wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, ID_SHELL_COMMAND_STOP);
    wxPostEvent(GetParent(), event);
  }
  // Ctrl-V pressed, used for pasting as well.
  else if (event.GetModifiers() == wxMOD_CONTROL && key == 'V')
  {
    if (GetCurrentPos() < m_CommandStartPosition) DocumentEnd();
    if (m_Echo) event.Skip();
  }
  // Backspace or delete key pressed.
  else if (key == WXK_BACK || key == WXK_DELETE)
  {
    if (GetCurrentPos() <= m_CommandStartPosition)
    {
      // Ignore, so do nothing.
    }
    else
    {
      // Allow.
      if (m_Echo) event.Skip();
    }
  }
  // The rest.
  else
  {
    // If we enter regular text and not already building a command, first goto end.
    if (event.GetModifiers() == wxMOD_NONE &&
        key < WXK_START &&
        GetCurrentPos() < m_CommandStartPosition)
    {
      DocumentEnd();
    }

    m_CommandsIterator = m_Commands.end();

    if (m_Echo) event.Skip();
  }
}

void wxExSTCShell::Prompt(const wxString& text, bool add_eol)
{
  if (!text.empty())
  {
    AppendText(text);
  }

  if (GetTextLength() > 0 && add_eol)
  {
    AppendText(GetEOL());
  }

  AppendText(m_Prompt);

  DocumentEnd();

  m_CommandStartPosition = GetCurrentPos();

  EmptyUndoBuffer();
}

bool wxExSTCShell::SetCommandFromHistory(const wxString& short_command)
{
  const auto no_asked_for = atoi(short_command.c_str());

  if (no_asked_for > 0)
  {
    int no = 1;

    for (
      auto it = m_Commands.begin();
      it != m_Commands.end();
      it++)
    {
      if (no == no_asked_for)
      {
        m_Command = *it;
        return true;
      }

      no++;
    }
  }
  else
  {
    wxString short_command_check;

    if (m_CommandEnd == GetEOL())
    {
      short_command_check = short_command;
    }
    else
    {
      short_command_check =
        short_command.substr(
          0,
          short_command.length() - m_CommandEnd.length());
    }

    for (
      auto it = m_Commands.rbegin();
      it != m_Commands.rend();
      it++)
    {
      const wxString command = *it;

      if (command.StartsWith(short_command_check))
      {
        m_Command = command;
        return true;
      }
    }
  }

  return false;
}

void wxExSTCShell::ShowCommand(int key)
{
  SetTargetStart(GetTextLength());
  SetTargetEnd(0);
  SetSearchFlags(wxSTC_FIND_REGEXP);

  if (SearchInTarget("^" + m_Prompt + ".*") != -1)
  {
    SetTargetEnd(GetTextLength());

    if (key == WXK_UP)
    {
      if (m_CommandsIterator != m_Commands.begin())
      {
        m_CommandsIterator--;
      }
    }
    else
    {
      if (m_CommandsIterator != m_Commands.end())
      {
        m_CommandsIterator++;
      }
    }

    if (m_CommandsIterator != m_Commands.end())
    {
      ReplaceTarget(m_Prompt + *m_CommandsIterator);
    }
    else
    {
      ReplaceTarget(m_Prompt);
    }

    DocumentEnd();
  }
}

void wxExSTCShell::ShowHistory()
{
  int command_no = 1;

  for (
    auto it = m_Commands.begin();
    it != m_Commands.end();
    it++)
  {
    const wxString command = *it;

    AppendText(wxString::Format("\n%d %s",
      command_no++,
      command.c_str()));
  }
}

#endif // wxUSE_GUI
<commit_msg>reset lexer in shell<commit_after>/******************************************************************************\
* File:          shell.cpp
* Purpose:       Implementation of class wxExSTCShell
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
*
* Copyright (c) 1998-2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <numeric>
#include <functional>
#include <wx/config.h>
#include <wx/tokenzr.h>
#include <wx/extension/shell.h>
#include <wx/extension/defs.h> // for ID_SHELL_COMMAND

#if wxUSE_GUI

BEGIN_EVENT_TABLE(wxExSTCShell, wxExSTC)
  EVT_KEY_DOWN(wxExSTCShell::OnKey)
  EVT_MENU(wxID_PASTE, wxExSTCShell::OnCommand)
END_EVENT_TABLE()

wxExSTCShell::wxExSTCShell(
  wxWindow* parent,
  const wxString& prompt,
  const wxString& command_end,
  bool echo,
  int commands_save_in_config,
  long menu_flags,
  wxWindowID id,
  const wxPoint& pos,
  const wxSize& size,
  long style)
  : wxExSTC(
      parent,
      wxEmptyString,
      0,
      menu_flags,
      id,
      pos,
      size,
      style)
  , m_Command(wxEmptyString)
  , m_CommandEnd((command_end == wxEmptyString ? GetEOL(): command_end))
  , m_CommandStartPosition(0)
  , m_Echo(echo)
  // take a char that is not likely to appear inside commands
  , m_CommandsInConfigDelimiter(wxUniChar(0x03))
  , m_CommandsSaveInConfig(commands_save_in_config)
  , m_Prompt(prompt)
{
  // Override defaults from config.
  SetEdgeMode(wxSTC_EDGE_NONE);
  ResetMargins(false); // do not reset divider margin

  // Start with a prompt.
  Prompt();

  if (m_CommandsSaveInConfig > 0)
  {
    // Get all previous commands.
    wxStringTokenizer tkz(wxConfigBase::Get()->Read("Shell"),
      m_CommandsInConfigDelimiter);

    while (tkz.HasMoreTokens())
    {
      const wxString val = tkz.GetNextToken();
      m_Commands.push_front(val);
    }
  }

  // Take care that m_CommandsIterator is valid.
  m_CommandsIterator = m_Commands.end();

  SetLexer(wxEmptyString);
}

wxExSTCShell::~wxExSTCShell()
{
  if (m_CommandsSaveInConfig > 0)
  {
    wxString values;
    int items = 0;

    for (
      auto it = m_Commands.rbegin();
      it != m_Commands.rend() && items < m_CommandsSaveInConfig;
      it++)
    {
      values += *it + m_CommandsInConfigDelimiter;
      items++;
    }

    wxConfigBase::Get()->Write("Shell", values);
  }
}

const wxString wxExSTCShell::GetHistory() const
{
  return accumulate(m_Commands.begin(), m_Commands.end(), wxString());
}

void wxExSTCShell::KeepCommand()
{
  m_Commands.remove(m_Command);
  m_Commands.push_back(m_Command);
}

void wxExSTCShell::OnCommand(wxCommandEvent& command)
{
  switch (command.GetId())
  {
    case wxID_PASTE:
      // Take care that we cannot paste somewhere inside.
      if (GetCurrentPos() < m_CommandStartPosition)
      {
        DocumentEnd();
      }

      Paste();
      break;

    default:
      wxFAIL;
      break;
  }
}

void wxExSTCShell::OnKey(wxKeyEvent& event)
{
  const auto key = event.GetKeyCode();

  // Enter key pressed, we might have entered a command.
  if (key == WXK_RETURN)
  {
    // First get the command.
    SetTargetStart(GetTextLength());
    SetTargetEnd(0);
    SetSearchFlags(wxSTC_FIND_REGEXP);

    if (SearchInTarget("^" + m_Prompt + ".*") != -1)
    {
      m_Command = GetText().substr(
        GetTargetStart() + m_Prompt.length(),
        GetTextLength() - 1);
      m_Command.Trim();
    }

    if (m_Command.empty())
    {
      Prompt();
    }
    else if (
      m_CommandEnd == GetEOL() ||
      m_Command.EndsWith(m_CommandEnd))
    {
      // We have a command.
      EmptyUndoBuffer();

      // History command.
      if (m_Command == wxString("history") +
         (m_CommandEnd == GetEOL() ? wxString(wxEmptyString): m_CommandEnd))
      {
        KeepCommand();
        ShowHistory();
        Prompt();
      }
      // !.. command, get it from history.
      else if (m_Command.StartsWith("!"))
      {
        if (SetCommandFromHistory(m_Command.substr(1)))
        {
          AppendText(GetEOL() + m_Command);

          // We don't keep the command, so commands are not rearranged and
          // repeatingly calling !5 always gives the same command, just as bash does.

          wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, ID_SHELL_COMMAND);
          event.SetString(m_Command);
          wxPostEvent(GetParent(), event);
        }
        else
        {
          Prompt(GetEOL() + m_Command + ": " + _("event not found"));
        }
      }
      // Other command, send to parent.
      else
      {
        KeepCommand();
        wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, ID_SHELL_COMMAND);
        event.SetString(m_Command);
        wxPostEvent(GetParent(), event);
      }

      m_Command.clear();
    }
    else
    {
      if (m_Echo) event.Skip();
    }

    m_CommandsIterator = m_Commands.end();
  }
  // Up or down key pressed, and at the end of document.
  else if ((key == WXK_UP || key == WXK_DOWN) &&
            GetCurrentPos() == GetTextLength())
  {
    ShowCommand(key);
  }
  // Home key pressed.
  else if (key == WXK_HOME)
  {
    Home();

    const wxString line = GetLine(GetCurrentLine());

    if (line.StartsWith(m_Prompt))
    {
      GotoPos(GetCurrentPos() + m_Prompt.length());
    }
  }
  // Ctrl-Q pressed, used to stop processing.
  else if (event.GetModifiers() == wxMOD_CONTROL && key == 'Q')
  {
    wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, ID_SHELL_COMMAND_STOP);
    wxPostEvent(GetParent(), event);
  }
  // Ctrl-V pressed, used for pasting as well.
  else if (event.GetModifiers() == wxMOD_CONTROL && key == 'V')
  {
    if (GetCurrentPos() < m_CommandStartPosition) DocumentEnd();
    if (m_Echo) event.Skip();
  }
  // Backspace or delete key pressed.
  else if (key == WXK_BACK || key == WXK_DELETE)
  {
    if (GetCurrentPos() <= m_CommandStartPosition)
    {
      // Ignore, so do nothing.
    }
    else
    {
      // Allow.
      if (m_Echo) event.Skip();
    }
  }
  // The rest.
  else
  {
    // If we enter regular text and not already building a command, first goto end.
    if (event.GetModifiers() == wxMOD_NONE &&
        key < WXK_START &&
        GetCurrentPos() < m_CommandStartPosition)
    {
      DocumentEnd();
    }

    m_CommandsIterator = m_Commands.end();

    if (m_Echo) event.Skip();
  }
}

void wxExSTCShell::Prompt(const wxString& text, bool add_eol)
{
  if (!text.empty())
  {
    AppendText(text);
  }

  if (GetTextLength() > 0 && add_eol)
  {
    AppendText(GetEOL());
  }

  AppendText(m_Prompt);

  DocumentEnd();

  m_CommandStartPosition = GetCurrentPos();

  EmptyUndoBuffer();
}

bool wxExSTCShell::SetCommandFromHistory(const wxString& short_command)
{
  const auto no_asked_for = atoi(short_command.c_str());

  if (no_asked_for > 0)
  {
    int no = 1;

    for (
      auto it = m_Commands.begin();
      it != m_Commands.end();
      it++)
    {
      if (no == no_asked_for)
      {
        m_Command = *it;
        return true;
      }

      no++;
    }
  }
  else
  {
    wxString short_command_check;

    if (m_CommandEnd == GetEOL())
    {
      short_command_check = short_command;
    }
    else
    {
      short_command_check =
        short_command.substr(
          0,
          short_command.length() - m_CommandEnd.length());
    }

    for (
      auto it = m_Commands.rbegin();
      it != m_Commands.rend();
      it++)
    {
      const wxString command = *it;

      if (command.StartsWith(short_command_check))
      {
        m_Command = command;
        return true;
      }
    }
  }

  return false;
}

void wxExSTCShell::ShowCommand(int key)
{
  SetTargetStart(GetTextLength());
  SetTargetEnd(0);
  SetSearchFlags(wxSTC_FIND_REGEXP);

  if (SearchInTarget("^" + m_Prompt + ".*") != -1)
  {
    SetTargetEnd(GetTextLength());

    if (key == WXK_UP)
    {
      if (m_CommandsIterator != m_Commands.begin())
      {
        m_CommandsIterator--;
      }
    }
    else
    {
      if (m_CommandsIterator != m_Commands.end())
      {
        m_CommandsIterator++;
      }
    }

    if (m_CommandsIterator != m_Commands.end())
    {
      ReplaceTarget(m_Prompt + *m_CommandsIterator);
    }
    else
    {
      ReplaceTarget(m_Prompt);
    }

    DocumentEnd();
  }
}

void wxExSTCShell::ShowHistory()
{
  int command_no = 1;

  for (
    auto it = m_Commands.begin();
    it != m_Commands.end();
    it++)
  {
    const wxString command = *it;

    AppendText(wxString::Format("\n%d %s",
      command_no++,
      command.c_str()));
  }
}

#endif // wxUSE_GUI
<|endoftext|>


<commit_before>// Copyright 2013 Michael Lopez
//
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.

//  Congruence Closure data structure
//
//  This is an abstract congruence closure data structure that stores
//  equalities for some expression type. It supports equality queries, identify
//  differences in expressions, and supports unification.
//
//  The expression type E must support the following operators:
//    args(E) -> Range(E)     -- returns a range of the arguments of an
//                               expression
//    same_node(E,E) -> bool  -- true iff the expressions represent the same
//                               function symbol
//    num_args(E) -> Nat      -- the number of arguments of an expression

#ifndef DIMITRI_CONGRUENCE_HPP
#define DIMITRI_CONGRUENCE_HPP

#include <map>
#include <vector>
#include <algorithm>
#include <utility>

namespace dimitri {

  // ------------------ //
  // --- Maybe type --- //
  // ------------------ //
  template <typename X>
    struct maybe {
      maybe ();
      maybe (const X&);
      maybe (const maybe&);
      bool is_nothing () const { return !is_just; }
      bool is_just;
      X val;
    };

  // ------------------ //
  // --- Union Find --- //
  // ------------------ //
  // The mighty union find data structure (or a simpler version of it). This
  // data structure maintains a partition of the integers [0,parent.size()).

  struct union_find_t {
    using size_t = std::size_t;

    // -- Constructors
    union_find_t ();
    union_find_t (size_t);
    union_find_t (const union_find_t&);

    // -- Set algebra
    bool in_same_set (size_t, size_t);
    void union_sets (size_t, size_t);

    // -- Get a fresh variable
    size_t fresh_variable ();

    //  -- Parent mapping
    std::vector<size_t> parent;

    //  -- Get the roots of the elements in the universe
    size_t root_of (size_t);
  };

  // ------------------------------ //
  // --- Canonical element maps --- //
  // ------------------------------ //
  // This data structure simply maintatins a mapping from expressions to
  // integers in the partition. It glues the expression language to the
  // union_find_t type.

  template <typename E>
    struct canonical_map_t
    {
      // using size_t = std::size_t;
      using expr_t = E;
      using size_t = std::size_t;

      canonical_map_t ();

      maybe<size_t> get (expr_t);
      void set (expr_t, size_t);

      // -- Representative elements
      std::map<expr_t,size_t> representatives;
    };

  // -------------------------- //
  // --- Congruence closure --- //
  // -------------------------- //
  // This data structure computes and maintains a congruence closure over some
  // expression type Expr. The requirements on the expression language are
  // enumerated in the README.md file.

  template <
    typename Expr,
    typename Args,
    typename Same_symbol,
    typename Num_args
  >
    struct congruence_t {

      using expr_t = Expr;
      using expr_pair_t = std::pair<expr_t,expr_t>;
      using size_t = std::size_t;

      congruence_t (
        const Args& = Arg(), const Same_symbol& = Same_symbol(),
        const Num_args& = Num_args());

      // Congruence Interface
      bool is_congruent (expr_t, expr_t);
      std::vector<expr_pair_t> report_differences (expr_t, expr_t);
      void set_congruent (expr_t, expr_t);

      // Expression algebra
      Args args;
      Same_symbol is_same_symbol;
      Num_args num_args;

      // Auxiliary data structures
      canonical_map_t<expr_t> reps;
      union_find_t sets;

      // Congruence algebra
      std::vector<expr_pair_t> differences (expr_t, expr_t);
      size_t get_or_gen_canonical (expr_t);
      bool not_directly_congruent (expr_pair_t);
    };

//// ----------------------------------------------------------------------- ////
//// ----- implementation details ------------------------------------------ ////
//// ----------------------------------------------------------------------- ////

  // ------------- //
  // --- Maybe --- //
  // ------------- //

  template <typename X>
    maybe<X>::maybe ()
      : is_just(false), val()
    { }

  template <typename X>
    maybe<X>::maybe (const X& x)
      : is_just(true), val(x)
    { }

    template <typename X>
    maybe<X>::maybe (const maybe& m)
      : is_just(m.is_just), val(m.val)
    { }

  // ------------------ //
  // --- Union Find --- //
  // ------------------ //

  union_find_t::union_find_t ()
    : parent ()
  { }

  // -- Set partition of [0,n) o be singletons
  // FIXME necessary?
  union_find_t::union_find_t (size_t n)
    : parent (n,0)
  { for (size_t i = 0; i < n; ++i) parent[i] = i; }

  union_find_t::union_find_t (const union_find_t& c)
    : parent(c.parent)
  { }

  // -- true iff m and n are in the same set
  bool union_find_t::in_same_set (size_t m, size_t n)
  {
    return m == n or root_of(m) == root_of(n);
  }

  // -- union the sets in the partition
  // axiom: !in_same_set(m,n)
  void union_find_t::union_sets (size_t m, size_t n)
  {
    n = root_of(n);
    parent[n] = m;
  }

  // -- return a fresh variable
  size_t union_find_t::new_free_variable ()
  {
    size_t var = parent.size();
    parent.push_back(var);
    return var;
  }

  // -- get the canonical element of the set containing n
  auto union_find_t::root_of (size_t n) -> size_t
  {
    size_t parent_of_n = parent[n];
    while (n != parent_of_n) {
      n = parent_of_n;
      parent_of_n = parent[n]; }
    return n;
  }

}

#endif // DIMITRI_CONGRUENCE_HPP<commit_msg>Added auxiliary expression traversal data structure to congruence.hpp<commit_after>// Copyright 2013 Michael Lopez
//
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.

//  Congruence Closure data structure
//
//  This is an abstract congruence closure data structure that stores
//  equalities for some expression type. It supports equality queries, identify
//  differences in expressions, and supports unification.
//
//  The expression type E must support the following operators:
//    args(E) -> Range(E)     -- returns a range of the arguments of an
//                               expression
//    same_node(E,E) -> bool  -- true iff the expressions represent the same
//                               function symbol
//    num_args(E) -> Nat      -- the number of arguments of an expression

#ifndef DIMITRI_CONGRUENCE_HPP
#define DIMITRI_CONGRUENCE_HPP

#include <map>
#include <vector>
#include <algorithm>
#include <utility>

namespace dimitri {

  // ------------------ //
  // --- Maybe type --- //
  // ------------------ //
  template <typename X>
    struct maybe {
      maybe ();
      maybe (const X&);
      maybe (const maybe&);
      bool is_nothing () const { return !is_just; }
      bool is_just;
      X val;
    };

  // ------------------ //
  // --- Union Find --- //
  // ------------------ //
  // The mighty union find data structure (or a simpler version of it). This
  // data structure maintains a partition of the integers [0,parent.size()).

  struct union_find_t {
    using size_t = std::size_t;

    // -- Constructors
    union_find_t ();
    union_find_t (size_t);
    union_find_t (const union_find_t&);

    // -- Set algebra
    bool in_same_set (size_t, size_t);
    void union_sets (size_t, size_t);

    // -- Get a fresh variable
    size_t fresh_variable ();

    //  -- Parent mapping
    std::vector<size_t> parent;

    //  -- Get the roots of the elements in the universe
    size_t root_of (size_t);
  };

  // ------------------------------ //
  // --- Canonical element maps --- //
  // ------------------------------ //
  // This data structure simply maintatins a mapping from expressions to
  // integers in the partition. It glues the expression language to the
  // union_find_t type.

  template <typename E>
    struct canonical_map_t
    {
      // using size_t = std::size_t;
      using expr_t = E;
      using size_t = std::size_t;

      canonical_map_t ();

      maybe<size_t> get (expr_t);
      void set (expr_t, size_t);

      // -- Representative elements
      std::map<expr_t,size_t> representatives;
    };

  // ---------------------------- //
  // --- Expression Traversal --- //
  // ---------------------------- //
  // Ad-hoc expression traverser
  template <
    typename E,
    typename Args,
    typename Same_node,
    typename Num_args
  >
    struct expr_traversal {
      using expr_t = E;
      using expr_pair_t = std::pair<expr_t,expr_t>;

      expr_traversal (
        std::vector<std::pair<expr_t,expr_t>>&, const Args&, const Same_node&,
        const Num_args&);
      void traverse (expr_t e1, expr_t e2);

      // The differences between the expressions
      std::vector<expr_pair_t>& expr_pairs;

      Args args;
      Same_node is_same_node;
      Num_args num_args;
    };

  // -------------------------- //
  // --- Congruence closure --- //
  // -------------------------- //
  // This data structure computes and maintains a congruence closure over some
  // expression type Expr. The requirements on the expression language are
  // enumerated in the README.md file.
  // NOTE is there a way to remove the num args requirement? If Args is a
  // function that returns a random access iterator range, then Num args is not
  // necessary. However, as with GCC, this is not always the case. Hmm. I think
  // it can go. Must confer with brain.

  template <
    typename Expr,
    typename Args,
    typename Same_symbol,
    typename Num_args
  >
    struct congruence_t {

      using expr_t = Expr;
      using expr_pair_t = std::pair<expr_t,expr_t>;
      using size_t = std::size_t;

      congruence_t (
        const Args& = Arg(), const Same_symbol& = Same_symbol(),
        const Num_args& = Num_args());

      // Congruence Interface
      bool is_congruent (expr_t, expr_t);
      std::vector<expr_pair_t> report_differences (expr_t, expr_t);
      void set_congruent (expr_t, expr_t);

      // Expression algebra
      Args args;
      Same_symbol is_same_symbol;
      Num_args num_args;

      // Auxiliary data structures
      canonical_map_t<expr_t> reps;
      union_find_t sets;

      // Congruence algebra
      std::vector<expr_pair_t> differences (expr_t, expr_t);
      size_t get_or_gen_canonical (expr_t);
      bool not_directly_congruent (expr_pair_t);
    };

//// ----------------------------------------------------------------------- ////
//// ----- implementation details ------------------------------------------ ////
//// ----------------------------------------------------------------------- ////

  // ------------- //
  // --- Maybe --- //
  // ------------- //

  template <typename X>
    maybe<X>::maybe ()
      : is_just(false), val()
    { }

  template <typename X>
    maybe<X>::maybe (const X& x)
      : is_just(true), val(x)
    { }

    template <typename X>
    maybe<X>::maybe (const maybe& m)
      : is_just(m.is_just), val(m.val)
    { }

  // ------------------ //
  // --- Union Find --- //
  // ------------------ //

  union_find_t::union_find_t ()
    : parent ()
  { }

  // -- Set partition of [0,n) o be singletons
  // FIXME necessary?
  union_find_t::union_find_t (size_t n)
    : parent (n,0)
  { for (size_t i = 0; i < n; ++i) parent[i] = i; }

  union_find_t::union_find_t (const union_find_t& c)
    : parent(c.parent)
  { }

  // -- true iff m and n are in the same set
  bool union_find_t::in_same_set (size_t m, size_t n)
  {
    return m == n or root_of(m) == root_of(n);
  }

  // -- union the sets in the partition
  // axiom: !in_same_set(m,n)
  void union_find_t::union_sets (size_t m, size_t n)
  {
    n = root_of(n);
    parent[n] = m;
  }

  // -- return a fresh variable
  size_t union_find_t::new_free_variable ()
  {
    size_t var = parent.size();
    parent.push_back(var);
    return var;
  }

  // -- get the canonical element of the set containing n
  auto union_find_t::root_of (size_t n) -> size_t
  {
    size_t parent_of_n = parent[n];
    while (n != parent_of_n) {
      n = parent_of_n;
      parent_of_n = parent[n]; }
    return n;
  }

}

#endif // DIMITRI_CONGRUENCE_HPP<|endoftext|>