<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <algorithm>
#include <memory>

#include <boost/variant/variant.hpp>

#include "VariablesAnnotator.hpp"

#include "IsConstantVisitor.hpp"
#include "GetTypeVisitor.hpp"
#include "SemanticalException.hpp"
#include "Context.hpp"
#include "GlobalContext.hpp"
#include "FunctionContext.hpp"
#include "Types.hpp"
#include "Variable.hpp"

#include "Compiler.hpp"
#include "Options.hpp"
#include "TypeTransformer.hpp"
#include "Utils.hpp"

#include "VisitorUtils.hpp"
#include "ASTVisitor.hpp"

#include "ast/SourceFile.hpp"

using namespace eddic;

struct VariablesVisitor : public boost::static_visitor<> {
    AUTO_RECURSE_PROGRAM()
    AUTO_RECURSE_FUNCTION_CALLS()
    AUTO_RECURSE_SIMPLE_LOOPS()
    AUTO_RECURSE_BRANCHES()
    AUTO_RECURSE_BINARY_CONDITION()

    void operator()(ast::FunctionDeclaration& declaration){
        //Add all the parameters to the function context
        for(auto& parameter : declaration.Content->parameters){
            Type type = visit(TypeTransformer(), parameter.parameterType);

            declaration.Content->context->addParameter(parameter.parameterName, type);
        }

        visit_each(*this, declaration.Content->instructions);
    }

    void operator()(ast::GlobalVariableDeclaration& declaration){
        if (declaration.Content->context->exists(declaration.Content->variableName)) {
            throw SemanticalException("The global Variable " + declaration.Content->variableName + " has already been declared");
        }

        if(!visit(IsConstantVisitor(), *declaration.Content->value)){
            throw SemanticalException("The value must be constant");
        }

        BaseType baseType = stringToBaseType(declaration.Content->variableType);
        Type type(baseType, declaration.Content->constant);
        declaration.Content->context->addVariable(declaration.Content->variableName, type, *declaration.Content->value);
    }

    void operator()(ast::GlobalArrayDeclaration& declaration){
        if (declaration.Content->context->exists(declaration.Content->arrayName)) {
            throw SemanticalException("The global Variable " + declaration.Content->arrayName + " has already been declared");
        }

        BaseType baseType = stringToBaseType(declaration.Content->arrayType);
        Type type(baseType, declaration.Content->arraySize, false);

        declaration.Content->context->addVariable(declaration.Content->arrayName, type);
    }

    void operator()(ast::Foreach& foreach){
        if(foreach.Content->context->exists(foreach.Content->variableName)){
            throw SemanticalException("The foreach variable " + foreach.Content->variableName  + " has already been declared");
        }

        foreach.Content->context->addVariable(foreach.Content->variableName, stringToType(foreach.Content->variableType));

        visit_each(*this, foreach.Content->instructions);
    }

    void operator()(ast::ForeachIn& foreach){
        if(foreach.Content->context->exists(foreach.Content->variableName)){
            throw SemanticalException("The foreach variable " + foreach.Content->variableName  + " has already been declared");
        }

        if(!foreach.Content->context->exists(foreach.Content->arrayName)){
            throw SemanticalException("The foreach array " + foreach.Content->arrayName  + " has not been declared");
        }

        static int generated = 0;

        foreach.Content->var = foreach.Content->context->addVariable(foreach.Content->variableName, stringToType(foreach.Content->variableType));
        foreach.Content->arrayVar = foreach.Content->context->getVariable(foreach.Content->arrayName);
        foreach.Content->iterVar = foreach.Content->context->addVariable("foreach_iter_" + toString(++generated), stringToType("int"));

        visit_each(*this, foreach.Content->instructions);
    }

    void operator()(ast::Assignment& assignment){
        if (!assignment.Content->context->exists(assignment.Content->variableName)) {
            throw SemanticalException("Variable " + assignment.Content->variableName + " has not  been declared");
        }

        visit(*this, assignment.Content->value);

        assignment.Content->context->getVariable(assignment.Content->variableName)->addReference();
    }

    void operator()(ast::SuffixOperation& operation){
        if (!operation.Content->context->exists(operation.Content->variableName)) {
            throw SemanticalException("Variable " + operation.Content->variableName + " has not  been declared");
        }

        operation.Content->variable = operation.Content->context->getVariable(operation.Content->variableName);
        operation.Content->variable->addReference();
    }

    void operator()(ast::PrefixOperation& operation){
        if (!operation.Content->context->exists(operation.Content->variableName)) {
            throw SemanticalException("Variable " + operation.Content->variableName + " has not  been declared");
        }

        operation.Content->variable = operation.Content->context->getVariable(operation.Content->variableName);
        operation.Content->variable->addReference();
    }

    void operator()(ast::Return& return_){
        visit(*this, return_.Content->value);
    }

    void operator()(ast::ArrayAssignment& assignment){
        if (!assignment.Content->context->exists(assignment.Content->variableName)) {
            throw SemanticalException("Array " + assignment.Content->variableName + " has not  been declared");
        }

        visit(*this, assignment.Content->indexValue);
        visit(*this, assignment.Content->value);

        assignment.Content->context->getVariable(assignment.Content->variableName)->addReference();
    }

    void operator()(ast::VariableDeclaration& declaration){
        if (declaration.Content->context->exists(declaration.Content->variableName)) {
            throw SemanticalException("Variable " + declaration.Content->variableName + " has already been declared");
        }

        visit(*this, *declaration.Content->value);

        BaseType baseType = stringToBaseType(declaration.Content->variableType);
        Type type(baseType, declaration.Content->const_);

        if(type.isConst()){
            if(!visit(IsConstantVisitor(), *declaration.Content->value)){
                throw SemanticalException("The value must be constant");
            }

            declaration.Content->context->addVariable(declaration.Content->variableName, type, *declaration.Content->value);
        } else {
            declaration.Content->context->addVariable(declaration.Content->variableName, type);
        }
    }

    void operator()(ast::ArrayDeclaration& declaration){
        if (declaration.Content->context->exists(declaration.Content->arrayName)) {
            throw SemanticalException("The variable " + declaration.Content->arrayName + " has already been declared");
        }

        BaseType baseType = stringToBaseType(declaration.Content->arrayType);
        Type type(baseType, declaration.Content->arraySize, false);

        declaration.Content->context->addVariable(declaration.Content->arrayName, type);
    }

    void operator()(ast::Swap& swap){
        if (swap.Content->lhs == swap.Content->rhs) {
            throw SemanticalException("Cannot swap a variable with itself");
        }

        if (!swap.Content->context->exists(swap.Content->lhs) || !swap.Content->context->exists(swap.Content->rhs)) {
            throw SemanticalException("Variable has not been declared in the swap");
        }

        swap.Content->lhs_var = swap.Content->context->getVariable(swap.Content->lhs);
        swap.Content->rhs_var = swap.Content->context->getVariable(swap.Content->rhs);

        //Reference both variables
        swap.Content->lhs_var->addReference();
        swap.Content->rhs_var->addReference();
    }

    void operator()(ast::VariableValue& variable){
        if (!variable.Content->context->exists(variable.Content->variableName)) {
            throw SemanticalException("Variable " + variable.Content->variableName + " has not been declared");
        }

        //Reference the variable
        variable.Content->var = variable.Content->context->getVariable(variable.Content->variableName);
        variable.Content->var->addReference();
    }

    void operator()(ast::ArrayValue& array){
        if (!array.Content->context->exists(array.Content->arrayName)) {
            throw SemanticalException("Array " + array.Content->arrayName + " has not been declared");
        }

        //Reference the variable
        array.Content->var = array.Content->context->getVariable(array.Content->arrayName);
        array.Content->var->addReference();

        visit(*this, array.Content->indexValue);
    }

    void operator()(ast::ComposedValue& value){
        visit(*this, value.Content->first);

        for_each(value.Content->operations.begin(), value.Content->operations.end(),
            [&](ast::Operation& operation){ visit(*this, operation.get<1>()); });
    }

    void operator()(ast::Plus& value){
        visit(*this, value.Content->value);
    }

    void operator()(ast::Minus& value){
        visit(*this, value.Content->value);
    }

    void operator()(ast::Import&){
        //Nothing to check here
    }

    void operator()(ast::StandardImport&){
        //Nothing to check here
    }

    void operator()(ast::TerminalNode&){
        //Terminal nodes have no need for variable checking
    }
};

void VariablesAnnotator::annotate(ast::SourceFile& program) const {
    VariablesVisitor visitor;
    visit_non_variant(visitor, program);
}
<commit_msg>Implement variables annotation for compound assignment<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <algorithm>
#include <memory>

#include <boost/variant/variant.hpp>

#include "VariablesAnnotator.hpp"

#include "IsConstantVisitor.hpp"
#include "GetTypeVisitor.hpp"
#include "SemanticalException.hpp"
#include "Context.hpp"
#include "GlobalContext.hpp"
#include "FunctionContext.hpp"
#include "Types.hpp"
#include "Variable.hpp"

#include "Compiler.hpp"
#include "Options.hpp"
#include "TypeTransformer.hpp"
#include "Utils.hpp"

#include "VisitorUtils.hpp"
#include "ASTVisitor.hpp"

#include "ast/SourceFile.hpp"

using namespace eddic;

struct VariablesVisitor : public boost::static_visitor<> {
    AUTO_RECURSE_PROGRAM()
    AUTO_RECURSE_FUNCTION_CALLS()
    AUTO_RECURSE_SIMPLE_LOOPS()
    AUTO_RECURSE_BRANCHES()
    AUTO_RECURSE_BINARY_CONDITION()

    void operator()(ast::FunctionDeclaration& declaration){
        //Add all the parameters to the function context
        for(auto& parameter : declaration.Content->parameters){
            Type type = visit(TypeTransformer(), parameter.parameterType);

            declaration.Content->context->addParameter(parameter.parameterName, type);
        }

        visit_each(*this, declaration.Content->instructions);
    }

