<commit_before>/**
 * @file seaicing.cpp
 *
 *  Created on: Jan 03, 2013
 *  @author aaltom
 */

#include "seaicing.h"
#include <iostream>
#include "plugin_factory.h"
#include "logger_factory.h"
#include <boost/lexical_cast.hpp>
#include "util.h"

#define HIMAN_AUXILIARY_INCLUDE

#include "fetcher.h"
#include "writer.h"
#include "pcuda.h"
#include "neons.h"

#undef HIMAN_AUXILIARY_INCLUDE

using namespace std;
using namespace himan::plugin;

seaicing::seaicing() : itsUseCuda(false)
{
	itsClearTextFormula = "SeaIcing = FF * ( -0.35 -T2m ) / ( 1 + 0.3 * ( T0 + 0.35 ))";

	itsLogger = std::unique_ptr<logger> (logger_factory::Instance()->GetLog("seaicing"));

}

void seaicing::Process(std::shared_ptr<const plugin_configuration> conf)
{

	unique_ptr<timer> initTimer;

	if (conf->StatisticsEnabled())
	{
		initTimer = unique_ptr<timer> (timer_factory::Instance()->GetTimer());
		initTimer->Start();
	}

	shared_ptr<plugin::pcuda> c = dynamic_pointer_cast<plugin::pcuda> (plugin_factory::Instance()->Plugin("pcuda"));

	if (c && c->HaveCuda())
	{
		string msg = "I possess the powers of CUDA ";

		if (!conf->UseCuda())
		{
			msg += ", but I won't use them";
		}
		else
		{
			msg += ", and I'm not afraid to use them";
			itsUseCuda = true;
		}

		itsLogger->Info(msg);

	}

	// Get number of threads to use

	unsigned short threadCount = ThreadCount(conf->ThreadCount());

	if (conf->StatisticsEnabled())
	{
		conf->Statistics()->UsedThreadCount(threadCount);
		conf->Statistics()->UsedGPUCount(0);
	}

	boost::thread_group g;

	shared_ptr<info> targetInfo = conf->Info();

	/*
	 * Set target parameter to seaicing
	 * - name ICEIND-N
	 * - univ_id 190
	 * - grib2 descriptor 0'00'002
	 *
	 * We need to specify grib and querydata parameter information
	 * since we don't know which one will be the output format.
	 * (todo: we could check from conf but why bother?)
	 *
	 */

	vector<param> theParams;

	param requestedParam("ICEIND-N", 190);

	// GRIB 2
	requestedParam.GribDiscipline(0);
	requestedParam.GribCategory(0);
	requestedParam.GribParameter(2);

	// GRIB 1

	if (conf->OutputFileType() == kGRIB1)
	{
		shared_ptr<neons> n = dynamic_pointer_cast<neons> (plugin_factory::Instance()->Plugin("neons"));

		long parm_id = n->NeonsDB().GetGridParameterId(targetInfo->Producer().TableVersion(), requestedParam.Name());
		requestedParam.GribIndicatorOfParameter(parm_id);
		requestedParam.GribTableVersion(targetInfo->Producer().TableVersion());

	}

	theParams.push_back(requestedParam);

	targetInfo->Params(theParams);

	/*
	 * Create data structures.
	 */

	targetInfo->Create();

	/*
	 * Initialize parent class functions for dimension handling
	 */

	Dimension(conf->LeadingDimension());
	FeederInfo(shared_ptr<info> (new info(*targetInfo)));
	FeederInfo()->Param(requestedParam);

	if (conf->StatisticsEnabled())
	{
		initTimer->Stop();
		conf->Statistics()->AddToInitTime(initTimer->GetTime());
	}

	/*
	 * Each thread will have a copy of the target info.
	 */

	for (size_t i = 0; i < threadCount; i++)
	{

		itsLogger->Info("Thread " + boost::lexical_cast<string> (i + 1) + " starting");

		boost::thread* t = new boost::thread(&seaicing::Run,
											 this,
											 shared_ptr<info> (new info(*targetInfo)),
											 conf,
											 i + 1);

		g.add_thread(t);

	}

	g.join_all();

	if (conf->FileWriteOption() == kSingleFile)
	{

		shared_ptr<writer> theWriter = dynamic_pointer_cast <writer> (plugin_factory::Instance()->Plugin("writer"));

		string theOutputFile = conf->ConfigurationFile();

		theWriter->ToFile(targetInfo, conf, theOutputFile);

	}
}

void seaicing::Run(shared_ptr<info> myTargetInfo, shared_ptr<const plugin_configuration> conf, unsigned short theThreadIndex)
{
	while (AdjustLeadingDimension(myTargetInfo))
	{
		Calculate(myTargetInfo, conf, theThreadIndex);
	}
}

/*
 * Calculate()
 *
 * This function does the actual calculation.
 */

void seaicing::Calculate(shared_ptr<info> myTargetInfo, shared_ptr<const plugin_configuration> conf, unsigned short theThreadIndex)
{

	shared_ptr<fetcher> theFetcher = dynamic_pointer_cast <fetcher> (plugin_factory::Instance()->Plugin("fetcher"));

	// Required source parameters

	param TParam("T-K");
	level TgLevel(himan::kHeight, 0, "HEIGHT");
	param FfParam("FFG-MS");  // 10 meter wind
	level FfLevel(himan::kHeight, 10, "HEIGHT");

	unique_ptr<logger> myThreadedLogger = std::unique_ptr<logger> (logger_factory::Instance()->GetLog("seaicingThread #" + boost::lexical_cast<string> (theThreadIndex)));

	ResetNonLeadingDimension(myTargetInfo);

	myTargetInfo->FirstParam();

	while (AdjustNonLeadingDimension(myTargetInfo))
	{

		myThreadedLogger->Debug("Calculating time " + myTargetInfo->Time().ValidDateTime()->String("%Y%m%d%H%M") +
								" level " + boost::lexical_cast<string> (myTargetInfo->Level().Value()));

		shared_ptr<info> TInfo;
		shared_ptr<info> TgInfo;
		shared_ptr<info> FfInfo;

		try
		{
			// Source info for T
			TInfo = theFetcher->Fetch(conf,
								 myTargetInfo->Time(),
								 myTargetInfo->Level(),
								 TParam);

			// Source info for Tg
			TgInfo = theFetcher->Fetch(conf,
								 myTargetInfo->Time(),
								 TgLevel,
								 TParam);

			// Source info for FF
			FfInfo = theFetcher->Fetch(conf,
								 myTargetInfo->Time(),
								 FfLevel,
								 FfParam);

		}
		catch (HPExceptionType e)
		{
			//HPExceptionType t = static_cast<HPExceptionType> (e);

			switch (e)
			{
			case kFileDataNotFound:
				itsLogger->Info("Skipping step " + boost::lexical_cast<string> (myTargetInfo->Time().Step()) + ", level " + boost::lexical_cast<string> (myTargetInfo->Level().Value()));
				myTargetInfo->Data()->Fill(kFloatMissing); // Fill data with missing value

				if (conf->StatisticsEnabled())
				{
					conf->Statistics()->AddToMissingCount(myTargetInfo->Grid()->Size());
					conf->Statistics()->AddToValueCount(myTargetInfo->Grid()->Size());
				}

				continue;
				break;

			default:
				throw runtime_error(ClassName() + ": Unable to proceed");
				break;
			}
		}

		unique_ptr<timer> processTimer = unique_ptr<timer> (timer_factory::Instance()->GetTimer());

		if (conf->StatisticsEnabled())
		{
			processTimer->Start();
		}

		shared_ptr<NFmiGrid> targetGrid(myTargetInfo->Grid()->ToNewbaseGrid());
		shared_ptr<NFmiGrid> TGrid(TInfo->Grid()->ToNewbaseGrid());
		shared_ptr<NFmiGrid> TgGrid(TgInfo->Grid()->ToNewbaseGrid());
		shared_ptr<NFmiGrid> FfGrid(FfInfo->Grid()->ToNewbaseGrid());

		int missingCount = 0;
		int count = 0;

		assert(targetGrid->Size() == myTargetInfo->Data()->Size());

		bool equalGrids = (*myTargetInfo->Grid() == *TInfo->Grid() &&
							*myTargetInfo->Grid() == *TgInfo->Grid() &&
							*myTargetInfo->Grid() == *FfInfo->Grid());

		myTargetInfo->ResetLocation();

		targetGrid->Reset();

		string deviceType = "CPU";

		while (myTargetInfo->NextLocation() && targetGrid->Next())
		{
			count++;

			double T = kFloatMissing;
			double Tg = kFloatMissing;
			double Ff = kFloatMissing;

			InterpolateToPoint(targetGrid, TGrid, equalGrids, T);
			InterpolateToPoint(targetGrid, TgGrid, equalGrids, Tg);
			InterpolateToPoint(targetGrid, FfGrid, equalGrids, Ff);

			if (T == kFloatMissing || Tg == kFloatMissing || Ff == kFloatMissing)
			{
				missingCount++;

				myTargetInfo->Value(-10);  // No missing values
				continue;
			}

			double seaIcing;
			double TBase = 273.15;

			T = T - TBase;
			Tg = Tg - TBase;

			if (Tg < -2 )
			{
				seaIcing = -10;
			}
			else
			{
				seaIcing = Ff * ( -0.35 -T ) / ( 1 + 0.3 * ( Tg + 0.35 ));

				if (seaIcing > 100)
				{
					seaIcing = 100;
				}
			}

			if (!myTargetInfo->Value(seaIcing))
			{
				throw runtime_error(ClassName() + ": Failed to set value to matrix");
			}

		}

		/*
		 * Newbase normalizes scanning mode to bottom left -- if that's not what
		 * the target scanning mode is, we have to swap the data back.
		 */

		SwapTo(myTargetInfo, kBottomLeft);

		if (conf->StatisticsEnabled())
		{
			processTimer->Stop();
			conf->Statistics()->AddToProcessingTime(processTimer->GetTime());

#ifdef DEBUG
			itsLogger->Debug("Calculation took " + boost::lexical_cast<string> (processTimer->GetTime()) + " microseconds on " + deviceType);
#endif
			conf->Statistics()->AddToMissingCount(missingCount);
			conf->Statistics()->AddToValueCount(count);
		}

		/*
		 * Now we are done for this level
		 *
		 * Clone info-instance to writer since it might change our descriptor places
		 */

		myThreadedLogger->Info("Missing values: " + boost::lexical_cast<string> (missingCount) + "/" + boost::lexical_cast<string> (count));

		if (conf->FileWriteOption() == kNeons || conf->FileWriteOption() == kMultipleFiles)
		{
			shared_ptr<writer> theWriter = dynamic_pointer_cast <writer> (plugin_factory::Instance()->Plugin("writer"));

			theWriter->ToFile(shared_ptr<info> (new info(*myTargetInfo)), conf);
		}
	}
}
<commit_msg>Fixed a wrong parameter name and level<commit_after>/**
 * @file seaicing.cpp
 *
 *  Created on: Jan 03, 2013
 *  @author aaltom
 */

