<commit_before>#include <SFML/Graphics.hpp>
#include <SFML/System/Vector2.hpp>
#include <iostream>
#include <chrono>
#include <thread>
using namespace std;
using namespace sf;
using namespace chrono;

#define MAX_ENEMIES 255
#define DEFAULT_WINDOW_RESOULUTION_X 600  // 461
#define DEFAULT_WINDOW_RESOULUTION_Y 1000 // 768
#define DEFAULT_WINDOW_RESOULUTION DEFAULT_WINDOW_RESOULUTION_X, DEFAULT_WINDOW_RESOULUTION_Y
#define GAME_WORLD_X 600
#define GAME_WORLD_Y 1000
#define GAME_RESOULUTION GAME_WORLD_X, GAME_WORLD_Y

Vector2u scaledGameResolution;
Vector2f scaledGameResolutionNormal;
Vector2u scaledGameOffset;
Vector2f scaledGameOffsetNormal;

View gameView;
View menuView;
enum Gamestates {Start,Game,Pause,Dead};
Gamestates state = Gamestates::Start;

const string filepath = "..\\res/";
static const string textureNames[]{"img/spaceship1.png",
                                   "img/spaceship2.png",
                                   "img/spaceship3.png",
                                   "img/Spaceship-Drakir1.png",
                                   "img/Spaceship-Drakir2.png",
                                   "img/Spaceship-Drakir3.png",
                                   "img/Spaceship-Drakir4.png",
                                   "img/Spaceship-Drakir5.png",
                                   "img/Spaceship-Drakir6.png",
                                   "img/Spaceship-Drakir7.png",
                                   "img/bullet.png"};

Texture *textures[11];
Font *gameFont;
Sprite *playerSprite;
Sprite *bulletsprite;
Text *scoreText;
static Sprite *enemies[MAX_ENEMIES];

static unsigned int currentEnemies = 0;
float playerMoveSpeed = 600.0f;
unsigned int score = 0;
float runTime = 0; // time in seconds that the game has been running
high_resolution_clock::time_point previous;

static Vector2f GetNewEnemyPos() { return Vector2f((float)(rand() % GAME_WORLD_Y), -128.0f); }

void Resize(RenderWindow &window) {
  const Vector2f win = (Vector2f)window.getSize();
  float scale = 1.0f;
  float scale2 = 1.0f;
  const float GWX = (float)GAME_WORLD_X;
  const float GWY = (float)GAME_WORLD_Y;
  if (win.y > win.x) {
    // wide
    scale = win.x / GWX;
    if (win.y < (scale * GWY)) {
      scale2 = win.y / GWY;
    }
  } else {
    // tall (or square)
    scale = win.y / GWY;
    if (win.x < (scale * GWX)) {
      scale2 = win.x / GWX;
    }
  }
  scale = min(scale, scale2);
  scaledGameResolution =
      Vector2u((unsigned int)floor(scale * GWX), (unsigned int)floor(scale * GWY));
  scaledGameOffset = Vector2u((unsigned int)max(0.0f, (win.x - scaledGameResolution.x) * 0.5f),
                              (unsigned int)max(0.0f, (win.y - scaledGameResolution.y) * 0.5f));
  scaledGameResolutionNormal =
      Vector2f((float)scaledGameResolution.x / win.x, (float)scaledGameResolution.y / win.y);
  scaledGameOffsetNormal =
      Vector2f((float)scaledGameOffset.x / win.x, (float)scaledGameOffset.y / win.y);
}

void Loadcontent() {
  gameFont = new Font();
  gameFont->loadFromFile(filepath + "/fonts/AmericanCaptain.ttf");
  scoreText = new Text();
  scoreText->setFont(*gameFont);
  scoreText->setPosition(0, 0);
  scoreText->setCharacterSize(24);
  scoreText->setColor(Color::Red);

  for (size_t i = 0; i < 11; i++) {
    textures[i] = new Texture();
    if (!textures[i]->loadFromFile(filepath + textureNames[i])) {
      throw invalid_argument("Loading error!");
    }
  }
  playerSprite = new Sprite();
  playerSprite->setTexture(*textures[0]);
  playerSprite->setPosition(512, 256);
  bulletsprite = new Sprite();
  bulletsprite->setTexture(*textures[10]);
  bulletsprite->setPosition(0, -128.0f);
  for (auto &e : enemies) {
    e = new Sprite();
    e->setTexture(*textures[(rand() % 7) + 3]);
    e->setPosition(GetNewEnemyPos());
  }
}

void Unload() {
  for (auto &t : textures) {
    delete t;
    t = nullptr;
  }
  for (auto &e : enemies) {
    delete e;
    e = nullptr;
  }
  delete gameFont;
  gameFont = nullptr;
  delete scoreText;
  scoreText = nullptr;
  delete bulletsprite;
  bulletsprite = nullptr;
  delete playerSprite;
  playerSprite = nullptr;
}

void Normalize(Vector2f &v) {
  float length = sqrt(v.x * v.x + v.y * v.y);
  if (length == 0.0f) {
    return;
  }
  v.x /= length;
  v.y /= length;
}

void FireBullet() {
  if (bulletsprite->getPosition().y <= -128.0f) {
    bulletsprite->setPosition(playerSprite->getPosition().x + 30,
                              playerSprite->getPosition().y - 1);
  }
}
void ResetGame() {
  score = 0;
  runTime = 0;
  currentEnemies = 0;
  playerSprite->setPosition(512, 256);
  for (auto e : enemies) {
    e->setPosition(GetNewEnemyPos());
  }
}
void PlayerDeath() {}

void menuUpdate(RenderWindow &window) {

	Event e;

	while (window.pollEvent(e)) {

		if (e.type == Event::Closed)
			window.close();

		if (e.type == sf::Event::Resized) {
			Resize(window);
			menuView.setViewport(FloatRect(scaledGameOffsetNormal.x, scaledGameOffsetNormal.y,
				scaledGameResolutionNormal.x, scaledGameResolutionNormal.y));
			window.setView(menuView);
		}

		// keyboard event handling
		if (e.type == Event::KeyPressed) {
			if (e.key.code == Keyboard::Escape) {
				window.close();
			}
			else if (e.key.code == Keyboard::B) {
				Resize(window);
			}
			else if (e.key.code == Keyboard::S && state == Gamestates::Start || state == Gamestates::Pause) {
				state = Gamestates::Game;
			}
		}
	}

}

void Update(RenderWindow &window) {

  high_resolution_clock::time_point now = high_resolution_clock::now();
  // time in nanoseconds since last update
  const auto delta = (duration_cast<duration<unsigned int, nano>>(now - previous)).count();
  const float deltaSeconds = ((float)delta) / 1000000000.0f;
  previous = now;

  runTime += deltaSeconds;
  currentEnemies = min((int)ceil(runTime * 0.6f) + 1, MAX_ENEMIES);

  { // Input
    Event e;
    Vector2f moveDirection(0, 0);

    while (window.pollEvent(e)) {

      if (e.type == Event::Closed)
        window.close();

      if (e.type == sf::Event::Resized) {
        Resize(window);
        gameView.setViewport(FloatRect(scaledGameOffsetNormal.x, scaledGameOffsetNormal.y,
                                       scaledGameResolutionNormal.x, scaledGameResolutionNormal.y));
        window.setView(gameView);
      }

      // keyboard event handling
      if (e.type == Event::KeyPressed) {
        if (e.key.code == Keyboard::Escape) {
          window.close();
        } else if (e.key.code == Keyboard::Space) {
          FireBullet();
        } else if (e.key.code == Keyboard::B) {
          Resize(window);
        }
      }
	  if (Keyboard::isKeyPressed(Keyboard::P)) {
		  state = Gamestates::Pause;
	  }
    }

    if (Keyboard::isKeyPressed(Keyboard::Space)) {
      FireBullet();
    }

    if (Keyboard::isKeyPressed(Keyboard::Up) || Keyboard::isKeyPressed(Keyboard::W)) {
      moveDirection += Vector2f(0, -1);
    }
    if (Keyboard::isKeyPressed(Keyboard::Down) || Keyboard::isKeyPressed(Keyboard::S)) {
      moveDirection += Vector2f(0, 1);
    }
    if (Keyboard::isKeyPressed(Keyboard::Left) || Keyboard::isKeyPressed(Keyboard::A)) {
      moveDirection += Vector2f(-1, 0);
    }
    if (Keyboard::isKeyPressed(Keyboard::Right) || Keyboard::isKeyPressed(Keyboard::D)) {
      moveDirection += Vector2f(1, 0);
    }

    // joystick input
    if (Joystick::isConnected(0)) {
      const float joystickX = Joystick::getAxisPosition(0, Joystick::X);
      const float joystickY = Joystick::getAxisPosition(0, Joystick::Y);

      if (abs(joystickX) > 40.0f) {
        moveDirection += Vector2f((float)((signbit(joystickX) * -2) + 1), 0);
      }
      if (abs(joystickY) > 40.0f) {
        moveDirection += Vector2f(0, (float)((signbit(joystickY) * -2) + 1));
      }

	  if (Joystick::isButtonPressed(0, 2)) {
		  state == Gamestates::Pause;
	  }
      if (Joystick::isButtonPressed(0, 1)) {
        FireBullet();
      }
    }
    if (playerSprite->getPosition().x < 0) {
      moveDirection.x = max(0.0f, moveDirection.x);
    }
    if (playerSprite->getPosition().y < 0) {
      moveDirection.y = max(0.0f, moveDirection.y);
    }
    if (playerSprite->getPosition().x > (GAME_WORLD_X - playerSprite->getLocalBounds().width)) {
      moveDirection.x = min(0.0f, moveDirection.x);
    }
    if (playerSprite->getPosition().y > (GAME_WORLD_Y - playerSprite->getLocalBounds().height)) {
      moveDirection.y = min(0.0f, moveDirection.y);
    }
    Normalize(moveDirection);
    moveDirection = (moveDirection * playerMoveSpeed) * deltaSeconds;

    playerSprite->setPosition(playerSprite->getPosition() + moveDirection);
  } // End Input

  if (bulletsprite->getPosition().y > -128.0f) {
    bulletsprite->setPosition(bulletsprite->getPosition().x,
                              bulletsprite->getPosition().y - 1000.0f * deltaSeconds);
  }

  for (size_t i = 0; i < MAX_ENEMIES; i++) {
    if (i < currentEnemies) {
      // if not dead, move
      if (enemies[i]->getPosition().y < GAME_WORLD_X) {
        enemies[i]->setPosition(
            enemies[i]->getPosition() +
            Vector2f(sinf(runTime + i) * 100.0f * deltaSeconds, 100.0f * deltaSeconds));
        // collisions
        if (bulletsprite->getGlobalBounds().intersects(enemies[i]->getGlobalBounds())) {
          enemies[i]->setPosition(GetNewEnemyPos());
          score += 100;
        }
        if (playerSprite->getGlobalBounds().intersects(enemies[i]->getGlobalBounds())) {
          PlayerDeath();
        }
      } else {
        // enemy is offscreen, kill
        enemies[i]->setPosition(GetNewEnemyPos());
      }
    } else {
      // if alive
      if (enemies[i]->getPosition().y != -128.0f) {
        // kill
        enemies[i]->setPosition(GetNewEnemyPos());
      }
    }
  }

  scoreText->setString("Score =" + to_string(score + ceil(runTime)));
}

void menuRender(RenderWindow &window) {
	window.clear(sf::Color::Black);

	RectangleShape rectangle(Vector2f(0, 0));
	rectangle.setSize(Vector2f(GAME_RESOULUTION));
	rectangle.setFillColor(Color::Green);
	window.draw(rectangle);
	window.display();
}

void Render(RenderWindow &window) {
  window.clear(sf::Color::Black);
  RectangleShape rectangle(Vector2f(0, 0));
  rectangle.setSize(Vector2f(GAME_RESOULUTION));
  rectangle.setFillColor(Color::Green);
  window.draw(rectangle);

  window.draw(*playerSprite);
  window.draw(*bulletsprite);
  for (size_t i = 0; i < currentEnemies; i++) {
    window.draw(*enemies[i]);
  }
  window.draw(*scoreText);
  window.display();
}

int main() {
  Loadcontent();
  RenderWindow *window =
      new RenderWindow(VideoMode(DEFAULT_WINDOW_RESOULUTION), "Advanced Minigame");
  window->setVerticalSyncEnabled(true);
  Resize(*window);

  // let's define  the game view
  gameView = View(FloatRect(0, 0, GAME_RESOULUTION));
  gameView.setViewport(FloatRect(scaledGameOffsetNormal.x, scaledGameOffsetNormal.y,
                                 scaledGameResolutionNormal.x, scaledGameResolutionNormal.y));

  // let's define the menu view
  menuView = View(FloatRect(0, 0, GAME_RESOULUTION));
  menuView.setViewport(FloatRect(scaledGameOffsetNormal.x, scaledGameOffsetNormal.y,
	  scaledGameResolutionNormal.x, scaledGameResolutionNormal.y));

  previous = high_resolution_clock::now();

	  while (window->isOpen()) {
		  if (state == Gamestates::Start)
		  {
			  menuUpdate(*window);
			  menuRender(*window);

		  }
		  else if (state == Gamestates::Game) {
			  // Activate gameview
			  Update(*window);
			  Render(*window);
		  }
		  else if (state == Gamestates::Pause)
		  {
			  menuUpdate(*window);
			  menuRender(*window);
		  }
	  }

  Unload();
  delete window;
  window = nullptr;
  return 0;
}<commit_msg>Making menu text and functionality got highlighting text working<commit_after>#include <SFML/Graphics.hpp>
#include <SFML/System/Vector2.hpp>
#include <iostream>
#include <chrono>
#include <thread>
using namespace std;
using namespace sf;
using namespace chrono;

