<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "3DChartObjects.hxx"
#include <vcl/virdev.hxx>
#include <vcl/svapp.hxx>

#include <vcl/opengl/OpenGLHelper.hxx>

namespace chart {

namespace opengl3D {

Renderable3DObject::Renderable3DObject(OpenGL3DRenderer* pRenderer, sal_uInt32 nId):
    mpRenderer(pRenderer),
    mnUniqueId(nId)
{
}

void Renderable3DObject::render()
{
    (void) mnUniqueId;
}

Bar::Bar(OpenGL3DRenderer* pRenderer, const glm::mat4& rPosition, sal_uInt32 aColor, sal_uInt32 nId)
    : Renderable3DObject(pRenderer, nId)
    , mbRoundedCorners(true)
    , maPos(rPosition)
    , maColor(aColor)
{
    SAL_INFO("chart2.3dopengl", rPosition);
}

void Bar::render()
{
    mpRenderer->AddShape3DExtrudeObject(mbRoundedCorners, maColor.GetColor(), 0xFFFFFF, maPos, mnUniqueId);
    mpRenderer->EndAddShape3DExtrudeObject();
}

Line::Line(OpenGL3DRenderer* pRenderer, sal_uInt32 nId):
    Renderable3DObject(pRenderer, nId)
{
}

void Line::render()
{
    mpRenderer->AddShapePolygon3DObject(0, true, maLineColor.GetColor(), 0, 0, mnUniqueId);
    mpRenderer->AddPolygon3DObjectPoint(maPosBegin.x, maPosBegin.y, maPosBegin.z);
    mpRenderer->AddPolygon3DObjectPoint(maPosEnd.x, maPosEnd.y, maPosEnd.z);
    mpRenderer->EndAddPolygon3DObjectPoint();
    mpRenderer->EndAddShapePolygon3DObject();
}

void Line::setPosition(const glm::vec3& rBegin, const glm::vec3& rEnd)
{
    maPosBegin = rBegin;
    maPosEnd = rEnd;
}

void Line::setLineColor(const Color& rColor)
{
    maLineColor = rColor;
}

const BitmapEx& TextCache::getText(OUString rText)
{
    TextCacheType::const_iterator itr = maTextCache.find(rText);
    if(itr != maTextCache.end())
        return *itr->second;

    VirtualDevice aDevice(*Application::GetDefaultDevice(), 0, 0);
    Font aFont = aDevice.GetFont();
    aFont.SetSize(Size(0, 96));
    aFont.SetColor(COL_BLACK);
    ::Rectangle aRect;
    aDevice.SetFont(aFont);
    aDevice.Erase();
    aDevice.GetTextBoundRect(aRect, rText);
    Size aSize = aRect.GetSize();
    aSize.Width() += 5;
    aSize.Height() *= 1.6;
    aDevice.SetOutputSizePixel(aSize);
    aDevice.SetBackground(Wallpaper(COL_TRANSPARENT));
    aDevice.DrawText(Point(0,0), rText);

    BitmapEx* pText = new BitmapEx(aDevice.GetBitmapEx(Point(0,0), aSize));
    maTextCache.insert(rText, pText);
    return *pText;
}

Text::Text(OpenGL3DRenderer* pRenderer, TextCache& rTextCache, const OUString& rStr, sal_uInt32 nId):
    Renderable3DObject(pRenderer, nId),
    mrText(rTextCache.getText(rStr))
{
}

void Text::render()
{
    glm::vec3 dir2 = maTopRight - maTopLeft;
    glm::vec3 bottomLeft = maBottomRight - dir2;
    mpRenderer->CreateTextTexture(mrText, maTopLeft, maTopRight, maBottomRight, bottomLeft, mnUniqueId);
}

Size Text::getSize() const
{
    return mrText.GetSizePixel();
}

void Text::setPosition(const glm::vec3& rTopLeft, const glm::vec3& rTopRight, const glm::vec3& rBottomRight)
{
    maTopLeft = rTopLeft;
    maTopRight = rTopRight;
    maBottomRight = rBottomRight;
}

Rectangle::Rectangle(OpenGL3DRenderer* pRenderer, sal_uInt32 nId):
    Renderable3DObject(pRenderer, nId)
{
}

void Rectangle::render()
{
    glm::vec3 dir1 = maBottomRight - maTopLeft;
    glm::vec3 dir2 = maTopRight - maTopLeft;
    glm::vec3 normal = glm::normalize(glm::cross(dir1, dir2));
    mpRenderer->AddShapePolygon3DObject(maColor.GetColor(), false, 0, 1, 0xFFFFFF, mnUniqueId);
    glm::vec3 bottomLeft = maBottomRight - dir2;
    //set polygon points and normals
    mpRenderer->AddPolygon3DObjectPoint(maBottomRight.x, maBottomRight.y, maBottomRight.z);
    mpRenderer->AddPolygon3DObjectNormalPoint(normal.x, normal.y, normal.z);
    mpRenderer->AddPolygon3DObjectPoint(maTopRight.x, maTopRight.y, maTopRight.z);
    mpRenderer->AddPolygon3DObjectNormalPoint(normal.x, normal.y, normal.z);
    mpRenderer->AddPolygon3DObjectPoint(maTopLeft.x, maTopLeft.y, maTopLeft.z);
    mpRenderer->AddPolygon3DObjectNormalPoint(normal.x, normal.y, normal.z);
    mpRenderer->AddPolygon3DObjectPoint(bottomLeft.x, bottomLeft.y, bottomLeft.z);
    mpRenderer->AddPolygon3DObjectNormalPoint(normal.x, normal.y, normal.z);
    mpRenderer->EndAddPolygon3DObjectPoint();
    mpRenderer->EndAddPolygon3DObjectNormalPoint();
    mpRenderer->EndAddShapePolygon3DObject();
    //we should render the edge if the edge color is different from the fill color
    if (maColor.GetColor() != maLineColor.GetColor())
    {
        mpRenderer->AddShapePolygon3DObject(0, true, maLineColor.GetColor(), 0, 0xFFFFFF, mnUniqueId);
        mpRenderer->AddPolygon3DObjectPoint(maBottomRight.x, maBottomRight.y, maBottomRight.z);
        mpRenderer->AddPolygon3DObjectPoint(maTopRight.x, maTopRight.y, maTopRight.z);
        mpRenderer->AddPolygon3DObjectPoint(maTopLeft.x, maTopLeft.y, maTopLeft.z);
        mpRenderer->AddPolygon3DObjectPoint(bottomLeft.x, bottomLeft.y, bottomLeft.z);
        mpRenderer->EndAddPolygon3DObjectPoint();
        mpRenderer->EndAddShapePolygon3DObject();
    }
}

void Rectangle::setPosition(const glm::vec3& rTopLeft, const glm::vec3& rTopRight, const glm::vec3& rBottomRight)
{
    maTopLeft = rTopLeft;
    maTopRight = rTopRight;
    maBottomRight = rBottomRight;
}

void Rectangle::setFillColor(const Color& rColor)
{
    maColor = rColor;
}

void Rectangle::setLineColor(const Color& rColor)
{
    maLineColor = rColor;
}

Camera::Camera(OpenGL3DRenderer* pRenderer):
    Renderable3DObject(pRenderer, 0),
    maPos(10,-50,20),
    maUp(0, 0, 1),
    maDirection(glm::vec3(0,0,0))
{
}

void Camera::render()
{
    mpRenderer->SetCameraInfo(maPos, maDirection, maUp);
}

void Camera::setPosition(const glm::vec3& rPos)
{
    maPos = rPos;
}

void Camera::setDirection(const glm::vec3& rDir)
{
    maDirection = rDir;
}

void Camera::zoom(sal_uInt32 /*nId*/)
{
    // TODO here
}

}

}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Improve computation of the text area to make it nicer.<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "3DChartObjects.hxx"
#include <vcl/virdev.hxx>
#include <vcl/svapp.hxx>

#include <vcl/opengl/OpenGLHelper.hxx>

namespace chart {

namespace opengl3D {

Renderable3DObject::Renderable3DObject(OpenGL3DRenderer* pRenderer, sal_uInt32 nId):
    mpRenderer(pRenderer),
    mnUniqueId(nId)
{
}

void Renderable3DObject::render()
{
    (void) mnUniqueId;
}

Bar::Bar(OpenGL3DRenderer* pRenderer, const glm::mat4& rPosition, sal_uInt32 aColor, sal_uInt32 nId)
    : Renderable3DObject(pRenderer, nId)
    , mbRoundedCorners(true)
    , maPos(rPosition)
    , maColor(aColor)
{
    SAL_INFO("chart2.3dopengl", rPosition);
}

void Bar::render()
{
    mpRenderer->AddShape3DExtrudeObject(mbRoundedCorners, maColor.GetColor(), 0xFFFFFF, maPos, mnUniqueId);
    mpRenderer->EndAddShape3DExtrudeObject();
}

Line::Line(OpenGL3DRenderer* pRenderer, sal_uInt32 nId):
    Renderable3DObject(pRenderer, nId)
{
}

void Line::render()
{
    mpRenderer->AddShapePolygon3DObject(0, true, maLineColor.GetColor(), 0, 0, mnUniqueId);
    mpRenderer->AddPolygon3DObjectPoint(maPosBegin.x, maPosBegin.y, maPosBegin.z);
    mpRenderer->AddPolygon3DObjectPoint(maPosEnd.x, maPosEnd.y, maPosEnd.z);
    mpRenderer->EndAddPolygon3DObjectPoint();
    mpRenderer->EndAddShapePolygon3DObject();
}

void Line::setPosition(const glm::vec3& rBegin, const glm::vec3& rEnd)
{
    maPosBegin = rBegin;
    maPosEnd = rEnd;
}

void Line::setLineColor(const Color& rColor)
{
    maLineColor = rColor;
}

const BitmapEx& TextCache::getText(OUString rText)
{
    TextCacheType::const_iterator itr = maTextCache.find(rText);
    if(itr != maTextCache.end())
        return *itr->second;

    VirtualDevice aDevice(*Application::GetDefaultDevice(), 0, 0);
    Font aFont = aDevice.GetFont();
    aFont.SetSize(Size(0, 96));
    aFont.SetColor(COL_BLACK);
    aDevice.SetFont(aFont);
    aDevice.Erase();

    aDevice.SetOutputSize(Size(aDevice.GetTextWidth(rText), aDevice.GetTextHeight()));
    aDevice.SetBackground(Wallpaper(COL_TRANSPARENT));
    aDevice.DrawText(Point(0,0), rText);

    BitmapEx* pText = new BitmapEx(aDevice.GetBitmapEx(Point(0,0), aDevice.GetOutputSize()));
    maTextCache.insert(rText, pText);
    return *pText;
}

Text::Text(OpenGL3DRenderer* pRenderer, TextCache& rTextCache, const OUString& rStr, sal_uInt32 nId):
    Renderable3DObject(pRenderer, nId),
    mrText(rTextCache.getText(rStr))
{
}

void Text::render()
{
    glm::vec3 dir2 = maTopRight - maTopLeft;
    glm::vec3 bottomLeft = maBottomRight - dir2;
    mpRenderer->CreateTextTexture(mrText, maTopLeft, maTopRight, maBottomRight, bottomLeft, mnUniqueId);
}

Size Text::getSize() const
{
    return mrText.GetSizePixel();
}

void Text::setPosition(const glm::vec3& rTopLeft, const glm::vec3& rTopRight, const glm::vec3& rBottomRight)
{
    maTopLeft = rTopLeft;
    maTopRight = rTopRight;
    maBottomRight = rBottomRight;
}

Rectangle::Rectangle(OpenGL3DRenderer* pRenderer, sal_uInt32 nId):
    Renderable3DObject(pRenderer, nId)
{
}

void Rectangle::render()
{
    glm::vec3 dir1 = maBottomRight - maTopLeft;
    glm::vec3 dir2 = maTopRight - maTopLeft;
    glm::vec3 normal = glm::normalize(glm::cross(dir1, dir2));
    mpRenderer->AddShapePolygon3DObject(maColor.GetColor(), false, 0, 1, 0xFFFFFF, mnUniqueId);
    glm::vec3 bottomLeft = maBottomRight - dir2;
    //set polygon points and normals
    mpRenderer->AddPolygon3DObjectPoint(maBottomRight.x, maBottomRight.y, maBottomRight.z);
    mpRenderer->AddPolygon3DObjectNormalPoint(normal.x, normal.y, normal.z);
    mpRenderer->AddPolygon3DObjectPoint(maTopRight.x, maTopRight.y, maTopRight.z);
    mpRenderer->AddPolygon3DObjectNormalPoint(normal.x, normal.y, normal.z);
    mpRenderer->AddPolygon3DObjectPoint(maTopLeft.x, maTopLeft.y, maTopLeft.z);
    mpRenderer->AddPolygon3DObjectNormalPoint(normal.x, normal.y, normal.z);
    mpRenderer->AddPolygon3DObjectPoint(bottomLeft.x, bottomLeft.y, bottomLeft.z);
    mpRenderer->AddPolygon3DObjectNormalPoint(normal.x, normal.y, normal.z);
    mpRenderer->EndAddPolygon3DObjectPoint();
    mpRenderer->EndAddPolygon3DObjectNormalPoint();
    mpRenderer->EndAddShapePolygon3DObject();
    //we should render the edge if the edge color is different from the fill color
    if (maColor.GetColor() != maLineColor.GetColor())
    {
        mpRenderer->AddShapePolygon3DObject(0, true, maLineColor.GetColor(), 0, 0xFFFFFF, mnUniqueId);
        mpRenderer->AddPolygon3DObjectPoint(maBottomRight.x, maBottomRight.y, maBottomRight.z);
        mpRenderer->AddPolygon3DObjectPoint(maTopRight.x, maTopRight.y, maTopRight.z);
        mpRenderer->AddPolygon3DObjectPoint(maTopLeft.x, maTopLeft.y, maTopLeft.z);
        mpRenderer->AddPolygon3DObjectPoint(bottomLeft.x, bottomLeft.y, bottomLeft.z);
        mpRenderer->EndAddPolygon3DObjectPoint();
        mpRenderer->EndAddShapePolygon3DObject();
    }
}

void Rectangle::setPosition(const glm::vec3& rTopLeft, const glm::vec3& rTopRight, const glm::vec3& rBottomRight)
{
    maTopLeft = rTopLeft;
    maTopRight = rTopRight;
    maBottomRight = rBottomRight;
}

void Rectangle::setFillColor(const Color& rColor)
{
    maColor = rColor;
}

void Rectangle::setLineColor(const Color& rColor)
{
    maLineColor = rColor;
}

Camera::Camera(OpenGL3DRenderer* pRenderer):
    Renderable3DObject(pRenderer, 0),
    maPos(10,-50,20),
    maUp(0, 0, 1),
    maDirection(glm::vec3(0,0,0))
{
}

void Camera::render()
{
    mpRenderer->SetCameraInfo(maPos, maDirection, maUp);
}

void Camera::setPosition(const glm::vec3& rPos)
{
    maPos = rPos;
}

void Camera::setDirection(const glm::vec3& rDir)
{
    maDirection = rDir;
}

void Camera::zoom(sal_uInt32 /*nId*/)
{
    // TODO here
}

}

}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ftpcontentidentifier.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-20 05:23:36 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