#include "seaicing.h"
#include <iostream>
#include "plugin_factory.h"
#include "logger_factory.h"
#include <boost/lexical_cast.hpp>
#include "util.h"

#define HIMAN_AUXILIARY_INCLUDE

#include "fetcher.h"
#include "writer.h"
#include "pcuda.h"
#include "neons.h"

#undef HIMAN_AUXILIARY_INCLUDE

using namespace std;
using namespace himan::plugin;

#include "cuda_extern.h"

seaicing::seaicing() : itsUseCuda(false)
{
	itsClearTextFormula = "SeaIcing = FF * ( -0.35 -T2m ) / ( 1 + 0.3 * ( T0 + 0.35 ))";

	itsLogger = std::unique_ptr<logger> (logger_factory::Instance()->GetLog("seaicing"));

}

void seaicing::Process(std::shared_ptr<const plugin_configuration> conf)
{

	unique_ptr<timer> initTimer;

	if (conf->StatisticsEnabled())
	{
		initTimer = unique_ptr<timer> (timer_factory::Instance()->GetTimer());
		initTimer->Start();
	}

	shared_ptr<plugin::pcuda> c = dynamic_pointer_cast<plugin::pcuda> (plugin_factory::Instance()->Plugin("pcuda"));

	if (c && c->HaveCuda())
	{
		string msg = "I possess the powers of CUDA ";

		if (!conf->UseCuda())
		{
			msg += ", but I won't use them";
		}
		else
		{
			msg += ", and I'm not afraid to use them";
			itsUseCuda = true;
		}

		itsLogger->Info(msg);

	}

	// Get number of threads to use

	unsigned short threadCount = ThreadCount(conf->ThreadCount());

        if (conf->StatisticsEnabled())
	{
		conf->Statistics()->UsedThreadCount(threadCount);
	//	conf->Statistics()->UsedCudaCount(itsCudaDeviceCount);
	}

	if (conf->StatisticsEnabled())
	{
		conf->Statistics()->UsedThreadCount(threadCount);
		conf->Statistics()->UsedGPUCount(0);
	}

	boost::thread_group g;

	shared_ptr<info> targetInfo = conf->Info();

	/*
	 * Set target parameter to seaicing
	 * - name ICEIND-N
	 * - univ_id 190
	 * - grib2 descriptor 0'00'002
	 *
	 * We need to specify grib and querydata parameter information
	 * since we don't know which one will be the output format.
	 * (todo: we could check from conf but why bother?)
	 *
	 */

	vector<param> theParams;

	param requestedParam("ICEIND-N", 190);

	// GRIB 2
	requestedParam.GribDiscipline(0);
	requestedParam.GribCategory(0);
	requestedParam.GribParameter(2);

	// GRIB 1

	if (conf->OutputFileType() == kGRIB1)
	{
		shared_ptr<neons> n = dynamic_pointer_cast<neons> (plugin_factory::Instance()->Plugin("neons"));

		long parm_id = n->NeonsDB().GetGridParameterId(targetInfo->Producer().TableVersion(), requestedParam.Name());
		requestedParam.GribIndicatorOfParameter(parm_id);
		requestedParam.GribTableVersion(targetInfo->Producer().TableVersion());

	}

	theParams.push_back(requestedParam);

	targetInfo->Params(theParams);

	/*
	 * Create data structures.
	 */

	targetInfo->Create();

	/*
	 * Initialize parent class functions for dimension handling
	 */

	Dimension(conf->LeadingDimension());
	FeederInfo(shared_ptr<info> (new info(*targetInfo)));
	FeederInfo()->Param(requestedParam);

	if (conf->StatisticsEnabled())
	{
		initTimer->Stop();
		conf->Statistics()->AddToInitTime(initTimer->GetTime());
	}

	/*
	 * Each thread will have a copy of the target info.
	 */

	for (size_t i = 0; i < threadCount; i++)
	{

		itsLogger->Info("Thread " + boost::lexical_cast<string> (i + 1) + " starting");

		boost::thread* t = new boost::thread(&seaicing::Run,
											 this,
											 shared_ptr<info> (new info(*targetInfo)),
											 conf,
											 i + 1);

		g.add_thread(t);

	}

	g.join_all();

	if (conf->FileWriteOption() == kSingleFile)
	{

		shared_ptr<writer> theWriter = dynamic_pointer_cast <writer> (plugin_factory::Instance()->Plugin("writer"));

		string theOutputFile = conf->ConfigurationFile();

		theWriter->ToFile(targetInfo, conf, theOutputFile);

	}
}

void seaicing::Run(shared_ptr<info> myTargetInfo, shared_ptr<const plugin_configuration> conf, unsigned short theThreadIndex)
{
	while (AdjustLeadingDimension(myTargetInfo))
	{
		Calculate(myTargetInfo, conf, theThreadIndex);
	}
}

/*
 * Calculate()
 *
 * This function does the actual calculation.
 */