#define MAX_ENEMIES 255
#define DEFAULT_WINDOW_RESOULUTION_X 600  // 461
#define DEFAULT_WINDOW_RESOULUTION_Y 1000 // 768
#define DEFAULT_WINDOW_RESOULUTION DEFAULT_WINDOW_RESOULUTION_X, DEFAULT_WINDOW_RESOULUTION_Y
#define GAME_WORLD_X 600
#define GAME_WORLD_Y 1000
#define GAME_RESOULUTION GAME_WORLD_X, GAME_WORLD_Y

Vector2u scaledGameResolution;
Vector2f scaledGameResolutionNormal;
Vector2u scaledGameOffset;
Vector2f scaledGameOffsetNormal;

View gameView;
View menuView;
enum Gamestates {Start,Game,Pause,Dead};
Gamestates state = Gamestates::Start;

const string filepath = "..\\res/";
static const string textureNames[]{"img/spaceship1.png",
                                   "img/spaceship2.png",
                                   "img/spaceship3.png",
                                   "img/Spaceship-Drakir1.png",
                                   "img/Spaceship-Drakir2.png",
                                   "img/Spaceship-Drakir3.png",
                                   "img/Spaceship-Drakir4.png",
                                   "img/Spaceship-Drakir5.png",
                                   "img/Spaceship-Drakir6.png",
                                   "img/Spaceship-Drakir7.png",
                                   "img/bullet.png"};

Texture *textures[11];
Font *gameFont;
Sprite *playerSprite;
Sprite *bulletsprite;
Text *scoreText;
Text *menuText;
static Sprite *enemies[MAX_ENEMIES];

static unsigned int currentEnemies = 0;
float playerMoveSpeed = 600.0f;
unsigned int score = 0;
float runTime = 0; // time in seconds that the game has been running
high_resolution_clock::time_point previous;

static Vector2f GetNewEnemyPos() { return Vector2f((float)(rand() % GAME_WORLD_Y), -128.0f); }

void Resize(RenderWindow &window) {
  const Vector2f win = (Vector2f)window.getSize();
  float scale = 1.0f;
  float scale2 = 1.0f;
  const float GWX = (float)GAME_WORLD_X;
  const float GWY = (float)GAME_WORLD_Y;
  if (win.y > win.x) {
    // wide
    scale = win.x / GWX;
    if (win.y < (scale * GWY)) {
      scale2 = win.y / GWY;
    }
  } else {
    // tall (or square)
    scale = win.y / GWY;
    if (win.x < (scale * GWX)) {
      scale2 = win.x / GWX;
    }
  }
  scale = min(scale, scale2);
  scaledGameResolution =
      Vector2u((unsigned int)floor(scale * GWX), (unsigned int)floor(scale * GWY));
  scaledGameOffset = Vector2u((unsigned int)max(0.0f, (win.x - scaledGameResolution.x) * 0.5f),
                              (unsigned int)max(0.0f, (win.y - scaledGameResolution.y) * 0.5f));
  scaledGameResolutionNormal =
      Vector2f((float)scaledGameResolution.x / win.x, (float)scaledGameResolution.y / win.y);
  scaledGameOffsetNormal =
      Vector2f((float)scaledGameOffset.x / win.x, (float)scaledGameOffset.y / win.y);
}

void Loadcontent() {
  gameFont = new Font();
  gameFont->loadFromFile(filepath + "/fonts/AmericanCaptain.ttf");
  scoreText = new Text();
  scoreText->setFont(*gameFont);
  scoreText->setPosition(0, 0);
  scoreText->setCharacterSize(24);
  scoreText->setColor(Color::Red);

  menuText = new Text();
  menuText->setFont(*gameFont);
  menuText->setCharacterSize(24);
  menuText->setColor(Color::White);

  for (size_t i = 0; i < 11; i++) {
    textures[i] = new Texture();
    if (!textures[i]->loadFromFile(filepath + textureNames[i])) {
      throw invalid_argument("Loading error!");
    }
  }
  playerSprite = new Sprite();
  playerSprite->setTexture(*textures[0]);
  playerSprite->setPosition(512, 256);
  bulletsprite = new Sprite();
  bulletsprite->setTexture(*textures[10]);
  bulletsprite->setPosition(0, -128.0f);
  for (auto &e : enemies) {
    e = new Sprite();
    e->setTexture(*textures[(rand() % 7) + 3]);
    e->setPosition(GetNewEnemyPos());
  }
}

void Unload() {
  for (auto &t : textures) {
    delete t;
    t = nullptr;
  }
  for (auto &e : enemies) {
    delete e;
    e = nullptr;
  }
  delete gameFont;
  gameFont = nullptr;
  delete scoreText;
  scoreText = nullptr;
  delete bulletsprite;
  bulletsprite = nullptr;
  delete playerSprite;
  playerSprite = nullptr;
}

void Normalize(Vector2f &v) {
  float length = sqrt(v.x * v.x + v.y * v.y);
  if (length == 0.0f) {
    return;
  }
  v.x /= length;
  v.y /= length;
}

void FireBullet() {
  if (bulletsprite->getPosition().y <= -128.0f) {
    bulletsprite->setPosition(playerSprite->getPosition().x + 30,
                              playerSprite->getPosition().y - 1);
  }
}
void ResetGame() {
  score = 0;
  runTime = 0;
  currentEnemies = 0;
  playerSprite->setPosition(512, 256);
  for (auto e : enemies) {
    e->setPosition(GetNewEnemyPos());
  }
}
void PlayerDeath() {}

void menuUpdate(RenderWindow &window) {

	Event e;

	while (window.pollEvent(e)) {

		if (e.type == Event::Closed)
			window.close();

		if (e.type == sf::Event::Resized) {
			Resize(window);
			menuView.setViewport(FloatRect(scaledGameOffsetNormal.x, scaledGameOffsetNormal.y,
				scaledGameResolutionNormal.x, scaledGameResolutionNormal.y));
			window.setView(menuView);
		}

		sf::Vector2i mousePosition = sf::Mouse::getPosition(window);

		if (menuText->getGlobalBounds().contains((sf::Vector2f)mousePosition)) {
			menuText->setColor(Color::Red);
		}
		else {
			menuText->setColor(Color::White);
		}
		// keyboard event handling
		if (e.type == Event::KeyPressed) {
			if (e.key.code == Keyboard::Escape) {
				window.close();
			}
			else if (e.key.code == Keyboard::B) {
				Resize(window);
			}
			else if (e.key.code == Keyboard::S && state == Gamestates::Start || state == Gamestates::Pause) {
				state = Gamestates::Game;
			}
		}
	}

}

void Update(RenderWindow &window) {

  high_resolution_clock::time_point now = high_resolution_clock::now();
  // time in nanoseconds since last update
  const auto delta = (duration_cast<duration<unsigned int, nano>>(now - previous)).count();
  const float deltaSeconds = ((float)delta) / 1000000000.0f;
  previous = now;

  runTime += deltaSeconds;
  currentEnemies = min((int)ceil(runTime * 0.6f) + 1, MAX_ENEMIES);

  { // Input
    Event e;
    Vector2f moveDirection(0, 0);

    while (window.pollEvent(e)) {

      if (e.type == Event::Closed)
        window.close();

      if (e.type == sf::Event::Resized) {
        Resize(window);
        gameView.setViewport(FloatRect(scaledGameOffsetNormal.x, scaledGameOffsetNormal.y,
                                       scaledGameResolutionNormal.x, scaledGameResolutionNormal.y));
        window.setView(gameView);
      }

      // keyboard event handling
      if (e.type == Event::KeyPressed) {
        if (e.key.code == Keyboard::Escape) {
          window.close();
        } else if (e.key.code == Keyboard::Space) {
          FireBullet();
        } else if (e.key.code == Keyboard::B) {
          Resize(window);
        }
      }
	  if (Keyboard::isKeyPressed(Keyboard::P)) {
		  state = Gamestates::Pause;
	  }
    }

    if (Keyboard::isKeyPressed(Keyboard::Space)) {
      FireBullet();
    }

    if (Keyboard::isKeyPressed(Keyboard::Up) || Keyboard::isKeyPressed(Keyboard::W)) {
      moveDirection += Vector2f(0, -1);
    }
    if (Keyboard::isKeyPressed(Keyboard::Down) || Keyboard::isKeyPressed(Keyboard::S)) {
      moveDirection += Vector2f(0, 1);
    }
    if (Keyboard::isKeyPressed(Keyboard::Left) || Keyboard::isKeyPressed(Keyboard::A)) {
      moveDirection += Vector2f(-1, 0);
    }
    if (Keyboard::isKeyPressed(Keyboard::Right) || Keyboard::isKeyPressed(Keyboard::D)) {
      moveDirection += Vector2f(1, 0);
    }

    // joystick input
    if (Joystick::isConnected(0)) {
      const float joystickX = Joystick::getAxisPosition(0, Joystick::X);
      const float joystickY = Joystick::getAxisPosition(0, Joystick::Y);

      if (abs(joystickX) > 40.0f) {
        moveDirection += Vector2f((float)((signbit(joystickX) * -2) + 1), 0);
      }
      if (abs(joystickY) > 40.0f) {
        moveDirection += Vector2f(0, (float)((signbit(joystickY) * -2) + 1));
      }

	  if (Joystick::isButtonPressed(0, 2)) {
		  state == Gamestates::Pause;
	  }
      if (Joystick::isButtonPressed(0, 1)) {
        FireBullet();
      }
    }
    if (playerSprite->getPosition().x < 0) {
      moveDirection.x = max(0.0f, moveDirection.x);
    }
    if (playerSprite->getPosition().y < 0) {
      moveDirection.y = max(0.0f, moveDirection.y);
    }
    if (playerSprite->getPosition().x > (GAME_WORLD_X - playerSprite->getLocalBounds().width)) {
      moveDirection.x = min(0.0f, moveDirection.x);
    }
    if (playerSprite->getPosition().y > (GAME_WORLD_Y - playerSprite->getLocalBounds().height)) {
      moveDirection.y = min(0.0f, moveDirection.y);
    }
    Normalize(moveDirection);
    moveDirection = (moveDirection * playerMoveSpeed) * deltaSeconds;

    playerSprite->setPosition(playerSprite->getPosition() + moveDirection);
  } // End Input

  if (bulletsprite->getPosition().y > -128.0f) {
    bulletsprite->setPosition(bulletsprite->getPosition().x,
                              bulletsprite->getPosition().y - 1000.0f * deltaSeconds);
  }

  for (size_t i = 0; i < MAX_ENEMIES; i++) {
    if (i < currentEnemies) {
      // if not dead, move
      if (enemies[i]->getPosition().y < GAME_WORLD_X) {
        enemies[i]->setPosition(
            enemies[i]->getPosition() +
            Vector2f(sinf(runTime + i) * 100.0f * deltaSeconds, 100.0f * deltaSeconds));
        // collisions
        if (bulletsprite->getGlobalBounds().intersects(enemies[i]->getGlobalBounds())) {
          enemies[i]->setPosition(GetNewEnemyPos());
          score += 100;
        }
        if (playerSprite->getGlobalBounds().intersects(enemies[i]->getGlobalBounds())) {
          PlayerDeath();
        }
      } else {
        // enemy is offscreen, kill
        enemies[i]->setPosition(GetNewEnemyPos());
      }
    } else {
      // if alive
      if (enemies[i]->getPosition().y != -128.0f) {
        // kill
        enemies[i]->setPosition(GetNewEnemyPos());
      }
    }
  }

  scoreText->setString("Score =" + to_string(score + ceil(runTime)));
}

void menuRender(RenderWindow &window) {
	window.clear(sf::Color::Black);
	menuText->setString("Insert game name here");

	RectangleShape rectangle(Vector2f(0, 0));
	rectangle.setSize(Vector2f(GAME_RESOULUTION));
	rectangle.setFillColor(Color::Green);
	menuText->setPosition(rectangle.getSize().x / 2, 0);
	window.draw(rectangle);
	window.draw(*menuText);
	window.display();
}

void Render(RenderWindow &window) {
  window.clear(sf::Color::Black);
  RectangleShape rectangle(Vector2f(0, 0));
  rectangle.setSize(Vector2f(GAME_RESOULUTION));
  rectangle.setFillColor(Color::Green);
  window.draw(rectangle);

  window.draw(*playerSprite);
  window.draw(*bulletsprite);
  for (size_t i = 0; i < currentEnemies; i++) {
    window.draw(*enemies[i]);
  }
  window.draw(*scoreText);
  window.display();
}

