<commit_before>/** @file
 *
 * @ingroup modularLibrary
 *
 * @brief A Viewer Object.
 *
 * @details
 *
 * @authors Théo de la Hogue
 *
 * @copyright © 2010, Théo de la Hogue @n
 * This code is licensed under the terms of the "New BSD License" @n
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTViewer.h"

#define thisTTClass			TTViewer
#define thisTTClassName		"Viewer"
#define thisTTClassTags		"viewer"

TTObjectBasePtr TTViewer::instantiate (TTSymbol name, TTValue arguments)
{
	return new TTViewer(arguments);
}

extern "C" void TTViewer::registerClass()
{
	TTClassRegister(TTSymbol("Viewer"), thisTTClassTags, TTViewer::instantiate);
}

TTViewer::TTViewer(const TTValue& arguments) :
TTCallback(arguments),
mAddress(kTTAdrsEmpty),
mDescription(kTTSym_none),
mType(kTTSym_generic),
mTags(kTTSym_none),
mHighlight(NO),
mFreeze(NO),
mDataspace(kTTSym_none),
mDataspaceUnit(kTTSym_none),
mDataspaceConverter("dataspace"),
mActive(YES)
{
	addAttributeWithSetter(Address, kTypeSymbol);
	addAttribute(Description, kTypeSymbol);
	addAttribute(Type, kTypeSymbol);
	addAttribute(Tags, kTypeSymbol);
	addAttributeWithSetter(Highlight, kTypeBoolean);
	addAttributeWithSetter(Freeze, kTypeBoolean);

	addAttribute(Dataspace, kTypeSymbol);
	addAttributeProperty(Dataspace, readOnly, YES);
    addAttributeProperty(Dataspace, hidden, YES);
	addAttributeWithSetter(DataspaceUnit, kTypeSymbol);

	addAttributeWithSetter(Active, kTypeBoolean);

	addAttributeWithSetter(ReturnedValue, kTypeLocalValue);
	addAttributeProperty(ReturnedValue, readOnly, YES);
	addAttributeProperty(ReturnedValue, hidden, YES);

	addMessageWithArguments(Send);
	addMessageProperty(Send, hidden, YES);

    addMessageWithArguments(Grab);
	addMessageProperty(Grab, hidden, YES);
}

TTViewer::~TTViewer()
{
    // disable reception to avoid crash
    mActive = NO;
}

TTErr TTViewer::setAddress(const TTValue& value)
{
    TTBoolean   memoActive = mActive;

	mAddress = value[0];

    // disable reception to avoid crash
    mActive = NO;

    // if no address : delete sender, receiver and observers
	if (mAddress == kTTAdrsEmpty) {

        if (mSender.valid()) {
            mSender.set(kTTSym_address, kTTAdrsEmpty);
            mSender = TTObject();
        }

        if (mReceiver.valid()) {
            mReceiver.set(kTTSym_address, kTTAdrsEmpty);
            mReceiver = TTObject();
        }

        if (mDataspaceObserver.valid()) {
            mDataspaceObserver.set(kTTSym_address, kTTAdrsEmpty);
            mDataspaceObserver = TTObject();
        }

        if (mDataspaceUnitObserver.valid()) {
            mDataspaceUnitObserver.set(kTTSym_address, kTTAdrsEmpty);
            mDataspaceUnitObserver = TTObject();
        }

		return kTTErrGeneric;
    }

	// the default attribute to bind is value
	if (mAddress.getAttribute() == NO_ATTRIBUTE)
		mAddress.appendAttribute(kTTSym_value);

    // create sender if needed
    if (!mSender.valid())
        mSender = TTObject(kTTSym_Sender);

	// change sender address
	mSender.set(kTTSym_address, mAddress);

    // create receiver if needed
    if (!mReceiver.valid()) {

        TTValue args;

        TTObject returnAddressCallback = TTObject("callback");
        returnAddressCallback.set(kTTSym_baton, TTObject(this));
        returnAddressCallback.set(kTTSym_function, TTPtr(&TTViewerReceiveAddressCallback));
        args.append(returnAddressCallback);

        TTObject returnValueCallback = TTObject("callback");
        returnValueCallback.set(kTTSym_baton, TTObject(this));
        returnValueCallback.set(kTTSym_function, TTPtr(&TTViewerReceiveValueCallback));
        args.append(returnValueCallback);

        mReceiver = TTObject(kTTSym_Receiver, args);
    }

	// change receiver address
	mReceiver.set(kTTSym_address, mAddress);

    // create dataspace observer if needed
    if (!mDataspaceObserver.valid()) {

        TTValue     args;
        TTObject    empty;

        args.append(empty);

        TTObject returnDataspaceCallback = TTObject("callback");
        returnDataspaceCallback.set(kTTSym_baton, TTObject(this));
        returnDataspaceCallback.set(kTTSym_function, TTPtr(&TTViewerDataspaceCallback));
        args.append(returnDataspaceCallback);

        mDataspaceObserver = TTObject(kTTSym_Receiver, args);
    }

    // change dataspace observer address and get the value
    mDataspaceObserver.set(kTTSym_address, mAddress.appendAttribute(kTTSym_dataspace));
	mDataspaceObserver.send(kTTSym_Get);

    // create dataspace unit observer if needed
    if (!mDataspaceUnitObserver.valid()) {

        TTValue     args;
        TTObject    empty;

        args.append(empty);

        TTObject returnDataspaceUnitCallback = TTObject("callback");
        returnDataspaceUnitCallback.set(kTTSym_baton, TTObject(this));
        returnDataspaceUnitCallback.set(kTTSym_function, TTPtr(&TTViewerDataspaceUnitCallback));
        args.append(returnDataspaceUnitCallback);

        mDataspaceUnitObserver = TTObject(kTTSym_Receiver, args);
    }

    // change dataspace unit observer address and get the value
    mDataspaceUnitObserver.set(kTTSym_address, mAddress.appendAttribute(kTTSym_dataspaceUnit));
	mDataspaceUnitObserver.send(kTTSym_Get);

    // enable reception
    mActive = memoActive;

    // refresh
    return mReceiver.send(kTTSym_Get);
}

TTErr TTViewer::setActive(const TTValue& value)
{
	mActive = value;

    if (mReceiver.valid()) {

        mReceiver.set(kTTSym_active, mActive);

        if (mActive)
            return mReceiver.send(kTTSym_Get);
        else
            return kTTErrNone;
    }

	return kTTErrGeneric;
}

TTErr TTViewer::setHighlight(const TTValue& value)
{
    TTAttributePtr	anAttribute = NULL;
	TTErr			err;

	mHighlight = value;

	err = this->findAttribute(kTTSym_highlight, &anAttribute);

	if (!err)
		anAttribute->sendNotification(kTTSym_notify, mHighlight);	// we use kTTSym_notify because we know that observers are TTCallback

	return kTTErrNone;
}

TTErr TTViewer::setFreeze(const TTValue& value)
{
	mFreeze = value;

    if (mReceiver.valid()) {

        // update the value if the Viewer is unfreezed
        if (!mFreeze)
            return mReceiver.send(kTTSym_Get);
        else
            return kTTErrNone;
    }

	return kTTErrGeneric;
}

TTErr TTViewer::setReturnedValue(const TTValue& value)
{
	TTAttributePtr	anAttribute = NULL;
	TTErr			err;

	mReturnedValue = value;

	err = this->findAttribute(kTTSym_returnedValue, &anAttribute);

	if (!err)
		anAttribute->sendNotification(kTTSym_notify, mReturnedValue);	// we use kTTSym_notify because we know that observers are TTCallback

	return kTTErrNone;
}

TTErr TTViewer::Send(const TTValue& inputValue, TTValue& outputValue)
{
    if (!mActive)
        return kTTErrNone;

    TTValue none, valueToSend;

    // insert view unit before "ramp" (except for empty value)
    if (inputValue.size() > 0 &&
        mDataspaceUnit != kTTSym_none &&
        mAddress.getAttribute() == kTTSym_value)
    {
        TTBoolean ramp = false;

        for (TTInt32 i = 0; i < inputValue.size(); i++)
        {
            if (inputValue[i].type() == kTypeSymbol)
            {
                TTSymbol s = inputValue[i];
                if (s == kTTSym_ramp)
                {
                    ramp = true;
                    valueToSend.append(mDataspaceUnit);
                }
            }

            valueToSend.append(inputValue[i]);
        }

        if (!ramp)
            valueToSend.append(mDataspaceUnit);
    }
    else
        valueToSend = inputValue;

    if (mSender.valid())
        return mSender.send(kTTSym_Send, valueToSend);
    else
        return kTTErrGeneric;
}

TTErr TTViewer::Grab(const TTValue& inputValue, TTValue& outputValue)
{
    if (mReceiver.valid()) {

        return mReceiver.send(kTTSym_Grab, inputValue, outputValue);
    }

    return kTTErrGeneric;
}

TTErr TTViewer::setDataspaceUnit(const TTValue& value)
{
	TTValue n = value;				// use new value to protect the attribute
	mDataspaceUnit = value;

	return mDataspaceConverter.set("outputUnit", mDataspaceUnit);

	// TODO : notifyObservers(kTTSym_dataspaceUnit, n);
}

#if 0
#pragma mark -
#pragma mark Some Methods
#endif

TTErr TTViewerReceiveAddressCallback(const TTValue& baton, const TTValue& data)
{
    return kTTErrNone;
}

TTErr TTViewerReceiveValueCallback(const TTValue& baton, const TTValue& data)
{
    TTObject    o;
	TTViewerPtr aViewer;
	TTValue		converted;

	// unpack baton (a #TTViewer)
    o = baton[0];
	aViewer = (TTViewerPtr)o.instance();

	if (aViewer->mActive) {

		if (!aViewer->mFreeze)
			// convert data
			aViewer->mDataspaceConverter.send("convert", data, converted);

		else
			// use last data
			converted = aViewer->mReturnedValue;

		// return value
        aViewer->deliver(converted);
        aViewer->setReturnedValue(converted);
	}

	return kTTErrNone;
}

TTErr TTViewerDataspaceCallback(const TTValue& baton, const TTValue& data)
{
    TTObject    o;
	TTViewerPtr aViewer;
	TTValue		v;
    TTSymbol    dataspace;

	// unpack baton (a #TTViewer)
    o = baton[0];
	aViewer = (TTViewerPtr)o.instance();

    dataspace = data;

    // filter repetitions
    if (dataspace != aViewer->mDataspace) {

        aViewer->mDataspace = data;

        return aViewer->mDataspaceConverter.set(kTTSym_dataspace, aViewer->mDataspace);
    }

	return kTTErrNone;
}

TTErr TTViewerDataspaceUnitCallback(const TTValue& baton, const TTValue& data)
{
    TTObject    o;
	TTViewerPtr aViewer;
	TTValue		v;
	TTErr		err;

	// unpack baton (a #TTViewer)
    o = baton[0];
	aViewer = (TTViewerPtr)o.instance();

    // set input unit like the data unit
    aViewer->mDataspaceConverter.set("inputUnit", data);

    // if no unit : set the output unit like the data unit
    if (aViewer->mDataspaceUnit == kTTSym_none)
        aViewer->mDataspaceUnit = data;

    // if the unit is wrong : use the default unit
    err = aViewer->mDataspaceConverter.set("outputUnit", aViewer->mDataspaceUnit);
    if (err) {
        aViewer->mDataspaceConverter.get("outputUnit", v);
        aViewer->mDataspaceUnit = v[0];
        aViewer->mDataspaceConverter.set("outputUnit", aViewer->mDataspaceUnit);
    }

	return kTTErrNone;
}
<commit_msg>Fixing #827 even when attibute is kTTSymEmpty<commit_after>/** @file
 *
 * @ingroup modularLibrary
 *
 * @brief A Viewer Object.
 *
 * @details
 *
 * @authors Théo de la Hogue
 *
 * @copyright © 2010, Théo de la Hogue @n
 * This code is licensed under the terms of the "New BSD License" @n
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTViewer.h"

#define thisTTClass			TTViewer
#define thisTTClassName		"Viewer"
#define thisTTClassTags		"viewer"

TTObjectBasePtr TTViewer::instantiate (TTSymbol name, TTValue arguments)
{
	return new TTViewer(arguments);
}

extern "C" void TTViewer::registerClass()
{
	TTClassRegister(TTSymbol("Viewer"), thisTTClassTags, TTViewer::instantiate);
}

TTViewer::TTViewer(const TTValue& arguments) :
TTCallback(arguments),
mAddress(kTTAdrsEmpty),
mDescription(kTTSym_none),
mType(kTTSym_generic),
mTags(kTTSym_none),
mHighlight(NO),
mFreeze(NO),
mDataspace(kTTSym_none),
mDataspaceUnit(kTTSym_none),
mDataspaceConverter("dataspace"),
mActive(YES)
{
	addAttributeWithSetter(Address, kTypeSymbol);
	addAttribute(Description, kTypeSymbol);
	addAttribute(Type, kTypeSymbol);
	addAttribute(Tags, kTypeSymbol);
	addAttributeWithSetter(Highlight, kTypeBoolean);
	addAttributeWithSetter(Freeze, kTypeBoolean);

	addAttribute(Dataspace, kTypeSymbol);
	addAttributeProperty(Dataspace, readOnly, YES);
    addAttributeProperty(Dataspace, hidden, YES);
	addAttributeWithSetter(DataspaceUnit, kTypeSymbol);

	addAttributeWithSetter(Active, kTypeBoolean);

	addAttributeWithSetter(ReturnedValue, kTypeLocalValue);
	addAttributeProperty(ReturnedValue, readOnly, YES);
	addAttributeProperty(ReturnedValue, hidden, YES);

	addMessageWithArguments(Send);
	addMessageProperty(Send, hidden, YES);

    addMessageWithArguments(Grab);
	addMessageProperty(Grab, hidden, YES);
}

TTViewer::~TTViewer()
{
    // disable reception to avoid crash
    mActive = NO;
}

TTErr TTViewer::setAddress(const TTValue& value)
{
    TTBoolean   memoActive = mActive;

	mAddress = value[0];

    // disable reception to avoid crash
    mActive = NO;

    // if no address : delete sender, receiver and observers
	if (mAddress == kTTAdrsEmpty) {

        if (mSender.valid()) {
            mSender.set(kTTSym_address, kTTAdrsEmpty);
            mSender = TTObject();
        }

        if (mReceiver.valid()) {
            mReceiver.set(kTTSym_address, kTTAdrsEmpty);
            mReceiver = TTObject();
        }

        if (mDataspaceObserver.valid()) {
            mDataspaceObserver.set(kTTSym_address, kTTAdrsEmpty);
            mDataspaceObserver = TTObject();
        }

        if (mDataspaceUnitObserver.valid()) {
            mDataspaceUnitObserver.set(kTTSym_address, kTTAdrsEmpty);
            mDataspaceUnitObserver = TTObject();
        }

		return kTTErrGeneric;
    }

	// the default attribute to bind is value
	if (mAddress.getAttribute() == NO_ATTRIBUTE)
		mAddress.appendAttribute(kTTSym_value);

    // create sender if needed
    if (!mSender.valid())
        mSender = TTObject(kTTSym_Sender);

	// change sender address
	mSender.set(kTTSym_address, mAddress);

    // create receiver if needed
    if (!mReceiver.valid()) {

        TTValue args;

        TTObject returnAddressCallback = TTObject("callback");
        returnAddressCallback.set(kTTSym_baton, TTObject(this));
        returnAddressCallback.set(kTTSym_function, TTPtr(&TTViewerReceiveAddressCallback));
        args.append(returnAddressCallback);

        TTObject returnValueCallback = TTObject("callback");
        returnValueCallback.set(kTTSym_baton, TTObject(this));
        returnValueCallback.set(kTTSym_function, TTPtr(&TTViewerReceiveValueCallback));
        args.append(returnValueCallback);

        mReceiver = TTObject(kTTSym_Receiver, args);
    }

	// change receiver address
	mReceiver.set(kTTSym_address, mAddress);

    // create dataspace observer if needed
    if (!mDataspaceObserver.valid()) {

        TTValue     args;
        TTObject    empty;

        args.append(empty);

        TTObject returnDataspaceCallback = TTObject("callback");
        returnDataspaceCallback.set(kTTSym_baton, TTObject(this));
        returnDataspaceCallback.set(kTTSym_function, TTPtr(&TTViewerDataspaceCallback));
        args.append(returnDataspaceCallback);

        mDataspaceObserver = TTObject(kTTSym_Receiver, args);
    }

    // change dataspace observer address and get the value
    mDataspaceObserver.set(kTTSym_address, mAddress.appendAttribute(kTTSym_dataspace));
	mDataspaceObserver.send(kTTSym_Get);

    // create dataspace unit observer if needed
    if (!mDataspaceUnitObserver.valid()) {

        TTValue     args;
        TTObject    empty;

        args.append(empty);

        TTObject returnDataspaceUnitCallback = TTObject("callback");
        returnDataspaceUnitCallback.set(kTTSym_baton, TTObject(this));
        returnDataspaceUnitCallback.set(kTTSym_function, TTPtr(&TTViewerDataspaceUnitCallback));
        args.append(returnDataspaceUnitCallback);

        mDataspaceUnitObserver = TTObject(kTTSym_Receiver, args);
    }

    // change dataspace unit observer address and get the value
    mDataspaceUnitObserver.set(kTTSym_address, mAddress.appendAttribute(kTTSym_dataspaceUnit));
	mDataspaceUnitObserver.send(kTTSym_Get);

    // enable reception
    mActive = memoActive;

    // refresh
    return mReceiver.send(kTTSym_Get);
}

TTErr TTViewer::setActive(const TTValue& value)
{
	mActive = value;

    if (mReceiver.valid()) {

        mReceiver.set(kTTSym_active, mActive);

        if (mActive)
            return mReceiver.send(kTTSym_Get);
        else
            return kTTErrNone;
    }

	return kTTErrGeneric;
}

TTErr TTViewer::setHighlight(const TTValue& value)
{
    TTAttributePtr	anAttribute = NULL;
	TTErr			err;

	mHighlight = value;

	err = this->findAttribute(kTTSym_highlight, &anAttribute);

	if (!err)
		anAttribute->sendNotification(kTTSym_notify, mHighlight);	// we use kTTSym_notify because we know that observers are TTCallback

	return kTTErrNone;
}

TTErr TTViewer::setFreeze(const TTValue& value)
{
	mFreeze = value;

    if (mReceiver.valid()) {

        // update the value if the Viewer is unfreezed
        if (!mFreeze)
            return mReceiver.send(kTTSym_Get);
        else
            return kTTErrNone;
    }

	return kTTErrGeneric;
}

TTErr TTViewer::setReturnedValue(const TTValue& value)
{
	TTAttributePtr	anAttribute = NULL;
	TTErr			err;

	mReturnedValue = value;

	err = this->findAttribute(kTTSym_returnedValue, &anAttribute);

	if (!err)
		anAttribute->sendNotification(kTTSym_notify, mReturnedValue);	// we use kTTSym_notify because we know that observers are TTCallback

	return kTTErrNone;
}

TTErr TTViewer::Send(const TTValue& inputValue, TTValue& outputValue)
{
    if (!mActive)
        return kTTErrNone;

    TTValue none, valueToSend;

    // insert view unit before "ramp" (except for empty value)
    if (inputValue.size() > 0 &&
        mDataspaceUnit != kTTSym_none &&
        (mAddress.getAttribute() == kTTSym_value || mAddress.getAttribute() == kTTSymEmpty))
    {
        TTBoolean ramp = false;

        for (TTInt32 i = 0; i < inputValue.size(); i++)
        {
            if (inputValue[i].type() == kTypeSymbol)
            {
                TTSymbol s = inputValue[i];
                if (s == kTTSym_ramp)
                {
                    ramp = true;
                    valueToSend.append(mDataspaceUnit);
                }
            }

            valueToSend.append(inputValue[i]);
        }

        if (!ramp)
            valueToSend.append(mDataspaceUnit);
    }
    else
        valueToSend = inputValue;

    if (mSender.valid())
        return mSender.send(kTTSym_Send, valueToSend);
    else
        return kTTErrGeneric;
}

TTErr TTViewer::Grab(const TTValue& inputValue, TTValue& outputValue)
{
    if (mReceiver.valid()) {

        return mReceiver.send(kTTSym_Grab, inputValue, outputValue);
    }

    return kTTErrGeneric;
}

TTErr TTViewer::setDataspaceUnit(const TTValue& value)
{
	TTValue n = value;				// use new value to protect the attribute
	mDataspaceUnit = value;

	return mDataspaceConverter.set("outputUnit", mDataspaceUnit);

	// TODO : notifyObservers(kTTSym_dataspaceUnit, n);
}

#if 0
#pragma mark -
#pragma mark Some Methods
#endif

TTErr TTViewerReceiveAddressCallback(const TTValue& baton, const TTValue& data)
{
    return kTTErrNone;
}

TTErr TTViewerReceiveValueCallback(const TTValue& baton, const TTValue& data)
{
    TTObject    o;
	TTViewerPtr aViewer;
	TTValue		converted;

	// unpack baton (a #TTViewer)
    o = baton[0];
	aViewer = (TTViewerPtr)o.instance();

	if (aViewer->mActive) {

		if (!aViewer->mFreeze)
			// convert data
			aViewer->mDataspaceConverter.send("convert", data, converted);

		else
			// use last data
			converted = aViewer->mReturnedValue;

		// return value
        aViewer->deliver(converted);
        aViewer->setReturnedValue(converted);
	}

	return kTTErrNone;
}

TTErr TTViewerDataspaceCallback(const TTValue& baton, const TTValue& data)
{
    TTObject    o;
	TTViewerPtr aViewer;
	TTValue		v;
    TTSymbol    dataspace;

	// unpack baton (a #TTViewer)
    o = baton[0];
	aViewer = (TTViewerPtr)o.instance();

    dataspace = data;

    // filter repetitions
    if (dataspace != aViewer->mDataspace) {

        aViewer->mDataspace = data;

        return aViewer->mDataspaceConverter.set(kTTSym_dataspace, aViewer->mDataspace);
    }

	return kTTErrNone;
}

TTErr TTViewerDataspaceUnitCallback(const TTValue& baton, const TTValue& data)
{
    TTObject    o;
	TTViewerPtr aViewer;
	TTValue		v;
	TTErr		err;

	// unpack baton (a #TTViewer)
    o = baton[0];
	aViewer = (TTViewerPtr)o.instance();

    // set input unit like the data unit
    aViewer->mDataspaceConverter.set("inputUnit", data);

    // if no unit : set the output unit like the data unit
    if (aViewer->mDataspaceUnit == kTTSym_none)
        aViewer->mDataspaceUnit = data;

    // if the unit is wrong : use the default unit
    err = aViewer->mDataspaceConverter.set("outputUnit", aViewer->mDataspaceUnit);
    if (err) {
        aViewer->mDataspaceConverter.get("outputUnit", v);
        aViewer->mDataspaceUnit = v[0];
        aViewer->mDataspaceConverter.set("outputUnit", aViewer->mDataspaceUnit);
    }

	return kTTErrNone;
}
<|endoftext|>


<commit_before>// -------------------------------------------------------------------------
//    @FileName			:    NFCLogModule.cpp
//    @Author           :    LvSheng.Huang
//    @Date             :    2012-12-15
//    @Module           :    NFCLogModule
//    @Desc             :
// -------------------------------------------------------------------------

#define GLOG_NO_ABBREVIATED_SEVERITIES
#include <stdarg.h>
#include "NFCLogModule.h"
#include "easylogging++.h"

INITIALIZE_EASYLOGGINGPP

unsigned int NFCLogModule::idx = 0;

bool NFCLogModule::CheckLogFileExist(const char* filename)
{
    std::stringstream stream;
    stream << filename << "." << ++idx;
    std::fstream file;
    file.open(stream.str(), std::ios::in);
    if (file)
    {
        return CheckLogFileExist(filename);
    }

    return false;
}

void NFCLogModule::rolloutHandler(const char* filename, std::size_t size)
{
    std::stringstream stream;
    if (!CheckLogFileExist(filename))
    {
        stream << filename << "." << idx;
        rename(filename, stream.str().c_str());
    }
}

NFCLogModule::NFCLogModule(NFIPluginManager* p)
{
    pPluginManager = p;
}

bool NFCLogModule::Init()
{
    mnLogCountTotal = 0;

    el::Loggers::addFlag(el::LoggingFlag::StrictLogFileSizeCheck);
    el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog);
#if NF_PLATFORM == NF_PLATFORM_WIN
    el::Configurations conf("log_win.conf");
#else
    el::Configurations conf("log.conf");
#endif
    el::Loggers::reconfigureAllLoggers(conf);
    el::Helpers::installPreRollOutCallback(rolloutHandler);

    return true;
}

bool NFCLogModule::Shut()
{
    el::Helpers::uninstallPreRollOutCallback();

    return true;
}

bool NFCLogModule::BeforeShut()
{
    return true;

}

bool NFCLogModule::AfterInit()
{
    return true;

}

bool NFCLogModule::Execute()
{
    return true;

}

bool NFCLogModule::Log(const NF_LOG_LEVEL nll, const char* format, ...)
{
    mnLogCountTotal++;

    char szBuffer[1024 * 10] = {0};

    va_list args;
    va_start(args, format);
    vsnprintf(szBuffer, sizeof(szBuffer) - 1, format, args);
    va_end(args);

    switch (nll)
    {
        case NFILogModule::NLL_DEBUG_NORMAL:
            LOG(DEBUG) << mnLogCountTotal << " " << szBuffer;
            break;
        case NFILogModule::NLL_INFO_NORMAL:
            LOG(INFO) << mnLogCountTotal << " " << szBuffer;
            break;
        case NFILogModule::NLL_WARING_NORMAL:
            LOG(WARNING) << mnLogCountTotal << " " << szBuffer;
            break;
        case NFILogModule::NLL_ERROR_NORMAL:
        {
            LOG(ERROR) << mnLogCountTotal << " " << szBuffer;
            //LogStack();
        }
        break;
        case NFILogModule::NLL_FATAL_NORMAL:
            LOG(FATAL) << mnLogCountTotal << " " << szBuffer;
            break;
        default:
            LOG(INFO) << mnLogCountTotal << " " << szBuffer;
            break;
    }

    return true;
}

bool NFCLogModule::LogElement(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strElement, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[ELEMENT] Indent[%s] Element[%s] %s %s %d", ident.ToString().c_str(), strElement.c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[ELEMENT] Indent[%s] Element[%s] %s", ident.ToString().c_str(), strElement.c_str(), strDesc.c_str());
    }

    return true;
}

bool NFCLogModule::LogProperty(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strProperty, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[PROPERTY] Indent[%s] Property[%s] %s %s %d", ident.ToString().c_str(), strProperty.c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[PROPERTY] Indent[%s] Property[%s] %s", ident.ToString().c_str(), strProperty.c_str(), strDesc.c_str());
    }

    return true;

}

bool NFCLogModule::LogRecord(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strRecord, const std::string& strDesc, const int nRow, const int nCol, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[RECORD] Indent[%s] Record[%s] Row[%d] Col[%d] %s %s %d", ident.ToString().c_str(), strRecord.c_str(), nRow, nCol, strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[RECORD] Indent[%s] Record[%s] Row[%d] Col[%d] %s", ident.ToString().c_str(), strRecord.c_str(), nRow, nCol, strDesc.c_str());
    }

    return true;

}

bool NFCLogModule::LogRecord(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strRecord, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[RECORD] Indent[%s] Record[%s] %s %s %d", ident.ToString().c_str(), strRecord.c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[RECORD] Indent[%s] Record[%s] %s", ident.ToString().c_str(), strRecord.c_str(), strDesc.c_str());
    }

    return true;
}

bool NFCLogModule::LogObject(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[OBJECT] Indent[%s] %s %s %d", ident.ToString().c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[OBJECT] Indent[%s] %s", ident.ToString().c_str(), strDesc.c_str());
    }

    return true;

}

void NFCLogModule::LogStack()
{

    //To Add
    /*
    #ifdef NF_DEBUG_MODE
    time_t t = time(0);
    char szDmupName[MAX_PATH];
    tm* ptm = localtime(&t);

    sprintf(szDmupName, "%d_%d_%d_%d_%d_%d.dmp",  ptm->tm_year + 1900, ptm->tm_mon, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
    // 创建Dump文件
    HANDLE hDumpFile = CreateFile(szDmupName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

    // Dump信息
    MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
    //dumpInfo.ExceptionPointers = pException;
    dumpInfo.ThreadId = GetCurrentThreadId();
    dumpInfo.ClientPointers = TRUE;

    // 写入Dump文件内容
    MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);

    CloseHandle(hDumpFile);

    #endif
    */
}