/**************************************************************************
                                TODO
 **************************************************************************

 *************************************************************************/
#ifndef _FTP_FTPCONTENTIDENTIFIER_HXX_
#define _FTP_FTPCONTENTIDENTIFIER_HXX_

#include <vector>
#include "curl.hxx"
#include <curl/easy.h>
#include <cppuhelper/weak.hxx>
#include <cppuhelper/queryinterface.hxx>
#include <com/sun/star/ucb/XContentIdentifier.hpp>
#include <com/sun/star/lang/XTypeProvider.hpp>

#include "ftpdirp.hxx"
#include "ftpurl.hxx"

namespace ftp {

    class FTPContentProvider;

    class FTPContentIdentifier
        : public cppu::OWeakObject,
          public com::sun::star::lang::XTypeProvider,
          public com::sun::star::ucb::XContentIdentifier
    {
    public:

        FTPContentIdentifier(const rtl::OUString& ident);

        ~FTPContentIdentifier();

        // XInterface

        virtual com::sun::star::uno::Any SAL_CALL
        queryInterface( const com::sun::star::uno::Type& rType )
            throw( com::sun::star::uno::RuntimeException );

        virtual void SAL_CALL acquire( void ) throw();

        virtual void SAL_CALL release( void ) throw();

        // XTypeProvider

        virtual
        com::sun::star::uno::Sequence<com::sun::star::uno::Type> SAL_CALL
        getTypes(
        )
            throw(
                com::sun::star::uno::RuntimeException
            );

        virtual com::sun::star::uno::Sequence<sal_Int8> SAL_CALL
        getImplementationId(
        )
            throw(
                com::sun::star::uno::RuntimeException
            );

        // XContentIdentifier

        virtual ::rtl::OUString SAL_CALL
        getContentIdentifier(
        )
            throw (
                com::sun::star::uno::RuntimeException
            );

        virtual ::rtl::OUString SAL_CALL
        getContentProviderScheme(
        )
            throw (
                ::com::sun::star::uno::RuntimeException
            );

    private:

        rtl::OUString m_ident;
    };

}

#endif
<commit_msg>INTEGRATION: CWS changefileheader (1.7.138); FILE MERGED 2008/03/31 15:30:19 rt 1.7.138.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: ftpcontentidentifier.hxx,v $
 * $Revision: 1.8 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

/**************************************************************************
                                TODO
 **************************************************************************

 *************************************************************************/
#ifndef _FTP_FTPCONTENTIDENTIFIER_HXX_
#define _FTP_FTPCONTENTIDENTIFIER_HXX_

#include <vector>
#include "curl.hxx"
#include <curl/easy.h>
#include <cppuhelper/weak.hxx>
#include <cppuhelper/queryinterface.hxx>
#include <com/sun/star/ucb/XContentIdentifier.hpp>
#include <com/sun/star/lang/XTypeProvider.hpp>

#include "ftpdirp.hxx"
#include "ftpurl.hxx"

namespace ftp {

    class FTPContentProvider;

    class FTPContentIdentifier
        : public cppu::OWeakObject,
          public com::sun::star::lang::XTypeProvider,
          public com::sun::star::ucb::XContentIdentifier
    {
    public:

        FTPContentIdentifier(const rtl::OUString& ident);

        ~FTPContentIdentifier();

        // XInterface

        virtual com::sun::star::uno::Any SAL_CALL
        queryInterface( const com::sun::star::uno::Type& rType )
            throw( com::sun::star::uno::RuntimeException );

        virtual void SAL_CALL acquire( void ) throw();

        virtual void SAL_CALL release( void ) throw();

        // XTypeProvider

        virtual
        com::sun::star::uno::Sequence<com::sun::star::uno::Type> SAL_CALL
        getTypes(
        )
            throw(
                com::sun::star::uno::RuntimeException
            );

        virtual com::sun::star::uno::Sequence<sal_Int8> SAL_CALL
        getImplementationId(
        )
            throw(
                com::sun::star::uno::RuntimeException
            );

        // XContentIdentifier

        virtual ::rtl::OUString SAL_CALL
        getContentIdentifier(
        )
            throw (
                com::sun::star::uno::RuntimeException
            );

        virtual ::rtl::OUString SAL_CALL
        getContentProviderScheme(
        )
            throw (
                ::com::sun::star::uno::RuntimeException
            );

    private:

        rtl::OUString m_ident;
    };

}

#endif
<|endoftext|>


