<commit_before>#include <v8.h>
#include <node.h>
#include <node_object_wrap.h>
#include <node_version.h>
#include <nan.h>
#include <queue>
#include <uv.h>

#include "lib/RtMidi/RtMidi.h"
#include "lib/RtMidi/RtMidi.cpp"

class NodeMidiOutput : public Nan::ObjectWrap
{
private:
    RtMidiOut* out;
public:
    static Nan::Persistent<v8::FunctionTemplate> s_ct;
    static void Init(v8::Handle<v8::Object> target)
    {
        Nan::HandleScope scope;

        v8::Local<v8::FunctionTemplate> t = Nan::New<v8::FunctionTemplate>(NodeMidiOutput::New);

        s_ct.Reset(t);
        t->SetClassName(Nan::New<v8::String>("NodeMidiOutput").ToLocalChecked());
        t->InstanceTemplate()->SetInternalFieldCount(1);

        Nan::SetPrototypeMethod(t, "getPortCount", GetPortCount);
        Nan::SetPrototypeMethod(t, "getPortName", GetPortName);

        Nan::SetPrototypeMethod(t, "openPort", OpenPort);
        Nan::SetPrototypeMethod(t, "openVirtualPort", OpenVirtualPort);
        Nan::SetPrototypeMethod(t, "closePort", ClosePort);

        Nan::SetPrototypeMethod(t, "sendMessage", SendMessage);

        target->Set(Nan::New<v8::String>("output").ToLocalChecked(), t->GetFunction());
    }

    NodeMidiOutput()
    {
        out = new RtMidiOut();
    }

    ~NodeMidiOutput()
    {
        delete out;
    }

    static NAN_METHOD(New)
    {
        Nan::HandleScope scope;

        if (!info.IsConstructCall()) {
            return Nan::ThrowTypeError("Use the new operator to create instances of this object.");
        }

        NodeMidiOutput* output = new NodeMidiOutput();
        output->Wrap(info.This());

        info.GetReturnValue().Set(info.This());
    }

    static NAN_METHOD(GetPortCount)
    {
        Nan::HandleScope scope;
        NodeMidiOutput* output = Nan::ObjectWrap::Unwrap<NodeMidiOutput>(info.This());
        v8::Local<v8::Integer> result = Nan::New<v8::Uint32>(output->out->getPortCount());
        info.GetReturnValue().Set(result);
    }

    static NAN_METHOD(GetPortName)
    {
        Nan::HandleScope scope;
        NodeMidiOutput* output = Nan::ObjectWrap::Unwrap<NodeMidiOutput>(info.This());
        if (info.Length() == 0 || !info[0]->IsUint32()) {
            return Nan::ThrowTypeError("First argument must be an integer");
        }

        unsigned int portNumber = info[0]->Uint32Value();
        v8::Local<v8::String> result = Nan::New<v8::String>(output->out->getPortName(portNumber).c_str()).ToLocalChecked();
        info.GetReturnValue().Set(result);
    }

    static NAN_METHOD(OpenPort)
    {
        Nan::HandleScope scope;
        NodeMidiOutput* output = Nan::ObjectWrap::Unwrap<NodeMidiOutput>(info.This());
        if (info.Length() == 0 || !info[0]->IsUint32()) {
            return Nan::ThrowTypeError("First argument must be an integer");
        }
        unsigned int portNumber = info[0]->Uint32Value();
        if (portNumber >= output->out->getPortCount()) {
            return Nan::ThrowRangeError("Invalid MIDI port number");
        }

        output->out->openPort(portNumber);
        return;
    }

    static NAN_METHOD(OpenVirtualPort)
    {
        Nan::HandleScope scope;
        NodeMidiOutput* output = Nan::ObjectWrap::Unwrap<NodeMidiOutput>(info.This());
        if (info.Length() == 0 || !info[0]->IsString()) {
            return Nan::ThrowTypeError("First argument must be a string");
        }

        std::string name(*v8::String::Utf8Value(info[0].As<v8::String>()));

        output->out->openVirtualPort(name);
        return;
    }

    static NAN_METHOD(ClosePort)
    {
        Nan::HandleScope scope;
        NodeMidiOutput* output = Nan::ObjectWrap::Unwrap<NodeMidiOutput>(info.This());
        output->out->closePort();
        return;
    }

    static NAN_METHOD(SendMessage)
    {
        Nan::HandleScope scope;
        NodeMidiOutput* output = Nan::ObjectWrap::Unwrap<NodeMidiOutput>(info.This());
        if (info.Length() == 0 || !info[0]->IsArray()) {
            return Nan::ThrowTypeError("First argument must be an array");
        }

        v8::Local<v8::Object> message = info[0]->ToObject();
        int32_t messageLength = message->Get(Nan::New<v8::String>("length").ToLocalChecked())->Int32Value();
        std::vector<unsigned char> messageOutput;
        for (int32_t i = 0; i != messageLength; ++i) {
            messageOutput.push_back(message->Get(Nan::New<v8::Integer>(i))->Int32Value());
        }
        output->out->sendMessage(&messageOutput);
        return;
    }
};

const char* symbol_emit = "emit";
const char* symbol_message = "message";

class NodeMidiInput : public Nan::ObjectWrap
{
private:
    RtMidiIn* in;

public:
    uv_async_t message_async;
    uv_mutex_t message_mutex;

    struct MidiMessage
    {
        double deltaTime;
        std::vector<unsigned char> message;
    };
    std::queue<MidiMessage*> message_queue;

    static Nan::Persistent<v8::FunctionTemplate> s_ct;
    static void Init(v8::Handle<v8::Object> target)
    {
        Nan::HandleScope scope;

        v8::Local<v8::FunctionTemplate> t = Nan::New<v8::FunctionTemplate>(NodeMidiInput::New);

        s_ct.Reset(t);
        t->SetClassName(Nan::New<v8::String>("NodeMidiInput").ToLocalChecked());
        t->InstanceTemplate()->SetInternalFieldCount(1);

        Nan::SetPrototypeMethod(t, "getPortCount", GetPortCount);
        Nan::SetPrototypeMethod(t, "getPortName", GetPortName);

        Nan::SetPrototypeMethod(t, "openPort", OpenPort);
        Nan::SetPrototypeMethod(t, "openVirtualPort", OpenVirtualPort);
        Nan::SetPrototypeMethod(t, "closePort", ClosePort);

        Nan::SetPrototypeMethod(t, "ignoreTypes", IgnoreTypes);

        target->Set(Nan::New<v8::String>("input").ToLocalChecked(), t->GetFunction());
    }

    NodeMidiInput()
    {
        in = new RtMidiIn();
        uv_mutex_init(&message_mutex);
    }

    ~NodeMidiInput()
    {
        in->closePort();
        delete in;
        uv_mutex_destroy(&message_mutex);
    }

    static NAUV_WORK_CB(EmitMessage)
    {
        Nan::HandleScope scope;
        NodeMidiInput *input = static_cast<NodeMidiInput*>(async->data);
        uv_mutex_lock(&input->message_mutex);
        v8::Local<v8::Function> emitFunction = input->handle()->Get(Nan::New<v8::String>(symbol_emit).ToLocalChecked()).As<v8::Function>();
        while (!input->message_queue.empty())
        {
            MidiMessage* message = input->message_queue.front();
            v8::Local<v8::Value> info[3];
            info[0] = Nan::New<v8::String>(symbol_message).ToLocalChecked();
            info[1] = Nan::New<v8::Number>(message->deltaTime);
            int32_t count = (int32_t)message->message.size();
            v8::Local<v8::Array> data = Nan::New<v8::Array>(count);
            for (int32_t i = 0; i < count; ++i) {
                data->Set(Nan::New<v8::Number>(i), Nan::New<v8::Integer>(message->message[i]));
            }
            info[2] = data;
            Nan::MakeCallback(input->handle(), emitFunction, 3, info);
            input->message_queue.pop();
            delete message;
        }
        uv_mutex_unlock(&input->message_mutex);
    }

    static void Callback(double deltaTime, std::vector<unsigned char> *message, void *userData)
    {
        NodeMidiInput *input = static_cast<NodeMidiInput*>(userData);
        MidiMessage* data = new MidiMessage();
        data->deltaTime = deltaTime;
        data->message = *message;
        uv_mutex_lock(&input->message_mutex);
        input->message_queue.push(data);
        uv_mutex_unlock(&input->message_mutex);
        uv_async_send(&input->message_async);
    }

    static NAN_METHOD(New)
    {
        Nan::HandleScope scope;

        if (!info.IsConstructCall()) {
            return Nan::ThrowTypeError("Use the new operator to create instances of this object.");
        }

        NodeMidiInput* input = new NodeMidiInput();
        input->message_async.data = input;
        uv_async_init(uv_default_loop(), &input->message_async, NodeMidiInput::EmitMessage);
        input->Wrap(info.This());

        info.GetReturnValue().Set(info.This());
    }

    static NAN_METHOD(GetPortCount)
    {
        Nan::HandleScope scope;
        NodeMidiInput* input = Nan::ObjectWrap::Unwrap<NodeMidiInput>(info.This());
        v8::Local<v8::Integer> result = Nan::New<v8::Uint32>(input->in->getPortCount());
        info.GetReturnValue().Set(result);
    }

    static NAN_METHOD(GetPortName)
    {
        Nan::HandleScope scope;
        NodeMidiInput* input = Nan::ObjectWrap::Unwrap<NodeMidiInput>(info.This());
        if (info.Length() == 0 || !info[0]->IsUint32()) {
            return Nan::ThrowTypeError("First argument must be an integer");
        }

        unsigned int portNumber = info[0]->Uint32Value();
        v8::Local<v8::String> result = Nan::New<v8::String>(input->in->getPortName(portNumber).c_str()).ToLocalChecked();
        info.GetReturnValue().Set(result);
    }

    static NAN_METHOD(OpenPort)
    {
        Nan::HandleScope scope;
        NodeMidiInput* input = Nan::ObjectWrap::Unwrap<NodeMidiInput>(info.This());
        if (info.Length() == 0 || !info[0]->IsUint32()) {
            return Nan::ThrowTypeError("First argument must be an integer");
        }
        unsigned int portNumber = info[0]->Uint32Value();
        if (portNumber >= input->in->getPortCount()) {
            return Nan::ThrowRangeError("Invalid MIDI port number");
        }

        input->Ref();
        input->in->setCallback(&NodeMidiInput::Callback, Nan::ObjectWrap::Unwrap<NodeMidiInput>(info.This()));
        input->in->openPort(portNumber);
        return;
    }

    static NAN_METHOD(OpenVirtualPort)
    {
        Nan::HandleScope scope;
        NodeMidiInput* input = Nan::ObjectWrap::Unwrap<NodeMidiInput>(info.This());
        if (info.Length() == 0 || !info[0]->IsString()) {
            return Nan::ThrowTypeError("First argument must be a string");
        }

        std::string name(*v8::String::Utf8Value(info[0].As<v8::String>()));

        input->Ref();
        input->in->setCallback(&NodeMidiInput::Callback, Nan::ObjectWrap::Unwrap<NodeMidiInput>(info.This()));
        input->in->openVirtualPort(name);
        return;
    }

    static NAN_METHOD(ClosePort)
    {
        Nan::HandleScope scope;
        NodeMidiInput* input = Nan::ObjectWrap::Unwrap<NodeMidiInput>(info.This());
        if (input->in->isPortOpen()) {
            input->Unref();
        }
        input->in->cancelCallback();
        input->in->closePort();
        uv_close((uv_handle_t*)&input->message_async, NULL);
        return;
    }

    static NAN_METHOD(IgnoreTypes)
    {
        Nan::HandleScope scope;
        NodeMidiInput* input = Nan::ObjectWrap::Unwrap<NodeMidiInput>(info.This());
        if (info.Length() != 3 || !info[0]->IsBoolean() || !info[1]->IsBoolean() || !info[2]->IsBoolean()) {
            return Nan::ThrowTypeError("Arguments must be boolean");
        }

        bool filter_sysex = info[0]->BooleanValue();
        bool filter_timing = info[1]->BooleanValue();
        bool filter_sensing = info[2]->BooleanValue();
        input->in->ignoreTypes(filter_sysex, filter_timing, filter_sensing);
        return;
    }
};

Nan::Persistent<v8::FunctionTemplate> NodeMidiOutput::s_ct;
Nan::Persistent<v8::FunctionTemplate> NodeMidiInput::s_ct;

extern "C" {
    void init (v8::Handle<v8::Object> target)
    {
        NodeMidiOutput::Init(target);
        NodeMidiInput::Init(target);
    }
    NODE_MODULE(midi, init)
}
<commit_msg>remove unused headers<commit_after>#include <nan.h>
#include <queue>
#include <uv.h>

