<commit_before>
#include "MethodDeclHandler.h"

#include <regex>

namespace typegrind
{

      MethodDeclHandler::MethodDeclHandler(clang::Rewriter*& rewriter, MethodMatcher const& matchers)
              : mRewriter(rewriter)
              , mMatchers(matchers)
      {
      }

      clang::StringRef MethodDeclHandler::getID() const {
          return "typegrind";
      }

      void MethodDeclHandler::run(const clang::ast_matchers::MatchFinder::MatchResult &result)
      {
        const clang::CXXMethodDecl* decl = result.Nodes.getNodeAs<clang::CXXMethodDecl>("decl");
        if(!decl) return;
        if (!decl->hasBody()) return;

        if(decl->getTemplateSpecializationKind() == clang::TSK_ImplicitInstantiation) return;

        //llvm::outs() << decl->getNameInfo().getAsString() << "\n";
        std::string prettyName;
        {
          llvm::raw_string_ostream prettyNameStream(prettyName);
          decl->getCanonicalDecl()->getNameForDiagnostic(prettyNameStream, clang::PrintingPolicy(result.Context->getPrintingPolicy()), true);
          prettyNameStream.flush();
        }

        auto match = mMatchers.matches(prettyName);
        if(!match) return;

        //if(mVisited.find(prettyName) != mVisited.end()) return;
        //mVisited.insert(prettyName);

        auto& sm = result.Context->getSourceManager();
        auto ploc = sm.getPresumedLoc(decl->getLocEnd());
        std::string locStr = "'";
        locStr += ploc.getFilename();
        locStr += ":";
        locStr += std::to_string(ploc.getLine());
        locStr += "'";

        clang::Stmt *funcBody = decl->getBody();
        mRewriter->InsertTextAfterToken(funcBody->getSourceRange().getBegin(), " TYPEGRIND_LOG_METHOD_ENTER(\""+prettyName+"\", "+locStr+", \""+match->custom_name+"\", "+std::to_string(match->flags)+") ");

        // if constructor - initializer lists
        {
          const clang::CXXConstructorDecl* constrDecl = result.Nodes.getNodeAs<clang::CXXConstructorDecl>("decl");
          if(constrDecl)
          {
            for(auto initer: constrDecl->inits())
            {
              if(!initer->isMemberInitializer()) continue;
              mRewriter->InsertTextAfterToken(initer->getLParenLoc(), "TYPEGRIND_LOG_METHOD_INITIALIZER(\""+prettyName+"\", "+locStr+", \""+match->custom_name+"\", "+std::to_string(match->flags)+", (");
              mRewriter->InsertTextBefore(initer->getRParenLoc(), "))");
            }
          }
        }
      }
}
<commit_msg>using " instead of '<commit_after>
#include "MethodDeclHandler.h"

#include <regex>

namespace typegrind
{

      MethodDeclHandler::MethodDeclHandler(clang::Rewriter*& rewriter, MethodMatcher const& matchers)
              : mRewriter(rewriter)
              , mMatchers(matchers)
      {
      }

      clang::StringRef MethodDeclHandler::getID() const {
          return "typegrind";
      }

      void MethodDeclHandler::run(const clang::ast_matchers::MatchFinder::MatchResult &result)
      {
        const clang::CXXMethodDecl* decl = result.Nodes.getNodeAs<clang::CXXMethodDecl>("decl");
        if(!decl) return;
        if (!decl->hasBody()) return;

        if(decl->getTemplateSpecializationKind() == clang::TSK_ImplicitInstantiation) return;

        //llvm::outs() << decl->getNameInfo().getAsString() << "\n";
        std::string prettyName;
        {
          llvm::raw_string_ostream prettyNameStream(prettyName);
          decl->getCanonicalDecl()->getNameForDiagnostic(prettyNameStream, clang::PrintingPolicy(result.Context->getPrintingPolicy()), true);
          prettyNameStream.flush();
        }

        auto match = mMatchers.matches(prettyName);
        if(!match) return;

        //if(mVisited.find(prettyName) != mVisited.end()) return;
        //mVisited.insert(prettyName);

        auto& sm = result.Context->getSourceManager();
        auto ploc = sm.getPresumedLoc(decl->getLocEnd());
        std::string locStr = "\"";
        locStr += ploc.getFilename();
        locStr += ":";
        locStr += std::to_string(ploc.getLine());
        locStr += "\"";

        clang::Stmt *funcBody = decl->getBody();
        mRewriter->InsertTextAfterToken(funcBody->getSourceRange().getBegin(), " TYPEGRIND_LOG_METHOD_ENTER(\""+prettyName+"\", "+locStr+", \""+match->custom_name+"\", "+std::to_string(match->flags)+") ");

        // if constructor - initializer lists
        {
          const clang::CXXConstructorDecl* constrDecl = result.Nodes.getNodeAs<clang::CXXConstructorDecl>("decl");
          if(constrDecl)
          {
            for(auto initer: constrDecl->inits())
            {
              if(!initer->isMemberInitializer()) continue;
              mRewriter->InsertTextAfterToken(initer->getLParenLoc(), "TYPEGRIND_LOG_METHOD_INITIALIZER(\""+prettyName+"\", "+locStr+", \""+match->custom_name+"\", "+std::to_string(match->flags)+", (");
              mRewriter->InsertTextBefore(initer->getRParenLoc(), "))");
            }
          }
        }
      }
}
<|endoftext|>


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

#include "condor_common.h"
#include "condor_debug.h"
#include "condor_config.h"
#include "condor_string.h"
#include "daemon_list.h"
#include "dc_collector.h"
#include "internet.h"
#include "ipv6_hostname.h"
#include <vector>

DaemonList::DaemonList()
{
}

DaemonList::~DaemonList( void )
{
	Daemon* tmp;
	list.Rewind();
	while( list.Next(tmp) ) {
		delete tmp;
	}
}

void
DaemonList::init( daemon_t type, const char* host_list, const char* pool_list )
{
	Daemon* tmp;
	char* host;
	char const *pool = NULL;
	StringList foo;
	StringList pools;
	if( host_list ) {
		foo.initializeFromString( host_list );
		foo.rewind();
	}
	if( pool_list ) {
		pools.initializeFromString( pool_list );
		pools.rewind();
	}
	while( true ) {
		host = foo.next();
		pool = pools.next();
		if( !host && !pool ) {
			break;
		}
		tmp = buildDaemon( type, host, pool );
		append( tmp );
	}
}

Daemon*
DaemonList::buildDaemon( daemon_t type, const char* host, char const *pool )
{
	Daemon* tmp;
	switch( type ) {
	case DT_COLLECTOR:
		tmp = new DCCollector( host );
		break;
	default:
		tmp = new Daemon( type, host, pool );
		break;
	}
	return tmp;
}

/*************************************************************
 ** SimpleList API
 ************************************************************/

bool
DaemonList::append( Daemon* d) { return list.Append(d); }

bool
DaemonList::Append( Daemon* d) { return list.Append(d); }

bool
DaemonList::isEmpty( void ) { return list.IsEmpty(); }

bool
DaemonList::IsEmpty( void ) { return list.IsEmpty(); }

int
DaemonList::number( void ) { return list.Number(); }

int
DaemonList::Number( void ) { return list.Number(); }

void
DaemonList::rewind( void ) { list.Rewind(); }

void
DaemonList::Rewind( void ) { list.Rewind(); }

bool
DaemonList::current( Daemon* & d ) { return list.Current(d); }

bool
DaemonList::Current( Daemon* & d ) { return list.Current(d); }

bool
DaemonList::next( Daemon* & d ) { return list.Next(d); }

bool
DaemonList::Next( Daemon* & d ) { return list.Next(d); }

bool
DaemonList::atEnd() { return list.AtEnd(); }

bool
DaemonList::AtEnd() { return list.AtEnd(); }

void
DaemonList::deleteCurrent() { this->DeleteCurrent(); }

/*
  NOTE: SimpleList does NOT delete the Daemon objects themselves,
  DeleteCurrent() is only going to delete the pointer itself.  Since
  we're responsible for all this memory (we create the Daemon objects
  in DaemonList::init() and DaemonList::buildDaemon()), we have to be
  responsbile to deallocate it when we're done.  We're already doing
  this correctly in the DaemonList destructor, and we have to do it
  here in the DeleteCurrent() interface, too.
*/
void
DaemonList::DeleteCurrent() {
	Daemon* cur = NULL;
	if( list.Current(cur) && cur ) {
		delete cur;
	}
	list.DeleteCurrent();
}

CollectorList::CollectorList() {
}

CollectorList::~CollectorList() {
}

CollectorList *
CollectorList::create( const char * pool )
{
	CollectorList * result = new CollectorList();
	DCCollector * collector = NULL;

	if (pool) {
			// Eventually we might want to query this collector
			// for all the other collectors in the pool....
		result->append (new DCCollector (pool));
		return result;
	}

		// Read the new names from config file
	StringList collector_name_list;
	char * collector_name_param = NULL;
	collector_name_param = getCmHostFromConfig( "COLLECTOR" );
	if( collector_name_param ) {
		collector_name_list.initializeFromString(collector_name_param);

			// Create collector objects
		collector_name_list.rewind();
		char * collector_name = NULL;
		while ((collector_name = collector_name_list.next()) != NULL) {
			collector = new DCCollector (collector_name);
			result->append (collector);
		}
	} else {
			// Otherwise, just return an empty list
		dprintf( D_ALWAYS, "Warning: Collector information was not found in the configuration file. ClassAds will not be sent to the collector and this daemon will not join a larger Condor pool.\n");
	}
	if( collector_name_param ) {
		free( collector_name_param );
	}
	return result;
}

/***
 *
 * Resort a collector list for locality;
 * prioritize the collector that is best suited for the negotiator
 * running on this machine. This minimizes the delay for fetching
 * ads from the Collector by the Negotiator, which some people
 * consider more critical.
 *
 ***/

int
CollectorList::resortLocal( const char *preferred_collector )
{
		// Find the collector in the list that is best suited for
		// this host. This is determined either by
		// a) preferred_collector passed in
        // b) the collector that has the same hostname as this negotiator
	char * tmp_preferred_collector = NULL;

	if ( !preferred_collector ) {
        // figure out our hostname for plan b) above
		MyString _hostname_str = get_local_fqdn();
		const char * _hostname = _hostname_str.Value();
		if (!(*_hostname)) {
				// Can't get our hostname??? fuck off
			return -1;
		}

		tmp_preferred_collector = strdup(_hostname);
		preferred_collector = tmp_preferred_collector; // So we know to free later
	}

		// First, pick out collector(s) that is on this host
	Daemon *daemon;
	SimpleList<Daemon*> prefer_list;
	this->list.Rewind();
	while ( this->list.Next(daemon) ) {
		if ( same_host (preferred_collector, daemon->fullHostname()) ) {
			this->list.DeleteCurrent();
			prefer_list.Prepend( daemon );
		}
	}

		// Walk through the list of preferred collectors,
		// stuff 'em in the main "list"
	this->list.Rewind();
	prefer_list.Rewind();
	while ( prefer_list.Next(daemon) ) {
		this->list.Prepend( daemon );
	}

	free(tmp_preferred_collector); // Warning, preferred_collector (may have) just became invalid, so do this just before returning.
	return 0;
}

int
CollectorList::sendUpdates (int cmd, ClassAd * ad1, ClassAd* ad2, bool nonblocking) {
	int success_count = 0;

	this->rewind();
	DCCollector * daemon;
	while (this->next(daemon)) {
		dprintf( D_FULLDEBUG,
				 "Trying to update collector %s\n",
				 daemon->addr() );
		if( daemon->sendUpdate(cmd, ad1, ad2, nonblocking) ) {
			success_count++;
		}
	}

	return success_count;
}

