<commit_before>/*
    Copyright (c) 2017 Maxim Teryokhin
    This code is licensed under MIT. See LICENSE file for more details.
*/

#include <iostream>
#include <algorithm>
#include <vector>
#include <iterator>
#include <set>
#include <map>

using namespace std;

template<class T>
void print_vector(vector<T>& v)
{
    for (T& x: v)
        cout << x << ' ';
    cout << endl;
}

class greater_than
{
private:
    int n;
public:
    greater_than(int n): n(n) {}
    bool operator()(int a)
    {
        return a > n;
    }
};

void Task_1(vector<int>& v)
{
    cout << "\nTask 1:\nEven-first sorted: ";
    sort(v.begin(), v.end(), [](int& a, int& b){
        if (a % 2 == b % 2)
            return a < b;
        else
            return (a % 2 == 0);
    });
    print_vector(v);
}

void Tasks_2_and_4(vector<int>& v)
{
    cout << "\nTasks 2 and 4:\nElements, greater than 5: ";
    ostream_iterator<int> out_it (cout," ");
    copy_if(v.begin(), v.end(), out_it, greater_than(5));
}

void Task_5()
{
    cout << "\n\nЗадание 5:";
    ostream_iterator<string> out_it (cout," ");
    set<string> river_bank{"пескарь", "мидия", "рак"};
    set<string> at_the_depth{"бычок", "окунь", "мидия"};

    cout << "\nВсе обитатели реки:\n";
    set_union(river_bank.begin(), river_bank.end(), at_the_depth.begin(), at_the_depth.end(), out_it);
    cout << "\nВодятся по всей реке:\n";
    set_intersection(river_bank.begin(), river_bank.end(), at_the_depth.begin(), at_the_depth.end(), out_it);
    cout << "\nВодятся у дерева, но не на глубине:\n";
    set_difference(river_bank.begin(), river_bank.end(), at_the_depth.begin(), at_the_depth.end(), out_it);

}

void Task_6()
{
    multimap<int, string> numbers = {
        { 1, "адзін" },
        { 1, "один" },
        { 1, "one" },
        { 2, "два" },
        { 2, "two" },
        { 3, "тры" },
        { 3, "три" },
        { 3, "three" },
        { 4, "чатыры" },
        { 4, "четыре" },
        { 4, "four" }
    };
    cout << "\n\nЗадание 6:\nВведите число N: ";
    int n;
    cin >> n;
    auto low = numbers.lower_bound(n);
    auto up =  numbers.upper_bound(n);
    if (low != numbers.end()){
        cout << "Варианты написания числа \"" << n << "\": ";
        for (auto it = low; it != up; it++)
            cout << it->second << ", ";
    }
    else
        cout << "Вариантов написания числа \"" << n << "\" нет";
    cout << endl;

}

int main()
{
    vector<int> v{ 1, 8, 7, 4, 3, 6, 2, 5 };
    cout << "Initial vector:\n";
    print_vector(v);
    Task_1(v);
    Tasks_2_and_4(v);
    Task_5();
    Task_6();

    return 0;
}
<commit_msg>Lesson 1 complete solution<commit_after>/*
    Copyright (c) 2017 Maxim Teryokhin
    This code is licensed under MIT. See LICENSE file for more details.
*/

#include <iostream>
#include <algorithm>
#include <vector>
#include <iterator>
#include <set>
#include <map>
#include <functional>

using namespace std;

template<class T>
void print_vector(vector<T>& v)
{
    for (T& x: v)
        cout << x << ' ';
    cout << endl;
}

class greater_than
{
private:
    int n;
public:
    greater_than(int n): n(n) {}
    bool operator()(int a)
    {
        return a > n;
    }
};

void Task_1(vector<int>& v)
{
    cout << "\nTask 1:\nEven-first sorted: ";
    sort(v.begin(), v.end(), [](int& a, int& b){
        if (a % 2 == b % 2)
            return a < b;
        else
            return (a % 2 == 0);
    });
    print_vector(v);
}

void Tasks_2_and_4(vector<int>& v)
{
    cout << "\nTasks 2 and 4:\nElements, greater than 5: ";
    ostream_iterator<int> out_it (cout," ");
    copy_if(v.begin(), v.end(), out_it, greater_than(5));
}

void Task_3(vector<int>& v)
{
    cout << "\n\nTask 3:\nEven-first sorted: ";
    ostream_iterator<int> out_it (cout," ");
    auto greater_binded = bind(greater<int>(), placeholders::_1, 5);
    copy_if(v.begin(), v.end(), out_it, greater_binded);
}

void Task_5()
{
    cout << "\n\nЗадание 5:";
    ostream_iterator<string> out_it (cout,", ");
    set<string> river_bank{"пескарь", "мидия", "рак"};
    set<string> at_the_depth{"бычок", "окунь", "мидия"};

    cout << "\nВсе обитатели реки:\n";
    set_union(river_bank.begin(), river_bank.end(), at_the_depth.begin(), at_the_depth.end(), out_it);
    cout << "\nВодятся по всей реке:\n";
    set_intersection(river_bank.begin(), river_bank.end(), at_the_depth.begin(), at_the_depth.end(), out_it);
    cout << "\nВодятся у дерева, но не на глубине:\n";
    set_difference(river_bank.begin(), river_bank.end(), at_the_depth.begin(), at_the_depth.end(), out_it);

}

void Task_6()
{
    multimap<int, string> numbers = {
        { 1, "адзін" },
        { 1, "один" },
        { 1, "one" },
        { 2, "два" },
        { 2, "two" },
        { 3, "тры" },
        { 3, "три" },
        { 3, "three" },
        { 4, "чатыры" },
        { 4, "четыре" },
        { 4, "four" }
    };
    cout << "\n\nЗадание 6:\nВведите число N: ";
    int n;
    cin >> n;
    auto low = numbers.lower_bound(n);
    auto up =  numbers.upper_bound(n);
    if (low != numbers.end()){
        cout << "Варианты написания числа \"" << n << "\": ";
        for (auto it = low; it != up; it++)
            cout << it->second << ", ";
    }
    else
        cout << "Вариантов написания числа \"" << n << "\" нет";
    cout << endl;

}

int main()
{
    vector<int> v{ 1, 8, 7, 4, 3, 6, 2, 5 };
    cout << "Initial vector:\n";
    print_vector(v);
    Task_1(v);
    Tasks_2_and_4(v);
    Task_3(v);
    Task_5();
    Task_6();

    return 0;
}
<|endoftext|>


<commit_before>//
// Status bar implementation
//
// Copyright (c) 2001-2003 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//

// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

#include "vtdata/ElevationGrid.h"
#include "vtdata/vtLog.h"

#include "StatusBar.h"
#include "BuilderView.h"
#include "Helper.h"

MyStatusBar::MyStatusBar(wxWindow *parent) : wxStatusBar(parent, -1)
{
	VTLOG(" Creating Status Bar.\n");
	static const int widths[Field_Max] = { -1, 38, 55, 65, 52, 170, 76 };

	SetFieldsCount(Field_Max);
	SetStatusWidths(Field_Max, widths);

	m_bShowMinutes = false;
	m_ShowVertUnits = LU_METERS;
}

MyStatusBar::~MyStatusBar()
{
}

void MyStatusBar::OnSize(wxSizeEvent& event)
{
	// could do resizing of status bar elements here if needed
//    m_checkbox->SetSize(rect.x + 2, rect.y + 2, rect.width - 4, rect.height - 4);
//    event.Skip();
}

wxString MyStatusBar::FormatCoord(bool bGeo, double coord)
{
	wxString str;
	if (bGeo)
	{
		str = ::FormatCoord(bGeo, coord, m_bShowMinutes);
	}
	else	// something meters-based
	{
		str.Printf(_T("%.0f"), coord);
	}
	return str;
}

void MyStatusBar::SetTexts(MainFrame *frame)
{
//	VTLOG(" StatusBar SetTexts: ");

	vtProjection &proj = frame->GetAtProjection();
	bool bGeo = (proj.IsGeographic() != 0);

	wxString2 str = proj.GetProjectionNameShort();
	SetStatusText(str, Field_Coord);

	int zone = proj.GetUTMZone();
	if (zone != 0)
		str.Printf(_T("Zone %d"), zone);
	else
		str = _T("");
	SetStatusText(str, Field_Zone);

	str = DatumToStringShort(proj.GetDatum());
	SetStatusText(str, Field_Datum);

	LinearUnits lu = proj.GetUnits();
	str = GetLinearUnitName(lu);
	SetStatusText(str, Field_HUnits);

	DPoint2 p;
	BuilderView *pView = frame->GetView();
	if (pView)
	{
		pView->GetMouseLocation(p);
		str = _T("Mouse: ");
		str += FormatCoord(bGeo, p.x);
		str += _T(", ");
		str += FormatCoord(bGeo, p.y);

		SetStatusText(str, Field_Mouse);
//		VTLOG(" '%s' ", (const char *)str);

		float height = frame->GetHeightFromTerrain(p);
		if (height == INVALID_ELEVATION)
			str = _T("");
		else
		{
			if (m_ShowVertUnits == LU_METERS)
				str.Printf(_T("%.2f m"), height);
			else
				str.Printf(_T("%.2f ft"), height / GetMetersPerUnit(m_ShowVertUnits));
		}
		SetStatusText(str, Field_Height);
	}
	else
	{
		SetStatusText(_T("Mouse"), Field_Mouse);
		SetStatusText(_T(""), Field_Height);
	}
//	VTLOG(" Done.\n");
}

//
// Not sure why the event table must be down here, but it does - for WinZip
//
BEGIN_EVENT_TABLE(MyStatusBar, wxStatusBar)
EVT_SIZE(MyStatusBar::OnSize)
END_EVENT_TABLE()

<commit_msg>made 'units' area a little wider on status bar<commit_after>//
// Status bar implementation
//
// Copyright (c) 2001-2003 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//

// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

#include "vtdata/ElevationGrid.h"
#include "vtdata/vtLog.h"

#include "StatusBar.h"
#include "BuilderView.h"
#include "Helper.h"

MyStatusBar::MyStatusBar(wxWindow *parent) : wxStatusBar(parent, -1)
{
	VTLOG(" Creating Status Bar.\n");
	static const int widths[Field_Max] =
	{
		-1,		// main message area
		38,		// Geo or short projection identifier
		55,		// Zone
		65,		// Datum
		58,		// Units
		170,	// Coordinates of cursor
		76		// Elevation under cursor
	};

	SetFieldsCount(Field_Max);
	SetStatusWidths(Field_Max, widths);

	m_bShowMinutes = false;
	m_ShowVertUnits = LU_METERS;
}

MyStatusBar::~MyStatusBar()
{
}

void MyStatusBar::OnSize(wxSizeEvent& event)
{
	// could do resizing of status bar elements here if needed
//    m_checkbox->SetSize(rect.x + 2, rect.y + 2, rect.width - 4, rect.height - 4);
//    event.Skip();
}

wxString MyStatusBar::FormatCoord(bool bGeo, double coord)
{
	wxString str;
	if (bGeo)
	{
		str = ::FormatCoord(bGeo, coord, m_bShowMinutes);
	}
	else	// something meters-based
	{
		str.Printf(_T("%.0f"), coord);
	}
	return str;
}

