<commit_before>#include "Stdafx.h"

#include "AimpExtension.h"
#include "..\Utils.h"
#include "ManagedAimpCore.h"

namespace AIMP
{
    namespace SDK
    {
        //template<typename TAimpNativeObject>
        //TAimpNativeObject* AimpExtension::MakeObject(REFIID objectId)
        //{
        //    TAimpNativeObject* object = NULL;

        //    if (GetCore()->CreateObject(objectId, (void**)&object) == S_OK)
        //    {
        //        return object;
        //    }

        //    return NULL;
        //}

        IAIMPString* AimpExtension::GetAimpString(String ^value)
        {
            IAIMPString *strObject = MakeObject<IAIMPString>(IID_IAIMPString);
            pin_ptr<const WCHAR> strDate = PtrToStringChars(value);
            strObject->SetData((PWCHAR)strDate, value->Length);
            return strObject;
        }

        IAIMPImage* AimpExtension::GetImage(System::Drawing::Bitmap^ image)
        {
            System::IO::MemoryStream ^stream;
            IAIMPStream *aimpStream = NULL;
            IAIMPImage *img = NULL;

            try
            {
                stream = gcnew System::IO::MemoryStream();
                image->Save(stream, System::Drawing::Imaging::ImageFormat::Png);
                array<Byte>^ buffer = stream->ToArray();

                if (Utils::CheckResult(GetCore()->CreateObject(IID_IAIMPMemoryStream, (void**)&aimpStream)) == AIMP::SDK::AimpActionResult::Ok
                    && Utils::CheckResult(GetCore()->CreateObject(IID_IAIMPImage, (void**)&img)) == AIMP::SDK::AimpActionResult::Ok)
                {
                    aimpStream->SetSize(stream->Length);
                    pin_ptr<System::Byte> p = &buffer[0];
                    unsigned char* pby = p;
                    if (Utils::CheckResult(aimpStream->Write(pby, (int)stream->Length, nullptr)) == AIMP::SDK::AimpActionResult::Ok)
                    {
                        img->LoadFromStream(aimpStream);
                    }

                    return img;
                }
            }
            finally
            {
                if (stream != nullptr)
                {
                    stream->Close();
                }
                aimpStream->Release();
                aimpStream = NULL;
            }

            return NULL;
        }

        IAIMPCore* AimpExtension::GetCore()
        {
            return AIMP::SDK::ManagedAimpCore::GetAimpCore();
        }

        AIMP::SDK::Visuals::AimpVisualData^ AimpExtension::PAIMPVisualDataToManaged(PAIMPVisualData data)
        {
            AIMP::SDK::Visuals::AimpVisualData ^result = gcnew AIMP::SDK::Visuals::AimpVisualData();
            result->Peaks = gcnew array<float>(2);
            result->Spectrum = gcnew array<array<float>^>(3);
            result->WaveForm = gcnew array<array<float>^>(2);

            result->Peaks[0] = data->Peaks[0];
            result->Peaks[1] = data->Peaks[1];

            for (int i = 0; i < 3; i++)
            {
                array<float> ^arr = gcnew array<float>(AIMP_VISUAL_SPECTRUM_MAX);
                for (int j = 0; j < AIMP_VISUAL_SPECTRUM_MAX; j++)
                {
                    arr[j] = data->Spectrum[i][j];
                }
                result->Spectrum[i] = arr;
            }

            for (int i = 0; i < 2; i++)
            {
                array<float> ^arr = gcnew array<float>(AIMP_VISUAL_WAVEFORM_MAX);
                for (int j = 0; j < AIMP_VISUAL_WAVEFORM_MAX; j++)
                {
                    arr[j] = data->WaveForm[i][j];
                }
                result->WaveForm[i] = arr;
            }

            return result;
        }

        System::Drawing::Bitmap^ AimpExtension::GetBitmap(IAIMPImageContainer* imageContainer)
        {
            IAIMPImage* image = NULL;
            try
            {
                if (Utils::CheckResult(ManagedAimpCore::GetAimpCore()->CreateObject(IID_IAIMPImage, (void**)&image)) == AimpActionResult::Ok)
                {
                    return nullptr;
                }

                imageContainer->CreateImage(&image);

                if (image == NULL)
                {
                    return nullptr;
                }
                return GetBitmap(image);
            }
            finally
            {
                image->Release();
                image = NULL;
            }

            return nullptr;
        }

        System::Drawing::Bitmap^ AimpExtension::GetBitmap(IAIMPImage* image)
        {
            SIZE size;
            if (Utils::CheckResult(image->GetSize(&size)) == AimpActionResult::Ok)
            {
                if (size.cx == 0 || size.cy == 0)
                {
                    return nullptr;
                }

                System::Drawing::Bitmap^ bmp = gcnew System::Drawing::Bitmap(size.cx, size.cy);

                IAIMPStream *stream;
                AIMP::SDK::ManagedAimpCore::GetAimpCore()->CreateObject(IID_IAIMPMemoryStream, (void**)&stream);
                image->SaveToStream(stream, AIMP_IMAGE_FORMAT_PNG);
                if (stream->GetSize() > 0)
                {
                    Int64 size = stream->GetSize();
                    unsigned char *buf = new unsigned char[(int)size];
                    HRESULT r = stream->Seek(0, AIMP_STREAM_SEEKMODE_FROM_BEGINNING);
                    r = stream->Read(buf, (int)size);

                    System::IO::MemoryStream^ strm = gcnew System::IO::MemoryStream();
                    try
                    {
                        for (int i = 0; i < size; i++)
                        {
                            strm->WriteByte(buf[i]);
                        }
                        bmp = gcnew System::Drawing::Bitmap(strm);
                    }
                    finally
                    {
                        strm->Close();
                        strm = nullptr;

                        delete[] buf;
                        stream->Release();
                        image->Release();
                        stream = NULL;
                        image = NULL;
                    }
                }

                return bmp;
            }

            return nullptr;
        }

        IAIMPImageContainer* AimpExtension::ToContainer(System::Drawing::Bitmap ^image)
        {
            IAIMPImageContainer *container;
            if (Utils::CheckResult(ManagedAimpCore::GetAimpCore()->CreateObject(IID_IAIMPImageContainer, (void**)&container)) == AimpActionResult::Ok)
            {
                System::IO::Stream ^stream = nullptr;
                try
                {
                    stream = gcnew System::IO::MemoryStream();
                    image->Save(stream, System::Drawing::Imaging::ImageFormat::Jpeg);
                    stream->Seek(0, System::IO::SeekOrigin::Begin);
                    if (Utils::CheckResult(container->SetDataSize((DWORD)stream->Length)) != AimpActionResult::Ok)
                    {
                        return NULL;
                    }

                    byte *b = container->GetData();
                    for (int i = 0; i < stream->Length - 1; i++)
                    {
                        b[i] = stream->ReadByte();
                    }

                    return container;
                }
                finally
                {
                    if (stream != nullptr)
                    {
                        stream->Close();
                    }
                }
            }

            return NULL;
        }

        String^ AimpExtension::GetString(IAIMPString* value)
        {
            return gcnew String(value->GetData());
        }

        AimpActionResult PropertyListExtension::SetObject(IAIMPPropertyList* propertyList, int propertyId, IUnknown *value)
        {
            return Utils::CheckResult(propertyList->SetValueAsObject(propertyId, value));
        }

        AimpActionResult PropertyListExtension::SetString(IAIMPPropertyList* propertyList, int propertyId, String ^value)
        {
            // No need to process empty value
            if (String::IsNullOrWhiteSpace(value))
            {
                return AimpActionResult::InvalidArguments;
            }

            IAIMPString *str = NULL;
            try
            {
                str = AimpExtension::GetAimpString(value);
                return SetObject(propertyList, propertyId, str);
            }
            finally
            {
                str->Release();
                str = NULL;
            }

            return AimpActionResult::Unexpected;
        }

        AimpActionResult PropertyListExtension::SetInt32(IAIMPPropertyList* propertyList, int propertyId, int value)
        {
            return Utils::CheckResult(propertyList->SetValueAsInt32(propertyId, value));
        }

