<commit_before>/*-------------salesman.cpp---------------------------------------------------//
*
* Purpose: To solve the travelling saleman problem with genetic algorithms
*
*   Notes: Not settled that c++ is the best language for this
*
*-----------------------------------------------------------------------------*/

#include <iostream>
#include <vector>
#include <string>
#include <random>
#include "../visualization/cairo/cairo_vis.h"

struct City{
    std::string name;
    vec loc;

    City(const std::string &n, vec l) : name(n), loc(l) { }
};

struct Chromosome{
    double fitness;
    std::vector<City*> path;
};

// Function to create initial list of cities, positions predefined
std::vector<City> init_cities();

// Function to initialize the population as random "walks" through cities
std::vector<Chromosome> init(std::vector<City> &cities, int size);

// Function to perform tournament selection
Chromosome tournament(std::vector<Chromosome> &population, int t_size);

// Function to perform tournament selection of our population
std::vector<Chromosome> selection(std::vector<Chromosome> &population,
                                  int t_size, int num_parents);

// Function for crossover
std::vector<Chromosome> crossover(std::vector<Chromosome> &parents, int size,
                                  std::vector<Chromosome> &elite);

// Function for mutation
std::vector<Chromosome> mutate(std::vector<Chromosome> &offspring);

// Function for repopulation
std::vector<Chromosome> repopulate(std::vector<Chromosome> &offspring,
                                   std::vector<Chromosome> &elite);

/*----------------------------------------------------------------------------//
* MAIN
*-----------------------------------------------------------------------------*/

int main(){
}

/*----------------------------------------------------------------------------//
* SUBROUTINES
*-----------------------------------------------------------------------------*/

// Function to create initial list of cities, positions predefined
std::vector<City> init_cities(){

    std::vector<City> cities = {

        City("A", {0.75, 0.25}),
        City("B", {0.25, 0.75}),
        City("C", {0.5, 0.5}),
        City("D", {0.75, 0.75}),
        City("E", {0.25, 0.25})
    };

    return cities;
}

// Function to initialize the population as random "walks" through cities
std::vector<Chromosome> init(std::vector<City> &cities, int size){

    // Initializing random device
    std::random_device rd;
    std::mt19937 gen(rd());

    // initializing population set
    std::vector<Chromosome> population(size);

    // initializing list of cities to work with
    std::vector<City*> genes;

    for (int i = 0; i < cities.size(); ++i){
        genes.push_back(&cities[i]);
    }

    // We need to start and end at the same city while also visiting all others
    // We will do this by shuffling our path / genes
    for (int i = 0; i < size; i++){

        std::shuffle(genes.begin(), genes.end(), gen);
        population[i].path = genes;
    }

    return population;
}

// Function to perform tournament selection
Chromosome tournament(std::vector<Chromosome> &population, int t_size){

    // Creating random number generator for selection
    static std::random_device rd;
    static std::mt19937 gen(rd());
    static std::uniform_int_distribution<int>
        choice(0, population.size() -1);

    Chromosome best = population[choice(gen)];
    Chromosome candidate;

    for (int i = 2; i < population.size(); i++){
        candidate = population[choice(gen)];
        if (candidate.fitness < best.fitness){
            best = candidate;
        }
    }

    return best;
}

// Function to perform tournament selection of our population
std::vector<Chromosome> selection(std::vector<Chromosome> &population,
                                  int t_size, int num_parents){
    std::vector<Chromosome> parents(num_parents);

    // selecting each individual parent
    for (int i = 0; i < num_parents; i++){
        parents[i] = tournament(population, t_size);
    }

    return parents;
}

// Function for crossover
std::vector<Chromosome> crossover(std::vector<Chromosome> &parents, int size,
                                  std::vector<Chromosome> &elite){

    // We need to initialize the children first
    std::vector<Chromosome> offspring(size);

    // The crossover step here will produce 2 children from 2 parents,
    // And we will be using std::swap for this.

    // This will basically be a single-point crossover, so we need to randomly
    // Decide at which point we will be performing the crossover

    static std::random_device rd;
    static std::mt19937 gen(rd());

    static std::uniform_int_distribution<int>
        cross_pt(0,size-1);

    Chromosome child1;
    Chromosome child2;

    for (int i = 0; i < size; i += 2){

        //in here we need to do the crossover.

        offspring[i] = child1;
        offspring[i+1] = child2;
    }

    return offspring;
}

<commit_msg>adding a genetic algorithm!<commit_after>/*-------------salesman.cpp---------------------------------------------------//
*
* Purpose: To solve the travelling saleman problem with genetic algorithms
*
*   Notes: Not settled that c++ is the best language for this
*
*-----------------------------------------------------------------------------*/

#include <iostream>
#include <vector>
#include <string>
#include <random>
#include "../visualization/cairo/cairo_vis.h"

struct City{
    std::string name;
    vec loc;

    City(const std::string &n, vec l) : name(n), loc(l) { }
};

struct Chromosome{
    double fitness;
    std::vector<City*> path;
};

// Function to create initial list of cities, positions predefined
std::vector<City> init_cities();

// Function to initialize the population as random "walks" through cities
std::vector<Chromosome> init(std::vector<City> &cities, int size);

// Function to perform tournament selection
Chromosome tournament(std::vector<Chromosome> &population, int t_size);

// Function to perform tournament selection of our population
std::vector<Chromosome> selection(std::vector<Chromosome> &population,
                                  int t_size, int num_parents);

// Function for crossover
std::vector<Chromosome> crossover(std::vector<Chromosome> &parents,
                                  double cross_rate);

// Function to return the location of a provided city on the chromosome
int ch_loc(Chromosome &parent, std::string city, int ignore);

// Function to find the elite of the previous generation
std::vector<Chromosome> find_elite(std::vector<Chromosome> &population,
                                  int elite_num);

// Function for repopulation
std::vector<Chromosome> repopulate(std::vector<Chromosome> &offspring,
                                   std::vector<Chromosome> &elite);

// Function to find the fitness
void find_fitness(std::vector<Chromosome> &population);

// Function to output the current city path
void output_path(Chromosome &ch);

// Function to implement mutation
void mutate(std::vector<Chromosome> &population, double mut_rate);

/*----------------------------------------------------------------------------//
* MAIN
*-----------------------------------------------------------------------------*/

int main(){

    int generations = 100;
    int pop_size = 100;

    // Now we just need to put it all together!
    std::vector<City> cities = init_cities();

    std::vector<Chromosome> population = init(cities, pop_size);
    std::vector<Chromosome> offspring, parents, elite;
    for (int i = 0; i < generations; ++i){

        std::cout << i << '\n';
        find_fitness(population);
        parents = selection(population, 10, 100);
        offspring = crossover(parents, 0.5);
        elite = find_elite(population, 5);
        population = repopulate(offspring, elite);
        mutate(population, 0.10);
    }

    for (int i = 0; i < population.size(); ++i){
        for (int j = 0; j < population[i].path.size(); ++j){
            std::cout << population[i].path[j]->name ;
        }
        std::cout << '\n';
    }
}

/*----------------------------------------------------------------------------//
* SUBROUTINES
*-----------------------------------------------------------------------------*/

// Function to create initial list of cities, positions predefined
std::vector<City> init_cities(){

    std::vector<City> cities = {

        City("A", {0.75, 0.25}),
        City("B", {0.25, 0.75}),
        City("C", {0.5, 0.5}),
        City("D", {0.75, 0.75}),
        City("E", {0.25, 0.25}),
        City("F", {0.125, 0.625}),
        City("G", {0.25, 0.5})
    };

    return cities;
}

// Function to initialize the population as random "walks" through cities
std::vector<Chromosome> init(std::vector<City> &cities, int size){

    // Initializing random device
    std::random_device rd;
    std::mt19937 gen(rd());

    // initializing population set
    std::vector<Chromosome> population(size);

    // initializing list of cities to work with
    std::vector<City*> genes;

    for (int i = 0; i < cities.size(); ++i){
        genes.push_back(&cities[i]);
    }

    // We need to start and end at the same city while also visiting all others
    // We will do this by shuffling our path / genes
    for (int i = 0; i < size; i++){

        std::shuffle(genes.begin(), genes.end(), gen);
        population[i].path = genes;
    }

    return population;
}

// Function to perform tournament selection
Chromosome tournament(std::vector<Chromosome> &population, int t_size){

    // Creating random number generator for selection
    static std::random_device rd;
    static std::mt19937 gen(rd());
    static std::uniform_int_distribution<int>
        choice(0, population.size() -1);

    Chromosome best = population[choice(gen)];
    Chromosome candidate;

    for (int i = 0; i < t_size; i++){
        candidate = population[choice(gen)];
        if (candidate.fitness < best.fitness){
            best = candidate;
        }
    }

    return best;
}

// Function to perform tournament selection of our population
std::vector<Chromosome> selection(std::vector<Chromosome> &population,
                                  int t_size, int num_parents){
    std::vector<Chromosome> parents(num_parents);

    // selecting each individual parent
    for (int i = 0; i < num_parents; i++){
        parents[i] = tournament(population, t_size);
    }

    return parents;
}

// Function for crossover
std::vector<Chromosome> crossover(std::vector<Chromosome> &parents,
                                  double cross_rate){

    // We need to initialize the children first
    std::vector<Chromosome> offspring = parents;

    // The crossover step here will produce 2 children from 2 parents,
    // And we will be using std::swap for this.

    // This will basically be a single-point crossover, so we need to randomly
    // Decide at which point we will be performing the crossover

    static std::random_device rd;
    static std::mt19937 gen(rd());

    static std::uniform_int_distribution<int>
        cross_pt_dist(0,parents[0].path.size() - 1);

    Chromosome child1;
    Chromosome child2;

    int cross_pt = 0;
    std::string cross_city1, cross_city2;

/*
    std::cout << "outputting all parents" << '\n';
    for (int i = 0; i < parents.size(); ++i){
        output_path(parents[i]);
    }
*/

    for (int i = 0; i < offspring.size(); i += 2){

        if (std::rand() % 100 * 0.01 < cross_rate){

            //in here we need to do the crossover.

            // First, we need to find the location of the initial swap
            cross_pt = cross_pt_dist(gen);
            //std::cout << "cp is: " << cross_pt << '\n';
            //std::cout << "i is: " << i << '\n';
            cross_city1 = offspring[i].path[cross_pt]->name;
            cross_city2 = offspring[i+1].path[cross_pt]->name;
            //std::cout << "match this: "<< cross_city1 << '\n';
            //std::cout << "with: "<< cross_city2 << '\n';
            std::swap(offspring[i].path[cross_pt],
                      offspring[i+1].path[cross_pt]);

            while(cross_city1 != cross_city2 || cross_pt != -1){
                //std::cout << offspring[i].path[cross_pt]->name << '\n';
                //std::cout << cross_pt << '\t' << cross_city2 << '\n';
                //output_path(offspring[i]);
                //output_path(offspring[i+1]);
                cross_city2 = offspring[i+1].path[cross_pt]->name;
                std::swap(offspring[i].path[cross_pt],
                          offspring[i+1].path[cross_pt]);
                cross_pt = ch_loc(offspring[i], cross_city2, cross_pt);
            }

            //std::cout << "while done " << i << '\n';
        }
    }

/*
    std::cout << "outputting all offspring" << '\n';
    for (int i = 0; i < offspring.size(); ++i){
        output_path(offspring[i]);
    }
*/

    return offspring;
}

// Function to return the location of a provided city on the chromosome
int ch_loc(Chromosome &parent, std::string city, int ignore){

    int loc = -1;

    for (int i = 0; i < parent.path.size(); ++i){
        if (i != ignore){
            if (parent.path[i]->name == city){
                return i;
            }
        }
    }

    return loc;
}