#include "lib/RtMidi/RtMidi.h"
#include "lib/RtMidi/RtMidi.cpp"

class NodeMidiOutput : public Nan::ObjectWrap
{
private:
    RtMidiOut* out;
public:
    static Nan::Persistent<v8::FunctionTemplate> s_ct;
    static void Init(v8::Handle<v8::Object> target)
    {
        Nan::HandleScope scope;

        v8::Local<v8::FunctionTemplate> t = Nan::New<v8::FunctionTemplate>(NodeMidiOutput::New);

        s_ct.Reset(t);
        t->SetClassName(Nan::New<v8::String>("NodeMidiOutput").ToLocalChecked());
        t->InstanceTemplate()->SetInternalFieldCount(1);

        Nan::SetPrototypeMethod(t, "getPortCount", GetPortCount);
        Nan::SetPrototypeMethod(t, "getPortName", GetPortName);

        Nan::SetPrototypeMethod(t, "openPort", OpenPort);
        Nan::SetPrototypeMethod(t, "openVirtualPort", OpenVirtualPort);
        Nan::SetPrototypeMethod(t, "closePort", ClosePort);

        Nan::SetPrototypeMethod(t, "sendMessage", SendMessage);

        target->Set(Nan::New<v8::String>("output").ToLocalChecked(), t->GetFunction());
    }

    NodeMidiOutput()
    {
        out = new RtMidiOut();
    }

    ~NodeMidiOutput()
    {
        delete out;
    }

    static NAN_METHOD(New)
    {
        Nan::HandleScope scope;

        if (!info.IsConstructCall()) {
            return Nan::ThrowTypeError("Use the new operator to create instances of this object.");
        }

        NodeMidiOutput* output = new NodeMidiOutput();
        output->Wrap(info.This());

        info.GetReturnValue().Set(info.This());
    }

    static NAN_METHOD(GetPortCount)
    {
        Nan::HandleScope scope;
        NodeMidiOutput* output = Nan::ObjectWrap::Unwrap<NodeMidiOutput>(info.This());
        v8::Local<v8::Integer> result = Nan::New<v8::Uint32>(output->out->getPortCount());
        info.GetReturnValue().Set(result);
    }

    static NAN_METHOD(GetPortName)
    {
        Nan::HandleScope scope;
        NodeMidiOutput* output = Nan::ObjectWrap::Unwrap<NodeMidiOutput>(info.This());
        if (info.Length() == 0 || !info[0]->IsUint32()) {
            return Nan::ThrowTypeError("First argument must be an integer");
        }

        unsigned int portNumber = info[0]->Uint32Value();
        v8::Local<v8::String> result = Nan::New<v8::String>(output->out->getPortName(portNumber).c_str()).ToLocalChecked();
        info.GetReturnValue().Set(result);
    }

    static NAN_METHOD(OpenPort)
    {
        Nan::HandleScope scope;
        NodeMidiOutput* output = Nan::ObjectWrap::Unwrap<NodeMidiOutput>(info.This());
        if (info.Length() == 0 || !info[0]->IsUint32()) {
            return Nan::ThrowTypeError("First argument must be an integer");
        }
        unsigned int portNumber = info[0]->Uint32Value();
        if (portNumber >= output->out->getPortCount()) {
            return Nan::ThrowRangeError("Invalid MIDI port number");
        }

        output->out->openPort(portNumber);
        return;
    }

    static NAN_METHOD(OpenVirtualPort)
    {
        Nan::HandleScope scope;
        NodeMidiOutput* output = Nan::ObjectWrap::Unwrap<NodeMidiOutput>(info.This());
        if (info.Length() == 0 || !info[0]->IsString()) {
            return Nan::ThrowTypeError("First argument must be a string");
        }

        std::string name(*v8::String::Utf8Value(info[0].As<v8::String>()));

        output->out->openVirtualPort(name);
        return;
    }

    static NAN_METHOD(ClosePort)
    {
        Nan::HandleScope scope;
        NodeMidiOutput* output = Nan::ObjectWrap::Unwrap<NodeMidiOutput>(info.This());
        output->out->closePort();
        return;
    }

    static NAN_METHOD(SendMessage)
    {
        Nan::HandleScope scope;
        NodeMidiOutput* output = Nan::ObjectWrap::Unwrap<NodeMidiOutput>(info.This());
        if (info.Length() == 0 || !info[0]->IsArray()) {
            return Nan::ThrowTypeError("First argument must be an array");
        }

        v8::Local<v8::Object> message = info[0]->ToObject();
        int32_t messageLength = message->Get(Nan::New<v8::String>("length").ToLocalChecked())->Int32Value();
        std::vector<unsigned char> messageOutput;
        for (int32_t i = 0; i != messageLength; ++i) {
            messageOutput.push_back(message->Get(Nan::New<v8::Integer>(i))->Int32Value());
        }
        output->out->sendMessage(&messageOutput);
        return;
    }
};

const char* symbol_emit = "emit";
const char* symbol_message = "message";

class NodeMidiInput : public Nan::ObjectWrap
{
private:
    RtMidiIn* in;

public:
    uv_async_t message_async;
    uv_mutex_t message_mutex;

    struct MidiMessage
    {
        double deltaTime;
        std::vector<unsigned char> message;
    };
    std::queue<MidiMessage*> message_queue;

    static Nan::Persistent<v8::FunctionTemplate> s_ct;
    static void Init(v8::Handle<v8::Object> target)
    {
        Nan::HandleScope scope;

        v8::Local<v8::FunctionTemplate> t = Nan::New<v8::FunctionTemplate>(NodeMidiInput::New);

        s_ct.Reset(t);
        t->SetClassName(Nan::New<v8::String>("NodeMidiInput").ToLocalChecked());
        t->InstanceTemplate()->SetInternalFieldCount(1);

        Nan::SetPrototypeMethod(t, "getPortCount", GetPortCount);
        Nan::SetPrototypeMethod(t, "getPortName", GetPortName);

        Nan::SetPrototypeMethod(t, "openPort", OpenPort);
        Nan::SetPrototypeMethod(t, "openVirtualPort", OpenVirtualPort);
        Nan::SetPrototypeMethod(t, "closePort", ClosePort);

        Nan::SetPrototypeMethod(t, "ignoreTypes", IgnoreTypes);

        target->Set(Nan::New<v8::String>("input").ToLocalChecked(), t->GetFunction());
    }

    NodeMidiInput()
    {
        in = new RtMidiIn();
        uv_mutex_init(&message_mutex);
    }

    ~NodeMidiInput()
    {
        in->closePort();
        delete in;
        uv_mutex_destroy(&message_mutex);
    }

    static NAUV_WORK_CB(EmitMessage)
    {
        Nan::HandleScope scope;
        NodeMidiInput *input = static_cast<NodeMidiInput*>(async->data);
        uv_mutex_lock(&input->message_mutex);
        v8::Local<v8::Function> emitFunction = input->handle()->Get(Nan::New<v8::String>(symbol_emit).ToLocalChecked()).As<v8::Function>();
        while (!input->message_queue.empty())
        {
            MidiMessage* message = input->message_queue.front();
            v8::Local<v8::Value> info[3];
            info[0] = Nan::New<v8::String>(symbol_message).ToLocalChecked();
            info[1] = Nan::New<v8::Number>(message->deltaTime);
            int32_t count = (int32_t)message->message.size();
            v8::Local<v8::Array> data = Nan::New<v8::Array>(count);
            for (int32_t i = 0; i < count; ++i) {
                data->Set(Nan::New<v8::Number>(i), Nan::New<v8::Integer>(message->message[i]));
            }
            info[2] = data;
            Nan::MakeCallback(input->handle(), emitFunction, 3, info);
            input->message_queue.pop();
            delete message;
        }
        uv_mutex_unlock(&input->message_mutex);
    }

    static void Callback(double deltaTime, std::vector<unsigned char> *message, void *userData)
    {
        NodeMidiInput *input = static_cast<NodeMidiInput*>(userData);
        MidiMessage* data = new MidiMessage();
        data->deltaTime = deltaTime;
        data->message = *message;
        uv_mutex_lock(&input->message_mutex);
        input->message_queue.push(data);
        uv_mutex_unlock(&input->message_mutex);
        uv_async_send(&input->message_async);
    }

    static NAN_METHOD(New)
    {
        Nan::HandleScope scope;

        if (!info.IsConstructCall()) {
            return Nan::ThrowTypeError("Use the new operator to create instances of this object.");
        }

        NodeMidiInput* input = new NodeMidiInput();
        input->message_async.data = input;
        uv_async_init(uv_default_loop(), &input->message_async, NodeMidiInput::EmitMessage);
        input->Wrap(info.This());

        info.GetReturnValue().Set(info.This());
    }

    static NAN_METHOD(GetPortCount)
    {
        Nan::HandleScope scope;
        NodeMidiInput* input = Nan::ObjectWrap::Unwrap<NodeMidiInput>(info.This());
        v8::Local<v8::Integer> result = Nan::New<v8::Uint32>(input->in->getPortCount());
        info.GetReturnValue().Set(result);
    }

    static NAN_METHOD(GetPortName)
    {
        Nan::HandleScope scope;
        NodeMidiInput* input = Nan::ObjectWrap::Unwrap<NodeMidiInput>(info.This());
        if (info.Length() == 0 || !info[0]->IsUint32()) {
            return Nan::ThrowTypeError("First argument must be an integer");
        }

        unsigned int portNumber = info[0]->Uint32Value();
        v8::Local<v8::String> result = Nan::New<v8::String>(input->in->getPortName(portNumber).c_str()).ToLocalChecked();
        info.GetReturnValue().Set(result);
    }

    static NAN_METHOD(OpenPort)
    {
        Nan::HandleScope scope;
        NodeMidiInput* input = Nan::ObjectWrap::Unwrap<NodeMidiInput>(info.This());
        if (info.Length() == 0 || !info[0]->IsUint32()) {
            return Nan::ThrowTypeError("First argument must be an integer");
        }
        unsigned int portNumber = info[0]->Uint32Value();
        if (portNumber >= input->in->getPortCount()) {
            return Nan::ThrowRangeError("Invalid MIDI port number");
        }

        input->Ref();
        input->in->setCallback(&NodeMidiInput::Callback, Nan::ObjectWrap::Unwrap<NodeMidiInput>(info.This()));
        input->in->openPort(portNumber);
        return;
    }

    static NAN_METHOD(OpenVirtualPort)
    {
        Nan::HandleScope scope;
        NodeMidiInput* input = Nan::ObjectWrap::Unwrap<NodeMidiInput>(info.This());
        if (info.Length() == 0 || !info[0]->IsString()) {
            return Nan::ThrowTypeError("First argument must be a string");
        }

        std::string name(*v8::String::Utf8Value(info[0].As<v8::String>()));

        input->Ref();
        input->in->setCallback(&NodeMidiInput::Callback, Nan::ObjectWrap::Unwrap<NodeMidiInput>(info.This()));
        input->in->openVirtualPort(name);
        return;
    }

    static NAN_METHOD(ClosePort)
    {
        Nan::HandleScope scope;
        NodeMidiInput* input = Nan::ObjectWrap::Unwrap<NodeMidiInput>(info.This());
        if (input->in->isPortOpen()) {
            input->Unref();
        }
        input->in->cancelCallback();
        input->in->closePort();
        uv_close((uv_handle_t*)&input->message_async, NULL);
        return;
    }

    static NAN_METHOD(IgnoreTypes)
    {
        Nan::HandleScope scope;
        NodeMidiInput* input = Nan::ObjectWrap::Unwrap<NodeMidiInput>(info.This());
        if (info.Length() != 3 || !info[0]->IsBoolean() || !info[1]->IsBoolean() || !info[2]->IsBoolean()) {
            return Nan::ThrowTypeError("Arguments must be boolean");
        }

        bool filter_sysex = info[0]->BooleanValue();
        bool filter_timing = info[1]->BooleanValue();
        bool filter_sensing = info[2]->BooleanValue();
        input->in->ignoreTypes(filter_sysex, filter_timing, filter_sensing);
        return;
    }
};

Nan::Persistent<v8::FunctionTemplate> NodeMidiOutput::s_ct;
Nan::Persistent<v8::FunctionTemplate> NodeMidiInput::s_ct;

extern "C" {
    void init (v8::Handle<v8::Object> target)
    {
        NodeMidiOutput::Init(target);
        NodeMidiInput::Init(target);
    }
    NODE_MODULE(midi, init)
}
<|endoftext|>


<commit_before><commit_msg>file_util: don't compile any of the deprecated functions on non-Windows<commit_after><|endoftext|>


<commit_before>#include "pch.h"
#include "jnc_OperatorMgr.h"
#include "jnc_Module.h"

