<commit_before>#ifndef MJOLNIR_CORE_G_BAOAB_LANGEVIN_INTEGRATOR_HPP
#define MJOLNIR_CORE_G_BAOAB_LANGEVIN_INTEGRATOR_HPP
#include <mjolnir/core/SimulatorTraits.hpp>
#include <mjolnir/core/RandomNumberGenerator.hpp>

namespace mjolnir
{

// g-BAOAB Langevin integrator developed by the following papers
// Leimkuhler B., Matthews C., Proc. R. Soc. A Math. Phys. Eng. Sci. (2016)
template<typename traitsT>
class GBAOABLangevinIntegrator
{
    public:
      using traits_type      = traitsT;
      using real_type        = typename traits_type::real_type;
      using coordinate_type  = typename traits_type::coordinate_type;
      using indices_type     = std::array<std::size_t, 2>;
      using constraints_type = std::vector<std::pair<indices_type, real_type>>;
      using system_type      = System<traitsT>;
      using forcefield_type  = ForceField<traitsT>;
      using rng_type         = RandomNumberGenerator<traits_type>;
      using remover_type     = SystemMotionRemover<traits_type>;

    public:

      GBAOABLangevinIntegrator(const real_type dt, std::vector<real_type>&& gamma,
                               constraints_type&& constraint, remover_type&& remover)
          : dt_(dt), halfdt_(dt / 2), gammas_(std::move(gamma)),
            noise_coeff_ (gammas_.size()), remover_(std::move(remover))
      {}
      ~GBAOABLangevinIntegrator() = default;

      void initialize(system_type& sys, forcefield_type& ff, rng_type& rng);

      real_type step(const real_type time, system_type& sys, forcefield_type& ff,
                     rng_type& rng);

      void update(const system_type& sys)
      {
          if(!sys.has_attribute("temperature"))
          {
              throw std::out_of_range("mjolnir::g-BAOABLangevinIntegrator: "
                  "Langevin Integrator requires reference temperature, but "
                  "`temperature` is not found in `system.attribute`.");
          }
          this->temperature_ = sys.attribute("temperature");
          this->reset_parameter(sys);
          return;
      }

      real_type delta_t() const noexcept {return dt_;}
      std::vector<real_type> const& parameters() const noexcept {return gammas_;}

    private:

      void reset_parameter(const system_type& sys) noexcept
      {
          const auto kBT = physics::constants<real_type>::kB() * this->temperature_;
          for(std::size_t i=0; i<sys.size(); ++i)
          {
              const auto gamma     = this->gammas_.at(i);
              const auto gamma_dt  = -1 * gamma * this->dt_;
              this->exp_gamma_dt_.at(i) = std::exp(gamma_dt);
              this->noise_coeff_ .at(i) = std::sqrt(
                      kBT * (1 - std::exp(2 * gamma_dt)) * sys.rmass(i));
          }
          return;
      };

      coordinate_type gen_R(rng_type& rng) noexcept
      {
          const auto x = rng.gaussian();
          const auto y = rng.gaussian();
          const auto z = rng.gaussian();
          return math::make_coordinate<coordinate_type>(x, y, z);
      }

    private:
      real_type dt_;
      real_type halfdt_;
      real_type temperature_;

      std::vector<real_type> gammas_;
      std::vector<real_type> exp_gamma_dt_;
      std::vector<real_type> noise_coeff_;
      std::vector<coordinate_type> old_position_;

      remover_type remover_;
};

template<typename traitsT>
void GBAOABLangevinIntegrator<traitsT>::initialize(
        system_type& system, forcefield_type& ff, rng_type&)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();

    // calculate parameters for each particles
    this->update(system);

    // calculate force
    for(std::size_t i=0; i<system.size(); ++i)
    {
        system.force(i) = math::make_coordinate<coordinate_type>(0, 0, 0);
    }
    ff.calc_force(system);

    // buffering old posiiton
    old_position_.resize(system.size());
    for(std::size_t i=0; i<system.size(); ++i)
    {
        old_position_[i] = system.position(i);
    }

    return;
}

template<typename traitsT>
typename GBAOABLangevinIntegrator<traitsT>::real_type
GBAOABLangevinIntegrator<traitsT>::step(
        const real_type time, system_type& sys, forcefield_type& ff, rng_type& rng)
{
    coordinate_type dp = math::make_coordinate<coordinate_type>(0, 0, 0);
    // B step
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        auto& rm = sys.rmass(i); // reciprocal mass
        sys.velocity(i)  += this->halfdt_ * sys.rmass(i) * sys.force(i);
    }
    // velocity collection step
    // TODO
    // A step
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        sys.position(i) += this->halfdt_ * sys.velocity(i);
    }
    // coordinate collection step
    // TODO
    // velocity collection step
    // TODO
    // O step
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        sys.velocity(i) *= this->exp_gamma_dt_[i]; // *= exp(- gamma dt)
        sys.velocity(i) += this->noise_coeff_[i] * this->gen_R(rng);
    }
    // velocity collection step
    // TODO
    // A step
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        sys.position(i) += this->halfdt_ * sys.velocity(i);
    }
    // coordinate collection step
    // TODO
    // velocity collection step
    // TODO
    // update neighbor list; reduce margin, reconstruct the list if needed;
    real_type largest_disp2(0.0);
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        coordinate_type displacement = this->old_position_[i] - sys.position(i);
        largest_disp2 = std::max(largest_disp2, math::length_sq(displacement));
    }

    ff.reduce_margin(2 * std::sqrt(largest_disp2), sys);

    // B step
    ff.calc_force(sys);
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        sys.velocity(i) += this->halfdt_ * sys.rmass(i) * sys.force(i);
    }
    // velocity collection step
    // TODO

    remover_.remove(sys);

    return time + dt_;
}

} // mjolnir
#endif /* MJOLNIR_CORE_G_BAOAB_LANGEVIN_INTEGRATOR_HPP */
<commit_msg>fix: non geodesic part of g-BAOAB Langevin<commit_after>#ifndef MJOLNIR_CORE_G_BAOAB_LANGEVIN_INTEGRATOR_HPP
#define MJOLNIR_CORE_G_BAOAB_LANGEVIN_INTEGRATOR_HPP
#include <mjolnir/core/SimulatorTraits.hpp>
#include <mjolnir/core/RandomNumberGenerator.hpp>

namespace mjolnir
{

// g-BAOAB Langevin integrator developed by the following papers
// Leimkuhler B., Matthews C., Proc. R. Soc. A Math. Phys. Eng. Sci. (2016)
template<typename traitsT>
class GBAOABLangevinIntegrator
{
    public:
      using traits_type      = traitsT;
      using real_type        = typename traits_type::real_type;
      using coordinate_type  = typename traits_type::coordinate_type;
      using indices_type     = std::array<std::size_t, 2>;
      using constraints_type = std::vector<std::pair<indices_type, real_type>>;
      using system_type      = System<traitsT>;
      using forcefield_type  = ForceField<traitsT>;
      using rng_type         = RandomNumberGenerator<traits_type>;
      using remover_type     = SystemMotionRemover<traits_type>;

    public:

      GBAOABLangevinIntegrator(const real_type dt, std::vector<real_type>&& gamma,
                               constraints_type&& constraint, remover_type&& remover)
          : dt_(dt), halfdt_(dt / 2), gammas_(std::move(gamma)),
            exp_gamma_dt_(gammas_.size()), noise_coeff_ (gammas_.size()),
            remover_(std::move(remover))
      {}
      ~GBAOABLangevinIntegrator() = default;

      void initialize(system_type& sys, forcefield_type& ff, rng_type& rng);

      real_type step(const real_type time, system_type& sys, forcefield_type& ff,
                     rng_type& rng);

      void update(const system_type& sys)
      {
          if(!sys.has_attribute("temperature"))
          {
              throw std::out_of_range("mjolnir::g-BAOABLangevinIntegrator: "
                  "Langevin Integrator requires reference temperature, but "
                  "`temperature` is not found in `system.attribute`.");
          }
          this->temperature_ = sys.attribute("temperature");
          this->reset_parameter(sys);
          return;
      }

      real_type delta_t() const noexcept {return dt_;}
      std::vector<real_type> const& parameters() const noexcept {return gammas_;}

    private:

      void reset_parameter(const system_type& sys) noexcept
      {
          const auto kBT = physics::constants<real_type>::kB() * this->temperature_;
          for(std::size_t i=0; i<sys.size(); ++i)
          {
              const auto gamma     = this->gammas_.at(i);
              const auto gamma_dt  = -1 * gamma * this->dt_;
              this->exp_gamma_dt_.at(i) = std::exp(gamma_dt);
              this->noise_coeff_ .at(i) = std::sqrt(
                      kBT * (1 - std::exp(2 * gamma_dt)) * sys.rmass(i));
          }
          return;
      };

      coordinate_type gen_R(rng_type& rng) noexcept
      {
          const auto x = rng.gaussian();
          const auto y = rng.gaussian();
          const auto z = rng.gaussian();
          return math::make_coordinate<coordinate_type>(x, y, z);
      }

    private:
      real_type dt_;
      real_type halfdt_;
      real_type temperature_;

      std::vector<real_type> gammas_;
      std::vector<real_type> exp_gamma_dt_;
      std::vector<real_type> noise_coeff_;
      std::vector<coordinate_type> old_position_;

      remover_type remover_;
};

template<typename traitsT>
void GBAOABLangevinIntegrator<traitsT>::initialize(
        system_type& system, forcefield_type& ff, rng_type&)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();

    // calculate parameters for each particles
    this->update(system);

    // calculate force
    for(std::size_t i=0; i<system.size(); ++i)
    {
        system.force(i) = math::make_coordinate<coordinate_type>(0, 0, 0);
    }
    ff.calc_force(system);

    // buffering old position
    old_position_.reserve(system.size());
    for(std::size_t i=0; i<system.size(); ++i)
    {
        old_position_.push_back(system.position(i));
    }

    return;
}

