<commit_before>// Lesson 13.cpp : Defines the entry point for the console application.

#include <render_framework\render_framework.h>
#include <chrono>
#pragma comment (lib , "Render Framework" )

using namespace std;
using namespace glm;
using namespace render_framework;
using namespace chrono;

#define OBJECTS 1

// Global scope box
shared_ptr<mesh> object[1];
shared_ptr<free_camera> cam;

/*
 * moveCamera
 *
 * Moves the object around inside the window using the keyboard arrow keys.
 */
void moveCamera(float deltaTime)
{
	// Move the quad when arrow keys are pressed
	if (glfwGetKey(renderer::get_instance().get_window(), 'W')) {
		cam->move(vec3(0.0, 0.0, -5.0) * deltaTime);
	}
	if (glfwGetKey(renderer::get_instance().get_window(), 'S')) {
		cam->move(vec3(0.0, 0.0, 5.0) * deltaTime);
	}
	if (glfwGetKey(renderer::get_instance().get_window(), 'A')) {
		cam->move(vec3(-5.0, 0.0, 0.0) * deltaTime);
	}
	if (glfwGetKey(renderer::get_instance().get_window(), 'D')) {
		cam->move(vec3(5.0, 0.0, 0.0) * deltaTime);
	}
	if (glfwGetKey(renderer::get_instance().get_window(), 'Q')) {
		cam->rotate(half_pi<float>() * deltaTime, 0.0);
	}
	if (glfwGetKey(renderer::get_instance().get_window(), 'E')) {
		cam->rotate(-half_pi<float>() * deltaTime, 0.0);
	}
	if (glfwGetKey(renderer::get_instance().get_window(), GLFW_KEY_UP)) {
		cam->rotate(0.0, half_pi<float>() * deltaTime);
	}
	if (glfwGetKey(renderer::get_instance().get_window(), GLFW_KEY_DOWN)) {
		cam->rotate(0.0, -half_pi<float>() * deltaTime);
	}
} // moveCamera()

/*
 * Update routine
 *
 * Updates the application state
 */
void update(float deltaTime) {

	moveCamera(deltaTime);

	cam->update(deltaTime);

} // update()

bool load_content() {

	int i = 0;
	for (i=0;i<OBJECTS;i++) {
		// Create box
		object[i] = make_shared<mesh>();
		object[i]->geom = geometry_builder::create_box();

		// Load in effect.  Start with shaders
		auto eff = make_shared<effect>();
		eff->add_shader("shader.vert", GL_VERTEX_SHADER);
		eff->add_shader("shader.frag", GL_FRAGMENT_SHADER);
		if (!effect_loader::build_effect(eff)) {
			return false;
		}

		// Create material for box
		object[i]->mat = make_shared<material>();
		object[i]->mat->effect = eff;
		object[i]->mat->set_texture("tex", texture_loader::load("Checkered.png"));

		object[i]->trans.translate(vec3(0.0, (float) i*2+1, 0.0));
	}

	return true;

} // load_content()

bool load_camera() {
	// Initialize the camera
	cam = make_shared<free_camera>();

	/* Set the projection matrix */
	// First get the aspect ratio (width/height)
	float aspect = (float)renderer::get_instance().get_screen_width() /
					(float)renderer::get_instance().get_screen_width();
	// Use this to set the camera projection matrix
	cam->set_projection(
						quarter_pi<float>(),			// FOV
						aspect,							// Aspect ratio
						2.414f,							// Near plane
						10000.0f);						// Far plane
	// Set the camera properties
	cam->set_position(vec3(0.0, 0.0, 20.0));

	// Attach camera to renderer
	renderer::get_instance().set_camera(cam);

	// Set the view matrix
	auto view = lookAt(
					vec3(20.0f, 20.0f, 20.0f),	// Camera position
					vec3(0.0f, 0.0f, 0.0f),		// Target
					vec3(0.0f, 1.0f, 0.0f));	// Up vector
	renderer::get_instance().set_view(view);

	return true;
} // load_camera

int main()
{
	// Initialize the renderer
	if (!renderer::get_instance().initialise()) return -1;

	// Set the clear colour to cyan
	glClearColor(0.0f, 1.0f, 1.0f, 1.0f);

	if (!load_content()) {
		return -1;
	}

	if (!load_camera()) {
		return -1;
	}

	// Monitor the elapsed time per frame
	auto currentTimeStamp = system_clock::now();
	auto prevTimeStamp = system_clock::now();

	// Main render loop
	while (renderer::get_instance().is_running())
	{
		// Get current time
		currentTimeStamp = system_clock::now();
		// Calculate elapsed time
		auto elapsed = duration_cast<milliseconds>(currentTimeStamp - prevTimeStamp);
		// Convert to fractions of a second
		auto seconds = float(elapsed.count()) / 1000.0;

		// Update Scene
		update(seconds);

		// Check if running
		if (renderer::get_instance().begin_render())
		{
			// Render Cube
			int i = 0;
			for (i = 0; i <OBJECTS; i++) {
				renderer::get_instance().render(object[i]);
			}

			// End the render
			renderer::get_instance().end_render();
		}

		prevTimeStamp = currentTimeStamp;

	} // Main render loop
}
<commit_msg>Completed Lesson 29<commit_after>// Lesson 13.cpp : Defines the entry point for the console application.

#include <render_framework\render_framework.h>
#include <chrono>
#pragma comment (lib , "Render Framework" )

using namespace std;
using namespace glm;
using namespace render_framework;
using namespace chrono;

#define OBJECTS 1

// Global scope box
shared_ptr<mesh> object[1];
shared_ptr<chase_camera> cam;
shared_ptr<mesh> plane;

/*
 * userTranslation
 *
 * Moves the object around inside the window using the keyboard arrow keys.
 */
void userTranslation(float deltaTime)
{
	// Move the quad when arrow keys are pressed
	if (glfwGetKey(renderer::get_instance().get_window(), GLFW_KEY_RIGHT)) {
		object[0]->trans.translate(vec3(10.0, 0.0, 0.0) * deltaTime);
	}
	if (glfwGetKey(renderer::get_instance().get_window(), GLFW_KEY_LEFT)) {
		object[0]->trans.translate(vec3(-10.0, 0.0, 0.0) * deltaTime);
	}
	if (glfwGetKey(renderer::get_instance().get_window(), GLFW_KEY_UP)) {
		object[0]->trans.translate(vec3(0.0, 0.0, -10.0) * deltaTime);
	}
	if (glfwGetKey(renderer::get_instance().get_window(), GLFW_KEY_DOWN)) {
		object[0]->trans.translate(vec3(0.0, 0.0, 10.0) * deltaTime);
	}
	if (glfwGetKey(renderer::get_instance().get_window(), 'W')) {
		object[0]->trans.translate(vec3(0.0, 10.0, 0.0) * deltaTime);
	}
	if (glfwGetKey(renderer::get_instance().get_window(), 'S')) {
		object[0]->trans.translate(vec3(0.0, -10.0, 0.0) * deltaTime);
	}

} // userTranslation()

/*
 * Update routine
 *
 * Updates the application state
 */
void update(float deltaTime) {

	userTranslation(deltaTime);

	cam->move(object[0]->trans.position, eulerAngles(object[0]->trans.orientation));

	cam->rotate(vec3(0.0, half_pi<float>() * deltaTime, 0.0));

	cam->update(deltaTime);

} // update()

bool load_content() {

	int i = 0;
	for (i=0;i<OBJECTS;i++) {
		// Create box
		object[i] = make_shared<mesh>();
		object[i]->geom = geometry_builder::create_box();

		// Load in effect.  Start with shaders
		auto eff = make_shared<effect>();
		eff->add_shader("shader.vert", GL_VERTEX_SHADER);
		eff->add_shader("shader.frag", GL_FRAGMENT_SHADER);
		if (!effect_loader::build_effect(eff)) {
			return false;
		}

		// Create material for box
		object[i]->mat = make_shared<material>();
		object[i]->mat->effect = eff;

		// Set texture for shader
		object[i]->mat->set_texture("tex", texture_loader::load("Checkered.png"));

		// Create plane
		plane = make_shared<mesh>();
		plane->geom = geometry_builder::create_plane();
		plane->trans.translate(vec3(0.0, -0.5, 0.0));

		// Reuse the material from the box
		plane->mat = object[i]->mat;
	}

	return true;

} // load_content()

bool load_camera() {
	// Initialize the camera
	cam = make_shared<chase_camera>();

	/* Set the projection matrix */
	// First get the aspect ratio (width/height)
	float aspect = (float)renderer::get_instance().get_screen_width() /
					(float)renderer::get_instance().get_screen_width();
	// Use this to set the camera projection matrix
	cam->set_projection(
						quarter_pi<float>(),			// FOV
						aspect,							// Aspect ratio
						2.414f,							// Near plane
						10000.0f);						// Far plane
	// Set the camera properties
	cam->set_position(vec3(0.0, 0.0, 20.0));
	cam->set_springiness(0.001);
	cam->set_position_offset(vec3(0.0, 5.0, 10.0));

	// Attach camera to renderer
	renderer::get_instance().set_camera(cam);

	// Set the view matrix
	auto view = lookAt(
					vec3(20.0f, 20.0f, 20.0f),	// Camera position
					vec3(0.0f, 0.0f, 0.0f),		// Target
					vec3(0.0f, 1.0f, 0.0f));	// Up vector
	renderer::get_instance().set_view(view);

	return true;
} // load_camera

int main()
{
	// Initialize the renderer
	if (!renderer::get_instance().initialise()) return -1;

	// Set the clear colour to cyan
	glClearColor(0.0f, 1.0f, 1.0f, 1.0f);

	if (!load_content()) {
		return -1;
	}

	if (!load_camera()) {
		return -1;
	}

	// Monitor the elapsed time per frame
	auto currentTimeStamp = system_clock::now();
	auto prevTimeStamp = system_clock::now();

	// Main render loop
	while (renderer::get_instance().is_running())
	{
		// Get current time
		currentTimeStamp = system_clock::now();
		// Calculate elapsed time
		auto elapsed = duration_cast<milliseconds>(currentTimeStamp - prevTimeStamp);
		// Convert to fractions of a second
		auto seconds = float(elapsed.count()) / 1000.0;

		// Update Scene
		update(seconds);

		// Check if running
		if (renderer::get_instance().begin_render())
		{
			// Render Cube
			int i = 0;
			for (i = 0; i <OBJECTS; i++) {
				renderer::get_instance().render(object[i]);
			}

			// Render plane
			renderer::get_instance().render(plane);

			// End the render
			renderer::get_instance().end_render();
		}

		prevTimeStamp = currentTimeStamp;

	} // Main render loop
}
<|endoftext|>


<commit_before>#include "scppt.h"
#include "engine/world/WorldSystem.h"
#include "engine/world/Room.h"
#include "engine/world/Tile.h"
#include "engine/UI/Window.h"
#include "game/actor/player/PlayerActor.h"
#include "engine/scene/SceneSystem.h"

#include "precompiled.h"
#include "engine/math/vec2.h"
#include "engine/items/BaseInventory.h"
#include "game/items/IronItem.h"
#include "game/items/ArrowItem.h"
#include "game/items/containers/QuiverItem.h"

#include <map>

using namespace engine;

int testFails = 0;
int testOks   = 0;

int main(){
	SCPPT_START;

	PRINTLN("-> Tile");
	{
		world::Tile testTile;
		testTile.setType(world::TILE_TREE);

		SCPPT_COMPARE("Tree blocks movement",testTile.blocks,==,true);
		SCPPT_COMPARE("Tree has HP",testTile.hp,>,0);
	}

	PRINTLN("-> Room");
	{
		world::Room testRoom;
		testRoom.roomType = world::ROOM_TYPE_WATER;

		for(int i = 0;i <25;++i){
			testRoom.generate();
		}

		SCPPT_COMPARE("Rooms generate something",testRoom.getTile(5,5)->visual,==,'.');
	}

	PRINTLN("-> Window");
	{
		UI::Window window;
		window.setName("asdf");

		window.printDebugInfo();
	}

	PRINTLN("-> Player");
	{
		game::actor::player::PlayerActor *playerActor = new game::actor::player::PlayerActor();

		playerActor->update();
	}

	PRINTLN("-> Scene ");
	{
		engine::scene::SceneSystem *sceneSystem = new engine::scene::SceneSystem();
		SCPPT_COMPARE("Initializing scene", sceneSystem->init(),==,true);
	}

	PRINTLN("Tests complete");

	SCPPT_END;
}
<commit_msg>Added couple of tests<commit_after>#include "scppt.h"
#include "engine/world/WorldSystem.h"
#include "engine/world/Room.h"
#include "engine/world/Tile.h"
#include "engine/UI/Window.h"
#include "game/actor/player/PlayerActor.h"
#include "engine/scene/SceneSystem.h"

#include "precompiled.h"
#include "engine/math/vec2.h"
#include "engine/items/BaseInventory.h"
#include "game/items/IronItem.h"
#include "game/items/ArrowItem.h"
#include "game/items/containers/QuiverItem.h"