<commit_before>/*
 * Copyright 2014 Kamil Michalak <kmichalak8@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#ifndef ASSERT_HPP
#define ASSERT_HPP

#include <gtest/gtest.h>

void EXPECT_SEME_ORDER(std::vector<std::string> vec, std::string *strings)
{
	int counter = 0;
	for (std::vector<std::string>::iterator it = vec.begin(); it != vec.end(); ++it) {
		EXPECT_EQ(0, strings[counter++].compare(*it));
	}

}

#endif // ASSERT_H<commit_msg>Define assertions in assert.hpp as an inlined functions<commit_after>/*
 * Copyright 2014 Kamil Michalak <kmichalak8@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#ifndef ASSERT_HPP
#define ASSERT_HPP

#include <gtest/gtest.h>

inline void EXPECT_SEME_ORDER(std::vector<std::string> vec, std::string *strings)
{
	int counter = 0;
	for (std::vector<std::string>::iterator it = vec.begin(); it != vec.end(); ++it) {
		EXPECT_EQ(0, strings[counter++].compare(*it));
	}

}

inline void EXPECT_STR_CONTAINS(std::string stringValue, std::string stringToSearch)
{
	std::size_t foundPos = stringValue.find(stringToSearch);
	EXPECT_NE(std::string::npos, foundPos);
}

#endif // ASSERT_H<|endoftext|>


<commit_before>#include "ride/finddlg.h"

#include "ride/wx.h"
#include "ride/generated/ui.h"
#include "ride/wxutils.h"

#include "wx/stc/stc.h"
#include "ride/settings.h"
#include <wx/dir.h>
#include "ride/mainwindow.h"
#include "ride/fileedit.h"

class FindDlg : public ui::Find {
public:
  FindDlg(wxWindow* parent, const wxString& find, const ride::FindDlg& data, FindAction find_action, FindScope find_scope);

  const wxString GetText() const {
    return uiFindText->GetValue();
  }

  const int GetFlags();

  void ToData(ride::FindDlg& data) const;

  wxStyledTextCtrl* GetStc() {
    return m_scintilla1;
  }

  bool LookInCurrentFile() const {
    return uiLookIn->GetSelection() == 0;
  }

  bool IsRecursive() const {
    return uiIncludeSubFolders->GetValue();
  }

  const wxString getReplaceText() const {
    return uiReplaceText->GetValue();
  }

  bool KeepFilesOpen() const {
    return uiKeepFilesOpen->GetValue();
  }

protected:
  void OnCancel(wxCommandEvent& event);
  void OnOk(wxCommandEvent& event);
  void OnEnter(wxCommandEvent& event) {
    OnOk(event);
  }
};

FindDlg::FindDlg(wxWindow* parent, const wxString& find, const ride::FindDlg& data, FindAction find_action, FindScope find_scope)
  : ui::Find(parent, wxID_ANY)
{
  uiFindText->SetValue(find);
  uiFindText->SelectAll();
  uiFindText->SetFocus();

  uiLookIn->Append("Current file");
  uiLookIn->Append("This project");
  uiLookIn->SetSelection(static_cast<int>(find_scope)); // assume the enum is file -> project

  uiFindTarget->Append("Normal text");
  uiFindTarget->Append("Regex");
  uiFindTarget->Append("Posix");

  uiIncludeSubFolders->SetValue(data.sub_folders());
  uiMatchCase->SetValue(data.match_case());
  uiMatchWholeWord->SetValue(data.match_whole_word());
  uiFindWordStart->SetValue(data.match_start());
  uiFileTypes->SetValue(data.file_types().c_str());
  uiFindTarget->SetSelection(data.target());

  uiReplaceStatic->Enable(find_action == FindAction::Replace);
  uiReplaceText->Enable(find_action == FindAction::Replace);
}

void FindDlg::ToData(ride::FindDlg& data) const {
  data.set_sub_folders(uiIncludeSubFolders->GetValue());
  data.set_match_case(uiMatchCase->GetValue());
  data.set_match_whole_word(uiMatchWholeWord->GetValue());
  data.set_match_start(uiFindWordStart->GetValue());
  data.set_file_types(uiFileTypes->GetValue());
  data.set_target(static_cast<::ride::FindDlgTarget>(uiFindTarget->GetSelection()));
}

void FindDlg::OnCancel(wxCommandEvent& event) {
  EndModal(wxID_CANCEL);
}

void FindDlg::OnOk(wxCommandEvent& event) {
  if (uiFindText->GetValue().length() <= 0) {
    ShowInfo(this, "Need to enter search text", "Missing Search Text");
    return;
  }
  EndModal(wxID_OK);
}

const int FindDlg::GetFlags() {
  int ret = 0;

  if (uiMatchCase->GetValue()) {
    ret |= wxSTC_FIND_MATCHCASE;
  }

  if (uiMatchWholeWord->GetValue()) {
    ret |= wxSTC_FIND_WHOLEWORD;
  }

  if (uiFindWordStart->GetValue()) {
    ret |= wxSTC_FIND_WORDSTART;
  }

  switch (uiFindTarget->GetSelection()) {
  case 0:
    break;
  case 1:
    ret |= wxSTC_FIND_REGEXP;
    break;
  case 2:
    ret |= wxSTC_FIND_POSIX;
    break;
  default:
    assert(false && "invalid selection");
    break;
  }

  return ret;
}

struct FindResult {
  FindResult(const wxString& f, const wxString& co, const int sl, const int sc, const int el, const int ec)
    : file(f)
    , content(co)
    , start_line(sl)
    , start_col(sc)
    , end_line(el)
    , end_col(ec)
  {
  }

  wxString file;
  wxString content;
  int start_line;
  int start_col;
  int end_line;
  int end_col;
};

int FindInStc(wxStyledTextCtrl* stc, const wxString& file, const wxString& text, int flags, std::vector<FindResult>* res,
  FindAction find_action, const wxString& replaceText) {
  assert(res);
  assert(stc);
  int next_index = 0;
  int count = 0;
  while (true) {
    int end_index = 0;
    const int start_index = stc->FindText(next_index, stc->GetLength(), text, &end_index, flags);
    if (start_index == -1) return count;
    assert(start_index != end_index);

    const int target_start_index = start_index;
    int target_end_index = end_index;

    // replace text
    if (find_action == FindAction::Replace) {
      stc->SetTargetStart(start_index);
      stc->SetTargetEnd(end_index);
      const bool useRegex = flags & wxSTC_FIND_REGEXP || flags & wxSTC_FIND_POSIX;
      const int change = useRegex
        ? stc->ReplaceTargetRE(replaceText)
       : stc->ReplaceTarget(replaceText);
      assert(change > 0);
      next_index = start_index + change;
      target_end_index = start_index + change;
    }
    else {
      next_index = end_index;
    }

    // add item to the result list
    const int start_line = stc->LineFromPosition(target_start_index);
    const int start_col = target_start_index - stc->PositionFromLine(target_start_index);
    const int end_line = stc->LineFromPosition(target_end_index);
    const int end_col = target_end_index - stc->PositionFromLine(end_line);
    res->push_back(FindResult(file, stc->GetLine(start_line).Trim(true).Trim(false), start_line + 1, start_col + 1, end_line + 1, end_col + 1));
    ++count;
  }

  return count;
}

void FindInFiles(MainWindow* parent, wxStyledTextCtrl* fallback, const wxString& file, const wxString& text, int flags,
  std::vector<FindResult>* res, FindAction find_action, const wxString& replaceText, bool keepFilesOpen) {
  FileEdit* edit = parent->GetFile(file);
  wxStyledTextCtrl* stc = NULL;
  if (edit) {
    stc = edit->GetStc();
  }
  else {
    fallback->LoadFile(file);

    if (find_action == FindAction::Replace && keepFilesOpen) {
      int found = fallback->FindText(0, stc->GetLength(), text, NULL, flags);
      if (found > 0) {
        FileEdit* opened_edit = parent->OpenFile(file);
        stc = opened_edit->GetStc();
      }
    }
    if( stc == NULL ) {
      stc = fallback;
    }
  }
  assert(stc);
  int count = FindInStc(stc, file, text, flags, res, find_action, replaceText);

  if (find_action == FindAction::Replace && count > 0 && stc == fallback) {
    if (false == stc->SaveFile(file)) {
      ShowError(parent, "Failed to save after replace!", "Error saving!");
    }
  }
}

bool ShowFindDlg(MainWindow* parent, const wxString& current_selection, const wxString& current_file,
  const wxString root_folder, wxStyledTextCtrl* output, FindAction find_action, FindScope find_scope) {
  static ride::FindDlg find_dlg_data;
  FindDlg dlg(parent, current_selection, find_dlg_data, find_action, find_scope);

  if (wxID_OK != dlg.ShowModal()) return false;
  dlg.ToData(find_dlg_data);

  std::vector<FindResult> results;
  wxString file_info = current_file;

  // we can't create a styled ctrl so we cheat by having a 0x0 widget on the find dlg
  // and use that for searching/replacing...
  wxStyledTextCtrl* fallback = dlg.GetStc();

  if (dlg.LookInCurrentFile()) {
    FindInFiles(parent, fallback, current_file, dlg.GetText(), dlg.GetFlags(), &results, find_action, dlg.getReplaceText(), dlg.KeepFilesOpen());
  }
  else {
    wxArrayString files;
    const std::vector<wxString> patterns = Split(find_dlg_data.file_types(), ";");
    size_t count = 0;
    for (const auto pattern : patterns) {
      count += wxDir::GetAllFiles(root_folder, &files, pattern,
        dlg.IsRecursive() ? wxDIR_FILES | wxDIR_DIRS : wxDIR_FILES);
    }

    file_info = wxString::Format("%d files in %s", count, root_folder);
    for (const auto file : files) {
      FindInFiles(parent, fallback, file, dlg.GetText(), dlg.GetFlags(), &results, find_action, dlg.getReplaceText(), dlg.KeepFilesOpen());
    }
  }

  const auto count = results.size();

  ClearOutput(output);

  const wxString find_text = find_action == FindAction::Find
    ? wxString::Format("Searched for '%s'", dlg.GetText())
    : wxString::Format("Replaced '%s' with '%s'", dlg.GetText(), dlg.getReplaceText());
  WriteLine(output, wxString::Format("%s in %s", find_text, file_info));
  WriteLine(output, wxString::Format("%s %d matches", find_action == FindAction::Find ? "Found" : "Replaced", count));
  WriteLine(output, "");
  for (auto res : results) {
    // try to format the same way rust related error looks like so we can reuse the parser code for both and get some synergy effects
    const wxString mess = wxString::Format("%s:%d : %d : %d : %d %s: %s", res.file, res.start_line, res.start_col, res.end_line, res.end_col, find_action == FindAction::Find ? "found" : "replaced", res.content);
    WriteLine(output, mess);
  }

  return true;
}
<commit_msg>Fixed wrong index bug<commit_after>#include "ride/finddlg.h"

#include "ride/wx.h"
#include "ride/generated/ui.h"
#include "ride/wxutils.h"

#include "wx/stc/stc.h"
#include "ride/settings.h"
#include <wx/dir.h>
#include "ride/mainwindow.h"
#include "ride/fileedit.h"

class FindDlg : public ui::Find {
public:
  FindDlg(wxWindow* parent, const wxString& find, const ride::FindDlg& data, FindAction find_action, FindScope find_scope);

  const wxString GetText() const {
    return uiFindText->GetValue();
  }

  const int GetFlags();

  void ToData(ride::FindDlg& data) const;

  wxStyledTextCtrl* GetStc() {
    return m_scintilla1;
  }

  bool LookInCurrentFile() const {
    return uiLookIn->GetSelection() == 0;
  }

  bool IsRecursive() const {
    return uiIncludeSubFolders->GetValue();
  }

  const wxString getReplaceText() const {
    return uiReplaceText->GetValue();
  }

  bool KeepFilesOpen() const {
    return uiKeepFilesOpen->GetValue();
  }

protected:
  void OnCancel(wxCommandEvent& event);
  void OnOk(wxCommandEvent& event);
  void OnEnter(wxCommandEvent& event) {
    OnOk(event);
  }
};

FindDlg::FindDlg(wxWindow* parent, const wxString& find, const ride::FindDlg& data, FindAction find_action, FindScope find_scope)
  : ui::Find(parent, wxID_ANY)
{
  uiFindText->SetValue(find);
  uiFindText->SelectAll();
  uiFindText->SetFocus();

  uiLookIn->Append("Current file");
  uiLookIn->Append("This project");
  uiLookIn->SetSelection(static_cast<int>(find_scope)); // assume the enum is file -> project

  uiFindTarget->Append("Normal text");
  uiFindTarget->Append("Regex");
  uiFindTarget->Append("Posix");

  uiIncludeSubFolders->SetValue(data.sub_folders());
  uiMatchCase->SetValue(data.match_case());
  uiMatchWholeWord->SetValue(data.match_whole_word());
  uiFindWordStart->SetValue(data.match_start());
  uiFileTypes->SetValue(data.file_types().c_str());
  uiFindTarget->SetSelection(data.target());

  uiReplaceStatic->Enable(find_action == FindAction::Replace);
  uiReplaceText->Enable(find_action == FindAction::Replace);
}

void FindDlg::ToData(ride::FindDlg& data) const {
  data.set_sub_folders(uiIncludeSubFolders->GetValue());
  data.set_match_case(uiMatchCase->GetValue());
  data.set_match_whole_word(uiMatchWholeWord->GetValue());
  data.set_match_start(uiFindWordStart->GetValue());
  data.set_file_types(uiFileTypes->GetValue());
  data.set_target(static_cast<::ride::FindDlgTarget>(uiFindTarget->GetSelection()));
}

void FindDlg::OnCancel(wxCommandEvent& event) {
  EndModal(wxID_CANCEL);
}

void FindDlg::OnOk(wxCommandEvent& event) {
  if (uiFindText->GetValue().length() <= 0) {
    ShowInfo(this, "Need to enter search text", "Missing Search Text");
    return;
  }
  EndModal(wxID_OK);
}

const int FindDlg::GetFlags() {
  int ret = 0;

  if (uiMatchCase->GetValue()) {
    ret |= wxSTC_FIND_MATCHCASE;
  }

  if (uiMatchWholeWord->GetValue()) {
    ret |= wxSTC_FIND_WHOLEWORD;
  }

  if (uiFindWordStart->GetValue()) {
    ret |= wxSTC_FIND_WORDSTART;
  }

  switch (uiFindTarget->GetSelection()) {
  case 0:
    break;
  case 1:
    ret |= wxSTC_FIND_REGEXP;
    break;
  case 2:
    ret |= wxSTC_FIND_POSIX;
    break;
  default:
    assert(false && "invalid selection");
    break;
  }

  return ret;
}

struct FindResult {
  FindResult(const wxString& f, const wxString& co, const int sl, const int sc, const int el, const int ec)
    : file(f)
    , content(co)
    , start_line(sl)
    , start_col(sc)
    , end_line(el)
    , end_col(ec)
  {
  }

  wxString file;
  wxString content;
  int start_line;
  int start_col;
  int end_line;
  int end_col;
};

int FindInStc(wxStyledTextCtrl* stc, const wxString& file, const wxString& text, int flags, std::vector<FindResult>* res,
  FindAction find_action, const wxString& replaceText) {
  assert(res);
  assert(stc);
  int next_index = 0;
  int count = 0;
  while (true) {
    int end_index = 0;
    const int start_index = stc->FindText(next_index, stc->GetLength(), text, &end_index, flags);
    if (start_index == -1) return count;
    assert(start_index != end_index);

    const int target_start_index = start_index;
    int target_end_index = end_index;

    // replace text
    if (find_action == FindAction::Replace) {
      stc->SetTargetStart(start_index);
      stc->SetTargetEnd(end_index);
      const bool useRegex = flags & wxSTC_FIND_REGEXP || flags & wxSTC_FIND_POSIX;
      const int change = useRegex
        ? stc->ReplaceTargetRE(replaceText)
       : stc->ReplaceTarget(replaceText);
      assert(change > 0);
      next_index = start_index + change;
      target_end_index = start_index + change;
    }
    else {
      next_index = end_index;
    }

    // add item to the result list
    const int start_line = stc->LineFromPosition(target_start_index);
    const int start_col = target_start_index - stc->PositionFromLine(start_line);
    const int end_line = stc->LineFromPosition(target_end_index);
    const int end_col = target_end_index - stc->PositionFromLine(end_line);
    res->push_back(FindResult(file, stc->GetLine(start_line).Trim(true).Trim(false), start_line + 1, start_col + 1, end_line + 1, end_col + 1));
    ++count;
  }

  return count;
}

void FindInFiles(MainWindow* parent, wxStyledTextCtrl* fallback, const wxString& file, const wxString& text, int flags,
  std::vector<FindResult>* res, FindAction find_action, const wxString& replaceText, bool keepFilesOpen) {
  FileEdit* edit = parent->GetFile(file);
  wxStyledTextCtrl* stc = NULL;
  if (edit) {
    stc = edit->GetStc();
  }
  else {
    fallback->LoadFile(file);

    if (find_action == FindAction::Replace && keepFilesOpen) {
      int found = fallback->FindText(0, stc->GetLength(), text, NULL, flags);
      if (found > 0) {
        FileEdit* opened_edit = parent->OpenFile(file);
        stc = opened_edit->GetStc();
      }
    }
    if( stc == NULL ) {
      stc = fallback;
    }
  }
  assert(stc);
  int count = FindInStc(stc, file, text, flags, res, find_action, replaceText);

  if (find_action == FindAction::Replace && count > 0 && stc == fallback) {
    if (false == stc->SaveFile(file)) {
      ShowError(parent, "Failed to save after replace!", "Error saving!");
    }
  }
}

bool ShowFindDlg(MainWindow* parent, const wxString& current_selection, const wxString& current_file,
  const wxString root_folder, wxStyledTextCtrl* output, FindAction find_action, FindScope find_scope) {
  static ride::FindDlg find_dlg_data;
  FindDlg dlg(parent, current_selection, find_dlg_data, find_action, find_scope);

  if (wxID_OK != dlg.ShowModal()) return false;
  dlg.ToData(find_dlg_data);

  std::vector<FindResult> results;
  wxString file_info = current_file;

  // we can't create a styled ctrl so we cheat by having a 0x0 widget on the find dlg
  // and use that for searching/replacing...
  wxStyledTextCtrl* fallback = dlg.GetStc();

  if (dlg.LookInCurrentFile()) {
    FindInFiles(parent, fallback, current_file, dlg.GetText(), dlg.GetFlags(), &results, find_action, dlg.getReplaceText(), dlg.KeepFilesOpen());
  }
  else {
    wxArrayString files;
    const std::vector<wxString> patterns = Split(find_dlg_data.file_types(), ";");
    size_t count = 0;
    for (const auto pattern : patterns) {
      count += wxDir::GetAllFiles(root_folder, &files, pattern,
        dlg.IsRecursive() ? wxDIR_FILES | wxDIR_DIRS : wxDIR_FILES);
    }

    file_info = wxString::Format("%d files in %s", count, root_folder);
    for (const auto file : files) {
      FindInFiles(parent, fallback, file, dlg.GetText(), dlg.GetFlags(), &results, find_action, dlg.getReplaceText(), dlg.KeepFilesOpen());
    }
  }

  const auto count = results.size();

  ClearOutput(output);

  const wxString find_text = find_action == FindAction::Find
    ? wxString::Format("Searched for '%s'", dlg.GetText())
    : wxString::Format("Replaced '%s' with '%s'", dlg.GetText(), dlg.getReplaceText());
  WriteLine(output, wxString::Format("%s in %s", find_text, file_info));
  WriteLine(output, wxString::Format("%s %d matches", find_action == FindAction::Find ? "Found" : "Replaced", count));
  WriteLine(output, "");
  for (auto res : results) {
    // try to format the same way rust related error looks like so we can reuse the parser code for both and get some synergy effects
    const wxString mess = wxString::Format("%s:%d : %d : %d : %d %s: %s", res.file, res.start_line, res.start_col, res.end_line, res.end_col, find_action == FindAction::Find ? "found" : "replaced", res.content);
    WriteLine(output, mess);
  }

  return true;
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2017 DeepCortex GmbH <legal@eventql.io>
 * Authors:
 *   - Laura Schlimmer <laura@eventql.io>
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License ("the license") as
 * published by the Free Software Foundation, either version 3 of the License,
 * or any later version.
 *
 * In accordance with Section 7(e) of the license, the licensing of the Program
 * under the license does not imply a trademark license. Therefore any rights,
 * title and interest in our trademarks remain entirely with us.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the license for more details.
 *
 * You can be released from the requirements of the license by purchasing a
 * commercial license. Buying such a license is mandatory as soon as you develop
 * commercial activities involving this program without disclosing the source
 * code of your own applications
 */