template<typename traitsT>
typename GBAOABLangevinIntegrator<traitsT>::real_type
GBAOABLangevinIntegrator<traitsT>::step(
        const real_type time, system_type& sys, forcefield_type& ff, rng_type& rng)
{
    // B step
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        sys.velocity(i)  += this->halfdt_ * sys.rmass(i) * sys.force(i);
    }
    // velocity correction step
    // TODO
    // A step
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        sys.position(i) += this->halfdt_ * sys.velocity(i);
    }
    // coordinate correction step
    // TODO
    // velocity correction step
    // TODO
    // O step
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        sys.velocity(i) *= this->exp_gamma_dt_[i]; // *= exp(- gamma dt)
        sys.velocity(i) += this->noise_coeff_[i] * this->gen_R(rng);
    }
    // velocity correction step
    // TODO
    // A step
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        sys.position(i) += this->halfdt_ * sys.velocity(i);
    }
    // coordinate correction step
    // TODO
    // velocity correction step
    // TODO
    // update neighbor list; reduce margin, reconstruct the list if needed;
    real_type largest_disp2(0.0);
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        coordinate_type displacement = sys.position(i) - this->old_position_[i];
        largest_disp2 = std::max(largest_disp2, math::length_sq(displacement));
        sys.position(i) = sys.adjust_position(sys.position(i));

        // reset force
        sys.force(i) = math::make_coordinate<coordinate_type>(0, 0, 0);
    }

    ff.reduce_margin(2 * std::sqrt(largest_disp2), sys);

    // B step
    ff.calc_force(sys);
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        sys.velocity(i) += this->halfdt_ * sys.rmass(i) * sys.force(i);
    }
    // velocity correction step
    // TODO

    remover_.remove(sys);

    for(std::size_t i=0; i<sys.size(); ++i)
    {
        this->old_position_[i] = sys.position(i);
    }

    return time + dt_;
}

} // mjolnir
#endif /* MJOLNIR_CORE_G_BAOAB_LANGEVIN_INTEGRATOR_HPP */
<|endoftext|>


<commit_before>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                        Intel License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of Intel Corporation may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#include "mltest.h"

CvTS test_system("ml");

const char* blacklist[] =
{
    "kmeans",      //ticket 616
    "artrees",     //ticket 460
    "aboost",      //ticket 474
    0
};

int main( int argc, char** argv )
{
    return test_system.run( argc, argv, blacklist );
}

/* End of file. */
<commit_msg>moved CvGBTrees_test test to blacklist (issue 630)<commit_after>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                        Intel License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of Intel Corporation may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#include "mltest.h"

CvTS test_system("ml");

const char* blacklist[] =
{
    "kmeans",          //ticket 616
    "artrees",         //ticket 460
    "aboost",          //ticket 474
    "CvGBTrees_test",  //ticket 630
    0
};

int main( int argc, char** argv )
{
    return test_system.run( argc, argv, blacklist );
}

/* End of file. */
<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file LexVerilog.cxx
 ** Lexer for Verilog.
 ** Written by Avi Yegudin, based on C++ lexer by Neil Hodgson
 **/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool IsAWordChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\'');
}

static inline bool IsAWordStart(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '$');
}

static void ColouriseVerilogDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                            Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
	WordList &keywords4 = *keywordlists[3];

	// Do not leak onto next line
	if (initStyle == SCE_V_STRINGEOL)
		initStyle = SCE_V_DEFAULT;

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {

		if (sc.atLineStart && (sc.state == SCE_V_STRING)) {
			// Prevent SCE_V_STRINGEOL from leaking back to previous line
			sc.SetState(SCE_V_STRING);
		}

		// Handle line continuation generically.
		if (sc.ch == '\\') {
			if (sc.chNext == '\n' || sc.chNext == '\r') {
				sc.Forward();
				if (sc.ch == '\r' && sc.chNext == '\n') {
					sc.Forward();
				}
				continue;
			}
		}

		// Determine if the current state should terminate.
		if (sc.state == SCE_V_OPERATOR) {
			sc.SetState(SCE_V_DEFAULT);
		} else if (sc.state == SCE_V_NUMBER) {
			if (!IsAWordChar(sc.ch)) {
				sc.SetState(SCE_V_DEFAULT);
			}
		} else if (sc.state == SCE_V_IDENTIFIER) {
			if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
				char s[100];
                                sc.GetCurrent(s, sizeof(s));
				if (keywords.InList(s)) {
					sc.ChangeState(SCE_V_WORD);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_V_WORD2);
				} else if (keywords3.InList(s)) {
					sc.ChangeState(SCE_V_WORD3);
                                } else if (keywords4.InList(s)) {
					sc.ChangeState(SCE_V_USER);
				}
				sc.SetState(SCE_V_DEFAULT);
			}
		} else if (sc.state == SCE_V_PREPROCESSOR) {
                        if (!IsAWordChar(sc.ch)) {
                                sc.SetState(SCE_V_DEFAULT);
                        }
		} else if (sc.state == SCE_V_COMMENT) {
			if (sc.Match('*', '/')) {
				sc.Forward();
				sc.ForwardSetState(SCE_V_DEFAULT);
			}
		} else if (sc.state == SCE_V_COMMENTLINE || sc.state == SCE_V_COMMENTLINEBANG) {
			if (sc.atLineStart) {
				sc.SetState(SCE_V_DEFAULT);
			}
                } else if (sc.state == SCE_V_STRING) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_V_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_V_STRINGEOL);
				sc.ForwardSetState(SCE_V_DEFAULT);
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_V_DEFAULT) {
			if (IsADigit(sc.ch) || (sc.ch == '\'') || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_V_NUMBER);
			} else if (IsAWordStart(sc.ch)) {
				sc.SetState(SCE_V_IDENTIFIER);
			} else if (sc.Match('/', '*')) {
                                sc.SetState(SCE_V_COMMENT);
				sc.Forward();	// Eat the * so it isn't used for the end of the comment
			} else if (sc.Match('/', '/')) {
				if (sc.Match("//!"))	// Nice to have a different comment style
					sc.SetState(SCE_V_COMMENTLINEBANG);
				else
					sc.SetState(SCE_V_COMMENTLINE);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_V_STRING);
			} else if (sc.ch == '`') {
				sc.SetState(SCE_V_PREPROCESSOR);
				// Skip whitespace between ` and preprocessor word
				do {
					sc.Forward();
				} while ((sc.ch == ' ' || sc.ch == '\t') && sc.More());
				if (sc.atLineEnd) {
					sc.SetState(SCE_V_DEFAULT);
				}
			} else if (isoperator(static_cast<char>(sc.ch)) || sc.ch == '@' || sc.ch == '#') {
				sc.SetState(SCE_V_OPERATOR);
			}
		}
	}
	sc.Complete();
}

static bool IsStreamCommentStyle(int style) {
	return style == SCE_V_COMMENT;
}

static bool IsCommentLine(int line, Accessor &styler) {
	int pos = styler.LineStart(line);
	int eolPos = styler.LineStart(line + 1) - 1;
	for (int i = pos; i < eolPos; i++) {
		char ch = styler[i];
		char chNext = styler.SafeGetCharAt(i + 1);
		int style = styler.StyleAt(i);
		if (ch == '/' && chNext == '/' &&
		   (style == SCE_V_COMMENTLINE || style == SCE_V_COMMENTLINEBANG)) {
			return true;
		} else if (!IsASpaceOrTab(ch)) {
			return false;
		}
	}
	return false;
}
// Store both the current line's fold level and the next lines in the
// level store to make it easy to pick up with each increment
// and to make it possible to fiddle the current level for "} else {".
static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle,
                            Accessor &styler) {
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0;
        // Verilog specific folding options:
        // fold_at_module -
        //      Generally used methodology in verilog code is
        //      one module per file, so folding at module definition is useless.
        // fold_at_brace/parenthese -
        //      Folding of long port lists can be convenient.
	bool foldAtModule = styler.GetPropertyInt("fold.verilog.flags", 0) != 0;
	bool foldAtBrace  = 1;
	bool foldAtParenthese  = 1;

	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelCurrent = SC_FOLDLEVELBASE;
	if (lineCurrent > 0)
		levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
	int levelMinCurrent = levelCurrent;
	int levelNext = levelCurrent;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (foldComment && IsStreamCommentStyle(style)) {
			if (!IsStreamCommentStyle(stylePrev)) {
				levelNext++;
			} else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
				// Comments don't end at end of line and the next character may be unstyled.
				levelNext--;
			}
		}
		if (foldComment && atEOL && IsCommentLine(lineCurrent, styler))
		{
			if (!IsCommentLine(lineCurrent - 1, styler)
			    && IsCommentLine(lineCurrent + 1, styler))
				levelNext++;
			else if (IsCommentLine(lineCurrent - 1, styler)
			         && !IsCommentLine(lineCurrent+1, styler))
				levelNext--;
		}
		if (foldComment && (style == SCE_V_COMMENTLINE)) {
			if ((ch == '/') && (chNext == '/')) {
				char chNext2 = styler.SafeGetCharAt(i + 2);
				if (chNext2 == '{') {
					levelNext++;
				} else if (chNext2 == '}') {
					levelNext--;
				}
			}
		}
		if (foldPreprocessor && (style == SCE_V_PREPROCESSOR)) {
			if (ch == '`') {
				unsigned int j = i + 1;
				while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
					j++;
				}
				if (styler.Match(j, "if")) {
					levelNext++;
				} else if (styler.Match(j, "end")) {
					levelNext--;
				}
			}
		}
                if (style == SCE_V_OPERATOR) {
                    if (foldAtParenthese) {
			if (ch == '(') {
				levelNext++;
			} else if (ch == ')') {
				levelNext--;
			}
                    }
		}
                if (style == SCE_V_OPERATOR) {
                    if (foldAtBrace) {
			if (ch == '{') {
				levelNext++;
			} else if (ch == '}') {
				levelNext--;
			}
                    }
		}
                if (style == SCE_V_WORD && stylePrev != SCE_V_WORD) {
                        unsigned int j = i;
                        if (styler.Match(j, "case") ||
                            styler.Match(j, "casex") ||
                            styler.Match(j, "casez") ||
                            styler.Match(j, "function") ||
                            styler.Match(j, "fork") ||
                            styler.Match(j, "table") ||
                            styler.Match(j, "task") ||
                            styler.Match(j, "generate") ||
                            styler.Match(j, "specify") ||
                            styler.Match(j, "primitive") ||
                            (styler.Match(j, "module") && foldAtModule) ||
                            styler.Match(j, "begin")) {
                                levelNext++;
                        } else if (styler.Match(j, "endcase") ||
                                   styler.Match(j, "endfunction") ||
                                   styler.Match(j, "join") ||
                                   styler.Match(j, "endtask") ||
                                   styler.Match(j, "endgenerate") ||
                                   styler.Match(j, "endtable") ||
                                   styler.Match(j, "endspecify") ||
                                   styler.Match(j, "endprimitive") ||
                                   (styler.Match(j, "endmodule") && foldAtModule) ||
                                   (styler.Match(j, "end") && !IsAWordChar(styler.SafeGetCharAt(j+3)))) {
                                levelNext--;
                        }
		}
		if (atEOL) {
			int levelUse = levelCurrent;
			if (foldAtElse) {
				levelUse = levelMinCurrent;
			}
			int lev = levelUse | levelNext << 16;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if (levelUse < levelNext)
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelCurrent = levelNext;
			levelMinCurrent = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
}