bool NFCLogModule::LogNormal(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strInfo, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "Indent[%s] %s %s %s %d", ident.ToString().c_str(), strInfo.c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "Indent[%s] %s %s", ident.ToString().c_str(), strInfo.c_str(), strDesc.c_str());
    }

    return true;
}

bool NFCLogModule::LogNormal(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strInfo, const int nDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "Indent[%s] %s %d %s %d", ident.ToString().c_str(), strInfo.c_str(), nDesc, func, line);
    }
    else
    {
        Log(nll, "Indent[%s] %s %d", ident.ToString().c_str(), strInfo.c_str(), nDesc);
    }

    return true;
}

bool NFCLogModule::LogNormal(const NF_LOG_LEVEL nll, const NFGUID ident, const std::ostringstream& stream, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "Indent[%s] %s %s %d", ident.ToString().c_str(), strInfo.c_str(), func, line);
    }
    else
    {
        Log(nll, "Indent[%s] %s", ident.ToString().c_str(), strInfo.c_str());
    }

    return true;
}

bool NFCLogModule::LogNormal(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strInfo, const char* func /*= ""*/, int line /*= 0*/)
{
    if (line > 0)
    {
        Log(nll, "Indent[%s] %s %s %d", ident.ToString().c_str(), strInfo.c_str(), func, line);
    }
    else
    {
        Log(nll, "Indent[%s] %s", ident.ToString().c_str(), strInfo.c_str());
    }

    return true;
}

