<commit_before>/*************************************************************************
 * Copyright (c) 2013 eProsima. All rights reserved.
 *
 * This copy of FastCdr is licensed to you under the terms described in the
 * EPROSIMARTPS_LIBRARY_LICENSE file included in this distribution.
 *
 *************************************************************************/

/*
 * CDRMessage.cpp
 *
 *  Created on: Feb 24, 2014
 *      Author: Gonzalo Rodriguez Canosa
 *      email:  gonzalorodriguez@eprosima.com
 */

#include <algorithm>

#include "eprosimartps/CDRMessage.h"

namespace eprosima {
namespace rtps {

CDRMessage::CDRMessage() {
	// TODO Auto-generated constructor stub

}

CDRMessage::~CDRMessage() {
	// TODO Auto-generated destructor stub
}

//bool CDRMessage::initCDRMsg(CDRMessage_t* msg, uint size) {
//	if(msg->buffer!=NULL)
//		free(msg->buffer);
//	msg->buffer = (octet*)malloc(size);
//	msg->max_size = size;
//	msg->pos = 0;
//	msg->length = 0;
//	return true;
//}

bool CDRMessage::initCDRMsg(CDRMessage_t*msg) {
	if(msg->buffer==NULL)
	{
		msg->buffer = (octet*)malloc(RTPSMESSAGE_MAX_SIZE);
		msg->max_size = RTPSMESSAGE_MAX_SIZE;
	}
	msg->pos = 0;
	msg->length = 0;
	return true;
}

bool CDRMessage::appendMsg(CDRMessage_t*first, CDRMessage_t*second) {
	return(CDRMessage::addData(first,second->buffer,second->length));
}

bool CDRMessage::readEntityId(CDRMessage_t* msg,EntityId_t* id) {
	if(msg->pos+4>msg->length)
		return false;
	uint32_t* aux1 = (uint32_t*) id->value;
	uint32_t* aux2 = (uint32_t*) &msg->buffer[msg->pos];
	*aux1 = *aux2;
	msg->pos+=4;
	return true;
}

bool CDRMessage::readData(CDRMessage_t* msg,octet* o,uint16_t length) {
	memcpy(o,&msg->buffer[msg->pos],length);
	msg->pos+=length;
	return true;
}

bool CDRMessage::readDataReversed(CDRMessage_t* msg,octet* o,uint16_t length) {
	for(uint i=0;i<length;i++)
	{
		*(o+i)=*(msg->buffer+msg->pos+length-1-i);
	}
	msg->pos+=length;
	return true;
}

bool CDRMessage::readInt32(CDRMessage_t* msg,int32_t* lo) {
	if(msg->pos+4>msg->length)
		return false;
	octet* dest = (octet*)lo;
	if(msg->msg_endian == DEFAULT_ENDIAN){
		readData(msg,dest,4);
	}
	else{
		readDataReversed(msg,dest,4);
	}
	return true;
}

bool CDRMessage::readUInt32(CDRMessage_t* msg,uint32_t* ulo) {
	if(msg->pos+4>msg->length)
		return false;
	octet* dest = (octet*)ulo;
	if(msg->msg_endian == DEFAULT_ENDIAN){
		readData(msg,dest,4);
	}
	else{
		readDataReversed(msg,dest,4);
	}
	return true;
}

bool CDRMessage::readSequenceNumber(CDRMessage_t* msg,SequenceNumber_t* sn) {
	if(msg->pos+8>msg->length)
		return false;
	readInt32(msg,&sn->high);
	readUInt32(msg,&sn->low);
	return true;
}

bool CDRMessage::readLocator(CDRMessage_t* msg,Locator_t* loc) {
	if(msg->pos+24>msg->length)
		return false;
	readInt32(msg,&loc->kind);
	readUInt32(msg,&loc->port);

	readData(msg,loc->address,16);

	return true;
}

bool CDRMessage::readInt16(CDRMessage_t* msg,int16_t* i16) {
	if(msg->pos+2>msg->length)
		return false;
	octet* o = (octet*)i16;
	if(msg->msg_endian == DEFAULT_ENDIAN){
		*o = msg->buffer[msg->pos];
		*(o+1) = msg->buffer[msg->pos+1];
	}
	else{
		*o = msg->buffer[msg->pos+1];
		*(o+1) = msg->buffer[msg->pos];
	}
	msg->pos+=2;
	return true;
}

bool CDRMessage::readUInt16(CDRMessage_t* msg,uint16_t* i16) {
	if(msg->pos+2>msg->length)
		return false;
	octet* o = (octet*)i16;
	if(msg->msg_endian == DEFAULT_ENDIAN){
		*o = msg->buffer[msg->pos];
		*(o+1) = msg->buffer[msg->pos+1];
	}
	else{
		*o = msg->buffer[msg->pos+1];
		*(o+1) = msg->buffer[msg->pos];
	}
	msg->pos+=2;
	return true;
}

bool CDRMessage::readOctet(CDRMessage_t* msg, octet* o) {
	if(msg->pos+1>msg->length)
		return false;
	*o = msg->buffer[msg->pos];
	msg->pos++;
	return true;
}

bool CDRMessage::addData(CDRMessage_t*msg, octet* data, uint length) {
	if(msg->pos + length > msg->max_size)
	{
		pError( "Message size not enough "<<endl);

		return false;
	}

	memcpy(&msg->buffer[msg->pos],data,length);
	msg->pos +=length;
	msg->length+=length;
	return true;
}

bool CDRMessage::addDataReversed(CDRMessage_t*msg, octet* data, uint length) {
	if(msg->pos + length > msg->max_size)
	{
		pError( "Message size not enough "<<endl);
		return false;
	}
	for(uint i = 0;i<length;i++)
	{
		msg->buffer[msg->pos+i] = *(data+length-1-i);
	}
	msg->pos +=length;
	msg->length+=length;
	return true;
}

bool CDRMessage::addOctet(CDRMessage_t*msg, octet O)
{
	if(msg->pos + 1 > msg->max_size)
	{
		pError( "Message size not enough "<<endl);
		return false;
	}
	//const void* d = (void*)&O;
	msg->buffer[msg->pos] = O;
	msg->pos++;
	msg->length++;
	return true;
}

bool CDRMessage::addUInt16(CDRMessage_t*msg,
		unsigned short U)
{
	if(msg->pos + 2 > msg->max_size)
	{
		pError( "Message size not enough "<<endl);
		return false;
	}
	octet* o= (octet*)&U;
	if(msg->msg_endian == DEFAULT_ENDIAN)
	{
		msg->buffer[msg->pos] = *(o);
		msg->buffer[msg->pos+1] = *(o+1);
	}
	else
	{
		msg->buffer[msg->pos] = *(o+1);
		msg->buffer[msg->pos+1] = *(o);
	}
	msg->pos+=2;
	msg->length+=2;
	return true;
}

bool CDRMessage::addInt32(CDRMessage_t* msg, int32_t lo) {
	octet* o= (octet*)&lo;
	if(msg->pos + 4 > msg->max_size)
	{
		pError( "Message size not enough "<<endl);
		return false;
	}
	if(msg->msg_endian == DEFAULT_ENDIAN)
	{
		for(uint8_t i=0;i<4;i++)
		{
			msg->buffer[msg->pos+i] = *(o+i);
		}
	}
	else
	{
		for(uint8_t i=0;i<4;i++)
		{
			msg->buffer[msg->pos+i] = *(o+3-i);
		}
	}
	msg->pos+=4;
	msg->length+=4;
	return true;
}

bool CDRMessage::addUInt32(CDRMessage_t* msg, uint32_t ulo) {
	octet* o= (octet*)&ulo;
	if(msg->pos + 4 > msg->max_size)
	{
		pError( "Message size not enough "<<endl);
		return false;
	}
	if(msg->msg_endian == DEFAULT_ENDIAN)
	{
		for(uint8_t i=0;i<4;i++)
		{
			msg->buffer[msg->pos+i] = *(o+i);
		}
	}
	else
	{
		for(uint8_t i=0;i<4;i++)
		{
			msg->buffer[msg->pos+i] = *(o+3-i);
		}
	}
	msg->pos+=4;
	msg->length+=4;
	return true;
}

bool CDRMessage::addInt64(CDRMessage_t* msg, int64_t lolo) {
	octet* o= (octet*)&lolo;
	if(msg->pos + 8 > msg->max_size)
	{
		pError( "Message size not enough "<<endl);
		return false;
	}
	if(msg->msg_endian == DEFAULT_ENDIAN)
	{
		for(uint8_t i=0;i<8;i++)
		{
			msg->buffer[msg->pos+i] = *(o+i);
		}
	}
	else
	{
		for(uint8_t i=0;i<8;i++)
		{
			msg->buffer[msg->pos+i] = *(o+7-i);
		}
	}
	msg->pos+=8;
	msg->length+=8;
	return true;
}

bool CDRMessage::addEntityId(CDRMessage_t* msg, EntityId_t*ID) {
	if(msg->pos+4>=msg->max_size)
	{
		pError( "Message size not enough "<<endl);
		return false;
	}
	int* aux1;
	int* aux2;
	aux1 = (int*)(&msg->buffer[msg->pos]);
	aux2 = (int*) ID->value;
	*aux1 = *aux2;
	msg->pos +=4;
	msg->length+=4;
	return true;
}

bool CDRMessage::addSequenceNumber(CDRMessage_t* msg,
		SequenceNumber_t* sn) {
	addInt32(msg,sn->high);
	addUInt32(msg,sn->low);

	return true;
}

bool sort_seqNum (SequenceNumber_t s1,SequenceNumber_t s2)
{
	return(s1.to64long() < s2.to64long());
}

bool CDRMessage::addSequenceNumberSet(CDRMessage_t* msg,
		SequenceNumberSet_t* sns) {
	addSequenceNumber(msg, &sns->base);
	//Add set
	std::sort(sns->set.begin(),sns->set.end(),sort_seqNum);
	SequenceNumber_t maxseqNum = *std::max_element(sns->set.begin(),sns->set.end(),sort_seqNum);
	uint32_t numBits = (uint32_t)(maxseqNum.to64long() - sns->base.to64long());
	addUInt32(msg,numBits);
	std::vector<SequenceNumber_t>::iterator it;
	uint32_t n_octet = 0;
	uint8_t bit = 0;
	octet o = 0;
	//Compute the bitmap in terms of octets:
	for(it=sns->set.begin();it!=sns->set.end();it++)
	{
		bit = it->to64long()-sns->base.to64long()-n_octet*8;
		switch(bit)
		{
			case 0: o= o| BIT(7); break;
			case 1: o= o| BIT(6); break;
			case 2: o= o| BIT(5); break;
			case 3: o= o| BIT(4); break;
			case 4: o= o| BIT(3); break;
			case 5: o= o| BIT(2); break;
			case 6: o= o| BIT(1); break;
			case 7: o= o| BIT(0); break;
		}
		if(bit>7)
		{
			addOctet(msg,o);
			o = 0x0;
			for(int i=0;i<(floor(bit/8)-1);i++)
				addOctet(msg,o);
			n_octet += floor(bit/8);
			it--;
		}
	}
	//add enough octets as gap
	while((n_octet+1)%4 != 0)
	{
		o=0;
		addOctet(msg,o);
	}
	return true;
}

bool CDRMessage::addLocator(CDRMessage_t* msg, Locator_t* loc) {
	addInt32(msg,loc->kind);
	addUInt32(msg,loc->port);

	addData(msg,loc->address,16);

	return true;
}

} /* namespace rtps */
} /* namespace eprosima */

<commit_msg>CDRMessage read functions rewritten.<commit_after>/*************************************************************************
 * Copyright (c) 2013 eProsima. All rights reserved.
 *
 * This copy of FastCdr is licensed to you under the terms described in the
 * EPROSIMARTPS_LIBRARY_LICENSE file included in this distribution.
 *
 *************************************************************************/