namespace jnc {

//.............................................................................

void
OperatorMgr::getDataRefObjHdr (
	const Value& value,
	Value* resultValue
	)
{
	ASSERT (value.getType ()->getTypeKind () == TypeKind_DataRef);
	DataPtrType* ptrType = (DataPtrType*) value.getType ();
	DataPtrTypeKind ptrTypeKind = ptrType->getPtrTypeKind ();

	if (ptrTypeKind == DataPtrTypeKind_Lean)
	{
		getLeanDataPtrObjHdr (value, resultValue);
	}
	else
	{
		m_module->m_llvmIrBuilder.createExtractValue (
			value,
			3,
			m_module->m_typeMgr.getStdType (StdType_ObjHdrPtr),
			resultValue
			);
	}
}

void
OperatorMgr::checkPtr (
	StdFunction stdTryCheckFunction,
	StdFunction stdCheckFunction,
	const Value* argValueArray,
	size_t argCount
	)
{
	Scope* scope = m_module->m_namespaceMgr.getCurrentScope ();
	ASSERT (scope);

	if (!(scope->getFlags () & ScopeFlag_CanThrow))
	{
		Function* checkFunction = m_module->m_functionMgr.getStdFunction (stdCheckFunction);

		m_module->m_llvmIrBuilder.createCall (
			checkFunction,
			checkFunction->getType (),
			argValueArray,
			argCount,
			NULL
			);
	}
	else
	{
		Function* checkFunction = m_module->m_functionMgr.getStdFunction (stdTryCheckFunction);
		FunctionType* checkFunctionType = checkFunction->getType ();

		Value returnValue;
		m_module->m_llvmIrBuilder.createCall (
			checkFunction,
			checkFunctionType,
			argValueArray,
			argCount,
			&returnValue
			);

		bool result = m_module->m_controlFlowMgr.throwIf (returnValue, checkFunctionType);
		ASSERT (result);
	}
}

void
OperatorMgr::checkDataPtrRange (const Value& value)
{
	ASSERT (value.getType ()->getTypeKind () == TypeKind_DataPtr || value.getType ()->getTypeKind () == TypeKind_DataRef);
	DataPtrType* type = (DataPtrType*) value.getType ();

	if (m_module->m_operatorMgr.isUnsafeRgn () || (type->getFlags () & PtrTypeFlag_Safe))
		return;

	Value ptrValue;
	Value rangeBeginValue;
	Value rangeEndValue;

	DataPtrTypeKind ptrTypeKind = type->getPtrTypeKind ();
	switch (ptrTypeKind)
	{
	case DataPtrTypeKind_Thin:
		return;

	case DataPtrTypeKind_Lean:
		getLeanDataPtrRange (value, &rangeBeginValue, &rangeEndValue);
		m_module->m_llvmIrBuilder.createBitCast (value, m_module->m_typeMgr.getStdType (StdType_BytePtr), &ptrValue);
		break;

	case DataPtrTypeKind_Normal:
		m_module->m_llvmIrBuilder.createExtractValue (value, 0, NULL, &ptrValue);
		m_module->m_llvmIrBuilder.createExtractValue (value, 1, NULL, &rangeBeginValue);
		m_module->m_llvmIrBuilder.createExtractValue (value, 2, NULL, &rangeEndValue);
		break;

	default:
		ASSERT (false);
		return;
	}

	Value sizeValue (
		type->getTargetType ()->getSize (),
		m_module->m_typeMgr.getPrimitiveType (TypeKind_SizeT)
		);

	Value argValueArray [] =
	{
		ptrValue,
		sizeValue,
		rangeBeginValue,
		rangeEndValue,
	};

	checkPtr (
		StdFunction_TryCheckDataPtrRange,
		StdFunction_CheckDataPtrRange,
		argValueArray,
		countof (argValueArray)
		);
}

bool
OperatorMgr::checkDataPtrScopeLevel (
	const Value& srcValue,
	const Value& dstValue
	)
{
	ASSERT (srcValue.getType ()->getTypeKind () == TypeKind_DataPtr);

	DataPtrType* ptrType = (DataPtrType*) srcValue.getType ();
	DataPtrTypeKind ptrTypeKind = ptrType->getPtrTypeKind ();

	if (m_module->m_operatorMgr.isUnsafeRgn () || ptrTypeKind == DataPtrTypeKind_Thin)
		return true;

	if (srcValue.getValueKind () == ValueKind_Variable && dstValue.getValueKind () == ValueKind_Variable)
	{
		if (srcValue.getVariable ()->getScopeLevel () > dstValue.getVariable ()->getScopeLevel ())
		{
			err::setFormatStringError ("data pointer scope level mismatch");
			return false;
		}

		return true;
	}

	Value srcObjHdrValue;

	if (ptrTypeKind == DataPtrTypeKind_Lean)
		getLeanDataPtrObjHdr (srcValue, &srcObjHdrValue);
	else
		m_module->m_llvmIrBuilder.createExtractValue (srcValue, 3, m_module->m_typeMgr.getStdType (StdType_ObjHdrPtr), &srcObjHdrValue);

	Function* checkFunction;
	Value dstObjHdrValue;

	if (dstValue.getValueKind () == ValueKind_Variable)
	{
		checkFunction = m_module->m_functionMgr.getStdFunction (StdFunction_CheckScopeLevelDirect);
		dstObjHdrValue = m_module->m_namespaceMgr.getScopeLevel (dstValue.getVariable ()->getScopeLevel ());
	}
	else
	{
		checkFunction = m_module->m_functionMgr.getStdFunction (StdFunction_CheckScopeLevel);
		getDataRefObjHdr (dstValue, &dstObjHdrValue);
	}

	LlvmScopeComment comment (&m_module->m_llvmIrBuilder, "check data pointer scope level");

	m_module->m_llvmIrBuilder.createCall2 (
		checkFunction,
		checkFunction->getType (),
		srcObjHdrValue,
		dstObjHdrValue,
		NULL
		);

	return true;
}

void
OperatorMgr::checkClassPtrScopeLevel (
	const Value& srcValue,
	const Value& dstValue
	)
{
	ASSERT (srcValue.getType ()->getTypeKindFlags () & TypeKindFlag_ClassPtr);

	if (m_module->m_operatorMgr.isUnsafeRgn ())
		return;

	Value dstObjHdrValue;
	getDataRefObjHdr (dstValue, &dstObjHdrValue);

	LlvmScopeComment comment (&m_module->m_llvmIrBuilder, "check class scope level");

	Value ifaceValue;
	m_module->m_llvmIrBuilder.createBitCast (srcValue, m_module->m_typeMgr.getStdType (StdType_AbstractClassPtr), &ifaceValue);

	Function* checkFunction = m_module->m_functionMgr.getStdFunction (StdFunction_CheckClassPtrScopeLevel);

	m_module->m_llvmIrBuilder.createCall2 (
		checkFunction,
		checkFunction->getType (),
		ifaceValue,
		dstObjHdrValue,
		NULL
		);
}

void
OperatorMgr::checkNullPtr (const Value& value)
{
	Type* type = value.getType ();

	if (m_module->m_operatorMgr.isUnsafeRgn () || (type->getFlags () & PtrTypeFlag_Safe))
		return;

	TypeKind typeKind = type->getTypeKind ();

	bool isThin;

	switch (typeKind)
	{
	case TypeKind_ClassPtr:
	case TypeKind_ClassRef:
		isThin = true;
		break;

	case TypeKind_FunctionPtr:
	case TypeKind_FunctionRef:
		isThin = ((FunctionPtrType*) type)->getPtrTypeKind () == FunctionPtrTypeKind_Thin;
		break;

	case TypeKind_PropertyPtr:
	case TypeKind_PropertyRef:
		isThin = ((PropertyPtrType*) type)->getPtrTypeKind () == PropertyPtrTypeKind_Thin;
		break;

	default:
		ASSERT (false);
		return;
	}

	Value ptrValue;
	Value typeKindValue (typeKind, m_module->m_typeMgr.getPrimitiveType (TypeKind_Int));

	if (isThin)
		m_module->m_llvmIrBuilder.createBitCast (value, m_module->m_typeMgr.getStdType (StdType_BytePtr), &ptrValue);
	else
		m_module->m_llvmIrBuilder.createExtractValue (value, 0, NULL, &ptrValue);

	Value argValueArray [] =
	{
		ptrValue,
		typeKindValue,
	};

	checkPtr (
		StdFunction_TryCheckNullPtr,
		StdFunction_CheckNullPtr,
		argValueArray,
		countof (argValueArray)
		);

}

void
OperatorMgr::checkFunctionPtrScopeLevel (
	const Value& srcValue,
	const Value& dstValue
	)
{
	ASSERT (srcValue.getType ()->getTypeKindFlags () & TypeKindFlag_FunctionPtr);
	FunctionPtrType* ptrType = (FunctionPtrType*) srcValue.getType ();

	if (m_module->m_operatorMgr.isUnsafeRgn () || !ptrType->hasClosure ())
		return;

	Value closureValue;
	m_module->m_llvmIrBuilder.createExtractValue (srcValue, 1, m_module->m_typeMgr.getStdType (StdType_AbstractClassPtr), &closureValue);
	checkClassPtrScopeLevel (closureValue, dstValue);
}

void
OperatorMgr::checkPropertyPtrScopeLevel (
	const Value& srcValue,
	const Value& dstValue
	)
{
	ASSERT (srcValue.getType ()->getTypeKind () == TypeKind_PropertyPtr);
	PropertyPtrType* ptrType = (PropertyPtrType*) srcValue.getType ();

	if (m_module->m_operatorMgr.isUnsafeRgn () || !ptrType->hasClosure ())
		return;

	Value closureValue;
	m_module->m_llvmIrBuilder.createExtractValue (srcValue, 1, m_module->m_typeMgr.getStdType (StdType_AbstractClassPtr), &closureValue);
	checkClassPtrScopeLevel (closureValue, dstValue);
}

void
OperatorMgr::checkVariantScopeLevel (
	const Value& srcValue,
	const Value& dstValue
	)
{
	ASSERT (srcValue.getType ()->getTypeKind () == TypeKind_Variant);

	if (m_module->m_operatorMgr.isUnsafeRgn ())
		return;

	Value dstObjHdrValue;
	getDataRefObjHdr (dstValue, &dstObjHdrValue);

	LlvmScopeComment comment (&m_module->m_llvmIrBuilder, "check variant scope level");

	Function* checkFunction = m_module->m_functionMgr.getStdFunction (StdFunction_CheckVariantScopeLevel);

	m_module->m_llvmIrBuilder.createCall2 (
		checkFunction,
		checkFunction->getType (),
		srcValue,
		dstObjHdrValue,
		NULL
		);
}

//.............................................................................

} // namespace jnc {
<commit_msg>[jancy] critical bugfix: checkVariantScopeLevel should use OperatorMgr::callOperator and not LlvmIrBuilder::createCall -- due to TypeFlag_StructRet<commit_after>#include "pch.h"
#include "jnc_OperatorMgr.h"
#include "jnc_Module.h"