bool NFCLogModule::LogDebugFunctionDump(const NFGUID ident, const int nMsg, const std::string& strArg,  const char* func /*= ""*/, const int line /*= 0*/)
{
    //#ifdef NF_DEBUG_MODE
    LogNormal(NFILogModule::NLL_WARING_NORMAL, ident, strArg + "MsgID:", nMsg, func, line);
    //#endif
    return true;
}

bool NFCLogModule::ChangeLogLevel(const std::string& strLevel)
{
    el::Level logLevel = el::LevelHelper::convertFromString(strLevel.c_str());
    el::Logger* pLogger = el::Loggers::getLogger("default");
    if (NULL == pLogger)
    {
        return false;
    }

    el::Configurations* pConfigurations = pLogger->configurations();
    el::base::TypedConfigurations* pTypeConfigurations = pLogger->typedConfigurations();
    if (NULL == pConfigurations)
    {
        return false;
    }

    // log级别为debug, info, warning, error, fatal(级别逐渐提高)
    // 当传入为info时，则高于(包含)info的级别会输出
    // !!!!!! NOTICE:故意没有break，请千万注意 !!!!!!
    switch (logLevel)
    {
        case el::Level::Fatal:
        {
            el::Configuration errorConfiguration(el::Level::Error, el::ConfigurationType::Enabled, "false");
            pConfigurations->set(&errorConfiguration);
        }
        case el::Level::Error:
        {
            el::Configuration warnConfiguration(el::Level::Warning, el::ConfigurationType::Enabled, "false");
            pConfigurations->set(&warnConfiguration);
        }
        case el::Level::Warning:
        {
            el::Configuration infoConfiguration(el::Level::Info, el::ConfigurationType::Enabled, "false");
            pConfigurations->set(&infoConfiguration);
        }
        case el::Level::Info:
        {
            el::Configuration debugConfiguration(el::Level::Debug, el::ConfigurationType::Enabled, "false");
            pConfigurations->set(&debugConfiguration);

        }
        case el::Level::Debug:
            break;
        default:
            break;
    }

    el::Loggers::reconfigureAllLoggers(*pConfigurations);
    LogNormal(NFILogModule::NLL_INFO_NORMAL, NFGUID(), "[Log] Change log level", strLevel, __FUNCTION__, __LINE__);
    return true;
}
<commit_msg>fixed for log module<commit_after>// -------------------------------------------------------------------------
//    @FileName			:    NFCLogModule.cpp
//    @Author           :    LvSheng.Huang
//    @Date             :    2012-12-15
//    @Module           :    NFCLogModule
//    @Desc             :
// -------------------------------------------------------------------------

#define GLOG_NO_ABBREVIATED_SEVERITIES
#include <stdarg.h>
#include "NFCLogModule.h"
#include "easylogging++.h"

INITIALIZE_EASYLOGGINGPP

unsigned int NFCLogModule::idx = 0;

bool NFCLogModule::CheckLogFileExist(const char* filename)
{
    std::stringstream stream;
    stream << filename << "." << ++idx;
    std::fstream file;
    file.open(stream.str(), std::ios::in);
    if (file)
    {
        return CheckLogFileExist(filename);
    }

    return false;
}

void NFCLogModule::rolloutHandler(const char* filename, std::size_t size)
{
    std::stringstream stream;
    if (!CheckLogFileExist(filename))
    {
        stream << filename << "." << idx;
        rename(filename, stream.str().c_str());
    }
}