static void FoldVerilogDoc(unsigned int startPos, int length, int initStyle, WordList *[],
                       Accessor &styler) {
	FoldNoBoxVerilogDoc(startPos, length, initStyle, styler);
}

static const char * const verilogWordLists[] = {
            "Primary keywords and identifiers",
            "Secondary keywords and identifiers",
            "System Tasks",
            "User defined tasks and identifiers",
            "Unused",
            0,
        };

LexerModule lmVerilog(SCLEX_VERILOG, ColouriseVerilogDoc, "verilog", FoldVerilogDoc, verilogWordLists);
<commit_msg>Update to support SystemVerilog.<commit_after>// Scintilla source code edit control
/** @file LexVerilog.cxx
 ** Lexer for Verilog.
 ** Written by Avi Yegudin, based on C++ lexer by Neil Hodgson
 **/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool IsAWordChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\''|| ch == '$');
}

static inline bool IsAWordStart(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '$');
}

static void ColouriseVerilogDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                            Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
	WordList &keywords4 = *keywordlists[3];

	// Do not leak onto next line
	if (initStyle == SCE_V_STRINGEOL)
		initStyle = SCE_V_DEFAULT;

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {

		if (sc.atLineStart && (sc.state == SCE_V_STRING)) {
			// Prevent SCE_V_STRINGEOL from leaking back to previous line
			sc.SetState(SCE_V_STRING);
		}

		// Handle line continuation generically.
		if (sc.ch == '\\') {
			if (sc.chNext == '\n' || sc.chNext == '\r') {
				sc.Forward();
				if (sc.ch == '\r' && sc.chNext == '\n') {
					sc.Forward();
				}
				continue;
			}
		}

		// Determine if the current state should terminate.
		if (sc.state == SCE_V_OPERATOR) {
			sc.SetState(SCE_V_DEFAULT);
		} else if (sc.state == SCE_V_NUMBER) {
			if (!IsAWordChar(sc.ch)) {
				sc.SetState(SCE_V_DEFAULT);
			}
		} else if (sc.state == SCE_V_IDENTIFIER) {
			if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
				char s[100];
                                sc.GetCurrent(s, sizeof(s));
				if (keywords.InList(s)) {
					sc.ChangeState(SCE_V_WORD);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_V_WORD2);
				} else if (keywords3.InList(s)) {
					sc.ChangeState(SCE_V_WORD3);
                                } else if (keywords4.InList(s)) {
					sc.ChangeState(SCE_V_USER);
				}
				sc.SetState(SCE_V_DEFAULT);
			}
		} else if (sc.state == SCE_V_PREPROCESSOR) {
                        if (!IsAWordChar(sc.ch)) {
                                sc.SetState(SCE_V_DEFAULT);
                        }
		} else if (sc.state == SCE_V_COMMENT) {
			if (sc.Match('*', '/')) {
				sc.Forward();
				sc.ForwardSetState(SCE_V_DEFAULT);
			}
		} else if (sc.state == SCE_V_COMMENTLINE || sc.state == SCE_V_COMMENTLINEBANG) {
			if (sc.atLineStart) {
				sc.SetState(SCE_V_DEFAULT);
			}
                } else if (sc.state == SCE_V_STRING) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_V_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_V_STRINGEOL);
				sc.ForwardSetState(SCE_V_DEFAULT);
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_V_DEFAULT) {
			if (IsADigit(sc.ch) || (sc.ch == '\'') || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_V_NUMBER);
			} else if (IsAWordStart(sc.ch)) {
				sc.SetState(SCE_V_IDENTIFIER);
			} else if (sc.Match('/', '*')) {
                                sc.SetState(SCE_V_COMMENT);
				sc.Forward();	// Eat the * so it isn't used for the end of the comment
			} else if (sc.Match('/', '/')) {
				if (sc.Match("//!"))	// Nice to have a different comment style
					sc.SetState(SCE_V_COMMENTLINEBANG);
				else
					sc.SetState(SCE_V_COMMENTLINE);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_V_STRING);
			} else if (sc.ch == '`') {
				sc.SetState(SCE_V_PREPROCESSOR);
				// Skip whitespace between ` and preprocessor word
				do {
					sc.Forward();
				} while ((sc.ch == ' ' || sc.ch == '\t') && sc.More());
				if (sc.atLineEnd) {
					sc.SetState(SCE_V_DEFAULT);
				}
			} else if (isoperator(static_cast<char>(sc.ch)) || sc.ch == '@' || sc.ch == '#') {
				sc.SetState(SCE_V_OPERATOR);
			}
		}
	}
	sc.Complete();
}

static bool IsStreamCommentStyle(int style) {
	return style == SCE_V_COMMENT;
}

static bool IsCommentLine(int line, Accessor &styler) {
	int pos = styler.LineStart(line);
	int eolPos = styler.LineStart(line + 1) - 1;
	for (int i = pos; i < eolPos; i++) {
		char ch = styler[i];
		char chNext = styler.SafeGetCharAt(i + 1);
		int style = styler.StyleAt(i);
		if (ch == '/' && chNext == '/' &&
		   (style == SCE_V_COMMENTLINE || style == SCE_V_COMMENTLINEBANG)) {
			return true;
		} else if (!IsASpaceOrTab(ch)) {
			return false;
		}
	}
	return false;
}
// Store both the current line's fold level and the next lines in the
// level store to make it easy to pick up with each increment
// and to make it possible to fiddle the current level for "} else {".
static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle,
                            Accessor &styler) {
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0;
        // Verilog specific folding options:
        // fold_at_module -
        //      Generally used methodology in verilog code is
        //      one module per file, so folding at module definition is useless.
        // fold_at_brace/parenthese -
        //      Folding of long port lists can be convenient.
	bool foldAtModule = styler.GetPropertyInt("fold.verilog.flags", 0) != 0;
	bool foldAtBrace  = 1;
	bool foldAtParenthese  = 1;

	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelCurrent = SC_FOLDLEVELBASE;
	if (lineCurrent > 0)
		levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
	int levelMinCurrent = levelCurrent;
	int levelNext = levelCurrent;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (foldComment && IsStreamCommentStyle(style)) {
			if (!IsStreamCommentStyle(stylePrev)) {
				levelNext++;
			} else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
				// Comments don't end at end of line and the next character may be unstyled.
				levelNext--;
			}
		}
		if (foldComment && atEOL && IsCommentLine(lineCurrent, styler))
		{
			if (!IsCommentLine(lineCurrent - 1, styler)
			    && IsCommentLine(lineCurrent + 1, styler))
				levelNext++;
			else if (IsCommentLine(lineCurrent - 1, styler)
			         && !IsCommentLine(lineCurrent+1, styler))
				levelNext--;
		}
		if (foldComment && (style == SCE_V_COMMENTLINE)) {
			if ((ch == '/') && (chNext == '/')) {
				char chNext2 = styler.SafeGetCharAt(i + 2);
				if (chNext2 == '{') {
					levelNext++;
				} else if (chNext2 == '}') {
					levelNext--;
				}
			}
		}
		if (foldPreprocessor && (style == SCE_V_PREPROCESSOR)) {
			if (ch == '`') {
				unsigned int j = i + 1;
				while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
					j++;
				}
				if (styler.Match(j, "if")) {
					levelNext++;
				} else if (styler.Match(j, "end")) {
					levelNext--;
				}
			}
		}
                if (style == SCE_V_OPERATOR) {
                    if (foldAtParenthese) {
			if (ch == '(') {
				levelNext++;
			} else if (ch == ')') {
				levelNext--;
			}
                    }
		}
                if (style == SCE_V_OPERATOR) {
                    if (foldAtBrace) {
			if (ch == '{') {
				levelNext++;
			} else if (ch == '}') {
				levelNext--;
			}
                    }
		}
                if (style == SCE_V_WORD && stylePrev != SCE_V_WORD) {
                        unsigned int j = i;
                        if (styler.Match(j, "case") ||
                            styler.Match(j, "casex") ||
                            styler.Match(j, "casez") ||
                            styler.Match(j, "class") ||
                            styler.Match(j, "function") ||
                            styler.Match(j, "generate") ||
                            styler.Match(j, "covergroup") ||
                            styler.Match(j, "package") ||
                            styler.Match(j, "primitive") ||
                            styler.Match(j, "program") ||
                            styler.Match(j, "sequence") ||
                            styler.Match(j, "specify") ||
                            styler.Match(j, "table") ||
                            styler.Match(j, "task") ||
                            styler.Match(j, "fork") ||
                            (styler.Match(j, "module") && foldAtModule) ||
                            styler.Match(j, "begin")) {
                                levelNext++;
                        } else if (styler.Match(j, "endcase") ||
                                   styler.Match(j, "endclass") ||
                                   styler.Match(j, "endfunction") ||
                                   styler.Match(j, "endgenerate") ||
                                   styler.Match(j, "endgroup") ||
                                   styler.Match(j, "endpackage") ||
                                   styler.Match(j, "endprimitive") ||
                                   styler.Match(j, "endprogram") ||
                                   styler.Match(j, "endsequence") ||
                                   styler.Match(j, "endspecify") ||
                                   styler.Match(j, "endtable") ||
                                   styler.Match(j, "endtask") ||
                                   styler.Match(j, "join") ||
                                   styler.Match(j, "join_any") ||
                                   styler.Match(j, "join_none") ||
                                   (styler.Match(j, "endmodule") && foldAtModule) ||
                                   (styler.Match(j, "end") && !IsAWordChar(styler.SafeGetCharAt(j+3)))) {
                                levelNext--;
                        }
		}
		if (atEOL) {
			int levelUse = levelCurrent;
			if (foldAtElse) {
				levelUse = levelMinCurrent;
			}
			int lev = levelUse | levelNext << 16;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if (levelUse < levelNext)
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelCurrent = levelNext;
			levelMinCurrent = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
}