QueryResult
CollectorList::query(CondorQuery & cQuery, ClassAdList & adList, CondorError *errstack) {

	int num_collectors = this->number();
	if (num_collectors < 1) {
		return Q_NO_COLLECTOR_HOST;
	}

	std::vector<DCCollector *> vCollectors;
	DCCollector * daemon;
	QueryResult result;

	bool problems_resolving = false;

	// switch containers for easier random access.
	this->rewind();
	while (this->next(daemon)) {
		vCollectors.push_back(daemon);
	}

        while ( vCollectors.size() )
        {
            // choose a random collector in the list to query.
            unsigned int idx = get_random_int() % vCollectors.size() ;
            daemon = vCollectors[idx];

	    if ( !daemon->isBlacklisted() )
	    {
		if ( ! daemon->addr() ) {
			if ( daemon->name() ) {
				dprintf( D_ALWAYS,
						 "Can't resolve collector %s; skipping\n",
						 daemon->name() );
			} else {
				dprintf( D_ALWAYS,
						 "Can't resolve nameless collector; skipping\n" );
			}
			problems_resolving = true;

		}
		else
                {

                    dprintf (D_FULLDEBUG,
                                    "Trying to query collector %s\n",
                                    daemon->addr());

                    if( num_collectors > 1 ) {
                            daemon->blacklistMonitorQueryStarted();
                    }

                    result =
                            cQuery.fetchAds (adList, daemon->addr(), errstack);

                    if( num_collectors > 1 ) {
                            daemon->blacklistMonitorQueryFinished( result == Q_OK );
                    }

                    if (result == Q_OK) {
                            return result;
                    }
                }
	    }
	    else
	    {
	      dprintf( D_ALWAYS,"Collector %s blacklisted; skipping\n", daemon->name() );
	    }

	    // if you got here remove it from the list of potential candidates.
	    vCollectors.erase( vCollectors.begin()+idx );
	}

	// only push an error if the error stack exists and is currently empty
	if(problems_resolving && errstack && !errstack->code(0)) {
		char* tmplist = getCmHostFromConfig( "COLLECTOR" );
		errstack->pushf("CONDOR_STATUS",1,"Unable to resolve COLLECTOR_HOST (%s).",tmplist?tmplist:"(null)");
	}

		// If we've gotten here, there are no good collectors
	return Q_COMMUNICATION_ERROR;
}

bool
CollectorList::next( DCCollector* & d )
{
	return DaemonList::Next( (Daemon*&)d );
}

bool
CollectorList::Next( DCCollector* & d )
{
	return next( d );
}

bool
CollectorList::next( Daemon* & d )
{
	return DaemonList::Next( d );
}

bool
CollectorList::Next( Daemon* & d )
{
	return next( d );
}
<commit_msg>Don't crash when querying a collector whose name doesn't resolve. #3946<commit_after>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/

#include "condor_common.h"
#include "condor_debug.h"
#include "condor_config.h"
#include "condor_string.h"
#include "daemon_list.h"
#include "dc_collector.h"
#include "internet.h"
#include "ipv6_hostname.h"
#include <vector>

DaemonList::DaemonList()
{
}

DaemonList::~DaemonList( void )
{
	Daemon* tmp;
	list.Rewind();
	while( list.Next(tmp) ) {
		delete tmp;
	}
}

void
DaemonList::init( daemon_t type, const char* host_list, const char* pool_list )
{
	Daemon* tmp;
	char* host;
	char const *pool = NULL;
	StringList foo;
	StringList pools;
	if( host_list ) {
		foo.initializeFromString( host_list );
		foo.rewind();
	}
	if( pool_list ) {
		pools.initializeFromString( pool_list );
		pools.rewind();
	}
	while( true ) {
		host = foo.next();
		pool = pools.next();
		if( !host && !pool ) {
			break;
		}
		tmp = buildDaemon( type, host, pool );
		append( tmp );
	}
}

Daemon*
DaemonList::buildDaemon( daemon_t type, const char* host, char const *pool )
{
	Daemon* tmp;
	switch( type ) {
	case DT_COLLECTOR:
		tmp = new DCCollector( host );
		break;
	default:
		tmp = new Daemon( type, host, pool );
		break;
	}
	return tmp;
}

/*************************************************************
 ** SimpleList API
 ************************************************************/

bool
DaemonList::append( Daemon* d) { return list.Append(d); }

bool
DaemonList::Append( Daemon* d) { return list.Append(d); }

bool
DaemonList::isEmpty( void ) { return list.IsEmpty(); }

bool
DaemonList::IsEmpty( void ) { return list.IsEmpty(); }

int
DaemonList::number( void ) { return list.Number(); }

int
DaemonList::Number( void ) { return list.Number(); }

void
DaemonList::rewind( void ) { list.Rewind(); }

void
DaemonList::Rewind( void ) { list.Rewind(); }

bool
DaemonList::current( Daemon* & d ) { return list.Current(d); }

bool
DaemonList::Current( Daemon* & d ) { return list.Current(d); }

bool
DaemonList::next( Daemon* & d ) { return list.Next(d); }

bool
DaemonList::Next( Daemon* & d ) { return list.Next(d); }

bool
DaemonList::atEnd() { return list.AtEnd(); }

bool
DaemonList::AtEnd() { return list.AtEnd(); }

void
DaemonList::deleteCurrent() { this->DeleteCurrent(); }

/*
  NOTE: SimpleList does NOT delete the Daemon objects themselves,
  DeleteCurrent() is only going to delete the pointer itself.  Since
  we're responsible for all this memory (we create the Daemon objects
  in DaemonList::init() and DaemonList::buildDaemon()), we have to be
  responsbile to deallocate it when we're done.  We're already doing
  this correctly in the DaemonList destructor, and we have to do it
  here in the DeleteCurrent() interface, too.
*/
void
DaemonList::DeleteCurrent() {
	Daemon* cur = NULL;
	if( list.Current(cur) && cur ) {
		delete cur;
	}
	list.DeleteCurrent();
}

CollectorList::CollectorList() {
}

CollectorList::~CollectorList() {
}

CollectorList *
CollectorList::create( const char * pool )
{
	CollectorList * result = new CollectorList();
	DCCollector * collector = NULL;

	if (pool) {
			// Eventually we might want to query this collector
			// for all the other collectors in the pool....
		result->append (new DCCollector (pool));
		return result;
	}

		// Read the new names from config file
	StringList collector_name_list;
	char * collector_name_param = NULL;
	collector_name_param = getCmHostFromConfig( "COLLECTOR" );
	if( collector_name_param ) {
		collector_name_list.initializeFromString(collector_name_param);

			// Create collector objects
		collector_name_list.rewind();
		char * collector_name = NULL;
		while ((collector_name = collector_name_list.next()) != NULL) {
			collector = new DCCollector (collector_name);
			result->append (collector);
		}
	} else {
			// Otherwise, just return an empty list
		dprintf( D_ALWAYS, "Warning: Collector information was not found in the configuration file. ClassAds will not be sent to the collector and this daemon will not join a larger Condor pool.\n");
	}
	if( collector_name_param ) {
		free( collector_name_param );
	}
	return result;
}

/***
 *
 * Resort a collector list for locality;
 * prioritize the collector that is best suited for the negotiator
 * running on this machine. This minimizes the delay for fetching
 * ads from the Collector by the Negotiator, which some people
 * consider more critical.
 *
 ***/

int
CollectorList::resortLocal( const char *preferred_collector )
{
		// Find the collector in the list that is best suited for
		// this host. This is determined either by
		// a) preferred_collector passed in
        // b) the collector that has the same hostname as this negotiator
	char * tmp_preferred_collector = NULL;

	if ( !preferred_collector ) {
        // figure out our hostname for plan b) above
		MyString _hostname_str = get_local_fqdn();
		const char * _hostname = _hostname_str.Value();
		if (!(*_hostname)) {
				// Can't get our hostname??? fuck off
			return -1;
		}

		tmp_preferred_collector = strdup(_hostname);
		preferred_collector = tmp_preferred_collector; // So we know to free later
	}

		// First, pick out collector(s) that is on this host
	Daemon *daemon;
	SimpleList<Daemon*> prefer_list;
	this->list.Rewind();
	while ( this->list.Next(daemon) ) {
		if ( same_host (preferred_collector, daemon->fullHostname()) ) {
			this->list.DeleteCurrent();
			prefer_list.Prepend( daemon );
		}
	}

		// Walk through the list of preferred collectors,
		// stuff 'em in the main "list"
	this->list.Rewind();
	prefer_list.Rewind();
	while ( prefer_list.Next(daemon) ) {
		this->list.Prepend( daemon );
	}

	free(tmp_preferred_collector); // Warning, preferred_collector (may have) just became invalid, so do this just before returning.
	return 0;
}

int
CollectorList::sendUpdates (int cmd, ClassAd * ad1, ClassAd* ad2, bool nonblocking) {
	int success_count = 0;

	this->rewind();
	DCCollector * daemon;
	while (this->next(daemon)) {
		dprintf( D_FULLDEBUG,
				 "Trying to update collector %s\n",
				 daemon->addr() );
		if( daemon->sendUpdate(cmd, ad1, ad2, nonblocking) ) {
			success_count++;
		}
	}

	return success_count;
}

QueryResult
CollectorList::query(CondorQuery & cQuery, ClassAdList & adList, CondorError *errstack) {

	int num_collectors = this->number();
	if (num_collectors < 1) {
		return Q_NO_COLLECTOR_HOST;
	}

	std::vector<DCCollector *> vCollectors;
	DCCollector * daemon;
	QueryResult result;

	bool problems_resolving = false;

	// switch containers for easier random access.
	this->rewind();
	while (this->next(daemon)) {
		vCollectors.push_back(daemon);
	}

	while ( vCollectors.size() ) {
		// choose a random collector in the list to query.
		unsigned int idx = get_random_int() % vCollectors.size() ;
		daemon = vCollectors[idx];

		if ( ! daemon->addr() ) {
			if ( daemon->name() ) {
				dprintf( D_ALWAYS,
						 "Can't resolve collector %s; skipping\n",
						 daemon->name() );
			} else {
				dprintf( D_ALWAYS,
						 "Can't resolve nameless collector; skipping\n" );
			}
			problems_resolving = true;
		} else if ( daemon->isBlacklisted() ) {
			dprintf( D_ALWAYS,"Collector %s blacklisted; skipping\n",
					 daemon->name() );
		} else {
			dprintf (D_FULLDEBUG,
					 "Trying to query collector %s\n",
					 daemon->addr());

			if( num_collectors > 1 ) {
				daemon->blacklistMonitorQueryStarted();
			}

			result = cQuery.fetchAds (adList, daemon->addr(), errstack);

			if( num_collectors > 1 ) {
				daemon->blacklistMonitorQueryFinished( result == Q_OK );
			}

			if (result == Q_OK) {
				return result;
			}
		}

		// if you got here remove it from the list of potential candidates.
		vCollectors.erase( vCollectors.begin()+idx );
	}

	// only push an error if the error stack exists and is currently empty
	if(problems_resolving && errstack && !errstack->code(0)) {
		char* tmplist = getCmHostFromConfig( "COLLECTOR" );
		errstack->pushf("CONDOR_STATUS",1,"Unable to resolve COLLECTOR_HOST (%s).",tmplist?tmplist:"(null)");
	}

		// If we've gotten here, there are no good collectors
	return Q_COMMUNICATION_ERROR;
}

bool
CollectorList::next( DCCollector* & d )
{
	return DaemonList::Next( (Daemon*&)d );
}

bool
CollectorList::Next( DCCollector* & d )
{
	return next( d );
}

bool
CollectorList::next( Daemon* & d )
{
	return DaemonList::Next( d );
}

bool
CollectorList::Next( Daemon* & d )
{
	return next( d );
}
<|endoftext|>


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

#include "src/cpp/thread_manager/thread_manager.h"

#include <climits>
#include <mutex>
#include <thread>

#include <grpc/support/log.h>