        AimpActionResult PropertyListExtension::SetInt64(IAIMPPropertyList* propertyList, int propertyId, Int64 value)
        {
            return Utils::CheckResult(propertyList->SetValueAsInt64(propertyId, value));
        }

        AimpActionResult PropertyListExtension::SetFloat(IAIMPPropertyList* propertyList, int propertyId, double value)
        {
            return Utils::CheckResult(propertyList->SetValueAsFloat(propertyId, value));
        }

        AimpActionResult PropertyListExtension::SetBool(IAIMPPropertyList* propertyList, int propertyId, bool value)
        {
            return SetInt32(propertyList, propertyId, value ? 1 : 0);
        }

        AimpActionResult PropertyListExtension::GetString(IAIMPPropertyList* propertyList, int propertyId, String^% value)
        {
            IAIMPString* str = NULL;
            String ^val = String::Empty;

            try
            {
                AimpActionResult result = Utils::CheckResult(propertyList->GetValueAsObject(propertyId, IID_IAIMPString, (void**)&str));
                if (result != AimpActionResult::Ok)
                {
                    value = String::Empty;
                    return result;
                }

                if (str != NULL)
                {
                    result = GetString(str, val);
                    value = val;
                    return result;
                }
            }
            catch (System::Exception ^ex)
            {
                return AimpActionResult::Fail;
            }
            finally
            {
                if (str != NULL)
                {
                    str->Release();
                    str = NULL;
                }
            }

            return AimpActionResult::Unexpected;
        }

        AimpActionResult PropertyListExtension::GetString(IAIMPString* aimpString, String^% value)
        {
            value = gcnew String(aimpString->GetData());
            return AimpActionResult::Ok;
        }

        AimpActionResult PropertyListExtension::GetObject(IAIMPPropertyList* propertyList, int propertyId, REFIID objectId, void** value)
        {
            AimpActionResult result = Utils::CheckResult(propertyList->GetValueAsObject(propertyId, objectId, (void**)&value));
            return result;
        }

        AimpActionResult PropertyListExtension::GetInt32(IAIMPPropertyList* propertyList, int propertyId, int %value)
        {
            int val = 0;
            AimpActionResult result = Utils::CheckResult(propertyList->GetValueAsInt32(propertyId, &val));
            value = val;
            return result;
        }

        AimpActionResult PropertyListExtension::GetInt64(IAIMPPropertyList* propertyList, int propertyId, Int64 %value)
        {
            Int64 val = 0;
            AimpActionResult result = Utils::CheckResult(propertyList->GetValueAsInt64(propertyId, &val));
            value = val;
            return result;
        }

        AimpActionResult PropertyListExtension::GetFloat(IAIMPPropertyList* propertyList, int propertyId, double %value)
        {
            double val = 0;
            AimpActionResult result = Utils::CheckResult(propertyList->GetValueAsFloat(propertyId, &val));
            value = val;
            return result;
        }

        AimpActionResult PropertyListExtension::GetBool(IAIMPPropertyList* propertyList, int propertyId, bool %value)
        {
            int *val = 0;
            AimpActionResult result = GetInt32(propertyList, propertyId, *val);
            value = val > 0;
            return result;
        }

        String^ PropertyListExtension::GetString(IAIMPPropertyList *propertyList, int propertyId)
        {
            String^ val = String::Empty;
            if (GetString(propertyList, propertyId, *&val) == AimpActionResult::Ok)
            {
                return val;
            }

            return val;
        }

        int PropertyListExtension::GetInt32(IAIMPPropertyList *propertyList, int propertyId)
        {
            int val = 0;
            if (GetInt32(propertyList, propertyId, val) == AimpActionResult::Ok)
            {
                return val;
            }

            return 0;
        }

        Int64 PropertyListExtension::GetInt64(IAIMPPropertyList *propertyList, int propertyId)
        {
            Int64 val;
            if (GetInt64(propertyList, propertyId, val) == AimpActionResult::Ok)
            {
                return val;
            }

            return 0;
        }

        double PropertyListExtension::GetFloat(IAIMPPropertyList *propertyList, int propertyId)
        {
            double val;
            if (GetFloat(propertyList, propertyId, val) == AimpActionResult::Ok)
            {
                return val;
            }

            return 0;
        }

        bool PropertyListExtension::GetBool(IAIMPPropertyList *propertyList, int propertyId)
        {
            bool val;
            if (GetBool(propertyList, propertyId, val) == AimpActionResult::Ok)
            {
                return val;
            }

            return false;
        }

        AimpActionResult PropertyListExtension::GetVariant(IAIMPPropertyList2 *propertyList, int propertyId, Object^% value)
        {
            VARIANT *val = NULL;
            AimpActionResult result = Utils::CheckResult(propertyList->GetValueAsVariant(propertyId, val));
            value = AimpExtension::FromVaiant(val);
            //value = AimpExtension::ToManaged(val);
            //value = val->cVal;
            //value = AIMP::SDK::Variant();
            return result;
        }

        AimpActionResult PropertyListExtension::SetVariant(IAIMPPropertyList2 *propertyList, int propertyId, Object^% val)
        {
            return AimpActionResult::NotImplemented;
        }

        VARIANT AimpExtension::ToVariant(System::Object^ objectValue)
        {
            VARIANT varTag;
            VariantInit(&varTag);
            IntPtr h = IntPtr(&varTag);
            System::Runtime::InteropServices::Marshal::GetNativeVariantForObject(objectValue, h);
            return varTag;
        }

        System::Object^ AimpExtension::FromVaiant(VARIANT* variant)
        {
            void *p = variant;
            return System::Runtime::InteropServices::Marshal::GetObjectForNativeVariant(IntPtr(p));
        }
    }
}
<commit_msg>Fix GetObject at PropertyList<commit_after>#include "Stdafx.h"

#include "AimpExtension.h"
#include "..\Utils.h"
#include "ManagedAimpCore.h"

namespace AIMP
{
    namespace SDK
    {
        //template<typename TAimpNativeObject>
        //TAimpNativeObject* AimpExtension::MakeObject(REFIID objectId)
        //{
        //    TAimpNativeObject* object = NULL;

        //    if (GetCore()->CreateObject(objectId, (void**)&object) == S_OK)
        //    {
        //        return object;
        //    }

        //    return NULL;
        //}

        IAIMPString* AimpExtension::GetAimpString(String ^value)
        {
            IAIMPString *strObject = MakeObject<IAIMPString>(IID_IAIMPString);
            pin_ptr<const WCHAR> strDate = PtrToStringChars(value);
            strObject->SetData((PWCHAR)strDate, value->Length);
            return strObject;
        }

        IAIMPImage* AimpExtension::GetImage(System::Drawing::Bitmap^ image)
        {
            System::IO::MemoryStream ^stream;
            IAIMPStream *aimpStream = NULL;
            IAIMPImage *img = NULL;

            try
            {
                stream = gcnew System::IO::MemoryStream();
                image->Save(stream, System::Drawing::Imaging::ImageFormat::Png);
                array<Byte>^ buffer = stream->ToArray();

                if (Utils::CheckResult(GetCore()->CreateObject(IID_IAIMPMemoryStream, (void**)&aimpStream)) == AIMP::SDK::AimpActionResult::Ok
                    && Utils::CheckResult(GetCore()->CreateObject(IID_IAIMPImage, (void**)&img)) == AIMP::SDK::AimpActionResult::Ok)
                {
                    aimpStream->SetSize(stream->Length);
                    pin_ptr<System::Byte> p = &buffer[0];
                    unsigned char* pby = p;
                    if (Utils::CheckResult(aimpStream->Write(pby, (int)stream->Length, nullptr)) == AIMP::SDK::AimpActionResult::Ok)
                    {
                        img->LoadFromStream(aimpStream);
                    }

                    return img;
                }
            }
            finally
            {
                if (stream != nullptr)
                {
                    stream->Close();
                }
                aimpStream->Release();
                aimpStream = NULL;
            }

            return NULL;
        }

        IAIMPCore* AimpExtension::GetCore()
        {
            return AIMP::SDK::ManagedAimpCore::GetAimpCore();
        }