void MyStatusBar::SetTexts(MainFrame *frame)
{
//	VTLOG(" StatusBar SetTexts: ");

	vtProjection &proj = frame->GetAtProjection();
	bool bGeo = (proj.IsGeographic() != 0);

	wxString2 str = proj.GetProjectionNameShort();
	SetStatusText(str, Field_Coord);

	int zone = proj.GetUTMZone();
	if (zone != 0)
		str.Printf(_T("Zone %d"), zone);
	else
		str = _T("");
	SetStatusText(str, Field_Zone);

	str = DatumToStringShort(proj.GetDatum());
	SetStatusText(str, Field_Datum);

	LinearUnits lu = proj.GetUnits();
	str = GetLinearUnitName(lu);
	SetStatusText(str, Field_HUnits);

	DPoint2 p;
	BuilderView *pView = frame->GetView();
	if (pView)
	{
		pView->GetMouseLocation(p);
		str = _T("Mouse: ");
		str += FormatCoord(bGeo, p.x);
		str += _T(", ");
		str += FormatCoord(bGeo, p.y);

		SetStatusText(str, Field_Mouse);
//		VTLOG(" '%s' ", (const char *)str);

		float height = frame->GetHeightFromTerrain(p);
		if (height == INVALID_ELEVATION)
			str = _T("");
		else
		{
			if (m_ShowVertUnits == LU_METERS)
				str.Printf(_T("%.2f m"), height);
			else
				str.Printf(_T("%.2f ft"), height / GetMetersPerUnit(m_ShowVertUnits));
		}
		SetStatusText(str, Field_Height);
	}
	else
	{
		SetStatusText(_T("Mouse"), Field_Mouse);
		SetStatusText(_T(""), Field_Height);
	}
//	VTLOG(" Done.\n");
}

//
// Not sure why the event table must be down here, but it does - for WinZip
//
BEGIN_EVENT_TABLE(MyStatusBar, wxStatusBar)
EVT_SIZE(MyStatusBar::OnSize)
END_EVENT_TABLE()

<|endoftext|>


<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2006 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "AsyncVideoDecoder.h"
#include "EOFVideoMsg.h"
#include "InfoVideoMsg.h"
#include "ErrorVideoMsg.h"

#include "../base/ObjectCounter.h"

#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>

#include <iostream>

using namespace boost;
using namespace std;

namespace avg {

AsyncVideoDecoder::AsyncVideoDecoder(VideoDecoderPtr pSyncDecoder)
    : m_pSyncDecoder(pSyncDecoder),
      m_pDecoderThread(0),
      m_Size(0,0),
      m_bEOF(false),
      m_bSeekPending(false),
      m_LastFrameTime(-1000)
{
    ObjectCounter::get()->incRef(&typeid(*this));
}

AsyncVideoDecoder::~AsyncVideoDecoder()
{
    if (m_pDecoderThread) {
        close();
    }
    ObjectCounter::get()->decRef(&typeid(*this));
}

void AsyncVideoDecoder::open(const std::string& sFilename, YCbCrMode ycbcrMode,
        bool bThreadedDemuxer)
{
    m_bEOF = false;
    m_bSeekPending = false;
    m_sFilename = sFilename;
    m_pCmdQ = VideoDecoderThread::CmdQueuePtr(new VideoDecoderThread::CmdQueue);
    m_pMsgQ = VideoMsgQueuePtr(new VideoMsgQueue(8));
    m_pDecoderThread = new boost::thread(
            VideoDecoderThread(*m_pMsgQ, *m_pCmdQ, m_pSyncDecoder, sFilename,
                    ycbcrMode, bThreadedDemuxer));
    getInfoMsg();
    m_TimePerFrame = (long long)(1000.0/getFPS());
    m_LastFrameTime = -1000;
}

void AsyncVideoDecoder::close()
{
    if (m_pDecoderThread) {
        m_pCmdQ->push(Command<VideoDecoderThread>(boost::bind(
                &VideoDecoderThread::stop, _1)));
        getNextBmps(false); // If the Queue is full, this breaks the lock in the thread.
        m_pDecoderThread->join();
        delete m_pDecoderThread;
        m_pDecoderThread = 0;
    }
}

void AsyncVideoDecoder::seek(int DestFrame)
{
    waitForSeekDone();
    m_bEOF = false;
    m_pCmdQ->push(Command<VideoDecoderThread>(boost::bind(
                &VideoDecoderThread::seek, _1, DestFrame)));
    m_bSeekPending = true;
}

IntPoint AsyncVideoDecoder::getSize()
{
    return m_Size;
}

int AsyncVideoDecoder::getNumFrames()
{
    assert(m_pDecoderThread);
    return m_NumFrames;
}

double AsyncVideoDecoder::getFPS()
{
    assert(m_pDecoderThread);
    return m_FPS;
}

PixelFormat AsyncVideoDecoder::getPixelFormat()
{
    assert(m_pDecoderThread);
    return m_PF;
}

bool AsyncVideoDecoder::renderToBmp(BitmapPtr pBmp, long long TimeWanted)
{
    FrameVideoMsgPtr pFrameMsg = getBmpsForTime(TimeWanted);
    if (pFrameMsg) {
        *pBmp = *(pFrameMsg->getBitmap(0));
        return true;
    } else {
        return false;
    }
}

bool AsyncVideoDecoder::renderToYCbCr420p(BitmapPtr pBmpY, BitmapPtr pBmpCb,
       BitmapPtr pBmpCr, long long TimeWanted)
{
    FrameVideoMsgPtr pFrameMsg = getBmpsForTime(TimeWanted);
    if (pFrameMsg) {
        pBmpY->copyPixels(*(pFrameMsg->getBitmap(0)));
        pBmpCb->copyPixels(*(pFrameMsg->getBitmap(1)));
        pBmpCr->copyPixels(*(pFrameMsg->getBitmap(2)));
        return true;
    } else {
        return false;
    }
}

long long AsyncVideoDecoder::getCurFrameTime()
{
    return m_LastFrameTime;
}

bool AsyncVideoDecoder::isEOF()
{
    return m_bEOF;
}

void AsyncVideoDecoder::getInfoMsg()
{
    VideoMsgPtr pMsg = m_pMsgQ->pop(true);
    InfoVideoMsgPtr pInfoMsg = dynamic_pointer_cast<InfoVideoMsg>(pMsg);
    ErrorVideoMsgPtr pErrorMsg(dynamic_pointer_cast<ErrorVideoMsg>(pMsg));
    if (pErrorMsg) {
        close();
        throw(pErrorMsg->getException());
    } else {
        assert(pInfoMsg); // The first message sent by the decoder thread after open
        // should be an info or error message.
        m_Size = pInfoMsg->getSize();
        m_NumFrames = pInfoMsg->getNumFrames();
        m_FPS = pInfoMsg->getFPS();
        m_PF = pInfoMsg->getPF();
    }
}

FrameVideoMsgPtr AsyncVideoDecoder::getBmpsForTime(long long TimeWanted)
{
    // XXX: This code is sort-of duplicated in FFMpegDecoder::readFrameForTime()
    long long FrameTime = -1000;
    FrameVideoMsgPtr pFrameMsg;
//    cerr << "getBmpsForTime " << TimeWanted << ", LastFrameTime= " << m_LastFrameTime << endl;
    if (TimeWanted == -1) {
        pFrameMsg = getNextBmps(true);
    } else {
        if (TimeWanted-m_LastFrameTime < 0.5*m_TimePerFrame) {
//            cerr << "   LastFrameTime = " << m_LastFrameTime << ", display again." <<  endl;
            // The last frame is still current. Display it again.
            return FrameVideoMsgPtr();
        } else {
            while (FrameTime-TimeWanted < -0.5*m_TimePerFrame && !m_bEOF) {
                pFrameMsg = getNextBmps(false);
                if (pFrameMsg) {
                    FrameTime = pFrameMsg->getFrameTime();
//                    cerr << "   readFrame returned time " << FrameTime << "." <<  endl;
                } else {
//                    cerr << "   no frame available." <<  endl;
                    return FrameVideoMsgPtr();
                }
            }
//            cerr << "  frame ok." << endl;
        }
    }
    m_LastFrameTime = pFrameMsg->getFrameTime();
    return pFrameMsg;
}

FrameVideoMsgPtr AsyncVideoDecoder::getNextBmps(bool bWait)
{
    try {
        waitForSeekDone();
        VideoMsgPtr pMsg = m_pMsgQ->pop(bWait);
        FrameVideoMsgPtr pFrameMsg = dynamic_pointer_cast<FrameVideoMsg>(pMsg);
        while (!pFrameMsg) {
            EOFVideoMsgPtr pEOFMsg(dynamic_pointer_cast<EOFVideoMsg>(pMsg));
            ErrorVideoMsgPtr pErrorMsg(dynamic_pointer_cast<ErrorVideoMsg>(pMsg));
            if (pEOFMsg) {
                m_bEOF = true;
                return FrameVideoMsgPtr();
            } else if(pErrorMsg) {
                m_bEOF = true;
                close();
                return FrameVideoMsgPtr();
            } else {
                // Unhandled message type.
                assert(false);
            }
            VideoMsgPtr pMsg = m_pMsgQ->pop(bWait);
            FrameVideoMsgPtr pFrameMsg = dynamic_pointer_cast<FrameVideoMsg>(pMsg);
        }
        return pFrameMsg;
    } catch (Exception& e) {
        return FrameVideoMsgPtr();
    }
}

void AsyncVideoDecoder::waitForSeekDone()
{
    if (m_bSeekPending) {
        m_bSeekPending = false;
        VideoMsgPtr pMsg;
        bool bDone = false;
        do {
            VideoMsgPtr pMsg = m_pMsgQ->pop(true);
            FrameVideoMsgPtr pFrameMsg = dynamic_pointer_cast<FrameVideoMsg>(pMsg);
            if (pFrameMsg) {
                bDone = pFrameMsg->isSeekDone();
            }
        } while (!bDone);
    }
}

}
<commit_msg>Fixed loop bug for async videos.<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2006 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "AsyncVideoDecoder.h"
#include "EOFVideoMsg.h"
#include "InfoVideoMsg.h"
#include "ErrorVideoMsg.h"

#include "../base/ObjectCounter.h"

#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>

#include <iostream>

using namespace boost;
using namespace std;