int main() {
  Loadcontent();
  RenderWindow *window =
      new RenderWindow(VideoMode(DEFAULT_WINDOW_RESOULUTION), "Advanced Minigame");
  window->setVerticalSyncEnabled(true);
  Resize(*window);

  // let's define  the game view
  gameView = View(FloatRect(0, 0, GAME_RESOULUTION));
  gameView.setViewport(FloatRect(scaledGameOffsetNormal.x, scaledGameOffsetNormal.y,
                                 scaledGameResolutionNormal.x, scaledGameResolutionNormal.y));

  // let's define the menu view
  menuView = View(FloatRect(0, 0, GAME_RESOULUTION));
  menuView.setViewport(FloatRect(scaledGameOffsetNormal.x, scaledGameOffsetNormal.y,
	  scaledGameResolutionNormal.x, scaledGameResolutionNormal.y));

  previous = high_resolution_clock::now();

	  while (window->isOpen()) {
		  if (state == Gamestates::Start)
		  {
			  menuUpdate(*window);
			  menuRender(*window);

		  }
		  else if (state == Gamestates::Game) {
			  // Activate gameview
			  Update(*window);
			  Render(*window);
		  }
		  else if (state == Gamestates::Pause)
		  {
			  menuUpdate(*window);
			  menuRender(*window);
		  }
	  }

  Unload();
  delete window;
  window = nullptr;
  return 0;
}<|endoftext|>


<commit_before>#define PUGIXML_NO_EXCEPTIONS
#define PUGIXML_HEADER_ONLY

#include <string>
#include "json/json.hpp"
#include "pugixml/src/pugixml.hpp"

using json = nlohmann::json;
using string = std::string;
using xquery = pugi::xpath_query;
using nodeset = pugi::xpath_node_set;

enum ReturnType { NUMBER, STRING, BOOLEAN };

template <typename T>
void walk(T& doc, json& n, json& output, string key);

inline bool string_contains(string to_check, string prefix) {
  return to_check.size() >= prefix.size() &&
         to_check.compare(0, prefix.size(), prefix) == 0;
}

inline ReturnType get_return_type(string& path) {
  if (string_contains(path, "count(") || string_contains(path, "sum(") ||
      string_contains(path, "number(") || string_contains(path, "ceiling(") ||
      string_contains(path, "floor(") || string_contains(path, "round("))
    return NUMBER;

  if (string_contains(path, "boolean("))
    return BOOLEAN;
  return STRING;
}

template <typename T>
bool seek_single_boolean(T& xnode, json& j) {
  string path = j;
  xquery query(path.c_str());
  return query.evaluate_boolean(xnode);
}

template <typename T>
string seek_single_string(T& xnode, json& j) {
  string path = j;
  if (path.empty()) {
    return "";
  } else if (path.find("#") != std::string::npos) {
    return path.substr(1, path.size());
  } else {
    xquery query(path.c_str());
    return query.evaluate_string(xnode);
  }
}

template <typename T>
double seek_single_number(T& xnode, json& j) {
  string path = j;
  xquery query(path.c_str());
  return query.evaluate_number(xnode);
}

template <typename T>
json seek_array(T& doc, json& node) {
  // a special case for backward compatible with xpath-object-transform
  if (node.empty()) {
    return json::array();
  }

  string base_path = node[0];
  xquery q(base_path.c_str());
  pugi::xpath_node_set nodes = q.evaluate_node_set(doc);
  json tmp = json::array();

  for (size_t i = 0; i < nodes.size(); ++i) {
    pugi::xpath_node n = nodes[i];
    auto inner = node[1];

    if (inner.is_object()) {
      json obj = json({});
      for (json::iterator it = inner.begin(); it != inner.end(); ++it) {
        walk(n, it.value(), obj, it.key());
      }

      tmp.push_back(obj);
    } else if (inner.is_string()) {
      string path = inner;
      ReturnType type = get_return_type((path));
      if (type == NUMBER) {
        tmp.push_back(seek_single_number(n, inner));
      }
      if (type == STRING) {
        tmp.push_back(seek_single_string(n, inner));
      }
      if (type == BOOLEAN) {
        tmp.push_back(seek_single_boolean(n, inner));
      }
    }
  }

  return tmp;
}

template <typename T>
json seek_object(T& doc, json& node) {
  auto output = json({});
  for (json::iterator it = node.begin(); it != node.end(); ++it) {
    string key = it.key();
    walk(doc, *it, output, key);
  }
  return output;
}

template <typename T>
void walk(T& doc, json& n, json& output, string key) {
  if (n.is_array()) {
    output[key] = seek_array(doc, n);
  } else if (n.is_object()) {
    output[key] = seek_object(doc, n);
  } else if (n.is_string()) {
    string path = n;
    ReturnType type = get_return_type(path);
    if (type == NUMBER) {
      output[key] = seek_single_number(doc, n);
    }
    if (type == STRING) {
      output[key] = seek_single_string(doc, n);
    }
    if (type == BOOLEAN) {
      output[key] = seek_single_boolean(doc, n);
    }
  }
}

string transform(string xml, string fmt) {
  pugi::xml_document doc;
  if (!doc.load_string(xml.c_str())) {
    return "";
  }

  auto j = json::parse(fmt);
  json result;

  for (json::iterator it = j.begin(); it != j.end(); ++it) {
    string key = it.key();
    auto& node = j[key];
    walk(doc, node, result, key);
  }

  return result.dump();
}<commit_msg>fix: error C2365: 'BOOLEAN': redefinition<commit_after>#define PUGIXML_NO_EXCEPTIONS
#define PUGIXML_HEADER_ONLY

#include <string>
#include "json/json.hpp"
#include "pugixml/src/pugixml.hpp"

using json = nlohmann::json;
using string = std::string;
using xquery = pugi::xpath_query;
using nodeset = pugi::xpath_node_set;

enum ReturnType { T_NUMBER, T_STRING, T_BOOLEAN };

template <typename T>
void walk(T& doc, json& n, json& output, string key);

inline bool string_contains(string to_check, string prefix) {
  return to_check.size() >= prefix.size() &&
         to_check.compare(0, prefix.size(), prefix) == 0;
}

inline ReturnType get_return_type(string& path) {
  if (string_contains(path, "count(") || string_contains(path, "sum(") ||
      string_contains(path, "number(") || string_contains(path, "ceiling(") ||
      string_contains(path, "floor(") || string_contains(path, "round("))
    return T_NUMBER;

  if (string_contains(path, "boolean("))
    return T_BOOLEAN;
  return T_STRING;
}

template <typename T>
bool seek_single_boolean(T& xnode, json& j) {
  string path = j;
  xquery query(path.c_str());
  return query.evaluate_boolean(xnode);
}

template <typename T>
string seek_single_string(T& xnode, json& j) {
  string path = j;
  if (path.empty()) {
    return "";
  } else if (path.find("#") != std::string::npos) {
    return path.substr(1, path.size());
  } else {
    xquery query(path.c_str());
    return query.evaluate_string(xnode);
  }
}

template <typename T>
double seek_single_number(T& xnode, json& j) {
  string path = j;
  xquery query(path.c_str());
  return query.evaluate_number(xnode);
}

template <typename T>
json seek_array(T& doc, json& node) {
  // a special case for backward compatible with xpath-object-transform
  if (node.empty()) {
    return json::array();
  }

  string base_path = node[0];
  xquery q(base_path.c_str());
  pugi::xpath_node_set nodes = q.evaluate_node_set(doc);
  json tmp = json::array();

  for (size_t i = 0; i < nodes.size(); ++i) {
    pugi::xpath_node n = nodes[i];
    auto inner = node[1];

    if (inner.is_object()) {
      json obj = json({});
      for (json::iterator it = inner.begin(); it != inner.end(); ++it) {
        walk(n, it.value(), obj, it.key());
      }

      tmp.push_back(obj);
    } else if (inner.is_string()) {
      string path = inner;
      ReturnType type = get_return_type((path));
      if (type == T_NUMBER) {
        tmp.push_back(seek_single_number(n, inner));
      }
      if (type == T_STRING) {
        tmp.push_back(seek_single_string(n, inner));
      }
      if (type == T_BOOLEAN) {
        tmp.push_back(seek_single_boolean(n, inner));
      }
    }
  }

  return tmp;
}

template <typename T>
json seek_object(T& doc, json& node) {
  auto output = json({});
  for (json::iterator it = node.begin(); it != node.end(); ++it) {
    string key = it.key();
    walk(doc, *it, output, key);
  }
  return output;
}

template <typename T>
void walk(T& doc, json& n, json& output, string key) {
  if (n.is_array()) {
    output[key] = seek_array(doc, n);
  } else if (n.is_object()) {
    output[key] = seek_object(doc, n);
  } else if (n.is_string()) {
    string path = n;
    ReturnType type = get_return_type(path);
    if (type == T_NUMBER) {
      output[key] = seek_single_number(doc, n);
    }
    if (type == T_STRING) {
      output[key] = seek_single_string(doc, n);
    }
    if (type == T_BOOLEAN) {
      output[key] = seek_single_boolean(doc, n);
    }
  }
}

string transform(string xml, string fmt) {
  pugi::xml_document doc;
  if (!doc.load_string(xml.c_str())) {
    return "";
  }

  auto j = json::parse(fmt);
  json result;

  for (json::iterator it = j.begin(); it != j.end(); ++it) {
    string key = it.key();
    auto& node = j[key];
    walk(doc, node, result, key);
  }

  return result.dump();
}<|endoftext|>


<commit_before>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
 * CONDOR Copyright Notice
 *
 * See LICENSE.TXT for additional notices and disclaimers.
 *
 * Copyright (c)1990-1998 CONDOR Team, Computer Sciences Department,
 * University of Wisconsin-Madison, Madison, WI.  All Rights Reserved.
 * No use of the CONDOR Software Program Source Code is authorized
 * without the express consent of the CONDOR Team.  For more information
 * contact: CONDOR Team, Attention: Professor Miron Livny,
 * 7367 Computer Sciences, 1210 W. Dayton St., Madison, WI 53706-1685,
 * (608) 262-0856 or miron@cs.wisc.edu.
 *
 * U.S. Government Rights Restrictions: Use, duplication, or disclosure
 * by the U.S. Government is subject to restrictions as set forth in
 * subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and
 * (2) of Commercial Computer Software-Restricted Rights at 48 CFR
 * 52.227-19, as applicable, CONDOR Team, Attention: Professor Miron
 * Livny, 7367 Computer Sciences, 1210 W. Dayton St., Madison,
 * WI 53706-1685, (608) 262-0856 or miron@cs.wisc.edu.
****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/

#include "condor_common.h"
#include "condor_debug.h"
#include "condor_config.h"

#include "daemon.h"
#include "condor_string.h"
#include "condor_attributes.h"
#include "condor_adtypes.h"
#include "condor_query.h"
#include "get_daemon_addr.h"
#include "get_full_hostname.h"
#include "my_hostname.h"
#include "internet.h"

Daemon::Daemon( daemon_t type, const char* name, const char* pool )
{
	char buf[256], *tmp;
	_type = type;
	_addr = NULL;
	_port = 0;
	_is_local = false;
	memset( (void*)&_sin_addr, '\0', sizeof(struct in_addr) );

	if( name ) {
			// Make sure we fully resolve the hostname
		_name = get_daemon_name( name );
	} else {
		_name = NULL;
	}

	if( pool ) {
		_pool = strnewp( pool );
	} else {
		_pool = NULL;
	}

		// Get all the other info.
	init();

		// init() will always fill in _full_hostname, but not
		// _hostname.  In all cases, we just want to trim off the
		// domain the same way.
	strcpy( buf, _full_hostname );
	tmp = strchr( buf, '.' );
	if( tmp ) {
		*tmp = '\0';
	}
	_hostname = strnewp( buf );

		// Now that we're done with the init() code, if we still don't
		// have a name, fill that in.
	if( ! _name ) {
		_name = my_daemon_name( daemonString(type) );
	}
}

Daemon::~Daemon()
{
	if( _name ) delete [] _name;
	if( _pool ) delete [] _pool;
	if( _addr ) delete [] _addr;
	if( _hostname ) delete [] _hostname;
	if( _full_hostname ) delete [] _full_hostname;
}

ReliSock*
Daemon::reliSock( int sec )
{
	ReliSock* reli;
	reli = new ReliSock();
	if( sec ) {
		reli->timeout( sec );
	}
	if( reli->connect(_addr, 0) ) {
		return reli;
	} else {
		delete reli;
		return NULL;
	}
}

SafeSock*
Daemon::safeSock( int sec )
{
	SafeSock* safe;
	safe = new SafeSock();
	if( sec ) {
		safe->timeout( sec );
	}
	if( safe->connect(_addr, 0) ) {
		return safe;
	} else {
		delete safe;
		return NULL;
	}
}