static void FoldVerilogDoc(unsigned int startPos, int length, int initStyle, WordList *[],
                       Accessor &styler) {
	FoldNoBoxVerilogDoc(startPos, length, initStyle, styler);
}

static const char * const verilogWordLists[] = {
            "Primary keywords and identifiers",
            "Secondary keywords and identifiers",
            "System Tasks",
            "User defined tasks and identifiers",
            "Unused",
            0,
        };

LexerModule lmVerilog(SCLEX_VERILOG, ColouriseVerilogDoc, "verilog", FoldVerilogDoc, verilogWordLists);
<|endoftext|>


<commit_before>#include "coverageobject.h"

#include <Cutelyst/Application>
#include <Cutelyst/Controller>
#include <Cutelyst/Plugins/CSRFProtection/CSRFProtection>

#include <QObject>
#include <QTest>
#include <QNetworkCookie>

using namespace Cutelyst;

class TestCsrfProtection : public CoverageObject
{
    Q_OBJECT
public:
    explicit TestCsrfProtection(QObject *parent = nullptr) : CoverageObject(parent) {}

    void initTest();
    void cleanupTest();

private Q_SLOTS:
    void initTestCase();

    void doTest_data();
    void doTest();
    void detachToOnArgument();
    void csrfIgnorArgument();
    void ignoreNamespace();
    void ignoreNamespaceRequired();
    void csrfRedirect();

    void cleanupTestCase();

private:
    TestEngine *m_engine;
    QNetworkCookie m_cookie;
    const QString m_cookieName = QStringLiteral("xsrftoken");
    const QString m_fieldName = QStringLiteral("xsrfprotect");
    const QString m_headerName = QStringLiteral("X-MY-CSRF");
    QString m_fieldValue;

    TestEngine *getEngine();

    void performTest();
};

class CsrfprotectionTest : public Controller
{
    Q_OBJECT
public:
    explicit CsrfprotectionTest(QObject *parent) : Controller(parent) {}

    C_ATTR(testCsrf, :Local :AutoArgs)
    void testCsrf(Context *c)
    {
        c->res()->setContentType(QStringLiteral("text/plain"));
        if (c->req()->isGet()) {
            c->res()->setBody(CSRFProtection::getToken(c));
        } else {
            c->res()->setBody(QByteArrayLiteral("allowed"));
        }
    }

    C_ATTR(testCsrfIgnore, :Local :AutoArgs :CSRFIgnore)
    void testCsrfIgnore(Context *c)
    {
        c->res()->setContentType(QStringLiteral("text/plain"));
        c->res()->setBody(QByteArrayLiteral("allowed"));
    }

    C_ATTR(testCsrfRedirect, :Local :AutoArgs)
    void testCsrfRedirect(Context *c)
    {
        c->res()->redirect(QStringLiteral("http//www.example.com"));
    }

    C_ATTR(testCsrfDetachTo, :Local :AutoArgs :CSRFDetachTo(csrfdenied))
    void testCsrfDetachTo(Context *c)
    {
        c->res()->setContentType(QStringLiteral("text/plain"));
        c->res()->setBody(QByteArrayLiteral("allowed"));
    }

    C_ATTR(csrfdenied, :Private :AutoArgs)
    void csrfdenied(Context *c)
    {
        c->res()->setContentType(QStringLiteral("text/plain"));
        c->res()->setBody(QByteArrayLiteral("detachdenied"));
        c->detach();
    }
};

class CsrfprotectionNsTest : public Controller
{
    Q_OBJECT
    C_NAMESPACE("testns")
public:
    explicit CsrfprotectionNsTest(QObject *parent) : Controller(parent) {}

    C_ATTR(testCsrf, :Local :AutoArgs)
    void testCsrf(Context *c)
    {
        c->res()->setContentType(QStringLiteral("text/plain"));
        c->res()->setBody(QByteArrayLiteral("allowed"));
    }

    C_ATTR(testCsrfRequired, :Local :AutoArgs :CSRFRequire)
    void testCsrfRequired(Context *c)
    {
        c->res()->setContentType(QStringLiteral("text/plain"));
        c->res()->setBody(QByteArrayLiteral("allowed"));
    }
};

void TestCsrfProtection::initTestCase()
{
    m_engine = getEngine();
    QVERIFY(m_engine);
    if (m_cookie.value().isEmpty()) {
        const QVariantMap result = m_engine->createRequest(QStringLiteral("GET"), QStringLiteral("csrfprotection/test/testCsrf"), QByteArray(), Headers(), nullptr);
        const QList<QNetworkCookie> cookies = QNetworkCookie::parseCookies(result.value(QStringLiteral("headers")).value<Headers>().header(QStringLiteral("Set-Cookie")).toLatin1());
        QVERIFY(!cookies.empty());
        for (const QNetworkCookie &cookie : cookies) {
            if (cookie.name() == m_cookieName.toLatin1()) {
                m_cookie = cookie;
                break;
            }
        }
        QVERIFY(!m_cookie.value().isEmpty());
        initTest();
    }
}

TestEngine* TestCsrfProtection::getEngine()
{
    qputenv("RECURSION", QByteArrayLiteral("100"));
    auto app = new TestApplication;
    auto engine = new TestEngine(app, QVariantMap());
    auto csrf = new CSRFProtection(app);
    csrf->setCookieName(m_cookieName);
    csrf->setGenericErrorMessage(QStringLiteral("denied"));
    csrf->setFormFieldName(m_fieldName);
    csrf->setHeaderName(m_headerName);
    csrf->setIgnoredNamespaces(QStringList(QStringLiteral("testns")));
    new CsrfprotectionTest(app);
    new CsrfprotectionNsTest(app);
    if (!engine->init()) {
        delete engine;
        return nullptr;
    }
    return engine;
}

void TestCsrfProtection::cleanupTestCase()
{
    delete m_engine;
}

void TestCsrfProtection::initTest()
{
    Headers headers;
    headers.setHeader(QStringLiteral("Cookie"), QString::fromLatin1(m_cookie.toRawForm(QNetworkCookie::NameAndValueOnly)));
    m_fieldValue = m_engine->createRequest(QStringLiteral("GET"), QStringLiteral("csrfprotection/test/testCsrf"), QByteArray(), headers, nullptr).value(QStringLiteral("body")).toString();
}

void TestCsrfProtection::cleanupTest()
{
    m_fieldValue.clear();
}

void TestCsrfProtection::doTest()
{
    QFETCH(QString, method);
    QFETCH(Headers, headers);
    QFETCH(QByteArray, body);
    QFETCH(int, status);
    QFETCH(QByteArray, output);

    const QVariantMap result = m_engine->createRequest(method, QStringLiteral("csrfprotection/test/testCsrf"), QByteArray(), headers, &body);

    QCOMPARE(result.value(QStringLiteral("statusCode")).value<int>(), status);
    QCOMPARE(result.value(QStringLiteral("body")).toByteArray(), output);
}

void TestCsrfProtection::doTest_data()
{
    QTest::addColumn<QString>("method");
    QTest::addColumn<Headers>("headers");
    QTest::addColumn<QByteArray>("body");
    QTest::addColumn<int>("status");
    QTest::addColumn<QByteArray>("output");

    for (const QString &method : {QStringLiteral("POST"), QStringLiteral("PUT"), QStringLiteral("PATCH"), QStringLiteral("DELETE")}) {
        const QString cookieValid = QString::fromLatin1(m_cookie.toRawForm(QNetworkCookie::NameAndValueOnly));
        QString cookieInvalid = cookieValid;
        QChar& cookieLast = cookieInvalid[cookieInvalid.size() - 1];
        if (cookieLast.isDigit()) {
            if (cookieLast.unicode() < 57) {
                cookieLast.unicode()++;
            } else {
                cookieLast.unicode()--;
            }
        } else {
            if (cookieLast.isUpper()) {
                cookieLast = cookieLast.toLower();
            } else {
                cookieLast = cookieLast.toUpper();
            }
        }

        QString fieldValueInvalid = m_fieldValue;
        QChar& fieldLast = fieldValueInvalid[fieldValueInvalid.size() - 2];
        if (fieldLast.isDigit()) {
            if (fieldLast.unicode() < 57) {
                fieldLast.unicode()++;
            } else {
                fieldLast.unicode()--;
            }
        } else {
            if (fieldLast.isUpper()) {
                fieldLast = fieldLast.toLower();
            } else {
                fieldLast = fieldLast.toUpper();
            }
        }

        const QString fieldValid = m_fieldName + QLatin1Char('=') + m_fieldValue;
        const QString fieldInvalid = m_fieldName + QLatin1Char('=') + fieldValueInvalid;

        Headers headers;
        headers.setContentType(QStringLiteral("application/x-www-form-urlencoded"));
        QByteArray body;

        QTest::newRow(qUtf8Printable(QStringLiteral("%1: cookie(absent), header(absent), field(absent)").arg(method))) << method << headers << body << 403 << QByteArrayLiteral("denied");

        headers.setHeader(QStringLiteral("Cookie"), cookieValid);
        QTest::newRow(qUtf8Printable(QStringLiteral("%1: cookie(valid), header(absent), field(absent)").arg(method))) << method << headers << body << 403 << QByteArrayLiteral("denied");

        headers.setHeader(QStringLiteral("Cookie"), cookieInvalid);
        QTest::newRow(qUtf8Printable(QStringLiteral("%1: cookie(invalid), header(absent), field(absent)").arg(method))) << method << headers << body << 403 << QByteArrayLiteral("denied");

        headers.removeHeader(QStringLiteral("Cookie"));
        headers.setHeader(m_headerName, m_fieldValue);
        QTest::newRow(qUtf8Printable(QStringLiteral("%1: cookie(absent), header(valid), field(absent)").arg(method))) << method << headers << body << 403 << QByteArrayLiteral("denied");

        headers.setHeader(QStringLiteral("Cookie"), cookieValid);
        QTest::newRow(qUtf8Printable(QStringLiteral("%1: cookie(valid), header(valid), field(absent)").arg(method))) << method << headers << body << 200 << QByteArrayLiteral("allowed");

        headers.setHeader(QStringLiteral("Cookie"), cookieInvalid);
        QTest::newRow(qUtf8Printable(QStringLiteral("%1: cookie(invalid), header(valid), field(absent)").arg(method))) << method << headers << body << 403 << QByteArrayLiteral("denied");

        headers.setHeader(m_headerName, fieldValueInvalid);
        QTest::newRow(qUtf8Printable(QStringLiteral("%1: cookie(invalid), header(invalid), field(absent)").arg(method))) << method << headers << body << 403 << QByteArrayLiteral("denied");

        headers.setHeader(QStringLiteral("Cookie"), cookieValid);
        QTest::newRow(qUtf8Printable(QStringLiteral("%1: cookie(valid), header(invalid), field(absent)").arg(method))) << method << headers << body << 403 << QByteArrayLiteral("denied");

        body = method != u"DELETE" ? fieldValid.toLatin1() : QByteArray();
        int status = (method != u"DELETE") ? 200 : 403;
        QByteArray result = (method != u"DELETE") ? QByteArrayLiteral("allowed") : QByteArrayLiteral("denied");
        QTest::newRow(qUtf8Printable(QStringLiteral("%1: cookie(valid), header(invalid), field(valid)").arg(method))) << method << headers << body << status << result;

        body = fieldInvalid.toLatin1();
        QTest::newRow(qUtf8Printable(QStringLiteral("%1: cookie(valid), header(invalid), field(invalid)").arg(method))) << method << headers << body << 403 << QByteArrayLiteral("denied");

        headers.setHeader(m_headerName, m_fieldValue);
        status = method == u"DELETE" ? 200 : 403;
        result = method == u"DELETE" ? QByteArrayLiteral("allowed") : QByteArrayLiteral("denied");
        QTest::newRow(qUtf8Printable(QStringLiteral("%1: cookie(valid), header(valid), field(invalid)").arg(method))) << method << headers << body << status << result;

        headers.setHeader(QStringLiteral("Cookie"), cookieInvalid);
        body = fieldValid.toLatin1();
        QTest::newRow(qUtf8Printable(QStringLiteral("%1: cookie(invalid), header(valid), field(valid)").arg(method))) << method << headers << body << 403 << QByteArrayLiteral("denied");
    }
}