NFCLogModule::NFCLogModule(NFIPluginManager* p)
{
    pPluginManager = p;
}

bool NFCLogModule::Init()
{
    mnLogCountTotal = 0;

    el::Loggers::addFlag(el::LoggingFlag::StrictLogFileSizeCheck);
    el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog);
#if NF_PLATFORM == NF_PLATFORM_WIN
    el::Configurations conf("log_win.conf");
#else
    el::Configurations conf("log.conf");
#endif
    el::Loggers::reconfigureAllLoggers(conf);
    el::Helpers::installPreRollOutCallback(rolloutHandler);

    return true;
}

bool NFCLogModule::Shut()
{
    el::Helpers::uninstallPreRollOutCallback();

    return true;
}

bool NFCLogModule::BeforeShut()
{
    return true;

}

bool NFCLogModule::AfterInit()
{
    return true;

}

bool NFCLogModule::Execute()
{
    return true;

}

bool NFCLogModule::Log(const NF_LOG_LEVEL nll, const char* format, ...)
{
    mnLogCountTotal++;

    char szBuffer[1024 * 10] = {0};

    va_list args;
    va_start(args, format);
    vsnprintf(szBuffer, sizeof(szBuffer) - 1, format, args);
    va_end(args);

    switch (nll)
    {
        case NFILogModule::NLL_DEBUG_NORMAL:
            LOG(DEBUG) << mnLogCountTotal << " " << szBuffer;
            break;
        case NFILogModule::NLL_INFO_NORMAL:
            LOG(INFO) << mnLogCountTotal << " " << szBuffer;
            break;
        case NFILogModule::NLL_WARING_NORMAL:
            LOG(WARNING) << mnLogCountTotal << " " << szBuffer;
            break;
        case NFILogModule::NLL_ERROR_NORMAL:
        {
            LOG(ERROR) << mnLogCountTotal << " " << szBuffer;
            //LogStack();
        }
        break;
        case NFILogModule::NLL_FATAL_NORMAL:
            LOG(FATAL) << mnLogCountTotal << " " << szBuffer;
            break;
        default:
            LOG(INFO) << mnLogCountTotal << " " << szBuffer;
            break;
    }

    return true;
}

bool NFCLogModule::LogElement(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strElement, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[ELEMENT] Indent[%s] Element[%s] %s %s %d", ident.ToString().c_str(), strElement.c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[ELEMENT] Indent[%s] Element[%s] %s", ident.ToString().c_str(), strElement.c_str(), strDesc.c_str());
    }

    return true;
}

bool NFCLogModule::LogProperty(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strProperty, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[PROPERTY] Indent[%s] Property[%s] %s %s %d", ident.ToString().c_str(), strProperty.c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[PROPERTY] Indent[%s] Property[%s] %s", ident.ToString().c_str(), strProperty.c_str(), strDesc.c_str());
    }

    return true;

}

bool NFCLogModule::LogRecord(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strRecord, const std::string& strDesc, const int nRow, const int nCol, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[RECORD] Indent[%s] Record[%s] Row[%d] Col[%d] %s %s %d", ident.ToString().c_str(), strRecord.c_str(), nRow, nCol, strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[RECORD] Indent[%s] Record[%s] Row[%d] Col[%d] %s", ident.ToString().c_str(), strRecord.c_str(), nRow, nCol, strDesc.c_str());
    }

    return true;

}

bool NFCLogModule::LogRecord(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strRecord, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[RECORD] Indent[%s] Record[%s] %s %s %d", ident.ToString().c_str(), strRecord.c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[RECORD] Indent[%s] Record[%s] %s", ident.ToString().c_str(), strRecord.c_str(), strDesc.c_str());
    }

    return true;
}

bool NFCLogModule::LogObject(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[OBJECT] Indent[%s] %s %s %d", ident.ToString().c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[OBJECT] Indent[%s] %s", ident.ToString().c_str(), strDesc.c_str());
    }

    return true;

}

void NFCLogModule::LogStack()
{

    //To Add
    /*
    #ifdef NF_DEBUG_MODE
    time_t t = time(0);
    char szDmupName[MAX_PATH];
    tm* ptm = localtime(&t);

    sprintf(szDmupName, "%d_%d_%d_%d_%d_%d.dmp",  ptm->tm_year + 1900, ptm->tm_mon, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
    // 创建Dump文件
    HANDLE hDumpFile = CreateFile(szDmupName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

    // Dump信息
    MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
    //dumpInfo.ExceptionPointers = pException;
    dumpInfo.ThreadId = GetCurrentThreadId();
    dumpInfo.ClientPointers = TRUE;

    // 写入Dump文件内容
    MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);

    CloseHandle(hDumpFile);

    #endif
    */
}

bool NFCLogModule::LogNormal(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strInfo, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "Indent[%s] %s %s %s %d", ident.ToString().c_str(), strInfo.c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "Indent[%s] %s %s", ident.ToString().c_str(), strInfo.c_str(), strDesc.c_str());
    }

    return true;
}

bool NFCLogModule::LogNormal(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strInfo, const int nDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "Indent[%s] %s %d %s %d", ident.ToString().c_str(), strInfo.c_str(), nDesc, func, line);
    }
    else
    {
        Log(nll, "Indent[%s] %s %d", ident.ToString().c_str(), strInfo.c_str(), nDesc);
    }

    return true;
}

bool NFCLogModule::LogNormal(const NF_LOG_LEVEL nll, const NFGUID ident, const std::ostringstream& stream, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "Indent[%s] %s %d", ident.ToString().c_str(), func, line);
    }
    else
    {
        Log(nll, "Indent[%s] %s", ident.ToString().c_str());
    }

    return true;
}

bool NFCLogModule::LogNormal(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strInfo, const char* func /*= ""*/, int line /*= 0*/)
{
    if (line > 0)
    {
        Log(nll, "Indent[%s] %s %s %d", ident.ToString().c_str(), strInfo.c_str(), func, line);
    }
    else
    {
        Log(nll, "Indent[%s] %s", ident.ToString().c_str(), strInfo.c_str());
    }

    return true;
}

bool NFCLogModule::LogDebugFunctionDump(const NFGUID ident, const int nMsg, const std::string& strArg,  const char* func /*= ""*/, const int line /*= 0*/)
{
    //#ifdef NF_DEBUG_MODE
    LogNormal(NFILogModule::NLL_WARING_NORMAL, ident, strArg + "MsgID:", nMsg, func, line);
    //#endif
    return true;
}

bool NFCLogModule::ChangeLogLevel(const std::string& strLevel)
{
    el::Level logLevel = el::LevelHelper::convertFromString(strLevel.c_str());
    el::Logger* pLogger = el::Loggers::getLogger("default");
    if (NULL == pLogger)
    {
        return false;
    }

    el::Configurations* pConfigurations = pLogger->configurations();
    el::base::TypedConfigurations* pTypeConfigurations = pLogger->typedConfigurations();
    if (NULL == pConfigurations)
    {
        return false;
    }

    // log级别为debug, info, warning, error, fatal(级别逐渐提高)
    // 当传入为info时，则高于(包含)info的级别会输出
    // !!!!!! NOTICE:故意没有break，请千万注意 !!!!!!
    switch (logLevel)
    {
        case el::Level::Fatal:
        {
            el::Configuration errorConfiguration(el::Level::Error, el::ConfigurationType::Enabled, "false");
            pConfigurations->set(&errorConfiguration);
        }
        case el::Level::Error:
        {
            el::Configuration warnConfiguration(el::Level::Warning, el::ConfigurationType::Enabled, "false");
            pConfigurations->set(&warnConfiguration);
        }
        case el::Level::Warning:
        {
            el::Configuration infoConfiguration(el::Level::Info, el::ConfigurationType::Enabled, "false");
            pConfigurations->set(&infoConfiguration);
        }
        case el::Level::Info:
        {
            el::Configuration debugConfiguration(el::Level::Debug, el::ConfigurationType::Enabled, "false");
            pConfigurations->set(&debugConfiguration);

        }
        case el::Level::Debug:
            break;
        default:
            break;
    }

    el::Loggers::reconfigureAllLoggers(*pConfigurations);
    LogNormal(NFILogModule::NLL_INFO_NORMAL, NFGUID(), "[Log] Change log level", strLevel, __FUNCTION__, __LINE__);
    return true;
}
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2008 Torus Knot Software Ltd
Also see acknowledgements in Readme.html

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program 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 program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.

You may alternatively use this source under the terms of a specific version of
the OGRE Unrestricted License provided you have obtained such a license from
Torus Knot Software Ltd.
-----------------------------------------------------------------------------
*/
#include "OgreStableHeaders.h"
#include "OgrePrerequisites.h"
#include "OgreMemoryNedAlloc.h"
#include "OgrePlatformInformation.h"
#include "OgreMemoryTracker.h"

#if OGRE_MEMORY_ALLOCATOR == OGRE_MEMORY_ALLOCATOR_NED

// include ned implementation
#include <nedmalloc.c>

namespace Ogre
{

	//---------------------------------------------------------------------
	void* NedAllocImpl::allocBytes(size_t count,
		const char* file, int line, const char* func)
	{
		void* ptr = nedalloc::nedmalloc(count);
	#if OGRE_MEMORY_TRACKER
		// this alloc policy doesn't do pools (yet, ned can do it)
		MemoryTracker::get()._recordAlloc(ptr, count, 0, file, line, func);
	#else
		// avoid unused params warning
		file;line;func;
	#endif
		return ptr;
	}
	//---------------------------------------------------------------------
	void NedAllocImpl::deallocBytes(void* ptr)
	{
#if OGRE_MEMORY_TRACKER
		MemoryTracker::get()._recordDealloc(ptr);
#endif
		nedalloc::nedfree(ptr);
	}
	//---------------------------------------------------------------------
	void* NedAllocImpl::allocBytesAligned(size_t align, size_t count,
		const char* file, int line, const char* func)
	{
		// default to platform SIMD alignment if none specified
		void* ptr =  align ? nedalloc::nedmemalign(align, count)
			: nedalloc::nedmemalign(OGRE_SIMD_ALIGNMENT, count);
#if OGRE_MEMORY_TRACKER
		// this alloc policy doesn't do pools (yet, ned can do it)
		MemoryTracker::get()._recordAlloc(ptr, count, 0, file, line, func);
#else
		// avoid unused params warning
		file;line;func;
#endif
		return ptr;
	}
	//---------------------------------------------------------------------
	void NedAllocImpl::deallocBytesAligned(size_t align, void* ptr)
	{
#if OGRE_MEMORY_TRACKER
		// this alloc policy doesn't do pools (yet, ned can do it)
		MemoryTracker::get()._recordDealloc(ptr);
#endif
		nedalloc::nedfree(ptr);
	}

}

#endif

<commit_msg>Ned deallocator should deal with null pointers<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2008 Torus Knot Software Ltd
Also see acknowledgements in Readme.html

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program 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 program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.

You may alternatively use this source under the terms of a specific version of
the OGRE Unrestricted License provided you have obtained such a license from
Torus Knot Software Ltd.
-----------------------------------------------------------------------------
*/
#include "OgreStableHeaders.h"
#include "OgrePrerequisites.h"
#include "OgreMemoryNedAlloc.h"
#include "OgrePlatformInformation.h"
#include "OgreMemoryTracker.h"