/*
 * CDRMessage.cpp
 *
 *  Created on: Feb 24, 2014
 *      Author: Gonzalo Rodriguez Canosa
 *      email:  gonzalorodriguez@eprosima.com
 */

#include <algorithm>

#include "eprosimartps/CDRMessage.h"

namespace eprosima {
namespace rtps {

CDRMessage::CDRMessage() {
	// TODO Auto-generated constructor stub

}

CDRMessage::~CDRMessage() {
	// TODO Auto-generated destructor stub
}

//bool CDRMessage::initCDRMsg(CDRMessage_t* msg, uint size) {
//	if(msg->buffer!=NULL)
//		free(msg->buffer);
//	msg->buffer = (octet*)malloc(size);
//	msg->max_size = size;
//	msg->pos = 0;
//	msg->length = 0;
//	return true;
//}

bool CDRMessage::initCDRMsg(CDRMessage_t*msg)
{
	if(msg->buffer==NULL)
	{
		msg->buffer = (octet*)malloc(RTPSMESSAGE_MAX_SIZE);
		msg->max_size = RTPSMESSAGE_MAX_SIZE;
	}
	msg->pos = 0;
	msg->length = 0;
	return true;
}

bool CDRMessage::appendMsg(CDRMessage_t*first, CDRMessage_t*second) {
	return(CDRMessage::addData(first,second->buffer,second->length));
}

bool CDRMessage::readEntityId(CDRMessage_t* msg,EntityId_t* id) {
	if(msg->pos+4>msg->length)
		return false;
	uint32_t* aux1 = (uint32_t*) id->value;
	uint32_t* aux2 = (uint32_t*) &msg->buffer[msg->pos];
	*aux1 = *aux2;
	msg->pos+=4;
	return true;
}

bool CDRMessage::readData(CDRMessage_t* msg,octet* o,uint16_t length) {
	memcpy(o,&msg->buffer[msg->pos],length);
	msg->pos+=length;
	return true;
}

bool CDRMessage::readDataReversed(CDRMessage_t* msg,octet* o,uint16_t length) {
	for(uint i=0;i<length;i++)
	{
		*(o+i)=*(msg->buffer+msg->pos+length-1-i);
	}
	msg->pos+=length;
	return true;
}

bool CDRMessage::readInt32(CDRMessage_t* msg,int32_t* lo) {
	if(msg->pos+4>msg->length)
		return false;
	octet* dest = (octet*)lo;
	if(msg->msg_endian == DEFAULT_ENDIAN){
		for(uint8_t i =0;i<4;i++)
			dest[i] = msg->buffer[msg->pos+i];
		msg->pos+=4;
	}
	else{
		readDataReversed(msg,dest,4);
	}
	return true;
}

bool CDRMessage::readUInt32(CDRMessage_t* msg,uint32_t* ulo) {
	if(msg->pos+4>msg->length)
		return false;
	octet* dest = (octet*)ulo;
	if(msg->msg_endian == DEFAULT_ENDIAN){
		for(uint8_t i =0;i<4;i++)
			dest[i] = msg->buffer[msg->pos+i];
		msg->pos+=4;
	}
	else{
		readDataReversed(msg,dest,4);
	}
	return true;
}

bool CDRMessage::readSequenceNumber(CDRMessage_t* msg,SequenceNumber_t* sn) {
	if(msg->pos+8>msg->length)
		return false;
	readInt32(msg,&sn->high);
	readUInt32(msg,&sn->low);
	return true;
}

bool CDRMessage::readLocator(CDRMessage_t* msg,Locator_t* loc) {
	if(msg->pos+24>msg->length)
		return false;
	readInt32(msg,&loc->kind);
	readUInt32(msg,&loc->port);

	readData(msg,loc->address,16);

	return true;
}

bool CDRMessage::readInt16(CDRMessage_t* msg,int16_t* i16) {
	if(msg->pos+2>msg->length)
		return false;
	octet* o = (octet*)i16;
	if(msg->msg_endian == DEFAULT_ENDIAN){
		*o = msg->buffer[msg->pos];
		*(o+1) = msg->buffer[msg->pos+1];
	}
	else{
		*o = msg->buffer[msg->pos+1];
		*(o+1) = msg->buffer[msg->pos];
	}
	msg->pos+=2;
	return true;
}

bool CDRMessage::readUInt16(CDRMessage_t* msg,uint16_t* i16) {
	if(msg->pos+2>msg->length)
		return false;
	octet* o = (octet*)i16;
	if(msg->msg_endian == DEFAULT_ENDIAN){
		*o = msg->buffer[msg->pos];
		*(o+1) = msg->buffer[msg->pos+1];
	}
	else{
		*o = msg->buffer[msg->pos+1];
		*(o+1) = msg->buffer[msg->pos];
	}
	msg->pos+=2;
	return true;
}

bool CDRMessage::readOctet(CDRMessage_t* msg, octet* o) {
	if(msg->pos+1>msg->length)
		return false;
	*o = msg->buffer[msg->pos];
	msg->pos++;
	return true;
}

bool CDRMessage::addData(CDRMessage_t*msg, octet* data, uint length) {
	if(msg->pos + length > msg->max_size)
	{
		pError( "Message size not enough "<<endl);

		return false;
	}

	memcpy(&msg->buffer[msg->pos],data,length);
	msg->pos +=length;
	msg->length+=length;
	return true;
}

bool CDRMessage::addDataReversed(CDRMessage_t*msg, octet* data, uint length) {
	if(msg->pos + length > msg->max_size)
	{
		pError( "Message size not enough "<<endl);
		return false;
	}
	for(uint i = 0;i<length;i++)
	{
		msg->buffer[msg->pos+i] = *(data+length-1-i);
	}
	msg->pos +=length;
	msg->length+=length;
	return true;
}

bool CDRMessage::addOctet(CDRMessage_t*msg, octet O)
{
	if(msg->pos + 1 > msg->max_size)
	{
		pError( "Message size not enough "<<endl);
		return false;
	}
	//const void* d = (void*)&O;
	msg->buffer[msg->pos] = O;
	msg->pos++;
	msg->length++;
	return true;
}

bool CDRMessage::addUInt16(CDRMessage_t*msg,
		unsigned short U)
{
	if(msg->pos + 2 > msg->max_size)
	{
		pError( "Message size not enough "<<endl);
		return false;
	}
	octet* o= (octet*)&U;
	if(msg->msg_endian == DEFAULT_ENDIAN)
	{
		msg->buffer[msg->pos] = *(o);
		msg->buffer[msg->pos+1] = *(o+1);
	}
	else
	{
		msg->buffer[msg->pos] = *(o+1);
		msg->buffer[msg->pos+1] = *(o);
	}
	msg->pos+=2;
	msg->length+=2;
	return true;
}

bool CDRMessage::addInt32(CDRMessage_t* msg, int32_t lo) {
	octet* o= (octet*)&lo;
	if(msg->pos + 4 > msg->max_size)
	{
		pError( "Message size not enough "<<endl);
		return false;
	}
	if(msg->msg_endian == DEFAULT_ENDIAN)
	{
		for(uint8_t i=0;i<4;i++)
		{
			msg->buffer[msg->pos+i] = *(o+i);
		}
	}
	else
	{
		for(uint8_t i=0;i<4;i++)
		{
			msg->buffer[msg->pos+i] = *(o+3-i);
		}
	}
	msg->pos+=4;
	msg->length+=4;
	return true;
}

bool CDRMessage::addUInt32(CDRMessage_t* msg, uint32_t ulo) {
	octet* o= (octet*)&ulo;
	if(msg->pos + 4 > msg->max_size)
	{
		pError( "Message size not enough "<<endl);
		return false;
	}
	if(msg->msg_endian == DEFAULT_ENDIAN)
	{
		for(uint8_t i=0;i<4;i++)
		{
			msg->buffer[msg->pos+i] = *(o+i);
		}
	}
	else
	{
		for(uint8_t i=0;i<4;i++)
		{
			msg->buffer[msg->pos+i] = *(o+3-i);
		}
	}
	msg->pos+=4;
	msg->length+=4;
	return true;
}

bool CDRMessage::addInt64(CDRMessage_t* msg, int64_t lolo) {
	octet* o= (octet*)&lolo;
	if(msg->pos + 8 > msg->max_size)
	{
		pError( "Message size not enough "<<endl);
		return false;
	}
	if(msg->msg_endian == DEFAULT_ENDIAN)
	{
		for(uint8_t i=0;i<8;i++)
		{
			msg->buffer[msg->pos+i] = *(o+i);
		}
	}
	else
	{
		for(uint8_t i=0;i<8;i++)
		{
			msg->buffer[msg->pos+i] = *(o+7-i);
		}
	}
	msg->pos+=8;
	msg->length+=8;
	return true;
}

bool CDRMessage::addEntityId(CDRMessage_t* msg, EntityId_t*ID) {
	if(msg->pos+4>=msg->max_size)
	{
		pError( "Message size not enough "<<endl);
		return false;
	}
	int* aux1;
	int* aux2;
	aux1 = (int*)(&msg->buffer[msg->pos]);
	aux2 = (int*) ID->value;
	*aux1 = *aux2;
	msg->pos +=4;
	msg->length+=4;
	return true;
}

bool CDRMessage::addSequenceNumber(CDRMessage_t* msg,
		SequenceNumber_t* sn) {
	addInt32(msg,sn->high);
	addUInt32(msg,sn->low);

	return true;
}

bool sort_seqNum (SequenceNumber_t s1,SequenceNumber_t s2)
{
	return(s1.to64long() < s2.to64long());
}

bool CDRMessage::addSequenceNumberSet(CDRMessage_t* msg,
		SequenceNumberSet_t* sns) {
	addSequenceNumber(msg, &sns->base);
	//Add set
	std::sort(sns->set.begin(),sns->set.end(),sort_seqNum);
	SequenceNumber_t maxseqNum = *std::max_element(sns->set.begin(),sns->set.end(),sort_seqNum);
	uint32_t numBits = (uint32_t)(maxseqNum.to64long() - sns->base.to64long());
	addUInt32(msg,numBits);
	std::vector<SequenceNumber_t>::iterator it;
	uint32_t n_octet = 0;
	uint8_t bit_n = 0;
	octet o = 0;
	//Compute the bitmap in terms of octets:
	for(it=sns->set.begin();it!=sns->set.end();it++)
	{
		bit_n = it->to64long()-sns->base.to64long()-n_octet*8;
		switch(bit_n)
		{
			case 0: o= o| BIT(7); break;
			case 1: o= o| BIT(6); break;
			case 2: o= o| BIT(5); break;
			case 3: o= o| BIT(4); break;
			case 4: o= o| BIT(3); break;
			case 5: o= o| BIT(2); break;
			case 6: o= o| BIT(1); break;
			case 7: o= o| BIT(0); break;
		}
		if(bit_n>7)
		{
			addOctet(msg,o);
			o = 0x0;
			for(int i=0;i<(floor(bit_n/8)-1);i++)
				addOctet(msg,o);
			n_octet += floor(bit_n/8);
			it--;
		}
	}
	//add enough octets as gap
	while((n_octet+1)%4 != 0)
	{
		o=0;
		addOctet(msg,o);
	}
	return true;
}

bool CDRMessage::addLocator(CDRMessage_t* msg, Locator_t* loc) {
	addInt32(msg,loc->kind);
	addUInt32(msg,loc->port);

	addData(msg,loc->address,16);

	return true;
}

} /* namespace rtps */
} /* namespace eprosima */

<|endoftext|>


<commit_before>/*
 Copyright (c) 2015 Anon authors, see AUTHORS file.

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
*/

#include "tcp_client.h"
#include "tcp_server.h"
#include "dns_cache.h"
#include <netdb.h>