    void operator()(ast::GlobalVariableDeclaration& declaration){
        if (declaration.Content->context->exists(declaration.Content->variableName)) {
            throw SemanticalException("The global Variable " + declaration.Content->variableName + " has already been declared");
        }

        if(!visit(IsConstantVisitor(), *declaration.Content->value)){
            throw SemanticalException("The value must be constant");
        }

        BaseType baseType = stringToBaseType(declaration.Content->variableType);
        Type type(baseType, declaration.Content->constant);
        declaration.Content->context->addVariable(declaration.Content->variableName, type, *declaration.Content->value);
    }

    void operator()(ast::GlobalArrayDeclaration& declaration){
        if (declaration.Content->context->exists(declaration.Content->arrayName)) {
            throw SemanticalException("The global Variable " + declaration.Content->arrayName + " has already been declared");
        }

        BaseType baseType = stringToBaseType(declaration.Content->arrayType);
        Type type(baseType, declaration.Content->arraySize, false);

        declaration.Content->context->addVariable(declaration.Content->arrayName, type);
    }

    void operator()(ast::Foreach& foreach){
        if(foreach.Content->context->exists(foreach.Content->variableName)){
            throw SemanticalException("The foreach variable " + foreach.Content->variableName  + " has already been declared");
        }

        foreach.Content->context->addVariable(foreach.Content->variableName, stringToType(foreach.Content->variableType));

        visit_each(*this, foreach.Content->instructions);
    }

    void operator()(ast::ForeachIn& foreach){
        if(foreach.Content->context->exists(foreach.Content->variableName)){
            throw SemanticalException("The foreach variable " + foreach.Content->variableName  + " has already been declared");
        }

        if(!foreach.Content->context->exists(foreach.Content->arrayName)){
            throw SemanticalException("The foreach array " + foreach.Content->arrayName  + " has not been declared");
        }

        static int generated = 0;

        foreach.Content->var = foreach.Content->context->addVariable(foreach.Content->variableName, stringToType(foreach.Content->variableType));
        foreach.Content->arrayVar = foreach.Content->context->getVariable(foreach.Content->arrayName);
        foreach.Content->iterVar = foreach.Content->context->addVariable("foreach_iter_" + toString(++generated), stringToType("int"));

        visit_each(*this, foreach.Content->instructions);
    }

    void operator()(ast::Assignment& assignment){
        if (!assignment.Content->context->exists(assignment.Content->variableName)) {
            throw SemanticalException("Variable " + assignment.Content->variableName + " has not  been declared");
        }

        visit(*this, assignment.Content->value);

        assignment.Content->context->getVariable(assignment.Content->variableName)->addReference();
    }

    void operator()(ast::CompoundAssignment& assignment){
        if (!assignment.Content->context->exists(assignment.Content->variableName)) {
            throw SemanticalException("Variable " + assignment.Content->variableName + " has not  been declared");
        }

        visit(*this, assignment.Content->value);

        assignment.Content->context->getVariable(assignment.Content->variableName)->addReference();
    }

    void operator()(ast::SuffixOperation& operation){
        if (!operation.Content->context->exists(operation.Content->variableName)) {
            throw SemanticalException("Variable " + operation.Content->variableName + " has not  been declared");
        }

        operation.Content->variable = operation.Content->context->getVariable(operation.Content->variableName);
        operation.Content->variable->addReference();
    }

    void operator()(ast::PrefixOperation& operation){
        if (!operation.Content->context->exists(operation.Content->variableName)) {
            throw SemanticalException("Variable " + operation.Content->variableName + " has not  been declared");
        }

        operation.Content->variable = operation.Content->context->getVariable(operation.Content->variableName);
        operation.Content->variable->addReference();
    }

    void operator()(ast::Return& return_){
        visit(*this, return_.Content->value);
    }

    void operator()(ast::ArrayAssignment& assignment){
        if (!assignment.Content->context->exists(assignment.Content->variableName)) {
            throw SemanticalException("Array " + assignment.Content->variableName + " has not  been declared");
        }

        visit(*this, assignment.Content->indexValue);
        visit(*this, assignment.Content->value);

        assignment.Content->context->getVariable(assignment.Content->variableName)->addReference();
    }

    void operator()(ast::VariableDeclaration& declaration){
        if (declaration.Content->context->exists(declaration.Content->variableName)) {
            throw SemanticalException("Variable " + declaration.Content->variableName + " has already been declared");
        }

        visit(*this, *declaration.Content->value);

        BaseType baseType = stringToBaseType(declaration.Content->variableType);
        Type type(baseType, declaration.Content->const_);

        if(type.isConst()){
            if(!visit(IsConstantVisitor(), *declaration.Content->value)){
                throw SemanticalException("The value must be constant");
            }

            declaration.Content->context->addVariable(declaration.Content->variableName, type, *declaration.Content->value);
        } else {
            declaration.Content->context->addVariable(declaration.Content->variableName, type);
        }
    }

    void operator()(ast::ArrayDeclaration& declaration){
        if (declaration.Content->context->exists(declaration.Content->arrayName)) {
            throw SemanticalException("The variable " + declaration.Content->arrayName + " has already been declared");
        }

        BaseType baseType = stringToBaseType(declaration.Content->arrayType);
        Type type(baseType, declaration.Content->arraySize, false);

        declaration.Content->context->addVariable(declaration.Content->arrayName, type);
    }

    void operator()(ast::Swap& swap){
        if (swap.Content->lhs == swap.Content->rhs) {
            throw SemanticalException("Cannot swap a variable with itself");
        }

        if (!swap.Content->context->exists(swap.Content->lhs) || !swap.Content->context->exists(swap.Content->rhs)) {
            throw SemanticalException("Variable has not been declared in the swap");
        }

        swap.Content->lhs_var = swap.Content->context->getVariable(swap.Content->lhs);
        swap.Content->rhs_var = swap.Content->context->getVariable(swap.Content->rhs);

        //Reference both variables
        swap.Content->lhs_var->addReference();
        swap.Content->rhs_var->addReference();
    }

    void operator()(ast::VariableValue& variable){
        if (!variable.Content->context->exists(variable.Content->variableName)) {
            throw SemanticalException("Variable " + variable.Content->variableName + " has not been declared");
        }

        //Reference the variable
        variable.Content->var = variable.Content->context->getVariable(variable.Content->variableName);
        variable.Content->var->addReference();
    }

    void operator()(ast::ArrayValue& array){
        if (!array.Content->context->exists(array.Content->arrayName)) {
            throw SemanticalException("Array " + array.Content->arrayName + " has not been declared");
        }

        //Reference the variable
        array.Content->var = array.Content->context->getVariable(array.Content->arrayName);
        array.Content->var->addReference();

        visit(*this, array.Content->indexValue);
    }

    void operator()(ast::ComposedValue& value){
        visit(*this, value.Content->first);

        for_each(value.Content->operations.begin(), value.Content->operations.end(),
            [&](ast::Operation& operation){ visit(*this, operation.get<1>()); });
    }

    void operator()(ast::Plus& value){
        visit(*this, value.Content->value);
    }

    void operator()(ast::Minus& value){
        visit(*this, value.Content->value);
    }

    void operator()(ast::Import&){
        //Nothing to check here
    }

    void operator()(ast::StandardImport&){
        //Nothing to check here
    }

    void operator()(ast::TerminalNode&){
        //Terminal nodes have no need for variable checking
    }
};

void VariablesAnnotator::annotate(ast::SourceFile& program) const {
    VariablesVisitor visitor;
    visit_non_variant(visitor, program);
}
<|endoftext|>


<commit_before>#ifndef BOP_MATRIX_HPP
#define BOP_MATRIX_HPP

#include <memory>
#include <initializer_list>
#include <string>
#include <sstream>
#include <new>
#include "Vector.hpp"

/*
	bop::maths::Matrix class file
*/

namespace bop {
	namespace maths{
		template<class T>
		class Matrix {
			protected:
				unsigned int width;
				unsigned int height;
			public:
				Vector<T>* data;

				//Constructors
				Matrix(unsigned int size, T fill = 0) {
					/*
						Square matrix constructor, sets all values as
						the given fill value.
					*/
					this->data = new Vector<T>[size];
					for (unsigned int i = 0; i < size; i++) {
						this->data[i] = Vector<T>(size, fill);
					}
					this->width = size;
					this->height = size;
				}

				Matrix(unsigned int width, unsigned int height, T fill = 0) {
					/*
						Non-square matrix constructor, sets all values as
						the given fill value.
					*/
					this->data = new Vector<T>[height];
					for (int i = 0; i < height; i++) {
						this->data[i] = Vector<T>(width, fill);
					}
					this->height = height;
					this->width = width;
				}

				Matrix(std::initializer_list< std::initializer_list<T> > list) {
					/*
						Creates a matrix from a 2-dimensional initializer_list.
					*/
					this->height = list.size();
					this->data = new Vector<T>[this->height];
					unsigned int min_w = list.begin()->size();
					int i = 0;
					for (auto elem : list) {
						if (elem.size() < min_w) min_w = elem.size();
						this->data[i] = elem;
						i++;
					}
					this->width = min_w;
				}

				Matrix(Matrix<T>& mat) {
					/*
						Copy constructor.
					*/
					this->width = mat.width;
					this->height = mat.height;
					this->data = new Vector<T>[this->height];
					for (unsigned int i = 0; i < this->width; i++) {
						this->data[i] = mat.data[i];
					}
				}

				Matrix(Matrix<T>&& mat) {
					/*
						Move constructor.
					*/
					this->width = mat.width;
					this->height = mat.height;
					this->data = mat.data;
				}

				Matrix() {
					/*
						Empty constructor.
					*/
				}

				//Destructor
				~Matrix() {
					delete[] this->data;
				}

				//Operator overloads
				inline Vector<T>& operator[] (const unsigned int index) {
					return this->data[index];
				}