// Function to find the elite of the previous generation
std::vector<Chromosome> find_elite(std::vector<Chromosome> &population,
                                  int elite_num){

    // First, we need to sort the array to find the best of the best!
    std::vector<Chromosome> sorted_pop(population.size());

    sorted_pop = population;
    std::sort(sorted_pop.begin(), sorted_pop.end(),
              [](const Chromosome &i, const Chromosome &j){
                  return i.fitness < j.fitness;});

    std::vector<Chromosome> elite(elite_num);
    for (int i = 0; i < elite_num; ++i){
        elite[i] = sorted_pop[i];
        std::cout << sorted_pop[i].fitness << '\n';
    }

    std::cout << '\n';

    return elite;

}

// Function for repopulation
std::vector<Chromosome> repopulate(std::vector<Chromosome> &offspring,
                                   std::vector<Chromosome> &elite){

    std::vector<Chromosome> new_population(offspring.size());

    for (size_t i = 0; i < elite.size(); ++i){
        new_population[i] = elite[i];
    }

    for (size_t i = elite.size(); i < offspring.size(); ++i){
        new_population[i] = offspring[i];
    }

    return new_population;
}

// function to find the fitness of each individual in the population
void find_fitness(std::vector<Chromosome> &population){

    double dist = 0;
    for (auto &ind : population){
        dist = 0;
        for (int i = 1; i < ind.path.size(); ++i){
            dist += distance(ind.path[i-1]->loc, ind.path[i]->loc);
        }

        ind.fitness = dist;
    }
}

// Function to output the current city path
void output_path(Chromosome &ch){

    for (int i = 0; i < ch.path.size(); ++i){
        std::cout << ch.path[i]->name;
    }

    std::cout << '\n';
}

// Function to implement mutation
void mutate(std::vector<Chromosome> &population, double mut_rate){

    static std::random_device rd;
    static std::mt19937 gen(rd());

    static std::uniform_int_distribution<int>
        cross_pt_dist(0,population[0].path.size() - 1);

    int cross_pt1;
    int cross_pt2;

    for (auto &ind : population){
        output_path(ind);
        if (std::rand() % 100 * 0.01 < mut_rate){
            cross_pt1 = cross_pt_dist(gen);
            cross_pt2 = cross_pt_dist(gen);
            std::swap(ind.path[cross_pt1],
                      ind.path[cross_pt2]);
        }

    }
}
<|endoftext|>


<commit_before>#include "GameProcess.h"
#include "Object.h"
#include "Engine.h"
#include "World.h"
#include "App.h"
#include "ToolsCamera.h"
#include "ControlsApp.h"
#include "MathLib.h"
#include "Game.h"
#include "Editor.h"
#include "Input.h"
#include "BlueRayUtils.h"
#include "World.h"
#include "Action.h"
#include "FPSRoleLocal.h"
#include "StarControl.h"
#include "RayControl.h"
#include "CameraBase.h"
#include "ActorBase.h"
#include "sys/SysControl.h"
#include "FileSystem.h"
#include "RenderManager.h"
#include "Texture.h"

using namespace MathLib;

CGameProcess::CGameProcess(void)
{

}

CGameProcess::~CGameProcess(void)
{

}
int CGameProcess::Init()
{
	g_Engine.pFileSystem->CacheFilesFormExt("char");
	g_Engine.pFileSystem->CacheFilesFormExt("node");
	g_Engine.pFileSystem->CacheFilesFormExt("smesh");
	g_Engine.pFileSystem->CacheFilesFormExt("sanim");

	g_Engine.pWorld->LoadWorld("data/scene/terrain/test/test.world");
	//g_Engine.pWorld->LoadWorld("data/scene/terrain/cj/cj.world");
	g_Engine.pControls->SetKeyPressFunc(KeyPress);
	g_Engine.pControls->SetKeyReleaseFunc(KeyRelease);

	m_pRole = new CFPSRoleLocal();
	m_pRole->Init(10001, "data/role/hero/FpsRole/fps.char");

	m_pRole->SetActorPosition(vec3(0, 0, 0));	//设置角色初始位置。以门处作为原点，三维坐标系vec3是向量
	m_pSkillSystem = new CSkillSystem(this);
	m_pCameraBase = new CCameraBase();
	m_pCameraBase->SetEnabled(1);
	g_pSysControl->SetMouseGrab(1);

	m_pStarControl = new CStarControl();
	m_pRayControl = new CRayControl();

	return 1;
}

int CGameProcess::ShutDown()			//关闭游戏进程
{
	delete m_pRole;
	delete m_pSkillSystem;
	delete m_pCameraBase;
	delete m_pStarControl;
	delete m_pRayControl;

	DelAllListen();
	return 0;
}

int CGameProcess::Update()
{
	float ifps = g_Engine.pGame->GetIFps();

	if (g_Engine.pInput->IsKeyDown('1'))
	{
		CAction* pAction = m_pRole->OrceAction("attack02");
		if (pAction)
		{
			pAction->SetupSkillThrow(vec3_zero, -1.0f, 2.0f);
			m_pRole->StopMove();
		}
	}
	else if (g_Engine.pInput->IsKeyDown('2'))
	{
		CAction* pAction = m_pRole->OrceAction("skill01");
		if (pAction)
		{
			m_pRole->StopMove();
		}
	}
	else if (g_Engine.pInput->IsKeyDown('3'))
	{
		CAction* pAction = m_pRole->OrceAction("skill02");
		if (pAction)
		{
			m_pRole->StopMove();
			CRoleBase* pTarget = NULL;
			for (int i = 0; i < 20; i++)
			{
				float l = (m_vAIList[i]->GetPosition() - m_pRole->GetPosition()).length();
				if (l > 5.0f && l < 15.0f)
				{
					pTarget = m_vAIList[i];
					break;
				}
			}
			if (pTarget)
			{
				CVector<int> vTarget;
				vTarget.Append(pTarget->GetRoleID());
				pAction->SetupSkillBulletTarget(vTarget);
				m_pRole->SetDirection((pTarget->GetPosition() - m_pRole->GetPosition()).normalize(), 1);
			}
		}
	}
	else if (g_Engine.pInput->IsKeyDown('4'))//多发子弹
	{
		CAction* pAction = m_pRole->OrceAction("skill02");
		if (pAction)
		{
			m_pRole->StopMove();
			CVector<int> vTarget;
			for (int i = 0; i < 20; i++)
			{
				float l = (m_vAIList[i]->GetPosition() - m_pRole->GetPosition()).length();
				if (l > 5.0f && l < 20.0f)
				{
					vTarget.Append(m_vAIList[i]->GetRoleID());
				}
			}
			if (!vTarget.Empty())
			{
				pAction->SetupSkillBulletTarget(vTarget);
			}
		}
	}
	else if (g_Engine.pInput->IsKeyDown('5'))
	{
		CAction* pAction = m_pRole->OrceAction("skill03");
		if (pAction)
		{
			m_pRole->StopMove();
			CVector<vec3> vPos;
			pAction->SetupSkillTargetPoint(vPos);
		}
	}
	else if (g_Engine.pInput->IsKeyDown('6'))
	{
		CAction* pAction = m_pRole->OrceAction("skill06");
		if (pAction)
		{
			m_pRole->StopMove();
			CVector<vec3> vPos;
			for (int i = 0; i < 20; i++)
			{
				float l = (m_vAIList[i]->GetPosition() - m_pRole->GetPosition()).length();
				if (l > 5.0f && l < 20.0f)
					vPos.Append(m_vAIList[i]->GetPosition());

			}
			pAction->SetupSkillTargetPoint(vPos);
		}
	}
	else if (g_Engine.pInput->IsKeyDown('7'))
	{
		CAction* pAction = m_pRole->OrceAction("skill05");
		if (pAction)
		{
			m_pRole->StopMove();
			CVector<int> vTarget;
			for (int i = 0; i < 20; i++)
			{
				float l = (m_vAIList[i]->GetPosition() - m_pRole->GetPosition()).length();
				if (l > 5.0f && l < 20.0f)
					vTarget.Append(m_vAIList[i]->GetRoleID());
			}
			if (!vTarget.Empty())
			{
				pAction->SetupSkillBulletTarget(vTarget);
			}
		}
	}
	else if (g_Engine.pInput->IsKeyDown('8'))
	{
		CAction* pAction = m_pRole->OrceAction("skill07");
		if (pAction)
		{
			m_pRole->StopMove();
			CVector<vec3> vPos;
			for (int i = 0; i < 20; i++)
			{
				float l = (m_vAIList[i]->GetPosition() - m_pRole->GetPosition()).length();
				if (l > 5.0f && l < 20.0f)
					vPos.Append(m_vAIList[i]->GetPosition());
			}
			pAction->SetupSkillBulletPosition(vPos);
		}
	}
	else if (g_Engine.pInput->IsKeyDown('9'))
	{
		CAction* pAction = m_pRole->OrceAction("skill08");
		if (pAction)
		{
			m_pRole->StopMove();
			pAction->SetupSkillBulletDirection(1);
		}

	}
	else if (g_Engine.pInput->IsKeyUp(CInput::KEY_ESC))
	{
		g_Engine.pApp->Exit();
	}
	if(g_Engine.pInput->IsLBDown())
	{
		vec3 p0,p1;
		BlueRay::GetPlayerMouseDirection(p0,p1);
		vec3 vRetPoint,vRetNormal;
		int nS = -1;
		g_Engine.pWorld->GetIntersection(p0,p1,CBRObject::MASK_SCENE,vRetPoint,vRetNormal,nS);

		if(-1 != nS)
		{
			m_pRole->MoveToPath(vRetPoint);
		}
	}
	for(int i = 0;i < 20;i++)
	{
		if(!m_vAIList[i]->IsMoveing())
		{
			vec3 vPos = vec3(g_Engine.pGame->GetRandomFloat(-20.0f,20.0f),g_Engine.pGame->GetRandomFloat(-20.0f,20.0f),1.1f);
			m_vAIList[i]->MoveToPath(vPos);
		}

		m_vAIList[i]->Update(ifps);
	}
	if (g_Engine.pInput->IsLBDown())	//shubiaozuojian
	{
		g_pSysControl->SetMouseGrab(1);
		m_pStarControl->Click();
	}
	if (g_Engine.pInput->IsKeyDown(CInput::KEY_ESC))
	{
		g_pSysControl->SetMouseGrab(0);
	}
	m_pCameraBase->SetMouseControls(g_pSysControl->GetMouseGrab());
	m_pCameraBase->Update(ifps);

	m_pRole->SetActorDirection(m_pCameraBase->GetViewDirection());
	m_pRole->UpdateActor(ifps);
	m_pCameraBase->SetPosition(m_pRole->GetActorPosition() + m_pRole->GetCameraOffset());

	vec3 x = m_pCameraBase->GetModelview().getRow3(0);
	vec3 y = m_pCameraBase->GetModelview().getRow3(1);
	vec3 z = m_pCameraBase->GetModelview().getRow3(2);

	mat4 r = mat4_identity;

	r.setColumn3(0, -x);	//
	r.setColumn3(1, z);		//
	r.setColumn3(2, y);		//

	m_pRole->UpdateTransform(r);

	m_pRole->Update(ifps);
	m_pSkillSystem->Update(ifps);

	m_pStarControl->Update(m_pCameraBase->GetPosition(), m_pCameraBase->GetDirection());

	return 1;
}

int CGameProcess::Render()
{
	////test
	//m_pTestHero->Render();
	//g_Engine.pVisualizer->RenderLine3D(vec3(0.0f,0.0f,1.0f), vec3(10.0f,0.0f,1.0f), vec4(1.0f,0.0f,0.0f,1.0f));
	//g_Engine.pVisualizer->RenderLine3D(vec3(0.0f,0.0f,1.0f), vec3(0.0f,10.0f,1.0f), vec4(0.0f,1.0f,0.0f,1.0f));
	//g_Engine.pVisualizer->RenderLine3D(vec3(0.0f,0.0f,1.0f), vec3(0.0f,0.0f,11.0f), vec4(0.0f,0.0f,1.0f,1.0f));
	////~test

	return 1;
}