void
Daemon::init()
{
	switch( _type ) {
	case DT_SCHEDD:
		get_daemon_info( "SCHEDD", ATTR_SCHEDD_IP_ADDR, SCHEDD_AD );
		break;
	case DT_STARTD:
		get_daemon_info( "STARTD", ATTR_STARTD_IP_ADDR, STARTD_AD );
		break;
	case DT_MASTER:
		get_daemon_info( "MASTER", ATTR_MASTER_IP_ADDR, MASTER_AD );
		break;
	case DT_COLLECTOR:
		if( ! get_cm_info("COLLECTOR", COLLECTOR_PORT) ) {
			EXCEPT( "Daemon: no host or address for COLLECTOR in config file" );
		}
		break;
	case DT_NEGOTIATOR:
		if( ! get_cm_info("NEGOTIATOR", NEGOTIATOR_PORT) ) {
			EXCEPT( "Daemon: no host or address for NEGOTIATOR in config file" );
		}
		break;
	case DT_VIEW_COLLECTOR:
		if( get_cm_info("CONDOR_VIEW", COLLECTOR_PORT) ) {
				// If we found it, we're done.
			break;
		}
			// If there's nothing CONDOR_VIEW-specific, try just using
			// "COLLECTOR".
		if( ! get_cm_info("COLLECTOR", COLLECTOR_PORT) ) {
			EXCEPT( "Daemon: no host or address for CONDOR_VIEW or COLLECTOR in config file" );
		}
		break;
	default:
		EXCEPT( "Unknown daemon type (%d) in Daemon::init", _type );
	}

}

void
Daemon::get_daemon_info( const char* subsys,
						 const char* attribute, AdTypes adtype )
{
	char				buf[500];
	char				*addr_file, *tmp, *my_name;
	FILE				*addr_fp;
	struct sockaddr_in	sin;

		// See what the local daemon would be named.
	my_name = my_daemon_name( subsys );

		// Figure out if we want to find a local daemon or not, and
		// fill in the various hostname fields.
	if( _name && *_name ) {
		if( !strcmp( _name, my_name ) ) {
			_is_local = true;
		}
		_full_hostname = strnewp( get_host_part(_name) );
	} else {
		_is_local = true;
			// We might have a copy of an empty string here, so
			// prevent a potential memory leak.
		if( _name ) delete [] _name;
		_name = strnewp( my_name );
		_full_hostname = strnewp( my_full_hostname() );
		_sin_addr = *(my_sin_addr());
	}

		// We're done with this now.
	delete [] my_name;

	if( _is_local ) {
		sprintf( buf, "%s_ADDRESS_FILE", subsys );
		addr_file = param( buf );
		if( addr_file ) {
			if( (addr_fp = fopen(addr_file, "r")) ) {
					// Read out the sinful string.
				fgets( buf, 100, addr_fp );
				fclose( addr_fp );
					// chop off the newline
				tmp = strchr( buf, '\n' );
				if( tmp ) {
					*tmp = '\0';
				}
			}
			free( addr_file );
		}
		if( is_valid_sinful(buf) ) {
			_addr = strnewp( buf );
		}
	}

	if( ! _addr ) {
		CondorQuery			query(adtype);
		ClassAd*			scan;
		ClassAdList			ads;

		sprintf(buf, "%s == \"%s\"", ATTR_NAME, _name );
		query.addConstraint(buf);
		query.fetchAds(ads, _pool);
		ads.Open();
		scan = ads.Next();
		if(!scan) {
				// Badness XXX
			return;
		}
		if(scan->EvalString(attribute, NULL, buf) == FALSE) {
				// Badness XXX
			return;
		}
		_addr = strnewp( buf );
	}

		// Now that we have the sinful string, fill in some other
		// goodies.
	_port = string_to_port( _addr );
	if( ! _sin_addr.s_addr ) {
		string_to_sin( _addr, &sin );
		_sin_addr = sin.sin_addr;
	}
}

bool
Daemon::get_cm_info( const char* subsys, int port )
{
	char buf[64];
	struct hostent* hostp;
	char* host = NULL;

		// We know this without any work.
	_port = port;

		// Figure out what name we're really going to use.
	if( _name && *_name ) {
			// If we were given a name, use that.
		host = strdup( _name );
	}

	if( ! host ) {
			// Try the config file for a subsys-specific IP addr
		sprintf( buf, "%s_IP_ADDR", subsys );
		host = param( buf );
	}

	if( ! host ) {
			// Try the config file for a CM-specific IP addr
		host = param( "CM_IP_ADDR" );
	}

	if( ! host ) {
			// Try the config file for a subsys-specific hostname
		sprintf( buf, "%s_HOST", subsys );
		host = param( buf );
	}

	if( ! host ) {
			// Try the config file for a CM-specific hostname
		host = param( "CM_HOST" );
	}

	if( ! host ) {
		return false;
	}

	if( is_ipaddr(host, &_sin_addr) ) {
		sprintf( buf, "<%s:%d>", host, _port );
		free( host );
		_addr = strnewp( buf );
			// Make sure we've got the canonical name
		hostp = gethostbyaddr( (char*)&_sin_addr,
							   sizeof(struct in_addr), AF_INET );
		if( ! hostp ) {
				// BADNESS - what to do?
			return false;
		}
		_full_hostname = strnewp( hostp->h_name );
	} else {
			// We were given a hostname, not an address.
		hostp = gethostbyname( host );
		free( host );
		if( ! hostp ) {
				// BADNESS - what to do?
			return false;
		}
		_sin_addr = *(struct in_addr*)(hostp->h_addr_list[0]);
		sprintf( buf, "<%s:%d>", inet_ntoa(_sin_addr), _port );
		_addr = strnewp( buf );
		_full_hostname = strnewp( hostp->h_name );
	}
	if( ! _name ) {
		_name = strnewp( _full_hostname );
	}
	if( !strcmp(_full_hostname, my_full_hostname()) ) {
		_is_local = true;
	}
	return true;
}

<commit_msg>changed so if an inverse DNS lookup fails, it is not a fatal error.  this change allows someone to use an IP address with -pool options, even when the IP address does not have a DNS entry.<commit_after>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
 * CONDOR Copyright Notice
 *
 * See LICENSE.TXT for additional notices and disclaimers.
 *
 * Copyright (c)1990-1998 CONDOR Team, Computer Sciences Department,
 * University of Wisconsin-Madison, Madison, WI.  All Rights Reserved.
 * No use of the CONDOR Software Program Source Code is authorized
 * without the express consent of the CONDOR Team.  For more information
 * contact: CONDOR Team, Attention: Professor Miron Livny,
 * 7367 Computer Sciences, 1210 W. Dayton St., Madison, WI 53706-1685,
 * (608) 262-0856 or miron@cs.wisc.edu.
 *
 * U.S. Government Rights Restrictions: Use, duplication, or disclosure
 * by the U.S. Government is subject to restrictions as set forth in
 * subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and
 * (2) of Commercial Computer Software-Restricted Rights at 48 CFR
 * 52.227-19, as applicable, CONDOR Team, Attention: Professor Miron
 * Livny, 7367 Computer Sciences, 1210 W. Dayton St., Madison,
 * WI 53706-1685, (608) 262-0856 or miron@cs.wisc.edu.
****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/

#include "condor_common.h"
#include "condor_debug.h"
#include "condor_config.h"

#include "daemon.h"
#include "condor_string.h"
#include "condor_attributes.h"
#include "condor_adtypes.h"
#include "condor_query.h"
#include "get_daemon_addr.h"
#include "get_full_hostname.h"
#include "my_hostname.h"
#include "internet.h"

Daemon::Daemon( daemon_t type, const char* name, const char* pool )
{
	char buf[256], *tmp;
	_type = type;
	_addr = NULL;
	_port = 0;
	_is_local = false;
	memset( (void*)&_sin_addr, '\0', sizeof(struct in_addr) );

	if( name && name[0] ) {
			// Make sure we fully resolve the hostname
		_name = get_daemon_name( name );
	} else {
		_name = NULL;
	}

	if( pool ) {
		_pool = strnewp( pool );
	} else {
		_pool = NULL;
	}

		// Get all the other info.
	init();

		// init() will always fill in _full_hostname, but not
		// _hostname.  In all cases, we just want to trim off the
		// domain the same way.
	strcpy( buf, _full_hostname );
	tmp = strchr( buf, '.' );
	if( tmp ) {
		*tmp = '\0';
	}
	_hostname = strnewp( buf );

		// Now that we're done with the init() code, if we still don't
		// have a name, fill that in.
	if( ! _name ) {
		_name = my_daemon_name( daemonString(type) );
	}
}

Daemon::~Daemon()
{
	if( _name ) delete [] _name;
	if( _pool ) delete [] _pool;
	if( _addr ) delete [] _addr;
	if( _hostname ) delete [] _hostname;
	if( _full_hostname ) delete [] _full_hostname;
}

ReliSock*
Daemon::reliSock( int sec )
{
	ReliSock* reli;
	reli = new ReliSock();
	if( sec ) {
		reli->timeout( sec );
	}
	if( reli->connect(_addr, 0) ) {
		return reli;
	} else {
		delete reli;
		return NULL;
	}
}

SafeSock*
Daemon::safeSock( int sec )
{
	SafeSock* safe;
	safe = new SafeSock();
	if( sec ) {
		safe->timeout( sec );
	}
	if( safe->connect(_addr, 0) ) {
		return safe;
	} else {
		delete safe;
		return NULL;
	}
}

void
Daemon::init()
{
	switch( _type ) {
	case DT_SCHEDD:
		get_daemon_info( "SCHEDD", ATTR_SCHEDD_IP_ADDR, SCHEDD_AD );
		break;
	case DT_STARTD:
		get_daemon_info( "STARTD", ATTR_STARTD_IP_ADDR, STARTD_AD );
		break;
	case DT_MASTER:
		get_daemon_info( "MASTER", ATTR_MASTER_IP_ADDR, MASTER_AD );
		break;
	case DT_COLLECTOR:
		if( ! get_cm_info("COLLECTOR", COLLECTOR_PORT) ) {
			EXCEPT( "Daemon: no host or address for COLLECTOR in config file" );
		}
		break;
	case DT_NEGOTIATOR:
		if( ! get_cm_info("NEGOTIATOR", NEGOTIATOR_PORT) ) {
			EXCEPT( "Daemon: no host or address for NEGOTIATOR in config file" );
		}
		break;
	case DT_VIEW_COLLECTOR:
		if( get_cm_info("CONDOR_VIEW", COLLECTOR_PORT) ) {
				// If we found it, we're done.
			break;
		}
			// If there's nothing CONDOR_VIEW-specific, try just using
			// "COLLECTOR".
		if( ! get_cm_info("COLLECTOR", COLLECTOR_PORT) ) {
			EXCEPT( "Daemon: no host or address for CONDOR_VIEW or COLLECTOR in config file" );
		}
		break;
	default:
		EXCEPT( "Unknown daemon type (%d) in Daemon::init", _type );
	}

}

void
Daemon::get_daemon_info( const char* subsys,
						 const char* attribute, AdTypes adtype )
{
	char				buf[500];
	char				*addr_file, *tmp, *my_name;
	FILE				*addr_fp;
	struct sockaddr_in	sin;

		// See what the local daemon would be named.
	my_name = my_daemon_name( subsys );

		// Figure out if we want to find a local daemon or not, and
		// fill in the various hostname fields.
	if( _name && *_name ) {
		if( !strcmp( _name, my_name ) ) {
			_is_local = true;
		}
		_full_hostname = strnewp( get_host_part(_name) );
	} else {
		_is_local = true;
			// We might have a copy of an empty string here, so
			// prevent a potential memory leak.
		if( _name ) delete [] _name;
		_name = strnewp( my_name );
		_full_hostname = strnewp( my_full_hostname() );
		_sin_addr = *(my_sin_addr());
	}

		// We're done with this now.
	delete [] my_name;

	if( _is_local ) {
		sprintf( buf, "%s_ADDRESS_FILE", subsys );
		addr_file = param( buf );
		if( addr_file ) {
			if( (addr_fp = fopen(addr_file, "r")) ) {
					// Read out the sinful string.
				fgets( buf, 100, addr_fp );
				fclose( addr_fp );
					// chop off the newline
				tmp = strchr( buf, '\n' );
				if( tmp ) {
					*tmp = '\0';
				}
			}
			free( addr_file );
		}
		if( is_valid_sinful(buf) ) {
			_addr = strnewp( buf );
		}
	}

	if( ! _addr ) {
		CondorQuery			query(adtype);
		ClassAd*			scan;
		ClassAdList			ads;

		sprintf(buf, "%s == \"%s\"", ATTR_NAME, _name );
		query.addConstraint(buf);
		query.fetchAds(ads, _pool);
		ads.Open();
		scan = ads.Next();
		if(!scan) {
				// Badness XXX
			return;
		}
		if(scan->EvalString(attribute, NULL, buf) == FALSE) {
				// Badness XXX
			return;
		}
		_addr = strnewp( buf );
	}

		// Now that we have the sinful string, fill in some other
		// goodies.
	_port = string_to_port( _addr );
	if( ! _sin_addr.s_addr ) {
		string_to_sin( _addr, &sin );
		_sin_addr = sin.sin_addr;
	}
}