				Matrix<T>& operator= (const Matrix<T> &mat) {
					this->width = mat.width;
					this->height = mat.height;
					delete[] this->data;
					this->data = new Vector<T>[this->height];
					for (unsigned int i = 0; i < this->height; i++) {
						this->data[i] = mat.data[i];
					}
				}

				//Boolean logic overloads
				bool operator== (const Matrix<T>& mat) {
					if (this->width == mat.width && this->height == mat.height) {
						bool same = true;
						for (unsigned int i = 0; i < this->height && same; i++) {
							same = (this->data[i] == mat.data[i]);
						}
						return same;
					}
					else return false;
				}

				bool operator!= (const Matrix<T>& mat) {
					return !(this->operator==(mat));
				}

				//Arithmetic overloads
				Matrix<T>& operator*= (const T scalar) {
					/*
						Scalar multiplication member operator, multiplies all
						elements by the given scalar.
					*/
					for (int i = 0; i < this->height; i++) {
						this->data[i] *= scalar;
					}
					return *this;
				}

				Matrix<T>& operator*= (Matrix<T> &mat) {
					/*
						Matrix multiplication member operator.
					*/
					Vector<T>* temp = new Vector<T>[this->height];
					for (int i = 0; i < this->height; i++) {
						temp[i] = Vector<T>(mat.width);
					}
					for (int r = 0; r < this->height; r++) {
						for (int c = 0; c < mat.width; c++) {
							T product = 0;
							for (int i = 0; i < mat.width; i++) {
								product += (this->data[r][i] * mat.data[i][c]);
							}
							temp[r][c] = product;
						}
					}
					delete[] this->data;
					this->data = temp;
					this->width = mat.width;
					return *this;
				}

				Matrix<T>& operator/= (const T scalar) {
					/*
						Scalar division member operator, divides all elements
						by the given scalar.
					*/
					for (int i = 0; i < this->height; i++) {
						this->data[i] /= scalar;
					}
					return *this;
				}

				Matrix<T>& operator+= (Matrix<T> &mat) {
					/*
						Addition member operator, adds all the elements of a
						given matrix to the matrix.
					*/
					for (int i = 0; i < this->height; i++) {
						this->data[i] += mat[i];
					}
					return *this;
				}

				Matrix<T>& operator-= (Matrix<T> &mat) {
					/*
						Subtraction member operator, subtracts the value of
						each element in a given matrix from the matrix.
					*/
					for (int i = 0; i < this->height; i++) {
						this->data[i] -= mat[i];
					}
					return *this;
				}

				//Information functions
				inline unsigned int w() {
					/*
						Returns the width of the Matrix.
					*/
					return this->width;
				}

				inline unsigned int h() {
					/*
						Returns the height of the Matrix.
					*/
					return this->height;
				}

				inline bool square() {
					/*
						Tests if the Matrix is a square Matrix.
					*/
					return (this->width == this->height);
				}

				bool identity() {
					/*
						Tests if the matrix is an identity matrix.
					*/
					if (this->width == this->height) {
						bool identity = true;
						for (unsigned int y = 0; y < this->height && identity; y++) {
							for (unsigned int x = 0; x < this->width && identity; x++) {
								if (x == y) identity = (this->data[y][x] == 1);
								else identity = (this->data[y][x] == 0);
							}
						}
						return identity;
					}
					else return false;
				}

				std::string string(bool newlines = true) {
					/*
						Similar to the maths::Vector::string function, returns
						a human-readable representation of the Matrix.
					*/
					std::ostringstream mat_str;
					for (unsigned int i = 0; i < this->height; i++) {
						mat_str << '[' << this->data[i].string(false) << ']';
						if (newlines) mat_str << '\n';
					}
					return mat_str.str();
				}

				//Matrix manipulation functions.

				inline void swapRows(unsigned int index_a, unsigned int index_b) {
					/*
						Row swap function, for use in such algorithms as Gauss-Jordan
						elimination.
					*/
					this->data[index_a].swap(this->data[index_b]);
				}

				void swap(Matrix<T>& mat) {
					/*
						Matrix object swap function.
					*/
					Vector<T>* temp_arr = mat.data;
					unsigned int temp_w = mat.width;
					unsigned int temp_h = mat.height;
					mat.data = this->data;
					mat.width = this->width;
					mat.height = this->height;
					this->data = temp_arr;
					this->width = temp_w;
					this->height = temp_h;
				}
		};

		//External arithmetic overloads

		template<class T>
		Matrix<T> operator* (Matrix<T> &mat, const T scalar) {
			Matrix<T> mat_p(mat);
			mat_p *= scalar;
			return mat_p;
		}

		template<class T>
		Matrix<T> operator* (Matrix<T> &mat1, Matrix<T>& mat2) {
			Matrix<T> mat_p(mat1);
			mat_p *= mat2;
			return mat_p;
		}

		template<class T>
		Matrix<T> operator/ (Matrix<T> &mat, const T scalar) {
			Matrix<T> mat_p(mat)
			mat_p /= scalar;
			return mat_p;
		}

		template<class T>
		Matrix<T> operator+ (Matrix<T> &mat1, Matrix<T>& mat2) {
			Matrix<T> mat_sum(mat1);
			mat_sum += mat2;
			return mat_sum;
		}

		template<class T>
		Matrix<T> operator- (Matrix<T> &mat1, Matrix<T>& mat2) {
			Matrix<T> mat_sum(mat1);
			mat_sum -= mat2;
			return mat_sum;
		}

		//Matrix related functions
		template<class T>
		T determinant(Matrix<T>& mat, Vector<bool>& allowed_cols, unsigned int& size) {
			/*
				Recursive matrix determinant function.
			*/
			if (size == 2) {
				//the  base case, finding the 2 by 2 matrix determinant
				int c1 = -1, c2 = -1;
				for (unsigned int i = 0; i < mat.w(); i++) {
					if (allowed_cols[i]) {
						if (c1 < 0) {
							c1 = i;
						}
						else if (c2 < 0) {
							c2 = i;
						}
						else {
							break;
						}
					}
				}
				return (mat[mat.h() - 2][c1] * mat[mat.h() - 1][c2]) - (mat[mat.h() - 2][c2] * mat[mat.h() - 1][c1]);
			}
			else {
				size--;
				T product = 0;
				T multi = 1;
				for (int i = 0; i < mat.w(); i++) {
					if (!allowed_cols[i]) continue;
					else {
						allowed_cols[i] = false;
						product += (multi * (mat[mat.h() - size][i] * determinant(mat, allowed_cols, size)));
						multi *= -1;
						allowed_cols[i] = true;

					}
				}
				size++;
				return product;
			}
		}

		template<class T>
		T determinant(const Matrix<T>& mat) {
			/*
				Matrix determinant init function.
			*/
			if (!mat.square()) return static_cast<T>(0);
			else {
				if (mat.w() == 2) {
					//shortcut to determinant of a 2 by 2 matrix
					return (mat[0][0] * mat[1][1]) - (mat[0][1] * mat[1][0]);
				}
				else {
					Vector<bool> allowed_cols(mat.w(), true);
					T product = 0;
					T multi = 1;
					int size = mat.h() - 1;
					for (int i = 0; i < mat.w(); i++) {
						allowed_cols[i] = false;
						product += (multi * (mat[0][i] * determinant(mat, allowed_cols, size)));
						multi *= -1;
						allowed_cols[i] = true;
					}
					return product;
				}
			}
		}

		template<class T>
		Matrix<T> identityMatrix(unsigned int size) {
			/*
				Returns an Identity Matrix.
			*/
			Matrix<T> unit_m(size);
			for (int i = 0; i < size; i++) {
				unit_m[i] = 1;
			}
			return unit_m;
		}

		template<class T>
		bool invertable(Matrix<T> &mat) {
			return (mat.square() && determinant(mat) != 0);
		}

		template<class T>
		Matrix<T> inverseMatrix(Matrix<T> mat, bool tested = true) {
			/*
				Matrix inverse by Gauss-Jordan method ([A|I] -> [I|A']).
				Assumes that the matrix has already been tested as invertible.
				takes a COPY of a matrix, as this method requires the
				manipulation of the rows of the matrix.
			*/
			if (!tested && invertable(mat) == 0) {
				/*
					In the case that the matrix is not invertible, the function will
					return an identity matrix with the height of the given matrix.
				*/
				return identityMatrix(mat.h());
			}
			else {
				if (mat.h() == 2) {
					/*
						2 by 2 matrix shortcut.
					*/
					T temp = mat[0][0];
					mat[0][0] = mat[1][1];
					mat[1][1] = temp;
					temp = mat[1][0];
					mat[1][0] = -mat[0][1];
					mat[0][1] = -temp;
					return mat;

				}
				else {
					Matrix<T> inverse = identityMatrix(mat.h());
					/*
						Sort the matrix rows by pivot index and
					*/

				}
			}
		}

		template<class T>
		Matrix<T> transposeMatrix(Matrix<T> &mat) {
			/*
				Creates & returns a transposed version of the given matrix.
			*/
			Matrix<T> trans(mat.h(), mat.w(), 0);
			for (unsigned int y = 0; y < mat.h(); y++) {
				for (unsigned int x = 0; x < mat.w(); x++) {
					trans[x][y] = mat[y][x];
				}
			}
			return trans;
		}

	}
}

#endif<commit_msg>Missing semicolon<commit_after>#ifndef BOP_MATRIX_HPP
#define BOP_MATRIX_HPP

#include <memory>
#include <initializer_list>
#include <string>
#include <sstream>
#include <new>
#include "Vector.hpp"

/*
	bop::maths::Matrix class file
*/

namespace bop {
	namespace maths{
		template<class T>
		class Matrix {
			protected:
				unsigned int width;
				unsigned int height;
			public:
				Vector<T>* data;

				//Constructors
				Matrix(unsigned int size, T fill = 0) {
					/*
						Square matrix constructor, sets all values as
						the given fill value.
					*/
					this->data = new Vector<T>[size];
					for (unsigned int i = 0; i < size; i++) {
						this->data[i] = Vector<T>(size, fill);
					}
					this->width = size;
					this->height = size;
				}