#include <map>

using namespace engine;

int testFails = 0;
int testOks   = 0;

int main(){
	SCPPT_START;

	PRINTLN("-> Tile");
	{
		world::Tile testTile;
		testTile.setType(world::TILE_TREE);

		SCPPT_COMPARE("Tree blocks movement",testTile.blocks,==,true);
		SCPPT_COMPARE("Tree has HP",testTile.hp,>,0);
	}

	PRINTLN("-> Room");
	{
		world::Room testRoom;
		testRoom.roomType = world::ROOM_TYPE_WATER;

		for(int i = 0;i <25;++i){
			testRoom.generate();
		}

		SCPPT_COMPARE("Rooms generate something",testRoom.getTile(5,5)->visual,==,'.');
	}

	PRINTLN("-> Window");
	{
		UI::Window window;
		window.setName("asdf");

		window.printDebugInfo();
	}

	PRINTLN("-> Player");
	{
		game::actor::player::PlayerActor *playerActor = new game::actor::player::PlayerActor();

		playerActor->update();

		SCPPT_COMPARE("Player has positive HP",playerActor->getHp(),>,0);
		SCPPT_COMPARE("Player has a name",playerActor->getName(),!=,"");
	}

	PRINTLN("-> Scene ");
	{
		engine::scene::SceneSystem *sceneSystem = new engine::scene::SceneSystem();
		SCPPT_COMPARE("Initializing scene", sceneSystem->init(),==,true);
	}

	PRINTLN("Tests complete");

	SCPPT_END;
}
<|endoftext|>


<commit_before>///
/// @file   test.cpp
/// @brief  primesum integration tests.
///
/// Copyright (C) 2016 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primesum-internal.hpp>
#include <primesum.hpp>
#include <int128_t.hpp>

#include <stdint.h>
#include <iostream>
#include <cstdlib>
#include <string>
#include <exception>
#include <sstream>
#include <ctime>

#ifdef _OPENMP
  #include <omp.h>
#endif

/// For types: f1(x) , f2(x)
#define CHECK_11(f1, f2) check_equal(#f1, x, f1 (x), f2 (x))

/// For types: f1(x) , f2(x, threads)
#define CHECK_21(f1, f2) check_equal(#f1, x, f1 (x, get_num_threads()), f2 (x))

/// For types: f1(x, threads) , f2(x, threads)
#define CHECK_22(f1, f2) check_equal(#f1, x, f1 (x, get_num_threads()), f2 (x, get_num_threads()))

#define CHECK_EQUAL(f1, f2, check, iters) \
{ \
  cout << "Testing " << #f1 << "(x)" << flush; \
 \
  /* test for 0 <= x < 10000 */ \
  for (int64_t x = 0; x < 10000; x++) \
    check(f1, f2); \
 \
  int64_t x = 0; \
  /* test using random increment */ \
  for (int64_t i = 0; i < iters; i++, x += get_rand()) \
  { \
    check(f1, f2); \
    double percent = 100.0 * (i + 1.0) / iters; \
    cout << "\rTesting " << #f1 "(x) " << (int) percent << "%" << flush; \
  } \
 \
  cout << endl; \
}

using namespace std;
using namespace primesum;

namespace {

int get_rand()
{
  // 0 <= get_rand() < 10^7
  return (rand() % 10000) * 1000 + 1;
}

void check_equal(const string& f1, int64_t x, int64_t res1, int64_t res2)
{
  if (res1 != res2)
  {
    ostringstream oss;
    oss << f1 << "(" << x << ") = " << res1
        << " is an error, the correct result is " << res2;
    throw primesum_error(oss.str());
  }
}

void test_phi_thread_safety(int64_t iters)
{
#ifdef _OPENMP
  cout << "Testing phi(x, a)" << flush;

  int64_t sum1 = 0;
  int64_t sum2 = 0;

  for (int64_t i = 0; i < iters; i++)
    sum1 += pi_legendre(10000000 + i, 1);

  #pragma omp parallel for reduction(+: sum2)
  for (int64_t i = 0; i < iters; i++)
    sum2 += pi_legendre(10000000 + i, 1);

  if (sum1 != sum2)
    throw primesum_error("Error: multi-threaded phi(x, a) is broken.");

  std::cout << "\rTesting phi(x, a) 100%" << endl;
#endif
}

} // namespace

namespace primesum {

bool test()
{
  set_print_status(false);
  srand(static_cast<unsigned>(time(0)));

  try
  {
    test_phi_thread_safety(100);

    CHECK_EQUAL(pi_lmo1,                         prime_sum_tiny,      CHECK_11,  50);
    CHECK_EQUAL(pi_lmo2,                         pi_lmo1,             CHECK_11,  100);
    CHECK_EQUAL(pi_lmo3,                         pi_lmo2,             CHECK_11,  300);
    CHECK_EQUAL(pi_lmo4,                         pi_lmo3,             CHECK_11,  400);
    CHECK_EQUAL(pi_lmo5,                         pi_lmo4,             CHECK_11,  600);
    CHECK_EQUAL(pi_lmo_parallel1,                pi_lmo5,             CHECK_21,  600);
    CHECK_EQUAL(pi_deleglise_rivat_parallel1,    pi_lmo_parallel1,    CHECK_22,  900);
  }
  catch (exception& e)
  {
    cerr << endl << e.what() << endl;
    return false;
  }

  cout << "All tests passed successfully!" << endl;
  return true;
}

} // namespace
<commit_msg>Silence unused parameter warning<commit_after>///
/// @file   test.cpp
/// @brief  primesum integration tests.
///
/// Copyright (C) 2016 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primesum-internal.hpp>
#include <primesum.hpp>
#include <int128_t.hpp>

#include <stdint.h>
#include <iostream>
#include <cstdlib>
#include <string>
#include <exception>
#include <sstream>
#include <ctime>

#ifdef _OPENMP
  #include <omp.h>
#endif

/// For types: f1(x) , f2(x)
#define CHECK_11(f1, f2) check_equal(#f1, x, f1 (x), f2 (x))

/// For types: f1(x) , f2(x, threads)
#define CHECK_21(f1, f2) check_equal(#f1, x, f1 (x, get_num_threads()), f2 (x))

/// For types: f1(x, threads) , f2(x, threads)
#define CHECK_22(f1, f2) check_equal(#f1, x, f1 (x, get_num_threads()), f2 (x, get_num_threads()))

#define CHECK_EQUAL(f1, f2, check, iters) \
{ \
  cout << "Testing " << #f1 << "(x)" << flush; \
 \
  /* test for 0 <= x < 10000 */ \
  for (int64_t x = 0; x < 10000; x++) \
    check(f1, f2); \
 \
  int64_t x = 0; \
  /* test using random increment */ \
  for (int64_t i = 0; i < iters; i++, x += get_rand()) \
  { \
    check(f1, f2); \
    double percent = 100.0 * (i + 1.0) / iters; \
    cout << "\rTesting " << #f1 "(x) " << (int) percent << "%" << flush; \
  } \
 \
  cout << endl; \
}

using namespace std;
using namespace primesum;

namespace {

int get_rand()
{
  // 0 <= get_rand() < 10^7
  return (rand() % 10000) * 1000 + 1;
}

void check_equal(const string& f1, int64_t x, int64_t res1, int64_t res2)
{
  if (res1 != res2)
  {
    ostringstream oss;
    oss << f1 << "(" << x << ") = " << res1
        << " is an error, the correct result is " << res2;
    throw primesum_error(oss.str());
  }
}

#ifdef _OPENMP

void test_phi_thread_safety(int64_t iters)
{
  cout << "Testing phi(x, a)" << flush;

  int64_t sum1 = 0;
  int64_t sum2 = 0;

  for (int64_t i = 0; i < iters; i++)
    sum1 += pi_legendre(10000000 + i, 1);

  #pragma omp parallel for reduction(+: sum2)
  for (int64_t i = 0; i < iters; i++)
    sum2 += pi_legendre(10000000 + i, 1);

  if (sum1 != sum2)
    throw primesum_error("Error: multi-threaded phi(x, a) is broken.");

  std::cout << "\rTesting phi(x, a) 100%" << endl;
}

#endif

} // namespace

namespace primesum {

bool test()
{
  set_print_status(false);
  srand(static_cast<unsigned>(time(0)));

  try
  {
#ifdef _OPENMP
    test_phi_thread_safety(100);
#endif

    CHECK_EQUAL(pi_lmo1,                         prime_sum_tiny,      CHECK_11,  50);
    CHECK_EQUAL(pi_lmo2,                         pi_lmo1,             CHECK_11,  100);
    CHECK_EQUAL(pi_lmo3,                         pi_lmo2,             CHECK_11,  300);
    CHECK_EQUAL(pi_lmo4,                         pi_lmo3,             CHECK_11,  400);
    CHECK_EQUAL(pi_lmo5,                         pi_lmo4,             CHECK_11,  600);
    CHECK_EQUAL(pi_lmo_parallel1,                pi_lmo5,             CHECK_21,  600);
    CHECK_EQUAL(pi_deleglise_rivat_parallel1,    pi_lmo_parallel1,    CHECK_22,  900);
  }
  catch (exception& e)
  {
    cerr << endl << e.what() << endl;
    return false;
  }

  cout << "All tests passed successfully!" << endl;
  return true;
}

} // namespace
<|endoftext|>


<commit_before>#define CATCH_CONFIG_MAIN
#include "../inc/catch.hpp"

extern "C"
{
#include "../inc/PreReader.h"
};

TEST_CASE("PreReader initialization", "[prInit]")
{
	// some random file
	FILE *file = stdin;
	struct PreReader pr;

	prInit(&pr, file);

	REQUIRE(pr.file == file);
	REQUIRE(pr.read_pos == 0);
	REQUIRE(pr.write_pos == 0);
}

TEST_CASE("PreReader get next char", "[prNext]")
{
	struct PreReader pr;
	char data[] = "abcdef\0\n\t\b!@#$";
	FILE *file = fmemopen(data, 14, "r");

	REQUIRE(file != NULL);
	prInit(&pr, file);

	// test normal reading
	for (int i = 0; i < 14; i++)
		REQUIRE(prNext(&pr) == (int)(data)[i]);

	REQUIRE(prNext(&pr) == EOF);
	REQUIRE(prNext(&pr) == EOF);

	// test invalid parameter
	REQUIRE(prNext(NULL) == EOF);

	fseek(pr.file, 0, SEEK_SET);
	pr.write_pos = 0;
	pr.read_pos = 1;
	REQUIRE(prNext(&pr) == EOF);

	pr.write_pos = PREREADER_BUFFER_SIZE;
	pr.read_pos = 6;
	REQUIRE(prNext(&pr) == 0);

	pr.write_pos = PREREADER_BUFFER_SIZE + 1;
	REQUIRE(prNext(&pr) == EOF);

	// close file
	REQUIRE(fclose(file) == 0);

	// test reload
	char bigdata[PREREADER_BUFFER_SIZE + 1];
	bigdata[PREREADER_BUFFER_SIZE - 1] = 'A';
	bigdata[PREREADER_BUFFER_SIZE] = 'B';
	file = fmemopen(bigdata, PREREADER_BUFFER_SIZE + 1, "r");

	REQUIRE(file != NULL);
	prInit(&pr, file);

	for (int i = 0; i < PREREADER_BUFFER_SIZE + 1; i++)
		REQUIRE(prNext(&pr) == (int)bigdata[i]);

	REQUIRE(prNext(&pr) == EOF);
	REQUIRE(prNext(&pr) == EOF);
}<commit_msg>Added unit test for parseLogEntry().<commit_after>#define CATCH_CONFIG_MAIN
#include "../inc/catch.hpp"

extern "C"
{
#include "../inc/Date.h"
#include "../inc/LogEntry.h"
#include "../inc/parse.h"
#include "../inc/PreReader.h"
};