namespace avg {

AsyncVideoDecoder::AsyncVideoDecoder(VideoDecoderPtr pSyncDecoder)
    : m_pSyncDecoder(pSyncDecoder),
      m_pDecoderThread(0),
      m_Size(0,0),
      m_bEOF(false),
      m_bSeekPending(false),
      m_LastFrameTime(-1000)
{
    ObjectCounter::get()->incRef(&typeid(*this));
}

AsyncVideoDecoder::~AsyncVideoDecoder()
{
    if (m_pDecoderThread) {
        close();
    }
    ObjectCounter::get()->decRef(&typeid(*this));
}

void AsyncVideoDecoder::open(const std::string& sFilename, YCbCrMode ycbcrMode,
        bool bThreadedDemuxer)
{
    m_bEOF = false;
    m_bSeekPending = false;
    m_sFilename = sFilename;
    m_pCmdQ = VideoDecoderThread::CmdQueuePtr(new VideoDecoderThread::CmdQueue);
    m_pMsgQ = VideoMsgQueuePtr(new VideoMsgQueue(8));
    m_pDecoderThread = new boost::thread(
            VideoDecoderThread(*m_pMsgQ, *m_pCmdQ, m_pSyncDecoder, sFilename,
                    ycbcrMode, bThreadedDemuxer));
    getInfoMsg();
    m_TimePerFrame = (long long)(1000.0/getFPS());
    m_LastFrameTime = -1000;
}

void AsyncVideoDecoder::close()
{
    if (m_pDecoderThread) {
        m_pCmdQ->push(Command<VideoDecoderThread>(boost::bind(
                &VideoDecoderThread::stop, _1)));
        getNextBmps(false); // If the Queue is full, this breaks the lock in the thread.
        m_pDecoderThread->join();
        delete m_pDecoderThread;
        m_pDecoderThread = 0;
    }
}

void AsyncVideoDecoder::seek(int DestFrame)
{
    waitForSeekDone();
    m_bEOF = false;
    m_pCmdQ->push(Command<VideoDecoderThread>(boost::bind(
                &VideoDecoderThread::seek, _1, DestFrame)));
    m_bSeekPending = true;
}

IntPoint AsyncVideoDecoder::getSize()
{
    return m_Size;
}

int AsyncVideoDecoder::getNumFrames()
{
    assert(m_pDecoderThread);
    return m_NumFrames;
}

double AsyncVideoDecoder::getFPS()
{
    assert(m_pDecoderThread);
    return m_FPS;
}

PixelFormat AsyncVideoDecoder::getPixelFormat()
{
    assert(m_pDecoderThread);
    return m_PF;
}

bool AsyncVideoDecoder::renderToBmp(BitmapPtr pBmp, long long TimeWanted)
{
    FrameVideoMsgPtr pFrameMsg = getBmpsForTime(TimeWanted);
    if (pFrameMsg) {
        *pBmp = *(pFrameMsg->getBitmap(0));
        return true;
    } else {
        return false;
    }
}

bool AsyncVideoDecoder::renderToYCbCr420p(BitmapPtr pBmpY, BitmapPtr pBmpCb,
       BitmapPtr pBmpCr, long long TimeWanted)
{
    FrameVideoMsgPtr pFrameMsg = getBmpsForTime(TimeWanted);
    if (pFrameMsg) {
        pBmpY->copyPixels(*(pFrameMsg->getBitmap(0)));
        pBmpCb->copyPixels(*(pFrameMsg->getBitmap(1)));
        pBmpCr->copyPixels(*(pFrameMsg->getBitmap(2)));
        return true;
    } else {
        return false;
    }
}

long long AsyncVideoDecoder::getCurFrameTime()
{
    return m_LastFrameTime;
}

bool AsyncVideoDecoder::isEOF()
{
    return m_bEOF;
}

void AsyncVideoDecoder::getInfoMsg()
{
    VideoMsgPtr pMsg = m_pMsgQ->pop(true);
    InfoVideoMsgPtr pInfoMsg = dynamic_pointer_cast<InfoVideoMsg>(pMsg);
    ErrorVideoMsgPtr pErrorMsg(dynamic_pointer_cast<ErrorVideoMsg>(pMsg));
    if (pErrorMsg) {
        close();
        throw(pErrorMsg->getException());
    } else {
        assert(pInfoMsg); // The first message sent by the decoder thread after open
        // should be an info or error message.
        m_Size = pInfoMsg->getSize();
        m_NumFrames = pInfoMsg->getNumFrames();
        m_FPS = pInfoMsg->getFPS();
        m_PF = pInfoMsg->getPF();
    }
}

FrameVideoMsgPtr AsyncVideoDecoder::getBmpsForTime(long long TimeWanted)
{
    // XXX: This code is sort-of duplicated in FFMpegDecoder::readFrameForTime()
    long long FrameTime = -1000;
    FrameVideoMsgPtr pFrameMsg;
//    cerr << "getBmpsForTime " << TimeWanted << ", LastFrameTime= " << m_LastFrameTime << endl;
    if (TimeWanted == -1) {
        pFrameMsg = getNextBmps(true);
    } else {
        if (TimeWanted-m_LastFrameTime < 0.5*m_TimePerFrame) {
//            cerr << "   LastFrameTime = " << m_LastFrameTime << ", display again." <<  endl;
            // The last frame is still current. Display it again.
            return FrameVideoMsgPtr();
        } else {
            while (FrameTime-TimeWanted < -0.5*m_TimePerFrame && !m_bEOF) {
                pFrameMsg = getNextBmps(false);
                if (pFrameMsg) {
                    FrameTime = pFrameMsg->getFrameTime();
//                    cerr << "   readFrame returned time " << FrameTime << "." <<  endl;
                } else {
//                    cerr << "   no frame available." <<  endl;
                    return FrameVideoMsgPtr();
                }
            }
//            cerr << "  frame ok." << endl;
        }
    }
    if (pFrameMsg) {
        m_LastFrameTime = pFrameMsg->getFrameTime();
    }
    return pFrameMsg;
}

FrameVideoMsgPtr AsyncVideoDecoder::getNextBmps(bool bWait)
{
    try {
        waitForSeekDone();
        VideoMsgPtr pMsg = m_pMsgQ->pop(bWait);
        FrameVideoMsgPtr pFrameMsg = dynamic_pointer_cast<FrameVideoMsg>(pMsg);
        while (!pFrameMsg) {
            EOFVideoMsgPtr pEOFMsg(dynamic_pointer_cast<EOFVideoMsg>(pMsg));
            ErrorVideoMsgPtr pErrorMsg(dynamic_pointer_cast<ErrorVideoMsg>(pMsg));
            if (pEOFMsg) {
                m_bEOF = true;
                return FrameVideoMsgPtr();
            } else if(pErrorMsg) {
                m_bEOF = true;
                close();
                return FrameVideoMsgPtr();
            } else {
                // Unhandled message type.
                assert(false);
            }
            VideoMsgPtr pMsg = m_pMsgQ->pop(bWait);
            FrameVideoMsgPtr pFrameMsg = dynamic_pointer_cast<FrameVideoMsg>(pMsg);
        }
        return pFrameMsg;
    } catch (Exception& e) {
        return FrameVideoMsgPtr();
    }
}

void AsyncVideoDecoder::waitForSeekDone()
{
    if (m_bSeekPending) {
        m_bSeekPending = false;
        VideoMsgPtr pMsg;
        bool bDone = false;
        do {
            VideoMsgPtr pMsg = m_pMsgQ->pop(true);
            FrameVideoMsgPtr pFrameMsg = dynamic_pointer_cast<FrameVideoMsg>(pMsg);
            if (pFrameMsg) {
                bDone = pFrameMsg->isSeekDone();
            }
        } while (!bDone);
    }
}

}
<|endoftext|>


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

#include <utility>

namespace generic
{

namespace
{

template <typename F, int I, typename L, typename R, typename ...A>
inline F cify(L&& l, R (*)(A...))
{
  static L const l_(::std::forward<L>(l));

  struct S
  {
    static R f(A... args) noexcept(noexcept(l_(::std::forward<A>(args)...)))
    {
      return l_(::std::forward<A>(args)...);
    }
  };

  return &S::f;
}

}

template <typename F, int I = 0, typename L>
inline F cify(L&& l)
{
  return cify<F, I>(::std::forward<L>(l), F());
}

}

#endif // GENERIC_CIFY_HPP
<commit_msg>some fixes<commit_after>#ifndef GENERIC_CIFY_HPP
# define GENERIC_CIFY_HPP
# pragma once

#include <utility>

namespace generic
{

namespace
{

template <typename F, int I, typename L, typename R, typename ...A>
inline F cify(L&& l, R (*)(A...))
{
  static L const l(::std::forward<L>(l));

  struct S
  {
    static R f(A... args) noexcept(noexcept(l(::std::forward<A>(args)...)))
    {
      return l(::std::forward<A>(args)...);
    }
  };

  return S::f;
}

}

template <typename F, int I = 0, typename L>
inline F cify(L&& l)
{
  return cify<F, I>(::std::forward<L>(l), F());
}

}

#endif // GENERIC_CIFY_HPP
<|endoftext|>


<commit_before>#pragma once

#include "depthai-shared/utility/Serialization.hpp"
#include "tl/optional.hpp"

// tl::optional serialization for nlohmann json
// partial specialization (full specialization works too)
namespace nlohmann {
template <typename T>
struct adl_serializer<tl::optional<T>> {
    static void to_json(json& j, const tl::optional<T>& opt) {  // NOLINT this is a specialization, naming conventions don't apply
        if(opt == tl::nullopt) {
            j = nullptr;
        } else {
            j = *opt;  // this will call adl_serializer<T>::to_json which will
                       // find the free function to_json in T's namespace!
        }
    }

    static void from_json(const json& j, tl::optional<T>& opt) {  // NOLINT this is a specialization, naming conventions don't apply
        if(j.is_null()) {
            opt = tl::nullopt;
        } else {
            opt = j.get<T>();  // same as above, but with
                               // adl_serializer<T>::from_json
        }
    }
};
}  // namespace nlohmann

// tl::optional serialization for libnop
namespace nop {

//
// Optional<T> encoding formats:
//
// Empty Optional<T>:
//
// +-----+
// | NIL |
// +-----+
//
// Non-empty Optional<T>
//
// +---//----+
// | ELEMENT |
// +---//----+
//
// Element must be a valid encoding of type T.
//

template <typename T>
struct Encoding<tl::optional<T>> : EncodingIO<tl::optional<T>> {
    using Type = tl::optional<T>;

    static constexpr EncodingByte Prefix(const Type& value) {
        return value ? Encoding<T>::Prefix(*value) : EncodingByte::Nil;
    }

    static constexpr std::size_t Size(const Type& value) {
        return value ? Encoding<T>::Size(*value) : BaseEncodingSize(EncodingByte::Nil);
    }

    static constexpr bool Match(EncodingByte prefix) {
        return prefix == EncodingByte::Nil || Encoding<T>::Match(prefix);
    }

    template <typename Writer>
    static constexpr Status<void> WritePayload(EncodingByte prefix, const Type& value, Writer* writer) {
        if(value)
            return Encoding<T>::WritePayload(prefix, *value, writer);
        else
            return {};
    }

    template <typename Reader>
    static constexpr Status<void> ReadPayload(EncodingByte prefix, Type* value, Reader* reader) {
        if(prefix == EncodingByte::Nil) {
            value->reset();
        } else {
            T temp;
            auto status = Encoding<T>::ReadPayload(prefix, &temp, reader);
            if(!status) return status;

            *value = std::move(temp);
        }

        return {};
    }
};

}  // namespace nop<commit_msg>Updated optional<commit_after>#pragma once

#include "depthai-shared/utility/Serialization.hpp"
#include "tl/optional.hpp"

// tl::optional serialization for nlohmann json
// partial specialization (full specialization works too)
namespace nlohmann {
template <typename T>
struct adl_serializer<tl::optional<T>> {
    static void to_json(json& j, const tl::optional<T>& opt) {  // NOLINT this is a specialization, naming conventions don't apply
        if(opt == tl::nullopt) {
            j = nullptr;
        } else {
            j = *opt;  // this will call adl_serializer<T>::to_json which will
                       // find the free function to_json in T's namespace!
        }
    }

    static void from_json(const json& j, tl::optional<T>& opt) {  // NOLINT this is a specialization, naming conventions don't apply
        if(j.is_null()) {
            opt = tl::nullopt;
        } else {
            opt = j.get<T>();  // same as above, but with
                               // adl_serializer<T>::from_json
        }
    }
};
}  // namespace nlohmann

// tl::optional serialization for libnop
namespace nop {

//
// Optional<T> encoding formats:
//
// Empty Optional<T>:
//
// +-----+
// | NIL |
// +-----+
//
// Non-empty Optional<T>
//
// +---//----+
// | ELEMENT |
// +---//----+
//
// Element must be a valid encoding of type T.
//

template <typename T>
struct Encoding<tl::optional<T>> : EncodingIO<tl::optional<T>> {
    using Type = tl::optional<T>;

    static constexpr EncodingByte Prefix(const Type& value) {
        return value ? Encoding<T>::Prefix(*value) : EncodingByte::Nil;
    }

    static constexpr std::size_t Size(const Type& value) {
        return value ? Encoding<T>::Size(*value) : BaseEncodingSize(EncodingByte::Nil);
    }

    static constexpr bool Match(EncodingByte prefix) {
        return prefix == EncodingByte::Nil || Encoding<T>::Match(prefix);
    }

    template <typename Writer>
    static constexpr Status<void> WritePayload(EncodingByte prefix, const Type& value, Writer* writer) {
        if(value) {
            return Encoding<T>::WritePayload(prefix, *value, writer);
        } else {
            return {};
        }
    }

    template <typename Reader>
    static constexpr Status<void> ReadPayload(EncodingByte prefix, Type* value, Reader* reader) {
        if(prefix == EncodingByte::Nil) {
            value->reset();
        } else {
            T temp;
            auto status = Encoding<T>::ReadPayload(prefix, &temp, reader);
            if(!status) return status;

            *value = std::move(temp);
        }

        return {};
    }
};

}  // namespace nop<|endoftext|>


<commit_before>//===- RegisterInfoEmitter.cpp - Generate a Register File Desc. -*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tablegen backend is responsible for emitting a description of a target
// register file for a code generator.  It uses instances of the Register,
// RegisterAliases, and RegisterClass classes to gather this information.
//
//===----------------------------------------------------------------------===//