				Matrix(unsigned int width, unsigned int height, T fill = 0) {
					/*
						Non-square matrix constructor, sets all values as
						the given fill value.
					*/
					this->data = new Vector<T>[height];
					for (int i = 0; i < height; i++) {
						this->data[i] = Vector<T>(width, fill);
					}
					this->height = height;
					this->width = width;
				}

				Matrix(std::initializer_list< std::initializer_list<T> > list) {
					/*
						Creates a matrix from a 2-dimensional initializer_list.
					*/
					this->height = list.size();
					this->data = new Vector<T>[this->height];
					unsigned int min_w = list.begin()->size();
					int i = 0;
					for (auto elem : list) {
						if (elem.size() < min_w) min_w = elem.size();
						this->data[i] = elem;
						i++;
					}
					this->width = min_w;
				}

				Matrix(Matrix<T>& mat) {
					/*
						Copy constructor.
					*/
					this->width = mat.width;
					this->height = mat.height;
					this->data = new Vector<T>[this->height];
					for (unsigned int i = 0; i < this->width; i++) {
						this->data[i] = mat.data[i];
					}
				}

				Matrix(Matrix<T>&& mat) {
					/*
						Move constructor.
					*/
					this->width = mat.width;
					this->height = mat.height;
					this->data = mat.data;
				}

				Matrix() {
					/*
						Empty constructor.
					*/
				}

				//Destructor
				~Matrix() {
					delete[] this->data;
				}

				//Operator overloads
				inline Vector<T>& operator[] (const unsigned int index) {
					return this->data[index];
				}

				Matrix<T>& operator= (const Matrix<T> &mat) {
					this->width = mat.width;
					this->height = mat.height;
					delete[] this->data;
					this->data = new Vector<T>[this->height];
					for (unsigned int i = 0; i < this->height; i++) {
						this->data[i] = mat.data[i];
					}
				}

				//Boolean logic overloads
				bool operator== (const Matrix<T>& mat) {
					if (this->width == mat.width && this->height == mat.height) {
						bool same = true;
						for (unsigned int i = 0; i < this->height && same; i++) {
							same = (this->data[i] == mat.data[i]);
						}
						return same;
					}
					else return false;
				}

				bool operator!= (const Matrix<T>& mat) {
					return !(this->operator==(mat));
				}

				//Arithmetic overloads
				Matrix<T>& operator*= (const T scalar) {
					/*
						Scalar multiplication member operator, multiplies all
						elements by the given scalar.
					*/
					for (int i = 0; i < this->height; i++) {
						this->data[i] *= scalar;
					}
					return *this;
				}

				Matrix<T>& operator*= (Matrix<T> &mat) {
					/*
						Matrix multiplication member operator.
					*/
					Vector<T>* temp = new Vector<T>[this->height];
					for (int i = 0; i < this->height; i++) {
						temp[i] = Vector<T>(mat.width);
					}
					for (int r = 0; r < this->height; r++) {
						for (int c = 0; c < mat.width; c++) {
							T product = 0;
							for (int i = 0; i < mat.width; i++) {
								product += (this->data[r][i] * mat.data[i][c]);
							}
							temp[r][c] = product;
						}
					}
					delete[] this->data;
					this->data = temp;
					this->width = mat.width;
					return *this;
				}

				Matrix<T>& operator/= (const T scalar) {
					/*
						Scalar division member operator, divides all elements
						by the given scalar.
					*/
					for (int i = 0; i < this->height; i++) {
						this->data[i] /= scalar;
					}
					return *this;
				}

				Matrix<T>& operator+= (Matrix<T> &mat) {
					/*
						Addition member operator, adds all the elements of a
						given matrix to the matrix.
					*/
					for (int i = 0; i < this->height; i++) {
						this->data[i] += mat[i];
					}
					return *this;
				}

				Matrix<T>& operator-= (Matrix<T> &mat) {
					/*
						Subtraction member operator, subtracts the value of
						each element in a given matrix from the matrix.
					*/
					for (int i = 0; i < this->height; i++) {
						this->data[i] -= mat[i];
					}
					return *this;
				}

				//Information functions
				inline unsigned int w() {
					/*
						Returns the width of the Matrix.
					*/
					return this->width;
				}

				inline unsigned int h() {
					/*
						Returns the height of the Matrix.
					*/
					return this->height;
				}

				inline bool square() {
					/*
						Tests if the Matrix is a square Matrix.
					*/
					return (this->width == this->height);
				}

				bool identity() {
					/*
						Tests if the matrix is an identity matrix.
					*/
					if (this->width == this->height) {
						bool identity = true;
						for (unsigned int y = 0; y < this->height && identity; y++) {
							for (unsigned int x = 0; x < this->width && identity; x++) {
								if (x == y) identity = (this->data[y][x] == 1);
								else identity = (this->data[y][x] == 0);
							}
						}
						return identity;
					}
					else return false;
				}

				std::string string(bool newlines = true) {
					/*
						Similar to the maths::Vector::string function, returns
						a human-readable representation of the Matrix.
					*/
					std::ostringstream mat_str;
					for (unsigned int i = 0; i < this->height; i++) {
						mat_str << '[' << this->data[i].string(false) << ']';
						if (newlines) mat_str << '\n';
					}
					return mat_str.str();
				}

				//Matrix manipulation functions.

				inline void swapRows(unsigned int index_a, unsigned int index_b) {
					/*
						Row swap function, for use in such algorithms as Gauss-Jordan
						elimination.
					*/
					this->data[index_a].swap(this->data[index_b]);
				}

				void swap(Matrix<T>& mat) {
					/*
						Matrix object swap function.
					*/
					Vector<T>* temp_arr = mat.data;
					unsigned int temp_w = mat.width;
					unsigned int temp_h = mat.height;
					mat.data = this->data;
					mat.width = this->width;
					mat.height = this->height;
					this->data = temp_arr;
					this->width = temp_w;
					this->height = temp_h;
				}
		};

		//External arithmetic overloads

		template<class T>
		Matrix<T> operator* (Matrix<T> &mat, const T scalar) {
			Matrix<T> mat_p(mat);
			mat_p *= scalar;
			return mat_p;
		}

		template<class T>
		Matrix<T> operator* (Matrix<T> &mat1, Matrix<T>& mat2) {
			Matrix<T> mat_p(mat1);
			mat_p *= mat2;
			return mat_p;
		}

		template<class T>
		Matrix<T> operator/ (Matrix<T> &mat, const T scalar) {
			Matrix<T> mat_p(mat);
			mat_p /= scalar;
			return mat_p;
		}

		template<class T>
		Matrix<T> operator+ (Matrix<T> &mat1, Matrix<T>& mat2) {
			Matrix<T> mat_sum(mat1);
			mat_sum += mat2;
			return mat_sum;
		}

		template<class T>
		Matrix<T> operator- (Matrix<T> &mat1, Matrix<T>& mat2) {
			Matrix<T> mat_sum(mat1);
			mat_sum -= mat2;
			return mat_sum;
		}

		//Matrix related functions
		template<class T>
		T determinant(Matrix<T>& mat, Vector<bool>& allowed_cols, unsigned int& size) {
			/*
				Recursive matrix determinant function.
			*/
			if (size == 2) {
				//the  base case, finding the 2 by 2 matrix determinant
				int c1 = -1, c2 = -1;
				for (unsigned int i = 0; i < mat.w(); i++) {
					if (allowed_cols[i]) {
						if (c1 < 0) {
							c1 = i;
						}
						else if (c2 < 0) {
							c2 = i;
						}
						else {
							break;
						}
					}
				}
				return (mat[mat.h() - 2][c1] * mat[mat.h() - 1][c2]) - (mat[mat.h() - 2][c2] * mat[mat.h() - 1][c1]);
			}
			else {
				size--;
				T product = 0;
				T multi = 1;
				for (int i = 0; i < mat.w(); i++) {
					if (!allowed_cols[i]) continue;
					else {
						allowed_cols[i] = false;
						product += (multi * (mat[mat.h() - size][i] * determinant(mat, allowed_cols, size)));
						multi *= -1;
						allowed_cols[i] = true;

					}
				}
				size++;
				return product;
			}
		}

		template<class T>
		T determinant(const Matrix<T>& mat) {
			/*
				Matrix determinant init function.
			*/
			if (!mat.square()) return static_cast<T>(0);
			else {
				if (mat.w() == 2) {
					//shortcut to determinant of a 2 by 2 matrix
					return (mat[0][0] * mat[1][1]) - (mat[0][1] * mat[1][0]);
				}
				else {
					Vector<bool> allowed_cols(mat.w(), true);
					T product = 0;
					T multi = 1;
					int size = mat.h() - 1;
					for (int i = 0; i < mat.w(); i++) {
						allowed_cols[i] = false;
						product += (multi * (mat[0][i] * determinant(mat, allowed_cols, size)));
						multi *= -1;
						allowed_cols[i] = true;
					}
					return product;
				}
			}
		}

		template<class T>
		Matrix<T> identityMatrix(unsigned int size) {
			/*
				Returns an Identity Matrix.
			*/
			Matrix<T> unit_m(size);
			for (int i = 0; i < size; i++) {
				unit_m[i] = 1;
			}
			return unit_m;
		}

		template<class T>
		bool invertable(Matrix<T> &mat) {
			return (mat.square() && determinant(mat) != 0);
		}