        AIMP::SDK::Visuals::AimpVisualData^ AimpExtension::PAIMPVisualDataToManaged(PAIMPVisualData data)
        {
            AIMP::SDK::Visuals::AimpVisualData ^result = gcnew AIMP::SDK::Visuals::AimpVisualData();
            result->Peaks = gcnew array<float>(2);
            result->Spectrum = gcnew array<array<float>^>(3);
            result->WaveForm = gcnew array<array<float>^>(2);

            result->Peaks[0] = data->Peaks[0];
            result->Peaks[1] = data->Peaks[1];

            for (int i = 0; i < 3; i++)
            {
                array<float> ^arr = gcnew array<float>(AIMP_VISUAL_SPECTRUM_MAX);
                for (int j = 0; j < AIMP_VISUAL_SPECTRUM_MAX; j++)
                {
                    arr[j] = data->Spectrum[i][j];
                }
                result->Spectrum[i] = arr;
            }

            for (int i = 0; i < 2; i++)
            {
                array<float> ^arr = gcnew array<float>(AIMP_VISUAL_WAVEFORM_MAX);
                for (int j = 0; j < AIMP_VISUAL_WAVEFORM_MAX; j++)
                {
                    arr[j] = data->WaveForm[i][j];
                }
                result->WaveForm[i] = arr;
            }

            return result;
        }

        System::Drawing::Bitmap^ AimpExtension::GetBitmap(IAIMPImageContainer* imageContainer)
        {
            IAIMPImage* image = NULL;
            try
            {
                if (Utils::CheckResult(ManagedAimpCore::GetAimpCore()->CreateObject(IID_IAIMPImage, (void**)&image)) == AimpActionResult::Ok)
                {
                    return nullptr;
                }

                imageContainer->CreateImage(&image);

                if (image == NULL)
                {
                    return nullptr;
                }
                return GetBitmap(image);
            }
            finally
            {
                image->Release();
                image = NULL;
            }

            return nullptr;
        }

        System::Drawing::Bitmap^ AimpExtension::GetBitmap(IAIMPImage* image)
        {
            SIZE size;
            if (Utils::CheckResult(image->GetSize(&size)) == AimpActionResult::Ok)
            {
                if (size.cx == 0 || size.cy == 0)
                {
                    return nullptr;
                }

                System::Drawing::Bitmap^ bmp = gcnew System::Drawing::Bitmap(size.cx, size.cy);

                IAIMPStream *stream;
                AIMP::SDK::ManagedAimpCore::GetAimpCore()->CreateObject(IID_IAIMPMemoryStream, (void**)&stream);
                image->SaveToStream(stream, AIMP_IMAGE_FORMAT_PNG);
                if (stream->GetSize() > 0)
                {
                    Int64 size = stream->GetSize();
                    unsigned char *buf = new unsigned char[(int)size];
                    HRESULT r = stream->Seek(0, AIMP_STREAM_SEEKMODE_FROM_BEGINNING);
                    r = stream->Read(buf, (int)size);

                    System::IO::MemoryStream^ strm = gcnew System::IO::MemoryStream();
                    try
                    {
                        for (int i = 0; i < size; i++)
                        {
                            strm->WriteByte(buf[i]);
                        }
                        bmp = gcnew System::Drawing::Bitmap(strm);
                    }
                    finally
                    {
                        strm->Close();
                        strm = nullptr;

                        delete[] buf;
                        stream->Release();
                        image->Release();
                        stream = NULL;
                        image = NULL;
                    }
                }

                return bmp;
            }

            return nullptr;
        }

        IAIMPImageContainer* AimpExtension::ToContainer(System::Drawing::Bitmap ^image)
        {
            IAIMPImageContainer *container;
            if (Utils::CheckResult(ManagedAimpCore::GetAimpCore()->CreateObject(IID_IAIMPImageContainer, (void**)&container)) == AimpActionResult::Ok)
            {
                System::IO::Stream ^stream = nullptr;
                try
                {
                    stream = gcnew System::IO::MemoryStream();
                    image->Save(stream, System::Drawing::Imaging::ImageFormat::Jpeg);
                    stream->Seek(0, System::IO::SeekOrigin::Begin);
                    if (Utils::CheckResult(container->SetDataSize((DWORD)stream->Length)) != AimpActionResult::Ok)
                    {
                        return NULL;
                    }

                    byte *b = container->GetData();
                    for (int i = 0; i < stream->Length - 1; i++)
                    {
                        b[i] = stream->ReadByte();
                    }

                    return container;
                }
                finally
                {
                    if (stream != nullptr)
                    {
                        stream->Close();
                    }
                }
            }

            return NULL;
        }

        String^ AimpExtension::GetString(IAIMPString* value)
        {
            return gcnew String(value->GetData());
        }

        AimpActionResult PropertyListExtension::SetObject(IAIMPPropertyList* propertyList, int propertyId, IUnknown *value)
        {
            return Utils::CheckResult(propertyList->SetValueAsObject(propertyId, value));
        }

        AimpActionResult PropertyListExtension::SetString(IAIMPPropertyList* propertyList, int propertyId, String ^value)
        {
            // No need to process empty value
            if (String::IsNullOrWhiteSpace(value))
            {
                return AimpActionResult::InvalidArguments;
            }

            IAIMPString *str = NULL;
            try
            {
                str = AimpExtension::GetAimpString(value);
                return SetObject(propertyList, propertyId, str);
            }
            finally
            {
                str->Release();
                str = NULL;
            }

            return AimpActionResult::Unexpected;
        }

        AimpActionResult PropertyListExtension::SetInt32(IAIMPPropertyList* propertyList, int propertyId, int value)
        {
            return Utils::CheckResult(propertyList->SetValueAsInt32(propertyId, value));
        }

        AimpActionResult PropertyListExtension::SetInt64(IAIMPPropertyList* propertyList, int propertyId, Int64 value)
        {
            return Utils::CheckResult(propertyList->SetValueAsInt64(propertyId, value));
        }

        AimpActionResult PropertyListExtension::SetFloat(IAIMPPropertyList* propertyList, int propertyId, double value)
        {
            return Utils::CheckResult(propertyList->SetValueAsFloat(propertyId, value));
        }

        AimpActionResult PropertyListExtension::SetBool(IAIMPPropertyList* propertyList, int propertyId, bool value)
        {
            return SetInt32(propertyList, propertyId, value ? 1 : 0);
        }

        AimpActionResult PropertyListExtension::GetString(IAIMPPropertyList* propertyList, int propertyId, String^% value)
        {
            IAIMPString* str = NULL;
            String ^val = String::Empty;

            try
            {
                AimpActionResult result = Utils::CheckResult(propertyList->GetValueAsObject(propertyId, IID_IAIMPString, (void**)&str));
                if (result != AimpActionResult::Ok)
                {
                    value = String::Empty;
                    return result;
                }

                if (str != NULL)
                {
                    result = GetString(str, val);
                    value = val;
                    return result;
                }
            }
            catch (System::Exception ^ex)
            {
                return AimpActionResult::Fail;
            }
            finally
            {
                if (str != NULL)
                {
                    str->Release();
                    str = NULL;
                }
            }

            return AimpActionResult::Unexpected;
        }

        AimpActionResult PropertyListExtension::GetString(IAIMPString* aimpString, String^% value)
        {
            value = gcnew String(aimpString->GetData());
            return AimpActionResult::Ok;
        }

        AimpActionResult PropertyListExtension::GetObject(IAIMPPropertyList* propertyList, int propertyId, REFIID objectId, void** value)
        {
            AimpActionResult result = Utils::CheckResult(propertyList->GetValueAsObject(propertyId, objectId, value));
            return result;
        }

        AimpActionResult PropertyListExtension::GetInt32(IAIMPPropertyList* propertyList, int propertyId, int %value)
        {
            int val = 0;
            AimpActionResult result = Utils::CheckResult(propertyList->GetValueAsInt32(propertyId, &val));
            value = val;
            return result;
        }

        AimpActionResult PropertyListExtension::GetInt64(IAIMPPropertyList* propertyList, int propertyId, Int64 %value)
        {
            Int64 val = 0;
            AimpActionResult result = Utils::CheckResult(propertyList->GetValueAsInt64(propertyId, &val));
            value = val;
            return result;
        }