namespace jnc {

//.............................................................................

void
OperatorMgr::getDataRefObjHdr (
	const Value& value,
	Value* resultValue
	)
{
	ASSERT (value.getType ()->getTypeKind () == TypeKind_DataRef);
	DataPtrType* ptrType = (DataPtrType*) value.getType ();
	DataPtrTypeKind ptrTypeKind = ptrType->getPtrTypeKind ();

	if (ptrTypeKind == DataPtrTypeKind_Lean)
	{
		getLeanDataPtrObjHdr (value, resultValue);
	}
	else
	{
		m_module->m_llvmIrBuilder.createExtractValue (
			value,
			3,
			m_module->m_typeMgr.getStdType (StdType_ObjHdrPtr),
			resultValue
			);
	}
}

void
OperatorMgr::checkPtr (
	StdFunction stdTryCheckFunction,
	StdFunction stdCheckFunction,
	const Value* argValueArray,
	size_t argCount
	)
{
	Scope* scope = m_module->m_namespaceMgr.getCurrentScope ();
	ASSERT (scope);

	if (!(scope->getFlags () & ScopeFlag_CanThrow))
	{
		Function* checkFunction = m_module->m_functionMgr.getStdFunction (stdCheckFunction);

		m_module->m_llvmIrBuilder.createCall (
			checkFunction,
			checkFunction->getType (),
			argValueArray,
			argCount,
			NULL
			);
	}
	else
	{
		Function* checkFunction = m_module->m_functionMgr.getStdFunction (stdTryCheckFunction);
		FunctionType* checkFunctionType = checkFunction->getType ();

		Value returnValue;
		m_module->m_llvmIrBuilder.createCall (
			checkFunction,
			checkFunctionType,
			argValueArray,
			argCount,
			&returnValue
			);

		bool result = m_module->m_controlFlowMgr.throwIf (returnValue, checkFunctionType);
		ASSERT (result);
	}
}

void
OperatorMgr::checkDataPtrRange (const Value& value)
{
	ASSERT (value.getType ()->getTypeKind () == TypeKind_DataPtr || value.getType ()->getTypeKind () == TypeKind_DataRef);
	DataPtrType* type = (DataPtrType*) value.getType ();

	if (m_module->m_operatorMgr.isUnsafeRgn () || (type->getFlags () & PtrTypeFlag_Safe))
		return;

	Value ptrValue;
	Value rangeBeginValue;
	Value rangeEndValue;

	DataPtrTypeKind ptrTypeKind = type->getPtrTypeKind ();
	switch (ptrTypeKind)
	{
	case DataPtrTypeKind_Thin:
		return;

	case DataPtrTypeKind_Lean:
		getLeanDataPtrRange (value, &rangeBeginValue, &rangeEndValue);
		m_module->m_llvmIrBuilder.createBitCast (value, m_module->m_typeMgr.getStdType (StdType_BytePtr), &ptrValue);
		break;

	case DataPtrTypeKind_Normal:
		m_module->m_llvmIrBuilder.createExtractValue (value, 0, NULL, &ptrValue);
		m_module->m_llvmIrBuilder.createExtractValue (value, 1, NULL, &rangeBeginValue);
		m_module->m_llvmIrBuilder.createExtractValue (value, 2, NULL, &rangeEndValue);
		break;

	default:
		ASSERT (false);
		return;
	}

	Value sizeValue (
		type->getTargetType ()->getSize (),
		m_module->m_typeMgr.getPrimitiveType (TypeKind_SizeT)
		);

	Value argValueArray [] =
	{
		ptrValue,
		sizeValue,
		rangeBeginValue,
		rangeEndValue,
	};

	checkPtr (
		StdFunction_TryCheckDataPtrRange,
		StdFunction_CheckDataPtrRange,
		argValueArray,
		countof (argValueArray)
		);
}

bool
OperatorMgr::checkDataPtrScopeLevel (
	const Value& srcValue,
	const Value& dstValue
	)
{
	ASSERT (srcValue.getType ()->getTypeKind () == TypeKind_DataPtr);

	DataPtrType* ptrType = (DataPtrType*) srcValue.getType ();
	DataPtrTypeKind ptrTypeKind = ptrType->getPtrTypeKind ();

	if (m_module->m_operatorMgr.isUnsafeRgn () || ptrTypeKind == DataPtrTypeKind_Thin)
		return true;

	if (srcValue.getValueKind () == ValueKind_Variable && dstValue.getValueKind () == ValueKind_Variable)
	{
		if (srcValue.getVariable ()->getScopeLevel () > dstValue.getVariable ()->getScopeLevel ())
		{
			err::setFormatStringError ("data pointer scope level mismatch");
			return false;
		}

		return true;
	}

	Value srcObjHdrValue;

	if (ptrTypeKind == DataPtrTypeKind_Lean)
		getLeanDataPtrObjHdr (srcValue, &srcObjHdrValue);
	else
		m_module->m_llvmIrBuilder.createExtractValue (srcValue, 3, m_module->m_typeMgr.getStdType (StdType_ObjHdrPtr), &srcObjHdrValue);

	Function* checkFunction;
	Value dstObjHdrValue;

	if (dstValue.getValueKind () == ValueKind_Variable)
	{
		checkFunction = m_module->m_functionMgr.getStdFunction (StdFunction_CheckScopeLevelDirect);
		dstObjHdrValue = m_module->m_namespaceMgr.getScopeLevel (dstValue.getVariable ()->getScopeLevel ());
	}
	else
	{
		checkFunction = m_module->m_functionMgr.getStdFunction (StdFunction_CheckScopeLevel);
		getDataRefObjHdr (dstValue, &dstObjHdrValue);
	}

	LlvmScopeComment comment (&m_module->m_llvmIrBuilder, "check data pointer scope level");

	m_module->m_llvmIrBuilder.createCall2 (
		checkFunction,
		checkFunction->getType (),
		srcObjHdrValue,
		dstObjHdrValue,
		NULL
		);

	return true;
}

void
OperatorMgr::checkClassPtrScopeLevel (
	const Value& srcValue,
	const Value& dstValue
	)
{
	ASSERT (srcValue.getType ()->getTypeKindFlags () & TypeKindFlag_ClassPtr);

	if (m_module->m_operatorMgr.isUnsafeRgn ())
		return;

	Value dstObjHdrValue;
	getDataRefObjHdr (dstValue, &dstObjHdrValue);

	LlvmScopeComment comment (&m_module->m_llvmIrBuilder, "check class scope level");

	Value ifaceValue;
	m_module->m_llvmIrBuilder.createBitCast (srcValue, m_module->m_typeMgr.getStdType (StdType_AbstractClassPtr), &ifaceValue);

	Function* checkFunction = m_module->m_functionMgr.getStdFunction (StdFunction_CheckClassPtrScopeLevel);

	m_module->m_llvmIrBuilder.createCall2 (
		checkFunction,
		checkFunction->getType (),
		ifaceValue,
		dstObjHdrValue,
		NULL
		);
}

void
OperatorMgr::checkNullPtr (const Value& value)
{
	Type* type = value.getType ();

	if (m_module->m_operatorMgr.isUnsafeRgn () || (type->getFlags () & PtrTypeFlag_Safe))
		return;

	TypeKind typeKind = type->getTypeKind ();

	bool isThin;

	switch (typeKind)
	{
	case TypeKind_ClassPtr:
	case TypeKind_ClassRef:
		isThin = true;
		break;

	case TypeKind_FunctionPtr:
	case TypeKind_FunctionRef:
		isThin = ((FunctionPtrType*) type)->getPtrTypeKind () == FunctionPtrTypeKind_Thin;
		break;

	case TypeKind_PropertyPtr:
	case TypeKind_PropertyRef:
		isThin = ((PropertyPtrType*) type)->getPtrTypeKind () == PropertyPtrTypeKind_Thin;
		break;

	default:
		ASSERT (false);
		return;
	}

	Value ptrValue;
	Value typeKindValue (typeKind, m_module->m_typeMgr.getPrimitiveType (TypeKind_Int));

	if (isThin)
		m_module->m_llvmIrBuilder.createBitCast (value, m_module->m_typeMgr.getStdType (StdType_BytePtr), &ptrValue);
	else
		m_module->m_llvmIrBuilder.createExtractValue (value, 0, NULL, &ptrValue);

	Value argValueArray [] =
	{
		ptrValue,
		typeKindValue,
	};

	checkPtr (
		StdFunction_TryCheckNullPtr,
		StdFunction_CheckNullPtr,
		argValueArray,
		countof (argValueArray)
		);

}

void
OperatorMgr::checkFunctionPtrScopeLevel (
	const Value& srcValue,
	const Value& dstValue
	)
{
	ASSERT (srcValue.getType ()->getTypeKindFlags () & TypeKindFlag_FunctionPtr);
	FunctionPtrType* ptrType = (FunctionPtrType*) srcValue.getType ();

	if (m_module->m_operatorMgr.isUnsafeRgn () || !ptrType->hasClosure ())
		return;

	Value closureValue;
	m_module->m_llvmIrBuilder.createExtractValue (srcValue, 1, m_module->m_typeMgr.getStdType (StdType_AbstractClassPtr), &closureValue);
	checkClassPtrScopeLevel (closureValue, dstValue);
}

void
OperatorMgr::checkPropertyPtrScopeLevel (
	const Value& srcValue,
	const Value& dstValue
	)
{
	ASSERT (srcValue.getType ()->getTypeKind () == TypeKind_PropertyPtr);
	PropertyPtrType* ptrType = (PropertyPtrType*) srcValue.getType ();

	if (m_module->m_operatorMgr.isUnsafeRgn () || !ptrType->hasClosure ())
		return;

	Value closureValue;
	m_module->m_llvmIrBuilder.createExtractValue (srcValue, 1, m_module->m_typeMgr.getStdType (StdType_AbstractClassPtr), &closureValue);
	checkClassPtrScopeLevel (closureValue, dstValue);
}

void
OperatorMgr::checkVariantScopeLevel (
	const Value& srcValue,
	const Value& dstValue
	)
{
	ASSERT (srcValue.getType ()->getTypeKind () == TypeKind_Variant);

	if (m_module->m_operatorMgr.isUnsafeRgn ())
		return;

	Value dstObjHdrValue;
	getDataRefObjHdr (dstValue, &dstObjHdrValue);

	LlvmScopeComment comment (&m_module->m_llvmIrBuilder, "check variant scope level");

	Function* checkFunction = m_module->m_functionMgr.getStdFunction (StdFunction_CheckVariantScopeLevel);
	m_module->m_operatorMgr.callOperator (checkFunction, srcValue, dstObjHdrValue);
}

//.............................................................................

} // namespace jnc {
<|endoftext|>