int CGameProcess::KeyPress(unsigned int nKey)
{
	if (nKey == 'w')
	{
		//g_Engine.pControls->SetState(CControls::STATE_RESTORE, 1);
		g_Engine.pControls->SetState(CControls::STATE_FORWARD, 1);
	}
	else if (nKey == 's')
	{
		g_Engine.pControls->SetState(CControls::STATE_RESTORE, 1);
		g_Engine.pControls->SetState(CControls::STATE_BACKWARD, 1);
	}
	else if (nKey == 'a')
	{
		g_Engine.pControls->SetState(CControls::STATE_RESTORE, 1);
		g_Engine.pControls->SetState(CControls::STATE_MOVE_LEFT, 1);
	}
	else if (nKey == 'd')
	{
		g_Engine.pControls->SetState(CControls::STATE_RESTORE, 1);
		g_Engine.pControls->SetState(CControls::STATE_MOVE_RIGHT, 1);
	}
	else if (nKey == 'q')
	{
		g_Engine.pControls->SetState(CControls::STATE_JUMP, 1);
	}
	else if (nKey == 'e')
	{
		g_Engine.pControls->SetState(CControls::STATE_CROUCH, 1);
	}
	else if (nKey == CApp::KEY_SHIFT)
	{
		g_Engine.pControls->SetState(CControls::STATE_RUN, 1);
	}
	return 1;

}
int CGameProcess::KeyRelease(unsigned int nKey)
{
	if (nKey == 'w')
	{
		g_Engine.pControls->SetState(CControls::STATE_RESTORE, 0);
		g_Engine.pControls->SetState(CControls::STATE_FORWARD, 0);
	}
	else if (nKey == 's')
	{
		g_Engine.pControls->SetState(CControls::STATE_RESTORE, 0);
		g_Engine.pControls->SetState(CControls::STATE_BACKWARD, 0);
	}
	else if (nKey == 'a')
	{
		g_Engine.pControls->SetState(CControls::STATE_RESTORE, 0);
		g_Engine.pControls->SetState(CControls::STATE_MOVE_LEFT, 0);
	}
	else if (nKey == 'd')
	{
		g_Engine.pControls->SetState(CControls::STATE_RESTORE, 0);
		g_Engine.pControls->SetState(CControls::STATE_MOVE_RIGHT, 0);
	}
	else if (nKey == 'q')
	{
		g_Engine.pControls->SetState(CControls::STATE_JUMP, 0);
	}
	else if (nKey == 'e')
	{
		g_Engine.pControls->SetState(CControls::STATE_CROUCH, 0);
	}
	else if (nKey == CApp::KEY_SHIFT)
	{
		g_Engine.pControls->SetState(CControls::STATE_RUN, 0);
	}

	return 1;
}

CRoleBase* CGameProcess::GetRole(int nID)
{
	for(int i = 0;i < 20;i++)
	{
		if(m_vAIList[i]->GetRoleID() == nID)
		{
			return m_vAIList[i];
		}
	}

	return NULL;
}<commit_msg>Signed-off-by: mrlitong <litongtongxue@gmail.com><commit_after>#include "GameProcess.h"
#include "Object.h"
#include "Engine.h"
#include "World.h"
#include "App.h"
#include "ToolsCamera.h"
#include "ControlsApp.h"
#include "MathLib.h"
#include "Game.h"
#include "Editor.h"
#include "Input.h"
#include "BlueRayUtils.h"
#include "World.h"
#include "Action.h"
#include "FPSRoleLocal.h"
#include "StarControl.h"
#include "RayControl.h"
#include "CameraBase.h"
#include "ActorBase.h"
#include "sys/SysControl.h"
#include "FileSystem.h"
#include "RenderManager.h"
#include "Texture.h"

using namespace MathLib;

CGameProcess::CGameProcess(void)
{

}

CGameProcess::~CGameProcess(void)
{

}
int CGameProcess::Init()
{
	g_Engine.pFileSystem->CacheFilesFormExt("char");
	g_Engine.pFileSystem->CacheFilesFormExt("node");
	g_Engine.pFileSystem->CacheFilesFormExt("smesh");
	g_Engine.pFileSystem->CacheFilesFormExt("sanim");

	g_Engine.pWorld->LoadWorld("data/scene/terrain/test/test.world");
	//g_Engine.pWorld->LoadWorld("data/scene/terrain/cj/cj.world");
	g_Engine.pControls->SetKeyPressFunc(KeyPress);
	g_Engine.pControls->SetKeyReleaseFunc(KeyRelease);

	m_pRole = new CFPSRoleLocal();
	m_pRole->Init(10001, "data/role/hero/FpsRole/fps.char");

	m_pRole->SetActorPosition(vec3(0, 0, 0));	//设置角色初始位置。以门处作为原点，三维坐标系vec3是向量
	m_pSkillSystem = new CSkillSystem(this);
	m_pCameraBase = new CCameraBase();
	m_pCameraBase->SetEnabled(1);
	g_pSysControl->SetMouseGrab(1);

	m_pStarControl = new CStarControl();
	m_pRayControl = new CRayControl();

	return 1;
}

int CGameProcess::ShutDown()			//关闭游戏进程
{
	delete m_pRole;
	delete m_pSkillSystem;
	delete m_pCameraBase;
	delete m_pStarControl;
	delete m_pRayControl;

	DelAllListen();
	return 0;
}

int CGameProcess::Update()
{
	float ifps = g_Engine.pGame->GetIFps();

	if (g_Engine.pInput->IsKeyDown('1'))
	{
		CAction* pAction = m_pRole->OrceAction("attack02");
		if (pAction)
		{
			pAction->SetupSkillThrow(vec3_zero, -1.0f, 2.0f);
			m_pRole->StopMove();
		}
	}
	else if (g_Engine.pInput->IsKeyDown('2'))
	{
		CAction* pAction = m_pRole->OrceAction("skill01");
		if (pAction)
		{
			m_pRole->StopMove();
		}
	}
	else if (g_Engine.pInput->IsKeyDown('3'))
	{
		CAction* pAction = m_pRole->OrceAction("skill02");
		if (pAction)
		{
			m_pRole->StopMove();
			CRoleBase* pTarget = NULL;
			for (int i = 0; i < 20; i++)
			{
				float l = (m_vAIList[i]->GetPosition() - m_pRole->GetPosition()).length();
				if (l > 5.0f && l < 15.0f)
				{
					pTarget = m_vAIList[i];
					break;
				}
			}
			if (pTarget)
			{
				CVector<int> vTarget;
				vTarget.Append(pTarget->GetRoleID());
				pAction->SetupSkillBulletTarget(vTarget);
				m_pRole->SetDirection((pTarget->GetPosition() - m_pRole->GetPosition()).normalize(), 1);
			}
		}
	}
	else if (g_Engine.pInput->IsKeyDown('4'))//多发子弹
	{
		CAction* pAction = m_pRole->OrceAction("skill02");
		if (pAction)
		{
			m_pRole->StopMove();
			CVector<int> vTarget;
			for (int i = 0; i < 20; i++)
			{
				float l = (m_vAIList[i]->GetPosition() - m_pRole->GetPosition()).length();
				if (l > 5.0f && l < 20.0f)
				{
					vTarget.Append(m_vAIList[i]->GetRoleID());
				}
			}
			if (!vTarget.Empty())
			{
				pAction->SetupSkillBulletTarget(vTarget);
			}
		}
	}
	else if (g_Engine.pInput->IsKeyDown('5'))
	{
		CAction* pAction = m_pRole->OrceAction("skill03");
		if (pAction)
		{
			m_pRole->StopMove();
			CVector<vec3> vPos;
			pAction->SetupSkillTargetPoint(vPos);
		}
	}
	else if (g_Engine.pInput->IsKeyDown('6'))
	{
		CAction* pAction = m_pRole->OrceAction("skill06");
		if (pAction)
		{
			m_pRole->StopMove();
			CVector<vec3> vPos;
			for (int i = 0; i < 20; i++)
			{
				float l = (m_vAIList[i]->GetPosition() - m_pRole->GetPosition()).length();
				if (l > 5.0f && l < 20.0f)
					vPos.Append(m_vAIList[i]->GetPosition());

			}
			pAction->SetupSkillTargetPoint(vPos);
		}
	}
	else if (g_Engine.pInput->IsKeyDown('7'))
	{
		CAction* pAction = m_pRole->OrceAction("skill05");
		if (pAction)
		{
			m_pRole->StopMove();
			CVector<int> vTarget;
			for (int i = 0; i < 20; i++)
			{
				float l = (m_vAIList[i]->GetPosition() - m_pRole->GetPosition()).length();
				if (l > 5.0f && l < 20.0f)
					vTarget.Append(m_vAIList[i]->GetRoleID());
			}
			if (!vTarget.Empty())
			{
				pAction->SetupSkillBulletTarget(vTarget);
			}
		}
	}
	else if (g_Engine.pInput->IsKeyDown('8'))
	{
		CAction* pAction = m_pRole->OrceAction("skill07");
		if (pAction)
		{
			m_pRole->StopMove();
			CVector<vec3> vPos;
			for (int i = 0; i < 20; i++)
			{
				float l = (m_vAIList[i]->GetPosition() - m_pRole->GetPosition()).length();
				if (l > 5.0f && l < 20.0f)
					vPos.Append(m_vAIList[i]->GetPosition());
			}
			pAction->SetupSkillBulletPosition(vPos);
		}
	}
	else if (g_Engine.pInput->IsKeyDown('9'))
	{
		CAction* pAction = m_pRole->OrceAction("skill08");
		if (pAction)
		{
			m_pRole->StopMove();
			pAction->SetupSkillBulletDirection(1);
		}

	}
	else if (g_Engine.pInput->IsKeyUp(CInput::KEY_ESC))
	{
		g_Engine.pApp->Exit();
	}
	if(g_Engine.pInput->IsLBDown())
	{
		vec3 p0,p1;
		BlueRay::GetPlayerMouseDirection(p0,p1);
		vec3 vRetPoint,vRetNormal;
		int nS = -1;
		g_Engine.pWorld->GetIntersection(p0,p1,CBRObject::MASK_SCENE,vRetPoint,vRetNormal,nS);

		if(-1 != nS)
		{
			m_pRole->MoveToPath(vRetPoint);
		}
	}
	for(int i = 0;i < 20;i++)
	{
		if(!m_vAIList[i]->IsMoveing())
		{
			vec3 vPos = vec3(g_Engine.pGame->GetRandomFloat(-20.0f,20.0f),g_Engine.pGame->GetRandomFloat(-20.0f,20.0f),1.1f);
			m_vAIList[i]->MoveToPath(vPos);
		}

		m_vAIList[i]->Update(ifps);
	}
	if (g_Engine.pInput->IsLBDown())	//shubiaozuojian
	{
		g_pSysControl->SetMouseGrab(1);
		m_pStarControl->Click();
	}
	if (g_Engine.pInput->IsKeyDown(CInput::KEY_ESC))
	{
		g_pSysControl->SetMouseGrab(0);
	}
	m_pCameraBase->SetMouseControls(g_pSysControl->GetMouseGrab());
	m_pCameraBase->Update(ifps);

	m_pRole->SetActorDirection(m_pCameraBase->GetViewDirection());
	m_pRole->UpdateActor(ifps);
	m_pCameraBase->SetPosition(m_pRole->GetActorPosition() + m_pRole->GetCameraOffset());

	vec3 x = m_pCameraBase->GetModelview().getRow3(0);
	vec3 y = m_pCameraBase->GetModelview().getRow3(1);
	vec3 z = m_pCameraBase->GetModelview().getRow3(2);

	mat4 r = mat4_identity;

	r.setColumn3(0, -x);	//
	r.setColumn3(1, z);		//
	r.setColumn3(2, y);		//

	m_pRole->UpdateTransform(r);

	m_pRole->Update(ifps);
	m_pSkillSystem->Update(ifps);

	m_pStarControl->Update(m_pCameraBase->GetPosition(), m_pCameraBase->GetDirection());

	return 1;
}