#if OGRE_MEMORY_ALLOCATOR == OGRE_MEMORY_ALLOCATOR_NED

// include ned implementation
#include <nedmalloc.c>

namespace Ogre
{

	//---------------------------------------------------------------------
	void* NedAllocImpl::allocBytes(size_t count,
		const char* file, int line, const char* func)
	{
		void* ptr = nedalloc::nedmalloc(count);
	#if OGRE_MEMORY_TRACKER
		// this alloc policy doesn't do pools (yet, ned can do it)
		MemoryTracker::get()._recordAlloc(ptr, count, 0, file, line, func);
	#else
		// avoid unused params warning
		file;line;func;
	#endif
		return ptr;
	}
	//---------------------------------------------------------------------
	void NedAllocImpl::deallocBytes(void* ptr)
	{
		// deal with null
		if (!ptr)
			return;
#if OGRE_MEMORY_TRACKER
		MemoryTracker::get()._recordDealloc(ptr);
#endif
		nedalloc::nedfree(ptr);
	}
	//---------------------------------------------------------------------
	void* NedAllocImpl::allocBytesAligned(size_t align, size_t count,
		const char* file, int line, const char* func)
	{
		// default to platform SIMD alignment if none specified
		void* ptr =  align ? nedalloc::nedmemalign(align, count)
			: nedalloc::nedmemalign(OGRE_SIMD_ALIGNMENT, count);
#if OGRE_MEMORY_TRACKER
		// this alloc policy doesn't do pools (yet, ned can do it)
		MemoryTracker::get()._recordAlloc(ptr, count, 0, file, line, func);
#else
		// avoid unused params warning
		file;line;func;
#endif
		return ptr;
	}
	//---------------------------------------------------------------------
	void NedAllocImpl::deallocBytesAligned(size_t align, void* ptr)
	{
		// deal with null
		if (!ptr)
			return;
#if OGRE_MEMORY_TRACKER
		// this alloc policy doesn't do pools (yet, ned can do it)
		MemoryTracker::get()._recordDealloc(ptr);
#endif
		nedalloc::nedfree(ptr);
	}

}

#endif

<|endoftext|>


<commit_before><commit_msg>Adding the possibility to select the POI based on pdg (ALICE3 LoI)<commit_after><|endoftext|>


<commit_before>#include "transactionrecord.h"
#include "wallet/wallet.h"
#include "base58.h"

std::string GetTxProject(uint256 hash, int& out_blocknumber, int& out_blocktype, double& out_rac);

/* Return positive answer if transaction should be shown in list. */
bool TransactionRecord::showTransaction(const CWalletTx &wtx, bool datetime_limit_flag, const int64_t &datetime_limit)
{

    // Do not show transactions earlier than the datetime_limit if the flag is set.
    if (datetime_limit_flag && (int64_t) wtx.nTime < datetime_limit)
    {
        return false;
    }

    std::string ShowOrphans = GetArg("-showorphans", "false");

	//R Halford - POS Transactions - If Orphaned follow showorphans directive:
	if (wtx.IsCoinStake() && !wtx.IsInMainChain())
	{
	       //Orphaned tx
		   return (ShowOrphans=="true" ? true : false);
    }

    if (wtx.IsCoinBase())
    {
        // Ensures we show generated coins / mined transactions at depth 1
        if (!wtx.IsInMainChain())
        {
            return false;
        }
    }

    // Suppress OP_RETURN transactions if they did not originate from you.
    // This is not "very" taxing but necessary since the transaction is in the wallet already.
    if (!wtx.IsFromMe())
    {
        for (auto const& txout : wtx.vout)
        {
            if (txout.scriptPubKey == (CScript() << OP_RETURN))
                return false;
        }
    }
    return true;
}

/*
 * Decompose CWallet transaction to model transaction records.
 */
QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx)
{
    QList<TransactionRecord> parts;
    int64_t nTime = wtx.GetTxTime();
    int64_t nCredit = wtx.GetCredit(true);
    int64_t nDebit = wtx.GetDebit();
    int64_t nNet = nCredit - nDebit;
    size_t wtx_size = wtx.vout.size();
    uint256 hash = wtx.GetHash();

    std::map<std::string, std::string> mapValue = wtx.mapValue;

    bool fContractPresent = false;
    NN::ContractType ContractType;

    if (!wtx.GetContracts().empty())
    {
         const auto& contract = wtx.GetContracts().begin();
         fContractPresent = true;
         ContractType = contract->m_type.Value();
    }

    // This is legacy CoinBase for PoW, no longer used.
    if (wtx.IsCoinBase())
    {
        for (const auto& txout :wtx.vout)
        {
            if (wallet->IsMine(txout) != ISMINE_NO)
            {
                TransactionRecord sub(hash, nTime);
                CTxDestination address;
                sub.idx = parts.size(); // sequence number

                if (ExtractDestination(txout.scriptPubKey, address))
                {
                    sub.address = CBitcoinAddress(address).ToString();
                }

                // Generated (proof-of-work)
                sub.type = TransactionRecord::Generated;
                sub.credit = txout.nValue;

                parts.append(sub);
            }
        }
    }
    // Since we are now separating out the sent sidestake info
    // into a separate subtransaction, we need to include the entire
    // value of the coinstake transaction here, rather than the previous
    // counting of only IsMine outputs.
    else if (wtx.IsCoinStake())
    {
        // We check the first coinstake output (zero is empty) for IsMine to
        // determine how to characterize the entire coinstake transaction. The
        // sidestakes to other (not mine) addresses are accounted for as negatives
        // in a separate subtransaction. The first output is ALWAYS guaranteed to be
        // the stake return to the original owner, and so matches the input.
        if (wallet->IsMine(wtx.vout[1]) != ISMINE_NO)
        {
            TransactionRecord sub(hash, nTime);
            CTxDestination address;
            sub.idx = parts.size();
            sub.vout = 1;

            sub.type = TransactionRecord::Generated;
            // The coinstake HAS to be from an address.
            if(ExtractDestination(wtx.vout[1].scriptPubKey, address))
            {
                sub.address = CBitcoinAddress(address).ToString();
            }

            // Here we add up all of the outputs, whether they are ours (the stake return with
            // apportioned reward, or not (sidestake), because the part that is not ours
            // will be accounted in the separated sidestake send transaction.
            sub.credit = 0;
            for (const auto& txout : wtx.vout)
            {
                sub.credit += txout.nValue;
            }

            sub.debit = -nDebit;

            // Append the subtransaction to the parts QList (transaction record).
            parts.append(sub);
        }

        // We only want outputs > 1 because the zeroth output is always empty,
        // and the first output is always the staker's. Output 2 onwards may or
        // may not be a sidestake, depending on whether stakesplitting is active,
        // or whether sidestaking is even turned on.
        // There is no coalescing here. A separate subtransaction is created for each
        // sidestake.
        for (unsigned int t = 2; t < wtx_size; t++)
        {
            // If this is not a stake split AND either vout[1] is mine OR
            // vout[t] is mine
            if (wtx.vout[t].scriptPubKey != wtx.vout[1].scriptPubKey &&
                    (wallet->IsMine(wtx.vout[1]) != ISMINE_NO ||
                     wallet->IsMine(wtx.vout[t]) != ISMINE_NO))
            {
                TransactionRecord sub(hash, nTime);
                CTxDestination address;
                sub.idx = parts.size(); // sequence number
                sub.vout = t;

                sub.type = TransactionRecord::Generated;

                if (ExtractDestination(wtx.vout[t].scriptPubKey, address))
                {
                    sub.address = CBitcoinAddress(address).ToString();
                }

                int64_t nValue = wtx.vout[t].nValue;

                if (wallet->IsMine(wtx.vout[t]) != ISMINE_NO)
                {
                    sub.credit = nValue;
                }
                else
                {
                    sub.debit = -nValue;
                }

                parts.append(sub);
            }
        }
    }
    else if (nNet > 0)
    {
        for (const auto& txout : wtx.vout)
        {
            if (wallet->IsMine(txout) != ISMINE_NO)
            {
                TransactionRecord sub(hash, nTime);
                CTxDestination address;
                sub.idx = parts.size(); // sequence number

                if (ExtractDestination(txout.scriptPubKey, address))
                {
                    // Received by Bitcoin Address
                    sub.type = TransactionRecord::RecvWithAddress;
                    sub.address = CBitcoinAddress(address).ToString();
                }
                else
                {
                    // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction
                    sub.type = TransactionRecord::RecvFromOther;
                    sub.address = mapValue["from"];
                }

                sub.credit = txout.nValue;

                parts.append(sub);
            }
        }
    }
    else // Everything else
    {
        bool fAllFromMe = true;
        for (auto const& txin : wtx.vin)
            fAllFromMe = fAllFromMe && (wallet->IsMine(txin) != ISMINE_NO);

        bool fAllToMe = true;
        for (auto const& txout : wtx.vout)
            fAllToMe = fAllToMe && (wallet->IsMine(txout) != ISMINE_NO);

        if (fAllFromMe && fAllToMe)
        {
            // Payment to self
            int64_t nChange = wtx.GetChange();

            parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "",
                                           -(nDebit - nChange), nCredit - nChange, 0));
        }
        else if (fAllFromMe)
        {
            //
            // Debit
            //
            int64_t nTxFee = nDebit - wtx.GetValueOut();

            // for tracking message type display
            bool fMessageDisplayed = false;

            for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++)
            {
                const CTxOut& txout = wtx.vout[nOut];
                TransactionRecord sub(hash, nTime);
                sub.idx = parts.size();

                if(wallet->IsMine(txout) != ISMINE_NO)
                {
                    // Ignore parts sent to self, as this is usually the change
                    // from a transaction sent back to our own address.
                    continue;
                }

                CTxDestination address;
                if (ExtractDestination(txout.scriptPubKey, address))
                {
                    // Sent to Bitcoin Address
                    sub.type = TransactionRecord::SendToAddress;
                    sub.address = CBitcoinAddress(address).ToString();
                }
                else
                {
                    // Sent to IP, or other non-address transaction like OP_EVAL
                    sub.type = TransactionRecord::SendToOther;
                    sub.address = mapValue["to"];
                }

                int64_t nValue = txout.nValue;
                /* Add fee to first output */
                if (nTxFee > 0)
                {
                    nValue += nTxFee;
                    nTxFee = 0;
                }
                sub.debit = -nValue;

                // Determine if the transaction is a beacon advertisement or a vote.
                // For right now, there should only be one contract in a transaction.
                // We will simply select the first and only one. Note that we are
                // looping through the outputs one by one in the for loop above this,
                // So if we get here, we are not a coinbase or coinstake, and we are on
                // an ouput that isn't ours. The worst that can happen from this
                // simple approach is to label more than one output with the
                // first found contract type. For right now, this is sufficient, because
                // the contracts that are sent right now only contain two outputs,
                // the burn and the change. We will have to get more sophisticated
                // when we allow more than one contract per transaction.

                // Notice this doesn't mess with the value or debit, it simply
                // overrides the TransactionRecord enum type.
                if (fContractPresent)
                {
                    switch (ContractType)
                    {
                    case NN::ContractType::BEACON:
                        sub.type = TransactionRecord::BeaconAdvertisement;
                        break;
                    case NN::ContractType::POLL:
                        sub.type = TransactionRecord::Poll;
                        break;
                    case NN::ContractType::VOTE:
                        sub.type = TransactionRecord::Vote;
                        break;
                    case NN::ContractType::MESSAGE:
                        // Only display the message type for the first not is mine output
                        if (!fMessageDisplayed && wallet->IsMine(txout) == ISMINE_NO)
                        {
                            sub.type = TransactionRecord::Message;
                            fMessageDisplayed = true;
                        }
                        // Do not display the op return output for a send message contract separately.
                        else if (txout.scriptPubKey[0] == OP_RETURN)
                        {
                            continue;
                        }
                        break;
                    default:
                        break; // Suppress warning
                    }
                }

                parts.append(sub);
            }
        }
        else
        {
            //
            // Mixed debit transaction, can't break down payees
            //
            parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", nNet, 0, 0));
        }
    }

    return parts;
}