namespace tcp_client
{

std::pair<int, std::unique_ptr<fiber_pipe>> connect(const struct sockaddr *addr, socklen_t addrlen)
{
  int fd = socket(addr->sa_family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
  if (fd == -1) {
    anon_log("socket(addr->sa_family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0) faied, err: " << error_string(errno));
    return std::make_pair(errno, std::unique_ptr<fiber_pipe>());
  }

  std::unique_ptr<fiber_pipe> pipe(new fiber_pipe(fd, fiber_pipe::network));
  // anon_log("connecting new socket, fd: " << fd);
  auto cr = ::connect(fd, addr, addrlen);

  if (cr == 0)
  {
    anon_log("a little weird, but ok.  non-blocking connect succeeded immediately");
  }
  else if (errno != EINPROGRESS)
  {
    anon_log("connect(fd, " << *addr << ", addrlen) failed, err: " << error_string(errno));
    return std::make_pair(errno, std::unique_ptr<fiber_pipe>());
  }
  else
  {
    // fiber-sleep until connect completes
    io_params::sleep_cur_until_write_possible(pipe.get());

    // anon_log("new socket connected, fd: " << fd);

    // did connect succeed or fail?
    int result;
    socklen_t optlen = sizeof(result);
    if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &result, &optlen) != 0)
      do_error("getsockopt(fd, SOL_SOCKET, SO_ERROR, &result, &optlen)");

    if (result != 0)
    {

#if ANON_LOG_NET_TRAFFIC > 0
      anon_log("async connect(" << *addr << ") completed with error: " << (result > 0 ? error_string(result) : gai_strerror(result)));
#endif

      return std::make_pair(result, std::unique_ptr<fiber_pipe>());
    }
  }

  return std::make_pair(0, std::move(pipe));
}

static void inform(tcp_caller *tcpc, int err_code)
{
  tcpc->exec(err_code, std::unique_ptr<fiber_pipe>());
}

void do_connect_and_run(const char *host, int port, tcp_caller *tcpc, size_t stack_size)
{
  dns_cache::lookup_and_run(host, port, [tcpc](int err_code, const struct sockaddr *addr, socklen_t addrlen) {
    std::unique_ptr<tcp_caller> td(tcpc);

    if (err_code != 0)
      inform(tcpc, err_code);
    else
    {

      int fd = socket(addr->sa_family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
      if (fd == -1)
      {
        anon_log_error("socket(addr->sa_family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)");
        inform(tcpc, errno);
      }

#if defined(ANON_LOG_DNS_LOOKUP)
      anon_log("initiating async connect() to " << *addr);
#endif

      auto cr = connect(fd, addr, addrlen);
      std::unique_ptr<fiber_pipe> pipe(new fiber_pipe(fd, fiber_pipe::network));

      if (cr == 0)
      {

        anon_log("a little weird, but ok.  non-blocking connect succeeded immediately");
      }
      else if (errno != EINPROGRESS)
      {

        inform(tcpc, errno);
      }
      else
      {

        // fiber-sleep until connect completes
        io_params::sleep_cur_until_write_possible(pipe.get());

        // did connect succeed or fail?
        int result;
        socklen_t optlen = sizeof(result);
        if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &result, &optlen) != 0)
        {
          inform(tcpc, errno);
        }

        if (result != 0)
        {

#if ANON_LOG_NET_TRAFFIC > 0
          anon_log("async connect() with fd: " << fd << " completed with error: " << (result > 0 ? error_string(result) : gai_strerror(result)));
#endif

          inform(tcpc, result);
          return;
        }
      }

      // connect succeeded, call the functor
      tcpc->exec(0, std::move(pipe));
    }
  },
                            stack_size);
}

std::pair<int, std::unique_ptr<fiber_pipe>> connect(const char *host, int port)
{
  int err = 0;
  fiber_cond cond;
  fiber_mutex mtx;
  std::unique_ptr<fiber_pipe> fp;

  auto f = [&err, &fp, &mtx, &cond](int err_code, std::unique_ptr<fiber_pipe> &&pipe) {
    fiber_lock lock(mtx);
    err = err_code;
    if (err == 0)
      fp = std::move(pipe);
    cond.notify_all();
  };

  tcp_caller *tcpc = new tcp_call<decltype(f)>(f);
  do_connect_and_run(host, port, tcpc, fiber::k_default_stack_size);

  {
    fiber_lock lock(mtx);
    while (!err && !fp)
      cond.wait(lock);
  }

  return std::make_pair(err, std::move(fp));
}

} // namespace tcp_client
<commit_msg>return early after calling inform on errors<commit_after>/*
 Copyright (c) 2015 Anon authors, see AUTHORS file.

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
*/

#include "tcp_client.h"
#include "tcp_server.h"
#include "dns_cache.h"
#include <netdb.h>

namespace tcp_client
{

std::pair<int, std::unique_ptr<fiber_pipe>> connect(const struct sockaddr *addr, socklen_t addrlen)
{
  int fd = socket(addr->sa_family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
  if (fd == -1) {
    anon_log("socket(addr->sa_family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0) faied, err: " << error_string(errno));
    return std::make_pair(errno, std::unique_ptr<fiber_pipe>());
  }

  std::unique_ptr<fiber_pipe> pipe(new fiber_pipe(fd, fiber_pipe::network));
  // anon_log("connecting new socket, fd: " << fd);
  auto cr = ::connect(fd, addr, addrlen);

  if (cr == 0)
  {
    anon_log("a little weird, but ok.  non-blocking connect succeeded immediately");
  }
  else if (errno != EINPROGRESS)
  {
    anon_log("connect(fd, " << *addr << ", addrlen) failed, err: " << error_string(errno));
    return std::make_pair(errno, std::unique_ptr<fiber_pipe>());
  }
  else
  {
    // fiber-sleep until connect completes
    io_params::sleep_cur_until_write_possible(pipe.get());

    // anon_log("new socket connected, fd: " << fd);

    // did connect succeed or fail?
    int result;
    socklen_t optlen = sizeof(result);
    if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &result, &optlen) != 0)
      do_error("getsockopt(fd, SOL_SOCKET, SO_ERROR, &result, &optlen)");

    if (result != 0)
    {

#if ANON_LOG_NET_TRAFFIC > 0
      anon_log("async connect(" << *addr << ") completed with error: " << (result > 0 ? error_string(result) : gai_strerror(result)));
#endif

      return std::make_pair(result, std::unique_ptr<fiber_pipe>());
    }
  }

  return std::make_pair(0, std::move(pipe));
}

static void inform(tcp_caller *tcpc, int err_code)
{
  tcpc->exec(err_code, std::unique_ptr<fiber_pipe>());
}

void do_connect_and_run(const char *host, int port, tcp_caller *tcpc, size_t stack_size)
{
  dns_cache::lookup_and_run(host, port, [tcpc](int err_code, const struct sockaddr *addr, socklen_t addrlen) {
    std::unique_ptr<tcp_caller> td(tcpc);

    if (err_code != 0) {
      inform(tcpc, err_code);
      return;
    }
    else
    {

      int fd = socket(addr->sa_family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
      if (fd == -1)
      {
        anon_log_error("socket(addr->sa_family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)");
        inform(tcpc, errno);
        return;
      }

#if defined(ANON_LOG_DNS_LOOKUP)
      anon_log("initiating async connect() to " << *addr);
#endif

      auto cr = connect(fd, addr, addrlen);
      std::unique_ptr<fiber_pipe> pipe(new fiber_pipe(fd, fiber_pipe::network));

      if (cr == 0)
      {
        anon_log("a little weird, but ok.  non-blocking connect succeeded immediately");
      }
      else if (errno != EINPROGRESS)
      {
        inform(tcpc, errno);
        return;
      }
      else
      {
        // fiber-sleep until connect completes
        io_params::sleep_cur_until_write_possible(pipe.get());

        // did connect succeed or fail?
        int result;
        socklen_t optlen = sizeof(result);
        if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &result, &optlen) != 0)
        {
          inform(tcpc, errno);
          return;
        }

        if (result != 0)
        {
#if ANON_LOG_NET_TRAFFIC > 0
          anon_log("async connect() with fd: " << fd << " completed with error: " << (result > 0 ? error_string(result) : gai_strerror(result)));
#endif

          inform(tcpc, result);
          return;
        }
      }

      // connect succeeded, call the functor
      tcpc->exec(0, std::move(pipe));
    }
  },
  stack_size);
}

std::pair<int, std::unique_ptr<fiber_pipe>> connect(const char *host, int port)
{
  int err = 0;
  fiber_cond cond;
  fiber_mutex mtx;
  std::unique_ptr<fiber_pipe> fp;

  auto f = [&err, &fp, &mtx, &cond](int err_code, std::unique_ptr<fiber_pipe> &&pipe) {
    fiber_lock lock(mtx);
    err = err_code;
    if (err == 0)
      fp = std::move(pipe);
    cond.notify_all();
  };

  tcp_caller *tcpc = new tcp_call<decltype(f)>(f);
  do_connect_and_run(host, port, tcpc, fiber::k_default_stack_size);

  {
    fiber_lock lock(mtx);
    while (!err && !fp)
      cond.wait(lock);
  }

  return std::make_pair(err, std::move(fp));
}

} // namespace tcp_client
<|endoftext|>


<commit_before>// Copyright (c) 2011 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS.  All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.

#include <cstdio>
#include <cstdlib>
#include <cstring>

// libwebm parser includes
#include "mkvreader.hpp"
#include "mkvparser.hpp"

// libwebm muxer includes
#include "mkvmuxer.hpp"
#include "mkvwriter.hpp"
#include "mkvmuxerutil.hpp"

namespace {

void Usage() {
  printf("Usage: sample_muxer -i input -o output [options]\n");
  printf("\n");
  printf("Main options:\n");
  printf("  -h | -?                     show help\n");
  printf("  -video <int>                >0 outputs video\n");
  printf("  -audio <int>                >0 outputs audio\n");
  printf("  -live <int>                 >0 puts the muxer into live mode\n");
  printf("                              0 puts the muxer into file mode\n");
  printf("  -output_cues <int>          >0 outputs cues element\n");
  printf("  -cues_on_video_track <int>  >0 outputs cues on video track\n");
  printf("  -cues_on_audio_track <int>  >0 outputs cues on audio track\n");
  printf("                              0 outputs cues on audio track\n");
  printf("  -max_cluster_duration <double> in seconds\n");
  printf("  -max_cluster_size <int>     in bytes\n");
  printf("  -switch_tracks <int>        >0 switches tracks in output\n");
  printf("  -audio_track_number <int>   >0 Changes the audio track number\n");
  printf("  -video_track_number <int>   >0 Changes the video track number\n");
  printf("  -chunking <string>          Chunk output\n");
  printf("\n");
  printf("Video options:\n");
  printf("  -display_width <int>        Display width in pixels\n");
  printf("  -display_height <int>       Display height in pixels\n");
  printf("  -stereo_mode <int>          3D video mode\n");
  printf("\n");
  printf("Cues options:\n");
  printf("  -output_cues_block_number <int> >0 outputs cue block number\n");
}

} //end namespace