int CGameProcess::Render()
{
	////test
	//m_pTestHero->Render();
	//g_Engine.pVisualizer->RenderLine3D(vec3(0.0f,0.0f,1.0f), vec3(10.0f,0.0f,1.0f), vec4(1.0f,0.0f,0.0f,1.0f));
	//g_Engine.pVisualizer->RenderLine3D(vec3(0.0f,0.0f,1.0f), vec3(0.0f,10.0f,1.0f), vec4(0.0f,1.0f,0.0f,1.0f));
	//g_Engine.pVisualizer->RenderLine3D(vec3(0.0f,0.0f,1.0f), vec3(0.0f,0.0f,11.0f), vec4(0.0f,0.0f,1.0f,1.0f));
	////~test

	return 1;
}

int CGameProcess::KeyPress(unsigned int nKey)
{
	if (nKey == 'w')
	{
		//g_Engine.pControls->SetState(CControls::STATE_RESTORE, 1);
		g_Engine.pControls->SetState(CControls::STATE_FORWARD, 1);
	}
	else if (nKey == 's')
	{
		g_Engine.pControls->SetState(CControls::STATE_RESTORE, 1);
		g_Engine.pControls->SetState(CControls::STATE_BACKWARD, 1);
	}
	else if (nKey == 'a')
	{
		g_Engine.pControls->SetState(CControls::STATE_RESTORE, 1);
		g_Engine.pControls->SetState(CControls::STATE_MOVE_LEFT, 1);
	}
	else if (nKey == 'd')
	{
		g_Engine.pControls->SetState(CControls::STATE_RESTORE, 1);
		g_Engine.pControls->SetState(CControls::STATE_MOVE_RIGHT, 1);
	}
	else if (nKey == 'q')
	{
		g_Engine.pControls->SetState(CControls::STATE_JUMP, 1);
	}
	else if (nKey == 'e')
	{
		g_Engine.pControls->SetState(CControls::STATE_CROUCH, 1);
	}
	else if (nKey == CApp::KEY_SHIFT)
	{
		g_Engine.pControls->SetState(CControls::STATE_RUN, 1);
	}
	return 1;

}
int CGameProcess::KeyRelease(unsigned int nKey)
{
	if (nKey == 'w')
	{
		g_Engine.pControls->SetState(CControls::STATE_RESTORE, 0);
		g_Engine.pControls->SetState(CControls::STATE_FORWARD, 0);
	}
	else if (nKey == 's')
	{
		g_Engine.pControls->SetState(CControls::STATE_RESTORE, 0);
		g_Engine.pControls->SetState(CControls::STATE_BACKWARD, 0);
	}
	else if (nKey == 'a')
	{
		g_Engine.pControls->SetState(CControls::STATE_RESTORE, 0);
		g_Engine.pControls->SetState(CControls::STATE_MOVE_LEFT, 0);
	}
	else if (nKey == 'd')
	{
		g_Engine.pControls->SetState(CControls::STATE_RESTORE, 0);
		g_Engine.pControls->SetState(CControls::STATE_MOVE_RIGHT, 0);
	}
	else if (nKey == 'q')
	{
		g_Engine.pControls->SetState(CControls::STATE_JUMP, 0);
	}
	else if (nKey == 'e')
	{
		g_Engine.pControls->SetState(CControls::STATE_CROUCH, 0);
	}
	else if (nKey == CApp::KEY_SHIFT)
	{
		g_Engine.pControls->SetState(CControls::STATE_RUN, 0);
	}

	return 1;
}

CRoleBase* CGameProcess::GetRole(int nID)
{
	for(int i = 0;i < 20;i++)
	{
		if(m_vAIList[i]->GetRoleID() == nID)
		{
			return m_vAIList[i];
		}
	}

	return NULL;
}
CRoleBase* CGameProcess::GetRoleFormIndex(int nIndex)
{
	//return m_vAIList[nIndex];
	return NULL;
}
<|endoftext|>


<commit_before>/*

  AVLTree.hpp

*/

#ifndef __AVL_TREE__HPP__
#define __AVL_TREE__HPP__

#if !defined(__cplusplus) || (__cplusplus < 201103L)
#error "C++11 support is required."
#endif

#include <cstdint>
#include <utility>
#include <iterator>
#include <functional>
#include <iostream>

template<class key_type,
         class mapped_type,
         class key_compare = std::less<key_type>
         >
class AVLTree {

	// Internal data structure.
	struct Node {

		std::pair<const key_type, mapped_type> Mapping;
		Node*  Parent;
		Node*  Left;
		Node*  Right;
		size_t Height;

		// Construct by providing arguments.
		template<class K, class D>
		Node(K&& InitKey,
		     D&& InitData,
		     Node* InitParent,
		     Node* InitLeft,
		     Node* InitRight,
		     size_t InitHeight):
			Mapping( std::forward<K>(InitKey), std::forward<D>(InitData) ),
			Parent( InitParent ),
			Left( InitLeft ),
			Right( InitRight ),
			Height( InitHeight ) {
			;
			}

		// Construct a new tree from an existing tree.
		Node(const Node* Tree, Node* InitParent):
			Mapping( Tree->Mapping ),
			Parent( InitParent ),
			Left( (Tree->Left != nullptr) ? (new Node(Tree->Left, this)) : nullptr ),
			Right( (Tree->Right != nullptr) ? (new Node(Tree->Right, this)) : nullptr ),
			Height( Tree->Height ) {
			;
			}

		~Node() {

			delete Left;
			delete Right;

			}

		static size_t HeightOf(Node* Tree) noexcept {

			return (Tree != nullptr) ? (Tree->Height) : 0;

			};

		template<class K, class D>
		static std::pair<Node*, bool> Insert(Node** PtrToThisNode, Node* Parent, K&& KeyToInsert, D&& DataToInsert, key_compare& );

		// Returns new root of child tree.
		static Node* RightRotate(Node* ) noexcept;
		static Node* LeftRotate(Node* ) noexcept;
		static Node* Begin(Node* ) noexcept;
		static Node* Find(Node* Tree, const key_type& KeyToFind, key_compare& );

		static void Dump(Node* CurrentNode) {

			if( CurrentNode == nullptr ){

				std::cout << "()";
				return;

				}

			std::cout << "((" << (CurrentNode->Mapping).first << ": " << (CurrentNode->Mapping).second << "), ";
			Dump(CurrentNode->Left);
			std::cout << ", ";
			Dump(CurrentNode->Right);
			std::cout << ')';

			}

		};

	Node* Root;
	key_compare Comp;

	// Public stuff.
	public:

	class iterator : public std::iterator<std::bidirectional_iterator_tag, decltype(Node::Mapping)> {

		Node* CurrentNode;

		// This can only be used in member functions of AVLTree.
		iterator(Node* InitPtr):
			CurrentNode( InitPtr ) {
			;
			}

		// It enables AVLTree to call the private constructor.
		friend class AVLTree;

		public:

		iterator():
			CurrentNode( nullptr ) {
			;
			}

		iterator(const iterator& ) = default;
		~iterator() = default;
		iterator& operator=(const iterator& ) = default;

		decltype(Node::Mapping)& operator*(void) const noexcept {

			return (CurrentNode->Mapping);

			}

		decltype(Node::Mapping)* operator->(void) const noexcept {

			return &(CurrentNode->Mapping);

			}

		iterator& operator++(void);
		iterator& operator--(void);

		iterator operator++(int) {

			iterator It(*this);

			++(*this);

			return It;

			}

		iterator operator--(int) {

			iterator It(*this);

			--(*this);

			return It;

			}

		bool operator==(const iterator& RHS) const noexcept {

			return ( (this->CurrentNode) == RHS.CurrentNode );

			}

		bool operator!=(const iterator& RHS) const noexcept {

			return ( (this->CurrentNode) != RHS.CurrentNode );

			}

		};

	// Const iterator.
	class const_iterator : public std::iterator<std::bidirectional_iterator_tag, const decltype(Node::Mapping)> {

		iterator It;

		public:

		const_iterator():
			It( nullptr ) {
			;
			}

		const_iterator(const iterator& RHS):
			It( RHS ) {
			;
			}

		const_iterator(const const_iterator& ) = default;
		~const_iterator() = default;
		const_iterator& operator=(const const_iterator& ) = default;

		const decltype(Node::Mapping)& operator*(void) const noexcept {

			return *It;

			}

		const decltype(Node::Mapping)* operator->(void) const noexcept {

			return &(*It);

			}

		const_iterator& operator++(void) {

			++It;

			return (*this);

			}

		const_iterator& operator--(void) {

			--It;

			return (*this);

			}

		const_iterator operator++(int) {

			return (It++);

			}

		const_iterator operator--(int) {

			return (It--);

			}

		bool operator==(const const_iterator& RHS) const noexcept {

			return ( It == RHS.It );

			}

		bool operator!=(const const_iterator& RHS) const noexcept {

			return ( It != RHS.It );

			}

		};

	AVLTree():
		Root(nullptr),
		Comp() {
		;
		}

	AVLTree(const AVLTree& RHS):
		Root( (RHS.Root != nullptr) ? new Node(RHS.Root, nullptr) : 0 ),
		Comp( RHS.Comp ) {
		;
		}

	AVLTree(AVLTree&& RHS):
		Root( RHS.Root ),
		Comp( std::move(RHS.Comp) ){

		RHS.Root = nullptr;

		}

	~AVLTree() {

		delete Root;

		}

	iterator begin(void) {

		return Node::Begin(Root);

		}

	iterator end(void) {

		return nullptr;

		}

	const_iterator begin(void) const {

		return iterator(Node::Begin(Root));

		}

	const_iterator end(void) const {

		return iterator(nullptr);

		}

	iterator find(const key_type& KeyToFind) {

		return Node::Find(Root, KeyToFind, Comp);

		}

	const_iterator find(const key_type& KeyToFind) const {

		return iterator(Node::Find(Root, KeyToFind, Comp));

		}

	template<class K, class D>
	std::pair<iterator, bool> insert(K&& KeyToInsert, D&& DataToInsert);

	AVLTree& operator=(const AVLTree& RHS) {

		if( this != &RHS ) {

			delete Root;

			if( RHS.Root != nullptr )
				Root = new Node(RHS.Root, nullptr);
			else
				Root = nullptr;

			Comp = RHS.Comp;

			}

		return *this;

		}

	template<class K>
	mapped_type& operator[](K&& Index) {

		auto Result = insert(std::forward<K>(Index), mapped_type());
		return (Result.first)->second;

		}

	AVLTree& operator=(AVLTree&& RHS) {

		if( this != &RHS ) {

			delete this->Root;
			this->Root = RHS.Root;
			RHS.Root = nullptr;
			Comp = std::move( RHS.Comp );

			}

		return *this;

		}

	size_t GetHeight(void) const noexcept {

		if( Root == nullptr )
			return 0;

		return Root->Height;

		}

	void Dump(void) const {

		Node::Dump(Root);
		std::cout << std::endl;

		}

	};

template<class key_type,
         class mapped_type,
         class key_compare
         >
auto AVLTree<key_type, mapped_type, key_compare>::iterator::operator++(void) -> iterator& {

	if( CurrentNode == nullptr )
		return (*this);

	// TODO: Find the next node in an in-order manner.

	return (*this);

	}