void TestCsrfProtection::detachToOnArgument()
{
    const QVariantMap result = m_engine->createRequest(QStringLiteral("POST"), QStringLiteral("csrfprotection/test/testCsrfDetachTo"), QByteArray(), Headers(), nullptr);
    QCOMPARE(result.value(QStringLiteral("statusCode")).value<int>(), 403);
    QCOMPARE(result.value(QStringLiteral("body")).toByteArray(), QByteArrayLiteral("detachdenied"));
}

void TestCsrfProtection::csrfIgnorArgument()
{
    const QVariantMap result = m_engine->createRequest(QStringLiteral("POST"), QStringLiteral("csrfprotection/test/testCsrfIgnore"), QByteArray(), Headers(), nullptr);
    QCOMPARE(result.value(QStringLiteral("statusCode")).value<int>(), 200);
    QCOMPARE(result.value(QStringLiteral("body")).toByteArray(), QByteArrayLiteral("allowed"));
}

void TestCsrfProtection::ignoreNamespace()
{
    const QVariantMap result = m_engine->createRequest(QStringLiteral("POST"), QStringLiteral("testns/testCsrf"), QByteArray(), Headers(), nullptr);
    QCOMPARE(result.value(QStringLiteral("statusCode")).value<int>(), 200);
    QCOMPARE(result.value(QStringLiteral("body")).toByteArray(), QByteArrayLiteral("allowed"));
}

void TestCsrfProtection::ignoreNamespaceRequired()
{
    const QVariantMap result = m_engine->createRequest(QStringLiteral("POST"), QStringLiteral("testns/testCsrfRequired"), QByteArray(), Headers(), nullptr);
    QCOMPARE(result.value(QStringLiteral("statusCode")).value<int>(), 403);
    QCOMPARE(result.value(QStringLiteral("body")).toByteArray(), QByteArrayLiteral("denied"));
}

void TestCsrfProtection::csrfRedirect()
{
    const QVariantMap result = m_engine->createRequest(QStringLiteral("POST"), QStringLiteral("csrfprotection/test/testCsrfRedirect"), QByteArray(), Headers(), nullptr);
    QCOMPARE(result.value(QStringLiteral("statusCode")).value<int>(), 403);
    QCOMPARE(result.value(QStringLiteral("body")).toByteArray(), QByteArrayLiteral("denied"));
}

QTEST_MAIN(TestCsrfProtection)

#include "testcsrfprotection.moc"
<commit_msg>CSRFProtection plugin: fix tests on Qt5<commit_after>#include "coverageobject.h"

#include <Cutelyst/Application>
#include <Cutelyst/Controller>
#include <Cutelyst/Plugins/CSRFProtection/CSRFProtection>

#include <QObject>
#include <QTest>
#include <QNetworkCookie>

using namespace Cutelyst;

class TestCsrfProtection : public CoverageObject
{
    Q_OBJECT
public:
    explicit TestCsrfProtection(QObject *parent = nullptr) : CoverageObject(parent) {}

    void initTest();
    void cleanupTest();

private Q_SLOTS:
    void initTestCase();

    void doTest_data();
    void doTest();
    void detachToOnArgument();
    void csrfIgnorArgument();
    void ignoreNamespace();
    void ignoreNamespaceRequired();
    void csrfRedirect();

    void cleanupTestCase();

private:
    TestEngine *m_engine;
    QNetworkCookie m_cookie;
    const QString m_cookieName = QStringLiteral("xsrftoken");
    const QString m_fieldName = QStringLiteral("xsrfprotect");
    const QString m_headerName = QStringLiteral("X-MY-CSRF");
    QString m_fieldValue;

    TestEngine *getEngine();

    void performTest();
};

class CsrfprotectionTest : public Controller
{
    Q_OBJECT
public:
    explicit CsrfprotectionTest(QObject *parent) : Controller(parent) {}

    C_ATTR(testCsrf, :Local :AutoArgs)
    void testCsrf(Context *c)
    {
        c->res()->setContentType(QStringLiteral("text/plain"));
        if (c->req()->isGet()) {
            c->res()->setBody(CSRFProtection::getToken(c));
        } else {
            c->res()->setBody(QByteArrayLiteral("allowed"));
        }
    }

    C_ATTR(testCsrfIgnore, :Local :AutoArgs :CSRFIgnore)
    void testCsrfIgnore(Context *c)
    {
        c->res()->setContentType(QStringLiteral("text/plain"));
        c->res()->setBody(QByteArrayLiteral("allowed"));
    }

    C_ATTR(testCsrfRedirect, :Local :AutoArgs)
    void testCsrfRedirect(Context *c)
    {
        c->res()->redirect(QStringLiteral("http//www.example.com"));
    }

    C_ATTR(testCsrfDetachTo, :Local :AutoArgs :CSRFDetachTo(csrfdenied))
    void testCsrfDetachTo(Context *c)
    {
        c->res()->setContentType(QStringLiteral("text/plain"));
        c->res()->setBody(QByteArrayLiteral("allowed"));
    }

    C_ATTR(csrfdenied, :Private :AutoArgs)
    void csrfdenied(Context *c)
    {
        c->res()->setContentType(QStringLiteral("text/plain"));
        c->res()->setBody(QByteArrayLiteral("detachdenied"));
        c->detach();
    }
};

class CsrfprotectionNsTest : public Controller
{
    Q_OBJECT
    C_NAMESPACE("testns")
public:
    explicit CsrfprotectionNsTest(QObject *parent) : Controller(parent) {}

    C_ATTR(testCsrf, :Local :AutoArgs)
    void testCsrf(Context *c)
    {
        c->res()->setContentType(QStringLiteral("text/plain"));
        c->res()->setBody(QByteArrayLiteral("allowed"));
    }

    C_ATTR(testCsrfRequired, :Local :AutoArgs :CSRFRequire)
    void testCsrfRequired(Context *c)
    {
        c->res()->setContentType(QStringLiteral("text/plain"));
        c->res()->setBody(QByteArrayLiteral("allowed"));
    }
};

void TestCsrfProtection::initTestCase()
{
    m_engine = getEngine();
    QVERIFY(m_engine);
    if (m_cookie.value().isEmpty()) {
        const QVariantMap result = m_engine->createRequest(QStringLiteral("GET"), QStringLiteral("csrfprotection/test/testCsrf"), QByteArray(), Headers(), nullptr);
        const QList<QNetworkCookie> cookies = QNetworkCookie::parseCookies(result.value(QStringLiteral("headers")).value<Headers>().header(QStringLiteral("Set-Cookie")).toLatin1());
        QVERIFY(!cookies.empty());
        for (const QNetworkCookie &cookie : cookies) {
            if (cookie.name() == m_cookieName.toLatin1()) {
                m_cookie = cookie;
                break;
            }
        }
        QVERIFY(!m_cookie.value().isEmpty());
        initTest();
    }
}

TestEngine* TestCsrfProtection::getEngine()
{
    qputenv("RECURSION", QByteArrayLiteral("100"));
    auto app = new TestApplication;
    auto engine = new TestEngine(app, QVariantMap());
    auto csrf = new CSRFProtection(app);
    csrf->setCookieName(m_cookieName);
    csrf->setGenericErrorMessage(QStringLiteral("denied"));
    csrf->setFormFieldName(m_fieldName);
    csrf->setHeaderName(m_headerName);
    csrf->setIgnoredNamespaces(QStringList(QStringLiteral("testns")));
    new CsrfprotectionTest(app);
    new CsrfprotectionNsTest(app);
    if (!engine->init()) {
        delete engine;
        return nullptr;
    }
    return engine;
}

void TestCsrfProtection::cleanupTestCase()
{
    delete m_engine;
}

void TestCsrfProtection::initTest()
{
    Headers headers;
    headers.setHeader(QStringLiteral("Cookie"), QString::fromLatin1(m_cookie.toRawForm(QNetworkCookie::NameAndValueOnly)));
    m_fieldValue = m_engine->createRequest(QStringLiteral("GET"), QStringLiteral("csrfprotection/test/testCsrf"), QByteArray(), headers, nullptr).value(QStringLiteral("body")).toString();
}

void TestCsrfProtection::cleanupTest()
{
    m_fieldValue.clear();
}

void TestCsrfProtection::doTest()
{
    QFETCH(QString, method);
    QFETCH(Headers, headers);
    QFETCH(QByteArray, body);
    QFETCH(int, status);
    QFETCH(QByteArray, output);

    const QVariantMap result = m_engine->createRequest(method, QStringLiteral("csrfprotection/test/testCsrf"), QByteArray(), headers, &body);

    QCOMPARE(result.value(QStringLiteral("statusCode")).value<int>(), status);
    QCOMPARE(result.value(QStringLiteral("body")).toByteArray(), output);
}