void seaicing::Calculate(shared_ptr<info> myTargetInfo, shared_ptr<const plugin_configuration> conf, unsigned short theThreadIndex)
{

	shared_ptr<fetcher> theFetcher = dynamic_pointer_cast <fetcher> (plugin_factory::Instance()->Plugin("fetcher"));

        param TParam("T-K");
        level TLevel(himan::kHeight, 2, "HEIGHT");
	param FfParam("FF-MS");  // 10 meter wind
	level FfLevel(himan::kHeight, 10, "HEIGHT");

	unique_ptr<logger> myThreadedLogger = std::unique_ptr<logger> (logger_factory::Instance()->GetLog("seaicingThread #" + boost::lexical_cast<string> (theThreadIndex)));

	ResetNonLeadingDimension(myTargetInfo);

	myTargetInfo->FirstParam();

	while (AdjustNonLeadingDimension(myTargetInfo))
	{

		myThreadedLogger->Debug("Calculating time " + myTargetInfo->Time().ValidDateTime()->String("%Y%m%d%H%M") +
								" level " + boost::lexical_cast<string> (myTargetInfo->Level().Value()));

		shared_ptr<info> TInfo;
		shared_ptr<info> TgInfo;
		shared_ptr<info> FfInfo;

		try
		{
			// Source info for T
			TInfo = theFetcher->Fetch(conf,
								 myTargetInfo->Time(),
								 TLevel,
								 TParam);

			// Source info for Tg
			TgInfo = theFetcher->Fetch(conf,
								 myTargetInfo->Time(),
								 myTargetInfo->Level(),
								 TParam);

			// Source info for FF
			FfInfo = theFetcher->Fetch(conf,
								 myTargetInfo->Time(),
								 FfLevel,
								 FfParam);

		}
		catch (HPExceptionType& e)
		{
			//HPExceptionType t = static_cast<HPExceptionType> (e);

			switch (e)
			{
			case kFileDataNotFound:
				itsLogger->Info("Skipping step " + boost::lexical_cast<string> (myTargetInfo->Time().Step()) + ", level " + boost::lexical_cast<string> (myTargetInfo->Level().Value()));
				myTargetInfo->Data()->Fill(kFloatMissing); // Fill data with missing value

				if (conf->StatisticsEnabled())
				{
					conf->Statistics()->AddToMissingCount(myTargetInfo->Grid()->Size());
					conf->Statistics()->AddToValueCount(myTargetInfo->Grid()->Size());
				}

				continue;
				break;

			default:
				throw runtime_error(ClassName() + ": Unable to proceed");
				break;
			}
		}

                unique_ptr<timer> processTimer = unique_ptr<timer> (timer_factory::Instance()->GetTimer());

		if (conf->StatisticsEnabled())
		{
			processTimer->Start();
		}

		shared_ptr<NFmiGrid> targetGrid(myTargetInfo->Grid()->ToNewbaseGrid());
		shared_ptr<NFmiGrid> TGrid(TInfo->Grid()->ToNewbaseGrid());
		shared_ptr<NFmiGrid> TgGrid(TgInfo->Grid()->ToNewbaseGrid());
		shared_ptr<NFmiGrid> FfGrid(FfInfo->Grid()->ToNewbaseGrid());

		int missingCount = 0;
		int count = 0;

		assert(targetGrid->Size() == myTargetInfo->Data()->Size());

		bool equalGrids = (*myTargetInfo->Grid() == *TInfo->Grid() &&
							*myTargetInfo->Grid() == *TgInfo->Grid() &&
							*myTargetInfo->Grid() == *FfInfo->Grid());

		myTargetInfo->ResetLocation();

		targetGrid->Reset();

		string deviceType = "CPU";

		while (myTargetInfo->NextLocation() && targetGrid->Next())
		{
			count++;

			double T = kFloatMissing;
			double Tg = kFloatMissing;
			double Ff = kFloatMissing;

			InterpolateToPoint(targetGrid, TGrid, equalGrids, T);
			InterpolateToPoint(targetGrid, TgGrid, equalGrids, Tg);
			InterpolateToPoint(targetGrid, FfGrid, equalGrids, Ff);

			if (T == kFloatMissing || Tg == kFloatMissing || Ff == kFloatMissing)
			{
				missingCount++;

				myTargetInfo->Value(-10);  // No missing values
				continue;
			}

			double seaIcing;
			double TBase = 273.15;

			T = T - TBase;
			Tg = Tg - TBase;

			if (Tg < -2 )
			{
				seaIcing = -10;
			}
			else
			{
				seaIcing = Ff * ( -0.35 -T ) / ( 1 + 0.3 * ( Tg + 0.35 ));

				if (seaIcing > 100)
				{
					seaIcing = 100;
				}
			}

			if (!myTargetInfo->Value(seaIcing))
			{
				throw runtime_error(ClassName() + ": Failed to set value to matrix");
			}

		}

                if (conf->StatisticsEnabled())
		{
			processTimer->Stop();
			conf->Statistics()->AddToProcessingTime(processTimer->GetTime());

			conf->Statistics()->AddToMissingCount(missingCount);
			conf->Statistics()->AddToValueCount(count);

		}

		/*
		 * Newbase normalizes scanning mode to bottom left -- if that's not what
		 * the target scanning mode is, we have to swap the data back.
		 */

		SwapTo(myTargetInfo, kBottomLeft);

		if (conf->StatisticsEnabled())
		{
			processTimer->Stop();
			conf->Statistics()->AddToProcessingTime(processTimer->GetTime());

#ifdef DEBUG
			itsLogger->Debug("Calculation took " + boost::lexical_cast<string> (processTimer->GetTime()) + " microseconds on " + deviceType);
#endif
			conf->Statistics()->AddToMissingCount(missingCount);
			conf->Statistics()->AddToValueCount(count);
		}

		/*
		 * Now we are done for this level
		 *
		 * Clone info-instance to writer since it might change our descriptor places
		 */

		myThreadedLogger->Info("Missing values: " + boost::lexical_cast<string> (missingCount) + "/" + boost::lexical_cast<string> (count));

		if (conf->FileWriteOption() == kNeons || conf->FileWriteOption() == kMultipleFiles)
		{
			shared_ptr<writer> theWriter = dynamic_pointer_cast <writer> (plugin_factory::Instance()->Plugin("writer"));

			theWriter->ToFile(shared_ptr<info> (new info(*myTargetInfo)), conf);
		}
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/web_contents/web_contents_view_android.h"

#include "base/logging.h"
#include "content/browser/android/content_view_core_impl.h"
#include "content/browser/android/media_player_manager_android.h"
#include "content/browser/renderer_host/render_widget_host_view_android.h"
#include "content/browser/renderer_host/render_view_host_factory.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/interstitial_page_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/web_contents_delegate.h"

namespace content {
WebContentsView* CreateWebContentsView(
    WebContentsImpl* web_contents,
    WebContentsViewDelegate* delegate,
    RenderViewHostDelegateView** render_view_host_delegate_view) {
  WebContentsViewAndroid* rv = new WebContentsViewAndroid(
      web_contents, delegate);
  *render_view_host_delegate_view = rv;
  return rv;
}

WebContentsViewAndroid::WebContentsViewAndroid(
    WebContentsImpl* web_contents,
    WebContentsViewDelegate* delegate)
    : web_contents_(web_contents),
      content_view_core_(NULL),
      delegate_(delegate) {
}

WebContentsViewAndroid::~WebContentsViewAndroid() {
}

void WebContentsViewAndroid::SetContentViewCore(
    ContentViewCoreImpl* content_view_core) {
  content_view_core_ = content_view_core;
  RenderWidgetHostViewAndroid* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
      web_contents_->GetRenderWidgetHostView());
  if (rwhv)
    rwhv->SetContentViewCore(content_view_core_);

  if (web_contents_->ShowingInterstitialPage()) {
    rwhv = static_cast<RenderWidgetHostViewAndroid*>(
        static_cast<InterstitialPageImpl*>(
            web_contents_->GetInterstitialPage())->
                GetRenderViewHost()->GetView());
    if (rwhv)
      rwhv->SetContentViewCore(content_view_core_);
  }
}

void WebContentsViewAndroid::CreateView(const gfx::Size& initial_size) {
}

RenderWidgetHostView* WebContentsViewAndroid::CreateViewForWidget(
    RenderWidgetHost* render_widget_host) {
  if (render_widget_host->GetView()) {
    // During testing, the view will already be set up in most cases to the
    // test view, so we don't want to clobber it with a real one. To verify that
    // this actually is happening (and somebody isn't accidentally creating the
    // view twice), we check for the RVH Factory, which will be set when we're
    // making special ones (which go along with the special views).
    DCHECK(RenderViewHostFactory::has_factory());
    return render_widget_host->GetView();
  }
  // Note that while this instructs the render widget host to reference
  // |native_view_|, this has no effect without also instructing the
  // native view (i.e. ContentView) how to obtain a reference to this widget in
  // order to paint it. See ContentView::GetRenderWidgetHostViewAndroid for an
  // example of how this is achieved for InterstitialPages.
  RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(render_widget_host);
  return new RenderWidgetHostViewAndroid(rwhi, content_view_core_);
}

gfx::NativeView WebContentsViewAndroid::GetNativeView() const {
  return content_view_core_;
}

gfx::NativeView WebContentsViewAndroid::GetContentNativeView() const {
  return content_view_core_;
}

gfx::NativeWindow WebContentsViewAndroid::GetTopLevelNativeWindow() const {
  return content_view_core_->GetWindowAndroid();
}

void WebContentsViewAndroid::GetContainerBounds(gfx::Rect* out) const {
  RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
  if (rwhv)
    *out = rwhv->GetViewBounds();
}

void WebContentsViewAndroid::SetPageTitle(const string16& title) {
  if (content_view_core_)
    content_view_core_->SetTitle(title);
}

void WebContentsViewAndroid::OnTabCrashed(base::TerminationStatus status,
                                          int error_code) {
  RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
      web_contents_->GetRenderViewHost());
  if (rvh->media_player_manager())
    rvh->media_player_manager()->DestroyAllMediaPlayers();
  if (content_view_core_)
    content_view_core_->OnTabCrashed();
}

void WebContentsViewAndroid::SizeContents(const gfx::Size& size) {
  // TODO(klobag): Do we need to do anything else?
  RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
  if (rwhv)
    rwhv->SetSize(size);
}

void WebContentsViewAndroid::RenderViewCreated(RenderViewHost* host) {
}

void WebContentsViewAndroid::Focus() {
  if (web_contents_->ShowingInterstitialPage())
    web_contents_->GetInterstitialPage()->Focus();
  else
    web_contents_->GetRenderWidgetHostView()->Focus();
}

void WebContentsViewAndroid::SetInitialFocus() {
  if (web_contents_->FocusLocationBarByDefault())
    web_contents_->SetFocusToLocationBar(false);
  else
    Focus();
}

void WebContentsViewAndroid::StoreFocus() {
  NOTIMPLEMENTED();
}

void WebContentsViewAndroid::RestoreFocus() {
  NOTIMPLEMENTED();
}

WebDropData* WebContentsViewAndroid::GetDropData() const {
  NOTIMPLEMENTED();
  return NULL;
}

bool WebContentsViewAndroid::IsEventTracking() const {
  NOTIMPLEMENTED();
  return false;
}

void WebContentsViewAndroid::CloseTabAfterEventTracking() {
  NOTIMPLEMENTED();
}

gfx::Rect WebContentsViewAndroid::GetViewBounds() const {
  RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
  if (rwhv)
    return rwhv->GetViewBounds();
  else
    return gfx::Rect();
}

void WebContentsViewAndroid::ShowContextMenu(
    const ContextMenuParams& params,
    ContextMenuSourceType type) {
  if (delegate_.get())
    delegate_->ShowContextMenu(params, type);
}

void WebContentsViewAndroid::ShowPopupMenu(
    const gfx::Rect& bounds,
    int item_height,
    double item_font_size,
    int selected_item,
    const std::vector<WebMenuItem>& items,
    bool right_aligned,
    bool allow_multiple_selection) {
  if (content_view_core_) {
    content_view_core_->ShowSelectPopupMenu(
        items, selected_item, allow_multiple_selection);
  }
}

void WebContentsViewAndroid::StartDragging(
    const WebDropData& drop_data,
    WebKit::WebDragOperationsMask allowed_ops,
    const gfx::ImageSkia& image,
    const gfx::Vector2d& image_offset,
    const DragEventSourceInfo& event_info) {
  NOTIMPLEMENTED();
}

void WebContentsViewAndroid::UpdateDragCursor(WebKit::WebDragOperation op) {
  NOTIMPLEMENTED();
}

void WebContentsViewAndroid::GotFocus() {
  // This is only used in the views FocusManager stuff but it bleeds through
  // all subclasses. http://crbug.com/21875
}

// This is called when we the renderer asks us to take focus back (i.e., it has
// iterated past the last focusable element on the page).
void WebContentsViewAndroid::TakeFocus(bool reverse) {
  if (web_contents_->GetDelegate() &&
      web_contents_->GetDelegate()->TakeFocus(web_contents_, reverse))
    return;
  web_contents_->GetRenderWidgetHostView()->Focus();
}

} // namespace content
<commit_msg>[Android] Attach RenderWidgetHostView to ContentView at construction time.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/web_contents/web_contents_view_android.h"

#include "base/logging.h"
#include "content/browser/android/content_view_core_impl.h"
#include "content/browser/android/media_player_manager_android.h"
#include "content/browser/renderer_host/render_widget_host_view_android.h"
#include "content/browser/renderer_host/render_view_host_factory.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/interstitial_page_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/web_contents_delegate.h"

namespace content {
WebContentsView* CreateWebContentsView(
    WebContentsImpl* web_contents,
    WebContentsViewDelegate* delegate,
    RenderViewHostDelegateView** render_view_host_delegate_view) {
  WebContentsViewAndroid* rv = new WebContentsViewAndroid(
      web_contents, delegate);
  *render_view_host_delegate_view = rv;
  return rv;
}

WebContentsViewAndroid::WebContentsViewAndroid(
    WebContentsImpl* web_contents,
    WebContentsViewDelegate* delegate)
    : web_contents_(web_contents),
      content_view_core_(NULL),
      delegate_(delegate) {
}

WebContentsViewAndroid::~WebContentsViewAndroid() {
}

void WebContentsViewAndroid::SetContentViewCore(
    ContentViewCoreImpl* content_view_core) {
  content_view_core_ = content_view_core;
  RenderWidgetHostViewAndroid* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
      web_contents_->GetRenderWidgetHostView());
  if (rwhv)
    rwhv->SetContentViewCore(content_view_core_);