bool
Daemon::get_cm_info( const char* subsys, int port )
{
	char buf[64];
	struct hostent* hostp;
	char* host = NULL;

		// We know this without any work.
	_port = port;

		// Figure out what name we're really going to use.
	if( _name && *_name ) {
			// If we were given a name, use that.
		host = strdup( _name );
	}

	if( ! host ) {
			// Try the config file for a subsys-specific IP addr
		sprintf( buf, "%s_IP_ADDR", subsys );
		host = param( buf );
	}

	if( ! host ) {
			// Try the config file for a CM-specific IP addr
		host = param( "CM_IP_ADDR" );
	}

	if( ! host ) {
			// Try the config file for a subsys-specific hostname
		sprintf( buf, "%s_HOST", subsys );
		host = param( buf );
	}

	if( ! host ) {
			// Try the config file for a CM-specific hostname
		host = param( "CM_HOST" );
	}

	if( ! host ) {
		return false;
	}

	if( is_ipaddr(host, &_sin_addr) ) {
		sprintf( buf, "<%s:%d>", host, _port );
		free( host );
		_addr = strnewp( buf );
			// Make sure we've got the canonical name
		hostp = gethostbyaddr( (char*)&_sin_addr,
							   sizeof(struct in_addr), AF_INET );
		if( ! hostp ) {
				// BADNESS - what to do?
				// Whatever we do, this should not be a fatal error. -Todd
			_full_hostname = strnewp(" ");
		} else {
			_full_hostname = strnewp( hostp->h_name );
		}
	} else {
			// We were given a hostname, not an address.
		hostp = gethostbyname( host );
		free( host );
		if( ! hostp ) {
				// BADNESS - what to do?
			return false;
		}
		_sin_addr = *(struct in_addr*)(hostp->h_addr_list[0]);
		sprintf( buf, "<%s:%d>", inet_ntoa(_sin_addr), _port );
		_addr = strnewp( buf );
		_full_hostname = strnewp( hostp->h_name );
	}
	if( ! _name ) {
		_name = strnewp( _full_hostname );
	}
	if( !strcmp(_full_hostname, my_full_hostname()) ) {
		_is_local = true;
	}
	return true;
}

<|endoftext|>


<commit_before>/*
** Copyright 1997 by the Condor Design Team
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted,
** provided that the above copyright notice appear in all copies and that
** both that copyright notice and this permission notice appear in
** supporting documentation, and that the names of the University of
** Wisconsin and the Condor Design Team not be used in advertising or
** publicity pertaining to distribution of the software without specific,
** written prior permission.  The University of Wisconsin and the Condor
** Design Team make no representations about the suitability of this
** software for any purpose.  It is provided "as is" without express
** or implied warranty.
**
** THE UNIVERSITY OF WISCONSIN AND THE CONDOR DESIGN TEAM DISCLAIM ALL
** WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE UNIVERSITY OF
** WISCONSIN OR THE CONDOR DESIGN TEAM BE LIABLE FOR ANY SPECIAL, INDIRECT
** OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
** OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
** OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
** OR PERFORMANCE OF THIS SOFTWARE.
**
** Authors:  Adiel Yoaz
** 	         University of Wisconsin, Computer Sciences Dept.
**
*/

//-----------------------------------------------------------------

#include "condor_common.h"
#include <iostream.h>
#include "condor_commands.h"
#include "condor_config.h"
#include "condor_classad.h"
#include "condor_debug.h"
#include "condor_io.h"
#include "TimeClass.h"
#include "MyString.h"

//-----------------------------------------------------------------

struct LineRec {
  MyString Name;
  float Priority;
  int Res;
};

//-----------------------------------------------------------------

static void Usage(char* argv[]);
static void ProcessInfo(AttrList* ad);
static int CountElem(AttrList* ad);
static void CollectInfo(AttrList* ad, LineRec* LR);
static void PrintInfo(AttrList* ad, LineRec* LR, int NumElem);

//-----------------------------------------------------------------

extern "C" {
int CompPrio(LineRec* a, LineRec* b);
}

//-----------------------------------------------------------------

main(int argc, char* argv[])
{
  int SetMode=0;

  if (argc>1) { // set priority
    if (argc!=4 || strcmp(argv[1],"-set")!=0 ) {
      Usage(argv);
      exit(1);
    }
    SetMode=1;
  }

  config( 0 );
  char* NegotiatorHost = param( "NEGOTIATOR_HOST" );
  if (!NegotiatorHost) {
    printf( "No NegotiatorHost host specified in config file\n" );
  }

  if (SetMode) { // set priority

    char* UidDomain=param("UID_DOMAIN");
    if (!UidDomain) {
      printf("No UID_DOMAIN specified in config file\n");
      exit(1);
    }

    char tmp[512];
    sprintf(tmp, "%s@%s", argv[2], UidDomain);
    double Priority=atof(argv[3]);

    // send request
    ReliSock sock(NegotiatorHost, NEGOTIATOR_PORT);
    sock.encode();
    if (!sock.put(SET_PRIORITY) ||
        !sock.put(tmp) ||
        !sock.put(Priority) ||
        !sock.end_of_message()) {
      printf("failed to send SET_PRIORITY command to negotiator\n");
      exit(1);
    }

  }

  else {  // list priorities

    // send request
    ReliSock sock(NegotiatorHost, NEGOTIATOR_PORT);
    sock.encode();
    if (!sock.put(GET_PRIORITY) ||
        !sock.end_of_message()) {
      printf("failed to send GET_PRIORITY command to negotiator\n");
      exit(1);
    }

    // get reply
    sock.decode();
    AttrList* ad=new AttrList();
    if (!ad->get(sock) ||
        !sock.end_of_message()) {
      printf("failed to get classad from negotiator\n");
      exit(1);
    }

    ProcessInfo(ad);
  }

  exit(0);
}

//-----------------------------------------------------------------

static void ProcessInfo(AttrList* ad)
{
  int NumElem=CountElem(ad);
  LineRec* LR=new LineRec[NumElem];
  CollectInfo(ad,LR);
  qsort(LR,NumElem,sizeof(LineRec),CompPrio);
  PrintInfo(ad,LR,NumElem);
}

//-----------------------------------------------------------------

static int CountElem(AttrList* ad)
{
  int count=0;
  ad->ResetExpr();
  while(ad->NextExpr()) count++;
  return (count-1)/3;
}

//-----------------------------------------------------------------

extern "C" {
int CompPrio(LineRec* a, LineRec* b)
{
  if (a->Priority>b->Priority) return 1;
  return -1;
}
}

//-----------------------------------------------------------------

static void CollectInfo(AttrList* ad, LineRec* LR)
{
  ExprTree* exp;
  ad->ResetExpr();
  exp=ad->NextExpr();
  int i=0;
  while(exp=ad->NextExpr()) {
    LR[i].Name=((String*) exp->RArg())->Value();
    LR[i].Priority=((Float*) ad->NextExpr()->RArg())->Value();
    LR[i].Res=((Integer*) ad->NextExpr()->RArg())->Value();
    i++;
  }

  return;
}

//-----------------------------------------------------------------

static void PrintInfo(AttrList* ad, LineRec* LR, int NumElem)
{
  // ad->AttrList::fPrint(stdout);
  ExprTree* exp;
  ad->ResetExpr();
  exp=ad->NextExpr();
  Time T=((Integer*) exp->RArg())->Value();
  // printf("%f\n",d);
  printf("Last Priority Update: %s\n",T.Asc());

  char* Fmt1="%-30s   %12.3f   %4d\n";
  char* Fmt2="%-30s   %12s   %4s\n";
  char* Fmt3="%-30s   %12s   %4d\n";

  printf(Fmt2,"Name","Priority","Resources Used");
  printf(Fmt2,"----","--------","--------------");

  int Res=0;
  for (int i=0; i<NumElem; i++) {
    printf(Fmt1,(const char*)LR[i].Name,LR[i].Priority,LR[i].Res);
	Res+=LR[i].Res;
  }

  // printf(Fmt2,"----","--------","--------------");
  // printf(Fmt3,"Total","",Res);

  return;
}

//-----------------------------------------------------------------

static void Usage(char* argv[]) {
  printf("usage: %s [ -set user priority ]\n", argv[0]);
}

<commit_msg>+ Changed Usage( char* argv[] ) to be usage( char* name ), like   usage() in every other condor tool/daemon. + We don't automatically append the local UID_DOMAIN to the name   specified when trying to set priorities: we can't assume we know   what user the administrator is trying to update, they've got to give   us the full name. + We make sure the user has an @ sign in the submittor name they're   trying to set, and print out an error message and exit if not. + Error messages go to stderr, where they belong.<commit_after>/*
** Copyright 1997 by the Condor Design Team
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted,
** provided that the above copyright notice appear in all copies and that
** both that copyright notice and this permission notice appear in
** supporting documentation, and that the names of the University of
** Wisconsin and the Condor Design Team not be used in advertising or
** publicity pertaining to distribution of the software without specific,
** written prior permission.  The University of Wisconsin and the Condor
** Design Team make no representations about the suitability of this
** software for any purpose.  It is provided "as is" without express
** or implied warranty.
**
** THE UNIVERSITY OF WISCONSIN AND THE CONDOR DESIGN TEAM DISCLAIM ALL
** WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE UNIVERSITY OF
** WISCONSIN OR THE CONDOR DESIGN TEAM BE LIABLE FOR ANY SPECIAL, INDIRECT
** OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
** OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
** OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
** OR PERFORMANCE OF THIS SOFTWARE.
**
** Authors:  Adiel Yoaz
** 	         University of Wisconsin, Computer Sciences Dept.
**
*/

//-----------------------------------------------------------------

#include "condor_common.h"
#include <iostream.h>
#include "condor_commands.h"
#include "condor_config.h"
#include "condor_classad.h"
#include "condor_debug.h"
#include "condor_io.h"
#include "TimeClass.h"
#include "MyString.h"

//-----------------------------------------------------------------

struct LineRec {
  MyString Name;
  float Priority;
  int Res;
};

//-----------------------------------------------------------------

static void usage(char* name);
static void ProcessInfo(AttrList* ad);
static int CountElem(AttrList* ad);
static void CollectInfo(AttrList* ad, LineRec* LR);
static void PrintInfo(AttrList* ad, LineRec* LR, int NumElem);

//-----------------------------------------------------------------

extern "C" {
int CompPrio(LineRec* a, LineRec* b);
}

//-----------------------------------------------------------------

main(int argc, char* argv[])
{
  int SetMode=0;

  if (argc>1) { // set priority
    if (argc!=4 || strcmp(argv[1],"-set")!=0 ) {
      usage( argv[0] );
      exit(1);
    }
    SetMode=1;
  }

  config( 0 );
  char* NegotiatorHost = param( "NEGOTIATOR_HOST" );
  if (!NegotiatorHost) {
    fprintf( stderr, "No NegotiatorHost host specified in config file\n" );
	exit(1);
  }

  if (SetMode) { // set priority

    char* tmp;
	if( ! (tmp = strchr(argv[2], '@')) ) {
		fprintf( stderr,
				 "%s: You must specify the full name of the submittor you wish\n",
				 argv[0] );
		fprintf( stderr, "\tto update the priority of (%s or %s)\n",
				 "user@uid.domain", "user@full.host.name" );
		exit(1);
	}
    double Priority=atof(argv[3]);

    // send request
    ReliSock sock(NegotiatorHost, NEGOTIATOR_PORT);
    sock.encode();
    if (!sock.put(SET_PRIORITY) ||
        !sock.put(argv[2]) ||
        !sock.put(Priority) ||
        !sock.end_of_message()) {
      fprintf( stderr, "failed to send SET_PRIORITY command to negotiator\n" );
      exit(1);
    }

  }

  else {  // list priorities

    // send request
    ReliSock sock(NegotiatorHost, NEGOTIATOR_PORT);
    sock.encode();
    if (!sock.put(GET_PRIORITY) ||
        !sock.end_of_message()) {
      fprintf( stderr, "failed to send GET_PRIORITY command to negotiator\n" );
      exit(1);
    }

    // get reply
    sock.decode();
    AttrList* ad=new AttrList();
    if (!ad->get(sock) ||
        !sock.end_of_message()) {
      fprintf( stderr, "failed to get classad from negotiator\n" );
      exit(1);
    }

    ProcessInfo(ad);
  }

  exit(0);
}

//-----------------------------------------------------------------

static void ProcessInfo(AttrList* ad)
{
  int NumElem=CountElem(ad);
  LineRec* LR=new LineRec[NumElem];
  CollectInfo(ad,LR);
  qsort(LR,NumElem,sizeof(LineRec),CompPrio);
  PrintInfo(ad,LR,NumElem);
}

//-----------------------------------------------------------------

static int CountElem(AttrList* ad)
{
  int count=0;
  ad->ResetExpr();
  while(ad->NextExpr()) count++;
  return (count-1)/3;
}

//-----------------------------------------------------------------

extern "C" {
int CompPrio(LineRec* a, LineRec* b)
{
  if (a->Priority>b->Priority) return 1;
  return -1;
}
}

//-----------------------------------------------------------------

static void CollectInfo(AttrList* ad, LineRec* LR)
{
  ExprTree* exp;
  ad->ResetExpr();
  exp=ad->NextExpr();
  int i=0;
  while(exp=ad->NextExpr()) {
    LR[i].Name=((String*) exp->RArg())->Value();
    LR[i].Priority=((Float*) ad->NextExpr()->RArg())->Value();
    LR[i].Res=((Integer*) ad->NextExpr()->RArg())->Value();
    i++;
  }

  return;
}

//-----------------------------------------------------------------