void TransactionRecord::updateStatus(const CWalletTx &wtx)
{
    AssertLockHeld(cs_main);
    // Determine transaction status

    // Find the block the tx is in
    CBlockIndex* pindex = NULL;
    BlockMap::iterator mi = mapBlockIndex.find(wtx.hashBlock);
    if (mi != mapBlockIndex.end())
        pindex = (*mi).second;

    // Sort order, unrecorded transactions sort to the top
    status.sortKey = strprintf("%010d-%01d-%010u-%03d",
        (pindex ? pindex->nHeight : std::numeric_limits<int>::max()),
        (wtx.IsCoinBase() ? 1 : 0),
        wtx.nTimeReceived,
        idx);
    status.countsForBalance = wtx.IsTrusted() && !(wtx.GetBlocksToMaturity() > 0);
    status.depth = wtx.GetDepthInMainChain();
    status.cur_num_blocks = nBestHeight;

    if (!IsFinalTx(wtx, nBestHeight + 1))
    {
        if (wtx.nLockTime < LOCKTIME_THRESHOLD)
        {
            status.status = TransactionStatus::OpenUntilBlock;
            status.open_for = wtx.nLockTime - nBestHeight;
        }
        else
        {
            status.status = TransactionStatus::OpenUntilDate;
            status.open_for = wtx.nLockTime;
        }
    }

    // For generated transactions, determine maturity
    else if(type == TransactionRecord::Generated)
    {
        if (wtx.GetBlocksToMaturity() > 0)
        {
            status.status = TransactionStatus::Immature;

            if (wtx.IsInMainChain())
            {
                status.matures_in = wtx.GetBlocksToMaturity();

                // Check if the block was requested by anyone
                if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
                    status.status = TransactionStatus::MaturesWarning;
            }
            else
            {
                status.status = TransactionStatus::NotAccepted;
            }
        }
        else
        {
            status.status = TransactionStatus::Confirmed;
        }
    }
    else
    {
        if (status.depth < 0)
        {
            status.status = TransactionStatus::Conflicted;
        }
        else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
        {
            status.status = TransactionStatus::Offline;
        }
        else if (status.depth == 0)
        {
            status.status = TransactionStatus::Unconfirmed;
        }
        else if (status.depth < RecommendedNumConfirmations)
        {
            status.status = TransactionStatus::Confirming;
        }
        else
        {
            status.status = TransactionStatus::Confirmed;
        }
    }
}

bool TransactionRecord::statusUpdateNeeded()
{
    AssertLockHeld(cs_main);
    return status.cur_num_blocks != nBestHeight;
}

std::string TransactionRecord::getTxID()
{
    return hash.ToString();
}

<commit_msg>Adjust OP_RETURN filter to only filter version 1 transactions<commit_after>#include "transactionrecord.h"
#include "wallet/wallet.h"
#include "base58.h"

std::string GetTxProject(uint256 hash, int& out_blocknumber, int& out_blocktype, double& out_rac);

/* Return positive answer if transaction should be shown in list. */
bool TransactionRecord::showTransaction(const CWalletTx &wtx, bool datetime_limit_flag, const int64_t &datetime_limit)
{

    // Do not show transactions earlier than the datetime_limit if the flag is set.
    if (datetime_limit_flag && (int64_t) wtx.nTime < datetime_limit)
    {
        return false;
    }

    std::string ShowOrphans = GetArg("-showorphans", "false");

	//R Halford - POS Transactions - If Orphaned follow showorphans directive:
	if (wtx.IsCoinStake() && !wtx.IsInMainChain())
	{
	       //Orphaned tx
		   return (ShowOrphans=="true" ? true : false);
    }

    if (wtx.IsCoinBase())
    {
        // Ensures we show generated coins / mined transactions at depth 1
        if (!wtx.IsInMainChain())
        {
            return false;
        }
    }

    // Suppress OP_RETURN transactions if they did not originate from you.
    // This is not "very" taxing but necessary since the transaction is in the wallet already.
    // We only do this for version 1 transactions, because this legacy error does not occur
    // anymore, and we can't filter entire transactions that have OP_RETURNs, since
    // some outputs are relevent with the new contract types, such as messages.
    if (wtx.nVersion == 1 && !wtx.IsFromMe())
    {
        for (auto const& txout : wtx.vout)
        {
            if (txout.scriptPubKey == (CScript() << OP_RETURN))
                return false;
        }
    }
    return true;
}

/*
 * Decompose CWallet transaction to model transaction records.
 */
QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx)
{
    QList<TransactionRecord> parts;
    int64_t nTime = wtx.GetTxTime();
    int64_t nCredit = wtx.GetCredit(true);
    int64_t nDebit = wtx.GetDebit();
    int64_t nNet = nCredit - nDebit;
    size_t wtx_size = wtx.vout.size();
    uint256 hash = wtx.GetHash();

    std::map<std::string, std::string> mapValue = wtx.mapValue;

    bool fContractPresent = false;
    NN::ContractType ContractType;

    if (!wtx.GetContracts().empty())
    {
         const auto& contract = wtx.GetContracts().begin();
         fContractPresent = true;
         ContractType = contract->m_type.Value();
    }

    // This is legacy CoinBase for PoW, no longer used.
    if (wtx.IsCoinBase())
    {
        for (const auto& txout :wtx.vout)
        {
            if (wallet->IsMine(txout) != ISMINE_NO)
            {
                TransactionRecord sub(hash, nTime);
                CTxDestination address;
                sub.idx = parts.size(); // sequence number

                if (ExtractDestination(txout.scriptPubKey, address))
                {
                    sub.address = CBitcoinAddress(address).ToString();
                }

                // Generated (proof-of-work)
                sub.type = TransactionRecord::Generated;
                sub.credit = txout.nValue;

                parts.append(sub);
            }
        }
    }
    // Since we are now separating out the sent sidestake info
    // into a separate subtransaction, we need to include the entire
    // value of the coinstake transaction here, rather than the previous
    // counting of only IsMine outputs.
    else if (wtx.IsCoinStake())
    {
        // We check the first coinstake output (zero is empty) for IsMine to
        // determine how to characterize the entire coinstake transaction. The
        // sidestakes to other (not mine) addresses are accounted for as negatives
        // in a separate subtransaction. The first output is ALWAYS guaranteed to be
        // the stake return to the original owner, and so matches the input.
        if (wallet->IsMine(wtx.vout[1]) != ISMINE_NO)
        {
            TransactionRecord sub(hash, nTime);
            CTxDestination address;
            sub.idx = parts.size();
            sub.vout = 1;

            sub.type = TransactionRecord::Generated;
            // The coinstake HAS to be from an address.
            if(ExtractDestination(wtx.vout[1].scriptPubKey, address))
            {
                sub.address = CBitcoinAddress(address).ToString();
            }

            // Here we add up all of the outputs, whether they are ours (the stake return with
            // apportioned reward, or not (sidestake), because the part that is not ours
            // will be accounted in the separated sidestake send transaction.
            sub.credit = 0;
            for (const auto& txout : wtx.vout)
            {
                sub.credit += txout.nValue;
            }

            sub.debit = -nDebit;

            // Append the subtransaction to the parts QList (transaction record).
            parts.append(sub);
        }

        // We only want outputs > 1 because the zeroth output is always empty,
        // and the first output is always the staker's. Output 2 onwards may or
        // may not be a sidestake, depending on whether stakesplitting is active,
        // or whether sidestaking is even turned on.
        // There is no coalescing here. A separate subtransaction is created for each
        // sidestake.
        for (unsigned int t = 2; t < wtx_size; t++)
        {
            // If this is not a stake split AND either vout[1] is mine OR
            // vout[t] is mine
            if (wtx.vout[t].scriptPubKey != wtx.vout[1].scriptPubKey &&
                    (wallet->IsMine(wtx.vout[1]) != ISMINE_NO ||
                     wallet->IsMine(wtx.vout[t]) != ISMINE_NO))
            {
                TransactionRecord sub(hash, nTime);
                CTxDestination address;
                sub.idx = parts.size(); // sequence number
                sub.vout = t;

                sub.type = TransactionRecord::Generated;

                if (ExtractDestination(wtx.vout[t].scriptPubKey, address))
                {
                    sub.address = CBitcoinAddress(address).ToString();
                }

                int64_t nValue = wtx.vout[t].nValue;

                if (wallet->IsMine(wtx.vout[t]) != ISMINE_NO)
                {
                    sub.credit = nValue;
                }
                else
                {
                    sub.debit = -nValue;
                }

                parts.append(sub);
            }
        }
    }
    else if (nNet > 0)
    {
        for (const auto& txout : wtx.vout)
        {
            if (wallet->IsMine(txout) != ISMINE_NO)
            {
                TransactionRecord sub(hash, nTime);
                CTxDestination address;
                sub.idx = parts.size(); // sequence number

                if (ExtractDestination(txout.scriptPubKey, address))
                {
                    // Received by Bitcoin Address
                    sub.type = TransactionRecord::RecvWithAddress;
                    sub.address = CBitcoinAddress(address).ToString();
                }
                else
                {
                    // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction
                    sub.type = TransactionRecord::RecvFromOther;
                    sub.address = mapValue["from"];
                }

                if (fContractPresent && ContractType == NN::ContractType::MESSAGE)
                {
                    sub.type = TransactionRecord::Message;
                }

                sub.credit = txout.nValue;

                parts.append(sub);
            }
        }
    }
    else // Everything else
    {
        bool fAllFromMe = true;
        for (auto const& txin : wtx.vin)
            fAllFromMe = fAllFromMe && (wallet->IsMine(txin) != ISMINE_NO);

        bool fAllToMe = true;
        for (auto const& txout : wtx.vout)
            fAllToMe = fAllToMe && (wallet->IsMine(txout) != ISMINE_NO);

        if (fAllFromMe && fAllToMe)
        {
            // Payment to self
            int64_t nChange = wtx.GetChange();

            parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "",
                                           -(nDebit - nChange), nCredit - nChange, 0));
        }
        else if (fAllFromMe)
        {
            //
            // Debit
            //
            int64_t nTxFee = nDebit - wtx.GetValueOut();

            // for tracking message type display
            bool fMessageDisplayed = false;

            for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++)
            {
                const CTxOut& txout = wtx.vout[nOut];
                TransactionRecord sub(hash, nTime);
                sub.idx = parts.size();

                if(wallet->IsMine(txout) != ISMINE_NO)
                {
                    // Ignore parts sent to self, as this is usually the change
                    // from a transaction sent back to our own address.
                    continue;
                }

                CTxDestination address;
                if (ExtractDestination(txout.scriptPubKey, address))
                {
                    // Sent to Bitcoin Address
                    sub.type = TransactionRecord::SendToAddress;
                    sub.address = CBitcoinAddress(address).ToString();
                }
                else
                {
                    // Sent to IP, or other non-address transaction like OP_EVAL
                    sub.type = TransactionRecord::SendToOther;
                    sub.address = mapValue["to"];
                }

                int64_t nValue = txout.nValue;
                /* Add fee to first output */
                if (nTxFee > 0)
                {
                    nValue += nTxFee;
                    nTxFee = 0;
                }
                sub.debit = -nValue;

                // Determine if the transaction is a beacon advertisement or a vote.
                // For right now, there should only be one contract in a transaction.
                // We will simply select the first and only one. Note that we are
                // looping through the outputs one by one in the for loop above this,
                // So if we get here, we are not a coinbase or coinstake, and we are on
                // an ouput that isn't ours. The worst that can happen from this
                // simple approach is to label more than one output with the
                // first found contract type. For right now, this is sufficient, because
                // the contracts that are sent right now only contain two outputs,
                // the burn and the change. We will have to get more sophisticated
                // when we allow more than one contract per transaction.

                // Notice this doesn't mess with the value or debit, it simply
                // overrides the TransactionRecord enum type.
                if (fContractPresent)
                {
                    switch (ContractType)
                    {
                    case NN::ContractType::BEACON:
                        sub.type = TransactionRecord::BeaconAdvertisement;
                        break;
                    case NN::ContractType::POLL:
                        sub.type = TransactionRecord::Poll;
                        break;
                    case NN::ContractType::VOTE:
                        sub.type = TransactionRecord::Vote;
                        break;
                    case NN::ContractType::MESSAGE:
                        // Only display the message type for the first not is mine output
                        if (!fMessageDisplayed && wallet->IsMine(txout) == ISMINE_NO)
                        {
                            sub.type = TransactionRecord::Message;
                            fMessageDisplayed = true;
                        }
                        // Do not display the op return output for a send message contract separately.
                        else if (txout.scriptPubKey[0] == OP_RETURN)
                        {
                            continue;
                        }
                        break;
                    default:
                        break; // Suppress warning
                    }
                }

                parts.append(sub);
            }
        }
        else
        {
            //
            // Mixed debit transaction, can't break down payees
            //
            parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", nNet, 0, 0));
        }
    }

    return parts;
}