namespace grpc {

ThreadManager::WorkerThread::WorkerThread(ThreadManager* thd_mgr)
    : thd_mgr_(thd_mgr) {
  // Make thread creation exclusive with respect to its join happening in
  // ~WorkerThread().
  std::lock_guard<std::mutex> lock(wt_mu_);
  thd_ = std::thread(&ThreadManager::WorkerThread::Run, this);
}

void ThreadManager::WorkerThread::Run() {
  thd_mgr_->MainWorkLoop();
  thd_mgr_->MarkAsCompleted(this);
}

ThreadManager::WorkerThread::~WorkerThread() {
  // Don't join until the thread is fully constructed.
  std::lock_guard<std::mutex> lock(wt_mu_);
  thd_.join();
}

ThreadManager::ThreadManager(int min_pollers, int max_pollers)
    : shutdown_(false),
      num_pollers_(0),
      min_pollers_(min_pollers),
      max_pollers_(max_pollers == -1 ? INT_MAX : max_pollers),
      num_threads_(0) {}

ThreadManager::~ThreadManager() {
  {
    std::lock_guard<std::mutex> lock(mu_);
    GPR_ASSERT(num_threads_ == 0);
  }

  CleanupCompletedThreads();
}

void ThreadManager::Wait() {
  std::unique_lock<std::mutex> lock(mu_);
  while (num_threads_ != 0) {
    shutdown_cv_.wait(lock);
  }
}

void ThreadManager::Shutdown() {
  std::lock_guard<std::mutex> lock(mu_);
  shutdown_ = true;
}

bool ThreadManager::IsShutdown() {
  std::lock_guard<std::mutex> lock(mu_);
  return shutdown_;
}

void ThreadManager::MarkAsCompleted(WorkerThread* thd) {
  {
    std::lock_guard<std::mutex> list_lock(list_mu_);
    completed_threads_.push_back(thd);
  }

  std::lock_guard<std::mutex> lock(mu_);
  num_threads_--;
  if (num_threads_ == 0) {
    shutdown_cv_.notify_one();
  }
}

void ThreadManager::CleanupCompletedThreads() {
  std::list<WorkerThread*> completed_threads;
  {
    // swap out the completed threads list: allows other threads to clean up
    // more quickly
    std::unique_lock<std::mutex> lock(list_mu_);
    completed_threads.swap(completed_threads_);
  }
  for (auto thd : completed_threads) delete thd;
}

void ThreadManager::Initialize() {
  {
    std::unique_lock<std::mutex> lock(mu_);
    num_pollers_ = min_pollers_;
    num_threads_ = min_pollers_;
  }

  for (int i = 0; i < min_pollers_; i++) {
    // Create a new thread (which ends up calling the MainWorkLoop() function
    new WorkerThread(this);
  }
}

void ThreadManager::MainWorkLoop() {
  while (true) {
    void* tag;
    bool ok;
    WorkStatus work_status = PollForWork(&tag, &ok);

    std::unique_lock<std::mutex> lock(mu_);
    // Reduce the number of pollers by 1 and check what happened with the poll
    num_pollers_--;
    bool done = false;
    switch (work_status) {
      case TIMEOUT:
        // If we timed out and we have more pollers than we need (or we are
        // shutdown), finish this thread
        if (shutdown_ || num_pollers_ > max_pollers_) done = true;
        break;
      case SHUTDOWN:
        // If the thread manager is shutdown, finish this thread
        done = true;
        break;
      case WORK_FOUND:
        // If we got work and there are now insufficient pollers, start a new
        // one
        if (!shutdown_ && num_pollers_ < min_pollers_) {
          num_pollers_++;
          num_threads_++;
          // Drop lock before spawning thread to avoid contention
          lock.unlock();
          new WorkerThread(this);
        } else {
          // Drop lock for consistency with above branch
          lock.unlock();
        }
        // Lock is always released at this point - do the application work
        DoWork(tag, ok);
        // Take the lock again to check post conditions
        lock.lock();
        // If we're shutdown, we should finish at this point.
        if (shutdown_) done = true;
        break;
    }
    // If we decided to finish the thread, break out of the while loop
    if (done) break;
    // ... otherwise increase poller count and continue
    // There's a chance that we'll exceed the max poller count: that is
    // explicitly ok - we'll decrease after one poll timeout, and prevent
    // some thrashing starting up and shutting down threads
    num_pollers_++;
  };

  CleanupCompletedThreads();

  // If we are here, either ThreadManager is shutting down or it already has
  // enough threads.
}

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

#include "src/cpp/thread_manager/thread_manager.h"

#include <climits>
#include <mutex>
#include <thread>

#include <grpc/support/log.h>

namespace grpc {

ThreadManager::WorkerThread::WorkerThread(ThreadManager* thd_mgr)
    : thd_mgr_(thd_mgr) {
  // Make thread creation exclusive with respect to its join happening in
  // ~WorkerThread().
  std::lock_guard<std::mutex> lock(wt_mu_);
  thd_ = std::thread(&ThreadManager::WorkerThread::Run, this);
}

void ThreadManager::WorkerThread::Run() {
  thd_mgr_->MainWorkLoop();
  thd_mgr_->MarkAsCompleted(this);
}

ThreadManager::WorkerThread::~WorkerThread() {
  // Don't join until the thread is fully constructed.
  std::lock_guard<std::mutex> lock(wt_mu_);
  thd_.join();
}

ThreadManager::ThreadManager(int min_pollers, int max_pollers)
    : shutdown_(false),
      num_pollers_(0),
      min_pollers_(min_pollers),
      max_pollers_(max_pollers == -1 ? INT_MAX : max_pollers),
      num_threads_(0) {}

ThreadManager::~ThreadManager() {
  {
    std::lock_guard<std::mutex> lock(mu_);
    GPR_ASSERT(num_threads_ == 0);
  }

  CleanupCompletedThreads();
}

void ThreadManager::Wait() {
  std::unique_lock<std::mutex> lock(mu_);
  while (num_threads_ != 0) {
    shutdown_cv_.wait(lock);
  }
}

void ThreadManager::Shutdown() {
  std::lock_guard<std::mutex> lock(mu_);
  shutdown_ = true;
}

bool ThreadManager::IsShutdown() {
  std::lock_guard<std::mutex> lock(mu_);
  return shutdown_;
}

void ThreadManager::MarkAsCompleted(WorkerThread* thd) {
  {
    std::lock_guard<std::mutex> list_lock(list_mu_);
    completed_threads_.push_back(thd);
  }

  std::lock_guard<std::mutex> lock(mu_);
  num_threads_--;
  if (num_threads_ == 0) {
    shutdown_cv_.notify_one();
  }
}

void ThreadManager::CleanupCompletedThreads() {
  std::list<WorkerThread*> completed_threads;
  {
    // swap out the completed threads list: allows other threads to clean up
    // more quickly
    std::unique_lock<std::mutex> lock(list_mu_);
    completed_threads.swap(completed_threads_);
  }
  for (auto thd : completed_threads) delete thd;
}

void ThreadManager::Initialize() {
  {
    std::unique_lock<std::mutex> lock(mu_);
    num_pollers_ = min_pollers_;
    num_threads_ = min_pollers_;
  }

  for (int i = 0; i < min_pollers_; i++) {
    // Create a new thread (which ends up calling the MainWorkLoop() function
    new WorkerThread(this);
  }
}

void ThreadManager::MainWorkLoop() {
  while (true) {
    void* tag;
    bool ok;
    WorkStatus work_status = PollForWork(&tag, &ok);

    std::unique_lock<std::mutex> lock(mu_);
    // Reduce the number of pollers by 1 and check what happened with the poll
    num_pollers_--;
    bool done = false;
    switch (work_status) {
      case TIMEOUT:
        // If we timed out and we have more pollers than we need (or we are
        // shutdown), finish this thread
        if (shutdown_ || num_pollers_ > max_pollers_) done = true;
        break;
      case SHUTDOWN:
        // If the thread manager is shutdown, finish this thread
        done = true;
        break;
      case WORK_FOUND:
        // If we got work and there are now insufficient pollers, start a new
        // one
        if (!shutdown_ && num_pollers_ < min_pollers_) {
          num_pollers_++;
          num_threads_++;
          // Drop lock before spawning thread to avoid contention
          lock.unlock();
          new WorkerThread(this);
        } else {
          // Drop lock for consistency with above branch
          lock.unlock();
        }
        // Lock is always released at this point - do the application work
        DoWork(tag, ok);
        // Take the lock again to check post conditions
        lock.lock();
        // If we're shutdown, we should finish at this point.
        if (shutdown_) done = true;
        break;
    }
    // If we decided to finish the thread, break out of the while loop
    if (done) break;

    // Otherwise go back to polling as long as it doesn't exceed max_pollers_
    //
    // **WARNING**:
    // There is a possibility of threads thrashing here (i.e excessive thread
    // shutdowns and creations than the ideal case). This happens if max_poller_
    // count is small and the rate of incoming requests is also small. In such
    // scenarios we can possibly configure max_pollers_ to a higher value and/or
    // increase the cq timeout.
    //
    // However, not doing this check here and unconditionally incrementing
    // num_pollers (and hoping that the system will eventually settle down) has
    // far worse consequences i.e huge number of threads getting created to the
    // point of thread-exhaustion. For example: if the incoming request rate is
    // very high, all the polling threads will return very quickly from
    // PollForWork() with WORK_FOUND. They all briefly decrement num_pollers_
    // counter thereby possibly - and briefly - making it go below min_pollers;
    // This will most likely result in the creation of a new poller since
    // num_pollers_ dipped below min_pollers_.
    //
    // Now, If we didn't do the max_poller_ check here, all these threads will
    // go back to doing PollForWork() and the whole cycle repeats (with a new
    // thread being added in each cycle). Once the total number of threads in
    // the system crosses a certain threshold (around ~1500), there is heavy
    // contention on mutexes (the mu_ here or the mutexes in gRPC core like the
    // pollset mutex) that makes DoWork() take longer to finish thereby causing
    // new poller threads to be created even faster. This results in a thread
    // avalanche.
    if (num_pollers_ < max_pollers_) {
      num_pollers_++;
    } else {
      break;
    }
  };

  CleanupCompletedThreads();

  // If we are here, either ThreadManager is shutting down or it already has
  // enough threads.
}

}  // namespace grpc
<|endoftext|>


<commit_before>
#include <iostream>
#include <unordered_map>
#include <boost/algorithm/string.hpp>
#include <vector>
#include <Galois/Galois.h>
#include <Galois/Graph/Graph.h>

#include <cstring>
#include <string>
#include <fstream>
using namespace std;
using namespace boost;
#define MAX_NODES 10000

typedef enum{pi,po,nd} node_type;

struct Node {
 string label_type;//a0,b0...
 node_type type;// pi,po,nd
 int fanins;
 bool fanout;
 int level;
 };

int main() {

	unordered_map <string, int> map;
	//unordered_map<string, int> map;
	int node_index = 0;

	typedef Galois::Graph::FirstGraph<Node,int,true> Graph;

	Graph g;
	Node nodes[MAX_NODES];
	Graph::GraphNode gnodes[MAX_NODES];

	vector<string> fields;

	ifstream fin;
	fin.open("/home/aditya/CS_220/alan-abc/examples/sk"); // open a file
	if (!fin.good()){
		cout << "file not found\n";
	    return 1; // exit if file not found
	}
	  // read each line of the file
	  while (!fin.eof())
	  {
	    // read an entire line into memory
	    string line;
	    getline(fin,line);
	    trim(line);
	    split(fields, line, is_any_of(" "));

	    if(fields[0].compare("input") == 0 || fields[0].compare("output") == 0||fields[0].compare("wire") == 0)
	    {
	    	for(unsigned i =1;i<fields.size();i++){
	    		//add to hash map to index to corresponding node in array
	    		if(fields[i].size()>1)
	    		{
				//Add data to each node for level and type of input
 				if(fields[0].compare("input") == 0)
				{
					nodes[node_index].type = pi;
					nodes[node_index].level = 0;
					nodes[node_index].label_type = fields[i].substr(0,fields[i].length()-1);
				}
				if(fields[0].compare("output") == 0)
				{
					nodes[node_index].type = po;
					nodes[node_index].label_type = fields[i].substr(0,fields[i].length()-1);
				}
				if(fields[0].compare("wire") == 0)
				{
					nodes[node_index].type = nd;
					nodes[node_index].label_type = fields[i].substr(0,fields[i].length()-1);
				}
	    			//remove last char b/c its ',' or ';'
	    			map[fields[i].substr(0,fields[i].length()-1)] = node_index;
	    			gnodes[node_index] = g.createNode(nodes[node_index]);

	    			node_index++;
	    		}

	    	}
	    }
	    if(fields[0].compare("assign") == 0)
	    {
	    	size_t invert = fields[3].find_first_of("~");
		if(fields[4].compare("|") == 0)
		{
			g.getEdgeData(g.addEdge(gnodes[map[fields[3].substr(1,fields[3].length())]],gnodes[map[fields[1]]])) = 2;//Edge weight: 2- Negative 1 - Positive
			g.getEdgeData(g.addEdge(gnodes[map[fields[5].substr(1,fields[3].length()-1)]],gnodes[map[fields[1]]])) = 2;
			nodes[map[fields[1]]].fanout = 0;// TO DO: Negated output: Try using getData()
		}

		else{
	    	if (invert != string::npos){
	    		//addEdge(src,dest)
	    		//remove the '~' from the start of string
	    		//map[string] returns node index to find which node
	    		g.getEdgeData(g.addEdge(gnodes[map[fields[3].substr(1,fields[3].length())]],gnodes[map[fields[1]]])) = 2;//
	    		//TODO add edge weights
	    	}
		else
			g.getEdgeData(g.addEdge(gnodes[map[fields[3].substr(1,fields[3].length())]],gnodes[map[fields[1]]])) = 1;

	    	invert = fields[5].find_first_of("~");
	    	if (invert != string::npos){
	    		//remove first and last char b/c '~' to start and ';' at th
	    		g.getEdgeData(g.addEdge(gnodes[map[fields[5].substr(1,fields[3].length()-1)]],gnodes[map[fields[1]]])) = 2;
	    	}
		else
			g.getEdgeData(g.addEdge(gnodes[map[fields[5].substr(1,fields[3].length()-1)]],gnodes[map[fields[1]]])) = 1;
		}

	    }

	  }

	cout << g.getData(gnodes[0]).label_type << endl;
	// Traverse graph
 	for (Graph::iterator ii = g.begin(), ei = g.end(); ii != ei; ++ii) {
   		Graph::GraphNode src = *ii;
		cout << g.getData(src).label_type << endl;
	   	//for (Graph::edge_iterator jj = g.edge_begin(src), ej = g.edge_end(src); ++jj) {
     		//Graph::GraphNode dst = graph.getEdgeDst(jj);
     		//int edgeData = g.getEdgeData(jj);
     		//assert(edgeData == 5);
   		//}
 	}
/*
	for (Graph::GraphNode src : g) {
   	for (Graph::edge_iterator edge : g.out_edges(src)) {
     		Graph::GraphNode dst = g.getEdgeDst(edge);
     		int edgeData = g.getEdgeData(edge);
     		cout << (g.getData(src)).label_type << "\n";
   		}
 	}
*/

/*
	  for(unsigned i = 0; i<map.bucket_count();i++){
		  std::cout << "bucket #" << i << " contains:";
		      for ( auto local_it = map.begin(i); local_it!= map.end(i); ++local_it )
		        std::cout << " " << local_it->first << ":" << local_it->second;
		      std::cout << std::endl;
	  }
	  */
	  //cout << map["n12,"]<<"\n"<<map["n11,"];

	return 0;
}
<commit_msg>Label printing corrected in galoisparse<commit_after>
#include <iostream>
#include <unordered_map>
#include <boost/algorithm/string.hpp>
#include <vector>
#include <Galois/Galois.h>
#include <Galois/Graph/Graph.h>

#include <cstring>
#include <string>
#include <fstream>
using namespace std;
using namespace boost;
#define MAX_NODES 10000

typedef enum{pi,po,nd} node_type;

struct Node {
 string label_type;//a0,b0...
 node_type type;// pi,po,nd
 int fanins;
 bool fanout;
 int level;
 };

int main() {

	unordered_map <string, int> map;
	//unordered_map<string, int> map;
	int node_index = 0;

	typedef Galois::Graph::FirstGraph<Node,int,true> Graph;

	Graph g;
	Node nodes[MAX_NODES];
	Graph::GraphNode gnodes[MAX_NODES];

	vector<string> fields;

	ifstream fin;
	fin.open("/home/aditya/CS_220/alan-abc/examples/sk"); // open a file
	if (!fin.good()){
		cout << "file not found\n";
	    return 1; // exit if file not found
	}
	  // read each line of the file
	  while (!fin.eof())
	  {
	    // read an entire line into memory
	    string line;
	    getline(fin,line);
	    trim(line);
	    split(fields, line, is_any_of(" "));

	    if(fields[0].compare("input") == 0 || fields[0].compare("output") == 0||fields[0].compare("wire") == 0)
	    {
	    	for(unsigned i =1;i<fields.size();i++){
	    		//add to hash map to index to corresponding node in array
	    		if(fields[i].size()>1)
	    		{
				//Add data to each node for level and type of input
 				if(fields[0].compare("input") == 0)
				{
					nodes[node_index].type = pi;
					nodes[node_index].level = 0;
					nodes[node_index].label_type = fields[i].substr(0,fields[i].length()-1);
				}
				if(fields[0].compare("output") == 0)
				{
					nodes[node_index].type = po;
					nodes[node_index].label_type = fields[i].substr(0,fields[i].length()-1);
				}
				if(fields[0].compare("wire") == 0)
				{
					nodes[node_index].type = nd;
					nodes[node_index].label_type = fields[i].substr(0,fields[i].length()-1);
				}
	    			//remove last char b/c its ',' or ';'
	    			map[fields[i].substr(0,fields[i].length()-1)] = node_index;
	    			gnodes[node_index] = g.createNode(nodes[node_index]);
				g.addNode(gnodes[node_index]);

	    			node_index++;
	    		}

	    	}
	    }
	    if(fields[0].compare("assign") == 0)
	    {
	    	size_t invert = fields[3].find_first_of("~");
		if(fields[4].compare("|") == 0)
		{
			g.getEdgeData(g.addEdge(gnodes[map[fields[3].substr(1,fields[3].length())]],gnodes[map[fields[1]]])) = 2;//Edge weight: 2- Negative 1 - Positive
			g.getEdgeData(g.addEdge(gnodes[map[fields[5].substr(1,fields[3].length()-1)]],gnodes[map[fields[1]]])) = 2;
			nodes[map[fields[1]]].fanout = 0;// TO DO: Negated output: Try using getData()
		}

		else{
	    	if (invert != string::npos){
	    		//addEdge(src,dest)
	    		//remove the '~' from the start of string
	    		//map[string] returns node index to find which node
	    		g.getEdgeData(g.addEdge(gnodes[map[fields[3].substr(1,fields[3].length())]],gnodes[map[fields[1]]])) = 2;//
	    		//TODO add edge weights
	    	}
		else
			g.getEdgeData(g.addEdge(gnodes[map[fields[3].substr(1,fields[3].length())]],gnodes[map[fields[1]]])) = 1;

	    	invert = fields[5].find_first_of("~");
	    	if (invert != string::npos){
	    		//remove first and last char b/c '~' to start and ';' at th
	    		g.getEdgeData(g.addEdge(gnodes[map[fields[5].substr(1,fields[3].length()-1)]],gnodes[map[fields[1]]])) = 2;
	    	}
		else
			g.getEdgeData(g.addEdge(gnodes[map[fields[5].substr(1,fields[3].length()-1)]],gnodes[map[fields[1]]])) = 1;
		}

	    }

	  }

	//cout << g.getData(gnodes[0]).label_type << endl;
	// Traverse graph
 	for (Graph::iterator ii = g.begin(), ei = g.end(); ii != ei; ++ii) {
   		Graph::GraphNode src = *ii;
		cout << g.getData(src).label_type << endl;
	   	//for (Graph::edge_iterator jj = g.edge_begin(src), ej = g.edge_end(src); ++jj) {
     		//Graph::GraphNode dst = graph.getEdgeDst(jj);
     		//int edgeData = g.getEdgeData(jj);
     		//assert(edgeData == 5);
   		//}
 	}
/*
	for (Graph::GraphNode src : g) {
   	for (Graph::edge_iterator edge : g.out_edges(src)) {
     		Graph::GraphNode dst = g.getEdgeDst(edge);
     		int edgeData = g.getEdgeData(edge);
     		cout << (g.getData(src)).label_type << "\n";
   		}
 	}
*/

/*
	  for(unsigned i = 0; i<map.bucket_count();i++){
		  std::cout << "bucket #" << i << " contains:";
		      for ( auto local_it = map.begin(i); local_it!= map.end(i); ++local_it )
		        std::cout << " " << local_it->first << ":" << local_it->second;
		      std::cout << std::endl;
	  }
	  */
	  //cout << map["n12,"]<<"\n"<<map["n11,"];

	return 0;
}
<|endoftext|>


<commit_before>
#include <iostream>
#include <unordered_map>
#include <boost/algorithm/string.hpp>
#include <vector>
#include <Galois/Galois.h>
#include <Galois/Graph/Graph.h>

//#include <cstring>
#include <string>
#include <fstream>
using namespace std;
using namespace boost;

typedef enum{pi,po,nd} node_type;

struct Node {
 string label_type;//a0,b0...
 node_type type;// pi,po,nd
 int fanins; // Not required as of now
 bool fanout; //Not required as of now
 int level;
 };

typedef Galois::Graph::FirstGraph<Node,int,true> Graph;

Graph g;

int node_index = 0;
vector<Graph::GraphNode> gnodes;

vector<string> fields;

bool checkWorkability(Graph::GraphNode gnode){
	int count = 0;
	for (Graph::edge_iterator edge : g.out_edges(gnode)) {
		int edgedata = g.getEdgeData(edge);
	   	if(edgedata == 1|| edgedata ==2)
	   		count++;
	   	}
	if (count > 1)
		return false;
	else
		return true;
}

void parseFileintoGraph(string inFile, unordered_map <string, int> &map){
	ifstream fin;
	fin.open(inFile); // open a file
	if (!fin.good()){
		cout << "file not found\n";

	}
	else
	// read each line of the file
	while (!fin.eof())
	{
	// read an entire line into memory
	string line;
	getline(fin,line);
	trim(line);
	split(fields, line, is_any_of(" "));
	Node n;
	if(fields[0].compare("input") == 0 || fields[0].compare("output") == 0||fields[0].compare("wire") == 0)
	{
		for(unsigned i =1;i<fields.size();i++){
			//add to hash map to index to corresponding node in array
			if(fields[i].size()>1)
			{
				//Add data to each node for level and type of input
				if(fields[0].compare("input") == 0)
				{
					n.type = pi;
					n.level = 0;
					n.label_type = fields[i].substr(0,fields[i].length()-1);

					//nodes[node_index].type = pi;
					//nodes[node_index].level = 0;
					//nodes[node_index].label_type = fields[i].substr(0,fields[i].length()-1);
				}
				if(fields[0].compare("output") == 0)
				{
					n.type = po;
					n.level = -1;
					n.label_type = fields[i].substr(0,fields[i].length()-1);
					//nodes[node_index].type = po;
					//nodes[node_index].label_type = fields[i].substr(0,fields[i].length()-1);
				}
				if(fields[0].compare("wire") == 0)
				{
					n.type = nd;
					n.level = -2;
					n.label_type = fields[i].substr(0,fields[i].length()-1);
					//nodes[node_index].type = nd;
					//nodes[node_index].label_type = fields[i].substr(0,fields[i].length()-1);
				}
				//remove last char b/c its ',' or ';'
				map[fields[i].substr(0,fields[i].length()-1)] = node_index;
				//gnodes[node_index] = g.createNode(nodes[node_index]);
				gnodes.push_back(g.createNode(n));

				g.addNode(gnodes[gnodes.size()-1]);
				//cout << "node index: "<< node_index<<endl;
				node_index++;
			}

		}
	}
	//cout <<"compare assign"<<endl;
	if(fields[0].compare("assign") == 0)
	{
		int level1,level2;
		string f1,f3,f5;
		f1 = fields[1];
		f3 = fields[3];
		f5 = fields[5];
		if(fields[4].compare("|") == 0)
		{	//Edge weight: 2- Negative 1 - Positive
			f3 = f3.substr(0,f3.length());
			f5 = f5.substr(0,f5.length()-1);
			g.getEdgeData(g.addEdge(gnodes[map[f3]]//src
										   ,gnodes[map[f1]])) = 2;//dest

			g.getEdgeData(g.addEdge(gnodes[map[f5]]
										   ,gnodes[map[f1]])) = 2;

			level1 = g.getData(gnodes[map[f3]]).level;
			level2 = g.getData(gnodes[map[f5]]).level;
			g.getEdgeData(g.addEdge(gnodes[map[f1]],
					  gnodes[map[f3]])) = 3;//back edges to determine fanins -> wt. = 3
			g.getEdgeData(g.addEdge(gnodes[map[f1]],
					  gnodes[map[f5]])) = 3;//back edges to determins fanins -> wt. = 3
		}

		else
		{	size_t invert = fields[3].find_first_of("~");
			if (invert != string::npos){
				f3 = f3.substr(1,f3.length());
				//addEdge(src,dest)
				//remove the '~' from the start of string
				//map[string] returns node index to find which node
				g.getEdgeData(g.addEdge(gnodes[map[f3]],gnodes[map[f1]])) = 2;//
				level1 = g.getData(gnodes[map[f3]]).level;
				g.getEdgeData(g.addEdge(gnodes[map[f1]],
							  gnodes[map[f3]])) = 3;// Back edges to determine fanins -> wt. = 3
			}
			else{
				g.getEdgeData(g.addEdge(gnodes[map[f3]],gnodes[map[f1]])) = 1;
				level1 = g.getData(gnodes[map[f3]]).level;
				g.getEdgeData(g.addEdge(gnodes[map[f1]],
						  gnodes[map[f3]])) = 3;// Back edges to determine fanins -> wt. = 3

			}
			invert = fields[5].find_first_of("~");
			if (invert != string::npos){
				f5 = f5.substr(1,f5.length()-2);
				//remove first and last char b/c '~' to start and ';' at th
				//cout <<fields[5] << " substr"<<fields[5].substr(1,fields[5].length()-1)<<" "<<map[fields[5].substr(1,fields[5].length()-1)]<< " "<< nodes[map[fields[5].substr(1,fields[5].length()-1)]].label_type <<endl;
				g.getEdgeData(g.addEdge(gnodes[map[f5]],gnodes[map[f1]])) = 2;
				level2 = g.getData(gnodes[map[f5]]).level;
				g.getEdgeData(g.addEdge(gnodes[map[f1]],
						  gnodes[map[f5]])) = 3;// Back edges to determine fanins -> wt. = 3
			}
			else{
				f5 = f5.substr(0,f5.length()-1);
				g.getEdgeData(g.addEdge(gnodes[map[f5]],gnodes[map[f1]])) = 1;
				level2 = g.getData(gnodes[map[f5]]).level;
				g.getEdgeData(g.addEdge(gnodes[map[f1]],
						  gnodes[map[f5]])) = 3;// Back edges to determine fanins -> wt. = 3
			}
		}

	if(level1>=level2)
		g.getData(gnodes[map[fields[1]]]).level= level1+1;
	else
		g.getData(gnodes[map[fields[1]]]).level= level2+1;
	}

	}
}

int main(int argc, char *argv[]) {
	unordered_map <string, int> map;
	if ( argc != 2 )
    		cout<<"usage: "<< argv[0] <<" <filename>\n";
  	else
  			parseFileintoGraph(argv[1],map);

	//cout << g.getData(gnodes[0]).label_type << endl;
	// Traverse graph
 	//for (Graph::iterator ii = g.begin(), ei = g.end(); ii != ei; ++ii) {
	for ( Graph::GraphNode src : g){
   		//Graph::GraphNode src = *ii;
		cout <<"src: "<< g.getData(src).label_type;
		cout <<" level: "<<g.getData(src).level;

		for (Graph::edge_iterator edge : g.out_edges(src)) {
   			Graph::GraphNode dst = g.getEdgeDst(edge);
     		cout <<" dest: "<< g.getData(dst).label_type;
     		int edgeData = g.getEdgeData(edge);
     		cout << " edge data " << edgeData;
     		//assert(edgeData == 5);
   		}
	   	cout <<endl;
 	}
 	if(checkWorkability(gnodes[map["n15"]]))
 		cout << "1 output"<<endl;
 	else
 		cout <<"more than 1 output"<<endl;

	return 0;
}
<commit_msg>Added function:find_cut - returns the child nodes which are part of the cut TO DO: Use check_workability<commit_after>
#include <iostream>
#include <unordered_map>
#include <boost/algorithm/string.hpp>
#include <vector>
#include <Galois/Galois.h>
#include <Galois/Graph/Graph.h>

//#include <cstring>
#include <string>
#include <fstream>
using namespace std;
using namespace boost;

typedef enum{pi,po,nd} node_type;

struct Node {
 string label_type;//a0,b0...
 node_type type;// pi,po,nd
 int fanins; // Not required as of now
 bool fanout; //Not required as of now
 int level;
 };

typedef Galois::Graph::FirstGraph<Node,int,true> Graph;

Graph g;

int node_index = 0;
vector<Graph::GraphNode> gnodes;

vector<string> fields;

bool checkWorkability(Graph::GraphNode gnode){
	int count = 0;
	for (Graph::edge_iterator edge : g.out_edges(gnode)) {
		int edgedata = g.getEdgeData(edge);
	   	if(edgedata == 1|| edgedata ==2)
	   		count++;
	   	}
	if (count > 1)
		return false;
	else
		return true;
}

bool find_cut(Graph::GraphNode &top,Graph::GraphNode &child_left,Graph::GraphNode &child_right)
{
	if ( g.getData(top).level != 0 && g.getData(top).level != 1) {
		for (Graph::edge_iterator edge : g.out_edges(top)){
			Graph::GraphNode dst = g.getEdgeDst(edge);
			if(g.getEdgeData(edge) == 3){
				if(child_left==NULL){
					child_left=dst;
				}
				else{
					child_right=dst;
				}
			}
		}
		return true;
	}
	else
		return false;
}

void parseFileintoGraph(string inFile, unordered_map <string, int> &map){
	ifstream fin;
	fin.open(inFile); // open a file
	if (!fin.good()){
		cout << "file not found\n";

	}
	else
	// read each line of the file
	while (!fin.eof())
	{
	// read an entire line into memory
	string line;
	getline(fin,line);
	trim(line);
	split(fields, line, is_any_of(" "));
	Node n;
	if(fields[0].compare("input") == 0 || fields[0].compare("output") == 0||fields[0].compare("wire") == 0)
	{
		for(unsigned i =1;i<fields.size();i++){
			//add to hash map to index to corresponding node in array
			if(fields[i].size()>1)
			{
				//Add data to each node for level and type of input
				if(fields[0].compare("input") == 0)
				{
					n.type = pi;
					n.level = 0;
					n.label_type = fields[i].substr(0,fields[i].length()-1);

					//nodes[node_index].type = pi;
					//nodes[node_index].level = 0;
					//nodes[node_index].label_type = fields[i].substr(0,fields[i].length()-1);
				}
				if(fields[0].compare("output") == 0)
				{
					n.type = po;
					n.level = -1;
					n.label_type = fields[i].substr(0,fields[i].length()-1);
					//nodes[node_index].type = po;
					//nodes[node_index].label_type = fields[i].substr(0,fields[i].length()-1);
				}
				if(fields[0].compare("wire") == 0)
				{
					n.type = nd;
					n.level = -2;
					n.label_type = fields[i].substr(0,fields[i].length()-1);
					//nodes[node_index].type = nd;
					//nodes[node_index].label_type = fields[i].substr(0,fields[i].length()-1);
				}
				//remove last char b/c its ',' or ';'
				map[fields[i].substr(0,fields[i].length()-1)] = node_index;
				//gnodes[node_index] = g.createNode(nodes[node_index]);
				gnodes.push_back(g.createNode(n));

				g.addNode(gnodes[gnodes.size()-1]);
				//cout << "node index: "<< node_index<<endl;
				node_index++;
			}

		}
	}
	//cout <<"compare assign"<<endl;
	if(fields[0].compare("assign") == 0)
	{
		int level1,level2;
		string f1,f3,f5;
		f1 = fields[1];
		f3 = fields[3];
		f5 = fields[5];
		if(fields[4].compare("|") == 0)
		{	//Edge weight: 2- Negative 1 - Positive
			f3 = f3.substr(0,f3.length());
			f5 = f5.substr(0,f5.length()-1);
			g.getEdgeData(g.addEdge(gnodes[map[f3]]//src
										   ,gnodes[map[f1]])) = 2;//dest

			g.getEdgeData(g.addEdge(gnodes[map[f5]]
										   ,gnodes[map[f1]])) = 2;

			level1 = g.getData(gnodes[map[f3]]).level;
			level2 = g.getData(gnodes[map[f5]]).level;
			g.getEdgeData(g.addEdge(gnodes[map[f1]],
					  gnodes[map[f3]])) = 3;//back edges to determine fanins -> wt. = 3
			g.getEdgeData(g.addEdge(gnodes[map[f1]],
					  gnodes[map[f5]])) = 3;//back edges to determins fanins -> wt. = 3
		}

		else
		{	size_t invert = fields[3].find_first_of("~");
			if (invert != string::npos){
				f3 = f3.substr(1,f3.length());
				//addEdge(src,dest)
				//remove the '~' from the start of string
				//map[string] returns node index to find which node
				g.getEdgeData(g.addEdge(gnodes[map[f3]],gnodes[map[f1]])) = 2;//
				level1 = g.getData(gnodes[map[f3]]).level;
				g.getEdgeData(g.addEdge(gnodes[map[f1]],
							  gnodes[map[f3]])) = 3;// Back edges to determine fanins -> wt. = 3
			}
			else{
				g.getEdgeData(g.addEdge(gnodes[map[f3]],gnodes[map[f1]])) = 1;
				level1 = g.getData(gnodes[map[f3]]).level;
				g.getEdgeData(g.addEdge(gnodes[map[f1]],
						  gnodes[map[f3]])) = 3;// Back edges to determine fanins -> wt. = 3

			}
			invert = fields[5].find_first_of("~");
			if (invert != string::npos){
				f5 = f5.substr(1,f5.length()-2);
				//remove first and last char b/c '~' to start and ';' at th
				//cout <<fields[5] << " substr"<<fields[5].substr(1,fields[5].length()-1)<<" "<<map[fields[5].substr(1,fields[5].length()-1)]<< " "<< nodes[map[fields[5].substr(1,fields[5].length()-1)]].label_type <<endl;
				g.getEdgeData(g.addEdge(gnodes[map[f5]],gnodes[map[f1]])) = 2;
				level2 = g.getData(gnodes[map[f5]]).level;
				g.getEdgeData(g.addEdge(gnodes[map[f1]],
						  gnodes[map[f5]])) = 3;// Back edges to determine fanins -> wt. = 3
			}
			else{
				f5 = f5.substr(0,f5.length()-1);
				g.getEdgeData(g.addEdge(gnodes[map[f5]],gnodes[map[f1]])) = 1;
				level2 = g.getData(gnodes[map[f5]]).level;
				g.getEdgeData(g.addEdge(gnodes[map[f1]],
						  gnodes[map[f5]])) = 3;// Back edges to determine fanins -> wt. = 3
			}
		}

	if(level1>=level2)
		g.getData(gnodes[map[fields[1]]]).level= level1+1;
	else
		g.getData(gnodes[map[fields[1]]]).level= level2+1;
	}

	}
}

int main(int argc, char *argv[]) {
	unordered_map <string, int> map;
	if ( argc != 2 )
    		cout<<"usage: "<< argv[0] <<" <filename>\n";
  	else
  			parseFileintoGraph(argv[1],map);

	//cout << g.getData(gnodes[0]).label_type << endl;
	// Traverse graph
 	//for (Graph::iterator ii = g.begin(), ei = g.end(); ii != ei; ++ii) {
	for ( Graph::GraphNode src : g){
   		//Graph::GraphNode src = *ii;
		cout <<"src: "<< g.getData(src).label_type;
		cout <<" level: "<<g.getData(src).level;

		for (Graph::edge_iterator edge : g.out_edges(src)) {
   			Graph::GraphNode dst = g.getEdgeDst(edge);
     		cout <<" dest: "<< g.getData(dst).label_type;
     		int edgeData = g.getEdgeData(edge);
     		cout << " edge data " << edgeData;
     		//assert(edgeData == 5);
   		}
	   	cout <<endl;
 	}
 	if(checkWorkability(gnodes[map["n15"]]))
 		cout << "1 output"<<endl;
 	else
 		cout <<"more than 1 output"<<endl;

	bool out;
	Graph::GraphNode child_left=NULL,child_right=NULL;
	if(find_cut(gnodes[map["s0"]],child_left,child_right)){
		cout<<"Src node:"<<g.getData(gnodes[map["s0"]]).label_type << endl;
		cout<<"Child node 1:"<<g.getData(child_left).label_type << endl;
		cout<<"Child node 2:"<<g.getData(child_right).label_type << endl;
	}

	return 0;
}
<|endoftext|>


<commit_before>#include "../../../../../platform/http_thread_callback.hpp"

#include "../core/jni_helper.hpp"

#include "../maps/DownloadUI.hpp"

#include "Platform.hpp"

class HttpThread
{
private:
  jobject m_self;

public:
  HttpThread(string const & url,
             downloader::IHttpThreadCallback & cb,
             int64_t beg,
             int64_t end,
             int64_t expectedFileSize,
             string const & pb)
  {
    /// should create java object here.
    JNIEnv * env = jni::GetEnv();

    jclass klass = env->FindClass("com/mapswithme/maps/downloader/DownloadChunkTask");
    ASSERT(klass, ("Can't find java class com/mapswithme/maps/downloader/DownloadChunkTask"));

    jmethodID methodId = env->GetMethodID(klass, "<init>", "(JLjava/lang/String;JJJLjava/lang/String;Ljava/lang/String;)V");
    ASSERT(methodId, ("Can't find java constructor in com/mapswithme/maps/downloader/DownloadChunkTask"));

    // User id is always the same, so do not waste time on every chunk call
    static string uniqueUserId = GetPlatform().UniqueClientId();

    m_self = env->NewGlobalRef(env->NewObject(klass, methodId, reinterpret_cast<jlong>(&cb),
        env->NewStringUTF(url.c_str()), beg, end, expectedFileSize, env->NewStringUTF(pb.c_str()),
        env->NewStringUTF(uniqueUserId.c_str())));

    methodId = env->GetMethodID(klass, "start", "()V");
    ASSERT(methodId, ("Can't find java method 'start' in com/mapswithme/maps/downloader/DownloadChunkTask"));

    env->CallVoidMethod(m_self, methodId);
  }