int main(int argc, char* argv[]) {
  using mkvmuxer::uint64;

  char* input = NULL;
  char* output = NULL;

  // Segment variables
  bool output_video = true;
  bool output_audio = true;
  bool live_mode = false;
  bool output_cues = true;
  bool cues_on_video_track = true;
  bool cues_on_audio_track = true;
  uint64 max_cluster_duration = 0;
  uint64 max_cluster_size = 0;
  bool switch_tracks = false;
  int audio_track_number = 0; // 0 tells muxer to decide.
  int video_track_number = 0; // 0 tells muxer to decide.
  bool chunking = false;
  const char* chunk_name = NULL;

  bool output_cues_block_number = true;

  uint64 display_width = 0;
  uint64 display_height = 0;
  uint64 stereo_mode = 0;

  for (int i = 1; i < argc; ++i) {
    char* end;

    if (!strcmp("-h", argv[i]) || !strcmp("-?", argv[i])) {
      Usage();
      return EXIT_SUCCESS;
    } else if (!strcmp("-i", argv[i])) {
      input = argv[++i];
    } else if (!strcmp("-o", argv[i])) {
      output = argv[++i];
    } else if (!strcmp("-video", argv[i])) {
      output_video = strtol(argv[++i], &end, 10) == 0 ? false : true;
    } else if (!strcmp("-audio", argv[i])) {
      output_audio = strtol(argv[++i], &end, 10) == 0 ? false : true;
    } else if (!strcmp("-live", argv[i])) {
      live_mode = strtol(argv[++i], &end, 10) == 0 ? false : true;
    } else if (!strcmp("-output_cues", argv[i])) {
      output_cues = strtol(argv[++i], &end, 10) == 0 ? false : true;
    } else if (!strcmp("-cues_on_video_track", argv[i])) {
      cues_on_video_track = strtol(argv[++i], &end, 10) == 0 ? false : true;
    } else if (!strcmp("-cues_on_audio_track", argv[i])) {
      cues_on_audio_track = strtol(argv[++i], &end, 10) == 0 ? false : true;
    } else if (!strcmp("-max_cluster_duration", argv[i])) {
      const double seconds = strtod(argv[++i], &end);
      max_cluster_duration =
          static_cast<uint64>(seconds * 1000000000.0);
    } else if (!strcmp("-max_cluster_size", argv[i])) {
      max_cluster_size = strtol(argv[++i], &end, 10);
    } else if (!strcmp("-switch_tracks", argv[i])) {
      switch_tracks = strtol(argv[++i], &end, 10) == 0 ? false : true;
    } else if (!strcmp("-audio_track_number", argv[i])) {
      audio_track_number = strtol(argv[++i], &end, 10);
    } else if (!strcmp("-video_track_number", argv[i])) {
      video_track_number = strtol(argv[++i], &end, 10);
    } else if (!strcmp("-chunking", argv[i])) {
      chunking = true;
      chunk_name = argv[++i];
    } else if (!strcmp("-display_width", argv[i])) {
      display_width = strtol(argv[++i], &end, 10);
    } else if (!strcmp("-display_height", argv[i])) {
      display_height = strtol(argv[++i], &end, 10);
    } else if (!strcmp("-stereo_mode", argv[i])) {
      stereo_mode = strtol(argv[++i], &end, 10);
    } else if (!strcmp("-output_cues_block_number", argv[i])) {
      output_cues_block_number =
          strtol(argv[++i], &end, 10) == 0 ? false : true;
    }
  }

  if (input == NULL || output == NULL) {
    Usage();
    return EXIT_FAILURE;
  }

  // Get parser header info
  mkvparser::MkvReader reader;

  if (reader.Open(input)) {
    printf("\n Filename is invalid or error while opening.\n");
    return EXIT_FAILURE;
  }

  long long pos = 0;
  mkvparser::EBMLHeader ebml_header;
  ebml_header.Parse(&reader, pos);

  mkvparser::Segment* parser_segment;
  long long ret = mkvparser::Segment::CreateInstance(&reader,
                                                     pos,
                                                     parser_segment);
  if (ret) {
    printf("\n Segment::CreateInstance() failed.");
    return EXIT_FAILURE;
  }

  ret = parser_segment->Load();
  if (ret < 0) {
    printf("\n Segment::Load() failed.");
    return EXIT_FAILURE;
  }

  const mkvparser::SegmentInfo* const segment_info = parser_segment->GetInfo();
  const long long timeCodeScale = segment_info->GetTimeCodeScale();

  // Set muxer header info
  mkvmuxer::MkvWriter writer;

  if (!writer.Open(output)) {
    printf("\n Filename is invalid or error while opening.\n");
    return EXIT_FAILURE;
  }

  // Set Segment element attributes
  mkvmuxer::Segment muxer_segment;

  if (!muxer_segment.Init(&writer)) {
    printf("\n Could not initialize muxer segment!\n");
    return EXIT_FAILURE;
  }

  if (live_mode)
    muxer_segment.set_mode(mkvmuxer::Segment::kLive);
  else
    muxer_segment.set_mode(mkvmuxer::Segment::kFile);

  if (chunking)
    muxer_segment.SetChunking(true, chunk_name);

  if (max_cluster_duration > 0)
    muxer_segment.set_max_cluster_duration(max_cluster_duration);
  if (max_cluster_size > 0)
    muxer_segment.set_max_cluster_size(max_cluster_size);
  muxer_segment.OutputCues(output_cues);

  // Set SegmentInfo element attributes
  mkvmuxer::SegmentInfo* const info = muxer_segment.GetSegmentInfo();
  info->set_timecode_scale(timeCodeScale);
  info->set_writing_app("sample_muxer");

  // Set Tracks element attributes
  enum { kVideoTrack = 1, kAudioTrack = 2 };
  const mkvparser::Tracks* const parser_tracks = parser_segment->GetTracks();
  unsigned long i = 0;
  uint64 vid_track = 0; // no track added
  uint64 aud_track = 0; // no track added

  while (i != parser_tracks->GetTracksCount()) {
    int track_num = i++;
    if (switch_tracks)
      track_num = i % parser_tracks->GetTracksCount();

    const mkvparser::Track* const parser_track =
        parser_tracks->GetTrackByIndex(track_num);

    if (parser_track == NULL)
      continue;

    // TODO(fgalligan): Add support for language to parser.
    const char* const track_name = parser_track->GetNameAsUTF8();

    const long long track_type = parser_track->GetType();

    if (track_type == kVideoTrack && output_video) {
      // Get the video track from the parser
      const mkvparser::VideoTrack* const pVideoTrack =
          static_cast<const mkvparser::VideoTrack*>(parser_track);
      const long long width =  pVideoTrack->GetWidth();
      const long long height = pVideoTrack->GetHeight();

      // Add the video track to the muxer
      vid_track = muxer_segment.AddVideoTrack(static_cast<int>(width),
                                              static_cast<int>(height),
                                              video_track_number);
      if (!vid_track) {
        printf("\n Could not add video track.\n");
        return EXIT_FAILURE;
      }

      mkvmuxer::VideoTrack* const video =
          static_cast<mkvmuxer::VideoTrack*>(
              muxer_segment.GetTrackByNumber(vid_track));
      if (!video) {
        printf("\n Could not get video track.\n");
        return EXIT_FAILURE;
      }

      if (track_name)
        video->set_name(track_name);

      if (display_width > 0)
        video->set_display_width(display_width);
      if (display_height > 0)
        video->set_display_height(display_height);
      if (stereo_mode > 0)
        video->SetStereoMode(stereo_mode);

      const double rate = pVideoTrack->GetFrameRate();
      if (rate > 0.0) {
        video->set_frame_rate(rate);
      }
    } else if (track_type == kAudioTrack && output_audio) {
      // Get the audio track from the parser
      const mkvparser::AudioTrack* const pAudioTrack =
          static_cast<const mkvparser::AudioTrack*>(parser_track);
      const long long channels =  pAudioTrack->GetChannels();
      const double sample_rate = pAudioTrack->GetSamplingRate();

      // Add the audio track to the muxer
      aud_track = muxer_segment.AddAudioTrack(static_cast<int>(sample_rate),
                                              static_cast<int>(channels),
                                              audio_track_number);
      if (!aud_track) {
        printf("\n Could not add audio track.\n");
        return EXIT_FAILURE;
      }

      mkvmuxer::AudioTrack* const audio =
          static_cast<mkvmuxer::AudioTrack*>(
              muxer_segment.GetTrackByNumber(aud_track));
      if (!audio) {
        printf("\n Could not get audio track.\n");
        return EXIT_FAILURE;
      }

      if (track_name)
        audio->set_name(track_name);

      size_t private_size;
      const unsigned char* const private_data =
          pAudioTrack->GetCodecPrivate(private_size);
      if (private_size > 0) {
        if (!audio->SetCodecPrivate(private_data, private_size)) {
          printf("\n Could not add audio private data.\n");
          return EXIT_FAILURE;
        }
      }

      const long long bit_depth = pAudioTrack->GetBitDepth();
      if (bit_depth > 0)
        audio->set_bit_depth(bit_depth);
    }
  }

  // Set Cues element attributes
  mkvmuxer::Cues* const cues = muxer_segment.GetCues();
  cues->set_output_block_number(output_cues_block_number);
  if (cues_on_video_track && vid_track)
    muxer_segment.CuesTrack(vid_track);
  if (cues_on_audio_track && aud_track)
    muxer_segment.CuesTrack(aud_track);

  // Write clusters
  unsigned char* data = NULL;
  int data_len = 0;

  const mkvparser::Cluster* cluster = parser_segment->GetFirst();

  while ((cluster != NULL) && !cluster->EOS()) {
    const mkvparser::BlockEntry* block_entry;

    long status = cluster->GetFirst(block_entry);

    if (status)
    {
        printf("\n Could not get first block of cluster.\n");
        return EXIT_FAILURE;
    }

    while ((block_entry != NULL) && !block_entry->EOS()) {
      const mkvparser::Block* const block = block_entry->GetBlock();
      const long long trackNum = block->GetTrackNumber();
      const mkvparser::Track* const parser_track =
          parser_tracks->GetTrackByNumber(
              static_cast<unsigned long>(trackNum));
      const long long track_type = parser_track->GetType();

      if ((track_type == kAudioTrack && output_audio) ||
          (track_type == kVideoTrack && output_video)) {
        const int frame_count = block->GetFrameCount();
        const long long time_ns = block->GetTime(cluster);
        const bool is_key = block->IsKey();

        for (int i = 0; i < frame_count; ++i) {
          const mkvparser::Block::Frame& frame = block->GetFrame(i);

          if (frame.len > data_len) {
            delete [] data;
            data = new unsigned char[frame.len];
            if (!data)
              return EXIT_FAILURE;
            data_len = frame.len;
          }

          if (frame.Read(&reader, data))
            return EXIT_FAILURE;

          uint64 track_num = vid_track;
          if (track_type == kAudioTrack)
            track_num = aud_track;

          if (!muxer_segment.AddFrame(data,
                                      frame.len,
                                      track_num,
                                      time_ns,
                                      is_key)) {
            printf("\n Could not add frame.\n");
            return EXIT_FAILURE;
          }
        }
      }

      status = cluster->GetNext(block_entry, block_entry);

      if (status)
      {
          printf("\n Could not get next block of cluster.\n");
          return EXIT_FAILURE;
      }
    }

    cluster = parser_segment->GetNext(cluster);
  }

  muxer_segment.Finalize();

  delete [] data;
  delete parser_segment;

  writer.Close();
  reader.Close();

  return EXIT_SUCCESS;
}

<commit_msg>sample_muxer: Fixed bug with outputting audio cues.<commit_after>// Copyright (c) 2011 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS.  All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.

#include <cstdio>
#include <cstdlib>
#include <cstring>

// libwebm parser includes
#include "mkvreader.hpp"
#include "mkvparser.hpp"

// libwebm muxer includes
#include "mkvmuxer.hpp"
#include "mkvwriter.hpp"
#include "mkvmuxerutil.hpp"