void TestCsrfProtection::doTest_data()
{
    QTest::addColumn<QString>("method");
    QTest::addColumn<Headers>("headers");
    QTest::addColumn<QByteArray>("body");
    QTest::addColumn<int>("status");
    QTest::addColumn<QByteArray>("output");

    for (const QString &method : {QStringLiteral("POST"), QStringLiteral("PUT"), QStringLiteral("PATCH"), QStringLiteral("DELETE")}) {
        const QString cookieValid = QString::fromLatin1(m_cookie.toRawForm(QNetworkCookie::NameAndValueOnly));
        QString cookieInvalid = cookieValid;
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
        auto& cookieLast = cookieInvalid[cookieInvalid.size() - 1];
#else
        QCharRef cookieLast = cookieInvalid[cookieInvalid.size() - 1];
#endif
        if (cookieLast.isDigit()) {
            if (cookieLast.unicode() < 57) {
                cookieLast.unicode()++;
            } else {
                cookieLast.unicode()--;
            }
        } else {
            if (cookieLast.isUpper()) {
                cookieLast = cookieLast.toLower();
            } else {
                cookieLast = cookieLast.toUpper();
            }
        }

        QString fieldValueInvalid = m_fieldValue;
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
        auto& fieldLast = fieldValueInvalid[fieldValueInvalid.size() - 2];
#else
        QCharRef fieldLast = fieldValueInvalid[fieldValueInvalid.size() - 2];
#endif
        if (fieldLast.isDigit()) {
            if (fieldLast.unicode() < 57) {
                fieldLast.unicode()++;
            } else {
                fieldLast.unicode()--;
            }
        } else {
            if (fieldLast.isUpper()) {
                fieldLast = fieldLast.toLower();
            } else {
                fieldLast = fieldLast.toUpper();
            }
        }

        const QString fieldValid = m_fieldName + QLatin1Char('=') + m_fieldValue;
        const QString fieldInvalid = m_fieldName + QLatin1Char('=') + fieldValueInvalid;

        Headers headers;
        headers.setContentType(QStringLiteral("application/x-www-form-urlencoded"));
        QByteArray body;

        QTest::newRow(qUtf8Printable(QStringLiteral("%1: cookie(absent), header(absent), field(absent)").arg(method))) << method << headers << body << 403 << QByteArrayLiteral("denied");

        headers.setHeader(QStringLiteral("Cookie"), cookieValid);
        QTest::newRow(qUtf8Printable(QStringLiteral("%1: cookie(valid), header(absent), field(absent)").arg(method))) << method << headers << body << 403 << QByteArrayLiteral("denied");

        headers.setHeader(QStringLiteral("Cookie"), cookieInvalid);
        QTest::newRow(qUtf8Printable(QStringLiteral("%1: cookie(invalid), header(absent), field(absent)").arg(method))) << method << headers << body << 403 << QByteArrayLiteral("denied");

        headers.removeHeader(QStringLiteral("Cookie"));
        headers.setHeader(m_headerName, m_fieldValue);
        QTest::newRow(qUtf8Printable(QStringLiteral("%1: cookie(absent), header(valid), field(absent)").arg(method))) << method << headers << body << 403 << QByteArrayLiteral("denied");

        headers.setHeader(QStringLiteral("Cookie"), cookieValid);
        QTest::newRow(qUtf8Printable(QStringLiteral("%1: cookie(valid), header(valid), field(absent)").arg(method))) << method << headers << body << 200 << QByteArrayLiteral("allowed");

        headers.setHeader(QStringLiteral("Cookie"), cookieInvalid);
        QTest::newRow(qUtf8Printable(QStringLiteral("%1: cookie(invalid), header(valid), field(absent)").arg(method))) << method << headers << body << 403 << QByteArrayLiteral("denied");

        headers.setHeader(m_headerName, fieldValueInvalid);
        QTest::newRow(qUtf8Printable(QStringLiteral("%1: cookie(invalid), header(invalid), field(absent)").arg(method))) << method << headers << body << 403 << QByteArrayLiteral("denied");

        headers.setHeader(QStringLiteral("Cookie"), cookieValid);
        QTest::newRow(qUtf8Printable(QStringLiteral("%1: cookie(valid), header(invalid), field(absent)").arg(method))) << method << headers << body << 403 << QByteArrayLiteral("denied");

        body = method != u"DELETE" ? fieldValid.toLatin1() : QByteArray();
        int status = (method != u"DELETE") ? 200 : 403;
        QByteArray result = (method != u"DELETE") ? QByteArrayLiteral("allowed") : QByteArrayLiteral("denied");
        QTest::newRow(qUtf8Printable(QStringLiteral("%1: cookie(valid), header(invalid), field(valid)").arg(method))) << method << headers << body << status << result;

        body = fieldInvalid.toLatin1();
        QTest::newRow(qUtf8Printable(QStringLiteral("%1: cookie(valid), header(invalid), field(invalid)").arg(method))) << method << headers << body << 403 << QByteArrayLiteral("denied");

        headers.setHeader(m_headerName, m_fieldValue);
        status = method == u"DELETE" ? 200 : 403;
        result = method == u"DELETE" ? QByteArrayLiteral("allowed") : QByteArrayLiteral("denied");
        QTest::newRow(qUtf8Printable(QStringLiteral("%1: cookie(valid), header(valid), field(invalid)").arg(method))) << method << headers << body << status << result;

        headers.setHeader(QStringLiteral("Cookie"), cookieInvalid);
        body = fieldValid.toLatin1();
        QTest::newRow(qUtf8Printable(QStringLiteral("%1: cookie(invalid), header(valid), field(valid)").arg(method))) << method << headers << body << 403 << QByteArrayLiteral("denied");
    }
}

void TestCsrfProtection::detachToOnArgument()
{
    const QVariantMap result = m_engine->createRequest(QStringLiteral("POST"), QStringLiteral("csrfprotection/test/testCsrfDetachTo"), QByteArray(), Headers(), nullptr);
    QCOMPARE(result.value(QStringLiteral("statusCode")).value<int>(), 403);
    QCOMPARE(result.value(QStringLiteral("body")).toByteArray(), QByteArrayLiteral("detachdenied"));
}

void TestCsrfProtection::csrfIgnorArgument()
{
    const QVariantMap result = m_engine->createRequest(QStringLiteral("POST"), QStringLiteral("csrfprotection/test/testCsrfIgnore"), QByteArray(), Headers(), nullptr);
    QCOMPARE(result.value(QStringLiteral("statusCode")).value<int>(), 200);
    QCOMPARE(result.value(QStringLiteral("body")).toByteArray(), QByteArrayLiteral("allowed"));
}

void TestCsrfProtection::ignoreNamespace()
{
    const QVariantMap result = m_engine->createRequest(QStringLiteral("POST"), QStringLiteral("testns/testCsrf"), QByteArray(), Headers(), nullptr);
    QCOMPARE(result.value(QStringLiteral("statusCode")).value<int>(), 200);
    QCOMPARE(result.value(QStringLiteral("body")).toByteArray(), QByteArrayLiteral("allowed"));
}

void TestCsrfProtection::ignoreNamespaceRequired()
{
    const QVariantMap result = m_engine->createRequest(QStringLiteral("POST"), QStringLiteral("testns/testCsrfRequired"), QByteArray(), Headers(), nullptr);
    QCOMPARE(result.value(QStringLiteral("statusCode")).value<int>(), 403);
    QCOMPARE(result.value(QStringLiteral("body")).toByteArray(), QByteArrayLiteral("denied"));
}

void TestCsrfProtection::csrfRedirect()
{
    const QVariantMap result = m_engine->createRequest(QStringLiteral("POST"), QStringLiteral("csrfprotection/test/testCsrfRedirect"), QByteArray(), Headers(), nullptr);
    QCOMPARE(result.value(QStringLiteral("statusCode")).value<int>(), 403);
    QCOMPARE(result.value(QStringLiteral("body")).toByteArray(), QByteArrayLiteral("denied"));
}

QTEST_MAIN(TestCsrfProtection)

#include "testcsrfprotection.moc"
<|endoftext|>


<commit_before>#ifndef GRAPHICS_HPP
#define GRAPHICS_HPP

#include "Graphics.h"
#include <algorithm>

#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480   //minimum size to allow for 64x64 maps

Graphics::Graphics(Uint16 xSize, Uint16 tileOffset, Uint16 tileAmount) {
    this->selXMin = std::min(8*64, 8*xSize) + 1;
    this->xDisplaySize = std::min(64, 0+xSize);
    this->tileOffset = tileOffset;
    this->tileAmount = tileAmount;
    this->currentPal = 0;
    this->highPriorityDisplay = true;
    this->lowPriorityDisplay = true;
    this->screenTileYOffset = 0;
    this->screenTileXOffset = 0;
    this->selTileYOffset = 0;

    /* calculate selector width */
    this->selectorWidth = 8;
    while(8*tileAmount / selectorWidth > SCREEN_HEIGHT) {
        if(8 * (xSize+selectorWidth) < SCREEN_WIDTH) selectorWidth += 8;
        else break;
    }

    if(SDL_Init(SDL_INIT_VIDEO)<0) {
        fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
        exit(1);
    }
    atexit(SDL_Quit);

    window = SDL_CreateWindow( "PlaneEd", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE );
    if ( window == NULL )
    {
        fprintf( stderr, "Error - %s\n", SDL_GetError() );
        exit(1);
    }

    render = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED );
    if ( render == NULL )
    {
        fprintf( stderr, "Error - %s\n", SDL_GetError() );
        exit(1);
    }

    SDL_RenderSetLogicalSize(render, SCREEN_WIDTH, SCREEN_HEIGHT);

    screen = SDL_CreateRGBSurface(0, SCREEN_WIDTH, SCREEN_HEIGHT, 32, 0, 0, 0, 0);
    if(screen==NULL) {
        fprintf(stderr, "Unable to set 640x480 video: %s\n", SDL_GetError());
        exit(1);
    }
    texture = SDL_CreateTextureFromSurface(render, screen);
    if(texture==NULL) {
        fprintf( stderr, "Error - %s\n", SDL_GetError() );
        exit(1);
    }
}