		template<class T>
		Matrix<T> inverseMatrix(Matrix<T> mat, bool tested = true) {
			/*
				Matrix inverse by Gauss-Jordan method ([A|I] -> [I|A']).
				Assumes that the matrix has already been tested as invertible.
				takes a COPY of a matrix, as this method requires the
				manipulation of the rows of the matrix.
			*/
			if (!tested && invertable(mat) == 0) {
				/*
					In the case that the matrix is not invertible, the function will
					return an identity matrix with the height of the given matrix.
				*/
				return identityMatrix(mat.h());
			}
			else {
				if (mat.h() == 2) {
					/*
						2 by 2 matrix shortcut.
					*/
					T temp = mat[0][0];
					mat[0][0] = mat[1][1];
					mat[1][1] = temp;
					temp = mat[1][0];
					mat[1][0] = -mat[0][1];
					mat[0][1] = -temp;
					return mat;

				}
				else {
					Matrix<T> inverse = identityMatrix(mat.h());
					/*
						Sort the matrix rows by pivot index and
					*/

				}
			}
		}

		template<class T>
		Matrix<T> transposeMatrix(Matrix<T> &mat) {
			/*
				Creates & returns a transposed version of the given matrix.
			*/
			Matrix<T> trans(mat.h(), mat.w(), 0);
			for (unsigned int y = 0; y < mat.h(); y++) {
				for (unsigned int x = 0; x < mat.w(); x++) {
					trans[x][y] = mat[y][x];
				}
			}
			return trans;
		}

	}
}

#endif<|endoftext|>


<commit_before>//g++ *.cpp -lpthread -lwiringPi -std=c++11
//LATER MET GUI MAKEFILE <sudo make>

#include "I22cCom.h"
// Sensors -------------------
#include "Sensor.h"
#include "Log.h"
#include "Camera.h"
#include "Light.h"
#include "MotionSensor.h"
#include "PressureSensor.h"
// GUI ----------
#include "dialog.h"
#include <QApplication>
#include "temperatuur.h"
// ----------
//#define I2CLOC "/dev/i2c-1"// <-- this is the real I2C device you need with the scale model
#define I2CLOC "/dev/simudrv"
#define LOG "Slaaplog.txt"

#include <vector>
#include <iostream>
#include <wiringPi.h>  //compile with -lwiringPi

using namespace std;

vector<Sensor*> motionSensors;    //Vector of the sensors
vector<Light*> lights;      //Vector of the lights
vector<int> active;
PressureSensor* pressureSensor;
Camera* cam;                //Pointer to the camera
Log* log;

int pressureValue;
bool asleep = false;
bool day = true;
bool anomaly = false;
int temperature = 20;
long sleepTimer = 0;

void checkAnomaly();
void updateSensors();
void checkCam();
void sendAlert();
void init();

int GUImain(int argc, char *argv[]){
	QApplication a(argc, argv);
	Dialog w;
	w.show();
	a.exec();
}

int main() {
  init();
  while(1) {
        updateSensors();
        checkAnomaly();
        checkCam();
        checkTemperature();
  }
}

/*Init for the main*/
void init() {
	std::thread GUIloop(GUImain);
	GUIloop.join();
	wiringPiSetupGpio();
	I2CCom i2c(I2CLOC);     //the i2c to communicate with sensor
	Light x(22);
	MotionSensor s1(0xFC,i2c);
	MotionSensor s2(0xBC,i2c);
	MotionSensor s3(0xEC,i2c);
	PressureSensor s4(0x06, i2c);
	Log l1(LOG);
	Camera c1;
	cam = &c1;
	log = &l1;
	pressureSensor = &s4;
	motionSensors.push_back(&s1);
	motionSensors.push_back(&s2);
	motionSensors.push_back(&s3);
	lights.push_back(&x);

active.resize(motionSensors.size());
}
/*Updates sensors*/
void updateSensors() {
    //update van elke sensor de value en de active
    bool alert = true;
    for(int i = 0; i<motionSensors.size();i++) {
        if(motionSensors[i]->check()) {
            //active[i]=1;
            alert = false;
		cout <<"halleyula" <<endl;
        } else{
            //active[i]=0;
        }
    }
    if (s4->check()) {
        asleep = true;
    }
    if(alert & !asleep) {
        sendAlert();
    }
    pressureValue = s4->getValue();
}

/*Send Alarm*/
void sendAlert(){
    cout<<"Alert"<<endl;
}

/*Sets the camera*/
void checkCam(){
    if(day) {
        cam->setCamera(true);
    } else if(anomaly) {
        cam->setCamera(true);
    } else {
        cam->setCamera(false);
    }
}

void checkAnomaly(){
    if(pressureValue < 20) {
        asleep = false;
        sleepTimer = 0;
    } else if(pressureValue > 20 && pressureValue < 150) {
        anomaly = true;
        sleepTimer = 0;
    } else if(pressureValue > 150 && pressureValue < 200) {
        sleepTimer = 0;
        // Changing positions while asleep
        //Do nothing, maybe verify if person really is sleeping
    } else if(pressureValue > 200 && sleepTimer = 0) {
        sleepTimer = time(0) + 900;
    } else if(pressureValue >200 && sleepTimer != 0) {
        if( time(0) >= sleepTimer) {
            asleep = true
        }
    }

}

checkTemperature() {
    temperature = IngesteldeTemperatuur;
}

<commit_msg>added comments<commit_after>//g++ *.cpp -lpthread -lwiringPi -std=c++11
//LATER MET GUI MAKEFILE <sudo make>

#include "I22cCom.h"
// Sensors -------------------
#include "Sensor.h"
#include "Log.h"
#include "Camera.h"
#include "Light.h"
#include "MotionSensor.h"
#include "PressureSensor.h"
// GUI ----------
#include "dialog.h"
#include <QApplication>
#include "temperatuur.h"
// ----------
//#define I2CLOC "/dev/i2c-1"// <-- this is the real I2C device you need with the scale model
#define I2CLOC "/dev/simudrv"
#define LOG "Slaaplog.txt"

#include <vector>
#include <iostream>
#include <wiringPi.h>  //compile with -lwiringPi

using namespace std;

vector<Sensor*> motionSensors;    //Vector of the sensors
vector<Light*> lights;      //Vector of the lights
vector<int> active;
PressureSensor* pressureSensor;
Camera* cam;                //Pointer to the camera
Log* log;

int pressureValue;
bool asleep = false;
bool day = true;
bool anomaly = false;
int temperature = 20;
long sleepTimer = 0;

void checkAnomaly();
void updateSensors();
void checkCam();
void sendAlert();
void init();

int GUImain(int argc, char *argv[]){
	QApplication a(argc, argv);
	Dialog w;
	w.show();
	a.exec();
}

int main() {
  init();
  while(1) {
        updateSensors();
        checkAnomaly();
        checkCam();
        checkTemperature();
  }
}

/*Init for the main*/
void init() {
	std::thread GUIloop(GUImain);
	GUIloop.join();
	wiringPiSetupGpio();
	I2CCom i2c(I2CLOC);     //the i2c to communicate with sensor
	Light x(22);
	MotionSensor s1(0xFC,i2c);
	MotionSensor s2(0xBC,i2c);
	MotionSensor s3(0xEC,i2c);
	PressureSensor s4(0x06, i2c);
	Log l1(LOG);
	Camera c1;
	cam = &c1;
	log = &l1;
	pressureSensor = &s4;
	motionSensors.push_back(&s1);
	motionSensors.push_back(&s2);
	motionSensors.push_back(&s3);
	lights.push_back(&x);

active.resize(motionSensors.size());
}
/*Updates sensors*/
void updateSensors() {
    //update van elke sensor de value en de active
    bool alert = true;
    for(int i = 0; i<motionSensors.size();i++) {
        if(motionSensors[i]->check()) {
            //active[i]=1;
            alert = false;
		cout <<"halleyula" <<endl;
        } else{
            //active[i]=0;
        }
    }
    if (s4->check()) {
        asleep = true;
    }
    if(alert & !asleep) {
        sendAlert();
    }
    pressureValue = s4->getValue();
}

/*Send Alarm*/
void sendAlert(){
    cout<<"Alert"<<endl;
}

/*Sets the camera*/
void checkCam(){
    if(day) {
        cam->setCamera(true);
    } else if(anomaly) {
        cam->setCamera(true);
    } else {
        cam->setCamera(false);
    }
}

/*Checks if there is an anomaly, otherwise checks if Tim's asleep*/
void checkAnomaly(){
    if(pressureValue < 20) {
        asleep = false;
        sleepTimer = 0;
    } else if(pressureValue > 20 && pressureValue < 150) {
        anomaly = true;
        sleepTimer = 0;
    } else if(pressureValue > 150 && pressureValue < 200) {
        sleepTimer = 0;
        // Changing positions while asleep
        //Do nothing, maybe verify if person really is sleeping
    } else if(pressureValue > 200 && sleepTimer = 0) {
        sleepTimer = time(0) + 900;
    } else if(pressureValue >200 && sleepTimer != 0) {
        if( time(0) >= sleepTimer) {
            asleep = true
        }
    }

}

/*Checks the set temperature from the gui*/
checkTemperature() {
    temperature = IngesteldeTemperatuur;
}

<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions 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.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
#include "ElemAttribute.hpp"

#include <sax/AttributeList.hpp>

#include <PlatformSupport/DOMStringHelper.hpp>
#include <PlatformSupport/XalanUnicode.hpp>

#include <DOMSupport/DOMServices.hpp>

#include "AVT.hpp"
#include "Constants.hpp"
#include "StylesheetConstructionContext.hpp"
#include "StylesheetExecutionContext.hpp"