void TransactionRecord::updateStatus(const CWalletTx &wtx)
{
    AssertLockHeld(cs_main);
    // Determine transaction status

    // Find the block the tx is in
    CBlockIndex* pindex = NULL;
    BlockMap::iterator mi = mapBlockIndex.find(wtx.hashBlock);
    if (mi != mapBlockIndex.end())
        pindex = (*mi).second;

    // Sort order, unrecorded transactions sort to the top
    status.sortKey = strprintf("%010d-%01d-%010u-%03d",
        (pindex ? pindex->nHeight : std::numeric_limits<int>::max()),
        (wtx.IsCoinBase() ? 1 : 0),
        wtx.nTimeReceived,
        idx);
    status.countsForBalance = wtx.IsTrusted() && !(wtx.GetBlocksToMaturity() > 0);
    status.depth = wtx.GetDepthInMainChain();
    status.cur_num_blocks = nBestHeight;

    if (!IsFinalTx(wtx, nBestHeight + 1))
    {
        if (wtx.nLockTime < LOCKTIME_THRESHOLD)
        {
            status.status = TransactionStatus::OpenUntilBlock;
            status.open_for = wtx.nLockTime - nBestHeight;
        }
        else
        {
            status.status = TransactionStatus::OpenUntilDate;
            status.open_for = wtx.nLockTime;
        }
    }

    // For generated transactions, determine maturity
    else if(type == TransactionRecord::Generated)
    {
        if (wtx.GetBlocksToMaturity() > 0)
        {
            status.status = TransactionStatus::Immature;

            if (wtx.IsInMainChain())
            {
                status.matures_in = wtx.GetBlocksToMaturity();

                // Check if the block was requested by anyone
                if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
                    status.status = TransactionStatus::MaturesWarning;
            }
            else
            {
                status.status = TransactionStatus::NotAccepted;
            }
        }
        else
        {
            status.status = TransactionStatus::Confirmed;
        }
    }
    else
    {
        if (status.depth < 0)
        {
            status.status = TransactionStatus::Conflicted;
        }
        else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
        {
            status.status = TransactionStatus::Offline;
        }
        else if (status.depth == 0)
        {
            status.status = TransactionStatus::Unconfirmed;
        }
        else if (status.depth < RecommendedNumConfirmations)
        {
            status.status = TransactionStatus::Confirming;
        }
        else
        {
            status.status = TransactionStatus::Confirmed;
        }
    }
}

bool TransactionRecord::statusUpdateNeeded()
{
    AssertLockHeld(cs_main);
    return status.cur_num_blocks != nBestHeight;
}

std::string TransactionRecord::getTxID()
{
    return hash.ToString();
}

<|endoftext|>


<commit_before>// Copyright (c) 2010 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 "chrome/browser/task_manager.h"

#include "app/l10n_util.h"
#include "base/file_path.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/extensions/crashed_extension_infobar.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/tab_contents/infobar_delegate.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/page_transition_types.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "grit/generated_resources.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

const FilePath::CharType* kTitle1File = FILE_PATH_LITERAL("title1.html");

class ResourceChangeObserver : public TaskManagerModelObserver {
 public:
  ResourceChangeObserver(const TaskManagerModel* model,
                         int target_resource_count)
      : model_(model),
        target_resource_count_(target_resource_count) {
  }

  virtual void OnModelChanged() {
    OnResourceChange();
  }

  virtual void OnItemsChanged(int start, int length) {
    OnResourceChange();
  }

  virtual void OnItemsAdded(int start, int length) {
    OnResourceChange();
  }

  virtual void OnItemsRemoved(int start, int length) {
    OnResourceChange();
  }

 private:
  void OnResourceChange() {
    if (model_->ResourceCount() == target_resource_count_)
      MessageLoopForUI::current()->Quit();
  }

  const TaskManagerModel* model_;
  const int target_resource_count_;
};

}  // namespace

class TaskManagerBrowserTest : public ExtensionBrowserTest {
 public:
  TaskManagerModel* model() const {
    return TaskManager::GetInstance()->model();
  }

  void WaitForResourceChange(int target_count) {
    if (model()->ResourceCount() == target_count)
      return;
    ResourceChangeObserver observer(model(), target_count);
    model()->AddObserver(&observer);
    ui_test_utils::RunMessageLoop();
    model()->RemoveObserver(&observer);
  }
};

// Regression test for http://crbug.com/13361
IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, ShutdownWhileOpen) {
  browser()->window()->ShowTaskManager();
}

IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticeTabContentsChanges) {
  EXPECT_EQ(0, model()->ResourceCount());

  // Show the task manager. This populates the model, and helps with debugging
  // (you see the task manager).
  browser()->window()->ShowTaskManager();

  // Browser and the New Tab Page.
  EXPECT_EQ(2, model()->ResourceCount());

  // Open a new tab and make sure we notice that.
  GURL url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory),
                                     FilePath(kTitle1File)));
  browser()->AddTabWithURL(url, GURL(), PageTransition::TYPED,
                           true, 0, false, NULL);
  WaitForResourceChange(3);

  // Close the tab and verify that we notice.
  TabContents* first_tab = browser()->GetTabContentsAt(0);
  ASSERT_TRUE(first_tab);
  browser()->CloseTabContents(first_tab);
  WaitForResourceChange(2);
}

#if defined(OS_WIN)
// http://crbug.com/31663
#define NoticeExtensionChanges DISABLED_NoticeExtensionChanges
#endif

IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticeExtensionChanges) {
  EXPECT_EQ(0, model()->ResourceCount());

  // Show the task manager. This populates the model, and helps with debugging
  // (you see the task manager).
  browser()->window()->ShowTaskManager();

  // Browser and the New Tab Page.
  EXPECT_EQ(2, model()->ResourceCount());

  // Loading an extension should result in a new resource being
  // created for it.
  ASSERT_TRUE(LoadExtension(
      test_data_dir_.AppendASCII("common").AppendASCII("one_in_shelf")));
  WaitForResourceChange(3);

  // Make sure we also recognize extensions with just background pages.
  ASSERT_TRUE(LoadExtension(
      test_data_dir_.AppendASCII("common").AppendASCII("background_page")));
  WaitForResourceChange(4);
}

IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, KillExtension) {
  // Show the task manager. This populates the model, and helps with debugging
  // (you see the task manager).
  browser()->window()->ShowTaskManager();

  ASSERT_TRUE(LoadExtension(
      test_data_dir_.AppendASCII("common").AppendASCII("background_page")));

  // Wait until we see the loaded extension in the task manager (the three
  // resources are: the browser process, New Tab Page, and the extension).
  WaitForResourceChange(3);

  EXPECT_TRUE(model()->GetResourceExtension(0) == NULL);
  EXPECT_TRUE(model()->GetResourceExtension(1) == NULL);
  ASSERT_TRUE(model()->GetResourceExtension(2) != NULL);

  // Kill the extension process and make sure we notice it.
  TaskManager::GetInstance()->KillProcess(2);
  WaitForResourceChange(2);
}

IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, KillExtensionAndReload) {
  // Show the task manager. This populates the model, and helps with debugging
  // (you see the task manager).
  browser()->window()->ShowTaskManager();

  ASSERT_TRUE(LoadExtension(
      test_data_dir_.AppendASCII("common").AppendASCII("background_page")));

  // Wait until we see the loaded extension in the task manager (the three
  // resources are: the browser process, New Tab Page, and the extension).
  WaitForResourceChange(3);

  EXPECT_TRUE(model()->GetResourceExtension(0) == NULL);
  EXPECT_TRUE(model()->GetResourceExtension(1) == NULL);
  ASSERT_TRUE(model()->GetResourceExtension(2) != NULL);

  // Kill the extension process and make sure we notice it.
  TaskManager::GetInstance()->KillProcess(2);
  WaitForResourceChange(2);

  // Reload the extension using the "crashed extension" infobar while the task
  // manager is still visible. Make sure we don't crash and the extension
  // gets reloaded and noticed in the task manager.
  TabContents* current_tab = browser()->GetSelectedTabContents();
  ASSERT_EQ(1, current_tab->infobar_delegate_count());
  InfoBarDelegate* delegate = current_tab->GetInfoBarDelegateAt(0);
  CrashedExtensionInfoBarDelegate* crashed_delegate =
      delegate->AsCrashedExtensionInfoBarDelegate();
  ASSERT_TRUE(crashed_delegate);
  crashed_delegate->Accept();
  WaitForResourceChange(3);
}