TEST_CASE("parse log entry", "[parseLogEntry]")
{
	// format: %t#%h#%u#%s#%I#%O#%U#%{Referer}i#%m
	struct PreReader reader;
	struct LogEntry entry;
	FILE *file;

	// normal log line
	const char *s0 = "[07/Nov/2016:17:40:56 +0000]#1.2.3.4#-#200#1112#3757#/index.html#/#GET";
	file = fmemopen((char*)s0, strlen(s0), "r");
	prInit(&reader, file);

	REQUIRE(parseLogEntry(&reader, NULL) == -1);
	REQUIRE(parseLogEntry(NULL, &entry) == -1);
	REQUIRE(parseLogEntry(NULL, NULL) == -1);

	REQUIRE(parseLogEntry(&reader, &entry) == 0);
	REQUIRE(entry.date.day == 7);
	REQUIRE(entry.date.month == 11);
	REQUIRE(entry.date.year == 2016);
	REQUIRE(entry.http_method == HTTP_GET);
	REQUIRE(entry.http_status == 200);
	REQUIRE(entry.request_size == 1112);
	REQUIRE(entry.response_size == 3757);
	REQUIRE(strcmp(entry.remote_address, "1.2.3.4") == 0);
	REQUIRE(strcmp(entry.username, "-") == 0);
	REQUIRE(strcmp(entry.requested_file, "/index.html") == 0);
	REQUIRE(strcmp(entry.referer, "/") == 0);

	fclose(file);

	// very strange but still valid log line
	const char *s1 = "[255/mAR/65535:4:2:0 +1337]#fancy.url.com##65535#4294967295#0#/!@#$##";
	file = fmemopen((char*)s1, strlen(s1), "r");
	prInit(&reader, file);

	REQUIRE(parseLogEntry(&reader, &entry) == 0);
	REQUIRE(entry.date.day == 255);
	REQUIRE(entry.date.month == 3);
	REQUIRE(entry.date.year == 65535);
	REQUIRE(entry.http_method == HTTP_UNKNOWN);
	REQUIRE(entry.http_status == 65535);
	REQUIRE(entry.request_size == 4294967295);
	REQUIRE(entry.response_size == 0);
	REQUIRE(strcmp(entry.remote_address, "fancy.url.com") == 0);
	REQUIRE(entry.username == NULL);
	REQUIRE(strcmp(entry.requested_file, "/!@#$") == 0);
	REQUIRE(entry.referer == NULL);

	fclose(file);

	// invalid format (negative year)
	const char *s2 = "[3/Oct/-1:4:2:0 +1337]#8.8.8.8#mike#200#257#2395#/index.html##GET";
	file = fmemopen((char*)s2, strlen(s2), "r");
	prInit(&reader, file);

	REQUIRE(parseLogEntry(&reader, &entry) == 1);

	fclose(file);
}

TEST_CASE("PreReader initialization", "[prInit]")
{
	// some random file
	FILE *file = stdin;
	struct PreReader pr;

	prInit(&pr, file);

	REQUIRE(pr.file == file);
	REQUIRE(pr.read_pos == 0);
	REQUIRE(pr.write_pos == 0);
}

TEST_CASE("PreReader get next char", "[prNext]")
{
	struct PreReader pr;
	const char *data = "abcdef\0\n\t\b!@#$";
	FILE *file = fmemopen((void*)data, 14, "r");

	REQUIRE(file != NULL);
	prInit(&pr, file);

	// test normal reading
	for (int i = 0; i < 14; i++)
		REQUIRE(prNext(&pr) == (int)(data)[i]);

	REQUIRE(prNext(&pr) == EOF);
	REQUIRE(prNext(&pr) == EOF);

	// test invalid parameter
	REQUIRE(prNext(NULL) == EOF);

	fseek(pr.file, 0, SEEK_SET);
	pr.write_pos = 0;
	pr.read_pos = 1;
	REQUIRE(prNext(&pr) == EOF);

	pr.write_pos = PREREADER_BUFFER_SIZE;
	pr.read_pos = 6;
	REQUIRE(prNext(&pr) == 0);

	pr.write_pos = PREREADER_BUFFER_SIZE + 1;
	REQUIRE(prNext(&pr) == EOF);

	// close file
	REQUIRE(fclose(file) == 0);

	// test reload
	char bigdata[PREREADER_BUFFER_SIZE + 1];
	bigdata[PREREADER_BUFFER_SIZE - 1] = 'A';
	bigdata[PREREADER_BUFFER_SIZE] = 'B';
	file = fmemopen(bigdata, PREREADER_BUFFER_SIZE + 1, "r");

	REQUIRE(file != NULL);
	prInit(&pr, file);

	for (int i = 0; i < PREREADER_BUFFER_SIZE + 1; i++)
		REQUIRE(prNext(&pr) == (int)bigdata[i]);

	REQUIRE(prNext(&pr) == EOF);
	REQUIRE(prNext(&pr) == EOF);
}<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <sstream>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include <sys/utsname.h>

static const char* const ANSI_COLOR_RESET_FG            = "\x1b[39m";

static const char* const ANSI_COLOR_TITLE_FG            = ANSI_COLOR_RESET_FG;
static const char* const ANSI_COLOR_EXPLANATION_FG      = ANSI_COLOR_RESET_FG;
static const char* const ANSI_COLOR_COMMENT_FG          = "\x1b[32m";

static const char* const ANSI_COLOR_CODE_FG             = "\x1b[31m";
static const char* const ANSI_COLOR_CODE_PLACEHOLDER_FG = "\x1b[34m";

static const char* const ANSI_BOLD_ON                   = "\x1b[1m";
static const char* const ANSI_BOLD_OFF                  = "\x1b[22m";

// Constants.
std::string const kBaseUrl =
    "http://raw.github.com/tldr-pages/tldr/master/pages";

void init_response(struct response* r);
size_t writeCallback(char* raw, size_t size, size_t nmemb, std::string* data);

// Fetching.
std::string getUrlForArgAndPlatform(std::string const& arg,
                                    std::string const& platform);
std::string getUrlForArg(std::string const& arg);
std::string getContentForUrl(std::string const& url);

// Utilities.
void replaceAll(std::string& str, std::string const& from,
                std::string const& to);

int main(int argc, char* argv[])
{
    struct utsname sys;
    uname(&sys);

    if (argc > 1)
    {
        std::string arg(argv[1]);
        std::string url = getUrlForArg(arg);
        std::string urlForPlatform = getUrlForArgAndPlatform(arg, sys.sysname);

        std::string response = getContentForUrl(urlForPlatform);
        if (response.empty()) { response = getContentForUrl(url); }

        replaceAll(response, "{{", ANSI_COLOR_CODE_PLACEHOLDER_FG);
        replaceAll(response, "}}", ANSI_COLOR_RESET_FG);

        std::string const stripPrefix("#");
        std::string const explainPrefix(">");
        std::string const commentPrefix("-");
        std::string const codePrefix("`");
        std::stringstream ss(response);
        std::string to;
        bool firstComment = true;

        while (std::getline(ss, to, '\n'))
        {
            // Title
            if (to.compare(0, stripPrefix.size(), stripPrefix) == 0)
            {
                replaceAll(to, "#", ANSI_COLOR_TITLE_FG);
                std::cout << std::endl
                          << ANSI_BOLD_ON
                          << to
                          << ANSI_BOLD_OFF
                          << ANSI_COLOR_RESET_FG
                          << std::endl;
            }
            // Command explanation
            else if (to.compare(0, explainPrefix.size(), explainPrefix) == 0)
            {
                replaceAll(to, ">", ANSI_COLOR_EXPLANATION_FG);
                std::cout << to << ANSI_COLOR_RESET_FG << std::endl;
            }
            // Example comment
            else if (to.compare(0, commentPrefix.size(), commentPrefix) == 0)
            {
                if (firstComment)
                {
                    std::cout << std::endl;
                    firstComment = false;
                }

                replaceAll(to, "-", ANSI_COLOR_COMMENT_FG);
                std::cout << to << ANSI_COLOR_RESET_FG << std::endl;
            }
            // Code example
            else if (to.compare(0, codePrefix.size(), codePrefix) == 0)
            {
                // Remove trailing backtick (`).
                to = to.substr(0, to.size() - 1);

                // Replace first backtick (`) with three spaces for aligned indentation.
                replaceAll(to, "`", "   ");
                std::cout << ANSI_COLOR_CODE_FG
                          << to
                          << ANSI_COLOR_RESET_FG
                          << std::endl
                          << std::endl;
            }
        }
    }
}

// =====================================
// URL determination.
// =====================================
std::string getUrlForArgAndPlatform(std::string const& arg,
                                    std::string const& platform)
{
    int isLinux = !platform.compare("Linux");
    int isOSX = !platform.compare("Darwin");

    std::string platformUrlDelimiter;
    if (isLinux) { platformUrlDelimiter = "linux"; }
    else if (isOSX) { platformUrlDelimiter = "osx"; }
    else { platformUrlDelimiter = "common"; }

    std::string url(kBaseUrl);
    url += "/" + platformUrlDelimiter + "/" + arg + ".md";

    return url;
}

std::string getUrlForArg(std::string const& arg)
{
    return getUrlForArgAndPlatform(arg, "common");
}

// =====================================
// Curl Fetching.
// =====================================
size_t writeCallback(char* raw, size_t size, size_t nmemb, std::string* data)
{
    if (data == NULL) { return 0; }

    data->append(raw, size * nmemb);
    return size * nmemb;
}

std::string getContentForUrl(std::string const& url)
{
    CURL* curl;
    CURLcode res;
    std::string response;

    curl = curl_easy_init();
    if (curl)
    {
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);

        res = curl_easy_perform(curl);
        if (res == CURLE_OK)
        {
            long httpCode = 0;
            curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);

            if (httpCode == 200)
            {
                curl_easy_cleanup(curl);
                return response;
            }
            else
            {
                curl_easy_cleanup(curl);
                return "";
            }
        }

        curl_easy_cleanup(curl);
    }

    return "";
}

// =====================================
// Utilities.
// =====================================
void replaceAll(std::string& str, std::string const& from,
                std::string const& to)
{
    if (from.empty()) { return; }

    size_t start_pos = 0;
    while ((start_pos = str.find(from, start_pos)) != std::string::npos)
    {
        str.replace(start_pos, from.length(), to);
        start_pos += to.length();
    }
}

<commit_msg>replace bare strings<commit_after>#include <iostream>
#include <string>
#include <sstream>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include <sys/utsname.h>

static const char* const ANSI_COLOR_RESET_FG            = "\x1b[39m";

static const char* const ANSI_COLOR_TITLE_FG            = ANSI_COLOR_RESET_FG;
static const char* const ANSI_COLOR_EXPLANATION_FG      = ANSI_COLOR_RESET_FG;
static const char* const ANSI_COLOR_COMMENT_FG          = "\x1b[32m";

static const char* const ANSI_COLOR_CODE_FG             = "\x1b[31m";
static const char* const ANSI_COLOR_CODE_PLACEHOLDER_FG = "\x1b[34m";

static const char* const ANSI_BOLD_ON                   = "\x1b[1m";
static const char* const ANSI_BOLD_OFF                  = "\x1b[22m";

// Constants.
std::string const kBaseUrl =
    "http://raw.github.com/tldr-pages/tldr/master/pages";

void init_response(struct response* r);
size_t writeCallback(char* raw, size_t size, size_t nmemb, std::string* data);

// Fetching.
std::string getUrlForArgAndPlatform(std::string const& arg,
                                    std::string const& platform);
std::string getUrlForArg(std::string const& arg);
std::string getContentForUrl(std::string const& url);

// Utilities.
void replaceAll(std::string& str, std::string const& from,
                std::string const& to);

int main(int argc, char* argv[])
{
    struct utsname sys;
    uname(&sys);

    if (argc > 1)
    {
        std::string arg(argv[1]);
        std::string url = getUrlForArg(arg);
        std::string urlForPlatform = getUrlForArgAndPlatform(arg, sys.sysname);

        std::string response = getContentForUrl(urlForPlatform);
        if (response.empty()) { response = getContentForUrl(url); }

        replaceAll(response, "{{", ANSI_COLOR_CODE_PLACEHOLDER_FG);
        replaceAll(response, "}}", ANSI_COLOR_RESET_FG);

        std::string const stripPrefix("#");
        std::string const explainPrefix(">");
        std::string const commentPrefix("-");
        std::string const codePrefix("`");
        std::stringstream ss(response);
        std::string to;
        bool firstComment = true;

        while (std::getline(ss, to, '\n'))
        {
            // Title
            if (to.compare(0, stripPrefix.size(), stripPrefix) == 0)
            {
                replaceAll(to, "#", ANSI_COLOR_TITLE_FG);
                std::cout << std::endl
                          << ANSI_BOLD_ON
                          << to
                          << ANSI_BOLD_OFF
                          << ANSI_COLOR_RESET_FG
                          << std::endl;
            }
            // Command explanation
            else if (to.compare(0, explainPrefix.size(), explainPrefix) == 0)
            {
                replaceAll(to, explainPrefix, ANSI_COLOR_EXPLANATION_FG);
                std::cout << to << ANSI_COLOR_RESET_FG << std::endl;
            }
            // Example comment
            else if (to.compare(0, commentPrefix.size(), commentPrefix) == 0)
            {
                if (firstComment)
                {
                    std::cout << std::endl;
                    firstComment = false;
                }

                replaceAll(to, commentPrefix, ANSI_COLOR_COMMENT_FG);
                std::cout << to << ANSI_COLOR_RESET_FG << std::endl;
            }
            // Code example
            else if (to.compare(0, codePrefix.size(), codePrefix) == 0)
            {
                // Remove trailing backtick (`).
                to = to.substr(0, to.size() - 1);

                // Replace first backtick (`) with three spaces for aligned indentation.
                replaceAll(to, "`", "   ");
                std::cout << ANSI_COLOR_CODE_FG
                          << to
                          << ANSI_COLOR_RESET_FG
                          << std::endl
                          << std::endl;
            }
        }
    }
}