<commit_before>/*
    Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org>

    This file is part of the KDE project

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

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    aint with this library see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

// Own
#include "GeoParser.h"

// Qt
#include <QtCore/QDebug>

// Geodata
#include "GeoDocument.h"
#include "GeoTagHandler.h"

namespace Marble
{

// Set to a value greather than 0, to dump parent node chain while parsing
#define DUMP_PARENT_STACK 0

GeoParser::GeoParser( GeoDataGenericSourceType source )
    : QXmlStreamReader(),
      m_document( 0 ),
      m_source( source )
{
}

GeoParser::~GeoParser()
{
}

#if DUMP_PARENT_STACK > 0
static void dumpParentStack( const QString& name, int size, bool close )
{
    static int depth = 0;

    if ( !close )
        depth++;

    QString result;
    for ( int i = 0; i < depth; ++i )
        result += ' ';

    if ( close ) {
        depth--;
        result += "</";
    } else
        result += '<';

    result += name + "> stack size " + QString::number( size );
    fprintf( stderr, "%s\n", qPrintable( result ));
}
#endif

bool GeoParser::read( QIODevice* device )
{
    // Assert previous document got released.
    Q_ASSERT( !m_document );
    m_document = createDocument();
    Q_ASSERT( m_document );

    // Set data source
    setDevice( device );

    // Start parsing
    while ( !atEnd() ) {
        readNext();

        if ( isStartElement() ) {
            if ( isValidDocumentElement() ) {
#if DUMP_PARENT_STACK > 0
                dumpParentStack( name().toString(), m_nodeStack.size(), false );
#endif

                parseDocument();

                if ( !m_nodeStack.isEmpty() )
                    raiseError(
                        QObject::tr("Parsing failed. Still %1 unclosed tag(s) after document end.", "",
                        m_nodeStack.size() ));
            } else
                raiseDocumentElementError();
        }
    }

    if ( error() )
        qDebug() << "[GeoParser::read] -> Error occurred:" << errorString();

    return !error();
}

bool GeoParser::isValidElement( const QString& tagName ) const
{
    return name() == tagName;
}

GeoStackItem GeoParser::parentElement( unsigned int depth )
{
    QStack<GeoStackItem>::const_iterator it = m_nodeStack.constEnd() - 1;

    if ( it - depth < m_nodeStack.constBegin() )
        return GeoStackItem();

    return *(it - depth);
}

void GeoParser::parseDocument()
{
    Q_ASSERT( isStartElement() );

    while ( !atEnd() ) {
        readNext();
        GeoTagHandler::QualifiedName qName( name().toString(),
                                            namespaceUri().toString() );
        if ( isEndElement() ) {
            if ( !isValidDocumentElement() )
                m_nodeStack.pop();

#if DUMP_PARENT_STACK > 0
            dumpParentStack( name().toString(), m_nodeStack.size(), true );
#endif
            break;
        }

        if ( isStartElement() ) {
            bool processChildren = true;
            GeoStackItem stackItem( qName, 0 );

            if ( const GeoTagHandler* handler = GeoTagHandler::recognizes( qName )) {
                stackItem.assignNode( handler->parse( *this ));
                processChildren = !isEndElement();
            }

            // Only add GeoStackItem to the parent chain, if the tag handler
            // for the current element possibly contains non-textual children.
            // Consider following DGML snippet "<name>Test</name>" - the
            // DGMLNameTagHandler assumes that <name> only contains textual
            // children, and reads the joined value of all children using
            // readElementText(). This implicates that tags like <name>
            // don't contain any children that would need to be processed using
            // this parseDocument() function.
            if ( processChildren ) {
                m_nodeStack.push( stackItem );

#if DUMP_PARENT_STACK > 0
                dumpParentStack( name().toString(), m_nodeStack.size(), false );
#endif

                parseDocument();
            }
#if DUMP_PARENT_STACK > 0
            else {
                // This is only used for debugging purposes.
                m_nodeStack.push( stackItem );
                dumpParentStack( name().toString(), m_nodeStack.size(), false );

                m_nodeStack.pop();
                dumpParentStack( name().toString(), m_nodeStack.size(), true );
            }
#endif
        }
    }
}

void GeoParser::raiseDocumentElementError()
{
    raiseError( QObject::tr( "File format unrecognized" ));
}

void GeoParser::raiseWarning( const QString& warning )
{
    // TODO: Maybe introduce a strict parsing mode where we feed the warning to
    // raiseError() (which stops parsing).
    qDebug() << "[GeoParser::raiseWarning] -> " << warning;
}

QString GeoParser::attribute( const char* attributeName ) const
{
    return attributes().value( QString::fromLatin1( attributeName )).toString();
}

GeoDocument* GeoParser::releaseDocument()
{
    GeoDocument* document = m_document;
    m_document = 0;
    return document;
}

}
<commit_msg>Replace %1 with %n.<commit_after>/*
    Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org>

    This file is part of the KDE project

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

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    aint with this library see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

// Own
#include "GeoParser.h"

// Qt
#include <QtCore/QDebug>

// Geodata
#include "GeoDocument.h"
#include "GeoTagHandler.h"

namespace Marble
{

// Set to a value greather than 0, to dump parent node chain while parsing
#define DUMP_PARENT_STACK 0

GeoParser::GeoParser( GeoDataGenericSourceType source )
    : QXmlStreamReader(),
      m_document( 0 ),
      m_source( source )
{
}

GeoParser::~GeoParser()
{
}

#if DUMP_PARENT_STACK > 0
static void dumpParentStack( const QString& name, int size, bool close )
{
    static int depth = 0;

    if ( !close )
        depth++;

    QString result;
    for ( int i = 0; i < depth; ++i )
        result += ' ';

    if ( close ) {
        depth--;
        result += "</";
    } else
        result += '<';

    result += name + "> stack size " + QString::number( size );
    fprintf( stderr, "%s\n", qPrintable( result ));
}
#endif

bool GeoParser::read( QIODevice* device )
{
    // Assert previous document got released.
    Q_ASSERT( !m_document );
    m_document = createDocument();
    Q_ASSERT( m_document );

    // Set data source
    setDevice( device );

    // Start parsing
    while ( !atEnd() ) {
        readNext();

        if ( isStartElement() ) {
            if ( isValidDocumentElement() ) {
#if DUMP_PARENT_STACK > 0
                dumpParentStack( name().toString(), m_nodeStack.size(), false );
#endif

                parseDocument();

                if ( !m_nodeStack.isEmpty() )
                    raiseError(
                        QObject::tr("Parsing failed. Still %n unclosed tag(s) after document end.", "",
                        m_nodeStack.size() ));
            } else
                raiseDocumentElementError();
        }
    }

    if ( error() )
        qDebug() << "[GeoParser::read] -> Error occurred:" << errorString();

    return !error();
}

bool GeoParser::isValidElement( const QString& tagName ) const
{
    return name() == tagName;
}

GeoStackItem GeoParser::parentElement( unsigned int depth )
{
    QStack<GeoStackItem>::const_iterator it = m_nodeStack.constEnd() - 1;

    if ( it - depth < m_nodeStack.constBegin() )
        return GeoStackItem();

    return *(it - depth);
}

void GeoParser::parseDocument()
{
    Q_ASSERT( isStartElement() );

    while ( !atEnd() ) {
        readNext();
        GeoTagHandler::QualifiedName qName( name().toString(),
                                            namespaceUri().toString() );
        if ( isEndElement() ) {
            if ( !isValidDocumentElement() )
                m_nodeStack.pop();

#if DUMP_PARENT_STACK > 0
            dumpParentStack( name().toString(), m_nodeStack.size(), true );
#endif
            break;
        }

        if ( isStartElement() ) {
            bool processChildren = true;
            GeoStackItem stackItem( qName, 0 );

            if ( const GeoTagHandler* handler = GeoTagHandler::recognizes( qName )) {
                stackItem.assignNode( handler->parse( *this ));
                processChildren = !isEndElement();
            }

            // Only add GeoStackItem to the parent chain, if the tag handler
            // for the current element possibly contains non-textual children.
            // Consider following DGML snippet "<name>Test</name>" - the
            // DGMLNameTagHandler assumes that <name> only contains textual
            // children, and reads the joined value of all children using
            // readElementText(). This implicates that tags like <name>
            // don't contain any children that would need to be processed using
            // this parseDocument() function.
            if ( processChildren ) {
                m_nodeStack.push( stackItem );

#if DUMP_PARENT_STACK > 0
                dumpParentStack( name().toString(), m_nodeStack.size(), false );
#endif

                parseDocument();
            }
#if DUMP_PARENT_STACK > 0
            else {
                // This is only used for debugging purposes.
                m_nodeStack.push( stackItem );
                dumpParentStack( name().toString(), m_nodeStack.size(), false );

                m_nodeStack.pop();
                dumpParentStack( name().toString(), m_nodeStack.size(), true );
            }
#endif
        }
    }
}

void GeoParser::raiseDocumentElementError()
{
    raiseError( QObject::tr( "File format unrecognized" ));
}

void GeoParser::raiseWarning( const QString& warning )
{
    // TODO: Maybe introduce a strict parsing mode where we feed the warning to
    // raiseError() (which stops parsing).
    qDebug() << "[GeoParser::raiseWarning] -> " << warning;
}

QString GeoParser::attribute( const char* attributeName ) const
{
    return attributes().value( QString::fromLatin1( attributeName )).toString();
}

GeoDocument* GeoParser::releaseDocument()
{
    GeoDocument* document = m_document;
    m_document = 0;
    return document;
}

}
<|endoftext|>


<commit_before>#include "sqlite_add_indices.hpp"

#include <fstream>
#include <iostream>
#include <string>

#include "operators/print.hpp"

#include "hyrise.hpp"
#include "utils/meta_table_manager.hpp"
#include "utils/sqlite_wrapper.hpp"
#include "utils/timer.hpp"

namespace opossum {

void add_indices_to_sqlite(const std::string& schema_file_path, const std::string& create_indices_file_path,
                           std::shared_ptr<SQLiteWrapper>& sqlite_wrapper) {
  Assert(sqlite_wrapper, "sqlite_wrapper should be set");

  std::cout << "- Adding indexes to SQLite" << std::endl;
  Timer timer;

  // SQLite does not support adding primary keys to non-empty tables, so we rename the table, create an empty one from
  // the provided schema and copy the data.
  for (const auto& table_name : Hyrise::get().storage_manager.table_names()) {
    // SQLite doesn't like an unescaped "ORDER" as a table name, thus we escape it. No need to escape the
    // "..._unindexed" name.
    const auto escaped_table_name = std::string{"\""} + table_name + "\"";

    sqlite_wrapper->main_connection.raw_execute_query(std::string{"ALTER TABLE "}
                                                          .append(escaped_table_name)
                                                          .append(" RENAME TO ")
                                                          .append(table_name)
                                                          .append("_unindexed"));
  }

  // Recreate tables using the passed schema sql file
  std::ifstream schema_file(schema_file_path);
  std::string schema_sql((std::istreambuf_iterator<char>(schema_file)), std::istreambuf_iterator<char>());
  sqlite_wrapper->main_connection.raw_execute_query(schema_sql);

  // If indices are not part of the schema file, add them here
  if (!create_indices_file_path.empty()) {
    std::ifstream create_indices_file(create_indices_file_path);
    std::string create_indices_sql((std::istreambuf_iterator<char>(create_indices_file)),
                                   std::istreambuf_iterator<char>());
    sqlite_wrapper->main_connection.raw_execute_query(create_indices_sql);
  }

  // Copy over data
  for (const auto& table_name : Hyrise::get().storage_manager.table_names()) {
    Timer per_table_time;
    std::cout << "-  Adding indexes to SQLite table " << table_name << std::flush;

    const auto escaped_table_name = std::string{"\""} + table_name + "\"";

    sqlite_wrapper->main_connection.raw_execute_query(std::string{"INSERT INTO "}
                                                          .append(escaped_table_name)
                                                          .append(" SELECT * FROM ")
                                                          .append(table_name)
                                                          .append("_unindexed"));

    std::cout << " (" << per_table_time.lap_formatted() << ")" << std::endl;
  }

  std::cout << "- Added indexes to SQLite (" << timer.lap_formatted() << ")" << std::endl;
}

}  // namespace opossum
<commit_msg>Better error message for --verify (#2338)<commit_after>#include "sqlite_add_indices.hpp"

#include <fstream>
#include <iostream>
#include <string>

#include "operators/print.hpp"

#include "hyrise.hpp"
#include "utils/meta_table_manager.hpp"
#include "utils/sqlite_wrapper.hpp"
#include "utils/timer.hpp"

namespace opossum {

void add_indices_to_sqlite(const std::string& schema_file_path, const std::string& create_indices_file_path,
                           std::shared_ptr<SQLiteWrapper>& sqlite_wrapper) {
  Assert(sqlite_wrapper, "sqlite_wrapper should be set");

  std::cout << "- Adding indexes to SQLite" << std::endl;
  Timer timer;

  // SQLite does not support adding primary keys to non-empty tables, so we rename the table, create an empty one from
  // the provided schema and copy the data.
  for (const auto& table_name : Hyrise::get().storage_manager.table_names()) {
    // SQLite doesn't like an unescaped "ORDER" as a table name, thus we escape it. No need to escape the
    // "..._unindexed" name.
    const auto escaped_table_name = std::string{"\""} + table_name + "\"";

    sqlite_wrapper->main_connection.raw_execute_query(std::string{"ALTER TABLE "}
                                                          .append(escaped_table_name)
                                                          .append(" RENAME TO ")
                                                          .append(table_name)
                                                          .append("_unindexed"));
  }

  // Recreate tables using the passed schema sql file
  std::ifstream schema_file(schema_file_path);
  Assert(schema_file.good(), std::string{"Schema file "} + schema_file_path +
                                 " not found - try running the binary from the Hyrise root or the build directory");
  std::string schema_sql((std::istreambuf_iterator<char>(schema_file)), std::istreambuf_iterator<char>());
  sqlite_wrapper->main_connection.raw_execute_query(schema_sql);

  // If indices are not part of the schema file, add them here
  if (!create_indices_file_path.empty()) {
    std::ifstream create_indices_file(create_indices_file_path);
    Assert(create_indices_file.good(),
           std::string{"Index file "} + create_indices_file_path +
               " not found - try running the binary from the Hyrise root or the build directory");
    std::string create_indices_sql((std::istreambuf_iterator<char>(create_indices_file)),
                                   std::istreambuf_iterator<char>());
    sqlite_wrapper->main_connection.raw_execute_query(create_indices_sql);
  }

  // Copy over data
  for (const auto& table_name : Hyrise::get().storage_manager.table_names()) {
    Timer per_table_time;
    std::cout << "-  Adding indexes to SQLite table " << table_name << std::flush;

    const auto escaped_table_name = std::string{"\""} + table_name + "\"";

    sqlite_wrapper->main_connection.raw_execute_query(std::string{"INSERT INTO "}
                                                          .append(escaped_table_name)
                                                          .append(" SELECT * FROM ")
                                                          .append(table_name)
                                                          .append("_unindexed"));

    std::cout << " (" << per_table_time.lap_formatted() << ")" << std::endl;
  }

  std::cout << "- Added indexes to SQLite (" << timer.lap_formatted() << ")" << std::endl;
}

}  // namespace opossum
<|endoftext|>


<commit_before>//! \file
/*
**  Copyright (C) - Triton
**
**  This program is under the terms of the BSD License.
*/

#ifndef TRITON_CALLBACKS_H
#define TRITON_CALLBACKS_H

#include <list>

#include "ast.hpp"
#include "tritonTypes.hpp"

#ifdef TRITON_PYTHON_BINDINGS
  #include "pythonBindings.hpp"
#endif

//! The Triton namespace
namespace triton {
/*!
 *  \addtogroup triton
 *  @{
 */

  //! The Callbacks namespace
  namespace callbacks {
  /*!
   *  \ingroup triton
   *  \addtogroup callbacks
   *  @{
   */

    /*! Enumerates all kinds callbacks. */
    enum callback_e {
      MEMORY_HIT,               /*!< Memory hits callback */
      SYMBOLIC_SIMPLIFICATION,  /*!< Symbolic simplification callback */
    };

    /*! \brief The prototype of a memory hit callback.
     *
     * \description The callback takes as uniq argument an address which representes the memory
     * cell hit. Callbacks will be called each time that a memory cell will be hit.
     */
    typedef void (*memoryHitCallback)(triton::uint64 address);