#include <iostream>
#include "eventql/util/stdtypes.h"
#include "eventql/util/exception.h"
#include "eventql/util/status.h"
#include "eventql/util/stringutil.h"
#include "eventql/util/io/fileutil.h"
#include "eventql/util/io/inputstream.h"
#include "eventql/util/cli/flagparser.h"
#include "eventql/util/csv/CSVInputStream.h"
#include "eventql/util/csv/CSVOutputStream.h"
#include "eventql/sql/runtime/defaultruntime.h"
#include "eventql/sql/CSTableScanProvider.h"
#include "eventql/sql/result_list.h"

#include "eventql/eventql.h"
using namespace csql;

enum class ResultExpectation { TABLE, CHART, ERROR };

const auto kTestListFile = "./sql_tests.lst";
const auto kDirectoryPath = "./sql";
const auto kSQLPathEnding = ".sql";
const auto kResultPathEnding = ".result.txt";
const auto kChartColumnName = "__chart";
const auto kDefaultResultExpectation = ResultExpectation::TABLE;

std::string getResultCSV(ResultList* result, const std::string& row_sep = "\n") {
  std::string result_csv;
  auto is = new StringOutputStream(&result_csv);
  auto csv_is = new CSVOutputStream(
      std::unique_ptr<OutputStream>(is),
      ";",
      row_sep);

  auto columns = result->getColumns();
  csv_is->appendRow(columns);

  auto num_rows = result->getNumRows();
  for (size_t i = 0; i < num_rows; ++i) {
    auto row = result->getRow(i);
    csv_is->appendRow(row);
  }

  return result_csv;
}

Status checkTableResult(
    ResultList* result,
    const std::string& result_file_path) {
  auto csv_is = CSVInputStream::openFile(result_file_path);
  std::vector<std::string> columns;
  if (!csv_is->readNextRow(&columns)) {
    return Status(eRuntimeError, "CSV needs a header");
  }

  /* compare columns */
  if (result->getNumColumns() != columns.size()) {
    return Status(eRuntimeError, StringUtil::format(
        "wrong number of columns, expected $0 to be $1",
        result->getNumColumns(),
        columns.size()));
  }

  auto returned_columns = result->getColumns();
  for (size_t i = 0; i < returned_columns.size(); ++i) {
    if (returned_columns[i] != columns[i]) {
      return Status(eRuntimeError, StringUtil::format(
          "wrong columns name, expected $0 to be $1",
          returned_columns[i],
          columns[i]));
    }
  }

  /* compare rows */
  auto num_returned_rows = result->getNumRows();
  size_t count = 0;
  std::vector<std::string> row;
  while (csv_is->readNextRow(&row)) {
    if (count >= num_returned_rows) {
      return Status(eRuntimeError, "not enough rows returned");
    }

    auto returned_row = result->getRow(count);
    if (returned_row.size() != row.size()) {
      return Status(eRuntimeError, StringUtil::format(
          "wrong number of values, expected $0 to be $1",
          returned_row.size(),
          row.size()));
    }

    for (size_t i = 0; i < row.size(); ++i) {
      if (row[i] != returned_row[i]) {
        return Status(
            eRuntimeError,
            StringUtil::format(
                "result mismatch at row $0, column $1; expected: >$2<, got: >$3<",
                count,
                i,
                row[i],
                returned_row[i]));
      }
    }

    ++count;
  }

  if (count < num_returned_rows) {
    return Status(eRuntimeError, StringUtil::format(
        "too many rows, expected $0 to be $1",
        num_returned_rows,
        count));
  }

  return Status::success();
}

Status checkChartResult(
    ResultList* result,
    const std::string& result_file_path) {
  auto num_returned_rows = result->getNumRows();
  if (num_returned_rows != 1) {
    return Status(eRuntimeError, StringUtil::format(
        "wrong number of rows returned, expected $0 to be 1",
        num_returned_rows));
  }

  auto is = FileInputStream::openFile(result_file_path);
  std::string expected_result;
  is->readUntilEOF(&expected_result);

  auto returned_result = result->getRow(0)[0];
  if (expected_result != returned_result) {
    return Status(eRuntimeError, "result charts don't match");
  }

  return Status::success();
}

Status checkErrorResult(
    const std::string& error_message,
    ResultList* result,
    const std::string& result_file_path) {
  auto is = FileInputStream::openFile(result_file_path);

  {
    std::string result_expectation_line;
    is->readLine(&result_expectation_line);
  }

  std::string expected_error;
  is->readUntilEOF(&expected_error);
  StringUtil::chomp(&expected_error);

  if (expected_error == error_message) {
    return Status::success();
  } else {
    if (error_message.empty()) {
      auto result_csv = getResultCSV(result, " ");
      return Status(eRuntimeError, StringUtil::format(
          "expected error: $0 but got result: $1",
          expected_error,
          result_csv));

    } else {
      return Status(eRuntimeError, StringUtil::format(
          "expected error: $0 but got error $1",
          expected_error,
          error_message));
    }
  }
}

Status runTest(const std::string& test) {
  auto sql_file_path = FileUtil::joinPaths(
      kDirectoryPath,
      StringUtil::format("$0$1", test, kSQLPathEnding));

  if (!FileUtil::exists(sql_file_path)) {
    return Status(
        eIOError,
        StringUtil::format("File does not exist: $0", sql_file_path));
  }

  auto result_file_path = FileUtil::joinPaths(
      kDirectoryPath,
      StringUtil::format("$0$1", test, kResultPathEnding));

  if (!FileUtil::exists(result_file_path)) {
    return Status(
        eIOError,
        StringUtil::format("File does not exist: $0", result_file_path));
  }

  auto result_expectation = kDefaultResultExpectation;
  {
    auto result_is = FileInputStream::openFile(result_file_path);
    std::string first_line;
    if (result_is->readLine(&first_line)) {
      StringUtil::chomp(&first_line);
      if (first_line == "ERROR!") {
        result_expectation = ResultExpectation::ERROR;
      }
    }
  }

  /* input table path */
  auto sql_is = FileInputStream::openFile(sql_file_path);
  std::string input_table_path;
  if (!sql_is->readLine(&input_table_path) ||
      !StringUtil::beginsWith(input_table_path, "--")) {
    return Status(eRuntimeError, "no input table provided");
  }

  StringUtil::replaceAll(&input_table_path, "--");
  StringUtil::ltrim(&input_table_path);
  StringUtil::chomp(&input_table_path);

  if (!FileUtil::exists(input_table_path)) {
    return Status(
        eRuntimeError,
        StringUtil::format("file does not exist: $0", input_table_path));
  }

  std::string query;
  sql_is->readUntilEOF(&query);

  /* execute query */
  auto runtime = Runtime::getDefaultRuntime();
  auto txn = runtime->newTransaction();

  txn->setTableProvider(new CSTableScanProvider("testtable", input_table_path));
  ResultList result;

  std::string error_message;
  try {
    auto qplan = runtime->buildQueryPlan(txn.get(), query);
    qplan->execute(0, &result);
  } catch (const std::exception& e) {
    error_message = e.what();

    if (result_expectation != ResultExpectation::ERROR) {
      return Status(
          eRuntimeError,
          StringUtil::format("unexpected error: $0", error_message));
    }
  }

  if (result.getNumColumns() == 1 &&
      result.getColumns()[0] == kChartColumnName) {
    result_expectation = ResultExpectation::CHART;
  }

  switch (result_expectation) {
    case ResultExpectation::TABLE:
      return checkTableResult(&result, result_file_path);

    case ResultExpectation::CHART:
      return checkChartResult(&result, result_file_path);

    case ResultExpectation::ERROR:
      return checkErrorResult(error_message, &result, result_file_path);
  }
}

int main(int argc, const char** argv) {
  cli::FlagParser flags;

  flags.defineFlag(
      "help",
      cli::FlagParser::T_SWITCH,
      false,
      "?",
      NULL,
      "help",
      "<help>");

  flags.defineFlag(
      "test",
      cli::FlagParser::T_STRING,
      false,
      "t",
      NULL,
      "test",
      "<test_number>");

  flags.parseArgv(argc, argv);

  if (flags.isSet("help")) {
    std::cout
      << StringUtil::format(
            "EventQL $0 ($1)\n"
            "Copyright (c) 2016, DeepCortex GmbH. All rights reserved.\n\n",
            eventql::kVersionString,
            eventql::kBuildID);

    std::cout
      << "Usage: $ evql-test-sql [OPTIONS]" << std::endl
      <<  "   --verbose                 Print debug output to STDERR" << std::endl
      <<  "   -?, --help                Display this help text and exit" <<std::endl
      <<  "   -t, --test <test_number>  Run a test specified by its test number" <<std::endl;
    return 0;
  }

  std::string test_nr;
  if (flags.isSet("test")) {
    test_nr = flags.getString("test");
  }

  try {
    auto is = FileInputStream::openFile(kTestListFile);

    std::string line;
    size_t count = 1;
    while (is->readLine(&line)) {
      StringUtil::chomp(&line);

      if (!test_nr.empty() && !StringUtil::beginsWith(line, test_nr)) {
        continue;
      }

      auto ret = runTest(line);
      if (ret.isSuccess()) {
        std::cout
          << "ok "
          << count
          << " - "
          << "[" << line << "] "
          << "Test passed"
          << std::endl;

      } else {
        std::cout
          << "not ok "
          << count
          << " - "
          << "[" << line << "] "
          << ret.message()
          << std::endl;
      }

      line.clear();
      ++count;
    }

  } catch (const std::exception& e) {
    std::cout << e.what();
    return 1;
  }

  return 0;
}

<commit_msg>evql-test-sql: added csv output format<commit_after>/**
 * Copyright (c) 2017 DeepCortex GmbH <legal@eventql.io>
 * Authors:
 *   - Laura Schlimmer <laura@eventql.io>
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License ("the license") as
 * published by the Free Software Foundation, either version 3 of the License,
 * or any later version.
 *
 * In accordance with Section 7(e) of the license, the licensing of the Program
 * under the license does not imply a trademark license. Therefore any rights,
 * title and interest in our trademarks remain entirely with us.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the license for more details.
 *
 * You can be released from the requirements of the license by purchasing a
 * commercial license. Buying such a license is mandatory as soon as you develop
 * commercial activities involving this program without disclosing the source
 * code of your own applications
 */