namespace {

void Usage() {
  printf("Usage: sample_muxer -i input -o output [options]\n");
  printf("\n");
  printf("Main options:\n");
  printf("  -h | -?                     show help\n");
  printf("  -video <int>                >0 outputs video\n");
  printf("  -audio <int>                >0 outputs audio\n");
  printf("  -live <int>                 >0 puts the muxer into live mode\n");
  printf("                              0 puts the muxer into file mode\n");
  printf("  -output_cues <int>          >0 outputs cues element\n");
  printf("  -cues_on_video_track <int>  >0 outputs cues on video track\n");
  printf("  -cues_on_audio_track <int>  >0 outputs cues on audio track\n");
  printf("  -max_cluster_duration <double> in seconds\n");
  printf("  -max_cluster_size <int>     in bytes\n");
  printf("  -switch_tracks <int>        >0 switches tracks in output\n");
  printf("  -audio_track_number <int>   >0 Changes the audio track number\n");
  printf("  -video_track_number <int>   >0 Changes the video track number\n");
  printf("  -chunking <string>          Chunk output\n");
  printf("\n");
  printf("Video options:\n");
  printf("  -display_width <int>        Display width in pixels\n");
  printf("  -display_height <int>       Display height in pixels\n");
  printf("  -stereo_mode <int>          3D video mode\n");
  printf("\n");
  printf("Cues options:\n");
  printf("  -output_cues_block_number <int> >0 outputs cue block number\n");
}

} //end namespace

int main(int argc, char* argv[]) {
  using mkvmuxer::uint64;

  char* input = NULL;
  char* output = NULL;

  // Segment variables
  bool output_video = true;
  bool output_audio = true;
  bool live_mode = false;
  bool output_cues = true;
  bool cues_on_video_track = true;
  bool cues_on_audio_track = false;
  uint64 max_cluster_duration = 0;
  uint64 max_cluster_size = 0;
  bool switch_tracks = false;
  int audio_track_number = 0; // 0 tells muxer to decide.
  int video_track_number = 0; // 0 tells muxer to decide.
  bool chunking = false;
  const char* chunk_name = NULL;

  bool output_cues_block_number = true;

  uint64 display_width = 0;
  uint64 display_height = 0;
  uint64 stereo_mode = 0;

  const int argc_check = argc - 1;
  for (int i = 1; i < argc; ++i) {
    char* end;

    if (!strcmp("-h", argv[i]) || !strcmp("-?", argv[i])) {
      Usage();
      return EXIT_SUCCESS;
    } else if (!strcmp("-i", argv[i]) && i < argc_check) {
      input = argv[++i];
    } else if (!strcmp("-o", argv[i]) && i < argc_check) {
      output = argv[++i];
    } else if (!strcmp("-video", argv[i]) && i < argc_check) {
      output_video = strtol(argv[++i], &end, 10) == 0 ? false : true;
    } else if (!strcmp("-audio", argv[i]) && i < argc_check) {
      output_audio = strtol(argv[++i], &end, 10) == 0 ? false : true;
    } else if (!strcmp("-live", argv[i]) && i < argc_check) {
      live_mode = strtol(argv[++i], &end, 10) == 0 ? false : true;
    } else if (!strcmp("-output_cues", argv[i]) && i < argc_check) {
      output_cues = strtol(argv[++i], &end, 10) == 0 ? false : true;
    } else if (!strcmp("-cues_on_video_track", argv[i]) && i < argc_check) {
      cues_on_video_track = strtol(argv[++i], &end, 10) == 0 ? false : true;
      if (cues_on_video_track)
        cues_on_audio_track = false;
    } else if (!strcmp("-cues_on_audio_track", argv[i]) && i < argc_check) {
      cues_on_audio_track = strtol(argv[++i], &end, 10) == 0 ? false : true;
      if (cues_on_audio_track)
        cues_on_video_track = false;
    } else if (!strcmp("-max_cluster_duration", argv[i]) && i < argc_check) {
      const double seconds = strtod(argv[++i], &end);
      max_cluster_duration =
          static_cast<uint64>(seconds * 1000000000.0);
    } else if (!strcmp("-max_cluster_size", argv[i]) && i < argc_check) {
      max_cluster_size = strtol(argv[++i], &end, 10);
    } else if (!strcmp("-switch_tracks", argv[i]) && i < argc_check) {
      switch_tracks = strtol(argv[++i], &end, 10) == 0 ? false : true;
    } else if (!strcmp("-audio_track_number", argv[i]) && i < argc_check) {
      audio_track_number = strtol(argv[++i], &end, 10);
    } else if (!strcmp("-video_track_number", argv[i]) && i < argc_check) {
      video_track_number = strtol(argv[++i], &end, 10);
    } else if (!strcmp("-chunking", argv[i]) && i < argc_check) {
      chunking = true;
      chunk_name = argv[++i];
    } else if (!strcmp("-display_width", argv[i]) && i < argc_check) {
      display_width = strtol(argv[++i], &end, 10);
    } else if (!strcmp("-display_height", argv[i]) && i < argc_check) {
      display_height = strtol(argv[++i], &end, 10);
    } else if (!strcmp("-stereo_mode", argv[i]) && i < argc_check) {
      stereo_mode = strtol(argv[++i], &end, 10);
    } else if (!strcmp("-output_cues_block_number", argv[i]) &&
               i < argc_check) {
      output_cues_block_number =
          strtol(argv[++i], &end, 10) == 0 ? false : true;
    }
  }

  if (input == NULL || output == NULL) {
    Usage();
    return EXIT_FAILURE;
  }

  // Get parser header info
  mkvparser::MkvReader reader;

  if (reader.Open(input)) {
    printf("\n Filename is invalid or error while opening.\n");
    return EXIT_FAILURE;
  }

  long long pos = 0;
  mkvparser::EBMLHeader ebml_header;
  ebml_header.Parse(&reader, pos);

  mkvparser::Segment* parser_segment;
  long long ret = mkvparser::Segment::CreateInstance(&reader,
                                                     pos,
                                                     parser_segment);
  if (ret) {
    printf("\n Segment::CreateInstance() failed.");
    return EXIT_FAILURE;
  }

  ret = parser_segment->Load();
  if (ret < 0) {
    printf("\n Segment::Load() failed.");
    return EXIT_FAILURE;
  }

  const mkvparser::SegmentInfo* const segment_info = parser_segment->GetInfo();
  const long long timeCodeScale = segment_info->GetTimeCodeScale();

  // Set muxer header info
  mkvmuxer::MkvWriter writer;

  if (!writer.Open(output)) {
    printf("\n Filename is invalid or error while opening.\n");
    return EXIT_FAILURE;
  }

  // Set Segment element attributes
  mkvmuxer::Segment muxer_segment;

  if (!muxer_segment.Init(&writer)) {
    printf("\n Could not initialize muxer segment!\n");
    return EXIT_FAILURE;
  }

  if (live_mode)
    muxer_segment.set_mode(mkvmuxer::Segment::kLive);
  else
    muxer_segment.set_mode(mkvmuxer::Segment::kFile);

  if (chunking)
    muxer_segment.SetChunking(true, chunk_name);

  if (max_cluster_duration > 0)
    muxer_segment.set_max_cluster_duration(max_cluster_duration);
  if (max_cluster_size > 0)
    muxer_segment.set_max_cluster_size(max_cluster_size);
  muxer_segment.OutputCues(output_cues);

  // Set SegmentInfo element attributes
  mkvmuxer::SegmentInfo* const info = muxer_segment.GetSegmentInfo();
  info->set_timecode_scale(timeCodeScale);
  info->set_writing_app("sample_muxer");

  // Set Tracks element attributes
  enum { kVideoTrack = 1, kAudioTrack = 2 };
  const mkvparser::Tracks* const parser_tracks = parser_segment->GetTracks();
  unsigned long i = 0;
  uint64 vid_track = 0; // no track added
  uint64 aud_track = 0; // no track added

  while (i != parser_tracks->GetTracksCount()) {
    int track_num = i++;
    if (switch_tracks)
      track_num = i % parser_tracks->GetTracksCount();

    const mkvparser::Track* const parser_track =
        parser_tracks->GetTrackByIndex(track_num);

    if (parser_track == NULL)
      continue;

    // TODO(fgalligan): Add support for language to parser.
    const char* const track_name = parser_track->GetNameAsUTF8();

    const long long track_type = parser_track->GetType();

    if (track_type == kVideoTrack && output_video) {
      // Get the video track from the parser
      const mkvparser::VideoTrack* const pVideoTrack =
          static_cast<const mkvparser::VideoTrack*>(parser_track);
      const long long width =  pVideoTrack->GetWidth();
      const long long height = pVideoTrack->GetHeight();

      // Add the video track to the muxer
      vid_track = muxer_segment.AddVideoTrack(static_cast<int>(width),
                                              static_cast<int>(height),
                                              video_track_number);
      if (!vid_track) {
        printf("\n Could not add video track.\n");
        return EXIT_FAILURE;
      }

      mkvmuxer::VideoTrack* const video =
          static_cast<mkvmuxer::VideoTrack*>(
              muxer_segment.GetTrackByNumber(vid_track));
      if (!video) {
        printf("\n Could not get video track.\n");
        return EXIT_FAILURE;
      }

      if (track_name)
        video->set_name(track_name);

      if (display_width > 0)
        video->set_display_width(display_width);
      if (display_height > 0)
        video->set_display_height(display_height);
      if (stereo_mode > 0)
        video->SetStereoMode(stereo_mode);

      const double rate = pVideoTrack->GetFrameRate();
      if (rate > 0.0) {
        video->set_frame_rate(rate);
      }
    } else if (track_type == kAudioTrack && output_audio) {
      // Get the audio track from the parser
      const mkvparser::AudioTrack* const pAudioTrack =
          static_cast<const mkvparser::AudioTrack*>(parser_track);
      const long long channels =  pAudioTrack->GetChannels();
      const double sample_rate = pAudioTrack->GetSamplingRate();

      // Add the audio track to the muxer
      aud_track = muxer_segment.AddAudioTrack(static_cast<int>(sample_rate),
                                              static_cast<int>(channels),
                                              audio_track_number);
      if (!aud_track) {
        printf("\n Could not add audio track.\n");
        return EXIT_FAILURE;
      }

      mkvmuxer::AudioTrack* const audio =
          static_cast<mkvmuxer::AudioTrack*>(
              muxer_segment.GetTrackByNumber(aud_track));
      if (!audio) {
        printf("\n Could not get audio track.\n");
        return EXIT_FAILURE;
      }

      if (track_name)
        audio->set_name(track_name);

      size_t private_size;
      const unsigned char* const private_data =
          pAudioTrack->GetCodecPrivate(private_size);
      if (private_size > 0) {
        if (!audio->SetCodecPrivate(private_data, private_size)) {
          printf("\n Could not add audio private data.\n");
          return EXIT_FAILURE;
        }
      }

      const long long bit_depth = pAudioTrack->GetBitDepth();
      if (bit_depth > 0)
        audio->set_bit_depth(bit_depth);
    }
  }

  // Set Cues element attributes
  mkvmuxer::Cues* const cues = muxer_segment.GetCues();
  cues->set_output_block_number(output_cues_block_number);
  if (cues_on_video_track && vid_track)
    muxer_segment.CuesTrack(vid_track);
  if (cues_on_audio_track && aud_track)
    muxer_segment.CuesTrack(aud_track);

  // Write clusters
  unsigned char* data = NULL;
  int data_len = 0;

  const mkvparser::Cluster* cluster = parser_segment->GetFirst();

  while ((cluster != NULL) && !cluster->EOS()) {
    const mkvparser::BlockEntry* block_entry;

    long status = cluster->GetFirst(block_entry);

    if (status)
    {
        printf("\n Could not get first block of cluster.\n");
        return EXIT_FAILURE;
    }

    while ((block_entry != NULL) && !block_entry->EOS()) {
      const mkvparser::Block* const block = block_entry->GetBlock();
      const long long trackNum = block->GetTrackNumber();
      const mkvparser::Track* const parser_track =
          parser_tracks->GetTrackByNumber(
              static_cast<unsigned long>(trackNum));
      const long long track_type = parser_track->GetType();

      if ((track_type == kAudioTrack && output_audio) ||
          (track_type == kVideoTrack && output_video)) {
        const int frame_count = block->GetFrameCount();
        const long long time_ns = block->GetTime(cluster);
        const bool is_key = block->IsKey();

        for (int i = 0; i < frame_count; ++i) {
          const mkvparser::Block::Frame& frame = block->GetFrame(i);

          if (frame.len > data_len) {
            delete [] data;
            data = new unsigned char[frame.len];
            if (!data)
              return EXIT_FAILURE;
            data_len = frame.len;
          }

          if (frame.Read(&reader, data))
            return EXIT_FAILURE;

          uint64 track_num = vid_track;
          if (track_type == kAudioTrack)
            track_num = aud_track;

          if (!muxer_segment.AddFrame(data,
                                      frame.len,
                                      track_num,
                                      time_ns,
                                      is_key)) {
            printf("\n Could not add frame.\n");
            return EXIT_FAILURE;
          }
        }
      }

      status = cluster->GetNext(block_entry, block_entry);

      if (status)
      {
          printf("\n Could not get next block of cluster.\n");
          return EXIT_FAILURE;
      }
    }

    cluster = parser_segment->GetNext(cluster);
  }

  muxer_segment.Finalize();

  delete [] data;
  delete parser_segment;

  writer.Close();
  reader.Close();

  return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2005-2006 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * 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;
 * neither the name of the copyright holders 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
 * OWNER 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.
 *
 * Authors: Korey Sewell
 */

#include <algorithm>
#include <list>
#include <string>

#include "cpu/o3/lsq.hh"

template <class Impl>
Tick
LSQ<Impl>::DcachePort::recvAtomic(PacketPtr pkt)
{
    panic("O3CPU model does not work with atomic mode!");
    return curTick;
}

template <class Impl>
void
LSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt)
{
    DPRINTF(LSQ, "LSQ doesn't update things on a recvFunctional.");
}