  ~HttpThread()
  {
    JNIEnv * env = jni::GetEnv();
    jmethodID methodId = jni::GetJavaMethodID(env, m_self, "cancel", "(Z)Z");
    ASSERT(methodId, ("Can't find java method 'cancel' in com/mapswithme/maps/downloader/DownloadChunkTask"));

    env->CallBooleanMethod(m_self, methodId, false);
    env->DeleteGlobalRef(m_self);
  }
};

namespace downloader
{
  HttpThread * CreateNativeHttpThread(string const & url,
                                      downloader::IHttpThreadCallback & cb,
                                      int64_t beg,
                                      int64_t end,
                                      int64_t size,
                                      string const & pb)
  {
    return new HttpThread(url, cb, beg, end, size, pb);
  }

  void DeleteNativeHttpThread(HttpThread * request)
  {
    delete request;
  }

} // namespace downloader

extern "C"
{
  JNIEXPORT void JNICALL
  Java_com_mapswithme_maps_downloader_DownloadChunkTask_onWrite(JNIEnv * env, jobject thiz,
      jlong httpCallbackID, jlong beg, jbyteArray data, jlong size)
  {
    downloader::IHttpThreadCallback * cb = reinterpret_cast<downloader::IHttpThreadCallback*>(httpCallbackID);
    jbyte * buf = env->GetByteArrayElements(data, 0);
    cb->OnWrite(beg, buf, size);
    env->ReleaseByteArrayElements(data, buf, 0);
  }

  JNIEXPORT void JNICALL
  Java_com_mapswithme_maps_downloader_DownloadChunkTask_onFinish(JNIEnv * env, jobject thiz,
      jlong httpCallbackID, jlong httpCode, jlong beg, jlong end)
  {
    downloader::IHttpThreadCallback * cb = reinterpret_cast<downloader::IHttpThreadCallback*>(httpCallbackID);
    cb->OnFinish(httpCode, beg, end);
  }
}
<commit_msg>fixed compilation error.<commit_after>#include "../../../../../platform/http_thread_callback.hpp"

#include "../core/jni_helper.hpp"

#include "Platform.hpp"

class HttpThread
{
private:
  jobject m_self;

public:
  HttpThread(string const & url,
             downloader::IHttpThreadCallback & cb,
             int64_t beg,
             int64_t end,
             int64_t expectedFileSize,
             string const & pb)
  {
    /// should create java object here.
    JNIEnv * env = jni::GetEnv();

    jclass klass = env->FindClass("com/mapswithme/maps/downloader/DownloadChunkTask");
    ASSERT(klass, ("Can't find java class com/mapswithme/maps/downloader/DownloadChunkTask"));

    jmethodID methodId = env->GetMethodID(klass, "<init>", "(JLjava/lang/String;JJJLjava/lang/String;Ljava/lang/String;)V");
    ASSERT(methodId, ("Can't find java constructor in com/mapswithme/maps/downloader/DownloadChunkTask"));

    // User id is always the same, so do not waste time on every chunk call
    static string uniqueUserId = GetPlatform().UniqueClientId();

    m_self = env->NewGlobalRef(env->NewObject(klass, methodId, reinterpret_cast<jlong>(&cb),
        env->NewStringUTF(url.c_str()), beg, end, expectedFileSize, env->NewStringUTF(pb.c_str()),
        env->NewStringUTF(uniqueUserId.c_str())));

    methodId = env->GetMethodID(klass, "start", "()V");
    ASSERT(methodId, ("Can't find java method 'start' in com/mapswithme/maps/downloader/DownloadChunkTask"));

    env->CallVoidMethod(m_self, methodId);
  }