        AimpActionResult PropertyListExtension::GetFloat(IAIMPPropertyList* propertyList, int propertyId, double %value)
        {
            double val = 0;
            AimpActionResult result = Utils::CheckResult(propertyList->GetValueAsFloat(propertyId, &val));
            value = val;
            return result;
        }

        AimpActionResult PropertyListExtension::GetBool(IAIMPPropertyList* propertyList, int propertyId, bool %value)
        {
            int *val = 0;
            AimpActionResult result = GetInt32(propertyList, propertyId, *val);
            value = val > 0;
            return result;
        }

        String^ PropertyListExtension::GetString(IAIMPPropertyList *propertyList, int propertyId)
        {
            String^ val = String::Empty;
            if (GetString(propertyList, propertyId, *&val) == AimpActionResult::Ok)
            {
                return val;
            }

            return val;
        }

        int PropertyListExtension::GetInt32(IAIMPPropertyList *propertyList, int propertyId)
        {
            int val = 0;
            if (GetInt32(propertyList, propertyId, val) == AimpActionResult::Ok)
            {
                return val;
            }

            return 0;
        }

        Int64 PropertyListExtension::GetInt64(IAIMPPropertyList *propertyList, int propertyId)
        {
            Int64 val;
            if (GetInt64(propertyList, propertyId, val) == AimpActionResult::Ok)
            {
                return val;
            }

            return 0;
        }

        double PropertyListExtension::GetFloat(IAIMPPropertyList *propertyList, int propertyId)
        {
            double val;
            if (GetFloat(propertyList, propertyId, val) == AimpActionResult::Ok)
            {
                return val;
            }

            return 0;
        }

        bool PropertyListExtension::GetBool(IAIMPPropertyList *propertyList, int propertyId)
        {
            bool val;
            if (GetBool(propertyList, propertyId, val) == AimpActionResult::Ok)
            {
                return val;
            }

            return false;
        }

        AimpActionResult PropertyListExtension::GetVariant(IAIMPPropertyList2 *propertyList, int propertyId, Object^% value)
        {
            VARIANT *val = NULL;
            AimpActionResult result = Utils::CheckResult(propertyList->GetValueAsVariant(propertyId, val));
            value = AimpExtension::FromVaiant(val);
            //value = AimpExtension::ToManaged(val);
            //value = val->cVal;
            //value = AIMP::SDK::Variant();
            return result;
        }

        AimpActionResult PropertyListExtension::SetVariant(IAIMPPropertyList2 *propertyList, int propertyId, Object^% val)
        {
            return AimpActionResult::NotImplemented;
        }

        VARIANT AimpExtension::ToVariant(System::Object^ objectValue)
        {
            VARIANT varTag;
            VariantInit(&varTag);
            IntPtr h = IntPtr(&varTag);
            System::Runtime::InteropServices::Marshal::GetNativeVariantForObject(objectValue, h);
            return varTag;
        }

        System::Object^ AimpExtension::FromVaiant(VARIANT* variant)
        {
            void *p = variant;
            return System::Runtime::InteropServices::Marshal::GetObjectForNativeVariant(IntPtr(p));
        }
    }
}
<|endoftext|>


<commit_before>/**
 * @file ncl.cpp
 *
 * Template for future plugins.
 *
 * @date Apr 10, 2013
 * @author peramaki
 */

#include "ncl.h"
#include "plugin_factory.h"
#include "logger_factory.h"
#include <boost/lexical_cast.hpp>
#include <boost/thread.hpp>

#define HIMAN_AUXILIARY_INCLUDE

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

#undef HIMAN_AUXILIARY_INCLUDE

#ifdef DEBUG
#include "timer_factory.h"
#endif

using namespace std;
using namespace himan::plugin;

#include "cuda_extern.h"

const string itsName("ncl");

ncl::ncl() : itsUseCuda(false)
{
	itsLogger = unique_ptr<logger> (logger_factory::Instance()->GetLog(itsName));

}

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

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

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

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

		itsLogger->Info(msg);

		itsCudaDeviceCount = c->DeviceCount();

	}

	// Get number of threads to use

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

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

	boost::thread_group g;

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

	/*
	 * Set target parameter to potential temperature
	 * - name PARM_NAME
	 * - univ_id UNIV_ID
	 * - grib2 descriptor X'Y'Z
	 *
	 * We need to specify grib and querydata parameter information
	 * since we don't know which one will be the output format.
	 *
	 */

	vector<param> theParams;

	// GRIB 2

	param theRequestedParam;
	theRequestedParam.GribDiscipline(0);
	theRequestedParam.GribCategory(3);
	theRequestedParam.GribParameter(6);

	if (conf->Exists("temp") && conf->GetValue("temp") == "-20" )
	{
    	theRequestedParam.Name("HM20C-M");
    	theRequestedParam.UnivId(28);
    	targetTemperature = -20;
    }

    if (conf->Exists("temp") && conf->GetValue("temp") == "0" )
	{
    	theRequestedParam.Name("H0C-M");
    	theRequestedParam.UnivId(270);
    	targetTemperature = 0;

    }

	/*
	 * GRIB 1 parameters go here
	 *
	 */
 	if (conf->OutputFileType() == kGRIB1)
	{
		shared_ptr<neons> n = dynamic_pointer_cast<neons> (plugin_factory::Instance()->Plugin("neons"));

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

	}

	// ----

	theParams.push_back(theRequestedParam);

	targetInfo->Params(theParams);

	/*
	 * Create data structures.
	 */

	targetInfo->Create();

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

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

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

	vector<shared_ptr<info> > targetInfos;

	targetInfos.resize(threadCount);

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

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

		targetInfos[i] = shared_ptr<info> (new info(*targetInfo));

		boost::thread* t = new boost::thread(&ncl::Run,
								this,
								targetInfos[i],
								conf,
								i + 1);

		g.add_thread(t);

	}

	g.join_all();

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

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

		string theOutputFile = conf->ConfigurationFile();

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

	}
}