#include "RegisterInfoEmitter.h"
#include "CodeGenTarget.h"
#include "CodeGenRegisters.h"
#include "Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/STLExtras.h"
#include <set>
using namespace llvm;

// runEnums - Print out enum values for all of the registers.
void RegisterInfoEmitter::runEnums(std::ostream &OS) {
  CodeGenTarget Target;
  const std::vector<CodeGenRegister> &Registers = Target.getRegisters();

  std::string Namespace = Registers[0].TheDef->getValueAsString("Namespace");

  EmitSourceFileHeader("Target Register Enum Values", OS);
  OS << "namespace llvm {\n\n";

  if (!Namespace.empty())
    OS << "namespace " << Namespace << " {\n";
  OS << "  enum {\n    NoRegister,\n";

  for (unsigned i = 0, e = Registers.size(); i != e; ++i)
    OS << "    " << Registers[i].getName() << ", \t// " << i+1 << "\n";

  OS << "  };\n";
  if (!Namespace.empty())
    OS << "}\n";
  OS << "} // End llvm namespace \n";
}

void RegisterInfoEmitter::runHeader(std::ostream &OS) {
  EmitSourceFileHeader("Register Information Header Fragment", OS);
  CodeGenTarget Target;
  const std::string &TargetName = Target.getName();
  std::string ClassName = TargetName + "GenRegisterInfo";

  OS << "#include \"llvm/Target/MRegisterInfo.h\"\n\n";

  OS << "namespace llvm {\n\n";

  OS << "struct " << ClassName << " : public MRegisterInfo {\n"
     << "  " << ClassName
     << "(int CallFrameSetupOpcode = -1, int CallFrameDestroyOpcode = -1);\n"
     << "  const unsigned* getCalleeSaveRegs() const;\n"
     << "};\n\n";

  std::vector<Record*> RegisterClasses =
    Records.getAllDerivedDefinitions("RegisterClass");

  OS << "namespace " << TargetName << " { // Register classes\n";
  for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
    const std::string &Name = RegisterClasses[i]->getName();
    if (Name.size() < 9 || Name[9] != '.')       // Ignore anonymous classes
      OS << "  extern TargetRegisterClass *" << Name << "RegisterClass;\n";
  }
  OS << "} // end of namespace " << TargetName << "\n\n";
  OS << "} // End llvm namespace \n";
}

// RegisterInfoEmitter::run - Main register file description emitter.
//
void RegisterInfoEmitter::run(std::ostream &OS) {
  CodeGenTarget Target;
  EmitSourceFileHeader("Register Information Source Fragment", OS);

  OS << "namespace llvm {\n\n";

  // Start out by emitting each of the register classes... to do this, we build
  // a set of registers which belong to a register class, this is to ensure that
  // each register is only in a single register class.
  //
  const std::vector<CodeGenRegisterClass> &RegisterClasses =
    Target.getRegisterClasses();

  std::set<Record*> RegistersFound;
  std::vector<std::string> RegClassNames;

  // Loop over all of the register classes... emitting each one.
  OS << "namespace {     // Register classes...\n";

  // RegClassesBelongedTo - Keep track of which register classes each reg
  // belongs to.
  std::multimap<Record*, const CodeGenRegisterClass*> RegClassesBelongedTo;

  for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
    const CodeGenRegisterClass &RC = RegisterClasses[rc];

    std::string Name = RC.getName();
    if (Name.size() > 9 && Name[9] == '.') {
      static unsigned AnonCounter = 0;
      Name = "AnonRegClass_"+utostr(AnonCounter++);
    }

    RegClassNames.push_back(Name);

    // Emit the register list now...
    OS << "  // " << Name << " Register Class...\n  const unsigned " << Name
       << "[] = {\n    ";
    for (unsigned i = 0, e = RC.Elements.size(); i != e; ++i) {
      Record *Reg = RC.Elements[i];
      if (RegistersFound.count(Reg))
        throw "Register '" + Reg->getName() +
              "' included in multiple register classes!";
      RegistersFound.insert(Reg);
      OS << getQualifiedName(Reg) << ", ";

      // Keep track of which regclasses this register is in.
      RegClassesBelongedTo.insert(std::make_pair(Reg, &RC));
    }
    OS << "\n  };\n\n";

    OS << "  struct " << Name << "Class : public TargetRegisterClass {\n"
       << "    " << Name << "Class() : TargetRegisterClass("
       << RC.SpillSize/8 << ", " << RC.SpillAlignment/8 << ", " << Name << ", "
       << Name << " + " << RC.Elements.size() << ") {}\n"
       << RC.MethodDefinitions << "  } " << Name << "Instance;\n\n";
  }

  OS << "  const TargetRegisterClass* const RegisterClasses[] = {\n";
  for (unsigned i = 0, e = RegClassNames.size(); i != e; ++i)
    OS << "    &" << RegClassNames[i] << "Instance,\n";
  OS << "  };\n";

  // Emit register class aliases...
  std::vector<Record*> RegisterAliasesRecs =
    Records.getAllDerivedDefinitions("RegisterAliases");
  std::map<Record*, std::set<Record*> > RegisterAliases;

  for (unsigned i = 0, e = RegisterAliasesRecs.size(); i != e; ++i) {
    Record *AS = RegisterAliasesRecs[i];
    Record *R = AS->getValueAsDef("Reg");
    ListInit *LI = AS->getValueAsListInit("Aliases");

    // Add information that R aliases all of the elements in the list... and
    // that everything in the list aliases R.
    for (unsigned j = 0, e = LI->getSize(); j != e; ++j) {
      DefInit *Reg = dynamic_cast<DefInit*>(LI->getElement(j));
      if (!Reg) throw "ERROR: Alias list element is not a def!";
      if (RegisterAliases[R].count(Reg->getDef()))
        std::cerr << "Warning: register alias between " << getQualifiedName(R)
                  << " and " << getQualifiedName(Reg->getDef())
                  << " specified multiple times!\n";
      RegisterAliases[R].insert(Reg->getDef());

      if (RegisterAliases[Reg->getDef()].count(R))
        std::cerr << "Warning: register alias between " << getQualifiedName(R)
                  << " and " << getQualifiedName(Reg->getDef())
                  << " specified multiple times!\n";
      RegisterAliases[Reg->getDef()].insert(R);
    }
  }

  if (!RegisterAliases.empty())
    OS << "\n\n  // Register Alias Sets...\n";

  // Emit the empty alias list
  OS << "  const unsigned Empty_AliasSet[] = { 0 };\n";
  // Loop over all of the registers which have aliases, emitting the alias list
  // to memory.
  for (std::map<Record*, std::set<Record*> >::iterator
         I = RegisterAliases.begin(), E = RegisterAliases.end(); I != E; ++I) {
    OS << "  const unsigned " << I->first->getName() << "_AliasSet[] = { ";
    for (std::set<Record*>::iterator ASI = I->second.begin(),
           E = I->second.end(); ASI != E; ++ASI)
      OS << getQualifiedName(*ASI) << ", ";
    OS << "0 };\n";
  }

  OS << "\n  const MRegisterDesc RegisterDescriptors[] = { // Descriptors\n";
  OS << "    { \"NOREG\",\t0,\t\t0,\t0 },\n";

  // Now that register alias sets have been emitted, emit the register
  // descriptors now.
  const std::vector<CodeGenRegister> &Registers = Target.getRegisters();
  for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
    const CodeGenRegister &Reg = Registers[i];
    OS << "    { \"";
    if (!Reg.TheDef->getValueAsString("Name").empty())
      OS << Reg.TheDef->getValueAsString("Name");
    else
      OS << Reg.getName();
    OS << "\",\t";
    if (RegisterAliases.count(Reg.TheDef))
      OS << Reg.getName() << "_AliasSet,\t";
    else
      OS << "Empty_AliasSet,\t";

    // Figure out what the size and alignment of the spill slots are for this
    // reg.  This may be explicitly declared in the register, or it may be
    // inferred from the register classes it is part of.
    std::multimap<Record*, const CodeGenRegisterClass*>::iterator I, E;
    tie(I, E) = RegClassesBelongedTo.equal_range(Reg.TheDef);
    unsigned SpillSize = Reg.DeclaredSpillSize;
    unsigned SpillAlign = Reg.DeclaredSpillAlignment;
    for (; I != E; ++I) {   // For each reg class this belongs to.
      const CodeGenRegisterClass *RC = I->second;
      if (SpillSize == 0)
        SpillSize = RC->SpillSize;
      else if (SpillSize != RC->SpillSize)
        throw "Spill size for regclass '" + RC->getName() +
              "' doesn't match spill sized already inferred for register '" +
              Reg.getName() + "'!";
      if (SpillAlign == 0)
        SpillAlign = RC->SpillAlignment;
      else if (SpillAlign != RC->SpillAlignment)
        throw "Spill alignment for regclass '" + RC->getName() +
              "' doesn't match spill sized already inferred for register '" +
              Reg.getName() + "'!";
    }

    OS << SpillSize << ", " << SpillAlign << " },\n";
  }
  OS << "  };\n";      // End of register descriptors...
  OS << "}\n\n";       // End of anonymous namespace...

  OS << "namespace " << Target.getName() << " { // Register classes\n";
  for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
    const std::string &Name = RegisterClasses[i].getName();
    if (Name.size() < 9 || Name[9] != '.')    // Ignore anonymous classes
      OS << "  TargetRegisterClass *" << Name << "RegisterClass = &"
         << Name << "Instance;\n";
  }
  OS << "} // end of namespace " << Target.getName() << "\n\n";

  std::string ClassName = Target.getName() + "GenRegisterInfo";

  // Emit the constructor of the class...
  OS << ClassName << "::" << ClassName
     << "(int CallFrameSetupOpcode, int CallFrameDestroyOpcode)\n"
     << "  : MRegisterInfo(RegisterDescriptors, " << Registers.size()+1
     << ", RegisterClasses, RegisterClasses+" << RegClassNames.size() << ",\n "
     << "                 CallFrameSetupOpcode, CallFrameDestroyOpcode) {}\n\n";

  // Emit the getCalleeSaveRegs method...
  OS << "const unsigned* " << ClassName << "::getCalleeSaveRegs() const {\n"
     << "  static const unsigned CalleeSaveRegs[] = {\n    ";

  const std::vector<Record*> &CSR = Target.getCalleeSavedRegisters();
  for (unsigned i = 0, e = CSR.size(); i != e; ++i)
    OS << getQualifiedName(CSR[i]) << ", ";
  OS << " 0\n  };\n  return CalleeSaveRegs;\n}\n\n";
  OS << "} // End llvm namespace \n";
}
<commit_msg>Revamp the Register class, and allow the use of the RegisterGroup class to specify aliases directly in register definitions.<commit_after>//===- RegisterInfoEmitter.cpp - Generate a Register File Desc. -*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tablegen backend is responsible for emitting a description of a target
// register file for a code generator.  It uses instances of the Register,
// RegisterAliases, and RegisterClass classes to gather this information.
//
//===----------------------------------------------------------------------===//

#include "RegisterInfoEmitter.h"
#include "CodeGenTarget.h"
#include "CodeGenRegisters.h"
#include "Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/STLExtras.h"
#include <set>
using namespace llvm;

// runEnums - Print out enum values for all of the registers.
void RegisterInfoEmitter::runEnums(std::ostream &OS) {
  CodeGenTarget Target;
  const std::vector<CodeGenRegister> &Registers = Target.getRegisters();

  std::string Namespace = Registers[0].TheDef->getValueAsString("Namespace");

  EmitSourceFileHeader("Target Register Enum Values", OS);
  OS << "namespace llvm {\n\n";

  if (!Namespace.empty())
    OS << "namespace " << Namespace << " {\n";
  OS << "  enum {\n    NoRegister,\n";

  for (unsigned i = 0, e = Registers.size(); i != e; ++i)
    OS << "    " << Registers[i].getName() << ", \t// " << i+1 << "\n";

  OS << "  };\n";
  if (!Namespace.empty())
    OS << "}\n";
  OS << "} // End llvm namespace \n";
}