template<class key_type,
         class mapped_type,
         class key_compare
         >
auto AVLTree<key_type, mapped_type, key_compare>::iterator::operator--(void) -> iterator& {

	if( CurrentNode == nullptr )
		return (*this);

	// TODO: Find the previous node in an in-order manner.

	return (*this);

	}

template<class key_type,
         class mapped_type,
         class key_compare
         >
auto AVLTree<key_type, mapped_type, key_compare>::Node::Begin(Node* CurrentNode) noexcept -> Node* {

		if( CurrentNode == nullptr )
			return CurrentNode;

		Node* Next;

		while( (Next = CurrentNode->Left) != nullptr )
			CurrentNode = Next;

		return CurrentNode;

		}

template<class key_type,
         class mapped_type,
         class key_compare
         >
auto AVLTree<key_type, mapped_type, key_compare>::Node::Find(Node* Tree, const key_type& KeyToFind, key_compare& Comp) -> Node* {

	Node* CurrentNode = Tree;

	// TODO: Use Comp to find where it located.
	//       You may want to take a look of the implementation of Insert.

	return CurrentNode;

	}

template<class key_type,
         class mapped_type,
         class key_compare
         >
template<class K, class D>
auto AVLTree<key_type, mapped_type, key_compare>::insert(K&& KeyToInsert, D&& DataToInsert) -> std::pair<iterator, bool> {

	auto Result = Node::Insert(&Root,
	                           nullptr,
	                           std::forward<K>(KeyToInsert),
	                           std::forward<D>(DataToInsert),
	                           Comp);

	return std::pair<iterator, bool>(Result.first, Result.second);

	}

template<class key_type,
         class mapped_type,
         class key_compare
         >
template<class K, class D>
auto AVLTree<key_type, mapped_type, key_compare>::Node::Insert(Node** PtrToThisNode, Node* Parent, K&& KeyToInsert, D&& DataToInsert, key_compare& Comp) -> std::pair<Node*, bool> {

	Node* ThisNode = *PtrToThisNode;

	// We found where to insert the data.
	if( ThisNode == nullptr ) {

		ThisNode = new Node(std::forward<K>(KeyToInsert),
		                    std::forward<D>(DataToInsert),
		                    Parent,
		                    nullptr,
		                    nullptr,
		                    1
		                    );

		// Fix parent's pointer to the new node and return where it's inserted.
		return std::pair<Node*, bool>(*PtrToThisNode = ThisNode, true);

		}

	std::pair<Node*, bool> InsertResult;

	// If the data shall be placed in left child.
	if( Comp(KeyToInsert, (ThisNode->Mapping).first) ) {

		InsertResult = Insert(&(ThisNode->Left),
		                      ThisNode,
		                      std::forward<K>(KeyToInsert),
		                      std::forward<D>(DataToInsert),
		                      Comp);

		size_t LeftHeight = Node::HeightOf(ThisNode->Left);
		size_t RightHeight = Node::HeightOf(ThisNode->Right);

		// If left child is higher.
		if( LeftHeight >= RightHeight + 2 ) {

			Node* LeftNode = ThisNode->Left;

			if( Node::HeightOf(LeftNode->Left) < Node::HeightOf(LeftNode->Right) )
				ThisNode->Left = LeftNode = LeftRotate(LeftNode);

			*PtrToThisNode = ThisNode = RightRotate(ThisNode);

			}
		// Already balanced. No need to rotate.
		else
			ThisNode->Height = 1 + std::max(LeftHeight, RightHeight);

		}
	// If the data shall be placed in right tree.
	else if( Comp((ThisNode->Mapping).first, KeyToInsert) ) {

		InsertResult = Insert(&(ThisNode->Right),
		                      ThisNode,
		                      std::forward<K>(KeyToInsert),
		                      std::forward<D>(DataToInsert),
		                      Comp);

		size_t LeftHeight = Node::HeightOf(ThisNode->Left);
		size_t RightHeight = Node::HeightOf(ThisNode->Right);

		// If right child is higher.
		if( RightHeight >= LeftHeight + 2 ){

			Node* RightNode = ThisNode->Right;

			if( Node::HeightOf(RightNode->Left) > Node::HeightOf(RightNode->Right) )
				ThisNode->Right = RightNode = RightRotate(RightNode);

			*PtrToThisNode = ThisNode = LeftRotate(ThisNode);

			}
		// Already balanced. No need to rotate.
		else
			ThisNode->Height = 1 + std::max(LeftHeight, RightHeight);

		}
	// Found.
	else {

		InsertResult.first = ThisNode;
		InsertResult.second = false;

		}

	return InsertResult;

	}

template<class key_type,
         class mapped_type,
         class key_compare
         >
auto AVLTree<key_type, mapped_type, key_compare>::Node::RightRotate(Node* ThisNode) noexcept -> Node* {

	// TODO: Right rotate the tree and return the new root.
	//       The height of modified trees should also be fixed accordingly.

	return ThisNode;

	}

template<class key_type,
         class mapped_type,
         class key_compare
         >
auto AVLTree<key_type, mapped_type, key_compare>::Node::LeftRotate(Node* ThisNode) noexcept -> Node* {

	// TODO: Left rotate the tree and return the new root.
	//       The height of modified trees should also be fixed accordingly.

	return ThisNode;

	}

#endif
<commit_msg>Finish HW6<commit_after>/*

  AVLTree.hpp

*/

#ifndef __AVL_TREE__HPP__
#define __AVL_TREE__HPP__

#if !defined(__cplusplus) || (__cplusplus < 201103L)
#error "C++11 support is required."
#endif

#include <cstdint>
#include <utility>
#include <iterator>
#include <functional>
#include <iostream>

template<class key_type,
         class mapped_type,
         class key_compare = std::less<key_type>
         >
class AVLTree {

	// Internal data structure.
	struct Node {

		std::pair<const key_type, mapped_type> Mapping;
		Node*  Parent;
		Node*  Left;
		Node*  Right;
		size_t Height;

		// Construct by providing arguments.
		template<class K, class D>
		Node(K&& InitKey,
		     D&& InitData,
		     Node* InitParent,
		     Node* InitLeft,
		     Node* InitRight,
		     size_t InitHeight):
			Mapping( std::forward<K>(InitKey), std::forward<D>(InitData) ),
			Parent( InitParent ),
			Left( InitLeft ),
			Right( InitRight ),
			Height( InitHeight ) {
			;
			}

		// Construct a new tree from an existing tree.
		Node(const Node* Tree, Node* InitParent):
			Mapping( Tree->Mapping ),
			Parent( InitParent ),
			Left( (Tree->Left != nullptr) ? (new Node(Tree->Left, this)) : nullptr ),
			Right( (Tree->Right != nullptr) ? (new Node(Tree->Right, this)) : nullptr ),
			Height( Tree->Height ) {
			;
			}

		~Node() {

			delete Left;
			delete Right;

			}

		static size_t HeightOf(Node* Tree) noexcept {

			return (Tree != nullptr) ? (Tree->Height) : 0;

			};

		template<class K, class D>
		static std::pair<Node*, bool> Insert(Node** PtrToThisNode, Node* Parent, K&& KeyToInsert, D&& DataToInsert, key_compare& );

		// Returns new root of child tree.
		static Node* RightRotate(Node* ) noexcept;
		static Node* LeftRotate(Node* ) noexcept;
		static Node* Begin(Node* ) noexcept;
		static Node* Find(Node* Tree, const key_type& KeyToFind, key_compare& );

		static void Dump(Node* CurrentNode) {

			if( CurrentNode == nullptr ){

				std::cout << "()";
				return;

				}

			std::cout << "((" << (CurrentNode->Mapping).first << ": " << (CurrentNode->Mapping).second << "), ";
			Dump(CurrentNode->Left);
			std::cout << ", ";
			Dump(CurrentNode->Right);
			std::cout << ')';

			}

		};

	Node* Root;
	key_compare Comp;

	// Public stuff.
	public:

	class iterator : public std::iterator<std::bidirectional_iterator_tag, decltype(Node::Mapping)> {

		Node* CurrentNode;

		// This can only be used in member functions of AVLTree.
		iterator(Node* InitPtr):
			CurrentNode( InitPtr ) {
			;
			}

		// It enables AVLTree to call the private constructor.
		friend class AVLTree;

		public:

		iterator():
			CurrentNode( nullptr ) {
			;
			}

		iterator(const iterator& ) = default;
		~iterator() = default;
		iterator& operator=(const iterator& ) = default;

		decltype(Node::Mapping)& operator*(void) const noexcept {

			return (CurrentNode->Mapping);

			}

		decltype(Node::Mapping)* operator->(void) const noexcept {

			return &(CurrentNode->Mapping);

			}

		iterator& operator++(void);
		iterator& operator--(void);

		iterator operator++(int) {

			iterator It(*this);

			++(*this);

			return It;

			}

		iterator operator--(int) {

			iterator It(*this);

			--(*this);

			return It;

			}

		bool operator==(const iterator& RHS) const noexcept {

			return ( (this->CurrentNode) == RHS.CurrentNode );

			}

		bool operator!=(const iterator& RHS) const noexcept {

			return ( (this->CurrentNode) != RHS.CurrentNode );

			}

		};

	// Const iterator.
	class const_iterator : public std::iterator<std::bidirectional_iterator_tag, const decltype(Node::Mapping)> {

		iterator It;

		public:

		const_iterator():
			It( nullptr ) {
			;
			}

		const_iterator(const iterator& RHS):
			It( RHS ) {
			;
			}

		const_iterator(const const_iterator& ) = default;
		~const_iterator() = default;
		const_iterator& operator=(const const_iterator& ) = default;

		const decltype(Node::Mapping)& operator*(void) const noexcept {

			return *It;

			}

		const decltype(Node::Mapping)* operator->(void) const noexcept {

			return &(*It);

			}

		const_iterator& operator++(void) {

			++It;

			return (*this);

			}

		const_iterator& operator--(void) {

			--It;

			return (*this);

			}

		const_iterator operator++(int) {

			return (It++);

			}

		const_iterator operator--(int) {

			return (It--);

			}

		bool operator==(const const_iterator& RHS) const noexcept {

			return ( It == RHS.It );

			}

		bool operator!=(const const_iterator& RHS) const noexcept {

			return ( It != RHS.It );

			}

		};

	AVLTree():
		Root(nullptr),
		Comp() {
		;
		}

	AVLTree(const AVLTree& RHS):
		Root( (RHS.Root != nullptr) ? new Node(RHS.Root, nullptr) : 0 ),
		Comp( RHS.Comp ) {
		;
		}

	AVLTree(AVLTree&& RHS):
		Root( RHS.Root ),
		Comp( std::move(RHS.Comp) ){

		RHS.Root = nullptr;

		}

	~AVLTree() {

		delete Root;

		}

	iterator begin(void) {

		return Node::Begin(Root);

		}

	iterator end(void) {

		return nullptr;

		}

	const_iterator begin(void) const {

		return iterator(Node::Begin(Root));

		}

	const_iterator end(void) const {

		return iterator(nullptr);

		}

	iterator find(const key_type& KeyToFind) {

		return Node::Find(Root, KeyToFind, Comp);

		}

	const_iterator find(const key_type& KeyToFind) const {

		return iterator(Node::Find(Root, KeyToFind, Comp));

		}

	template<class K, class D>
	std::pair<iterator, bool> insert(K&& KeyToInsert, D&& DataToInsert);

	AVLTree& operator=(const AVLTree& RHS) {

		if( this != &RHS ) {

			delete Root;

			if( RHS.Root != nullptr )
				Root = new Node(RHS.Root, nullptr);
			else
				Root = nullptr;

			Comp = RHS.Comp;

			}

		return *this;

		}