  if (web_contents_->ShowingInterstitialPage()) {
    rwhv = static_cast<RenderWidgetHostViewAndroid*>(
        static_cast<InterstitialPageImpl*>(
            web_contents_->GetInterstitialPage())->
                GetRenderViewHost()->GetView());
    if (rwhv)
      rwhv->SetContentViewCore(content_view_core_);
  }
}

void WebContentsViewAndroid::CreateView(const gfx::Size& initial_size) {
}

RenderWidgetHostView* WebContentsViewAndroid::CreateViewForWidget(
    RenderWidgetHost* render_widget_host) {
  if (render_widget_host->GetView()) {
    // During testing, the view will already be set up in most cases to the
    // test view, so we don't want to clobber it with a real one. To verify that
    // this actually is happening (and somebody isn't accidentally creating the
    // view twice), we check for the RVH Factory, which will be set when we're
    // making special ones (which go along with the special views).
    DCHECK(RenderViewHostFactory::has_factory());
    return render_widget_host->GetView();
  }
  // Note that while this instructs the render widget host to reference
  // |native_view_|, this has no effect without also instructing the
  // native view (i.e. ContentView) how to obtain a reference to this widget in
  // order to paint it. See ContentView::GetRenderWidgetHostViewAndroid for an
  // example of how this is achieved for InterstitialPages.
  RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(render_widget_host);
  RenderWidgetHostView* view = new RenderWidgetHostViewAndroid(
      rwhi, content_view_core_);
  view->Show();
  return view;
}

gfx::NativeView WebContentsViewAndroid::GetNativeView() const {
  return content_view_core_;
}

gfx::NativeView WebContentsViewAndroid::GetContentNativeView() const {
  return content_view_core_;
}

gfx::NativeWindow WebContentsViewAndroid::GetTopLevelNativeWindow() const {
  return content_view_core_->GetWindowAndroid();
}

void WebContentsViewAndroid::GetContainerBounds(gfx::Rect* out) const {
  RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
  if (rwhv)
    *out = rwhv->GetViewBounds();
}

void WebContentsViewAndroid::SetPageTitle(const string16& title) {
  if (content_view_core_)
    content_view_core_->SetTitle(title);
}

void WebContentsViewAndroid::OnTabCrashed(base::TerminationStatus status,
                                          int error_code) {
  RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
      web_contents_->GetRenderViewHost());
  if (rvh->media_player_manager())
    rvh->media_player_manager()->DestroyAllMediaPlayers();
  if (content_view_core_)
    content_view_core_->OnTabCrashed();
}

void WebContentsViewAndroid::SizeContents(const gfx::Size& size) {
  // TODO(klobag): Do we need to do anything else?
  RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
  if (rwhv)
    rwhv->SetSize(size);
}

void WebContentsViewAndroid::RenderViewCreated(RenderViewHost* host) {
}

void WebContentsViewAndroid::Focus() {
  if (web_contents_->ShowingInterstitialPage())
    web_contents_->GetInterstitialPage()->Focus();
  else
    web_contents_->GetRenderWidgetHostView()->Focus();
}

void WebContentsViewAndroid::SetInitialFocus() {
  if (web_contents_->FocusLocationBarByDefault())
    web_contents_->SetFocusToLocationBar(false);
  else
    Focus();
}

void WebContentsViewAndroid::StoreFocus() {
  NOTIMPLEMENTED();
}

void WebContentsViewAndroid::RestoreFocus() {
  NOTIMPLEMENTED();
}

WebDropData* WebContentsViewAndroid::GetDropData() const {
  NOTIMPLEMENTED();
  return NULL;
}

bool WebContentsViewAndroid::IsEventTracking() const {
  NOTIMPLEMENTED();
  return false;
}

void WebContentsViewAndroid::CloseTabAfterEventTracking() {
  NOTIMPLEMENTED();
}

gfx::Rect WebContentsViewAndroid::GetViewBounds() const {
  RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
  if (rwhv)
    return rwhv->GetViewBounds();
  else
    return gfx::Rect();
}

void WebContentsViewAndroid::ShowContextMenu(
    const ContextMenuParams& params,
    ContextMenuSourceType type) {
  if (delegate_.get())
    delegate_->ShowContextMenu(params, type);
}

void WebContentsViewAndroid::ShowPopupMenu(
    const gfx::Rect& bounds,
    int item_height,
    double item_font_size,
    int selected_item,
    const std::vector<WebMenuItem>& items,
    bool right_aligned,
    bool allow_multiple_selection) {
  if (content_view_core_) {
    content_view_core_->ShowSelectPopupMenu(
        items, selected_item, allow_multiple_selection);
  }
}

void WebContentsViewAndroid::StartDragging(
    const WebDropData& drop_data,
    WebKit::WebDragOperationsMask allowed_ops,
    const gfx::ImageSkia& image,
    const gfx::Vector2d& image_offset,
    const DragEventSourceInfo& event_info) {
  NOTIMPLEMENTED();
}

void WebContentsViewAndroid::UpdateDragCursor(WebKit::WebDragOperation op) {
  NOTIMPLEMENTED();
}

void WebContentsViewAndroid::GotFocus() {
  // This is only used in the views FocusManager stuff but it bleeds through
  // all subclasses. http://crbug.com/21875
}

// This is called when we the renderer asks us to take focus back (i.e., it has
// iterated past the last focusable element on the page).
void WebContentsViewAndroid::TakeFocus(bool reverse) {
  if (web_contents_->GetDelegate() &&
      web_contents_->GetDelegate()->TakeFocus(web_contents_, reverse))
    return;
  web_contents_->GetRenderWidgetHostView()->Focus();
}

} // namespace content
<|endoftext|>


<commit_before>// Copyright (c) 2017-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <consensus/tx_verify.h>

#include <consensus/consensus.h>
#include <primitives/transaction.h>
#include <script/interpreter.h>
#include <consensus/validation.h>

// TODO remove the following dependencies
#include <chain.h>
#include <coins.h>
#include <util/moneystr.h>
// SYSCOIN
#include <services/asset.h>
bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
{
    if (tx.nLockTime == 0)
        return true;
    if ((int64_t)tx.nLockTime < ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime))
        return true;
    for (const auto& txin : tx.vin) {
        if (!(txin.nSequence == CTxIn::SEQUENCE_FINAL))
            return false;
    }
    return true;
}

std::pair<int, int64_t> CalculateSequenceLocks(const CTransaction &tx, int flags, std::vector<int>* prevHeights, const CBlockIndex& block)
{
    assert(prevHeights->size() == tx.vin.size());

    // Will be set to the equivalent height- and time-based nLockTime
    // values that would be necessary to satisfy all relative lock-
    // time constraints given our view of block chain history.
    // The semantics of nLockTime are the last invalid height/time, so
    // use -1 to have the effect of any height or time being valid.
    int nMinHeight = -1;
    int64_t nMinTime = -1;

    // tx.nVersion is signed integer so requires cast to unsigned otherwise
    // we would be doing a signed comparison and half the range of nVersion
    // wouldn't support BIP 68.
    bool fEnforceBIP68 = static_cast<uint32_t>(tx.nVersion) >= 2
                      && flags & LOCKTIME_VERIFY_SEQUENCE;

    // Do not enforce sequence numbers as a relative lock time
    // unless we have been instructed to
    if (!fEnforceBIP68) {
        return std::make_pair(nMinHeight, nMinTime);
    }

    for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) {
        const CTxIn& txin = tx.vin[txinIndex];

        // Sequence numbers with the most significant bit set are not
        // treated as relative lock-times, nor are they given any
        // consensus-enforced meaning at this point.
        if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) {
            // The height of this input is not relevant for sequence locks
            (*prevHeights)[txinIndex] = 0;
            continue;
        }

        int nCoinHeight = (*prevHeights)[txinIndex];

        if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) {
            int64_t nCoinTime = block.GetAncestor(std::max(nCoinHeight-1, 0))->GetMedianTimePast();
            // NOTE: Subtract 1 to maintain nLockTime semantics
            // BIP 68 relative lock times have the semantics of calculating
            // the first block or time at which the transaction would be
            // valid. When calculating the effective block time or height
            // for the entire transaction, we switch to using the
            // semantics of nLockTime which is the last invalid block
            // time or height.  Thus we subtract 1 from the calculated
            // time or height.

            // Time-based relative lock-times are measured from the
            // smallest allowed timestamp of the block containing the
            // txout being spent, which is the median time past of the
            // block prior.
            nMinTime = std::max(nMinTime, nCoinTime + (int64_t)((txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) << CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) - 1);
        } else {
            nMinHeight = std::max(nMinHeight, nCoinHeight + (int)(txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) - 1);
        }
    }

    return std::make_pair(nMinHeight, nMinTime);
}

bool EvaluateSequenceLocks(const CBlockIndex& block, std::pair<int, int64_t> lockPair)
{
    assert(block.pprev);
    int64_t nBlockTime = block.pprev->GetMedianTimePast();
    if (lockPair.first >= block.nHeight || lockPair.second >= nBlockTime)
        return false;

    return true;
}

bool SequenceLocks(const CTransaction &tx, int flags, std::vector<int>* prevHeights, const CBlockIndex& block)
{
    return EvaluateSequenceLocks(block, CalculateSequenceLocks(tx, flags, prevHeights, block));
}

unsigned int GetLegacySigOpCount(const CTransaction& tx)
{
    unsigned int nSigOps = 0;
    for (const auto& txin : tx.vin)
    {
        nSigOps += txin.scriptSig.GetSigOpCount(false);
    }
    for (const auto& txout : tx.vout)
    {
        nSigOps += txout.scriptPubKey.GetSigOpCount(false);
    }
    return nSigOps;
}

unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& inputs)
{
    if (tx.IsCoinBase())
        return 0;

    unsigned int nSigOps = 0;
    for (unsigned int i = 0; i < tx.vin.size(); i++)
    {
        const Coin& coin = inputs.AccessCoin(tx.vin[i].prevout);
        assert(!coin.IsSpent());
        const CTxOut &prevout = coin.out;
        if (prevout.scriptPubKey.IsPayToScriptHash())
            nSigOps += prevout.scriptPubKey.GetSigOpCount(tx.vin[i].scriptSig);
    }
    return nSigOps;
}