static void PrintInfo(AttrList* ad, LineRec* LR, int NumElem)
{
  // ad->AttrList::fPrint(stdout);
  ExprTree* exp;
  ad->ResetExpr();
  exp=ad->NextExpr();
  Time T=((Integer*) exp->RArg())->Value();
  // printf("%f\n",d);
  printf("Last Priority Update: %s\n",T.Asc());

  char* Fmt1="%-30s   %12.3f   %4d\n";
  char* Fmt2="%-30s   %12s   %4s\n";
  char* Fmt3="%-30s   %12s   %4d\n";

  printf(Fmt2,"Name","Priority","Resources Used");
  printf(Fmt2,"----","--------","--------------");

  int Res=0;
  for (int i=0; i<NumElem; i++) {
    printf(Fmt1,(const char*)LR[i].Name,LR[i].Priority,LR[i].Res);
	Res+=LR[i].Res;
  }

  // printf(Fmt2,"----","--------","--------------");
  // printf(Fmt3,"Total","",Res);

  return;
}

//-----------------------------------------------------------------

static void usage(char* name) {
  fprintf( stderr, "usage: %s [ -set user priority_value ]\n", name );
}

<|endoftext|>


<commit_before>//
//  Atari2600.cpp
//  ElectrEm
//
//  Created by Thomas Harte on 14/07/2015.
//  Copyright © 2015 Thomas Harte. All rights reserved.
//

#include "Atari2600.hpp"
#include <algorithm>
#include <stdio.h>

using namespace Atari2600;
static const char atari2600DataType[] = "Atari2600";

Machine::Machine()
{
	_timestamp = 0;
	_horizontalTimer = 0;
	_lastOutputStateDuration = 0;
	_lastOutputState = OutputState::Sync;
	_crt = new Outputs::CRT(228, 256, 1, 4);

	reset();
}

void Machine::get_output_pixel(uint8_t *pixel, int offset)
{
	// get the playfield pixel
	const int x = offset >> 2;
	const int mirrored = (x / 20) & (_playFieldControl&1);
	const int index = mirrored ? x - 20 : 19 - (x%20);
	const int byte = 2 - (index >> 3);
	const int lowestBit = (byte&1)^1;
	const int bit = (index & 7)^(lowestBit | (lowestBit << 1) | (lowestBit << 2));

	uint8_t playFieldPixel = (_playField[byte] >> bit)&1;

	// TODO: almost everything!
	pixel[0] = playFieldPixel ? 0xff : 0x00;
	pixel[1] = playFieldPixel ? 0xff : 0x00;
	pixel[2] = playFieldPixel ? 0xff : 0x00;
}

void Machine::output_pixels(int count)
{
	while(count--)
	{
		// logic: if in vsync, output that; otherwise if in vblank then output that;
		// otherwise output a pixel
		if(_vSyncEnabled) {
			output_state(OutputState::Sync, nullptr);
		} else {

			// blank is decoded as 68 counts; sync and colour burst as 16 counts

			// guesses, until I can find information: 26 cycles blank, 16 sync, 26 blank, 160 pixels
			if(_horizontalTimer < 26) output_state(OutputState::Blank, nullptr);
			else if (_horizontalTimer < 42) output_state(OutputState::Sync, nullptr);
			else if (_horizontalTimer < 68) output_state(OutputState::Blank, nullptr);
			else {
				if(_vBlankEnabled) {
					output_state(OutputState::Blank, nullptr);
				} else {
					uint8_t outputPixel[3];
					get_output_pixel(outputPixel, _horizontalTimer - 68);
					output_state(OutputState::Pixel, outputPixel);
				}
			}
		}

		_horizontalTimer = (_horizontalTimer + 1)%228;
	}
}

void Machine::output_state(OutputState state, uint8_t *pixel)
{
	_lastOutputStateDuration++;
	if(state != _lastOutputState)
	{
		switch(_lastOutputState)
		{
			case OutputState::Blank:	{
				_crt->allocate_write_area(1);
				_outputBuffer = _crt->get_write_target_for_buffer(0);

				if(_outputBuffer)
				{
					_outputBuffer[0] = _outputBuffer[1] = _outputBuffer[2] = 0;
					_outputBuffer[3] = 0xff;
				}
				_crt->output_level(_lastOutputStateDuration, atari2600DataType);
			} break;
			case OutputState::Sync:		_crt->output_sync(_lastOutputStateDuration);					break;
			case OutputState::Pixel:	_crt->output_data(_lastOutputStateDuration, atari2600DataType);	break;
		}
		_lastOutputStateDuration = 0;
		_lastOutputState = state;

		if(state == OutputState::Pixel)
		{
			_crt->allocate_write_area(160);
			_outputBuffer = _crt->get_write_target_for_buffer(0);
		}
	}

	if(state == OutputState::Pixel && _outputBuffer)
	{
		_outputBuffer[(_lastOutputStateDuration * 4) + 0] = pixel[0];
		_outputBuffer[(_lastOutputStateDuration * 4) + 1] = pixel[1];
		_outputBuffer[(_lastOutputStateDuration * 4) + 2] = pixel[2];
		_outputBuffer[(_lastOutputStateDuration * 4) + 3] = 0xff;
	}
}

void Machine::perform_bus_operation(CPU6502::BusOperation operation, uint16_t address, uint8_t *value)
{
	uint8_t returnValue = 0xff;

	output_pixels(3);

	_timestamp++;

	// check for a ROM access
	if ((address&0x1000) && isReadOperation(operation)) {
//		if(operation == CPU6502::BusOperation::ReadOpcode) printf("[%04x]\n", address);
		returnValue &= _rom[address&_romMask];
	}

	// check for a RAM access
	if ((address&0x1280) == 0x80) {

		if(isReadOperation(operation)) {
			returnValue &= _ram[address&0x7f];
		} else {
			_ram[address&0x7f] = *value;
		}
	}

	// check for a TIA access
	if (!(address&0x1080)) {
		if(isReadOperation(operation)) {
		} else {
			switch(address & 0x3f) {
				case 0:	_vSyncEnabled = !!(*value & 0x02);	break;
				case 1:	_vBlankEnabled = !!(*value & 0x02);	break;

				case 2: {
					const int cyclesToRunFor = 228 - _horizontalTimer;
					_piaTimerValue -= cyclesToRunFor;
					output_pixels(cyclesToRunFor);
				} break;
				case 3: _horizontalTimer = 0; break;

				case 0x0a: _playFieldControl = *value; break;
				case 0x0d: _playField[0] = *value; break;
				case 0x0e: _playField[1] = *value; break;
				case 0x0f: _playField[2] = *value; break;
			}
		}
//		printf("Uncaught TIA %04x\n", address);
	}

	// check for a PIA access
	if ((address&0x1280) == 0x280) {
		if(isReadOperation(operation)) {
			switch(address & 0xf) {
				case 0x04: returnValue &= _piaTimerValue >> _piaTimerShift; break;
			}
		} else {
			switch(address & 0x0f) {
				case 0x04:	_piaTimerShift = 0;		_piaTimerValue = *value << 0; break;
				case 0x05:	_piaTimerShift = 3;		_piaTimerValue = *value << 3; break;
				case 0x06:	_piaTimerShift = 6;		_piaTimerValue = *value << 6; break;
				case 0x07:	_piaTimerShift = 10;	_piaTimerValue = *value << 10; break;
			}
		}
//		printf("Uncaught PIA %04x\n", address);
	}

	if(isReadOperation(operation)) {
		*value = returnValue;
	}

	_piaTimerValue--;
}

void Machine::set_rom(size_t length, const uint8_t *data)
{
	length = std::min((size_t)4096, length);
	memcpy(_rom, data, length);
	_romMask = length - 1;
	reset();
}
<commit_msg>Removed a stray newline.<commit_after>//
//  Atari2600.cpp
//  ElectrEm
//
//  Created by Thomas Harte on 14/07/2015.
//  Copyright © 2015 Thomas Harte. All rights reserved.
//

#include "Atari2600.hpp"
#include <algorithm>
#include <stdio.h>

using namespace Atari2600;
static const char atari2600DataType[] = "Atari2600";

Machine::Machine()
{
	_timestamp = 0;
	_horizontalTimer = 0;
	_lastOutputStateDuration = 0;
	_lastOutputState = OutputState::Sync;
	_crt = new Outputs::CRT(228, 256, 1, 4);

	reset();
}

void Machine::get_output_pixel(uint8_t *pixel, int offset)
{
	// get the playfield pixel
	const int x = offset >> 2;
	const int mirrored = (x / 20) & (_playFieldControl&1);
	const int index = mirrored ? x - 20 : 19 - (x%20);
	const int byte = 2 - (index >> 3);
	const int lowestBit = (byte&1)^1;
	const int bit = (index & 7)^(lowestBit | (lowestBit << 1) | (lowestBit << 2));

	uint8_t playFieldPixel = (_playField[byte] >> bit)&1;

	// TODO: almost everything!
	pixel[0] = playFieldPixel ? 0xff : 0x00;
	pixel[1] = playFieldPixel ? 0xff : 0x00;
	pixel[2] = playFieldPixel ? 0xff : 0x00;
}

void Machine::output_pixels(int count)
{
	while(count--)
	{
		// logic: if in vsync, output that; otherwise if in vblank then output that;
		// otherwise output a pixel
		if(_vSyncEnabled) {
			output_state(OutputState::Sync, nullptr);
		} else {

			// blank is decoded as 68 counts; sync and colour burst as 16 counts

			// guesses, until I can find information: 26 cycles blank, 16 sync, 26 blank, 160 pixels
			if(_horizontalTimer < 26) output_state(OutputState::Blank, nullptr);
			else if (_horizontalTimer < 42) output_state(OutputState::Sync, nullptr);
			else if (_horizontalTimer < 68) output_state(OutputState::Blank, nullptr);
			else {
				if(_vBlankEnabled) {
					output_state(OutputState::Blank, nullptr);
				} else {
					uint8_t outputPixel[3];
					get_output_pixel(outputPixel, _horizontalTimer - 68);
					output_state(OutputState::Pixel, outputPixel);
				}
			}
		}

		_horizontalTimer = (_horizontalTimer + 1)%228;
	}
}

void Machine::output_state(OutputState state, uint8_t *pixel)
{
	_lastOutputStateDuration++;
	if(state != _lastOutputState)
	{
		switch(_lastOutputState)
		{
			case OutputState::Blank:	{
				_crt->allocate_write_area(1);
				_outputBuffer = _crt->get_write_target_for_buffer(0);

				if(_outputBuffer)
				{
					_outputBuffer[0] = _outputBuffer[1] = _outputBuffer[2] = 0;
					_outputBuffer[3] = 0xff;
				}
				_crt->output_level(_lastOutputStateDuration, atari2600DataType);
			} break;
			case OutputState::Sync:		_crt->output_sync(_lastOutputStateDuration);					break;
			case OutputState::Pixel:	_crt->output_data(_lastOutputStateDuration, atari2600DataType);	break;
		}
		_lastOutputStateDuration = 0;
		_lastOutputState = state;

		if(state == OutputState::Pixel)
		{
			_crt->allocate_write_area(160);
			_outputBuffer = _crt->get_write_target_for_buffer(0);
		}
	}

	if(state == OutputState::Pixel && _outputBuffer)
	{
		_outputBuffer[(_lastOutputStateDuration * 4) + 0] = pixel[0];
		_outputBuffer[(_lastOutputStateDuration * 4) + 1] = pixel[1];
		_outputBuffer[(_lastOutputStateDuration * 4) + 2] = pixel[2];
		_outputBuffer[(_lastOutputStateDuration * 4) + 3] = 0xff;
	}
}

void Machine::perform_bus_operation(CPU6502::BusOperation operation, uint16_t address, uint8_t *value)
{
	uint8_t returnValue = 0xff;

	output_pixels(3);

	_timestamp++;

	// check for a ROM access
	if ((address&0x1000) && isReadOperation(operation)) {
//		if(operation == CPU6502::BusOperation::ReadOpcode) printf("[%04x]\n", address);
		returnValue &= _rom[address&_romMask];
	}

	// check for a RAM access
	if ((address&0x1280) == 0x80) {

		if(isReadOperation(operation)) {
			returnValue &= _ram[address&0x7f];
		} else {
			_ram[address&0x7f] = *value;
		}
	}

	// check for a TIA access
	if (!(address&0x1080)) {
		if(isReadOperation(operation)) {
		} else {
			switch(address & 0x3f) {
				case 0:	_vSyncEnabled = !!(*value & 0x02);	break;
				case 1:	_vBlankEnabled = !!(*value & 0x02);	break;

				case 2: {
					const int cyclesToRunFor = 228 - _horizontalTimer;
					_piaTimerValue -= cyclesToRunFor;
					output_pixels(cyclesToRunFor);
				} break;
				case 3: _horizontalTimer = 0; break;

				case 0x0a: _playFieldControl = *value; break;
				case 0x0d: _playField[0] = *value; break;
				case 0x0e: _playField[1] = *value; break;
				case 0x0f: _playField[2] = *value; break;
			}
		}
//		printf("Uncaught TIA %04x\n", address);
	}

	// check for a PIA access
	if ((address&0x1280) == 0x280) {
		if(isReadOperation(operation)) {
			switch(address & 0xf) {
				case 0x04: returnValue &= _piaTimerValue >> _piaTimerShift; break;
			}
		} else {
			switch(address & 0x0f) {
				case 0x04:	_piaTimerShift = 0;		_piaTimerValue = *value << 0; break;
				case 0x05:	_piaTimerShift = 3;		_piaTimerValue = *value << 3; break;
				case 0x06:	_piaTimerShift = 6;		_piaTimerValue = *value << 6; break;
				case 0x07:	_piaTimerShift = 10;	_piaTimerValue = *value << 10; break;
			}
		}
//		printf("Uncaught PIA %04x\n", address);
	}

	if(isReadOperation(operation)) {
		*value = returnValue;
	}

	_piaTimerValue--;
}