void ncl::Run(shared_ptr<info> myTargetInfo,
				shared_ptr<const plugin_configuration> conf,
				unsigned short threadIndex)
{

	while (AdjustLeadingDimension(myTargetInfo))
	{
		Calculate(myTargetInfo, conf, threadIndex);
	}
}

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

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

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

	param HParam("HL-M");
	param TParam("T-K");

	int levelNumber = 65;

	level HLevel(himan::kHybrid, levelNumber, "HYBRID");

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

	ResetNonLeadingDimension(myTargetInfo);

	myTargetInfo->FirstParam();

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

		shared_ptr<info> HInfo;
		shared_ptr<info> TInfo;
		shared_ptr<info> prevHInfo;
		shared_ptr<info> prevTInfo;

		try
		{

			HInfo = theFetcher->Fetch(conf,
								 myTargetInfo->Time(),
								 HLevel,
								 HParam);

			TInfo = theFetcher->Fetch(conf,
								 myTargetInfo->Time(),
								 HLevel,
								 TParam);

		}
		catch (HPExceptionType e)
		{
			switch (e)
			{
				case kFileDataNotFound:
					itsLogger->Warning("Skipping step " + boost::lexical_cast<string> (myTargetInfo->Time().Step()) + ", level " + boost::lexical_cast<string> (myTargetInfo->Level().Value()));
					myTargetInfo->Data()->Fill(kFloatMissing);

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

					continue;
					break;

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

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

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

		int missingCount = 0;
		int count = 0;

		/*
		 * Converting original grid-data to newbase grid
		 *
		 */

		bool firstLevel = true;

		myTargetInfo->Data()->Fill(0);

		HInfo->ResetLocation();
		TInfo->ResetLocation();

		level curLevel = HLevel;
		level prevLevel;

		while (--levelNumber > 0)
		{
			shared_ptr<NFmiGrid> targetGrid(myTargetInfo->Grid()->ToNewbaseGrid());

			targetGrid->Reset();
			myTargetInfo->ResetLocation();

			 //minneköhän tää pitäis pistää
			//itsLogger->Debug("kierros woop " +  boost::lexical_cast<string> (count) );

			shared_ptr<NFmiGrid> HGrid(HInfo->Grid()->ToNewbaseGrid());
			shared_ptr<NFmiGrid> TGrid(TInfo->Grid()->ToNewbaseGrid());
			shared_ptr<NFmiGrid> prevHGrid;
			shared_ptr<NFmiGrid> prevTGrid;

			if (!firstLevel)
			{
				prevHGrid = shared_ptr<NFmiGrid>(prevHInfo->Grid()->ToNewbaseGrid());
				prevTGrid = shared_ptr<NFmiGrid>(prevTInfo->Grid()->ToNewbaseGrid());
			}

			bool equalGrids = (*myTargetInfo->Grid() == *HInfo->Grid() && *myTargetInfo->Grid() == *TInfo->Grid() && ( firstLevel || ( *myTargetInfo->Grid() == *prevHInfo->Grid() && *myTargetInfo->Grid() == *prevTInfo->Grid() ) ) );

			while ( myTargetInfo->NextLocation() && targetGrid->Next() && HGrid->Next() && TGrid->Next() && ( firstLevel || (prevHGrid->Next() && prevTGrid->Next() ) ) )
			{
				count++;
				string deviceType;

				deviceType = "CPU";

				double height = kFloatMissing;
				double temp = kFloatMissing;
				double prevHeight = kFloatMissing;
				double prevTemp = kFloatMissing;

				double targetHeight = myTargetInfo->Value();

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

				InterpolateToPoint(targetGrid, HGrid, equalGrids, height);
				InterpolateToPoint(targetGrid, TGrid, equalGrids, temp);

				if (!firstLevel)
				{
					InterpolateToPoint(targetGrid, prevHGrid, equalGrids, prevHeight);
					InterpolateToPoint(targetGrid, prevTGrid, equalGrids, prevTemp);
				}

				if (height == kFloatMissing || temp == kFloatMissing || (!firstLevel && ( prevHeight == kFloatMissing || prevTemp == kFloatMissing)))
				{
					missingCount++;

					myTargetInfo->Value(kFloatMissing);
					continue;
				}

				temp -= 273.15;
				prevTemp -= 273.15;

				if (targetHeight == 0)
				{
					//itsLogger->Debug("level: " + boost::lexical_cast<string> (height));

					if (temp < targetTemperature)
					{
						if (!firstLevel)
						{
							double p_rel = (targetTemperature - temp) / (prevTemp - temp);
							targetHeight = height + (prevHeight - height) * p_rel;
						}
						else
						{
							targetHeight = -99999;
						}
					}
				}
				//Inversiotilanteessa pelastetaan vielä pisteitä uudelleen laskentaan
				else if (targetHeight != 0 && temp > targetTemperature)
				{
					targetHeight = 0;
				}

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

			}

			prevLevel = curLevel;
			curLevel = level(himan::kHybrid, levelNumber, "HYBRID");

			HInfo = FetchPrevious(conf, myTargetInfo->Time(), curLevel, HParam);
			TInfo = FetchPrevious(conf, myTargetInfo->Time(), curLevel, TParam);

			prevHInfo = FetchPrevious(conf, myTargetInfo->Time(), prevLevel, HParam);
			prevTInfo = FetchPrevious(conf, myTargetInfo->Time(), prevLevel, TParam);

			firstLevel = false;
		}

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

#ifdef DEBUG
			itsLogger->Debug("Calculation took " + boost::lexical_cast<string> (processTimer->GetTime()) + " microseconds on "  + deviceType);
#endif

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

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

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

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

			theWriter->ToFile(shared_ptr<info> (new info(*myTargetInfo)), conf);
		}
	}
}
shared_ptr<himan::info> ncl::FetchPrevious(shared_ptr<const plugin_configuration> conf, const forecast_time& wantedTime, const level& wantedLevel, const param& wantedParam)
{
	shared_ptr<fetcher> f = dynamic_pointer_cast <fetcher> (plugin_factory::Instance()->Plugin("fetcher"));

	try
	{
		return f->Fetch(conf,
						wantedTime,
						wantedLevel,
						wantedParam);
   	}
	catch (HPExceptionType e)
	{
		throw e;
	}

}<commit_msg>logic fix<commit_after>/**
 * @file ncl.cpp
 *
 * Template for future plugins.
 *
 * @date Apr 10, 2013
 * @author peramaki
 */

#include "ncl.h"
#include "plugin_factory.h"
#include "logger_factory.h"
#include <boost/lexical_cast.hpp>
#include <boost/thread.hpp>

#define HIMAN_AUXILIARY_INCLUDE

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

#undef HIMAN_AUXILIARY_INCLUDE

#ifdef DEBUG
#include "timer_factory.h"
#endif

using namespace std;
using namespace himan::plugin;

#include "cuda_extern.h"

const string itsName("ncl");

ncl::ncl() : itsUseCuda(false)
{
	itsLogger = unique_ptr<logger> (logger_factory::Instance()->GetLog(itsName));

}

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

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

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

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

		itsLogger->Info(msg);

		itsCudaDeviceCount = c->DeviceCount();

	}

	// Get number of threads to use

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

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

	boost::thread_group g;

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

	/*
	 * Set target parameter to potential temperature
	 * - name PARM_NAME
	 * - univ_id UNIV_ID
	 * - grib2 descriptor X'Y'Z
	 *
	 * We need to specify grib and querydata parameter information
	 * since we don't know which one will be the output format.
	 *
	 */

	vector<param> theParams;

	// GRIB 2

	param theRequestedParam;
	theRequestedParam.GribDiscipline(0);
	theRequestedParam.GribCategory(3);
	theRequestedParam.GribParameter(6);

	if (conf->Exists("temp") && conf->GetValue("temp") == "-20" )
	{
    	theRequestedParam.Name("HM20C-M");
    	theRequestedParam.UnivId(28);
    	targetTemperature = -20;
    }

    if (conf->Exists("temp") && conf->GetValue("temp") == "0" )
	{
    	theRequestedParam.Name("H0C-M");
    	theRequestedParam.UnivId(270);
    	targetTemperature = 0;

    }

	/*
	 * GRIB 1 parameters go here
	 *
	 */
 	if (conf->OutputFileType() == kGRIB1)
	{
		shared_ptr<neons> n = dynamic_pointer_cast<neons> (plugin_factory::Instance()->Plugin("neons"));

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

	}

	// ----

	theParams.push_back(theRequestedParam);

	targetInfo->Params(theParams);

	/*
	 * Create data structures.
	 */

	targetInfo->Create();

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

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

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

	vector<shared_ptr<info> > targetInfos;

	targetInfos.resize(threadCount);

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

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

		targetInfos[i] = shared_ptr<info> (new info(*targetInfo));

		boost::thread* t = new boost::thread(&ncl::Run,
								this,
								targetInfos[i],
								conf,
								i + 1);

		g.add_thread(t);

	}

	g.join_all();

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

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

		string theOutputFile = conf->ConfigurationFile();

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

	}
}