void RegisterInfoEmitter::runHeader(std::ostream &OS) {
  EmitSourceFileHeader("Register Information Header Fragment", OS);
  CodeGenTarget Target;
  const std::string &TargetName = Target.getName();
  std::string ClassName = TargetName + "GenRegisterInfo";

  OS << "#include \"llvm/Target/MRegisterInfo.h\"\n\n";

  OS << "namespace llvm {\n\n";

  OS << "struct " << ClassName << " : public MRegisterInfo {\n"
     << "  " << ClassName
     << "(int CallFrameSetupOpcode = -1, int CallFrameDestroyOpcode = -1);\n"
     << "  const unsigned* getCalleeSaveRegs() const;\n"
     << "};\n\n";

  std::vector<Record*> RegisterClasses =
    Records.getAllDerivedDefinitions("RegisterClass");

  OS << "namespace " << TargetName << " { // Register classes\n";
  for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
    const std::string &Name = RegisterClasses[i]->getName();
    if (Name.size() < 9 || Name[9] != '.')       // Ignore anonymous classes
      OS << "  extern TargetRegisterClass *" << Name << "RegisterClass;\n";
  }
  OS << "} // end of namespace " << TargetName << "\n\n";
  OS << "} // End llvm namespace \n";
}

// RegisterInfoEmitter::run - Main register file description emitter.
//
void RegisterInfoEmitter::run(std::ostream &OS) {
  CodeGenTarget Target;
  EmitSourceFileHeader("Register Information Source Fragment", OS);

  OS << "namespace llvm {\n\n";

  // Start out by emitting each of the register classes... to do this, we build
  // a set of registers which belong to a register class, this is to ensure that
  // each register is only in a single register class.
  //
  const std::vector<CodeGenRegisterClass> &RegisterClasses =
    Target.getRegisterClasses();

  std::set<Record*> RegistersFound;
  std::vector<std::string> RegClassNames;

  // Loop over all of the register classes... emitting each one.
  OS << "namespace {     // Register classes...\n";

  // RegClassesBelongedTo - Keep track of which register classes each reg
  // belongs to.
  std::multimap<Record*, const CodeGenRegisterClass*> RegClassesBelongedTo;

  for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
    const CodeGenRegisterClass &RC = RegisterClasses[rc];

    std::string Name = RC.getName();
    if (Name.size() > 9 && Name[9] == '.') {
      static unsigned AnonCounter = 0;
      Name = "AnonRegClass_"+utostr(AnonCounter++);
    }

    RegClassNames.push_back(Name);

    // Emit the register list now...
    OS << "  // " << Name << " Register Class...\n  const unsigned " << Name
       << "[] = {\n    ";
    for (unsigned i = 0, e = RC.Elements.size(); i != e; ++i) {
      Record *Reg = RC.Elements[i];
      if (RegistersFound.count(Reg))
        throw "Register '" + Reg->getName() +
              "' included in multiple register classes!";
      RegistersFound.insert(Reg);
      OS << getQualifiedName(Reg) << ", ";

      // Keep track of which regclasses this register is in.
      RegClassesBelongedTo.insert(std::make_pair(Reg, &RC));
    }
    OS << "\n  };\n\n";

    OS << "  struct " << Name << "Class : public TargetRegisterClass {\n"
       << "    " << Name << "Class() : TargetRegisterClass("
       << RC.SpillSize/8 << ", " << RC.SpillAlignment/8 << ", " << Name << ", "
       << Name << " + " << RC.Elements.size() << ") {}\n"
       << RC.MethodDefinitions << "  } " << Name << "Instance;\n\n";
  }

  OS << "  const TargetRegisterClass* const RegisterClasses[] = {\n";
  for (unsigned i = 0, e = RegClassNames.size(); i != e; ++i)
    OS << "    &" << RegClassNames[i] << "Instance,\n";
  OS << "  };\n";

  // Emit register class aliases...
  std::map<Record*, std::set<Record*> > RegisterAliases;
  const std::vector<CodeGenRegister> &Regs = Target.getRegisters();

  for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
    Record *R = Regs[i].TheDef;
    ListInit *LI = Regs[i].TheDef->getValueAsListInit("Aliases");
    // Add information that R aliases all of the elements in the list... and
    // that everything in the list aliases R.
    for (unsigned j = 0, e = LI->getSize(); j != e; ++j) {
      DefInit *Reg = dynamic_cast<DefInit*>(LI->getElement(j));
      if (!Reg) throw "ERROR: Alias list element is not a def!";
      if (RegisterAliases[R].count(Reg->getDef()))
        std::cerr << "Warning: register alias between " << getQualifiedName(R)
                  << " and " << getQualifiedName(Reg->getDef())
                  << " specified multiple times!\n";
      RegisterAliases[R].insert(Reg->getDef());

      if (RegisterAliases[Reg->getDef()].count(R))
        std::cerr << "Warning: register alias between " << getQualifiedName(R)
                  << " and " << getQualifiedName(Reg->getDef())
                  << " specified multiple times!\n";
      RegisterAliases[Reg->getDef()].insert(R);
    }
  }

  if (!RegisterAliases.empty())
    OS << "\n\n  // Register Alias Sets...\n";

  // Emit the empty alias list
  OS << "  const unsigned Empty_AliasSet[] = { 0 };\n";
  // Loop over all of the registers which have aliases, emitting the alias list
  // to memory.
  for (std::map<Record*, std::set<Record*> >::iterator
         I = RegisterAliases.begin(), E = RegisterAliases.end(); I != E; ++I) {
    OS << "  const unsigned " << I->first->getName() << "_AliasSet[] = { ";
    for (std::set<Record*>::iterator ASI = I->second.begin(),
           E = I->second.end(); ASI != E; ++ASI)
      OS << getQualifiedName(*ASI) << ", ";
    OS << "0 };\n";
  }

  OS << "\n  const MRegisterDesc RegisterDescriptors[] = { // Descriptors\n";
  OS << "    { \"NOREG\",\t0,\t\t0,\t0 },\n";

  // Now that register alias sets have been emitted, emit the register
  // descriptors now.
  const std::vector<CodeGenRegister> &Registers = Target.getRegisters();
  for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
    const CodeGenRegister &Reg = Registers[i];
    OS << "    { \"";
    if (!Reg.TheDef->getValueAsString("Name").empty())
      OS << Reg.TheDef->getValueAsString("Name");
    else
      OS << Reg.getName();
    OS << "\",\t";
    if (RegisterAliases.count(Reg.TheDef))
      OS << Reg.getName() << "_AliasSet,\t";
    else
      OS << "Empty_AliasSet,\t";

    // Figure out what the size and alignment of the spill slots are for this
    // reg.  This may be explicitly declared in the register, or it may be
    // inferred from the register classes it is part of.
    std::multimap<Record*, const CodeGenRegisterClass*>::iterator I, E;
    tie(I, E) = RegClassesBelongedTo.equal_range(Reg.TheDef);
    unsigned SpillSize = Reg.DeclaredSpillSize;
    unsigned SpillAlign = Reg.DeclaredSpillAlignment;
    for (; I != E; ++I) {   // For each reg class this belongs to.
      const CodeGenRegisterClass *RC = I->second;
      if (SpillSize == 0)
        SpillSize = RC->SpillSize;
      else if (SpillSize != RC->SpillSize)
        throw "Spill size for regclass '" + RC->getName() +
              "' doesn't match spill sized already inferred for register '" +
              Reg.getName() + "'!";
      if (SpillAlign == 0)
        SpillAlign = RC->SpillAlignment;
      else if (SpillAlign != RC->SpillAlignment)
        throw "Spill alignment for regclass '" + RC->getName() +
              "' doesn't match spill sized already inferred for register '" +
              Reg.getName() + "'!";
    }

    OS << SpillSize << ", " << SpillAlign << " },\n";
  }
  OS << "  };\n";      // End of register descriptors...
  OS << "}\n\n";       // End of anonymous namespace...

  OS << "namespace " << Target.getName() << " { // Register classes\n";
  for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
    const std::string &Name = RegisterClasses[i].getName();
    if (Name.size() < 9 || Name[9] != '.')    // Ignore anonymous classes
      OS << "  TargetRegisterClass *" << Name << "RegisterClass = &"
         << Name << "Instance;\n";
  }
  OS << "} // end of namespace " << Target.getName() << "\n\n";

  std::string ClassName = Target.getName() + "GenRegisterInfo";

  // Emit the constructor of the class...
  OS << ClassName << "::" << ClassName
     << "(int CallFrameSetupOpcode, int CallFrameDestroyOpcode)\n"
     << "  : MRegisterInfo(RegisterDescriptors, " << Registers.size()+1
     << ", RegisterClasses, RegisterClasses+" << RegClassNames.size() << ",\n "
     << "                 CallFrameSetupOpcode, CallFrameDestroyOpcode) {}\n\n";

  // Emit the getCalleeSaveRegs method...
  OS << "const unsigned* " << ClassName << "::getCalleeSaveRegs() const {\n"
     << "  static const unsigned CalleeSaveRegs[] = {\n    ";

  const std::vector<Record*> &CSR = Target.getCalleeSavedRegisters();
  for (unsigned i = 0, e = CSR.size(); i != e; ++i)
    OS << getQualifiedName(CSR[i]) << ", ";
  OS << " 0\n  };\n  return CalleeSaveRegs;\n}\n\n";
  OS << "} // End llvm namespace \n";
}
<|endoftext|>


<commit_before>/*
 * This file is part of TelepathyQt4
 *
 * Copyright (C) 2009 Collabora Ltd. <http://www.collabora.co.uk/>
 * Copyright (C) 2009 Nokia Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "TelepathyQt4/channel-factory.h"

#include "TelepathyQt4/_gen/future-constants.h"

#include "TelepathyQt4/debug-internal.h"

#include <TelepathyQt4/Channel>
#include <TelepathyQt4/Connection>
#include <TelepathyQt4/Constants>
#include <TelepathyQt4/FileTransferChannel>
#include <TelepathyQt4/IncomingFileTransferChannel>
#include <TelepathyQt4/OutgoingFileTransferChannel>
#include <TelepathyQt4/RoomListChannel>
#include <TelepathyQt4/StreamedMediaChannel>
#include <TelepathyQt4/TextChannel>

namespace Tp
{

/**
 * \class ChannelFactory
 * \ingroup clientchannel
 * \headerfile TelepathyQt4/channel-factory.h <TelepathyQt4/ChannelFactory>
 *
 * \brief Constructs Channel objects
 *
 * \todo This class is currently only a placeholder to enable using factories in general in other
 * classes. There is no actual configurability in the construction behavior, although a
 * factory-style construction API is provided.
 */

/**
 * Create a new ChannelFactory object for the given \a bus.
 *
 * The returned factory will construct channel subclasses provided by TelepathyQt4 as appropriate
 * for the channel immutable properties, but not make any features ready.
 *
 * \param bus The QDBusConnection the proxies constructed using this factory should use.
 * \return An ChannelFactoryPtr pointing to the newly created factory.
 */
ChannelFactoryPtr ChannelFactory::create(const QDBusConnection &bus)
{
    return ChannelFactoryPtr(new ChannelFactory(bus));
}

/**
 * Class constructor.
 *
 * The constructed factory will construct channel subclasses provided by TelepathyQt4 as appropriate
 * for the channel immutable properties, but not make any features ready.
 *
 * \param bus The QDBusConnection the proxies constructed using this factory should use.
 */
ChannelFactory::ChannelFactory(const QDBusConnection &bus)
    : DBusProxyFactory(bus)
{
}

/**
 * Class destructor.
 */
ChannelFactory::~ChannelFactory()
{
}