void Machine::set_rom(size_t length, const uint8_t *data)
{
	length = std::min((size_t)4096, length);
	memcpy(_rom, data, length);
	_romMask = length - 1;
	reset();
}
<|endoftext|>


<commit_before>/**
 * @file template.cpp
 * @brief plustache template
 * @author Daniel Schauenberg <d@unwiredcouch.com>
 */

#include <template.hpp>

/**
 * @brief constructor taking no arguments
 */
template_t::template_t()
{
    // set template path
    template_path = "";
    template_t::compile_data();
}

/**
 * @brief constructor taking the template path as argument
 *
 * @param tmpl_path path to the template directory
 */
template_t::template_t(string tmpl_path)
{
    template_path = tmpl_path;
}

/**
 * @brief function to compile all the basic data like regex, tags, etc.
 */
void template_t::compile_data()
{
    // lookup table for html escape
    escape_lut["&"] = "&";
    escape_lut["<"] = "<";
    escape_lut[">"] = ">";
    escape_lut["\\"] = "\";
    escape_lut["\""] = """;
    // regex for what to escape in a html string
    escape_chars.assign("(<|>|\"|\\\\|&)");
    otag = "\\{\\{";
    ctag = "\\}\\}";
    // tag and section regex
    tag.assign(otag + "(#|=|&|!|>|\\{)?(.+?)(\\})?" + ctag);
    section.assign(otag + "(\\^|\\#)([^\\}]*)" + ctag + "\\s*(.+?)\\s*"
                   + otag + "/\\2"+ctag);
}

/**
 * @brief destructor nothing to do here
 */
template_t::~template_t()
{

}

/**
 * @brief method to render tags with a given map
 *
 * @param tmplate template string to render
 * @param ctx map of values
 *
 * @return rendered string
 */
string template_t::render_tags(string tmplate, context ctx)
{
    // initialize data
    string ret = "";
    string rest = "";
    string::const_iterator start, end;
    match_results<std::string::const_iterator> matches;
    start = tmplate.begin();
    end = tmplate.end();
    // return whole string when no tags are found
    if (!regex_search(start, end, matches, tag, match_default | format_all))
    {
        ret = tmplate;
    }
    // loop through tags and replace
    while (regex_search(start, end, matches, tag, match_default | format_all))
    {
        string modifier(matches[1].first, matches[1].second);
        string key(matches[2].first, matches[2].second);
        algorithm::trim(key);
        algorithm::trim(modifier);
        string text(start, matches[0].second);
        string repl;
        // don't html escape this
        if (modifier == "&" || modifier == "{")
        {
            try
            {
                // get value
                string s = ctx.get(key)[0][key];
                // escape backslash in string
                const string f = "\\";
                size_t found = s.find(f);
                while(found != string::npos)
                {
                    s.replace(found,f.length(),"\\\\");
                    found = s.find(f, found+2);
                }
                repl.assign(s);
            }
            catch(int i) { repl.assign(""); }
        }
        // this is a comment
        else if (modifier == "!")
        {
            repl.assign("");
        }
        // found a partial
        else if (modifier == ">")
        {
            repl.assign(template_t::render(template_t::get_partial(key), ctx));
        }
        // normal tag
        else
        {
            try
            {
                repl.assign(template_t::html_escape(ctx.get(key)[0][key]));
            }
            catch(int i) { repl.assign(""); }
        }

        // replace
        ret += regex_replace(text, tag, repl, match_default | format_all);
        // change delimiter after was removed
        if (modifier == "=")
        {
          // regex for finding delimiters
          regex delim("(.+?) (.+?)=");
          // match object
          match_results<std::string::const_iterator> delim_m;
          // search for the delimiters
          regex_search(matches[2].first, matches[2].second, delim_m, delim,
                       match_default | format_all);
          // set new otag and ctag
          string new_otag = delim_m[1];
          string new_ctag = delim_m[2];
          // change delimiters
          template_t::change_delimiter(new_otag, new_ctag);
        }
        // set start for next tag and rest of string
        rest.assign(matches[0].second, end);
        start = matches[0].second;
    }
    // append and return
    ret += rest;
    return ret;
}

/**
 * @brief method to render sections with a given map
 *
 * @param tmplate template string to render
 * @param ctx map of values
 *
 * @return rendered string
 */
string template_t::render_sections(string tmplate, context ctx)
{
    // initialize data structures
    string ret = "";
    string rest = "";
    string::const_iterator start, end;
    match_results<std::string::const_iterator> matches;
    start = tmplate.begin();
    end = tmplate.end();
    // return the whole template if no sections are found
    if (!regex_search(start, end, matches, section,
                        match_default | format_all))
    {
        ret = tmplate;
    }
    // loop through sections and render
    while (regex_search(start, end, matches, section,
                        match_default | format_all))
    {
        // string assignments
        string text(start, matches[0].second);
        string key(matches[2].first, matches[2].second);
        string modifier(matches[1]);
        // trimming
        algorithm::trim(key);
        algorithm::trim(modifier);
        string repl = "";
        string show = "false";
        buckets values;
        values = ctx.get(key);
        if (values.size() == 1)
        {
            show = values[0][key] != "" ? values[0][key] : "false";
        }
        else if(values.size() > 1)
        {
            show = "true";
        }
        // inverted section?
        if (modifier == "^" && show == "false") show = "true";
        else if (modifier == "^" && show == "true") show = "false";
        // assign replacement content
        if (show == "true")
        {
            if (regex_search(matches[3].first, matches[3].second,
                             section, match_default | format_all))
            {
                repl.assign(template_t::render_sections(matches[3], ctx));
            }
            else
            {
              if (values.size() > 1)
              {
                for(buckets::iterator it = values.begin();
                    it != values.end(); ++it)
                {
                  context small_ctx;
                  small_ctx = ctx;
                  for(bucket::const_iterator it_map = (*it).begin();
                      it_map != (*it).end(); it_map++)
                  {
                    small_ctx.add(it_map->first, it_map->second);
                  }
                  repl += template_t::render_tags(matches[3], small_ctx);
                }
              }
              else
              {
                repl.assign(matches[3]);
              }
            }
        }
        else repl.assign("");
        ret += regex_replace(text, section, repl, match_default | format_all);
        rest.assign(matches[0].second, end);
        start = matches[0].second;
    }
    // append and return
    ret += rest;
    return ret;
}

/**
 * @brief method for rendering a template
 *
 * @param tmplate template to render as raw string or file path
 * @param ctx context object
 *
 * @return rendered string
 */
string template_t::render(string tmplate, context ctx)
{
    // get template
    string tmp = get_template(tmplate);

    string first = template_t::render_sections(tmp, ctx);
    string second = template_t::render_tags(first, ctx);
    return second;
}

/**
 * @brief method for rendering a template
 *
 * @param tmplate template to render as raw string or filepath
 * @param ctx map of values
 *
 * @return rendered string
 */
string template_t::render(string tmplate, bucket ctx)
{
    // get template
    string tmp = get_template(tmplate);
    context contxt;
    for(bucket::const_iterator it = ctx.begin(); it != ctx.end(); it++)
    {
        contxt.add(it->first, it->second);
    }

    string first = template_t::render_sections(tmp, contxt);
    string second = template_t::render_tags(first, contxt);
    return second;
}

//
// HELPER FUNCTIONS
//

/**
 * @brief method to escape html strings
 *
 * @param s string to escape
 *
 * @return escaped string
 */
string template_t::html_escape(string s)
{
    /** initialize working strings and iterators */
    string ret = "";
    string rest = "";
    string::const_iterator start, end;
    match_results<std::string::const_iterator> matches;
    start = s.begin();
    end = s.end();
    // return original string if nothing is found
    if (!regex_search(start, end, matches, escape_chars,
                        match_default | format_all))
    {
        ret = s;
    }
    // search for html chars
    while (regex_search(start, end, matches, escape_chars,
                        match_default | format_all))
    {
        string key(matches[0].first, matches[0].second);
        string text(start, matches[0].second);
        algorithm::trim(key);
        string repl;
        repl = escape_lut[key];
        ret += regex_replace(text, escape_chars, repl,
                             match_default | format_all);
        rest.assign(matches[0].second, end);
        start = matches[0].second;
    }
    ret += rest;
    return ret;
}

/**
 * @brief method to load partial template from file
 *
 * @param s name of the partial to load
 *
 * @return partial template as string
 */
string template_t::get_partial(string partial)
{
    string ret = "";
    string file_with_path = template_path;
    partial += ".mustache";
    file_with_path += partial;
    // file path with template path prefix
    ifstream extended_file(file_with_path.c_str());
    // true if it was a valid file path
    if (extended_file.is_open())
    {
        ret.assign((istreambuf_iterator<char>(extended_file)),
                    istreambuf_iterator<char>());
        extended_file.close();
    }
    else
    {
        // file path without prefix
        ifstream file(partial.c_str());
        if(file.is_open())
        {
          ret.assign((istreambuf_iterator<char>(file)),
                      istreambuf_iterator<char>());
          file.close();
        }
    }
    return ret;
}

/**
 * @brief method to change delimiters
 *
 * @param opentag delimiter for open tag
 * @param closetag delimiter for closed tag
 */
void template_t::change_delimiter(string opentag, string closetag)
{
    otag = opentag;
    ctag = closetag;
    // tag and section regex
    template_t::tag.assign(otag + "(#|=|&|!|>|\\{)?(.+?)(\\})?" + ctag);
    template_t::section.assign(otag + "(\\^|\\#)([^\\}]*)" + ctag +
                               "\\s*(.+?)\\s*" + otag + "/\\2"+ctag);
}

/**
 * @brief function to prepare template for rendering
 *
 * @param tmpl path to template or template directory
 *
 * @return template as string
 */
string template_t::get_template(string tmpl)
{
    // string to hold the template
    string tmp = "";
    ifstream file(tmpl.c_str());
    ifstream file_from_tmpl_dir((template_path + tmpl).c_str());
    // true if it was a valid local file path
    if (file.is_open())
    {
        tmp.assign((istreambuf_iterator<char>(file)),
                    istreambuf_iterator<char>());
        file.close();
    }
    // maybe the template is in the standard directory
    else if (file_from_tmpl_dir.is_open())
    {
        tmp.assign((istreambuf_iterator<char>(file_from_tmpl_dir)),
                    istreambuf_iterator<char>());
        file_from_tmpl_dir.close();

    }
    // tmplate was maybe a complete template and no file path
    else
    {
        tmp = tmpl;
    }

    // cleanup
    if (file.is_open()) file.close();
    if (file_from_tmpl_dir.is_open()) file_from_tmpl_dir.close();

    // return template
    return tmp;
}
<commit_msg>fix for single element collections<commit_after>/**
 * @file template.cpp
 * @brief plustache template
 * @author Daniel Schauenberg <d@unwiredcouch.com>
 */

#include <template.hpp>

/**
 * @brief constructor taking no arguments
 */
template_t::template_t()
{
    // set template path
    template_path = "";
    template_t::compile_data();
}

/**
 * @brief constructor taking the template path as argument
 *
 * @param tmpl_path path to the template directory
 */
template_t::template_t(string tmpl_path)
{
    template_path = tmpl_path;
}

/**
 * @brief function to compile all the basic data like regex, tags, etc.
 */
void template_t::compile_data()
{
    // lookup table for html escape
    escape_lut["&"] = "&";
    escape_lut["<"] = "<";
    escape_lut[">"] = ">";
    escape_lut["\\"] = "\";
    escape_lut["\""] = """;
    // regex for what to escape in a html string
    escape_chars.assign("(<|>|\"|\\\\|&)");
    otag = "\\{\\{";
    ctag = "\\}\\}";
    // tag and section regex
    tag.assign(otag + "(#|=|&|!|>|\\{)?(.+?)(\\})?" + ctag);
    section.assign(otag + "(\\^|\\#)([^\\}]*)" + ctag + "\\s*(.+?)\\s*"
                   + otag + "/\\2"+ctag);
}

/**
 * @brief destructor nothing to do here
 */
template_t::~template_t()
{

}

/**
 * @brief method to render tags with a given map
 *
 * @param tmplate template string to render
 * @param ctx map of values
 *
 * @return rendered string
 */