void ncl::Run(shared_ptr<info> myTargetInfo,
				shared_ptr<const plugin_configuration> conf,
				unsigned short threadIndex)
{

	while (AdjustLeadingDimension(myTargetInfo))
	{
		Calculate(myTargetInfo, conf, threadIndex);
	}
}

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

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

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

	param HParam("HL-M");
	param TParam("T-K");

	int levelNumber = 65;

	level HLevel(himan::kHybrid, levelNumber, "HYBRID");

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

	ResetNonLeadingDimension(myTargetInfo);

	myTargetInfo->FirstParam();

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

		shared_ptr<info> HInfo;
		shared_ptr<info> TInfo;
		shared_ptr<info> prevHInfo;
		shared_ptr<info> prevTInfo;

		try
		{

			HInfo = theFetcher->Fetch(conf,
								 myTargetInfo->Time(),
								 HLevel,
								 HParam);

			TInfo = theFetcher->Fetch(conf,
								 myTargetInfo->Time(),
								 HLevel,
								 TParam);

		}
		catch (HPExceptionType e)
		{
			switch (e)
			{
				case kFileDataNotFound:
					itsLogger->Warning("Skipping step " + boost::lexical_cast<string> (myTargetInfo->Time().Step()) + ", level " + boost::lexical_cast<string> (myTargetInfo->Level().Value()));
					myTargetInfo->Data()->Fill(kFloatMissing);

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

					continue;
					break;

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

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

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

		int missingCount = 0;
		int count = 0;

		/*
		 * Converting original grid-data to newbase grid
		 *
		 */

		bool firstLevel = true;

		myTargetInfo->Data()->Fill(0);

		HInfo->ResetLocation();
		TInfo->ResetLocation();

		level curLevel = HLevel;
		level prevLevel;

		shared_ptr<NFmiGrid> targetGrid(myTargetInfo->Grid()->ToNewbaseGrid());

		while (--levelNumber > 0)
		{

			targetGrid->Reset();
			myTargetInfo->FirstLocation();

			 //minneköhän tää pitäis pistää
			//itsLogger->Debug("kierros woop " +  boost::lexical_cast<string> (count) );

			shared_ptr<NFmiGrid> HGrid(HInfo->Grid()->ToNewbaseGrid());
			shared_ptr<NFmiGrid> TGrid(TInfo->Grid()->ToNewbaseGrid());
			shared_ptr<NFmiGrid> prevHGrid;
			shared_ptr<NFmiGrid> prevTGrid;

			if (!firstLevel)
			{
				prevHGrid = shared_ptr<NFmiGrid>(prevHInfo->Grid()->ToNewbaseGrid());
				prevTGrid = shared_ptr<NFmiGrid>(prevTInfo->Grid()->ToNewbaseGrid());
			}

			bool equalGrids = (	*myTargetInfo->Grid() == *HInfo->Grid()
								&& *myTargetInfo->Grid() == *TInfo->Grid()
								&& ( firstLevel || ( *myTargetInfo->Grid() == *prevHInfo->Grid() && *myTargetInfo->Grid() == *prevTInfo->Grid() ) ) );

			while ( myTargetInfo->NextLocation() && targetGrid->Next() && HGrid->Next() && TGrid->Next() && ( firstLevel || (prevHGrid->Next() && prevTGrid->Next() ) ) )
			{
				count++;
				string deviceType;

				deviceType = "CPU";

				double height = kFloatMissing;
				double temp = kFloatMissing;
				double prevHeight = kFloatMissing;
				double prevTemp = kFloatMissing;

				double targetHeight = myTargetInfo->Value();

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

				InterpolateToPoint(targetGrid, HGrid, equalGrids, height);
				InterpolateToPoint(targetGrid, TGrid, equalGrids, temp);

				if (!firstLevel)
				{
					InterpolateToPoint(targetGrid, prevHGrid, equalGrids, prevHeight);
					InterpolateToPoint(targetGrid, prevTGrid, equalGrids, prevTemp);
				}

				if (height == kFloatMissing || temp == kFloatMissing || (!firstLevel && ( prevHeight == kFloatMissing || prevTemp == kFloatMissing)))
				{
					missingCount++;

					myTargetInfo->Value(kFloatMissing);
					continue;
				}

				temp -= 273.15;
				prevTemp -= 273.15;

				if (targetHeight == 0)
				{
					//itsLogger->Debug("level: " + boost::lexical_cast<string> (height));

					if (temp < targetTemperature)
					{
						if (!firstLevel)
						{
							double p_rel = (targetTemperature - temp) / (prevTemp - temp);
							targetHeight = height + (prevHeight - height) * p_rel;
						}
						else
						{
							targetHeight = kFloatMissing;
						}
					}
				}
				//Inversiotilanteessa pelastetaan vielä pisteitä uudelleen laskentaan
				else if (targetHeight != 0 && temp > targetTemperature)
				{
					targetHeight = 0;
				}

				//itsLogger->Debug("level: " + boost::lexical_cast<string> (targetHeight));
				if (!myTargetInfo->Value(targetHeight))
				{
					throw runtime_error(ClassName() + ": Failed to set value to matrix");
				}

			}

			prevLevel = curLevel;
			curLevel = level(himan::kHybrid, levelNumber, "HYBRID");

			HInfo = FetchPrevious(conf, myTargetInfo->Time(), curLevel, HParam);
			TInfo = FetchPrevious(conf, myTargetInfo->Time(), curLevel, TParam);

			prevHInfo = FetchPrevious(conf, myTargetInfo->Time(), prevLevel, HParam);
			prevTInfo = FetchPrevious(conf, myTargetInfo->Time(), prevLevel, TParam);

			firstLevel = false;
		}

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

#ifdef DEBUG
			itsLogger->Debug("Calculation took " + boost::lexical_cast<string> (processTimer->GetTime()) + " microseconds on "  + deviceType);
#endif

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

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

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

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

			theWriter->ToFile(shared_ptr<info> (new info(*myTargetInfo)), conf);
		}
	}
}
shared_ptr<himan::info> ncl::FetchPrevious(shared_ptr<const plugin_configuration> conf, const forecast_time& wantedTime, const level& wantedLevel, const param& wantedParam)
{
	shared_ptr<fetcher> f = dynamic_pointer_cast <fetcher> (plugin_factory::Instance()->Plugin("fetcher"));

	try
	{
		return f->Fetch(conf,
						wantedTime,
						wantedLevel,
						wantedParam);
   	}
	catch (HPExceptionType e)
	{
		throw e;
	}

}<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 2746
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<commit_msg>P4 to Git Change 1611372 by chui@ocl-promo-incrementor on 2018/09/27 02:56:48<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 2747
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 2752
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<commit_msg>P4 to Git Change 1614408 by chui@ocl-promo-incrementor on 2018/10/04 02:56:51<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 2753
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 1992
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<commit_msg>P4 to Git Change 1224277 by johtaylo@johtaylo-JTBUILDER03-increment on 2016/01/02 03:00:11<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 1993
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 2481
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<commit_msg>P4 to Git Change 1449639 by johtaylo@johtaylo-jtincrementor-increment on 2017/08/21 03:00:05<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 2482
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 2694
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<commit_msg>P4 to Git Change 1580522 by chui@ocl-promo-incrementor on 2018/07/14 03:00:23<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 2695
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 2998
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<commit_msg>P4 to Git Change 1999173 by chui@ocl-promo-incrementor on 2019/09/17 03:00:37<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 2999
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 2084
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<commit_msg>P4 to Git Change 1254404 by johtaylo@johtaylo-JTBUILDER03-increment on 2016/04/05 03:00:10<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 2085
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 1906
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<commit_msg>P4 to Git Change 1197854 by johtaylo@johtaylo-JTBUILDER03-increment on 2015/10/08 03:00:13<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 1907
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 2186
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<commit_msg>P4 to Git Change 1299375 by johtaylo@johtaylo-JTBUILDER03-increment on 2016/08/05 03:00:10<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 2187
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 2313
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<commit_msg>P4 to Git Change 1357043 by johtaylo@johtaylo-jtincrementor-increment on 2016/12/24 03:00:05<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 2314
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 2992
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<commit_msg>P4 to Git Change 1995962 by chui@ocl-promo-incrementor on 2019/09/10 03:00:33<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 2993
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<|endoftext|>


<commit_before>#include <common/endian.h>

#include <event/event_callback.h>

#include <http/http_protocol.h>

#include <io/pipe/pipe.h>
#include <io/pipe/pipe_producer.h>

#include <ssh/ssh_algorithm_negotiation.h>
#include <ssh/ssh_protocol.h>
#include <ssh/ssh_transport_pipe.h>

namespace {
	static uint8_t zero_padding[255];
}

SSH::TransportPipe::TransportPipe(void)
: PipeProducer("/ssh/transport/pipe"),
  state_(GetIdentificationString),
  block_size_(8),
  mac_length_(0),
  algorithm_negotiation_(NULL),
  receive_callback_(NULL),
  receive_action_(NULL)
{
	Buffer identification_string("SSH-2.0-WANProxy " + (std::string)log_ + "\r\n");
	produce(&identification_string);
}

SSH::TransportPipe::~TransportPipe()
{
	ASSERT(receive_callback_ == NULL);
	ASSERT(receive_action_ == NULL);
}

Action *
SSH::TransportPipe::receive(EventCallback *cb)
{
	ASSERT(receive_callback_ == NULL);
	ASSERT(receive_action_ == NULL);

	/*
	 * XXX
	 * This pattern is implemented about three different
	 * ways in the WANProxy codebase, and they are all kind
	 * of awful.  Need a better way to handle code that
	 * needs executed either on the request of the caller
	 * or when data comes in that satisfies a deferred
	 * callback to a caller.
	 */
	receive_callback_ = cb;
	receive_do();

	if (receive_callback_ != NULL)
		return (cancellation(this, &SSH::TransportPipe::receive_cancel));

	ASSERT(receive_action_ != NULL);
	Action *a = receive_action_;
	receive_action_ = NULL;
	return (a);
}