int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, int flags)
{
    int64_t nSigOps = GetLegacySigOpCount(tx) * WITNESS_SCALE_FACTOR;

    if (tx.IsCoinBase())
        return nSigOps;

    if (flags & SCRIPT_VERIFY_P2SH) {
        nSigOps += GetP2SHSigOpCount(tx, inputs) * WITNESS_SCALE_FACTOR;
    }

    for (unsigned int i = 0; i < tx.vin.size(); i++)
    {
        const Coin& coin = inputs.AccessCoin(tx.vin[i].prevout);
        assert(!coin.IsSpent());
        const CTxOut &prevout = coin.out;
        nSigOps += CountWitnessSigOps(tx.vin[i].scriptSig, prevout.scriptPubKey, &tx.vin[i].scriptWitness, flags);
    }
    return nSigOps;
}
// SYSCOIN remove const CTransaction
bool Consensus::CheckTxInputs(CTransaction& tx, TxValidationState& state, const CCoinsViewCache &inputs, int nSpendHeight, CAmount& txfee, const CAssetAllocation &allocation)
{
    // are the actual inputs available?
    if (!inputs.HaveInputs(tx)) {
        return state.Invalid(TxValidationResult::TX_MISSING_INPUTS, "bad-txns-inputs-missingorspent",
                         strprintf("%s: inputs missing/spent", __func__));
    }
    const bool &isSyscoinWithNoInputTx = IsSyscoinWithNoInputTx(tx.nVersion);
    const bool &isSyscoinTx = IsSyscoinTx(tx.nVersion);
    const bool &isAssetTx = IsAssetTx(tx.nVersion);
    CAmount nValueIn = 0;
    std::unordered_map<int32_t, CAmount> mapAssetIn;
    std::unordered_map<int32_t, CAmount> mapAssetOut;
    std::unordered_set<uint32_t> setUsedIndex;
    for (unsigned int i = 0; i < tx.vin.size(); ++i) {
        const COutPoint &prevout = tx.vin[i].prevout;
        const Coin& coin = inputs.AccessCoin(prevout);
        assert(!coin.IsSpent());

        // If prev is coinbase, check that it's matured
        if (coin.IsCoinBase() && nSpendHeight - coin.nHeight < COINBASE_MATURITY) {
            return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "bad-txns-premature-spend-of-coinbase",
                strprintf("tried to spend coinbase at depth %d", nSpendHeight - coin.nHeight));
        }
        if(coin.out.assetInfo.nAsset > 0) {
            auto inRes = mapAssetIn.emplace(coin.out.assetInfo.nAsset, 0);
            if(!inRes.second) {
                inRes.first->second += coin.out.assetInfo.nValue;
            }
            if(coin.out.assetInfo.nValue == 0) {
                if(!isAssetTx) {
                    return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-asset-inputvalue-zero-change-non-asset");
                }
            }
            else if(!AssetRange(coin.out.assetInfo.nValue) || !AssetRange(inRes.first->second)) {
                return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-asset-inputvalues-outofrange");
            }
        }
        // Check for negative or overflow input values
        nValueIn += coin.out.nValue;
        if (!MoneyRange(coin.out.nValue) || !MoneyRange(nValueIn)) {
            return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-inputvalues-outofrange");
        }

    }
    const CAmount &value_out = tx.GetValueOut();
    if (nValueIn < value_out){
        return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-in-belowout",
            strprintf("value in (%s) < value out (%s)", FormatMoney(nValueIn), FormatMoney(value_out)));
    }
    if(isSyscoinTx) {
        if(allocation.voutAssets.empty()) {
            return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-asset-empty-map-out");
        }
        // CTxOut does not serialize assetInfo to make it consistent with Bitcoin serializaion, CTxOutInfo (used by utxo db) persists assetInfo
        // it will add txoutinfo based on vout.assetInfo
        std::vector<CTxOut>& vout = *const_cast<std::vector<CTxOut>*>(&tx.vout);
        for(unsigned int i =0;i< vout.size(); i++) {
            if(!vout[i].assetInfo.IsNull())
                return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-asset-info-not-null");
        }
        for(const auto &it: allocation.voutAssets) {
            const int32_t &nAsset = it.first;
            if(it.second.empty()) {
                return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-asset-empty-out");
            }
            CAmount nTotal = 0;
            // never allow more than 1 change output (zero value output) per asset
            // this bool should be sufficient because later on uniqueness per asset is enforced with bad-txns-asset-not-unique check
            bool bFoundChange = false;
            for(const auto& voutAsset: it.second) {
                const CAmount& nAmount = voutAsset.nValue;
                nTotal += nAmount;
                if(nAmount == 0) {
                    if(!isAssetTx) {
                        return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-asset-zero-change-non-asset");
                    }
                    if(bFoundChange) {
                        return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-asset-multiple-change-out-found");
                    }
                    else {
                        bFoundChange = true;
                    }
                }
                else if(!AssetRange(nAmount) || !AssetRange(nTotal)) {
                    return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-asset-out-outofrange");
                }
                const uint32_t& nOut = voutAsset.n;
                auto itSet = setUsedIndex.emplace(nOut);
                if(!itSet.second) {
                    return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-asset-out-not-unique");
                }
                if(nOut > vout.size()) {
                    return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-asset-invalid-vout-index");
                }
                vout[nOut].assetInfo = CAssetCoinInfo(nAsset, nAmount);
            }
            if(isAssetTx && !bFoundChange) {
                return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-asset-no-change-found");
            }
            if(nTotal > 0 && !AssetRange(nTotal)) {
                return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-asset-total-outofrange");
            }
            auto itRes = mapAssetOut.emplace(it.first, nTotal);
            if(!itRes.second) {
                return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-asset-not-unique");
            }
        }
        // if input was used, validate it against output (note, no fees for assets in == out)
        if(!isSyscoinWithNoInputTx && mapAssetIn != mapAssetOut) {
            return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-assets-io-mismatch");
        }
    }

    // Tally transaction fees
    const CAmount txfee_aux = nValueIn - value_out;
    if (!MoneyRange(txfee_aux)) {
        return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-fee-outofrange");
    }
    txfee = txfee_aux;
    return true;
}
<commit_msg>clear assetinfo before assigning<commit_after>// Copyright (c) 2017-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <consensus/tx_verify.h>

#include <consensus/consensus.h>
#include <primitives/transaction.h>
#include <script/interpreter.h>
#include <consensus/validation.h>

// TODO remove the following dependencies
#include <chain.h>
#include <coins.h>
#include <util/moneystr.h>
// SYSCOIN
#include <services/asset.h>
bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
{
    if (tx.nLockTime == 0)
        return true;
    if ((int64_t)tx.nLockTime < ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime))
        return true;
    for (const auto& txin : tx.vin) {
        if (!(txin.nSequence == CTxIn::SEQUENCE_FINAL))
            return false;
    }
    return true;
}

std::pair<int, int64_t> CalculateSequenceLocks(const CTransaction &tx, int flags, std::vector<int>* prevHeights, const CBlockIndex& block)
{
    assert(prevHeights->size() == tx.vin.size());

    // Will be set to the equivalent height- and time-based nLockTime
    // values that would be necessary to satisfy all relative lock-
    // time constraints given our view of block chain history.
    // The semantics of nLockTime are the last invalid height/time, so
    // use -1 to have the effect of any height or time being valid.
    int nMinHeight = -1;
    int64_t nMinTime = -1;

    // tx.nVersion is signed integer so requires cast to unsigned otherwise
    // we would be doing a signed comparison and half the range of nVersion
    // wouldn't support BIP 68.
    bool fEnforceBIP68 = static_cast<uint32_t>(tx.nVersion) >= 2
                      && flags & LOCKTIME_VERIFY_SEQUENCE;

    // Do not enforce sequence numbers as a relative lock time
    // unless we have been instructed to
    if (!fEnforceBIP68) {
        return std::make_pair(nMinHeight, nMinTime);
    }

    for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) {
        const CTxIn& txin = tx.vin[txinIndex];

        // Sequence numbers with the most significant bit set are not
        // treated as relative lock-times, nor are they given any
        // consensus-enforced meaning at this point.
        if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) {
            // The height of this input is not relevant for sequence locks
            (*prevHeights)[txinIndex] = 0;
            continue;
        }

        int nCoinHeight = (*prevHeights)[txinIndex];

        if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) {
            int64_t nCoinTime = block.GetAncestor(std::max(nCoinHeight-1, 0))->GetMedianTimePast();
            // NOTE: Subtract 1 to maintain nLockTime semantics
            // BIP 68 relative lock times have the semantics of calculating
            // the first block or time at which the transaction would be
            // valid. When calculating the effective block time or height
            // for the entire transaction, we switch to using the
            // semantics of nLockTime which is the last invalid block
            // time or height.  Thus we subtract 1 from the calculated
            // time or height.

            // Time-based relative lock-times are measured from the
            // smallest allowed timestamp of the block containing the
            // txout being spent, which is the median time past of the
            // block prior.
            nMinTime = std::max(nMinTime, nCoinTime + (int64_t)((txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) << CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) - 1);
        } else {
            nMinHeight = std::max(nMinHeight, nCoinHeight + (int)(txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) - 1);
        }
    }

    return std::make_pair(nMinHeight, nMinTime);
}

bool EvaluateSequenceLocks(const CBlockIndex& block, std::pair<int, int64_t> lockPair)
{
    assert(block.pprev);
    int64_t nBlockTime = block.pprev->GetMedianTimePast();
    if (lockPair.first >= block.nHeight || lockPair.second >= nBlockTime)
        return false;

    return true;
}

bool SequenceLocks(const CTransaction &tx, int flags, std::vector<int>* prevHeights, const CBlockIndex& block)
{
    return EvaluateSequenceLocks(block, CalculateSequenceLocks(tx, flags, prevHeights, block));
}

unsigned int GetLegacySigOpCount(const CTransaction& tx)
{
    unsigned int nSigOps = 0;
    for (const auto& txin : tx.vin)
    {
        nSigOps += txin.scriptSig.GetSigOpCount(false);
    }
    for (const auto& txout : tx.vout)
    {
        nSigOps += txout.scriptPubKey.GetSigOpCount(false);
    }
    return nSigOps;
}

unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& inputs)
{
    if (tx.IsCoinBase())
        return 0;

    unsigned int nSigOps = 0;
    for (unsigned int i = 0; i < tx.vin.size(); i++)
    {
        const Coin& coin = inputs.AccessCoin(tx.vin[i].prevout);
        assert(!coin.IsSpent());
        const CTxOut &prevout = coin.out;
        if (prevout.scriptPubKey.IsPayToScriptHash())
            nSigOps += prevout.scriptPubKey.GetSigOpCount(tx.vin[i].scriptSig);
    }
    return nSigOps;
}

int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, int flags)
{
    int64_t nSigOps = GetLegacySigOpCount(tx) * WITNESS_SCALE_FACTOR;

    if (tx.IsCoinBase())
        return nSigOps;

    if (flags & SCRIPT_VERIFY_P2SH) {
        nSigOps += GetP2SHSigOpCount(tx, inputs) * WITNESS_SCALE_FACTOR;
    }

    for (unsigned int i = 0; i < tx.vin.size(); i++)
    {
        const Coin& coin = inputs.AccessCoin(tx.vin[i].prevout);
        assert(!coin.IsSpent());
        const CTxOut &prevout = coin.out;
        nSigOps += CountWitnessSigOps(tx.vin[i].scriptSig, prevout.scriptPubKey, &tx.vin[i].scriptWitness, flags);
    }
    return nSigOps;
}
// SYSCOIN remove const CTransaction
bool Consensus::CheckTxInputs(CTransaction& tx, TxValidationState& state, const CCoinsViewCache &inputs, int nSpendHeight, CAmount& txfee, const CAssetAllocation &allocation)
{
    // are the actual inputs available?
    if (!inputs.HaveInputs(tx)) {
        return state.Invalid(TxValidationResult::TX_MISSING_INPUTS, "bad-txns-inputs-missingorspent",
                         strprintf("%s: inputs missing/spent", __func__));
    }
    const bool &isSyscoinWithNoInputTx = IsSyscoinWithNoInputTx(tx.nVersion);
    const bool &isSyscoinTx = IsSyscoinTx(tx.nVersion);
    const bool &isAssetTx = IsAssetTx(tx.nVersion);
    CAmount nValueIn = 0;
    std::unordered_map<int32_t, CAmount> mapAssetIn;
    std::unordered_map<int32_t, CAmount> mapAssetOut;
    std::unordered_set<uint32_t> setUsedIndex;
    for (unsigned int i = 0; i < tx.vin.size(); ++i) {
        const COutPoint &prevout = tx.vin[i].prevout;
        const Coin& coin = inputs.AccessCoin(prevout);
        assert(!coin.IsSpent());

        // If prev is coinbase, check that it's matured
        if (coin.IsCoinBase() && nSpendHeight - coin.nHeight < COINBASE_MATURITY) {
            return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "bad-txns-premature-spend-of-coinbase",
                strprintf("tried to spend coinbase at depth %d", nSpendHeight - coin.nHeight));
        }
        if(coin.out.assetInfo.nAsset > 0) {
            auto inRes = mapAssetIn.emplace(coin.out.assetInfo.nAsset, 0);
            if(!inRes.second) {
                inRes.first->second += coin.out.assetInfo.nValue;
            }
            if(coin.out.assetInfo.nValue == 0) {
                if(!isAssetTx) {
                    return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-asset-inputvalue-zero-change-non-asset");
                }
            }
            else if(!AssetRange(coin.out.assetInfo.nValue) || !AssetRange(inRes.first->second)) {
                return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-asset-inputvalues-outofrange");
            }
        }
        // Check for negative or overflow input values
        nValueIn += coin.out.nValue;
        if (!MoneyRange(coin.out.nValue) || !MoneyRange(nValueIn)) {
            return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-inputvalues-outofrange");
        }

    }
    const CAmount &value_out = tx.GetValueOut();
    if (nValueIn < value_out){
        return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-in-belowout",
            strprintf("value in (%s) < value out (%s)", FormatMoney(nValueIn), FormatMoney(value_out)));
    }
    if(isSyscoinTx) {
        if(allocation.voutAssets.empty()) {
            return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-asset-empty-map-out");
        }
        // CTxOut does not serialize assetInfo to make it consistent with Bitcoin serializaion, CTxOutInfo (used by utxo db) persists assetInfo
        // it will add txoutinfo based on vout.assetInfo
        std::vector<CTxOut>& vout = *const_cast<std::vector<CTxOut>*>(&tx.vout);
        // clear out assetinfo so it can be re-assigned to the right vout
        for(auto& v: vout) {
            v.assetInfo.SetNull();
        }
        for(const auto &it: allocation.voutAssets) {
            const int32_t &nAsset = it.first;
            if(it.second.empty()) {
                return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-asset-empty-out");
            }
            CAmount nTotal = 0;
            // never allow more than 1 change output (zero value output) per asset
            // this bool should be sufficient because later on uniqueness per asset is enforced with bad-txns-asset-not-unique check
            bool bFoundChange = false;
            for(const auto& voutAsset: it.second) {
                const CAmount& nAmount = voutAsset.nValue;
                nTotal += nAmount;
                if(nAmount == 0) {
                    // 0 amount output not possible for anything except asset tx (new/update/send)
                    if(!isAssetTx) {
                        return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-asset-zero-change-non-asset");
                    }
                    // only 1 is allowed for change
                    if(bFoundChange) {
                        return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-asset-multiple-change-out-found");
                    }
                    else {
                        bFoundChange = true;
                    }
                }
                else if(!AssetRange(nAmount) || !AssetRange(nTotal)) {
                    return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-asset-out-outofrange");
                }
                const uint32_t& nOut = voutAsset.n;
                auto itSet = setUsedIndex.emplace(nOut);
                if(!itSet.second) {
                    return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-asset-out-not-unique");
                }
                if(nOut > vout.size()) {
                    return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-asset-invalid-vout-index");
                }
                vout[nOut].assetInfo = CAssetCoinInfo(nAsset, nAmount);
            }
            // change is required (even though it is sending 0, receiving 0) for asset tx
            if(isAssetTx && !bFoundChange) {
                return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-asset-no-change-found");
            }
            if(nTotal > 0 && !AssetRange(nTotal)) {
                return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-asset-total-outofrange");
            }
            auto itRes = mapAssetOut.emplace(it.first, nTotal);
            if(!itRes.second) {
                return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-asset-not-unique");
            }
        }
        // if input was used, validate it against output (note, no fees for assets in == out)
        if(!isSyscoinWithNoInputTx && mapAssetIn != mapAssetOut) {
            return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-assets-io-mismatch");
        }
    }

    // Tally transaction fees
    const CAmount txfee_aux = nValueIn - value_out;
    if (!MoneyRange(txfee_aux)) {
        return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-fee-outofrange");
    }
    txfee = txfee_aux;
    return true;
}
<|endoftext|>


<commit_before>#pragma once
#ifndef BE_CORE_SYNCHRONIZED_WORK_QUEUE_HPP_
#define BE_CORE_SYNCHRONIZED_WORK_QUEUE_HPP_

#include "be.hpp"
#include "work_queue_traits.hpp"
#include "time.hpp"
#include <functional>
#include <mutex>

namespace be {

///////////////////////////////////////////////////////////////////////////////
template <typename WorkQueue>
class SynchronizedWorkQueue : WorkQueue {
   using traits_type = WorkQueueTraits<WorkQueue>;
   using priority_enable_type = std::enable_if_t<traits_type::supports_priorities::value, typename traits_type::priority_type>;
public:
   using priority_type = typename traits_type::priority_type;

   SynchronizedWorkQueue() = default;

   // move operations are not thread-safe!
   SynchronizedWorkQueue(SynchronizedWorkQueue&& other)
      : WorkQueue(std::move(other)),
        pull_wait_duration_(std::move(other.pull_wait_duration_)),
        shutdown_(std::move(other.shutdown_)) { }

   // move operations are not thread-safe!
   SynchronizedWorkQueue& operator=(SynchronizedWorkQueue&& other) {
      static_cast<WorkQueue&>(*this) = std::move(other);
      pull_wait_duration_ = std::move(other.pull_wait_duration_);
      shutdown_ = std::move(other.shutdown_);
      return *this;
   }

   priority_enable_type default_priority() const {
      std::lock_guard<std::mutex> guard(mutex_);
      return static_cast<const WorkQueue*>(this)->default_priority();
   }

   void default_priority(priority_enable_type priority) {
      std::lock_guard<std::mutex> guard(mutex_);
      static_cast<WorkQueue*>(this)->default_priority(priority);
   }

   void post(std::function<void()> func) {
      std::lock_guard<std::mutex> guard(mutex_);
      static_cast<WorkQueue*>(this)->post(std::move(func));
      cv_.notify_one();
   }

   void post(std::function<void()> func, priority_enable_type priority) {
      std::lock_guard<std::mutex> guard(mutex_);
      static_cast<WorkQueue*>(this)->post(std::move(func), priority);
      cv_.notify_one();
   }

   TU pull_wait_duration() const {
      std::lock_guard<std::mutex> guard(mutex_);
      return pull_wait_duration_;
   }

   void pull_wait_duration(TU duration) {
      std::lock_guard<std::mutex> guard(mutex_);
      pull_wait_duration_ = duration;
   }

   explicit operator bool() const {
      std::lock_guard<std::mutex> guard(mutex_);
      return !shutdown_ && (bool)static_cast<const WorkQueue&>(*this);
   }

   void shutdown(bool shutdown = true) {
      std::lock_guard<std::mutex> guard(mutex_);
      shutdown_ = shutdown;
      cv_.notify_all();
   }

   std::size_t size() const {
      std::lock_guard<std::mutex> guard(mutex_);
      return static_cast<const WorkQueue*>(this)->size();
   }

   bool empty() const {
      std::lock_guard<std::mutex> guard(mutex_);
      return static_cast<const WorkQueue*>(this)->empty();
   }

   std::function<void()> poll() {
      std::lock_guard<std::mutex> guard(mutex_);
      return static_cast<WorkQueue*>(this)->poll();
   }