    /*! \brief The prototype of a symbolic simplification callback.
     *
     * \description The callback takes as uniq argument an AbstractNode and must return a valid AbstractNode.
     * The returned node is used as assignment. See also the page about \ref SMT_simplification_page.
     */
    typedef triton::ast::AbstractNode* (*symbolicSimplificationCallback)(triton::ast::AbstractNode* node);

    //! \class Callbacks
    /*! \brief The callbacks class */
    class Callbacks {
      protected:
        #ifdef TRITON_PYTHON_BINDINGS
        //! [python] Callbacks for all memory hits.
        std::list<PyObject*> pyMemoryHitCallbacks;

        //! [python] Callbacks for all symbolic simplifications.
        std::list<PyObject*> pySymbolicSimplificationCallbacks;
        #endif

        //! [c++] Callbacks for all memory hits.
        std::list<triton::callbacks::memoryHitCallback> memoryHitCallbacks;

        //! [c++] Callbacks for all symbolic simplifications.
        std::list<triton::callbacks::symbolicSimplificationCallback> symbolicSimplificationCallbacks;

        //! Returns the number of callbacks recorded.
        triton::uint32 countCallbacks(void) const;

      public:
        //! True if there is at least one callback defined.
        bool isDefined;

        //! Constructor.
        Callbacks();

        //! Constructor.
        Callbacks(const Callbacks& copy);

        //! Destructor.
        ~Callbacks();

        //! Copies a Callbacks class
        void operator=(const Callbacks& copy);

        //! Adds a memory hit callback.
        void addCallback(triton::callbacks::memoryHitCallback cb);

        //! Adds a symbolic simplification callback.
        void addCallback(triton::callbacks::symbolicSimplificationCallback cb);

        #ifdef TRITON_PYTHON_BINDINGS
        //! Adds a python callback.
        void addCallback(triton::callbacks::callback_e kind, PyObject* function);
        #endif

        //! Deletes a memory hit callback.
        void deleteCallback(triton::callbacks::memoryHitCallback cb);

        //! Deletes a symbolic simplification callback.
        void deleteCallback(triton::callbacks::symbolicSimplificationCallback cb);

        #ifdef TRITON_PYTHON_BINDINGS
        //! Deletes a python callback.
        void deleteCallback(triton::callbacks::callback_e kind, PyObject* function);
        #endif

        //! Processes callbacks according to the kind and the C++ polymorphism.
        triton::ast::AbstractNode* processCallbacks(triton::callbacks::callback_e kind, triton::ast::AbstractNode* node) const;

        //! Processes callbacks according to the kind and the C++ polymorphism.
        void processCallbacks(triton::callbacks::callback_e kind, triton::uint64 address) const;
    };

  /*! @} End of callbacks namespace */
  };
/*! @} End of triton namespace */
};

#endif /* TRITON_CALLBACKS_H */
<commit_msg>#318 in progress<commit_after>//! \file
/*
**  Copyright (C) - Triton
**
**  This program is under the terms of the BSD License.
*/

#ifndef TRITON_CALLBACKS_H
#define TRITON_CALLBACKS_H

#include <list>

#include "ast.hpp"
#include "tritonTypes.hpp"

#ifdef TRITON_PYTHON_BINDINGS
  #include "pythonBindings.hpp"
#endif

//! The Triton namespace
namespace triton {
/*!
 *  \addtogroup triton
 *  @{
 */

  //! The Callbacks namespace
  namespace callbacks {
  /*!
   *  \ingroup triton
   *  \addtogroup callbacks
   *  @{
   */

    /*! Enumerates all kinds callbacks. */
    enum callback_e {
      MEMORY_HIT,               /*!< Memory hits callback */
      SYMBOLIC_SIMPLIFICATION,  /*!< Symbolic simplification callback */
    };

    /*! \brief The prototype of a memory hit callback.
     *
     * \description The callback takes as uniq argument an address which representes the memory
     * cell hit. Callbacks will be called each time that a memory cell will be hit.
     */
    typedef void (*memoryHitCallback)(triton::uint64 address);

    /*! \brief The prototype of a symbolic simplification callback.
     *
     * \description The callback takes as uniq argument an triton::ast::AbstractNode and must return a valid triton::ast::AbstractNode.
     * The returned node is used as assignment. See also the page about \ref SMT_simplification_page.
     */
    typedef triton::ast::AbstractNode* (*symbolicSimplificationCallback)(triton::ast::AbstractNode* node);

    //! \class Callbacks
    /*! \brief The callbacks class */
    class Callbacks {
      protected:
        #ifdef TRITON_PYTHON_BINDINGS
        //! [python] Callbacks for all memory hits.
        std::list<PyObject*> pyMemoryHitCallbacks;

        //! [python] Callbacks for all symbolic simplifications.
        std::list<PyObject*> pySymbolicSimplificationCallbacks;
        #endif

        //! [c++] Callbacks for all memory hits.
        std::list<triton::callbacks::memoryHitCallback> memoryHitCallbacks;

        //! [c++] Callbacks for all symbolic simplifications.
        std::list<triton::callbacks::symbolicSimplificationCallback> symbolicSimplificationCallbacks;

        //! Returns the number of callbacks recorded.
        triton::uint32 countCallbacks(void) const;

      public:
        //! True if there is at least one callback defined.
        bool isDefined;

        //! Constructor.
        Callbacks();

        //! Constructor.
        Callbacks(const Callbacks& copy);

        //! Destructor.
        ~Callbacks();

        //! Copies a Callbacks class
        void operator=(const Callbacks& copy);

        //! Adds a memory hit callback.
        void addCallback(triton::callbacks::memoryHitCallback cb);

        //! Adds a symbolic simplification callback.
        void addCallback(triton::callbacks::symbolicSimplificationCallback cb);

        #ifdef TRITON_PYTHON_BINDINGS
        //! Adds a python callback.
        void addCallback(triton::callbacks::callback_e kind, PyObject* function);
        #endif

        //! Deletes a memory hit callback.
        void deleteCallback(triton::callbacks::memoryHitCallback cb);

        //! Deletes a symbolic simplification callback.
        void deleteCallback(triton::callbacks::symbolicSimplificationCallback cb);

        #ifdef TRITON_PYTHON_BINDINGS
        //! Deletes a python callback.
        void deleteCallback(triton::callbacks::callback_e kind, PyObject* function);
        #endif

        //! Processes callbacks according to the kind and the C++ polymorphism.
        triton::ast::AbstractNode* processCallbacks(triton::callbacks::callback_e kind, triton::ast::AbstractNode* node) const;

        //! Processes callbacks according to the kind and the C++ polymorphism.
        void processCallbacks(triton::callbacks::callback_e kind, triton::uint64 address) const;
    };

  /*! @} End of callbacks namespace */
  };
/*! @} End of triton namespace */
};

#endif /* TRITON_CALLBACKS_H */
<|endoftext|>


<commit_before>/*
 * info.cpp
 *
 *  Created on: Nov 22, 2012
 *      Author: partio
 */

#include "info.h"
#include <limits> // for std::numeric_limits<size_t>::max();
#include <boost/lexical_cast.hpp>
#include "plugin_factory.h"
#include "logger_factory.h"

#ifdef NEWBASE_INTERPOLATION
#include <NFmiLatLonArea.h>
#include <NFmiRotatedLatLonArea.h>
#include <NFmiStereographicArea.h>
#endif

#define HIMAN_AUXILIARY_INCLUDE

#include "neons.h"

#undef HIMAN_AUXILIARY_INCLUDE

using namespace std;
using namespace himan;

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

    itsDataMatrix = shared_ptr<matrix_t> (new matrix_t());
    itsTimeIterator = shared_ptr<time_iter> (new time_iter());
}

info::~info()
{
}

shared_ptr<info> info::Clone() const
{

    shared_ptr<info> clone = shared_ptr<info> (new info());

    clone->Projection(itsProjection);
    clone->Orientation(itsOrientation);

    clone->BottomLeftLatitude(itsBottomLeftLatitude);
    clone->BottomLeftLongitude(itsBottomLeftLongitude);
    clone->TopRightLatitude(itsTopRightLatitude);
    clone->TopRightLongitude(itsTopRightLongitude);

    clone->Data(itsDataMatrix);

    clone->ParamIterator(*itsParamIterator);
    clone->LevelIterator(*itsLevelIterator);
    clone->TimeIterator(*itsTimeIterator);

    clone->Producer(itsProducer);

    clone->OriginDateTime(itsOriginDateTime.String("%Y-%m-%d %H:%M:%S"), "%Y-%m-%d %H:%M:%S");

    /*
    clone->ParamIndex(itsParamIndex);
    clone->TimeIndex(itsTimeIndex);
    clone->LevelIndex(itsLevelIndex);
    */
    clone->LocationIndex(itsLocationIndex);

    return clone;

}

void info::Init()
{

    itsProjection = kUnknownProjection;

    itsBottomLeftLatitude = kHPMissingFloat;
    itsBottomLeftLongitude = kHPMissingFloat;
    itsTopRightLatitude = kHPMissingFloat;
    itsTopRightLongitude = kHPMissingFloat;
    itsOrientation = kHPMissingFloat;

    itsScanningMode = kTopLeft;

}

std::ostream& info::Write(std::ostream& file) const
{

    file << "<" << ClassName() << " " << Version() << ">" << endl;

    file << "__itsProjection__ " << itsProjection << endl;
    file << "__itsBottomLeftLongitude__ " << itsBottomLeftLongitude << endl;
    file << "__itsBottomLeftLatitude__ " << itsBottomLeftLatitude << endl;
    file << "__itsTopRightLongitude__ " << itsTopRightLongitude << endl;
    file << "__itsTopRightLatitude__ " << itsTopRightLatitude << endl;
    file << "__itsOrientation__ " << itsOrientation << endl;

    file << "__itsOriginDateTime__ " << OriginDateTime().String() << endl;

    file << "__itsProducer__ " << itsProducer << endl;

    file << itsParamIterator << endl;
    file << itsLevelIterator << endl;
    file << itsTimeIterator << endl;

    return file;
}

bool info::Create()
{

    itsDataMatrix = shared_ptr<matrix_t> (new matrix_t(itsTimeIterator->Size(), itsLevelIterator->Size(), itsParamIterator->Size()));

    Reset();

    while (NextTime())
    {
        ResetLevel();

        while (NextLevel())
        {
            ResetParam();

            while (NextParam())
                // Create empty placeholders
            {
            	Data(shared_ptr<d_matrix_t> (new d_matrix_t(0, 0)));
            }
        }
    }

    return true;

}

HPProjectionType info::Projection() const
{
    return itsProjection;
}

void info::Projection(HPProjectionType theProjection)
{
    itsProjection = theProjection;
}

double info::BottomLeftLatitude() const
{
    return itsBottomLeftLatitude;
}
double info::BottomLeftLongitude() const
{
    return itsBottomLeftLongitude;
}
double info::TopRightLongitude() const
{
    return itsTopRightLongitude;
}
double info::TopRightLatitude() const
{
    return itsTopRightLatitude;
}

void info::BottomLeftLatitude(double theBottomLeftLatitude)
{
    itsBottomLeftLatitude = theBottomLeftLatitude;
}

void info::BottomLeftLongitude(double theBottomLeftLongitude)
{
    itsBottomLeftLongitude = theBottomLeftLongitude;
}
void info::TopRightLatitude(double theTopRightLatitude)
{
    itsTopRightLatitude = theTopRightLatitude;
}
void info::TopRightLongitude(double theTopRightLongitude)
{
    itsTopRightLongitude = theTopRightLongitude;
}

double info::Orientation() const
{
    return itsOrientation;
}

void info::Orientation(double theOrientation)
{
    itsOrientation = theOrientation;
}

const producer& info::Producer() const
{
    return itsProducer;
}

void info::Producer(long theFmiProducerId)
{
    itsProducer = producer(theFmiProducerId);
}

void info::Producer(const producer& theProducer)
{
    itsProducer = theProducer;
}
/*
vector<shared_ptr<param> > info::Params() const
{
	return itsParams;
}
*/
void info::ParamIterator(const param_iter& theParamIterator)
{
    itsParamIterator = shared_ptr<param_iter> (new param_iter(theParamIterator));
}

void info::Params(const vector<param>& theParams)
{
    itsParamIterator = shared_ptr<param_iter> (new param_iter(theParams));
}
/*
vector<shared_ptr<level> > info::Levels() const
{
	return itsLevels;
}
*/

void info::LevelIterator(const level_iter& theLevelIterator)
{
    itsLevelIterator = shared_ptr<level_iter> (new level_iter(theLevelIterator));
}

void info::Levels(const vector<level>& theLevels)
{
    //itsLevels = theLevels;
    itsLevelIterator = shared_ptr<level_iter> (new level_iter(theLevels));
}
/*
vector<shared_ptr<forecast_time> > info::Times() const
{
	return itsTimes;
}*/