/*
 * Because this is primarily for WAN optimization we always use minimal
 * padding and zero padding.  Quick and dirty.  Perhaps revisit later,
 * although it makes send() asynchronous unless we add a blocking
 * RNG interface.
 */
void
SSH::TransportPipe::send(Buffer *payload)
{
	Buffer packet;
	uint8_t padding_len;
	uint32_t packet_len;

	ASSERT(state_ == GetPacket);

	packet_len = sizeof padding_len + payload->length();
	padding_len = 4 + (block_size_ - ((sizeof packet_len + packet_len + 4) % block_size_));
	packet_len += padding_len;

	packet_len = BigEndian::encode(packet_len);
	packet.append(&packet_len);
	packet.append(padding_len);
	packet.append(payload);
	packet.append(zero_padding, padding_len);

	if (mac_length_ != 0)
		NOTREACHED();

	payload->clear();

	produce(&packet);
}

void
SSH::TransportPipe::consume(Buffer *in)
{
	/* XXX XXX XXX */
	if (in->empty()) {
		if (!input_buffer_.empty())
			DEBUG(log_) << "Received EOS with data outstanding.";
		produce_eos();
		return;
	}

	in->moveout(&input_buffer_);

	if (state_ == GetIdentificationString) {
		HTTPProtocol::ParseStatus status;

		while (!input_buffer_.empty()) {
			Buffer line;
			status = HTTPProtocol::ExtractLine(&line, &input_buffer_);
			switch (status) {
			case HTTPProtocol::ParseSuccess:
				break;
			case HTTPProtocol::ParseFailure:
				ERROR(log_) << "Invalid line while waiting for identification string.";
				produce_error();
				return;
			case HTTPProtocol::ParseIncomplete:
				/* Wait for more.  */
				return;
			}

			if (!line.prefix("SSH-"))
				continue; /* Next line.  */

			if (!line.prefix("SSH-2.0")) {
				ERROR(log_) << "Unsupported version.";
				produce_error();
				return;
			}

			state_ = GetPacket;
			/*
			 * XXX
			 * Should have a callback here?
			 */
			if (algorithm_negotiation_ != NULL) {
				Buffer packet;
				if (algorithm_negotiation_->output(&packet))
					send(&packet);
			}
			break;
		}
	}

	if (state_ == GetPacket && receive_callback_ != NULL)
		receive_do();
}

void
SSH::TransportPipe::receive_cancel(void)
{
	if (receive_action_ != NULL) {
		receive_action_->cancel();
		receive_action_ = NULL;
	}

	if (receive_callback_ != NULL) {
		delete receive_callback_;
		receive_callback_ = NULL;
	}
}

void
SSH::TransportPipe::receive_do(void)
{
	ASSERT(receive_action_ == NULL);
	ASSERT(receive_callback_ != NULL);

	if (state_ != GetPacket)
		return;

	while (!input_buffer_.empty()) {
		Buffer packet;
		Buffer mac;
		uint32_t packet_len;
		uint8_t padding_len;
		uint8_t msg;

		if (input_buffer_.length() <= sizeof packet_len) {
			DEBUG(log_) << "Waiting for packet length.";
			return;
		}

		input_buffer_.extract(&packet_len);
		packet_len = BigEndian::decode(packet_len);

		if (packet_len == 0) {
			ERROR(log_) << "Need to handle 0-length packet.";
			produce_error();
			return;
		}

		if (input_buffer_.length() < sizeof packet_len + packet_len + mac_length_) {
			DEBUG(log_) << "Need " << sizeof packet_len + packet_len + mac_length_ << "bytes; have " << input_buffer_.length() << ".";
			return;
		}

		input_buffer_.moveout(&packet, sizeof packet_len, packet_len);
		if (mac_length_ != 0)
			input_buffer_.moveout(&mac, 0, mac_length_);

		padding_len = packet.peek();
		packet.skip(sizeof padding_len);
		if (padding_len != 0) {
			if (packet.length() < padding_len) {
				ERROR(log_) << "Padding too large for packet.";
				produce_error();
				return;
			}
			packet.trim(padding_len);
		}

		if (packet.empty()) {
			ERROR(log_) << "Need to handle empty packet.";
			produce_error();
			return;
		}

		/*
		 * Pass by range to registered handlers for each range.
		 * Unhandled messages go to the receive_callback_, and
		 * the caller can register key exchange mechanisms,
		 * and handle (or discard) whatever they don't handle.
		 *
		 * NB: The caller could do all this, but it's assumed
		 *     that they usually have better things to do.  If
		 *     they register no handlers, they can certainly do
		 *     so by hand.
		 */
		msg = packet.peek();
		if (msg >= SSH::Message::TransportRangeBegin &&
		    msg <= SSH::Message::TransportRangeEnd) {
			DEBUG(log_) << "Using default handler for transport message.";
		} else if (msg >= SSH::Message::AlgorithmNegotiationRangeBegin &&
			   msg <= SSH::Message::AlgorithmNegotiationRangeEnd) {
			if (algorithm_negotiation_ != NULL) {
				if (algorithm_negotiation_->input(&packet))
					continue;
			}
			DEBUG(log_) << "Using default handler for algorithm negotiation message.";
		} else if (msg >= SSH::Message::KeyExchangeMethodRangeBegin &&
			   msg <= SSH::Message::KeyExchangeMethodRangeEnd) {
			DEBUG(log_) << "Using default handler for key exchange method message.";
		} else if (msg >= SSH::Message::UserAuthenticationGenericRangeBegin &&
			   msg <= SSH::Message::UserAuthenticationGenericRangeEnd) {
			DEBUG(log_) << "Using default handler for generic user authentication message.";
		} else if (msg >= SSH::Message::UserAuthenticationMethodRangeBegin &&
			   msg <= SSH::Message::UserAuthenticationMethodRangeEnd) {
			DEBUG(log_) << "Using default handler for user authentication method message.";
		} else if (msg >= SSH::Message::ConnectionProtocolGlobalRangeBegin &&
			   msg <= SSH::Message::ConnectionProtocolGlobalRangeEnd) {
			DEBUG(log_) << "Using default handler for generic connection protocol message.";
		} else if (msg >= SSH::Message::ConnectionChannelRangeBegin &&
			   msg <= SSH::Message::ConnectionChannelRangeEnd) {
			DEBUG(log_) << "Using default handler for connection channel message.";
		} else if (msg >= SSH::Message::ClientProtocolReservedRangeBegin &&
			   msg <= SSH::Message::ClientProtocolReservedRangeEnd) {
			DEBUG(log_) << "Using default handler for client protocol message.";
		} else if (msg >= SSH::Message::LocalExtensionRangeBegin) {
			/* Because msg is a uint8_t, it will always be <= SSH::Message::LocalExtensionRangeEnd.  */
			DEBUG(log_) << "Using default handler for local extension message.";
		} else {
			ASSERT(msg == 0);
			ERROR(log_) << "Message outside of protocol range received.  Passing to default handler, but not expecting much.";
		}

		receive_callback_->param(Event(Event::Done, packet));
		receive_action_ = receive_callback_->schedule();
		receive_callback_ = NULL;

		return;
	}
}
<commit_msg>Use new moveout(Buffer *).<commit_after>#include <common/endian.h>

#include <event/event_callback.h>

#include <http/http_protocol.h>

#include <io/pipe/pipe.h>
#include <io/pipe/pipe_producer.h>

#include <ssh/ssh_algorithm_negotiation.h>
#include <ssh/ssh_protocol.h>
#include <ssh/ssh_transport_pipe.h>

namespace {
	static uint8_t zero_padding[255];
}

SSH::TransportPipe::TransportPipe(void)
: PipeProducer("/ssh/transport/pipe"),
  state_(GetIdentificationString),
  block_size_(8),
  mac_length_(0),
  algorithm_negotiation_(NULL),
  receive_callback_(NULL),
  receive_action_(NULL)
{
	Buffer identification_string("SSH-2.0-WANProxy " + (std::string)log_ + "\r\n");
	produce(&identification_string);
}