string template_t::render_tags(string tmplate, context ctx)
{
    // initialize data
    string ret = "";
    string rest = "";
    string::const_iterator start, end;
    match_results<std::string::const_iterator> matches;
    start = tmplate.begin();
    end = tmplate.end();
    // return whole string when no tags are found
    if (!regex_search(start, end, matches, tag, match_default | format_all))
    {
        ret = tmplate;
    }
    // loop through tags and replace
    while (regex_search(start, end, matches, tag, match_default | format_all))
    {
        string modifier(matches[1].first, matches[1].second);
        string key(matches[2].first, matches[2].second);
        algorithm::trim(key);
        algorithm::trim(modifier);
        string text(start, matches[0].second);
        string repl;
        // don't html escape this
        if (modifier == "&" || modifier == "{")
        {
            try
            {
                // get value
                string s = ctx.get(key)[0][key];
                // escape backslash in string
                const string f = "\\";
                size_t found = s.find(f);
                while(found != string::npos)
                {
                    s.replace(found,f.length(),"\\\\");
                    found = s.find(f, found+2);
                }
                repl.assign(s);
            }
            catch(int i) { repl.assign(""); }
        }
        // this is a comment
        else if (modifier == "!")
        {
            repl.assign("");
        }
        // found a partial
        else if (modifier == ">")
        {
            repl.assign(template_t::render(template_t::get_partial(key), ctx));
        }
        // normal tag
        else
        {
            try
            {
                repl.assign(template_t::html_escape(ctx.get(key)[0][key]));
            }
            catch(int i) { repl.assign(""); }
        }

        // replace
        ret += regex_replace(text, tag, repl, match_default | format_all);
        // change delimiter after was removed
        if (modifier == "=")
        {
          // regex for finding delimiters
          regex delim("(.+?) (.+?)=");
          // match object
          match_results<std::string::const_iterator> delim_m;
          // search for the delimiters
          regex_search(matches[2].first, matches[2].second, delim_m, delim,
                       match_default | format_all);
          // set new otag and ctag
          string new_otag = delim_m[1];
          string new_ctag = delim_m[2];
          // change delimiters
          template_t::change_delimiter(new_otag, new_ctag);
        }
        // set start for next tag and rest of string
        rest.assign(matches[0].second, end);
        start = matches[0].second;
    }
    // append and return
    ret += rest;
    return ret;
}

/**
 * @brief method to render sections with a given map
 *
 * @param tmplate template string to render
 * @param ctx map of values
 *
 * @return rendered string
 */
string template_t::render_sections(string tmplate, context ctx)
{
    // initialize data structures
    string ret = "";
    string rest = "";
    string::const_iterator start, end;
    match_results<std::string::const_iterator> matches;
    start = tmplate.begin();
    end = tmplate.end();
    // return the whole template if no sections are found
    if (!regex_search(start, end, matches, section,
                        match_default | format_all))
    {
        ret = tmplate;
    }
    // loop through sections and render
    while (regex_search(start, end, matches, section,
                        match_default | format_all))
    {
        // string assignments
        string text(start, matches[0].second);
        string key(matches[2].first, matches[2].second);
        string modifier(matches[1]);
        // trimming
        algorithm::trim(key);
        algorithm::trim(modifier);
        string repl = "";
        string show = "false";
        buckets values;
        values = ctx.get(key);
        if (values.size() == 1)
        {
            // if we don't have a collection, we find the key and an
            // empty map bucket means false
            if (values[0].find(key) != values[0].end())
            {
              show = values[0][key] != "" ? values[0][key] : "false";
            }
            // if we have a collection, we want to show it if there is
            // something to show
            else
            {
              show = values[0].size() > 0 ? "true" : "false";
            }
        }
        else if(values.size() > 1)
        {
            show = "true";
        }
        // inverted section?
        if (modifier == "^" && show == "false") show = "true";
        else if (modifier == "^" && show == "true") show = "false";
        // assign replacement content
        if (show == "true")
        {
            if (regex_search(matches[3].first, matches[3].second,
                             section, match_default | format_all))
            {
                repl.assign(template_t::render_sections(matches[3], ctx));
            }
            else
            {
                for(buckets::iterator it = values.begin();
                    it != values.end(); ++it)
                {
                  context small_ctx;
                  small_ctx = ctx;
                  for(bucket::const_iterator it_map = (*it).begin();
                      it_map != (*it).end(); it_map++)
                  {
                    small_ctx.add(it_map->first, it_map->second);
                  }
                  repl += template_t::render_tags(matches[3], small_ctx);
                }
            }
        }
        else repl.assign("");
        ret += regex_replace(text, section, repl, match_default | format_all);
        rest.assign(matches[0].second, end);
        start = matches[0].second;
    }
    // append and return
    ret += rest;
    return ret;
}

/**
 * @brief method for rendering a template
 *
 * @param tmplate template to render as raw string or file path
 * @param ctx context object
 *
 * @return rendered string
 */
string template_t::render(string tmplate, context ctx)
{
    // get template
    string tmp = get_template(tmplate);

    string first = template_t::render_sections(tmp, ctx);
    string second = template_t::render_tags(first, ctx);
    return second;
}

/**
 * @brief method for rendering a template
 *
 * @param tmplate template to render as raw string or filepath
 * @param ctx map of values
 *
 * @return rendered string
 */
string template_t::render(string tmplate, bucket ctx)
{
    // get template
    string tmp = get_template(tmplate);
    context contxt;
    for(bucket::const_iterator it = ctx.begin(); it != ctx.end(); it++)
    {
        contxt.add(it->first, it->second);
    }

    string first = template_t::render_sections(tmp, contxt);
    string second = template_t::render_tags(first, contxt);
    return second;
}

//
// HELPER FUNCTIONS
//

/**
 * @brief method to escape html strings
 *
 * @param s string to escape
 *
 * @return escaped string
 */
string template_t::html_escape(string s)
{
    /** initialize working strings and iterators */
    string ret = "";
    string rest = "";
    string::const_iterator start, end;
    match_results<std::string::const_iterator> matches;
    start = s.begin();
    end = s.end();
    // return original string if nothing is found
    if (!regex_search(start, end, matches, escape_chars,
                        match_default | format_all))
    {
        ret = s;
    }
    // search for html chars
    while (regex_search(start, end, matches, escape_chars,
                        match_default | format_all))
    {
        string key(matches[0].first, matches[0].second);
        string text(start, matches[0].second);
        algorithm::trim(key);
        string repl;
        repl = escape_lut[key];
        ret += regex_replace(text, escape_chars, repl,
                             match_default | format_all);
        rest.assign(matches[0].second, end);
        start = matches[0].second;
    }
    ret += rest;
    return ret;
}

/**
 * @brief method to load partial template from file
 *
 * @param s name of the partial to load
 *
 * @return partial template as string
 */
string template_t::get_partial(string partial)
{
    string ret = "";
    string file_with_path = template_path;
    partial += ".mustache";
    file_with_path += partial;
    // file path with template path prefix
    ifstream extended_file(file_with_path.c_str());
    // true if it was a valid file path
    if (extended_file.is_open())
    {
        ret.assign((istreambuf_iterator<char>(extended_file)),
                    istreambuf_iterator<char>());
        extended_file.close();
    }
    else
    {
        // file path without prefix
        ifstream file(partial.c_str());
        if(file.is_open())
        {
          ret.assign((istreambuf_iterator<char>(file)),
                      istreambuf_iterator<char>());
          file.close();
        }
    }
    return ret;
}

/**
 * @brief method to change delimiters
 *
 * @param opentag delimiter for open tag
 * @param closetag delimiter for closed tag
 */
void template_t::change_delimiter(string opentag, string closetag)
{
    otag = opentag;
    ctag = closetag;
    // tag and section regex
    template_t::tag.assign(otag + "(#|=|&|!|>|\\{)?(.+?)(\\})?" + ctag);
    template_t::section.assign(otag + "(\\^|\\#)([^\\}]*)" + ctag +
                               "\\s*(.+?)\\s*" + otag + "/\\2"+ctag);
}

/**
 * @brief function to prepare template for rendering
 *
 * @param tmpl path to template or template directory
 *
 * @return template as string
 */
string template_t::get_template(string tmpl)
{
    // string to hold the template
    string tmp = "";
    ifstream file(tmpl.c_str());
    ifstream file_from_tmpl_dir((template_path + tmpl).c_str());
    // true if it was a valid local file path
    if (file.is_open())
    {
        tmp.assign((istreambuf_iterator<char>(file)),
                    istreambuf_iterator<char>());
        file.close();
    }
    // maybe the template is in the standard directory
    else if (file_from_tmpl_dir.is_open())
    {
        tmp.assign((istreambuf_iterator<char>(file_from_tmpl_dir)),
                    istreambuf_iterator<char>());
        file_from_tmpl_dir.close();

    }
    // tmplate was maybe a complete template and no file path
    else
    {
        tmp = tmpl;
    }

    // cleanup
    if (file.is_open()) file.close();
    if (file_from_tmpl_dir.is_open()) file_from_tmpl_dir.close();

    // return template
    return tmp;
}
<|endoftext|>


<commit_before>//
//  Oric.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 11/10/2016.
//  Copyright © 2016 Thomas Harte. All rights reserved.
//

#ifndef Oric_hpp
#define Oric_hpp

#include "../../Processors/6502/CPU6502.hpp"
#include "../../Components/6522/6522.hpp"
#include "../../Storage/Tape/Tape.hpp"

#include "../ConfigurationTarget.hpp"
#include "../CRTMachine.hpp"
#include "../Typer.hpp"

#include "Video.hpp"

#include <cstdint>
#include <vector>

namespace Oric {

class VIA: public MOS::MOS6522<VIA>, public MOS::MOS6522IRQDelegate {
	public:
		using MOS6522IRQDelegate::set_interrupt_status;
};

class Machine:
	public CPU6502::Processor<Machine>,
	public CRTMachine::Machine,
	public ConfigurationTarget::Machine,
	public MOS::MOS6522IRQDelegate::Delegate {

	public:
		Machine();

		void set_rom(std::vector<uint8_t> data);

		// to satisfy ConfigurationTarget::Machine
		void configure_as_target(const StaticAnalyser::Target &target);

		// to satisfy CPU6502::Processor
		unsigned int perform_bus_operation(CPU6502::BusOperation operation, uint16_t address, uint8_t *value);
		void synchronise();

		// to satisfy CRTMachine::Machine
		virtual void setup_output(float aspect_ratio);
		virtual void close_output();
		virtual std::shared_ptr<Outputs::CRT::CRT> get_crt() { return _videoOutput->get_crt(); }
		virtual std::shared_ptr<Outputs::Speaker> get_speaker() { return nullptr; }
		virtual void run_for_cycles(int number_of_cycles) { CPU6502::Processor<Machine>::run_for_cycles(number_of_cycles); }

		// to satisfy MOS::MOS6522IRQDelegate::Delegate
		void mos6522_did_change_interrupt_status(void *mos6522);

	private:
		// RAM and ROM
		uint8_t _ram[65536], _rom[16384];
		int _cycles_since_video_update;
		inline void update_video();

		// Outputs
		std::unique_ptr<VideoOutput> _videoOutput;

		//
		VIA _via;
};

}
#endif /* Oric_hpp */
<commit_msg>Made an attempt at implementing the loopbacks necessary for diagnostics.<commit_after>//
//  Oric.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 11/10/2016.
//  Copyright © 2016 Thomas Harte. All rights reserved.
//

#ifndef Oric_hpp
#define Oric_hpp

#include "../../Processors/6502/CPU6502.hpp"
#include "../../Components/6522/6522.hpp"
#include "../../Storage/Tape/Tape.hpp"

#include "../ConfigurationTarget.hpp"
#include "../CRTMachine.hpp"
#include "../Typer.hpp"

#include "Video.hpp"

#include <cstdint>
#include <vector>

namespace Oric {

class VIA: public MOS::MOS6522<VIA>, public MOS::MOS6522IRQDelegate {
	public:
		using MOS6522IRQDelegate::set_interrupt_status;

		void set_port_output(Port port, uint8_t value, uint8_t direction_mask) {
			port_outputs[port] = value;
			if(port)
				set_control_line_input(port, Line::One, (value << 1)&value&128);
		}
		uint8_t get_port_input(Port port) {
			if(port)
			{
				return port_outputs[0];
			}
			else
				return (uint8_t)((port_outputs[port] >> 4) | (port_outputs[port] << 4));
		}
		uint8_t port_outputs[2];
};

class Machine:
	public CPU6502::Processor<Machine>,
	public CRTMachine::Machine,
	public ConfigurationTarget::Machine,
	public MOS::MOS6522IRQDelegate::Delegate {

	public:
		Machine();

		void set_rom(std::vector<uint8_t> data);

		// to satisfy ConfigurationTarget::Machine
		void configure_as_target(const StaticAnalyser::Target &target);

		// to satisfy CPU6502::Processor
		unsigned int perform_bus_operation(CPU6502::BusOperation operation, uint16_t address, uint8_t *value);
		void synchronise();

		// to satisfy CRTMachine::Machine
		virtual void setup_output(float aspect_ratio);
		virtual void close_output();
		virtual std::shared_ptr<Outputs::CRT::CRT> get_crt() { return _videoOutput->get_crt(); }
		virtual std::shared_ptr<Outputs::Speaker> get_speaker() { return nullptr; }
		virtual void run_for_cycles(int number_of_cycles) { CPU6502::Processor<Machine>::run_for_cycles(number_of_cycles); }

		// to satisfy MOS::MOS6522IRQDelegate::Delegate
		void mos6522_did_change_interrupt_status(void *mos6522);

	private:
		// RAM and ROM
		uint8_t _ram[65536], _rom[16384];
		int _cycles_since_video_update;
		inline void update_video();

		// Outputs
		std::unique_ptr<VideoOutput> _videoOutput;

		//
		VIA _via;
};

}
#endif /* Oric_hpp */
<|endoftext|>