void info::TimeIterator(const time_iter& theTimeIterator)
{
    itsTimeIterator = shared_ptr<time_iter> (new time_iter(theTimeIterator));
}

void info::Times(const vector<forecast_time>& theTimes)
{
    //itsTimes = theTimes;
    itsTimeIterator = shared_ptr<time_iter> (new time_iter(theTimes));
}

raw_time info::OriginDateTime() const
{
    return itsOriginDateTime;
}

void info::OriginDateTime(const string& theOriginDateTime, const string& theTimeMask)
{
    itsOriginDateTime = raw_time(theOriginDateTime, theTimeMask);
}

bool info::Param(const param& theRequestedParam)
{
    return itsParamIterator->Set(theRequestedParam);
}

bool info::NextParam()
{
    return itsParamIterator->Next();
}

void info::ResetParam()
{
    itsParamIterator->Reset();
}

bool info::FirstParam()
{
    return itsParamIterator->First();
}

size_t info::ParamIndex() const
{
    return itsParamIterator->Index();
}

void info::ParamIndex(size_t theParamIndex)
{
    itsParamIterator->Set(theParamIndex);
}

param& info::Param() const
{
    return itsParamIterator->At();
}

bool info::NextLevel()
{
    return itsLevelIterator->Next();
}

void info::Reset()
{
    ResetLevel();
    ResetParam();
    ResetTime();
    ResetLocation();
}

void info::ResetLevel()
{
    itsLevelIterator->Reset();
}

bool info::FirstLevel()
{
    return itsLevelIterator->First();
}

size_t info::LevelIndex() const
{
    return itsLevelIterator->Index();
}

void info::LevelIndex(size_t theLevelIndex)
{
    itsLevelIterator->Set(theLevelIndex);
}

bool info::Level(const level& theLevel)
{
    return itsLevelIterator->Set(theLevel);
}

level& info::Level() const
{
    return itsLevelIterator->At();
}

bool info::NextTime()
{
    return itsTimeIterator->Next();
}

void info::ResetTime()
{
    itsTimeIterator->Reset();
}

bool info::FirstTime()
{
    return itsTimeIterator->First();
}

size_t info::TimeIndex() const
{
    return itsTimeIterator->Index();
}

void info::TimeIndex(size_t theTimeIndex)
{
    itsTimeIterator->Set(theTimeIndex);
}

bool info::Time(const forecast_time& theTime)
{
    return itsTimeIterator->Set(theTime);
}

forecast_time& info::Time() const
{
    return itsTimeIterator->At();
}

bool info::NextLocation()
{
    if (itsLocationIndex == kMAX_SIZE_T)
    {
        itsLocationIndex = 0;    // ResetLocation() has been called before this function
    }

    else
    {
        itsLocationIndex++;
    }

    size_t locationSize = Data()->Size();

    if (itsLocationIndex >= locationSize)
    {
        itsLocationIndex = (locationSize == 0) ? 0 : locationSize - 1;

        return false;
    }

    return true;

}

void info::ResetLocation()
{
    itsLocationIndex = kMAX_SIZE_T;
}

bool info::FirstLocation()
{
    ResetLocation();

    return NextTime();
}

void info::LocationIndex(size_t theLocationIndex)
{
    itsLocationIndex = theLocationIndex;
}

shared_ptr<d_matrix_t> info::Data() const
{
    return itsDataMatrix->At(TimeIndex(), LevelIndex(), ParamIndex());
}

shared_ptr<d_matrix_t> info::Data(size_t timeIndex, size_t levelIndex, size_t paramIndex) const
{
    return itsDataMatrix->At(timeIndex, levelIndex, paramIndex);
}

void info::Data(shared_ptr<matrix_t> m)
{
    itsDataMatrix = m;
}

void info::Data(shared_ptr<d_matrix_t> d)
{
    itsDataMatrix->At(TimeIndex(), LevelIndex(), ParamIndex()) = d;
}

bool info::Value(double theValue)
{
    return Data()->Set(itsLocationIndex, theValue) ;
}

double info::Value() const
{
    return Data()->At(itsLocationIndex);
}

size_t info::Ni() const
{
    return Data()->SizeX();
}

size_t info::Nj() const
{
    return Data()->SizeY();
}

double info::Di() const
{
    return abs((itsBottomLeftLongitude - itsTopRightLongitude) / Ni());
}

double info::Dj() const
{
    return abs((itsBottomLeftLatitude - itsTopRightLatitude) / Nj());
}

HPScanningMode info::ScanningMode() const
{
    return itsScanningMode;
}

void info::ScanningMode(HPScanningMode theScanningMode)
{
    itsScanningMode = theScanningMode;
}

bool info::GridAndAreaEquals(shared_ptr<const info> other) const
{

	/**
	 * @todo A clever way to compare if two areas are equal. For newbase we need bottomleft/topright coordinates
     * but grib gives us just first gridpoints.
	 *
	 */

    if (itsBottomLeftLatitude != other->BottomLeftLatitude())
    {
        itsLogger->Trace("BottomLeftLatitudes aren't the same");
        return false;
    }

    if (itsBottomLeftLongitude != other->BottomLeftLongitude())
    {
        itsLogger->Trace("BottomLeftLongitude aren't the same");
        return false;
    }

    if (itsTopRightLatitude != other->TopRightLatitude())
    {
        itsLogger->Trace("TopRightLatitudes aren't the same");
        return false;
    }

    if (itsTopRightLongitude != other->TopRightLongitude())
    {
        cout << itsTopRightLongitude << " != " <<  other->TopRightLongitude() << endl;

        itsLogger->Trace("TopRightLongitudes aren't the same");
        return false;
    }

    if (itsProjection != other->Projection())
    {
        return false;
    }

    if (itsOrientation != other->Orientation())
    {
        return false;
    }

    if (Ni() != other->Ni())
    {
        return false;
    }

    if (Nj() != other->Nj())
    {
        return false;
    }

    return true;

}

#ifdef NEWBASE_INTERPOLATION

shared_ptr<NFmiGrid> info::ToNewbaseGrid() const
{

    FmiInterpolationMethod interp = kLinearly;
    FmiDirection dir = static_cast<FmiDirection> (itsScanningMode);

    NFmiArea* theArea = 0;

    // Newbase does not understand grib2 longitude coordinates

    double bottomLeftLongitude = itsBottomLeftLongitude;
    double topRightLongitude = itsTopRightLongitude;

    if (bottomLeftLongitude > 180 || topRightLongitude > 180)
    {
        bottomLeftLongitude -= 180;
        topRightLongitude -= 180;
    }

    switch (itsProjection)
    {
    case kLatLonProjection:
    {
        theArea = new NFmiLatLonArea(NFmiPoint(bottomLeftLongitude, itsBottomLeftLatitude),
                                     NFmiPoint(topRightLongitude, itsTopRightLatitude));

        break;
    }

    case kRotatedLatLonProjection:
    {
        theArea = new NFmiRotatedLatLonArea(NFmiPoint(bottomLeftLongitude, itsBottomLeftLatitude),
                                            NFmiPoint(topRightLongitude, itsTopRightLatitude),
                                            NFmiPoint(0., -30.) // south pole location
                                           );
        break;
    }

    case kStereographicProjection:
    {
        theArea = new NFmiStereographicArea(NFmiPoint(bottomLeftLongitude, itsBottomLeftLatitude),
                                            NFmiPoint(topRightLongitude, itsTopRightLatitude),
                                            itsOrientation);
        break;

    }

    default:
        throw runtime_error(ClassName() + ": No supported projection found");

        break;
    }

    shared_ptr<NFmiGrid> theGrid (new NFmiGrid(theArea, Ni(), Nj(), dir, interp));

    size_t dataSize = Data()->Size();

    if (dataSize)   // Do we have data
    {

        NFmiDataPool thePool;

        float* arr = new float[dataSize];

        // convert double array to float

        for (unsigned int i = 0; i < dataSize; i++)
        {
            arr[i] = static_cast<float> (Data()->At(i));
        }

        if (!thePool.Init(dataSize, arr))
        {
            throw runtime_error("DataPool init failed");
        }

        if (!theGrid->Init(&thePool))
        {
            throw runtime_error("Grid data init failed");
        }

        delete [] arr;
    }

    delete theArea;

    return theGrid;

}

#endif

<commit_msg>Rename kMAX_SIZE_T, add functions for south pole coordinates and compare coordinates with kCoordinateEpsilon<commit_after>/*
 * info.cpp
 *
 *  Created on: Nov 22, 2012
 *      Author: partio
 */

#include "info.h"
#include <limits> // for std::numeric_limits<size_t>::max();
#include <boost/lexical_cast.hpp>
#include "plugin_factory.h"
#include "logger_factory.h"

#ifdef NEWBASE_INTERPOLATION
#include <NFmiLatLonArea.h>
#include <NFmiRotatedLatLonArea.h>
#include <NFmiStereographicArea.h>
#endif

#define HIMAN_AUXILIARY_INCLUDE

#include "neons.h"

#undef HIMAN_AUXILIARY_INCLUDE

using namespace std;
using namespace himan;

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

    itsDataMatrix = shared_ptr<matrix_t> (new matrix_t());
    itsTimeIterator = shared_ptr<time_iter> (new time_iter());
}

info::~info()
{
}

shared_ptr<info> info::Clone() const
{

    shared_ptr<info> clone = shared_ptr<info> (new info());

    clone->Projection(itsProjection);
    clone->Orientation(itsOrientation);

    clone->BottomLeftLatitude(itsBottomLeftLatitude);
    clone->BottomLeftLongitude(itsBottomLeftLongitude);
    clone->TopRightLatitude(itsTopRightLatitude);
    clone->TopRightLongitude(itsTopRightLongitude);

    clone->SouthPoleLatitude(itsSouthPoleLatitude);
    clone->SouthPoleLongitude(itsSouthPoleLongitude);

    clone->Data(itsDataMatrix);

    clone->ParamIterator(*itsParamIterator);
    clone->LevelIterator(*itsLevelIterator);
    clone->TimeIterator(*itsTimeIterator);

    clone->Producer(itsProducer);

    clone->OriginDateTime(itsOriginDateTime.String("%Y-%m-%d %H:%M:%S"), "%Y-%m-%d %H:%M:%S");

    /*
    clone->ParamIndex(itsParamIndex);
    clone->TimeIndex(itsTimeIndex);
    clone->LevelIndex(itsLevelIndex);
    */
    clone->LocationIndex(itsLocationIndex);

    return clone;

}

void info::Init()
{

    itsProjection = kUnknownProjection;

    itsBottomLeftLatitude = kHPMissingFloat;
    itsBottomLeftLongitude = kHPMissingFloat;
    itsTopRightLatitude = kHPMissingFloat;
    itsTopRightLongitude = kHPMissingFloat;

    itsSouthPoleLatitude = kHPMissingFloat;
    itsSouthPoleLongitude = kHPMissingFloat;

    itsOrientation = kHPMissingFloat;

    itsScanningMode = kTopLeft;

}

std::ostream& info::Write(std::ostream& file) const
{

    file << "<" << ClassName() << " " << Version() << ">" << endl;

    file << "__itsProjection__ " << itsProjection << endl;
    file << "__itsBottomLeftLongitude__ " << itsBottomLeftLongitude << endl;
    file << "__itsBottomLeftLatitude__ " << itsBottomLeftLatitude << endl;
    file << "__itsTopRightLongitude__ " << itsTopRightLongitude << endl;
    file << "__itsTopRightLatitude__ " << itsTopRightLatitude << endl;
    file << "__itsOrientation__ " << itsOrientation << endl;

    file << "__itsOriginDateTime__ " << OriginDateTime().String() << endl;

    file << "__itsProducer__ " << itsProducer << endl;

    file << itsParamIterator << endl;
    file << itsLevelIterator << endl;
    file << itsTimeIterator << endl;

    return file;
}

bool info::Create()
{

    itsDataMatrix = shared_ptr<matrix_t> (new matrix_t(itsTimeIterator->Size(), itsLevelIterator->Size(), itsParamIterator->Size()));

    Reset();

    while (NextTime())
    {
        ResetLevel();

        while (NextLevel())
        {
            ResetParam();

            while (NextParam())
                // Create empty placeholders
            {
            	Data(shared_ptr<d_matrix_t> (new d_matrix_t(0, 0)));
            }
        }
    }

    return true;

}

HPProjectionType info::Projection() const
{
    return itsProjection;
}

void info::Projection(HPProjectionType theProjection)
{
    itsProjection = theProjection;
}

double info::BottomLeftLatitude() const
{
    return itsBottomLeftLatitude;
}
double info::BottomLeftLongitude() const
{
    return itsBottomLeftLongitude;
}
double info::TopRightLongitude() const
{
    return itsTopRightLongitude;
}
double info::TopRightLatitude() const
{
    return itsTopRightLatitude;
}