#include <iostream>
#include "eventql/util/stdtypes.h"
#include "eventql/util/exception.h"
#include "eventql/util/status.h"
#include "eventql/util/stringutil.h"
#include "eventql/util/io/fileutil.h"
#include "eventql/util/io/inputstream.h"
#include "eventql/util/io/TerminalOutputStream.h"
#include "eventql/util/cli/flagparser.h"
#include "eventql/util/csv/CSVInputStream.h"
#include "eventql/util/csv/CSVOutputStream.h"
#include "eventql/sql/runtime/defaultruntime.h"
#include "eventql/sql/CSTableScanProvider.h"
#include "eventql/sql/result_list.h"

#include "eventql/eventql.h"
using namespace csql;

enum class ResultExpectation { TABLE, CHART, ERROR };

enum class OutputFormat { TAP, CSV, VERBOSE };

const auto kTestListFile = "./sql_tests.lst";
const auto kDirectoryPath = "./sql";
const auto kSQLPathEnding = ".sql";
const auto kResultPathEnding = ".result.txt";
const auto kChartColumnName = "__chart";
const auto kDefaultResultExpectation = ResultExpectation::TABLE;
const auto kDefaultOutputFormat = OutputFormat::TAP;

static void printError(const std::string& error_string) {
  auto stderr_os = TerminalOutputStream::fromStream(OutputStream::getStderr());
  stderr_os->print(
      "ERROR:",
      { TerminalStyle::RED, TerminalStyle::UNDERSCORE });
  stderr_os->print(" " + error_string + "\n");
}

std::string getResultCSV(ResultList* result, const std::string& row_sep = "\n") {
  std::string result_csv;
  auto is = new StringOutputStream(&result_csv);
  auto csv_is = new CSVOutputStream(
      std::unique_ptr<OutputStream>(is),
      ";",
      row_sep);

  auto columns = result->getColumns();
  csv_is->appendRow(columns);

  auto num_rows = result->getNumRows();
  for (size_t i = 0; i < num_rows; ++i) {
    auto row = result->getRow(i);
    csv_is->appendRow(row);
  }

  return result_csv;
}

Status checkTableResult(
    ResultList* result,
    const std::string& result_file_path) {
  auto csv_is = CSVInputStream::openFile(result_file_path);
  std::vector<std::string> columns;
  if (!csv_is->readNextRow(&columns)) {
    return Status(eRuntimeError, "CSV needs a header");
  }

  /* compare columns */
  if (result->getNumColumns() != columns.size()) {
    return Status(eRuntimeError, StringUtil::format(
        "wrong number of columns, expected $0 to be $1",
        result->getNumColumns(),
        columns.size()));
  }

  auto returned_columns = result->getColumns();
  for (size_t i = 0; i < returned_columns.size(); ++i) {
    if (returned_columns[i] != columns[i]) {
      return Status(eRuntimeError, StringUtil::format(
          "wrong columns name, expected $0 to be $1",
          returned_columns[i],
          columns[i]));
    }
  }

  /* compare rows */
  auto num_returned_rows = result->getNumRows();
  size_t count = 0;
  std::vector<std::string> row;
  while (csv_is->readNextRow(&row)) {
    if (count >= num_returned_rows) {
      return Status(eRuntimeError, "not enough rows returned");
    }

    auto returned_row = result->getRow(count);
    if (returned_row.size() != row.size()) {
      return Status(eRuntimeError, StringUtil::format(
          "wrong number of values, expected $0 to be $1",
          returned_row.size(),
          row.size()));
    }

    for (size_t i = 0; i < row.size(); ++i) {
      if (row[i] != returned_row[i]) {
        return Status(
            eRuntimeError,
            StringUtil::format(
                "result mismatch at row $0, column $1; expected: >$2<, got: >$3<",
                count,
                i,
                row[i],
                returned_row[i]));
      }
    }

    ++count;
  }

  if (count < num_returned_rows) {
    return Status(eRuntimeError, StringUtil::format(
        "too many rows, expected $0 to be $1",
        num_returned_rows,
        count));
  }

  return Status::success();
}

Status checkChartResult(
    ResultList* result,
    const std::string& result_file_path) {
  auto num_returned_rows = result->getNumRows();
  if (num_returned_rows != 1) {
    return Status(eRuntimeError, StringUtil::format(
        "wrong number of rows returned, expected $0 to be 1",
        num_returned_rows));
  }

  auto is = FileInputStream::openFile(result_file_path);
  std::string expected_result;
  is->readUntilEOF(&expected_result);

  auto returned_result = result->getRow(0)[0];
  if (expected_result != returned_result) {
    return Status(eRuntimeError, "result charts don't match");
  }

  return Status::success();
}

Status checkErrorResult(
    const std::string& error_message,
    ResultList* result,
    const std::string& result_file_path) {
  auto is = FileInputStream::openFile(result_file_path);

  {
    std::string result_expectation_line;
    is->readLine(&result_expectation_line);
  }

  std::string expected_error;
  is->readUntilEOF(&expected_error);
  StringUtil::chomp(&expected_error);

  if (expected_error == error_message) {
    return Status::success();
  } else {
    if (error_message.empty()) {
      auto result_csv = getResultCSV(result, " ");
      return Status(eRuntimeError, StringUtil::format(
          "expected error: $0 but got result: $1",
          expected_error,
          result_csv));

    } else {
      return Status(eRuntimeError, StringUtil::format(
          "expected error: $0 but got error $1",
          expected_error,
          error_message));
    }
  }
}

Status runTest(const std::string& test, OutputFormat output_format) {
  auto sql_file_path = FileUtil::joinPaths(
      kDirectoryPath,
      StringUtil::format("$0$1", test, kSQLPathEnding));

  if (!FileUtil::exists(sql_file_path)) {
    return Status(
        eIOError,
        StringUtil::format("File does not exist: $0", sql_file_path));
  }

  auto result_file_path = FileUtil::joinPaths(
      kDirectoryPath,
      StringUtil::format("$0$1", test, kResultPathEnding));

  if (!FileUtil::exists(result_file_path)) {
    return Status(
        eIOError,
        StringUtil::format("File does not exist: $0", result_file_path));
  }

  auto result_expectation = kDefaultResultExpectation;
  {
    auto result_is = FileInputStream::openFile(result_file_path);
    std::string first_line;
    if (result_is->readLine(&first_line)) {
      StringUtil::chomp(&first_line);
      if (first_line == "ERROR!") {
        result_expectation = ResultExpectation::ERROR;
      }
    }
  }

  /* input table path */
  auto sql_is = FileInputStream::openFile(sql_file_path);
  std::string input_table_path;
  if (!sql_is->readLine(&input_table_path) ||
      !StringUtil::beginsWith(input_table_path, "--")) {
    return Status(eRuntimeError, "no input table provided");
  }

  StringUtil::replaceAll(&input_table_path, "--");
  StringUtil::ltrim(&input_table_path);
  StringUtil::chomp(&input_table_path);

  if (!FileUtil::exists(input_table_path)) {
    return Status(
        eRuntimeError,
        StringUtil::format("file does not exist: $0", input_table_path));
  }

  std::string query;
  sql_is->readUntilEOF(&query);

  /* execute query */
  auto runtime = Runtime::getDefaultRuntime();
  auto txn = runtime->newTransaction();

  txn->setTableProvider(new CSTableScanProvider("testtable", input_table_path));
  ResultList result;

  std::string error_message;
  auto rc = Status::success();
  try {
    auto qplan = runtime->buildQueryPlan(txn.get(), query);
    qplan->execute(0, &result);
  } catch (const std::exception& e) {
    error_message = e.what();

    if (result_expectation != ResultExpectation::ERROR) {
      return Status(
          eRuntimeError,
          StringUtil::format("unexpected error: $0", error_message));
    }
  }

  if (result.getNumColumns() == 1 &&
      result.getColumns()[0] == kChartColumnName) {
    result_expectation = ResultExpectation::CHART;
  }

  switch (result_expectation) {
    case ResultExpectation::TABLE:
      rc = checkTableResult(&result, result_file_path);
      break;

    case ResultExpectation::CHART:
      rc = checkChartResult(&result, result_file_path);
      break;

    case ResultExpectation::ERROR:
      rc = checkErrorResult(error_message, &result, result_file_path);
      break;
  }

  if (rc.isSuccess()) {
    return rc;
  }

  switch (output_format) {
    case OutputFormat::CSV:
      return Status(eRuntimeError, getResultCSV(&result));

    case OutputFormat::VERBOSE:

    case OutputFormat::TAP:
      return rc;
  }
}

int main(int argc, const char** argv) {
  cli::FlagParser flags;

  flags.defineFlag(
      "help",
      cli::FlagParser::T_SWITCH,
      false,
      "?",
      NULL,
      "help",
      "<help>");

  flags.defineFlag(
      "test",
      cli::FlagParser::T_STRING,
      false,
      "t",
      NULL,
      "test",
      "<test_number>");

  flags.defineFlag(
      "tap",
      cli::FlagParser::T_SWITCH,
      false,
      NULL,
      NULL,
      "tap",
      "<tap>");

  flags.defineFlag(
      "csv",
      cli::FlagParser::T_SWITCH,
      false,
      NULL,
      NULL,
      "csv",
      "<csv>");

  flags.defineFlag(
      "verbose",
      cli::FlagParser::T_SWITCH,
      false,
      NULL,
      NULL,
      "verbose",
      "<verbose>");

  flags.parseArgv(argc, argv);

  if (flags.isSet("help")) {
    std::cout
      << StringUtil::format(
            "EventQL $0 ($1)\n"
            "Copyright (c) 2016, DeepCortex GmbH. All rights reserved.\n\n",
            eventql::kVersionString,
            eventql::kBuildID);

    std::cout
      << "Usage: $ evql-test-sql [OPTIONS]" << std::endl
      <<  "   --tap                     Print the test output as TAP" << std::endl
      <<  "   -t, --test <test_number>  Run a test specified by its test number" <<std::endl
      <<  "   --csv                     Print the result as CSV (use only together with --test) " << std::endl
      <<  "   --verbose                 Print the expected and the actual result as tables (use only togehter with --test)" << std::endl
      <<  "   -?, --help                Display this help text and exit" <<std::endl;
    return 0;
  }

  if (flags.getArgv().size() > 0) {
    printError(StringUtil::format(
        "invalid argument: '$0', run evql-test-sql --help for help\n",
        flags.getArgv()[0]));

    return 1;
  }

  if (flags.isSet("csv") && !flags.isSet("test")) {
    printError("--csv can only be used if --test is set, run evql-test-sql --help for help\n");
    return 1;
  }

  if (flags.isSet("verbose") && !flags.isSet("test")) {
    printError("--verbose can only be used if --test is set, run evql-test-sql --help for help\n");
    return 1;
  }

  auto output_format = kDefaultOutputFormat;
  if (flags.isSet("tap")) {
    output_format = OutputFormat::TAP;
  }

  if (flags.isSet("csv")) {
    output_format = OutputFormat::CSV;
  }

  if (flags.isSet("verbose")) {
    output_format = OutputFormat::VERBOSE;
  }

  std::string test_nr;
  if (flags.isSet("test")) {
    test_nr = flags.getString("test");
  }

  try {
    auto is = FileInputStream::openFile(kTestListFile);

    std::string line;
    size_t count = 1;
    while (is->readLine(&line)) {
      StringUtil::chomp(&line);

      if (!test_nr.empty() && !StringUtil::beginsWith(line, test_nr)) {
        continue;
      }

      auto ret = runTest(line, output_format);
      if (ret.isSuccess()) {
        std::cout
          << "ok "
          << count
          << " - "
          << "[" << line << "] "
          << "Test passed"
          << std::endl;

      } else {

        switch (output_format) {
          case OutputFormat::TAP:
            std::cout
              << "not ok "
              << count
              << " - "
              << "[" << line << "] ";

          case OutputFormat::VERBOSE:
          case OutputFormat::CSV:
            std::cout << ret.message() << std::endl;
        }
      }

      line.clear();
      ++count;
    }

  } catch (const std::exception& e) {
    printError(e.what());
    return 1;
  }

  return 0;
}

<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////////////////////
///
/// @file
/// @author     Kuba Sejdak
/// @date       21.07.2016
///
/// @copyright  This file is a part of cosmos OS. All rights reserved.
///
////////////////////////////////////////////////////////////////////////////////////////////////

#include "buddy_allocator.h"
#include "pagepool_dynamic.h"
#include "pagepool_static.h"