template <class Impl>
void
LSQ<Impl>::DcachePort::recvStatusChange(Status status)
{
    if (status == RangeChange) {
        if (!snoopRangeSent) {
            snoopRangeSent = true;
            sendStatusChange(Port::RangeChange);
        }
        return;
    }
    panic("O3CPU doesn't expect recvStatusChange callback!");
}

template <class Impl>
bool
LSQ<Impl>::DcachePort::recvTiming(PacketPtr pkt)
{
    if (pkt->isResponse()) {
        lsq->thread[pkt->req->getThreadNum()].completeDataAccess(pkt);
    }
    else {
    //else it is a coherence request, maybe you need to do something
        warn("Recieved a coherence request (Invalidate?), 03CPU doesn't"
             "update LSQ for these\n");
    }
    return true;
}

template <class Impl>
void
LSQ<Impl>::DcachePort::recvRetry()
{
    if (lsq->retryTid == -1)
    {
        //Squashed, so drop it
        return;
    }
    lsq->thread[lsq->retryTid].recvRetry();
    // Speculatively clear the retry Tid.  This will get set again if
    // the LSQUnit was unable to complete its access.
    lsq->retryTid = -1;
}

template <class Impl>
LSQ<Impl>::LSQ(Params *params)
    : dcachePort(this), LQEntries(params->LQEntries),
      SQEntries(params->SQEntries), numThreads(params->numberOfThreads),
      retryTid(-1)
{
    DPRINTF(LSQ, "Creating LSQ object.\n");

    dcachePort.snoopRangeSent = false;

    //**********************************************/
    //************ Handle SMT Parameters ***********/
    //**********************************************/
    std::string policy = params->smtLSQPolicy;

    //Convert string to lowercase
    std::transform(policy.begin(), policy.end(), policy.begin(),
                   (int(*)(int)) tolower);

    //Figure out fetch policy
    if (policy == "dynamic") {
        lsqPolicy = Dynamic;

        maxLQEntries = LQEntries;
        maxSQEntries = SQEntries;

        DPRINTF(LSQ, "LSQ sharing policy set to Dynamic\n");

    } else if (policy == "partitioned") {
        lsqPolicy = Partitioned;

        //@todo:make work if part_amt doesnt divide evenly.
        maxLQEntries = LQEntries / numThreads;
        maxSQEntries = SQEntries / numThreads;

        DPRINTF(Fetch, "LSQ sharing policy set to Partitioned: "
                "%i entries per LQ | %i entries per SQ",
                maxLQEntries,maxSQEntries);

    } else if (policy == "threshold") {
        lsqPolicy = Threshold;

        assert(params->smtLSQThreshold > LQEntries);
        assert(params->smtLSQThreshold > SQEntries);

        //Divide up by threshold amount
        //@todo: Should threads check the max and the total
        //amount of the LSQ
        maxLQEntries  = params->smtLSQThreshold;
        maxSQEntries  = params->smtLSQThreshold;

        DPRINTF(LSQ, "LSQ sharing policy set to Threshold: "
                "%i entries per LQ | %i entries per SQ",
                maxLQEntries,maxSQEntries);

    } else {
        assert(0 && "Invalid LSQ Sharing Policy.Options Are:{Dynamic,"
                    "Partitioned, Threshold}");
    }

    //Initialize LSQs
    for (int tid=0; tid < numThreads; tid++) {
        thread[tid].init(params, this, maxLQEntries, maxSQEntries, tid);
        thread[tid].setDcachePort(&dcachePort);
    }
}

template<class Impl>
std::string
LSQ<Impl>::name() const
{
    return iewStage->name() + ".lsq";
}

template<class Impl>
void
LSQ<Impl>::regStats()
{
    //Initialize LSQs
    for (int tid=0; tid < numThreads; tid++) {
        thread[tid].regStats();
    }
}

template<class Impl>
void
LSQ<Impl>::setActiveThreads(std::list<unsigned> *at_ptr)
{
    activeThreads = at_ptr;
    assert(activeThreads != 0);
}

template<class Impl>
void
LSQ<Impl>::setCPU(O3CPU *cpu_ptr)
{
    cpu = cpu_ptr;

    dcachePort.setName(name());

    for (int tid=0; tid < numThreads; tid++) {
        thread[tid].setCPU(cpu_ptr);
    }
}

template<class Impl>
void
LSQ<Impl>::setIEW(IEW *iew_ptr)
{
    iewStage = iew_ptr;

    for (int tid=0; tid < numThreads; tid++) {
        thread[tid].setIEW(iew_ptr);
    }
}

template <class Impl>
void
LSQ<Impl>::switchOut()
{
    for (int tid = 0; tid < numThreads; tid++) {
        thread[tid].switchOut();
    }
}

template <class Impl>
void
LSQ<Impl>::takeOverFrom()
{
    for (int tid = 0; tid < numThreads; tid++) {
        thread[tid].takeOverFrom();
    }
}

template <class Impl>
int
LSQ<Impl>::entryAmount(int num_threads)
{
    if (lsqPolicy == Partitioned) {
        return LQEntries / num_threads;
    } else {
        return 0;
    }
}

template <class Impl>
void
LSQ<Impl>::resetEntries()
{
    if (lsqPolicy != Dynamic || numThreads > 1) {
        int active_threads = activeThreads->size();

        int maxEntries;

        if (lsqPolicy == Partitioned) {
            maxEntries = LQEntries / active_threads;
        } else if (lsqPolicy == Threshold && active_threads == 1) {
            maxEntries = LQEntries;
        } else {
            maxEntries = LQEntries;
        }

        std::list<unsigned>::iterator threads  = activeThreads->begin();
        std::list<unsigned>::iterator end = activeThreads->end();

        while (threads != end) {
            unsigned tid = *threads++;

            resizeEntries(maxEntries, tid);
        }
    }
}

template<class Impl>
void
LSQ<Impl>::removeEntries(unsigned tid)
{
    thread[tid].clearLQ();
    thread[tid].clearSQ();
}

template<class Impl>
void
LSQ<Impl>::resizeEntries(unsigned size,unsigned tid)
{
    thread[tid].resizeLQ(size);
    thread[tid].resizeSQ(size);
}

template<class Impl>
void
LSQ<Impl>::tick()
{
    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        thread[tid].tick();
    }
}

template<class Impl>
void
LSQ<Impl>::insertLoad(DynInstPtr &load_inst)
{
    unsigned tid = load_inst->threadNumber;

    thread[tid].insertLoad(load_inst);
}

template<class Impl>
void
LSQ<Impl>::insertStore(DynInstPtr &store_inst)
{
    unsigned tid = store_inst->threadNumber;

    thread[tid].insertStore(store_inst);
}

template<class Impl>
Fault
LSQ<Impl>::executeLoad(DynInstPtr &inst)
{
    unsigned tid = inst->threadNumber;

    return thread[tid].executeLoad(inst);
}

template<class Impl>
Fault
LSQ<Impl>::executeStore(DynInstPtr &inst)
{
    unsigned tid = inst->threadNumber;

    return thread[tid].executeStore(inst);
}

template<class Impl>
void
LSQ<Impl>::writebackStores()
{
    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        if (numStoresToWB(tid) > 0) {
            DPRINTF(Writeback,"[tid:%i] Writing back stores. %i stores "
                "available for Writeback.\n", tid, numStoresToWB(tid));
        }

        thread[tid].writebackStores();
    }
}

template<class Impl>
bool
LSQ<Impl>::violation()
{
    /* Answers: Does Anybody Have a Violation?*/
    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        if (thread[tid].violation())
            return true;
    }

    return false;
}

template<class Impl>
int
LSQ<Impl>::getCount()
{
    unsigned total = 0;

    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        total += getCount(tid);
    }

    return total;
}

template<class Impl>
int
LSQ<Impl>::numLoads()
{
    unsigned total = 0;

    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        total += numLoads(tid);
    }

    return total;
}

template<class Impl>
int
LSQ<Impl>::numStores()
{
    unsigned total = 0;

    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        total += thread[tid].numStores();
    }

    return total;
}

template<class Impl>
int
LSQ<Impl>::numLoadsReady()
{
    unsigned total = 0;

    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        total += thread[tid].numLoadsReady();
    }

    return total;
}

template<class Impl>
unsigned
LSQ<Impl>::numFreeEntries()
{
    unsigned total = 0;

    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        total += thread[tid].numFreeEntries();
    }

    return total;
}

template<class Impl>
unsigned
LSQ<Impl>::numFreeEntries(unsigned tid)
{
    //if( lsqPolicy == Dynamic )
    //return numFreeEntries();
    //else
        return thread[tid].numFreeEntries();
}

template<class Impl>
bool
LSQ<Impl>::isFull()
{
    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        if (!(thread[tid].lqFull() || thread[tid].sqFull()))
            return false;
    }

    return true;
}

template<class Impl>
bool
LSQ<Impl>::isFull(unsigned tid)
{
    //@todo: Change to Calculate All Entries for
    //Dynamic Policy
    if (lsqPolicy == Dynamic)
        return isFull();
    else
        return thread[tid].lqFull() || thread[tid].sqFull();
}

template<class Impl>
bool
LSQ<Impl>::lqFull()
{
    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        if (!thread[tid].lqFull())
            return false;
    }

    return true;
}

template<class Impl>
bool
LSQ<Impl>::lqFull(unsigned tid)
{
    //@todo: Change to Calculate All Entries for
    //Dynamic Policy
    if( lsqPolicy == Dynamic )
        return lqFull();
    else
        return thread[tid].lqFull();
}

template<class Impl>
bool
LSQ<Impl>::sqFull()
{
    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        if (!sqFull(tid))
            return false;
    }

    return true;
}

template<class Impl>
bool
LSQ<Impl>::sqFull(unsigned tid)
{
     //@todo: Change to Calculate All Entries for
    //Dynamic Policy
    if( lsqPolicy == Dynamic )
        return sqFull();
    else
        return thread[tid].sqFull();
}