void info::BottomLeftLatitude(double theBottomLeftLatitude)
{
    itsBottomLeftLatitude = theBottomLeftLatitude;
}

void info::BottomLeftLongitude(double theBottomLeftLongitude)
{
    itsBottomLeftLongitude = theBottomLeftLongitude;
}

void info::TopRightLatitude(double theTopRightLatitude)
{
    itsTopRightLatitude = theTopRightLatitude;
}

void info::TopRightLongitude(double theTopRightLongitude)
{
    itsTopRightLongitude = theTopRightLongitude;
}

void info::SouthPoleLatitude(double theSouthPoleLatitude)
{
    itsSouthPoleLatitude = theSouthPoleLatitude;
}

double info::SouthPoleLatitude() const
{
    return itsSouthPoleLatitude;
}

void info::SouthPoleLongitude(double theSouthPoleLongitude)
{
    itsSouthPoleLongitude = theSouthPoleLongitude;
}

double info::SouthPoleLongitude() const
{
    return itsSouthPoleLongitude;
}

double info::Orientation() const
{
    return itsOrientation;
}

void info::Orientation(double theOrientation)
{
    itsOrientation = theOrientation;
}

const producer& info::Producer() const
{
    return itsProducer;
}

void info::Producer(long theFmiProducerId)
{
    itsProducer = producer(theFmiProducerId);
}

void info::Producer(const producer& theProducer)
{
    itsProducer = theProducer;
}
/*
vector<shared_ptr<param> > info::Params() const
{
	return itsParams;
}
*/
void info::ParamIterator(const param_iter& theParamIterator)
{
    itsParamIterator = shared_ptr<param_iter> (new param_iter(theParamIterator));
}

void info::Params(const vector<param>& theParams)
{
    itsParamIterator = shared_ptr<param_iter> (new param_iter(theParams));
}
/*
vector<shared_ptr<level> > info::Levels() const
{
	return itsLevels;
}
*/

void info::LevelIterator(const level_iter& theLevelIterator)
{
    itsLevelIterator = shared_ptr<level_iter> (new level_iter(theLevelIterator));
}

void info::Levels(const vector<level>& theLevels)
{
    //itsLevels = theLevels;
    itsLevelIterator = shared_ptr<level_iter> (new level_iter(theLevels));
}
/*
vector<shared_ptr<forecast_time> > info::Times() const
{
	return itsTimes;
}*/

void info::TimeIterator(const time_iter& theTimeIterator)
{
    itsTimeIterator = shared_ptr<time_iter> (new time_iter(theTimeIterator));
}

void info::Times(const vector<forecast_time>& theTimes)
{
    //itsTimes = theTimes;
    itsTimeIterator = shared_ptr<time_iter> (new time_iter(theTimes));
}

raw_time info::OriginDateTime() const
{
    return itsOriginDateTime;
}

void info::OriginDateTime(const string& theOriginDateTime, const string& theTimeMask)
{
    itsOriginDateTime = raw_time(theOriginDateTime, theTimeMask);
}

bool info::Param(const param& theRequestedParam)
{
    return itsParamIterator->Set(theRequestedParam);
}

bool info::NextParam()
{
    return itsParamIterator->Next();
}

void info::ResetParam()
{
    itsParamIterator->Reset();
}

bool info::FirstParam()
{
    return itsParamIterator->First();
}

size_t info::ParamIndex() const
{
    return itsParamIterator->Index();
}

void info::ParamIndex(size_t theParamIndex)
{
    itsParamIterator->Set(theParamIndex);
}

param& info::Param() const
{
    return itsParamIterator->At();
}

bool info::NextLevel()
{
    return itsLevelIterator->Next();
}

void info::Reset()
{
    ResetLevel();
    ResetParam();
    ResetTime();
    ResetLocation();
}

void info::ResetLevel()
{
    itsLevelIterator->Reset();
}

bool info::FirstLevel()
{
    return itsLevelIterator->First();
}

size_t info::LevelIndex() const
{
    return itsLevelIterator->Index();
}

void info::LevelIndex(size_t theLevelIndex)
{
    itsLevelIterator->Set(theLevelIndex);
}

bool info::Level(const level& theLevel)
{
    return itsLevelIterator->Set(theLevel);
}

level& info::Level() const
{
    return itsLevelIterator->At();
}

bool info::NextTime()
{
    return itsTimeIterator->Next();
}

void info::ResetTime()
{
    itsTimeIterator->Reset();
}

bool info::FirstTime()
{
    return itsTimeIterator->First();
}

size_t info::TimeIndex() const
{
    return itsTimeIterator->Index();
}

void info::TimeIndex(size_t theTimeIndex)
{
    itsTimeIterator->Set(theTimeIndex);
}

bool info::Time(const forecast_time& theTime)
{
    return itsTimeIterator->Set(theTime);
}

forecast_time& info::Time() const
{
    return itsTimeIterator->At();
}

bool info::NextLocation()
{
    if (itsLocationIndex == kIteratorResetValue)
    {
        itsLocationIndex = 0;    // ResetLocation() has been called before this function
    }

    else
    {
        itsLocationIndex++;
    }

    size_t locationSize = Data()->Size();

    if (itsLocationIndex >= locationSize)
    {
        itsLocationIndex = (locationSize == 0) ? 0 : locationSize - 1;

        return false;
    }

    return true;

}

void info::ResetLocation()
{
    itsLocationIndex = kIteratorResetValue;
}

bool info::FirstLocation()
{
    ResetLocation();

    return NextTime();
}

void info::LocationIndex(size_t theLocationIndex)
{
    itsLocationIndex = theLocationIndex;
}

shared_ptr<d_matrix_t> info::Data() const
{
    return itsDataMatrix->At(TimeIndex(), LevelIndex(), ParamIndex());
}

shared_ptr<d_matrix_t> info::Data(size_t timeIndex, size_t levelIndex, size_t paramIndex) const
{
    return itsDataMatrix->At(timeIndex, levelIndex, paramIndex);
}

void info::Data(shared_ptr<matrix_t> m)
{
    itsDataMatrix = m;
}

void info::Data(shared_ptr<d_matrix_t> d)
{
    itsDataMatrix->At(TimeIndex(), LevelIndex(), ParamIndex()) = d;
}

bool info::Value(double theValue)
{
    return Data()->Set(itsLocationIndex, theValue) ;
}

double info::Value() const
{
    return Data()->At(itsLocationIndex);
}

size_t info::Ni() const
{
    return Data()->SizeX();
}

size_t info::Nj() const
{
    return Data()->SizeY();
}

double info::Di() const
{
    return abs((itsBottomLeftLongitude - itsTopRightLongitude) / Ni());
}

double info::Dj() const
{
    return abs((itsBottomLeftLatitude - itsTopRightLatitude) / Nj());
}

HPScanningMode info::ScanningMode() const
{
    return itsScanningMode;
}

void info::ScanningMode(HPScanningMode theScanningMode)
{
    itsScanningMode = theScanningMode;
}

bool info::GridAndAreaEquals(shared_ptr<const info> other) const
{

	const float kCoordinateEpsilon = 0.00001;

	/**
	 * @todo A clever way to compare if two areas are equal. For newbase we need bottomleft/topright coordinates
     * but grib gives us just first gridpoints.
	 *
	 */

    if (fabs(itsBottomLeftLatitude - other->BottomLeftLatitude()) > kCoordinateEpsilon)
    {
        itsLogger->Trace("BottomLeftLatitudes don't match: " + boost::lexical_cast<string> (itsBottomLeftLatitude) + " vs " + boost::lexical_cast<string> (other->BottomLeftLatitude()));
        return false;
    }

    if (fabs(itsBottomLeftLongitude - other->BottomLeftLongitude()) > kCoordinateEpsilon)
    {
        itsLogger->Trace("BottomLeftLongitude don't match: " + boost::lexical_cast<string> (itsBottomLeftLongitude) + " vs " + boost::lexical_cast<string> (other->BottomLeftLongitude()));
        return false;
    }

    if (fabs(itsTopRightLatitude - other->TopRightLatitude()) > kCoordinateEpsilon)
    {
        itsLogger->Trace("TopRightLatitudes don't match: " + boost::lexical_cast<string> (itsTopRightLatitude) + " vs " + boost::lexical_cast<string> (other->TopRightLatitude()));
        return false;
    }

    if (fabs(itsTopRightLongitude - other->TopRightLongitude()) > kCoordinateEpsilon)
    {
        itsLogger->Trace("TopRightLongitudes don't match: " + boost::lexical_cast<string> (itsTopRightLongitude) + " vs " + boost::lexical_cast<string> (other->TopRightLongitude()));
        return false;
    }

    if (itsProjection != other->Projection())
    {
        itsLogger->Trace("Projections don't match: " + boost::lexical_cast<string> (itsProjection) + " vs " + boost::lexical_cast<string> (other->Projection()));
        return false;
    }

    if (itsProjection == kRotatedLatLonProjection)
    {
		if (fabs(itsSouthPoleLatitude - other->SouthPoleLatitude()) > kCoordinateEpsilon)
    	{
        	itsLogger->Trace("SouthPoleLatitudes don't match: " + boost::lexical_cast<string> (itsSouthPoleLatitude) + " vs " + boost::lexical_cast<string> (other->SouthPoleLatitude()));
        	return false;
    	}
		if (fabs(itsSouthPoleLongitude - other->SouthPoleLongitude()) > kCoordinateEpsilon)
    	{
        	itsLogger->Trace("SouthPoleLongitudes don't match: " + boost::lexical_cast<string> (itsSouthPoleLongitude) + " vs " + boost::lexical_cast<string> (other->SouthPoleLongitude()));
        	return false;
    	}
    }

    if (itsOrientation != other->Orientation())
    {
    	itsLogger->Trace("Orientations don't match: " + boost::lexical_cast<string> (itsOrientation) + " vs " + boost::lexical_cast<string> (other->Orientation()));
        return false;
    }

    if (Ni() != other->Ni())
    {
    	itsLogger->Trace("Grid X-counts don't match: " + boost::lexical_cast<string> (Ni()) + " vs " + boost::lexical_cast<string> (other->Ni()));
        return false;
    }

    if (Nj() != other->Nj())
    {
    	itsLogger->Trace("Grid Y-counts don't match: " + boost::lexical_cast<string> (Nj()) + " vs " + boost::lexical_cast<string> (other->Nj()));
        return false;
    }

    return true;

}

#ifdef NEWBASE_INTERPOLATION

shared_ptr<NFmiGrid> info::ToNewbaseGrid() const
{

    FmiInterpolationMethod interp = kLinearly;
    FmiDirection dir = static_cast<FmiDirection> (itsScanningMode);

    NFmiArea* theArea = 0;

    // Newbase does not understand grib2 longitude coordinates

    double bottomLeftLongitude = itsBottomLeftLongitude;
    double topRightLongitude = itsTopRightLongitude;

    if (bottomLeftLongitude > 180 || topRightLongitude > 180)
    {
        bottomLeftLongitude -= 180;
        topRightLongitude -= 180;
    }

    switch (itsProjection)
    {
    case kLatLonProjection:
    {
        theArea = new NFmiLatLonArea(NFmiPoint(bottomLeftLongitude, itsBottomLeftLatitude),
                                     NFmiPoint(topRightLongitude, itsTopRightLatitude));

        break;
    }

    case kRotatedLatLonProjection:
    {
        theArea = new NFmiRotatedLatLonArea(NFmiPoint(bottomLeftLongitude, itsBottomLeftLatitude),
                                            NFmiPoint(topRightLongitude, itsTopRightLatitude),
                                            NFmiPoint(0., -30.) // south pole location
                                           );
        break;
    }

    case kStereographicProjection:
    {
        theArea = new NFmiStereographicArea(NFmiPoint(bottomLeftLongitude, itsBottomLeftLatitude),
                                            NFmiPoint(topRightLongitude, itsTopRightLatitude),
                                            itsOrientation);
        break;

    }

    default:
        throw runtime_error(ClassName() + ": No supported projection found");

        break;
    }

    shared_ptr<NFmiGrid> theGrid (new NFmiGrid(theArea, Ni(), Nj(), dir, interp));

    size_t dataSize = Data()->Size();

    if (dataSize)   // Do we have data
    {

        NFmiDataPool thePool;

        float* arr = new float[dataSize];

        // convert double array to float

        for (unsigned int i = 0; i < dataSize; i++)
        {
            arr[i] = static_cast<float> (Data()->At(i));
        }

        if (!thePool.Init(dataSize, arr))
        {
            throw runtime_error("DataPool init failed");
        }

        if (!theGrid->Init(&thePool))
        {
            throw runtime_error("Grid data init failed");
        }

        delete [] arr;
    }

    delete theArea;

    return theGrid;

}

#endif

<|endoftext|>