ElemAttribute::ElemAttribute(
			StylesheetConstructionContext&	constructionContext,
			Stylesheet&						stylesheetTree,
			const AttributeList&			atts,
			int								lineNumber,
			int								columnNumber) :
	ElemTemplateElement(constructionContext,
						stylesheetTree,
						lineNumber,
						columnNumber,
						Constants::ELEMNAME_ATTRIBUTE),
	m_pNameAVT(0),
	m_pNamespaceAVT(0)
{
	const unsigned int	nAttrs = atts.getLength();

	for(unsigned int i = 0; i < nAttrs; i++)
	{
		const XalanDOMChar*	const	aname = atts.getName(i);

		if(equals(aname, Constants::ATTRNAME_NAME))
		{
			m_pNameAVT = new AVT(getLocator(), aname, atts.getType(i), atts.getValue(i),
				*this, constructionContext);
		}
		else if(equals(aname,Constants::ATTRNAME_NAMESPACE))
		{
			m_pNamespaceAVT = new AVT(getLocator(), aname, atts.getType(i), atts.getValue(i),
				*this, constructionContext);
		}
		else if(!(isAttrOK(aname, atts, i, constructionContext) ||
				 processSpaceAttr(aname, atts, i, constructionContext)))
		{
			constructionContext.error(
				"xsl:attribute has an illegal attribute",
				0,
				this);
		}
	}

	if(0 == m_pNameAVT)
	{
#if defined(XALAN_CANNOT_DELETE_CONST)
		delete (AVT*)m_pNamespaceAVT;
#else
		delete m_pNamespaceAVT;
#endif

		constructionContext.error(
			"xsl:attribute must have a 'name' attribute",
			0,
			this);
	}

}

ElemAttribute::~ElemAttribute()
{
#if defined(XALAN_CANNOT_DELETE_CONST)
	delete (AVT*)m_pNameAVT;

	delete (AVT*)m_pNamespaceAVT;
#else
	delete m_pNameAVT;

	delete m_pNamespaceAVT;
#endif
}

const XalanDOMString&
ElemAttribute::getElementName() const
{
	return Constants::ELEMNAME_ATTRIBUTE_WITH_PREFIX_STRING;
}

void
ElemAttribute::execute(StylesheetExecutionContext&		executionContext) const
{
	assert(m_pNameAVT != 0);

	ElemTemplateElement::execute(executionContext);

	StylesheetExecutionContext::GetAndReleaseCachedString	attrNameGuard(executionContext);

	XalanDOMString&		attrName = attrNameGuard.get();

	XalanNode* sourceNode = executionContext.getCurrentNode();

	m_pNameAVT->evaluate(attrName, sourceNode, *this, executionContext);

	if(!isEmpty(attrName))
	{
		// save original attribute name
		StylesheetExecutionContext::GetAndReleaseCachedString	origAttrNameGuard(executionContext);

		XalanDOMString&		origAttrName = origAttrNameGuard.get();

		assign(origAttrName, attrName);

		const XalanDOMString::size_type		origAttrNameLength = length(origAttrName);

		XalanDOMString::size_type			indexOfNSSep = 0;

		StylesheetExecutionContext::GetAndReleaseCachedString	attrNameSpaceGuard(executionContext);

		XalanDOMString&		attrNameSpace = attrNameSpaceGuard.get();

		if(0 != m_pNamespaceAVT)
		{
			m_pNamespaceAVT->evaluate(attrNameSpace, sourceNode, *this, executionContext);

			if(isEmpty(attrNameSpace))
			{
				indexOfNSSep = origAttrNameLength;
			}
			else
			{
				indexOfNSSep = indexOf(origAttrName, XalanUnicode::charColon);

				// See if the namespace already exists.  If it does, we'll get the
				// prefix that was used when it was declared.
				const XalanDOMString*  const	prefix =
					executionContext.getResultPrefixForNamespace(attrNameSpace);

				if(prefix != 0)
				{
					assert(length(*prefix) != 0);

					if(indexOfNSSep < origAttrNameLength)
					{
						reserve(
							attrName,
							length(attrName) - (indexOfNSSep + 1) + DOMServices::s_XMLNamespaceSeparatorStringLength + length(*prefix) + 1);

						assign(attrName, substring(attrName, indexOfNSSep + 1));
					}
					else
					{
						reserve(
							attrName,
							length(attrName) + DOMServices::s_XMLNamespaceSeparatorStringLength + length(*prefix) + 1);
					}

					insert(attrName, 0, DOMServices::s_XMLNamespaceSeparatorString);
					insert(attrName, 0, *prefix);
				}
				else
				{
					StylesheetExecutionContext::GetAndReleaseCachedString	newPrefixGuard(executionContext);

					XalanDOMString&		newPrefix = newPrefixGuard.get();

					// If the prefix on the QName is xmlns, we cannot use it.
					const bool			fPrefixIsXMLNS =
						startsWith(origAttrName, DOMServices::s_XMLNamespaceWithSeparator);

					// If there's a prefix, and it's not xmlns, then use
					// the prefix that's provided.
					if(indexOfNSSep < origAttrNameLength &&
					    fPrefixIsXMLNS == false)
					{
						newPrefix = substring(origAttrName, 0, indexOfNSSep);

						// OK, make sure that the prefix provided maps to
						// the same namespace as the one the user requested,
						// and see if it's in use...
						const XalanDOMString* const	theNamespace =
							executionContext.getResultNamespaceForPrefix(newPrefix);

						if (theNamespace != 0 &&
							equals(*theNamespace, attrNameSpace) == false &&
							executionContext.isPendingResultPrefix(newPrefix) == true)
						{
							// It doesn't, so we'll need to manufacture a
							// prefix.
							clear(newPrefix);

							// Strip the user-supplied prefix from the name...
							attrName = substring(origAttrName, indexOfNSSep + 1);
						}
					}

					if (length(newPrefix) == 0)
					{
						// If there's a prefix, and it's xmlns, then strip it
						// off...
						if (fPrefixIsXMLNS == true)
						{
							assign(attrName, substring(attrName, indexOfNSSep + 1));
						}

						// Get a new, unique namespace prefix...
						executionContext.getUniqueNamespaceValue(newPrefix);

						// Reserve some space in the string.
						reserve(
							attrName,
							length(attrName) + DOMServices::s_XMLNamespaceSeparatorStringLength + length(newPrefix) + 1);

						insert(attrName, 0, DOMServices::s_XMLNamespaceSeparatorString);
						insert(attrName, 0, newPrefix);
					}

					// OK, now we have to generate a namespace declaration...
					StylesheetExecutionContext::GetAndReleaseCachedString	nsDeclGuard(executionContext);

					XalanDOMString&		nsDecl = nsDeclGuard.get();

					reserve(nsDecl, DOMServices::s_XMLNamespaceWithSeparatorLength + length(newPrefix) + 1);

					assign(nsDecl, DOMServices::s_XMLNamespaceWithSeparator);

					append(nsDecl, newPrefix);

					// Add the namespace declaration...
					executionContext.addResultAttribute(nsDecl, attrNameSpace);
				}
			}
		}
      // Note we are using original attribute name for these tests.
		else if(executionContext.isElementPending() == true &&
				!equals(origAttrName, DOMServices::s_XMLNamespace))
		{
			// Don't try to create a namespace declaration for anything that
			// starts with xml:
			if (startsWith(origAttrName, DOMServices::s_XMLString) == true)
			{
				// This just fakes out the test below.  It would be better if
				// we had a better way of testing this...
				indexOfNSSep = origAttrNameLength;
			}
			else
			{
				// make sure that if a prefix is specified on the attribute name, it is valid
				indexOfNSSep = indexOf(origAttrName, XalanUnicode::charColon);

				if(indexOfNSSep < origAttrNameLength)
				{
					StylesheetExecutionContext::GetAndReleaseCachedString	nsprefixGuard(executionContext);

					XalanDOMString&		nsprefix = nsprefixGuard.get();

					nsprefix = substring(origAttrName, 0, indexOfNSSep);

					const XalanDOMString* const		theNamespace =
						getNamespaceForPrefix(nsprefix);

					if (theNamespace != 0)
					{
						assign(attrNameSpace, *theNamespace);
					}

					if (isEmpty(attrNameSpace))
					{
						// Could not resolve prefix
						executionContext.warn("Warning: Could not resolve prefix " + nsprefix, sourceNode, this);
					}
					else
					{
						// Check to see if there's already a namespace declaration in scope...
						const XalanDOMString* const		prefix =
							executionContext.getResultPrefixForNamespace(attrNameSpace);

						if (prefix == 0)
						{
							// We need to generate a namespace declaration...
							StylesheetExecutionContext::GetAndReleaseCachedString	nsDeclGuard(executionContext);

							XalanDOMString&		nsDecl = nsDeclGuard.get();

							reserve(nsDecl, DOMServices::s_XMLNamespaceWithSeparatorLength + length(nsprefix) + 1);

							assign(nsDecl, DOMServices::s_XMLNamespaceWithSeparator);

							append(nsDecl, nsprefix);

							// Add the namespace declaration...
							executionContext.addResultAttribute(nsDecl, attrNameSpace);
						}
					}
				}
			}
		}
		else
		{
			executionContext.warn("Warning: Trying to add attribute after element child has been added, ignoring...", sourceNode, this);
		}

		// If there was no namespace, or the namespace was resolved, process
		// the result attribute.
		if (indexOfNSSep == origAttrNameLength || !isEmpty(attrNameSpace))
		{
			childrenToResultAttribute(
				executionContext,
				attrName);
		}
	}
}

bool
ElemAttribute::childTypeAllowed(int		xslToken) const
{
	bool	fResult = false;

	switch(xslToken)
	{
		// char-instructions
	case Constants::ELEMNAME_TEXTLITERALRESULT:
	case Constants::ELEMNAME_APPLY_TEMPLATES:
	case Constants::ELEMNAME_APPLY_IMPORTS:
	case Constants::ELEMNAME_CALLTEMPLATE:
	case Constants::ELEMNAME_FOREACH:
	case Constants::ELEMNAME_VALUEOF:
	case Constants::ELEMNAME_COPY_OF:
	case Constants::ELEMNAME_NUMBER:
	case Constants::ELEMNAME_CHOOSE:
	case Constants::ELEMNAME_IF:
	case Constants::ELEMNAME_TEXT:
	case Constants::ELEMNAME_COPY:
	case Constants::ELEMNAME_VARIABLE:
	case Constants::ELEMNAME_MESSAGE:
		// instructions
		// case Constants.ELEMNAME_PI:
		// case Constants.ELEMNAME_COMMENT:
		// case Constants.ELEMNAME_ELEMENT:
		// case Constants.ELEMNAME_ATTRIBUTE:
		fResult = true;
		break;

	default:
		break;
	}

	return fResult;
}
<commit_msg>Make sure that a new namespace declaration is generated when an attribute's namespace is the default namespace. (namespace128, namespace130)<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions 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.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
#include "ElemAttribute.hpp"