	template<class K>
	mapped_type& operator[](K&& Index) {

		auto Result = insert(std::forward<K>(Index), mapped_type());
		return (Result.first)->second;

		}

	AVLTree& operator=(AVLTree&& RHS) {

		if( this != &RHS ) {

			delete this->Root;
			this->Root = RHS.Root;
			RHS.Root = nullptr;
			Comp = std::move( RHS.Comp );

			}

		return *this;

		}

	size_t GetHeight(void) const noexcept {

		if( Root == nullptr )
			return 0;

		return Root->Height;

		}

	void Dump(void) const {

		Node::Dump(Root);
		std::cout << std::endl;

		}

	};

template<class key_type,
         class mapped_type,
         class key_compare
         >
auto AVLTree<key_type, mapped_type, key_compare>::iterator::operator++(void) -> iterator& {

	if( CurrentNode == nullptr )
		return (*this);

	// TODO: Find the next node in an in-order manner.
	key_compare Comp;
	Node *Next;
	if(CurrentNode->Right == nullptr){
		Next = CurrentNode->Parent;
		while(Next != nullptr && Comp((Next->Mapping).first, (CurrentNode->Mapping).first)){
			Next = Next->Parent;
		}
	} else {
		Next = CurrentNode->Right;
		while(Next->Left != nullptr){
			Next = Next->Left;
		}
	}
	*this = iterator(Next);
	return (*this);

	}

template<class key_type,
         class mapped_type,
         class key_compare
         >
auto AVLTree<key_type, mapped_type, key_compare>::iterator::operator--(void) -> iterator& {

	if( CurrentNode == nullptr )
		return (*this);

	// TODO: Find the previous node in an in-order manner.
	key_compare Comp;
	Node *Next;
	if(CurrentNode->Left == nullptr){
		Next = CurrentNode->Parent;
		while(Next != nullptr && Comp((CurrentNode->Mapping).first, (Next->Mapping).first)){ //bug: it will execute when Next != nullptr
			Next = Next->Parent;
		}
	} else {
		Next = CurrentNode->Left;
		while(Next->Right != nullptr){
			Next = Next->Right;
		}
	}
	*this = iterator(Next);
	return (*this);

	}

template<class key_type,
         class mapped_type,
         class key_compare
         >
auto AVLTree<key_type, mapped_type, key_compare>::Node::Begin(Node* CurrentNode) noexcept -> Node* {

		if( CurrentNode == nullptr )
			return CurrentNode;

		Node* Next;

		while( (Next = CurrentNode->Left) != nullptr )
			CurrentNode = Next;

		return CurrentNode;

		}

template<class key_type,
         class mapped_type,
         class key_compare
         >
auto AVLTree<key_type, mapped_type, key_compare>::Node::Find(Node* Tree, const key_type& KeyToFind, key_compare& Comp) -> Node* {

	Node* CurrentNode = Tree;

	// TODO: Use Comp to find where it located.
	//       You may want to take a look of the implementation of Insert.

	// If the data shall be placed in left tree.
	if(Comp(KeyToFind, CurrentNode->Mapping.first)){
		return Find(CurrentNode->Left, KeyToFind, Comp);
	}
		// If the data shall be placed in right tree.
 	else if(Comp(CurrentNode->Mapping.first, KeyToFind)){
		return Find(CurrentNode->Right, KeyToFind, Comp);
	}
	// Found.
	return CurrentNode;

	}

template<class key_type,
         class mapped_type,
         class key_compare
         >
template<class K, class D>
auto AVLTree<key_type, mapped_type, key_compare>::insert(K&& KeyToInsert, D&& DataToInsert) -> std::pair<iterator, bool> {

	auto Result = Node::Insert(&Root,
	                           nullptr,
	                           std::forward<K>(KeyToInsert),
	                           std::forward<D>(DataToInsert),
	                           Comp);

	return std::pair<iterator, bool>(Result.first, Result.second);

	}

template<class key_type,
         class mapped_type,
         class key_compare
         >
template<class K, class D>
auto AVLTree<key_type, mapped_type, key_compare>::Node::Insert(Node** PtrToThisNode, Node* Parent, K&& KeyToInsert, D&& DataToInsert, key_compare& Comp) -> std::pair<Node*, bool> {

	Node* ThisNode = *PtrToThisNode;

	// We found where to insert the data.
	if( ThisNode == nullptr ) {

		ThisNode = new Node(std::forward<K>(KeyToInsert),
		                    std::forward<D>(DataToInsert),
		                    Parent,
		                    nullptr,
		                    nullptr,
		                    1
		                    );

		// Fix parent's pointer to the new node and return where it's inserted.
		return std::pair<Node*, bool>(*PtrToThisNode = ThisNode, true);

		}

	std::pair<Node*, bool> InsertResult;

	// If the data shall be placed in left child.
	if( Comp(KeyToInsert, (ThisNode->Mapping).first) ) {

		InsertResult = Insert(&(ThisNode->Left),
		                      ThisNode,
		                      std::forward<K>(KeyToInsert),
		                      std::forward<D>(DataToInsert),
		                      Comp);

		size_t LeftHeight = Node::HeightOf(ThisNode->Left);
		size_t RightHeight = Node::HeightOf(ThisNode->Right);

		// If left child is higher.
		if( LeftHeight >= RightHeight + 2 ) {

			Node* LeftNode = ThisNode->Left;

			if( Node::HeightOf(LeftNode->Left) < Node::HeightOf(LeftNode->Right) )
				ThisNode->Left = LeftNode = LeftRotate(LeftNode);

			*PtrToThisNode = ThisNode = RightRotate(ThisNode);

			}
		// Already balanced. No need to rotate.
		else
			ThisNode->Height = 1 + std::max(LeftHeight, RightHeight);

		}
	// If the data shall be placed in right tree.
	else if( Comp((ThisNode->Mapping).first, KeyToInsert) ) {

		InsertResult = Insert(&(ThisNode->Right),
		                      ThisNode,
		                      std::forward<K>(KeyToInsert),
		                      std::forward<D>(DataToInsert),
		                      Comp);

		size_t LeftHeight = Node::HeightOf(ThisNode->Left);
		size_t RightHeight = Node::HeightOf(ThisNode->Right);

		// If right child is higher.
		if( RightHeight >= LeftHeight + 2 ){

			Node* RightNode = ThisNode->Right;

			if( Node::HeightOf(RightNode->Left) > Node::HeightOf(RightNode->Right) )
				ThisNode->Right = RightNode = RightRotate(RightNode);

			*PtrToThisNode = ThisNode = LeftRotate(ThisNode);

			}
		// Already balanced. No need to rotate.
		else
			ThisNode->Height = 1 + std::max(LeftHeight, RightHeight);

		}
	// Found.
	else {

		InsertResult.first = ThisNode;
		InsertResult.second = false;

		}

	return InsertResult;

	}

template<class key_type,
         class mapped_type,
         class key_compare
         >
auto AVLTree<key_type, mapped_type, key_compare>::Node::RightRotate(Node* ThisNode) noexcept -> Node* {

	// TODO: Right rotate the tree and return the new root.
	//       The height of modified trees should also be fixed accordingly.
	Node* LeftNode = ThisNode->Left;
	LeftNode->Parent = ThisNode->Parent;
	ThisNode->Parent = LeftNode;
	ThisNode->Left = LeftNode->Right;
	LeftNode->Right = ThisNode;
	ThisNode = LeftNode;
	return ThisNode;

	}

template<class key_type,
         class mapped_type,
         class key_compare
         >
auto AVLTree<key_type, mapped_type, key_compare>::Node::LeftRotate(Node* ThisNode) noexcept -> Node* {

	// TODO: Left rotate the tree and return the new root.
	//       The height of modified trees should also be fixed accordingly.
	Node* RightNode = ThisNode->Right;
	RightNode->Parent = ThisNode->Parent;
	ThisNode->Parent = RightNode;
	ThisNode->Right = RightNode->Left;
	RightNode->Left = ThisNode;
	ThisNode = RightNode;
	return ThisNode;

	}

#endif
<|endoftext|>


<commit_before><commit_msg>fdo#52547 SOT: Prefer embedding image data to embedding linked image.<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: stgio.cxx,v $
 * $Revision: 1.7 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sot.hxx"

#include "stg.hxx"
#include "stgelem.hxx"
#include "stgcache.hxx"
#include "stgstrms.hxx"
#include "stgdir.hxx"
#include "stgio.hxx"
#include <rtl/instance.hxx>

///////////////////////////// class StgIo //////////////////////////////

// This class holds the storage header and all internal streams.

StgIo::StgIo() : StgCache()
{
    pTOC      = NULL;
    pDataFAT  = NULL;
    pDataStrm = NULL;
    pFAT      = NULL;
    bCopied   = FALSE;
}

StgIo::~StgIo()
{
    delete pTOC;
    delete pDataFAT;
    delete pDataStrm;
    delete pFAT;
}

// Load the header. Do not set an error code if the header is invalid.

BOOL StgIo::Load()
{
    if( pStrm )
    {
        if( aHdr.Load( *this ) )
        {
            if( aHdr.Check() )
                SetupStreams();
            else
                return FALSE;
        }
    }
    return Good();
}

// Set up an initial, empty storage

BOOL StgIo::Init()
{
    aHdr.Init();
    SetupStreams();
    return CommitAll();
}

void StgIo::SetupStreams()
{
    delete pTOC;
    delete pDataFAT;
    delete pDataStrm;
    delete pFAT;
    pTOC      = NULL;
    pDataFAT  = NULL;
    pDataStrm = NULL;
    pFAT      = NULL;
    ResetError();
    SetPhysPageSize( 1 << aHdr.GetPageSize() );
    pFAT = new StgFATStrm( *this );
    pTOC = new StgDirStrm( *this );
    if( !GetError() )
    {
        StgDirEntry* pRoot = pTOC->GetRoot();
        if( pRoot )
        {
            pDataFAT = new StgDataStrm( *this, aHdr.GetDataFATStart(), -1 );
            pDataStrm = new StgDataStrm( *this, pRoot );
            pDataFAT->SetIncrement( 1 << aHdr.GetPageSize() );
            pDataStrm->SetIncrement( GetDataPageSize() );
            pDataStrm->SetEntry( *pRoot );
        }
        else
            SetError( SVSTREAM_FILEFORMAT_ERROR );
    }
}

// get the logical data page size

short StgIo::GetDataPageSize()
{
    return 1 << aHdr.GetDataPageSize();
}

// Commit everything

BOOL StgIo::CommitAll()
{
    // Store the data (all streams and the TOC)
    if( pTOC->Store() )
    {
        if( Commit( NULL ) )
        {
            aHdr.SetDataFATStart( pDataFAT->GetStart() );
            aHdr.SetDataFATSize( pDataFAT->GetPages() );
            aHdr.SetTOCStart( pTOC->GetStart() );
            if( aHdr.Store( *this ) )
            {
                pStrm->Flush();
                ULONG n = pStrm->GetError();
                SetError( n );
#ifdef DBG_UTIL
                if( n==0 ) ValidateFATs();
#endif
                return BOOL( n == 0 );
            }
        }
    }
    SetError( SVSTREAM_WRITE_ERROR );
    return FALSE;
}

class EasyFat
{
    INT32 *pFat;
    BOOL  *pFree;
    INT32 nPages;
    INT32 nPageSize;

public:
    EasyFat( StgIo & rIo, StgStrm *pFatStream, INT32 nPSize );
    ~EasyFat() { delete pFat; delete pFree; }
    INT32 GetPageSize() { return nPageSize; }
    INT32 Count() { return nPages; }
    INT32 operator[]( INT32 nOffset ) { return pFat[ nOffset ]; }

    ULONG Mark( INT32 nPage, INT32 nCount, INT32 nExpect );
    BOOL HasUnrefChains();
};