// =====================================
// URL determination.
// =====================================
std::string getUrlForArgAndPlatform(std::string const& arg,
                                    std::string const& platform)
{
    int isLinux = !platform.compare("Linux");
    int isOSX = !platform.compare("Darwin");

    std::string platformUrlDelimiter;
    if (isLinux) { platformUrlDelimiter = "linux"; }
    else if (isOSX) { platformUrlDelimiter = "osx"; }
    else { platformUrlDelimiter = "common"; }

    std::string url(kBaseUrl);
    url += "/" + platformUrlDelimiter + "/" + arg + ".md";

    return url;
}

std::string getUrlForArg(std::string const& arg)
{
    return getUrlForArgAndPlatform(arg, "common");
}

// =====================================
// Curl Fetching.
// =====================================
size_t writeCallback(char* raw, size_t size, size_t nmemb, std::string* data)
{
    if (data == NULL) { return 0; }

    data->append(raw, size * nmemb);
    return size * nmemb;
}

std::string getContentForUrl(std::string const& url)
{
    CURL* curl;
    CURLcode res;
    std::string response;

    curl = curl_easy_init();
    if (curl)
    {
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);

        res = curl_easy_perform(curl);
        if (res == CURLE_OK)
        {
            long httpCode = 0;
            curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);

            if (httpCode == 200)
            {
                curl_easy_cleanup(curl);
                return response;
            }
            else
            {
                curl_easy_cleanup(curl);
                return "";
            }
        }

        curl_easy_cleanup(curl);
    }

    return "";
}

// =====================================
// Utilities.
// =====================================
void replaceAll(std::string& str, std::string const& from,
                std::string const& to)
{
    if (from.empty()) { return; }

    size_t start_pos = 0;
    while ((start_pos = str.find(from, start_pos)) != std::string::npos)
    {
        str.replace(start_pos, from.length(), to);
        start_pos += to.length();
    }
}

<|endoftext|>


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

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

#ifndef _SD_XMLVIEWSETTINGSCONTEXT_HXX
#include "viewcontext.hxx"
#endif
#ifndef _SDXMLIMP_IMPL_HXX
#include "sdxmlimp_impl.hxx"
#endif

#ifndef _XMLOFF_XMLTOKEN_HXX
#include "xmltoken.hxx"
#endif
#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif
#ifndef _XMLOFF_NMSPMAP_HXX
#include "nmspmap.hxx"
#endif
#ifndef _XMLOFF_VISAREACONTEXT_HXX
#include "VisAreaContext.hxx"
#endif

using namespace com::sun::star;
using namespace rtl;
using ::xmloff::token::IsXMLToken;

using ::xmloff::token::XML_EMBEDDED_VISIBLE_AREA;

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

SdXMLViewSettingsContext::SdXMLViewSettingsContext( SdXMLImport& rImport, USHORT nPrfx, const OUString& rLName, const uno::Reference<xml::sax::XAttributeList>& ) :
    SvXMLImportContext( rImport, nPrfx, rLName )
{
}

SdXMLViewSettingsContext::~SdXMLViewSettingsContext()
{
}

SvXMLImportContext *SdXMLViewSettingsContext::CreateChildContext( USHORT nPrefix,
                                     const OUString& rLocalName,
                                     const ::com::sun::star::uno::Reference<
                                          ::com::sun::star::xml::sax::XAttributeList>& xAttrList )
{
    SvXMLImportContext *pContext = 0;

    if (nPrefix == XML_NAMESPACE_OFFICE)
    {
        if ( IsXMLToken( rLocalName, XML_EMBEDDED_VISIBLE_AREA ) )
        {
            sal_Int16 nMeasureUnit = 0;

            uno::Reference< beans::XPropertySet > xProps( GetImport().GetModel(), uno::UNO_QUERY );
            if( xProps.is() )
                xProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "MapUnit" ) ) ) >>= nMeasureUnit;

            pContext = new XMLVisAreaContext(GetImport(), nPrefix, rLocalName, xAttrList, maVisArea, nMeasureUnit);
        }
    }

    if( !pContext )
        pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );

    return pContext;
}

void SdXMLViewSettingsContext::EndElement()
{
    uno::Reference< beans::XPropertySet > xProps( GetImport().GetModel(), uno::UNO_QUERY );
    if( xProps.is() )
    {
        uno::Any aAny;
        aAny <<= maVisArea;

        xProps->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "VisibleArea" ) ), aAny );
    }
}
<commit_msg>INTEGRATION: CWS vgbugs07 (1.5.124); FILE MERGED 2007/06/04 13:23:24 vg 1.5.124.1: #i76605# Remove -I .../inc/module hack introduced by hedaburemove01<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: viewcontext.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: hr $ $Date: 2007-06-27 15:07:18 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

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

#ifndef _SD_XMLVIEWSETTINGSCONTEXT_HXX
#include "viewcontext.hxx"
#endif
#ifndef _SDXMLIMP_IMPL_HXX
#include "sdxmlimp_impl.hxx"
#endif

#ifndef _XMLOFF_XMLTOKEN_HXX
#include <xmloff/xmltoken.hxx>
#endif
#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif
#ifndef _XMLOFF_NMSPMAP_HXX
#include <xmloff/nmspmap.hxx>
#endif
#ifndef _XMLOFF_VISAREACONTEXT_HXX
#include "VisAreaContext.hxx"
#endif

using namespace com::sun::star;
using namespace rtl;
using ::xmloff::token::IsXMLToken;

using ::xmloff::token::XML_EMBEDDED_VISIBLE_AREA;

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

SdXMLViewSettingsContext::SdXMLViewSettingsContext( SdXMLImport& rImport, USHORT nPrfx, const OUString& rLName, const uno::Reference<xml::sax::XAttributeList>& ) :
    SvXMLImportContext( rImport, nPrfx, rLName )
{
}

SdXMLViewSettingsContext::~SdXMLViewSettingsContext()
{
}

SvXMLImportContext *SdXMLViewSettingsContext::CreateChildContext( USHORT nPrefix,
                                     const OUString& rLocalName,
                                     const ::com::sun::star::uno::Reference<
                                          ::com::sun::star::xml::sax::XAttributeList>& xAttrList )
{
    SvXMLImportContext *pContext = 0;

    if (nPrefix == XML_NAMESPACE_OFFICE)
    {
        if ( IsXMLToken( rLocalName, XML_EMBEDDED_VISIBLE_AREA ) )
        {
            sal_Int16 nMeasureUnit = 0;

            uno::Reference< beans::XPropertySet > xProps( GetImport().GetModel(), uno::UNO_QUERY );
            if( xProps.is() )
                xProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "MapUnit" ) ) ) >>= nMeasureUnit;

            pContext = new XMLVisAreaContext(GetImport(), nPrefix, rLocalName, xAttrList, maVisArea, nMeasureUnit);
        }
    }

    if( !pContext )
        pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );

    return pContext;
}

void SdXMLViewSettingsContext::EndElement()
{
    uno::Reference< beans::XPropertySet > xProps( GetImport().GetModel(), uno::UNO_QUERY );
    if( xProps.is() )
    {
        uno::Any aAny;
        aAny <<= maVisArea;

        xProps->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "VisibleArea" ) ), aAny );
    }
}
<|endoftext|>


<commit_before>/*
 * v8cgi main file. Loosely based on V8's "shell" sample app.
 */

#include <v8.h>
#include "js_system.h"
#include "js_io.h"
#include "js_mysql.h"
#include "js_gd.h"
#include "js_common.h"

#include <sstream>
#include <libgen.h>

#define _STRING(x) #x
#define STRING(x) _STRING(x)

v8::Handle<v8::Array> __onexit;

void die(int code) {
	uint32_t max = __onexit->Length();
	v8::Handle<v8::Function> fun;
	for (unsigned int i=0;i<max;i++) {
		fun = v8::Handle<v8::Function>::Cast(__onexit->Get(JS_INT(i)));
		fun->Call(v8::Context::GetCurrent()->Global(), 0, NULL);
	}
	exit(code);
}

v8::Handle<v8::String> read_file(const char* name) {
	printf("%s",name);
	FILE* file = fopen(name, "rb");
	if (file == NULL) return v8::Handle<v8::String>();

	fseek(file, 0, SEEK_END);
	size_t size = ftell(file);
	rewind(file);

	char* chars = new char[size + 1];
	chars[size] = '\0';
	for (unsigned int i = 0; i < size;) {
		size_t read = fread(&chars[i], 1, size - i, file);
		i += read;
	}
	fclose(file);

	/* remove shebang line */
	std::string str = chars;
	if ( str.find('#',0) == 0 && str.find('!',1) == 1 ) {
		unsigned int pfix = str.find('\n',0);
		str.erase(0,pfix);
	};

	v8::Handle<v8::String> result = JS_STR(str.c_str());
	delete[] chars;
	return result;
}

void report_exception(v8::TryCatch* try_catch) {
	v8::HandleScope handle_scope;
	v8::String::Utf8Value exception(try_catch->Exception());
	v8::Handle<v8::Message> message = try_catch->Message();
	std::string msgstring = "";
	std::stringstream ss;
	std::string tmp;

	if (message.IsEmpty()) {
		msgstring += *exception;
		msgstring += "\n";
	} else {
		v8::String::Utf8Value filename(message->GetScriptResourceName());
		int linenum = message->GetLineNumber();
		msgstring += *filename;
		msgstring += ":";

		ss << linenum;
		ss >> tmp;

		msgstring += tmp;
		msgstring += ": ";
		msgstring += *exception;
		msgstring += "\n";
		v8::String::Utf8Value sourceline(message->GetSourceLine());
		msgstring += *sourceline;
		msgstring += "\n";

		// Print wavy underline (GetUnderline is deprecated).
		int start = message->GetStartColumn();
		for (int i = 0; i < start; i++) {
			msgstring += " ";
		}
		int end = message->GetEndColumn();
		for (int i = start; i < end; i++) {
			msgstring += "^";
		}
		msgstring += "\n";
	}

	int cgi = 0;
	v8::Local<v8::Function> fun;
	v8::Local<v8::Value> context = v8::Context::GetCurrent()->Global()->Get(JS_STR("response"));
	if (context->IsObject()) {
		v8::Local<v8::Value> print = context->ToObject()->Get(JS_STR("error"));
		if (print->IsObject()) {
			fun = v8::Local<v8::Function>::Cast(print);
			cgi = 1;
		}
	}
	if (!cgi) {
		context = v8::Context::GetCurrent()->Global()->Get(JS_STR("System"));
		fun = v8::Local<v8::Function>::Cast(context->ToObject()->Get(JS_STR("stdout")));
	}

	v8::Handle<v8::Value> data[1];
	data[0] = JS_STR(msgstring.c_str());
	fun->Call(context->ToObject(), 1, data);
}

int execute_file(const char * str) {
	v8::HandleScope handle_scope;
	v8::TryCatch try_catch;
	v8::Handle<v8::String> name = JS_STR(str);
	v8::Handle<v8::String> source = read_file(str);

	if (source.IsEmpty()) {
		printf("Error reading '%s'\n", str);
		return 1;
	}

	v8::Handle<v8::Script> script = v8::Script::Compile(source, name);
	if (script.IsEmpty()) {
		report_exception(&try_catch);
		return 1;
	} else {

		char * old = getcwd(NULL, 0);
		char * end = strrchr(str, '/');
		if (end == NULL) {
			end = strrchr(str, '\\');
		}

		if (end != NULL) {
			int len = end-str;
			char * base = (char *) malloc(len+1);
			strncpy(base, str, len);
    			base[len] = '\0';
    			chdir(base);
		}
		v8::Handle<v8::Value> result = script->Run();
		chdir(old);
		if (result.IsEmpty()) {
			report_exception(&try_catch);
			return 1;
		}
	}
	return 0;
}

int library(char * name) {
	v8::HandleScope handle_scope;
	v8::Handle<v8::Value> config = v8::Context::GetCurrent()->Global()->Get(JS_STR("Config"));
	v8::Handle<v8::Value> prefix = config->ToObject()->Get(JS_STR("libraryPath"));
	v8::String::Utf8Value pfx(prefix);
	std::string path = "";

	path += *pfx;
	path += "/";
	path += name;
	return execute_file(path.c_str());
}

v8::Handle<v8::Value> _include(const v8::Arguments& args) {
	bool ok = true;
	int result;
	for (int i = 0; i < args.Length(); i++) {
		v8::HandleScope handle_scope;
		v8::String::Utf8Value file(args[i]);
		result = execute_file(*file);
		if (result != 0) { ok = false; }
	}
	return JS_BOOL(ok);
}

v8::Handle<v8::Value> _library(const v8::Arguments & args) {
	bool ok = true;
	int result;

	v8::Handle<v8::Value> config = v8::Context::GetCurrent()->Global()->Get(JS_STR("Config"));
	v8::Handle<v8::Value> prefix = config->ToObject()->Get(JS_STR("libraryPath"));
	v8::String::Utf8Value pfx(prefix);

	for (int i = 0; i < args.Length(); i++) {
		v8::HandleScope handle_scope;
		v8::String::Utf8Value file(args[i]);
		result = library(*file);
		if (result != 0) { ok = false; }
	}
	return JS_BOOL(ok);
}