#include <hal/mmu.h>
#include <os/assert.h>

using namespace HAL;

namespace Memory {

static const uint32_t MEMORY_CHUNK_MAGIC = 0x08081990;

MemoryChunk::MemoryChunk()
    : m_magic(0)
    , m_virtualAddress(0)
    , m_size(0)
    , m_parentPage(nullptr)
{
}

bool MemoryChunk::checkMagic()
{
    return (m_magic == MEMORY_CHUNK_MAGIC);
}

uint32_t MemoryChunk::virtualAddress()
{
    return m_virtualAddress;
}

void* MemoryChunk::data()
{
    return reinterpret_cast<void*>(m_virtualAddress + sizeof(MemoryChunk));
}

uint16_t MemoryChunk::size()
{
    return m_size;
}

Page* MemoryChunk::parentPage()
{
    return m_parentPage;
}

void MemoryChunk::init(Page* parentPage)
{
    m_magic = MEMORY_CHUNK_MAGIC;
    m_parentPage = parentPage;
}

void MemoryChunk::setVirtualAddress(uint32_t virtualAddress)
{
    m_virtualAddress = virtualAddress;
}

void MemoryChunk::setSize(uint32_t size)
{
    m_size = size;
}

os::pair<MemoryChunk, MemoryChunk> MemoryChunk::split()
{
    uint32_t newSize = m_size / 2;

    MemoryChunk* first = reinterpret_cast<MemoryChunk*>(m_virtualAddress);
    first->init(m_parentPage);
    first->setVirtualAddress(m_virtualAddress);
    first->setSize(newSize);

    MemoryChunk* second = reinterpret_cast<MemoryChunk*>(m_virtualAddress + newSize);
    second->init(m_parentPage);
    first->setVirtualAddress(m_virtualAddress + newSize);
    second->setSize(newSize);

    return os::pair<MemoryChunk, MemoryChunk>(first, second);
}

void IAllocator::init()
{
    static StaticPagePool staticPool;
    static BuddyAllocator staticBuddy(&staticPool);
    staticAllocator = &staticBuddy;

    static DynamicPagePool dynamicPool;
    static BuddyAllocator dynamicBuddy(&dynamicPool);
    dynamicAllocator = &dynamicBuddy;
}

BuddyAllocator::BuddyAllocator(IPagePool* pagePool)
    : IAllocator(pagePool)
{
}

void* BuddyAllocator::allocate(uint32_t size)
{
    if (size == 0)
        return nullptr;

    uint32_t requiredSize = size + sizeof(MemoryChunk);
    int factor = sizeToFactor(requiredSize);

    while (true) {
        // Find proper chunk from the free chunks list.
        bool chunkAvailable = false;

        for (int i = factor; i < MEMORY_CHUNK_FACTOR; ++i) {
            if (m_freeChunks[i].size() == 0) {
                // There is no chunk with given factor.
                continue;
            }

            if (factorToSize(i) / 2 >= requiredSize) {
                // Smallest suitable chunk can be splitted to avoid fragmentation.
                splitChunk(m_freeChunks[i].front());
                chunkAvailable = true;
                break;
            }

            // Proper chunk found.
            return m_freeChunks[i].pop_front()->data();
        }

        if (chunkAvailable)
            continue;

        // No suitable chunk was found. Allocate new page.
        if (!allocatePage())
            return nullptr;
    }

    return nullptr;
}

void BuddyAllocator::release(void *memoryChunk)
{
    if (memoryChunk == nullptr)
        return;

    MemoryChunk* chunk = reinterpret_cast<MemoryChunk*>((char*) memoryChunk - sizeof(MemoryChunk));
    assert(chunk->checkMagic());
}

bool BuddyAllocator::allocatePage()
{
    auto page = m_pagePool->allocatePages(1);
    if (page.size() == 0)
        return false;

    /// @todo Map this page into kernel address space.
    // void* pageVirtualAddress = IMMU::map(page.front());
    void* pageVirtualAddress = reinterpret_cast<void*>(page.front()->physicalAddress());

    MemoryChunk* newChunk = reinterpret_cast<MemoryChunk*>(pageVirtualAddress);
    newChunk->init(page.front());
    newChunk->setVirtualAddress((uint32_t) pageVirtualAddress);
    newChunk->setSize(IMMU::pageSize());

    // Insert this chunk to the list of free chunks.
    m_freeChunks[sizeToFactor(newChunk->size())].push_back(newChunk);

    return true;
}

int BuddyAllocator::sizeToFactor(uint32_t size)
{
    for (int i = 0; i < MEMORY_CHUNK_FACTOR; ++i) {
        if (factorToSize(i) >= size)
            return i;
    }

    return -1;
}

uint32_t BuddyAllocator::factorToSize(int factor)
{
    return (1 << factor);
}

void BuddyAllocator::splitChunk(MemoryChunk* chunk)
{
    int factor = sizeToFactor(chunk->size());
    int index = m_freeChunks[factor].indexOf(chunk);
    assert(index != -1);

    auto chunkHalfs = chunk->split();
    m_freeChunks[factor].remove(index);
    m_freeChunks[factor - 1].push_back(chunkHalfs.first());
    m_freeChunks[factor - 1].push_back(chunkHalfs.second());
}

} // namespace Memory
<commit_msg>Add initializing page pools when allocator is itnialized.<commit_after>////////////////////////////////////////////////////////////////////////////////////////////////
///
/// @file
/// @author     Kuba Sejdak
/// @date       21.07.2016
///
/// @copyright  This file is a part of cosmos OS. All rights reserved.
///
////////////////////////////////////////////////////////////////////////////////////////////////

#include "buddy_allocator.h"
#include "pagepool_dynamic.h"
#include "pagepool_static.h"

#include <hal/mmu.h>
#include <os/assert.h>

using namespace HAL;

namespace Memory {

static const uint32_t MEMORY_CHUNK_MAGIC = 0x08081990;

MemoryChunk::MemoryChunk()
    : m_magic(0)
    , m_virtualAddress(0)
    , m_size(0)
    , m_parentPage(nullptr)
{
}

bool MemoryChunk::checkMagic()
{
    return (m_magic == MEMORY_CHUNK_MAGIC);
}

uint32_t MemoryChunk::virtualAddress()
{
    return m_virtualAddress;
}

void* MemoryChunk::data()
{
    return reinterpret_cast<void*>(m_virtualAddress + sizeof(MemoryChunk));
}

uint16_t MemoryChunk::size()
{
    return m_size;
}

Page* MemoryChunk::parentPage()
{
    return m_parentPage;
}

void MemoryChunk::init(Page* parentPage)
{
    m_magic = MEMORY_CHUNK_MAGIC;
    m_parentPage = parentPage;
}

void MemoryChunk::setVirtualAddress(uint32_t virtualAddress)
{
    m_virtualAddress = virtualAddress;
}

void MemoryChunk::setSize(uint32_t size)
{
    m_size = size;
}

os::pair<MemoryChunk, MemoryChunk> MemoryChunk::split()
{
    uint32_t newSize = m_size / 2;

    MemoryChunk* first = reinterpret_cast<MemoryChunk*>(m_virtualAddress);
    first->init(m_parentPage);
    first->setVirtualAddress(m_virtualAddress);
    first->setSize(newSize);

    MemoryChunk* second = reinterpret_cast<MemoryChunk*>(m_virtualAddress + newSize);
    second->init(m_parentPage);
    first->setVirtualAddress(m_virtualAddress + newSize);
    second->setSize(newSize);

    return os::pair<MemoryChunk, MemoryChunk>(first, second);
}

void IAllocator::init()
{
    static StaticPagePool staticPool;
    staticPool.init();
    static BuddyAllocator staticBuddy(&staticPool);
    staticAllocator = &staticBuddy;

    static DynamicPagePool dynamicPool;
    dynamicPool.init();
    static BuddyAllocator dynamicBuddy(&dynamicPool);
    dynamicAllocator = &dynamicBuddy;
}

BuddyAllocator::BuddyAllocator(IPagePool* pagePool)
    : IAllocator(pagePool)
{
}

void* BuddyAllocator::allocate(uint32_t size)
{
    if (size == 0)
        return nullptr;

    uint32_t requiredSize = size + sizeof(MemoryChunk);
    int factor = sizeToFactor(requiredSize);

    while (true) {
        // Find proper chunk from the free chunks list.
        bool chunkAvailable = false;

        for (int i = factor; i < MEMORY_CHUNK_FACTOR; ++i) {
            if (m_freeChunks[i].size() == 0) {
                // There is no chunk with given factor.
                continue;
            }

            if (factorToSize(i) / 2 >= requiredSize) {
                // Smallest suitable chunk can be splitted to avoid fragmentation.
                splitChunk(m_freeChunks[i].front());
                chunkAvailable = true;
                break;
            }

            // Proper chunk found.
            return m_freeChunks[i].pop_front()->data();
        }

        if (chunkAvailable)
            continue;

        // No suitable chunk was found. Allocate new page.
        if (!allocatePage())
            return nullptr;
    }

    return nullptr;
}

void BuddyAllocator::release(void *memoryChunk)
{
    if (memoryChunk == nullptr)
        return;

    MemoryChunk* chunk = reinterpret_cast<MemoryChunk*>((char*) memoryChunk - sizeof(MemoryChunk));
    assert(chunk->checkMagic());
}

bool BuddyAllocator::allocatePage()
{
    auto page = m_pagePool->allocatePages(1);
    if (page.size() == 0)
        return false;

    /// @todo Map this page into kernel address space.
    // void* pageVirtualAddress = IMMU::map(page.front());
    void* pageVirtualAddress = reinterpret_cast<void*>(page.front()->physicalAddress());

    MemoryChunk* newChunk = reinterpret_cast<MemoryChunk*>(pageVirtualAddress);
    newChunk->init(page.front());
    newChunk->setVirtualAddress((uint32_t) pageVirtualAddress);
    newChunk->setSize(IMMU::pageSize());

    // Insert this chunk to the list of free chunks.
    m_freeChunks[sizeToFactor(newChunk->size())].push_back(newChunk);

    return true;
}

int BuddyAllocator::sizeToFactor(uint32_t size)
{
    for (int i = 0; i < MEMORY_CHUNK_FACTOR; ++i) {
        if (factorToSize(i) >= size)
            return i;
    }

    return -1;
}

uint32_t BuddyAllocator::factorToSize(int factor)
{
    return (1 << factor);
}

void BuddyAllocator::splitChunk(MemoryChunk* chunk)
{
    int factor = sizeToFactor(chunk->size());
    int index = m_freeChunks[factor].indexOf(chunk);
    assert(index != -1);

    auto chunkHalfs = chunk->split();
    m_freeChunks[factor].remove(index);
    m_freeChunks[factor - 1].push_back(chunkHalfs.first());
    m_freeChunks[factor - 1].push_back(chunkHalfs.second());
}

} // namespace Memory
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkHistogramImageToImageMetricTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include "itkGaussianImageSource.h"
#include "itkImage.h"
#include "itkLinearInterpolateImageFunction.h"
#include "itkMeanSquaresHistogramImageToImageMetric.h"
#include "itkTranslationTransform.h"