   std::function<void()> pull() {
      std::unique_lock<std::mutex> lock(mutex_);
      if (static_cast<const WorkQueue*>(this)->empty()) {
         cv_.wait_for(lock, pull_wait_duration_);
      }
      return static_cast<WorkQueue*>(this)->pull();
   }

private:
   mutable std::mutex mutex_;
   std::condition_variable cv_;
   TU pull_wait_duration_ = std::chrono::seconds(1);
   bool shutdown_ = false;
};

} // be

#endif
<commit_msg>SynchronizedWorkQueue priority_type fixes<commit_after>#pragma once
#ifndef BE_CORE_SYNCHRONIZED_WORK_QUEUE_HPP_
#define BE_CORE_SYNCHRONIZED_WORK_QUEUE_HPP_

#include "be.hpp"
#include "work_queue_traits.hpp"
#include "time.hpp"
#include "t_select.hpp"
#include <functional>
#include <mutex>

namespace be {

///////////////////////////////////////////////////////////////////////////////
template <typename WorkQueue>
class SynchronizedWorkQueue : WorkQueue {
   using traits_type = WorkQueueTraits<WorkQueue>;
public:
   using priority_type = typename t::Select<traits_type::supports_priorities::value, typename traits_type::priority_type, Nil>::type;

   SynchronizedWorkQueue() = default;

   // move operations are not thread-safe!
   SynchronizedWorkQueue(SynchronizedWorkQueue&& other)
      : WorkQueue(std::move(other)),
        pull_wait_duration_(std::move(other.pull_wait_duration_)),
        shutdown_(std::move(other.shutdown_)) { }

   // move operations are not thread-safe!
   SynchronizedWorkQueue& operator=(SynchronizedWorkQueue&& other) {
      static_cast<WorkQueue&>(*this) = std::move(other);
      pull_wait_duration_ = std::move(other.pull_wait_duration_);
      shutdown_ = std::move(other.shutdown_);
      return *this;
   }

   template <typename = std::enable_if_t<traits_type::supports_priorities::value>>
   priority_type default_priority() const {
      std::lock_guard<std::mutex> guard(mutex_);
      return static_cast<const WorkQueue*>(this)->default_priority();
   }

   template <typename = std::enable_if_t<traits_type::supports_priorities::value>>
   void default_priority(priority_type priority) {
      std::lock_guard<std::mutex> guard(mutex_);
      static_cast<WorkQueue*>(this)->default_priority(priority);
   }

   void post(std::function<void()> func) {
      std::lock_guard<std::mutex> guard(mutex_);
      static_cast<WorkQueue*>(this)->post(std::move(func));
      cv_.notify_one();
   }

   template <typename = std::enable_if_t<traits_type::supports_priorities::value>>
   void post(std::function<void()> func, priority_type priority) {
      std::lock_guard<std::mutex> guard(mutex_);
      static_cast<WorkQueue*>(this)->post(std::move(func), priority);
      cv_.notify_one();
   }

   TU pull_wait_duration() const {
      std::lock_guard<std::mutex> guard(mutex_);
      return pull_wait_duration_;
   }

   void pull_wait_duration(TU duration) {
      std::lock_guard<std::mutex> guard(mutex_);
      pull_wait_duration_ = duration;
   }

   explicit operator bool() const {
      std::lock_guard<std::mutex> guard(mutex_);
      return !shutdown_ && (bool)static_cast<const WorkQueue&>(*this);
   }

   void shutdown(bool shutdown = true) {
      std::lock_guard<std::mutex> guard(mutex_);
      shutdown_ = shutdown;
      cv_.notify_all();
   }

   std::size_t size() const {
      std::lock_guard<std::mutex> guard(mutex_);
      return static_cast<const WorkQueue*>(this)->size();
   }

   bool empty() const {
      std::lock_guard<std::mutex> guard(mutex_);
      return static_cast<const WorkQueue*>(this)->empty();
   }

   std::function<void()> poll() {
      std::lock_guard<std::mutex> guard(mutex_);
      return static_cast<WorkQueue*>(this)->poll();
   }

   std::function<void()> pull() {
      std::unique_lock<std::mutex> lock(mutex_);
      if (static_cast<const WorkQueue*>(this)->empty()) {
         cv_.wait_for(lock, pull_wait_duration_);
      }
      return static_cast<WorkQueue*>(this)->pull();
   }

private:
   mutable std::mutex mutex_;
   std::condition_variable cv_;
   TU pull_wait_duration_ = std::chrono::seconds(1);
   bool shutdown_ = false;
};

} // be

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/

#ifndef TAO_PEGTL_INTERNAL_MUST_HPP
#define TAO_PEGTL_INTERNAL_MUST_HPP

#include "../config.hpp"

#include "raise.hpp"
#include "skip_control.hpp"

#include "../apply_mode.hpp"
#include "../rewind_mode.hpp"

#include "../analysis/generic.hpp"

namespace TAO_PEGTL_NAMESPACE::internal
{
   // The general case applies must<> to each of the
   // rules in the 'Rules' parameter pack individually.

   template< typename... Rules >
   struct must
      : seq< must< Rules >... >
   {};

   // While in theory the implementation for a single rule could
   // be simplified to must< Rule > = sor< Rule, raise< Rule > >, this
   // would result in some unnecessary run-time overhead.

   template< typename Rule >
   struct must< Rule >
   {
      using analyze_t = typename Rule::analyze_t;

      template< apply_mode A,
                rewind_mode,
                template< typename... >
                class Action,
                template< typename... >
                class Control,
                typename Input,
                typename... States >
      [[nodiscard]] static bool match( Input& in, States&&... st )
      {
         if( !Control< Rule >::template match< A, rewind_mode::dontcare, Action, Control >( in, st... ) ) {
            (void)raise< Rule >::template match< A, rewind_mode::dontcare, Action, Control >( in, st... );
         }
         return true;
      }
   };

   template< typename... Rules >
   inline constexpr bool skip_control< must< Rules... > > = true;

}  // namespace TAO_PEGTL_NAMESPACE::internal

#endif
<commit_msg>Add missing include<commit_after>// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/

#ifndef TAO_PEGTL_INTERNAL_MUST_HPP
#define TAO_PEGTL_INTERNAL_MUST_HPP

#include "../config.hpp"

#include "raise.hpp"
#include "seq.hpp"
#include "skip_control.hpp"

#include "../apply_mode.hpp"
#include "../rewind_mode.hpp"

#include "../analysis/generic.hpp"

namespace TAO_PEGTL_NAMESPACE::internal
{
   // The general case applies must<> to each of the
   // rules in the 'Rules' parameter pack individually.

   template< typename... Rules >
   struct must
      : seq< must< Rules >... >
   {};

   // While in theory the implementation for a single rule could
   // be simplified to must< Rule > = sor< Rule, raise< Rule > >, this
   // would result in some unnecessary run-time overhead.

   template< typename Rule >
   struct must< Rule >
   {
      using analyze_t = typename Rule::analyze_t;

      template< apply_mode A,
                rewind_mode,
                template< typename... >
                class Action,
                template< typename... >
                class Control,
                typename Input,
                typename... States >
      [[nodiscard]] static bool match( Input& in, States&&... st )
      {
         if( !Control< Rule >::template match< A, rewind_mode::dontcare, Action, Control >( in, st... ) ) {
            (void)raise< Rule >::template match< A, rewind_mode::dontcare, Action, Control >( in, st... );
         }
         return true;
      }
   };

   template< typename... Rules >
   inline constexpr bool skip_control< must< Rules... > > = true;

}  // namespace TAO_PEGTL_NAMESPACE::internal

#endif
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
//  CreatorTest.cc
//------------------------------------------------------------------------------
#include "Pre.h"
#include "UnitTest++/src/UnitTest++.h"
#include "Core/Creator.h"
#include "Core/RefCounted.h"
#include "Core/String/String.h"
#include "Core/Containers/Array.h"

using namespace Oryol;
using namespace Oryol::Core;

class CreatorTestClass : public RefCounted {
    OryolClassDecl(CreatorTestClass);
    OryolClassCreator(CreatorTestClass);
public:
    CreatorTestClass() : i0(0) {};
    CreatorTestClass(int i) : i0(i) {};
    CreatorTestClass(int i, String str) : i0(i), str0(str) {};
    CreatorTestClass(int i, String str, Array<int> arr) : i0(i), str0(str), array0(arr) {};
    virtual int32 Bla() const {
        return 0;
    };

    int i0;
    String str0;
    Array<int> array0;
};

class CreatorDerivedClass : public CreatorTestClass {
    OryolClassDecl(CreatorDerivedClass);
    OryolClassCreator(CreatorDerivedClass);
public:
    CreatorDerivedClass() : v0(0) {};
    CreatorDerivedClass(int64 v0_) : v0(v0_) {};
    virtual int32 Bla() const {
        return 1;
    };

    int64 v0;
};

void TestFunc(std::function<Core::Ptr<CreatorTestClass>()> bla) {
    auto obj = bla();
    CHECK(obj->Bla() == 1);
}

TEST(CreatorTest) {
    auto creat0 = CreatorTestClass::Creator();
    auto creat1 = CreatorTestClass::Creator(10);
    auto creat2 = CreatorTestClass::Creator(20, "Bla");
    auto creat3 = CreatorTestClass::Creator(30, "Blub", Array<int>( { 1, 2, 3, 4 } ));

    const auto obj0 = creat0();
    const auto obj1 = creat1();
    const auto obj2 = creat2();
    const auto obj3 = creat3();

    CHECK(obj0.isValid());
    CHECK(obj0->i0 == 0);
    CHECK(obj0->str0.Empty());
    CHECK(obj0->array0.Empty());

    CHECK(obj1.isValid());
    CHECK(obj1->i0 == 10);
    CHECK(obj1->str0.Empty());
    CHECK(obj0->array0.Empty());

    CHECK(obj2.isValid());
    CHECK(obj2->i0 == 20);
    CHECK(obj2->str0 == "Bla");
    CHECK(obj0->array0.Empty());

    CHECK(obj3.isValid());
    CHECK(obj3->i0 == 30);
    CHECK(obj3->str0 == "Blub");
    CHECK(obj3->array0.Size() == 4);
    CHECK(obj3->array0[0] == 1);
    CHECK(obj3->array0[1] == 2);
    CHECK(obj3->array0[2] == 3);
    CHECK(obj3->array0[3] == 4);

    TestFunc(CreatorDerivedClass::Creator(10));
}