v8::Handle<v8::Value> _exit(const v8::Arguments& args) {
	die(args[0]->Int32Value());
	return v8::Undefined();
}

v8::Handle<v8::Value> _onexit(const v8::Arguments& args) {
	__onexit->Set(JS_INT(__onexit->Length()), args[0]);
	return v8::Undefined();
}

int library_autoload() {
	v8::Handle<v8::Value> config = v8::Context::GetCurrent()->Global()->Get(JS_STR("Config"));
	v8::Handle<v8::Array> list = v8::Handle<v8::Array>::Cast(config->ToObject()->Get(JS_STR("libraryAutoload")));
	int cnt = list->Length();
	for (int i=0;i<cnt;i++) {
		v8::Handle<v8::Value> item = list->Get(JS_INT(i));
		v8::String::Utf8Value name(item);
		if (library(*name)) { return 1; }
	}
	return 0;
}

void init(char * cfg) {
	int result = execute_file(cfg);
	if (result) {
		printf("Cannot load configuration, quitting...\n");
		die(1);
	}
	result = library_autoload();
	if (result) {
		printf("Cannot load default libraries, quitting...\n");
		die(1);
	}
}

int main(int argc, char ** argv, char ** envp) {
	v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
	v8::HandleScope handle_scope;

	v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
	v8::Handle<v8::Context> context = v8::Context::New(NULL, global);
	v8::Context::Scope context_scope(context);

	__onexit = v8::Array::New();
	context->Global()->Set(JS_STR("library"), v8::FunctionTemplate::New(_library)->GetFunction());
	context->Global()->Set(JS_STR("include"), v8::FunctionTemplate::New(_include)->GetFunction());
	context->Global()->Set(JS_STR("exit"), v8::FunctionTemplate::New(_exit)->GetFunction());
	context->Global()->Set(JS_STR("onexit"), v8::FunctionTemplate::New(_onexit)->GetFunction());
	context->Global()->Set(JS_STR("global"), context->Global());
	context->Global()->Set(JS_STR("Config"), v8::Object::New());

	setup_system(envp, context->Global());
	setup_io(context->Global());

	#ifdef HAVE_MYSQL
	setup_mysql(context->Global());
	#endif

	#ifdef HAVE_GD
	setup_gd(context->Global());
	#endif

	char * cfg = STRING(CONFIG_PATH);
	int argptr = 0;
	for (int i = 1; i < argc; i++) {
		const char* str = argv[i];
		argptr = i;
		if (strcmp(str, "-c") == 0 && i + 1 < argc) {
			cfg = argv[i+1];
			argptr = 0;
			i++;
		}
	}

	init(cfg);

	if (!argptr) {
		// try the PATH_TRANSLATED env var
		v8::Handle<v8::Value> sys = v8::Context::GetCurrent()->Global()->Get(JS_STR("System"));
		v8::Handle<v8::Value> env = sys->ToObject()->Get(JS_STR("env"));
		v8::Handle<v8::Value> pt = env->ToObject()->Get(JS_STR("PATH_TRANSLATED"));
		if (pt->IsString()) {
			v8::String::Utf8Value name(pt);
			int result = execute_file(*name);
			if (result) { die(result); }
		} else {
			printf("Nothing to do.\n");
		}
	} else {
		int result = execute_file(argv[argptr]);
		if (result) { die(result); }
	}
	die(0);
}
<commit_msg>no libgen<commit_after>/*
 * v8cgi main file. Loosely based on V8's "shell" sample app.
 */

#include <v8.h>
#include "js_system.h"
#include "js_io.h"
#include "js_mysql.h"
#include "js_gd.h"
#include "js_common.h"

#include <sstream>

#define _STRING(x) #x
#define STRING(x) _STRING(x)

v8::Handle<v8::Array> __onexit;

void die(int code) {
	uint32_t max = __onexit->Length();
	v8::Handle<v8::Function> fun;
	for (unsigned int i=0;i<max;i++) {
		fun = v8::Handle<v8::Function>::Cast(__onexit->Get(JS_INT(i)));
		fun->Call(v8::Context::GetCurrent()->Global(), 0, NULL);
	}
	exit(code);
}

v8::Handle<v8::String> read_file(const char* name) {
	printf("%s",name);
	FILE* file = fopen(name, "rb");
	if (file == NULL) return v8::Handle<v8::String>();

	fseek(file, 0, SEEK_END);
	size_t size = ftell(file);
	rewind(file);

	char* chars = new char[size + 1];
	chars[size] = '\0';
	for (unsigned int i = 0; i < size;) {
		size_t read = fread(&chars[i], 1, size - i, file);
		i += read;
	}
	fclose(file);

	/* remove shebang line */
	std::string str = chars;
	if ( str.find('#',0) == 0 && str.find('!',1) == 1 ) {
		unsigned int pfix = str.find('\n',0);
		str.erase(0,pfix);
	};

	v8::Handle<v8::String> result = JS_STR(str.c_str());
	delete[] chars;
	return result;
}

void report_exception(v8::TryCatch* try_catch) {
	v8::HandleScope handle_scope;
	v8::String::Utf8Value exception(try_catch->Exception());
	v8::Handle<v8::Message> message = try_catch->Message();
	std::string msgstring = "";
	std::stringstream ss;
	std::string tmp;

	if (message.IsEmpty()) {
		msgstring += *exception;
		msgstring += "\n";
	} else {
		v8::String::Utf8Value filename(message->GetScriptResourceName());
		int linenum = message->GetLineNumber();
		msgstring += *filename;
		msgstring += ":";

		ss << linenum;
		ss >> tmp;

		msgstring += tmp;
		msgstring += ": ";
		msgstring += *exception;
		msgstring += "\n";
		v8::String::Utf8Value sourceline(message->GetSourceLine());
		msgstring += *sourceline;
		msgstring += "\n";

		// Print wavy underline (GetUnderline is deprecated).
		int start = message->GetStartColumn();
		for (int i = 0; i < start; i++) {
			msgstring += " ";
		}
		int end = message->GetEndColumn();
		for (int i = start; i < end; i++) {
			msgstring += "^";
		}
		msgstring += "\n";
	}

	int cgi = 0;
	v8::Local<v8::Function> fun;
	v8::Local<v8::Value> context = v8::Context::GetCurrent()->Global()->Get(JS_STR("response"));
	if (context->IsObject()) {
		v8::Local<v8::Value> print = context->ToObject()->Get(JS_STR("error"));
		if (print->IsObject()) {
			fun = v8::Local<v8::Function>::Cast(print);
			cgi = 1;
		}
	}
	if (!cgi) {
		context = v8::Context::GetCurrent()->Global()->Get(JS_STR("System"));
		fun = v8::Local<v8::Function>::Cast(context->ToObject()->Get(JS_STR("stdout")));
	}

	v8::Handle<v8::Value> data[1];
	data[0] = JS_STR(msgstring.c_str());
	fun->Call(context->ToObject(), 1, data);
}

int execute_file(const char * str) {
	v8::HandleScope handle_scope;
	v8::TryCatch try_catch;
	v8::Handle<v8::String> name = JS_STR(str);
	v8::Handle<v8::String> source = read_file(str);

	if (source.IsEmpty()) {
		printf("Error reading '%s'\n", str);
		return 1;
	}

	v8::Handle<v8::Script> script = v8::Script::Compile(source, name);
	if (script.IsEmpty()) {
		report_exception(&try_catch);
		return 1;
	} else {

		char * old = getcwd(NULL, 0);
		char * end = strrchr(str, '/');
		if (end == NULL) {
			end = strrchr(str, '\\');
		}

		if (end != NULL) {
			int len = end-str;
			char * base = (char *) malloc(len+1);
			strncpy(base, str, len);
    			base[len] = '\0';
    			chdir(base);
		}
		v8::Handle<v8::Value> result = script->Run();
		chdir(old);
		if (result.IsEmpty()) {
			report_exception(&try_catch);
			return 1;
		}
	}
	return 0;
}

int library(char * name) {
	v8::HandleScope handle_scope;
	v8::Handle<v8::Value> config = v8::Context::GetCurrent()->Global()->Get(JS_STR("Config"));
	v8::Handle<v8::Value> prefix = config->ToObject()->Get(JS_STR("libraryPath"));
	v8::String::Utf8Value pfx(prefix);
	std::string path = "";

	path += *pfx;
	path += "/";
	path += name;
	return execute_file(path.c_str());
}

v8::Handle<v8::Value> _include(const v8::Arguments& args) {
	bool ok = true;
	int result;
	for (int i = 0; i < args.Length(); i++) {
		v8::HandleScope handle_scope;
		v8::String::Utf8Value file(args[i]);
		result = execute_file(*file);
		if (result != 0) { ok = false; }
	}
	return JS_BOOL(ok);
}

v8::Handle<v8::Value> _library(const v8::Arguments & args) {
	bool ok = true;
	int result;

	v8::Handle<v8::Value> config = v8::Context::GetCurrent()->Global()->Get(JS_STR("Config"));
	v8::Handle<v8::Value> prefix = config->ToObject()->Get(JS_STR("libraryPath"));
	v8::String::Utf8Value pfx(prefix);

	for (int i = 0; i < args.Length(); i++) {
		v8::HandleScope handle_scope;
		v8::String::Utf8Value file(args[i]);
		result = library(*file);
		if (result != 0) { ok = false; }
	}
	return JS_BOOL(ok);
}

v8::Handle<v8::Value> _exit(const v8::Arguments& args) {
	die(args[0]->Int32Value());
	return v8::Undefined();
}

v8::Handle<v8::Value> _onexit(const v8::Arguments& args) {
	__onexit->Set(JS_INT(__onexit->Length()), args[0]);
	return v8::Undefined();
}

int library_autoload() {
	v8::Handle<v8::Value> config = v8::Context::GetCurrent()->Global()->Get(JS_STR("Config"));
	v8::Handle<v8::Array> list = v8::Handle<v8::Array>::Cast(config->ToObject()->Get(JS_STR("libraryAutoload")));
	int cnt = list->Length();
	for (int i=0;i<cnt;i++) {
		v8::Handle<v8::Value> item = list->Get(JS_INT(i));
		v8::String::Utf8Value name(item);
		if (library(*name)) { return 1; }
	}
	return 0;
}

void init(char * cfg) {
	int result = execute_file(cfg);
	if (result) {
		printf("Cannot load configuration, quitting...\n");
		die(1);
	}
	result = library_autoload();
	if (result) {
		printf("Cannot load default libraries, quitting...\n");
		die(1);
	}
}

int main(int argc, char ** argv, char ** envp) {
	v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
	v8::HandleScope handle_scope;

	v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
	v8::Handle<v8::Context> context = v8::Context::New(NULL, global);
	v8::Context::Scope context_scope(context);

	__onexit = v8::Array::New();
	context->Global()->Set(JS_STR("library"), v8::FunctionTemplate::New(_library)->GetFunction());
	context->Global()->Set(JS_STR("include"), v8::FunctionTemplate::New(_include)->GetFunction());
	context->Global()->Set(JS_STR("exit"), v8::FunctionTemplate::New(_exit)->GetFunction());
	context->Global()->Set(JS_STR("onexit"), v8::FunctionTemplate::New(_onexit)->GetFunction());
	context->Global()->Set(JS_STR("global"), context->Global());
	context->Global()->Set(JS_STR("Config"), v8::Object::New());

	setup_system(envp, context->Global());
	setup_io(context->Global());

	#ifdef HAVE_MYSQL
	setup_mysql(context->Global());
	#endif

	#ifdef HAVE_GD
	setup_gd(context->Global());
	#endif

	char * cfg = STRING(CONFIG_PATH);
	int argptr = 0;
	for (int i = 1; i < argc; i++) {
		const char* str = argv[i];
		argptr = i;
		if (strcmp(str, "-c") == 0 && i + 1 < argc) {
			cfg = argv[i+1];
			argptr = 0;
			i++;
		}
	}

	init(cfg);

	if (!argptr) {
		// try the PATH_TRANSLATED env var
		v8::Handle<v8::Value> sys = v8::Context::GetCurrent()->Global()->Get(JS_STR("System"));
		v8::Handle<v8::Value> env = sys->ToObject()->Get(JS_STR("env"));
		v8::Handle<v8::Value> pt = env->ToObject()->Get(JS_STR("PATH_TRANSLATED"));
		if (pt->IsString()) {
			v8::String::Utf8Value name(pt);
			int result = execute_file(*name);
			if (result) { die(result); }
		} else {
			printf("Nothing to do.\n");
		}
	} else {
		int result = execute_file(argv[argptr]);
		if (result) { die(result); }
	}
	die(0);
}
<|endoftext|>


<commit_before>#include "value.hh"
#include "exception.hh"

#include <algorithm>
#include <string>
#include <sstream>
#include <boost/lexical_cast.hpp>