void Graphics::ReadPalette(char* filename) {
    FILE* palfile = fopen(filename,"rb");
    if(palfile==NULL) {
        fprintf(stderr, "Cannot open palette file.\n");
        exit(1);
    }
    fseek(palfile, 0, SEEK_END);
    paletteLines = ftell(palfile)/0x20;
    if(paletteLines > 4) paletteLines = 4;
    rewind(palfile);
    if(paletteLines == 0) {
        fprintf(stderr, "Palette file too small.\n");
        exit(1);
    }
    palette = new Uint16[paletteLines][16];
    for(int i=0; i<paletteLines; i++)
        fread(palette[i], sizeof(unsigned char), 32, palfile);
    fclose(palfile);
    remove(filename);
}
#define getrgb(v) ((v&0xF000)>>8)|(v&0x0F0F|0xF000)	// Corrects G value, and sets alpha to max, so we can see
void Graphics::ReadTiles(char* filename) {
    FILE* tilefile = fopen(filename,"rb");
    if(tilefile==NULL) {
        fprintf(stderr, "Cannot open tile graphics file.\n");
        exit(1);
    }
    unsigned char tilebuffer[32]; //space for one tile
    tileData = new Uint16***[tileAmount];
    for(int t=0; t<tileAmount; t++) {
        fread(tilebuffer, sizeof(unsigned char), 32, tilefile);
        tileData[t] = new Uint16**[paletteLines];
        for(int p=0; p<paletteLines; p++) {
            tileData[t][p] = new Uint16*[4];
            for(int f=0; f<4; f++) tileData[t][p][f] = new Uint16[64];
            for(int i=0; i<32; i++) {
                tileData[t][p][0][2*i]   = getrgb(palette[p][(tilebuffer[i] & 0xF0)>>4]);
                tileData[t][p][0][2*i+1] = getrgb(palette[p][(tilebuffer[i] & 0x0F)]);
                tileData[t][p][1][8*(i/4)+7-2*(i%4)]   = getrgb(palette[p][(tilebuffer[i] & 0xF0)>>4]); //X-flip
                tileData[t][p][1][8*(i/4)+7-2*(i%4)-1] = getrgb(palette[p][(tilebuffer[i] & 0x0F)]);
                tileData[t][p][2][56-8*(i/4)+2*(i%4)]   = getrgb(palette[p][(tilebuffer[i] & 0xF0)>>4]); //Y-flip
                tileData[t][p][2][56-8*(i/4)+2*(i%4)+1] = getrgb(palette[p][(tilebuffer[i] & 0x0F)]);
                tileData[t][p][3][63-2*i]   = getrgb(palette[p][(tilebuffer[i] & 0xF0)>>4]); //XY-flip
                tileData[t][p][3][63-2*i-1] = getrgb(palette[p][(tilebuffer[i] & 0x0F)]);
            }
        }
    }
    fclose(tilefile);
    remove(filename);
}

void Graphics::CreateTiles(){
    tiles = new SDL_Surface***[tileAmount];
    for(int t=0; t<tileAmount; t++)
    {
        tiles[t] = new SDL_Surface**[paletteLines];
        for(int p=0; p<paletteLines; p++)
        {
            tiles[t][p] = new SDL_Surface*[4];
            for(int f=0; f<4; f++)
                tiles[t][p][f] = InitSurface(tileData[t][p][f], 8, 8, 16);
        }
    }
}

SDL_Surface* Graphics::InitSurface(Uint16 *pixelsT, int width, int height, int bbp) {
    void* pixels = pixelsT;
    SDL_Surface *surface = SDL_CreateRGBSurfaceFrom (pixels, width,
                         height, bbp, width*((bbp+7)/8), 0x0F00, 0x00F0, 0x000F, 0xF000);

    if (surface == NULL)
        fprintf(stderr, "Error - %s\n", SDL_GetError());

    return(surface);
}

void Graphics::DrawSurface(SDL_Surface *img, SDL_Surface *screen, int x, int y) {
    SDL_Rect RectTemp;
    RectTemp.x = x;
    RectTemp.y = y;
    SDL_BlitSurface(img, NULL, screen, &RectTemp);
}

void Graphics::ClearMap() {
    Uint32 color = SDL_MapRGB(screen->format, 0, 0, 0);
    SDL_Rect RectTemp;
    RectTemp.x = 0;
    RectTemp.y = 0;
    RectTemp.w = selXMin-1;
    RectTemp.h = SCREEN_HEIGHT;
    SDL_FillRect(this->screen, &RectTemp, color);
}

void Graphics::ClearSelector() {
    Uint32 color = SDL_MapRGB(screen->format, 0, 0, 0);
    SDL_Rect RectTemp;
    RectTemp.x = selXMin;
    RectTemp.y = 0;
    RectTemp.w = 8*selectorWidth;
    RectTemp.h = SCREEN_HEIGHT;
    SDL_FillRect(this->screen, &RectTemp, color);
}

void Graphics::DrawSelector() {
    ClearSelector();
    for(int i=0; i<tileAmount; i++)
        DrawSurface(tiles[i][currentPal][0], this->screen, selXMin + 8*(i%selectorWidth), 8*(i/selectorWidth - selTileYOffset));
    //SDL_Flip(screen);
    ProcessDisplay();
}

void Graphics::ProcessDisplay()
{
	SDL_UpdateTexture(texture, NULL, screen->pixels, screen->pitch);
	SDL_RenderClear(render);
	SDL_RenderCopy(render, texture, NULL, NULL);
	SDL_RenderPresent(render);
}

/* map coords */
void Graphics::DrawTileSingle(int x, int y, Tile tile) {
    y -= screenTileYOffset;
    x -= screenTileXOffset;
    if (x >= xDisplaySize) return;
    if((tile.priority && highPriorityDisplay) || (!tile.priority && lowPriorityDisplay)) {
        if((tile.tileID) - tileOffset >= this->tileAmount) {
            DrawTileNone(x, y);
            DrawTileInvalid(x, y);
        } else if((tile.tileID || !this->tileOffset) && tile.paletteLine < paletteLines)
            DrawSurface(tiles[(tile.tileID) - tileOffset][tile.paletteLine][(tile.xFlip | tile.yFlip)>>3], screen, 8*x, 8*y);
        else DrawTileBlank(x, y, tile);
    } else DrawTileNone(x, y);
}

bool Graphics::CheckSelValidPos(int x, int y) {
    if(x>=selXMin && x<selXMin+8*selectorWidth && y>=0 && (x-selXMin)/8+selectorWidth*(y/8 + selTileYOffset)<GetTileAmount()) return true;
    else return false;
}

void Graphics::DrawTileNone(int x, int y) {
    Uint32 color = SDL_MapRGB(screen->format, 0, 0, 0);
    DrawTileFullColor(x, y, color);
}

void Graphics::DrawTileBlank(int x, int y, Tile tile) {
    Uint32 color = SDL_MapRGB(
        screen->format,
        (palette[tile.paletteLine][0] & 0x0F00)>>4,
        (palette[tile.paletteLine][0] & 0x00F0),
        (palette[tile.paletteLine][0] & 0x000F)<<4
    );
    DrawTileFullColor(x, y, color);
}

void Graphics::DrawTileFullColor(int x, int y, Uint32 color) {
    SDL_Rect RectTemp;
    RectTemp.x = 8*x;
    RectTemp.y = 8*y;
    RectTemp.w = 8;
    RectTemp.h = 8;
    SDL_FillRect(this->screen, &RectTemp, color);
}

void Graphics::DrawTileInvalid(int x, int y) {
    //PosTileToScreen(x, y);
    for(int i=0; i<8; i++) {
        DrawPixel(8*x+i, 8*y+i);
        DrawPixel(8*x+i, 8*y+7-i);
    }
}

void Graphics::DrawPixel(int x, int y) {
    if(x<0 || x>=SCREEN_WIDTH || y<0 || y>=SCREEN_HEIGHT) return;
    Uint32 color = SDL_MapRGB(screen->format, 0xE0, 0xB0, 0xD0);

    Uint32 *pixel;
    pixel = (Uint32*) screen->pixels + y*screen->pitch/4 + x;
    *pixel = color;
}

/* map coords */
void Graphics::DrawRect(int x, int y) {
    PosTileToScreen(x, y);
    for(int i=0; i<8; i++) {
        DrawPixel(x+i, y);
        DrawPixel(x+i, y+7);
        DrawPixel(x, y+i);
        DrawPixel(x+7, y+i);
    }
}

/* map coords */
void Graphics::DrawFreeRect(int x, int y, int xSize, int ySize) {
    PosTileToScreen(x, y);
    for(int i=0; i<8*ySize; i++) {
        DrawPixel(x, y+i);
        DrawPixel(x + 8*xSize - 1, y+i);
    }
    for(int i=0; i<8*xSize; i++) {
        DrawPixel(x+i, y);
        DrawPixel(x+i, y + 8*ySize - 1);
    }
}

void Graphics::PosScreenToTile(int& x, int& y) {
    x /= 8;
    y /= 8;
    y += screenTileYOffset;
    x += screenTileXOffset;
}

void Graphics::PosScreenToTileRound(int& x, int& y) {
    x = (x+4)/8;
    y = (y+4)/8;
    y += screenTileYOffset;
    x += screenTileXOffset;
}

void Graphics::PosTileToScreen(int& x, int& y) {
    y -= screenTileYOffset;
    x -= screenTileXOffset;
    x *= 8;
    y *= 8;
}

#endif
<commit_msg>Renaming program to 'Captain PlaneEd'<commit_after>#ifndef GRAPHICS_HPP
#define GRAPHICS_HPP

#include "Graphics.h"
#include <algorithm>

#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480   //minimum size to allow for 64x64 maps