// Regression test for http://crbug.com/18693.
IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, ReloadExtension) {
  // Show the task manager. This populates the model, and helps with debugging
  // (you see the task manager).
  browser()->window()->ShowTaskManager();

  ASSERT_TRUE(LoadExtension(
      test_data_dir_.AppendASCII("common").AppendASCII("background_page")));

  // Wait until we see the loaded extension in the task manager (the three
  // resources are: the browser process, New Tab Page, and the extension).
  WaitForResourceChange(3);

  EXPECT_TRUE(model()->GetResourceExtension(0) == NULL);
  EXPECT_TRUE(model()->GetResourceExtension(1) == NULL);
  ASSERT_TRUE(model()->GetResourceExtension(2) != NULL);

  const Extension* extension = model()->GetResourceExtension(2);

  // Reload the extension a few times and make sure our resource count
  // doesn't increase.
  ReloadExtension(extension->id());
  WaitForResourceChange(3);
  extension = model()->GetResourceExtension(2);

  ReloadExtension(extension->id());
  WaitForResourceChange(3);
  extension = model()->GetResourceExtension(2);

  ReloadExtension(extension->id());
  WaitForResourceChange(3);
}

// Crashy, http://crbug.com/42301.
IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest,
                       DISABLED_PopulateWebCacheFields) {
  EXPECT_EQ(0, model()->ResourceCount());

  // Show the task manager. This populates the model, and helps with debugging
  // (you see the task manager).
  browser()->window()->ShowTaskManager();

  // Browser and the New Tab Page.
  EXPECT_EQ(2, model()->ResourceCount());

  // Open a new tab and make sure we notice that.
  GURL url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory),
                                     FilePath(kTitle1File)));
  browser()->AddTabWithURL(url, GURL(), PageTransition::TYPED,
                           true, 0, false, NULL);
  WaitForResourceChange(3);

  // Check that we get some value for the cache columns.
  DCHECK_NE(model()->GetResourceWebCoreImageCacheSize(2),
            l10n_util::GetString(IDS_TASK_MANAGER_NA_CELL_TEXT));
  DCHECK_NE(model()->GetResourceWebCoreScriptsCacheSize(2),
            l10n_util::GetString(IDS_TASK_MANAGER_NA_CELL_TEXT));
  DCHECK_NE(model()->GetResourceWebCoreCSSCacheSize(2),
            l10n_util::GetString(IDS_TASK_MANAGER_NA_CELL_TEXT));
}
<commit_msg>Disable crashy TaskManagerBrowserTest.ReloadExtension on Windows.<commit_after>// Copyright (c) 2010 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 "chrome/browser/task_manager.h"

#include "app/l10n_util.h"
#include "base/file_path.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/extensions/crashed_extension_infobar.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/tab_contents/infobar_delegate.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/page_transition_types.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "grit/generated_resources.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

const FilePath::CharType* kTitle1File = FILE_PATH_LITERAL("title1.html");

class ResourceChangeObserver : public TaskManagerModelObserver {
 public:
  ResourceChangeObserver(const TaskManagerModel* model,
                         int target_resource_count)
      : model_(model),
        target_resource_count_(target_resource_count) {
  }

  virtual void OnModelChanged() {
    OnResourceChange();
  }

  virtual void OnItemsChanged(int start, int length) {
    OnResourceChange();
  }

  virtual void OnItemsAdded(int start, int length) {
    OnResourceChange();
  }

  virtual void OnItemsRemoved(int start, int length) {
    OnResourceChange();
  }

 private:
  void OnResourceChange() {
    if (model_->ResourceCount() == target_resource_count_)
      MessageLoopForUI::current()->Quit();
  }

  const TaskManagerModel* model_;
  const int target_resource_count_;
};

}  // namespace

class TaskManagerBrowserTest : public ExtensionBrowserTest {
 public:
  TaskManagerModel* model() const {
    return TaskManager::GetInstance()->model();
  }

  void WaitForResourceChange(int target_count) {
    if (model()->ResourceCount() == target_count)
      return;
    ResourceChangeObserver observer(model(), target_count);
    model()->AddObserver(&observer);
    ui_test_utils::RunMessageLoop();
    model()->RemoveObserver(&observer);
  }
};

// Regression test for http://crbug.com/13361
IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, ShutdownWhileOpen) {
  browser()->window()->ShowTaskManager();
}

IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticeTabContentsChanges) {
  EXPECT_EQ(0, model()->ResourceCount());

  // Show the task manager. This populates the model, and helps with debugging
  // (you see the task manager).
  browser()->window()->ShowTaskManager();

  // Browser and the New Tab Page.
  EXPECT_EQ(2, model()->ResourceCount());

  // Open a new tab and make sure we notice that.
  GURL url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory),
                                     FilePath(kTitle1File)));
  browser()->AddTabWithURL(url, GURL(), PageTransition::TYPED,
                           true, 0, false, NULL);
  WaitForResourceChange(3);

  // Close the tab and verify that we notice.
  TabContents* first_tab = browser()->GetTabContentsAt(0);
  ASSERT_TRUE(first_tab);
  browser()->CloseTabContents(first_tab);
  WaitForResourceChange(2);
}

#if defined(OS_WIN)
// http://crbug.com/31663
#define NoticeExtensionChanges DISABLED_NoticeExtensionChanges
#endif

IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticeExtensionChanges) {
  EXPECT_EQ(0, model()->ResourceCount());

  // Show the task manager. This populates the model, and helps with debugging
  // (you see the task manager).
  browser()->window()->ShowTaskManager();

  // Browser and the New Tab Page.
  EXPECT_EQ(2, model()->ResourceCount());

  // Loading an extension should result in a new resource being
  // created for it.
  ASSERT_TRUE(LoadExtension(
      test_data_dir_.AppendASCII("common").AppendASCII("one_in_shelf")));
  WaitForResourceChange(3);

  // Make sure we also recognize extensions with just background pages.
  ASSERT_TRUE(LoadExtension(
      test_data_dir_.AppendASCII("common").AppendASCII("background_page")));
  WaitForResourceChange(4);
}

IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, KillExtension) {
  // Show the task manager. This populates the model, and helps with debugging
  // (you see the task manager).
  browser()->window()->ShowTaskManager();

  ASSERT_TRUE(LoadExtension(
      test_data_dir_.AppendASCII("common").AppendASCII("background_page")));

  // Wait until we see the loaded extension in the task manager (the three
  // resources are: the browser process, New Tab Page, and the extension).
  WaitForResourceChange(3);

  EXPECT_TRUE(model()->GetResourceExtension(0) == NULL);
  EXPECT_TRUE(model()->GetResourceExtension(1) == NULL);
  ASSERT_TRUE(model()->GetResourceExtension(2) != NULL);

  // Kill the extension process and make sure we notice it.
  TaskManager::GetInstance()->KillProcess(2);
  WaitForResourceChange(2);
}

IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, KillExtensionAndReload) {
  // Show the task manager. This populates the model, and helps with debugging
  // (you see the task manager).
  browser()->window()->ShowTaskManager();

  ASSERT_TRUE(LoadExtension(
      test_data_dir_.AppendASCII("common").AppendASCII("background_page")));

  // Wait until we see the loaded extension in the task manager (the three
  // resources are: the browser process, New Tab Page, and the extension).
  WaitForResourceChange(3);

  EXPECT_TRUE(model()->GetResourceExtension(0) == NULL);
  EXPECT_TRUE(model()->GetResourceExtension(1) == NULL);
  ASSERT_TRUE(model()->GetResourceExtension(2) != NULL);

  // Kill the extension process and make sure we notice it.
  TaskManager::GetInstance()->KillProcess(2);
  WaitForResourceChange(2);

  // Reload the extension using the "crashed extension" infobar while the task
  // manager is still visible. Make sure we don't crash and the extension
  // gets reloaded and noticed in the task manager.
  TabContents* current_tab = browser()->GetSelectedTabContents();
  ASSERT_EQ(1, current_tab->infobar_delegate_count());
  InfoBarDelegate* delegate = current_tab->GetInfoBarDelegateAt(0);
  CrashedExtensionInfoBarDelegate* crashed_delegate =
      delegate->AsCrashedExtensionInfoBarDelegate();
  ASSERT_TRUE(crashed_delegate);
  crashed_delegate->Accept();
  WaitForResourceChange(3);
}

// Regression test for http://crbug.com/18693.
#if defined(OS_WIN)
// Crashy, http://crbug.com/42315.
#define MAYBE_ReloadExtension DISABLED_ReloadExtension
#else
#define MAYBE_ReloadExtension ReloadExtension
#endif
IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, MAYBE_ReloadExtension) {
  // Show the task manager. This populates the model, and helps with debugging
  // (you see the task manager).
  browser()->window()->ShowTaskManager();

  ASSERT_TRUE(LoadExtension(
      test_data_dir_.AppendASCII("common").AppendASCII("background_page")));

  // Wait until we see the loaded extension in the task manager (the three
  // resources are: the browser process, New Tab Page, and the extension).
  WaitForResourceChange(3);

  EXPECT_TRUE(model()->GetResourceExtension(0) == NULL);
  EXPECT_TRUE(model()->GetResourceExtension(1) == NULL);
  ASSERT_TRUE(model()->GetResourceExtension(2) != NULL);

  const Extension* extension = model()->GetResourceExtension(2);

  // Reload the extension a few times and make sure our resource count
  // doesn't increase.
  ReloadExtension(extension->id());
  WaitForResourceChange(3);
  extension = model()->GetResourceExtension(2);

  ReloadExtension(extension->id());
  WaitForResourceChange(3);
  extension = model()->GetResourceExtension(2);

  ReloadExtension(extension->id());
  WaitForResourceChange(3);
}

// Crashy, http://crbug.com/42301.
IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest,
                       DISABLED_PopulateWebCacheFields) {
  EXPECT_EQ(0, model()->ResourceCount());

  // Show the task manager. This populates the model, and helps with debugging
  // (you see the task manager).
  browser()->window()->ShowTaskManager();

  // Browser and the New Tab Page.
  EXPECT_EQ(2, model()->ResourceCount());

  // Open a new tab and make sure we notice that.
  GURL url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory),
                                     FilePath(kTitle1File)));
  browser()->AddTabWithURL(url, GURL(), PageTransition::TYPED,
                           true, 0, false, NULL);
  WaitForResourceChange(3);

  // Check that we get some value for the cache columns.
  DCHECK_NE(model()->GetResourceWebCoreImageCacheSize(2),
            l10n_util::GetString(IDS_TASK_MANAGER_NA_CELL_TEXT));
  DCHECK_NE(model()->GetResourceWebCoreScriptsCacheSize(2),
            l10n_util::GetString(IDS_TASK_MANAGER_NA_CELL_TEXT));
  DCHECK_NE(model()->GetResourceWebCoreCSSCacheSize(2),
            l10n_util::GetString(IDS_TASK_MANAGER_NA_CELL_TEXT));
}
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 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 "base/test_suite.h"
#include "chrome/common/chrome_paths.h"

int main(int argc, char** argv) {
  TestSuite test_suite(argc, argv);

  // Register Chrome Path provider so that we can get test data dir.
  chrome::RegisterPathProvider();

  return test_suite.Run();
}
<commit_msg>Fix include.<commit_after>// Copyright (c) 2006-2008 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 "base/test/test_suite.h"
#include "chrome/common/chrome_paths.h"

int main(int argc, char** argv) {
  TestSuite test_suite(argc, argv);

  // Register Chrome Path provider so that we can get test data dir.
  chrome::RegisterPathProvider();

  return test_suite.Run();
}
<|endoftext|>