EasyFat::EasyFat( StgIo& rIo, StgStrm* pFatStream, INT32 nPSize )
{
    nPages = pFatStream->GetSize() >> 2;
    nPageSize = nPSize;
    pFat = new INT32[ nPages ];
    pFree = new BOOL[ nPages ];

    StgPage *pPage = NULL;
    INT32 nFatPageSize = (1 << rIo.aHdr.GetPageSize()) - 2;

    for( INT32 nPage = 0; nPage < nPages; nPage++ )
    {
        if( ! (nPage % nFatPageSize) )
        {
            pFatStream->Pos2Page( nPage << 2 );
            INT32 nPhysPage = pFatStream->GetPage();
            pPage = rIo.Get( nPhysPage, TRUE );
        }

        pFat[ nPage ] = pPage->GetPage( short( nPage % nFatPageSize ) );
        pFree[ nPage ] = TRUE;
    }
}

BOOL EasyFat::HasUnrefChains()
{
    for( INT32 nPage = 0; nPage < nPages; nPage++ )
    {
        if( pFree[ nPage ] && pFat[ nPage ] != -1 )
            return TRUE;
    }
    return FALSE;
}

ULONG EasyFat::Mark( INT32 nPage, INT32 nCount, INT32 nExpect )
{
    if( nCount > 0 )
        --nCount /= GetPageSize(), nCount++;

    INT32 nCurPage = nPage;
    while( nCount != 0 )
    {
        pFree[ nCurPage ] = FALSE;
        nCurPage = pFat[ nCurPage ];
        //Stream zu lang
        if( nCurPage != nExpect && nCount == 1 )
            return FAT_WRONGLENGTH;
        //Stream zu kurz
        if( nCurPage == nExpect && nCount != 1 && nCount != -1 )
            return FAT_WRONGLENGTH;
        // letzter Block bei Stream ohne Laenge
        if( nCurPage == nExpect && nCount == -1 )
            nCount = 1;
        if( nCount != -1 )
            nCount--;
        // Naechster Block nicht in der FAT
        if( nCount && ( nCurPage < 0 || nCurPage >= nPages ) )
            return FAT_OUTOFBOUNDS;
    }
    return FAT_OK;
}

class Validator
{
    ULONG nError;

    EasyFat aSmallFat;
    EasyFat aFat;

    StgIo &rIo;

    ULONG ValidateMasterFATs();
    ULONG ValidateDirectoryEntries();
    ULONG FindUnrefedChains();
    ULONG MarkAll( StgDirEntry *pEntry );

public:

    Validator( StgIo &rIo );
    BOOL IsError() { return nError != 0; }
};

Validator::Validator( StgIo &rIoP )
    : aSmallFat( rIoP, rIoP.pDataFAT, 1 << rIoP.aHdr.GetDataPageSize() ),
      aFat( rIoP, rIoP.pFAT, 1 << rIoP.aHdr.GetPageSize() ),
      rIo( rIoP )
{
    ULONG nErr = nError = FAT_OK;

    if( ( nErr = ValidateMasterFATs() ) != FAT_OK )
        nError = nErr;
    else if(    ( nErr = ValidateDirectoryEntries() ) != FAT_OK )
        nError = nErr;
    else if(    ( nErr = FindUnrefedChains()) != FAT_OK )
        nError = nErr;
}

ULONG Validator::ValidateMasterFATs()
{
    INT32 nCount = rIo.aHdr.GetFATSize();
    ULONG nErr;
    for( INT32 i = 0; i < nCount; i++ )
    {
        if( ( nErr = aFat.Mark(rIo.pFAT->GetPage( short(i), FALSE ), aFat.GetPageSize(), -3 )) != FAT_OK )
            return nErr;
    }
    if( rIo.aHdr.GetMasters() )
        if( ( nErr = aFat.Mark(rIo.aHdr.GetFATChain( ), aFat.GetPageSize(), -4 )) != FAT_OK )
            return nErr;
    return FAT_OK;
}

ULONG Validator::MarkAll( StgDirEntry *pEntry )
{
    StgIterator aIter( *pEntry );
    ULONG nErr = FAT_OK;
    for( StgDirEntry* p = aIter.First(); p ; p = aIter.Next() )
    {
        if( p->aEntry.GetType() == STG_STORAGE )
        {
            nErr = MarkAll( p );
            if( nErr != FAT_OK )
                return nErr;
        }
        else
        {
            INT32 nSize = p->aEntry.GetSize();
            if( nSize < rIo.aHdr.GetThreshold()  )
                nErr = aSmallFat.Mark( p->aEntry.GetStartPage(),nSize, -2 );
            else
                nErr = aFat.Mark( p->aEntry.GetStartPage(),nSize, -2 );
            if( nErr != FAT_OK )
                return nErr;
        }
    }
    return FAT_OK;
}

ULONG Validator::ValidateDirectoryEntries()
{
    // Normale DirEntries
    ULONG nErr = MarkAll( rIo.pTOC->GetRoot() );
    if( nErr != FAT_OK )
        return nErr;
    // Small Data
    nErr = aFat.Mark( rIo.pTOC->GetRoot()->aEntry.GetStartPage(),
                 rIo.pTOC->GetRoot()->aEntry.GetSize(), -2 );
    if( nErr != FAT_OK )
        return nErr;
    // Small Data FAT
    nErr = aFat.Mark(
        rIo.aHdr.GetDataFATStart(),
        rIo.aHdr.GetDataFATSize() * aFat.GetPageSize(), -2 );
    if( nErr != FAT_OK )
        return nErr;
    // TOC
    nErr = aFat.Mark(
        rIo.aHdr.GetTOCStart(), -1, -2 );
    return nErr;
}

ULONG Validator::FindUnrefedChains()
{
    if( aSmallFat.HasUnrefChains() ||
        aFat.HasUnrefChains() )
        return FAT_UNREFCHAIN;
    else
        return FAT_OK;
}

namespace { struct ErrorLink : public rtl::Static<Link, ErrorLink > {}; }

void StgIo::SetErrorLink( const Link& rLink )
{
    ErrorLink::get() = rLink;
}

const Link& StgIo::GetErrorLink()
{
    return ErrorLink::get();
}

ULONG StgIo::ValidateFATs()
{
    if( bFile )
    {
        Validator *pV = new Validator( *this );
        BOOL bRet1 = !pV->IsError(), bRet2 = TRUE ;
        delete pV;
        SvFileStream *pFileStrm = ( SvFileStream *) GetStrm();
        StgIo aIo;
        if( aIo.Open( pFileStrm->GetFileName(),
                      STREAM_READ  | STREAM_SHARE_DENYNONE) &&
            aIo.Load() )
        {
            pV = new Validator( aIo );
            bRet2 = !pV->IsError();
            delete pV;
        }

        ULONG nErr;
        if( bRet1 != bRet2 )
            nErr = bRet1 ? FAT_ONFILEERROR : FAT_INMEMORYERROR;
        else nErr = bRet1 ? FAT_OK : FAT_BOTHERROR;
        if( nErr != FAT_OK && !bCopied )
        {
            StgLinkArg aArg;
            aArg.aFile = pFileStrm->GetFileName();
            aArg.nErr = nErr;
            ErrorLink::get().Call( &aArg );
            bCopied = TRUE;
        }
//      DBG_ASSERT( nErr == FAT_OK ,"Storage kaputt");
        return nErr;
    }
//  DBG_ERROR("Validiere nicht (kein FileStorage)");
    return FAT_OK;
}

<commit_msg>#i10000# Fixed operator new[]/delete mismatch.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: stgio.cxx,v $
 * $Revision: 1.7 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sot.hxx"

#include "stg.hxx"
#include "stgelem.hxx"
#include "stgcache.hxx"
#include "stgstrms.hxx"
#include "stgdir.hxx"
#include "stgio.hxx"
#include <rtl/instance.hxx>

///////////////////////////// class StgIo //////////////////////////////

// This class holds the storage header and all internal streams.

StgIo::StgIo() : StgCache()
{
    pTOC      = NULL;
    pDataFAT  = NULL;
    pDataStrm = NULL;
    pFAT      = NULL;
    bCopied   = FALSE;
}

StgIo::~StgIo()
{
    delete pTOC;
    delete pDataFAT;
    delete pDataStrm;
    delete pFAT;
}

// Load the header. Do not set an error code if the header is invalid.

BOOL StgIo::Load()
{
    if( pStrm )
    {
        if( aHdr.Load( *this ) )
        {
            if( aHdr.Check() )
                SetupStreams();
            else
                return FALSE;
        }
    }
    return Good();
}

// Set up an initial, empty storage

BOOL StgIo::Init()
{
    aHdr.Init();
    SetupStreams();
    return CommitAll();
}

void StgIo::SetupStreams()
{
    delete pTOC;
    delete pDataFAT;
    delete pDataStrm;
    delete pFAT;
    pTOC      = NULL;
    pDataFAT  = NULL;
    pDataStrm = NULL;
    pFAT      = NULL;
    ResetError();
    SetPhysPageSize( 1 << aHdr.GetPageSize() );
    pFAT = new StgFATStrm( *this );
    pTOC = new StgDirStrm( *this );
    if( !GetError() )
    {
        StgDirEntry* pRoot = pTOC->GetRoot();
        if( pRoot )
        {
            pDataFAT = new StgDataStrm( *this, aHdr.GetDataFATStart(), -1 );
            pDataStrm = new StgDataStrm( *this, pRoot );
            pDataFAT->SetIncrement( 1 << aHdr.GetPageSize() );
            pDataStrm->SetIncrement( GetDataPageSize() );
            pDataStrm->SetEntry( *pRoot );
        }
        else
            SetError( SVSTREAM_FILEFORMAT_ERROR );
    }
}

// get the logical data page size

short StgIo::GetDataPageSize()
{
    return 1 << aHdr.GetDataPageSize();
}

// Commit everything

BOOL StgIo::CommitAll()
{
    // Store the data (all streams and the TOC)
    if( pTOC->Store() )
    {
        if( Commit( NULL ) )
        {
            aHdr.SetDataFATStart( pDataFAT->GetStart() );
            aHdr.SetDataFATSize( pDataFAT->GetPages() );
            aHdr.SetTOCStart( pTOC->GetStart() );
            if( aHdr.Store( *this ) )
            {
                pStrm->Flush();
                ULONG n = pStrm->GetError();
                SetError( n );
#ifdef DBG_UTIL
                if( n==0 ) ValidateFATs();
#endif
                return BOOL( n == 0 );
            }
        }
    }
    SetError( SVSTREAM_WRITE_ERROR );
    return FALSE;
}

class EasyFat
{
    INT32 *pFat;
    BOOL  *pFree;
    INT32 nPages;
    INT32 nPageSize;

public:
    EasyFat( StgIo & rIo, StgStrm *pFatStream, INT32 nPSize );
    ~EasyFat() { delete[] pFat; delete[] pFree; }
    INT32 GetPageSize() { return nPageSize; }
    INT32 Count() { return nPages; }
    INT32 operator[]( INT32 nOffset ) { return pFat[ nOffset ]; }

    ULONG Mark( INT32 nPage, INT32 nCount, INT32 nExpect );
    BOOL HasUnrefChains();
};

EasyFat::EasyFat( StgIo& rIo, StgStrm* pFatStream, INT32 nPSize )
{
    nPages = pFatStream->GetSize() >> 2;
    nPageSize = nPSize;
    pFat = new INT32[ nPages ];
    pFree = new BOOL[ nPages ];

    StgPage *pPage = NULL;
    INT32 nFatPageSize = (1 << rIo.aHdr.GetPageSize()) - 2;

    for( INT32 nPage = 0; nPage < nPages; nPage++ )
    {
        if( ! (nPage % nFatPageSize) )
        {
            pFatStream->Pos2Page( nPage << 2 );
            INT32 nPhysPage = pFatStream->GetPage();
            pPage = rIo.Get( nPhysPage, TRUE );
        }

        pFat[ nPage ] = pPage->GetPage( short( nPage % nFatPageSize ) );
        pFree[ nPage ] = TRUE;
    }
}