/**
 * Constructs a Channel proxy (and someday begins making it ready.)
 *
 * If a valid proxy already exists in the factory cache for the given combination of \a busName and
 * \a objectPath, it is returned instead. All newly created proxies are automatically cached until
 * they're either DBusProxy::invalidated() or the last reference to them outside the factory has
 * been dropped.
 *
 * The proxy can be accessed immediately after this function returns using PendingReady::proxy().
 *
 * \todo Make it configurable which subclass is constructed and which features, if any, are made
 * ready on it.
 *
 * \param connection Proxy for the owning connection of the channel.
 * \param channelPath The object path of the channel.
 * \param immutableProperties The immutable properties of the channel.
 * \return A PendingReady operation with the proxy in PendingReady::proxy().
 */
PendingReady *ChannelFactory::proxy(const ConnectionPtr &connection, const QString &channelPath,
        const QVariantMap &immutableProperties) const
{
    SharedPtr<RefCounted> proxy = cachedProxy(connection->busName(), channelPath);
    if (!proxy) {
        proxy = create(connection, channelPath, immutableProperties);
    }

    return nowHaveProxy(proxy);
}

ChannelPtr ChannelFactory::create(const ConnectionPtr &connection,
        const QString &channelPath, const QVariantMap &immutableProperties)
{
    QString channelType = immutableProperties.value(QLatin1String(
                TELEPATHY_INTERFACE_CHANNEL ".ChannelType")).toString();
    if (channelType == QLatin1String(TELEPATHY_INTERFACE_CHANNEL_TYPE_TEXT)) {
        return TextChannel::create(connection, channelPath, immutableProperties);
    }
    else if (channelType == QLatin1String(TELEPATHY_INTERFACE_CHANNEL_TYPE_STREAMED_MEDIA) ||
             channelType == QLatin1String(TP_FUTURE_INTERFACE_CHANNEL_TYPE_CALL)) {
        return StreamedMediaChannel::create(connection, channelPath, immutableProperties);
    }
    else if (channelType == QLatin1String(TELEPATHY_INTERFACE_CHANNEL_TYPE_ROOM_LIST)) {
        return RoomListChannel::create(connection, channelPath, immutableProperties);
    }
    else if (channelType == QLatin1String(TELEPATHY_INTERFACE_CHANNEL_TYPE_FILE_TRANSFER)) {
        if (immutableProperties.contains(QLatin1String(
                        TELEPATHY_INTERFACE_CHANNEL ".Requested"))) {
            bool requested = immutableProperties.value(QLatin1String(
                        TELEPATHY_INTERFACE_CHANNEL ".Requested")).toBool();
            if (requested) {
                return OutgoingFileTransferChannel::create(connection, channelPath,
                        immutableProperties);
            } else {
                return IncomingFileTransferChannel::create(connection, channelPath,
                        immutableProperties);
            }
        } else {
            warning() << "Trying to create a channel of type FileTransfer "
                "without the " TELEPATHY_INTERFACE_CHANNEL ".Requested "
                "property set in immutableProperties, returning a "
                "FileTransferChannel instance";
            return FileTransferChannel::create(connection, channelPath,
                    immutableProperties);
        }
    }

    // ContactList, old-style Tubes, or a future channel type
    return Channel::create(connection, channelPath, immutableProperties);
}

/**
 * Transforms well-known names to the corresponding unique names, as is appropriate for Channel
 *
 * \param uniqueOrWellKnown The name to transform.
 * \return The unique name corresponding to \a uniqueOrWellKnown (which may be it itself).
 */
QString ChannelFactory::finalBusNameFrom(const QString &uniqueOrWellKnown) const
{
    return StatefulDBusProxy::uniqueNameFrom(dbusConnection(), uniqueOrWellKnown);
}

/**
 * Returns features as configured for the channel class given by the Channel::immutableProperties()
 * of \a proxy.
 *
 * \todo Make the features configurable - currently an empty set is always returned.
 *
 * \param proxy The Channel proxy to determine the features for.
 * \return The channel class-specific features.
 */
Features ChannelFactory::featuresFor(const SharedPtr<RefCounted> &proxy) const
{
    // TODO return whatever the user / defaults has specified
    return Features();
}

} // Tp
<commit_msg>ChannelFactory: Handle ContactSearch channels.<commit_after>/*
 * This file is part of TelepathyQt4
 *
 * Copyright (C) 2009 Collabora Ltd. <http://www.collabora.co.uk/>
 * Copyright (C) 2009 Nokia Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "TelepathyQt4/channel-factory.h"

#include "TelepathyQt4/_gen/future-constants.h"

#include "TelepathyQt4/debug-internal.h"

#include <TelepathyQt4/Channel>
#include <TelepathyQt4/Connection>
#include <TelepathyQt4/Constants>
#include <TelepathyQt4/ContactSearchChannel>
#include <TelepathyQt4/FileTransferChannel>
#include <TelepathyQt4/IncomingFileTransferChannel>
#include <TelepathyQt4/OutgoingFileTransferChannel>
#include <TelepathyQt4/RoomListChannel>
#include <TelepathyQt4/StreamedMediaChannel>
#include <TelepathyQt4/TextChannel>

namespace Tp
{

/**
 * \class ChannelFactory
 * \ingroup clientchannel
 * \headerfile TelepathyQt4/channel-factory.h <TelepathyQt4/ChannelFactory>
 *
 * \brief Constructs Channel objects
 *
 * \todo This class is currently only a placeholder to enable using factories in general in other
 * classes. There is no actual configurability in the construction behavior, although a
 * factory-style construction API is provided.
 */

/**
 * Create a new ChannelFactory object for the given \a bus.
 *
 * The returned factory will construct channel subclasses provided by TelepathyQt4 as appropriate
 * for the channel immutable properties, but not make any features ready.
 *
 * \param bus The QDBusConnection the proxies constructed using this factory should use.
 * \return An ChannelFactoryPtr pointing to the newly created factory.
 */
ChannelFactoryPtr ChannelFactory::create(const QDBusConnection &bus)
{
    return ChannelFactoryPtr(new ChannelFactory(bus));
}

/**
 * Class constructor.
 *
 * The constructed factory will construct channel subclasses provided by TelepathyQt4 as appropriate
 * for the channel immutable properties, but not make any features ready.
 *
 * \param bus The QDBusConnection the proxies constructed using this factory should use.
 */
ChannelFactory::ChannelFactory(const QDBusConnection &bus)
    : DBusProxyFactory(bus)
{
}

/**
 * Class destructor.
 */
ChannelFactory::~ChannelFactory()
{
}

/**
 * Constructs a Channel proxy (and someday begins making it ready.)
 *
 * If a valid proxy already exists in the factory cache for the given combination of \a busName and
 * \a objectPath, it is returned instead. All newly created proxies are automatically cached until
 * they're either DBusProxy::invalidated() or the last reference to them outside the factory has
 * been dropped.
 *
 * The proxy can be accessed immediately after this function returns using PendingReady::proxy().
 *
 * \todo Make it configurable which subclass is constructed and which features, if any, are made
 * ready on it.
 *
 * \param connection Proxy for the owning connection of the channel.
 * \param channelPath The object path of the channel.
 * \param immutableProperties The immutable properties of the channel.
 * \return A PendingReady operation with the proxy in PendingReady::proxy().
 */
PendingReady *ChannelFactory::proxy(const ConnectionPtr &connection, const QString &channelPath,
        const QVariantMap &immutableProperties) const
{
    SharedPtr<RefCounted> proxy = cachedProxy(connection->busName(), channelPath);
    if (!proxy) {
        proxy = create(connection, channelPath, immutableProperties);
    }

    return nowHaveProxy(proxy);
}

ChannelPtr ChannelFactory::create(const ConnectionPtr &connection,
        const QString &channelPath, const QVariantMap &immutableProperties)
{
    QString channelType = immutableProperties.value(QLatin1String(
                TELEPATHY_INTERFACE_CHANNEL ".ChannelType")).toString();
    if (channelType == QLatin1String(TELEPATHY_INTERFACE_CHANNEL_TYPE_TEXT)) {
        return TextChannel::create(connection, channelPath, immutableProperties);
    } else if (channelType == QLatin1String(TELEPATHY_INTERFACE_CHANNEL_TYPE_STREAMED_MEDIA) ||
             channelType == QLatin1String(TP_FUTURE_INTERFACE_CHANNEL_TYPE_CALL)) {
        return StreamedMediaChannel::create(connection, channelPath, immutableProperties);
    } else if (channelType == QLatin1String(TELEPATHY_INTERFACE_CHANNEL_TYPE_ROOM_LIST)) {
        return RoomListChannel::create(connection, channelPath, immutableProperties);
    } else if (channelType == QLatin1String(TELEPATHY_INTERFACE_CHANNEL_TYPE_FILE_TRANSFER)) {
        if (immutableProperties.contains(QLatin1String(
                        TELEPATHY_INTERFACE_CHANNEL ".Requested"))) {
            bool requested = immutableProperties.value(QLatin1String(
                        TELEPATHY_INTERFACE_CHANNEL ".Requested")).toBool();
            if (requested) {
                return OutgoingFileTransferChannel::create(connection, channelPath,
                        immutableProperties);
            } else {
                return IncomingFileTransferChannel::create(connection, channelPath,
                        immutableProperties);
            }
        } else {
            warning() << "Trying to create a channel of type FileTransfer "
                "without the " TELEPATHY_INTERFACE_CHANNEL ".Requested "
                "property set in immutableProperties, returning a "
                "FileTransferChannel instance";
            return FileTransferChannel::create(connection, channelPath,
                    immutableProperties);
        }
    } else if (channelType == QLatin1String(TELEPATHY_INTERFACE_CHANNEL_TYPE_CONTACT_SEARCH)) {
        return ContactSearchChannel::create(connection, channelPath, immutableProperties);
    }

    // ContactList, old-style Tubes, or a future channel type
    return Channel::create(connection, channelPath, immutableProperties);
}

/**
 * Transforms well-known names to the corresponding unique names, as is appropriate for Channel
 *
 * \param uniqueOrWellKnown The name to transform.
 * \return The unique name corresponding to \a uniqueOrWellKnown (which may be it itself).
 */
QString ChannelFactory::finalBusNameFrom(const QString &uniqueOrWellKnown) const
{
    return StatefulDBusProxy::uniqueNameFrom(dbusConnection(), uniqueOrWellKnown);
}

/**
 * Returns features as configured for the channel class given by the Channel::immutableProperties()
 * of \a proxy.
 *
 * \todo Make the features configurable - currently an empty set is always returned.
 *
 * \param proxy The Channel proxy to determine the features for.
 * \return The channel class-specific features.
 */
Features ChannelFactory::featuresFor(const SharedPtr<RefCounted> &proxy) const
{
    // TODO return whatever the user / defaults has specified
    return Features();
}

} // Tp
<|endoftext|>


<commit_before><commit_msg>nss_oscp: convert LOG(INFO) to VLOG(1)<commit_after><|endoftext|>


<commit_before>#include <stdio.h>
#include <ctype.h>
#include <metaLine.h>

int testMetaLine(int , char * [])
{

  std::cout << "Creating test file ...";
  MetaLine* Line = new MetaLine(3);
  Line->ID(0);
  LinePnt* pnt;

  unsigned int i;
  for(i=0;i<10;i++)
  {
    pnt = new LinePnt(3);
    pnt->m_X[0]=(float)0.2;pnt->m_X[1]=i;pnt->m_X[2]=i;
    pnt->m_V[0][0]=(float)0.3;pnt->m_V[0][1]=i;pnt->m_V[0][2]=i;
    pnt->m_V[1][0]=(float)0.4;pnt->m_V[1][1]=i+1;pnt->m_V[1][2]=i+1;
    Line->GetPoints().push_back(pnt);
  }

  std::cout << "Writing test file ...";

  Line->BinaryData(true);

  Line->Write("myLine.meta");

  std::cout << "done" << std::endl;
  std::cout << "Reading test file ...";

  Line->Clear();
  Line->Read("myLine.meta");

  Line->PrintInfo();

  MetaLine::PointListType list =  Line->GetPoints();
  MetaLine::PointListType::const_iterator it = list.begin();

  i=0;
  while(it != list.end())
  {
    std::cout << "Point #" << i++ << ":" << std::endl;
    std::cout << "position = ";
    unsigned int d;
    for(d = 0; d < 3; d++)
    {
      std::cout << (*it)->m_X[d] << " ";
    }
    std::cout << std::endl;
    std::cout << "First normal = ";
    for(d = 0; d < 3; d++)
    {
      std::cout << (*it)->m_V[0][d] << " ";
    }
    std::cout << std::endl;
    std::cout << "Second normal = ";
    for(d = 0; d < 3; d++)
    {
      std::cout << (*it)->m_V[1][d] << " ";
    }
    std::cout << std::endl;
    it++;
  }

  delete Line;
  std::cout << "done" << std::endl;
  return 0;
}
<commit_msg>ENH: Increasing coverage<commit_after>#include <stdio.h>
#include <ctype.h>
#include <metaLine.h>