namespace izna {

value::value():
	m_type(value_type::NIL),
	m_val(0)
{}

value::value(int v):
	m_type(value_type::INTEGER),
	m_val(v)
{}

value::value(double v):
	m_type(value_type::REAL),
	m_val(reinterpret_cast<intptr_t>(new double(v)))
{}

value::value(bool v):
	m_type(value_type::BOOLEAN),
	m_val(v)
{}

value::value(const std::string &v):
	m_type(value_type::STRING),
	m_val(reinterpret_cast<intptr_t>(new std::string(v)))
{}

value::value(std::shared_ptr<node> params, std::shared_ptr<node> stmt):
	m_type(value_type::FUNC),
	m_val(reinterpret_cast<intptr_t>(new func(params, stmt)))
{}

value::value(const value &v):
	m_type(value_type::NIL),
	m_val(0)
{
	if (v.isReal())
	{
		auto val = reinterpret_cast<double *>(v.m_val);
		m_val = reinterpret_cast<intptr_t>(new double(*val));
	} else if (v.isString())
	{
		auto val = reinterpret_cast<std::string *>(v.m_val);
		m_val = reinterpret_cast<intptr_t>(new std::string(*val));
	} else if (v.isFunc())
	{
		auto val = reinterpret_cast<func *>(v.m_val);
		m_val = reinterpret_cast<intptr_t>(new func(*val));
	} else
	{
		m_val = v.m_val;
	}

	m_type = v.m_type;
}

value& value::operator=(const value &rhs)
{
	value tmp(rhs);
	swap(tmp);

	return *this;
}

value::value(value &&v):
	m_type(v.m_type),
	m_val(v.m_val)
{}

value& value::operator=(value &&v)
{
	swap(v);
	return *this;
}

void value::swap(value &b) noexcept
{
	std::swap(this->m_type, b.m_type);
	std::swap(this->m_val,  b.m_val);
}

value::~value()
{
	if (isReal())
	{
		delete reinterpret_cast<double *>(m_val);
	}

	if (isString())
	{
		delete reinterpret_cast<std::string *>(m_val);
	}

	if (isFunc())
	{
		delete reinterpret_cast<func *>(m_val);
	}
}

bool value::isNil() const
{
	return m_type == value_type::NIL;
}

bool value::isInteger() const
{
	return m_type == value_type::INTEGER;
}

bool value::isReal() const
{
	return m_type == value_type::REAL;
}

bool value::isBoolean() const
{
	return m_type == value_type::BOOLEAN;
}

bool value::isString() const
{
	return m_type == value_type::STRING;
}

bool value::isFunc() const
{
	return m_type == value_type::FUNC;
}

bool value::isTrue() const
{
	return m_type == value_type::BOOLEAN && m_val;
}

bool value::isFalse() const
{
	return m_type == value_type::BOOLEAN && !m_val;
}

int value::toInteger() const
{
	if (isInteger())
	{
		return m_val;
	}

	if (isReal())
	{
		return static_cast<int>(*reinterpret_cast<double *>(m_val));
	}

	throw type_error();
}

double value::toReal() const
{
	if (isInteger())
	{
		return static_cast<double>(m_val);
	}

	if (isReal())
	{
		return *reinterpret_cast<double *>(m_val);
	}

	throw type_error();
}

bool value::toBoolean() const
{
	if (isNil())
	{
		return false;
	}

	if (isBoolean())
	{
		return m_val;
	}

	if (isInteger())
	{
		return m_val;
	}

	if (isReal())
	{
		return reinterpret_cast<double *>(m_val);
	}

	if (isString())
	{
		return !reinterpret_cast<std::string *>(m_val)->empty();
	}

	throw type_error();
}

std::string value::toString() const
{
	if (isNil())
	{
		return "nil";
	}

	if (isFalse())
	{
		return "false";
	}

	if (isTrue())
	{
		return "true";
	}

	if (isInteger())
	{
		return boost::lexical_cast<std::string>(m_val);
	}

	if (isReal())
	{
		return boost::lexical_cast<std::string>(*reinterpret_cast<double *>(m_val));
	}

	if (isString())
	{
		return *reinterpret_cast<std::string *>(m_val);
	}

	if (isFunc())
	{
		return "function";
	}

	throw type_error();
}

func value::toFunc() const
{
	if (isFunc())
	{
		return *reinterpret_cast<func *>(m_val);
	}

	throw type_error();
}

#define ADD_OPERATE(type, opr) \
	if (is##type())\
	{\
		return value(this->to##type() opr rhs.to##type());\
	}

value value::Add(const value &rhs) const
{
	ADD_OPERATE(Boolean, +)
	ADD_OPERATE(Integer, +)
	ADD_OPERATE(Real, +)
	ADD_OPERATE(String, +)

	throw type_error();
}

value value::Sub(const value &rhs) const
{
	ADD_OPERATE(Boolean, -)
	ADD_OPERATE(Integer, -)
	ADD_OPERATE(Real, -)

	throw type_error();
}

value value::Mul(const value &rhs) const
{
	ADD_OPERATE(Boolean, *)
	ADD_OPERATE(Integer, *)
	ADD_OPERATE(Real, *)

	if (isString())
	{
		const int n = rhs.toInteger();
		const std::string s = toString();

		std::stringstream ss;
		for (int i = 0; i < n; ++i)
		{
			ss << s;
		}

		return value(ss.str());
	}

	throw type_error();
}

value value::Div(const value &rhs) const
{
	ADD_OPERATE(Boolean, /)
	ADD_OPERATE(Integer, /)
	ADD_OPERATE(Real, /)

	throw type_error();
}

value value::Mod(const value &rhs) const
{
	ADD_OPERATE(Boolean, %)
	ADD_OPERATE(Integer, %)

	throw type_error();
}

value value::LOr(const value &rhs) const
{
	return value(toBoolean() || rhs.toBoolean());
}

value value::LAnd(const value &rhs) const
{
	return value(toBoolean() && rhs.toBoolean());
}

value value::Eq(const value &rhs) const
{
	ADD_OPERATE(Boolean, ==)
	ADD_OPERATE(Integer, ==)
	ADD_OPERATE(Real, ==)
	ADD_OPERATE(String, ==)

	throw type_error();
}

value value::Ne(const value &rhs) const
{
	ADD_OPERATE(Boolean, !=)
	ADD_OPERATE(Integer, !=)
	ADD_OPERATE(Real, !=)
	ADD_OPERATE(String, !=)

	throw type_error();
}

value value::Less(const value &rhs) const
{
	ADD_OPERATE(Boolean, <)
	ADD_OPERATE(Integer, <)
	ADD_OPERATE(Real, <)
	ADD_OPERATE(String, <)

	throw type_error();
}

value value::LessEq(const value &rhs) const
{
	ADD_OPERATE(Boolean, <=)
	ADD_OPERATE(Integer, <=)
	ADD_OPERATE(Real, <=)
	ADD_OPERATE(String, <=)

	throw type_error();
}

value value::Greater(const value &rhs) const
{
	ADD_OPERATE(Boolean, >)
	ADD_OPERATE(Integer, >)
	ADD_OPERATE(Real, >)
	ADD_OPERATE(String, >)

	throw type_error();
}

value value::GreaterEq(const value &rhs) const
{
	ADD_OPERATE(Boolean, >=)
	ADD_OPERATE(Integer, >=)
	ADD_OPERATE(Real, >=)
	ADD_OPERATE(String, >=)

	throw type_error();
}

value value::Neg() const
{
	if (isInteger())
	{
		return value(-toInteger());
	}

	if (isReal())
	{
		return value(-toReal());
	}

	throw type_error();
}

} //izna

<commit_msg>fix a bug in move ctor<commit_after>#include "value.hh"
#include "exception.hh"

#include <algorithm>
#include <string>
#include <sstream>
#include <boost/lexical_cast.hpp>

namespace izna {

value::value():
	m_type(value_type::NIL),
	m_val(0)
{}

value::value(int v):
	m_type(value_type::INTEGER),
	m_val(v)
{}

value::value(double v):
	m_type(value_type::REAL),
	m_val(reinterpret_cast<intptr_t>(new double(v)))
{}

value::value(bool v):
	m_type(value_type::BOOLEAN),
	m_val(v)
{}

value::value(const std::string &v):
	m_type(value_type::STRING),
	m_val(reinterpret_cast<intptr_t>(new std::string(v)))
{}

value::value(std::shared_ptr<node> params, std::shared_ptr<node> stmt):
	m_type(value_type::FUNC),
	m_val(reinterpret_cast<intptr_t>(new func(params, stmt)))
{}

value::value(const value &v):
	m_type(value_type::NIL),
	m_val(0)
{
	if (v.isReal())
	{
		auto val = reinterpret_cast<double *>(v.m_val);
		m_val = reinterpret_cast<intptr_t>(new double(*val));
	} else if (v.isString())
	{
		auto val = reinterpret_cast<std::string *>(v.m_val);
		m_val = reinterpret_cast<intptr_t>(new std::string(*val));
	} else if (v.isFunc())
	{
		auto val = reinterpret_cast<func *>(v.m_val);
		m_val = reinterpret_cast<intptr_t>(new func(*val));
	} else
	{
		m_val = v.m_val;
	}

	m_type = v.m_type;
}

value& value::operator=(const value &rhs)
{
	value tmp(rhs);
	swap(tmp);

	return *this;
}

value::value(value &&v):
	m_type(value_type::NIL),
	m_val(0)
{
	swap(v);
}

value& value::operator=(value &&v)
{
	swap(v);
	return *this;
}

void value::swap(value &b) noexcept
{
	std::swap(this->m_type, b.m_type);
	std::swap(this->m_val,  b.m_val);
}

value::~value()
{
	if (isReal())
	{
		delete reinterpret_cast<double *>(m_val);
	}

	if (isString())
	{
		delete reinterpret_cast<std::string *>(m_val);
	}

	if (isFunc())
	{
		delete reinterpret_cast<func *>(m_val);
	}
}

bool value::isNil() const
{
	return m_type == value_type::NIL;
}

bool value::isInteger() const
{
	return m_type == value_type::INTEGER;
}

bool value::isReal() const
{
	return m_type == value_type::REAL;
}

bool value::isBoolean() const
{
	return m_type == value_type::BOOLEAN;
}

bool value::isString() const
{
	return m_type == value_type::STRING;
}

bool value::isFunc() const
{
	return m_type == value_type::FUNC;
}

bool value::isTrue() const
{
	return m_type == value_type::BOOLEAN && m_val;
}

bool value::isFalse() const
{
	return m_type == value_type::BOOLEAN && !m_val;
}

int value::toInteger() const
{
	if (isInteger())
	{
		return m_val;
	}

	if (isReal())
	{
		return static_cast<int>(*reinterpret_cast<double *>(m_val));
	}

	throw type_error();
}

double value::toReal() const
{
	if (isInteger())
	{
		return static_cast<double>(m_val);
	}

	if (isReal())
	{
		return *reinterpret_cast<double *>(m_val);
	}

	throw type_error();
}

bool value::toBoolean() const
{
	if (isNil())
	{
		return false;
	}

	if (isBoolean())
	{
		return m_val;
	}

	if (isInteger())
	{
		return m_val;
	}

	if (isReal())
	{
		return reinterpret_cast<double *>(m_val);
	}

	if (isString())
	{
		return !reinterpret_cast<std::string *>(m_val)->empty();
	}

	throw type_error();
}

std::string value::toString() const
{
	if (isNil())
	{
		return "nil";
	}

	if (isFalse())
	{
		return "false";
	}

	if (isTrue())
	{
		return "true";
	}

	if (isInteger())
	{
		return boost::lexical_cast<std::string>(m_val);
	}

	if (isReal())
	{
		return boost::lexical_cast<std::string>(*reinterpret_cast<double *>(m_val));
	}

	if (isString())
	{
		return *reinterpret_cast<std::string *>(m_val);
	}

	if (isFunc())
	{
		return "function";
	}

	throw type_error();
}

func value::toFunc() const
{
	if (isFunc())
	{
		return *reinterpret_cast<func *>(m_val);
	}

	throw type_error();
}

#define ADD_OPERATE(type, opr) \
	if (is##type())\
	{\
		return value(this->to##type() opr rhs.to##type());\
	}

value value::Add(const value &rhs) const
{
	ADD_OPERATE(Boolean, +)
	ADD_OPERATE(Integer, +)
	ADD_OPERATE(Real, +)
	ADD_OPERATE(String, +)

	throw type_error();
}

value value::Sub(const value &rhs) const
{
	ADD_OPERATE(Boolean, -)
	ADD_OPERATE(Integer, -)
	ADD_OPERATE(Real, -)

	throw type_error();
}

value value::Mul(const value &rhs) const
{
	ADD_OPERATE(Boolean, *)
	ADD_OPERATE(Integer, *)
	ADD_OPERATE(Real, *)

	if (isString())
	{
		const int n = rhs.toInteger();
		const std::string s = toString();

		std::stringstream ss;
		for (int i = 0; i < n; ++i)
		{
			ss << s;
		}

		return value(ss.str());
	}

	throw type_error();
}

value value::Div(const value &rhs) const
{
	ADD_OPERATE(Boolean, /)
	ADD_OPERATE(Integer, /)
	ADD_OPERATE(Real, /)

	throw type_error();
}

value value::Mod(const value &rhs) const
{
	ADD_OPERATE(Boolean, %)
	ADD_OPERATE(Integer, %)

	throw type_error();
}

value value::LOr(const value &rhs) const
{
	return value(toBoolean() || rhs.toBoolean());
}

value value::LAnd(const value &rhs) const
{
	return value(toBoolean() && rhs.toBoolean());
}

value value::Eq(const value &rhs) const
{
	ADD_OPERATE(Boolean, ==)
	ADD_OPERATE(Integer, ==)
	ADD_OPERATE(Real, ==)
	ADD_OPERATE(String, ==)

	throw type_error();
}

value value::Ne(const value &rhs) const
{
	ADD_OPERATE(Boolean, !=)
	ADD_OPERATE(Integer, !=)
	ADD_OPERATE(Real, !=)
	ADD_OPERATE(String, !=)

	throw type_error();
}

value value::Less(const value &rhs) const
{
	ADD_OPERATE(Boolean, <)
	ADD_OPERATE(Integer, <)
	ADD_OPERATE(Real, <)
	ADD_OPERATE(String, <)

	throw type_error();
}

value value::LessEq(const value &rhs) const
{
	ADD_OPERATE(Boolean, <=)
	ADD_OPERATE(Integer, <=)
	ADD_OPERATE(Real, <=)
	ADD_OPERATE(String, <=)

	throw type_error();
}

value value::Greater(const value &rhs) const
{
	ADD_OPERATE(Boolean, >)
	ADD_OPERATE(Integer, >)
	ADD_OPERATE(Real, >)
	ADD_OPERATE(String, >)

	throw type_error();
}

value value::GreaterEq(const value &rhs) const
{
	ADD_OPERATE(Boolean, >=)
	ADD_OPERATE(Integer, >=)
	ADD_OPERATE(Real, >=)
	ADD_OPERATE(String, >=)

	throw type_error();
}

value value::Neg() const
{
	if (isInteger())
	{
		return value(-toInteger());
	}

	if (isReal())
	{
		return value(-toReal());
	}

	throw type_error();
}

} //izna

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Endless Mobile
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 *
 * Written by:
 *     Jasper St. Pierre <jstpierre@mecheye.net>
 */

#include "value.h"
#include "gobject.h"

using namespace v8;

namespace GNodeJS {

Handle<Value> GIArgumentToV8(Isolate *isolate, GITypeInfo *type_info, GIArgument *arg) {
    GITypeTag type_tag = g_type_info_get_tag (type_info);

    switch (type_tag) {
    case GI_TYPE_TAG_VOID:
        return Undefined (isolate);

    case GI_TYPE_TAG_BOOLEAN:
        if (arg->v_boolean)
            return True (isolate);
        else
            return False (isolate);

    case GI_TYPE_TAG_INT32:
        return Integer::New (isolate, arg->v_int);
    case GI_TYPE_TAG_UINT32:
        return Integer::NewFromUnsigned (isolate, arg->v_uint);
    case GI_TYPE_TAG_INT16:
        return Integer::New (isolate, arg->v_int16);
    case GI_TYPE_TAG_UINT16:
        return Integer::NewFromUnsigned (isolate, arg->v_uint16);
    case GI_TYPE_TAG_INT8:
        return Integer::New (isolate, arg->v_int8);
    case GI_TYPE_TAG_UINT8:
        return Integer::NewFromUnsigned (isolate, arg->v_uint8);
    case GI_TYPE_TAG_FLOAT:
        return Number::New (isolate, arg->v_float);
    case GI_TYPE_TAG_DOUBLE:
        return Number::New (isolate, arg->v_double);

    /* For 64-bit integer types, use a float. When JS and V8 adopt
     * bigger sized integer types, start using those instead. */
    case GI_TYPE_TAG_INT64:
        return Number::New (isolate, arg->v_int64);
    case GI_TYPE_TAG_UINT64:
        return Number::New (isolate, arg->v_uint64);

    case GI_TYPE_TAG_UNICHAR:
        {
            char data[7] = { 0 };
            g_unichar_to_utf8 (arg->v_uint32, data);
            return String::NewFromUtf8 (isolate, data);
        }

    case GI_TYPE_TAG_UTF8:
        if (arg->v_pointer)
            return String::NewFromUtf8 (isolate, (char *) arg->v_pointer);
        else
            return Null (isolate);

    case GI_TYPE_TAG_INTERFACE:
        {
            GIBaseInfo *interface_info = g_type_info_get_interface (type_info);
            GIInfoType interface_type = g_base_info_get_type (interface_info);

            switch (interface_type) {
            case GI_INFO_TYPE_OBJECT:
                return WrapperFromGObject (isolate, (GObject *) arg->v_pointer);
            case GI_INFO_TYPE_ENUM:
                return Integer::New (isolate, arg->v_int);
            default:
                g_assert_not_reached ();
            }
        }
        break;

    default:
        g_assert_not_reached ();
    }
}

static GArray * V8ToGArray(Isolate *isolate, GITypeInfo *type_info, Handle<Value> value) {
    if (!value->IsArray ()) {
        isolate->ThrowException (Exception::TypeError (String::NewFromUtf8 (isolate, "Not an array.")));
        return NULL;
    }

    Local<Array> array = Local<Array>::Cast (value->ToObject ());
    GITypeInfo *elem_info = g_type_info_get_param_type (type_info, 0);

    int length = array->Length ();
    GArray *garray = g_array_sized_new (TRUE, FALSE, sizeof (GIArgument), length);
    for (int i = 0; i < length; i++) {
        Local<Value> value = array->Get (i);
        GIArgument arg;

        V8ToGIArgument (isolate, elem_info, &arg, value, false);
        g_array_append_val (garray, arg);
    }

    g_base_info_unref ((GIBaseInfo *) elem_info);
    return garray;
}

void V8ToGIArgument(Isolate *isolate, GITypeInfo *type_info, GIArgument *arg, Handle<Value> value, bool may_be_null) {
    GITypeTag type_tag = g_type_info_get_tag (type_info);

    if (value->IsNull ()) {
        arg->v_pointer = NULL;

        if (!may_be_null)
            isolate->ThrowException (Exception::TypeError (String::NewFromUtf8 (isolate, "Argument may not be null.")));

        return;
    }

    switch (type_tag) {
    case GI_TYPE_TAG_VOID:
        arg->v_pointer = NULL;
        break;
    case GI_TYPE_TAG_BOOLEAN:
        arg->v_boolean = value->BooleanValue ();
        break;
    case GI_TYPE_TAG_INT32:
        arg->v_int = value->Int32Value ();
        break;
    case GI_TYPE_TAG_UINT32:
        arg->v_uint = value->Uint32Value ();
        break;
    case GI_TYPE_TAG_INT64:
        arg->v_int64 = value->NumberValue ();
        break;
    case GI_TYPE_TAG_UINT64:
        arg->v_uint64 = value->NumberValue ();
        break;
    case GI_TYPE_TAG_FLOAT:
        arg->v_float = value->NumberValue ();
        break;
    case GI_TYPE_TAG_DOUBLE:
        arg->v_double = value->NumberValue ();
        break;

    case GI_TYPE_TAG_UTF8:
        {
            String::Utf8Value str (value);
            const char *data = *str;
            arg->v_pointer = g_strdup (data);
        }
        break;

    case GI_TYPE_TAG_INTERFACE:
        {
            GIBaseInfo *interface_info = g_type_info_get_interface (type_info);
            GIInfoType interface_type = g_base_info_get_type (interface_info);

            switch (interface_type) {
            case GI_INFO_TYPE_OBJECT:
                arg->v_pointer = GObjectFromWrapper (value);
                break;
            default:
                g_assert_not_reached ();
            }

            g_base_info_unref (interface_info);
        }
        break;

    case GI_TYPE_TAG_ARRAY:
        {
            GIArrayType array_type = g_type_info_get_array_type (type_info);
            GArray *garray = V8ToGArray (isolate, type_info, value);

            switch (array_type) {
            case GI_ARRAY_TYPE_C:
                arg->v_pointer = g_array_free (garray, FALSE);
                break;
            case GI_ARRAY_TYPE_ARRAY:
                arg->v_pointer = garray;
                break;
            default:
                g_assert_not_reached ();
            }
        }
        break;

    default:
        g_assert_not_reached ();
    }
}

void FreeGIArgument(GITypeInfo *type_info, GIArgument *arg) {
    GITypeTag type_tag = g_type_info_get_tag (type_info);

    switch (type_tag) {
    case GI_TYPE_TAG_UTF8:
        g_free (arg->v_pointer);
        break;

    case GI_TYPE_TAG_ARRAY:
        {
            GIArrayType array_type = g_type_info_get_array_type (type_info);

            switch (array_type) {
            case GI_ARRAY_TYPE_C:
                g_free (arg->v_pointer);
                break;
            case GI_ARRAY_TYPE_ARRAY:
                g_array_free ((GArray *) arg->v_pointer, TRUE);
                break;
            default:
                g_assert_not_reached ();
            }
        }
        break;
    default:
        break;
    }
}

void V8ToGValue(GValue *gvalue, Handle<Value> value) {
    if (G_VALUE_HOLDS_BOOLEAN (gvalue)) {
        g_value_set_boolean (gvalue, value->BooleanValue ());
    } else if (G_VALUE_HOLDS_INT (gvalue)) {
        g_value_set_int (gvalue, value->Int32Value ());
    } else if (G_VALUE_HOLDS_UINT (gvalue)) {
        g_value_set_uint (gvalue, value->Uint32Value ());
    } else if (G_VALUE_HOLDS_FLOAT (gvalue)) {
        g_value_set_float (gvalue, value->NumberValue ());
    } else if (G_VALUE_HOLDS_DOUBLE (gvalue)) {
        g_value_set_double (gvalue, value->NumberValue ());
    } else if (G_VALUE_HOLDS_STRING (gvalue)) {
        String::Utf8Value str (value);
        const char *data = *str;
        g_value_set_string (gvalue, data);
    } else if (G_VALUE_HOLDS_ENUM (gvalue)) {
        g_value_set_enum (gvalue, value->Int32Value ());
    } else if (G_VALUE_HOLDS_OBJECT (gvalue)) {
        g_value_set_object (gvalue, GObjectFromWrapper (value));
    } else {
        g_assert_not_reached ();
    }
}

Handle<Value> GValueToV8(Isolate *isolate, const GValue *gvalue) {
    if (G_VALUE_HOLDS_BOOLEAN (gvalue)) {
        if (g_value_get_boolean (gvalue))
            return True (isolate);
        else
            return False (isolate);
    } else if (G_VALUE_HOLDS_INT (gvalue)) {
        return Integer::New (isolate, g_value_get_int (gvalue));
    } else if (G_VALUE_HOLDS_UINT (gvalue)) {
        return Integer::NewFromUnsigned (isolate, g_value_get_uint (gvalue));
    } else if (G_VALUE_HOLDS_FLOAT (gvalue)) {
        return Number::New (isolate, g_value_get_float (gvalue));
    } else if (G_VALUE_HOLDS_DOUBLE (gvalue)) {
        return Number::New (isolate, g_value_get_double (gvalue));
    } else if (G_VALUE_HOLDS_STRING (gvalue)) {
        return String::NewFromUtf8 (isolate, g_value_get_string (gvalue));
    } else if (G_VALUE_HOLDS_ENUM (gvalue)) {
        return Integer::New (isolate, g_value_get_enum (gvalue));
    } else if (G_VALUE_HOLDS_OBJECT (gvalue)) {
        return WrapperFromGObject (isolate, G_OBJECT (g_value_get_object (gvalue)));
    } else {
        g_assert_not_reached ();
    }
}

};
<commit_msg>value: Support enum and flags in more locations<commit_after>/*
 * Copyright (C) 2014 Endless Mobile
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 *
 * Written by:
 *     Jasper St. Pierre <jstpierre@mecheye.net>
 */

#include "value.h"
#include "gobject.h"

using namespace v8;

namespace GNodeJS {

Handle<Value> GIArgumentToV8(Isolate *isolate, GITypeInfo *type_info, GIArgument *arg) {
    GITypeTag type_tag = g_type_info_get_tag (type_info);

    switch (type_tag) {
    case GI_TYPE_TAG_VOID:
        return Undefined (isolate);

    case GI_TYPE_TAG_BOOLEAN:
        if (arg->v_boolean)
            return True (isolate);
        else
            return False (isolate);

    case GI_TYPE_TAG_INT32:
        return Integer::New (isolate, arg->v_int);
    case GI_TYPE_TAG_UINT32:
        return Integer::NewFromUnsigned (isolate, arg->v_uint);
    case GI_TYPE_TAG_INT16:
        return Integer::New (isolate, arg->v_int16);
    case GI_TYPE_TAG_UINT16:
        return Integer::NewFromUnsigned (isolate, arg->v_uint16);
    case GI_TYPE_TAG_INT8:
        return Integer::New (isolate, arg->v_int8);
    case GI_TYPE_TAG_UINT8:
        return Integer::NewFromUnsigned (isolate, arg->v_uint8);
    case GI_TYPE_TAG_FLOAT:
        return Number::New (isolate, arg->v_float);
    case GI_TYPE_TAG_DOUBLE:
        return Number::New (isolate, arg->v_double);

    /* For 64-bit integer types, use a float. When JS and V8 adopt
     * bigger sized integer types, start using those instead. */
    case GI_TYPE_TAG_INT64:
        return Number::New (isolate, arg->v_int64);
    case GI_TYPE_TAG_UINT64:
        return Number::New (isolate, arg->v_uint64);

    case GI_TYPE_TAG_UNICHAR:
        {
            char data[7] = { 0 };
            g_unichar_to_utf8 (arg->v_uint32, data);
            return String::NewFromUtf8 (isolate, data);
        }

    case GI_TYPE_TAG_UTF8:
        if (arg->v_pointer)
            return String::NewFromUtf8 (isolate, (char *) arg->v_pointer);
        else
            return Null (isolate);

    case GI_TYPE_TAG_INTERFACE:
        {
            GIBaseInfo *interface_info = g_type_info_get_interface (type_info);
            GIInfoType interface_type = g_base_info_get_type (interface_info);

            switch (interface_type) {
            case GI_INFO_TYPE_OBJECT:
                return WrapperFromGObject (isolate, (GObject *) arg->v_pointer);
            case GI_INFO_TYPE_FLAGS:
            case GI_INFO_TYPE_ENUM:
                return Integer::New (isolate, arg->v_int);
            default:
                g_assert_not_reached ();
            }
        }
        break;

    default:
        g_assert_not_reached ();
    }
}

static GArray * V8ToGArray(Isolate *isolate, GITypeInfo *type_info, Handle<Value> value) {
    if (!value->IsArray ()) {
        isolate->ThrowException (Exception::TypeError (String::NewFromUtf8 (isolate, "Not an array.")));
        return NULL;
    }

    Local<Array> array = Local<Array>::Cast (value->ToObject ());
    GITypeInfo *elem_info = g_type_info_get_param_type (type_info, 0);

    int length = array->Length ();
    GArray *garray = g_array_sized_new (TRUE, FALSE, sizeof (GIArgument), length);
    for (int i = 0; i < length; i++) {
        Local<Value> value = array->Get (i);
        GIArgument arg;

        V8ToGIArgument (isolate, elem_info, &arg, value, false);
        g_array_append_val (garray, arg);
    }

    g_base_info_unref ((GIBaseInfo *) elem_info);
    return garray;
}

void V8ToGIArgument(Isolate *isolate, GITypeInfo *type_info, GIArgument *arg, Handle<Value> value, bool may_be_null) {
    GITypeTag type_tag = g_type_info_get_tag (type_info);

    if (value->IsNull ()) {
        arg->v_pointer = NULL;

        if (!may_be_null)
            isolate->ThrowException (Exception::TypeError (String::NewFromUtf8 (isolate, "Argument may not be null.")));

        return;
    }

    switch (type_tag) {
    case GI_TYPE_TAG_VOID:
        arg->v_pointer = NULL;
        break;
    case GI_TYPE_TAG_BOOLEAN:
        arg->v_boolean = value->BooleanValue ();
        break;
    case GI_TYPE_TAG_INT32:
        arg->v_int = value->Int32Value ();
        break;
    case GI_TYPE_TAG_UINT32:
        arg->v_uint = value->Uint32Value ();
        break;
    case GI_TYPE_TAG_INT64:
        arg->v_int64 = value->NumberValue ();
        break;
    case GI_TYPE_TAG_UINT64:
        arg->v_uint64 = value->NumberValue ();
        break;
    case GI_TYPE_TAG_FLOAT:
        arg->v_float = value->NumberValue ();
        break;
    case GI_TYPE_TAG_DOUBLE:
        arg->v_double = value->NumberValue ();
        break;

    case GI_TYPE_TAG_UTF8:
        {
            String::Utf8Value str (value);
            const char *data = *str;
            arg->v_pointer = g_strdup (data);
        }
        break;

    case GI_TYPE_TAG_INTERFACE:
        {
            GIBaseInfo *interface_info = g_type_info_get_interface (type_info);
            GIInfoType interface_type = g_base_info_get_type (interface_info);

            switch (interface_type) {
            case GI_INFO_TYPE_OBJECT:
                arg->v_pointer = GObjectFromWrapper (value);
                break;
            case GI_INFO_TYPE_FLAGS:
            case GI_INFO_TYPE_ENUM:
                arg->v_int = value->Int32Value ();
                break;
            default:
                g_assert_not_reached ();
            }

            g_base_info_unref (interface_info);
        }
        break;

    case GI_TYPE_TAG_ARRAY:
        {
            GIArrayType array_type = g_type_info_get_array_type (type_info);
            GArray *garray = V8ToGArray (isolate, type_info, value);

            switch (array_type) {
            case GI_ARRAY_TYPE_C:
                arg->v_pointer = g_array_free (garray, FALSE);
                break;
            case GI_ARRAY_TYPE_ARRAY:
                arg->v_pointer = garray;
                break;
            default:
                g_assert_not_reached ();
            }
        }
        break;

    default:
        g_assert_not_reached ();
    }
}

void FreeGIArgument(GITypeInfo *type_info, GIArgument *arg) {
    GITypeTag type_tag = g_type_info_get_tag (type_info);

    switch (type_tag) {
    case GI_TYPE_TAG_UTF8:
        g_free (arg->v_pointer);
        break;

    case GI_TYPE_TAG_ARRAY:
        {
            GIArrayType array_type = g_type_info_get_array_type (type_info);

            switch (array_type) {
            case GI_ARRAY_TYPE_C:
                g_free (arg->v_pointer);
                break;
            case GI_ARRAY_TYPE_ARRAY:
                g_array_free ((GArray *) arg->v_pointer, TRUE);
                break;
            default:
                g_assert_not_reached ();
            }
        }
        break;
    default:
        break;
    }
}

void V8ToGValue(GValue *gvalue, Handle<Value> value) {
    if (G_VALUE_HOLDS_BOOLEAN (gvalue)) {
        g_value_set_boolean (gvalue, value->BooleanValue ());
    } else if (G_VALUE_HOLDS_INT (gvalue)) {
        g_value_set_int (gvalue, value->Int32Value ());
    } else if (G_VALUE_HOLDS_UINT (gvalue)) {
        g_value_set_uint (gvalue, value->Uint32Value ());
    } else if (G_VALUE_HOLDS_FLOAT (gvalue)) {
        g_value_set_float (gvalue, value->NumberValue ());
    } else if (G_VALUE_HOLDS_DOUBLE (gvalue)) {
        g_value_set_double (gvalue, value->NumberValue ());
    } else if (G_VALUE_HOLDS_STRING (gvalue)) {
        String::Utf8Value str (value);
        const char *data = *str;
        g_value_set_string (gvalue, data);
    } else if (G_VALUE_HOLDS_ENUM (gvalue)) {
        g_value_set_enum (gvalue, value->Int32Value ());
    } else if (G_VALUE_HOLDS_OBJECT (gvalue)) {
        g_value_set_object (gvalue, GObjectFromWrapper (value));
    } else {
        g_assert_not_reached ();
    }
}

Handle<Value> GValueToV8(Isolate *isolate, const GValue *gvalue) {
    if (G_VALUE_HOLDS_BOOLEAN (gvalue)) {
        if (g_value_get_boolean (gvalue))
            return True (isolate);
        else
            return False (isolate);
    } else if (G_VALUE_HOLDS_INT (gvalue)) {
        return Integer::New (isolate, g_value_get_int (gvalue));
    } else if (G_VALUE_HOLDS_UINT (gvalue)) {
        return Integer::NewFromUnsigned (isolate, g_value_get_uint (gvalue));
    } else if (G_VALUE_HOLDS_FLOAT (gvalue)) {
        return Number::New (isolate, g_value_get_float (gvalue));
    } else if (G_VALUE_HOLDS_DOUBLE (gvalue)) {
        return Number::New (isolate, g_value_get_double (gvalue));
    } else if (G_VALUE_HOLDS_STRING (gvalue)) {
        return String::NewFromUtf8 (isolate, g_value_get_string (gvalue));
    } else if (G_VALUE_HOLDS_ENUM (gvalue)) {
        return Integer::New (isolate, g_value_get_enum (gvalue));
    } else if (G_VALUE_HOLDS_OBJECT (gvalue)) {
        return WrapperFromGObject (isolate, G_OBJECT (g_value_get_object (gvalue)));
    } else {
        g_assert_not_reached ();
    }
}

};
<|endoftext|>


<commit_before>#ifndef value_hh_INCLUDED
#define value_hh_INCLUDED

#include <memory>
#include <unordered_map>

#include "units.hh"

namespace Kakoune
{

struct bad_value_cast {};

struct Value
{
    Value() = default;

    template<typename T>
    Value(T&& val) : m_value{new Model<T>{std::forward<T>(val)}} {}

    Value(const Value& val)
    {
        if (val.m_value)
            m_value.reset(val.m_value->clone());
    }

    Value(Value&&) = default;

    Value& operator=(const Value& val)
    {
        if (val.m_value)
            m_value.reset(val.m_value->clone());
        else
            m_value.reset();
        return *this;
    }

    Value& operator=(Value&& val) = default;

    explicit operator bool() const { return (bool)m_value; }

    template<typename T>
    bool is_a() const
    {
        return m_value and m_value->type() == typeid(T);
    }

    template<typename T>
    T& as()
    {
        if (not is_a<T>())
            throw bad_value_cast{};
        return static_cast<Model<T>*>(m_value.get())->m_content;
    }

    template<typename T>
    const T& as() const
    {
        return const_cast<Value*>(this)->as<T>();
    }

private:
    struct Concept
    {
        virtual ~Concept() {}
        virtual const std::type_info& type() const = 0;
        virtual Concept* clone() const = 0;
    };

    template<typename T>
    struct Model : public Concept
    {
        Model(const T& val) : m_content(val) {}
        Model(T&& val) : m_content(std::move(val)) {}

        const std::type_info& type() const override { return typeid(T); }
        Concept* clone() const { return new Model(m_content); }

        T m_content;
    };

    std::unique_ptr<Concept> m_value;
};

struct ValueId : public StronglyTypedNumber<ValueId, int>
{
    constexpr ValueId(int value = 0) : StronglyTypedNumber<ValueId>(value) {}

    static ValueId get_free_id()
    {
        static ValueId next;
        return next++;
    }
};

using ValueMap = std::unordered_map<ValueId, Value>;

}

namespace std
{

template<>
struct hash<Kakoune::ValueId>
{
    size_t operator()(Kakoune::ValueId val) const
    {
        return std::hash<int>()((int)val);
    }
};

}

#endif // value_hh_INCLUDED
<commit_msg>Change Value to be non copyable<commit_after>#ifndef value_hh_INCLUDED
#define value_hh_INCLUDED

#include <memory>
#include <unordered_map>

#include "units.hh"

namespace Kakoune
{

struct bad_value_cast {};

struct Value
{
    Value() = default;

    template<typename T>
    Value(T&& val) : m_value{new Model<T>{std::forward<T>(val)}} {}

    Value(const Value& val) = delete;
    Value(Value&&) = default;

    Value& operator=(const Value& val) = delete;
    Value& operator=(Value&& val) = default;

    explicit operator bool() const { return (bool)m_value; }

    template<typename T>
    bool is_a() const
    {
        return m_value and m_value->type() == typeid(T);
    }

    template<typename T>
    T& as()
    {
        if (not is_a<T>())
            throw bad_value_cast{};
        return static_cast<Model<T>*>(m_value.get())->m_content;
    }

    template<typename T>
    const T& as() const
    {
        return const_cast<Value*>(this)->as<T>();
    }

private:
    struct Concept
    {
        virtual ~Concept() {}
        virtual const std::type_info& type() const = 0;
    };

    template<typename T>
    struct Model : public Concept
    {
        Model(T&& val) : m_content(std::move(val)) {}
        const std::type_info& type() const override { return typeid(T); }

        T m_content;
    };

    std::unique_ptr<Concept> m_value;
};

struct ValueId : public StronglyTypedNumber<ValueId, int>
{
    constexpr ValueId(int value = 0) : StronglyTypedNumber<ValueId>(value) {}

    static ValueId get_free_id()
    {
        static ValueId next;
        return next++;
    }
};

using ValueMap = std::unordered_map<ValueId, Value>;

}

namespace std
{

template<>
struct hash<Kakoune::ValueId>
{
    size_t operator()(Kakoune::ValueId val) const
    {
        return std::hash<int>()((int)val);
    }
};

}

#endif // value_hh_INCLUDED
<|endoftext|>