int itkHistogramImageToImageMetricTest(int , char*[] )
{
  // Create two simple images.
  const unsigned int ImageDimension = 2;
  typedef double PixelType;
  typedef double CoordinateRepresentationType;

  //Allocate Images
  typedef itk::Image<PixelType,ImageDimension> MovingImageType;
  typedef itk::Image<PixelType,ImageDimension> FixedImageType;

  // Declare Gaussian Sources
  typedef itk::GaussianImageSource<MovingImageType> MovingImageSourceType;
  typedef itk::GaussianImageSource<FixedImageType> FixedImageSourceType;
  typedef MovingImageSourceType::Pointer MovingImageSourcePointer;
  typedef FixedImageSourceType::Pointer FixedImageSourcePointer;

  // Note: the following declarations are classical arrays
  unsigned long fixedImageSize[] = {100,  100};
  unsigned long movingImageSize[] = {100,  100};

  float fixedImageSpacing[]  = {1.0f, 1.0f};
  float movingImageSpacing[] = {1.0f, 1.0f};

  float fixedImageOrigin[] = {0.0f, 0.0f};
  float movingImageOrigin[] = {0.0f, 0.0f};

  MovingImageSourceType::Pointer movingImageSource =
    MovingImageSourceType::New();
  FixedImageSourceType::Pointer  fixedImageSource  =
    FixedImageSourceType::New();

  movingImageSource->SetSize(movingImageSize);
  movingImageSource->SetOrigin(movingImageOrigin);
  movingImageSource->SetSpacing(movingImageSpacing);
  movingImageSource->SetNormalized(false);
  movingImageSource->SetScale(250.0f);

  fixedImageSource->SetSize(fixedImageSize);
  fixedImageSource->SetOrigin(fixedImageOrigin);
  fixedImageSource->SetSpacing(fixedImageSpacing);
  fixedImageSource->SetNormalized(false);
  fixedImageSource->SetScale(250.0f);

  movingImageSource->Update(); // Force the filter to run
  fixedImageSource->Update();  // Force the filter to run

  MovingImageType::Pointer movingImage = movingImageSource->GetOutput();
  FixedImageType::Pointer  fixedImage  = fixedImageSource->GetOutput();

  // Set up the metric.
  typedef itk::MeanSquaresHistogramImageToImageMetric<FixedImageType,
    MovingImageType> MetricType;
  typedef MetricType::TransformType TransformBaseType;
  typedef MetricType::ScalesType ScalesType;
  typedef MetricType::DerivativeType DerivativeType;
  typedef TransformBaseType::ParametersType ParametersType;

  MetricType::Pointer metric = MetricType::New();

  unsigned int nBins = 256;
  MetricType::HistogramType::SizeType histSize;
  histSize[0] = nBins;
  histSize[1] = nBins;
  metric->SetHistogramSize(histSize);

  // Plug the images into the metric.
  metric->SetFixedImage(fixedImage);
  metric->SetMovingImage(movingImage);

  // Set up a transform.
  typedef itk::TranslationTransform<CoordinateRepresentationType,
    ImageDimension> TransformType;

  TransformType::Pointer transform = TransformType::New();
  metric->SetTransform(transform.GetPointer());

  // Set up an interpolator.
  typedef itk::LinearInterpolateImageFunction<MovingImageType,
    double> InterpolatorType;

  InterpolatorType::Pointer interpolator = InterpolatorType::New();
  interpolator->SetInputImage(movingImage.GetPointer());
  metric->SetInterpolator(interpolator.GetPointer());

  // Define the region over which the metric will be computed.
  metric->SetFixedImageRegion(fixedImage->GetBufferedRegion());

  // Set up transform parameters.
  const unsigned int numberOfParameters = transform->GetNumberOfParameters();

  ParametersType parameters( numberOfParameters );
  for (unsigned int k = 0; k < numberOfParameters; k++)
    {
    parameters[k] = 0.0;
    }

  // Set scales for derivative calculation.
  ScalesType scales( numberOfParameters );
  for (unsigned int k = 0; k < numberOfParameters; k++)
    {
    scales[k] = 1;
    }

  const double STEP_LENGTH = 0.001;
  metric->SetDerivativeStepLength(STEP_LENGTH);
  metric->SetDerivativeStepLengthScales(scales);

  try
    {
    // Initialize the metric.
    metric->Initialize();

    // Test SetPaddingValue() and GetPaddingValue().
    metric->SetPaddingValue(-1);
    metric->SetUsePaddingValue(true);

    if (metric->GetPaddingValue() != -1)
      {
      std::cerr << "Incorrect padding value." << std::endl;
      return EXIT_FAILURE;
      }

    // Check to make sure the returned histogram size is the same as histSize.
    if (histSize != metric->GetHistogramSize())
      {
      std::cout << "Incorrect histogram size." << std::endl;
      return EXIT_FAILURE;
      }

    // Check GetDerivativeStepLength().
    if (metric->GetDerivativeStepLength() != STEP_LENGTH)
      {
      std::cout << "Incorrect derivative step length." << std::endl;
      return EXIT_FAILURE;
      }

    // Check GetDerivativeStepLengthScales().
    if (metric->GetDerivativeStepLengthScales() != scales)
      {
      std::cout << "Incorrect scales." << std::endl;
      return EXIT_FAILURE;
      }

    // Do some work
    DerivativeType derivatives( numberOfParameters );
    MetricType::MeasureType value;
    for (double y = -50.0; y <= 50.0; y += 25.0)
      {
      parameters[1] = y;
      for (double x = -50.0; x <= 50.0; x += 25.0)
        {
        parameters[0] = x;
        metric->GetValueAndDerivative (parameters, value, derivatives);
        std::cout << "Parameters: " << parameters
                  << ", Value: " << value
                  << ", Derivatives: " << derivatives << std::endl;
        }
      }

    // Exercise Print() method.
    metric->Print(std::cout);

    std::cout << "Test passed." << std::endl;
    }
  catch (itk::ExceptionObject& ex)
    {
    std::cerr << "Exception caught!" << std::endl;
    std::cerr << ex << std::endl;
    return EXIT_FAILURE;
    }

  // Force an exception
  try
    {
    ParametersType parameters( 2 );
    DerivativeType derivatives( 2 );
    ScalesType badScales( 1 );
    metric->SetDerivativeStepLengthScales(badScales);
    metric->Initialize();
    metric->GetDerivative (parameters, derivatives);
    }
  catch (itk::ExceptionObject &ex)
    {
    std::cerr << "Expected exception caught!" << std::endl;
    std::cerr << ex << std::endl;
    return EXIT_SUCCESS;
    }
  return EXIT_FAILURE;
}
<commit_msg>ENH: Exposing the Lower and Upper bounds of the Histogram as options to be      set from the API of the metric. This allows to focus the registration      on regions having pixels with a particular range of intensities.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkHistogramImageToImageMetricTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include "itkGaussianImageSource.h"
#include "itkImage.h"
#include "itkLinearInterpolateImageFunction.h"
#include "itkMeanSquaresHistogramImageToImageMetric.h"
#include "itkTranslationTransform.h"

int itkHistogramImageToImageMetricTest(int , char*[] )
{
  // Create two simple images.
  const unsigned int ImageDimension = 2;
  typedef double PixelType;
  typedef double CoordinateRepresentationType;

  //Allocate Images
  typedef itk::Image<PixelType,ImageDimension> MovingImageType;
  typedef itk::Image<PixelType,ImageDimension> FixedImageType;

  // Declare Gaussian Sources
  typedef itk::GaussianImageSource<MovingImageType> MovingImageSourceType;
  typedef itk::GaussianImageSource<FixedImageType> FixedImageSourceType;
  typedef MovingImageSourceType::Pointer MovingImageSourcePointer;
  typedef FixedImageSourceType::Pointer FixedImageSourcePointer;

  // Note: the following declarations are classical arrays
  unsigned long fixedImageSize[] = {100,  100};
  unsigned long movingImageSize[] = {100,  100};

  float fixedImageSpacing[]  = {1.0f, 1.0f};
  float movingImageSpacing[] = {1.0f, 1.0f};

  float fixedImageOrigin[] = {0.0f, 0.0f};
  float movingImageOrigin[] = {0.0f, 0.0f};

  MovingImageSourceType::Pointer movingImageSource =
    MovingImageSourceType::New();
  FixedImageSourceType::Pointer  fixedImageSource  =
    FixedImageSourceType::New();

  movingImageSource->SetSize(movingImageSize);
  movingImageSource->SetOrigin(movingImageOrigin);
  movingImageSource->SetSpacing(movingImageSpacing);
  movingImageSource->SetNormalized(false);
  movingImageSource->SetScale(250.0f);

  fixedImageSource->SetSize(fixedImageSize);
  fixedImageSource->SetOrigin(fixedImageOrigin);
  fixedImageSource->SetSpacing(fixedImageSpacing);
  fixedImageSource->SetNormalized(false);
  fixedImageSource->SetScale(250.0f);

  movingImageSource->Update(); // Force the filter to run
  fixedImageSource->Update();  // Force the filter to run

  MovingImageType::Pointer movingImage = movingImageSource->GetOutput();
  FixedImageType::Pointer  fixedImage  = fixedImageSource->GetOutput();

  // Set up the metric.
  typedef itk::MeanSquaresHistogramImageToImageMetric<FixedImageType,
    MovingImageType> MetricType;
  typedef MetricType::TransformType TransformBaseType;
  typedef MetricType::ScalesType ScalesType;
  typedef MetricType::DerivativeType DerivativeType;
  typedef TransformBaseType::ParametersType ParametersType;

  MetricType::Pointer metric = MetricType::New();

  unsigned int nBins = 256;
  MetricType::HistogramType::SizeType histSize;
  histSize[0] = nBins;
  histSize[1] = nBins;
  metric->SetHistogramSize(histSize);

  // Plug the images into the metric.
  metric->SetFixedImage(fixedImage);
  metric->SetMovingImage(movingImage);

  // Set up a transform.
  typedef itk::TranslationTransform<CoordinateRepresentationType,
    ImageDimension> TransformType;

  TransformType::Pointer transform = TransformType::New();
  metric->SetTransform(transform.GetPointer());

  // Set up an interpolator.
  typedef itk::LinearInterpolateImageFunction<MovingImageType,
    double> InterpolatorType;

  InterpolatorType::Pointer interpolator = InterpolatorType::New();
  interpolator->SetInputImage(movingImage.GetPointer());
  metric->SetInterpolator(interpolator.GetPointer());

  // Define the region over which the metric will be computed.
  metric->SetFixedImageRegion(fixedImage->GetBufferedRegion());

  // Set up transform parameters.
  const unsigned int numberOfParameters = transform->GetNumberOfParameters();

  ParametersType parameters( numberOfParameters );
  for (unsigned int k = 0; k < numberOfParameters; k++)
    {
    parameters[k] = 0.0;
    }

  // Set scales for derivative calculation.
  ScalesType scales( numberOfParameters );
  for (unsigned int k = 0; k < numberOfParameters; k++)
    {
    scales[k] = 1;
    }

  const double STEP_LENGTH = 0.001;
  metric->SetDerivativeStepLength(STEP_LENGTH);
  metric->SetDerivativeStepLengthScales(scales);

  try
    {
    // Initialize the metric.
    metric->Initialize();

    // Test SetPaddingValue() and GetPaddingValue().
    metric->SetPaddingValue(-1);
    metric->SetUsePaddingValue(true);

    if (metric->GetPaddingValue() != -1)
      {
      std::cerr << "Incorrect padding value." << std::endl;
      return EXIT_FAILURE;
      }

    // Check to make sure the returned histogram size is the same as histSize.
    if (histSize != metric->GetHistogramSize())
      {
      std::cout << "Incorrect histogram size." << std::endl;
      return EXIT_FAILURE;
      }

    // Check GetDerivativeStepLength().
    if (metric->GetDerivativeStepLength() != STEP_LENGTH)
      {
      std::cout << "Incorrect derivative step length." << std::endl;
      return EXIT_FAILURE;
      }

    // Check GetDerivativeStepLengthScales().
    if (metric->GetDerivativeStepLengthScales() != scales)
      {
      std::cout << "Incorrect scales." << std::endl;
      return EXIT_FAILURE;
      }

    // Do some work
    DerivativeType derivatives( numberOfParameters );
    MetricType::MeasureType value;
    for (double y = -50.0; y <= 50.0; y += 25.0)
      {
      parameters[1] = y;
      for (double x = -50.0; x <= 50.0; x += 25.0)
        {
        parameters[0] = x;
        metric->GetValueAndDerivative (parameters, value, derivatives);
        std::cout << "Parameters: " << parameters
                  << ", Value: " << value
                  << ", Derivatives: " << derivatives << std::endl;
        }
      }

    // Exercise Print() method.
    metric->Print(std::cout);

    std::cout << "Test passed." << std::endl;
    }
  catch (itk::ExceptionObject& ex)
    {
    std::cerr << "Exception caught!" << std::endl;
    std::cerr << ex << std::endl;
    return EXIT_FAILURE;
    }

  std::cout << "Exercise the SetLowerBound() and SetUpperBound() methods " << std::endl;

  MetricType::MeasurementVectorType lowerBound;
  MetricType::MeasurementVectorType upperBound;

  metric->SetLowerBound( lowerBound );
  metric->SetUpperBound( upperBound );

  try
    {
    // Initialize the metric.
    metric->Initialize();

    // Exercise Print() method.
    metric->Print(std::cout);

    std::cout << "Test passed." << std::endl;
    }
  catch (itk::ExceptionObject& ex)
    {
    std::cerr << "Exception caught!" << std::endl;
    std::cerr << ex << std::endl;
    return EXIT_FAILURE;
    }

  // Force an exception
  try
    {
    ParametersType parameters( 2 );
    DerivativeType derivatives( 2 );
    ScalesType badScales( 1 );
    metric->SetDerivativeStepLengthScales(badScales);
    metric->Initialize();
    metric->GetDerivative (parameters, derivatives);
    }
  catch (itk::ExceptionObject &ex)
    {
    std::cerr << "Expected exception caught!" << std::endl;
    std::cerr << ex << std::endl;
    return EXIT_SUCCESS;
    }
  return EXIT_FAILURE;
}
<|endoftext|>