int testMetaLine(int , char * [])
{

  std::cout << "Creating test file ...";
  MetaLine line0;
  MetaLine* Line = new MetaLine(3);
  Line->ID(0);
  LinePnt* pnt;

  unsigned int i;
  for(i=0;i<10;i++)
  {
    pnt = new LinePnt(3);
    pnt->m_X[0]=(float)0.2;pnt->m_X[1]=i;pnt->m_X[2]=i;
    pnt->m_V[0][0]=(float)0.3;pnt->m_V[0][1]=i;pnt->m_V[0][2]=i;
    pnt->m_V[1][0]=(float)0.4;pnt->m_V[1][1]=i+1;pnt->m_V[1][2]=i+1;
    Line->GetPoints().push_back(pnt);
  }

  std::cout << "Writing test file ...";

  Line->BinaryData(true);

  Line->Write("myLine.meta");

  std::cout << "done" << std::endl;
  std::cout << "Reading test file ...";

  Line->Clear();
  Line->Read("myLine.meta");

  MetaLine LineRead("myLine.meta");
  MetaLine LineCopy(&LineRead);

  std::cout << "PointDim = " << LineCopy.PointDim() << std::endl;
  std::cout << "NPoints = " << LineCopy.NPoints() << std::endl;
  std::cout << "ElementType = " << LineCopy.ElementType() << std::endl;

  Line->PrintInfo();

  MetaLine::PointListType list =  Line->GetPoints();
  MetaLine::PointListType::const_iterator it = list.begin();

  i=0;
  while(it != list.end())
  {
    std::cout << "Point #" << i++ << ":" << std::endl;
    std::cout << "position = ";
    unsigned int d;
    for(d = 0; d < 3; d++)
    {
      std::cout << (*it)->m_X[d] << " ";
    }
    std::cout << std::endl;
    std::cout << "First normal = ";
    for(d = 0; d < 3; d++)
    {
      std::cout << (*it)->m_V[0][d] << " ";
    }
    std::cout << std::endl;
    std::cout << "Second normal = ";
    for(d = 0; d < 3; d++)
    {
      std::cout << (*it)->m_V[1][d] << " ";
    }
    std::cout << std::endl;
    it++;
  }

  delete Line;
  std::cout << "done" << std::endl;
  return 0;
}
<|endoftext|>


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

namespace gnr
{

struct statebuf
{
  void *sp, *label;
};

}

#if defined(__GNUC__)
# if defined(i386) || defined(__i386) || defined(__i386__)
#  define clobber_all() asm volatile ("":::"eax", "ebx", "ecx", "edx", "esi", "edi", "ebp", "cc");
# elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
#  define clobber_all() asm volatile ("":::"rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "cc");
# elif defined(__arm__)
#  define clobber_all() asm volatile ("":::"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc");
# elif defined(__aarch64__)
#  define clobber_all() asm volatile ("":::"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30", "cc");
# else
#  error "unsupported architecture"
# endif
#else
# error "unsupported compiler"
#endif

#if defined(__GNUC__)
static inline bool __attribute__((always_inline)) savestate(
  gnr::statebuf& ssb) noexcept
{
  bool r;

# if defined(i386) || defined(__i386) || defined(__i386__)
  asm (
    "movl %%esp, %0\n\t" // store sp
    "lea 1f(%%eip), %%eax\n\t" // load label
    "movl %%eax, %1\n\t" // store label
    "movb $0, %2\n\t" // return false
    "jmp 2f\n\t"
    "1:"
    "movb $1, %2\n\t" // return true
    "2:"
    : "=m" (ssb.sp), "=m" (ssb.label), "=r" (r)
    :
    : "eax", "memory"
  );
# elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) ||\
   defined(__x86_64)
  asm (
    "movq %%rsp, %0\n\t" // store sp
    "lea 1f(%%rip), %%rax\n\t" // load label
    "movq %%rax, %1\n\t" // store label
    "movb $0, %2\n\t" // return false
    "jmp 2f\n\t"
    "1:"
    "movb $1, %2\n\t" // return true
    "2:"
    : "=m" (ssb.sp), "=m" (ssb.label), "=r" (r)
    :
    : "rax", "memory"
  );
# elif defined(__arm__)
  asm (
    "str sp, %0\n\t" // store sp
    "ldr r0, =1f\n\t" // load label
    "str r0, %1\n\t" // store label
    "mov %2, $0\n\t" // store 0 into result
    "b 2f\n\t"
    "1:"
    "mov %2, $1\n\t" // store 1 into result
    "2:"
    : "=m" (ssb.sp), "=m" (ssb.label), "=r" (r)
    :
    : "r0", "memory"
  );
# elif defined(__aarch64__)
  asm (
    "mov x0, sp\n\t"
    "str x0, %0\n\t" // store sp
    "ldr x0, =1f\n\t" // load label
    "str x0, %1\n\t" // store label
    "mov %w2, #0\n\t" // store 0 into result
    "b 2f\n\t"
    "1:"
    "mov %w2, #1\n\t" // store 1 into result
    "2:"
    : "=m" (ssb.sp), "=m" (ssb.label), "=r" (r)
    :
    : "x0", "memory"
  );
# else
#  error "unsupported architecture"
# endif

  return r;
}
#else
# error "unsupported compiler"
#endif

#if defined(__GNUC__)
# if defined(i386) || defined(__i386) || defined(__i386__)
#  define restorestate(SSB)          \
    asm (                            \
      "movl %0, %%esp\n\t"           \
      "jmp *%1"                      \
      :                              \
      : "m" (SSB.sp), "m" (SSB.label)\
    );                               \
    __builtin_unreachable();
# elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) ||\
   defined(__x86_64)
#  define restorestate(SSB)          \
    asm (                            \
      "movq %0, %%rsp\n\t"           \
      "jmp *%1"                      \
      :                              \
      : "m" (SSB.sp), "m" (SSB.label)\
    );                               \
    __builtin_unreachable();
# elif defined(__arm__)
#  define restorestate(SSB)          \
    asm (                            \
      "mov sp, %0\n\t"               \
      "mov pc, %1"                   \
      :                              \
      : "r" (SSB.sp), "r" (SSB.label)\
    );                               \
    __builtin_unreachable();
# elif defined(__aarch64__)
#  define restorestate(SSB)          \
    asm (                            \
      "mov sp, %0\n\t"               \
      "ret %1"                       \
      :                              \
      : "r" (SSB.sp), "r" (SSB.label)\
    );                               \
    __builtin_unreachable();
# else
#  error "unsupported architecture"
# endif
#else
# error "unsupported compiler"
#endif

#endif // CR_SAVESTATE_HPP
<commit_msg>some fixes<commit_after>#ifndef CR_SAVESTATE_HPP
# define CR_SAVESTATE_HPP
# pragma once

namespace gnr
{

struct statebuf
{
  void* sp, *label;
#if defined(i386) || defined(__i386) || defined(__i386__)
  void* bp;
#endif
};

}

#if defined(__GNUC__)
# if defined(i386) || defined(__i386) || defined(__i386__)
#  define clobber_all() asm volatile ("":::"eax", "ebx", "ecx", "edx", "esi", "edi", "cc");
# elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
#  define clobber_all() asm volatile ("":::"rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "cc");
# elif defined(__arm__)
#  define clobber_all() asm volatile ("":::"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "lr", "cc");
# elif defined(__aarch64__)
#  define clobber_all() asm volatile ("":::"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30", "cc");
# else
#  error "unsupported architecture"
# endif
#else
# error "unsupported compiler"
#endif

#if defined(__GNUC__)
static inline bool __attribute__((always_inline)) savestate(
  gnr::statebuf& ssb) noexcept
{
  bool r;

# if defined(i386) || defined(__i386) || defined(__i386__)
  asm (
    "movl %%esp, %0\n\t" // store sp
    "movl %%ebp, %1\n\t" // store bp
    "lea 1f, %%eax\n\t" // load label
    "movl %%eax, %2\n\t" // store label
    "movb $0, %3\n\t" // return false
    "jmp 2f\n\t"
    "1:"
    "movb $1, %3\n\t" // return true
    "2:"
    : "=m" (ssb.sp), "=m" (ssb.bp), "=m" (ssb.label), "=r" (r)
    :
    : "eax", "memory"
  );
# elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) ||\
   defined(__x86_64)
  asm (
    "movq %%rsp, %0\n\t" // store sp
    "lea 1f(%%rip), %%rax\n\t" // load label
    "movq %%rax, %1\n\t" // store label
    "movb $0, %2\n\t" // return false
    "jmp 2f\n\t"
    "1:"
    "movb $1, %2\n\t" // return true
    "2:"
    : "=m" (ssb.sp), "=m" (ssb.label), "=r" (r)
    :
    : "rax", "memory"
  );
# elif defined(__arm__)
  asm (
    "str sp, %0\n\t" // store sp
    "ldr r0, =1f\n\t" // load label
    "str r0, %1\n\t" // store label
    "mov %2, $0\n\t" // store 0 into result
    "b 2f\n\t"
    "1:"
    "mov %2, $1\n\t" // store 1 into result
    "2:"
    : "=m" (ssb.sp), "=m" (ssb.label), "=r" (r)
    :
    : "r0", "memory"
  );
# elif defined(__aarch64__)
  asm (
    "mov x0, sp\n\t"
    "str x0, %0\n\t" // store sp
    "ldr x0, =1f\n\t" // load label
    "str x0, %1\n\t" // store label
    "mov %w2, #0\n\t" // store 0 into result
    "b 2f\n\t"
    "1:"
    "mov %w2, #1\n\t" // store 1 into result
    "2:"
    : "=m" (ssb.sp), "=m" (ssb.label), "=r" (r)
    :
    : "x0", "memory"
  );
# else
#  error "unsupported architecture"
# endif

  return r;
}
#else
# error "unsupported compiler"
#endif

#if defined(__GNUC__)
# if defined(i386) || defined(__i386) || defined(__i386__)
#  define restorestate(SSB)                        \
    asm (                                          \
      "movl %0, %%esp\n\t"                         \
      "movl %1, %%ebp\n\t"                         \
      "jmp *%2"                                    \
      :                                            \
      : "m" (SSB.sp), "m" (SSB.bp), "m" (SSB.label)\
    );                                             \
    __builtin_unreachable();
# elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) ||\
   defined(__x86_64)
#  define restorestate(SSB)          \
    asm (                            \
      "movq %0, %%rsp\n\t"           \
      "jmp *%1"                      \
      :                              \
      : "m" (SSB.sp), "m" (SSB.label)\
    );                               \
    __builtin_unreachable();
# elif defined(__arm__)
#  define restorestate(SSB)          \
    asm (                            \
      "mov sp, %0\n\t"               \
      "mov pc, %1"                   \
      :                              \
      : "r" (SSB.sp), "r" (SSB.label)\
    );                               \
    __builtin_unreachable();
# elif defined(__aarch64__)
#  define restorestate(SSB)          \
    asm (                            \
      "mov sp, %0\n\t"               \
      "ret %1"                       \
      :                              \
      : "r" (SSB.sp), "r" (SSB.label)\
    );                               \
    __builtin_unreachable();
# else
#  error "unsupported architecture"
# endif
#else
# error "unsupported compiler"
#endif

#endif // CR_SAVESTATE_HPP
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id$