template<class Impl>
bool
LSQ<Impl>::isStalled()
{
    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        if (!thread[tid].isStalled())
            return false;
    }

    return true;
}

template<class Impl>
bool
LSQ<Impl>::isStalled(unsigned tid)
{
    if( lsqPolicy == Dynamic )
        return isStalled();
    else
        return thread[tid].isStalled();
}

template<class Impl>
bool
LSQ<Impl>::hasStoresToWB()
{
    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    if (threads == end)
        return false;

    while (threads != end) {
        unsigned tid = *threads++;

        if (!hasStoresToWB(tid))
            return false;
    }

    return true;
}

template<class Impl>
bool
LSQ<Impl>::willWB()
{
    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        if (!willWB(tid))
            return false;
    }

    return true;
}

template<class Impl>
void
LSQ<Impl>::dumpInsts()
{
    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        thread[tid].dumpInsts();
    }
}
<commit_msg>style<commit_after>/*
 * Copyright (c) 2005-2006 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * 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;
 * neither the name of the copyright holders 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
 * OWNER 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.
 *
 * Authors: Korey Sewell
 */

#include <algorithm>
#include <list>
#include <string>

#include "cpu/o3/lsq.hh"

template <class Impl>
Tick
LSQ<Impl>::DcachePort::recvAtomic(PacketPtr pkt)
{
    panic("O3CPU model does not work with atomic mode!");
    return curTick;
}

template <class Impl>
void
LSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt)
{
    DPRINTF(LSQ, "LSQ doesn't update things on a recvFunctional.");
}

template <class Impl>
void
LSQ<Impl>::DcachePort::recvStatusChange(Status status)
{
    if (status == RangeChange) {
        if (!snoopRangeSent) {
            snoopRangeSent = true;
            sendStatusChange(Port::RangeChange);
        }
        return;
    }
    panic("O3CPU doesn't expect recvStatusChange callback!");
}

template <class Impl>
bool
LSQ<Impl>::DcachePort::recvTiming(PacketPtr pkt)
{
    if (pkt->isResponse()) {
        lsq->thread[pkt->req->getThreadNum()].completeDataAccess(pkt);
    }
    else {
    //else it is a coherence request, maybe you need to do something
        warn("Recieved a coherence request (Invalidate?), 03CPU doesn't"
             "update LSQ for these\n");
    }
    return true;
}

template <class Impl>
void
LSQ<Impl>::DcachePort::recvRetry()
{
    if (lsq->retryTid == -1)
    {
        //Squashed, so drop it
        return;
    }
    lsq->thread[lsq->retryTid].recvRetry();
    // Speculatively clear the retry Tid.  This will get set again if
    // the LSQUnit was unable to complete its access.
    lsq->retryTid = -1;
}

template <class Impl>
LSQ<Impl>::LSQ(Params *params)
    : dcachePort(this), LQEntries(params->LQEntries),
      SQEntries(params->SQEntries), numThreads(params->numberOfThreads),
      retryTid(-1)
{
    DPRINTF(LSQ, "Creating LSQ object.\n");

    dcachePort.snoopRangeSent = false;

    //**********************************************/
    //************ Handle SMT Parameters ***********/
    //**********************************************/
    std::string policy = params->smtLSQPolicy;

    //Convert string to lowercase
    std::transform(policy.begin(), policy.end(), policy.begin(),
                   (int(*)(int)) tolower);

    //Figure out fetch policy
    if (policy == "dynamic") {
        lsqPolicy = Dynamic;

        maxLQEntries = LQEntries;
        maxSQEntries = SQEntries;

        DPRINTF(LSQ, "LSQ sharing policy set to Dynamic\n");

    } else if (policy == "partitioned") {
        lsqPolicy = Partitioned;

        //@todo:make work if part_amt doesnt divide evenly.
        maxLQEntries = LQEntries / numThreads;
        maxSQEntries = SQEntries / numThreads;

        DPRINTF(Fetch, "LSQ sharing policy set to Partitioned: "
                "%i entries per LQ | %i entries per SQ",
                maxLQEntries,maxSQEntries);

    } else if (policy == "threshold") {
        lsqPolicy = Threshold;

        assert(params->smtLSQThreshold > LQEntries);
        assert(params->smtLSQThreshold > SQEntries);

        //Divide up by threshold amount
        //@todo: Should threads check the max and the total
        //amount of the LSQ
        maxLQEntries  = params->smtLSQThreshold;
        maxSQEntries  = params->smtLSQThreshold;

        DPRINTF(LSQ, "LSQ sharing policy set to Threshold: "
                "%i entries per LQ | %i entries per SQ",
                maxLQEntries,maxSQEntries);

    } else {
        assert(0 && "Invalid LSQ Sharing Policy.Options Are:{Dynamic,"
                    "Partitioned, Threshold}");
    }

    //Initialize LSQs
    for (int tid=0; tid < numThreads; tid++) {
        thread[tid].init(params, this, maxLQEntries, maxSQEntries, tid);
        thread[tid].setDcachePort(&dcachePort);
    }
}

template<class Impl>
std::string
LSQ<Impl>::name() const
{
    return iewStage->name() + ".lsq";
}

template<class Impl>
void
LSQ<Impl>::regStats()
{
    //Initialize LSQs
    for (int tid=0; tid < numThreads; tid++) {
        thread[tid].regStats();
    }
}

template<class Impl>
void
LSQ<Impl>::setActiveThreads(std::list<unsigned> *at_ptr)
{
    activeThreads = at_ptr;
    assert(activeThreads != 0);
}

template<class Impl>
void
LSQ<Impl>::setCPU(O3CPU *cpu_ptr)
{
    cpu = cpu_ptr;

    dcachePort.setName(name());

    for (int tid=0; tid < numThreads; tid++) {
        thread[tid].setCPU(cpu_ptr);
    }
}

template<class Impl>
void
LSQ<Impl>::setIEW(IEW *iew_ptr)
{
    iewStage = iew_ptr;

    for (int tid=0; tid < numThreads; tid++) {
        thread[tid].setIEW(iew_ptr);
    }
}

template <class Impl>
void
LSQ<Impl>::switchOut()
{
    for (int tid = 0; tid < numThreads; tid++) {
        thread[tid].switchOut();
    }
}

template <class Impl>
void
LSQ<Impl>::takeOverFrom()
{
    for (int tid = 0; tid < numThreads; tid++) {
        thread[tid].takeOverFrom();
    }
}

template <class Impl>
int
LSQ<Impl>::entryAmount(int num_threads)
{
    if (lsqPolicy == Partitioned) {
        return LQEntries / num_threads;
    } else {
        return 0;
    }
}

template <class Impl>
void
LSQ<Impl>::resetEntries()
{
    if (lsqPolicy != Dynamic || numThreads > 1) {
        int active_threads = activeThreads->size();

        int maxEntries;

        if (lsqPolicy == Partitioned) {
            maxEntries = LQEntries / active_threads;
        } else if (lsqPolicy == Threshold && active_threads == 1) {
            maxEntries = LQEntries;
        } else {
            maxEntries = LQEntries;
        }

        std::list<unsigned>::iterator threads  = activeThreads->begin();
        std::list<unsigned>::iterator end = activeThreads->end();

        while (threads != end) {
            unsigned tid = *threads++;

            resizeEntries(maxEntries, tid);
        }
    }
}

template<class Impl>
void
LSQ<Impl>::removeEntries(unsigned tid)
{
    thread[tid].clearLQ();
    thread[tid].clearSQ();
}

template<class Impl>
void
LSQ<Impl>::resizeEntries(unsigned size,unsigned tid)
{
    thread[tid].resizeLQ(size);
    thread[tid].resizeSQ(size);
}

template<class Impl>
void
LSQ<Impl>::tick()
{
    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        thread[tid].tick();
    }
}

template<class Impl>
void
LSQ<Impl>::insertLoad(DynInstPtr &load_inst)
{
    unsigned tid = load_inst->threadNumber;

    thread[tid].insertLoad(load_inst);
}

template<class Impl>
void
LSQ<Impl>::insertStore(DynInstPtr &store_inst)
{
    unsigned tid = store_inst->threadNumber;

    thread[tid].insertStore(store_inst);
}

template<class Impl>
Fault
LSQ<Impl>::executeLoad(DynInstPtr &inst)
{
    unsigned tid = inst->threadNumber;

    return thread[tid].executeLoad(inst);
}

template<class Impl>
Fault
LSQ<Impl>::executeStore(DynInstPtr &inst)
{
    unsigned tid = inst->threadNumber;

    return thread[tid].executeStore(inst);
}

template<class Impl>
void
LSQ<Impl>::writebackStores()
{
    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        if (numStoresToWB(tid) > 0) {
            DPRINTF(Writeback,"[tid:%i] Writing back stores. %i stores "
                "available for Writeback.\n", tid, numStoresToWB(tid));
        }

        thread[tid].writebackStores();
    }
}

template<class Impl>
bool
LSQ<Impl>::violation()
{
    /* Answers: Does Anybody Have a Violation?*/
    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        if (thread[tid].violation())
            return true;
    }

    return false;
}

template<class Impl>
int
LSQ<Impl>::getCount()
{
    unsigned total = 0;

    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        total += getCount(tid);
    }

    return total;
}

template<class Impl>
int
LSQ<Impl>::numLoads()
{
    unsigned total = 0;

    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        total += numLoads(tid);
    }

    return total;
}

template<class Impl>
int
LSQ<Impl>::numStores()
{
    unsigned total = 0;

    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        total += thread[tid].numStores();
    }

    return total;
}

template<class Impl>
int
LSQ<Impl>::numLoadsReady()
{
    unsigned total = 0;

    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        total += thread[tid].numLoadsReady();
    }

    return total;
}

template<class Impl>
unsigned
LSQ<Impl>::numFreeEntries()
{
    unsigned total = 0;

    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        total += thread[tid].numFreeEntries();
    }

    return total;
}

template<class Impl>
unsigned
LSQ<Impl>::numFreeEntries(unsigned tid)
{
    //if (lsqPolicy == Dynamic)
    //return numFreeEntries();
    //else
        return thread[tid].numFreeEntries();
}

template<class Impl>
bool
LSQ<Impl>::isFull()
{
    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        if (!(thread[tid].lqFull() || thread[tid].sqFull()))
            return false;
    }

    return true;
}

template<class Impl>
bool
LSQ<Impl>::isFull(unsigned tid)
{
    //@todo: Change to Calculate All Entries for
    //Dynamic Policy
    if (lsqPolicy == Dynamic)
        return isFull();
    else
        return thread[tid].lqFull() || thread[tid].sqFull();
}

template<class Impl>
bool
LSQ<Impl>::lqFull()
{
    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        if (!thread[tid].lqFull())
            return false;
    }

    return true;
}

template<class Impl>
bool
LSQ<Impl>::lqFull(unsigned tid)
{
    //@todo: Change to Calculate All Entries for
    //Dynamic Policy
    if (lsqPolicy == Dynamic)
        return lqFull();
    else
        return thread[tid].lqFull();
}

template<class Impl>
bool
LSQ<Impl>::sqFull()
{
    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        if (!sqFull(tid))
            return false;
    }

    return true;
}

template<class Impl>
bool
LSQ<Impl>::sqFull(unsigned tid)
{
     //@todo: Change to Calculate All Entries for
    //Dynamic Policy
    if (lsqPolicy == Dynamic)
        return sqFull();
    else
        return thread[tid].sqFull();
}

template<class Impl>
bool
LSQ<Impl>::isStalled()
{
    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        if (!thread[tid].isStalled())
            return false;
    }

    return true;
}

template<class Impl>
bool
LSQ<Impl>::isStalled(unsigned tid)
{
    if (lsqPolicy == Dynamic)
        return isStalled();
    else
        return thread[tid].isStalled();
}