<commit_msg>Workaround for CreatorTest.cc on GCC<commit_after>//------------------------------------------------------------------------------
//  CreatorTest.cc
//------------------------------------------------------------------------------
#include "Pre.h"
#include "UnitTest++/src/UnitTest++.h"
#include "Core/Creator.h"
#include "Core/RefCounted.h"
#include "Core/String/String.h"
#include "Core/Containers/Array.h"

using namespace Oryol;
using namespace Oryol::Core;

class CreatorTestClass : public RefCounted {
    OryolClassDecl(CreatorTestClass);
    OryolClassCreator(CreatorTestClass);
public:
    CreatorTestClass() : i0(0) {};
    CreatorTestClass(int i) : i0(i) {};
    CreatorTestClass(int i, String str) : i0(i), str0(str) {};
    CreatorTestClass(int i, String str, Array<int> arr) : i0(i), str0(str), array0(arr) {};
    virtual int32 Bla() const {
        return 0;
    };

    int i0;
    String str0;
    Array<int> array0;
};

class CreatorDerivedClass : public CreatorTestClass {
    OryolClassDecl(CreatorDerivedClass);
    OryolClassCreator(CreatorDerivedClass);
public:
    CreatorDerivedClass() : v0(0) {};
    CreatorDerivedClass(int64 v0_) : v0(v0_) {};
    virtual int32 Bla() const {
        return 1;
    };

    int64 v0;
};

void TestFunc(std::function<Core::Ptr<CreatorTestClass>()> bla) {
    auto obj = bla();
    CHECK(obj->Bla() == 1);
}

TEST(CreatorTest) {
    auto creat0 = CreatorTestClass::Creator();

    #if !(defined(__GNUC__) && !defined(__clang__))
    /** WORKAROUND for GCC bug 'lambda argument pack' **/
    auto creat1 = CreatorTestClass::Creator(10);
    auto creat2 = CreatorTestClass::Creator(20, "Bla");
    auto creat3 = CreatorTestClass::Creator(30, "Blub", Array<int>( { 1, 2, 3, 4 } ));
    #endif

    const auto obj0 = creat0();

    #if !(defined(__GNUC__) && !defined(__clang__))
    /** WORKAROUND for GCC bug 'lambda argument pack' **/
    const auto obj1 = creat1();
    const auto obj2 = creat2();
    const auto obj3 = creat3();
    #endif

    CHECK(obj0.isValid());
    CHECK(obj0->i0 == 0);
    CHECK(obj0->str0.Empty());
    CHECK(obj0->array0.Empty());

    #if !(defined(__GNUC__) && !defined(__clang__))
    /** WORKAROUND for GCC bug 'lambda argument pack' **/
    CHECK(obj1.isValid());
    CHECK(obj1->i0 == 10);
    CHECK(obj1->str0.Empty());
    CHECK(obj0->array0.Empty());

    CHECK(obj2.isValid());
    CHECK(obj2->i0 == 20);
    CHECK(obj2->str0 == "Bla");
    CHECK(obj0->array0.Empty());

    CHECK(obj3.isValid());
    CHECK(obj3->i0 == 30);
    CHECK(obj3->str0 == "Blub");
    CHECK(obj3->array0.Size() == 4);
    CHECK(obj3->array0[0] == 1);
    CHECK(obj3->array0[1] == 2);
    CHECK(obj3->array0[2] == 3);
    CHECK(obj3->array0[3] == 4);

    TestFunc(CreatorDerivedClass::Creator(10));
    #endif
}

<|endoftext|>


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

using namespace ::rtl;

FeDeclarator::FeDeclarator(const OString& name, DeclaratorType declType, AstDeclaration* pComplPart)
    : m_pComplexPart(pComplPart)
    , m_name(name)
    , m_declType(declType)
{
}

FeDeclarator::~FeDeclarator()
{
}

sal_Bool FeDeclarator::checkType(AstDeclaration const * type)
{
    OString tmp(m_name);
    sal_Int32 count = m_name.lastIndexOf( ':' );
    if( count != -1 )
        tmp = m_name.copy( count+1 );

    if (tmp == type->getLocalName())
        return sal_False;
    else
        return sal_True;
}

AstType const * FeDeclarator::compose(AstDeclaration const * pDecl)
{
    AstArray*   pArray;
    AstType*    pType;

    if ( !pDecl->isType() )
    {
        idlc()->error()->noTypeError(pDecl);
        return NULL;
    }
    pType = (AstType*)pDecl;
    if (m_declType == FD_simple || m_pComplexPart == NULL)
        return pType;

    if (m_pComplexPart->getNodeType() == NT_array)
    {
        pArray = (AstArray*)m_pComplexPart;
        pArray->setType(pType);

        // insert array type in global scope
        AstScope* pScope = idlc()->scopes()->bottom();
        AstDeclaration* pDecl = NULL;
        if ( pScope )
        {
            pDecl = pScope->addDeclaration(pArray);
            if ( (AstDeclaration*)pArray != pDecl )
            {
                delete m_pComplexPart;
                m_pComplexPart = pDecl;
            }
        }
        return pArray;
    }

    return NULL; // return through this statement should not happen
}

FeInheritanceHeader::FeInheritanceHeader(NodeType nodeType, ::rtl::OString* pName, ::rtl::OString* pInherits)
    : m_nodeType(nodeType)
    , m_pName(pName)
    , m_pInherits(NULL)
{
    initializeInherits(pInherits);
}

void FeInheritanceHeader::initializeInherits(::rtl::OString* pInherits)
{
    if ( pInherits )
    {
        AstScope* pScope = idlc()->scopes()->topNonNull();
        AstDeclaration* pDecl = pScope->lookupByName(*pInherits);
        if ( pDecl )
        {
            if ( pDecl->getNodeType() == getNodeType()
                 && (pDecl->getNodeType() != NT_interface
                     || static_cast< AstInterface* >(pDecl)->isDefined()) )
            {
                m_pInherits = pDecl;
            }
            else
            {
                idlc()->error()->inheritanceError(
                    getNodeType(), getName(), pDecl);
            }
        }
        else
        {
            idlc()->error()->lookupError(*pInherits);
        }
    }
}
<commit_msg>INTEGRATION: CWS sb18 (1.5.4); FILE MERGED 2004/05/19 08:56:08 sb 1.5.4.3: #i21150# Check that an unpublished entity is not used in the declaration of a published entity. 2004/04/14 08:52:30 sb 1.5.4.2: #i21150# Added support for polymorphic struct types. 2004/04/08 14:37:17 sb 1.5.4.1: #i21150# Fixed UNOIDL typedef support; initial support for polymorphic struct types.<commit_after>/*************************************************************************
 *
 *  $RCSfile: fehelper.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: obo $ $Date: 2004-06-03 15:10:19 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _IDLC_FEHELPER_HXX_
#include <idlc/fehelper.hxx>
#endif
#ifndef _IDLC_ERRORHANDLER_HXX_
#include <idlc/errorhandler.hxx>
#endif
#ifndef _IDLC_ASTARRAY_HXX_
#include <idlc/astarray.hxx>
#endif
#include "idlc/idlc.hxx"

using namespace ::rtl;

FeDeclarator::FeDeclarator(const OString& name, DeclaratorType declType, AstDeclaration* pComplPart)
    : m_pComplexPart(pComplPart)
    , m_name(name)
    , m_declType(declType)
{
}

FeDeclarator::~FeDeclarator()
{
}

sal_Bool FeDeclarator::checkType(AstDeclaration const * type)
{
    OString tmp(m_name);
    sal_Int32 count = m_name.lastIndexOf( ':' );
    if( count != -1 )
        tmp = m_name.copy( count+1 );

    if (tmp == type->getLocalName())
        return sal_False;
    else
        return sal_True;
}

AstType const * FeDeclarator::compose(AstDeclaration const * pDecl)
{
    AstArray*   pArray;
    AstType*    pType;

    if ( pDecl == 0 )
    {
        return NULL;
    }
    if ( !pDecl->isType() )
    {
        idlc()->error()->noTypeError(pDecl);
        return NULL;
    }
    pType = (AstType*)pDecl;
    if (m_declType == FD_simple || m_pComplexPart == NULL)
        return pType;

    if (m_pComplexPart->getNodeType() == NT_array)
    {
        pArray = (AstArray*)m_pComplexPart;
        pArray->setType(pType);

        // insert array type in global scope
        AstScope* pScope = idlc()->scopes()->bottom();
        AstDeclaration* pDecl = NULL;
        if ( pScope )
        {
            pDecl = pScope->addDeclaration(pArray);
            if ( (AstDeclaration*)pArray != pDecl )
            {
                delete m_pComplexPart;
                m_pComplexPart = pDecl;
            }
        }
        return pArray;
    }

    return NULL; // return through this statement should not happen
}

FeInheritanceHeader::FeInheritanceHeader(
    NodeType nodeType, ::rtl::OString* pName, ::rtl::OString* pInherits,
    std::vector< rtl::OString > * typeParameters)
    : m_nodeType(nodeType)
    , m_pName(pName)
    , m_pInherits(NULL)
{
    if (typeParameters != 0) {
        m_typeParameters = *typeParameters;
    }
    initializeInherits(pInherits);
}

void FeInheritanceHeader::initializeInherits(::rtl::OString* pInherits)
{
    if ( pInherits )
    {
        AstScope* pScope = idlc()->scopes()->topNonNull();
        AstDeclaration* pDecl = pScope->lookupByName(*pInherits);
        if ( pDecl )
        {
            AstDeclaration const * resolved = resolveTypedefs(pDecl);
            if ( resolved->getNodeType() == getNodeType()
                 && (resolved->getNodeType() != NT_interface
                     || static_cast< AstInterface const * >(
                         resolved)->isDefined()) )
            {
                if ( idlc()->error()->checkPublished( pDecl ) )
                {
                    m_pInherits = pDecl;
                }
            }
            else
            {
                idlc()->error()->inheritanceError(
                    getNodeType(), getName(), pDecl);
            }
        }
        else
        {
            idlc()->error()->lookupError(*pInherits);
        }
    }
}
<|endoftext|>