#include <sax/AttributeList.hpp>

#include <PlatformSupport/DOMStringHelper.hpp>
#include <PlatformSupport/XalanUnicode.hpp>

#include <DOMSupport/DOMServices.hpp>

#include "AVT.hpp"
#include "Constants.hpp"
#include "StylesheetConstructionContext.hpp"
#include "StylesheetExecutionContext.hpp"

ElemAttribute::ElemAttribute(
			StylesheetConstructionContext&	constructionContext,
			Stylesheet&						stylesheetTree,
			const AttributeList&			atts,
			int								lineNumber,
			int								columnNumber) :
	ElemTemplateElement(constructionContext,
						stylesheetTree,
						lineNumber,
						columnNumber,
						Constants::ELEMNAME_ATTRIBUTE),
	m_pNameAVT(0),
	m_pNamespaceAVT(0)
{
	const unsigned int	nAttrs = atts.getLength();

	for(unsigned int i = 0; i < nAttrs; i++)
	{
		const XalanDOMChar*	const	aname = atts.getName(i);

		if(equals(aname, Constants::ATTRNAME_NAME))
		{
			m_pNameAVT = new AVT(getLocator(), aname, atts.getType(i), atts.getValue(i),
				*this, constructionContext);
		}
		else if(equals(aname,Constants::ATTRNAME_NAMESPACE))
		{
			m_pNamespaceAVT = new AVT(getLocator(), aname, atts.getType(i), atts.getValue(i),
				*this, constructionContext);
		}
		else if(!(isAttrOK(aname, atts, i, constructionContext) ||
				 processSpaceAttr(aname, atts, i, constructionContext)))
		{
			constructionContext.error(
				"xsl:attribute has an illegal attribute",
				0,
				this);
		}
	}

	if(0 == m_pNameAVT)
	{
#if defined(XALAN_CANNOT_DELETE_CONST)
		delete (AVT*)m_pNamespaceAVT;
#else
		delete m_pNamespaceAVT;
#endif

		constructionContext.error(
			"xsl:attribute must have a 'name' attribute",
			0,
			this);
	}

}

ElemAttribute::~ElemAttribute()
{
#if defined(XALAN_CANNOT_DELETE_CONST)
	delete (AVT*)m_pNameAVT;

	delete (AVT*)m_pNamespaceAVT;
#else
	delete m_pNameAVT;

	delete m_pNamespaceAVT;
#endif
}

const XalanDOMString&
ElemAttribute::getElementName() const
{
	return Constants::ELEMNAME_ATTRIBUTE_WITH_PREFIX_STRING;
}

void
ElemAttribute::execute(StylesheetExecutionContext&		executionContext) const
{
	assert(m_pNameAVT != 0);

	ElemTemplateElement::execute(executionContext);

	StylesheetExecutionContext::GetAndReleaseCachedString	attrNameGuard(executionContext);

	XalanDOMString&		attrName = attrNameGuard.get();

	XalanNode* sourceNode = executionContext.getCurrentNode();

	m_pNameAVT->evaluate(attrName, sourceNode, *this, executionContext);

	if(!isEmpty(attrName))
	{
		// save original attribute name
		StylesheetExecutionContext::GetAndReleaseCachedString	origAttrNameGuard(executionContext);

		XalanDOMString&		origAttrName = origAttrNameGuard.get();

		assign(origAttrName, attrName);

		const XalanDOMString::size_type		origAttrNameLength = length(origAttrName);

		XalanDOMString::size_type			indexOfNSSep = 0;

		StylesheetExecutionContext::GetAndReleaseCachedString	attrNameSpaceGuard(executionContext);

		XalanDOMString&		attrNameSpace = attrNameSpaceGuard.get();

		if(0 != m_pNamespaceAVT)
		{
			m_pNamespaceAVT->evaluate(attrNameSpace, sourceNode, *this, executionContext);

			if(isEmpty(attrNameSpace))
			{
				indexOfNSSep = origAttrNameLength;
			}
			else
			{
				indexOfNSSep = indexOf(origAttrName, XalanUnicode::charColon);

				// See if the namespace already exists.  If it does, we'll get the
				// prefix that was used when it was declared.
				const XalanDOMString*  const	prefix =
					executionContext.getResultPrefixForNamespace(attrNameSpace);

				if(prefix != 0 && length(*prefix) != 0)
				{
					if(indexOfNSSep < origAttrNameLength)
					{
						reserve(
							attrName,
							length(attrName) - (indexOfNSSep + 1) + DOMServices::s_XMLNamespaceSeparatorStringLength + length(*prefix) + 1);

						assign(attrName, substring(attrName, indexOfNSSep + 1));
					}
					else
					{
						reserve(
							attrName,
							length(attrName) + DOMServices::s_XMLNamespaceSeparatorStringLength + length(*prefix) + 1);
					}

					insert(attrName, 0, DOMServices::s_XMLNamespaceSeparatorString);
					insert(attrName, 0, *prefix);
				}
				else
				{
					StylesheetExecutionContext::GetAndReleaseCachedString	newPrefixGuard(executionContext);

					XalanDOMString&		newPrefix = newPrefixGuard.get();

					// If the prefix on the QName is xmlns, we cannot use it.
					const bool			fPrefixIsXMLNS =
						startsWith(origAttrName, DOMServices::s_XMLNamespaceWithSeparator);

					// If there's a prefix, and it's not xmlns, then use
					// the prefix that's provided.
					if(indexOfNSSep < origAttrNameLength &&
					    fPrefixIsXMLNS == false)
					{
						newPrefix = substring(origAttrName, 0, indexOfNSSep);

						// OK, make sure that the prefix provided maps to
						// the same namespace as the one the user requested,
						// and see if it's in use...
						const XalanDOMString* const	theNamespace =
							executionContext.getResultNamespaceForPrefix(newPrefix);

						if (theNamespace != 0 &&
							equals(*theNamespace, attrNameSpace) == false &&
							executionContext.isPendingResultPrefix(newPrefix) == true)
						{
							// It doesn't, so we'll need to manufacture a
							// prefix.
							clear(newPrefix);

							// Strip the user-supplied prefix from the name...
							attrName = substring(origAttrName, indexOfNSSep + 1);
						}
					}

					if (length(newPrefix) == 0)
					{
						// If there's a prefix, and it's xmlns, then strip it
						// off...
						if (fPrefixIsXMLNS == true)
						{
							assign(attrName, substring(attrName, indexOfNSSep + 1));
						}

						// Get a new, unique namespace prefix...
						executionContext.getUniqueNamespaceValue(newPrefix);

						// Reserve some space in the string.
						reserve(
							attrName,
							length(attrName) + DOMServices::s_XMLNamespaceSeparatorStringLength + length(newPrefix) + 1);

						insert(attrName, 0, DOMServices::s_XMLNamespaceSeparatorString);
						insert(attrName, 0, newPrefix);
					}

					// OK, now we have to generate a namespace declaration...
					StylesheetExecutionContext::GetAndReleaseCachedString	nsDeclGuard(executionContext);

					XalanDOMString&		nsDecl = nsDeclGuard.get();

					reserve(nsDecl, DOMServices::s_XMLNamespaceWithSeparatorLength + length(newPrefix) + 1);

					assign(nsDecl, DOMServices::s_XMLNamespaceWithSeparator);

					append(nsDecl, newPrefix);

					// Add the namespace declaration...
					executionContext.addResultAttribute(nsDecl, attrNameSpace);
				}
			}
		}
      // Note we are using original attribute name for these tests.
		else if(executionContext.isElementPending() == true &&
				!equals(origAttrName, DOMServices::s_XMLNamespace))
		{
			// Don't try to create a namespace declaration for anything that
			// starts with xml:
			if (startsWith(origAttrName, DOMServices::s_XMLString) == true)
			{
				// This just fakes out the test below.  It would be better if
				// we had a better way of testing this...
				indexOfNSSep = origAttrNameLength;
			}
			else
			{
				// make sure that if a prefix is specified on the attribute name, it is valid
				indexOfNSSep = indexOf(origAttrName, XalanUnicode::charColon);

				if(indexOfNSSep < origAttrNameLength)
				{
					StylesheetExecutionContext::GetAndReleaseCachedString	nsprefixGuard(executionContext);

					XalanDOMString&		nsprefix = nsprefixGuard.get();

					nsprefix = substring(origAttrName, 0, indexOfNSSep);

					const XalanDOMString* const		theNamespace =
						getNamespaceForPrefix(nsprefix);

					if (theNamespace != 0)
					{
						assign(attrNameSpace, *theNamespace);
					}

					if (isEmpty(attrNameSpace))
					{
						// Could not resolve prefix
						executionContext.warn("Warning: Could not resolve prefix " + nsprefix, sourceNode, this);
					}
					else
					{
						// Check to see if there's already a namespace declaration in scope...
						const XalanDOMString* const		prefix =
							executionContext.getResultPrefixForNamespace(attrNameSpace);

						if (prefix == 0)
						{
							// We need to generate a namespace declaration...
							StylesheetExecutionContext::GetAndReleaseCachedString	nsDeclGuard(executionContext);

							XalanDOMString&		nsDecl = nsDeclGuard.get();

							reserve(nsDecl, DOMServices::s_XMLNamespaceWithSeparatorLength + length(nsprefix) + 1);

							assign(nsDecl, DOMServices::s_XMLNamespaceWithSeparator);

							append(nsDecl, nsprefix);

							// Add the namespace declaration...
							executionContext.addResultAttribute(nsDecl, attrNameSpace);
						}
					}
				}
			}
		}
		else
		{
			executionContext.warn("Warning: Trying to add attribute after element child has been added, ignoring...", sourceNode, this);
		}

		// If there was no namespace, or the namespace was resolved, process
		// the result attribute.
		if (indexOfNSSep == origAttrNameLength || !isEmpty(attrNameSpace))
		{
			childrenToResultAttribute(
				executionContext,
				attrName);
		}
	}
}