  ~HttpThread()
  {
    JNIEnv * env = jni::GetEnv();
    jmethodID methodId = jni::GetJavaMethodID(env, m_self, "cancel", "(Z)Z");
    ASSERT(methodId, ("Can't find java method 'cancel' in com/mapswithme/maps/downloader/DownloadChunkTask"));

    env->CallBooleanMethod(m_self, methodId, false);
    env->DeleteGlobalRef(m_self);
  }
};

namespace downloader
{
  HttpThread * CreateNativeHttpThread(string const & url,
                                      downloader::IHttpThreadCallback & cb,
                                      int64_t beg,
                                      int64_t end,
                                      int64_t size,
                                      string const & pb)
  {
    return new HttpThread(url, cb, beg, end, size, pb);
  }

  void DeleteNativeHttpThread(HttpThread * request)
  {
    delete request;
  }

} // namespace downloader

extern "C"
{
  JNIEXPORT void JNICALL
  Java_com_mapswithme_maps_downloader_DownloadChunkTask_onWrite(JNIEnv * env, jobject thiz,
      jlong httpCallbackID, jlong beg, jbyteArray data, jlong size)
  {
    downloader::IHttpThreadCallback * cb = reinterpret_cast<downloader::IHttpThreadCallback*>(httpCallbackID);
    jbyte * buf = env->GetByteArrayElements(data, 0);
    cb->OnWrite(beg, buf, size);
    env->ReleaseByteArrayElements(data, buf, 0);
  }

  JNIEXPORT void JNICALL
  Java_com_mapswithme_maps_downloader_DownloadChunkTask_onFinish(JNIEnv * env, jobject thiz,
      jlong httpCallbackID, jlong httpCode, jlong beg, jlong end)
  {
    downloader::IHttpThreadCallback * cb = reinterpret_cast<downloader::IHttpThreadCallback*>(httpCallbackID);
    cb->OnFinish(httpCode, beg, end);
  }
}
<|endoftext|>


<commit_before>/*****************************************************************************/
/*  Copyright (c) 2015, Karl Pauwels                                         */
/*  All rights reserved.                                                     */
/*                                                                           */
/*  Redistribution and use in source and binary forms, with or without       */
/*  modification, are permitted provided that the following conditions       */
/*  are met:                                                                 */
/*                                                                           */
/*  1. Redistributions of source code must retain the above copyright        */
/*  notice, this list of conditions and the following disclaimer.            */
/*                                                                           */
/*  2. Redistributions in binary form must reproduce the above copyright     */
/*  notice, this list of conditions and the following disclaimer in the      */
/*  documentation and/or other materials provided with the distribution.     */
/*                                                                           */
/*  3. Neither the name of the copyright holder nor the names of its         */
/*  contributors may be used to endorse or promote products derived from     */
/*  this software without specific prior written permission.                 */
/*                                                                           */
/*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS      */
/*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT        */
/*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR    */
/*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT     */
/*  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,   */
/*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT         */
/*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,    */
/*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY    */
/*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT      */
/*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE    */
/*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.     */
/*****************************************************************************/

#include <d_multiple_rigid_pose_sparse.h>
#include <GL/gl.h>
#include <sys/time.h>
#include <cstdio>
#include <stdexcept>
#include <H5Cpp.h>
#include <hdf5_file.h>
#include <utilities.h>
#include <Eigen/Dense>
#include <opencv2/calib3d/calib3d.hpp>

namespace pose {

D_MultipleRigidPoseSparse::D_MultipleRigidPoseSparse(
    int n_cols, int n_rows, float nodal_point_x, float nodal_point_y,
    float focal_length_x, float focal_length_y, int device_id, int vec_size,
    int num_iter_ransac)
    : _running{true}, _n_objects{0}, _num_iter_ransac{num_iter_ransac},
      _max_matches{50000}, _DESCRIPTOR_LENGTH{128},
      _siftEngine{std::unique_ptr<SiftGPU>{new SiftGPU()}},
      _matcherEngine{
          std::unique_ptr<SiftMatchGPU>{new SiftMatchGPU(4096 * vec_size)}} {
  _camera_mat.create(3, 3, CV_32F);
  updateCalibration(n_cols, n_rows, nodal_point_x, nodal_point_y,
                    focal_length_x, focal_length_y);

  char device_id_str[2];
  sprintf(device_id_str, "%d", device_id);

  // allow for full hd with upscaling (2*1920 = 3840)
  // allow for 3K with upscaling (2*2304 = 4608)
  const char *argv_template[] = {"-m",          "-fo",   "-1",    "-s",
                                 "-v",          "0",     "-pack", "-cuda",
                                 device_id_str, "-maxd", "4608"};
  int argc = sizeof(argv_template) / sizeof(char *);

  char *argv[argc];
  for (int i = 0; i < argc; i++)
    argv[i] = strdup(argv_template[i]);

  _siftEngine->ParseParam(argc, argv);

  for (int i = 0; i < argc; i++)
    free(argv[i]);

  if (_siftEngine->CreateContextGL() != SiftGPU::SIFTGPU_FULL_SUPPORTED)
    throw std::runtime_error("D_MultipleRigidPoseSparse::D_"
                             "MultipleRigidPoseSparse: SiftGPU cannot create "
                             "GL contex\n");

  _matcherEngine->VerifyContextGL();
  _match_buffer.resize(_max_matches * 2);
}

void D_MultipleRigidPoseSparse::updateCalibration(int n_cols, int n_rows,
                                                  float nodal_point_x,
                                                  float nodal_point_y,
                                                  float focal_length_x,
                                                  float focal_length_y) {
  _n_cols = n_cols;
  _n_rows = n_rows;

  // probably wrong!
  _camera_mat.at<float>(0, 0) = focal_length_x;
  _camera_mat.at<float>(0, 1) = 0.f;
  _camera_mat.at<float>(0, 2) = nodal_point_x - _n_cols / 2.0;

  _camera_mat.at<float>(1, 0) = 0.f;
  _camera_mat.at<float>(1, 1) = focal_length_y;
  _camera_mat.at<float>(1, 2) = nodal_point_y - _n_rows / 2.0;

  _camera_mat.at<float>(2, 0) = 0.f;
  _camera_mat.at<float>(2, 1) = 0.f;
  _camera_mat.at<float>(2, 2) = 1.f;
}

void D_MultipleRigidPoseSparse::addModel(const char *obj_filename) {
  _n_objects++;

  // Read from HDF5-file
  std::vector<float> descriptors, positions;
  std::vector<int> d_size, p_size;
  util::HDF5File f(obj_filename);
  f.readArray("descriptors", descriptors, d_size);
  f.readArray("positions", positions, p_size);

  if (d_size.size() != 2)
    throw std::runtime_error("D_MultipleRigidPoseSparse::addModel: descriptors "
                             "field should be 2D\n");
  if (d_size.at(1) != _DESCRIPTOR_LENGTH)
    throw std::runtime_error(std::string(
        "D_MultipleRigidPoseSparse::addModel: descriptors should be " +
        std::to_string(_DESCRIPTOR_LENGTH) + "-dimensional\n"));
  if (p_size.size() != 2)
    throw std::runtime_error(
        "D_MultipleRigidPoseSparse::addModel: positions field should be 2D\n");
  if (p_size.at(1) != 3)
    throw std::runtime_error("D_MultipleRigidPoseSparse::addModel: positions "
                             "should be 3-dimensional\n");
  if (d_size.at(0) != p_size.at(0))
    throw std::runtime_error("D_MultipleRigidPoseSparse::addModel: different "
                             "number of positions and descriptors\n");

  ModelAssets model;
  model.model_size = d_size.at(0);

  for (int i = 0; i < model.model_size; i++) {
    SiftGPU::SiftKeypoint position;
    position.x = positions.at(i * 3);
    position.y = positions.at(i * 3 + 1);
    position.s = positions.at(i * 3 + 2);
    position.o = 0;
    model.positions.push_back(position);
  }

  model.descriptors = descriptors;

  _allModels.push_back(model);
}

void D_MultipleRigidPoseSparse::removeAllModels() {
  _allModels.clear();
  _n_objects = 0;
}

TranslationRotation3D
D_MultipleRigidPoseSparse::estimatePoseSpecificObject(const cv::Mat &image,
                                                      const int object) {
  return estimatePose(image, object);
}

TranslationRotation3D
D_MultipleRigidPoseSparse::estimatePoseRandomObject(const cv::Mat &image,
                                                    int &object) {
  double obj_probabilities[_n_objects];
  for (int i = 0; i < _n_objects; i++)
    obj_probabilities[i] = 1.0 / (double)_n_objects;

  double r = ((double)rand() / double(RAND_MAX));

  object = 0;
  double prob_ulim = obj_probabilities[object];

  while (r > prob_ulim) {
    object++;
    prob_ulim += obj_probabilities[object];
  }

  //  printf("%d -- %2.4f -- %2.4f %2.4f
  // %d!!!!\n",_n_objects,r,obj_probabilities[0],obj_probabilities[1],object);

  return estimatePose(image, object);
}

TranslationRotation3D
D_MultipleRigidPoseSparse::estimatePose(const cv::Mat &image, int object) {

  TranslationRotation3D currPose;

  if (_running) {

    ModelAssets &model = _allModels.at(object);

    _siftEngine->RunSIFT(_n_cols, _n_rows, image.data, GL_LUMINANCE,
                         GL_UNSIGNED_BYTE);

    int n_image_features = _siftEngine->GetFeatureNum();

    std::vector<float> img_feature_descriptors(_DESCRIPTOR_LENGTH *
                                               n_image_features);
    std::vector<SiftGPU::SiftKeypoint> img_positions(n_image_features);

    _siftEngine->GetFeatureVector(img_positions.data(),
                                  img_feature_descriptors.data());

    const unsigned long long one_d_texture_limit = 134217728;
    if (static_cast<unsigned long long>(model.model_size) *
            static_cast<unsigned long long>(n_image_features) >
        one_d_texture_limit) {

      // shuffling and downsampling image keypoints
      int max_n_image_features = one_d_texture_limit / model.model_size - 1;

      //      std::cout << "going to match " << model.model_size << " model to "
      //                << n_image_features << " image features - max allowed
      // image = "
      //                << max_n_image_features << std::endl;

      std::vector<int> shuffle_inds(n_image_features);
      std::iota(shuffle_inds.begin(), shuffle_inds.end(), 0);
      std::random_shuffle(shuffle_inds.begin(), shuffle_inds.end());

      Eigen::Map<Eigen::VectorXi> shuffle_inds_eig(shuffle_inds.data(),
                                                   n_image_features);
      Eigen::Map<Eigen::MatrixXf> all_keypoints_eig(
          (float *)img_positions.data(), 4, n_image_features);
      Eigen::Map<Eigen::MatrixXf> all_descriptors_eig(
          img_feature_descriptors.data(), _DESCRIPTOR_LENGTH, n_image_features);

      Eigen::PermutationMatrix<Eigen::Dynamic, Eigen::Dynamic, int> p(
          shuffle_inds_eig);
      all_keypoints_eig = all_keypoints_eig * p;
      all_descriptors_eig = all_descriptors_eig * p;

      n_image_features = max_n_image_features;
    }

    _matcherEngine->SetDescriptors(0, model.model_size,
                                   model.descriptors.data()); // model
    _matcherEngine->SetDescriptors(1, n_image_features,
                                   img_feature_descriptors.data()); // image

    // match and get result
    int num_match = _matcherEngine->GetSiftMatch(
        _max_matches, (int(*)[2])_match_buffer.data());

    // compute pnp
    std::vector<cv::Point3f> objectPoints;
    std::vector<cv::Point2f> imagePoints;

    for (int i = 0; i < num_match; i++) {
      SiftGPU::SiftKeypoint &objectKey =
          model.positions[_match_buffer.at(i * 2)];
      SiftGPU::SiftKeypoint &imageKey =
          img_positions[_match_buffer.at(i * 2 + 1)];

      cv::Point2f imagePoint(imageKey.x - _n_cols / 2,
                             imageKey.y - _n_rows / 2);
      cv::Point3f objectPoint(objectKey.x, objectKey.y, objectKey.s);

      objectPoints.push_back(objectPoint);
      imagePoints.push_back(imagePoint);
    }

    const float max_dist = 1.0; // 1.0F

    cv::Mat rvec, tvec;
    std::vector<int> inliers_cpu;
    if (objectPoints.size() > 4) {
      cv::solvePnPRansac(objectPoints, imagePoints, _camera_mat,
                         cv::Mat::zeros(1, 8, CV_32F), rvec, tvec, false,
                         _num_iter_ransac, max_dist, objectPoints.size(),
                         inliers_cpu, CV_P3P);
      double T[] = {tvec.at<double>(0, 0), tvec.at<double>(0, 1),
                    tvec.at<double>(0, 2)};
      double R[] = {rvec.at<double>(0, 0), rvec.at<double>(0, 1),
                    rvec.at<double>(0, 2)};
      currPose = TranslationRotation3D(T, R);
    }

    // require at least one inlier for the estimate to be valid (apart from the
    // four points used to estimate pose)
    currPose.setValid(currPose.isFinite() && (inliers_cpu.size() >= 5));

    // if (currPose.isValid()) {
    //   currPose.showCompact();
    //   std::cout << "inliers: " << inliers_cpu.size() << "/"
    //             << objectPoints.size() << std::endl << std::endl;
    // }

    //    double pnp_time = timer.read();

    //    std::cout << std::setprecision(2);
    //    std::cout << "extract: " << extract_time << " match: " << match_time
    //              << " pnp: " << pnp_time << std::endl;
  }

  return (currPose);
}
}
<commit_msg>Fixed issue with opencv3 solvePnPRansac<commit_after>/*****************************************************************************/
/*  Copyright (c) 2015, Karl Pauwels                                         */
/*  All rights reserved.                                                     */
/*                                                                           */
/*  Redistribution and use in source and binary forms, with or without       */
/*  modification, are permitted provided that the following conditions       */
/*  are met:                                                                 */
/*                                                                           */
/*  1. Redistributions of source code must retain the above copyright        */
/*  notice, this list of conditions and the following disclaimer.            */
/*                                                                           */
/*  2. Redistributions in binary form must reproduce the above copyright     */
/*  notice, this list of conditions and the following disclaimer in the      */
/*  documentation and/or other materials provided with the distribution.     */
/*                                                                           */
/*  3. Neither the name of the copyright holder nor the names of its         */
/*  contributors may be used to endorse or promote products derived from     */
/*  this software without specific prior written permission.                 */
/*                                                                           */
/*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS      */
/*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT        */
/*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR    */
/*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT     */
/*  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,   */
/*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT         */
/*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,    */
/*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY    */
/*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT      */
/*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE    */
/*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.     */
/*****************************************************************************/

#include <d_multiple_rigid_pose_sparse.h>
#include <GL/gl.h>
#include <sys/time.h>
#include <cstdio>
#include <stdexcept>
#include <H5Cpp.h>
#include <hdf5_file.h>
#include <utilities.h>
#include <Eigen/Dense>
#include <opencv2/calib3d/calib3d.hpp>

namespace pose {

D_MultipleRigidPoseSparse::D_MultipleRigidPoseSparse(
    int n_cols, int n_rows, float nodal_point_x, float nodal_point_y,
    float focal_length_x, float focal_length_y, int device_id, int vec_size,
    int num_iter_ransac)
    : _running{true}, _n_objects{0}, _num_iter_ransac{num_iter_ransac},
      _max_matches{50000}, _DESCRIPTOR_LENGTH{128},
      _siftEngine{std::unique_ptr<SiftGPU>{new SiftGPU()}},
      _matcherEngine{
          std::unique_ptr<SiftMatchGPU>{new SiftMatchGPU(4096 * vec_size)}} {
  _camera_mat.create(3, 3, CV_64F);
  updateCalibration(n_cols, n_rows, nodal_point_x, nodal_point_y,
                    focal_length_x, focal_length_y);

  char device_id_str[2];
  sprintf(device_id_str, "%d", device_id);

  // allow for full hd with upscaling (2*1920 = 3840)
  // allow for 3K with upscaling (2*2304 = 4608)
  const char *argv_template[] = {"-m",          "-fo",   "-1",    "-s",
                                 "-v",          "0",     "-pack", "-cuda",
                                 device_id_str, "-maxd", "4608"};
  int argc = sizeof(argv_template) / sizeof(char *);

  char *argv[argc];
  for (int i = 0; i < argc; i++)
    argv[i] = strdup(argv_template[i]);

  _siftEngine->ParseParam(argc, argv);

  for (int i = 0; i < argc; i++)
    free(argv[i]);

  if (_siftEngine->CreateContextGL() != SiftGPU::SIFTGPU_FULL_SUPPORTED)
    throw std::runtime_error("D_MultipleRigidPoseSparse::D_"
                             "MultipleRigidPoseSparse: SiftGPU cannot create "
                             "GL contex\n");

  _matcherEngine->VerifyContextGL();
  _match_buffer.resize(_max_matches * 2);
}

void D_MultipleRigidPoseSparse::updateCalibration(int n_cols, int n_rows,
                                                  float nodal_point_x,
                                                  float nodal_point_y,
                                                  float focal_length_x,
                                                  float focal_length_y) {
  _n_cols = n_cols;
  _n_rows = n_rows;

  _camera_mat.at<double>(0, 0) = focal_length_x;
  _camera_mat.at<double>(0, 1) = 0.f;
  _camera_mat.at<double>(0, 2) = nodal_point_x;

  _camera_mat.at<double>(1, 0) = 0.f;
  _camera_mat.at<double>(1, 1) = focal_length_y;
  _camera_mat.at<double>(1, 2) = nodal_point_y;

  _camera_mat.at<double>(2, 0) = 0.f;
  _camera_mat.at<double>(2, 1) = 0.f;
  _camera_mat.at<double>(2, 2) = 1.f;
}

void D_MultipleRigidPoseSparse::addModel(const char *obj_filename) {
  _n_objects++;

  // Read from HDF5-file
  std::vector<float> descriptors, positions;
  std::vector<int> d_size, p_size;
  util::HDF5File f(obj_filename);
  f.readArray("descriptors", descriptors, d_size);
  f.readArray("positions", positions, p_size);

  if (d_size.size() != 2)
    throw std::runtime_error("D_MultipleRigidPoseSparse::addModel: descriptors "
                             "field should be 2D\n");
  if (d_size.at(1) != _DESCRIPTOR_LENGTH)
    throw std::runtime_error(std::string(
        "D_MultipleRigidPoseSparse::addModel: descriptors should be " +
        std::to_string(_DESCRIPTOR_LENGTH) + "-dimensional\n"));
  if (p_size.size() != 2)
    throw std::runtime_error(
        "D_MultipleRigidPoseSparse::addModel: positions field should be 2D\n");
  if (p_size.at(1) != 3)
    throw std::runtime_error("D_MultipleRigidPoseSparse::addModel: positions "
                             "should be 3-dimensional\n");
  if (d_size.at(0) != p_size.at(0))
    throw std::runtime_error("D_MultipleRigidPoseSparse::addModel: different "
                             "number of positions and descriptors\n");

  ModelAssets model;
  model.model_size = d_size.at(0);

  for (int i = 0; i < model.model_size; i++) {
    SiftGPU::SiftKeypoint position;
    position.x = positions.at(i * 3);
    position.y = positions.at(i * 3 + 1);
    position.s = positions.at(i * 3 + 2);
    position.o = 0;
    model.positions.push_back(position);
  }

  model.descriptors = descriptors;

  _allModels.push_back(model);
}

void D_MultipleRigidPoseSparse::removeAllModels() {
  _allModels.clear();
  _n_objects = 0;
}

TranslationRotation3D
D_MultipleRigidPoseSparse::estimatePoseSpecificObject(const cv::Mat &image,
                                                      const int object) {
  return estimatePose(image, object);
}

TranslationRotation3D
D_MultipleRigidPoseSparse::estimatePoseRandomObject(const cv::Mat &image,
                                                    int &object) {
  double obj_probabilities[_n_objects];
  for (int i = 0; i < _n_objects; i++)
    obj_probabilities[i] = 1.0 / (double)_n_objects;

  double r = ((double)rand() / double(RAND_MAX));

  object = 0;
  double prob_ulim = obj_probabilities[object];

  while (r > prob_ulim) {
    object++;
    prob_ulim += obj_probabilities[object];
  }

  //  printf("%d -- %2.4f -- %2.4f %2.4f
  // %d!!!!\n",_n_objects,r,obj_probabilities[0],obj_probabilities[1],object);

  return estimatePose(image, object);
}

TranslationRotation3D
D_MultipleRigidPoseSparse::estimatePose(const cv::Mat &image, int object) {

  TranslationRotation3D currPose;

  if (_running) {

    ModelAssets &model = _allModels.at(object);

    _siftEngine->RunSIFT(_n_cols, _n_rows, image.data, GL_LUMINANCE,
                         GL_UNSIGNED_BYTE);

    int n_image_features = _siftEngine->GetFeatureNum();

    std::vector<float> img_feature_descriptors(_DESCRIPTOR_LENGTH *
                                               n_image_features);
    std::vector<SiftGPU::SiftKeypoint> img_positions(n_image_features);

    _siftEngine->GetFeatureVector(img_positions.data(),
                                  img_feature_descriptors.data());

    const unsigned long long one_d_texture_limit = 134217728;
    if (static_cast<unsigned long long>(model.model_size) *
            static_cast<unsigned long long>(n_image_features) >
        one_d_texture_limit) {

      // shuffling and downsampling image keypoints
      int max_n_image_features = one_d_texture_limit / model.model_size - 1;

      //      std::cout << "going to match " << model.model_size << " model to "
      //                << n_image_features << " image features - max allowed
      // image = "
      //                << max_n_image_features << std::endl;

      std::vector<int> shuffle_inds(n_image_features);
      std::iota(shuffle_inds.begin(), shuffle_inds.end(), 0);
      std::random_shuffle(shuffle_inds.begin(), shuffle_inds.end());

      Eigen::Map<Eigen::VectorXi> shuffle_inds_eig(shuffle_inds.data(),
                                                   n_image_features);
      Eigen::Map<Eigen::MatrixXf> all_keypoints_eig(
          (float *)img_positions.data(), 4, n_image_features);
      Eigen::Map<Eigen::MatrixXf> all_descriptors_eig(
          img_feature_descriptors.data(), _DESCRIPTOR_LENGTH, n_image_features);

      Eigen::PermutationMatrix<Eigen::Dynamic, Eigen::Dynamic, int> p(
          shuffle_inds_eig);
      all_keypoints_eig = all_keypoints_eig * p;
      all_descriptors_eig = all_descriptors_eig * p;

      n_image_features = max_n_image_features;
    }

    _matcherEngine->SetDescriptors(0, model.model_size,
                                   model.descriptors.data()); // model
    _matcherEngine->SetDescriptors(1, n_image_features,
                                   img_feature_descriptors.data()); // image

    // match and get result
    int num_match = _matcherEngine->GetSiftMatch(
        _max_matches, (int(*)[2])_match_buffer.data());

    // compute pnp
    std::vector<cv::Point3f> objectPoints;
    std::vector<cv::Point2f> imagePoints;

    for (int i = 0; i < num_match; i++) {
      SiftGPU::SiftKeypoint &objectKey =
          model.positions[_match_buffer.at(i * 2)];
      SiftGPU::SiftKeypoint &imageKey =
          img_positions[_match_buffer.at(i * 2 + 1)];

      cv::Point2f imagePoint(imageKey.x, imageKey.y);
      cv::Point3f objectPoint(objectKey.x, objectKey.y, objectKey.s);

      objectPoints.push_back(objectPoint);
      imagePoints.push_back(imagePoint);
    }

    const float max_dist = 1.0; // 1.0F

    std::vector<int> inliers_cpu;
    cv::Mat rvec = cv::Mat::zeros(3, 1, CV_64FC1);
    cv::Mat tvec = cv::Mat::zeros(3, 1, CV_64FC1);
    if (objectPoints.size() > 4) {
      cv::solvePnPRansac(objectPoints, imagePoints, _camera_mat,
                         cv::Mat::zeros(4, 1, CV_64FC1), rvec, tvec, false,
                         _num_iter_ransac, max_dist, .99,
                         inliers_cpu, cv::SOLVEPNP_P3P);
      double T[] = {tvec.at<double>(0), tvec.at<double>(1),
                    tvec.at<double>(2)};
      double R[] = {rvec.at<double>(0), rvec.at<double>(1),
                    rvec.at<double>(2)};
      currPose = TranslationRotation3D(T, R);
    }

    // require at least one inlier for the estimate to be valid (apart from the
    // four points used to estimate pose)
    currPose.setValid(currPose.isFinite() && (inliers_cpu.size() >= 5));

    // if (currPose.isValid()) {
    //   currPose.showCompact();
    //   std::cout << "inliers: " << inliers_cpu.size() << "/"
    //             << objectPoints.size() << std::endl << std::endl;
    // }

    //    double pnp_time = timer.read();

    //    std::cout << std::setprecision(2);
    //    std::cout << "extract: " << extract_time << " match: " << match_time
    //              << " pnp: " << pnp_time << std::endl;
  }

  return (currPose);
}
}
<|endoftext|>


<commit_before>/*
        AtlasXMLEncoder.cpp
        ----------------
        begin           : 1999.11.29
        copyright       : (C) 1999 by John Barrett (ZW)
        email           : jbarrett@box100.com
*/

#include "AtlasXMLEncoder.h"

#include <map.h>
#include <memory.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#include <string>

void AXMLEncoder::walkTree(int nest, string name, AObject& list)
{
	int	i;
	string	buf;
	string	pre;

	for (int j=0; j<nest; j++) {
		pre.append("    ");
	}

	if (list.isList()) {
		// precheck types here
		string pfix("");

		if (list.getListType() == AObject::AIntList)		pfix.append("int_");
		else if (list.getListType() == AObject::AFloatList)	pfix.append("float_");
		else if (list.getListType() == AObject::AStringList)	pfix.append("string_");

		if (name.length() > 0) {
			printf("%s<%slist name=\"%s\">\n", pre.c_str(), pfix.c_str(), name.c_str());
		} else {
			printf("%s<%slist>\n", pre.c_str(), pfix.c_str());
		}
		for (i=0; i<list.length(); i++) {
			AObject tmp;
			list.get(i, tmp);
			walkTree(nest+1, "", tmp);
		}
		printf("%s</list>\n",pre.c_str());
	}
	if (list.isMap()) {
		AObject keys = list.keys();
		if (name.length() > 0) {
			printf("%s<map name=\"%s\">\n",pre.c_str(), name.c_str());
		} else {
			printf("%s<map>\n", pre.c_str());
		}
		for (i=0; i<keys.length(); i++) {
			AObject key;
			keys.get(i, key);
			AObject tmp;
			list.get(key.asString(), tmp);
			walkTree(nest+1, key.asString(), tmp);
		}
		printf("%s</map>\n",pre.c_str());
	}

	if (list.isString()) {
		if (name.length() > 0) {
			printf("%s<string name=\"%s\">%s</str>\n",
				pre.c_str(), name.c_str(),list.asString().c_str()
			);
		} else {
			printf("%s<string>%s</str>\n",pre.c_str(), list.asString().c_str());
		}
	}
	if (list.isLong()) {
		if (name.length() > 0) {
			printf("%s<int name=\"%s\">%li</int>\n",
				pre.c_str(), name.c_str(),list.asLong()
			);
		} else {
			printf("%s<int>%li</int>\n", pre.c_str(), list.asLong());
		}
	}
	if (list.isFloat()) {
		if (name.length() > 0) {
			printf("%s<float name=\"%s\">%.2f</float>\n",
				pre.c_str(), name.c_str(),list.asFloat()
			);
		} else {
			printf("%s<float>%.2f</float>\n",pre.c_str(), list.asFloat());
		}
	}

}

string AXMLEncoder::encodeMessage(AObject& msg)
{
	int	i;

	// start a new message
	buffer = "";
	// format the message header
	printf("<obj>\n");
	walkTree(1, "", msg);
	// and close off the message
	printf("</obj>\n");
	// return result
	return buffer;
}

<commit_msg></str> -> </string><commit_after>/*
        AtlasXMLEncoder.cpp
        ----------------
        begin           : 1999.11.29
        copyright       : (C) 1999 by John Barrett (ZW)
        email           : jbarrett@box100.com
*/

#include "AtlasXMLEncoder.h"

#include <map.h>
#include <memory.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#include <string>

void AXMLEncoder::walkTree(int nest, string name, AObject& list)
{
	int	i;
	string	buf;
	string	pre;

	for (int j=0; j<nest; j++) {
		pre.append("    ");
	}

	if (list.isList()) {
		// precheck types here
		string pfix("");

		if (list.getListType() == AObject::AIntList)		pfix.append("int_");
		else if (list.getListType() == AObject::AFloatList)	pfix.append("float_");
		else if (list.getListType() == AObject::AStringList)	pfix.append("string_");

		if (name.length() > 0) {
			printf("%s<%slist name=\"%s\">\n", pre.c_str(), pfix.c_str(), name.c_str());
		} else {
			printf("%s<%slist>\n", pre.c_str(), pfix.c_str());
		}
		for (i=0; i<list.length(); i++) {
			AObject tmp;
			list.get(i, tmp);
			walkTree(nest+1, "", tmp);
		}
		printf("%s</list>\n",pre.c_str());
	}
	if (list.isMap()) {
		AObject keys = list.keys();
		if (name.length() > 0) {
			printf("%s<map name=\"%s\">\n",pre.c_str(), name.c_str());
		} else {
			printf("%s<map>\n", pre.c_str());
		}
		for (i=0; i<keys.length(); i++) {
			AObject key;
			keys.get(i, key);
			AObject tmp;
			list.get(key.asString(), tmp);
			walkTree(nest+1, key.asString(), tmp);
		}
		printf("%s</map>\n",pre.c_str());
	}

	if (list.isString()) {
		if (name.length() > 0) {
			printf("%s<string name=\"%s\">%s</string>\n",
				pre.c_str(), name.c_str(),list.asString().c_str()
			);
		} else {
			printf("%s<string>%s</string>\n",pre.c_str(), list.asString().c_str());
		}
	}
	if (list.isLong()) {
		if (name.length() > 0) {
			printf("%s<int name=\"%s\">%li</int>\n",
				pre.c_str(), name.c_str(),list.asLong()
			);
		} else {
			printf("%s<int>%li</int>\n", pre.c_str(), list.asLong());
		}
	}
	if (list.isFloat()) {
		if (name.length() > 0) {
			printf("%s<float name=\"%s\">%.2f</float>\n",
				pre.c_str(), name.c_str(),list.asFloat()
			);
		} else {
			printf("%s<float>%.2f</float>\n",pre.c_str(), list.asFloat());
		}
	}

}

string AXMLEncoder::encodeMessage(AObject& msg)
{
	int	i;

	// start a new message
	buffer = "";
	// format the message header
	printf("<obj>\n");
	walkTree(1, "", msg);
	// and close off the message
	printf("</obj>\n");
	// return result
	return buffer;
}

<|endoftext|>