#ifndef FEATURE_STYLE_PROCESSOR_HPP
#define FEATURE_STYLE_PROCESSOR_HPP

//stl
#include <vector>
// boost
#include <boost/progress.hpp>
// mapnik
#include <mapnik/envelope.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/map.hpp>
#include <mapnik/attribute_collector.hpp>
#include <mapnik/utils.hpp>
#include <mapnik/projection.hpp>

namespace mapnik
{
    template <typename Processor>
    class feature_style_processor
    {
        struct symbol_dispatch : public boost::static_visitor<>
        {
            symbol_dispatch (Processor & output,
                             Feature const& f,
                             proj_transform const& prj_trans)
                : output_(output),
                  f_(f),
                  prj_trans_(prj_trans)  {}

            template <typename T>
            void operator () (T const& sym) const
            {
                output_.process(sym,f_,prj_trans_);
            }

            Processor & output_;
            Feature const& f_;
            proj_transform const& prj_trans_;
        };
    public:
        feature_style_processor(Map const& m)
            : m_(m) {}

        void apply()
        {
            boost::progress_timer t;

            Processor & p = static_cast<Processor&>(*this);

            p.start_map_processing(m_);

            std::vector<Layer>::const_iterator itr = m_.layers().begin();
            std::vector<Layer>::const_iterator end = m_.layers().end();

            try
            {
                projection proj(m_.srs()); // map projection

                while (itr != end)
                {
                    if (itr->isVisible(m_.scale()))// &&
                        //itr->envelope().intersects(m_.getCurrentExtent())) TODO
                    {
                        apply_to_layer(*itr, p, proj);
                    }
                    ++itr;
                }
            }
            catch (proj_init_error& ex)
            {
                std::clog << ex.what() << "\n";
            }

            p.end_map_processing(m_);
        }
    private:
        void apply_to_layer(Layer const& lay, Processor & p, projection const& proj0)
        {
            p.start_layer_processing(lay);
            boost::shared_ptr<datasource> ds=lay.datasource();
            if (ds)
            {
                Envelope<double> const& ext=m_.getCurrentExtent();

                projection proj1(lay.srs());
                proj_transform prj_trans(proj0,proj1);

                double x0 = ext.minx();
                double y0 = ext.miny();
                double z0 = 0.0;
                double x1 = ext.maxx();
                double y1 = ext.maxy();
                double z1 = 0.0;
                prj_trans.forward(x0,y0,z0);
                prj_trans.forward(x1,y1,z1);
                Envelope<double> bbox(x0,y0,x1,y1);
                std::clog << bbox << "\n";

                double scale = m_.scale();

                std::vector<std::string> const& style_names = lay.styles();
                std::vector<std::string>::const_iterator stylesIter = style_names.begin();
                std::vector<std::string>::const_iterator stylesEnd = style_names.end();

                while (stylesIter != stylesEnd)
                {
                    std::set<std::string> names;
                    attribute_collector<Feature> collector(names);
                    std::vector<rule_type*> if_rules;
                    std::vector<rule_type*> else_rules;

                    bool active_rules=false;

                    feature_type_style const& style=m_.find_style(*stylesIter++);

                    query q(bbox); //BBOX query

                    const std::vector<rule_type>& rules=style.get_rules();
                    std::vector<rule_type>::const_iterator ruleIter=rules.begin();
                    std::vector<rule_type>::const_iterator ruleEnd=rules.end();

                    while (ruleIter!=ruleEnd)
                    {
                        if (ruleIter->active(scale))
                        {
                            active_rules=true;
                            ruleIter->accept(collector);

                            if (ruleIter->has_else_filter())
                            {
                                else_rules.push_back(const_cast<rule_type*>(&(*ruleIter)));
                            }
                            else
                            {
                                if_rules.push_back(const_cast<rule_type*>(&(*ruleIter)));
                            }
                        }
                        ++ruleIter;
                    }
                    std::set<std::string>::const_iterator namesIter=names.begin();
                    std::set<std::string>::const_iterator namesEnd =names.end();

                    // push all property names
                    while (namesIter!=namesEnd)
                    {
                        q.add_property_name(*namesIter);
                        ++namesIter;
                    }
                    if (active_rules)
                    {
                        featureset_ptr fs=ds->features(q);
                        if (fs)
                        {
                            feature_ptr feature;
                            while ((feature = fs->next()))
                            {
                                bool do_else=true;
                                std::vector<rule_type*>::const_iterator itr=if_rules.begin();
                                std::vector<rule_type*>::const_iterator end=if_rules.end();
                                while (itr != end)
                                {
                                    filter_ptr const& filter=(*itr)->get_filter();
                                    if (filter->pass(*feature))
                                    {
                                        do_else=false;
                                        const symbolizers& symbols = (*itr)->get_symbolizers();
                                        symbolizers::const_iterator symIter=symbols.begin();
                                        symbolizers::const_iterator symEnd =symbols.end();
                                        while (symIter != symEnd)
                                        {
                                            boost::apply_visitor
                                                (symbol_dispatch(p,*feature,prj_trans),*symIter++);
                                        }
                                    }
                                    ++itr;
                                }
                                if (do_else)
                                {
                                    //else filter
                                    std::vector<rule_type*>::const_iterator itr=
                                        else_rules.begin();
                                    std::vector<rule_type*>::const_iterator end=
                                        else_rules.end();
                                    while (itr != end)
                                    {
                                        const symbolizers& symbols = (*itr)->get_symbolizers();
                                        symbolizers::const_iterator symIter= symbols.begin();
                                        symbolizers::const_iterator symEnd = symbols.end();

                                        while (symIter!=symEnd)
                                        {
                                            boost::apply_visitor
                                                (symbol_dispatch(p,*feature,prj_trans),
                                                 *symIter++);
                                        }
                                        ++itr;
                                    }
                                }
                            }
                        }
                    }
                }

            }
            p.end_layer_processing(lay);
        }
        Map const& m_;
    };
}

#endif //FEATURE_STYLE_PROCESSOR_HPP
<commit_msg>changed boost::progress_timer to output to std::clog (which defaults to std::cerr)<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id$

#ifndef FEATURE_STYLE_PROCESSOR_HPP
#define FEATURE_STYLE_PROCESSOR_HPP

//stl
#include <vector>
// boost
#include <boost/progress.hpp>
// mapnik
#include <mapnik/envelope.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/map.hpp>
#include <mapnik/attribute_collector.hpp>
#include <mapnik/utils.hpp>
#include <mapnik/projection.hpp>

namespace mapnik
{
    template <typename Processor>
    class feature_style_processor
    {
        struct symbol_dispatch : public boost::static_visitor<>
        {
            symbol_dispatch (Processor & output,
                             Feature const& f,
                             proj_transform const& prj_trans)
                : output_(output),
                  f_(f),
                  prj_trans_(prj_trans)  {}

            template <typename T>
            void operator () (T const& sym) const
            {
                output_.process(sym,f_,prj_trans_);
            }

            Processor & output_;
            Feature const& f_;
            proj_transform const& prj_trans_;
        };
    public:
        feature_style_processor(Map const& m)
            : m_(m) {}

        void apply()
        {
            boost::progress_timer t(std::clog);

            Processor & p = static_cast<Processor&>(*this);

            p.start_map_processing(m_);

            std::vector<Layer>::const_iterator itr = m_.layers().begin();
            std::vector<Layer>::const_iterator end = m_.layers().end();

            try
            {
                projection proj(m_.srs()); // map projection

                while (itr != end)
                {
                    if (itr->isVisible(m_.scale()))// &&
                        //itr->envelope().intersects(m_.getCurrentExtent())) TODO
                    {
                        apply_to_layer(*itr, p, proj);
                    }
                    ++itr;
                }
            }
            catch (proj_init_error& ex)
            {
                std::clog << ex.what() << "\n";
            }

            p.end_map_processing(m_);
        }
    private:
        void apply_to_layer(Layer const& lay, Processor & p, projection const& proj0)
        {
            p.start_layer_processing(lay);
            boost::shared_ptr<datasource> ds=lay.datasource();
            if (ds)
            {
                Envelope<double> const& ext=m_.getCurrentExtent();

                projection proj1(lay.srs());
                proj_transform prj_trans(proj0,proj1);

                double x0 = ext.minx();
                double y0 = ext.miny();
                double z0 = 0.0;
                double x1 = ext.maxx();
                double y1 = ext.maxy();
                double z1 = 0.0;
                prj_trans.forward(x0,y0,z0);
                prj_trans.forward(x1,y1,z1);
                Envelope<double> bbox(x0,y0,x1,y1);
                std::clog << bbox << "\n";

                double scale = m_.scale();

                std::vector<std::string> const& style_names = lay.styles();
                std::vector<std::string>::const_iterator stylesIter = style_names.begin();
                std::vector<std::string>::const_iterator stylesEnd = style_names.end();

                while (stylesIter != stylesEnd)
                {
                    std::set<std::string> names;
                    attribute_collector<Feature> collector(names);
                    std::vector<rule_type*> if_rules;
                    std::vector<rule_type*> else_rules;

                    bool active_rules=false;

                    feature_type_style const& style=m_.find_style(*stylesIter++);

                    query q(bbox); //BBOX query

                    const std::vector<rule_type>& rules=style.get_rules();
                    std::vector<rule_type>::const_iterator ruleIter=rules.begin();
                    std::vector<rule_type>::const_iterator ruleEnd=rules.end();

                    while (ruleIter!=ruleEnd)
                    {
                        if (ruleIter->active(scale))
                        {
                            active_rules=true;
                            ruleIter->accept(collector);

                            if (ruleIter->has_else_filter())
                            {
                                else_rules.push_back(const_cast<rule_type*>(&(*ruleIter)));
                            }
                            else
                            {
                                if_rules.push_back(const_cast<rule_type*>(&(*ruleIter)));
                            }
                        }
                        ++ruleIter;
                    }
                    std::set<std::string>::const_iterator namesIter=names.begin();
                    std::set<std::string>::const_iterator namesEnd =names.end();

                    // push all property names
                    while (namesIter!=namesEnd)
                    {
                        q.add_property_name(*namesIter);
                        ++namesIter;
                    }
                    if (active_rules)
                    {
                        featureset_ptr fs=ds->features(q);
                        if (fs)
                        {
                            feature_ptr feature;
                            while ((feature = fs->next()))
                            {
                                bool do_else=true;
                                std::vector<rule_type*>::const_iterator itr=if_rules.begin();
                                std::vector<rule_type*>::const_iterator end=if_rules.end();
                                while (itr != end)
                                {
                                    filter_ptr const& filter=(*itr)->get_filter();
                                    if (filter->pass(*feature))
                                    {
                                        do_else=false;
                                        const symbolizers& symbols = (*itr)->get_symbolizers();
                                        symbolizers::const_iterator symIter=symbols.begin();
                                        symbolizers::const_iterator symEnd =symbols.end();
                                        while (symIter != symEnd)
                                        {
                                            boost::apply_visitor
                                                (symbol_dispatch(p,*feature,prj_trans),*symIter++);
                                        }
                                    }
                                    ++itr;
                                }
                                if (do_else)
                                {
                                    //else filter
                                    std::vector<rule_type*>::const_iterator itr=
                                        else_rules.begin();
                                    std::vector<rule_type*>::const_iterator end=
                                        else_rules.end();
                                    while (itr != end)
                                    {
                                        const symbolizers& symbols = (*itr)->get_symbolizers();
                                        symbolizers::const_iterator symIter= symbols.begin();
                                        symbolizers::const_iterator symEnd = symbols.end();

                                        while (symIter!=symEnd)
                                        {
                                            boost::apply_visitor
                                                (symbol_dispatch(p,*feature,prj_trans),
                                                 *symIter++);
                                        }
                                        ++itr;
                                    }
                                }
                            }
                        }
                    }
                }

            }
            p.end_layer_processing(lay);
        }
        Map const& m_;
    };
}

#endif //FEATURE_STYLE_PROCESSOR_HPP
<|endoftext|>