Graphics::Graphics(Uint16 xSize, Uint16 tileOffset, Uint16 tileAmount) {
    this->selXMin = std::min(8*64, 8*xSize) + 1;
    this->xDisplaySize = std::min(64, 0+xSize);
    this->tileOffset = tileOffset;
    this->tileAmount = tileAmount;
    this->currentPal = 0;
    this->highPriorityDisplay = true;
    this->lowPriorityDisplay = true;
    this->screenTileYOffset = 0;
    this->screenTileXOffset = 0;
    this->selTileYOffset = 0;

    /* calculate selector width */
    this->selectorWidth = 8;
    while(8*tileAmount / selectorWidth > SCREEN_HEIGHT) {
        if(8 * (xSize+selectorWidth) < SCREEN_WIDTH) selectorWidth += 8;
        else break;
    }

    if(SDL_Init(SDL_INIT_VIDEO)<0) {
        fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
        exit(1);
    }
    atexit(SDL_Quit);

    window = SDL_CreateWindow( "Captain PlaneEd", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE );
    if ( window == NULL )
    {
        fprintf( stderr, "Error - %s\n", SDL_GetError() );
        exit(1);
    }

    render = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED );
    if ( render == NULL )
    {
        fprintf( stderr, "Error - %s\n", SDL_GetError() );
        exit(1);
    }

    SDL_RenderSetLogicalSize(render, SCREEN_WIDTH, SCREEN_HEIGHT);

    screen = SDL_CreateRGBSurface(0, SCREEN_WIDTH, SCREEN_HEIGHT, 32, 0, 0, 0, 0);
    if(screen==NULL) {
        fprintf(stderr, "Unable to set 640x480 video: %s\n", SDL_GetError());
        exit(1);
    }
    texture = SDL_CreateTextureFromSurface(render, screen);
    if(texture==NULL) {
        fprintf( stderr, "Error - %s\n", SDL_GetError() );
        exit(1);
    }
}

void Graphics::ReadPalette(char* filename) {
    FILE* palfile = fopen(filename,"rb");
    if(palfile==NULL) {
        fprintf(stderr, "Cannot open palette file.\n");
        exit(1);
    }
    fseek(palfile, 0, SEEK_END);
    paletteLines = ftell(palfile)/0x20;
    if(paletteLines > 4) paletteLines = 4;
    rewind(palfile);
    if(paletteLines == 0) {
        fprintf(stderr, "Palette file too small.\n");
        exit(1);
    }
    palette = new Uint16[paletteLines][16];
    for(int i=0; i<paletteLines; i++)
        fread(palette[i], sizeof(unsigned char), 32, palfile);
    fclose(palfile);
    remove(filename);
}
#define getrgb(v) ((v&0xF000)>>8)|(v&0x0F0F|0xF000)	// Corrects G value, and sets alpha to max, so we can see
void Graphics::ReadTiles(char* filename) {
    FILE* tilefile = fopen(filename,"rb");
    if(tilefile==NULL) {
        fprintf(stderr, "Cannot open tile graphics file.\n");
        exit(1);
    }
    unsigned char tilebuffer[32]; //space for one tile
    tileData = new Uint16***[tileAmount];
    for(int t=0; t<tileAmount; t++) {
        fread(tilebuffer, sizeof(unsigned char), 32, tilefile);
        tileData[t] = new Uint16**[paletteLines];
        for(int p=0; p<paletteLines; p++) {
            tileData[t][p] = new Uint16*[4];
            for(int f=0; f<4; f++) tileData[t][p][f] = new Uint16[64];
            for(int i=0; i<32; i++) {
                tileData[t][p][0][2*i]   = getrgb(palette[p][(tilebuffer[i] & 0xF0)>>4]);
                tileData[t][p][0][2*i+1] = getrgb(palette[p][(tilebuffer[i] & 0x0F)]);
                tileData[t][p][1][8*(i/4)+7-2*(i%4)]   = getrgb(palette[p][(tilebuffer[i] & 0xF0)>>4]); //X-flip
                tileData[t][p][1][8*(i/4)+7-2*(i%4)-1] = getrgb(palette[p][(tilebuffer[i] & 0x0F)]);
                tileData[t][p][2][56-8*(i/4)+2*(i%4)]   = getrgb(palette[p][(tilebuffer[i] & 0xF0)>>4]); //Y-flip
                tileData[t][p][2][56-8*(i/4)+2*(i%4)+1] = getrgb(palette[p][(tilebuffer[i] & 0x0F)]);
                tileData[t][p][3][63-2*i]   = getrgb(palette[p][(tilebuffer[i] & 0xF0)>>4]); //XY-flip
                tileData[t][p][3][63-2*i-1] = getrgb(palette[p][(tilebuffer[i] & 0x0F)]);
            }
        }
    }
    fclose(tilefile);
    remove(filename);
}

void Graphics::CreateTiles(){
    tiles = new SDL_Surface***[tileAmount];
    for(int t=0; t<tileAmount; t++)
    {
        tiles[t] = new SDL_Surface**[paletteLines];
        for(int p=0; p<paletteLines; p++)
        {
            tiles[t][p] = new SDL_Surface*[4];
            for(int f=0; f<4; f++)
                tiles[t][p][f] = InitSurface(tileData[t][p][f], 8, 8, 16);
        }
    }
}

SDL_Surface* Graphics::InitSurface(Uint16 *pixelsT, int width, int height, int bbp) {
    void* pixels = pixelsT;
    SDL_Surface *surface = SDL_CreateRGBSurfaceFrom (pixels, width,
                         height, bbp, width*((bbp+7)/8), 0x0F00, 0x00F0, 0x000F, 0xF000);

    if (surface == NULL)
        fprintf(stderr, "Error - %s\n", SDL_GetError());

    return(surface);
}

void Graphics::DrawSurface(SDL_Surface *img, SDL_Surface *screen, int x, int y) {
    SDL_Rect RectTemp;
    RectTemp.x = x;
    RectTemp.y = y;
    SDL_BlitSurface(img, NULL, screen, &RectTemp);
}

void Graphics::ClearMap() {
    Uint32 color = SDL_MapRGB(screen->format, 0, 0, 0);
    SDL_Rect RectTemp;
    RectTemp.x = 0;
    RectTemp.y = 0;
    RectTemp.w = selXMin-1;
    RectTemp.h = SCREEN_HEIGHT;
    SDL_FillRect(this->screen, &RectTemp, color);
}

void Graphics::ClearSelector() {
    Uint32 color = SDL_MapRGB(screen->format, 0, 0, 0);
    SDL_Rect RectTemp;
    RectTemp.x = selXMin;
    RectTemp.y = 0;
    RectTemp.w = 8*selectorWidth;
    RectTemp.h = SCREEN_HEIGHT;
    SDL_FillRect(this->screen, &RectTemp, color);
}

void Graphics::DrawSelector() {
    ClearSelector();
    for(int i=0; i<tileAmount; i++)
        DrawSurface(tiles[i][currentPal][0], this->screen, selXMin + 8*(i%selectorWidth), 8*(i/selectorWidth - selTileYOffset));
    //SDL_Flip(screen);
    ProcessDisplay();
}

void Graphics::ProcessDisplay()
{
	SDL_UpdateTexture(texture, NULL, screen->pixels, screen->pitch);
	SDL_RenderClear(render);
	SDL_RenderCopy(render, texture, NULL, NULL);
	SDL_RenderPresent(render);
}

/* map coords */
void Graphics::DrawTileSingle(int x, int y, Tile tile) {
    y -= screenTileYOffset;
    x -= screenTileXOffset;
    if (x >= xDisplaySize) return;
    if((tile.priority && highPriorityDisplay) || (!tile.priority && lowPriorityDisplay)) {
        if((tile.tileID) - tileOffset >= this->tileAmount) {
            DrawTileNone(x, y);
            DrawTileInvalid(x, y);
        } else if((tile.tileID || !this->tileOffset) && tile.paletteLine < paletteLines)
            DrawSurface(tiles[(tile.tileID) - tileOffset][tile.paletteLine][(tile.xFlip | tile.yFlip)>>3], screen, 8*x, 8*y);
        else DrawTileBlank(x, y, tile);
    } else DrawTileNone(x, y);
}

bool Graphics::CheckSelValidPos(int x, int y) {
    if(x>=selXMin && x<selXMin+8*selectorWidth && y>=0 && (x-selXMin)/8+selectorWidth*(y/8 + selTileYOffset)<GetTileAmount()) return true;
    else return false;
}

void Graphics::DrawTileNone(int x, int y) {
    Uint32 color = SDL_MapRGB(screen->format, 0, 0, 0);
    DrawTileFullColor(x, y, color);
}

void Graphics::DrawTileBlank(int x, int y, Tile tile) {
    Uint32 color = SDL_MapRGB(
        screen->format,
        (palette[tile.paletteLine][0] & 0x0F00)>>4,
        (palette[tile.paletteLine][0] & 0x00F0),
        (palette[tile.paletteLine][0] & 0x000F)<<4
    );
    DrawTileFullColor(x, y, color);
}

void Graphics::DrawTileFullColor(int x, int y, Uint32 color) {
    SDL_Rect RectTemp;
    RectTemp.x = 8*x;
    RectTemp.y = 8*y;
    RectTemp.w = 8;
    RectTemp.h = 8;
    SDL_FillRect(this->screen, &RectTemp, color);
}

void Graphics::DrawTileInvalid(int x, int y) {
    //PosTileToScreen(x, y);
    for(int i=0; i<8; i++) {
        DrawPixel(8*x+i, 8*y+i);
        DrawPixel(8*x+i, 8*y+7-i);
    }
}

void Graphics::DrawPixel(int x, int y) {
    if(x<0 || x>=SCREEN_WIDTH || y<0 || y>=SCREEN_HEIGHT) return;
    Uint32 color = SDL_MapRGB(screen->format, 0xE0, 0xB0, 0xD0);

    Uint32 *pixel;
    pixel = (Uint32*) screen->pixels + y*screen->pitch/4 + x;
    *pixel = color;
}

/* map coords */
void Graphics::DrawRect(int x, int y) {
    PosTileToScreen(x, y);
    for(int i=0; i<8; i++) {
        DrawPixel(x+i, y);
        DrawPixel(x+i, y+7);
        DrawPixel(x, y+i);
        DrawPixel(x+7, y+i);
    }
}

/* map coords */
void Graphics::DrawFreeRect(int x, int y, int xSize, int ySize) {
    PosTileToScreen(x, y);
    for(int i=0; i<8*ySize; i++) {
        DrawPixel(x, y+i);
        DrawPixel(x + 8*xSize - 1, y+i);
    }
    for(int i=0; i<8*xSize; i++) {
        DrawPixel(x+i, y);
        DrawPixel(x+i, y + 8*ySize - 1);
    }
}

void Graphics::PosScreenToTile(int& x, int& y) {
    x /= 8;
    y /= 8;
    y += screenTileYOffset;
    x += screenTileXOffset;
}

void Graphics::PosScreenToTileRound(int& x, int& y) {
    x = (x+4)/8;
    y = (y+4)/8;
    y += screenTileYOffset;
    x += screenTileXOffset;
}

void Graphics::PosTileToScreen(int& x, int& y) {
    y -= screenTileYOffset;
    x -= screenTileXOffset;
    x *= 8;
    y *= 8;
}

#endif
<|endoftext|>