SSH::TransportPipe::~TransportPipe()
{
	ASSERT(receive_callback_ == NULL);
	ASSERT(receive_action_ == NULL);
}

Action *
SSH::TransportPipe::receive(EventCallback *cb)
{
	ASSERT(receive_callback_ == NULL);
	ASSERT(receive_action_ == NULL);

	/*
	 * XXX
	 * This pattern is implemented about three different
	 * ways in the WANProxy codebase, and they are all kind
	 * of awful.  Need a better way to handle code that
	 * needs executed either on the request of the caller
	 * or when data comes in that satisfies a deferred
	 * callback to a caller.
	 */
	receive_callback_ = cb;
	receive_do();

	if (receive_callback_ != NULL)
		return (cancellation(this, &SSH::TransportPipe::receive_cancel));

	ASSERT(receive_action_ != NULL);
	Action *a = receive_action_;
	receive_action_ = NULL;
	return (a);
}

/*
 * Because this is primarily for WAN optimization we always use minimal
 * padding and zero padding.  Quick and dirty.  Perhaps revisit later,
 * although it makes send() asynchronous unless we add a blocking
 * RNG interface.
 */
void
SSH::TransportPipe::send(Buffer *payload)
{
	Buffer packet;
	uint8_t padding_len;
	uint32_t packet_len;

	ASSERT(state_ == GetPacket);

	packet_len = sizeof padding_len + payload->length();
	padding_len = 4 + (block_size_ - ((sizeof packet_len + packet_len + 4) % block_size_));
	packet_len += padding_len;

	packet_len = BigEndian::encode(packet_len);
	packet.append(&packet_len);
	packet.append(padding_len);
	payload->moveout(&packet);
	packet.append(zero_padding, padding_len);

	if (mac_length_ != 0)
		NOTREACHED();

	produce(&packet);
}

void
SSH::TransportPipe::consume(Buffer *in)
{
	/* XXX XXX XXX */
	if (in->empty()) {
		if (!input_buffer_.empty())
			DEBUG(log_) << "Received EOS with data outstanding.";
		produce_eos();
		return;
	}

	in->moveout(&input_buffer_);

	if (state_ == GetIdentificationString) {
		HTTPProtocol::ParseStatus status;

		while (!input_buffer_.empty()) {
			Buffer line;
			status = HTTPProtocol::ExtractLine(&line, &input_buffer_);
			switch (status) {
			case HTTPProtocol::ParseSuccess:
				break;
			case HTTPProtocol::ParseFailure:
				ERROR(log_) << "Invalid line while waiting for identification string.";
				produce_error();
				return;
			case HTTPProtocol::ParseIncomplete:
				/* Wait for more.  */
				return;
			}

			if (!line.prefix("SSH-"))
				continue; /* Next line.  */

			if (!line.prefix("SSH-2.0")) {
				ERROR(log_) << "Unsupported version.";
				produce_error();
				return;
			}

			state_ = GetPacket;
			/*
			 * XXX
			 * Should have a callback here?
			 */
			if (algorithm_negotiation_ != NULL) {
				Buffer packet;
				if (algorithm_negotiation_->output(&packet))
					send(&packet);
			}
			break;
		}
	}

	if (state_ == GetPacket && receive_callback_ != NULL)
		receive_do();
}

void
SSH::TransportPipe::receive_cancel(void)
{
	if (receive_action_ != NULL) {
		receive_action_->cancel();
		receive_action_ = NULL;
	}

	if (receive_callback_ != NULL) {
		delete receive_callback_;
		receive_callback_ = NULL;
	}
}

void
SSH::TransportPipe::receive_do(void)
{
	ASSERT(receive_action_ == NULL);
	ASSERT(receive_callback_ != NULL);

	if (state_ != GetPacket)
		return;

	while (!input_buffer_.empty()) {
		Buffer packet;
		Buffer mac;
		uint32_t packet_len;
		uint8_t padding_len;
		uint8_t msg;

		if (input_buffer_.length() <= sizeof packet_len) {
			DEBUG(log_) << "Waiting for packet length.";
			return;
		}

		input_buffer_.extract(&packet_len);
		packet_len = BigEndian::decode(packet_len);

		if (packet_len == 0) {
			ERROR(log_) << "Need to handle 0-length packet.";
			produce_error();
			return;
		}

		if (input_buffer_.length() < sizeof packet_len + packet_len + mac_length_) {
			DEBUG(log_) << "Need " << sizeof packet_len + packet_len + mac_length_ << "bytes; have " << input_buffer_.length() << ".";
			return;
		}

		input_buffer_.moveout(&packet, sizeof packet_len, packet_len);
		if (mac_length_ != 0)
			input_buffer_.moveout(&mac, 0, mac_length_);

		padding_len = packet.peek();
		packet.skip(sizeof padding_len);
		if (padding_len != 0) {
			if (packet.length() < padding_len) {
				ERROR(log_) << "Padding too large for packet.";
				produce_error();
				return;
			}
			packet.trim(padding_len);
		}

		if (packet.empty()) {
			ERROR(log_) << "Need to handle empty packet.";
			produce_error();
			return;
		}

		/*
		 * Pass by range to registered handlers for each range.
		 * Unhandled messages go to the receive_callback_, and
		 * the caller can register key exchange mechanisms,
		 * and handle (or discard) whatever they don't handle.
		 *
		 * NB: The caller could do all this, but it's assumed
		 *     that they usually have better things to do.  If
		 *     they register no handlers, they can certainly do
		 *     so by hand.
		 */
		msg = packet.peek();
		if (msg >= SSH::Message::TransportRangeBegin &&
		    msg <= SSH::Message::TransportRangeEnd) {
			DEBUG(log_) << "Using default handler for transport message.";
		} else if (msg >= SSH::Message::AlgorithmNegotiationRangeBegin &&
			   msg <= SSH::Message::AlgorithmNegotiationRangeEnd) {
			if (algorithm_negotiation_ != NULL) {
				if (algorithm_negotiation_->input(&packet))
					continue;
			}
			DEBUG(log_) << "Using default handler for algorithm negotiation message.";
		} else if (msg >= SSH::Message::KeyExchangeMethodRangeBegin &&
			   msg <= SSH::Message::KeyExchangeMethodRangeEnd) {
			DEBUG(log_) << "Using default handler for key exchange method message.";
		} else if (msg >= SSH::Message::UserAuthenticationGenericRangeBegin &&
			   msg <= SSH::Message::UserAuthenticationGenericRangeEnd) {
			DEBUG(log_) << "Using default handler for generic user authentication message.";
		} else if (msg >= SSH::Message::UserAuthenticationMethodRangeBegin &&
			   msg <= SSH::Message::UserAuthenticationMethodRangeEnd) {
			DEBUG(log_) << "Using default handler for user authentication method message.";
		} else if (msg >= SSH::Message::ConnectionProtocolGlobalRangeBegin &&
			   msg <= SSH::Message::ConnectionProtocolGlobalRangeEnd) {
			DEBUG(log_) << "Using default handler for generic connection protocol message.";
		} else if (msg >= SSH::Message::ConnectionChannelRangeBegin &&
			   msg <= SSH::Message::ConnectionChannelRangeEnd) {
			DEBUG(log_) << "Using default handler for connection channel message.";
		} else if (msg >= SSH::Message::ClientProtocolReservedRangeBegin &&
			   msg <= SSH::Message::ClientProtocolReservedRangeEnd) {
			DEBUG(log_) << "Using default handler for client protocol message.";
		} else if (msg >= SSH::Message::LocalExtensionRangeBegin) {
			/* Because msg is a uint8_t, it will always be <= SSH::Message::LocalExtensionRangeEnd.  */
			DEBUG(log_) << "Using default handler for local extension message.";
		} else {
			ASSERT(msg == 0);
			ERROR(log_) << "Message outside of protocol range received.  Passing to default handler, but not expecting much.";
		}

		receive_callback_->param(Event(Event::Done, packet));
		receive_action_ = receive_callback_->schedule();
		receive_callback_ = NULL;

		return;
	}
}
<|endoftext|>