bool
ElemAttribute::childTypeAllowed(int		xslToken) const
{
	bool	fResult = false;

	switch(xslToken)
	{
		// char-instructions
	case Constants::ELEMNAME_TEXTLITERALRESULT:
	case Constants::ELEMNAME_APPLY_TEMPLATES:
	case Constants::ELEMNAME_APPLY_IMPORTS:
	case Constants::ELEMNAME_CALLTEMPLATE:
	case Constants::ELEMNAME_FOREACH:
	case Constants::ELEMNAME_VALUEOF:
	case Constants::ELEMNAME_COPY_OF:
	case Constants::ELEMNAME_NUMBER:
	case Constants::ELEMNAME_CHOOSE:
	case Constants::ELEMNAME_IF:
	case Constants::ELEMNAME_TEXT:
	case Constants::ELEMNAME_COPY:
	case Constants::ELEMNAME_VARIABLE:
	case Constants::ELEMNAME_MESSAGE:
		// instructions
		// case Constants.ELEMNAME_PI:
		// case Constants.ELEMNAME_COMMENT:
		// case Constants.ELEMNAME_ELEMENT:
		// case Constants.ELEMNAME_ATTRIBUTE:
		fResult = true;
		break;

	default:
		break;
	}

	return fResult;
}
<|endoftext|>


<commit_before>#include "DemoAppBase.h"

using namespace SoftRPDemo;

DemoAppBase::DemoAppBase(HINSTANCE hInstance, unsigned int width, unsigned int height)
		:SingleWindowApp(hInstance, width, height), m_viewPort{ getWidth(), getHeight() },
			m_renderTarget{}, m_depthBuffer{ getWidth(), getHeight() },
			m_inputVertexLayout{ SoftRP::InputVertexLayout::create(std::vector<size_t>{}) },
			m_outputVertexLayout{ SoftRP::OutputVertexLayout::create(0) } {

	m_lastTime = std::chrono::high_resolution_clock::now();
	updateView();
}

void DemoAppBase::onUpdate(){

	const auto now = std::chrono::high_resolution_clock::now();
	auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(now - m_lastTime);

	renderFrame(delta.count());

	m_lastTime = now;
	m_millis += delta;
	m_frameCount++;

	std::wstring delta_str = std::to_wstring(delta.count());

	if (m_millis >= std::chrono::milliseconds{ 1000 }) {
		m_fpsString = std::to_wstring(m_frameCount);
		m_frameCount = 1;
		m_millis = std::chrono::milliseconds{ 0 };
	}
	SetWindowText(getWindowHandle(),
				  (delta_str + std::wstring{ L" ms, " } + m_fpsString + std::wstring{ L" FPS" } + m_messageString).c_str());
}

void DemoAppBase::onResize(){

	unsigned int width = getWidth();
	unsigned int height = getHeight();

	m_viewPort = SoftRP::ViewPort{ width, height };

	m_depthBuffer.resize(width, height);

	m_camera.makePerspective(static_cast<float>(width) / static_cast<float>(height));

	m_renderTarget.setWindowHandle(getWindowHandle());
	m_renderTarget.resize(getWidth(), getHeight());
}

bool DemoAppBase::onMouseDown(MouseButton mouseButton, MousePos mousePos){
	if (mouseButton == MouseButton::MIDDLE)
		return false;
	SetCapture(getWindowHandle());
	m_lastMousePos.mouseX = mousePos.mouseX;
	m_lastMousePos.mouseY = mousePos.mouseY;
	m_mouseCaptured = true;
	m_leftButtonDown = mouseButton == MouseButton::LEFT;
	return true;
}

bool DemoAppBase::onMouseUp(MouseButton mouseButton, MousePos mousePos) {
	if (mouseButton == MouseButton::MIDDLE)
		return false;
	ReleaseCapture();
	m_mouseCaptured = false;
	return true;
}

bool DemoAppBase::onMouseMove(MousePos mousePos){
	if (!m_mouseCaptured)
		return false;

	float deltaX = degsToRadians(static_cast<float>(mousePos.mouseX - m_lastMousePos.mouseX));
	float deltaY = degsToRadians(static_cast<float>(mousePos.mouseY - m_lastMousePos.mouseY));
	m_lastMousePos.mouseX = mousePos.mouseX;
	m_lastMousePos.mouseY = mousePos.mouseY;

	if (m_leftButtonDown) {
		m_theta += deltaX* 0.25f;
		m_phi += deltaY*0.25f;
	} else {
		m_radius += 0.05f  * deltaX;
	}
	updateView();

	return true;
}

void DemoAppBase::updateView() {

	m_phi = max(m_phi, 0.5f);
	m_phi = min(m_phi, PI - 0.5f);

	m_radius = max(m_radius, m_minRadius);
	m_radius = min(m_radius, m_maxRadius);

	const auto cosTheta = std::cos(m_theta);
	const auto sinTheta = std::sin(m_theta);
	const auto cosPhi = std::cos(m_phi);
	const auto sinPhi = std::sin(m_phi);
	const float x = m_radius*cosTheta*sinPhi;
	const float z = m_radius*sinTheta*sinPhi;
	const float y = m_radius*cosPhi;
	m_camera.lookAt(SoftRP::Math::Vector3{ x, y, z }, m_lookAt);
}

void DemoAppBase::setWindowText(const std::wstring& text) {
	m_messageString = std::wstring{L", "} + text;
}

void DemoAppBase::setWindowText(std::wstring&& text) {
	m_messageString = std::wstring{ L", " } + std::move(text);
}<commit_msg>Fixed wrong fps computation<commit_after>#include "DemoAppBase.h"

using namespace SoftRPDemo;

DemoAppBase::DemoAppBase(HINSTANCE hInstance, unsigned int width, unsigned int height)
		:SingleWindowApp(hInstance, width, height), m_viewPort{ getWidth(), getHeight() },
			m_renderTarget{}, m_depthBuffer{ getWidth(), getHeight() },
			m_inputVertexLayout{ SoftRP::InputVertexLayout::create(std::vector<size_t>{}) },
			m_outputVertexLayout{ SoftRP::OutputVertexLayout::create(0) } {

	m_lastTime = std::chrono::high_resolution_clock::now();
	updateView();
}

void DemoAppBase::onUpdate(){

	const auto now = std::chrono::high_resolution_clock::now();
	auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(now - m_lastTime);

	renderFrame(delta.count());

	m_lastTime = now;
	m_millis += delta;
	m_frameCount++;

	std::wstring delta_str = std::to_wstring(delta.count());

	if (m_millis >= std::chrono::milliseconds{ 1000 }) {
		m_fpsString = std::to_wstring(m_frameCount);
		m_frameCount = 0;
		m_millis = m_millis - std::chrono::milliseconds{ 1000 };
	}
	SetWindowText(getWindowHandle(),
				  (delta_str + std::wstring{ L" ms, " } + m_fpsString + std::wstring{ L" FPS" } + m_messageString).c_str());
}

void DemoAppBase::onResize(){

	unsigned int width = getWidth();
	unsigned int height = getHeight();

	m_viewPort = SoftRP::ViewPort{ width, height };

	m_depthBuffer.resize(width, height);

	m_camera.makePerspective(static_cast<float>(width) / static_cast<float>(height));

	m_renderTarget.setWindowHandle(getWindowHandle());
	m_renderTarget.resize(getWidth(), getHeight());
}

bool DemoAppBase::onMouseDown(MouseButton mouseButton, MousePos mousePos){
	if (mouseButton == MouseButton::MIDDLE)
		return false;
	SetCapture(getWindowHandle());
	m_lastMousePos.mouseX = mousePos.mouseX;
	m_lastMousePos.mouseY = mousePos.mouseY;
	m_mouseCaptured = true;
	m_leftButtonDown = mouseButton == MouseButton::LEFT;
	return true;
}

bool DemoAppBase::onMouseUp(MouseButton mouseButton, MousePos mousePos) {
	if (mouseButton == MouseButton::MIDDLE)
		return false;
	ReleaseCapture();
	m_mouseCaptured = false;
	return true;
}

bool DemoAppBase::onMouseMove(MousePos mousePos){
	if (!m_mouseCaptured)
		return false;

	float deltaX = degsToRadians(static_cast<float>(mousePos.mouseX - m_lastMousePos.mouseX));
	float deltaY = degsToRadians(static_cast<float>(mousePos.mouseY - m_lastMousePos.mouseY));
	m_lastMousePos.mouseX = mousePos.mouseX;
	m_lastMousePos.mouseY = mousePos.mouseY;

	if (m_leftButtonDown) {
		m_theta += deltaX* 0.25f;
		m_phi += deltaY*0.25f;
	} else {
		m_radius += 0.05f  * deltaX;
	}
	updateView();

	return true;
}

void DemoAppBase::updateView() {

	m_phi = max(m_phi, 0.5f);
	m_phi = min(m_phi, PI - 0.5f);

	m_radius = max(m_radius, m_minRadius);
	m_radius = min(m_radius, m_maxRadius);

	const auto cosTheta = std::cos(m_theta);
	const auto sinTheta = std::sin(m_theta);
	const auto cosPhi = std::cos(m_phi);
	const auto sinPhi = std::sin(m_phi);
	const float x = m_radius*cosTheta*sinPhi;
	const float z = m_radius*sinTheta*sinPhi;
	const float y = m_radius*cosPhi;
	m_camera.lookAt(SoftRP::Math::Vector3{ x, y, z }, m_lookAt);
}

void DemoAppBase::setWindowText(const std::wstring& text) {
	m_messageString = std::wstring{L", "} + text;
}

void DemoAppBase::setWindowText(std::wstring&& text) {
	m_messageString = std::wstring{ L", " } + std::move(text);
}<|endoftext|>