BOOL EasyFat::HasUnrefChains()
{
    for( INT32 nPage = 0; nPage < nPages; nPage++ )
    {
        if( pFree[ nPage ] && pFat[ nPage ] != -1 )
            return TRUE;
    }
    return FALSE;
}

ULONG EasyFat::Mark( INT32 nPage, INT32 nCount, INT32 nExpect )
{
    if( nCount > 0 )
        --nCount /= GetPageSize(), nCount++;

    INT32 nCurPage = nPage;
    while( nCount != 0 )
    {
        pFree[ nCurPage ] = FALSE;
        nCurPage = pFat[ nCurPage ];
        //Stream zu lang
        if( nCurPage != nExpect && nCount == 1 )
            return FAT_WRONGLENGTH;
        //Stream zu kurz
        if( nCurPage == nExpect && nCount != 1 && nCount != -1 )
            return FAT_WRONGLENGTH;
        // letzter Block bei Stream ohne Laenge
        if( nCurPage == nExpect && nCount == -1 )
            nCount = 1;
        if( nCount != -1 )
            nCount--;
        // Naechster Block nicht in der FAT
        if( nCount && ( nCurPage < 0 || nCurPage >= nPages ) )
            return FAT_OUTOFBOUNDS;
    }
    return FAT_OK;
}

class Validator
{
    ULONG nError;

    EasyFat aSmallFat;
    EasyFat aFat;

    StgIo &rIo;

    ULONG ValidateMasterFATs();
    ULONG ValidateDirectoryEntries();
    ULONG FindUnrefedChains();
    ULONG MarkAll( StgDirEntry *pEntry );

public:

    Validator( StgIo &rIo );
    BOOL IsError() { return nError != 0; }
};

Validator::Validator( StgIo &rIoP )
    : aSmallFat( rIoP, rIoP.pDataFAT, 1 << rIoP.aHdr.GetDataPageSize() ),
      aFat( rIoP, rIoP.pFAT, 1 << rIoP.aHdr.GetPageSize() ),
      rIo( rIoP )
{
    ULONG nErr = nError = FAT_OK;

    if( ( nErr = ValidateMasterFATs() ) != FAT_OK )
        nError = nErr;
    else if(    ( nErr = ValidateDirectoryEntries() ) != FAT_OK )
        nError = nErr;
    else if(    ( nErr = FindUnrefedChains()) != FAT_OK )
        nError = nErr;
}

ULONG Validator::ValidateMasterFATs()
{
    INT32 nCount = rIo.aHdr.GetFATSize();
    ULONG nErr;
    for( INT32 i = 0; i < nCount; i++ )
    {
        if( ( nErr = aFat.Mark(rIo.pFAT->GetPage( short(i), FALSE ), aFat.GetPageSize(), -3 )) != FAT_OK )
            return nErr;
    }
    if( rIo.aHdr.GetMasters() )
        if( ( nErr = aFat.Mark(rIo.aHdr.GetFATChain( ), aFat.GetPageSize(), -4 )) != FAT_OK )
            return nErr;
    return FAT_OK;
}

ULONG Validator::MarkAll( StgDirEntry *pEntry )
{
    StgIterator aIter( *pEntry );
    ULONG nErr = FAT_OK;
    for( StgDirEntry* p = aIter.First(); p ; p = aIter.Next() )
    {
        if( p->aEntry.GetType() == STG_STORAGE )
        {
            nErr = MarkAll( p );
            if( nErr != FAT_OK )
                return nErr;
        }
        else
        {
            INT32 nSize = p->aEntry.GetSize();
            if( nSize < rIo.aHdr.GetThreshold()  )
                nErr = aSmallFat.Mark( p->aEntry.GetStartPage(),nSize, -2 );
            else
                nErr = aFat.Mark( p->aEntry.GetStartPage(),nSize, -2 );
            if( nErr != FAT_OK )
                return nErr;
        }
    }
    return FAT_OK;
}

ULONG Validator::ValidateDirectoryEntries()
{
    // Normale DirEntries
    ULONG nErr = MarkAll( rIo.pTOC->GetRoot() );
    if( nErr != FAT_OK )
        return nErr;
    // Small Data
    nErr = aFat.Mark( rIo.pTOC->GetRoot()->aEntry.GetStartPage(),
                 rIo.pTOC->GetRoot()->aEntry.GetSize(), -2 );
    if( nErr != FAT_OK )
        return nErr;
    // Small Data FAT
    nErr = aFat.Mark(
        rIo.aHdr.GetDataFATStart(),
        rIo.aHdr.GetDataFATSize() * aFat.GetPageSize(), -2 );
    if( nErr != FAT_OK )
        return nErr;
    // TOC
    nErr = aFat.Mark(
        rIo.aHdr.GetTOCStart(), -1, -2 );
    return nErr;
}

ULONG Validator::FindUnrefedChains()
{
    if( aSmallFat.HasUnrefChains() ||
        aFat.HasUnrefChains() )
        return FAT_UNREFCHAIN;
    else
        return FAT_OK;
}

namespace { struct ErrorLink : public rtl::Static<Link, ErrorLink > {}; }

void StgIo::SetErrorLink( const Link& rLink )
{
    ErrorLink::get() = rLink;
}

const Link& StgIo::GetErrorLink()
{
    return ErrorLink::get();
}

ULONG StgIo::ValidateFATs()
{
    if( bFile )
    {
        Validator *pV = new Validator( *this );
        BOOL bRet1 = !pV->IsError(), bRet2 = TRUE ;
        delete pV;
        SvFileStream *pFileStrm = ( SvFileStream *) GetStrm();
        StgIo aIo;
        if( aIo.Open( pFileStrm->GetFileName(),
                      STREAM_READ  | STREAM_SHARE_DENYNONE) &&
            aIo.Load() )
        {
            pV = new Validator( aIo );
            bRet2 = !pV->IsError();
            delete pV;
        }

        ULONG nErr;
        if( bRet1 != bRet2 )
            nErr = bRet1 ? FAT_ONFILEERROR : FAT_INMEMORYERROR;
        else nErr = bRet1 ? FAT_OK : FAT_BOTHERROR;
        if( nErr != FAT_OK && !bCopied )
        {
            StgLinkArg aArg;
            aArg.aFile = pFileStrm->GetFileName();
            aArg.nErr = nErr;
            ErrorLink::get().Call( &aArg );
            bCopied = TRUE;
        }
//      DBG_ASSERT( nErr == FAT_OK ,"Storage kaputt");
        return nErr;
    }
//  DBG_ERROR("Validiere nicht (kein FileStorage)");
    return FAT_OK;
}

<|endoftext|>


<commit_before>#include "DuplicateSession.h"
#include <MessageDuplicateDataRequest.pb.h>
#include <BlockHub.h>
#include <MRT.h>
#include <MasterSession.h>
#include <MessageSyncBlock.pb.h>

DuplicateSession::DuplicateSession()
{
}

DuplicateSession::DuplicateSession( uptr<MessageDuplicateBlock> msg )
{
    this->message_block_ = move_ptr( msg );
    this->index_ = BlockHub::Instance()->FindBlock( this->message_block_->path() ,
                                                    this->message_block_->partid() );

    if(this->index_ == nullptr )
        this->index_ = BlockHub::Instance()->CreateBlock( (int)this->message_block_->partid() ,
                                                          this->message_block_->fileoffset() ,
                                                          this->message_block_->path() );
}

DuplicateSession::~DuplicateSession()
{

}

void DuplicateSession::SendRequest()
{
    uptr<MessageDuplicateDataRequest> message = make_uptr( MessageDuplicateDataRequest );
    message->set_index     ( this->index_->Index );
    message->set_token     ( this->message_block_->token() );
    message->set_offset    ( this->block_offset_ );
    message->set_size      ( BLOCK_TRANSFER_SIZE );
    message->set_sessionid ( this->Id() );
    this->SendMessage      ( move_ptr( message ) );
}

void DuplicateSession::OnConnect()
{
}

void DuplicateSession::AcceptBlock( uptr<MessageDuplicateData> msg )
{
    BlockHub::Instance()->WriteBlock( this->index_->Index ,
                                      msg->offset() ,
                                      msg->data().c_str() ,
                                      msg->data().size() );

    this->index_->Size += msg->size();

    BlockHub::Instance()->SaveBlockIndex( this->index_ );

    if ( msg->islast() )
    {
        auto sync = make_uptr   ( MessageBlockMeta );
        sync->set_fileoffset    ( this->index_->FileOffset );
        sync->set_index         ( this->index_->Index );
        sync->set_partid        ( this->index_->PartId );
        sync->set_path          ( this->index_->Path );
        sync->set_size          ( this->index_->Size );
        sync->set_status        ( 0 );
        MasterSession::Instance ()->SendMessage( move_ptr( sync ) );

        Logger::Log( "duplicate % part:% size:% from %" ,
                     this->index_->Path ,
                     this->index_->PartId ,
                     this->index_->Size ,
                     this->ip_address() );

        this->Close();
        return;
    }

    this->block_offset_ += msg->size();
    this->SendRequest();
}
<commit_msg>update framework<commit_after>#include "DuplicateSession.h"
#include <MessageDuplicateDataRequest.pb.h>
#include <BlockHub.h>
#include <MRT.h>
#include <MasterSession.h>
#include <MessageSyncBlock.pb.h>

DuplicateSession::DuplicateSession()
{
}

DuplicateSession::DuplicateSession( uptr<MessageDuplicateBlock> msg )
{
    this->message_block_ = move_ptr( msg );
    this->index_ = BlockHub::Instance()->FindBlock( this->message_block_->path() ,
                                                    this->message_block_->partid() );

    if(this->index_ == nullptr )
        this->index_ = BlockHub::Instance()->CreateBlock( (int)this->message_block_->partid() ,
                                                          this->message_block_->fileoffset() ,
                                                          this->message_block_->path() );
    Logger::Log( "duplicate % part:% size:% from %" ,
                  this->index_->Path ,
                  this->index_->PartId ,
                  this->index_->Size ,
                  this->message_block_->address() );

}

DuplicateSession::~DuplicateSession()
{

}

void DuplicateSession::SendRequest()
{
    uptr<MessageDuplicateDataRequest> message = make_uptr( MessageDuplicateDataRequest );
    message->set_index     ( this->index_->Index );
    message->set_token     ( this->message_block_->token() );
    message->set_offset    ( this->block_offset_ );
    message->set_size      ( BLOCK_TRANSFER_SIZE );
    message->set_sessionid ( this->Id() );
    this->SendMessage      ( move_ptr( message ) );
}

void DuplicateSession::OnConnect()
{
}

void DuplicateSession::AcceptBlock( uptr<MessageDuplicateData> msg )
{
    BlockHub::Instance()->WriteBlock( this->index_->Index ,
                                      msg->offset() ,
                                      msg->data().c_str() ,
                                      msg->data().size() );

    this->index_->Size += msg->size();

    BlockHub::Instance()->SaveBlockIndex( this->index_ );

    if ( msg->islast() )
    {
        auto sync = make_uptr   ( MessageBlockMeta );
        sync->set_fileoffset    ( this->index_->FileOffset );
        sync->set_index         ( this->index_->Index );
        sync->set_partid        ( this->index_->PartId );
        sync->set_path          ( this->index_->Path );
        sync->set_size          ( this->index_->Size );
        sync->set_status        ( 0 );
        MasterSession::Instance ()->SendMessage( move_ptr( sync ) );

        this->Close();
        return;
    }

    this->block_offset_ += msg->size();
    this->SendRequest();
}
<|endoftext|>