template<class Impl>
bool
LSQ<Impl>::hasStoresToWB()
{
    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    if (threads == end)
        return false;

    while (threads != end) {
        unsigned tid = *threads++;

        if (!hasStoresToWB(tid))
            return false;
    }

    return true;
}

template<class Impl>
bool
LSQ<Impl>::willWB()
{
    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        if (!willWB(tid))
            return false;
    }

    return true;
}

template<class Impl>
void
LSQ<Impl>::dumpInsts()
{
    std::list<unsigned>::iterator threads = activeThreads->begin();
    std::list<unsigned>::iterator end = activeThreads->end();

    while (threads != end) {
        unsigned tid = *threads++;

        thread[tid].dumpInsts();
    }
}
<|endoftext|>


<commit_before>/// @file i_cant_link_2_mesh.cpp
/// @brief Implementation of handy interface to mesh
/// @author uentity
/// @version
/// @date 14.10.2011
/// @copyright This source code is released under the terms of
///            the BSD License. See LICENSE for more details.

#include "bs_mesh_stdafx.h"
#include "wpi_strategy_3d.h"
#include "wpi_algo.h"

#include "i_cant_link_2_mesh.h"
#include "bs_mesh_grdecl.h"
#include "well_path_ident.h"

// profiling
#include <google/profiler.h>

namespace blue_sky {

namespace {

// separate function for Python export
spv_float calc_cells_vertices_xyz_impl(t_long nx, t_long ny, spv_float coord, spv_float zcorn) {
	typedef smart_ptr< bs_mesh_grdecl, true > sp_grd_mesh;
	// build mesh_grdecl around given mesh
	sp_grd_mesh grd_src = BS_KERNEL.create_object(bs_mesh_grdecl::bs_type());
	if(!grd_src) return NULL;
	grd_src->init_props(nx, ny, coord, zcorn);
	// obtain coordinates for all vertices of all cells
	return grd_src->calc_cells_vertices_xyz();
}

class BS_API_PLUGIN handy_object : public handy_mesh_iface {
public:
	spv_float calc_cells_vertices_xyz(t_long nx, t_long ny, spv_float coord, spv_float zcorn) {
		return calc_cells_vertices_xyz_impl(nx, ny, coord, zcorn);
	}

	// 3D
	spv_uint where_is_points(t_long nx, t_long ny, spv_float coord, spv_float zcorn, spv_float points) {
		return blue_sky::where_is_points(nx, ny, coord, zcorn, points);
	}
	// 2D
	spv_uint where_is_points_2d(t_long nx, t_long ny, spv_float coord, spv_float zcorn, spv_float points) {
		return blue_sky::where_is_points_2d(nx, ny, coord, zcorn, points);
	}

	// 3D
	t_uint where_is_point(t_long nx, t_long ny, spv_float coord, spv_float zcorn, spv_float point) {
		return blue_sky::where_is_point(nx, ny, coord, zcorn, point);
	}
	// 2D
	t_uint where_is_point_2d(t_long nx, t_long ny, spv_float coord, spv_float zcorn, spv_float point) {
		return blue_sky::where_is_point_2d(nx, ny, coord, zcorn, point);
	}

	sp_smesh make_mesh_grdecl(t_long nx, t_long ny, spv_float coord, spv_float zcorn) {
		typedef smart_ptr< bs_mesh_grdecl, true > sp_grd_mesh;
		// build mesh_grdecl around given mesh
		sp_grd_mesh grd_src = BS_KERNEL.create_object(bs_mesh_grdecl::bs_type());
		if(!grd_src) return NULL;
		grd_src->init_props(nx, ny, coord, zcorn);
		return grd_src;
	}

	BLUE_SKY_TYPE_DECL(handy_object)
};

// std and copy ctors
handy_object::handy_object(bs_type_ctor_param)
{}

handy_object::handy_object(const handy_object& rhs)
	: bs_refcounter()
{}

}  // eof hidden namespace

BLUE_SKY_TYPE_IMPL(handy_object, objbase, "handy_mesh_iface", "Interface to everything needed from mesh", "")
BLUE_SKY_TYPE_STD_CREATE(handy_object)
BLUE_SKY_TYPE_STD_COPY(handy_object)

bool register_handy_mesh_iface(const plugin_descriptor& pd) {
	return BS_KERNEL.register_type(pd, handy_object::bs_type());
}

#ifdef BSPY_EXPORTING_PLUGIN
namespace python {
	using namespace boost::python;

	tuple enum_border_facets_vtk(t_long nx, t_long ny, spv_float coord, spv_float zcorn, spv_int mask) {
		typedef wpi::strategy_3d strat_t;
		typedef wpi::algo< strat_t > wpi_algo;

		spv_long cell_idx = BS_KERNEL.create_object(v_long::bs_type());
		spv_float points = BS_KERNEL.create_object(v_float::bs_type());
		ProfilerStart("/home/uentity/my_projects/blue-sky.git/gui/enum_border_facets_vtk.prof");
		spv_long res = wpi_algo::enum_border_facets_vtk(nx, ny, coord, zcorn, mask, cell_idx, points);
		ProfilerStop();
		return make_tuple(res, cell_idx, points);
	}

	tuple enum_border_edges_vtk(t_long nx, t_long ny, spv_float coord, spv_float zcorn, spv_int mask) {
		typedef wpi::strategy_3d strat_t;
		typedef wpi::algo< strat_t > wpi_algo;

		spv_long cell_idx = BS_KERNEL.create_object(v_long::bs_type());
		spv_float points = BS_KERNEL.create_object(v_float::bs_type());
		ProfilerStart("/home/uentity/my_projects/blue-sky.git/gui/enum_border_edges_vtk.prof");
		spv_long res = wpi_algo::enum_border_edges_vtk(nx, ny, coord, zcorn, mask, cell_idx, points);
		ProfilerStop();
		return make_tuple(res, cell_idx, points);
	}

	void py_export_handymesh() {
		def("calc_cells_vertices_xyz", &calc_cells_vertices_xyz_impl);
		def("enum_border_facets_vtk", &enum_border_facets_vtk);
		def("enum_border_edges_vtk", &enum_border_edges_vtk);
	}
} /* python */
#endif

} /* blue_sky */
<commit_msg>WPI: use bufpool tops_iterator strategy for VTK-related algorithms<commit_after>/// @file i_cant_link_2_mesh.cpp
/// @brief Implementation of handy interface to mesh
/// @author uentity
/// @version
/// @date 14.10.2011
/// @copyright This source code is released under the terms of
///            the BSD License. See LICENSE for more details.

#include "bs_mesh_stdafx.h"
#include "wpi_strategy_3d.h"
#include "wpi_algo.h"

#include "i_cant_link_2_mesh.h"
#include "bs_mesh_grdecl.h"
#include "well_path_ident.h"

// profiling
#include <google/profiler.h>
#include <google/heap-profiler.h>

namespace blue_sky {

namespace {

// separate function for Python export
spv_float calc_cells_vertices_xyz_impl(t_long nx, t_long ny, spv_float coord, spv_float zcorn) {
	typedef smart_ptr< bs_mesh_grdecl, true > sp_grd_mesh;
	// build mesh_grdecl around given mesh
	sp_grd_mesh grd_src = BS_KERNEL.create_object(bs_mesh_grdecl::bs_type());
	if(!grd_src) return NULL;
	grd_src->init_props(nx, ny, coord, zcorn);
	// obtain coordinates for all vertices of all cells
	return grd_src->calc_cells_vertices_xyz();
}

class BS_API_PLUGIN handy_object : public handy_mesh_iface {
public:
	spv_float calc_cells_vertices_xyz(t_long nx, t_long ny, spv_float coord, spv_float zcorn) {
		return calc_cells_vertices_xyz_impl(nx, ny, coord, zcorn);
	}

	// 3D
	spv_uint where_is_points(t_long nx, t_long ny, spv_float coord, spv_float zcorn, spv_float points) {
		return blue_sky::where_is_points(nx, ny, coord, zcorn, points);
	}
	// 2D
	spv_uint where_is_points_2d(t_long nx, t_long ny, spv_float coord, spv_float zcorn, spv_float points) {
		return blue_sky::where_is_points_2d(nx, ny, coord, zcorn, points);
	}

	// 3D
	t_uint where_is_point(t_long nx, t_long ny, spv_float coord, spv_float zcorn, spv_float point) {
		return blue_sky::where_is_point(nx, ny, coord, zcorn, point);
	}
	// 2D
	t_uint where_is_point_2d(t_long nx, t_long ny, spv_float coord, spv_float zcorn, spv_float point) {
		return blue_sky::where_is_point_2d(nx, ny, coord, zcorn, point);
	}

	sp_smesh make_mesh_grdecl(t_long nx, t_long ny, spv_float coord, spv_float zcorn) {
		typedef smart_ptr< bs_mesh_grdecl, true > sp_grd_mesh;
		// build mesh_grdecl around given mesh
		sp_grd_mesh grd_src = BS_KERNEL.create_object(bs_mesh_grdecl::bs_type());
		if(!grd_src) return NULL;
		grd_src->init_props(nx, ny, coord, zcorn);
		return grd_src;
	}

	BLUE_SKY_TYPE_DECL(handy_object)
};

// std and copy ctors
handy_object::handy_object(bs_type_ctor_param)
{}

handy_object::handy_object(const handy_object& rhs)
	: bs_refcounter()
{}

}  // eof hidden namespace

BLUE_SKY_TYPE_IMPL(handy_object, objbase, "handy_mesh_iface", "Interface to everything needed from mesh", "")
BLUE_SKY_TYPE_STD_CREATE(handy_object)
BLUE_SKY_TYPE_STD_COPY(handy_object)

bool register_handy_mesh_iface(const plugin_descriptor& pd) {
	return BS_KERNEL.register_type(pd, handy_object::bs_type());
}

#ifdef BSPY_EXPORTING_PLUGIN
namespace python {
	using namespace boost::python;

	tuple enum_border_facets_vtk(t_long nx, t_long ny, spv_float coord, spv_float zcorn, spv_int mask) {
		typedef wpi::strategy_3d_ex< wpi::online_tops_traits > strat_t;
		typedef wpi::algo< strat_t > wpi_algo;

		spv_long cell_idx = BS_KERNEL.create_object(v_long::bs_type());
		spv_float points = BS_KERNEL.create_object(v_float::bs_type());
		//ProfilerStart("/home/uentity/my_projects/blue-sky.git/gui/enum_border_facets_vtk.prof");
		spv_long res = wpi_algo::enum_border_facets_vtk(nx, ny, coord, zcorn, mask, cell_idx, points);
		//ProfilerStop();
		return make_tuple(res, cell_idx, points);
	}

	tuple enum_border_edges_vtk(t_long nx, t_long ny, spv_float coord, spv_float zcorn, spv_int mask) {
		typedef wpi::strategy_3d_ex< wpi::online_tops_traits > strat_t;
		typedef wpi::algo< strat_t > wpi_algo;

		spv_long cell_idx = BS_KERNEL.create_object(v_long::bs_type());
		spv_float points = BS_KERNEL.create_object(v_float::bs_type());
		//ProfilerStart("/home/uentity/my_projects/blue-sky.git/gui/enum_border_edges_vtk.prof");
		//HeapProfilerStart("/home/uentity/my_projects/blue-sky.git/gui/enum_border_edges_vtk");
		spv_long res = wpi_algo::enum_border_edges_vtk(nx, ny, coord, zcorn, mask, cell_idx, points);
		//HeapProfilerStop();
		return make_tuple(res, cell_idx, points);
	}

	void py_export_handymesh() {
		def("calc_cells_vertices_xyz", &calc_cells_vertices_xyz_impl);
		def("enum_border_facets_vtk", &enum_border_facets_vtk);
		def("enum_border_edges_vtk", &enum_border_edges_vtk);
	}
} /* python */
#endif

} /* blue_sky */
<|endoftext|>