<commit_before>#include "ride/project.h"
#include <wx/utils.h>
#include <wx/process.h>
#include <wx/txtstrm.h>
#include <wx/filename.h>
#include "ride/wxutils.h"

#include "ride/mainwindow.h"
#include "settings.pb.h"
#include "ride/proto.h"

#include <wx/choicdlg.h>

Project::Project(MainWindow* output, const wxString& root_folder) : main_(output), root_folder_(root_folder) {
  if (root_folder_.IsEmpty() == false) {
    if (LoadProto(&project_, GetProjectFile()) == false) {
    }
    if (project_.build_settings_size() == 0) {
      // add default build settings to the project
      ride::BuildSetting* debug = project_.add_build_settings();
      debug->set_name("Debug");
      debug->set_release(false);

      ride::BuildSetting* release = project_.add_build_settings();
      release->set_name("Release");
      release->set_release(true);
    }

    if (LoadProto(&user_, GetUserFile()) == false) {
    }

    // validate project file
    GetCurrentBuildSetting();
  }
}

Project::~Project() {
  Save();
}

const wxString& Project::root_folder() const {
  return root_folder_;
}

bool Project::Save() {
  if (root_folder_.IsEmpty() ) return false;
  bool project_saved = SaveProto(&project_, GetProjectFile());
  bool user_saved = SaveUser();
  return project_saved && user_saved;
}

int Project::tabwidth() const {
  return project_.tabwidth();
}
bool Project::usetabs() const {
  return project_.usetabs();
}

void Project::set_tabwidth(int tabwidth) {
  project_.set_tabwidth(tabwidth);
}
void Project::set_usetabs(bool usetabs) {
  project_.set_usetabs(usetabs);
}

const wxString Project::GetCargoFile() const {
  if (root_folder_.IsEmpty()) return "";
  wxFileName cargo(root_folder_, "cargo.toml");
  return cargo.GetFullPath();
}

const wxString Project::GetProjectFile() const {
  if (root_folder_.IsEmpty()) return "";
  wxFileName cargo(root_folder_, "project.ride");
  return cargo.GetFullPath();
}

const wxString Project::GetUserFile() const {
  if (root_folder_.IsEmpty()) return "";
  wxFileName cargo(root_folder_, "project.ride.user");
  return cargo.GetFullPath();
}

bool Project::IsPartOfProject(const wxString& filename) {
  // todo: implement a better logic for checking if the file is part of the project
  return true;
}

void Project::Settings() {
  // todo: implement me
}

void Project::SelectActiveBuild() {
  std::vector<wxString> names;
  names.reserve(project_.build_settings_size());
  for (const ride::BuildSetting& setting : project_.build_settings()) {
    names.push_back(setting.name());
  }

  wxSingleChoiceDialog dlg(NULL, "Select build", "Build", names.size(), &names[0]);
  dlg.SetSelection( user_.build_setting() );
  const int dialog_result = dlg.ShowModal();

  if (dialog_result != wxID_OK) return;
  user_.set_build_setting(dlg.GetSelection());
  SaveUser();
  SetMainStatusbarText();
}

void Project::SaveAllFiles() {
  main_->SaveAllChangedProjectFiles();
  Save();
}

void Project::Build(bool origin_main) {
  if (origin_main) {
    CleanOutput();
    SaveAllFiles();
  }

  // todo: expand commandline with arguments
  RunCmd("cargo build");
}

void Project::Clean(bool origin_main) {
  if (origin_main) {
    CleanOutput();
    SaveAllFiles();
  }

  // todo: expand commandline with arguments
  RunCmd("cargo clean");
}

void Project::Rebuild(bool origin_main) {
  if (origin_main) {
    CleanOutput();
    SaveAllFiles();
  }
  Clean(false);
  Build(false);
}

void Project::Doc(bool origin_main) {
  if (origin_main) {
    CleanOutput();
    SaveAllFiles();
  }

  // todo: expand commandline with arguments
  RunCmd("cargo doc");
}

void Project::Run(bool origin_main) {
  if (origin_main) {
    CleanOutput();
    SaveAllFiles();
  }

  Build(false);
  //todo: run the application
}

void Project::Test(bool origin_main) {
  if (origin_main) {
    CleanOutput();
    SaveAllFiles();
  }

  // todo: expand commandline with arguments
  RunCmd("cargo test");
}

void Project::Bench(bool origin_main) {
  if (origin_main) {
    CleanOutput();
    SaveAllFiles();
  }

  // todo: expand commandline with arguments
  RunCmd("cargo bench");
}

void Project::Update(bool origin_main) {
  if (origin_main) {
    CleanOutput();
    SaveAllFiles();
  }

  // todo: expand commandline with arguments
  RunCmd("cargo update");
}

//////////////////////////////////////////////////////////////////////////

void Project::CleanOutput() {
  main_->build_output().Clear();
}

void Project::Append(const wxString& str) {
  main_->build_output().Append(str);
}

void Project::RunCmd(const wxString& cmd) {
  if (root_folder_.IsEmpty()) {
    ShowInfo(main_, "No project open, you need to open a cargo project first!", "No project open!");
    return;
  }

  MultiRunner::RunCmd(Command(root_folder_, cmd));
}

bool Project::SaveUser() {
  return SaveProto(&user_, GetUserFile());
}

int Project::GetSelectedBuildIndex() {
  if (project_.build_settings_size() <= 0) return -1;

  if (user_.build_setting() < 0 || user_.build_setting() >= project_.build_settings_size()) {
    user_.set_build_setting(0);
    SaveUser();
    SetMainStatusbarText();
  }

  return user_.build_setting();
}

const ride::BuildSetting& Project::GetCurrentBuildSetting() {
  int index = GetSelectedBuildIndex();
  if (index == -1) return ride::BuildSetting::default_instance();
  else return project_.build_settings(index);
}

void Project::SetMainStatusbarText() {
  main_->SetStatusText(GetCurrentBuildSetting().name(), STATUSBAR_BUILD_CONF);
  main_->SetStatusText("Run", STATUSBAR_RUN_CONF);
}
<commit_msg>generate the build command from settings<commit_after>#include "ride/project.h"
#include <wx/utils.h>
#include <wx/process.h>
#include <wx/txtstrm.h>
#include <wx/filename.h>
#include "ride/wxutils.h"

#include "ride/mainwindow.h"
#include "settings.pb.h"
#include "ride/proto.h"

#include <wx/choicdlg.h>

Project::Project(MainWindow* output, const wxString& root_folder) : main_(output), root_folder_(root_folder) {
  if (root_folder_.IsEmpty() == false) {
    if (LoadProto(&project_, GetProjectFile()) == false) {
    }
    if (project_.build_settings_size() == 0) {
      // add default build settings to the project
      ride::BuildSetting* debug = project_.add_build_settings();
      debug->set_name("Debug");
      debug->set_release(false);

      ride::BuildSetting* release = project_.add_build_settings();
      release->set_name("Release");
      release->set_release(true);
    }

    if (LoadProto(&user_, GetUserFile()) == false) {
    }

    // validate project file
    GetCurrentBuildSetting();
  }
}

Project::~Project() {
  Save();
}

const wxString& Project::root_folder() const {
  return root_folder_;
}

bool Project::Save() {
  if (root_folder_.IsEmpty() ) return false;
  bool project_saved = SaveProto(&project_, GetProjectFile());
  bool user_saved = SaveUser();
  return project_saved && user_saved;
}

int Project::tabwidth() const {
  return project_.tabwidth();
}
bool Project::usetabs() const {
  return project_.usetabs();
}

void Project::set_tabwidth(int tabwidth) {
  project_.set_tabwidth(tabwidth);
}
void Project::set_usetabs(bool usetabs) {
  project_.set_usetabs(usetabs);
}

const wxString Project::GetCargoFile() const {
  if (root_folder_.IsEmpty()) return "";
  wxFileName cargo(root_folder_, "cargo.toml");
  return cargo.GetFullPath();
}

const wxString Project::GetProjectFile() const {
  if (root_folder_.IsEmpty()) return "";
  wxFileName cargo(root_folder_, "project.ride");
  return cargo.GetFullPath();
}

const wxString Project::GetUserFile() const {
  if (root_folder_.IsEmpty()) return "";
  wxFileName cargo(root_folder_, "project.ride.user");
  return cargo.GetFullPath();
}

bool Project::IsPartOfProject(const wxString& filename) {
  // todo: implement a better logic for checking if the file is part of the project
  return true;
}

void Project::Settings() {
  // todo: implement me
}

void Project::SelectActiveBuild() {
  std::vector<wxString> names;
  names.reserve(project_.build_settings_size());
  for (const ride::BuildSetting& setting : project_.build_settings()) {
    names.push_back(setting.name());
  }

  wxSingleChoiceDialog dlg(NULL, "Select build", "Build", names.size(), &names[0]);
  dlg.SetSelection( user_.build_setting() );
  const int dialog_result = dlg.ShowModal();

  if (dialog_result != wxID_OK) return;
  user_.set_build_setting(dlg.GetSelection());
  SaveUser();
  SetMainStatusbarText();
}

void Project::SaveAllFiles() {
  main_->SaveAllChangedProjectFiles();
  Save();
}

void Project::Build(bool origin_main) {
  if (origin_main) {
    CleanOutput();
    SaveAllFiles();
  }

  const ride::BuildSetting& build = GetCurrentBuildSetting();
  wxString cmd = "cargo build";

  if (build.release()) {
    cmd += " --release";
  }

  if (build.features_size() > 0) {
    cmd += " --features";
    for (const std::string& f : build.features()) {
      cmd += " " + f;
    }
  }

  if (build.default_features() == false) {
    cmd += " --no-default-features";
  }

  if (build.target().empty() == false) {
    cmd += " --target " + build.target();
  }

  if (build.verbose()) {
    cmd += " --verbose";
  }

  if (build.custom_arguments().empty() == false) {
    cmd += " " + build.custom_arguments();
  }

  RunCmd(cmd);
}

void Project::Clean(bool origin_main) {
  if (origin_main) {
    CleanOutput();
    SaveAllFiles();
  }

  // todo: expand commandline with arguments
  RunCmd("cargo clean");
}

void Project::Rebuild(bool origin_main) {
  if (origin_main) {
    CleanOutput();
    SaveAllFiles();
  }
  Clean(false);
  Build(false);
}

void Project::Doc(bool origin_main) {
  if (origin_main) {
    CleanOutput();
    SaveAllFiles();
  }

  // todo: expand commandline with arguments
  RunCmd("cargo doc");
}

void Project::Run(bool origin_main) {
  if (origin_main) {
    CleanOutput();
    SaveAllFiles();
  }

  Build(false);
  //todo: run the application
}

void Project::Test(bool origin_main) {
  if (origin_main) {
    CleanOutput();
    SaveAllFiles();
  }

  // todo: expand commandline with arguments
  RunCmd("cargo test");
}

void Project::Bench(bool origin_main) {
  if (origin_main) {
    CleanOutput();
    SaveAllFiles();
  }

  // todo: expand commandline with arguments
  RunCmd("cargo bench");
}

void Project::Update(bool origin_main) {
  if (origin_main) {
    CleanOutput();
    SaveAllFiles();
  }

  // todo: expand commandline with arguments
  RunCmd("cargo update");
}

//////////////////////////////////////////////////////////////////////////

void Project::CleanOutput() {
  main_->build_output().Clear();
}

void Project::Append(const wxString& str) {
  main_->build_output().Append(str);
}

void Project::RunCmd(const wxString& cmd) {
  if (root_folder_.IsEmpty()) {
    ShowInfo(main_, "No project open, you need to open a cargo project first!", "No project open!");
    return;
  }

  MultiRunner::RunCmd(Command(root_folder_, cmd));
}

bool Project::SaveUser() {
  return SaveProto(&user_, GetUserFile());
}

int Project::GetSelectedBuildIndex() {
  if (project_.build_settings_size() <= 0) return -1;

  if (user_.build_setting() < 0 || user_.build_setting() >= project_.build_settings_size()) {
    user_.set_build_setting(0);
    SaveUser();
    SetMainStatusbarText();
  }

  return user_.build_setting();
}

const ride::BuildSetting& Project::GetCurrentBuildSetting() {
  int index = GetSelectedBuildIndex();
  if (index == -1) return ride::BuildSetting::default_instance();
  else return project_.build_settings(index);
}

void Project::SetMainStatusbarText() {
  main_->SetStatusText(GetCurrentBuildSetting().name(), STATUSBAR_BUILD_CONF);
  main_->SetStatusText("Run", STATUSBAR_RUN_CONF);
}
<|endoftext|>